From 4e2b6ee4835543e3fa34075a853f2357c5fd4d9c Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 9 Dec 2015 22:25:09 +0000 Subject: - correct menu serialization; - custom menu items root introduced git-svn-id: http://svn.miranda-ng.org/main/trunk@15835 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/mir_app/src/genmenu.h | 5 ++ src/mir_app/src/menu_options.cpp | 39 +++------ src/mir_app/src/menu_utils.cpp | 185 ++++++++++++++++++++++++++++++--------- 3 files changed, 164 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/mir_app/src/genmenu.h b/src/mir_app/src/genmenu.h index 0a73caa036..2465612a10 100644 --- a/src/mir_app/src/genmenu.h +++ b/src/mir_app/src/genmenu.h @@ -37,6 +37,9 @@ struct TMO_LinkedList TMO_IntMenuItem *first, // first element of submenu, or NULL *last; // last element of submenu, or NULL + + void insert(TMO_IntMenuItem*); + void remove(TMO_IntMenuItem*); }; struct TMO_IntMenuItem @@ -117,6 +120,8 @@ TMO_IntMenuItem *MO_RecursiveWalkMenu(TMO_IntMenuItem*, pfnWalkFunc, void*); int InitGenMenu(); int UninitGenMenu(); +int Menu_LoadFromDatabase(TMO_IntMenuItem *pimi, void *param); + TMO_IntMenuItem * GetMenuItemByGlobalID(int globalMenuID); BOOL FindMenuHanleByGlobalID(HMENU hMenu, int globalID, struct _MenuItemHandles * dat); //GenMenu.c diff --git a/src/mir_app/src/menu_options.cpp b/src/mir_app/src/menu_options.cpp index f3c89cf9ad..8f7599c41f 100644 --- a/src/mir_app/src/menu_options.cpp +++ b/src/mir_app/src/menu_options.cpp @@ -91,7 +91,13 @@ class CGenMenuOptionsPage : public CDlgBase else ptszCustomName = _T(""); - CMString tszValue(FORMAT, _T("%d;%d;%s"), visible, runtimepos, ptszCustomName); + char pszParent[33]; + if (pimi->mi.root == NULL) + pszParent[0] = 0; + else + bin2hex(&pimi->mi.root->mi.uid, sizeof(MUUID), pszParent); + + CMString tszValue(FORMAT, _T("%d;%d;%S;%s"), visible, runtimepos, pszParent, ptszCustomName); db_set_ts(NULL, szModule, menuItemName, tszValue); if (pimi->mi.flags & CMIF_CUSTOM) @@ -153,7 +159,7 @@ class CGenMenuOptionsPage : public CDlgBase BuildTree(MenuObjectID, true); } - void BuildTreeInternal(const char *pszModule, bool bReread, HGENMENU pFirst, HTREEITEM hRoot) + void BuildTreeInternal(const char *pszModule, bool bReread, TMO_IntMenuItem *pFirst, HTREEITEM hRoot) { LIST arItems(10, SortMenuItems); @@ -162,32 +168,12 @@ class CGenMenuOptionsPage : public CDlgBase if (p->mi.flags & CMIF_SYSTEM) continue; - TCHAR customName[201]; customName[0] = 0; - int visible = 1, pos = 0; - if (!equalUUID(p->mi.uid, miid_last)) { - char menuItemName[256]; - bin2hex(&p->mi.uid, sizeof(p->mi.uid), menuItemName); - ptrT tszSettings(db_get_tsa(NULL, pszModule, menuItemName)); - if (tszSettings == NULL) - pos = p->mi.position; - else if (_stscanf(tszSettings, _T("%d;%d;%200s"), &visible, &pos, customName) < 2) - continue; - } - MenuItemOptData *PD = new MenuItemOptData(); - if (customName[0] != 0) - PD->name = mir_tstrdup(customName); - else - PD->name = mir_tstrdup(GetMenuItemText(p)); - PD->pimi = p; PD->defname = mir_tstrdup(GetMenuItemText(p)); - PD->bShow = visible != 0; - if (bReread) - PD->pos = pos; - else - PD->pos = (PD->pimi) ? PD->pimi->originalPosition : 0; - + PD->name = mir_tstrdup((p->CustomName != NULL) ? p->CustomName : PD->defname); + PD->bShow = (p->mi.flags & CMIF_HIDDEN) == 0; + PD->pos = (bReread) ? p->mi.position : p->originalPosition; PD->id = p->iCommand; arItems.insert(PD); } @@ -247,6 +233,9 @@ class CGenMenuOptionsPage : public CDlgBase char szModule[256]; mir_snprintf(szModule, "%s_Items", pmo->pszName); + if (bReread) // no need to reread database on reset + MO_RecursiveWalkMenu(pmo->m_items.first, Menu_LoadFromDatabase, szModule); + bRebuild = true; m_menuItems.SendMsg(WM_SETREDRAW, FALSE, 0); m_menuItems.DeleteAllItems(); diff --git a/src/mir_app/src/menu_utils.cpp b/src/mir_app/src/menu_utils.cpp index 266d67b7aa..4d4d6735d3 100644 --- a/src/mir_app/src/menu_utils.cpp +++ b/src/mir_app/src/menu_utils.cpp @@ -86,7 +86,7 @@ LPTSTR GetMenuItemText(TMO_IntMenuItem *pimi) TMO_IntMenuItem* MO_RecursiveWalkMenu(TMO_IntMenuItem *parent, pfnWalkFunc func, void* param) { if (parent == NULL) - return FALSE; + return NULL; TMO_IntMenuItem *pnext; for (TMO_IntMenuItem *pimi = parent; pimi != NULL; pimi = pnext) { @@ -102,7 +102,7 @@ TMO_IntMenuItem* MO_RecursiveWalkMenu(TMO_IntMenuItem *parent, pfnWalkFunc func, } } - return FALSE; + return NULL; } /////////////////////////////////////////////////////////////////////////////// @@ -749,11 +749,7 @@ MIR_APP_DLL(HGENMENU) Menu_AddItem(int hMenuObject, TMO_MenuItem *pmi, void *pUs } else p->owner = &pmo->m_items; - if (!p->owner->first) - p->owner->first = p; - if (p->owner->last) - p->owner->last->next = p; - p->owner->last = p; + p->owner->insert(p); return p; } @@ -896,8 +892,14 @@ static int sttDumpItem(TMO_IntMenuItem *pmi, void *szModule) int visible = (pmi->mi.flags & CMIF_HIDDEN) == 0; TCHAR *ptszName = (pmi->CustomName != NULL) ? pmi->CustomName : _T(""); + + char szRootUid[33]; + if (pmi->mi.root == NULL) + szRootUid[0] = 0; + else + bin2hex(&pmi->mi.root->mi.uid, sizeof(MUUID), szRootUid); - CMString szNewValue(FORMAT, _T("%d;%d;%s"), visible, pmi->mi.position, ptszName); + CMString szNewValue(FORMAT, _T("%d;%d;%S;%s"), visible, pmi->mi.position, szRootUid, ptszName); db_set_ts(NULL, (char*)szModule, menuItemName, szNewValue); Netlib_Logf(NULL, "MENU[%s] => %s, %d, %d", menuItemName, pmi->UniqName, visible, pmi->mi.position); @@ -918,14 +920,36 @@ static INT_PTR sttUpdateMenuService(WPARAM wParam, LPARAM) char szModule[256]; mir_snprintf(szModule, "%s_Items", pmo->pszName); - // read old settings first - MO_RecursiveWalkMenu(pmo->m_items.first, sttReadOldItem, szModule); - - // wipe out old trash, write new data & compatibility flag - CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)szModule); - db_set_b(NULL, szModule, "MenuFormat", true); + // was a menu converted? + if (db_get_b(NULL, szModule, "MenuFormat", 0) == 0) { // no + // read old settings + MO_RecursiveWalkMenu(pmo->m_items.first, sttReadOldItem, szModule); - MO_RecursiveWalkMenu(pmo->m_items.first, sttDumpItem, szModule); + // wipe out old trash, write new data & compatibility flag + CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)szModule); + db_set_b(NULL, szModule, "MenuFormat", true); + MO_RecursiveWalkMenu(pmo->m_items.first, sttDumpItem, szModule); + } + else { // yes, menu is already converted, simply load its data + for (int i = 0;; i++) { + char szSetting[100]; + mir_snprintf(szSetting, "Custom%d", i); + ptrA szCustomMenu(db_get_sa(NULL, szModule, szSetting)); + if (mir_strlen(szCustomMenu) != 32) + break; + + TMO_MenuItem mi = {}; + mi.flags = CMIF_CUSTOM; + mi.name.a = LPGEN("New submenu"); + mi.position = 500050000; + BYTE *p = (BYTE*)&mi.uid; + for (int i = 0; i < 16; i++) + sscanf(&szCustomMenu[i*2], "%02x", &p[i]); + Menu_AddItem(pmo->id, &mi, NULL); + } + + MO_RecursiveWalkMenu(pmo->m_items.first, Menu_LoadFromDatabase, szModule); + } } return 0; } @@ -934,12 +958,87 @@ static INT_PTR sttUpdateMenuService(WPARAM wParam, LPARAM) void ScheduleMenuUpdate() { - // already converted - if (db_get_b(NULL, "MainMenu_Items", "MenuFormat", 0) == 0) { - HANDLE hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - CreateServiceFunction(MS_MENU_UPDATE, sttUpdateMenuService); - CallService(MS_SYSTEM_WAITONHANDLE, (WPARAM)hEvent, (LPARAM)MS_MENU_UPDATE); + HANDLE hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + CreateServiceFunction(MS_MENU_UPDATE, sttUpdateMenuService); + CallService(MS_SYSTEM_WAITONHANDLE, (WPARAM)hEvent, (LPARAM)MS_MENU_UPDATE); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static int sttFindMenuItemByUid(TMO_IntMenuItem *pimi, void *pUid) +{ + return memcmp(&pimi->mi.uid, pUid, sizeof(MUUID)) == 0; +} + +int Menu_LoadFromDatabase(TMO_IntMenuItem *pimi, void *szModule) +{ + if ((pimi->mi.flags & CMIF_SYSTEM) || equalUUID(pimi->mi.uid, miid_last)) + return 0; + + char menuItemName[256]; + bin2hex(&pimi->mi.uid, sizeof(pimi->mi.uid), menuItemName); + + TIntMenuObject *pmo = pimi->parent; + ptrT szValue(db_get_tsa(NULL, (char*)szModule, menuItemName)); + if (szValue == NULL) + return 0; + + TCHAR *ptszToken = szValue, *pDelim = _tcschr(szValue, ';'); + int visible = true, pos = 0; + TCHAR tszCustomName[201]; tszCustomName[0] = 0; + char szCustomRoot[33]; szCustomRoot[0] = 0; + for (int i = 0; i < 4; i++) { + if (pDelim) + *pDelim = 0; + + switch (i) { + case 0: visible = _ttoi(ptszToken); break; + case 1: pos = _ttoi(ptszToken); break; + case 2: strncpy_s(szCustomRoot, _T2A(ptszToken), _TRUNCATE); break; + } + + ptszToken = pDelim + 1; + if ((pDelim = _tcschr(ptszToken, ';')) == NULL) { + if (i == 2 && *ptszToken != 0) + _tcsncpy_s(tszCustomName, ptszToken, _TRUNCATE); break; + break; + } } + + pimi->mi.position = pos; + if (visible) + pimi->mi.flags &= ~CMIF_HIDDEN; + else + pimi->mi.flags |= CMIF_HIDDEN; + + if (tszCustomName[0]) + replaceStrT(pimi->CustomName, tszCustomName); + + if (szCustomRoot[0]) { + char szCurrentUid[33]; + if (pimi->mi.root == NULL) + szCurrentUid[0] = 0; + else + bin2hex(&pimi->mi.root->mi.uid, sizeof(pimi->mi.root->mi.uid), szCurrentUid); + + if (0 != strcmp(szCurrentUid, szCustomRoot)) { // need to move menu item to another root + TMO_LinkedList *pNew; + if (szCustomRoot[0] != 0) { + TMO_IntMenuItem *p = MO_RecursiveWalkMenu(pmo->m_items.first, sttFindMenuItemByUid, &szCustomRoot); + if (p == NULL) + return NULL; + + pNew = &p->submenu; + } + else pNew = &pmo->m_items; + + // relink menu item + pimi->owner->remove(pimi); + pNew->insert(pimi); + } + } + + return 0; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -976,26 +1075,6 @@ static HMENU BuildRecursiveMenu(HMENU hMenu, TMO_IntMenuItem *pRootMenu, WPARAM continue; } - // if we have to check & apply database settings - if (!(mi->flags & CMIF_SYSTEM) && pmo->m_bUseUserDefinedItems) { - char menuItemName[256]; - int visible = true, pos = 0; - - if (!equalUUID(mi->uid, miid_last)) { - bin2hex(&mi->uid, sizeof(mi->uid), menuItemName); - ptrT szValue(db_get_tsa(NULL, szModule, menuItemName)); - if (szValue != NULL) { - TCHAR tszCustomName[201]; tszCustomName[0] = 0; - if (_stscanf(szValue, _T("%d;%d;%200s"), &visible, &pos, tszCustomName) >= 2) - mi->position = pos; - if (tszCustomName[0]) - replaceStrT(pmi->CustomName, tszCustomName); - } - } - if (!visible) - continue; - } - int i = WhereToPlace(hMenu, mi); MENUITEMINFO mii = { 0 }; @@ -1257,3 +1336,29 @@ void TIntMenuObject::freeItem(TMO_IntMenuItem *p) if (p->hBmp) DeleteObject(p->hBmp); mir_free(p); } + +///////////////////////////////////////////////////////////////////////////////////////// + +void TMO_LinkedList::insert(TMO_IntMenuItem *pItem) +{ + pItem->owner = this; + if (!first) + first = pItem; + if (last) + last->next = pItem; + last = pItem; +} + +void TMO_LinkedList::remove(TMO_IntMenuItem *pItem) +{ + TMO_IntMenuItem *pPrev = NULL; + for (TMO_IntMenuItem *p = first; p != NULL; p = p->next) { + if (p == pItem) { + if (first == pItem) first = pItem->next; + if (last == pItem) last = pPrev; + pItem->next = NULL; + return; + } + pPrev = p; + } +} -- cgit v1.2.3