diff options
author | George Hazan <ghazan@miranda.im> | 2018-05-30 21:50:04 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2018-05-30 21:50:04 +0300 |
commit | b99e1019f2d7403c8e2fd915cef82179415bd02a (patch) | |
tree | 2575eff46f0c46f43206b23be55401b11beba5d0 /src | |
parent | d2020205b35f89ca6db613873f0c68f04db2c9e4 (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')
-rw-r--r-- | src/mir_app/src/ei_baseIcon.cpp | 9 | ||||
-rw-r--r-- | src/mir_app/src/ei_callbackIcon.cpp | 10 | ||||
-rw-r--r-- | src/mir_app/src/ei_defaulticons.cpp | 16 | ||||
-rw-r--r-- | src/mir_app/src/ei_extraIcon.cpp | 12 | ||||
-rw-r--r-- | src/mir_app/src/ei_groupIcon.cpp | 27 | ||||
-rw-r--r-- | src/mir_app/src/ei_icolibIcon.cpp | 12 | ||||
-rw-r--r-- | src/mir_app/src/ei_options.cpp | 16 | ||||
-rw-r--r-- | src/mir_app/src/ei_services.cpp | 132 | ||||
-rw-r--r-- | src/mir_app/src/extraicons.h | 57 | ||||
-rw-r--r-- | src/mir_app/src/miranda.cpp | 10 | ||||
-rw-r--r-- | src/mir_app/src/miranda.h | 2 | ||||
-rw-r--r-- | src/mir_app/src/newplugins.cpp | 2 | ||||
-rw-r--r-- | src/mir_app/src/proto_accs.cpp | 906 |
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", ¶m);
-
- // 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", ¶m); + + // 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); +} |