summaryrefslogtreecommitdiff
path: root/src/mir_app
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2018-05-30 21:50:04 +0300
committerGeorge Hazan <ghazan@miranda.im>2018-05-30 21:50:04 +0300
commitb99e1019f2d7403c8e2fd915cef82179415bd02a (patch)
tree2575eff46f0c46f43206b23be55401b11beba5d0 /src/mir_app
parentd2020205b35f89ca6db613873f0c68f04db2c9e4 (diff)
Extra icons (mir_app):
- old reference system that used EI ids totally removed; - now HANDLE that is returned outside is a real pointer to EI; - old perversion with groups removed; - fixes #1394 (EI change require restart)
Diffstat (limited to 'src/mir_app')
-rw-r--r--src/mir_app/src/ei_baseIcon.cpp9
-rw-r--r--src/mir_app/src/ei_callbackIcon.cpp10
-rw-r--r--src/mir_app/src/ei_defaulticons.cpp16
-rw-r--r--src/mir_app/src/ei_extraIcon.cpp12
-rw-r--r--src/mir_app/src/ei_groupIcon.cpp27
-rw-r--r--src/mir_app/src/ei_icolibIcon.cpp12
-rw-r--r--src/mir_app/src/ei_options.cpp16
-rw-r--r--src/mir_app/src/ei_services.cpp132
-rw-r--r--src/mir_app/src/extraicons.h57
-rw-r--r--src/mir_app/src/miranda.cpp10
-rw-r--r--src/mir_app/src/miranda.h2
-rw-r--r--src/mir_app/src/newplugins.cpp2
-rw-r--r--src/mir_app/src/proto_accs.cpp906
13 files changed, 609 insertions, 602 deletions
diff --git a/src/mir_app/src/ei_baseIcon.cpp b/src/mir_app/src/ei_baseIcon.cpp
index 607d79cf8a..8876e90bc1 100644
--- a/src/mir_app/src/ei_baseIcon.cpp
+++ b/src/mir_app/src/ei_baseIcon.cpp
@@ -23,14 +23,14 @@ Boston, MA 02111-1307, USA.
#include "extraicons.h"
-BaseExtraIcon::BaseExtraIcon(int id, const char *name, const wchar_t *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, LPARAM param) :
+BaseExtraIcon::BaseExtraIcon(const char *name, const wchar_t *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, LPARAM param) :
ExtraIcon(name),
- m_id(id),
m_OnClick(OnClick),
m_onClickParam(param),
m_tszDescription(mir_wstrdup(description)),
m_szDescIcon(mir_strdup(descIcon))
{
+ m_id = registeredExtraIcons.getCount() + 1;
}
BaseExtraIcon::~BaseExtraIcon()
@@ -71,8 +71,7 @@ void BaseExtraIcon::onClick(MCONTACT hContact)
int BaseExtraIcon::ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage)
{
- ExtraIcon *tmp = extraIconsByHandle[m_id - 1];
- if (tmp != nullptr && tmp != this)
- return tmp->ClistSetExtraIcon(hContact, hImage);
+ if (m_pParent)
+ return m_pParent->ClistSetExtraIcon(hContact, hImage);
return Clist_SetExtraIcon(hContact, m_slot, hImage);
}
diff --git a/src/mir_app/src/ei_callbackIcon.cpp b/src/mir_app/src/ei_callbackIcon.cpp
index c7cff67a09..d38c61289b 100644
--- a/src/mir_app/src/ei_callbackIcon.cpp
+++ b/src/mir_app/src/ei_callbackIcon.cpp
@@ -23,9 +23,9 @@ Boston, MA 02111-1307, USA.
#include "extraicons.h"
-CallbackExtraIcon::CallbackExtraIcon(int _id, const char *_name, const wchar_t *_description, const char *_descIcon,
+CallbackExtraIcon::CallbackExtraIcon(const char *_name, const wchar_t *_description, const char *_descIcon,
MIRANDAHOOK _RebuildIcons, MIRANDAHOOK _ApplyIcon, MIRANDAHOOKPARAM _OnClick, LPARAM _param) :
- BaseExtraIcon(_id, _name, _description, _descIcon, _OnClick, _param),
+ BaseExtraIcon(_name, _description, _descIcon, _OnClick, _param),
m_pfnRebuildIcons(_RebuildIcons), m_pfnApplyIcon(_ApplyIcon), m_needToRebuild(true)
{
}
@@ -61,15 +61,15 @@ void CallbackExtraIcon::applyIcon(MCONTACT hContact)
m_pfnApplyIcon(hContact, 0);
}
-int CallbackExtraIcon::setIcon(int id, MCONTACT hContact, HANDLE icon)
+int CallbackExtraIcon::setIcon(MCONTACT hContact, HANDLE icon)
{
- if (!isEnabled() || hContact == 0 || id != m_id)
+ if (!isEnabled() || hContact == 0)
return -1;
return ClistSetExtraIcon(hContact, icon);
}
-int CallbackExtraIcon::setIconByName(int, MCONTACT, const char*)
+int CallbackExtraIcon::setIconByName(MCONTACT, const char*)
{
return -1;
}
diff --git a/src/mir_app/src/ei_defaulticons.cpp b/src/mir_app/src/ei_defaulticons.cpp
index 1a523d7a36..10ef3eeca1 100644
--- a/src/mir_app/src/ei_defaulticons.cpp
+++ b/src/mir_app/src/ei_defaulticons.cpp
@@ -25,8 +25,6 @@ Boston, MA 02111-1307, USA.
#include "extraicons.h"
-ExtraIcon* GetExtraIcon(HANDLE id);
-
////////////////////////////////////////////////////////////////////////////////////////
// DB extra icons
@@ -61,11 +59,8 @@ static void SetVisibility(MCONTACT hContact, int apparentMode, bool clear)
hIcolib = Skin_GetIconHandle(SKINICON_OTHER_VISIBLE_ALL);
}
- if (hIcolib != nullptr || clear) {
- ExtraIcon *extra = GetExtraIcon(hExtraIcon);
- if (extra)
- extra->setIcon((INT_PTR)hExtraIcon, hContact, hIcolib);
- }
+ if (hIcolib != nullptr || clear)
+ ExtraIcon_SetIcon(hExtraIcon, hContact, hIcolib);
}
static void SetGender(MCONTACT hContact, int gender, bool clear)
@@ -90,11 +85,8 @@ static void SetGender(MCONTACT hContact, int gender, bool clear)
else
ico = nullptr;
- if (ico != nullptr || clear) {
- ExtraIcon *extra = GetExtraIcon(hExtraGender);
- if (extra)
- extra->setIconByName((INT_PTR)hExtraGender, hContact, ico);
- }
+ if (ico != nullptr || clear)
+ ExtraIcon_SetIconByName(hExtraGender, hContact, ico);
}
struct Info
diff --git a/src/mir_app/src/ei_extraIcon.cpp b/src/mir_app/src/ei_extraIcon.cpp
index a0b0283fee..cf10d357e9 100644
--- a/src/mir_app/src/ei_extraIcon.cpp
+++ b/src/mir_app/src/ei_extraIcon.cpp
@@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA.
#include "extraicons.h"
ExtraIcon::ExtraIcon(const char *name) :
- m_szName(mir_strdup(name)), m_slot(-1), m_position(1000), m_hLangpack(0)
+ m_szName(mir_strdup(name))
{
}
@@ -62,6 +62,14 @@ bool ExtraIcon::isEnabled() const
return m_slot >= 0;
}
+void ExtraIcon::doApply(MCONTACT hContact)
+{
+ if (m_pParent)
+ m_pParent->applyIcon(hContact);
+ else
+ applyIcon(hContact);
+}
+
void ExtraIcon::applyIcons()
{
if (!isEnabled())
@@ -70,6 +78,6 @@ void ExtraIcon::applyIcons()
for (auto &hContact : Contacts()) {
// Clear to assert that it will be cleared
Clist_SetExtraIcon(hContact, m_slot, INVALID_HANDLE_VALUE);
- applyIcon(hContact);
+ doApply(hContact);
}
}
diff --git a/src/mir_app/src/ei_groupIcon.cpp b/src/mir_app/src/ei_groupIcon.cpp
index 36bbe8fea9..86442cc791 100644
--- a/src/mir_app/src/ei_groupIcon.cpp
+++ b/src/mir_app/src/ei_groupIcon.cpp
@@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA.
#include "extraicons.h"
ExtraIconGroup::ExtraIconGroup(const char *_name) :
- ExtraIcon(_name), m_setValidExtraIcon(false), m_insideApply(false),
+ ExtraIcon(_name),
m_items(1)
{
db_set_resident(EI_MODULE_NAME, _name);
@@ -95,24 +95,26 @@ void ExtraIconGroup::onClick(MCONTACT hContact)
m_pCurrentItem->onClick(hContact);
}
-int ExtraIconGroup::setIcon(int id, MCONTACT hContact, HANDLE value)
+int ExtraIconGroup::setIcon(MCONTACT, HANDLE)
{
- return internalSetIcon(id, hContact, (void*)value, false);
+ return -1;
+ // return internalSetIcon(hContact, (void*)value, false);
}
-int ExtraIconGroup::setIconByName(int id, MCONTACT hContact, const char *value)
+int ExtraIconGroup::setIconByName(MCONTACT, const char*)
{
- return internalSetIcon(id, hContact, (void*)value, true);
+ return -1;
+ // return internalSetIcon(hContact, (void*)value, true);
}
-int ExtraIconGroup::internalSetIcon(int id, MCONTACT hContact, HANDLE value, bool bByName)
+int ExtraIconGroup::internalSetIcon(ExtraIcon *pChild, MCONTACT hContact, HANDLE value, bool bByName)
{
if (m_insideApply) {
for (auto &p : m_items)
- if (p->getID() == id) {
+ if (p == pChild) {
if (bByName)
- return p->setIconByName(id, hContact, (const char*)value);
- return p->setIcon(id, hContact, value);
+ return p->setIconByName(hContact, (const char*)value);
+ return p->setIcon(hContact, value);
}
return -1;
@@ -121,7 +123,7 @@ int ExtraIconGroup::internalSetIcon(int id, MCONTACT hContact, HANDLE value, boo
int currentPos = m_items.getCount();
int storePos = m_items.getCount();
for (int i = 0; i < m_items.getCount(); i++) {
- if (m_items[i]->getID() == id)
+ if (m_items[i] == pChild)
storePos = i;
if (m_items[i] == m_pCurrentItem)
@@ -137,14 +139,13 @@ int ExtraIconGroup::internalSetIcon(int id, MCONTACT hContact, HANDLE value, boo
}
// Ok, we have to set the icon, but we have to assert it is a valid icon
-
m_setValidExtraIcon = false;
int ret;
if (bByName)
- ret = m_items[storePos]->setIconByName(id, hContact, (const char*)value);
+ ret = m_items[storePos]->setIconByName(hContact, (const char*)value);
else
- ret = m_items[storePos]->setIcon(id, hContact, (HANDLE)value);
+ ret = m_items[storePos]->setIcon(hContact, (HANDLE)value);
if (storePos < currentPos) {
if (m_setValidExtraIcon)
diff --git a/src/mir_app/src/ei_icolibIcon.cpp b/src/mir_app/src/ei_icolibIcon.cpp
index 31b6e0ef49..3935592e16 100644
--- a/src/mir_app/src/ei_icolibIcon.cpp
+++ b/src/mir_app/src/ei_icolibIcon.cpp
@@ -26,8 +26,8 @@ Boston, MA 02111-1307, USA.
#include "IcoLib.h"
-IcolibExtraIcon::IcolibExtraIcon(int _id, const char *_name, const wchar_t *_description, const char *_descIcon, MIRANDAHOOKPARAM _OnClick, LPARAM _param) :
- BaseExtraIcon(_id, _name, _description, _descIcon, _OnClick, _param)
+IcolibExtraIcon::IcolibExtraIcon(const char *_name, const wchar_t *_description, const char *_descIcon, MIRANDAHOOKPARAM _OnClick, LPARAM _param) :
+ BaseExtraIcon(_name, _description, _descIcon, _OnClick, _param)
{
db_set_resident(EI_MODULE_NAME, _name);
}
@@ -59,9 +59,9 @@ void IcolibExtraIcon::applyIcon(MCONTACT hContact)
ClistSetExtraIcon(hContact, hImage);
}
-int IcolibExtraIcon::setIcon(int id, MCONTACT hContact, HANDLE hIcoLib)
+int IcolibExtraIcon::setIcon(MCONTACT hContact, HANDLE hIcoLib)
{
- if (hContact == 0 || id != m_id)
+ if (hContact == 0)
return -1;
if (hIcoLib == INVALID_HANDLE_VALUE)
@@ -83,9 +83,9 @@ int IcolibExtraIcon::setIcon(int id, MCONTACT hContact, HANDLE hIcoLib)
return 0;
}
-int IcolibExtraIcon::setIconByName(int id, MCONTACT hContact, const char *icon)
+int IcolibExtraIcon::setIconByName(MCONTACT hContact, const char *icon)
{
- if (hContact == 0 || id != m_id)
+ if (hContact == 0)
return -1;
if (icon == INVALID_HANDLE_VALUE)
diff --git a/src/mir_app/src/ei_options.cpp b/src/mir_app/src/ei_options.cpp
index 113c34c67a..54c1d627d2 100644
--- a/src/mir_app/src/ei_options.cpp
+++ b/src/mir_app/src/ei_options.cpp
@@ -265,6 +265,8 @@ public:
ImageList_AddIcon(hImageList, hBlankIcon);
for (auto &extra : registeredExtraIcons) {
+ extra->setID(registeredExtraIcons.indexOf(&extra) + 1);
+
HICON hIcon = IcoLib_GetIcon(extra->getDescIcon());
if (hIcon == nullptr)
ImageList_AddIcon(hImageList, hBlankIcon);
@@ -300,10 +302,9 @@ public:
int *oldSlots = new int[registeredExtraIcons.getCount()];
int lastUsedSlot = -1;
for (int i = 0; i < registeredExtraIcons.getCount(); i++) {
- if (extraIconsByHandle[i] == registeredExtraIcons[i])
+ if (registeredExtraIcons[i]->getType() != EXTRAICON_TYPE_GROUP)
oldSlots[i] = registeredExtraIcons[i]->getSlot();
- else
- // Remove old slot for groups to re-set images
+ else // Remove old slot for groups to re-set images
oldSlots[i] = -1;
lastUsedSlot = max(lastUsedSlot, registeredExtraIcons[i]->getSlot());
}
@@ -322,7 +323,7 @@ public:
tvi.hItem = ht;
m_tree.GetItem(&tvi);
- intlist*ids = (intlist*)tvi.lParam;
+ intlist *ids = (intlist*)tvi.lParam;
if (ids == nullptr || ids->count < 1)
continue; // ???
@@ -389,14 +390,9 @@ public:
// Apply icons to new slots
RebuildListsBasedOnGroups(groups);
- for (auto &extra : extraIconsBySlot) {
- if (extra->getType() != EXTRAICON_TYPE_GROUP)
- if (oldSlots[((BaseExtraIcon *)extra)->getID() - 1] == extra->getSlot())
- continue;
-
+ for (auto &extra : extraIconsBySlot)
if (extra->isEnabled())
extra->applyIcons();
- }
delete[] oldSlots;
}
diff --git a/src/mir_app/src/ei_services.cpp b/src/mir_app/src/ei_services.cpp
index 354b0a8a72..60cb0e7567 100644
--- a/src/mir_app/src/ei_services.cpp
+++ b/src/mir_app/src/ei_services.cpp
@@ -35,16 +35,13 @@ int SortFunc(const ExtraIcon *p1, const ExtraIcon *p2)
if (ret != 0)
return ret;
- int id1 = (p1->getType() != EXTRAICON_TYPE_GROUP) ? ((BaseExtraIcon*)p1)->getID() : 0;
- int id2 = (p2->getType() != EXTRAICON_TYPE_GROUP) ? ((BaseExtraIcon*)p2)->getID() : 0;
- return id1 - id2;
+ return p1->getID() - p2->getID();
}
-LIST<ExtraIcon> extraIconsByHandle(10), extraIconsBySlot(10, SortFunc);
-LIST<BaseExtraIcon> registeredExtraIcons(10);
+LIST<ExtraIcon> extraIconsBySlot(10, SortFunc);
+LIST<BaseExtraIcon> registeredExtraIcons(10, PtrKeySortT);
-BOOL clistRebuildAlreadyCalled = FALSE;
-BOOL clistApplyAlreadyCalled = FALSE;
+static bool clistRebuildAlreadyCalled = false, clistApplyAlreadyCalled = false;
// Functions ////////////////////////////////////////////////////////////////////////////
@@ -87,24 +84,6 @@ int Clist_SetExtraIcon(MCONTACT hContact, int slot, HANDLE hImage)
return 0;
}
-ExtraIcon* GetExtraIcon(HANDLE id)
-{
- int i = (INT_PTR)id;
- if (i < 1 || i > extraIconsByHandle.getCount())
- return nullptr;
-
- return extraIconsByHandle[i - 1];
-}
-
-ExtraIcon* GetExtraIconBySlot(int slot)
-{
- for (auto &extra : extraIconsBySlot)
- if (extra->getSlot() == slot)
- return extra;
-
- return nullptr;
-}
-
BaseExtraIcon* GetExtraIconByName(const char *name)
{
for (auto &extra : registeredExtraIcons)
@@ -163,10 +142,8 @@ static ExtraIconGroup* IsInGroup(LIST<ExtraIconGroup> &groups, BaseExtraIcon *ex
void RebuildListsBasedOnGroups(LIST<ExtraIconGroup> &groups)
{
- extraIconsByHandle.destroy();
-
- for (auto &it : registeredExtraIcons)
- extraIconsByHandle.insert(it);
+ for (auto &extra : registeredExtraIcons)
+ extra->setParent(nullptr);
for (auto &extra : extraIconsBySlot)
if (extra->getType() == EXTRAICON_TYPE_GROUP)
@@ -175,18 +152,45 @@ void RebuildListsBasedOnGroups(LIST<ExtraIconGroup> &groups)
for (auto &group : groups) {
for (auto &it : group->m_items)
- extraIconsByHandle.put(it->getID()-1, group);
+ it->setParent(group);
extraIconsBySlot.insert(group);
}
- for (auto &extra : extraIconsByHandle)
- if (extra->getType() != EXTRAICON_TYPE_GROUP)
+ for (auto &extra : registeredExtraIcons)
+ if (extra->getParent() == nullptr)
extraIconsBySlot.insert(extra);
}
///////////////////////////////////////////////////////////////////////////////
+static void ResetSlots(BaseExtraIcon *extra, ExtraIconGroup *group)
+{
+ int slot = 0, oldMaxSlot = -1;
+ for (auto &ex : extraIconsBySlot) {
+ if (ex->getSlot() < 0)
+ continue;
+
+ int oldSlot = ex->getSlot();
+ if (oldSlot > oldMaxSlot)
+ oldMaxSlot = oldSlot+1;
+
+ ex->setSlot(slot++);
+
+ if (clistApplyAlreadyCalled && (ex == group || ex == extra || oldSlot != slot))
+ ex->applyIcons();
+ }
+
+ // slots were freed, we need to clear one or more items
+ if (extra == nullptr)
+ for (int i = slot; i < oldMaxSlot; i++)
+ for (auto &hContact : Contacts())
+ Clist_SetExtraIcon(hContact, i, INVALID_HANDLE_VALUE);
+
+ if (!g_bMirandaTerminated)
+ Clist_InitAutoRebuild(g_clistApi.hwndContactTree);
+}
+
MIR_APP_DLL(void) KillModuleExtraIcons(int _hLang)
{
LIST<ExtraIcon> arIcons(1);
@@ -204,7 +208,7 @@ MIR_APP_DLL(void) KillModuleExtraIcons(int _hLang)
LIST<ExtraIconGroup> groups(1);
LoadGroups(groups);
RebuildListsBasedOnGroups(groups);
- ExtraIcon_SetAll();
+ ResetSlots(0, 0);
for (auto &it : arIcons)
delete it;
@@ -214,7 +218,7 @@ MIR_APP_DLL(void) KillModuleExtraIcons(int _hLang)
int ClistExtraListRebuild(WPARAM, LPARAM)
{
- clistRebuildAlreadyCalled = TRUE;
+ clistRebuildAlreadyCalled = true;
ResetIcons();
@@ -229,10 +233,10 @@ int ClistExtraImageApply(WPARAM hContact, LPARAM)
if (hContact == 0)
return 0;
- clistApplyAlreadyCalled = TRUE;
+ clistApplyAlreadyCalled = true;
for (auto &it : extraIconsBySlot)
- it->applyIcon(hContact);
+ it->doApply(hContact);
return 0;
}
@@ -329,7 +333,6 @@ static void EI_PostCreate(BaseExtraIcon *extra, const char *name, int flags)
extra->setSlot(slot);
registeredExtraIcons.insert(extra);
- extraIconsByHandle.insert(extra);
LIST<ExtraIconGroup> groups(1);
LoadGroups(groups);
@@ -348,17 +351,7 @@ static void EI_PostCreate(BaseExtraIcon *extra, const char *name, int flags)
if (clistRebuildAlreadyCalled)
extra->rebuildIcons();
- slot = 0;
- for (auto &ex : extraIconsBySlot) {
- if (ex->getSlot() < 0)
- continue;
-
- int oldSlot = ex->getSlot();
- ex->setSlot(slot++);
-
- if (clistApplyAlreadyCalled && (ex == group || ex == extra || oldSlot != slot))
- extra->applyIcons();
- }
+ ResetSlots(extra, group);
}
}
@@ -379,11 +372,10 @@ EXTERN_C MIR_APP_DLL(HANDLE) ExtraIcon_RegisterCallback(const char *name, const
ptrW tszDesc(mir_a2u(description));
- int id = registeredExtraIcons.getCount() + 1;
- BaseExtraIcon *extra = new CallbackExtraIcon(id, name, tszDesc, descIcon == nullptr ? "" : descIcon, RebuildIcons, ApplyIcon, OnClick, onClickParam);
+ BaseExtraIcon *extra = new CallbackExtraIcon(name, tszDesc, descIcon == nullptr ? "" : descIcon, RebuildIcons, ApplyIcon, OnClick, onClickParam);
extra->m_hLangpack = GetPluginLangByInstance(GetInstByAddress(RebuildIcons));
EI_PostCreate(extra, name, flags);
- return (HANDLE)id;
+ return extra;
}
EXTERN_C MIR_APP_DLL(HANDLE) ExtraIcon_RegisterIcolib(const char *name, const char *description, const char *descIcon,
@@ -410,17 +402,16 @@ EXTERN_C MIR_APP_DLL(HANDLE) ExtraIcon_RegisterIcolib(const char *name, const ch
if (clistRebuildAlreadyCalled)
extra->rebuildIcons();
if (clistApplyAlreadyCalled)
- extraIconsByHandle[extra->getID() - 1]->applyIcons();
+ extra->applyIcons();
}
-
- return (HANDLE)extra->getID();
}
-
- int id = registeredExtraIcons.getCount() + 1;
- extra = new IcolibExtraIcon(id, name, tszDesc, descIcon == nullptr ? "" : descIcon, OnClick, onClickParam);
- extra->m_hLangpack = GetPluginLangByInstance(GetInstByAddress((void*)name));
- EI_PostCreate(extra, name, flags);
- return (HANDLE)id;
+ else {
+ extra = new IcolibExtraIcon(name, tszDesc, descIcon == nullptr ? "" : descIcon, OnClick, onClickParam);
+ extra->m_hLangpack = GetPluginLangByInstance(GetInstByAddress((void*)name));
+ EI_PostCreate(extra, name, flags);
+ }
+
+ return extra;
}
///////////////////////////////////////////////////////////////////////////////
@@ -430,11 +421,14 @@ MIR_APP_DLL(int) ExtraIcon_SetIcon(HANDLE hExtraIcon, MCONTACT hContact, HANDLE
if (hExtraIcon == nullptr || hContact == 0)
return -1;
- ExtraIcon *extra = GetExtraIcon(hExtraIcon);
+ BaseExtraIcon *extra = registeredExtraIcons.find((BaseExtraIcon*)hExtraIcon);
if (extra == nullptr)
return -1;
- return extra->setIcon((INT_PTR)hExtraIcon, hContact, hImage);
+ if (extra->getParent())
+ return extra->getParent()->internalSetIcon(extra, hContact, hImage, false);
+
+ return extra->setIcon(hContact, hImage);
}
MIR_APP_DLL(int) ExtraIcon_SetIconByName(HANDLE hExtraIcon, MCONTACT hContact, const char *icoName)
@@ -442,11 +436,14 @@ MIR_APP_DLL(int) ExtraIcon_SetIconByName(HANDLE hExtraIcon, MCONTACT hContact, c
if (hExtraIcon == nullptr || hContact == 0)
return -1;
- ExtraIcon *extra = GetExtraIcon(hExtraIcon);
+ BaseExtraIcon *extra = registeredExtraIcons.find((BaseExtraIcon*)hExtraIcon);
if (extra == nullptr)
return -1;
- return extra->setIconByName((INT_PTR)hExtraIcon, hContact, icoName);
+ if (extra->getParent())
+ return extra->getParent()->internalSetIcon(extra, hContact, (HANDLE)icoName, true);
+
+ return extra->setIconByName(hContact, icoName);
}
MIR_APP_DLL(int) ExtraIcon_Clear(HANDLE hExtraIcon, MCONTACT hContact)
@@ -454,11 +451,14 @@ MIR_APP_DLL(int) ExtraIcon_Clear(HANDLE hExtraIcon, MCONTACT hContact)
if (hExtraIcon == nullptr || hContact == 0)
return -1;
- ExtraIcon *extra = GetExtraIcon(hExtraIcon);
+ BaseExtraIcon *extra = registeredExtraIcons.find((BaseExtraIcon*)hExtraIcon);
if (extra == nullptr)
return -1;
- return extra->setIcon((INT_PTR)hExtraIcon, hContact, nullptr);
+ if (extra->getParent())
+ return extra->getParent()->internalSetIcon(extra, hContact, nullptr, false);
+
+ return extra->setIcon(hContact, nullptr);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/mir_app/src/extraicons.h b/src/mir_app/src/extraicons.h
index b15a9dd352..5c6a6b7a46 100644
--- a/src/mir_app/src/extraicons.h
+++ b/src/mir_app/src/extraicons.h
@@ -30,6 +30,8 @@ Boston, MA 02111-1307, USA.
#define EXTRAICON_TYPE_GROUP -1
+class ExtraIconGroup;
+
/////////////////////////////////////////////////////////////////////////////////////////
// ExtraIcon - base class for all extra icons
@@ -39,13 +41,21 @@ public:
ExtraIcon(const char *name);
virtual ~ExtraIcon();
+ __forceinline int getID() const { return m_id; }
+ __forceinline void setID(int _id) { m_id = _id; }
+
+ __forceinline ExtraIconGroup* getParent() const { return m_pParent; }
+ __forceinline void setParent(ExtraIconGroup *p) { m_pParent = p; }
+
+ void doApply(MCONTACT hContact);
+ void applyIcons();
+
virtual void rebuildIcons() = 0;
- virtual void applyIcons();
virtual void applyIcon(MCONTACT hContact) = 0;
virtual void onClick(MCONTACT hContact) = 0;
- virtual int setIcon(int id, MCONTACT hContact, HANDLE icon) = 0;
- virtual int setIconByName(int id, MCONTACT hContact, const char* icon) = 0;
+ virtual int setIcon(MCONTACT hContact, HANDLE icon) = 0;
+ virtual int setIconByName(MCONTACT hContact, const char* icon) = 0;
virtual void storeIcon(MCONTACT, void*) {};
virtual const char *getName() const;
@@ -63,13 +73,16 @@ public:
virtual int ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage) = 0;
- int m_hLangpack;
+ int m_hLangpack = 0;
protected:
ptrA m_szName;
- int m_slot;
- int m_position;
+ int m_id = 0;
+ int m_slot = -1;
+ int m_position = 1000;
+
+ ExtraIconGroup *m_pParent = nullptr;
};
/////////////////////////////////////////////////////////////////////////////////////////
@@ -78,11 +91,9 @@ protected:
class BaseExtraIcon : public ExtraIcon
{
public:
- BaseExtraIcon(int id, const char *name, const wchar_t *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, LPARAM param);
+ BaseExtraIcon(const char *name, const wchar_t *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, LPARAM param);
virtual ~BaseExtraIcon();
- __forceinline int getID() const { return m_id; }
-
virtual const wchar_t* getDescription() const;
virtual void setDescription(const wchar_t *desc);
virtual const char* getDescIcon() const;
@@ -95,7 +106,6 @@ public:
virtual int ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage);
protected:
- int m_id;
ptrW m_tszDescription;
ptrA m_szDescIcon;
MIRANDAHOOKPARAM m_OnClick;
@@ -108,7 +118,7 @@ protected:
class CallbackExtraIcon : public BaseExtraIcon
{
public:
- CallbackExtraIcon(int id, const char *name, const wchar_t *description, const char *descIcon,
+ CallbackExtraIcon(const char *name, const wchar_t *description, const char *descIcon,
MIRANDAHOOK RebuildIcons, MIRANDAHOOK ApplyIcon, MIRANDAHOOKPARAM OnClick, LPARAM param);
virtual ~CallbackExtraIcon();
@@ -117,8 +127,8 @@ public:
virtual void rebuildIcons();
virtual void applyIcon(MCONTACT hContact);
- virtual int setIcon(int id, MCONTACT hContact, HANDLE icon);
- virtual int setIconByName(int id, MCONTACT hContact, const char* icon);
+ virtual int setIcon(MCONTACT hContact, HANDLE icon);
+ virtual int setIconByName(MCONTACT hContact, const char* icon);
private:
int (*m_pfnRebuildIcons)(WPARAM wParam, LPARAM lParam);
@@ -133,7 +143,7 @@ private:
class IcolibExtraIcon : public BaseExtraIcon
{
public:
- IcolibExtraIcon(int id, const char *name, const wchar_t *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, LPARAM param);
+ IcolibExtraIcon(const char *name, const wchar_t *description, const char *descIcon, MIRANDAHOOKPARAM OnClick, LPARAM param);
virtual ~IcolibExtraIcon();
virtual int getType() const;
@@ -141,8 +151,8 @@ public:
virtual void rebuildIcons();
virtual void applyIcon(MCONTACT hContact);
- virtual int setIcon(int id, MCONTACT hContact, HANDLE icon);
- virtual int setIconByName(int id, MCONTACT hContact, const char* icon);
+ virtual int setIcon(MCONTACT hContact, HANDLE icon);
+ virtual int setIconByName(MCONTACT hContact, const char* icon);
virtual void storeIcon(MCONTACT hContact, void *icon);
};
@@ -151,8 +161,6 @@ public:
class ExtraIconGroup : public ExtraIcon
{
- int internalSetIcon(int id, MCONTACT hContact, HANDLE icon, bool bByName);
-
public:
ExtraIconGroup(const char *name);
virtual ~ExtraIconGroup();
@@ -163,8 +171,8 @@ public:
virtual void applyIcon(MCONTACT hContact);
virtual void onClick(MCONTACT hContact);
- virtual int setIcon(int id, MCONTACT hContact, HANDLE icon);
- virtual int setIconByName(int id, MCONTACT hContact, const char *icon);
+ virtual int setIcon(MCONTACT hContact, HANDLE icon);
+ virtual int setIconByName(MCONTACT hContact, const char *icon);
virtual const wchar_t* getDescription() const;
virtual const char* getDescIcon() const;
@@ -177,10 +185,12 @@ public:
virtual int ClistSetExtraIcon(MCONTACT hContact, HANDLE hImage);
+ int internalSetIcon(ExtraIcon *pChild, MCONTACT hContact, HANDLE icon, bool bByName);
+
protected:
ptrW m_tszDescription;
- bool m_setValidExtraIcon;
- bool m_insideApply;
+ bool m_setValidExtraIcon = false;
+ bool m_insideApply = false;
ExtraIcon *m_pCurrentItem = nullptr;
};
@@ -188,9 +198,8 @@ protected:
/////////////////////////////////////////////////////////////////////////////////////////
extern LIST<BaseExtraIcon> registeredExtraIcons;
-extern LIST<ExtraIcon> extraIconsByHandle, extraIconsBySlot;
void RebuildListsBasedOnGroups(LIST<ExtraIconGroup> &groups);
-ExtraIcon * GetExtraIconBySlot(int slot);
+extern LIST<ExtraIcon> extraIconsBySlot;
int ConvertToClistSlot(int slot);
diff --git a/src/mir_app/src/miranda.cpp b/src/mir_app/src/miranda.cpp
index 542c2ac55e..691d6847a3 100644
--- a/src/mir_app/src/miranda.cpp
+++ b/src/mir_app/src/miranda.cpp
@@ -51,7 +51,7 @@ ITaskbarList3 *pTaskbarInterface;
HANDLE hOkToExitEvent, hModulesLoadedEvent;
HANDLE hShutdownEvent, hPreShutdownEvent;
DWORD hMainThreadId;
-bool bModulesLoadedFired = false, bMirandaTerminated = false;
+bool g_bModulesLoadedFired = false, g_bMirandaTerminated = false;
int g_iIconX, g_iIconY, g_iIconSX, g_iIconSY;
CMPlugin g_plugin;
@@ -316,7 +316,7 @@ int WINAPI mir_main(LPTSTR cmdLine)
int result = 0;
if (LoadDefaultModules()) {
- bMirandaTerminated = true;
+ g_bMirandaTerminated = true;
NotifyEventHooks(hPreShutdownEvent, 0, 0);
NotifyEventHooks(hShutdownEvent, 0, 0);
UnloadDefaultModules();
@@ -326,7 +326,7 @@ int WINAPI mir_main(LPTSTR cmdLine)
else {
InitPathVar();
NotifyEventHooks(hModulesLoadedEvent, 0, 0);
- bModulesLoadedFired = true;
+ g_bModulesLoadedFired = true;
// ensure that the kernel hooks the SystemShutdownProc() after all plugins
HookEvent(ME_SYSTEM_SHUTDOWN, SystemShutdownProc);
@@ -364,7 +364,7 @@ int WINAPI mir_main(LPTSTR cmdLine)
}
else if (!dying) {
dying++;
- bMirandaTerminated = true;
+ g_bMirandaTerminated = true;
NotifyEventHooks(hPreShutdownEvent, 0, 0);
// this spins and processes the msg loop, objects and APC.
@@ -398,7 +398,7 @@ int WINAPI mir_main(LPTSTR cmdLine)
MIR_APP_DLL(bool) Miranda_IsTerminated()
{
- return bMirandaTerminated;
+ return g_bMirandaTerminated;
}
MIR_APP_DLL(bool) Miranda_OkToExit()
diff --git a/src/mir_app/src/miranda.h b/src/mir_app/src/miranda.h
index 3798094951..a381d71f3d 100644
--- a/src/mir_app/src/miranda.h
+++ b/src/mir_app/src/miranda.h
@@ -64,7 +64,7 @@ extern HANDLE hOkToExitEvent, hModulesLoadedEvent, hevLoadModule, hevUnloadModul
extern HANDLE hAccListChanged;
extern wchar_t mirandabootini[MAX_PATH];
extern struct pluginEntry *plugin_crshdmp, *plugin_service, *plugin_ssl, *plugin_clist;
-extern bool bModulesLoadedFired;
+extern bool g_bModulesLoadedFired, g_bMirandaTerminated;
/**** newplugins.cpp *******************************************************************/
diff --git a/src/mir_app/src/newplugins.cpp b/src/mir_app/src/newplugins.cpp
index f7f8b5814d..2be85d985e 100644
--- a/src/mir_app/src/newplugins.cpp
+++ b/src/mir_app/src/newplugins.cpp
@@ -507,7 +507,7 @@ LBL_Error:
goto LBL_Error;
CMPluginBase *ppb = ppe->m_pPlugin;
- if (bModulesLoadedFired) {
+ if (g_bModulesLoadedFired) {
if (CallPluginEventHook(ppb->getInst(), hModulesLoadedEvent, 0, 0) != 0)
goto LBL_Error;
diff --git a/src/mir_app/src/proto_accs.cpp b/src/mir_app/src/proto_accs.cpp
index 39604d8da2..55cbcd8270 100644
--- a/src/mir_app/src/proto_accs.cpp
+++ b/src/mir_app/src/proto_accs.cpp
@@ -1,452 +1,454 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (c) 2012-18 Miranda NG team (https://miranda-ng.org),
-Copyright (c) 2000-12 Miranda IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "stdafx.h"
-
-#include "clc.h"
-
-bool CheckProtocolOrder(void);
-void BuildProtoMenus();
-
-HICON Proto_GetIcon(PROTO_INTERFACE *ppro, int iconIndex);
-
-static bool bModuleInitialized = false;
-static HANDLE hHooks[3];
-
-static int CompareAccounts(const PROTOACCOUNT* p1, const PROTOACCOUNT* p2)
-{
- return mir_strcmp(p1->szModuleName, p2->szModuleName);
-}
-
-LIST<PROTOACCOUNT> accounts(10, CompareAccounts);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static int EnumDbModules(const char *szModuleName, void*)
-{
- ptrA szProtoName(db_get_sa(0, szModuleName, "AM_BaseProto"));
- if (szProtoName) {
- if (!Proto_GetAccount(szModuleName)) {
- PROTOACCOUNT *pa = new PROTOACCOUNT(szModuleName);
- pa->szProtoName = szProtoName.detach();
- pa->tszAccountName = mir_a2u(szModuleName);
- pa->bIsVisible = true;
- pa->bIsEnabled = false;
- pa->iOrder = accounts.getCount();
- accounts.insert(pa);
- }
- }
- return 0;
-}
-
-void LoadDbAccounts(void)
-{
- int ver = db_get_dw(0, "Protocols", "PrVer", -1);
- int count = db_get_dw(0, "Protocols", "ProtoCount", 0);
-
- for (int i = 0; i < count; i++) {
- char buf[10];
- _itoa(i, buf, 10);
- ptrA szModuleName(db_get_sa(0, "Protocols", buf));
- if (szModuleName == nullptr)
- continue;
-
- PROTOACCOUNT *pa = Proto_GetAccount(szModuleName);
- if (pa == nullptr) {
- pa = new PROTOACCOUNT(szModuleName);
- accounts.insert(pa);
- }
-
- _itoa(OFFSET_VISIBLE + i, buf, 10);
- pa->bIsVisible = db_get_dw(0, "Protocols", buf, 1) != 0;
-
- _itoa(OFFSET_PROTOPOS + i, buf, 10);
- pa->iOrder = db_get_dw(0, "Protocols", buf, 1);
-
- if (ver >= 4) {
- _itoa(OFFSET_NAME + i, buf, 10);
- pa->tszAccountName = db_get_wsa(0, "Protocols", buf);
-
- _itoa(OFFSET_ENABLED + i, buf, 10);
- pa->bIsEnabled = db_get_dw(0, "Protocols", buf, 1) != 0;
- if (!pa->bIsEnabled && !mir_strcmp(pa->szModuleName, META_PROTO)) {
- pa->bIsEnabled = true;
- db_set_dw(0, "Protocols", buf, 1);
- }
- pa->szProtoName = db_get_sa(0, szModuleName, "AM_BaseProto");
- }
- else pa->bIsEnabled = true;
-
- if (!pa->szProtoName) {
- pa->szProtoName = mir_strdup(szModuleName);
- db_set_s(0, szModuleName, "AM_BaseProto", pa->szProtoName);
- }
-
- if (!pa->tszAccountName)
- pa->tszAccountName = mir_a2u(szModuleName);
- }
-
- if (CheckProtocolOrder())
- WriteDbAccounts();
-
- int anum = accounts.getCount();
- db_enum_modules(EnumDbModules);
- if (anum != accounts.getCount())
- WriteDbAccounts();
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-struct enumDB_ProtoProcParam
-{
- int arrlen;
- char **pszSettingName;
-};
-
-static int enumDB_ProtoProc(const char* szSetting, void *lParam)
-{
- if (szSetting) {
- enumDB_ProtoProcParam* p = (enumDB_ProtoProcParam*)lParam;
-
- p->arrlen++;
- p->pszSettingName = (char**)mir_realloc(p->pszSettingName, p->arrlen*sizeof(char*));
- p->pszSettingName[p->arrlen - 1] = mir_strdup(szSetting);
- }
- return 0;
-}
-
-void WriteDbAccounts()
-{
- // enum all old settings to delete
- enumDB_ProtoProcParam param = { 0, nullptr };
- db_enum_settings(0, enumDB_ProtoProc, "Protocols", &param);
-
- // delete all settings
- if (param.arrlen) {
- for (int i = 0; i < param.arrlen; i++) {
- db_unset(0, "Protocols", param.pszSettingName[i]);
- mir_free(param.pszSettingName[i]);
- }
- mir_free(param.pszSettingName);
- }
-
- // write new data
- for (int i = 0; i < accounts.getCount(); i++) {
- PROTOACCOUNT *pa = accounts[i];
-
- char buf[20];
- _itoa(i, buf, 10);
- db_set_s(0, "Protocols", buf, pa->szModuleName);
-
- _itoa(OFFSET_PROTOPOS + i, buf, 10);
- db_set_dw(0, "Protocols", buf, pa->iOrder);
-
- _itoa(OFFSET_VISIBLE + i, buf, 10);
- db_set_dw(0, "Protocols", buf, pa->bIsVisible);
-
- _itoa(OFFSET_ENABLED + i, buf, 10);
- db_set_dw(0, "Protocols", buf, pa->bIsEnabled);
-
- _itoa(OFFSET_NAME + i, buf, 10);
- db_set_ws(0, "Protocols", buf, pa->tszAccountName);
- }
-
- db_unset(0, "Protocols", "ProtoCount");
- db_set_dw(0, "Protocols", "ProtoCount", accounts.getCount());
- db_set_dw(0, "Protocols", "PrVer", 4);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static int OnContactDeleted(WPARAM hContact, LPARAM)
-{
- if (hContact) {
- PROTOACCOUNT *pa = Proto_GetAccount(hContact);
- if (pa->IsEnabled() && pa->ppro)
- pa->ppro->OnContactDeleted(hContact);
- }
- return 0;
-}
-
-static int InitializeStaticAccounts(WPARAM, LPARAM)
-{
- int count = 0;
-
- for (auto &pa : accounts) {
- if (!pa->ppro || !pa->IsEnabled())
- continue;
-
- pa->ppro->OnModulesLoaded();
-
- if (!pa->bOldProto)
- count++;
- }
-
- BuildProtoMenus();
-
- if (count == 0 && !db_get_b(0, "FirstRun", "AccManager", 0)) {
- db_set_b(0, "FirstRun", "AccManager", 1);
- CallService(MS_PROTO_SHOWACCMGR, 0, 0);
- }
- // This is for pack creators with a profile with predefined accounts
- else if (db_get_b(0, "FirstRun", "ForceShowAccManager", 0)) {
- CallService(MS_PROTO_SHOWACCMGR, 0, 0);
- db_unset(0, "FirstRun", "ForceShowAccManager");
- }
- return 0;
-}
-
-static int UninitializeStaticAccounts(WPARAM, LPARAM)
-{
- // request permission to exit first
- for (auto &pa : accounts)
- if (pa->ppro && pa->IsEnabled())
- if (!pa->ppro->IsReadyToExit())
- return 1;
-
- // okay, all protocols are ready, exiting
- for (auto &pa : accounts)
- if (pa->ppro && pa->IsEnabled())
- pa->ppro->OnShutdown();
-
- return 0;
-}
-
-int LoadAccountsModule(void)
-{
- bModuleInitialized = true;
-
- for (auto &pa : accounts) {
- pa->bDynDisabled = !Proto_IsProtocolLoaded(pa->szProtoName);
- if (pa->ppro)
- continue;
-
- if (!pa->IsEnabled())
- continue;
-
- if (!ActivateAccount(pa, false))
- pa->bDynDisabled = true;
- }
-
- hHooks[0] = HookEvent(ME_SYSTEM_MODULESLOADED, InitializeStaticAccounts);
- hHooks[1] = HookEvent(ME_SYSTEM_PRESHUTDOWN, UninitializeStaticAccounts);
- hHooks[2] = HookEvent(ME_DB_CONTACT_DELETED, OnContactDeleted);
- return 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static HANDLE CreateProtoServiceEx(const char* szModule, const char* szService, MIRANDASERVICEOBJ pFunc, void* param)
-{
- char tmp[100];
- mir_snprintf(tmp, "%s%s", szModule, szService);
- return CreateServiceFunctionObj(tmp, pFunc, param);
-}
-
-bool ActivateAccount(PROTOACCOUNT *pa, bool bIsDynamic)
-{
- MBaseProto *ppd = Proto_GetProto(pa->szProtoName);
- if (ppd == nullptr)
- return false;
-
- if (ppd->fnInit == nullptr)
- return false;
-
- PROTO_INTERFACE *ppi = ppd->fnInit(pa->szModuleName, pa->tszAccountName);
- if (ppi == nullptr)
- return false;
-
- pa->ppro = ppi;
- if (ppi->m_hProtoIcon == nullptr)
- ppi->m_hProtoIcon = IcoLib_IsManaged(Skin_LoadProtoIcon(pa->szModuleName, ID_STATUS_ONLINE));
- ppi->m_iDesiredStatus = ppi->m_iStatus = ID_STATUS_OFFLINE;
-
- if (bIsDynamic) {
- if (bModulesLoadedFired)
- pa->ppro->OnModulesLoaded();
- if (!db_get_b(0, "CList", "MoveProtoMenus", true))
- pa->ppro->OnBuildProtoMenu();
- pa->bDynDisabled = false;
- }
- return true;
-}
-
-MIR_APP_DLL(int) Proto_GetAverageStatus(int *pAccountNumber)
-{
- int netProtoCount = 0, averageMode = 0;
-
- for (auto &pa : accounts) {
- if (!pa->IsVisible() || pa->IsLocked())
- continue;
-
- netProtoCount++;
- if (averageMode == 0)
- averageMode = pa->iRealStatus;
- else if (averageMode > 0 && averageMode != pa->iRealStatus) {
- averageMode = -1;
- if (pAccountNumber == nullptr)
- break;
- }
- }
-
- if (pAccountNumber)
- *pAccountNumber = netProtoCount;
- return averageMode;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-struct DeactivationThreadParam
-{
- PROTO_INTERFACE *ppro;
- pfnUninitProto fnUninit;
- int flags;
-};
-
-pfnUninitProto GetProtocolDestructor(char *szProto);
-
-static void __cdecl DeactivationThread(DeactivationThreadParam *param)
-{
- PROTO_INTERFACE *p = (PROTO_INTERFACE*)param->ppro;
- p->SetStatus(ID_STATUS_OFFLINE);
-
- char *szModuleName = NEWSTR_ALLOCA(p->m_szModuleName);
-
- if (param->flags & DAF_DYNAMIC) {
- while (!p->IsReadyToExit())
- SleepEx(100, TRUE);
-
- p->OnShutdown();
- }
-
- KillObjectThreads(p); // waits for them before terminating
- KillObjectEventHooks(p); // untie an object from the outside world
-
- if (param->flags & DAF_ERASE)
- p->OnErase();
-
- if (param->fnUninit)
- param->fnUninit(p);
-
- KillObjectServices(p);
-
- if (param->flags & DAF_ERASE)
- EraseAccount(szModuleName);
-
- delete param;
-}
-
-void DeactivateAccount(PROTOACCOUNT *pa, int flags)
-{
- if (pa->hwndAccMgrUI) {
- DestroyWindow(pa->hwndAccMgrUI);
- pa->hwndAccMgrUI = nullptr;
- pa->bAccMgrUIChanged = FALSE;
- }
-
- if (flags & DAF_DYNAMIC)
- NotifyEventHooks(hAccListChanged, PRAC_REMOVED, (LPARAM)pa);
- else
- pa->iIconBase = -1;
-
- if (pa->ppro == nullptr) {
- if (flags & DAF_ERASE)
- EraseAccount(pa->szModuleName);
- return;
- }
-
- DeactivationThreadParam *param = new DeactivationThreadParam;
- param->ppro = pa->ppro;
- param->fnUninit = GetProtocolDestructor(pa->szProtoName);
- param->flags = flags;
- pa->ppro = nullptr;
- if (flags & DAF_FORK)
- mir_forkThread<DeactivationThreadParam>(DeactivationThread, param);
- else
- DeactivationThread(param);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void KillModuleAccounts(HINSTANCE hInst)
-{
- for (auto &pd : g_arProtos.rev_iter()) {
- if (pd->hInst != hInst)
- continue;
-
- for (auto &pa : accounts.rev_iter()) {
- if (!mir_strcmp(pa->szProtoName, pd->szName)) {
- pa->bDynDisabled = true;
- DeactivateAccount(pa, DAF_DYNAMIC);
- }
- }
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void EraseAccount(const char *pszModuleName)
-{
- // remove protocol contacts first
- for (MCONTACT hContact = db_find_first(pszModuleName); hContact != 0;) {
- MCONTACT hNext = db_find_next(hContact, pszModuleName);
- db_delete_contact(hContact);
- hContact = hNext;
- }
-
- // remove all protocol settings
- db_delete_module(0, pszModuleName);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void UnloadAccount(PROTOACCOUNT *pa, int flags)
-{
- DeactivateAccount(pa, flags);
-
- // szModuleName should be freed only on a program's exit.
- // otherwise many plugins dependand on static protocol names will crash!
- // do NOT fix this 'leak', please
- if (!(flags & DAF_DYNAMIC))
- delete pa;
- else {
- replaceStrW(pa->tszAccountName, 0); replaceStr(pa->szProtoName, 0); replaceStr(pa->szUniqueId, 0);
- }
-}
-
-void UnloadAccountsModule()
-{
- if (!bModuleInitialized)
- return;
-
- auto T = accounts.rev_iter();
- for (auto &it : T) {
- UnloadAccount(it, 0);
- accounts.remove(T.indexOf(&it));
- }
- accounts.destroy();
-
- for (auto &it : hHooks)
- UnhookEvent(it);
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (c) 2012-18 Miranda NG team (https://miranda-ng.org),
+Copyright (c) 2000-12 Miranda IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+#include "clc.h"
+
+bool CheckProtocolOrder(void);
+void BuildProtoMenus();
+
+HICON Proto_GetIcon(PROTO_INTERFACE *ppro, int iconIndex);
+
+static bool bModuleInitialized = false;
+static HANDLE hHooks[3];
+
+static int CompareAccounts(const PROTOACCOUNT* p1, const PROTOACCOUNT* p2)
+{
+ return mir_strcmp(p1->szModuleName, p2->szModuleName);
+}
+
+LIST<PROTOACCOUNT> accounts(10, CompareAccounts);
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static int EnumDbModules(const char *szModuleName, void*)
+{
+ ptrA szProtoName(db_get_sa(0, szModuleName, "AM_BaseProto"));
+ if (szProtoName) {
+ if (!Proto_GetAccount(szModuleName)) {
+ PROTOACCOUNT *pa = new PROTOACCOUNT(szModuleName);
+ pa->szProtoName = szProtoName.detach();
+ pa->tszAccountName = mir_a2u(szModuleName);
+ pa->bIsVisible = true;
+ pa->bIsEnabled = false;
+ pa->iOrder = accounts.getCount();
+ accounts.insert(pa);
+ }
+ }
+ return 0;
+}
+
+void LoadDbAccounts(void)
+{
+ int ver = db_get_dw(0, "Protocols", "PrVer", -1);
+ int count = db_get_dw(0, "Protocols", "ProtoCount", 0);
+
+ for (int i = 0; i < count; i++) {
+ char buf[10];
+ _itoa(i, buf, 10);
+ ptrA szModuleName(db_get_sa(0, "Protocols", buf));
+ if (szModuleName == nullptr)
+ continue;
+
+ PROTOACCOUNT *pa = Proto_GetAccount(szModuleName);
+ if (pa == nullptr) {
+ pa = new PROTOACCOUNT(szModuleName);
+ accounts.insert(pa);
+ }
+
+ _itoa(OFFSET_VISIBLE + i, buf, 10);
+ pa->bIsVisible = db_get_dw(0, "Protocols", buf, 1) != 0;
+
+ _itoa(OFFSET_PROTOPOS + i, buf, 10);
+ pa->iOrder = db_get_dw(0, "Protocols", buf, 1);
+
+ if (ver >= 4) {
+ _itoa(OFFSET_NAME + i, buf, 10);
+ pa->tszAccountName = db_get_wsa(0, "Protocols", buf);
+
+ _itoa(OFFSET_ENABLED + i, buf, 10);
+ pa->bIsEnabled = db_get_dw(0, "Protocols", buf, 1) != 0;
+ if (!pa->bIsEnabled && !mir_strcmp(pa->szModuleName, META_PROTO)) {
+ pa->bIsEnabled = true;
+ db_set_dw(0, "Protocols", buf, 1);
+ }
+ pa->szProtoName = db_get_sa(0, szModuleName, "AM_BaseProto");
+ }
+ else pa->bIsEnabled = true;
+
+ if (!pa->szProtoName) {
+ pa->szProtoName = mir_strdup(szModuleName);
+ db_set_s(0, szModuleName, "AM_BaseProto", pa->szProtoName);
+ }
+
+ if (!pa->tszAccountName)
+ pa->tszAccountName = mir_a2u(szModuleName);
+ }
+
+ if (CheckProtocolOrder())
+ WriteDbAccounts();
+
+ int anum = accounts.getCount();
+ db_enum_modules(EnumDbModules);
+ if (anum != accounts.getCount())
+ WriteDbAccounts();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct enumDB_ProtoProcParam
+{
+ int arrlen;
+ char **pszSettingName;
+};
+
+static int enumDB_ProtoProc(const char* szSetting, void *lParam)
+{
+ if (szSetting) {
+ enumDB_ProtoProcParam* p = (enumDB_ProtoProcParam*)lParam;
+
+ p->arrlen++;
+ p->pszSettingName = (char**)mir_realloc(p->pszSettingName, p->arrlen*sizeof(char*));
+ p->pszSettingName[p->arrlen - 1] = mir_strdup(szSetting);
+ }
+ return 0;
+}
+
+void WriteDbAccounts()
+{
+ // enum all old settings to delete
+ enumDB_ProtoProcParam param = { 0, nullptr };
+ db_enum_settings(0, enumDB_ProtoProc, "Protocols", &param);
+
+ // delete all settings
+ if (param.arrlen) {
+ for (int i = 0; i < param.arrlen; i++) {
+ db_unset(0, "Protocols", param.pszSettingName[i]);
+ mir_free(param.pszSettingName[i]);
+ }
+ mir_free(param.pszSettingName);
+ }
+
+ // write new data
+ for (int i = 0; i < accounts.getCount(); i++) {
+ PROTOACCOUNT *pa = accounts[i];
+
+ char buf[20];
+ _itoa(i, buf, 10);
+ db_set_s(0, "Protocols", buf, pa->szModuleName);
+
+ _itoa(OFFSET_PROTOPOS + i, buf, 10);
+ db_set_dw(0, "Protocols", buf, pa->iOrder);
+
+ _itoa(OFFSET_VISIBLE + i, buf, 10);
+ db_set_dw(0, "Protocols", buf, pa->bIsVisible);
+
+ _itoa(OFFSET_ENABLED + i, buf, 10);
+ db_set_dw(0, "Protocols", buf, pa->bIsEnabled);
+
+ _itoa(OFFSET_NAME + i, buf, 10);
+ db_set_ws(0, "Protocols", buf, pa->tszAccountName);
+ }
+
+ db_unset(0, "Protocols", "ProtoCount");
+ db_set_dw(0, "Protocols", "ProtoCount", accounts.getCount());
+ db_set_dw(0, "Protocols", "PrVer", 4);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static int OnContactDeleted(WPARAM hContact, LPARAM)
+{
+ if (hContact) {
+ PROTOACCOUNT *pa = Proto_GetAccount(hContact);
+ if (pa->IsEnabled() && pa->ppro)
+ pa->ppro->OnContactDeleted(hContact);
+ }
+ return 0;
+}
+
+static int InitializeStaticAccounts(WPARAM, LPARAM)
+{
+ int count = 0;
+
+ for (auto &pa : accounts) {
+ if (!pa->ppro || !pa->IsEnabled())
+ continue;
+
+ pa->ppro->OnModulesLoaded();
+
+ if (!pa->bOldProto)
+ count++;
+ }
+
+ BuildProtoMenus();
+
+ if (count == 0 && !db_get_b(0, "FirstRun", "AccManager", 0)) {
+ db_set_b(0, "FirstRun", "AccManager", 1);
+ CallService(MS_PROTO_SHOWACCMGR, 0, 0);
+ }
+ // This is for pack creators with a profile with predefined accounts
+ else if (db_get_b(0, "FirstRun", "ForceShowAccManager", 0)) {
+ CallService(MS_PROTO_SHOWACCMGR, 0, 0);
+ db_unset(0, "FirstRun", "ForceShowAccManager");
+ }
+ return 0;
+}
+
+static int UninitializeStaticAccounts(WPARAM, LPARAM)
+{
+ // request permission to exit first
+ for (auto &pa : accounts)
+ if (pa->ppro && pa->IsEnabled())
+ if (!pa->ppro->IsReadyToExit())
+ return 1;
+
+ // okay, all protocols are ready, exiting
+ for (auto &pa : accounts)
+ if (pa->ppro && pa->IsEnabled())
+ pa->ppro->OnShutdown();
+
+ return 0;
+}
+
+int LoadAccountsModule(void)
+{
+ bModuleInitialized = true;
+
+ for (auto &pa : accounts) {
+ pa->bDynDisabled = !Proto_IsProtocolLoaded(pa->szProtoName);
+ if (pa->ppro)
+ continue;
+
+ if (!pa->IsEnabled())
+ continue;
+
+ if (!ActivateAccount(pa, false))
+ pa->bDynDisabled = true;
+ }
+
+ hHooks[0] = HookEvent(ME_SYSTEM_MODULESLOADED, InitializeStaticAccounts);
+ hHooks[1] = HookEvent(ME_SYSTEM_PRESHUTDOWN, UninitializeStaticAccounts);
+ hHooks[2] = HookEvent(ME_DB_CONTACT_DELETED, OnContactDeleted);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static HANDLE CreateProtoServiceEx(const char* szModule, const char* szService, MIRANDASERVICEOBJ pFunc, void* param)
+{
+ char tmp[100];
+ mir_snprintf(tmp, "%s%s", szModule, szService);
+ return CreateServiceFunctionObj(tmp, pFunc, param);
+}
+
+bool ActivateAccount(PROTOACCOUNT *pa, bool bIsDynamic)
+{
+ MBaseProto *ppd = Proto_GetProto(pa->szProtoName);
+ if (ppd == nullptr)
+ return false;
+
+ if (ppd->fnInit == nullptr)
+ return false;
+
+ PROTO_INTERFACE *ppi = ppd->fnInit(pa->szModuleName, pa->tszAccountName);
+ if (ppi == nullptr)
+ return false;
+
+ pa->ppro = ppi;
+ if (ppi->m_hProtoIcon == nullptr)
+ ppi->m_hProtoIcon = IcoLib_IsManaged(Skin_LoadProtoIcon(pa->szModuleName, ID_STATUS_ONLINE));
+ ppi->m_iDesiredStatus = ppi->m_iStatus = ID_STATUS_OFFLINE;
+
+ if (bIsDynamic) {
+ if (g_bModulesLoadedFired)
+ pa->ppro->OnModulesLoaded();
+ if (!db_get_b(0, "CList", "MoveProtoMenus", true))
+ pa->ppro->OnBuildProtoMenu();
+ pa->bDynDisabled = false;
+ }
+ return true;
+}
+
+MIR_APP_DLL(int) Proto_GetAverageStatus(int *pAccountNumber)
+{
+ int netProtoCount = 0, averageMode = 0;
+
+ for (auto &pa : accounts) {
+ if (!pa->IsVisible() || pa->IsLocked())
+ continue;
+
+ netProtoCount++;
+ if (averageMode == 0)
+ averageMode = pa->iRealStatus;
+ else if (averageMode > 0 && averageMode != pa->iRealStatus) {
+ averageMode = -1;
+ if (pAccountNumber == nullptr)
+ break;
+ }
+ }
+
+ if (pAccountNumber)
+ *pAccountNumber = netProtoCount;
+ return averageMode;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct DeactivationThreadParam
+{
+ PROTO_INTERFACE *ppro;
+ pfnUninitProto fnUninit;
+ int flags;
+};
+
+pfnUninitProto GetProtocolDestructor(char *szProto);
+
+static void __cdecl DeactivationThread(DeactivationThreadParam *param)
+{
+ PROTO_INTERFACE *p = (PROTO_INTERFACE*)param->ppro;
+ p->SetStatus(ID_STATUS_OFFLINE);
+
+ char *szModuleName = NEWSTR_ALLOCA(p->m_szModuleName);
+
+ if (param->flags & DAF_DYNAMIC) {
+ while (!p->IsReadyToExit())
+ SleepEx(100, TRUE);
+
+ p->OnShutdown();
+ }
+
+ KillObjectThreads(p); // waits for them before terminating
+ KillObjectEventHooks(p); // untie an object from the outside world
+
+ if (param->flags & DAF_ERASE)
+ p->OnErase();
+
+ if (param->fnUninit)
+ param->fnUninit(p);
+
+ KillObjectServices(p);
+
+ if (param->flags & DAF_ERASE)
+ EraseAccount(szModuleName);
+
+ delete param;
+}
+
+void DeactivateAccount(PROTOACCOUNT *pa, int flags)
+{
+ if (pa->hwndAccMgrUI) {
+ DestroyWindow(pa->hwndAccMgrUI);
+ pa->hwndAccMgrUI = nullptr;
+ pa->bAccMgrUIChanged = FALSE;
+ }
+
+ if (flags & DAF_DYNAMIC)
+ NotifyEventHooks(hAccListChanged, PRAC_REMOVED, (LPARAM)pa);
+ else
+ pa->iIconBase = -1;
+
+ if (pa->ppro == nullptr) {
+ if (flags & DAF_ERASE)
+ EraseAccount(pa->szModuleName);
+ return;
+ }
+
+ DeactivationThreadParam *param = new DeactivationThreadParam;
+ param->ppro = pa->ppro;
+ param->fnUninit = GetProtocolDestructor(pa->szProtoName);
+ param->flags = flags;
+ pa->ppro = nullptr;
+ if (flags & DAF_FORK)
+ mir_forkThread<DeactivationThreadParam>(DeactivationThread, param);
+ else
+ DeactivationThread(param);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void KillModuleAccounts(HINSTANCE hInst)
+{
+ for (auto &pd : g_arProtos.rev_iter()) {
+ if (pd->hInst != hInst)
+ continue;
+
+ for (auto &pa : accounts.rev_iter()) {
+ if (!mir_strcmp(pa->szProtoName, pd->szName)) {
+ pa->bDynDisabled = true;
+ DeactivateAccount(pa, DAF_DYNAMIC);
+ }
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void EraseAccount(const char *pszModuleName)
+{
+ // remove protocol contacts first
+ for (MCONTACT hContact = db_find_first(pszModuleName); hContact != 0;) {
+ MCONTACT hNext = db_find_next(hContact, pszModuleName);
+ db_delete_contact(hContact);
+ hContact = hNext;
+ }
+
+ // remove all protocol settings
+ db_delete_module(0, pszModuleName);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void UnloadAccount(PROTOACCOUNT *pa, int flags)
+{
+ DeactivateAccount(pa, flags);
+
+ // szModuleName should be freed only on a program's exit.
+ // otherwise many plugins dependand on static protocol names will crash!
+ // do NOT fix this 'leak', please
+ if (!(flags & DAF_DYNAMIC))
+ delete pa;
+ else {
+ replaceStrW(pa->tszAccountName, 0);
+ replaceStr(pa->szProtoName, 0);
+ replaceStr(pa->szUniqueId, 0);
+ }
+}
+
+void UnloadAccountsModule()
+{
+ if (!bModuleInitialized)
+ return;
+
+ auto T = accounts.rev_iter();
+ for (auto &it : T) {
+ UnloadAccount(it, 0);
+ accounts.remove(T.indexOf(&it));
+ }
+ accounts.destroy();
+
+ for (auto &it : hHooks)
+ UnhookEvent(it);
+}