From 4e406184646a2d90f228f58abd74661b4de2e2d2 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Thu, 1 Nov 2012 15:11:28 +0000 Subject: extraicons moved to the core git-svn-id: http://svn.miranda-ng.org/main/trunk@2131 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/modules/extraicons/BaseExtraIcon.cpp | 81 +++ src/modules/extraicons/BaseExtraIcon.h | 52 ++ src/modules/extraicons/CallbackExtraIcon.cpp | 73 +++ src/modules/extraicons/CallbackExtraIcon.h | 47 ++ src/modules/extraicons/DefaultExtraIcons.cpp | 394 ++++++++++++ src/modules/extraicons/DefaultExtraIcons.h | 26 + src/modules/extraicons/ExtraIcon.cpp | 134 +++++ src/modules/extraicons/ExtraIcon.h | 73 +++ src/modules/extraicons/ExtraIconGroup.cpp | 215 +++++++ src/modules/extraicons/ExtraIconGroup.h | 62 ++ src/modules/extraicons/IcolibExtraIcon.cpp | 114 ++++ src/modules/extraicons/IcolibExtraIcon.h | 41 ++ src/modules/extraicons/extraicons.cpp | 485 +++++++++++++++ src/modules/extraicons/extraicons.h | 66 ++ src/modules/extraicons/options.h | 32 + src/modules/extraicons/options_ei.cpp | 865 +++++++++++++++++++++++++++ src/modules/extraicons/res/AlwaysVis.ico | Bin 0 -> 2038 bytes src/modules/extraicons/res/Chatchannel.ico | Bin 0 -> 2038 bytes src/modules/extraicons/res/NeverVis.ico | Bin 0 -> 2038 bytes src/modules/extraicons/res/empty.ico | Bin 0 -> 766 bytes src/modules/extraicons/res/extraicons.rc | 147 +++++ src/modules/extraicons/res/female.ico | Bin 0 -> 2550 bytes src/modules/extraicons/res/male.ico | Bin 0 -> 2550 bytes src/modules/extraicons/usedIcons.cpp | 108 ++++ src/modules/extraicons/usedIcons.h | 29 + src/modules/plugins/newplugins.cpp | 7 +- 26 files changed, 3050 insertions(+), 1 deletion(-) create mode 100644 src/modules/extraicons/BaseExtraIcon.cpp create mode 100644 src/modules/extraicons/BaseExtraIcon.h create mode 100644 src/modules/extraicons/CallbackExtraIcon.cpp create mode 100644 src/modules/extraicons/CallbackExtraIcon.h create mode 100644 src/modules/extraicons/DefaultExtraIcons.cpp create mode 100644 src/modules/extraicons/DefaultExtraIcons.h create mode 100644 src/modules/extraicons/ExtraIcon.cpp create mode 100644 src/modules/extraicons/ExtraIcon.h create mode 100644 src/modules/extraicons/ExtraIconGroup.cpp create mode 100644 src/modules/extraicons/ExtraIconGroup.h create mode 100644 src/modules/extraicons/IcolibExtraIcon.cpp create mode 100644 src/modules/extraicons/IcolibExtraIcon.h create mode 100644 src/modules/extraicons/extraicons.cpp create mode 100644 src/modules/extraicons/extraicons.h create mode 100644 src/modules/extraicons/options.h create mode 100644 src/modules/extraicons/options_ei.cpp create mode 100644 src/modules/extraicons/res/AlwaysVis.ico create mode 100644 src/modules/extraicons/res/Chatchannel.ico create mode 100644 src/modules/extraicons/res/NeverVis.ico create mode 100644 src/modules/extraicons/res/empty.ico create mode 100644 src/modules/extraicons/res/extraicons.rc create mode 100644 src/modules/extraicons/res/female.ico create mode 100644 src/modules/extraicons/res/male.ico create mode 100644 src/modules/extraicons/usedIcons.cpp create mode 100644 src/modules/extraicons/usedIcons.h (limited to 'src/modules') diff --git a/src/modules/extraicons/BaseExtraIcon.cpp b/src/modules/extraicons/BaseExtraIcon.cpp new file mode 100644 index 0000000000..0e5dad79ee --- /dev/null +++ b/src/modules/extraicons/BaseExtraIcon.cpp @@ -0,0 +1,81 @@ +/* + Copyright (C) 2009 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 "..\..\core\commonheaders.h" + +#include "BaseExtraIcon.h" +#include "extraicons.h" + +BaseExtraIcon::BaseExtraIcon(int id, const char *name, const TCHAR *description, const char *descIcon, + MIRANDAHOOKPARAM OnClick, LPARAM param) : + ExtraIcon(name), id(id), description(description), descIcon(descIcon), OnClick(OnClick), onClickParam(param) +{ +} + +BaseExtraIcon::~BaseExtraIcon() +{ +} + +void BaseExtraIcon::setOnClick(MIRANDAHOOKPARAM OnClick, LPARAM param) +{ + this->OnClick = OnClick; + this->onClickParam = param; +} + +int BaseExtraIcon::getID() const +{ + return id; +} + +const TCHAR *BaseExtraIcon::getDescription() const +{ + return description.c_str(); +} + +void BaseExtraIcon::setDescription(const TCHAR *desc) +{ + description = desc; +} + +const char *BaseExtraIcon::getDescIcon() const +{ + return descIcon.c_str(); +} + +void BaseExtraIcon::setDescIcon(const char *icon) +{ + descIcon = icon; +} + +void BaseExtraIcon::onClick(HANDLE hContact) +{ + if (OnClick == NULL) + return; + + OnClick((WPARAM) hContact, (LPARAM) ConvertToClistSlot(slot), onClickParam); +} + +int BaseExtraIcon::ClistSetExtraIcon(HANDLE hContact, HANDLE hImage) +{ + ExtraIcon *tmp = extraIconsByHandle[id - 1]; + if (tmp != this) + return tmp->ClistSetExtraIcon(hContact, hImage); + else + return Clist_SetExtraIcon(hContact, slot, hImage); +} diff --git a/src/modules/extraicons/BaseExtraIcon.h b/src/modules/extraicons/BaseExtraIcon.h new file mode 100644 index 0000000000..e382d0d3a9 --- /dev/null +++ b/src/modules/extraicons/BaseExtraIcon.h @@ -0,0 +1,52 @@ +/* + Copyright (C) 2009 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 __BASEEXTRAICON_H__ +#define __BASEEXTRAICON_H__ + +#include "ExtraIcon.h" + +class BaseExtraIcon : public ExtraIcon +{ +public: + BaseExtraIcon(int id, const char *name, const TCHAR *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, + LPARAM param); + virtual ~BaseExtraIcon(); + + virtual int getID() const; + virtual const TCHAR *getDescription() const; + virtual void setDescription(const TCHAR *desc); + virtual const char *getDescIcon() const; + virtual void setDescIcon(const char *icon); + virtual int getType() const =0; + + virtual void onClick(HANDLE hContact); + virtual void setOnClick(MIRANDAHOOKPARAM OnClick, LPARAM param); + + virtual int ClistSetExtraIcon(HANDLE hContact, HANDLE hImage); + +protected: + int id; + std::tstring description; + std::string descIcon; + MIRANDAHOOKPARAM OnClick; + LPARAM onClickParam; +}; + +#endif // __BASEEXTRAICON_H__ diff --git a/src/modules/extraicons/CallbackExtraIcon.cpp b/src/modules/extraicons/CallbackExtraIcon.cpp new file mode 100644 index 0000000000..703628e73d --- /dev/null +++ b/src/modules/extraicons/CallbackExtraIcon.cpp @@ -0,0 +1,73 @@ +/* + Copyright (C) 2009 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 "..\..\core\commonheaders.h" + +#include "CallbackExtraIcon.h" + +CallbackExtraIcon::CallbackExtraIcon(int id, const char *name, const TCHAR *description, const char *descIcon, + MIRANDAHOOK RebuildIcons, MIRANDAHOOK ApplyIcon, MIRANDAHOOKPARAM OnClick, LPARAM param) : + BaseExtraIcon(id, name, description, descIcon, OnClick, param), RebuildIcons(RebuildIcons), ApplyIcon(ApplyIcon), + needToRebuild(true) +{ +} + +CallbackExtraIcon::~CallbackExtraIcon() +{ +} + +int CallbackExtraIcon::getType() const +{ + return EXTRAICON_TYPE_CALLBACK; +} + +void CallbackExtraIcon::rebuildIcons() +{ + if (!isEnabled()) + { + needToRebuild = true; + return; + } + needToRebuild = false; + + RebuildIcons(0, 0); +} + +void CallbackExtraIcon::applyIcon(HANDLE hContact) +{ + if (!isEnabled() || hContact == NULL) + return; + + if (needToRebuild) + rebuildIcons(); + + ApplyIcon((WPARAM) hContact, 0); +} + +int CallbackExtraIcon::setIcon(int id, HANDLE hContact, void *icon) +{ + if (!isEnabled() || hContact == NULL || id != this->id) + return -1; + + return ClistSetExtraIcon(hContact, (HANDLE) icon); +} + +void CallbackExtraIcon::storeIcon(HANDLE hContact, void *icon) +{ +} diff --git a/src/modules/extraicons/CallbackExtraIcon.h b/src/modules/extraicons/CallbackExtraIcon.h new file mode 100644 index 0000000000..547f81a477 --- /dev/null +++ b/src/modules/extraicons/CallbackExtraIcon.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2009 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 __CALLBACKEXTRAICON_H__ +#define __CALLBACKEXTRAICON_H__ + +#include "BaseExtraIcon.h" + +class CallbackExtraIcon : public BaseExtraIcon +{ +public: + CallbackExtraIcon(int id, const char *name, const TCHAR *description, const char *descIcon, + MIRANDAHOOK RebuildIcons, MIRANDAHOOK ApplyIcon, MIRANDAHOOKPARAM OnClick, LPARAM param); + virtual ~CallbackExtraIcon(); + + virtual int getType() const; + + virtual void rebuildIcons(); + virtual void applyIcon(HANDLE hContact); + + virtual int setIcon(int id, HANDLE hContact, void *icon); + virtual void storeIcon(HANDLE hContact, void *icon); + +private: + int(*RebuildIcons)(WPARAM wParam, LPARAM lParam); + int(*ApplyIcon)(WPARAM wParam, LPARAM lParam); + + bool needToRebuild; +}; + +#endif // __CALLBACKEXTRAICON_H__ diff --git a/src/modules/extraicons/DefaultExtraIcons.cpp b/src/modules/extraicons/DefaultExtraIcons.cpp new file mode 100644 index 0000000000..f7e44dafab --- /dev/null +++ b/src/modules/extraicons/DefaultExtraIcons.cpp @@ -0,0 +1,394 @@ +/* + Copyright (C) 2009 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 "..\..\core\commonheaders.h" + +#include "m_cluiframes.h" + +#include "extraicons.h" + +/* + 0, // EXTRA_ICON_VISMODE + 1, // EXTRA_ICON_EMAIL + 2, // EXTRA_ICON_PROTO + 3, // EXTRA_ICON_SMS + 4, // EXTRA_ICON_ADV1 + 5, // EXTRA_ICON_ADV2 + 6, // EXTRA_ICON_WEB + 7, // EXTRA_ICON_CLIENT + 8, // EXTRA_ICON_ADV3 + 9, // EXTRA_ICON_ADV4 + */ + +static void ProtocolInit(); +static void DBExtraIconsInit(); + +void DefaultExtraIcons_Load() +{ + DBExtraIconsInit(); + ProtocolInit(); +} + +void DefaultExtraIcons_Unload() +{ +} + +// DB extra icons /////////////////////////////////////////////////////////////////////// + +struct Info; + +HANDLE hExtraVisibility = NULL; +HANDLE hExtraChat = NULL; +HANDLE hExtraGender = NULL; + +static void SetVisibility(HANDLE hContact, int apparentMode, BOOL clear) +{ + if (hContact == NULL) + return; + + char *proto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (IsEmpty(proto)) + return; + + if (apparentMode <= 0) + apparentMode = DBGetContactSettingWord(hContact, proto, "ApparentMode", 0); + + const char *ico = NULL; + + if (DBGetContactSettingByte(hContact, proto, "ChatRoom", 0)) + { + // Is chat + if (apparentMode == ID_STATUS_OFFLINE) + ico = "ChatActivity"; + + if (ico == NULL && !clear) + return; + + ExtraIcon_SetIcon(hExtraChat, hContact, ico); + } + else + { + // Not chat + if (apparentMode == ID_STATUS_OFFLINE) + ico = "NeverVis"; + + else if (apparentMode == ID_STATUS_ONLINE) + ico = "AlwaysVis"; + + if (ico == NULL && !clear) + return; + + ExtraIcon_SetIcon(hExtraVisibility, hContact, ico); + } +} + +static void SetGender(HANDLE hContact, int gender, BOOL clear) +{ + if (hContact == NULL) + return; + + char *proto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (IsEmpty(proto)) + return; + + if (gender <= 0) + gender = DBGetContactSettingByte(hContact, proto, "Gender", 0); + if (gender <= 0) + gender = DBGetContactSettingByte(hContact, "UserInfo", "Gender", 0); + + const char *ico = NULL; + if (gender == 'M') + ico = "gender_male"; + else if (gender == 'F') + ico = "gender_female"; + else + ico = NULL; + + if (ico == NULL && !clear) + return; + + ExtraIcon_SetIcon(hExtraGender, hContact, ico); +} + +static void EmailOnClick(Info *info, const char *text); +static void HomepageOnClick(Info *info, const char *text); +static void DefaultSetIcon(HANDLE hContact, Info *info, const char *text); + +struct Info +{ + const char *name; + const char *desc; + const char *icon; + const char *db[8]; + void (*SetIcon)(HANDLE hContact, Info *info, const char *text); + void (*OnClick)(Info *info, const char *text); + HANDLE hExtraIcon; +} infos[] = { + { "homepage", "Homepage", "core_main_2", { NULL, "Homepage", + "UserInfo", "Homepage" }, DefaultSetIcon, &HomepageOnClick, NULL }, + { "sms", "Phone/SMS", "core_main_17", { NULL, "Cellular", + "UserInfo", "Cellular", + "UserInfo", "Phone", + "UserInfo", "MyPhone0" }, DefaultSetIcon, NULL, NULL }, + { "email", "E-mail", "core_main_14", { NULL, "e-mail", + "UserInfo", "e-mail", + "UserInfo", "Mye-mail0" }, DefaultSetIcon, &EmailOnClick, NULL }, +}; + +static void EmailOnClick(Info *info, const char *text) +{ + char cmd[1024]; + mir_snprintf(cmd, SIZEOF(cmd), "mailto:%s", text); + ShellExecuteA(NULL, "open", cmd, NULL, NULL, SW_SHOW); +} + +static void HomepageOnClick(Info *info, const char *text) +{ + ShellExecuteA(NULL, "open", text, NULL, NULL, SW_SHOW); +} + +static void DefaultSetIcon(HANDLE hContact, Info *info, const char *text) +{ + ExtraIcon_SetIcon(info->hExtraIcon, hContact, text ? info->icon : NULL); +} + +static void SetExtraIcons(HANDLE hContact) +{ + if (hContact == NULL) + return; + + char *proto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (IsEmpty(proto)) + return; + + for (unsigned int i = 0; i < SIZEOF(infos); ++i) + { + Info &info = infos[i]; + + bool show = false; + for (unsigned int j = 0; !show && j < SIZEOF(info.db); j += 2) + { + if (info.db[j + 1] == NULL) + break; + + DBVARIANT dbv = { 0 }; + if (!DBGetContactSettingString(hContact, info.db[j] == NULL ? proto : info.db[j], info.db[j+1], &dbv)) + { + if (!IsEmpty(dbv.pszVal)) + { + info.SetIcon(hContact, &info, dbv.pszVal); + show = true; + } + DBFreeVariant(&dbv); + } + } + } +} + +static int SettingChanged(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE) wParam; + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*) lParam; + + if (hContact == NULL) + return 0; + + char *proto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (IsEmpty(proto)) + return 0; + + bool isProto = (strcmp(cws->szModule, proto) == 0); + + if (isProto && strcmp(cws->szSetting, "ApparentMode") == 0) + { + SetVisibility(hContact, cws->value.type == DBVT_DELETED ? 0 : cws->value.wVal, TRUE); + return 0; + } + + if (strcmp(cws->szSetting, "Gender") == 0 && (isProto || strcmp(cws->szModule, "UserInfo") == 0)) + { + SetGender(hContact, cws->value.type == DBVT_DELETED ? 0 : cws->value.bVal, TRUE); + return 0; + } + + for (unsigned int i = 0; i < SIZEOF(infos); ++i) + { + Info &info = infos[i]; + + for (unsigned int j = 0; j < SIZEOF(info.db); j += 2) + { + if (info.db[j + 1] == NULL) + break; + if (info.db[j] == NULL && !isProto) + continue; + if (info.db[j] != NULL && strcmp(cws->szModule, info.db[j])) + continue; + if (strcmp(cws->szSetting, info.db[j + 1])) + continue; + + bool show = (cws->value.type != DBVT_DELETED && !IsEmpty(cws->value.pszVal)); + info.SetIcon(hContact, &info, show ? cws->value.pszVal : NULL); + + break; + } + } + + return 0; +} + +static int DefaultOnClick(WPARAM wParam, LPARAM lParam, LPARAM param) +{ + Info *info = (Info *) param; + if (info == NULL) + return 0; + + HANDLE hContact = (HANDLE) wParam; + if (hContact == NULL) + return 0; + + char *proto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (IsEmpty(proto)) + return 0; + + bool found = false; + for (unsigned int j = 0; !found && j < SIZEOF(info->db); j += 2) + { + if (info->db[j + 1] == NULL) + break; + + DBVARIANT dbv = { 0 }; + if (!DBGetContactSettingString(hContact, info->db[j] == NULL ? proto : info->db[j], info->db[j+1], &dbv)) + { + if (!IsEmpty(dbv.pszVal)) + { + info->OnClick(info, dbv.pszVal); + found = true; + } + + DBFreeVariant(&dbv); + } + } + + return 0; +} + +static void DBExtraIconsInit() +{ + hExtraChat = ExtraIcon_Register("chat_activity", "Chat activity", "ChatActivity"); + hExtraVisibility = ExtraIcon_Register("visibility", "Visibility", "AlwaysVis"); + hExtraGender = ExtraIcon_Register("gender", "Gender", "gender_male"); + for (unsigned int i = 0; i < SIZEOF(infos); ++i) + { + Info &info = infos[i]; + if (info.OnClick) + info.hExtraIcon = ExtraIcon_Register(info.name, info.desc, info.icon, DefaultOnClick, (LPARAM) &info); + else + info.hExtraIcon = ExtraIcon_Register(info.name, info.desc, info.icon); + } + + HANDLE hContact = db_find_first(); + while (hContact != NULL) + { + SetExtraIcons(hContact); + SetVisibility(hContact, -1, FALSE); + SetGender(hContact, -1, FALSE); + + hContact = db_find_next(hContact); + } + + HookEvent(ME_DB_CONTACT_SETTINGCHANGED, SettingChanged); +} + +// Protocol ///////////////////////////////////////////////////////////////////////////// + +struct ProtoInfo +{ + string proto; + HANDLE hImage; +}; + +vector protos; + +HANDLE hExtraProto = NULL; + +static int ProtocolRebuildIcons(WPARAM wParam, LPARAM lParam) +{ + protos.clear(); + return 0; +} + +static ProtoInfo *FindProto(const char * proto) +{ + for (unsigned int i = 0; i < protos.size(); ++i) + { + ProtoInfo *pi = &protos[i]; + if (strcmp(pi->proto.c_str(), proto) == 0) + return pi; + } + + HICON hIcon = LoadSkinnedProtoIcon(proto, ID_STATUS_ONLINE); + if (hIcon == NULL) + return NULL; + + HANDLE hImage = (HANDLE) CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM) hIcon, 0); + if (hImage == INVALID_HANDLE_VALUE) + return NULL; + + ProtoInfo tmp; + tmp.proto = proto; + tmp.hImage = hImage; + protos.push_back(tmp); + + return &protos[protos.size() - 1]; +} + +static int ProtocolApplyIcon(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE) wParam; + + char *proto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (IsEmpty(proto)) + return 0; + + ProtoInfo *pi = FindProto(proto); + + HANDLE hImage = INVALID_HANDLE_VALUE; + if (pi != NULL) + hImage = pi->hImage; + + ExtraIcon_SetIcon(hExtraProto, hContact, hImage); + + return 0; +} + +static int ProtocolOnClick(WPARAM wParam, LPARAM lParam, LPARAM param) +{ + HANDLE hContact = (HANDLE) wParam; + if (hContact == NULL) + return 0; + + CallService(MS_USERINFO_SHOWDIALOG, (WPARAM) hContact, 0); + return 0; +} + +static void ProtocolInit() +{ + hExtraProto = ExtraIcon_Register("protocol", "Account", "core_main_34", &ProtocolRebuildIcons, &ProtocolApplyIcon, + &ProtocolOnClick); +} diff --git a/src/modules/extraicons/DefaultExtraIcons.h b/src/modules/extraicons/DefaultExtraIcons.h new file mode 100644 index 0000000000..fba4602d41 --- /dev/null +++ b/src/modules/extraicons/DefaultExtraIcons.h @@ -0,0 +1,26 @@ +/* + Copyright (C) 2009 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 __DEFAULTEXTRAICONS_H__ +#define __DEFAULTEXTRAICONS_H__ + +void DefaultExtraIcons_Load(); +void DefaultExtraIcons_Unload(); + +#endif // __DEFAULTEXTRAICONS_H__ diff --git a/src/modules/extraicons/ExtraIcon.cpp b/src/modules/extraicons/ExtraIcon.cpp new file mode 100644 index 0000000000..50758a4056 --- /dev/null +++ b/src/modules/extraicons/ExtraIcon.cpp @@ -0,0 +1,134 @@ +/* + Copyright (C) 2009 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 "..\..\core\commonheaders.h" + +#include "BaseExtraIcon.h" +#include "ExtraIcon.h" +#include "extraicons.h" + +ExtraIcon::ExtraIcon(const char *name) : + name(name), slot(-1), position(1000) +{ +} + +ExtraIcon::~ExtraIcon() +{ +} + +const char *ExtraIcon::getName() const +{ + return name.c_str(); +} + +int ExtraIcon::getSlot() const +{ + return slot; +} + +void ExtraIcon::setSlot(int slot) +{ + this->slot = slot; +} + +int ExtraIcon::getPosition() const +{ + return position; +} + +void ExtraIcon::setPosition(int position) +{ + this->position = position; +} + +bool ExtraIcon::isEnabled() const +{ + return slot >= 0; +} + +void ExtraIcon::applyIcons() +{ + if (!isEnabled()) + return; + + HANDLE hContact = db_find_first(); + while (hContact != NULL) + { + // Clear to assert that it will be cleared + Clist_SetExtraIcon(hContact, slot, INVALID_HANDLE_VALUE); + + applyIcon(hContact); + + hContact = db_find_next(hContact); + } +} + +int ExtraIcon::compare(const ExtraIcon *other) const +{ + if (this == other) + return 0; + + int ret = getPosition() - other->getPosition(); + if (ret != 0) + return ret; + + int id = 0; + if (getType() != EXTRAICON_TYPE_GROUP) + id = ((BaseExtraIcon*) this)->getID(); + int otherId = 0; + if (other->getType() != EXTRAICON_TYPE_GROUP) + otherId = ((BaseExtraIcon*) other)->getID(); + return id - otherId; +} + +bool ExtraIcon::operator==(const ExtraIcon & other) const +{ + int c = compare(&other); + return c == 0; +} + +bool ExtraIcon::operator!=(const ExtraIcon & other) const +{ + int c = compare(&other); + return c != 0; +} + +bool ExtraIcon::operator<(const ExtraIcon & other) const +{ + int c = compare(&other); + return c < 0; +} + +bool ExtraIcon::operator<=(const ExtraIcon & other) const +{ + int c = compare(&other); + return c <= 0; +} + +bool ExtraIcon::operator>(const ExtraIcon & other) const +{ + int c = compare(&other); + return c > 0; +} + +bool ExtraIcon::operator>=(const ExtraIcon & other) const +{ + int c = compare(&other); + return c >= 0; +} diff --git a/src/modules/extraicons/ExtraIcon.h b/src/modules/extraicons/ExtraIcon.h new file mode 100644 index 0000000000..281e9e25eb --- /dev/null +++ b/src/modules/extraicons/ExtraIcon.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2009 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 __EXTRAICON_H__ +#define __EXTRAICON_H__ + +#include + +#define EXTRAICON_TYPE_GROUP -1 + +class ExtraIcon +{ +public: + ExtraIcon(const char *name); + virtual ~ExtraIcon(); + + virtual void rebuildIcons() =0; + virtual void applyIcons(); + virtual void applyIcon(HANDLE hContact) =0; + virtual void onClick(HANDLE hContact) =0; + + virtual int setIcon(int id, HANDLE hContact, void *icon) =0; + virtual void storeIcon(HANDLE hContact, void *icon) =0; + + virtual const char *getName() const; + virtual const TCHAR *getDescription() const =0; + virtual const char *getDescIcon() const =0; + virtual int getType() const =0; + + virtual int getSlot() const; + virtual void setSlot(int slot); + + virtual int getPosition() const; + virtual void setPosition(int position); + + virtual bool isEnabled() const; + + /// @retun <0 if this < other, 0 if this == other, >0 if this > other + virtual int compare(const ExtraIcon *other) const; + + bool operator==(const ExtraIcon &other) const; + bool operator!=(const ExtraIcon &other) const; + bool operator<(const ExtraIcon &other) const; + bool operator<=(const ExtraIcon &other) const; + bool operator>(const ExtraIcon &other) const; + bool operator>=(const ExtraIcon &other) const; + + virtual int ClistSetExtraIcon(HANDLE hContact, HANDLE hImage) =0; + +protected: + std::string name; + + int slot; + int position; +}; + +#endif // __EXTRAICON_H__ diff --git a/src/modules/extraicons/ExtraIconGroup.cpp b/src/modules/extraicons/ExtraIconGroup.cpp new file mode 100644 index 0000000000..6e823bde03 --- /dev/null +++ b/src/modules/extraicons/ExtraIconGroup.cpp @@ -0,0 +1,215 @@ +/* + Copyright (C) 2009 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 "..\..\core\commonheaders.h" + +#include "BaseExtraIcon.h" +#include "ExtraIconGroup.h" +#include "extraicons.h" + +ExtraIconGroup::ExtraIconGroup(const char *name) : + ExtraIcon(name), setValidExtraIcon(false), insideApply(false) +{ + char setting[512]; + mir_snprintf(setting, SIZEOF(setting), "%s/%s", MODULE_NAME, name); + CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (WPARAM) setting); +} + +ExtraIconGroup::~ExtraIconGroup() +{ + items.clear(); +} + +void ExtraIconGroup::addExtraIcon(BaseExtraIcon *extra) +{ + items.push_back(extra); + + description.clear(); + for (unsigned int i = 0; i < items.size(); ++i) + { + if (i > 0) + description += _T(" / "); + description += items[i]->getDescription(); + } +} + +void ExtraIconGroup::rebuildIcons() +{ + for (unsigned int i = 0; i < items.size(); ++i) + items[i]->rebuildIcons(); +} + +void ExtraIconGroup::applyIcon(HANDLE hContact) +{ + if (!isEnabled() || hContact == NULL) + return; + + setValidExtraIcon = false; + + insideApply = true; + + unsigned int i; + for (i = 0; i < items.size(); ++i) + { + items[i]->applyIcon(hContact); + + if (setValidExtraIcon) + break; + } + + insideApply = false; + + DBWriteContactSettingDword(hContact, MODULE_NAME, name.c_str(), setValidExtraIcon ? items[i]->getID() : 0); +} + +int ExtraIconGroup::getPosition() const +{ + int pos = INT_MAX; + for (unsigned int i = 0; i < items.size(); ++i) + pos = MIN(pos, items[i]->getPosition()); + return pos; +} + +void ExtraIconGroup::setSlot(int slot) +{ + ExtraIcon::setSlot(slot); + + for (unsigned int i = 0; i < items.size(); ++i) + items[i]->setSlot(slot); +} + +ExtraIcon * ExtraIconGroup::getCurrentItem(HANDLE hContact) const +{ + int id = (int) DBGetContactSettingDword(hContact, MODULE_NAME, name.c_str(), 0); + if (id < 1) + return NULL; + + for (unsigned int i = 0; i < items.size(); ++i) + if (id == items[i]->getID()) + return items[i]; + + return NULL; +} + +void ExtraIconGroup::onClick(HANDLE hContact) +{ + ExtraIcon *extra = getCurrentItem(hContact); + if (extra != NULL) + extra->onClick(hContact); +} + +int ExtraIconGroup::setIcon(int id, HANDLE hContact, void *icon) +{ + if (insideApply) + { + for (unsigned int i = 0; i < items.size(); ++i) + if (items[i]->getID() == id) + return items[i]->setIcon(id, hContact, icon); + + return -1; + } + + ExtraIcon *current = getCurrentItem(hContact); + int currentPos = (int)items.size(); + int storePos = (int)items.size(); + for (unsigned int i = 0; i < items.size(); ++i) + { + if (items[i]->getID() == id) + storePos = i; + + if (items[i] == current) + currentPos = i; + } + + if (storePos == items.size()) + return -1; + + if (storePos > currentPos) + { + items[storePos]->storeIcon(hContact, icon); + return 0; + } + + // Ok, we have to set the icon, but we have to assert it is a valid icon + + setValidExtraIcon = false; + + int ret = items[storePos]->setIcon(id, hContact, icon); + + if (storePos < currentPos) + { + if (setValidExtraIcon) + DBWriteContactSettingDword(hContact, MODULE_NAME, name.c_str(), items[storePos]->getID()); + } + else if (storePos == currentPos) + { + if (!setValidExtraIcon) + { + DBWriteContactSettingDword(hContact, MODULE_NAME, name.c_str(), 0); + + insideApply = true; + + for (++storePos; storePos < (int)items.size(); ++storePos) + { + items[storePos]->applyIcon(hContact); + + if (setValidExtraIcon) + break; + } + + insideApply = false; + + if (setValidExtraIcon) + DBWriteContactSettingDword(hContact, MODULE_NAME, name.c_str(), items[storePos]->getID()); + } + } + + return ret; +} + +void ExtraIconGroup::storeIcon(HANDLE hContact, void *icon) +{ +} + +const TCHAR *ExtraIconGroup::getDescription() const +{ + return description.c_str(); +} + +const char *ExtraIconGroup::getDescIcon() const +{ + for (unsigned int i = 0; i < items.size(); ++i) + if (!IsEmpty(items[i]->getDescIcon())) + return items[i]->getDescIcon(); + + return ""; +} + +int ExtraIconGroup::getType() const +{ + return EXTRAICON_TYPE_GROUP; +} + +int ExtraIconGroup::ClistSetExtraIcon(HANDLE hContact, HANDLE hImage) +{ + if (hImage != INVALID_HANDLE_VALUE) + setValidExtraIcon = true; + + return Clist_SetExtraIcon(hContact, slot, hImage); +} diff --git a/src/modules/extraicons/ExtraIconGroup.h b/src/modules/extraicons/ExtraIconGroup.h new file mode 100644 index 0000000000..eb2aec5561 --- /dev/null +++ b/src/modules/extraicons/ExtraIconGroup.h @@ -0,0 +1,62 @@ +/* + Copyright (C) 2009 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 __EXTRAICONGROUP_H__ +#define __EXTRAICONGROUP_H__ + +#include +#include "ExtraIcon.h" + +class BaseExtraIcon; + +class ExtraIconGroup : public ExtraIcon +{ +public: + ExtraIconGroup(const char *name); + virtual ~ExtraIconGroup(); + + virtual void addExtraIcon(BaseExtraIcon *extra); + + virtual void rebuildIcons(); + virtual void applyIcon(HANDLE hContact); + virtual void onClick(HANDLE hContact); + + virtual int setIcon(int id, HANDLE hContact, void *icon); + virtual void storeIcon(HANDLE hContact, void *icon); + + virtual const TCHAR *getDescription() const; + virtual const char *getDescIcon() const; + virtual int getType() const; + + virtual int getPosition() const; + virtual void setSlot(int slot); + + std::vector items; + + virtual int ClistSetExtraIcon(HANDLE hContact, HANDLE hImage); + +protected: + std::tstring description; + bool setValidExtraIcon; + bool insideApply; + + virtual ExtraIcon * getCurrentItem(HANDLE hContact) const; +}; + +#endif // __EXTRAICONGROUP_H__ diff --git a/src/modules/extraicons/IcolibExtraIcon.cpp b/src/modules/extraicons/IcolibExtraIcon.cpp new file mode 100644 index 0000000000..c50d815e57 --- /dev/null +++ b/src/modules/extraicons/IcolibExtraIcon.cpp @@ -0,0 +1,114 @@ +/* + Copyright (C) 2009 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 "..\..\core\commonheaders.h" + +#include "IcolibExtraIcon.h" + +#include "extraicons.h" +#include "usedIcons.h" + +IcolibExtraIcon::IcolibExtraIcon(int id, const char *name, const TCHAR *description, const char *descIcon, + MIRANDAHOOKPARAM OnClick, LPARAM param) : + BaseExtraIcon(id, name, description, descIcon, OnClick, param) +{ + char setting[512]; + mir_snprintf(setting, SIZEOF(setting), "%s/%s", MODULE_NAME, name); + CallService(MS_DB_SETSETTINGRESIDENT, TRUE, (WPARAM) setting); +} + +IcolibExtraIcon::~IcolibExtraIcon() +{ +} + +int IcolibExtraIcon::getType() const +{ + return EXTRAICON_TYPE_ICOLIB; +} + +void IcolibExtraIcon::rebuildIcons() +{ +} + +void IcolibExtraIcon::applyIcon(HANDLE hContact) +{ + if (!isEnabled() || hContact == NULL) + return; + + HANDLE hImage = INVALID_HANDLE_VALUE; + + DBVARIANT dbv = { 0 }; + if (!DBGetContactSettingString(hContact, MODULE_NAME, name.c_str(), &dbv)) + { + if (!IsEmpty(dbv.pszVal)) + hImage = GetIcon(dbv.pszVal); + + DBFreeVariant(&dbv); + } + + ClistSetExtraIcon(hContact, hImage); +} + +int IcolibExtraIcon::setIcon(int id, HANDLE hContact, void *icon) +{ + if (hContact == NULL || id != this->id) + return -1; + + if (isEnabled()) + { + DBVARIANT dbv = { 0 }; + if (!DBGetContactSettingString(hContact, MODULE_NAME, name.c_str(), &dbv)) + { + if (!IsEmpty(dbv.pszVal)) + RemoveIcon(dbv.pszVal); + + DBFreeVariant(&dbv); + } + } + + storeIcon(hContact, icon); + + if (isEnabled()) + { + const char *icolibName = (const char *) icon; + + HANDLE hImage; + if (IsEmpty(icolibName)) + hImage = INVALID_HANDLE_VALUE; + else + hImage = AddIcon(icolibName); + + return ClistSetExtraIcon(hContact, hImage); + } + + return 0; +} + +void IcolibExtraIcon::storeIcon(HANDLE hContact, void *icon) +{ + if (hContact == NULL) + return; + + const char *icolibName = (const char *) icon; + if (IsEmpty(icolibName)) + icolibName = ""; // Delete don't work and I don't know why + + DBWriteContactSettingString(hContact, MODULE_NAME, name.c_str(), icolibName); +} + diff --git a/src/modules/extraicons/IcolibExtraIcon.h b/src/modules/extraicons/IcolibExtraIcon.h new file mode 100644 index 0000000000..5f113e7251 --- /dev/null +++ b/src/modules/extraicons/IcolibExtraIcon.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2009 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 __ICOLIBEXTRAICON_H__ +#define __ICOLIBEXTRAICON_H__ + +#include "BaseExtraIcon.h" + +class IcolibExtraIcon : public BaseExtraIcon +{ +public: + IcolibExtraIcon(int id, const char *name, const TCHAR *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, + LPARAM param); + virtual ~IcolibExtraIcon(); + + virtual int getType() const; + + virtual void rebuildIcons(); + virtual void applyIcon(HANDLE hContact); + + virtual int setIcon(int id, HANDLE hContact, void *icon); + virtual void storeIcon(HANDLE hContact, void *icon); +}; + +#endif // __ICOLIBEXTRAICON_H__ diff --git a/src/modules/extraicons/extraicons.cpp b/src/modules/extraicons/extraicons.cpp new file mode 100644 index 0000000000..ae571991e4 --- /dev/null +++ b/src/modules/extraicons/extraicons.cpp @@ -0,0 +1,485 @@ +/* + Copyright (C) 2009 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 "..\..\core\commonheaders.h" + +#include "m_cluiframes.h" + +#include "BaseExtraIcon.h" +#include "CallbackExtraIcon.h" +#include "DefaultExtraIcons.h" +#include "ExtraIcon.h" +#include "ExtraIconGroup.h" +#include "IcolibExtraIcon.h" + +#include "extraicons.h" +#include "options.h" +#include "usedIcons.h" + +// Prototypes /////////////////////////////////////////////////////////////////////////// + +vector registeredExtraIcons; +vector extraIconsByHandle; +vector extraIconsBySlot; + +BOOL clistRebuildAlreadyCalled = FALSE; +BOOL clistApplyAlreadyCalled = FALSE; + +int clistFirstSlot = 0; +int clistSlotCount = 0; + +int ModulesLoaded(WPARAM wParam, LPARAM lParam); +int PreShutdown(WPARAM wParam, LPARAM lParam); +int IconsChanged(WPARAM wParam, LPARAM lParam); +int ClistExtraListRebuild(WPARAM wParam, LPARAM lParam); +int ClistExtraImageApply(WPARAM wParam, LPARAM lParam); +int ClistExtraClick(WPARAM wParam, LPARAM lParam); + +INT_PTR ExtraIcon_Register(WPARAM wParam, LPARAM lParam); +INT_PTR ExtraIcon_SetIcon(WPARAM wParam, LPARAM lParam); + +// Functions //////////////////////////////////////////////////////////////////////////// + +void LoadExtraIconsModule() +{ + DWORD ret = CallService(MS_CLUI_GETCAPS, CLUICAPS_FLAGS2, 0); + clistFirstSlot = HIWORD(ret); + clistSlotCount = LOWORD(ret); + + // Icons + TCHAR tszFile[MAX_PATH]; + GetModuleFileName(NULL, tszFile, MAX_PATH); + + SKINICONDESC sid = {0}; + sid.cbSize = sizeof(SKINICONDESC); + sid.flags = SIDF_PATH_TCHAR; + sid.ptszDefaultFile = tszFile; + sid.pszSection = "Contact List"; + + sid.pszName = "AlwaysVis"; + sid.pszDescription = LPGEN("Always Visible"); + sid.iDefaultIndex = -IDI_ALWAYSVIS; + Skin_AddIcon(&sid); + + sid.pszName = "NeverVis"; + sid.pszDescription = LPGEN("Never Visible"); + sid.iDefaultIndex = -IDI_NEVERVIS; + Skin_AddIcon(&sid); + + sid.pszName = "ChatActivity"; + sid.pszDescription = LPGEN("Chat Activity"); + sid.iDefaultIndex = -IDI_CHAT; + Skin_AddIcon(&sid); + + sid.pszName = "gender_male"; + sid.pszDescription = LPGEN("Male"); + sid.iDefaultIndex = -IDI_MALE; + Skin_AddIcon(&sid); + + sid.pszName = "gender_female"; + sid.pszDescription = LPGEN("Female"); + sid.iDefaultIndex = -IDI_FEMALE; + Skin_AddIcon(&sid); + + // Hooks + HookEvent(ME_SYSTEM_MODULESLOADED, &ModulesLoaded); + HookEvent(ME_SYSTEM_PRESHUTDOWN, &PreShutdown); + HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, &ClistExtraListRebuild); + HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, &ClistExtraImageApply); + HookEvent(ME_CLIST_EXTRA_CLICK, &ClistExtraClick); + + // Services + CreateServiceFunction(MS_EXTRAICON_REGISTER, &ExtraIcon_Register); + CreateServiceFunction(MS_EXTRAICON_SET_ICON, &ExtraIcon_SetIcon); + + DefaultExtraIcons_Load(); +} + +void UnloadExtraIconsModule(void) +{ + for (size_t i=0; i < registeredExtraIcons.size(); i++) + delete registeredExtraIcons[i]; +} + +// Called when all the modules are loaded +int ModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + // add our modules to the KnownModules list + CallService("DBEditorpp/RegisterSingleModule", (WPARAM) MODULE_NAME, 0); + CallService("DBEditorpp/RegisterSingleModule", (WPARAM) MODULE_NAME "Groups", 0); + + HookEvent(ME_SKIN2_ICONSCHANGED, &IconsChanged); + + InitOptions(); + return 0; +} + +int IconsChanged(WPARAM wParam, LPARAM lParam) +{ + return 0; +} + +int PreShutdown(WPARAM wParam, LPARAM lParam) +{ + DefaultExtraIcons_Unload(); + DeInitOptions(); + return 0; +} + +int GetNumberOfSlots() +{ + return clistSlotCount; +} + +int ConvertToClistSlot(int slot) +{ + if (slot < 0) + return slot; + + return clistFirstSlot + slot; +} + +int Clist_SetExtraIcon(HANDLE hContact, int slot, HANDLE hImage) +{ + IconExtraColumn iec = { 0 }; + iec.cbSize = sizeof(iec); + iec.ColumnType = ConvertToClistSlot(slot); + iec.hImage = hImage; + + return CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM) hContact, (LPARAM) &iec); +} + +ExtraIcon * GetExtraIcon(HANDLE id) +{ + unsigned int i = (int) id; + + if (i < 1 || i > extraIconsByHandle.size()) + return NULL; + + return extraIconsByHandle[i - 1]; +} + +ExtraIcon * GetExtraIconBySlot(int slot) +{ + for (unsigned int i = 0; i < extraIconsBySlot.size(); ++i) + { + ExtraIcon *extra = extraIconsBySlot[i]; + if (extra->getSlot() == slot) + return extra; + } + return NULL; +} + +BaseExtraIcon * GetExtraIconByName(const char *name) +{ + for (unsigned int i = 0; i < registeredExtraIcons.size(); ++i) + { + BaseExtraIcon *extra = registeredExtraIcons[i]; + if (strcmp(name, extra->getName()) == 0) + return extra; + } + return NULL; +} + +static void LoadGroups(vector &groups) +{ + unsigned int count = DBGetContactSettingWord(NULL, MODULE_NAME "Groups", "Count", 0); + for (unsigned int i = 0; i < count; ++i) + { + char setting[512]; + mir_snprintf(setting, SIZEOF(setting), "%d_count", i); + unsigned int items = DBGetContactSettingWord(NULL, MODULE_NAME "Groups", setting, 0); + if (items < 1) + continue; + + mir_snprintf(setting, SIZEOF(setting), "__group_%d", i); + ExtraIconGroup *group = new ExtraIconGroup(setting); + + for (unsigned int j = 0; j < items; ++j) + { + mir_snprintf(setting, SIZEOF(setting), "%d_%d", i, j); + + DBVARIANT dbv = { 0 }; + if (!DBGetContactSettingString(NULL, MODULE_NAME "Groups", setting, &dbv)) + { + if (!IsEmpty(dbv.pszVal)) + { + BaseExtraIcon *extra = GetExtraIconByName(dbv.pszVal); + if (extra != NULL) + { + group->items.push_back(extra); + + if (extra->getSlot() >= 0) + group->setSlot(extra->getSlot()); + } + } + DBFreeVariant(&dbv); + } + } + + if (group->items.size() < 2) + { + delete group; + continue; + } + + groups.push_back(group); + } +} + +static ExtraIconGroup * IsInGroup(vector &groups, BaseExtraIcon *extra) +{ + for (unsigned int i = 0; i < groups.size(); ++i) + { + ExtraIconGroup *group = groups[i]; + for (unsigned int j = 0; j < group->items.size(); ++j) + { + if (extra == group->items[j]) + return group; + } + } + return NULL; +} + +struct compareFunc : std::binary_function +{ + bool operator()(const ExtraIcon * one, const ExtraIcon * two) const + { + return *one < *two; + } +}; + +void RebuildListsBasedOnGroups(vector &groups) +{ + unsigned int i; + for (i = 0; i < extraIconsByHandle.size(); ++i) + extraIconsByHandle[i] = registeredExtraIcons[i]; + + for (i = 0; i < extraIconsBySlot.size(); ++i) + { + ExtraIcon *extra = extraIconsBySlot[i]; + if (extra->getType() != EXTRAICON_TYPE_GROUP) + continue; + + delete extra; + } + extraIconsBySlot.clear(); + + for (i = 0; i < groups.size(); ++i) + { + ExtraIconGroup *group = groups[i]; + + for (unsigned int j = 0; j < group->items.size(); ++j) + extraIconsByHandle[group->items[j]->getID() - 1] = group; + + extraIconsBySlot.push_back(group); + } + + for (i = 0; i < extraIconsByHandle.size(); ++i) + { + ExtraIcon *extra = extraIconsByHandle[i]; + if (extra->getType() != EXTRAICON_TYPE_GROUP) + extraIconsBySlot.push_back(extra); + } + + std::sort(extraIconsBySlot.begin(), extraIconsBySlot.end(), compareFunc()); +} + +INT_PTR ExtraIcon_Register(WPARAM wParam, LPARAM lParam) +{ + if (wParam == 0) + return 0; + + EXTRAICON_INFO *ei = (EXTRAICON_INFO *) wParam; + if (ei->cbSize < (int) sizeof(EXTRAICON_INFO)) + return 0; + if (ei->type != EXTRAICON_TYPE_CALLBACK && ei->type != EXTRAICON_TYPE_ICOLIB) + return 0; + if (IsEmpty(ei->name) || IsEmpty(ei->description)) + return 0; + if (ei->type == EXTRAICON_TYPE_CALLBACK && (ei->ApplyIcon == NULL || ei->RebuildIcons == NULL)) + return 0; + + TCHAR *desc = Langpack_PcharToTchar(ei->description); + + BaseExtraIcon *extra = GetExtraIconByName(ei->name); + if (extra != NULL) + { + if (ei->type != extra->getType() || ei->type != EXTRAICON_TYPE_ICOLIB) + return 0; + + // Found one, now merge it + + if (_tcsicmp(extra->getDescription(), desc)) + { + tstring newDesc = extra->getDescription(); + newDesc += _T(" / "); + newDesc += desc; + extra->setDescription(newDesc.c_str()); + } + + if (!IsEmpty(ei->descIcon)) + extra->setDescIcon(ei->descIcon); + + if (ei->OnClick != NULL) + extra->setOnClick(ei->OnClick, ei->onClickParam); + + if (extra->getSlot() > 0) + { + if (clistRebuildAlreadyCalled) + extra->rebuildIcons(); + if (clistApplyAlreadyCalled) + extraIconsByHandle[extra->getID() - 1]->applyIcons(); + } + + return extra->getID(); + } + + int id = (int)registeredExtraIcons.size() + 1; + + switch (ei->type) { + case EXTRAICON_TYPE_CALLBACK: + extra = new CallbackExtraIcon(id, ei->name, desc, ei->descIcon == NULL ? "" : ei->descIcon, + ei->RebuildIcons, ei->ApplyIcon, ei->OnClick, ei->onClickParam); + break; + case EXTRAICON_TYPE_ICOLIB: + extra = new IcolibExtraIcon(id, ei->name, desc, ei->descIcon == NULL ? "" : ei->descIcon, ei->OnClick, + ei->onClickParam); + break; + default: + return 0; + } + + char setting[512]; + mir_snprintf(setting, SIZEOF(setting), "Position_%s", ei->name); + extra->setPosition(DBGetContactSettingWord(NULL, MODULE_NAME, setting, 1000)); + + mir_snprintf(setting, SIZEOF(setting), "Slot_%s", ei->name); + int slot = DBGetContactSettingWord(NULL, MODULE_NAME, setting, 1); + if (slot == (WORD) -1) + slot = -1; + extra->setSlot(slot); + + registeredExtraIcons.push_back(extra); + extraIconsByHandle.push_back(extra); + + vector groups; + LoadGroups(groups); + + ExtraIconGroup *group = IsInGroup(groups, extra); + if (group != NULL) + { + RebuildListsBasedOnGroups(groups); + } + else + { + for (unsigned int i = 0; i < groups.size(); ++i) + delete groups[i]; + + extraIconsBySlot.push_back(extra); + std::sort(extraIconsBySlot.begin(), extraIconsBySlot.end(), compareFunc()); + } + + if (slot >= 0 || group != NULL) + { + if (clistRebuildAlreadyCalled) + extra->rebuildIcons(); + + slot = 0; + for (unsigned int i = 0; i < extraIconsBySlot.size(); ++i) + { + ExtraIcon *ex = extraIconsBySlot[i]; + if (ex->getSlot() < 0) + continue; + + int oldSlot = ex->getSlot(); + ex->setSlot(slot++); + + if (clistApplyAlreadyCalled && (ex == group || ex == extra || oldSlot != slot)) + extra->applyIcons(); + } + } + + return id; +} + +INT_PTR ExtraIcon_SetIcon(WPARAM wParam, LPARAM lParam) +{ + if (wParam == 0) + return -1; + + EXTRAICON *ei = (EXTRAICON *) wParam; + if (ei->cbSize < (int) sizeof(EXTRAICON)) + return -1; + if (ei->hExtraIcon == NULL || ei->hContact == NULL) + return -1; + + ExtraIcon *extra = GetExtraIcon(ei->hExtraIcon); + if (extra == NULL) + return -1; + + return extra->setIcon((int) ei->hExtraIcon, ei->hContact, ei->hImage); +} + +int ClistExtraListRebuild(WPARAM wParam, LPARAM lParam) +{ + clistRebuildAlreadyCalled = TRUE; + + ResetIcons(); + + for (unsigned int i = 0; i < extraIconsBySlot.size(); ++i) + extraIconsBySlot[i]->rebuildIcons(); + + return 0; +} + +int ClistExtraImageApply(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE) wParam; + if (hContact == NULL) + return 0; + + clistApplyAlreadyCalled = TRUE; + + for (unsigned int i = 0; i < extraIconsBySlot.size(); ++i) + extraIconsBySlot[i]->applyIcon(hContact); + + return 0; +} + +int ClistExtraClick(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE) wParam; + if (hContact == NULL) + return 0; + + int clistSlot = (int) lParam; + + for (unsigned int i = 0; i < extraIconsBySlot.size(); ++i) + { + ExtraIcon *extra = extraIconsBySlot[i]; + if (ConvertToClistSlot(extra->getSlot()) == clistSlot) + { + extra->onClick(hContact); + break; + } + } + + return 0; +} diff --git a/src/modules/extraicons/extraicons.h b/src/modules/extraicons/extraicons.h new file mode 100644 index 0000000000..21ad6e955f --- /dev/null +++ b/src/modules/extraicons/extraicons.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2009 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 MODULE_NAME "ExtraIcons" + +// Global Variables +extern HINSTANCE hInst; + +#define FREE(_m_) if (_m_ != NULL) { free(_m_); _m_ = NULL; } + +#define ICON_SIZE 16 + +class ExtraIconGroup; +class ExtraIcon; +class BaseExtraIcon; + +extern vector registeredExtraIcons; +extern vector extraIconsByHandle; +extern vector extraIconsBySlot; +void RebuildListsBasedOnGroups(vector &groups); +ExtraIcon * GetExtraIconBySlot(int slot); + +int GetNumberOfSlots(); +int ConvertToClistSlot(int slot); + +int Clist_SetExtraIcon(HANDLE hContact, int slot, HANDLE hImage); + +static inline BOOL IsEmpty(const char *str) +{ + return str == NULL || str[0] == 0; +} + +static inline int MIN(int a, int b) +{ + if (a <= b) + return a; + return b; +} + +static inline int MAX(int a, int b) +{ + if (a >= b) + return a; + return b; +} + +#endif // __COMMONS_H__ diff --git a/src/modules/extraicons/options.h b/src/modules/extraicons/options.h new file mode 100644 index 0000000000..5d50348c0e --- /dev/null +++ b/src/modules/extraicons/options.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2009 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__ + + +// Initializations needed by options +void InitOptions(); + +// Deinitializations needed by options +void DeInitOptions(); + + + +#endif // __OPTIONS_H__ diff --git a/src/modules/extraicons/options_ei.cpp b/src/modules/extraicons/options_ei.cpp new file mode 100644 index 0000000000..f0fd299482 --- /dev/null +++ b/src/modules/extraicons/options_ei.cpp @@ -0,0 +1,865 @@ +/* + Copyright (C) 2009 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 "..\..\core\commonheaders.h" + +#include "BaseExtraIcon.h" +#include "ExtraIconGroup.h" + +#include "extraicons.h" + +#define ICON_SIZE 16 + +// Prototypes ///////////////////////////////////////////////////////////////////////////////////// + +HANDLE hOptHook = NULL; + +// Functions ////////////////////////////////////////////////////////////////////////////////////// + +BOOL ScreenToClient(HWND hWnd, LPRECT lpRect) +{ + BOOL ret; + POINT pt; + + pt.x = lpRect->left; + pt.y = lpRect->top; + + 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; +} + +static void RemoveExtraIcons(int slot) +{ + HANDLE hContact = db_find_first(); + while (hContact != NULL) + { + Clist_SetExtraIcon(hContact, slot, INVALID_HANDLE_VALUE); + + hContact = db_find_next(hContact); + } +} + +#ifndef TVIS_FOCUSED +#define TVIS_FOCUSED 1 +#endif + +WNDPROC origTreeProc; + +static bool IsSelected(HWND tree, HTREEITEM hItem) +{ + return (TVIS_SELECTED & TreeView_GetItemState(tree, hItem, TVIS_SELECTED)) == TVIS_SELECTED; +} + +static void Tree_Select(HWND tree, HTREEITEM hItem) +{ + TreeView_SetItemState(tree, hItem, TVIS_SELECTED, TVIS_SELECTED); +} + +static void Tree_Unselect(HWND tree, HTREEITEM hItem) +{ + TreeView_SetItemState(tree, hItem, 0, TVIS_SELECTED); +} + +static void Tree_DropHilite(HWND tree, HTREEITEM hItem) +{ + TreeView_SetItemState(tree, hItem, TVIS_DROPHILITED, TVIS_DROPHILITED); +} + +static void Tree_DropUnhilite(HWND tree, HTREEITEM hItem) +{ + TreeView_SetItemState(tree, hItem, 0, TVIS_DROPHILITED); +} + +static void UnselectAll(HWND tree) +{ + TreeView_SelectItem(tree, NULL); + + HTREEITEM hItem = TreeView_GetRoot(tree); + while (hItem) + { + Tree_Unselect(tree, hItem); + hItem = TreeView_GetNextSibling(tree, hItem); + } +} + +static void Tree_SelectRange(HWND tree, HTREEITEM hStart, HTREEITEM hEnd) +{ + int start = 0; + int end = 0; + int i = 0; + HTREEITEM hItem = TreeView_GetRoot(tree); + while (hItem) + { + if (hItem == hStart) + start = i; + if (hItem == hEnd) + end = i; + + i++; + hItem = TreeView_GetNextSibling(tree, hItem); + } + + if (end < start) + { + int tmp = start; + start = end; + end = tmp; + } + + i = 0; + hItem = TreeView_GetRoot(tree); + while (hItem) + { + if (i >= start) + Tree_Select(tree, hItem); + if (i == end) + break; + + i++; + hItem = TreeView_GetNextSibling(tree, hItem); + } +} + +static int GetNumSelected(HWND tree) +{ + int ret = 0; + HTREEITEM hItem = TreeView_GetRoot(tree); + while (hItem) + { + if (IsSelected(tree, hItem)) + ret++; + hItem = TreeView_GetNextSibling(tree, hItem); + } + return ret; +} + +static void Tree_GetSelected(HWND tree, vector &selected) +{ + HTREEITEM hItem = TreeView_GetRoot(tree); + while (hItem) + { + if (IsSelected(tree, hItem)) + selected.push_back(hItem); + hItem = TreeView_GetNextSibling(tree, hItem); + } +} + +static void Tree_Select(HWND tree, vector &selected) +{ + for (unsigned int i = 0; i < selected.size(); i++) + if (selected[i] != NULL) + Tree_Select(tree, selected[i]); +} + +LRESULT CALLBACK TreeProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_LBUTTONDOWN: + { + DWORD pos = (DWORD) lParam; + + TVHITTESTINFO hti; + hti.pt.x = (short) LOWORD(pos); + hti.pt.y = (short) HIWORD(pos); + if (!TreeView_HitTest(hwndDlg, &hti)) + { + UnselectAll(hwndDlg); + break; + } + + if (!(wParam & (MK_CONTROL | MK_SHIFT)) || !(hti.flags & (TVHT_ONITEMICON | TVHT_ONITEMLABEL + | TVHT_ONITEMRIGHT))) + { + UnselectAll(hwndDlg); + TreeView_SelectItem(hwndDlg, hti.hItem); + break; + } + + if (wParam & MK_CONTROL) + { + vector selected; + Tree_GetSelected(hwndDlg, selected); + + + // Check if have to deselect it + for (unsigned int i = 0; i < selected.size(); i++) + { + if (selected[i] == hti.hItem) + { + // Deselect it + UnselectAll(hwndDlg); + selected[i] = NULL; + + if (i > 0) + hti.hItem = selected[0]; + + else if (i + 1 < selected.size()) + hti.hItem = selected[i + 1]; + + else + hti.hItem = NULL; + + break; + } + } + + TreeView_SelectItem(hwndDlg, hti.hItem); + Tree_Select(hwndDlg, selected); + } + else if (wParam & MK_SHIFT) + { + HTREEITEM hItem = TreeView_GetSelection(hwndDlg); + if (hItem == NULL) + break; + + vector selected; + Tree_GetSelected(hwndDlg, selected); + + TreeView_SelectItem(hwndDlg, hti.hItem); + Tree_Select(hwndDlg, selected); + Tree_SelectRange(hwndDlg, hItem, hti.hItem); + } + + return 0; + } + } + + return CallWindowProc(origTreeProc, hwndDlg, msg, wParam, lParam); +} + +static vector * Tree_GetIDs(HWND tree, HTREEITEM hItem) +{ + TVITEM tvi = { 0 }; + tvi.mask = TVIF_HANDLE | TVIF_PARAM; + tvi.hItem = hItem; + TreeView_GetItem(tree, &tvi); + + return (vector *) tvi.lParam; +} + +static HTREEITEM Tree_AddExtraIcon(HWND tree, BaseExtraIcon *extra, bool selected, HTREEITEM hAfter = TVI_LAST) +{ + vector *ids = new vector ; + ids->push_back(extra->getID()); + + TVINSERTSTRUCT tvis = { 0 }; + tvis.hParent = NULL; + tvis.hInsertAfter = hAfter; + tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE; + tvis.item.stateMask = TVIS_STATEIMAGEMASK; + tvis.item.iSelectedImage = tvis.item.iImage = extra->getID(); + tvis.item.lParam = (LPARAM) ids; + tvis.item.pszText = (LPTSTR)extra->getDescription(); + tvis.item.state = INDEXTOSTATEIMAGEMASK(selected ? 2 : 1); + return TreeView_InsertItem(tree, &tvis); +} + +static HTREEITEM Tree_AddExtraIconGroup(HWND tree, vector &group, bool selected, HTREEITEM hAfter = TVI_LAST) +{ + vector *ids = new vector ; + tstring desc; + int img = 0; + for (unsigned int i = 0; i < group.size(); ++i) + { + BaseExtraIcon *extra = registeredExtraIcons[group[i] - 1]; + ids->push_back(extra->getID()); + + if (img == 0 && !IsEmpty(extra->getDescIcon())) + img = extra->getID(); + + if (i > 0) + desc += _T(" / "); + desc += extra->getDescription(); + } + + TVINSERTSTRUCT tvis = { 0 }; + tvis.hParent = NULL; + tvis.hInsertAfter = hAfter; + tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE; + tvis.item.stateMask = TVIS_STATEIMAGEMASK; + tvis.item.iSelectedImage = tvis.item.iImage = img; + tvis.item.lParam = (LPARAM) ids; + tvis.item.pszText = (TCHAR*) desc.c_str(); + tvis.item.state = INDEXTOSTATEIMAGEMASK(selected ? 2 : 1); + return TreeView_InsertItem(tree, &tvis); +} + +static void GroupSelectedItems(HWND tree) +{ + vector toRemove; + vector ids; + bool selected = false; + HTREEITEM hPlace = NULL; + + + // Find items + + HTREEITEM hItem = TreeView_GetRoot(tree); + TVITEM tvi = { 0 }; + tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT | TVIF_STATE; + while (hItem) + { + if (IsSelected(tree, hItem)) + { + if (hPlace == NULL) + hPlace = hItem; + + tvi.hItem = hItem; + TreeView_GetItem(tree, &tvi); + + vector *iids = (vector *) tvi.lParam; + ids.insert(ids.end(), iids->begin(), iids->end()); + + if ((tvi.state & INDEXTOSTATEIMAGEMASK(3)) == INDEXTOSTATEIMAGEMASK(2)) + selected = true; + + toRemove.push_back(hItem); + } + + hItem = TreeView_GetNextSibling(tree, hItem); + } + + if (hPlace == NULL) + return; // None selected + + // Add new + int ii = ids.at(0); + ii = ids.at(1); + HTREEITEM hNew = Tree_AddExtraIconGroup(tree, ids, selected, hPlace); + + + // Remove old + for (unsigned int i = 0; i < toRemove.size(); ++i) + { + delete Tree_GetIDs(tree, toRemove[i]); + TreeView_DeleteItem(tree, toRemove[i]); + } + + // Select + UnselectAll(tree); + TreeView_SelectItem(tree, hNew); +} + +static void UngroupSelectedItems(HWND tree) +{ + HTREEITEM hItem = TreeView_GetSelection(tree); + if (hItem == NULL) + return; + vector *ids = Tree_GetIDs(tree, hItem); + if (ids->size() < 2) + return; + + bool selected = IsSelected(tree, hItem); + + for (size_t i = ids->size(); i > 0; --i) + { + BaseExtraIcon *extra = registeredExtraIcons[ids->at(i - 1) - 1]; + Tree_AddExtraIcon(tree, extra, selected, hItem); + } + + delete Tree_GetIDs(tree, hItem); + TreeView_DeleteItem(tree, hItem); + + UnselectAll(tree); +} + +static int ShowPopup(HWND hwndDlg, int popup) +{ + // Fix selection + HWND tree = GetDlgItem(hwndDlg, IDC_EXTRAORDER); + HTREEITEM hSelected = (HTREEITEM) SendMessage(tree, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0); + HTREEITEM hItem = TreeView_GetRoot(tree); + while (hItem) + { + if (hItem != hSelected && IsSelected(tree, hItem)) + Tree_DropHilite(tree, hItem); + hItem = TreeView_GetNextSibling(tree, hItem); + } + // InvalidateRect(tree, NULL, FALSE); + + HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_OPT_POPUP)); + HMENU submenu = GetSubMenu(menu, popup); + TranslateMenu(submenu); + + DWORD pos = GetMessagePos(); + int ret = TrackPopupMenu(submenu, TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_LEFTALIGN, LOWORD(pos), + HIWORD(pos), 0, hwndDlg, NULL); + + DestroyMenu(menu); + + + // Revert selection + hItem = TreeView_GetRoot(tree); + while (hItem) + { + if (hItem != hSelected && IsSelected(tree, hItem)) + Tree_DropUnhilite(tree, hItem); + hItem = TreeView_GetNextSibling(tree, hItem); + } + + return ret; +} + +static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) +{ + vector *a = (vector *) lParam1; + vector *b = (vector *) lParam2; + return registeredExtraIcons[a->at(0) - 1]->compare(registeredExtraIcons[b->at(0) - 1]); +} + +static INT_PTR CALLBACK OptionsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static int dragging = 0; + static HANDLE hDragItem = NULL; + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + + int numSlots = GetNumberOfSlots(); + if (numSlots < (int) registeredExtraIcons.size()) + { + TCHAR txt[512]; + mir_sntprintf(txt, SIZEOF(txt), TranslateT("* only the first %d icons will be shown"), numSlots); + + HWND label = GetDlgItem(hwndDlg, IDC_MAX_ICONS_L); + SetWindowText(label, txt); + ShowWindow(label, SW_SHOW); + } + + HWND tree = GetDlgItem(hwndDlg, IDC_EXTRAORDER); + SetWindowLongPtr(tree, GWL_STYLE, GetWindowLongPtr(tree, GWL_STYLE) | TVS_NOHSCROLL); + + int cx = GetSystemMetrics(SM_CXSMICON); + HIMAGELIST hImageList = ImageList_Create(cx, cx, ILC_COLOR32 | ILC_MASK, 2, 2); + + HICON hDefaultIcon = (HICON) LoadImage(hInst, MAKEINTRESOURCE(IDI_EMPTY), IMAGE_ICON, cx, cx, + LR_DEFAULTCOLOR | LR_SHARED); + ImageList_AddIcon(hImageList, hDefaultIcon); + DestroyIcon(hDefaultIcon); + + unsigned int i; + for (i = 0; i < registeredExtraIcons.size(); ++i) + { + ExtraIcon *extra = registeredExtraIcons[i]; + + HICON hIcon = Skin_GetIcon(extra->getDescIcon()); + if (hIcon == NULL) + { + HICON hDefaultIcon = (HICON) LoadImage(hInst, MAKEINTRESOURCE(IDI_EMPTY), IMAGE_ICON, cx, cx, + LR_DEFAULTCOLOR | LR_SHARED); + ImageList_AddIcon(hImageList, hDefaultIcon); + DestroyIcon(hDefaultIcon); + } + else + { + ImageList_AddIcon(hImageList, hIcon); + Skin_ReleaseIcon(hIcon); + } + } + TreeView_SetImageList(tree, hImageList, TVSIL_NORMAL); + + for (i = 0; i < extraIconsBySlot.size(); ++i) + { + ExtraIcon *extra = extraIconsBySlot[i]; + + if (extra->getType() == EXTRAICON_TYPE_GROUP) + { + ExtraIconGroup *group = (ExtraIconGroup *) extra; + vector ids; + for (unsigned int j = 0; j < group->items.size(); ++j) + ids.push_back(group->items[j]->getID()); + Tree_AddExtraIconGroup(tree, ids, extra->isEnabled()); + } + else + { + Tree_AddExtraIcon(tree, (BaseExtraIcon *) extra, extra->isEnabled()); + } + } + + TVSORTCB sort = { 0 }; + sort.hParent = NULL; + sort.lParam = 0; + sort.lpfnCompare = CompareFunc; + TreeView_SortChildrenCB(tree, &sort, 0); + + origTreeProc = (WNDPROC) SetWindowLongPtr(tree, GWLP_WNDPROC, (INT_PTR)TreeProc); + + return TRUE; + } + case WM_NOTIFY: + { + LPNMHDR lpnmhdr = (LPNMHDR) lParam; + if (lpnmhdr->idFrom == 0) + { + if (lpnmhdr->code == (UINT) PSN_APPLY) + { + unsigned int i; + + HWND tree = GetDlgItem(hwndDlg, IDC_EXTRAORDER); + + + // Store old slots + int *oldSlots = new int[registeredExtraIcons.size()]; + int lastUsedSlot = -1; + for (i = 0; i < registeredExtraIcons.size(); ++i) + { + if (extraIconsByHandle[i] == registeredExtraIcons[i]) + oldSlots[i] = registeredExtraIcons[i]->getSlot(); + else + // Remove old slot for groups to re-set images + oldSlots[i] = -1; + lastUsedSlot = MAX(lastUsedSlot, registeredExtraIcons[i]->getSlot()); + } + lastUsedSlot = MIN(lastUsedSlot, GetNumberOfSlots()); + + + // Get user data and create new groups + vector groups; + + BYTE pos = 0; + int firstEmptySlot = 0; + HTREEITEM ht = TreeView_GetRoot(tree); + TVITEM tvi = { 0 }; + tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE; + tvi.stateMask = TVIS_STATEIMAGEMASK; + while (ht) + { + tvi.hItem = ht; + TreeView_GetItem(tree, &tvi); + + vector *ids = (vector *) tvi.lParam; + if (ids == NULL || ids->size() < 1) + continue; // ??? + + bool enabled = ((tvi.state & INDEXTOSTATEIMAGEMASK(3)) == INDEXTOSTATEIMAGEMASK(2)); + int slot = (enabled ? firstEmptySlot++ : -1); + if (slot >= GetNumberOfSlots()) + slot = -1; + + if (ids->size() == 1) + { + BaseExtraIcon *extra = registeredExtraIcons[ids->at(0) - 1]; + extra->setPosition(pos++); + extra->setSlot(slot); + } + else + { + char name[128]; + mir_snprintf(name, SIZEOF(name), "__group_%d", groups.size()); + + ExtraIconGroup *group = new ExtraIconGroup(name); + + for (i = 0; i < ids->size(); ++i) + { + BaseExtraIcon *extra = registeredExtraIcons[ids->at(i) - 1]; + extra->setPosition(pos++); + + group->addExtraIcon(extra); + } + + group->setSlot(slot); + + groups.push_back(group); + } + + ht = TreeView_GetNextSibling(tree, ht); + } + + // Store data + for (i = 0; i < registeredExtraIcons.size(); ++i) + { + BaseExtraIcon *extra = registeredExtraIcons[i]; + + char setting[512]; + mir_snprintf(setting, SIZEOF(setting), "Position_%s", extra->getName()); + DBWriteContactSettingWord(NULL, MODULE_NAME, setting, extra->getPosition()); + + mir_snprintf(setting, SIZEOF(setting), "Slot_%s", extra->getName()); + DBWriteContactSettingWord(NULL, MODULE_NAME, setting, extra->getSlot()); + } + + CallService(MS_DB_MODULE_DELETE, 0, (LPARAM) MODULE_NAME "Groups"); + DBWriteContactSettingWord(NULL, MODULE_NAME "Groups", "Count", (WORD)groups.size()); + for (i = 0; i < groups.size(); ++i) + { + ExtraIconGroup *group = groups[i]; + + char setting[512]; + mir_snprintf(setting, SIZEOF(setting), "%d_count", i); + DBWriteContactSettingWord(NULL, MODULE_NAME "Groups", setting, (WORD)group->items.size()); + + for (unsigned int j = 0; j < group->items.size(); ++j) + { + BaseExtraIcon *extra = group->items[j]; + + mir_snprintf(setting, SIZEOF(setting), "%d_%d", i, j); + DBWriteContactSettingString(NULL, MODULE_NAME "Groups", setting, extra->getName()); + } + } + + // Clean removed slots + for (int j = firstEmptySlot; j <= lastUsedSlot; ++j) + RemoveExtraIcons(j); + + + // Apply icons to new slots + RebuildListsBasedOnGroups(groups); + for (i = 0; i < extraIconsBySlot.size(); ++i) + { + ExtraIcon *extra = extraIconsBySlot[i]; + + if (extra->getType() != EXTRAICON_TYPE_GROUP) + { + if (oldSlots[((BaseExtraIcon *) extra)->getID() - 1] == extra->getSlot()) + continue; + } + + extra->applyIcons(); + } + + delete[] oldSlots; + + return TRUE; + } + } + else if (lpnmhdr->idFrom == IDC_EXTRAORDER) + { + HWND tree = GetDlgItem(hwndDlg, IDC_EXTRAORDER); + + switch (lpnmhdr->code) { + case TVN_BEGINDRAG: + SetCapture(hwndDlg); + dragging = 1; + hDragItem = ((LPNMTREEVIEWA) lParam)->itemNew.hItem; + TreeView_SelectItem(tree, hDragItem); + break; + + case NM_CLICK: + { + DWORD pos = GetMessagePos(); + + TVHITTESTINFO hti; + hti.pt.x = (short) LOWORD(pos); + hti.pt.y = (short) HIWORD(pos); + ScreenToClient(lpnmhdr->hwndFrom, &hti.pt); + if (TreeView_HitTest(lpnmhdr->hwndFrom, &hti)) + { + if (hti.flags & TVHT_ONITEMSTATEICON) + { + TreeView_SelectItem(tree, hti.hItem); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM) hwndDlg, 0); + } + } + break; + } + case TVN_KEYDOWN: + { + TV_KEYDOWN *nmkd = (TV_KEYDOWN *) lpnmhdr; + if (nmkd->wVKey == VK_SPACE) + { + // Determine the selected tree item. + HTREEITEM hItem = TreeView_GetSelection(tree); + if (hItem != NULL) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM) hwndDlg, 0); + } + break; + } + case NM_RCLICK: + { + HTREEITEM hSelected = (HTREEITEM) SendMessage(tree, TVM_GETNEXTITEM, TVGN_DROPHILITE, 0); + if (hSelected != NULL && !IsSelected(tree, hSelected)) + { + UnselectAll(tree); + TreeView_SelectItem(tree, hSelected); + } + + int sels = GetNumSelected(tree); + if (sels > 1) + { + if (ShowPopup(hwndDlg, 0) == ID_GROUP) + { + GroupSelectedItems(tree); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM) hwndDlg, 0); + } + } + else if (sels == 1) + { + HTREEITEM hItem = TreeView_GetSelection(tree); + vector *ids = Tree_GetIDs(tree, hItem); + if (ids->size() > 1) + { + if (ShowPopup(hwndDlg, 1) == ID_UNGROUP) + { + UngroupSelectedItems(tree); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM) hwndDlg, 0); + } + } + } + break; + } + } + } + + break; + } + case WM_MOUSEMOVE: + { + if (!dragging) + break; + + HWND tree = GetDlgItem(hwndDlg, IDC_EXTRAORDER); + + TVHITTESTINFO hti; + hti.pt.x = (short) LOWORD(lParam); + hti.pt.y = (short) HIWORD(lParam); + ClientToScreen(hwndDlg, &hti.pt); + ScreenToClient(tree, &hti.pt); + TreeView_HitTest(tree, &hti); + if (hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT)) + { + HTREEITEM it = hti.hItem; + hti.pt.y -= TreeView_GetItemHeight(tree) / 2; + TreeView_HitTest(tree, &hti); + if (!(hti.flags & TVHT_ABOVE)) + TreeView_SetInsertMark(tree, hti.hItem, 1); + else + TreeView_SetInsertMark(tree, it, 0); + } + else + { + if (hti.flags & TVHT_ABOVE) + SendDlgItemMessage(hwndDlg, IDC_EXTRAORDER, WM_VSCROLL, MAKEWPARAM(SB_LINEUP,0), 0); + if (hti.flags & TVHT_BELOW) + SendDlgItemMessage(hwndDlg, IDC_EXTRAORDER, WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN,0), 0); + TreeView_SetInsertMark(tree, NULL, 0); + } + break; + } + case WM_LBUTTONUP: + { + if (!dragging) + break; + + HWND tree = GetDlgItem(hwndDlg, IDC_EXTRAORDER); + + TreeView_SetInsertMark(tree, NULL, 0); + dragging = 0; + ReleaseCapture(); + + TVHITTESTINFO hti; + hti.pt.x = (short) LOWORD(lParam); + hti.pt.y = (short) HIWORD(lParam); + ClientToScreen(hwndDlg, &hti.pt); + ScreenToClient(tree, &hti.pt); + hti.pt.y -= TreeView_GetItemHeight(tree) / 2; + TreeView_HitTest(tree,&hti); + if (hDragItem == hti.hItem) + break; + + if (!(hti.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT | TVHT_ABOVE | TVHT_BELOW))) + break; + + if (hti.flags & TVHT_ABOVE) + hti.hItem = TVI_FIRST; + else if (hti.flags & TVHT_BELOW) + hti.hItem = TVI_LAST; + + TVINSERTSTRUCT tvis; + TCHAR name[512]; + tvis.item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE; + tvis.item.stateMask = 0xFFFFFFFF; + tvis.item.pszText = name; + tvis.item.cchTextMax = SIZEOF(name); + tvis.item.hItem = (HTREEITEM) hDragItem; + TreeView_GetItem(tree, &tvis.item); + + TreeView_DeleteItem(tree, hDragItem); + + tvis.hParent = NULL; + tvis.hInsertAfter = hti.hItem; + TreeView_SelectItem(tree, TreeView_InsertItem(tree, &tvis)); + + SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM) hwndDlg, 0); + + break; + } + case WM_DESTROY: + { + HWND tree = GetDlgItem(hwndDlg, IDC_EXTRAORDER); + HTREEITEM hItem = TreeView_GetRoot(tree); + while (hItem) + { + delete Tree_GetIDs(tree, hItem); + hItem = TreeView_GetNextSibling(tree, hItem); + } + + break; + } + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int InitOptionsCallback(WPARAM wParam, LPARAM lParam) +{ + if (GetNumberOfSlots() < 1) + return 0; + + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.hInstance = hInst; + odp.pszGroup = LPGEN("Contact List"); + odp.pszTitle = LPGEN("Extra icons"); + odp.pszTab = LPGEN("General"); + odp.pfnDlgProc = OptionsDlgProc; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); + odp.flags = ODPF_BOLDGROUPS; + Options_AddPage(wParam, &odp); + + return 0; +} + +void InitOptions() +{ + hOptHook = HookEvent(ME_OPT_INITIALISE, InitOptionsCallback); +} + +void DeInitOptions() +{ + UnhookEvent(hOptHook); +} diff --git a/src/modules/extraicons/res/AlwaysVis.ico b/src/modules/extraicons/res/AlwaysVis.ico new file mode 100644 index 0000000000..05013a077d Binary files /dev/null and b/src/modules/extraicons/res/AlwaysVis.ico differ diff --git a/src/modules/extraicons/res/Chatchannel.ico b/src/modules/extraicons/res/Chatchannel.ico new file mode 100644 index 0000000000..2e48365971 Binary files /dev/null and b/src/modules/extraicons/res/Chatchannel.ico differ diff --git a/src/modules/extraicons/res/NeverVis.ico b/src/modules/extraicons/res/NeverVis.ico new file mode 100644 index 0000000000..6aebec2acc Binary files /dev/null and b/src/modules/extraicons/res/NeverVis.ico differ diff --git a/src/modules/extraicons/res/empty.ico b/src/modules/extraicons/res/empty.ico new file mode 100644 index 0000000000..8ba93283ac Binary files /dev/null and b/src/modules/extraicons/res/empty.ico differ diff --git a/src/modules/extraicons/res/extraicons.rc b/src/modules/extraicons/res/extraicons.rc new file mode 100644 index 0000000000..4ffca8abd2 --- /dev/null +++ b/src/modules/extraicons/res/extraicons.rc @@ -0,0 +1,147 @@ +//Microsoft Developer Studio generated resource script. +// +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "..\..\..\resource.h" +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_EI_OPTIONS DIALOGEX 0, 0, 276, 229 +STYLE DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Select the extra icons to be shown in the contact list:", + IDC_STATIC,1,9,274,13 + CONTROL "",IDC_EXTRAORDER,"SysTreeView32",TVS_NOTOOLTIPS | + TVS_CHECKBOXES | TVS_FULLROWSELECT | WS_BORDER | + WS_TABSTOP,1,24,274,160 + LTEXT "* only the first %d icons will be shown", + IDC_MAX_ICONS_L,1,190,274,13,NOT WS_VISIBLE + LTEXT "You can group/ungroup icons by selecting then (CTRL+left click) and using the popup menu (right click)", + IDC_STATIC,1,208,274,20 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_OPTIONS, DIALOG + BEGIN + LEFTMARGIN, 1 + RIGHTMARGIN, 275 + TOPMARGIN, 1 + BOTTOMMARGIN, 228 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ALWAYSVIS ICON "AlwaysVis.ico" +IDI_NEVERVIS ICON "NeverVis.ico" +IDI_CHAT ICON "Chatchannel.ico" +IDI_MALE ICON "male.ico" +IDI_FEMALE ICON "female.ico" +IDI_EMPTY ICON "empty.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_OPT_POPUP MENU DISCARDABLE +BEGIN + POPUP "Group" + BEGIN + MENUITEM "Group", ID_GROUP + END + POPUP "Ungroup" + BEGIN + MENUITEM "Ungroup", ID_UNGROUP + END +END + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (Canada) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENC) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_CAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""..\\..\\..\\resource.h""\r\n" + "#include ""winresrc.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (Canada) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/src/modules/extraicons/res/female.ico b/src/modules/extraicons/res/female.ico new file mode 100644 index 0000000000..faa08fc6c0 Binary files /dev/null and b/src/modules/extraicons/res/female.ico differ diff --git a/src/modules/extraicons/res/male.ico b/src/modules/extraicons/res/male.ico new file mode 100644 index 0000000000..5bee53143a Binary files /dev/null and b/src/modules/extraicons/res/male.ico differ diff --git a/src/modules/extraicons/usedIcons.cpp b/src/modules/extraicons/usedIcons.cpp new file mode 100644 index 0000000000..79ea375803 --- /dev/null +++ b/src/modules/extraicons/usedIcons.cpp @@ -0,0 +1,108 @@ +/* + Copyright (C) 2009 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 "..\..\core\commonheaders.h" + +#include "m_cluiframes.h" + +struct Icon +{ + string name; + int refCount; + HANDLE hImage; + + Icon(const char *icolibName) : + name(icolibName), refCount(0), hImage(INVALID_HANDLE_VALUE) + { + } +}; + +static vector usedIcons; + +static Icon * FindIcon(const char *icolibName) +{ + Icon *icon = NULL; + + for (unsigned int i = 0; i < usedIcons.size(); ++i) + { + Icon *tmp = &usedIcons[i]; + if (tmp->name != icolibName) + continue; + + icon = tmp; + break; + } + + if (icon == NULL) + { + usedIcons.push_back(Icon(icolibName)); + icon = &usedIcons[usedIcons.size() - 1]; + } + + if (icon->hImage == INVALID_HANDLE_VALUE) + { + HICON hIcon = Skin_GetIcon(icon->name.c_str()); + if (hIcon != NULL) + { + icon->hImage = (HANDLE) CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM) hIcon, 0); + Skin_ReleaseIcon(hIcon); + } + } + + return icon; +} + +HANDLE GetIcon(const char *icolibName) +{ + return FindIcon(icolibName)->hImage; +} + +HANDLE AddIcon(const char *icolibName) +{ + Icon *icon = FindIcon(icolibName); + icon->refCount++; + return icon->hImage; +} + +void RemoveIcon(const char *icolibName) +{ + for (unsigned int i = 0; i < usedIcons.size(); ++i) + { + Icon *icon = &usedIcons[i]; + + if (icon->name != icolibName) + continue; + + icon->refCount--; + break; + } +} + +static bool NotUsedIcon(const Icon &icon) +{ + return icon.refCount <= 0; +} + +void ResetIcons() +{ + usedIcons.erase(std::remove_if(usedIcons.begin(), usedIcons.end(), NotUsedIcon), usedIcons.end()); + + for (unsigned int i = 0; i < usedIcons.size(); ++i) + usedIcons[i].hImage = INVALID_HANDLE_VALUE; +} diff --git a/src/modules/extraicons/usedIcons.h b/src/modules/extraicons/usedIcons.h new file mode 100644 index 0000000000..ef3a0f0200 --- /dev/null +++ b/src/modules/extraicons/usedIcons.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2009 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 __USEDICONS_H__ +#define __USEDICONS_H__ + +HANDLE GetIcon(const char *icolibName); +HANDLE AddIcon(const char *icolibName); +void RemoveIcon(const char *icolibName); +void ResetIcons(); + + +#endif // __USEDICONS_H__ diff --git a/src/modules/plugins/newplugins.cpp b/src/modules/plugins/newplugins.cpp index 14378fd5e8..4c971519c6 100644 --- a/src/modules/plugins/newplugins.cpp +++ b/src/modules/plugins/newplugins.cpp @@ -25,6 +25,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "plugins.h" #include "..\database\profilemanager.h" +void LoadExtraIconsModule(); + extern bool bModulesLoadedFired; static int sttComparePluginsByName(const pluginEntry* p1, const pluginEntry* p2) @@ -88,7 +90,8 @@ static const MUUID pluginBannedList[] = { {0x9d6c3213, 0x02b4, 0x4fe1, { 0x92, 0xe6, 0x52, 0x6d, 0xe2, 0x4f, 0x8d, 0x65 }}, // old chat {0x240a91dc, 0x9464, 0x457a, { 0x97, 0x87, 0xff, 0x1e, 0xa8, 0x8e, 0x77, 0xe3 }}, // old clist - {0x657fe89b, 0xd121, 0x40c2, { 0x8a, 0xc9, 0xb9, 0xfa, 0x57, 0x55, 0xb3, 0x0c }} // old srmm + {0x657fe89b, 0xd121, 0x40c2, { 0x8a, 0xc9, 0xb9, 0xfa, 0x57, 0x55, 0xb3, 0x0c }}, // old srmm + {0x112f7d30, 0xcd19, 0x4c74, { 0xa0, 0x3b, 0xbf, 0xbb, 0x76, 0xb7, 0x5b, 0xc4 }} // extraicons }; static bool isPluginBanned(const MUUID& u1) @@ -600,6 +603,8 @@ static bool loadClistModule(TCHAR* exe, pluginEntry *p) p->bpi = bpi; p->pclass |= PCLASS_LOADED; pluginDefault[11].pImpl = p; + + LoadExtraIconsModule(); return true; } Plugin_Uninit(p); -- cgit v1.2.3