diff options
author | George Hazan <george.hazan@gmail.com> | 2012-11-01 15:11:28 +0000 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2012-11-01 15:11:28 +0000 |
commit | 4e406184646a2d90f228f58abd74661b4de2e2d2 (patch) | |
tree | 92687c81a5eda73e03ff03e7710bc519b804a2c9 /src/modules | |
parent | 09de5321514b772718acc6818db9200a975d3ea7 (diff) |
extraicons moved to the core
git-svn-id: http://svn.miranda-ng.org/main/trunk@2131 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'src/modules')
26 files changed, 3050 insertions, 1 deletions
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<ProtoInfo> 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 <string>
+
+#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 <vector>
+#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<BaseExtraIcon*> 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<BaseExtraIcon*> registeredExtraIcons;
+vector<ExtraIcon*> extraIconsByHandle;
+vector<ExtraIcon*> 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<ExtraIconGroup *> &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<ExtraIconGroup *> &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<const ExtraIcon *, const ExtraIcon *, bool>
+{
+ bool operator()(const ExtraIcon * one, const ExtraIcon * two) const
+ {
+ return *one < *two;
+ }
+};
+
+void RebuildListsBasedOnGroups(vector<ExtraIconGroup *> &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<ExtraIconGroup *> 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<BaseExtraIcon*> registeredExtraIcons;
+extern vector<ExtraIcon*> extraIconsByHandle;
+extern vector<ExtraIcon*> extraIconsBySlot;
+void RebuildListsBasedOnGroups(vector<ExtraIconGroup *> &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<HTREEITEM> &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<HTREEITEM> &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<HTREEITEM> 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<HTREEITEM> 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<int> * Tree_GetIDs(HWND tree, HTREEITEM hItem)
+{
+ TVITEM tvi = { 0 };
+ tvi.mask = TVIF_HANDLE | TVIF_PARAM;
+ tvi.hItem = hItem;
+ TreeView_GetItem(tree, &tvi);
+
+ return (vector<int> *) tvi.lParam;
+}
+
+static HTREEITEM Tree_AddExtraIcon(HWND tree, BaseExtraIcon *extra, bool selected, HTREEITEM hAfter = TVI_LAST)
+{
+ vector<int> *ids = new vector<int> ;
+ 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<int> &group, bool selected, HTREEITEM hAfter = TVI_LAST)
+{
+ vector<int> *ids = new vector<int> ;
+ 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<HTREEITEM> toRemove;
+ vector<int> 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<int> *iids = (vector<int> *) 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<int> *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<int> *a = (vector<int> *) lParam1;
+ vector<int> *b = (vector<int> *) 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<int> 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<ExtraIconGroup *> 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<int> *ids = (vector<int> *) 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<int> *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 Binary files differnew file mode 100644 index 0000000000..05013a077d --- /dev/null +++ b/src/modules/extraicons/res/AlwaysVis.ico diff --git a/src/modules/extraicons/res/Chatchannel.ico b/src/modules/extraicons/res/Chatchannel.ico Binary files differnew file mode 100644 index 0000000000..2e48365971 --- /dev/null +++ b/src/modules/extraicons/res/Chatchannel.ico diff --git a/src/modules/extraicons/res/NeverVis.ico b/src/modules/extraicons/res/NeverVis.ico Binary files differnew file mode 100644 index 0000000000..6aebec2acc --- /dev/null +++ b/src/modules/extraicons/res/NeverVis.ico diff --git a/src/modules/extraicons/res/empty.ico b/src/modules/extraicons/res/empty.ico Binary files differnew file mode 100644 index 0000000000..8ba93283ac --- /dev/null +++ b/src/modules/extraicons/res/empty.ico 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 Binary files differnew file mode 100644 index 0000000000..faa08fc6c0 --- /dev/null +++ b/src/modules/extraicons/res/female.ico diff --git a/src/modules/extraicons/res/male.ico b/src/modules/extraicons/res/male.ico Binary files differnew file mode 100644 index 0000000000..5bee53143a --- /dev/null +++ b/src/modules/extraicons/res/male.ico 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<Icon> 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);
|