summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2018-12-07 20:29:02 +0300
committerGeorge Hazan <ghazan@miranda.im>2018-12-07 20:29:02 +0300
commit8e52da65d2cfa36bf23fa7be0577e420f3cf0480 (patch)
treee6af6fbb59a385187294fd045b74486616d27361
parent3f09ad4929d58a73005361cb8bb5b8aa0b41f605 (diff)
fixes #1653 (recursive removal of embedded groups)
-rw-r--r--include/delphi/m_clist.inc1
-rw-r--r--include/m_clist.h10
-rw-r--r--src/mir_app/src/clistgroups.cpp91
-rw-r--r--src/mir_app/src/contact.cpp2
4 files changed, 54 insertions, 50 deletions
diff --git a/include/delphi/m_clist.inc b/include/delphi/m_clist.inc
index 5a3f10c88a..9839f5569a 100644
--- a/include/delphi/m_clist.inc
+++ b/include/delphi/m_clist.inc
@@ -159,7 +159,6 @@ const
}
type
CLISTGROUPCHANGE = record
- cbSize :int; //size in bytes of this structure
pszOldName:TChar; //old group name
pszNewName:TChar; //new group name
end;
diff --git a/include/m_clist.h b/include/m_clist.h
index ee96559b84..c94892139a 100644
--- a/include/m_clist.h
+++ b/include/m_clist.h
@@ -371,11 +371,11 @@ EXTERN_C MIR_APP_DLL(BOOL) Clist_IsDocked(void);
// wParam = hContact - NULL if operation on group
// lParam = pointer to CLISTGROUPCHANGE
-typedef struct {
- int cbSize; // size in bytes of this structure
- wchar_t *pszOldName; // old group name, NULL if a new group was created
- wchar_t *pszNewName; // new group name, NULL if an old group was deleted
-} CLISTGROUPCHANGE;
+struct CLISTGROUPCHANGE
+{
+ const wchar_t *pszOldName; // old group name, NULL if a new group was created
+ const wchar_t *pszNewName; // new group name, NULL if an old group was deleted
+};
#define ME_CLIST_GROUPCHANGE "CList/GroupChange"
diff --git a/src/mir_app/src/clistgroups.cpp b/src/mir_app/src/clistgroups.cpp
index c49f028d62..b8917f02be 100644
--- a/src/mir_app/src/clistgroups.cpp
+++ b/src/mir_app/src/clistgroups.cpp
@@ -36,7 +36,7 @@ struct CGroupInternal
{ mir_free(groupName);
}
- int groupId;
+ int groupId, oldId;
wchar_t *groupName;
void save()
@@ -135,7 +135,7 @@ static INT_PTR CreateGroupInternal(MGROUP hParent, const wchar_t *ptszName)
Clist_GroupAdded(newId + 1);
- CLISTGROUPCHANGE grpChg = { sizeof(grpChg), nullptr, newName };
+ CLISTGROUPCHANGE grpChg = { nullptr, newName };
NotifyEventHooks(hGroupChangeEvent, 0, (LPARAM)&grpChg);
return newId + 1;
@@ -176,6 +176,20 @@ MIR_APP_DLL(wchar_t*) Clist_GroupGetName(MGROUP hGroup, DWORD *pdwFlags)
/////////////////////////////////////////////////////////////////////////////////////////
+static bool isParentOf(const CMStringW &pParent, const wchar_t *p)
+{
+ if (mir_wstrncmp(pParent, p, pParent.GetLength()))
+ return false;
+
+ switch (p[pParent.GetLength()]) {
+ case '\\':
+ case 0:
+ return true;
+ default:
+ return false;
+ }
+}
+
MIR_APP_DLL(int) Clist_GroupDelete(MGROUP hGroup)
{
// get the name
@@ -194,67 +208,58 @@ MIR_APP_DLL(int) Clist_GroupDelete(MGROUP hGroup)
// must remove setting from all child contacts too
// children are demoted to the next group up, not deleted.
- wchar_t *szNewParent = NEWWSTR_ALLOCA(pGroup->groupName+1);
+ CMStringW wszOldName(pGroup->groupName + 1), wszNewParent;
{
- wchar_t *pszLastBackslash = wcsrchr(szNewParent, '\\');
- if (pszLastBackslash)
- pszLastBackslash[0] = '\0';
- else
- szNewParent[0] = '\0';
+ int idx = wszOldName.ReverseFind('\\');
+ if (idx != -1)
+ wszNewParent = wszOldName.Left(idx);
}
for (auto &hContact : Contacts()) {
ptrW tszGroupName(db_get_wsa(hContact, "CList", "Group"));
- if (mir_wstrcmp(tszGroupName, pGroup->groupName+1))
+ if (!tszGroupName || !isParentOf(wszOldName, tszGroupName))
continue;
- CLISTGROUPCHANGE grpChg = { sizeof(grpChg), nullptr, nullptr };
- grpChg.pszOldName = pGroup->groupName+1;
- if (szNewParent[0]) {
- db_set_ws(hContact, "CList", "Group", szNewParent);
- grpChg.pszNewName = szNewParent;
- }
- else {
- db_unset(hContact, "CList", "Group");
- grpChg.pszNewName = nullptr;
+ CLISTGROUPCHANGE grpChg = { wszOldName, 0 };
+ if (!wszNewParent.IsEmpty()) {
+ db_set_ws(hContact, "CList", "Group", wszNewParent);
+ grpChg.pszNewName = wszNewParent;
}
+ else db_unset(hContact, "CList", "Group");
NotifyEventHooks(hGroupChangeEvent, hContact, (LPARAM)&grpChg);
}
// shuffle list of groups up to fill gap
- arByIds.remove(pGroup);
- arByName.remove(pGroup);
+ for (auto &it : arByIds)
+ it->oldId = it->groupId;
- for (int i = hGroup-1; i < arByIds.getCount(); i++) {
- CGroupInternal *p = arByIds[i];
- p->groupId--;
- p->save();
+ int iGap = 0;
+ for (auto &it : arByIds.rev_iter()) {
+ if (!isParentOf(wszOldName, it->groupName + 1))
+ continue;
+
+ iGap++;
+ arByName.remove(it);
+ arByIds.remove(arByIds.indexOf(&it));
}
- char idstr[33];
- _itoa(arByIds.getCount(), idstr, 10);
- db_unset(0, "CListGroups", idstr);
-
- // rename subgroups
- wchar_t szNewName[256];
- size_t len = mir_wstrlen(pGroup->groupName+1);
- for (int i = 0; i < arByIds.getCount(); i++) {
- CGroupInternal *p = arByIds[i];
-
- if (!wcsncmp(pGroup->groupName+1, p->groupName+1, len) && p->groupName[len+1] == '\\' && wcschr(p->groupName + len + 2, '\\') == nullptr) {
- if (szNewParent[0])
- mir_snwprintf(szNewName, L"%s\\%s", szNewParent, p->groupName + len + 2);
- else
- mir_wstrncpy(szNewName, p->groupName + len + 2, _countof(szNewName));
- Clist_GroupRename(i + 1, szNewName);
- }
+ for (auto &it : arByIds) {
+ it->groupId = arByIds.indexOf(&it);
+ if (it->groupId != it->oldId)
+ it->save();
+ }
+
+ for (int i = 0; i < iGap; i++) {
+ char idstr[33];
+ _itoa(arByIds.getCount()+i, idstr, 10);
+ db_unset(0, "CListGroups", idstr);
}
SetCursor(LoadCursor(nullptr, IDC_ARROW));
Clist_LoadContactTree();
- const CLISTGROUPCHANGE grpChg = { sizeof(grpChg), pGroup->groupName+1, nullptr };
+ const CLISTGROUPCHANGE grpChg = { wszOldName, nullptr };
NotifyEventHooks(hGroupChangeEvent, 0, (LPARAM)&grpChg);
delete(pGroup);
@@ -381,7 +386,7 @@ static int RenameGroupWithMove(int groupId, const wchar_t *szName, int move)
}
}
- const CLISTGROUPCHANGE grpChg = { sizeof(grpChg), oldName, (wchar_t*)szName };
+ const CLISTGROUPCHANGE grpChg = { oldName, szName };
NotifyEventHooks(hGroupChangeEvent, 0, (LPARAM)&grpChg);
return 0;
}
diff --git a/src/mir_app/src/contact.cpp b/src/mir_app/src/contact.cpp
index 141a02f6a1..e822b9d8eb 100644
--- a/src/mir_app/src/contact.cpp
+++ b/src/mir_app/src/contact.cpp
@@ -40,7 +40,7 @@ MIR_APP_DLL(void) Clist_LoadContactTree(void)
MIR_APP_DLL(int) Clist_ContactChangeGroup(MCONTACT hContact, MGROUP hGroup)
{
- CLISTGROUPCHANGE grpChg = { sizeof(CLISTGROUPCHANGE), nullptr, nullptr };
+ CLISTGROUPCHANGE grpChg = {};
if (hGroup == 0)
db_unset(hContact, "CList", "Group");