From 18e0b1e1b7e216e13c58d863510af4a25df1fee1 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Mon, 23 Jul 2012 09:46:45 +0000 Subject: HistorySweeperLight, MyDetails, NewEventNotify: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@1112 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/MyDetails/src/commons.h | 109 ++ plugins/MyDetails/src/data.cpp | 689 +++++++++ plugins/MyDetails/src/data.h | 163 +++ plugins/MyDetails/src/frame.cpp | 2757 +++++++++++++++++++++++++++++++++++ plugins/MyDetails/src/frame.h | 38 + plugins/MyDetails/src/mydetails.cpp | 737 ++++++++++ plugins/MyDetails/src/options.cpp | 160 ++ plugins/MyDetails/src/options.h | 79 + plugins/MyDetails/src/resource.h | 71 + 9 files changed, 4803 insertions(+) create mode 100644 plugins/MyDetails/src/commons.h create mode 100644 plugins/MyDetails/src/data.cpp create mode 100644 plugins/MyDetails/src/data.h create mode 100644 plugins/MyDetails/src/frame.cpp create mode 100644 plugins/MyDetails/src/frame.h create mode 100644 plugins/MyDetails/src/mydetails.cpp create mode 100644 plugins/MyDetails/src/options.cpp create mode 100644 plugins/MyDetails/src/options.h create mode 100644 plugins/MyDetails/src/resource.h (limited to 'plugins/MyDetails/src') diff --git a/plugins/MyDetails/src/commons.h b/plugins/MyDetails/src/commons.h new file mode 100644 index 0000000000..4753c28d70 --- /dev/null +++ b/plugins/MyDetails/src/commons.h @@ -0,0 +1,109 @@ +/* +Copyright (C) 2005 Ricardo Pescuma Domenecci + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + + +#ifndef __COMMONS_H__ +# define __COMMONS_H__ + +#define _CRT_SECURE_NO_WARNINGS + +#define _WIN32_WINNT 0x0501 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "m_cluiframes.h" +#include "m_simpleaway.h" + +#include +#include + +#include + +#include "resource.h" + +#define MODULE_NAME "MyDetails" + +#define SETTING_FRAME_VISIBLE "FrameVisible" +#define SETTING_DEFAULT_NICK "DefaultNick" + +extern HINSTANCE hInst; + +extern long nickname_dialog_open; +extern long status_msg_dialog_open; + +#include "m_mydetails.h" +#include "data.h" +#include "options.h" +#include "frame.h" +#include "../utils/mir_smileys.h" +#include "../utils/mir_memory.h" +#include "../utils/mir_options.h" +#include "../utils/mir_icons.h" + +#define PS_GETMYAVATARMAXSIZE "/GetMyAvatarMaxSize" + +#define PS_GETMYNICKNAMEMAXLENGTH "/GetMyNicknameMaxLength" + +// See if a protocol service exists +__inline static int ProtoServiceExists(const char *szModule,const char *szService) +{ + char str[MAXMODULELABELLENGTH]; + strcpy(str,szModule); + strcat(str,szService); + return ServiceExists(str); +} + +// Helper +static __inline int DRAW_TEXT(HDC hDC, LPCTSTR lpString, int nCount, LPRECT lpRect, UINT uFormat, const char *protocol, + SmileysParseInfo parseInfo) +{ + if (!opts.replace_smileys) + return DrawText(hDC, lpString, nCount, lpRect, uFormat); + + return Smileys_DrawText(hDC, lpString, nCount, lpRect, uFormat | (opts.resize_smileys ? DT_RESIZE_SMILEYS : 0), + opts.use_contact_list_smileys ? "clist" : protocol, parseInfo); +} + +#endif // __COMMONS_H__ diff --git a/plugins/MyDetails/src/data.cpp b/plugins/MyDetails/src/data.cpp new file mode 100644 index 0000000000..c29af17ed0 --- /dev/null +++ b/plugins/MyDetails/src/data.cpp @@ -0,0 +1,689 @@ +/* +Copyright (C) 2005 Ricardo Pescuma Domenecci + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + + +#include "commons.h" +#include "data.h" + +static char *StatusModeToDbSetting(int status,const char *suffix); + +ProtocolArray *protocols = NULL; + +void InitProtocolData() +{ + PROTOACCOUNT **protos; + int count; + CallService(MS_PROTO_ENUMACCOUNTS, (WPARAM)&count, (LPARAM)&protos); + + protocols = new ProtocolArray(count); + + for (int i = 0; i < count; i++) { + PROTOACCOUNT* acc = protos[i]; + if (acc->type != PROTOTYPE_PROTOCOL) + continue; + + if (acc->szModuleName == NULL || acc->szModuleName[0] == '\0') + continue; + + // Found a protocol + Protocol *p = new Protocol(acc->szModuleName, acc->tszAccountName); + if ( p->IsValid()) + protocols->Add(p); + else + delete p; + } +} + +void DeInitProtocolData() +{ + delete protocols; +} + + +// Protocol Class /////////////////////////////////////////////////////////////////////////////////////////// + +Protocol::Protocol(const char *aName, const TCHAR* descr) +{ + lstrcpynA(name, aName, SIZEOF(name)); + lstrcpyn(description, descr, SIZEOF(description)); + + nickname[0] = _T('\0'); + status_message[0] = _T('\0'); + listening_to[0] = _T('\0'); + ace = NULL; + avatar_file[0] = _T('\0'); + avatar_bmp = NULL; + custom_status = 0; + data_changed = true; + + // Load services + int caps = CallProtoService(name, PS_GETCAPS, PFLAGNUM_1, 0); + valid = (caps & PF1_IM) == PF1_IM && strcmp(aName, "MetaContacts"); + if ( !valid) + return; + + can_have_listening_to = (ProtoServiceExists(name, PS_SET_LISTENINGTO) != 0); + + caps = CallProtoService(name, PS_GETCAPS, PFLAGNUM_4, 0); + can_have_avatar = (caps & PF4_AVATARS) != 0; + + PF3 = CallProtoService(name, PS_GETCAPS, (WPARAM)PFLAGNUM_3, 0); + + avatar_max_width = 0; + avatar_max_height = 0; + if (ProtoServiceExists(name, PS_GETMYAVATARMAXSIZE)) + CallProtoService(name, PS_GETMYAVATARMAXSIZE, (WPARAM) &avatar_max_width, (LPARAM) &avatar_max_height); + + can_set_nick = ProtoServiceExists(name, PS_SETMYNICKNAME) != FALSE; + + // Initial value + GetStatus(); + GetStatusMsg(); + GetNick(); + GetAvatar(); +} + +Protocol::~Protocol() +{ +} + +void Protocol::lcopystr(TCHAR *dest, TCHAR *src, size_t maxlen) +{ + if (lstrcmp(dest, src) != 0) + { + data_changed = true; + lstrcpyn(dest, src, maxlen); + } +} + +bool Protocol::IsValid() +{ + return valid; +} + + +int Protocol::GetStatus() +{ + int old_status = status; + status = CallProtoService(name, PS_GETSTATUS, 0, 0); + + if (old_status != status) + data_changed = true; + + if (/*status > ID_STATUS_OFFLINE &&*/ ProtoServiceExists(name, PS_ICQ_GETCUSTOMSTATUS)) + { + custom_status = CallProtoService(name, PS_ICQ_GETCUSTOMSTATUS, (WPARAM) &custom_status_name, + (LPARAM) &custom_status_message); + } + else + { + custom_status = 0; + } + + if (custom_status == 0) + { + TCHAR *tmp = (TCHAR*) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, status, GSMDF_TCHAR); + lcopystr(status_name, tmp, SIZEOF(status_name)); + } + else + { + DBVARIANT dbv; + TCHAR tmp[256]; tmp[0] = 0; + + if (custom_status_name != NULL && custom_status_name[0] != '\0' + && !DBGetContactSettingTString(0, name, _T2A(custom_status_name), &dbv)) + { + if (dbv.ptszVal != NULL && dbv.ptszVal[0] != _T('\0')) + lstrcpyn(tmp, dbv.ptszVal, SIZEOF(tmp)); + else + lstrcpyn(tmp, TranslateT(""), SIZEOF(tmp)); + + DBFreeVariant(&dbv); + } + else + { + lstrcpyn(tmp, TranslateT(""), SIZEOF(tmp)); + } + + if (custom_status_message != NULL && custom_status_message[0] != '\0' + && !DBGetContactSettingTString(0, name, _T2A(custom_status_message), &dbv)) + { + if (dbv.ptszVal != NULL && dbv.ptszVal[0] != '\0') + { + int len = lstrlen(tmp); + + if (len < SIZEOF(tmp)) + lstrcpyn(&tmp[len], _T(": "), SIZEOF(tmp) - len); + + len += 2; + + if (len < SIZEOF(tmp)) + lstrcpyn(&tmp[len], dbv.ptszVal, SIZEOF(tmp) - len); + } + + DBFreeVariant(&dbv); + } + + lcopystr(status_name, tmp, SIZEOF(status_name)); + } + + return status; +} + +void Protocol::SetStatus(int aStatus) +{ + TCHAR status_msg[256]; + + if (ServiceExists(MS_CS_SETSTATUSEX)) + { + // :'( + + // BEGIN From commomstatus.cpp (KeepStatus) + int i, count, pCount; + PROTOACCOUNT **accs; + + pCount = 0; + CallService(MS_PROTO_ENUMPROTOCOLS,(WPARAM)&count,(LPARAM)&accs); + for (i=0; i < count; i++) { + if (accs[i]->type != PROTOTYPE_PROTOCOL || CallProtoService(accs[i]->szModuleName,PS_GETCAPS,PFLAGNUM_2,0)==0) + continue; + pCount++; + } + // END From commomstatus.cpp (KeepStatus) + + + PROTOCOLSETTINGEX **pse = (PROTOCOLSETTINGEX **) mir_alloc0(pCount * sizeof(PROTOCOLSETTINGEX *)); + + for (i = 0; i < pCount; i++) { + pse[i] = (PROTOCOLSETTINGEX *) mir_alloc0(sizeof(PROTOCOLSETTINGEX)); + pse[i]->szName = ""; + } + + pse[0]->cbSize = sizeof(PROTOCOLSETTINGEX); + pse[0]->status = aStatus; + pse[0]->szName = name; + + GetStatusMsg(aStatus, status_msg, SIZEOF(status_msg)); + pse[0]->szMsg = status_msg; + + CallService(MS_CS_SETSTATUSEX, (WPARAM) &pse, 0); + + for (i = 0; i < pCount; i++) + mir_free(pse[i]); + mir_free(pse); + } + else + { + CallProtoService(name, PS_SETSTATUS, aStatus, 0); + + if (CanSetStatusMsg(aStatus)) { + TCHAR status_msg[MS_MYDETAILS_GETMYSTATUSMESSAGE_BUFFER_SIZE]; + GetStatusMsg(aStatus, status_msg, SIZEOF(status_msg)); + SetStatusMsg(aStatus, status_msg); + } + } +} + + +bool Protocol::CanGetStatusMsg() +{ + return CanGetStatusMsg(status); +} + +bool Protocol::CanGetStatusMsg(int aStatus) +{ + return (CallProtoService(name, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_MODEMSGSEND) != 0 + && (PF3 & Proto_Status2Flag(aStatus)); +} + + +bool Protocol::CanSetStatusMsg() +{ + return CanSetStatusMsg(GetStatus()); // <- Simple away handled by this one +} + +bool Protocol::CanSetStatusMsg(int aStatus) +{ + return CanGetStatusMsg(aStatus); +} + +void Protocol::GetStatusMsg(int aStatus, TCHAR *msg, size_t msg_size) +{ + if ( !CanGetStatusMsg()) + { + lcopystr(msg, _T(""), msg_size); + return; + } + + if (aStatus == status && ProtoServiceExists(name, PS_GETMYAWAYMSG) ) + { + TCHAR *tmp = (TCHAR*) CallProtoService(name, PS_GETMYAWAYMSG, 0, SGMA_TCHAR); + lcopystr(msg, tmp == NULL ? _T("") : tmp, msg_size); + } + + else if (ServiceExists(MS_AWAYMSG_GETSTATUSMSG)) + { + TCHAR *tmp = (TCHAR*) CallService(MS_AWAYMSG_GETSTATUSMSGT, (WPARAM)aStatus, 0); + if (tmp != NULL) + { + lcopystr(msg, tmp, msg_size); + mir_free(tmp); + } + else lcopystr(msg, _T(""), msg_size); + } +} + +TCHAR* Protocol::GetStatusMsg() +{ + GetStatusMsg(status, status_message, SIZEOF(status_message)); + return status_message; +} + +void Protocol::SetStatusMsg(const TCHAR *message) +{ + SetStatusMsg(GetStatus(), message); +} + +void Protocol::SetStatusMsg(int aStatus, const TCHAR *message) +{ + if ( !CanSetStatusMsg(aStatus)) + return; + + CallProtoService(name, PS_SETAWAYMSGT, (WPARAM)aStatus, (LPARAM)message); +} + +bool Protocol::HasAvatar() +{ + GetAvatar(); + + return avatar_bmp != NULL; +} + +bool Protocol::CanGetAvatar() +{ + if ( !can_have_avatar) + return false; + + if ( !ServiceExists(MS_AV_GETMYAVATAR)) + return false; + + return true; +} + +void Protocol::GetAvatar() +{ + // See if can get one + if ( !CanGetAvatar()) + return; + + avatar_file[0] = '\0'; + avatar_bmp = NULL; + ace = NULL; + + // Get HBITMAP from cache + ace = (avatarCacheEntry *)CallService(MS_AV_GETMYAVATAR, 0, (LPARAM) name); + if (ace != NULL) + avatar_bmp = ace->hbmPic; + + data_changed = true; +} + + +bool Protocol::CanGetNick() +{ + return ServiceExists(MS_CONTACT_GETCONTACTINFO) != FALSE; +} + +int Protocol::GetNickMaxLength() +{ + if (ProtoServiceExists(name, PS_GETMYNICKNAMEMAXLENGTH)) + { + int ret = CallProtoService(name, PS_GETMYNICKNAMEMAXLENGTH, 0, 0); + if (ret <= 0) + ret = MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE; + return ret; + } + else + return MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE; +} + +TCHAR* Protocol::GetNick() +{ + // See if can get one + if ( !CanGetNick()) + return NULL; + + // Get it + CONTACTINFO ci = { 0 }; + ci.cbSize = sizeof(ci); + ci.hContact = NULL; + ci.szProto = name; + ci.dwFlag = CNF_DISPLAY; + +#ifdef UNICODE + ci.dwFlag |= CNF_UNICODE; +#endif + + if ( !CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) + { + // CNF_DISPLAY always returns a string type + lcopystr(nickname, ci.pszVal, SIZEOF(nickname)); + mir_free(ci.pszVal); + } + else lcopystr(nickname, _T(""), SIZEOF(nickname)); + + return nickname; +} + + +bool Protocol::CanSetNick() +{ + return can_set_nick; +} + + +void Protocol::SetNick(const TCHAR *nick) +{ + // See if can get one + if ( !CanSetNick()) + return; + + if (nick == NULL) + return; + + // Get it + CallProtoService(name, PS_SETMYNICKNAME, SMNN_TCHAR, (LPARAM)nick); +} + + +bool Protocol::CanSetAvatar() +{ + return ServiceExists(MS_AV_SETMYAVATAR) != FALSE && ServiceExists(MS_AV_CANSETMYAVATAR) != FALSE && + CallService(MS_AV_CANSETMYAVATAR, (WPARAM) name, 0); +} + +void Protocol::SetAvatar(const TCHAR *file_name) +{ + if ( !CanSetAvatar()) + return; + + CallService(MS_AV_SETMYAVATART, (WPARAM) name, (LPARAM) file_name); +} + +bool Protocol::CanGetListeningTo() +{ + return can_have_listening_to; +} + +bool Protocol::CanSetListeningTo() +{ + return CanGetListeningTo() && ServiceExists(MS_LISTENINGTO_ENABLE); +} + +bool Protocol::ListeningToEnabled() +{ + return CanSetListeningTo() && CallService(MS_LISTENINGTO_ENABLED, (WPARAM) name, 0) != 0; +} + +TCHAR * Protocol::GetListeningTo() +{ + if ( !CanGetListeningTo()) + { + lcopystr(listening_to, _T(""), SIZEOF(listening_to)); + return listening_to; + } + + DBVARIANT dbv = {0}; + if ( DBGetContactSettingTString(NULL, name, "ListeningTo", &dbv)) + { + lcopystr(listening_to, _T(""), SIZEOF(listening_to)); + return listening_to; + } + + lcopystr(listening_to, dbv.ptszVal, SIZEOF(listening_to)); + DBFreeVariant(&dbv); + return listening_to; +} + +// ProtocolDataArray Class ///////////////////////////////////////////////////////////////////////////// + +ProtocolArray::ProtocolArray(int max_size) +{ + buffer = (Protocol **) malloc(max_size * sizeof(Protocol*)); + buffer_len = 0; + + GetDefaultNick(); + GetDefaultAvatar(); +} + + +ProtocolArray::~ProtocolArray() +{ + if (buffer != NULL) { + for ( int i = 0 ; i < buffer_len ; i++ ) + delete buffer[i]; + free(buffer); + } +} + + +int ProtocolArray::GetSize() +{ + return buffer_len; +} + + +void ProtocolArray::Add(Protocol *p) +{ + buffer[buffer_len] = p; + buffer_len++; +} + + +Protocol * ProtocolArray::Get(int i) +{ + if (i >= buffer_len) + return NULL; + else + return buffer[i]; +} + + +Protocol * ProtocolArray::Get(const char *name) +{ + if (name == NULL) + return NULL; + + for ( int i = 0 ; i < buffer_len ; i++ ) + { + if (strcmp(name, buffer[i]->name) == 0) + return buffer[i]; + } + + return NULL; +} + + +bool ProtocolArray::CanSetStatusMsgPerProtocol() +{ + return ServiceExists(MS_SA_CHANGESTATUSMSG) != 0; +} + + +void ProtocolArray::GetAvatars() +{ + for ( int i = 0 ; i < buffer_len ; i++ ) + { + buffer[i]->GetAvatar(); + } +} + +void ProtocolArray::GetStatusMsgs() +{ + for ( int i = 0 ; i < buffer_len ; i++ ) + buffer[i]->GetStatusMsg(); +} + +void ProtocolArray::GetStatuses() +{ + for ( int i = 0 ; i < buffer_len ; i++ ) + buffer[i]->GetStatus(); +} + +int ProtocolArray::GetGlobalStatus() +{ + int status = CallService(MS_CLIST_GETSTATUSMODE, 0, 0); + if (status == ID_STATUS_CONNECTING) + status = ID_STATUS_OFFLINE; + + return status; +} + +bool ProtocolArray::CanSetAvatars() +{ + return ServiceExists(MS_AV_SETMYAVATART) != FALSE; +} + +void ProtocolArray::SetAvatars(const TCHAR *file_name) +{ + if ( !CanSetAvatars()) + return; + + CallService(MS_AV_SETMYAVATART, NULL, (WPARAM) file_name); +} + +void ProtocolArray::SetNicks(const TCHAR *nick) +{ + if (nick == NULL || nick[0] == '\0') + return; + + lstrcpyn(default_nick, nick, SIZEOF(default_nick)); + + DBWriteContactSettingTString(0, MODULE_NAME, SETTING_DEFAULT_NICK, nick); + + for ( int i = 0 ; i < buffer_len ; i++ ) + buffer[i]->SetNick(default_nick); +} + + +void ProtocolArray::SetStatus(int aStatus) +{ + CallService(MS_CLIST_SETSTATUSMODE, aStatus, 0); +} + +void ProtocolArray::SetStatusMsgs(const TCHAR *message) +{ + for (int i = ID_STATUS_OFFLINE ; i <= ID_STATUS_IDLE; i++) + SetStatusMsgs(i, message); +} + +void ProtocolArray::SetStatusMsgs(int status, const TCHAR *message) +{ + DBWriteContactSettingTString(NULL,"SRAway",StatusModeToDbSetting(status,"Msg"),message); + + // Save default also + if ( !db_get_b(NULL,"SRAway",StatusModeToDbSetting(status,"UsePrev"),0)) + DBWriteContactSettingTString(NULL,"SRAway",StatusModeToDbSetting(status,"Default"),message); + + for ( int i = 0 ; i < buffer_len ; i++ ) + if (buffer[i]->status == status) + buffer[i]->SetStatusMsg(status, message); +} + +void ProtocolArray::GetDefaultNick() +{ + DBVARIANT dbv; + if ( !DBGetContactSettingTString(0, MODULE_NAME, SETTING_DEFAULT_NICK, &dbv)) { + lstrcpyn(default_nick, dbv.ptszVal, SIZEOF(default_nick)); + DBFreeVariant(&dbv); + } + else default_nick[0] = '\0'; +} + +void ProtocolArray::GetDefaultAvatar() +{ + DBVARIANT dbv; + if ( !DBGetContactSettingTString(0, "ContactPhoto", "File", &dbv)) { + lstrcpyn(default_avatar_file, dbv.ptszVal, SIZEOF(default_avatar_file)); + DBFreeVariant(&dbv); + } + else default_avatar_file[0] = '\0'; +} + +TCHAR* ProtocolArray::GetDefaultStatusMsg() +{ + return GetDefaultStatusMsg(CallService(MS_CLIST_GETSTATUSMODE, 0, 0)); +} + +TCHAR* ProtocolArray::GetDefaultStatusMsg(int status) +{ + default_status_message[0] = '\0'; + + if (ServiceExists(MS_AWAYMSG_GETSTATUSMSG)) { + if (status == ID_STATUS_CONNECTING) + status = ID_STATUS_OFFLINE; + + TCHAR *tmp = (TCHAR*) CallService(MS_AWAYMSG_GETSTATUSMSGT, (WPARAM)status, 0); + if (tmp != NULL) { + lstrcpyn(default_status_message, tmp, SIZEOF(default_status_message)); + mir_free(tmp); + } + } + + return default_status_message; +} + +bool ProtocolArray::CanSetListeningTo() +{ + return ServiceExists(MS_LISTENINGTO_ENABLE) != 0; +} + +bool ProtocolArray::ListeningToEnabled() +{ + return CanSetListeningTo() && CallService(MS_LISTENINGTO_ENABLED, 0, 0) != 0; +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////// +// Helper functions + +static char *StatusModeToDbSetting(int status,const char *suffix) +{ + char *prefix; + static char str[64]; + + switch(status) { + case ID_STATUS_AWAY: prefix="Away"; break; + case ID_STATUS_NA: prefix="Na"; break; + case ID_STATUS_DND: prefix="Dnd"; break; + case ID_STATUS_OCCUPIED: prefix="Occupied"; break; + case ID_STATUS_FREECHAT: prefix="FreeChat"; break; + case ID_STATUS_ONLINE: prefix="On"; break; + case ID_STATUS_OFFLINE: prefix="Off"; break; + case ID_STATUS_INVISIBLE: prefix="Inv"; break; + case ID_STATUS_ONTHEPHONE: prefix="Otp"; break; + case ID_STATUS_OUTTOLUNCH: prefix="Otl"; break; + case ID_STATUS_IDLE: prefix="Idl"; break; + default: return NULL; + } + lstrcpyA(str,prefix); lstrcatA(str,suffix); + return str; +} + + diff --git a/plugins/MyDetails/src/data.h b/plugins/MyDetails/src/data.h new file mode 100644 index 0000000000..d8c75beda4 --- /dev/null +++ b/plugins/MyDetails/src/data.h @@ -0,0 +1,163 @@ +/* +Copyright (C) 2005 Ricardo Pescuma Domenecci + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + + +#ifndef __DATA_H__ +# define __DATA_H__ + + +//#include "protocol_config.h" + +class Protocol +{ + // Attributes //////////// +protected: + bool valid; + bool can_set_nick; + bool can_have_avatar; + bool can_have_listening_to; + int PF3; + + void lcopystr(TCHAR *dest, TCHAR *src, size_t maxlen); + +public: + // Name of protocol + char name[256]; + TCHAR description[256]; + TCHAR nickname[256]; + TCHAR status_name[256]; + TCHAR *custom_status_name; + TCHAR status_message[1024]; + TCHAR *custom_status_message; + TCHAR listening_to[1024]; + AVATARCACHEENTRY *ace; + TCHAR avatar_file[1024]; + HBITMAP avatar_bmp; + int status; + int custom_status; + + int avatar_max_width; + int avatar_max_height; + + bool data_changed; + + + // Methods /////////////// + + Protocol(const char *name, const TCHAR *descr); + ~Protocol(); + + bool IsValid(); + + int GetStatus(); // Copy to cache and return a copy + void SetStatus(int aStatus); + + bool HasAvatar(); + bool CanGetAvatar(); + void GetAvatar(); // Copy to cache + + bool CanSetAvatar(); + void SetAvatar(const TCHAR *file_name); + //void SetAvatar(const char *file_name, HBITMAP hBmp); + + bool CanGetNick(); + TCHAR * GetNick(); // Copy to cache and return a copy + int GetNickMaxLength(); + bool CanSetNick(); + void SetNick(const TCHAR *nick); + + bool CanGetListeningTo(); + bool CanSetListeningTo(); + bool ListeningToEnabled(); + TCHAR * GetListeningTo(); // Copy to cache and return a copy + + bool CanGetStatusMsg(); + bool CanGetStatusMsg(int aStatus); + TCHAR * GetStatusMsg(); // Copy to cache and return a copy + void GetStatusMsg(int aStatus, TCHAR *msg, size_t msg_size); + bool CanSetStatusMsg(); + bool CanSetStatusMsg(int aStatus); + void SetStatusMsg(const TCHAR *message); + void SetStatusMsg(int aStatus, const TCHAR *message); +}; + + + +class ProtocolArray +{ +protected: + // Attributes //////////// + Protocol **buffer; + int buffer_len; + +public: + TCHAR default_nick[256]; + TCHAR default_avatar_file[256]; + TCHAR default_status_message[256]; + + // Methods /////////////// + + ProtocolArray(int max_size); + virtual ~ProtocolArray(); + + int GetSize(); + + void Add(Protocol *p); + Protocol* Get(int i); + Protocol* Get(const char *name); + + void GetAvatars(); + bool CanSetAvatars(); + void SetAvatars(const TCHAR *file); + + void SetNicks(const TCHAR *nick); + + void SetStatus(int aStatus); + + void SetStatusMsgs(const TCHAR *message); + void SetStatusMsgs(int status, const TCHAR *message); + + void GetStatusMsgs(); + void GetStatuses(); + int GetGlobalStatus(); + + bool CanSetStatusMsgPerProtocol(); + + void GetDefaultNick(); // Copy to cache + void GetDefaultAvatar(); // Copy to cache + TCHAR* GetDefaultStatusMsg(); // Copy to cache + TCHAR* GetDefaultStatusMsg(int status); + + bool CanSetListeningTo(); + bool ListeningToEnabled(); +}; + +extern ProtocolArray *protocols; + + + +void InitProtocolData(); +void DeInitProtocolData(); + + + + + + +#endif // __DATA_H__ diff --git a/plugins/MyDetails/src/frame.cpp b/plugins/MyDetails/src/frame.cpp new file mode 100644 index 0000000000..baaf0b26dd --- /dev/null +++ b/plugins/MyDetails/src/frame.cpp @@ -0,0 +1,2757 @@ +/* +Copyright (C) 2005 Ricardo Pescuma Domenecci + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "commons.h" + +#include + +// Prototypes ///////////////////////////////////////////////////////////////////////////////////// + +#define WINDOW_NAME_PREFIX "mydetails_window" +#define WINDOW_CLASS_NAME _T("MyDetailsFrame") +#define CONTAINER_CLASS_NAME _T("MyDetailsFrameContainer") + +#define ID_FRAME_TIMER 1011 +#define ID_RECALC_TIMER 1012 +#define ID_STATUSMESSAGE_TIMER 1013 + +#define RECALC_TIME 1000 + +#define IDC_HAND MAKEINTRESOURCE(32649) + +#define DEFAULT_NICKNAME _T("") +#define DEFAULT_STATUS_MESSAGE _T("") +#define DEFAULT_LISTENING_TO _T("") + + +// Messages +#define MWM_REFRESH (WM_USER+10) +#define MWM_NICK_CHANGED (WM_USER+11) +#define MWM_STATUS_CHANGED (WM_USER+12) +#define MWM_STATUS_MSG_CHANGED (WM_USER+13) +#define MWM_AVATAR_CHANGED (WM_USER+14) +#define MWM_LISTENINGTO_CHANGED (WM_USER+15) + + +HWND hwnd_frame = NULL; +HWND hwnd_container = NULL; + +int frame_id = -1; + +HANDLE hMenuShowHideFrame = 0; + +#define FONT_NICK 0 +#define FONT_PROTO 1 +#define FONT_STATUS 2 +#define FONT_AWAY_MSG 3 +#define FONT_LISTENING_TO 4 +#define NUM_FONTS 5 + +FontIDT font_id[NUM_FONTS]; +HFONT hFont[NUM_FONTS]; +COLORREF font_colour[NUM_FONTS]; + +// Defaults +TCHAR *font_names[] = { LPGENT("Nickname"), LPGENT("Protocol"), LPGENT("Status"), LPGENT("Status Message"), LPGENT("Listening To") }; +char font_sizes[] = { 13, 8, 8, 8, 8 }; +BYTE font_styles[] = { DBFONTF_BOLD, 0, 0, DBFONTF_ITALIC, DBFONTF_ITALIC }; +COLORREF font_colors[] = { RGB(0,0,0), RGB(0,0,0), RGB(0,0,0), RGB(150,150,150), RGB(150,150,150) }; + + +int CreateFrame(); +void FixMainMenu(); +void RefreshFrame(); +void RedrawFrame(); + + +// used when no multiwindow functionality available +bool MyDetailsFrameVisible(); +void SetMyDetailsFrameVisible(bool visible); +INT_PTR ShowHideMenuFunc(WPARAM wParam, LPARAM lParam); +INT_PTR ShowFrameFunc(WPARAM wParam, LPARAM lParam); +INT_PTR HideFrameFunc(WPARAM wParam, LPARAM lParam); +INT_PTR ShowHideFrameFunc(WPARAM wParam, LPARAM lParam); + +LRESULT CALLBACK FrameContainerWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK FrameWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +void SetCycleTime(); +void SetCycleTime(HWND hwnd); +void SetStatusMessageRefreshTime(); +void SetStatusMessageRefreshTime(HWND hwnd); +int SettingsChangedHook(WPARAM wParam, LPARAM lParam); +int AvatarChangedHook(WPARAM wParam, LPARAM lParam); +int ProtoAckHook(WPARAM wParam, LPARAM lParam); +int SmileyAddOptionsChangedHook(WPARAM wParam,LPARAM lParam); +int ListeningtoEnableStateChangedHook(WPARAM wParam,LPARAM lParam); + + +#define OUTSIDE_BORDER 6 +#define SPACE_IMG_TEXT 6 +#define SPACE_TEXT_TEXT 0 +#define SPACE_ICON_TEXT 2 +#define ICON_SIZE 16 + +#define BORDER_SPACE 2 + +struct MyDetailsFrameData +{ + RECT proto_rect; + bool draw_proto; + bool mouse_over_proto; + + bool draw_proto_cycle; + RECT next_proto_rect; + HWND next_proto_tt_hwnd; + RECT prev_proto_rect; + HWND prev_proto_tt_hwnd; + + RECT img_rect; + bool draw_img; + bool mouse_over_img; + + RECT nick_rect; + bool draw_nick; + bool mouse_over_nick; + HWND nick_tt_hwnd; + + RECT status_rect; + RECT status_icon_rect; + RECT status_text_rect; + bool draw_status; + bool mouse_over_status; + HWND status_tt_hwnd; + + RECT away_msg_rect; + bool draw_away_msg; + bool mouse_over_away_msg; + HWND away_msg_tt_hwnd; + + RECT listening_to_rect; + RECT listening_to_icon_rect; + RECT listening_to_text_rect; + bool draw_listening_to; + bool mouse_over_listening_to; + HWND listening_to_tt_hwnd; + + int protocol_number; + + bool showing_menu; + bool skinning; + bool recalc_rectangles; + + bool get_status_messages; +}; + + +// Functions ////////////////////////////////////////////////////////////////////////////////////// + +void InitFrames() +{ + InitContactListSmileys(); + + CreateFrame(); + + HookEvent(ME_DB_CONTACT_SETTINGCHANGED, SettingsChangedHook); + HookEvent(ME_AV_MYAVATARCHANGED, AvatarChangedHook); + HookEvent(ME_PROTO_ACK, ProtoAckHook); + HookEvent(ME_SMILEYADD_OPTIONSCHANGED,SmileyAddOptionsChangedHook); + HookEvent(ME_LISTENINGTO_ENABLE_STATE_CHANGED,ListeningtoEnableStateChangedHook); +} + + +void DeInitFrames() +{ + if (ServiceExists(MS_CLIST_FRAMES_REMOVEFRAME) && frame_id != -1) + { + CallService(MS_CLIST_FRAMES_REMOVEFRAME, (WPARAM)frame_id, 0); + } + + for (int i = 0 ; i < NUM_FONTS ; i++ ) + { + if (hFont[i] != 0) DeleteObject(hFont[i]); + } + + if (hwnd_frame != NULL) DestroyWindow(hwnd_frame); + if (hwnd_container != NULL) DestroyWindow(hwnd_container); +} + + +int ReloadFont(WPARAM wParam, LPARAM lParam) +{ + LOGFONT log_font; + + for (int i = 0 ; i < NUM_FONTS ; i++ ) + { + if (hFont[i] != 0) DeleteObject(hFont[i]); + + font_colour[i] = CallService(MS_FONT_GETT, (WPARAM)&font_id[i], (LPARAM)&log_font); + hFont[i] = CreateFontIndirect(&log_font); + } + + RefreshFrame(); + return 0; +} + +int SmileyAddOptionsChangedHook(WPARAM wParam,LPARAM lParam) +{ + RefreshFrame(); + return 0; +} + +int CreateFrame() +{ + HDC hdc = GetDC(NULL); + + for (int i = 0 ; i < NUM_FONTS ; i++) { + ZeroMemory(&font_id[i], sizeof(font_id[i])); + + font_id[i].cbSize = sizeof(FontIDT); + _tcsncpy(font_id[i].group, LPGENT("My Details"), SIZEOF(font_id[i].group)); + _tcsncpy(font_id[i].name, font_names[i], SIZEOF(font_id[i].name)); + strncpy(font_id[i].dbSettingsGroup, MODULE_NAME, SIZEOF(font_id[i].dbSettingsGroup)); + + char tmp[128]; + mir_snprintf(tmp, sizeof(tmp), "%sFont", font_names[i]); + strncpy(font_id[i].prefix, tmp, SIZEOF(font_id[i].prefix)); + + font_id[i].deffontsettings.colour = font_colors[i]; + font_id[i].deffontsettings.size = -MulDiv(font_sizes[i], GetDeviceCaps(hdc, LOGPIXELSY), 72); + font_id[i].deffontsettings.style = font_styles[i]; + font_id[i].deffontsettings.charset = DEFAULT_CHARSET; + _tcsncpy(font_id[i].deffontsettings.szFace, _T("Tahoma"), SIZEOF(font_id[i].deffontsettings.szFace)); + font_id[i].order = i; + font_id[i].flags = FIDF_DEFAULTVALID; + FontRegisterT(&font_id[i]); + } + + ReleaseDC(NULL, hdc); + + ReloadFont(0,0); + HookEvent(ME_FONT_RELOAD, ReloadFont); + + WNDCLASS wndclass; + wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; //CS_PARENTDC | CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = FrameWindowProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInst; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); + wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = WINDOW_CLASS_NAME; + RegisterClass(&wndclass); + + if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) { + hwnd_frame = CreateWindow(WINDOW_CLASS_NAME, TranslateT("My Details"), + WS_CHILD | WS_VISIBLE, + 0,0,10,10, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), NULL, hInst, NULL); + + CLISTFrame Frame = {0}; + + Frame.cbSize = sizeof(Frame); + Frame.tname = LPGENT("My Details"); + Frame.cbSize = sizeof(CLISTFrame); + Frame.hWnd = hwnd_frame; + Frame.align = alTop; + Frame.Flags = F_VISIBLE | F_SHOWTB | F_SHOWTBTIP | F_NOBORDER | F_SKINNED | F_TCHAR; + Frame.height = 100; + frame_id = CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM)&Frame, 0); + + if ( db_get_b(NULL, "MyDetails", "ForceHideFrame", 0)) { + int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0); + if (flags & F_VISIBLE) + CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0); + + db_unset(NULL, "MyDetails", "ForceHideFrame"); + } + + if ( db_get_b(NULL, "MyDetails", "ForceShowFrame", 0)) { + int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0); + if (!(flags & F_VISIBLE)) + CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0); + + db_unset(NULL, "MyDetails", "ForceShowFrame"); + } + } + else { + wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;//CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = FrameContainerWindowProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInst; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); + wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = CONTAINER_CLASS_NAME; + RegisterClass(&wndclass); + + hwnd_container = CreateWindowEx(WS_EX_TOOLWINDOW, CONTAINER_CLASS_NAME, TranslateT("My Details"), + (WS_THICKFRAME | WS_CAPTION | WS_SYSMENU) & ~WS_VISIBLE, + 0,0,200,130, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), NULL, hInst, NULL); + + hwnd_frame = CreateWindow(WINDOW_CLASS_NAME, TranslateT("My Details"), + WS_CHILD | WS_VISIBLE, + 0,0,10,10, hwnd_container, NULL, hInst, NULL); + + SetWindowLong(hwnd_container, GWLP_USERDATA, (LONG)hwnd_frame); + SendMessage(hwnd_container, WM_SIZE, 0, 0); + + // Create menu item + + CLISTMENUITEM menu = {0}; + + menu.cbSize=sizeof(menu); + menu.flags = CMIF_TCHAR; + menu.popupPosition = -0x7FFFFFFF; + menu.ptszPopupName = LPGENT("My Details"); + menu.position = 1; // 500010000 + menu.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + menu.ptszName = LPGENT("Show My Details"); + menu.pszService= MODULE_NAME "/ShowHideMyDetails"; + hMenuShowHideFrame = Menu_AddMainMenuItem(&menu); + + if ( db_get_b(0, MODULE_NAME, SETTING_FRAME_VISIBLE, 1) == 1) { + ShowWindow(hwnd_container, SW_SHOW); + FixMainMenu(); + } + } + + CreateServiceFunction(MS_MYDETAILS_SHOWFRAME, ShowFrameFunc); + CreateServiceFunction(MS_MYDETAILS_HIDEFRAME, HideFrameFunc); + CreateServiceFunction(MS_MYDETAILS_SHOWHIDEFRAME, ShowHideFrameFunc); + return 0; +} + + +bool FrameIsFloating() +{ + if (frame_id == -1) + return true; // no frames, always floating + + return (CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLOATING, frame_id), 0) != 0); +} + + +LRESULT CALLBACK FrameContainerWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_SHOWWINDOW: + if ((BOOL)wParam) + Utils_RestoreWindowPosition(hwnd, 0, MODULE_NAME, WINDOW_NAME_PREFIX); + else + Utils_SaveWindowPosition(hwnd, 0, MODULE_NAME, WINDOW_NAME_PREFIX); + break; + + case WM_ERASEBKGND: + SendMessage((HWND)GetWindowLong(hwnd, GWLP_USERDATA), WM_ERASEBKGND, wParam, lParam); + break; + + case WM_SIZE: + { + HWND child = (HWND)GetWindowLong(hwnd, GWLP_USERDATA); + RECT r; + GetClientRect(hwnd, &r); + + SetWindowPos(child, 0, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE); + InvalidateRect(child, NULL, TRUE); + } + return TRUE; + + case WM_CLOSE: + DBWriteContactSettingByte(0, MODULE_NAME, SETTING_FRAME_VISIBLE, 0); + ShowWindow(hwnd, SW_HIDE); + FixMainMenu(); + return TRUE; + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + + +BOOL ScreenToClient(HWND hWnd, LPRECT lpRect) +{ + POINT pt; + pt.x = lpRect->left; + pt.y = lpRect->top; + + BOOL ret = ScreenToClient(hWnd, &pt); + if ( !ret) + return ret; + + lpRect->left = pt.x; + lpRect->top = pt.y; + + pt.x = lpRect->right; + pt.y = lpRect->bottom; + + ret = ScreenToClient(hWnd, &pt); + + lpRect->right = pt.x; + lpRect->bottom = pt.y; + + return ret; +} + +BOOL MoveWindow(HWND hWnd, const RECT &rect, BOOL bRepaint) +{ + return MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, bRepaint); +} + +RECT GetInnerRect(const RECT &rc, const RECT &clipping) +{ + RECT rc_ret = rc; + rc_ret.left = max(rc.left, clipping.left); + rc_ret.top = max(rc.top, clipping.top); + rc_ret.right = min(rc.right, clipping.right); + rc_ret.bottom = min(rc.bottom, clipping.bottom); + + return rc_ret; +} + +RECT GetRect(HDC hdc, RECT rc, SIZE s, UINT uFormat, int next_top, int text_left, bool frame = true, + bool end_elipsis_on_frame = true) +{ + RECT r = rc; + + if (frame && end_elipsis_on_frame) + { + // Add space to ... + uFormat &= ~DT_END_ELLIPSIS; + + RECT rc_tmp = rc; + DrawText(hdc, _T(" ..."), 4, &rc_tmp, DT_CALCRECT | uFormat); + + s.cx += rc_tmp.right - rc_tmp.left; + } + + r.top = next_top; + r.bottom = r.top + s.cy; + + if (opts.draw_text_align_right) + { + r.left = r.right - s.cx; + } + else + { + r.left = text_left; + r.right = r.left + s.cx; + } + + if (frame) + { + r.bottom += 2 * BORDER_SPACE; + + if (opts.draw_text_align_right) + r.left -= 2 * BORDER_SPACE; + else + r.right += 2 * BORDER_SPACE; + } + + // Make it fit inside original rc + r.top = max(next_top, r.top); + r.bottom = min(rc.bottom, r.bottom); + r.left = max(text_left, r.left); + r.right = min(rc.right, r.right); + + return r; +} + +RECT GetRect(HDC hdc, RECT rc, const TCHAR *text, const TCHAR *def_text, Protocol *proto, UINT uFormat, + int next_top, int text_left, bool smileys = true, bool frame = true, bool end_elipsis_on_frame = true) +{ + const TCHAR *tmp; + + if (text[0] == '\0') + tmp = TranslateTS(def_text); + else + tmp = text; + + uFormat &= ~DT_END_ELLIPSIS; + + SIZE s; + RECT r_tmp = rc; + + // Only first line + TCHAR *tmp2 = _tcsdup(tmp); + TCHAR *pos = _tcschr(tmp2, '\r'); + if (pos != NULL) pos[0] = '\0'; + pos = _tcschr(tmp2, '\n'); + if (pos != NULL) pos[0] = '\0'; + + if (smileys) + DRAW_TEXT(hdc, tmp2, _tcslen(tmp2), &r_tmp, uFormat | DT_CALCRECT, proto->name, NULL); + else + DrawText(hdc, tmp2, _tcslen(tmp2), &r_tmp, uFormat | DT_CALCRECT); + + free(tmp2); + + s.cx = r_tmp.right - r_tmp.left; + s.cy = r_tmp.bottom - r_tmp.top; + + return GetRect(hdc, rc, s, uFormat, next_top, text_left, frame, end_elipsis_on_frame); +} + +HWND CreateTooltip(HWND hwnd, RECT &rect) +{ + // struct specifying control classes to register + INITCOMMONCONTROLSEX iccex; + HWND hwndTT; // handle to the ToolTip control + // struct specifying info about tool in ToolTip control + TOOLINFO ti; + unsigned int uid = 0; // for ti initialization + + // Load the ToolTip class from the DLL. + iccex.dwSize = sizeof(iccex); + iccex.dwICC = ICC_BAR_CLASSES; + + if (!InitCommonControlsEx(&iccex)) + return NULL; + + /* CREATE A TOOLTIP WINDOW */ + hwndTT = CreateWindowEx(WS_EX_TOPMOST, + TOOLTIPS_CLASS, + NULL, + WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + hwnd, + NULL, + hInst, + NULL + ); + + /* INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE */ + ti.cbSize = sizeof(TOOLINFO); + ti.uFlags = TTF_SUBCLASS; + ti.hwnd = hwnd; + ti.hinst = hInst; + ti.uId = uid; + ti.lpszText = LPSTR_TEXTCALLBACK; + // ToolTip control will cover the whole window + ti.rect.left = rect.left; + ti.rect.top = rect.top; + ti.rect.right = rect.right; + ti.rect.bottom = rect.bottom; + + /* SEND AN ADDTOOL MESSAGE TO THE TOOLTIP CONTROL WINDOW */ + SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti); + SendMessage(hwndTT, TTM_SETDELAYTIME, (WPARAM) (DWORD) TTDT_AUTOPOP, (LPARAM) MAKELONG(24 * 60 * 60 * 1000, 0)); + + return hwndTT; +} + +void DeleteTooltipWindows(MyDetailsFrameData *data) +{ + if (data->nick_tt_hwnd != NULL) { + DestroyWindow(data->nick_tt_hwnd); + data->nick_tt_hwnd = NULL; + } + + if (data->status_tt_hwnd != NULL) { + DestroyWindow(data->status_tt_hwnd); + data->status_tt_hwnd = NULL; + } + + if (data->next_proto_tt_hwnd != NULL) { + DestroyWindow(data->next_proto_tt_hwnd); + data->next_proto_tt_hwnd = NULL; + } + + if (data->prev_proto_tt_hwnd != NULL) { + DestroyWindow(data->prev_proto_tt_hwnd); + data->prev_proto_tt_hwnd = NULL; + } + + if (data->away_msg_tt_hwnd != NULL) { + DestroyWindow(data->away_msg_tt_hwnd); + data->away_msg_tt_hwnd = NULL; + } + + if (data->listening_to_tt_hwnd != NULL) { + DestroyWindow(data->listening_to_tt_hwnd); + data->listening_to_tt_hwnd = NULL; + } +} + +void CalcRectangles(HWND hwnd) +{ + HDC hdc = GetDC(hwnd); + HFONT hOldFont = (HFONT) GetCurrentObject(hdc, OBJ_FONT); + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWLP_USERDATA); + + if (hdc == NULL || data == NULL) + return; + + Protocol *proto = protocols->Get(data->protocol_number); + if (proto == NULL) + return; + + data->recalc_rectangles = false; + proto->data_changed = false; + + data->draw_proto = false; + data->draw_proto_cycle = false; + data->draw_img = false; + data->draw_nick = false; + data->draw_status = false; + data->draw_away_msg = false; + data->draw_listening_to = false; + + DeleteTooltipWindows(data); + + if (ServiceExists(MS_CLIST_FRAMES_SETFRAMEOPTIONS) && frame_id != -1) { + int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0); + if (flags & F_UNCOLLAPSED) { + RECT rf; + GetClientRect(hwnd, &rf); + + int size = 0; + + if (rf.bottom - rf.top != size) { + if (FrameIsFloating()) { + HWND parent = GetParent(hwnd); + if (parent != NULL) { + RECT rp_client, rp_window, r_window; + GetClientRect(parent, &rp_client); + GetWindowRect(parent, &rp_window); + GetWindowRect(hwnd, &r_window); + int diff = (rp_window.bottom - rp_window.top) - (rp_client.bottom - rp_client.top); + if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + diff += (r_window.top - rp_window.top); + + SetWindowPos(parent, 0, 0, 0, rp_window.right - rp_window.left, size + diff, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); + } + } + } + SelectObject(hdc, hOldFont); + ReleaseDC(hwnd, hdc); + return; + } + } + + RECT r; + GetClientRect(hwnd, &r); + + if (opts.resize_frame) + r.bottom = 0x7FFFFFFF; + + int next_top; + int text_left; + int avatar_bottom = 0; + + UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_END_ELLIPSIS + | (opts.draw_text_align_right ? DT_RIGHT : DT_LEFT) + | (opts.draw_text_rtl ? DT_RTLREADING : 0); + + // make some borders + r.left += min(opts.borders[LEFT], r.right); + r.right = max(r.right - opts.borders[RIGHT], r.left); + r.top += min(opts.borders[TOP], r.bottom); + r.bottom = max(r.bottom - opts.borders[BOTTOM], r.top); + + next_top = r.top; + text_left = r.left; + + // Draw image? + if (proto->CanGetAvatar()) { + if (proto->avatar_bmp != NULL) { + data->draw_img = true; + + BITMAP bmp; + if (GetObject(proto->avatar_bmp, sizeof(bmp), &bmp)) { + // make bounds + RECT rc = r; + + LONG width; + LONG height; + + if (opts.draw_avatar_custom_size) { + rc.right = opts.draw_avatar_custom_size_pixels; + + width = opts.draw_avatar_custom_size_pixels; + height = opts.draw_avatar_custom_size_pixels; + } + else if (opts.resize_frame) { + rc.right = rc.left + (rc.right - rc.left) / 3; + + width = rc.right - rc.left; + height = rc.bottom - rc.top; + } + else { + rc.right = rc.left + min((rc.right - rc.left) / 3, rc.bottom - rc.top); + + width = rc.right - rc.left; + height = rc.bottom - rc.top; + } + + // Fit to image proportions + if ( !opts.draw_avatar_allow_to_grow) { + if (width > bmp.bmWidth) + width = bmp.bmWidth; + + if (height > bmp.bmHeight) + height = bmp.bmHeight; + } + + if ( !opts.resize_frame && height * bmp.bmWidth / bmp.bmHeight <= width) + width = height * bmp.bmWidth / bmp.bmHeight; + else + height = width * bmp.bmHeight / bmp.bmWidth; + + rc.right = rc.left + width; + rc.bottom = rc.top + height; + + data->img_rect = rc; + + avatar_bottom = data->img_rect.bottom + SPACE_TEXT_TEXT; + + // Make space to nick + text_left = data->img_rect.right + SPACE_IMG_TEXT; + } + } + } + + // Always draw nick + data->draw_nick = true; + SelectObject(hdc, hFont[FONT_NICK]); + + data->nick_rect = GetRect(hdc, r, proto->nickname, DEFAULT_NICKNAME, proto, uFormat, next_top, text_left); + + if (proto->nickname[0] != '\0') + data->nick_tt_hwnd = CreateTooltip(hwnd, data->nick_rect); + + next_top = data->nick_rect.bottom + SPACE_TEXT_TEXT; + + // Fits more? + if (next_top > r.bottom) + goto finish; + + if (next_top > avatar_bottom && opts.use_avatar_space_to_draw_text) + text_left = r.left; + + // Protocol? + if (opts.draw_show_protocol_name) { + data->draw_proto = true; + + SelectObject(hdc, hFont[FONT_PROTO]); + + RECT tmp_r = r; + int tmp_text_left = text_left; + if (opts.show_protocol_cycle_button) + tmp_r.right -= 2 * ICON_SIZE; + + data->proto_rect = GetRect(hdc, tmp_r, proto->description, _T(""), proto, uFormat, + next_top, tmp_text_left, false, true, false); + + if (opts.show_protocol_cycle_button) { + data->draw_proto_cycle= true; + + RECT prev = r; + prev.top = next_top; + prev.bottom = min(r.bottom, prev.top + ICON_SIZE); + + int diff = (data->proto_rect.bottom - data->proto_rect.top) - (prev.bottom - prev.top); + if (diff < 0) { + diff = -diff / 2; + data->proto_rect.top += diff; + data->proto_rect.bottom += diff; + } + else { + diff = diff / 2; + prev.top += diff; + prev.bottom += diff; + } + + prev.right -= ICON_SIZE; + prev.left = prev.right - ICON_SIZE; + + RECT next = prev; + next.left += ICON_SIZE; + next.right += ICON_SIZE; + + prev.left = max(text_left, prev.left); + prev.right = min(r.right, prev.right); + next.left = max(text_left, next.left); + next.right = min(r.right, next.right); + + data->prev_proto_rect = prev; + data->next_proto_rect = next; + + data->next_proto_tt_hwnd = CreateTooltip(hwnd, data->next_proto_rect); + data->prev_proto_tt_hwnd = CreateTooltip(hwnd, data->prev_proto_rect); + + + next_top = max(data->next_proto_rect.bottom, data->proto_rect.bottom) + SPACE_TEXT_TEXT; + } + else next_top = data->proto_rect.bottom + SPACE_TEXT_TEXT; + } + + // Fits more? + if (next_top + 2 * BORDER_SPACE > r.bottom) + goto finish; + + if (next_top > avatar_bottom && opts.use_avatar_space_to_draw_text) + text_left = r.left; + + // Status data? + { + data->draw_status = true; + + SelectObject(hdc, hFont[FONT_STATUS]); + + // Text size + RECT r_tmp = r; + DrawText(hdc, proto->status_name, _tcslen(proto->status_name), &r_tmp, + DT_CALCRECT | (uFormat & ~DT_END_ELLIPSIS)); + + SIZE s; + s.cy = max(r_tmp.bottom - r_tmp.top, ICON_SIZE); + s.cx = ICON_SIZE + SPACE_ICON_TEXT + r_tmp.right - r_tmp.left; + + // Status global rect + data->status_rect = GetRect(hdc, r, s, uFormat, next_top, text_left, true, false); + + if (proto->status_name[0] != '\0') + data->status_tt_hwnd = CreateTooltip(hwnd, data->status_rect); + + next_top = data->status_rect.bottom + SPACE_TEXT_TEXT; + + RECT rc_inner = data->status_rect; + rc_inner.top += BORDER_SPACE; + rc_inner.bottom -= BORDER_SPACE; + rc_inner.left += BORDER_SPACE; + rc_inner.right -= BORDER_SPACE; + + // Icon + data->status_icon_rect = rc_inner; + + if (opts.draw_text_align_right || opts.draw_text_rtl) + data->status_icon_rect.left = max(data->status_icon_rect.right - ICON_SIZE, rc_inner.left); + else + data->status_icon_rect.right = min(data->status_icon_rect.left + ICON_SIZE, rc_inner.right); + + if (r_tmp.bottom - r_tmp.top > ICON_SIZE) { + data->status_icon_rect.top += (r_tmp.bottom - r_tmp.top - ICON_SIZE) / 2; + data->status_icon_rect.bottom = data->status_icon_rect.top + ICON_SIZE; + } + + // Text + data->status_text_rect = GetInnerRect(rc_inner, r); + + if (opts.draw_text_align_right || opts.draw_text_rtl) + data->status_text_rect.right = max(data->status_icon_rect.left - SPACE_ICON_TEXT, rc_inner.left); + else + data->status_text_rect.left = min(data->status_icon_rect.right + SPACE_ICON_TEXT, rc_inner.right); + + if (ICON_SIZE > r_tmp.bottom - r_tmp.top) { + data->status_text_rect.top += (ICON_SIZE - (r_tmp.bottom - r_tmp.top)) / 2; + data->status_text_rect.bottom = data->status_text_rect.top + r_tmp.bottom - r_tmp.top; + } + } + + // Fits more? + if (next_top + 2 * BORDER_SPACE > r.bottom) + goto finish; + + if (next_top > avatar_bottom && opts.use_avatar_space_to_draw_text) + text_left = r.left; + + // Away msg? + if (proto->CanGetStatusMsg()) { + data->draw_away_msg = true; + + SelectObject(hdc, hFont[FONT_AWAY_MSG]); + + data->away_msg_rect = GetRect(hdc, r, proto->status_message, DEFAULT_STATUS_MESSAGE, proto, uFormat, next_top, text_left); + + if (proto->status_message[0] != '\0') + data->away_msg_tt_hwnd = CreateTooltip(hwnd, data->away_msg_rect); + + next_top = data->away_msg_rect.bottom + SPACE_TEXT_TEXT; + } + + // Fits more? + if (next_top + 2 * BORDER_SPACE > r.bottom) + goto finish; + + if (next_top > avatar_bottom && opts.use_avatar_space_to_draw_text) + text_left = r.left; + + // Listening to + if (proto->ListeningToEnabled() && proto->GetStatus() > ID_STATUS_OFFLINE) { + data->draw_listening_to = true; + + if (proto->listening_to[0] == '\0') { + SelectObject(hdc, hFont[FONT_LISTENING_TO]); + + data->listening_to_rect = GetRect(hdc, r, proto->listening_to, DEFAULT_LISTENING_TO, proto, uFormat, + next_top, text_left); + + data->listening_to_text_rect = data->listening_to_rect; + ZeroMemory(&data->listening_to_icon_rect, sizeof(data->listening_to_icon_rect)); + + next_top = data->listening_to_rect.bottom + SPACE_TEXT_TEXT; + } + else { + SelectObject(hdc, hFont[FONT_LISTENING_TO]); + + // Text size + RECT r_tmp = r; + DrawText(hdc, proto->listening_to, _tcslen(proto->listening_to), &r_tmp, + DT_CALCRECT | (uFormat & ~DT_END_ELLIPSIS)); + + SIZE s; + s.cy = max(r_tmp.bottom - r_tmp.top, ICON_SIZE); + s.cx = ICON_SIZE + SPACE_ICON_TEXT + r_tmp.right - r_tmp.left; + + // listening to global rect + data->listening_to_rect = GetRect(hdc, r, s, uFormat, next_top, text_left, true, false); + + data->listening_to_tt_hwnd = CreateTooltip(hwnd, data->listening_to_rect); + + next_top = data->listening_to_rect.bottom + SPACE_TEXT_TEXT; + + RECT rc_inner = data->listening_to_rect; + rc_inner.top += BORDER_SPACE; + rc_inner.bottom -= BORDER_SPACE; + rc_inner.left += BORDER_SPACE; + rc_inner.right -= BORDER_SPACE; + + // Icon + data->listening_to_icon_rect = rc_inner; + + if (opts.draw_text_align_right || opts.draw_text_rtl) + data->listening_to_icon_rect.left = max(data->listening_to_icon_rect.right - ICON_SIZE, rc_inner.left); + else + data->listening_to_icon_rect.right = min(data->listening_to_icon_rect.left + ICON_SIZE, rc_inner.right); + + if (r_tmp.bottom - r_tmp.top > ICON_SIZE) { + data->listening_to_icon_rect.top += (r_tmp.bottom - r_tmp.top - ICON_SIZE) / 2; + data->listening_to_icon_rect.bottom = data->listening_to_icon_rect.top + ICON_SIZE; + } + + // Text + data->listening_to_text_rect = GetInnerRect(rc_inner, r); + + if (opts.draw_text_align_right || opts.draw_text_rtl) + data->listening_to_text_rect.right = max(data->listening_to_icon_rect.left - SPACE_ICON_TEXT, rc_inner.left); + else + data->listening_to_text_rect.left = min(data->listening_to_icon_rect.right + SPACE_ICON_TEXT, rc_inner.right); + + if (ICON_SIZE > r_tmp.bottom - r_tmp.top) { + data->listening_to_text_rect.top += (ICON_SIZE - (r_tmp.bottom - r_tmp.top)) / 2; + data->listening_to_text_rect.bottom = data->listening_to_text_rect.top + r_tmp.bottom - r_tmp.top; + } + } + } + + r.bottom = max(next_top - SPACE_TEXT_TEXT, avatar_bottom); + + if (opts.resize_frame && ServiceExists(MS_CLIST_FRAMES_SETFRAMEOPTIONS) && frame_id != -1) { + RECT rf; + GetClientRect(hwnd, &rf); + + int size = r.bottom + opts.borders[BOTTOM]; + + if (rf.bottom - rf.top != size) { + if (FrameIsFloating()) { + HWND parent = GetParent(hwnd); + + if (parent != NULL) { + RECT rp_client, rp_window, r_window; + GetClientRect(parent, &rp_client); + GetWindowRect(parent, &rp_window); + GetWindowRect(hwnd, &r_window); + int diff = (rp_window.bottom - rp_window.top) - (rp_client.bottom - rp_client.top); + if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + diff += (r_window.top - rp_window.top); + + SetWindowPos(parent, 0, 0, 0, rp_window.right - rp_window.left, size + diff, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); + } + } + else if (IsWindowVisible(hwnd) && ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) { + int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0); + if (flags & F_VISIBLE) { + CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_HEIGHT, frame_id), (LPARAM)(size)); + CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)frame_id, (LPARAM)(FU_TBREDRAW | FU_FMREDRAW | FU_FMPOS)); + } + } + } + } + +finish: + SelectObject(hdc, hOldFont); + ReleaseDC(hwnd, hdc); +} + + +HBITMAP CreateBitmap32(int cx, int cy) +{ + BITMAPINFO RGB32BitsBITMAPINFO; + UINT * ptPixels; + HBITMAP DirectBitmap; + + ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO)); + RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); + RGB32BitsBITMAPINFO.bmiHeader.biWidth=cx;//bm.bmWidth; + RGB32BitsBITMAPINFO.bmiHeader.biHeight=cy;//bm.bmHeight; + RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1; + RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32; + + DirectBitmap = CreateDIBSection(NULL, + (BITMAPINFO *)&RGB32BitsBITMAPINFO, + DIB_RGB_COLORS, + (void **)&ptPixels, + NULL, 0); + return DirectBitmap; +} + +void EraseBackground(HWND hwnd, HDC hdc, MyDetailsFrameData* data) +{ + RECT r; + GetClientRect(hwnd, &r); + + if (data->skinning) + SkinDrawWindowBack(hwnd, hdc, &r, "Main,ID=Background"); + else { + HBRUSH hB = CreateSolidBrush((COLORREF) DBGetContactSettingDword(NULL,"MyDetails","BackgroundColor",GetSysColor(COLOR_BTNFACE))); + FillRect(hdc, &r, hB); + DeleteObject(hB); + } +} + +void DrawTextWithRect(HDC hdc, const TCHAR *text, const TCHAR *def_text, RECT rc, UINT uFormat, + bool mouse_over, Protocol *proto, bool replace_smileys = true) +{ + const TCHAR *tmp; + if (text[0] == '\0') + tmp = TranslateTS(def_text); + else + tmp = text; + + // Only first line + TCHAR *tmp2 = _tcsdup(tmp); + TCHAR *pos = _tcsrchr(tmp2, '\r'); + if (pos != NULL) pos[0] = '\0'; + pos = _tcschr(tmp2, '\n'); + if (pos != NULL) pos[0] = '\0'; + + + RECT r = rc; + r.top += BORDER_SPACE; + r.bottom -= BORDER_SPACE; + r.left += BORDER_SPACE; + r.right -= BORDER_SPACE; + + HRGN rgn = CreateRectRgnIndirect(&r); + SelectClipRgn(hdc, rgn); + + RECT rc_tmp; + int text_height; + + if (mouse_over) + { + uFormat &= ~DT_END_ELLIPSIS; + + rc_tmp = r; + text_height = DrawText(hdc, _T(" ..."), 4, &rc_tmp, DT_CALCRECT | uFormat); + rc_tmp.top += (r.bottom - r.top - text_height) >> 1; + rc_tmp.bottom = rc_tmp.top + text_height; + + if (uFormat & DT_RTLREADING) + { + rc_tmp.right = r.left + (rc_tmp.right - rc_tmp.left); + rc_tmp.left = r.left; + + r.left += rc_tmp.right - rc_tmp.left; + } + else + { + rc_tmp.left = r.right - (rc_tmp.right - rc_tmp.left); + rc_tmp.right = r.right; + + r.right -= rc_tmp.right - rc_tmp.left; + } + } + + if (replace_smileys) + DRAW_TEXT(hdc, tmp2, _tcslen(tmp2), &r, uFormat, proto->name, NULL); + else + DrawText(hdc, tmp2, _tcslen(tmp2), &r, uFormat); + + if (mouse_over) + { + DrawText(hdc, _T(" ..."), 4, &rc_tmp, uFormat); + } + + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + + if (mouse_over) + FrameRect(hdc, &rc, (HBRUSH) GetStockObject(GRAY_BRUSH)); + + free(tmp2); +} + +void Draw(HWND hwnd, HDC hdc_orig) +{ + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWLP_USERDATA); + Protocol *proto = protocols->Get(data->protocol_number); + + if (proto == NULL) { + EraseBackground(hwnd, hdc_orig, data); + return; + } + + if (data->recalc_rectangles || proto->data_changed) + CalcRectangles(hwnd); + + RECT r_full; + GetClientRect(hwnd, &r_full); + RECT r = r_full; + + HDC hdc = CreateCompatibleDC(hdc_orig); + HBITMAP hBmp = CreateBitmap32(r.right,r.bottom);//,1,GetDeviceCaps(hdc,BITSPIXEL),NULL); + SelectObject(hdc, hBmp); + + int old_bk_mode = SetBkMode(hdc, TRANSPARENT); + HFONT old_font = (HFONT) SelectObject(hdc, hFont[0]); + COLORREF old_color = GetTextColor(hdc); + SetStretchBltMode(hdc, HALFTONE); + + // Erase + EraseBackground(hwnd, hdc, data); + + r.left += min(opts.borders[LEFT], r.right); + r.right = max(r.right - opts.borders[RIGHT], r.left); + r.top += min(opts.borders[TOP], r.bottom); + r.bottom = max(r.bottom - opts.borders[BOTTOM], r.top); + + // Draw items + + UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_END_ELLIPSIS + | (opts.draw_text_align_right ? DT_RIGHT : DT_LEFT) + | (opts.draw_text_rtl ? DT_RTLREADING : 0); + + // Image + if (data->draw_img) + { + RECT rc = GetInnerRect(data->img_rect, r); + HRGN rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + int width = data->img_rect.right - data->img_rect.left; + int height = data->img_rect.bottom - data->img_rect.top; + + int round_radius; + if (opts.draw_avatar_round_corner) + { + if (opts.draw_avatar_use_custom_corner_size) + round_radius = opts.draw_avatar_custom_corner_size; + else + round_radius = min(width, height) / 6; + } + else + { + round_radius = 0; + } + + + AVATARDRAWREQUEST adr = {0}; + adr.cbSize = sizeof(AVATARDRAWREQUEST); + adr.hTargetDC = hdc; + adr.rcDraw = data->img_rect; + + adr.dwFlags = AVDRQ_OWNPIC | AVDRQ_HIDEBORDERONTRANSPARENCY | + (opts.draw_avatar_border ? AVDRQ_DRAWBORDER : 0 ) | + (opts.draw_avatar_round_corner ? AVDRQ_ROUNDEDCORNER : 0 ); + adr.clrBorder = opts.draw_avatar_border_color; + adr.radius = round_radius; + adr.alpha = 255; + adr.szProto = proto->name; + + CallService(MS_AV_DRAWAVATAR, 0, (LPARAM) &adr); + + // Clipping rgn + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + } + + // Nick + if (data->draw_nick) + { + RECT rc = GetInnerRect(data->nick_rect, r); + HRGN rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + SelectObject(hdc, hFont[FONT_NICK]); + SetTextColor(hdc, font_colour[FONT_NICK]); + + DrawTextWithRect(hdc, proto->nickname, DEFAULT_NICKNAME, rc, uFormat, + data->mouse_over_nick && proto->CanSetNick(), proto); + + // Clipping rgn + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + } + + // Protocol cycle icon + if (data->draw_proto_cycle) + { + RECT rc = GetInnerRect(data->next_proto_rect, r); + HRGN rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + HICON icon = Skin_GetIcon("MYDETAILS_NEXT_PROTOCOL"); + if (icon == NULL) + icon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RIGHT_ARROW)); + DrawIconEx(hdc, data->next_proto_rect.left, data->next_proto_rect.top, icon, ICON_SIZE, ICON_SIZE, 0, NULL, DI_NORMAL); + Skin_ReleaseIcon(icon); + + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + + rc = GetInnerRect(data->prev_proto_rect, r); + rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + icon = Skin_GetIcon("MYDETAILS_PREV_PROTOCOL"); + if (icon == NULL) + icon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RIGHT_ARROW)); + DrawIconEx(hdc, data->prev_proto_rect.left, data->prev_proto_rect.top, icon, ICON_SIZE, ICON_SIZE, 0, NULL, DI_NORMAL); + Skin_ReleaseIcon(icon); + + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + } + + // Protocol + if (data->draw_proto) + { + RECT rc = GetInnerRect(data->proto_rect, r); + RECT rr = rc; + rr.top += BORDER_SPACE; + rr.bottom -= BORDER_SPACE; + rr.left += BORDER_SPACE; + rr.right -= BORDER_SPACE; + + HRGN rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + SelectObject(hdc, hFont[FONT_PROTO]); + SetTextColor(hdc, font_colour[FONT_PROTO]); + + DrawText(hdc, proto->description, _tcslen(proto->description), &rr, uFormat); + + // Clipping rgn + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + + if (data->mouse_over_proto) + FrameRect(hdc, &rc, (HBRUSH) GetStockObject(GRAY_BRUSH)); + } + + // Status + if (data->draw_status) + { + RECT rtmp = GetInnerRect(data->status_rect, r); + RECT rr = rtmp; + rr.top += BORDER_SPACE; + rr.bottom -= BORDER_SPACE; + rr.left += BORDER_SPACE; + rr.right -= BORDER_SPACE; + + RECT rc = GetInnerRect(data->status_icon_rect, rr); + HRGN rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + HICON status_icon; + if (proto->custom_status != 0 && ProtoServiceExists(proto->name, PS_ICQ_GETCUSTOMSTATUSICON)) + { + status_icon = (HICON) CallProtoService(proto->name, PS_ICQ_GETCUSTOMSTATUSICON, proto->custom_status, 0); + } + else + { + status_icon = LoadSkinnedProtoIcon(proto->name, proto->status); + } + if (status_icon != NULL) + { + DrawIconEx(hdc, data->status_icon_rect.left, data->status_icon_rect.top, status_icon, + ICON_SIZE, ICON_SIZE, 0, NULL, DI_NORMAL); + DeleteObject(status_icon); + } + + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + + rc = GetInnerRect(data->status_text_rect, rr); + rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + SelectObject(hdc, hFont[FONT_STATUS]); + SetTextColor(hdc, font_colour[FONT_STATUS]); + + DrawText(hdc, proto->status_name, _tcslen(proto->status_name), &rc, uFormat); + + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + + if (data->mouse_over_status) + FrameRect(hdc, &rtmp, (HBRUSH) GetStockObject(GRAY_BRUSH)); + } + + // Away message + if (data->draw_away_msg) + { + RECT rc = GetInnerRect(data->away_msg_rect, r); + HRGN rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + SelectObject(hdc, hFont[FONT_AWAY_MSG]); + SetTextColor(hdc, font_colour[FONT_AWAY_MSG]); + + DrawTextWithRect(hdc, proto->status_message, DEFAULT_STATUS_MESSAGE, rc, uFormat, + data->mouse_over_away_msg && proto->CanSetStatusMsg(), proto); + + // Clipping rgn + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + } + + // Listening to + if (data->draw_listening_to) + { + if (data->listening_to_icon_rect.left == 0 && data->listening_to_icon_rect.right == 0) + { + RECT rc = GetInnerRect(data->listening_to_rect, r); + HRGN rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + SelectObject(hdc, hFont[FONT_LISTENING_TO]); + SetTextColor(hdc, font_colour[FONT_LISTENING_TO]); + + DrawTextWithRect(hdc, proto->listening_to, DEFAULT_LISTENING_TO, rc, uFormat, + data->mouse_over_listening_to && protocols->CanSetListeningTo(), proto); + + // Clipping rgn + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + } + else + { + RECT rtmp = GetInnerRect(data->listening_to_rect, r); + RECT rr = rtmp; + rr.top += BORDER_SPACE; + rr.bottom -= BORDER_SPACE; + rr.left += BORDER_SPACE; + rr.right -= BORDER_SPACE; + + RECT rc = GetInnerRect(data->listening_to_icon_rect, rr); + HRGN rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + HICON icon = Skin_GetIcon("LISTENING_TO_ICON"); + if (icon == NULL) + icon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_LISTENINGTO)); + DrawIconEx(hdc, data->listening_to_icon_rect.left, data->listening_to_icon_rect.top, icon, ICON_SIZE, ICON_SIZE, 0, NULL, DI_NORMAL); + Skin_ReleaseIcon(icon); + + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + + rc = GetInnerRect(data->listening_to_text_rect, rr); + rgn = CreateRectRgnIndirect(&rc); + SelectClipRgn(hdc, rgn); + + SelectObject(hdc, hFont[FONT_LISTENING_TO]); + SetTextColor(hdc, font_colour[FONT_LISTENING_TO]); + + DrawText(hdc, proto->listening_to, _tcslen(proto->listening_to), &rc, uFormat); + + SelectClipRgn(hdc, NULL); + DeleteObject(rgn); + + if (data->mouse_over_listening_to && protocols->CanSetListeningTo()) + FrameRect(hdc, &rtmp, (HBRUSH) GetStockObject(GRAY_BRUSH)); + } + } + + SelectObject(hdc, old_font); + SetTextColor(hdc, old_color); + SetBkMode(hdc, old_bk_mode); + + BitBlt(hdc_orig, r_full.left, r_full.top, r_full.right - r_full.left, + r_full.bottom - r_full.top, hdc, r_full.left, r_full.top, SRCCOPY); + DeleteDC(hdc); + DeleteObject(hBmp); +} + +bool InsideRect(POINT *p, RECT *r) +{ + return p->x >= r->left && p->x < r->right && p->y >= r->top && p->y < r->bottom; +} + +void MakeHover(HWND hwnd, bool draw, bool *hover, POINT *p, RECT *r) +{ + if (draw && p != NULL && r != NULL && InsideRect(p, r)) + { + if ( !*hover) + { + *hover = true; + + InvalidateRect(hwnd, NULL, FALSE); + + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hwnd; + tme.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&tme); + } + } + else + { + if (*hover) + { + *hover = false; + + InvalidateRect(hwnd, NULL, FALSE); + } + } +} + +void ShowGlobalStatusMenu(HWND hwnd, MyDetailsFrameData *data, Protocol *proto, POINT &p) +{ + HMENU submenu = (HMENU) CallService(MS_CLIST_MENUGETSTATUS,0,0); + + if (opts.draw_text_align_right) + p.x = data->status_rect.right; + else + p.x = data->status_rect.left; + p.y = data->status_rect.bottom+1; + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD + | (opts.draw_text_align_right ? TPM_RIGHTALIGN : TPM_LEFTALIGN), p.x, p.y, 0, hwnd, NULL); + + if (ret) + CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(ret),MPCF_MAINMENU),(LPARAM)NULL); +} + +void ShowProtocolStatusMenu(HWND hwnd, MyDetailsFrameData *data, Protocol *proto, POINT &p) +{ + HMENU menu = (HMENU) CallService(MS_CLIST_MENUGETSTATUS,0,0); + HMENU submenu = NULL; + + if (menu != NULL) + { + // Find the correct menu item + int count = GetMenuItemCount(menu); + for (int i = 0 ; i < count && submenu == NULL; i++) + { + MENUITEMINFO mii = {0}; + + mii.cbSize = sizeof(mii); + + if (!IsWinVer98Plus()) + mii.fMask = MIIM_TYPE; + else + mii.fMask = MIIM_STRING; + + GetMenuItemInfo(menu, i, TRUE, &mii); + + if (mii.cch != 0) { + mii.cch++; + mii.dwTypeData = (TCHAR*)malloc(sizeof(TCHAR) * mii.cch); + GetMenuItemInfo(menu, i, TRUE, &mii); + + if ( _tcscmp(mii.dwTypeData, proto->description) == 0) + submenu = GetSubMenu(menu, i); + + free(mii.dwTypeData); + } + } + + if (submenu == NULL && protocols->GetSize() == 1) + { + submenu = menu; + } + } + + if (submenu != NULL) + { + if (opts.draw_text_align_right) + p.x = data->status_rect.right; + else + p.x = data->status_rect.left; + p.y = data->status_rect.bottom+1; + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD + | (opts.draw_text_align_right ? TPM_RIGHTALIGN : TPM_LEFTALIGN), p.x, p.y, 0, hwnd, NULL); + + if (ret) + CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(ret),MPCF_MAINMENU),(LPARAM)NULL); + + /* + if (to_remove < 5) + { + DestroyMenu(submenu); + } + */ + } + else + { + // Well, lets do it by hand + static int statusModePf2List[]={0xFFFFFFFF,PF2_ONLINE,PF2_SHORTAWAY,PF2_LONGAWAY,PF2_LIGHTDND,PF2_HEAVYDND,PF2_FREECHAT,PF2_INVISIBLE,PF2_ONTHEPHONE,PF2_OUTTOLUNCH}; + + menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); + submenu = GetSubMenu(menu, 0); + CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0); + + DWORD flags = CallProtoService(proto->name, PS_GETCAPS, PFLAGNUM_2,0); + for ( int i = GetMenuItemCount(submenu) -1 ; i >= 0 ; i-- ) + { + if ( !(flags & statusModePf2List[i])) + { + // Hide menu + RemoveMenu(submenu, i, MF_BYPOSITION); + } + } + + if (opts.draw_text_align_right) + p.x = data->status_rect.right; + else + p.x = data->status_rect.left; + p.y = data->status_rect.bottom+1; + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD + | (opts.draw_text_align_right ? TPM_RIGHTALIGN : TPM_LEFTALIGN), p.x, p.y, 0, hwnd, NULL); + DestroyMenu(menu); + if (ret) + { + proto->SetStatus(ret); + } + } +} + +void ShowListeningToMenu(HWND hwnd, MyDetailsFrameData *data, Protocol *proto, POINT &p) +{ + HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); + HMENU submenu = GetSubMenu(menu, 5); + CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0); + + // Add this proto to menu + TCHAR tmp[128]; + mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("Enable Listening To for %s"), proto->description); + + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; + mii.fType = MFT_STRING; + mii.fState = proto->ListeningToEnabled() ? MFS_CHECKED : 0; + mii.dwTypeData = tmp; + mii.cch = _tcslen(tmp); + mii.wID = 1; + + if ( !proto->CanSetListeningTo()) + { + mii.fState |= MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STATE; + mii.fState = protocols->ListeningToEnabled() ? MFS_CHECKED : 0; + + if ( !protocols->CanSetListeningTo()) + { + mii.fState |= MFS_DISABLED; + } + + SetMenuItemInfo(submenu, ID_LISTENINGTOPOPUP_SENDLISTENINGTO, FALSE, &mii); + + if (opts.draw_text_align_right) + p.x = data->listening_to_rect.right; + else + p.x = data->listening_to_rect.left; + p.y = data->listening_to_rect.bottom+1; + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD + | (opts.draw_text_align_right ? TPM_RIGHTALIGN : TPM_LEFTALIGN), p.x, p.y, 0, hwnd, NULL); + DestroyMenu(menu); + + switch(ret) + { + case 1: + { + CallService(MS_LISTENINGTO_ENABLE, (LPARAM) proto->name, !proto->ListeningToEnabled()); + break; + } + case ID_LISTENINGTOPOPUP_SENDLISTENINGTO: + { + CallService(MS_LISTENINGTO_ENABLE, 0, !protocols->ListeningToEnabled()); + break; + } + } + +} + + +LRESULT CALLBACK FrameWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_CREATE: + { + MyDetailsFrameData *data = new MyDetailsFrameData(); + ZeroMemory(data, sizeof(MyDetailsFrameData)); + SetWindowLong(hwnd, GWLP_USERDATA, (LONG) data); + + data->recalc_rectangles = true; + data->get_status_messages = false; + data->showing_menu = false; + data->skinning = ServiceExists(MS_SKIN_DRAWGLYPH) != 0; + + data->protocol_number = DBGetContactSettingWord(NULL,"MyDetails","ProtocolNumber",0); + if (data->protocol_number >= protocols->GetSize()) + data->protocol_number = 0; + + SetCycleTime(hwnd); + SetStatusMessageRefreshTime(hwnd); + + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_HOVER | TME_LEAVE; + tme.hwndTrack = hwnd; + tme.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&tme); + + return TRUE; + } + + case WM_PRINTCLIENT: + Draw(hwnd, (HDC)wParam); + return TRUE; + + case WM_PAINT: + { + RECT r; + + if (GetUpdateRect(hwnd, &r, FALSE)) + { + PAINTSTRUCT ps; + + HDC hdc = BeginPaint(hwnd, &ps); + Draw(hwnd, hdc); + EndPaint(hwnd, &ps); + } + + return TRUE; + } + + case WM_SIZE: + { + //InvalidateRect(hwnd, NULL, FALSE); + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWLP_USERDATA); + data->recalc_rectangles = true; + RedrawFrame(); + break; + } + + case WM_TIMER: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWLP_USERDATA); + + if (wParam == ID_FRAME_TIMER) + { + if ( !data->showing_menu) + CallService(MS_MYDETAILS_SHOWNEXTPROTOCOL, 0, 0); + } + else if (wParam == ID_RECALC_TIMER) + { + KillTimer(hwnd, ID_RECALC_TIMER); + + if (data->get_status_messages) + { + SetStatusMessageRefreshTime(hwnd); + data->get_status_messages = false; + + protocols->GetStatuses(); + protocols->GetStatusMsgs(); + + data->recalc_rectangles = true; + } + + RedrawFrame(); + } + else if (wParam == ID_STATUSMESSAGE_TIMER) + { + SetStatusMessageRefreshTime(hwnd); + + PostMessage(hwnd, MWM_STATUS_MSG_CHANGED, 0, 0); + } + + return TRUE; + } + + case WM_LBUTTONUP: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWLP_USERDATA); + Protocol *proto = protocols->Get(data->protocol_number); + if (proto == NULL) + break; + + POINT p; + p.x = LOWORD(lParam); + p.y = HIWORD(lParam); + + // In image? + if (data->draw_img && InsideRect(&p, &data->img_rect) && proto->CanSetAvatar()) + { + if (opts.global_on_avatar) + CallService(MS_MYDETAILS_SETMYAVATARUI, 0, 0); + else + CallService(MS_MYDETAILS_SETMYAVATARUI, 0, (LPARAM) proto->name); + } + // In nick? + else if (data->draw_nick && InsideRect(&p, &data->nick_rect) && proto->CanSetNick()) + { + if (opts.global_on_nickname) + CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, 0); + else + CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, (LPARAM) proto->name); + } + // In proto cycle button? + else if (data->draw_proto_cycle && InsideRect(&p, &data->next_proto_rect)) + { + CallService(MS_MYDETAILS_SHOWNEXTPROTOCOL, 0, 0); + } + else if (data->draw_proto_cycle && InsideRect(&p, &data->prev_proto_rect)) + { + CallService(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL, 0, 0); + } + // In status message? + else if (data->draw_away_msg && InsideRect(&p, &data->away_msg_rect) && proto->CanSetStatusMsg()) + { + if (opts.global_on_status_message) + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, 0); + else + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, (LPARAM) proto->name); + } + // In status? + else if (data->draw_status && InsideRect(&p, &data->status_rect)) + { + data->showing_menu = true; + + if (opts.global_on_status) + ShowGlobalStatusMenu(hwnd, data, proto, p); + else + ShowProtocolStatusMenu(hwnd, data, proto, p); + + data->showing_menu = false; + } + // In listening to? + else if (data->draw_listening_to && InsideRect(&p, &data->listening_to_rect) && protocols->CanSetListeningTo()) + { + ShowListeningToMenu(hwnd, data, proto, p); + } + // In protocol? + else if (data->draw_proto && InsideRect(&p, &data->proto_rect)) + { + data->showing_menu = true; + + HMENU menu = CreatePopupMenu(); + + for (int i = protocols->GetSize() - 1 ; i >= 0 ; i--) + { + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = protocols->Get(i)->description; + mii.cch = _tcslen(protocols->Get(i)->description); + mii.wID = i + 1; + + if (i == data->protocol_number) { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(menu, 0, TRUE, &mii); + } + + if (opts.draw_text_align_right) + p.x = data->proto_rect.right; + else + p.x = data->proto_rect.left; + p.y = data->proto_rect.bottom+1; + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(menu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL); + DestroyMenu(menu); + + if (ret != 0) + { + PluginCommand_ShowProtocol(NULL, (WPARAM) protocols->Get(ret-1)->name); + } + + data->showing_menu = false; + } + + break; + } + + case WM_MEASUREITEM: + { + return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam); + } + case WM_DRAWITEM: + { + return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam); + } + + case WM_CONTEXTMENU: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWLP_USERDATA); + Protocol *proto = protocols->Get(data->protocol_number); + if (proto == NULL) + break; + + POINT p; + p.x = LOWORD(lParam); + p.y = HIWORD(lParam); + + ScreenToClient(hwnd, &p); + + data->showing_menu = true; + + // In image? + if (data->draw_img && InsideRect(&p, &data->img_rect)) + { + HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); + HMENU submenu = GetSubMenu(menu, 4); + CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0); + + // Add this proto to menu + TCHAR tmp[128]; + mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("Set My Avatar for %s..."), proto->description); + + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = _tcslen(tmp); + mii.wID = 1; + + if ( !proto->CanSetAvatar()) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL); + DestroyMenu(menu); + + switch(ret) + { + case 1: + { + CallService(MS_MYDETAILS_SETMYAVATARUI, 0, (LPARAM) proto->name); + break; + } + case ID_AVATARPOPUP_SETMYAVATAR: + { + CallService(MS_MYDETAILS_SETMYAVATARUI, 0, 0); + break; + } + } + } + // In nick? + else if (data->draw_nick && InsideRect(&p, &data->nick_rect)) + { + HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); + HMENU submenu = GetSubMenu(menu, 2); + CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0); + + // Add this proto to menu + TCHAR tmp[128]; + mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("Set My Nickname for %s..."), proto->description); + + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = _tcslen(tmp); + mii.wID = 1; + + if ( !proto->CanSetNick()) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL); + DestroyMenu(menu); + + switch(ret) + { + case 1: + { + CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, (LPARAM) proto->name); + break; + } + case ID_NICKPOPUP_SETMYNICKNAME: + { + CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, 0); + break; + } + } + } + // In proto cycle button? + else if (data->draw_proto_cycle && InsideRect(&p, &data->next_proto_rect)) + { + CallService(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL, 0, 0); + } + else if (data->draw_proto_cycle && InsideRect(&p, &data->prev_proto_rect)) + { + CallService(MS_MYDETAILS_SHOWNEXTPROTOCOL, 0, 0); + } + // In status message? + else if (data->draw_away_msg && InsideRect(&p, &data->away_msg_rect)) + { + TCHAR tmp[128]; + + HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); + HMENU submenu = GetSubMenu(menu, 3); + TranslateMenu(submenu); + + if (protocols->CanSetStatusMsgPerProtocol()) { + // Add this proto to menu + mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("Set My Status Message for %s..."), proto->description); + + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = _tcslen(tmp); + mii.wID = 1; + + if ( !proto->CanSetStatusMsg()) { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + } + + // Add this to menu + mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("Set My Status Message for %s..."), + CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, proto->status, GSMDF_TCHAR)); + + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = _tcslen(tmp); + mii.wID = 2; + + if (proto->status == ID_STATUS_OFFLINE) { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL); + DestroyMenu(menu); + + switch(ret) { + case 1: + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, (LPARAM) proto->name); + break; + + case 2: + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, (WPARAM) proto->status, 0); + break; + + case ID_STATUSMESSAGEPOPUP_SETMYSTATUSMESSAGE: + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, 0); + break; + } + } + // In status? + else if (data->draw_status && InsideRect(&p, &data->status_rect)) + { + if (opts.global_on_status) + ShowProtocolStatusMenu(hwnd, data, proto, p); + else + ShowGlobalStatusMenu(hwnd, data, proto, p); + } + // In listening to? + else if (data->draw_listening_to && InsideRect(&p, &data->listening_to_rect) && protocols->CanSetListeningTo()) + { + ShowListeningToMenu(hwnd, data, proto, p); + } + // In protocol? + else if (data->draw_proto && InsideRect(&p, &data->proto_rect)) + { + } + // Default context menu + else + { + HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); + HMENU submenu = GetSubMenu(menu, 1); + CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0); + + if (opts.cycle_through_protocols) + RemoveMenu(submenu, ID_CYCLE_THROUGH_PROTOS, MF_BYCOMMAND); + else + RemoveMenu(submenu, ID_DONT_CYCLE_THROUGH_PROTOS, MF_BYCOMMAND); + + // Add this proto to menu + TCHAR tmp[128]; + MENUITEMINFO mii = {0}; + + mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("Enable Listening To for %s"), proto->description); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE; + mii.fType = MFT_STRING; + mii.fState = proto->ListeningToEnabled() ? MFS_CHECKED : 0; + mii.dwTypeData = tmp; + mii.cch = _tcslen(tmp); + mii.wID = 5; + + if ( !proto->CanSetListeningTo()) + { + mii.fState |= MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + // Add this to menu + mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("Set My Status Message for %s..."), + CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, proto->status, GSMDF_TCHAR)); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = _tcslen(tmp); + mii.wID = 4; + + if (proto->status == ID_STATUS_OFFLINE) { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + if (protocols->CanSetStatusMsgPerProtocol()) + { + // Add this proto to menu + mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("Set My Status Message for %s..."), proto->description); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = _tcslen(tmp); + mii.wID = 3; + + if ( !proto->CanSetStatusMsg()) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + } + + mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("Set My Nickname for %s..."), proto->description); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = _tcslen(tmp); + mii.wID = 2; + + if ( !proto->CanSetNick()) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("Set My Avatar for %s..."), proto->description); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID | MIIM_TYPE; + mii.fType = MFT_STRING; + mii.dwTypeData = tmp; + mii.cch = _tcslen(tmp); + mii.wID = 1; + + if ( !proto->CanSetAvatar()) + { + mii.fMask |= MIIM_STATE; + mii.fState = MFS_DISABLED; + } + + InsertMenuItem(submenu, 0, TRUE, &mii); + + ZeroMemory(&mii, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STATE; + mii.fState = protocols->ListeningToEnabled() ? MFS_CHECKED : 0; + + if ( !protocols->CanSetListeningTo()) + { + mii.fState |= MFS_DISABLED; + } + + SetMenuItemInfo(submenu, ID_CONTEXTPOPUP_ENABLELISTENINGTO, FALSE, &mii); + + ClientToScreen(hwnd, &p); + + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL); + DestroyMenu(menu); + + switch(ret) + { + case 1: + { + CallService(MS_MYDETAILS_SETMYAVATARUI, 0, (LPARAM) proto->name); + break; + } + case ID_AVATARPOPUP_SETMYAVATAR: + { + CallService(MS_MYDETAILS_SETMYAVATARUI, 0, 0); + break; + } + case 2: + { + CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, (LPARAM) proto->name); + break; + } + case ID_NICKPOPUP_SETMYNICKNAME: + { + CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, 0); + break; + } + case 3: + { + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, (LPARAM) proto->name); + break; + } + case 4: + { + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, (WPARAM) proto->status, 0); + break; + } + case ID_STATUSMESSAGEPOPUP_SETMYSTATUSMESSAGE: + { + CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, 0); + break; + } + case 5: + { + CallService(MS_LISTENINGTO_ENABLE, (LPARAM) proto->name, !proto->ListeningToEnabled()); + break; + } + case ID_CONTEXTPOPUP_ENABLELISTENINGTO: + { + CallService(MS_LISTENINGTO_ENABLE, 0, !protocols->ListeningToEnabled()); + break; + } + case ID_SHOW_NEXT_PROTO: + { + CallService(MS_MYDETAILS_SHOWNEXTPROTOCOL, 0, 0); + break; + } + case ID_SHOW_PREV_PROTO: + { + CallService(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL, 0, 0); + break; + } + case ID_CYCLE_THROUGH_PROTOS: + { + CallService(MS_MYDETAILS_CYCLE_THROUGH_PROTOCOLS, TRUE, 0); + break; + } + case ID_DONT_CYCLE_THROUGH_PROTOS: + { + CallService(MS_MYDETAILS_CYCLE_THROUGH_PROTOCOLS, FALSE, 0); + break; + } + } + } + + data->showing_menu = false; + + + break; + } + + case WM_MOUSELEAVE: + { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_HOVER; + tme.hwndTrack = hwnd; + tme.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&tme); + } + case WM_NCMOUSEMOVE: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWLP_USERDATA); + + MakeHover(hwnd, data->draw_img, &data->mouse_over_img, NULL, NULL); + MakeHover(hwnd, data->draw_nick, &data->mouse_over_nick, NULL, NULL); + MakeHover(hwnd, data->draw_proto, &data->mouse_over_proto, NULL, NULL); + MakeHover(hwnd, data->draw_status, &data->mouse_over_status, NULL, NULL); + MakeHover(hwnd, data->draw_away_msg, &data->mouse_over_away_msg, NULL, NULL); + MakeHover(hwnd, data->draw_listening_to, &data->mouse_over_listening_to, NULL, NULL); + + break; + } + + case WM_MOUSEHOVER: + { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hwnd; + tme.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&tme); + } + case WM_MOUSEMOVE: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWLP_USERDATA); + Protocol *proto = protocols->Get(data->protocol_number); + if (proto == NULL) + break; + + POINT p; + p.x = LOWORD(lParam); + p.y = HIWORD(lParam); + + MakeHover(hwnd, data->draw_img, &data->mouse_over_img, &p, &data->img_rect); + MakeHover(hwnd, data->draw_nick, &data->mouse_over_nick, &p, &data->nick_rect); + MakeHover(hwnd, data->draw_proto, &data->mouse_over_proto, &p, &data->proto_rect); + MakeHover(hwnd, data->draw_status, &data->mouse_over_status, &p, &data->status_rect); + MakeHover(hwnd, data->draw_away_msg, &data->mouse_over_away_msg, &p, &data->away_msg_rect); + MakeHover(hwnd, data->draw_listening_to, &data->mouse_over_listening_to, &p, &data->listening_to_rect); + + break; + } + + case WM_NOTIFY: + { + LPNMHDR lpnmhdr = (LPNMHDR) lParam; + + int i = (int) lpnmhdr->code; + + switch (lpnmhdr->code) { + case TTN_GETDISPINFO: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWLP_USERDATA); + Protocol *proto = protocols->Get(data->protocol_number); + + LPNMTTDISPINFO lpttd = (LPNMTTDISPINFO) lpnmhdr; + SendMessage(lpnmhdr->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 300); + + if (lpnmhdr->hwndFrom == data->nick_tt_hwnd) + lpttd->lpszText = proto->nickname; + else if (lpnmhdr->hwndFrom == data->status_tt_hwnd) + lpttd->lpszText = proto->status_name; + else if (lpnmhdr->hwndFrom == data->away_msg_tt_hwnd) + lpttd->lpszText = proto->status_message; + else if (lpnmhdr->hwndFrom == data->listening_to_tt_hwnd) + lpttd->lpszText = proto->listening_to; + else if (lpnmhdr->hwndFrom == data->next_proto_tt_hwnd) + lpttd->lpszText = _T("Show next protocol"); + else if (lpnmhdr->hwndFrom == data->prev_proto_tt_hwnd) + lpttd->lpszText = _T("Show previous protocol"); + + return 0; + } + } + + break; + } + + case WM_DESTROY: + { + KillTimer(hwnd, ID_FRAME_TIMER); + + MyDetailsFrameData *tmp = (MyDetailsFrameData *)GetWindowLong(hwnd, GWLP_USERDATA); + DeleteTooltipWindows(tmp); + if (tmp != NULL) delete tmp; + + break; + } + + // Custom Messages ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + case MWM_REFRESH: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWLP_USERDATA); +// data->recalc_rectangles = true; + + KillTimer(hwnd, ID_RECALC_TIMER); + SetTimer(hwnd, ID_RECALC_TIMER, RECALC_TIME, NULL); + break; + } + + case MWM_AVATAR_CHANGED: + { + Protocol *proto = protocols->Get((const char *) wParam); + + if (proto != NULL) + { + proto->GetAvatar(); + RefreshFrame(); + } + + break; + } + + case MWM_NICK_CHANGED: + { + Protocol *proto = protocols->Get((const char *) wParam); + + if (proto != NULL) + { + proto->GetNick(); + RefreshFrame(); + } + + break; + } + + case MWM_STATUS_CHANGED: + { + Protocol *proto = protocols->Get((const char *) wParam); + + if (proto != NULL) + { + proto->GetStatus(); + proto->GetStatusMsg(); + proto->GetNick(); + + RefreshFrame(); + } + + break; + } + + case MWM_STATUS_MSG_CHANGED: + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWLP_USERDATA); + data->get_status_messages = true; + + RefreshFrame(); + break; + } + + case MWM_LISTENINGTO_CHANGED: + { + if (wParam != NULL) + { + Protocol *proto = protocols->Get((const char *) wParam); + if (proto != NULL) + proto->GetListeningTo(); + } + + RefreshFrameAndCalcRects(); + break; + } + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + + +INT_PTR ShowHideFrameFunc(WPARAM wParam, LPARAM lParam) +{ + if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + { + CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0); + } + else + { + if (MyDetailsFrameVisible()) + { + SendMessage(hwnd_container, WM_CLOSE, 0, 0); + } + else + { + ShowWindow(hwnd_container, SW_SHOW); + DBWriteContactSettingByte(0, MODULE_NAME, SETTING_FRAME_VISIBLE, 1); + } + + FixMainMenu(); + } + return 0; +} + + +INT_PTR ShowFrameFunc(WPARAM wParam, LPARAM lParam) +{ + if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + { + int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0); + if (!(flags & F_VISIBLE)) + CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0); + } + else + { + if ( !MyDetailsFrameVisible()) + { + ShowWindow(hwnd_container, SW_SHOW); + DBWriteContactSettingByte(0, MODULE_NAME, SETTING_FRAME_VISIBLE, 1); + + FixMainMenu(); + } + + } + return 0; +} + + +INT_PTR HideFrameFunc(WPARAM wParam, LPARAM lParam) +{ + if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) + { + int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0); + if (flags & F_VISIBLE) + CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0); + } + else + { + if (MyDetailsFrameVisible()) + { + SendMessage(hwnd_container, WM_CLOSE, 0, 0); + + FixMainMenu(); + } + } + return 0; +} + + +void FixMainMenu() +{ + CLISTMENUITEM mi = {0}; + mi.cbSize = sizeof(CLISTMENUITEM); + mi.flags = CMIM_NAME; + + if (MyDetailsFrameVisible()) + mi.pszName = Translate("Hide My Details"); + else + mi.pszName = Translate("Show My Details"); + + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuShowHideFrame, (LPARAM)&mi); +} + +#include + +void RedrawFrame() +{ + if (frame_id == -1) + InvalidateRect(hwnd_container, NULL, TRUE); + else + CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)frame_id, (LPARAM)FU_TBREDRAW | FU_FMREDRAW); +} + +void RefreshFrameAndCalcRects() +{ + if (hwnd_frame != NULL) + { + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd_frame, GWLP_USERDATA); + data->recalc_rectangles = true; + + PostMessage(hwnd_frame, MWM_REFRESH, 0, 0); + } +} + +void RefreshFrame() +{ + if (hwnd_frame != NULL) + PostMessage(hwnd_frame, MWM_REFRESH, 0, 0); +} + +// only used when no multiwindow functionality is available +bool MyDetailsFrameVisible() +{ + return IsWindowVisible(hwnd_container) ? true : false; +} + +void SetMyDetailsFrameVisible(bool visible) +{ + if (frame_id == -1 && hwnd_container != 0) + { + ShowWindow(hwnd_container, visible ? SW_SHOW : SW_HIDE); + } +} + +void SetCycleTime() +{ + if (hwnd_frame != NULL) + SetCycleTime(hwnd_frame); +} + +void SetCycleTime(HWND hwnd) +{ + KillTimer(hwnd, ID_FRAME_TIMER); + + if (opts.cycle_through_protocols) + SetTimer(hwnd, ID_FRAME_TIMER, opts.seconds_to_show_protocol * 1000, 0); +} + +void SetStatusMessageRefreshTime() +{ + if (hwnd_frame != NULL) + SetStatusMessageRefreshTime(hwnd_frame); +} + +void SetStatusMessageRefreshTime(HWND hwnd) +{ + KillTimer(hwnd, ID_STATUSMESSAGE_TIMER); + + opts.refresh_status_message_timer = DBGetContactSettingWord(NULL,"MyDetails","RefreshStatusMessageTimer",12); + if (opts.refresh_status_message_timer > 0) + { + SetTimer(hwnd, ID_STATUSMESSAGE_TIMER, opts.refresh_status_message_timer * 1000, NULL); + } +} + +INT_PTR PluginCommand_ShowNextProtocol(WPARAM wParam,LPARAM lParam) +{ + if (hwnd_frame == NULL) + return -1; + + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd_frame, GWLP_USERDATA); + + data->protocol_number ++; + if (data->protocol_number >= protocols->GetSize()) + { + data->protocol_number = 0; + } + + DBWriteContactSettingWord(NULL,"MyDetails","ProtocolNumber",data->protocol_number); + + data->recalc_rectangles = true; + + SetCycleTime(); + + RedrawFrame(); + + return 0; +} + +INT_PTR PluginCommand_ShowPreviousProtocol(WPARAM wParam,LPARAM lParam) +{ + if (hwnd_frame == NULL) + return -1; + + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd_frame, GWLP_USERDATA); + + data->protocol_number --; + if (data->protocol_number < 0) + { + data->protocol_number = protocols->GetSize() - 1; + } + + DBWriteContactSettingWord(NULL,"MyDetails","ProtocolNumber",data->protocol_number); + + data->recalc_rectangles = true; + + SetCycleTime(); + + RedrawFrame(); + + return 0; +} + +INT_PTR PluginCommand_ShowProtocol(WPARAM wParam,LPARAM lParam) +{ + char * proto = (char *)lParam; + int proto_num = -1; + + if (proto == NULL) + return -1; + + for (int i = 0 ; i < protocols->GetSize() ; i++) + { + if (_stricmp(protocols->Get(i)->name, proto) == 0) + { + proto_num = i; + break; + } + } + + if (proto_num == -1) + return -2; + + if (hwnd_frame == NULL) + return -3; + + MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd_frame, GWLP_USERDATA); + + data->protocol_number = proto_num; + DBWriteContactSettingWord(NULL,"MyDetails","ProtocolNumber",data->protocol_number); + + data->recalc_rectangles = true; + + SetCycleTime(); + + RedrawFrame(); + + return 0; +} + +int SettingsChangedHook(WPARAM wParam, LPARAM lParam) +{ + if (hwnd_frame == NULL) + return 0; + + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam; + + if ((HANDLE)wParam == NULL) + { + Protocol *proto = protocols->Get((const char *) cws->szModule); + + if ( !strcmp(cws->szSetting,"Status") + || ( proto != NULL && proto->custom_status != 0 + && proto->custom_status_name != NULL + && !strcmp(cws->szSetting, _T2A(proto->custom_status_name))) + || ( proto != NULL && proto->custom_status != 0 + && proto->custom_status_message != NULL + && !strcmp(cws->szSetting, _T2A(proto->custom_status_message)))) + { + // Status changed + if (proto != NULL) + PostMessage(hwnd_frame, MWM_STATUS_CHANGED, (WPARAM) proto->name, 0); + } + else if (!strcmp(cws->szSetting,"MyHandle") + || !strcmp(cws->szSetting,"UIN") + || !strcmp(cws->szSetting,"Nick") + || !strcmp(cws->szSetting,"FirstName") + || !strcmp(cws->szSetting,"e-mail") + || !strcmp(cws->szSetting,"LastName") + || !strcmp(cws->szSetting,"JID")) + { + // Name changed + if (proto != NULL) + PostMessage(hwnd_frame, MWM_NICK_CHANGED, (WPARAM) proto->name, 0); + } + else if (strstr(cws->szModule,"Away")) + { + // Status message changed + PostMessage(hwnd_frame, MWM_STATUS_MSG_CHANGED, 0, 0); + } + else if (proto != NULL && strcmp(cws->szSetting,"ListeningTo") == 0) + { + PostMessage(hwnd_frame, MWM_LISTENINGTO_CHANGED, (WPARAM) proto->name, 0); + } + } + + return 0; +} + +int AvatarChangedHook(WPARAM wParam, LPARAM lParam) +{ + if (hwnd_frame == NULL) + return 0; + + Protocol *proto = protocols->Get((const char *) wParam); + + if (proto != NULL) + PostMessage(hwnd_frame, MWM_AVATAR_CHANGED, (WPARAM) proto->name, 0); + + return 0; +} + +int ProtoAckHook(WPARAM wParam, LPARAM lParam) +{ + if (hwnd_frame == NULL) + return 0; + + ACKDATA *ack = (ACKDATA*)lParam; + + if (ack->type == ACKTYPE_STATUS) + { + Protocol *proto = protocols->Get((const char *) ack->szModule); + + if (proto != NULL) + PostMessage(hwnd_frame, MWM_STATUS_CHANGED, (WPARAM) proto->name, 0); + } + else if (ack->type == ACKTYPE_AWAYMSG) + { + Protocol *proto = protocols->Get((const char *) ack->szModule); + + if (proto != NULL) + PostMessage(hwnd_frame, MWM_STATUS_MSG_CHANGED, (WPARAM) proto->name, 0); + } + + return 0; +} + +int ListeningtoEnableStateChangedHook(WPARAM wParam,LPARAM lParam) +{ + if (hwnd_frame == NULL) + return 0; + + if (wParam == NULL || protocols->Get((const char *) wParam) != NULL) + PostMessage(hwnd_frame, MWM_LISTENINGTO_CHANGED, wParam, 0); + + return 0; +} diff --git a/plugins/MyDetails/src/frame.h b/plugins/MyDetails/src/frame.h new file mode 100644 index 0000000000..5382d3ed46 --- /dev/null +++ b/plugins/MyDetails/src/frame.h @@ -0,0 +1,38 @@ +/* +Copyright (C) 2005 Ricardo Pescuma Domenecci + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + + +#ifndef __FRAME_H__ +# define __FRAME_H__ + + +void InitFrames(); +void DeInitFrames(); + +void RefreshFrame(); +void RefreshFrameAndCalcRects(); + +void SetCycleTime(); + +INT_PTR PluginCommand_ShowNextProtocol(WPARAM wParam,LPARAM lParam); +INT_PTR PluginCommand_ShowPreviousProtocol(WPARAM wParam,LPARAM lParam); +INT_PTR PluginCommand_ShowProtocol(WPARAM wParam,LPARAM lParam); + + +#endif // __FRAME_H__ \ No newline at end of file diff --git a/plugins/MyDetails/src/mydetails.cpp b/plugins/MyDetails/src/mydetails.cpp new file mode 100644 index 0000000000..4b34041cbb --- /dev/null +++ b/plugins/MyDetails/src/mydetails.cpp @@ -0,0 +1,737 @@ +/* +Copyright (C) 2005 Ricardo Pescuma Domenecci + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + + +#include "commons.h" + +// Prototypes ///////////////////////////////////////////////////////////////////////////////////// + +HINSTANCE hInst; +int hLangpack = 0; + +PLUGININFOEX pluginInfo={ + sizeof(PLUGININFOEX), + "My Details", + PLUGIN_MAKE_VERSION(0,0,1,11), + "Show and allows you to edit your details for all protocols.", + "Ricardo Pescuma Domenecci, Drugwash", + "", + "© 2005-2008 Ricardo Pescuma Domenecci, Drugwash", + "http://pescuma.org/miranda/mydetails", + UNICODE_AWARE, + { 0xa82baeb3, 0xa33c, 0x4036, { 0xb8, 0x37, 0x78, 0x3, 0xa5, 0xb6, 0xc2, 0xab } } // {A82BAEB3-A33C-4036-B837-7803A5B6C2AB} +}; + +// Hooks +HANDLE hModulesLoadedHook = NULL; +HANDLE hPreShutdownHook = NULL; + +long nickname_dialog_open; +HWND hwndSetNickname; + +long status_msg_dialog_open; +HWND hwndSetStatusMsg; + +// Hook called after init +static int MainInit(WPARAM wparam,LPARAM lparam); +static int MainUninit(WPARAM wParam, LPARAM lParam); + +// Services +static INT_PTR PluginCommand_SetMyNicknameUI(WPARAM wParam,LPARAM lParam); +static INT_PTR PluginCommand_SetMyNickname(WPARAM wParam,LPARAM lParam); +static INT_PTR PluginCommand_GetMyNickname(WPARAM wParam,LPARAM lParam); +static INT_PTR PluginCommand_SetMyAvatarUI(WPARAM wParam,LPARAM lParam); +static INT_PTR PluginCommand_SetMyAvatar(WPARAM wParam,LPARAM lParam); +static INT_PTR PluginCommand_GetMyAvatar(WPARAM wParam,LPARAM lParam); +static INT_PTR PluginCommand_SetMyStatusMessageUI(WPARAM wParam,LPARAM lParam); +static INT_PTR PluginCommand_CycleThroughtProtocols(WPARAM wParam,LPARAM lParam); + + +// Functions ////////////////////////////////////////////////////////////////////////////////////// + + +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + hInst = hinstDLL; + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +extern "C" __declspec(dllexport) const MUUID interfaces[] = { MIID_MDETAILS, MIID_LAST }; + +extern "C" __declspec(dllexport) int Load() +{ + mir_getLP(&pluginInfo); + + // Hook event to load messages and show first one + HookEvent(ME_SYSTEM_MODULESLOADED, MainInit); + HookEvent(ME_SYSTEM_PRESHUTDOWN, MainUninit); + + nickname_dialog_open = 0; + status_msg_dialog_open = 0; + + // Options + InitOptions(); + + // Register services + CreateServiceFunction(MS_MYDETAILS_SETMYNICKNAME, PluginCommand_SetMyNickname); + CreateServiceFunction(MS_MYDETAILS_SETMYNICKNAMEUI, PluginCommand_SetMyNicknameUI); + CreateServiceFunction(MS_MYDETAILS_SETMYAVATAR, PluginCommand_SetMyAvatar); + CreateServiceFunction(MS_MYDETAILS_SETMYAVATARUI, PluginCommand_SetMyAvatarUI); + CreateServiceFunction(MS_MYDETAILS_GETMYNICKNAME, PluginCommand_GetMyNickname); + CreateServiceFunction(MS_MYDETAILS_GETMYAVATAR, PluginCommand_GetMyAvatar); + CreateServiceFunction(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, PluginCommand_SetMyStatusMessageUI); + CreateServiceFunction(MS_MYDETAILS_SHOWNEXTPROTOCOL, PluginCommand_ShowNextProtocol); + CreateServiceFunction(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL, PluginCommand_ShowPreviousProtocol); + CreateServiceFunction(MS_MYDETAILS_SHOWPROTOCOL, PluginCommand_ShowProtocol); + CreateServiceFunction(MS_MYDETAILS_CYCLE_THROUGH_PROTOCOLS, PluginCommand_CycleThroughtProtocols); + + return 0; +} + +extern "C" __declspec(dllexport) int Unload(void) +{ + DestroyServiceFunction(MS_MYDETAILS_SETMYNICKNAME); + DestroyServiceFunction(MS_MYDETAILS_SETMYNICKNAMEUI); + DestroyServiceFunction(MS_MYDETAILS_SETMYAVATAR); + DestroyServiceFunction(MS_MYDETAILS_SETMYAVATARUI); + DestroyServiceFunction(MS_MYDETAILS_GETMYNICKNAME); + DestroyServiceFunction(MS_MYDETAILS_GETMYAVATAR); + DestroyServiceFunction(MS_MYDETAILS_SETMYSTATUSMESSAGEUI); + DestroyServiceFunction(MS_MYDETAILS_SHOWNEXTPROTOCOL); + DestroyServiceFunction(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL); + DestroyServiceFunction(MS_MYDETAILS_SHOWPROTOCOL); + DestroyServiceFunction(MS_MYDETAILS_CYCLE_THROUGH_PROTOCOLS); + + DeInitProtocolData(); + return 0; +} + + +static INT_PTR Menu_SetMyAvatarUI(WPARAM wParam,LPARAM lParam) +{ + return PluginCommand_SetMyAvatarUI(0, 0); +} + +static INT_PTR Menu_SetMyNicknameUI(WPARAM wParam,LPARAM lParam) +{ + return PluginCommand_SetMyNicknameUI(0, 0); +} + +static INT_PTR Menu_SetMyStatusMessageUI(WPARAM wParam,LPARAM lParam) +{ + return PluginCommand_SetMyStatusMessageUI(0, 0); +} + + +// Hook called after init +static int MainInit(WPARAM wparam,LPARAM lparam) +{ + InitProtocolData(); + + // Add options to menu + CLISTMENUITEM mi; + + if (protocols->CanSetAvatars()) { + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIF_TCHAR; + mi.popupPosition = 500050000; + mi.ptszPopupName = LPGENT("My Details"); + mi.position = 100001; + mi.ptszName = LPGENT("Set My Avatar..."); + CreateServiceFunction("MENU_" MS_MYDETAILS_SETMYAVATARUI, Menu_SetMyAvatarUI); + mi.pszService = "MENU_" MS_MYDETAILS_SETMYAVATARUI; + Menu_AddMainMenuItem(&mi); + } + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIF_TCHAR; + mi.popupPosition = 500050000; + mi.ptszPopupName = LPGENT("My Details"); + mi.position = 100002; + mi.ptszName = LPGENT("Set My Nickname..."); + CreateServiceFunction("MENU_" MS_MYDETAILS_SETMYNICKNAMEUI, Menu_SetMyNicknameUI); + mi.pszService = "MENU_" MS_MYDETAILS_SETMYNICKNAMEUI; + Menu_AddMainMenuItem(&mi); + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIF_TCHAR; + mi.popupPosition = 500050000; + mi.ptszPopupName = LPGENT("My Details"); + mi.position = 100003; + mi.ptszName = LPGENT("Set My Status Message..."); + CreateServiceFunction("MENU_" MS_MYDETAILS_SETMYSTATUSMESSAGEUI, Menu_SetMyStatusMessageUI); + mi.pszService = "MENU_" MS_MYDETAILS_SETMYSTATUSMESSAGEUI; + Menu_AddMainMenuItem(&mi); + + // Set protocols to show frame + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.flags = CMIF_TCHAR; + mi.popupPosition = 500050000; + mi.ptszPopupName = LPGENT("My Details"); + mi.position = 200001; + mi.ptszName = LPGENT("Show next protocol"); + mi.pszService = MS_MYDETAILS_SHOWNEXTPROTOCOL; + Menu_AddMainMenuItem(&mi); + + InitFrames(); + + if (CallService(MS_SKIN2_GETICON, 0, (LPARAM) "LISTENING_TO_ICON") == NULL) { + SKINICONDESC sid = {0}; + sid.cbSize = sizeof(SKINICONDESC); + sid.flags = SIDF_TCHAR; + sid.ptszSection = LPGENT("Contact List"); + sid.ptszDescription = LPGENT("Listening to"); + sid.pszName = "LISTENING_TO_ICON"; + sid.hDefaultIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_LISTENINGTO)); + Skin_AddIcon(&sid); + } + { + SKINICONDESC sid = {0}; + sid.cbSize = sizeof(SKINICONDESC); + sid.flags = SIDF_TCHAR; + sid.ptszSection = LPGENT("My Details"); + sid.ptszDescription = LPGENT("Previous protocol"); + sid.pszName = "MYDETAILS_PREV_PROTOCOL"; + sid.hDefaultIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_LEFT_ARROW)); + Skin_AddIcon(&sid); + } + { + SKINICONDESC sid = {0}; + sid.cbSize = sizeof(SKINICONDESC); + sid.flags = SIDF_TCHAR; + sid.ptszSection = LPGENT("My Details"); + sid.ptszDescription = LPGENT("Next protocol"); + sid.pszName = "MYDETAILS_NEXT_PROTOCOL"; + sid.hDefaultIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RIGHT_ARROW)); + Skin_AddIcon(&sid); + } + + return 0; +} + +static int MainUninit(WPARAM wParam, LPARAM lParam) +{ + DeInitFrames(); + return 0; +} + +// Set nickname /////////////////////////////////////////////////////////////////////////////////// + +#define WMU_SETDATA (WM_USER+1) + +static INT_PTR CALLBACK DlgProcSetNickname(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch ( msg ) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SendMessage(GetDlgItem(hwndDlg, IDC_NICKNAME), EM_LIMITTEXT, + MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE - 1, 0); + return TRUE; + + case WMU_SETDATA: + { + int proto_num = (int)wParam; + + SetWindowLong(hwndDlg, GWLP_USERDATA, proto_num); + + if (proto_num == -1) { + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedIcon(SKINICON_OTHER_MIRANDA)); + + // All protos have the same nick? + if (protocols->GetSize() > 0) { + TCHAR *nick = protocols->Get(0)->nickname; + + bool foundDefNick = true; + for (int i=1 ; foundDefNick && i < protocols->GetSize() ; i++) { + if (_tcsicmp(protocols->Get(i)->nickname, nick) != 0) { + foundDefNick = false; + break; + } + } + + if (foundDefNick) + if ( _tcsicmp(protocols->default_nick, nick) != 0) + lstrcpy(protocols->default_nick, nick); + } + + SetDlgItemText(hwndDlg, IDC_NICKNAME, protocols->default_nick); + SendDlgItemMessage(hwndDlg, IDC_NICKNAME, EM_LIMITTEXT, MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE, 0); + } + else { + Protocol *proto = protocols->Get(proto_num); + + TCHAR tmp[128]; + mir_sntprintf(tmp, SIZEOF(tmp), TranslateT("Set My Nickname for %s"), proto->description); + + SendMessage(hwndDlg, WM_SETTEXT, 0, (LPARAM)tmp); + + HICON hIcon = (HICON)CallProtoService(proto->name, PS_LOADICON, PLI_PROTOCOL, 0); + if (hIcon != NULL) + { + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); + DestroyIcon(hIcon); + } + + SetDlgItemText(hwndDlg, IDC_NICKNAME, proto->nickname); + SendDlgItemMessage(hwndDlg, IDC_NICKNAME, EM_LIMITTEXT, + min(MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE, proto->GetNickMaxLength()), 0); + } + + return TRUE; + } + + case WM_COMMAND: + switch(wParam) { + case IDOK: + { + TCHAR tmp[MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE]; + GetDlgItemText(hwndDlg, IDC_NICKNAME, tmp, SIZEOF(tmp)); + + int proto_num = (int)GetWindowLong(hwndDlg, GWLP_USERDATA); + if (proto_num == -1) + protocols->SetNicks(tmp); + else + protocols->Get(proto_num)->SetNick(tmp); + + DestroyWindow(hwndDlg); + break; + } + case IDCANCEL: + DestroyWindow(hwndDlg); + break; + } + break; + + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + InterlockedExchange(&nickname_dialog_open, 0); + break; + } + + return FALSE; +} + +static INT_PTR PluginCommand_SetMyNicknameUI(WPARAM wParam,LPARAM lParam) +{ + char *proto = (char*)lParam; + int proto_num = -1; + + if (proto != NULL) { + int i; + for (i = 0 ; i < protocols->GetSize() ; i++) { + if (_stricmp(protocols->Get(i)->name, proto) == 0) { + proto_num = i; + break; + } + } + + if (proto_num == -1) + return -1; + + if ( !protocols->Get(i)->CanSetNick()) + return -2; + + } + + if ( !nickname_dialog_open) { + InterlockedExchange(&nickname_dialog_open, 1); + + hwndSetNickname = CreateDialog(hInst, MAKEINTRESOURCE( IDD_SETNICKNAME ), NULL, DlgProcSetNickname); + + SendMessage(hwndSetNickname, WMU_SETDATA, proto_num, 0); + } + + SetForegroundWindow( hwndSetNickname ); + SetFocus( hwndSetNickname ); + ShowWindow( hwndSetNickname, SW_SHOW ); + + return 0; +} + +static INT_PTR PluginCommand_SetMyNickname(WPARAM wParam,LPARAM lParam) +{ + char * proto = (char *)wParam; + if (proto != NULL) { + for (int i = 0 ; i < protocols->GetSize() ; i++) { + if (_stricmp(protocols->Get(i)->name, proto) == 0) { + if ( !protocols->Get(i)->CanSetNick()) + return -2; + + protocols->Get(i)->SetNick((TCHAR*)lParam); + return 0; + } + } + + return -1; + } + + protocols->SetNicks((TCHAR*)lParam); + return 0; +} + +static INT_PTR PluginCommand_GetMyNickname(WPARAM wParam,LPARAM lParam) +{ + TCHAR* ret = (TCHAR*)lParam; + char * proto = (char *)wParam; + + if (ret == NULL) + return -1; + + if (proto == NULL) { + if (protocols->default_nick != NULL) + lstrcpyn(ret, protocols->default_nick, MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE); + else + ret[0] = '\0'; + + return 0; + } + else { + Protocol *protocol = protocols->Get(proto); + if (protocol != NULL) { + lstrcpyn(ret, protocol->nickname, MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE); + return 0; + } + + return -1; + } +} + +// Set avatar ///////////////////////////////////////////////////////////////////////////////////// + +static INT_PTR PluginCommand_SetMyAvatarUI(WPARAM wParam,LPARAM lParam) +{ + char * proto = (char *)lParam; + int proto_num = -1; + + if (proto != NULL) + { + int i; + for (i = 0 ; i < protocols->GetSize() ; i++) + { + if (_stricmp(protocols->Get(i)->name, proto) == 0) + { + proto_num = i; + break; + } + } + + if (proto_num == -1) + return -1; + + if ( !protocols->Get(i)->CanSetAvatar()) + { + return -2; + } + } + + if (proto_num == -1) + { + protocols->SetAvatars(NULL); + } + else + { + protocols->Get(proto_num)->SetAvatar(NULL); + } + + return 0; +} + +static INT_PTR PluginCommand_SetMyAvatar(WPARAM wParam,LPARAM lParam) +{ + char *proto = (char*)wParam; + if (proto != NULL) { + for (int i = 0 ; i < protocols->GetSize() ; i++) { + if (_stricmp(protocols->Get(i)->name, proto) == 0) { + if ( !protocols->Get(i)->CanSetAvatar()) + return -2; + + protocols->Get(i)->SetAvatar((TCHAR*)lParam); + return 0; + } + } + + return -1; + } + + protocols->SetAvatars((TCHAR*)lParam); + return 0; +} + +int Status2SkinIcon(int status) +{ + switch(status) { + case ID_STATUS_AWAY: return SKINICON_STATUS_AWAY; + case ID_STATUS_NA: return SKINICON_STATUS_NA; + case ID_STATUS_DND: return SKINICON_STATUS_DND; + case ID_STATUS_OCCUPIED: return SKINICON_STATUS_OCCUPIED; + case ID_STATUS_FREECHAT: return SKINICON_STATUS_FREE4CHAT; + case ID_STATUS_ONLINE: return SKINICON_STATUS_ONLINE; + case ID_STATUS_OFFLINE: return SKINICON_STATUS_OFFLINE; + case ID_STATUS_INVISIBLE: return SKINICON_STATUS_INVISIBLE; + case ID_STATUS_ONTHEPHONE: return SKINICON_STATUS_ONTHEPHONE; + case ID_STATUS_OUTTOLUNCH: return SKINICON_STATUS_OUTTOLUNCH; + case ID_STATUS_IDLE: return SKINICON_STATUS_AWAY; + } + return SKINICON_STATUS_OFFLINE; +} + +static INT_PTR PluginCommand_GetMyAvatar(WPARAM wParam,LPARAM lParam) +{ + TCHAR* ret = (TCHAR*)lParam; + char * proto = (char *)wParam; + + if (ret == NULL) + return -1; + + if (proto == NULL) { + if (protocols->default_avatar_file != NULL) + lstrcpyn(ret, protocols->default_avatar_file, MS_MYDETAILS_GETMYAVATAR_BUFFER_SIZE); + else + ret[0] = '\0'; + + return 0; + } + + for (int i = 0 ; i < protocols->GetSize() ; i++) { + if ( _stricmp(protocols->Get(i)->name, proto) == 0) { + if ( !protocols->Get(i)->CanGetAvatar()) + return -2; + + protocols->Get(i)->GetAvatar(); + + if (protocols->Get(i)->avatar_file != NULL) + lstrcpyn(ret, protocols->Get(i)->avatar_file, MS_MYDETAILS_GETMYAVATAR_BUFFER_SIZE); + else + ret[0] = '\0'; + + return 0; + } + } + + return -1; +} + +static LRESULT CALLBACK StatusMsgEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_CHAR: + if (wParam == 0x0a && (GetKeyState(VK_CONTROL) & 0x8000) != 0) { + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + break; + } + + return CallWindowProc((WNDPROC) GetWindowLong(hwnd, GWLP_USERDATA), hwnd, msg, wParam, lParam); +} + +struct SetStatusMessageData { + int status; + int proto_num; +}; + +static INT_PTR CALLBACK DlgProcSetStatusMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + SendMessage(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE), EM_LIMITTEXT, + MS_MYDETAILS_GETMYSTATUSMESSAGE_BUFFER_SIZE - 1, 0); + { + WNDPROC old_proc = (WNDPROC) SetWindowLong(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE), + GWLP_WNDPROC, (LONG) StatusMsgEditSubclassProc); + SetWindowLong(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE), GWLP_USERDATA, (long) old_proc); + } + return TRUE; + + case WMU_SETDATA: + { + SetStatusMessageData *data = (SetStatusMessageData *) malloc(sizeof(SetStatusMessageData)); + data->status = (int)wParam; + data->proto_num = (int)lParam; + + SetWindowLong(hwndDlg, GWLP_USERDATA, (LONG) data); + + if (data->proto_num >= 0) { + Protocol *proto = protocols->Get(data->proto_num); + + HICON hIcon = (HICON)CallProtoService(proto->name, PS_LOADICON, PLI_PROTOCOL, 0); + if (hIcon != NULL) { + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); + DestroyIcon(hIcon); + } + + TCHAR title[256]; + mir_sntprintf(title, SIZEOF(title), TranslateT("Set My Status Message for %s"), proto->description); + SendMessage(hwndDlg, WM_SETTEXT, 0, (LPARAM)title); + + SetDlgItemText(hwndDlg, IDC_STATUSMESSAGE, proto->GetStatusMsg()); + } + else if (data->status != 0) + { + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedIcon(Status2SkinIcon(data->status))); + + TCHAR title[256]; + mir_sntprintf(title, SIZEOF(title), TranslateT("Set My Status Message for %s"), + CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, data->status, GSMDF_TCHAR)); + SendMessage(hwndDlg, WM_SETTEXT, 0, (LPARAM)title); + + SetDlgItemText(hwndDlg, IDC_STATUSMESSAGE, protocols->GetDefaultStatusMsg(data->status)); + } + else + { + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedIcon(SKINICON_OTHER_MIRANDA)); + + SetDlgItemText(hwndDlg, IDC_STATUSMESSAGE, protocols->GetDefaultStatusMsg()); + } + + return TRUE; + } + case WM_COMMAND: + switch(wParam) { + case IDOK: + { + TCHAR tmp[MS_MYDETAILS_GETMYSTATUSMESSAGE_BUFFER_SIZE]; + GetDlgItemText(hwndDlg, IDC_STATUSMESSAGE, tmp, sizeof(tmp)); + + SetStatusMessageData *data = (SetStatusMessageData *) GetWindowLong(hwndDlg, GWLP_USERDATA); + + if (data->proto_num >= 0) + protocols->Get(data->proto_num)->SetStatusMsg(tmp); + else if (data->status == 0) + protocols->SetStatusMsgs(tmp); + else + protocols->SetStatusMsgs(data->status, tmp); + + DestroyWindow(hwndDlg); + } + break; + + case IDCANCEL: + DestroyWindow(hwndDlg); + break; + } + break; + + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + SetWindowLong(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE), GWLP_WNDPROC, + GetWindowLong(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE), GWLP_USERDATA)); + free((SetStatusMessageData *) GetWindowLong(hwndDlg, GWLP_USERDATA)); + InterlockedExchange(&status_msg_dialog_open, 0); + break; + } + + return FALSE; +} + +static INT_PTR PluginCommand_SetMyStatusMessageUI(WPARAM wParam,LPARAM lParam) +{ + int status = (int)wParam; + char * proto_name = (char *)lParam; + int proto_num = -1; + Protocol *proto = NULL; + + if (status != 0 && (status < ID_STATUS_OFFLINE || status > ID_STATUS_OUTTOLUNCH)) + return -10; + + if (proto_name != NULL) + { + for (int i = 0 ; i < protocols->GetSize() ; i++) + { + proto = protocols->Get(i); + + if (_stricmp(proto->name, proto_name) == 0) + { + proto_num = i; + break; + } + } + + if (proto_num == -1) { + return -1; + } + + if (protocols->CanSetStatusMsgPerProtocol() && !proto->CanSetStatusMsg()) { + return -2; + } + } + else if (ServiceExists(MS_SA_CHANGESTATUSMSG)) + { + if (proto == NULL && status == 0) + { + CallService(MS_SA_CHANGESTATUSMSG, protocols->GetGlobalStatus(), NULL); + } + else if (status == 0) + { + CallService(MS_SA_CHANGESTATUSMSG, proto->status, (LPARAM) proto_name); + } + else + { + CallService(MS_SA_CHANGESTATUSMSG, status, (LPARAM) proto_name); + } + + return 0; + } + + if (proto == NULL || proto->status != ID_STATUS_OFFLINE) + { + if ( !status_msg_dialog_open) + { + InterlockedExchange(&status_msg_dialog_open, 1); + + hwndSetStatusMsg = CreateDialog(hInst, MAKEINTRESOURCE( IDD_SETSTATUSMESSAGE ), NULL, DlgProcSetStatusMessage ); + + SendMessage(hwndSetStatusMsg, WMU_SETDATA, status, proto_num); + } + + SetForegroundWindow( hwndSetStatusMsg ); + SetFocus( hwndSetStatusMsg ); + ShowWindow( hwndSetStatusMsg, SW_SHOW ); + + return 0; + } + + return -3; +} + + +static INT_PTR PluginCommand_CycleThroughtProtocols(WPARAM wParam,LPARAM lParam) +{ + DBWriteContactSettingByte(NULL,"MyDetails","CicleThroughtProtocols", (BYTE) wParam); + + LoadOptions(); + + return 0; +} \ No newline at end of file diff --git a/plugins/MyDetails/src/options.cpp b/plugins/MyDetails/src/options.cpp new file mode 100644 index 0000000000..a4b722b241 --- /dev/null +++ b/plugins/MyDetails/src/options.cpp @@ -0,0 +1,160 @@ +/* +Copyright (C) 2005 Ricardo Pescuma Domenecci + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + + +#include "commons.h" +#include "options.h" + +// Prototypes ///////////////////////////////////////////////////////////////////////////////////// + +Options opts; + +// Functions ////////////////////////////////////////////////////////////////////////////////////// + +static OptPageControl pageControls[] = { + { &opts.cycle_through_protocols, CONTROL_CHECKBOX, IDC_CYCLE_THROUGH_PROTOS, "CicleThroughtProtocols", (BYTE) 1 }, + { &opts.seconds_to_show_protocol, CONTROL_SPIN, IDC_CYCLE_TIME, "CicleTime", (WORD) 5, IDC_CYCLE_TIME_SPIN, (WORD) 1, (WORD) 255 }, + { &opts.draw_show_protocol_name, CONTROL_CHECKBOX, IDC_SHOW_PROTO_NAME, "ShowProtocolName", (BYTE) 1 }, + { &opts.show_protocol_cycle_button, CONTROL_CHECKBOX, IDC_SHOW_CYCLE_PROTO_BUTTON, "ShowProtocolCycleButton", (BYTE) 0 }, + { &opts.draw_text_rtl, CONTROL_CHECKBOX, IDC_TEXT_RTL, "TextRTL", (BYTE) 0 }, + { &opts.draw_text_align_right, CONTROL_CHECKBOX, IDC_TEXT_ALIGN_RIGHT, "TextAlignRight", (BYTE) 0 }, + { &opts.replace_smileys, CONTROL_CHECKBOX, IDC_REPLACE_SMILEYS, "ReplaceSmileys", (BYTE) 1 }, + { &opts.resize_smileys, CONTROL_CHECKBOX, IDC_RESIZE_SMILEYS, "ResizeSmileys", (BYTE) 0 }, + { &opts.use_contact_list_smileys, CONTROL_CHECKBOX, IDC_USE_CONTACT_LIST_SMILEYS, "UseContactListSmileys", (BYTE) 0 }, + { &opts.global_on_avatar, CONTROL_CHECKBOX, IDC_GLOBAL_ON_AVATAR, "GlobalOnAvatar", (BYTE) 0 }, + { &opts.global_on_nickname, CONTROL_CHECKBOX, IDC_GLOBAL_ON_NICKNAME, "GlobalOnNickname", (BYTE) 0 }, + { &opts.global_on_status, CONTROL_CHECKBOX, IDC_GLOBAL_ON_STATUS, "GlobalOnStatus", (BYTE) 0 }, + { &opts.global_on_status_message, CONTROL_CHECKBOX, IDC_GLOBAL_ON_STATUS_MESSAGE, "GlobalOnStatusMessage", (BYTE) 0 }, + { &opts.draw_avatar_allow_to_grow, CONTROL_CHECKBOX, IDC_AVATAR_ALLOW_TO_GROW, "AvatarAllowToGrow", (BYTE) 0 }, + { &opts.draw_avatar_custom_size, CONTROL_CHECKBOX, IDC_AVATAR_CUSTOM_SIZE_CHK, "AvatarCustomSize", (BYTE) 0 }, + { &opts.draw_avatar_custom_size_pixels, CONTROL_SPIN, IDC_AVATAR_CUSTOM_SIZE, "AvatarCustomSizePixels", (WORD) 30, IDC_AVATAR_CUSTOM_SIZE_SPIN, (WORD) 1, (WORD) 255 }, + { &opts.draw_avatar_border, CONTROL_CHECKBOX, IDC_AVATAR_DRAW_BORDER, "AvatarDrawBorders", (BYTE) 0 }, + { &opts.draw_avatar_border_color, CONTROL_COLOR, IDC_AVATAR_BORDER_COLOR, "AvatarBorderColor", (DWORD) RGB(0,0,0) }, + { &opts.draw_avatar_round_corner, CONTROL_CHECKBOX, IDC_AVATAR_ROUND_CORNERS, "AvatarRoundCorners", (BYTE) 1 }, + { &opts.draw_avatar_use_custom_corner_size, CONTROL_CHECKBOX, IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK, "AvatarUseCustomCornerSize", (BYTE) 0 }, + { &opts.draw_avatar_custom_corner_size, CONTROL_SPIN, IDC_AVATAR_CUSTOM_CORNER_SIZE, "AvatarCustomCornerSize", (WORD) 4, IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN, (WORD) 1, (WORD) 255 }, + { &opts.use_avatar_space_to_draw_text, CONTROL_CHECKBOX, IDC_AVATAR_USE_FREE_SPACE, "AvatarUseFreeSpaceToDrawText", (BYTE) 1 }, + { &opts.resize_frame, CONTROL_CHECKBOX, IDC_RESIZE_FRAME, "ResizeFrame", (BYTE) 0 }, + { &opts.borders[RIGHT], CONTROL_SPIN, IDC_BORDER_RIGHT, "BorderRight", (WORD) 8, IDC_BORDER_RIGHT_SPIN, (WORD) 0, (WORD) 255 }, + { &opts.borders[LEFT], CONTROL_SPIN, IDC_BORDER_LEFT, "BorderLeft", (WORD) 8, IDC_BORDER_LEFT_SPIN, (WORD) 0, (WORD) 255 }, + { &opts.borders[TOP], CONTROL_SPIN, IDC_BORDER_TOP, "BorderTop", (WORD) 8, IDC_BORDER_TOP_SPIN, (WORD) 0, (WORD) 255 }, + { &opts.borders[BOTTOM], CONTROL_SPIN, IDC_BORDER_BOTTOM, "BorderBottom", (WORD) 8, IDC_BORDER_BOTTOM_SPIN, (WORD) 0, (WORD) 255 }, + { &opts.bkg_color, CONTROL_COLOR, IDC_AVATAR_BKG_COLOR, "BackgroundColor", (DWORD) GetSysColor(COLOR_BTNFACE) } +}; + + +// Initializations needed by options +void LoadOptions() +{ + LoadOpts(pageControls, SIZEOF(pageControls), MODULE_NAME); + + // This is created here to assert that this key always exists + opts.refresh_status_message_timer = DBGetContactSettingWord(NULL,"MyDetails","RefreshStatusMessageTimer",12); + DBWriteContactSettingWord(NULL,"MyDetails","RefreshStatusMessageTimer", opts.refresh_status_message_timer); + + SetCycleTime(); + RefreshFrameAndCalcRects(); +} + +static INT_PTR CALLBACK DlgProcOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + BOOL ret = SaveOptsDlgProc(pageControls, SIZEOF(pageControls), MODULE_NAME, hwndDlg, msg, wParam, lParam); + + switch (msg) { + case WM_INITDIALOG: + if (!IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER)) { + EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR_L),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR),FALSE); + } + + if (!IsDlgButtonChecked(hwndDlg,IDC_AVATAR_ROUND_CORNERS)) { + EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN),FALSE); + } + + if (!IsDlgButtonChecked(hwndDlg,IDC_SHOW_PROTO_NAME)) + EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_CYCLE_PROTO_BUTTON),FALSE); + + if ( !ServiceExists(MS_SMILEYADD_BATCHPARSE)) { + EnableWindow(GetDlgItem(hwndDlg,IDC_REPLACE_SMILEYS),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_USE_CONTACT_LIST_SMILEYS),FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_RESIZE_SMILEYS),FALSE); + } + + if ( !ServiceExists(MS_CLIST_FRAMES_SETFRAMEOPTIONS)) + EnableWindow(GetDlgItem(hwndDlg,IDC_RESIZE_FRAME),FALSE); + + break; + + case WM_COMMAND: + if (LOWORD(wParam)==IDC_AVATAR_DRAW_BORDER) { + BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER); + EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR_L),enabled); + EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR),enabled); + } + else if (LOWORD(wParam)==IDC_AVATAR_ROUND_CORNERS) { + BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_AVATAR_ROUND_CORNERS); + EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),enabled); + EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),enabled); + EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN),enabled); + } + else if (LOWORD(wParam)==IDC_SHOW_PROTO_NAME) { + BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW_PROTO_NAME); + EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_CYCLE_PROTO_BUTTON),enabled); + } + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + LoadOptions(); + return TRUE; + } + break; + } + break; + } + + return ret; +} + +int InitOptionsCallback(WPARAM wParam,LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.position = -200000000; + odp.hInstance = hInst; + odp.pfnDlgProc = DlgProcOpts; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTS); + odp.ptszGroup = LPGENT("Customize"); + odp.ptszTitle = LPGENT("My Details"); + odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR; + Options_AddPage(wParam, &odp); + return 0; +} + +void InitOptions() +{ + LoadOptions(); + + HookEvent(ME_OPT_INITIALISE, InitOptionsCallback); +} diff --git a/plugins/MyDetails/src/options.h b/plugins/MyDetails/src/options.h new file mode 100644 index 0000000000..c8b11ef725 --- /dev/null +++ b/plugins/MyDetails/src/options.h @@ -0,0 +1,79 @@ +/* +Copyright (C) 2005 Ricardo Pescuma Domenecci + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + + +#ifndef __OPTIONS_H__ +# define __OPTIONS_H__ + + +#define TOP 0 +#define LEFT 1 +#define BOTTOM 2 +#define RIGHT 3 + +struct Options +{ + bool cycle_through_protocols; + int seconds_to_show_protocol; + bool replace_smileys; + bool resize_smileys; + bool use_contact_list_smileys; + + bool draw_text_rtl; + bool draw_text_align_right; + + bool draw_show_protocol_name; + bool show_protocol_cycle_button; + + bool global_on_avatar; + bool global_on_nickname; + bool global_on_status; + bool global_on_status_message; + + bool draw_avatar_custom_size; + bool draw_avatar_allow_to_grow; + int draw_avatar_custom_size_pixels; + bool draw_avatar_border; + COLORREF draw_avatar_border_color; + bool draw_avatar_round_corner; + bool draw_avatar_use_custom_corner_size; + int draw_avatar_custom_corner_size; + + COLORREF bkg_color; + int borders[4]; + + bool use_avatar_space_to_draw_text; + + bool resize_frame; + + int refresh_status_message_timer; +}; + +extern Options opts; + + +// Initializations needed by options +void InitOptions(); + +// Loads the options from DB +// It don't need to be called, except in some rare cases +void LoadOptions(); + + +#endif // __OPTIONS_H__ diff --git a/plugins/MyDetails/src/resource.h b/plugins/MyDetails/src/resource.h new file mode 100644 index 0000000000..b53e46d1a3 --- /dev/null +++ b/plugins/MyDetails/src/resource.h @@ -0,0 +1,71 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// +#define IDD_SETNICKNAME 101 +#define IDD_OPTS 102 +#define IDD_SETSTATUSMESSAGE 103 +#define IDR_MENU1 104 +#define IDI_LISTENINGTO 105 +#define IDI_RIGHT_ARROW 106 +#define IDI_LEFT_ARROW 107 +#define IDC_NICKNAME 1000 +#define IDC_SHOW_PROTO_NAME 1001 +#define IDC_CYCLE_THROUGH_PROTOS 1002 +#define IDC_TEXT_RTL 1003 +#define IDC_TEXT_ALIGN_RIGHT 1004 +#define IDC_REPLACE_SMILEYS 1005 +#define IDC_RESIZE_SMILEYS 1006 +#define IDC_RESIZE_FRAME 1007 +#define IDC_RESIZE_SMILEYS2 1008 +#define IDC_USE_CONTACT_LIST_SMILEYS 1008 +#define IDC_STATUSMESSAGE 1009 +#define IDC_GLOBAL_ON_NICKNAME 1009 +#define IDC_AVATAR_ALLOW_TO_GROW 1010 +#define IDC_GLOBAL_ON_STATUS_MESSAGE 1011 +#define IDC_GLOBAL_ON_STATUS 1012 +#define IDC_GLOBAL_ON_AVATAR 1013 +#define IDC_SHOW_CYCLE_PROTO_BUTTON 1014 +#define IDC_AVATAR_CUSTOM_CORNER_SIZE 1622 +#define IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN 1623 +#define IDC_BORDER_TOP 1624 +#define IDC_BORDER_TOP_SPIN 1625 +#define IDC_BORDER_LEFT 1626 +#define IDC_BORDER_LEFT_SPIN 1627 +#define IDC_BORDER_BOTTOM 1628 +#define IDC_BORDER_BOTTOM_SPIN 1629 +#define IDC_BORDER_RIGHT 1630 +#define IDC_BORDER_RIGHT_SPIN 1631 +#define IDC_CYCLE_TIME 1632 +#define IDC_CYCLE_TIME_SPIN 1633 +#define IDC_AVATAR_CUSTOM_SIZE 1634 +#define IDC_AVATAR_CUSTOM_SIZE_SPIN 1635 +#define IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK 1761 +#define IDC_AVATAR_DRAW_BORDER 1764 +#define IDC_AVATAR_CUSTOM_SIZE_CHK 1765 +#define IDC_AVATAR_ROUND_CORNERS 1800 +#define IDC_AVATAR_USE_FREE_SPACE 1801 +#define IDC_AVATAR_BORDER_COLOR_L 1839 +#define IDC_AVATAR_BORDER_COLOR 1840 +#define IDC_AVATAR_BKG_COLOR_L 1841 +#define IDC_AVATAR_BKG_COLOR 1842 +#define ID_CYCLE_THROUGH_PROTOS 40004 +#define ID_DONT_CYCLE_THROUGH_PROTOS 40005 +#define ID_SHOW_NEXT_PROTO 40006 +#define ID_SHOW_PREV_PROTO 40007 +#define ID_NICKPOPUP_SETMYNICKNAME 40008 +#define ID_STATUSMESSAGEPOPUP_SETMYSTATUSMESSAGE 40009 +#define ID_AVATARPOPUP_SETMYAVATAR 40010 +#define ID_LISTENINGTOPOPUP_SENDLISTENINGTO 40011 +#define ID_CONTEXTPOPUP_ENABLELISTENINGTO 40012 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 40013 +#define _APS_NEXT_CONTROL_VALUE 1011 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif -- cgit v1.2.3