summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2016-04-13 18:37:10 +0000
committerGeorge Hazan <george.hazan@gmail.com>2016-04-13 18:37:10 +0000
commit951bdb6a6296837838b87125b41bf2e7a976b773 (patch)
treea0436ff3c18c07d6608b8d98adcb0517b55dd1c9
parent0b82425b2954a70f6a640d469e9bb5df9d10b528 (diff)
simple but effective clist group cache
git-svn-id: http://svn.miranda-ng.org/main/trunk@16649 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
-rw-r--r--include/m_clist.h9
-rw-r--r--src/mir_app/src/clistmod.cpp2
-rw-r--r--src/mir_app/src/groups.cpp252
3 files changed, 144 insertions, 119 deletions
diff --git a/include/m_clist.h b/include/m_clist.h
index 61b4f13322..a66e48cf45 100644
--- a/include/m_clist.h
+++ b/include/m_clist.h
@@ -411,17 +411,8 @@ __forceinline HANDLE Clist_CreateGroup(HANDLE hParent, LPCTSTR ptszGroupName)
// & isExpanded can be NULL if you don't want to know if the group is expanded or not.
#define MS_CLIST_GROUPGETNAME "CList/GroupGetName"
-/////////////////////////////////////////////////////////////////////////////////////////
-// get the name of a group
-// wParam = (WPARAM)(HANDLE)hGroup
-// lParam = (LPARAM)(DWORD*)&flags
-// returns a static buffer pointing to the name of the group
-// returns NULL if hGroup is invalid.
-// this buffer is only valid until the next call to this service
-// & flags can be NULL if you don't want any of that info.
#define GROUPF_EXPANDED 0x04
#define GROUPF_HIDEOFFLINE 0x08
-#define MS_CLIST_GROUPGETNAME2 "CList/GroupGetName2"
/////////////////////////////////////////////////////////////////////////////////////////
// move a group to directly before another group
diff --git a/src/mir_app/src/clistmod.cpp b/src/mir_app/src/clistmod.cpp
index 2f9b3bd220..1987c9db6f 100644
--- a/src/mir_app/src/clistmod.cpp
+++ b/src/mir_app/src/clistmod.cpp
@@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
INT_PTR ContactChangeGroup(WPARAM wParam, LPARAM lParam);
int InitCListEvents(void);
void UninitCListEvents(void);
+void UninitGroupServices(void);
int ContactSettingChanged(WPARAM wParam, LPARAM lParam);
int ContactAdded(WPARAM wParam, LPARAM lParam);
int ContactDeleted(WPARAM wParam, LPARAM lParam);
@@ -474,5 +475,6 @@ void UnloadContactListModule()
}
ImageList_Destroy(hCListImages);
UninitCListEvents();
+ UninitGroupServices();
DestroyHookableEvent(hContactDoubleClicked);
}
diff --git a/src/mir_app/src/groups.cpp b/src/mir_app/src/groups.cpp
index 0ed7df4f18..d01bcb8074 100644
--- a/src/mir_app/src/groups.cpp
+++ b/src/mir_app/src/groups.cpp
@@ -27,35 +27,65 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
HANDLE hGroupChangeEvent;
-static INT_PTR RenameGroup(WPARAM wParam, LPARAM lParam);
-static INT_PTR MoveGroupBefore(WPARAM wParam, LPARAM lParam);
+struct CGroupInternal
+{
+ CGroupInternal(const TCHAR *_name, int _id) :
+ groupId(_id),
+ groupName(mir_tstrdup(_name))
+ {}
-static int CountGroups(void)
+ int groupId;
+ TCHAR *groupName;
+};
+
+static int CompareGrpByName(const CGroupInternal *p1, const CGroupInternal *p2)
+{ return mir_tstrcmp(p1->groupName, p2->groupName);
+}
+static LIST<CGroupInternal> arByName(20, CompareGrpByName);
+
+static LIST<CGroupInternal> arByIds(20, NumericKeySortT);
+
+static void BuildGroupList()
{
for (int i = 0;; i++) {
- char str[33];
+ char str[32];
_itoa(i, str, 10);
- ptrT grpName(db_get_tsa(NULL, "CListGroups", str));
- if (grpName == NULL)
- return i;
+ ptrT tszGroup(db_get_tsa(NULL, "CListGroups", str));
+ if (tszGroup == NULL)
+ break;
+
+ if (tszGroup[0] & 0x80) {
+ tszGroup[0] &= 0x7f;
+ db_set_ts(NULL, "CListGroups", str, tszGroup);
+ }
+
+ CGroupInternal *p = new CGroupInternal((TCHAR*)tszGroup + 1, i);
+ arByIds.insert(p);
+ arByName.insert(p);
}
}
-static int GroupNameExists(const TCHAR *name, int skipGroup)
+static void WipeGroupList()
{
- for (int i = 0;; i++) {
- if (i == skipGroup)
- continue;
+ for (int i = 0; i < arByIds.getCount(); i++) {
+ mir_free(arByIds[i]->groupName);
+ delete arByIds[i];
+ }
+ arByIds.destroy();
+ arByName.destroy();
+}
- char idstr[33];
- _itoa(i, idstr, 10);
- ptrT grpName(db_get_tsa(NULL, "CListGroups", idstr));
- if (grpName == NULL)
- break;
+static int CountGroups(void)
+{
+ return arByIds.getCount();
+}
- if (!mir_tstrcmp((TCHAR*)grpName + 1, name))
- return i + 1;
- }
+static int GroupNameExists(const TCHAR *name, int skipGroup)
+{
+ CGroupInternal *tmp = (CGroupInternal*)_alloca(sizeof(CGroupInternal));
+ tmp->groupName = (TCHAR*)name;
+ if (tmp = arByName.find(tmp))
+ return (skipGroup == tmp->groupId) ? 0 : tmp->groupId + 1;
return 0;
}
@@ -69,12 +99,11 @@ static INT_PTR GroupExists(WPARAM, LPARAM lParam)
static INT_PTR CreateGroupInternal(INT_PTR iParent, const TCHAR *ptszName)
{
- int newId = CountGroups();
TCHAR newBaseName[127], newName[128];
char str[33];
int i;
- const TCHAR* grpName = ptszName ? ptszName : TranslateT("New group");
+ const TCHAR *grpName = ptszName ? ptszName : TranslateT("New group");
if (iParent) {
_itoa(iParent - 1, str, 10);
DBVARIANT dbv;
@@ -86,6 +115,7 @@ static INT_PTR CreateGroupInternal(INT_PTR iParent, const TCHAR *ptszName)
}
else mir_tstrncpy(newBaseName, grpName, _countof(newBaseName));
+ int newId = CountGroups();
_itoa(newId, str, 10);
mir_tstrncpy(newName + 1, newBaseName, _countof(newName) - 1);
if (ptszName) {
@@ -185,6 +215,7 @@ static INT_PTR DeleteGroup(WPARAM wParam, LPARAM)
_itoa(wParam - 1, str, 10);
if (db_get_ts(NULL, "CListGroups", str, &dbv))
return 1;
+
mir_tstrncpy(name, dbv.ptszVal + 1, _countof(name));
db_free(&dbv);
if (db_get_b(NULL, "CList", "ConfirmDelete", SETTING_CONFIRMDELETE_DEFAULT)) {
@@ -194,8 +225,9 @@ static INT_PTR DeleteGroup(WPARAM wParam, LPARAM)
return 1;
}
SetCursor(LoadCursor(NULL, IDC_WAIT));
- //must remove setting from all child contacts too
- //children are demoted to the next group up, not deleted.
+
+ // must remove setting from all child contacts too
+ // children are demoted to the next group up, not deleted.
mir_tstrcpy(szNewParent, name);
pszLastBackslash = _tcsrchr(szNewParent, '\\');
if (pszLastBackslash)
@@ -222,7 +254,8 @@ static INT_PTR DeleteGroup(WPARAM wParam, LPARAM)
NotifyEventHooks(hGroupChangeEvent, hContact, (LPARAM)&grpChg);
}
- //shuffle list of groups up to fill gap
+
+ // shuffle list of groups up to fill gap
for (i = wParam - 1;; i++) {
_itoa(i + 1, str, 10);
if (db_get_utf(NULL, "CListGroups", str, &dbv))
@@ -233,7 +266,8 @@ static INT_PTR DeleteGroup(WPARAM wParam, LPARAM)
}
_itoa(i, str, 10);
db_unset(NULL, "CListGroups", str);
- //rename subgroups
+
+ // rename subgroups
{
TCHAR szNewName[256];
size_t len = mir_tstrlen(name);
@@ -251,6 +285,10 @@ static INT_PTR DeleteGroup(WPARAM wParam, LPARAM)
db_free(&dbv);
}
}
+
+ WipeGroupList();
+ BuildGroupList();
+
SetCursor(LoadCursor(NULL, IDC_ARROW));
cli.pfnLoadContactTree();
@@ -259,6 +297,71 @@ static INT_PTR DeleteGroup(WPARAM wParam, LPARAM)
return 0;
}
+static INT_PTR MoveGroupBefore(WPARAM wParam, LPARAM lParam)
+{
+ int i, shuffleFrom, shuffleTo, shuffleDir;
+ char str[33];
+ TCHAR *szMoveName;
+ DBVARIANT dbv;
+
+ if (wParam == 0 || (LPARAM)wParam == lParam)
+ return 0;
+ _itoa(wParam - 1, str, 10);
+ if (db_get_ts(NULL, "CListGroups", str, &dbv))
+ return 0;
+ szMoveName = dbv.ptszVal;
+ //shuffle list of groups up to fill gap
+ if (lParam == 0) {
+ shuffleFrom = wParam - 1;
+ shuffleTo = -1;
+ shuffleDir = -1;
+ }
+ else {
+ if ((LPARAM)wParam < lParam) {
+ shuffleFrom = wParam - 1;
+ shuffleTo = lParam - 2;
+ shuffleDir = -1;
+ }
+ else {
+ shuffleFrom = wParam - 1;
+ shuffleTo = lParam - 1;
+ shuffleDir = 1;
+ }
+ }
+ if (shuffleDir == -1) {
+ for (i = shuffleFrom; i != shuffleTo; i++) {
+ _itoa(i + 1, str, 10);
+ if (db_get_utf(NULL, "CListGroups", str, &dbv)) {
+ shuffleTo = i;
+ break;
+ }
+ _itoa(i, str, 10);
+ db_set_utf(NULL, "CListGroups", str, dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ else {
+ for (i = shuffleFrom; i != shuffleTo; i--) {
+ _itoa(i - 1, str, 10);
+ if (db_get_utf(NULL, "CListGroups", str, &dbv)) {
+ mir_free(szMoveName);
+ return 1;
+ } //never happens
+ _itoa(i, str, 10);
+ db_set_utf(NULL, "CListGroups", str, dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ _itoa(shuffleTo, str, 10);
+ db_set_ts(NULL, "CListGroups", str, szMoveName);
+ mir_free(szMoveName);
+
+ WipeGroupList();
+ BuildGroupList();
+
+ return shuffleTo + 1;
+}
+
static int RenameGroupWithMove(int groupId, const TCHAR *szName, int move)
{
char idstr[33];
@@ -291,7 +394,7 @@ static int RenameGroupWithMove(int groupId, const TCHAR *szName, int move)
}
}
- //rename subgroups
+ // rename subgroups
{
TCHAR szNewName[256];
size_t len = mir_tstrlen(oldName);
@@ -309,16 +412,13 @@ static int RenameGroupWithMove(int groupId, const TCHAR *szName, int move)
}
}
- //finally must make sure it's after any parent items
+ // finally must make sure it's after any parent items
if (move) {
- TCHAR *pszLastBackslash;
- int i;
-
mir_tstrncpy(str, szName, _countof(str));
- pszLastBackslash = _tcsrchr(str, '\\');
+ TCHAR *pszLastBackslash = _tcsrchr(str, '\\');
if (pszLastBackslash != NULL) {
*pszLastBackslash = '\0';
- for (i = 0;; i++) {
+ for (int i = 0;; i++) {
_itoa(i, idstr, 10);
if (db_get_ts(NULL, "CListGroups", idstr, &dbv))
break;
@@ -331,6 +431,9 @@ static int RenameGroupWithMove(int groupId, const TCHAR *szName, int move)
db_free(&dbv);
}
}
+
+ WipeGroupList();
+ BuildGroupList();
}
const CLISTGROUPCHANGE grpChg = { sizeof(grpChg), oldName, (TCHAR*)szName };
@@ -387,67 +490,6 @@ static INT_PTR SetGroupFlags(WPARAM wParam, LPARAM lParam)
return 0;
}
-static INT_PTR MoveGroupBefore(WPARAM wParam, LPARAM lParam)
-{
- int i, shuffleFrom, shuffleTo, shuffleDir;
- char str[33];
- TCHAR *szMoveName;
- DBVARIANT dbv;
-
- if (wParam == 0 || (LPARAM)wParam == lParam)
- return 0;
- _itoa(wParam - 1, str, 10);
- if (db_get_ts(NULL, "CListGroups", str, &dbv))
- return 0;
- szMoveName = dbv.ptszVal;
- //shuffle list of groups up to fill gap
- if (lParam == 0) {
- shuffleFrom = wParam - 1;
- shuffleTo = -1;
- shuffleDir = -1;
- }
- else {
- if ((LPARAM)wParam < lParam) {
- shuffleFrom = wParam - 1;
- shuffleTo = lParam - 2;
- shuffleDir = -1;
- }
- else {
- shuffleFrom = wParam - 1;
- shuffleTo = lParam - 1;
- shuffleDir = 1;
- }
- }
- if (shuffleDir == -1) {
- for (i = shuffleFrom; i != shuffleTo; i++) {
- _itoa(i + 1, str, 10);
- if (db_get_utf(NULL, "CListGroups", str, &dbv)) {
- shuffleTo = i;
- break;
- }
- _itoa(i, str, 10);
- db_set_utf(NULL, "CListGroups", str, dbv.pszVal);
- db_free(&dbv);
- }
- }
- else {
- for (i = shuffleFrom; i != shuffleTo; i--) {
- _itoa(i - 1, str, 10);
- if (db_get_utf(NULL, "CListGroups", str, &dbv)) {
- mir_free(szMoveName);
- return 1;
- } //never happens
- _itoa(i, str, 10);
- db_set_utf(NULL, "CListGroups", str, dbv.pszVal);
- db_free(&dbv);
- }
- }
- _itoa(shuffleTo, str, 10);
- db_set_ts(NULL, "CListGroups", str, szMoveName);
- mir_free(szMoveName);
- return shuffleTo + 1;
-}
-
static INT_PTR BuildGroupMenu(WPARAM, LPARAM)
{
char idstr[33];
@@ -532,9 +574,8 @@ static INT_PTR BuildGroupMenu(WPARAM, LPARAM)
mii.dwItemData = groupId + 1;
}
InsertMenuItem(hThisMenu, menuId, TRUE, &mii);
- if (pNextField) {
+ if (pNextField)
hThisMenu = mii.hSubMenu;
- }
}
} while (pNextField);
@@ -545,32 +586,23 @@ static INT_PTR BuildGroupMenu(WPARAM, LPARAM)
int InitGroupServices(void)
{
- for (int i = 0;; i++) {
- char str[32];
- _itoa(i, str, 10);
-
- DBVARIANT dbv;
- if (db_get_utf(NULL, "CListGroups", str, &dbv))
- break;
- if (dbv.pszVal[0] & 0x80) {
- dbv.pszVal[0] &= 0x7f;
- db_set_utf(NULL, "CListGroups", str, dbv.pszVal);
- }
- db_free(&dbv);
- }
+ BuildGroupList();
CreateServiceFunction(MS_CLIST_GROUPEXISTS, GroupExists);
CreateServiceFunction(MS_CLIST_GROUPCREATE, CreateGroup);
CreateServiceFunction(MS_CLIST_GROUPDELETE, DeleteGroup);
CreateServiceFunction(MS_CLIST_GROUPRENAME, RenameGroup);
CreateServiceFunction(MS_CLIST_GROUPGETNAME, GetGroupName);
- CreateServiceFunction(MS_CLIST_GROUPGETNAME2, GetGroupName2);
CreateServiceFunction(MS_CLIST_GROUPSETEXPANDED, SetGroupExpandedState);
CreateServiceFunction(MS_CLIST_GROUPSETFLAGS, SetGroupFlags);
CreateServiceFunction(MS_CLIST_GROUPMOVEBEFORE, MoveGroupBefore);
CreateServiceFunction(MS_CLIST_GROUPBUILDMENU, BuildGroupMenu);
hGroupChangeEvent = CreateHookableEvent(ME_CLIST_GROUPCHANGE);
-
return 0;
}
+
+void UninitGroupServices(void)
+{
+ WipeGroupList();
+}