summaryrefslogtreecommitdiff
path: root/plugins/MyDetails/src
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-07-23 09:46:45 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-07-23 09:46:45 +0000
commit18e0b1e1b7e216e13c58d863510af4a25df1fee1 (patch)
tree1757a21d0c60cfe3ba093eccb9871a422da04fdb /plugins/MyDetails/src
parent955056f22174c2968568882d0f1a4d4929bc659e (diff)
HistorySweeperLight, MyDetails, NewEventNotify: changed folder structure
git-svn-id: http://svn.miranda-ng.org/main/trunk@1112 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/MyDetails/src')
-rw-r--r--plugins/MyDetails/src/commons.h109
-rw-r--r--plugins/MyDetails/src/data.cpp689
-rw-r--r--plugins/MyDetails/src/data.h163
-rw-r--r--plugins/MyDetails/src/frame.cpp2757
-rw-r--r--plugins/MyDetails/src/frame.h38
-rw-r--r--plugins/MyDetails/src/mydetails.cpp737
-rw-r--r--plugins/MyDetails/src/options.cpp160
-rw-r--r--plugins/MyDetails/src/options.h79
-rw-r--r--plugins/MyDetails/src/resource.h71
9 files changed, 4803 insertions, 0 deletions
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 <windows.h>
+#include <win2k.h>
+#include <commctrl.h>
+#include <stdio.h>
+
+#include <newpluginapi.h>
+#include <m_clist.h>
+#include <m_skin.h>
+#include <m_system.h>
+#include <m_system_cpp.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_database.h>
+#include <m_utils.h>
+#include <m_langpack.h>
+#include <m_awaymsg.h>
+#include <m_contacts.h>
+#include <m_options.h>
+#include <m_clui.h>
+#include <m_clc.h>
+#include <m_proto_listeningto.h>
+#include <m_listeningto.h>
+
+#include <m_fontservice.h>
+#include <m_variables.h>
+#include <m_avatars.h>
+#include <m_statusplugins.h>
+#include <m_icq.h>
+#include <m_icolib.h>
+#include "m_cluiframes.h"
+#include "m_simpleaway.h"
+
+#include <richedit.h>
+#include <m_smileyadd.h>
+
+#include <io.h>
+
+#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("<no status name>"), SIZEOF(tmp));
+
+ DBFreeVariant(&dbv);
+ }
+ else
+ {
+ lstrcpyn(tmp, TranslateT("<no status name>"), 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 <m_skin_eng.h>
+
+// 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("<no nickname>")
+#define DEFAULT_STATUS_MESSAGE _T("<no status message>")
+#define DEFAULT_LISTENING_TO _T("<nothing playing>")
+
+
+// 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 <math.h>
+
+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