/* INTERNAL ******************************************************************/
+BOOL FASTCALL IntSetMenuItemInfo(PMENU, PITEM, PROSMENUITEMINFO, PUNICODE_STRING);
+
/* maximum allowed depth of any branch in the menu tree.
* This value is slightly larger than in windows (25) to
* stay on the safe side. */
MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_RADIOCHECK | \
MFT_RIGHTORDER | MFT_RIGHTJUSTIFY /* same as MF_HELP */ )
+#define TYPE_MASK (MENUITEMINFO_TYPE_MASK | MF_POPUP | MF_SYSMENU)
+
+#define STATE_MASK (~TYPE_MASK)
+
+#define MENUITEMINFO_STATE_MASK (STATE_MASK & ~(MF_BYPOSITION | MF_MOUSESELECT))
+
+#define MII_STATE_MASK (MFS_GRAYED|MFS_CHECKED|MFS_HILITE|MFS_DEFAULT)
+
/* Maximum number of menu items a menu can contain */
#define MAX_MENU_ITEMS (0x4000)
#define MAX_GOINTOSUBMENU (0x10)
#define UpdateMenuItemState(state, change) \
{\
- if((change) & MFS_DISABLED) { \
- (state) |= MFS_DISABLED; \
+ if((change) & MF_GRAYED) { \
+ (state) |= MF_GRAYED; \
+ } else { \
+ (state) &= ~MF_GRAYED; \
+ } /* Separate the two for test_menu_resource_layout.*/ \
+ if((change) & MF_DISABLED) { \
+ (state) |= MF_DISABLED; \
} else { \
- (state) &= ~MFS_DISABLED; \
+ (state) &= ~MF_DISABLED; \
} \
if((change) & MFS_CHECKED) { \
(state) |= MFS_CHECKED; \
} \
}
-#define FreeMenuText(Menu,MenuItem) \
-{ \
- if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
- (MenuItem)->lpstr.Length) { \
- DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \
- } \
-}
-
-
-PMENU FASTCALL UserGetMenuObject(HMENU hMenu)
-{
- PMENU Menu;
-
- if (!hMenu)
- {
- EngSetLastError(ERROR_INVALID_MENU_HANDLE);
- return NULL;
- }
-
- Menu = (PMENU)UserGetObject(gHandleTable, hMenu, TYPE_MENU);
- if (!Menu)
- {
- EngSetLastError(ERROR_INVALID_MENU_HANDLE);
- return NULL;
- }
-
- return Menu;
-}
-
-
#if 0
void FASTCALL
-DumpMenuItemList(PITEM MenuItem)
+DumpMenuItemList(PMENU Menu, PITEM MenuItem)
{
- UINT cnt = 0;
- while(MenuItem)
+ UINT cnt = 0, i = Menu->cItems;
+ while(i)
{
if(MenuItem->lpstr.Length)
DbgPrint(" %d. %wZ\n", ++cnt, &MenuItem->lpstr);
if(MFS_GRAYED & MenuItem->fState)
DbgPrint("MFS_GRAYED ");
DbgPrint("\n wId=%d\n", MenuItem->wID);
- MenuItem = MenuItem->Next;
+ MenuItem++;
+ i--;
}
DbgPrint("Entries: %d\n", cnt);
return;
}
#endif
+#define FreeMenuText(Menu,MenuItem) \
+{ \
+ if((MENU_ITEM_TYPE((MenuItem)->fType) == MF_STRING) && \
+ (MenuItem)->lpstr.Length) { \
+ DesktopHeapFree(((PMENU)Menu)->head.rpdesk, (MenuItem)->lpstr.Buffer); \
+ } \
+}
+
PMENU FASTCALL
IntGetMenuObject(HMENU hMenu)
{
return Menu;
}
-BOOL FASTCALL
-IntFreeMenuItem(PMENU Menu, PITEM MenuItem, BOOL bRecurse)
+PMENU FASTCALL VerifyMenu(PMENU pMenu)
{
- FreeMenuText(Menu,MenuItem);
- if(bRecurse && MenuItem->spSubMenu)
- {
- IntDestroyMenuObject(MenuItem->spSubMenu, bRecurse, TRUE);
- }
-
- /* Free memory */
- DesktopHeapFree(Menu->head.rpdesk, MenuItem);
-
- return TRUE;
-}
+ HMENU hMenu;
+ PITEM pItem;
+ UINT i;
+ if (!pMenu) return NULL;
-BOOL FASTCALL
-IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bRecurse)
-{
- PITEM PrevMenuItem, MenuItem = NULL;
- if(IntGetMenuItemByFlag(Menu, uPosition, uFlags, &Menu, &MenuItem, &PrevMenuItem) > -1)
+ ERR("VerifyMenu 1!\n");
+ _SEH2_TRY
{
- if(MenuItem)
+ hMenu = UserHMGetHandle(pMenu);
+ pItem = pMenu->rgItems;
+ if (pItem)
{
- if(PrevMenuItem)
- PrevMenuItem->Next = MenuItem->Next;
- else
- {
- Menu->rgItems = MenuItem->Next;
- }
- Menu->cItems--;
- return IntFreeMenuItem(Menu, MenuItem, bRecurse);
+ i = pItem[0].wID;
+ pItem[0].wID = i;
}
}
- return FALSE;
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ ERR("Run away LOOP!\n");
+ _SEH2_YIELD(return NULL);
+ }
+ _SEH2_END
+ ERR("VerifyMenu 2!\n");
+ if ( UserObjectInDestroy(hMenu))
+ return NULL;
+ ERR("VerifyMenu 3!\n");
+ return pMenu;
}
-UINT FASTCALL
-IntDeleteMenuItems(PMENU Menu, BOOL bRecurse)
+BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse, BOOL RemoveFromProcess)
{
- UINT res = 0;
- PITEM NextItem;
- PITEM CurItem = Menu->rgItems;
- while(CurItem && Menu->cItems)
- {
- Menu->cItems--; //// This is the last of this mess~! Removal requires new start up sequence. Do it like windows and wine!
- //// wine MENU_CopySysPopup and ReactOS User32LoadSysMenuTemplateForKernel.
- //// SC_CLOSE First and SC_CLOSED Last
- //// Use menu item blocks not chain.
- /// So do it like windows~!
- NextItem = CurItem->Next;
- IntFreeMenuItem(Menu, CurItem, bRecurse);
- CurItem->Next = 0; // mark the item as end of the list!!!
- CurItem = NextItem;
- res++;
- }
- Menu->cItems = 0;
- Menu->rgItems = NULL;
- return res;
+ /* DestroyMenu should not destroy system menu popup owner */
+ if ((pMenu->fFlags & (MNF_POPUP | MNF_SYSSUBMENU)) == MNF_POPUP && pMenu->hWnd)
+ {
+ //PWND pWnd = ValidateHwndNoErr(pMenu->hWnd);
+ ERR("FIXME Pop up menu window thing'ie\n");
+
+ //co_UserDestroyWindow( pWnd );
+ //pMenu->hWnd = 0;
+ }
+
+ if (pMenu->rgItems) /* recursively destroy submenus */
+ {
+ int i;
+ ITEM *item = pMenu->rgItems;
+ for (i = pMenu->cItems; i > 0; i--, item++)
+ {
+ pMenu->cItems--; //// I hate recursion logic! (jt) 4/2014. See r63028 comment for IntDeleteMenuItems.
+ FreeMenuText(pMenu,item);
+ if (bRecurse && item->spSubMenu)//VerifyMenu(item->spSubMenu))
+ {
+ IntDestroyMenu(item->spSubMenu, bRecurse, RemoveFromProcess);
+ item->spSubMenu = NULL;
+ }
+ }
+ DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems );
+ pMenu->rgItems = NULL;
+ pMenu->cItems = 0; //// What ever~!
+ }
+ return TRUE;
}
BOOL FASTCALL
if(Menu)
{
PWND Window;
- //PWINSTATION_OBJECT WindowStation;
- //NTSTATUS Status;
-
+
/* Remove all menu items */
- IntDeleteMenuItems(Menu, bRecurse); /* Do not destroy submenus */
+ IntDestroyMenu( Menu, bRecurse, RemoveFromProcess);
if(RemoveFromProcess)
{
RemoveEntryList(&Menu->ListEntry);
}
- /*Status = ObReferenceObjectByHandle(Menu->Process->Win32WindowStation,
- 0,
- ExWindowStationObjectType,
- KernelMode,
- (PVOID*)&WindowStation,
- NULL);
- if(NT_SUCCESS(Status))*/
if (PsGetCurrentProcessSessionId() == Menu->head.rpdesk->rpwinstaParent->dwSessionId)
{
BOOL ret;
ret = UserObjectInDestroy(Menu->head.h);
if (ret && EngGetLastError() == ERROR_INVALID_HANDLE) ret = FALSE;
} // See test_subpopup_locked_by_menu tests....
- //ObDereferenceObject(WindowStation);
return ret;
}
}
return FALSE;
}
-BOOL IntDestroyMenu( PMENU pMenu, BOOL RemoveFromProcess)
-{
- /* DestroyMenu should not destroy system menu popup owner */
- if ((pMenu->fFlags & (MNF_POPUP | MNF_SYSSUBMENU)) == MNF_POPUP )//&& pMenu->hWnd)
- {
- //DestroyWindow( pMenu->hWnd );
- //pMenu->hWnd = 0;
- }
-
- if (pMenu->rgItems) /* recursively destroy submenus */
- {
- int i;
- ITEM *item = pMenu->rgItems;
- for (i = pMenu->cItems; i > 0; i--, item++)
- {
- if (item->spSubMenu) IntDestroyMenu(item->spSubMenu, RemoveFromProcess);
- //FreeMenuText(pMenu,item);
- }
- DesktopHeapFree(pMenu->head.rpdesk, pMenu->rgItems );
- }
- //IntDestroyMenuObject(pMenu, bRecurse, RemoveFromProcess);
- return TRUE;
-}
-
/**********************************************************************
* MENU_depth
*
* detect if there are loops in the menu tree (or the depth is too large)
*/
-int MENU_depth( PMENU pmenu, int depth)
+int FASTCALL MENU_depth( PMENU pmenu, int depth)
{
UINT i;
ITEM *item;
int subdepth;
+ if (!pmenu) return depth;
+
depth++;
if( depth > MAXMENUDEPTH) return depth;
item = pmenu->rgItems;
subdepth = depth;
- for( i = 0; i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++)
+ for( i = 0; item, i < pmenu->cItems && subdepth <= MAXMENUDEPTH; i++, item++)
{
- if( item->spSubMenu)
+ if( item->spSubMenu)//VerifyMenu(item->spSubMenu))
{
int bdepth = MENU_depth( item->spSubMenu, depth);
if( bdepth > subdepth) subdepth = bdepth;
* Find a menu item. Return a pointer on the item, and modifies *hmenu
* in case the item was in a sub-menu.
*/
-ITEM *MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags )
+PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags )
{
MENU *menu = *pmenu;
ITEM *fallback = NULL;
UINT fallback_pos = 0;
UINT i;
- PITEM pItem;
+
+ if (!menu) return NULL;
if (wFlags & MF_BYPOSITION)
{
+ if (!menu->cItems) return NULL;
if (*nPos >= menu->cItems) return NULL;
- pItem = menu->rgItems;
- //pItem = &menu->rgItems[*nPos];
- i = 0;
- while(pItem) // Do this for now.
- {
- if (i < (INT)menu->cItems)
- {
- if ( *nPos == i ) return pItem;
- }
- pItem = pItem->Next;
- i++;
- }
+ return &menu->rgItems[*nPos];
}
else
{
PITEM item = menu->rgItems;
- for (i = 0; item ,i < menu->cItems; i++, item = item->Next)//, item++)
+ for (i = 0; item, i < menu->cItems; i++, item++)
{
if (item->spSubMenu)
{
- PMENU psubmenu = item->spSubMenu;
+ PMENU psubmenu = item->spSubMenu;//VerifyMenu(item->spSubMenu);
PITEM subitem = MENU_FindItem( &psubmenu, nPos, wFlags );
if (subitem)
{
return fallback;
}
-BOOL IntRemoveMenu( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
+BOOL FASTCALL
+IntRemoveMenuItem( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
{
PITEM item, NewItems;
TRACE("(menu=%p pos=%04x flags=%04x)\n",pMenu, nPos, wFlags);
if (!(item = MENU_FindItem( &pMenu, &nPos, wFlags ))) return FALSE;
- /* Remove item */
-
- //FreeMenuText(pMenu,item);
+ /* Remove item */
+ FreeMenuText(pMenu,item);
if (bRecurse && item->spSubMenu)
{
- IntDestroyMenu(item->spSubMenu, TRUE);
+ IntDestroyMenuObject(item->spSubMenu, bRecurse, TRUE);
}
////// Use cAlloced with inc's of 8's....
if (--pMenu->cItems == 0)
return TRUE;
}
+/**********************************************************************
+ * MENU_InsertItem
+ *
+ * Insert (allocate) a new item into a menu.
+ */
+ITEM *MENU_InsertItem( PMENU menu, UINT pos, UINT flags, PMENU *submenu, UINT *npos )
+{
+ ITEM *newItems;
+
+ /* Find where to insert new item */
+
+ if (flags & MF_BYPOSITION) {
+ if (pos > menu->cItems)
+ pos = menu->cItems;
+ } else {
+ if (!MENU_FindItem( &menu, &pos, flags ))
+ {
+ if (submenu) *submenu = menu;
+ if (npos) *npos = pos;
+ pos = menu->cItems;
+ }
+ }
+
+ /* Make sure that MDI system buttons stay on the right side.
+ * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
+ * regardless of their id.
+ */
+ while ( pos > 0 &&
+ (INT_PTR)menu->rgItems[pos - 1].hbmp >= (INT_PTR)HBMMENU_SYSTEM &&
+ (INT_PTR)menu->rgItems[pos - 1].hbmp <= (INT_PTR)HBMMENU_MBAR_CLOSE_D)
+ pos--;
+
+ TRACE("inserting at %u flags %x\n", pos, flags);
+
+ /* Create new items array */
+
+ newItems = DesktopHeapAlloc(menu->head.rpdesk, sizeof(ITEM) * (menu->cItems+1) );
+ if (!newItems)
+ {
+ WARN("allocation failed\n" );
+ return NULL;
+ }
+ if (menu->cItems > 0)
+ {
+ /* Copy the old array into the new one */
+ if (pos > 0) RtlCopyMemory( newItems, menu->rgItems, pos * sizeof(ITEM) );
+ if (pos < menu->cItems) RtlCopyMemory( &newItems[pos+1], &menu->rgItems[pos], (menu->cItems-pos)*sizeof(ITEM) );
+ DesktopHeapFree(menu->head.rpdesk, menu->rgItems );
+ }
+ menu->rgItems = newItems;
+ menu->cItems++;
+ RtlZeroMemory( &newItems[pos], sizeof(*newItems) );
+ menu->cyMenu = 0; /* force size recalculate */
+ return &newItems[pos];
+}
+
+BOOL FASTCALL
+IntInsertMenuItem(
+ _In_ PMENU MenuObject,
+ UINT uItem,
+ BOOL fByPosition,
+ PROSMENUITEMINFO ItemInfo,
+ PUNICODE_STRING lpstr)
+{
+ PITEM MenuItem;
+ PMENU SubMenu = NULL;
+
+ NT_ASSERT(MenuObject != NULL);
+
+ if (MAX_MENU_ITEMS <= MenuObject->cItems)
+ {
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ SubMenu = MenuObject;
+
+ if(!(MenuItem = MENU_InsertItem( SubMenu, uItem, fByPosition ? MF_BYPOSITION : MF_BYCOMMAND, &SubMenu, &uItem ))) return FALSE;
+
+ if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo, lpstr))
+ {
+ IntRemoveMenuItem(SubMenu, uItem, fByPosition ? MF_BYPOSITION : MF_BYCOMMAND, FALSE);
+ return FALSE;
+ }
+
+ /* Force size recalculation! */
+ SubMenu->cyMenu = 0;
+ MenuItem->hbmpChecked = MenuItem->hbmpUnchecked = 0;
+
+ TRACE("IntInsertMenuItemToList = %i %d\n", uItem, (BOOL)((INT)uItem >= 0));
+
+ return TRUE;
+}
+
PMENU FASTCALL
IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar)
{
IntCloneMenuItems(PMENU Destination, PMENU Source)
{
PITEM MenuItem, NewMenuItem = NULL;
- PITEM Old = NULL;
+ UINT i;
if(!Source->cItems)
return FALSE;
+ NewMenuItem = DesktopHeapAlloc(Destination->head.rpdesk, (Source->cItems+1) * sizeof(ITEM));
+ if(!NewMenuItem) return FALSE;
+
+ RtlZeroMemory(NewMenuItem, (Source->cItems+1) * sizeof(ITEM));
+
+ Destination->rgItems = NewMenuItem;
+
MenuItem = Source->rgItems;
- while(MenuItem)
+ for (i = 0; i < Source->cItems; i++, MenuItem++, NewMenuItem++)
{
- Old = NewMenuItem;
- if(NewMenuItem)
- NewMenuItem->Next = MenuItem;
- NewMenuItem = DesktopHeapAlloc(Destination->head.rpdesk, sizeof(ITEM));
- if(!NewMenuItem)
- break;
- RtlZeroMemory(NewMenuItem, sizeof(NewMenuItem));
NewMenuItem->fType = MenuItem->fType;
NewMenuItem->fState = MenuItem->fState;
NewMenuItem->wID = MenuItem->wID;
NewMenuItem->lpstr.Buffer = MenuItem->lpstr.Buffer;
}
NewMenuItem->hbmp = MenuItem->hbmp;
-
- NewMenuItem->Next = NULL;
- if(Old)
- Old->Next = NewMenuItem;
- else
- Destination->rgItems = NewMenuItem;
- Destination->cItems++;
- MenuItem = MenuItem->Next;
}
-
return TRUE;
}
Menu->spwndNotify = NULL;
Menu->cyMenu = 0;
Menu->cxMenu = 0;
- Menu->cItems = 0;
+ Menu->cItems = Source->cItems;
Menu->iTop = 0;
Menu->iMaxTop = 0;
Menu->cxTextAlign = 0;
{
int i;
PITEM item = Menu->rgItems;
- for ( i = Menu->cItems; i; i--, item = item->Next)
- {
- if ( item->spSubMenu )
- {
- IntSetMenuInfo( item->spSubMenu, lpmi);
- }
- }
- /* PITEM item = Menu->rgItems;
for ( i = Menu->cItems; i; i--, item++)
{
if ( item->spSubMenu )
{
IntSetMenuInfo( item->spSubMenu, lpmi);
}
- }*/
+ }
}
if (sizeof(MENUINFO) < lpmi->cbSize)
{
return TRUE;
}
-//
-// Old and yeah~..... Why start with a -1 for position search?
-//
-int FASTCALL
-IntGetMenuItemByFlag(PMENU Menu,
- UINT uSearchBy,
- UINT fFlag,
- PMENU *SubMenu,
- PITEM *MenuItem,
- PITEM *PrevMenuItem)
-{
- PITEM PrevItem = NULL;
- PITEM CurItem = Menu->rgItems;
- int p;
- int ret;
-
- if(MF_BYPOSITION & fFlag)
- {
- p = uSearchBy;
- while(CurItem && (p > 0))
- {
- PrevItem = CurItem;
- CurItem = CurItem->Next;
- p--;
- }
- if(CurItem)
- {
- if(MenuItem)
- *MenuItem = CurItem;
- if(PrevMenuItem)
- *PrevMenuItem = PrevItem;
- }
- else
- {
- if(MenuItem)
- *MenuItem = NULL;
- if(PrevMenuItem)
- *PrevMenuItem = NULL; /* ? */
- return -1;
- }
-
- return uSearchBy - p;
- }
- else
- {
- p = 0;
- while(CurItem)
- {
- if(CurItem->wID == uSearchBy)
- {
- if(MenuItem)
- *MenuItem = CurItem;
- if(PrevMenuItem)
- *PrevMenuItem = PrevItem;
- if(SubMenu)
- *SubMenu = Menu;
-
- return p;
- }
- else
- {
- if(CurItem->spSubMenu)
- {
- ret = IntGetMenuItemByFlag(CurItem->spSubMenu, uSearchBy, fFlag, SubMenu, MenuItem, PrevMenuItem);
- if(ret != -1)
- {
- return ret;
- }
- }
- }
- PrevItem = CurItem;
- CurItem = CurItem->Next;
- p++;
- }
- }
- return -1;
-}
-
-
-int FASTCALL
-IntInsertMenuItemToList(PMENU Menu, PITEM MenuItem, int pos)
-{
- PITEM CurItem;
- PITEM LastItem = NULL;
- UINT npos = 0;
-
- CurItem = Menu->rgItems;
- while(CurItem && (pos != 0))
- {
- LastItem = CurItem;
- CurItem = CurItem->Next;
- pos--;
- npos++;
- }
-
- if(LastItem)
- {
- /* Insert the item after LastItem */
- LastItem->Next = MenuItem;
- }
- else
- {
- /* Insert at the beginning */
- Menu->rgItems = MenuItem;
- }
- MenuItem->Next = CurItem;
- Menu->cItems++;
-
- return npos;
-}
-
BOOL FASTCALL
IntGetMenuItemInfo(PMENU Menu, /* UNUSED PARAM!! */
PITEM MenuItem, PROSMENUITEMINFO lpmii)
IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUNICODE_STRING lpstr)
{
PMENU SubMenuObject;
- UINT fTypeMask = (MFT_BITMAP | MFT_MENUBARBREAK | MFT_MENUBREAK | MFT_OWNERDRAW | MFT_RADIOCHECK | MFT_RIGHTJUSTIFY | MFT_SEPARATOR);
if(!MenuItem || !MenuObject || !lpmii)
{
return FALSE;
}
- if (lpmii->fType & ~fTypeMask)
+ if ( lpmii->fMask & MIIM_FTYPE )
{
- ERR("IntSetMenuItemInfo invalid fType flags %x\n", lpmii->fType & ~fTypeMask);
- lpmii->fMask &= ~(MIIM_TYPE | MIIM_FTYPE);
+ MenuItem->fType &= ~MENUITEMINFO_TYPE_MASK;
+ MenuItem->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK;
}
- if (lpmii->fMask & MIIM_TYPE)
+ if (lpmii->fMask & MIIM_TYPE)
{
#if 0 //// Done in User32.
if (lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP))
{
FreeMenuText(MenuObject,MenuItem);
RtlInitUnicodeString(&MenuItem->lpstr, NULL);
+ MenuItem->Xlpstr = NULL;
}
if(lpmii->fType & MFT_BITMAP)
{
{ /* Win 9x/Me stuff */
MenuItem->hbmp = (HBITMAP)((ULONG_PTR)(LOWORD(lpmii->dwTypeData)));
}
+ lpmii->dwTypeData = 0;
}
- MenuItem->fType |= lpmii->fType;
- }
- if (lpmii->fMask & MIIM_FTYPE )
- {
- #if 0 //// ?
- if(( lpmii->fType & MFT_BITMAP))
- {
- ERR("IntSetMenuItemInfo: Can not use FTYPE and MFT_BITMAP.\n");
- SetLastNtError( ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- #endif
- MenuItem->fType &= ~MENUITEMINFO_TYPE_MASK;
- MenuItem->fType |= lpmii->fType & MENUITEMINFO_TYPE_MASK;
}
if(lpmii->fMask & MIIM_BITMAP)
{
- MenuItem->hbmp = lpmii->hbmpItem;
+ MenuItem->hbmp = lpmii->hbmpItem;
}
if(lpmii->fMask & MIIM_CHECKMARKS)
{
SubMenuObject = UserGetMenuObject(lpmii->hSubMenu);
if (SubMenuObject != NULL)
{
+ if ( MENU_depth( SubMenuObject, 0) > MAXMENUDEPTH)
+ {
+ ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded!\n");
+ return FALSE;
+ }
SubMenuObject->fFlags |= MNF_POPUP;
// Now fix the test_subpopup_locked_by_menu tests....
- if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu);
+ if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu);
MenuItem->spSubMenu = SubMenuObject;
UserReferenceObject(SubMenuObject);
}
}
else
{ // If submenu just dereference it.
- if (MenuItem->spSubMenu) UserDereferenceObject(MenuItem->spSubMenu);
+ if (MenuItem->spSubMenu) IntReleaseMenuObject(MenuItem->spSubMenu);
MenuItem->spSubMenu = NULL;
}
}
if ((lpmii->fMask & MIIM_STRING) ||
((lpmii->fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(lpmii->fType) == MF_STRING)))
{
+ /* free the string when used */
FreeMenuText(MenuObject,MenuItem);
+ RtlInitUnicodeString(&MenuItem->lpstr, NULL);
+ MenuItem->Xlpstr = NULL;
- if(lpmii->dwTypeData && lpmii->cch)
+ if(lpmii->dwTypeData && lpmii->cch && lpstr && lpstr->Buffer)
{
UNICODE_STRING Source;
MenuItem->cch = MenuItem->lpstr.Length / sizeof(WCHAR);
MenuItem->Xlpstr = (USHORT*)MenuItem->lpstr.Buffer;
}
- else
- {
- RtlInitUnicodeString(&MenuItem->lpstr, NULL);
- MenuItem->Xlpstr = NULL;
- }
- }
- else
- {
- if (0 == (MenuObject->fFlags & MNF_SYSDESKMN))
- {
- MenuItem->fType |= MF_SEPARATOR;
- }
- RtlInitUnicodeString(&MenuItem->lpstr, NULL);
}
}
- //if( !MenuItem->lpstr.Buffer && !(MenuItem->fType & MFT_OWNERDRAW) && !MenuItem->hbmp)
- // MenuItem->fType |= MFT_SEPARATOR; break system menu.....
-
- /* Force size recalculation! */
- MenuObject->cyMenu = 0;
+ if( !(MenuObject->fFlags & MNF_SYSDESKMN) &&
+ !MenuItem->Xlpstr &&
+ !lpmii->dwTypeData &&
+ !(MenuItem->fType & MFT_OWNERDRAW) &&
+ !MenuItem->hbmp)
+ MenuItem->fType |= MFT_SEPARATOR;
if (sizeof(ROSMENUITEMINFO) == lpmii->cbSize)
{
}
-/**********************************************************************
- * MENU_InsertItem
- *
- * Insert (allocate) a new item into a menu.
- */
-ITEM *MENU_InsertItem( PMENU menu, UINT pos, UINT flags )
-{
- ITEM *newItems;
-
- /* Find where to insert new item */
-
- if (flags & MF_BYPOSITION) {
- if (pos > menu->cItems)
- pos = menu->cItems;
- } else {
- if (!MENU_FindItem( &menu, &pos, flags ))
- pos = menu->cItems;
- }
-
- /* Make sure that MDI system buttons stay on the right side.
- * Note: XP treats only bitmap handles 1 - 6 as "magic" ones
- * regardless of their id.
- */
- while ( pos > 0 &&
- (INT_PTR)menu->rgItems[pos - 1].hbmp >= (INT_PTR)HBMMENU_SYSTEM &&
- (INT_PTR)menu->rgItems[pos - 1].hbmp <= (INT_PTR)HBMMENU_MBAR_CLOSE_D)
- pos--;
-
- TRACE("inserting at %u flags %x\n", pos, flags);
-
- /* Create new items array */
-
- newItems = DesktopHeapAlloc(menu->head.rpdesk, sizeof(ITEM) * (menu->cItems+1) );
- if (!newItems)
- {
- WARN("allocation failed\n" );
- return NULL;
- }
- if (menu->cItems > 0)
- {
- /* Copy the old array into the new one */
- if (pos > 0) RtlCopyMemory( newItems, menu->rgItems, pos * sizeof(ITEM) );
- if (pos < menu->cItems) RtlCopyMemory( &newItems[pos+1], &menu->rgItems[pos], (menu->cItems-pos)*sizeof(ITEM) );
- DesktopHeapFree(menu->head.rpdesk, menu->rgItems );
- }
- menu->rgItems = newItems;
- menu->cItems++;
- RtlZeroMemory( &newItems[pos], sizeof(*newItems) );
- menu->cyMenu = 0; /* force size recalculate */
- return &newItems[pos];
-}
-
-BOOL FASTCALL
-IntInsertMenuItem(
- _In_ PMENU MenuObject,
- UINT uItem,
- BOOL fByPosition,
- PROSMENUITEMINFO ItemInfo)
-{
- int pos;
- PITEM MenuItem;
- PMENU SubMenu = NULL;
-
- NT_ASSERT(MenuObject != NULL);
- //ERR("InsertMenuItem\n");
- if (MAX_MENU_ITEMS <= MenuObject->cItems)
- {
- EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
-
- if (fByPosition)
- {
- SubMenu = MenuObject;
- /* calculate position */
- pos = (int)uItem;
- if(uItem > MenuObject->cItems)
- {
- pos = MenuObject->cItems;
- }
- }
- else
- {
- pos = IntGetMenuItemByFlag(MenuObject, uItem, MF_BYCOMMAND, &SubMenu, NULL, NULL);
- }
- if (SubMenu == NULL)
- {
- /* Default to last position of menu */
- SubMenu = MenuObject;
- pos = MenuObject->cItems;
- }
-
-
- if (pos < -1)
- {
- pos = -1;
- }
-
- MenuItem = DesktopHeapAlloc(MenuObject->head.rpdesk, sizeof(ITEM));
- if (NULL == MenuItem)
- {
- EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
-
- RtlZeroMemory(MenuItem, sizeof(MenuItem));
-
- if(!IntSetMenuItemInfo(SubMenu, MenuItem, ItemInfo, NULL))
- {
- DesktopHeapFree(MenuObject->head.rpdesk, MenuItem);
- return FALSE;
- }
-
- /* Force size recalculation! */
- MenuObject->cyMenu = 0;
- MenuItem->hbmpChecked = MenuItem->hbmpUnchecked = 0;
-
- pos = IntInsertMenuItemToList(SubMenu, MenuItem, pos);
-
- TRACE("IntInsertMenuItemToList = %i\n", pos);
-
- return (pos >= 0);
-}
-
UINT FASTCALL
IntEnableMenuItem(PMENU MenuObject, UINT uIDEnableItem, UINT uEnable)
{
}
return res;
}
-#if 0 // Moved to User32.
-DWORD FASTCALL
-IntBuildMenuItemList(PMENU MenuObject, PVOID Buffer, ULONG nMax)
-{
- DWORD res = 0;
- ROSMENUITEMINFO mii;
- PVOID Buf;
- PITEM CurItem = MenuObject->rgItems;
- PWCHAR StrOut;
- NTSTATUS Status;
- WCHAR NulByte;
- if (0 != nMax)
- {
- if (nMax < MenuObject->cItems * sizeof(ROSMENUITEMINFO))
- {
- return 0;
- }
- StrOut = (PWCHAR)((char *) Buffer + MenuObject->cItems
- * sizeof(ROSMENUITEMINFO));
- nMax -= MenuObject->cItems * sizeof(ROSMENUITEMINFO);
- Buf = Buffer;
- mii.cbSize = sizeof(ROSMENUITEMINFO);
- mii.fMask = 0;
- NulByte = L'\0';
-
- while (NULL != CurItem)
- {
- mii.cch = CurItem->lpstr.Length / sizeof(WCHAR);
- mii.dwItemData = CurItem->dwItemData;
- if (0 != CurItem->lpstr.Length)
- {
- mii.dwTypeData = StrOut;
- }
- else
- {
- mii.dwTypeData = NULL;
- }
- mii.fState = CurItem->fState;
- mii.fType = CurItem->fType;
- mii.wID = CurItem->wID;
- mii.hbmpChecked = CurItem->hbmpChecked;
- mii.hbmpItem = CurItem->hbmp;
- mii.hbmpUnchecked = CurItem->hbmpUnchecked;
- mii.hSubMenu = CurItem->spSubMenu ? CurItem->spSubMenu->head.h : NULL;
- mii.Rect.left = CurItem->xItem;
- mii.Rect.top = CurItem->yItem;
- mii.Rect.right = CurItem->cxItem; // Do this for now......
- mii.Rect.bottom = CurItem->cyItem;
- mii.dxTab = CurItem->dxTab;
- mii.lpstr = CurItem->lpstr.Buffer; // Can be read from user side!
- //mii.maxBmpSize.cx = CurItem->cxBmp;
- //mii.maxBmpSize.cy = CurItem->cyBmp;
-
- Status = MmCopyToCaller(Buf, &mii, sizeof(ROSMENUITEMINFO));
- if (! NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- return 0;
- }
- Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO));
-
- if (0 != CurItem->lpstr.Length
- && (nMax >= CurItem->lpstr.Length + sizeof(WCHAR)))
- {
- /* Copy string */
- Status = MmCopyToCaller(StrOut, CurItem->lpstr.Buffer,
- CurItem->lpstr.Length);
- if (! NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- return 0;
- }
- StrOut += CurItem->lpstr.Length / sizeof(WCHAR);
- Status = MmCopyToCaller(StrOut, &NulByte, sizeof(WCHAR));
- if (! NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- return 0;
- }
- StrOut++;
- nMax -= CurItem->lpstr.Length + sizeof(WCHAR);
- }
- else if (0 != CurItem->lpstr.Length)
- {
- break;
- }
-
- CurItem = CurItem->Next;
- res++;
- }
- }
- else
- {
- while (NULL != CurItem)
- {
- res += sizeof(ROSMENUITEMINFO) + CurItem->lpstr.Length + sizeof(WCHAR);
- CurItem = CurItem->Next;
- }
- }
- return res;
-}
-#endif
DWORD FASTCALL
IntCheckMenuItem(PMENU MenuObject, UINT uIDCheckItem, UINT uCheck)
{
if (!(MenuItem = MENU_FindItem( &MenuObject, &uItemHilite, uHilite ))) return FALSE;
- if (MenuItem)
+ if (uHilite & MF_HILITE)
{
- if (uHilite & MF_HILITE)
- {
- MenuItem->fState |= MF_HILITE;
- }
- else
- {
- MenuItem->fState &= ~MF_HILITE;
- }
+ MenuItem->fState |= MF_HILITE;
+ }
+ else
+ {
+ MenuItem->fState &= ~MF_HILITE;
}
/* FIXME: Update the window's menu */
- return TRUE;
+ return TRUE; // Always returns true!!!!
}
BOOL FASTCALL
UserSetMenuDefaultItem(PMENU MenuObject, UINT uItem, UINT fByPos)
{
- BOOL ret = FALSE;
+ UINT i;
PITEM MenuItem = MenuObject->rgItems;
- while(MenuItem)
+ if (!MenuItem) return FALSE;
+
+ /* reset all default-item flags */
+ for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++)
{
- MenuItem->fState &= ~MFS_DEFAULT;
- MenuItem = MenuItem->Next;
+ MenuItem->fState &= ~MFS_DEFAULT;
}
/* no default item */
{
return TRUE;
}
-
- if(fByPos)
+ MenuItem = MenuObject->rgItems;
+ if ( fByPos )
{
- UINT pos = 0;
- while(MenuItem)
- {
- if(pos == uItem)
- {
- MenuItem->fState |= MFS_DEFAULT;
- ret = TRUE;
- }
- else
- {
- MenuItem->fState &= ~MFS_DEFAULT;
- }
- pos++;
- MenuItem = MenuItem->Next;
- }
+ if ( uItem >= MenuObject->cItems ) return FALSE;
+ MenuItem[uItem].fState |= MFS_DEFAULT;
+ return TRUE;
}
else
{
- while(MenuItem)
+ for (i = 0; MenuItem, i < MenuObject->cItems; i++, MenuItem++)
{
- if(!ret && (MenuItem->wID == uItem))
- {
- MenuItem->fState |= MFS_DEFAULT;
- ret = TRUE;
- }
- else
- {
- MenuItem->fState &= ~MFS_DEFAULT;
- }
- MenuItem = MenuItem->Next;
+ if (MenuItem->wID == uItem)
+ {
+ MenuItem->fState |= MFS_DEFAULT;
+ return TRUE;
+ }
}
+
}
- return ret;
+ return FALSE;
}
UINT FASTCALL
-IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags,
- DWORD *gismc)
+IntGetMenuDefaultItem(PMENU MenuObject, UINT fByPos, UINT gmdiFlags, DWORD *gismc)
{
- UINT x = 0;
- UINT res = -1;
- UINT sres;
+ UINT i = 0;
PITEM MenuItem = MenuObject->rgItems;
- while(MenuItem)
- {
- if(MenuItem->fState & MFS_DEFAULT)
- {
-
- if(!(gmdiFlags & GMDI_USEDISABLED) && (MenuItem->fState & MFS_DISABLED))
- break;
+ /* empty menu */
+ if (!MenuItem) return -1;
- if(fByPos)
- res = x;
- else
- res = MenuItem->wID;
-
- if((*gismc < MAX_GOINTOSUBMENU) && (gmdiFlags & GMDI_GOINTOPOPUPS) &&
- MenuItem->spSubMenu)
- {
-
- if(MenuItem->spSubMenu == MenuObject)
- break;
-
- (*gismc)++;
- sres = IntGetMenuDefaultItem(MenuItem->spSubMenu, fByPos, gmdiFlags, gismc);
- (*gismc)--;
+ while ( !( MenuItem->fState & MFS_DEFAULT ) )
+ {
+ i++; MenuItem++;
+ if (i >= MenuObject->cItems ) return -1;
+ }
- if(sres > (UINT)-1)
- res = sres;
- }
+ /* default: don't return disabled items */
+ if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (MenuItem->fState & MFS_DISABLED )) return -1;
- break;
- }
+ /* search rekursiv when needed */
+ if ( (MenuItem->fType & MF_POPUP) && (gmdiFlags & GMDI_GOINTOPOPUPS) && MenuItem->spSubMenu)
+ {
+ UINT ret;
+ (*gismc)++;
+ ret = IntGetMenuDefaultItem( MenuItem->spSubMenu, fByPos, gmdiFlags, gismc );
+ (*gismc)--;
+ if ( -1 != ret ) return ret;
- MenuItem = MenuItem->Next;
- x++;
+ /* when item not found in submenu, return the popup item */
}
-
- return res;
+ return ( fByPos ) ? i : MenuItem->wID;
}
VOID FASTCALL
{
LastHead = Win32Process->MenuListHead.Flink;
MenuObject = CONTAINING_RECORD(Win32Process->MenuListHead.Flink, MENU, ListEntry);
- ERR("Menus are stuck on the process list!\n");
+ TRACE("Menus are stuck on the process list!\n");
IntDestroyMenuObject(MenuObject, FALSE, TRUE);
}
PMENU Menu,
UINT uItem,
BOOL fByPosition,
- LPCMENUITEMINFOW UnsafeItemInfo)
+ LPCMENUITEMINFOW UnsafeItemInfo,
+ PUNICODE_STRING lpstr)
{
NTSTATUS Status;
ROSMENUITEMINFO ItemInfo;
EngSetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
- return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo);
+ return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo, lpstr);
}
/* Try to copy without last field (not present in older versions) */
return FALSE;
}
ItemInfo.hbmpItem = (HBITMAP)0;
- return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo);
+ return IntInsertMenuItem(Menu, uItem, fByPosition, &ItemInfo, lpstr);
}
SetLastNtError(Status);
return NO_SELECTED_ITEM;
item = menu->rgItems;
- for (i = 0; i < menu->cItems; i++, item = item->Next)//item++)
+ for (i = 0; i < menu->cItems; i++, item++)
{
if (!item->spSubMenu)
continue;
UINT Item,
BOOL ByPosition,
PROSMENUITEMINFO UnsafeItemInfo,
- BOOL SetOrGet)
+ BOOL SetOrGet,
+ PUNICODE_STRING lpstr)
{
PITEM MenuItem;
ROSMENUITEMINFO ItemInfo;
if (SetOrGet)
{
- Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, NULL);
+ Ret = IntSetMenuItemInfo(Menu, MenuItem, &ItemInfo, lpstr);
}
else
{
{
LONG XMove, YMove;
PITEM MenuItem;
- //int p = 0;
if (!pWnd)
{
return FALSE;
}
- //if(Menu->Process != PsGetCurrentProcess())
if (Menu->head.rpdesk != pti->rpdesk)
{
EngSetLastError(ERROR_ACCESS_DENIED);
//kmbi.fBarFocused = top_popup_hmenu == hMenu;
if (idItem)
{
- PITEM MenuItem;
- UINT nPos = idItem-1;
+ //PITEM MenuItem;
+ //UINT nPos = idItem-1;
kmbi.fFocused = Menu->iItem == idItem-1;
- //if (kmbi->fFocused && (Menu->rgItems[idItem - 1].spSubMenu))
- MenuItem = MENU_FindItem (&Menu, &nPos, MF_BYPOSITION);
- if ( MenuItem && kmbi.fFocused && MenuItem->spSubMenu )
+ if (kmbi.fFocused && (Menu->rgItems[idItem - 1].spSubMenu))
+ //MenuItem = MENU_FindItem (&Menu, &nPos, MF_BYPOSITION);
+ //if ( MenuItem && kmbi.fFocused && MenuItem->spSubMenu )
{
- //kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd;
- kmbi.hwndMenu = MenuItem->spSubMenu->hWnd;
+ kmbi.hwndMenu = Menu->rgItems[idItem - 1].spSubMenu->hWnd;
+ //kmbi.hwndMenu = MenuItem->spSubMenu->hWnd;
}
}
/* else
{
PMENU Menu, SubMenu;
PITEM MenuItem;
+ UINT i;
DECLARE_RETURN(UINT);
TRACE("Enter NtUserGetMenuIndex\n");
RETURN(0xFFFFFFFF);
MenuItem = Menu->rgItems;
- while(MenuItem)
+ for (i = 0; i < Menu->cItems; i++, MenuItem++)
{
- if (MenuItem->spSubMenu == SubMenu)
- RETURN(MenuItem->wID);
- MenuItem = MenuItem->Next;
+ if (MenuItem->spSubMenu == SubMenu)
+ RETURN(MenuItem->wID);
}
-
RETURN(0xFFFFFFFF);
CLEANUP:
Y -= Window->rcWindow.top;
mi = Menu->rgItems;
- for (i = 0; NULL != mi; i++)//, mi++)
+ for (i = 0; i < Menu->cItems; i++, mi++)
{
RECTL Rect;
Rect.left = mi->xItem;
{
break;
}
- mi = mi->Next;
}
RETURN( (mi ? i : NO_SELECTED_ITEM));
RETURN(FALSE);
}
- lstrCaption.Buffer = NULL;
+ RtlInitUnicodeString(&lstrCaption, 0);
/* Check if we got a Caption */
if (lpszCaption && lpszCaption->Buffer)
SetLastNtError(Status);
RETURN(FALSE);
}
- ///// Now use it!
}
- if (bInsert) RETURN( UserInsertMenuItem(Menu, uItem, fByPosition, lpmii));
+ if (bInsert) RETURN( UserInsertMenuItem(Menu, uItem, fByPosition, lpmii, &lstrCaption));
- RETURN( UserMenuItemInfo(Menu, uItem, fByPosition, (PROSMENUITEMINFO)lpmii, TRUE));
+ RETURN( UserMenuItemInfo(Menu, uItem, fByPosition, (PROSMENUITEMINFO)lpmii, TRUE, &lstrCaption));
CLEANUP:
TRACE("Leave NtUserThunkedMenuItemInfo, ret=%i\n",_ret_);
LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active);
BOOL WINAPI GdiValidateHandle(HGDIOBJ hobj);
+LRESULT DefWndNCHitTest(HWND hWnd, POINT Point);
+void FASTCALL NcGetSysPopupPos(HWND Wnd, RECT *Rect);
WINE_DEFAULT_DEBUG_CHANNEL(menu);
*/
FORCEINLINE PMENU MENU_GetMenu(HMENU hMenu)
{
- return ValidateHandle(hMenu, TYPE_MENU);
+ return ValidateHandleNoErr(hMenu, TYPE_MENU);
+}
+
+/***********************************************************************
+ * get_win_sys_menu
+ *
+ * Get the system menu of a window
+ */
+static HMENU get_win_sys_menu( HWND hwnd )
+{
+ HMENU ret = 0;
+ WND *win = ValidateHwnd( hwnd );
+ if (win)
+ {
+ ret = win->SystemMenu;
+ }
+ return ret;
}
/***********************************************************************
{
if (*nPos >= menu->cItems) return NULL;
pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
- //pItem = &menu->rgItems[*nPos];
- i = 0;
- while(pItem) // Do this for now.
- {
- if (i < (INT)menu->cItems)
- {
- if ( *nPos == i ) return pItem;
- }
- pItem = pItem->Next ? DesktopPtrToUser(pItem->Next) : NULL;
- i++;
- }
+ if (pItem) pItem = &pItem[*nPos];
+ return pItem;
}
else
{
PITEM item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
- for (i = 0; item ,i < menu->cItems; i++, item = item->Next ? DesktopPtrToUser(item->Next) : NULL)//, item++)
+ for (i = 0; item, i < menu->cItems; i++, item++)
{
if (item->spSubMenu)
{
UINT FASTCALL
IntGetMenuDefaultItem(PMENU Menu, BOOL fByPos, UINT gmdiFlags, DWORD *gismc)
{
- UINT x = 0;
- UINT res = -1;
- UINT sres;
+ UINT i = 0;
PITEM Item = Menu->rgItems ? DesktopPtrToUser(Menu->rgItems) : NULL;
- while(Item)
- {
- if (Item->fState & MFS_DEFAULT)
- {
- if (!(gmdiFlags & GMDI_USEDISABLED) &&
- (Item->fState & MFS_DISABLED) )
- break;
+ /* empty menu */
+ if (!Item) return -1;
- res = fByPos ? x : Item->wID;
+ while ( !( Item->fState & MFS_DEFAULT ) )
+ {
+ i++; Item++;
+ if (i >= Menu->cItems ) return -1;
+ }
- if ((*gismc < MAX_GOINTOSUBMENU) &&
- (gmdiFlags & GMDI_GOINTOPOPUPS) &&
- Item->spSubMenu)
- {
- if (DesktopPtrToUser(Item->spSubMenu) == Menu)
- break;
+ /* default: don't return disabled items */
+ if ( (!(GMDI_USEDISABLED & gmdiFlags)) && (Item->fState & MFS_DISABLED )) return -1;
- (*gismc)++;
- sres = IntGetMenuDefaultItem( DesktopPtrToUser(Item->spSubMenu), fByPos, gmdiFlags, gismc);
- (*gismc)--;
+ /* search rekursiv when needed */
+ if ( (Item->fType & MF_POPUP) && (gmdiFlags & GMDI_GOINTOPOPUPS) && Item->spSubMenu)
+ {
+ UINT ret;
+ (*gismc)++;
+ ret = IntGetMenuDefaultItem( DesktopPtrToUser(Item->spSubMenu), fByPos, gmdiFlags, gismc );
+ (*gismc)--;
+ if ( -1 != ret ) return ret;
- if(sres > (UINT)-1)
- res = sres;
- }
- break;
- }
- Item = Item->Next ? DesktopPtrToUser(Item->Next) : NULL;
- x++;
+ /* when item not found in submenu, return the popup item */
}
- return res;
+ return ( fByPos ) ? i : Item->wID;
}
static BOOL GetMenuItemInfo_common ( HMENU hmenu,
if (!pItem)
{
SetLastError( ERROR_MENU_ITEM_NOT_FOUND);
- //SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
lpmii->hbmpItem = pItem->hbmp;
if (lpmii->fMask & MIIM_STATE)
- lpmii->fState = pItem->fState & MII_STATE_MASK; //MENUITEMINFO_STATE_MASK;
+ lpmii->fState = pItem->fState & MENUITEMINFO_STATE_MASK;
if (lpmii->fMask & MIIM_ID)
lpmii->wID = pItem->wID;
MenuGetRosMenuInfo(PROSMENUINFO MenuInfo, HMENU Menu)
{
PMENU pMenu;
- if (!(pMenu = ValidateHandle(Menu, TYPE_MENU))) return FALSE;
+ if (!(pMenu = ValidateHandleNoErr(Menu, TYPE_MENU))) return FALSE;
MenuInfo->hbrBack = pMenu->hbrBack;
MenuInfo->dwContextHelpID = pMenu->dwContextHelpId;
{
ItemInfo->cch = strlenW(ItemInfo->dwTypeData);
}
+ if (ItemInfo->hSubMenu)
+ {
+ if (!IsMenu(ItemInfo->hSubMenu)) ItemInfo->hSubMenu = NULL;
+ }
Ret = NtUserThunkedMenuItemInfo(Menu, Index, TRUE, FALSE, (LPMENUITEMINFOW)ItemInfo, NULL);
return Ret;
}
}
}
-DWORD FASTCALL
-IntBuildMenuItemList(PMENU MenuObject, PVOID Buffer, ULONG nMax)
-{
- DWORD res = 0;
- ROSMENUITEMINFO mii;
- PVOID Buf;
- PITEM CurItem = MenuObject->rgItems ? DesktopPtrToUser(MenuObject->rgItems) : NULL;
- PWCHAR StrOut;
- WCHAR NulByte;
-
- if (0 != nMax)
- {
- if (nMax < MenuObject->cItems * sizeof(ROSMENUITEMINFO))
- {
- return 0;
- }
- StrOut = (PWCHAR)((char *) Buffer + MenuObject->cItems * sizeof(ROSMENUITEMINFO));
- nMax -= MenuObject->cItems * sizeof(ROSMENUITEMINFO);
- Buf = Buffer;
- mii.cbSize = sizeof(ROSMENUITEMINFO);
- mii.fMask = 0;
- NulByte = L'\0';
-
- while (NULL != CurItem)
- {
- mii.cch = CurItem->lpstr.Length / sizeof(WCHAR);
- mii.dwItemData = CurItem->dwItemData;
- if (0 != CurItem->lpstr.Length)
- {
- mii.dwTypeData = StrOut;
- }
- else
- {
- mii.dwTypeData = NULL;
- }
- mii.fState = CurItem->fState;
- mii.fType = CurItem->fType;
- mii.wID = CurItem->wID;
- mii.hbmpChecked = CurItem->hbmpChecked;
- mii.hbmpItem = CurItem->hbmp;
- mii.hbmpUnchecked = CurItem->hbmpUnchecked;
- if (CurItem->spSubMenu)
- {
- PMENU pSubMenu = DesktopPtrToUser(CurItem->spSubMenu);
- HMENU hSubMenu = UserHMGetHandle(pSubMenu);
- mii.hSubMenu = hSubMenu;
- }
- else
- mii.hSubMenu = NULL;
- mii.Rect.left = CurItem->xItem;
- mii.Rect.top = CurItem->yItem;
- mii.Rect.right = CurItem->cxItem; // Do this for now......
- mii.Rect.bottom = CurItem->cyItem;
- mii.dxTab = CurItem->dxTab;
- mii.lpstr = CurItem->lpstr.Buffer; // Can be read from user side!
- //mii.maxBmpSize.cx = CurItem->cxBmp;
- //mii.maxBmpSize.cy = CurItem->cyBmp;
-
- RtlCopyMemory(Buf, &mii, sizeof(ROSMENUITEMINFO));
- Buf = (PVOID)((ULONG_PTR)Buf + sizeof(ROSMENUITEMINFO));
-
- if (0 != CurItem->lpstr.Length && (nMax >= CurItem->lpstr.Length + sizeof(WCHAR)))
- {
- LPWSTR lpstr = CurItem->lpstr.Buffer ? DesktopPtrToUser(CurItem->lpstr.Buffer) : NULL;
- if (lpstr)
- {
- /* Copy string */
- RtlCopyMemory(StrOut, lpstr, CurItem->lpstr.Length);
-
- StrOut += CurItem->lpstr.Length / sizeof(WCHAR);
- RtlCopyMemory(StrOut, &NulByte, sizeof(WCHAR));
- StrOut++;
- nMax -= CurItem->lpstr.Length + sizeof(WCHAR);
- }
- }
- else if (0 != CurItem->lpstr.Length)
- {
- break;
- }
-
- CurItem = CurItem->Next ? DesktopPtrToUser(CurItem->Next) : NULL;
- res++;
- }
- }
- else
- {
- while (NULL != CurItem)
- {
- res += sizeof(ROSMENUITEMINFO) + CurItem->lpstr.Length + sizeof(WCHAR);
- CurItem = CurItem->Next ? DesktopPtrToUser(CurItem->Next) : NULL;
- }
- }
- return res;
-}
-
-/***********************************************************************
- * MenuGetAllRosMenuItemInfo
- *
- * Get full information about all menu items
- */
-static INT FASTCALL
-MenuGetAllRosMenuItemInfo(HMENU Menu, PROSMENUITEMINFO *ItemInfo)
-{
- DWORD BufSize;
- PMENU pMenu;
-
- if (!(pMenu = ValidateHandle(Menu, TYPE_MENU))) return -1;
-
- BufSize = IntBuildMenuItemList(pMenu, (PVOID)1, 0);
- if (BufSize == (DWORD) -1 || BufSize == 0)
- {
- return -1;
- }
- *ItemInfo = HeapAlloc(GetProcessHeap(), 0, BufSize);
- if (NULL == *ItemInfo)
- {
- return -1;
- }
-
- return IntBuildMenuItemList(pMenu, (PVOID)*ItemInfo, BufSize);
-}
-
-/***********************************************************************
- * MenuCleanupAllRosMenuItemInfo
- *
- * Cleanup after use of MenuGetAllRosMenuItemInfo
- */
-static VOID FASTCALL
-MenuCleanupAllRosMenuItemInfo(PROSMENUITEMINFO ItemInfo)
-{
- HeapFree(GetProcessHeap(), 0, ItemInfo);
-}
-
/***********************************************************************
* MenuInitSysMenuPopup
*
* PROSMENUINFO MenuInfo)
*
*****************************************************************************/
-static UINT MenuGetStartOfNextColumn(
- PROSMENUINFO MenuInfo)
+
+static UINT MENU_GetStartOfNextColumn(
+ HMENU hMenu )
{
- PROSMENUITEMINFO MenuItems;
+ MENU *menu = MENU_GetMenu(hMenu);
+ PITEM pItem;
UINT i;
- i = MenuInfo->iItem;
- if ( i == NO_SELECTED_ITEM )
- return i;
+ if(!menu)
+ return NO_SELECTED_ITEM;
- if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
- return NO_SELECTED_ITEM;
+ i = menu->iItem + 1;
+ if( i == NO_SELECTED_ITEM )
+ return i;
- for (i++ ; i < MenuInfo->cItems; i++)
- if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)))
- return i;
+ pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
+ if (!pItem) return NO_SELECTED_ITEM;
+ for( ; i < menu->cItems; ++i ) {
+ if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+ return i;
+ }
return NO_SELECTED_ITEM;
}
* PROSMENUINFO MenuInfo)
*
*****************************************************************************/
-
-static UINT FASTCALL MenuGetStartOfPrevColumn(
- PROSMENUINFO MenuInfo)
+static UINT MENU_GetStartOfPrevColumn(
+ HMENU hMenu )
{
- PROSMENUITEMINFO MenuItems;
- UINT i;
+ MENU *menu = MENU_GetMenu(hMenu);
+ UINT i;
+ PITEM pItem;
- if (!MenuInfo->iItem || MenuInfo->iItem == NO_SELECTED_ITEM)
- return NO_SELECTED_ITEM;
+ if( !menu )
+ return NO_SELECTED_ITEM;
- if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0)
- return NO_SELECTED_ITEM;
+ if( menu->iItem == 0 || menu->iItem == NO_SELECTED_ITEM )
+ return NO_SELECTED_ITEM;
+
+ pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
+ if (!pItem) return NO_SELECTED_ITEM;
/* Find the start of the column */
- for (i = MenuInfo->iItem;
- 0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
- --i)
- {
- ; /* empty */
- }
- if (i == 0)
- {
- MenuCleanupAllRosMenuItemInfo(MenuItems);
- return NO_SELECTED_ITEM;
- }
+ for(i = menu->iItem; i != 0 &&
+ !(pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK));
+ --i); /* empty */
- for (--i; 0 != i; --i)
- if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
- break;
+ if(i == 0)
+ return NO_SELECTED_ITEM;
+
+ for(--i; i != 0; --i) {
+ if (pItem[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))
+ break;
+ }
- MenuCleanupAllRosMenuItemInfo(MenuItems);
TRACE("ret %d.\n", i );
return i;
return NO_SELECTED_ITEM;
item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
- for (i = 0; i < menu->cItems; i++, item = item->Next ? DesktopPtrToUser(item->Next) : NULL)//item++)
+ for (i = 0; i < menu->cItems; i++, item++)
{
if (!item->spSubMenu)
continue;
* Find the menu item selected by a key press.
* Return item id, -1 if none, -2 if we should close the menu.
*/
-static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo,
+static UINT FASTCALL MENU_FindItemByKey(HWND WndOwner, HMENU hmenu,
WCHAR Key, BOOL ForceMenuChar)
{
- ROSMENUINFO SysMenuInfo;
- PROSMENUITEMINFO Items, ItemInfo;
LRESULT MenuChar;
- UINT i;
WORD Flags = 0;
- TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo);
+ TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char)Key, Key, hmenu );
- if (NULL == MenuInfo || ! IsMenu(MenuInfo->Self))
- {
- if (MenuGetRosMenuInfo(&SysMenuInfo, GetSystemMenu(WndOwner, FALSE)))
- {
- MenuInfo = &SysMenuInfo;
- }
- else
- {
- MenuInfo = NULL;
- }
- }
+ if (!IsMenu( hmenu )) hmenu = GetSubMenu( get_win_sys_menu(WndOwner), 0);
+ if (hmenu)
+ {
+ MENU *menu = MENU_GetMenu( hmenu );
+ ITEM *item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
- if (NULL != MenuInfo)
- {
- if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &Items) <= 0)
- {
- return -1;
- }
- if ( !ForceMenuChar )
- {
- ItemInfo = Items;
- for (i = 0; i < MenuInfo->cItems; i++, ItemInfo++)
- {
- if ((ItemInfo->lpstr) && NULL != ItemInfo->dwTypeData)
- {
- WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2;
- do
- {
- p = strchrW (p + 2, '&');
- }
- while (p != NULL && p [1] == '&');
- if (p && (toupperW(p[1]) == toupperW(Key))) return i;
- }
- }
- }
+ if( !ForceMenuChar )
+ {
+ UINT i;
+ BOOL cjk = GetSystemMetrics( SM_DBCSENABLED );
+
+ for (i = 0; i < menu->cItems; i++, item++)
+ {
+ LPWSTR text = item->Xlpstr ? DesktopPtrToUser(item->Xlpstr) : NULL;
+ if( text)
+ {
+ const WCHAR *p = text - 2;
+ do
+ {
+ const WCHAR *q = p + 2;
+ p = strchrW (q, '&');
+ if (!p && cjk) p = strchrW (q, '\036'); /* Japanese Win16 */
+ }
+ while (p != NULL && p [1] == '&');
+ if (p && (toupperW(p[1]) == toupperW(Key))) return i;
+ }
+ }
+ }
- Flags |= MenuInfo->fFlags & MNF_POPUP ? MF_POPUP : 0;
- Flags |= MenuInfo->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0;
+ Flags |= menu->fFlags & MNF_POPUP ? MF_POPUP : 0;
+ Flags |= menu->fFlags & MNF_SYSDESKMN ? MF_SYSMENU : 0;
MenuChar = SendMessageW(WndOwner, WM_MENUCHAR,
- MAKEWPARAM(Key, Flags), (LPARAM) MenuInfo->Self);
+ MAKEWPARAM(Key, Flags), (LPARAM) hmenu);
if (HIWORD(MenuChar) == MNC_EXECUTE) return LOWORD(MenuChar);
if (HIWORD(MenuChar) == MNC_CLOSE) return (UINT)(-2);
}
if ((lprect == NULL) || (MenuInfo == NULL)) return;
if (MenuInfo->cItems == 0) return;
- TRACE("left=%ld top=%ld right=%ld bottom=%ld\n", lprect->left, lprect->top, lprect->right, lprect->bottom);
+ TRACE("lprect %p %s\n", lprect, wine_dbgstr_rect( lprect));
MenuInfo->cxMenu = lprect->right - lprect->left;
MenuInfo->cyMenu = 0;
maxY = lprect->top + 1;
DeleteDC(hdcMem);
}
-
/***********************************************************************
* MenuDrawMenuItem
*
PWCHAR Text;
BOOL flat_menu = FALSE;
int bkgnd;
- PWND Wnd = ValidateHwnd(hWnd);
+ PWND Wnd = ValidateHwndNoErr(hWnd);
if (!Wnd)
return;
SetBkColor( hdc, GetSysColor( bkgnd ) );
}
+ TRACE("rect=%s\n", wine_dbgstr_rect( &lpitem->Rect));
rect = lpitem->Rect;
MENU_AdjustMenuItemRect(MenuInfo, &rect);
DT_LEFT | DT_VCENTER | DT_SINGLELINE;
if((MenuInfo->dwStyle & MNS_CHECKORBMP))
- rect.left += max(0, MenuInfo->cxTextAlign - GetSystemMetrics(SM_CXMENUCHECK));
+ rect.left += max(0, (int)(MenuInfo->cxTextAlign - GetSystemMetrics(SM_CXMENUCHECK)));
else
rect.left += MenuInfo->cxTextAlign;
DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT);
/* draw menu items */
+ //TRACE("hmenu %p Style %08x\n", hmenu, menu->dwStyle);
if (MenuGetRosMenuInfo(&MenuInfo, hmenu) && MenuInfo.cItems)
{
UINT u;
return DrawMenuBarTemp(hwnd, hDC, lprect, hMenu, NULL);
}
+/***********************************************************************
+ * MENU_InitPopup
+ *
+ * Popup menu initialization before WM_ENTERMENULOOP.
+ */
+static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags )
+{
+ MENU *menu;
+ DWORD ex_style = 0;
+ ROSMENUINFO MenuInfo;
+
+ TRACE("owner=%p hmenu=%p\n", hwndOwner, hmenu);
+
+ if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
+
+ /* store the owner for DrawItem */
+ if (!IsWindow( hwndOwner ))
+ {
+ SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+ return FALSE;
+ }
+ MenuGetRosMenuInfo(&MenuInfo, menu->head.h);
+ //menu->hwndOwner = hwndOwner;
+ MenuInfo.spwndNotify = ValidateHwndNoErr( hwndOwner );
+
+ if (flags & TPM_LAYOUTRTL)
+ ex_style = WS_EX_LAYOUTRTL;
+
+ /* NOTE: In Windows, top menu popup is not owned. */
+ //menu->hWnd = CreateWindowExW( ex_style, WC_MENU, NULL,
+ MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL,
+ WS_POPUP, 0, 0, 0, 0,
+ hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
+ (LPVOID)hmenu );
+ MenuSetRosMenuInfo(&MenuInfo);
+ if( !menu->hWnd ) return FALSE;
+ return TRUE;
+}
/***********************************************************************
* MenuShowPopup
POINT pt;
HMONITOR monitor;
MONITORINFO info;
- DWORD ex_style = 0;
TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n",
hwndOwner, hmenu, id, x, y, xanchor, yanchor);
MenuInfo.iItem = NO_SELECTED_ITEM;
}
- /* store the owner for DrawItem */
- if (!IsWindow(hwndOwner))
- {
- SetLastError( ERROR_INVALID_WINDOW_HANDLE );
- return FALSE;
- }
- MenuInfo.spwndNotify = ValidateHwndNoErr(hwndOwner);
+ //menu->dwArrowsOn = 0;
+ MenuInfo.dwArrowsOn = 0;
MenuSetRosMenuInfo(&MenuInfo);
-
MenuPopupMenuCalcSize(&MenuInfo, hwndOwner);
/* adjust popup menu pos so that it fits within the desktop */
GetMonitorInfoW( monitor, &info );
if (flags & TPM_LAYOUTRTL)
- {
- ex_style = WS_EX_LAYOUTRTL;
flags ^= TPM_RIGHTALIGN;
- }
+
if( flags & TPM_RIGHTALIGN ) x -= width;
if( flags & TPM_CENTERALIGN ) x -= width / 2;
}
if( y < info.rcMonitor.top ) y = info.rcMonitor.top;
- /* NOTE: In Windows, top menu popup is not owned. */
- MenuInfo.Wnd = CreateWindowExW( ex_style, WC_MENU, NULL,
- WS_POPUP, x, y, width, height,
- hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
- (LPVOID) MenuInfo.Self);
- if ( !MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo)) return FALSE;
if (!top_popup) {
top_popup = MenuInfo.Wnd;
top_popup_hmenu = hmenu;
}
-
- IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
-
/* Display the window */
- SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0,
- SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
+ SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, x, y, width, height,
+ SWP_SHOWWINDOW | SWP_NOACTIVATE);
UpdateWindow( MenuInfo.Wnd );
+
+ IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
+
return TRUE;
}
PWND pWnd;
PPOPUPMENU pPopupMenu;
- pWnd = ValidateHwnd(Wnd);
+ pWnd = ValidateHwndNoErr(Wnd);
if (pWnd)
{
if (!pWnd->fnid)
}
break;
+#ifdef __REACTOS__
+ case WM_NCDESTROY:
+ NtUserSetWindowFNID(Wnd, FNID_DESTROY);
+ break;
+#endif
+
case WM_SHOWWINDOW:
if (0 != wParam)
{
return res;
}
-
/**********************************************************************
* MENUEX_ParseResource
*
return res;
}
-NTSTATUS WINAPI
-User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength)
-{
- HMENU hmenu = LoadMenuW(User32Instance, L"SYSMENU");
- LRESULT Result = (LRESULT)hmenu;
- MENUINFO menuinfo = {0};
- MENUITEMINFOW info = {0};
-
- // removing space for checkboxes from menu
- menuinfo.cbSize = sizeof(menuinfo);
- menuinfo.fMask = MIM_STYLE;
- GetMenuInfo(hmenu, &menuinfo);
- menuinfo.dwStyle |= MNS_CHECKORBMP; // test_menu_bmp_and_string MNS_CHECKORBMP
- SetMenuInfo(hmenu, &menuinfo);
-
- // adding bitmaps to menu items
- info.cbSize = sizeof(info);
- info.fMask |= MIIM_BITMAP;
- info.hbmpItem = HBMMENU_POPUP_MINIMIZE;
- SetMenuItemInfoW(hmenu, SC_MINIMIZE, FALSE, &info);
- info.hbmpItem = HBMMENU_POPUP_RESTORE;
- SetMenuItemInfoW(hmenu, SC_RESTORE, FALSE, &info);
- info.hbmpItem = HBMMENU_POPUP_MAXIMIZE;
- SetMenuItemInfoW(hmenu, SC_MAXIMIZE, FALSE, &info);
- info.hbmpItem = HBMMENU_POPUP_CLOSE;
- SetMenuItemInfoW(hmenu, SC_CLOSE, FALSE, &info);
-
- return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
-}
-
-
-BOOL
-MenuInit(VOID)
-{
- NONCLIENTMETRICSW ncm;
-
- /* get the menu font */
- if(!hMenuFont || !hMenuFontBold)
- {
- ncm.cbSize = sizeof(ncm);
- if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
- {
- ERR("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n");
- return FALSE;
- }
-
- hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont);
- if(hMenuFont == NULL)
- {
- ERR("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
- return FALSE;
- }
-
- ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
- hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont);
- if(hMenuFontBold == NULL)
- {
- ERR("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
- DeleteObject(hMenuFont);
- hMenuFont = NULL;
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-VOID
-MenuCleanup(VOID)
-{
- if (hMenuFont)
- {
- DeleteObject(hMenuFont);
- hMenuFont = NULL;
- }
-
- if (hMenuFontBold)
- {
- DeleteObject(hMenuFontBold);
- hMenuFontBold = NULL;
- }
-}
/***********************************************************************
* DrawMenuBarTemp (USER32.@)
return MenuInfo.cyMenu;
}
-#if 0
-static BOOL MENU_InitPopup( HWND hwndOwner, HMENU hmenu, UINT flags )
-{
- POPUPMENU *menu;
- DWORD ex_style = 0;
-
- TRACE("owner=%p hmenu=%p\n", hwndOwner, hmenu);
- if (!(menu = MENU_GetMenu( hmenu ))) return FALSE;
-
- /* store the owner for DrawItem */
- if (!IsWindow( hwndOwner ))
- {
- SetLastError( ERROR_INVALID_WINDOW_HANDLE );
- return FALSE;
- }
- menu->hwndOwner = hwndOwner;
-
- if (flags & TPM_LAYOUTRTL)
- ex_style = WS_EX_LAYOUTRTL;
- /* NOTE: In Windows, top menu popup is not owned. */
- menu->hWnd = CreateWindowExW( ex_style, (LPCWSTR)POPUPMENU_CLASS_ATOM, NULL,
- WS_POPUP, 0, 0, 0, 0,
- hwndOwner, 0, (HINSTANCE)GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE),
- (LPVOID)hmenu );
- if( !menu->hWnd ) return FALSE;
- return TRUE;
-}
-#endif
/***********************************************************************
* MenuShowSubPopup
*
static HMENU FASTCALL
MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Flags)
{
- extern void FASTCALL NcGetSysPopupPos(HWND Wnd, RECT *Rect);
RECT Rect;
ROSMENUITEMINFO ItemInfo;
ROSMENUINFO SubMenuInfo;
/* use default alignment for submenus */
Flags &= ~(TPM_CENTERALIGN | TPM_RIGHTALIGN | TPM_VCENTERALIGN | TPM_BOTTOMALIGN);
- //MENU_InitPopup( WndOwner, ItemInfo.hSubMenu, Flags );
+ MENU_InitPopup( WndOwner, ItemInfo.hSubMenu, Flags );
MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->iItem, Flags,
Rect.left, Rect.top, Rect.right, Rect.bottom );
*/
void MENU_EndMenu( HWND hwnd )
{
- ROSMENUINFO MenuInfo;
- BOOL Ret = FALSE;
- if (top_popup_hmenu)
- Ret = MenuGetRosMenuInfo(&MenuInfo, top_popup_hmenu);
- if (Ret && hwnd == (MenuInfo.spwndNotify ? MenuInfo.spwndNotify->head.h : NULL)) EndMenu();
+ MENU *menu;
+ menu = top_popup_hmenu ? MENU_GetMenu( top_popup_hmenu ) : NULL;
+ if (menu && ( hwnd == menu->hWnd || hwnd == (menu->spwndNotify ? menu->spwndNotify->head.h : NULL)) )
+ EndMenu();
}
/***********************************************************************
* Return TRUE if we can go on with menu tracking.
*/
static BOOL FASTCALL
-MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags)
+MENU_ButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags)
{
int Index;
ROSMENUINFO MenuInfo;
*
*/
static INT FASTCALL
-MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
+MENU_ButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags)
{
INT Id;
ROSMENUINFO MenuInfo;
* Walks menu chain trying to find a menu pt maps to.
*/
static HMENU FASTCALL
-MenuPtMenu(HMENU Menu, POINT Pt)
+MENU_PtMenu(HMENU hMenu, POINT pt)
{
- extern LRESULT DefWndNCHitTest(HWND hWnd, POINT Point);
- ROSMENUINFO MenuInfo;
- ROSMENUITEMINFO ItemInfo;
- HMENU Ret = NULL;
- INT Ht;
+ MENU *menu;
+ PITEM pItem;
+ HMENU ret = NULL;
- if (! MenuGetRosMenuInfo(&MenuInfo, Menu))
- {
- return NULL;
- }
+ menu = MENU_GetMenu( hMenu );
+ if (!menu) return NULL;
/* try subpopup first (if any) */
- if (NO_SELECTED_ITEM != MenuInfo.iItem)
- {
- MenuInitRosMenuItemInfo(&ItemInfo);
- if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo) &&
- 0 != (ItemInfo.hSubMenu) &&
- 0 != (ItemInfo.fState & MF_MOUSESELECT))
- {
- Ret = MenuPtMenu(ItemInfo.hSubMenu, Pt);
- if (NULL != Ret)
- {
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return Ret;
- }
- }
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- }
+ if (menu->iItem != NO_SELECTED_ITEM)
+ {
+ pItem = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
+ if ( pItem ) pItem = &pItem[menu->iItem];
+ if ( pItem && pItem->spSubMenu && pItem->fState & MF_MOUSESELECT)
+ {
+ PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu);
+ ret = MENU_PtMenu( UserHMGetHandle(pSubMenu), pt);
+ }
+ }
/* check the current window (avoiding WM_HITTEST) */
- Ht = DefWndNCHitTest(MenuInfo.Wnd, Pt);
- if (0 != (MenuInfo.fFlags & MNF_POPUP))
- {
- if (HTNOWHERE != Ht && HTERROR != Ht)
- {
- Ret = Menu;
- }
- }
- else if (HTSYSMENU == Ht)
- {
- Ret = NtUserGetSystemMenu(MenuInfo.Wnd, FALSE);
- }
- else if (HTMENU == Ht)
- {
- Ret = GetMenu(MenuInfo.Wnd);
- }
-
- return Ret;
+ if (!ret)
+ {
+ INT ht = DefWndNCHitTest(menu->hWnd, pt);
+ if ( menu->fFlags & MNF_POPUP )
+ {
+ if (ht != HTNOWHERE && ht != HTERROR) ret = hMenu;
+ }
+ else if (ht == HTSYSMENU)
+ ret = NtUserGetSystemMenu(menu->hWnd, FALSE);
+ else if (ht == HTMENU)
+ ret = GetMenu( menu->hWnd );
+ }
+ return ret;
}
/***********************************************************************
*
* Return the handle of the selected sub-popup menu (if any).
*/
-static HMENU FASTCALL
-MenuGetSubPopup(HMENU Menu)
+static
+HMENU MENU_GetSubPopup( HMENU hmenu )
{
- ROSMENUINFO MenuInfo;
- ROSMENUITEMINFO ItemInfo;
+ MENU *menu;
+ ITEM *item;
- if (! MenuGetRosMenuInfo(&MenuInfo, Menu)
- || NO_SELECTED_ITEM == MenuInfo.iItem)
- {
- return NULL;
- }
+ menu = MENU_GetMenu( hmenu );
- MenuInitRosMenuItemInfo(&ItemInfo);
- if (! MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.iItem, &ItemInfo))
- {
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return NULL;
- }
- if (0 != (ItemInfo.hSubMenu) && 0 != (ItemInfo.fState & MF_MOUSESELECT))
+ if ((!menu) || (menu->iItem == NO_SELECTED_ITEM)) return 0;
+
+ //item = &menu->rgItems[menu->iItem];
+ item = menu->rgItems ? DesktopPtrToUser(menu->rgItems) : NULL;
+ if (item) item = &item[menu->iItem];
+ if (item && (item->spSubMenu) && (item->fState & MF_MOUSESELECT))
{
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return ItemInfo.hSubMenu;
+ PMENU pSubMenu = DesktopPtrToUser(item->spSubMenu);
+ return UserHMGetHandle(pSubMenu);
}
-
- MenuCleanupRosMenuItemInfo(&ItemInfo);
- return NULL;
+ return 0;
}
/***********************************************************************
while (MenuTmp != Mt->CurrentMenu)
{
MenuPrev = MenuTmp;
- MenuTmp = MenuGetSubPopup(MenuPrev);
+ MenuTmp = MENU_GetSubPopup(MenuPrev);
}
if (MenuGetRosMenuInfo(&MenuInfo, MenuPrev))
MenuPrev = MenuTmp = Mt->TopMenu;
- if (! MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu))
- {
- return;
- }
-
/* Try to move 1 column left (if possible) */
- if ( (PrevCol = MenuGetStartOfPrevColumn(&MenuInfo)) != NO_SELECTED_ITEM)
+ if ( (PrevCol = MENU_GetStartOfPrevColumn(Mt->CurrentMenu)) != NO_SELECTED_ITEM)
{
if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu))
{
while (MenuTmp != Mt->CurrentMenu)
{
MenuPrev = MenuTmp;
- MenuTmp = MenuGetSubPopup(MenuPrev);
+ MenuTmp = MENU_GetSubPopup(MenuPrev);
}
if (! MenuGetRosMenuInfo(&PrevMenuInfo, MenuPrev))
if (hmenutmp != Mt->CurrentMenu) return;
}
- if (! MenuGetRosMenuInfo(&CurrentMenuInfo, Mt->CurrentMenu))
- {
- return;
- }
-
/* Check to see if there's another column */
- if ( (NextCol = MenuGetStartOfNextColumn(&CurrentMenuInfo)) != NO_SELECTED_ITEM)
+ if ( (NextCol = MENU_GetStartOfNextColumn(Mt->CurrentMenu)) != NO_SELECTED_ITEM)
{
TRACE("Going to %d.\n", NextCol);
if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu))
MSG msg;
ROSMENUINFO MenuInfo;
ROSMENUITEMINFO ItemInfo;
+ PMENU menu;
BOOL fRemove;
INT executedMenuId = -1;
MTRACKER mt;
if (!IsMenu(hmenu))
{
- WARN("Invalid menu handle %p\n", hmenu);
- SetLastError( ERROR_INVALID_MENU_HANDLE );
+ WARN("Invalid menu handle %p\n", hmenu); // Error already set in IsMenu.
return FALSE;
}
- fEndMenu = FALSE;
if (! MenuGetRosMenuInfo(&MenuInfo, hmenu))
{
return FALSE;
if (wFlags & TPM_BUTTONDOWN)
{
/* Get the result in order to start the tracking or not */
- fRemove = MenuButtonDown( &mt, hmenu, wFlags );
+ fRemove = MENU_ButtonDown( &mt, hmenu, wFlags );
fEndMenu = !fRemove;
}
NtUserxSetGUIThreadHandle(MSQ_STATE_MENUOWNER, capture_win); // 1
SetCapture(capture_win); // 2
- while (! fEndMenu)
+ while (!fEndMenu)
{
BOOL ErrorExit = FALSE;
- PMENU menu = ValidateHandle(mt.CurrentMenu, TYPE_MENU);
+ menu = MENU_GetMenu( mt.CurrentMenu );
if (!menu) /* sometimes happens if I do a window manager close */
break;
else
{
/* ReactOS Check */
- if (!ValidateHwnd(mt.OwnerWnd) || !ValidateHwnd(MenuInfo.Wnd))
+ if (!ValidateHwndNoErr(mt.OwnerWnd) || !ValidateHwndNoErr(MenuInfo.Wnd))
{
ErrorExit = TRUE; // Do not wait on dead windows, now test_capture_4 works.
break;
mt.Pt.y = (short)HIWORD(msg.lParam);
/* Find a menu for this mouse event */
- hmenu = MenuPtMenu(mt.TopMenu, mt.Pt);
+ hmenu = MENU_PtMenu(mt.TopMenu, mt.Pt);
switch(msg.message)
{
/* no WM_NC... messages in captured state */
case WM_RBUTTONDBLCLK:
- ERR("WM_RBUTTONDBLCLK\n");
case WM_RBUTTONDOWN:
if (!(wFlags & TPM_RIGHTBUTTON)) break;
/* fall through */
case WM_LBUTTONDOWN:
/* If the message belongs to the menu, removes it from the queue */
/* Else, end menu tracking */
- fRemove = MenuButtonDown(&mt, hmenu, wFlags);
+ fRemove = MENU_ButtonDown(&mt, hmenu, wFlags);
fEndMenu = !fRemove;
break;
/* Check if a menu was selected by the mouse */
if (hmenu)
{
- executedMenuId = MenuButtonUp( &mt, hmenu, wFlags);
+ executedMenuId = MENU_ButtonUp( &mt, hmenu, wFlags);
TRACE("executedMenuId %d\n", executedMenuId);
/* End the loop if executedMenuId is an item ID */
case VK_END:
if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu))
{
- MenuSelectItem(mt.OwnerWnd, &MenuInfo,
- NO_SELECTED_ITEM, FALSE, 0 );
- MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
- VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
+ MenuSelectItem(mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, 0 );
+ MenuMoveSelection(mt.OwnerWnd, &MenuInfo, VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV);
}
break;
mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags);
}
else /* otherwise try to move selection */
- MenuMoveSelection(mt.OwnerWnd, &MenuInfo,
- (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT );
+ MenuMoveSelection(mt.OwnerWnd, &MenuInfo, (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT );
}
break;
/* We will find a better way real soon... */
if (msg.wParam < 32) break;
- pos = MenuFindItemByKey(mt.OwnerWnd, &MenuInfo,
- LOWORD(msg.wParam), FALSE);
+ pos = MENU_FindItemByKey(mt.OwnerWnd, mt.CurrentMenu, LOWORD(msg.wParam), FALSE);
if (pos == (UINT)-2) fEndMenu = TRUE;
else if (pos == (UINT)-1) MessageBeep(0);
else
{
- MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos,
- TRUE, 0);
+ MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos, TRUE, 0);
executedMenuId = MenuExecFocusedItem(&mt, &MenuInfo, wFlags);
fEndMenu = (executedMenuId != -2);
}
* It also enables menus to be displayed in more than one window,
* but there are some bugs left that need to be fixed in this case.
*/
- if (MenuGetRosMenuInfo(&MenuInfo, hMenu))
+ if (!bPopup && (MenuGetRosMenuInfo(&MenuInfo, hMenu)))
{
MenuInfo.Wnd = hWnd;
MenuSetRosMenuInfo(&MenuInfo);
}
+ //if (!bPopup) menu->hWnd = hWnd;
+ if (!top_popup)
+ {
+ top_popup = MenuInfo.Wnd;//menu->hWnd;
+ top_popup_hmenu = hMenu;
+ }
+
+ fEndMenu = FALSE;
/* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */
if (!(wFlags & TPM_NONOTIFY))
CHILDID_SELF, 0);
return TRUE;
}
+
/***********************************************************************
* MenuExitTracking
*/
}
}
-
/***********************************************************************
* MenuTrackKbdMenuBar
*
MenuInitTracking( hwnd, hTrackMenu, FALSE, wFlags );
+ /* fetch the window menu again, it may have changed */
+ hTrackMenu = (wParam & HTSYSMENU) ? get_win_sys_menu( hwnd ) : GetMenu( hwnd );
+
if (! MenuGetRosMenuInfo(&MenuInfo, hTrackMenu))
{
goto track_menu;
if( wChar && wChar != ' ' )
{
- uItem = MenuFindItemByKey( hwnd, &MenuInfo, wChar, (wParam & HTSYSMENU) );
+ uItem = MENU_FindItemByKey( hwnd, hTrackMenu, wChar, (wParam & HTSYSMENU) );
if ( uItem >= (UINT)(-2) )
{
if( uItem == (UINT)(-1) ) MessageBeep(0);
/**********************************************************************
* TrackPopupMenuEx (USER32.@)
*/
-BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y,
- HWND Wnd, LPTPMPARAMS Tpm)
+BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, int x, int y,
+ HWND hWnd, LPTPMPARAMS lpTpm)
{
BOOL ret = FALSE;
- ROSMENUINFO MenuInfo;
+ MENU *menu;
- if (!IsMenu(Menu))
+ TRACE("hmenu %p flags %04x (%d,%d) hwnd %p lpTpm %p rect %s\n",
+ hMenu, wFlags, x, y, hWnd, lpTpm,
+ lpTpm ? wine_dbgstr_rect( &lpTpm->rcExclude) : "-" );
+
+ /* Parameter check */
+ /* FIXME: this check is performed several times, here and in the called
+ functions. That could be optimized */
+ if (!(menu = MENU_GetMenu( hMenu )))
{
SetLastError( ERROR_INVALID_MENU_HANDLE );
return FALSE;
}
- /* ReactOS Check */
- if (!ValidateHwnd(Wnd))
- {
- /* invalid window see wine menu.c test_menu_trackpopupmenu line 3146 */
- return FALSE;
- }
-
- MenuGetRosMenuInfo(&MenuInfo, Menu);
- if (IsWindow(MenuInfo.Wnd))
+ if (IsWindow(menu->hWnd))
{
SetLastError( ERROR_POPUP_ALREADY_ACTIVE );
return FALSE;
}
- MenuInitTracking(Wnd, Menu, TRUE, Flags);
+ if (MENU_InitPopup( hWnd, hMenu, wFlags ))
+ {
+ MenuInitTracking(hWnd, hMenu, TRUE, wFlags);
+
+ /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
+ if (!(wFlags & TPM_NONOTIFY))
+ SendMessageW(hWnd, WM_INITMENUPOPUP, (WPARAM) hMenu, 0);
- /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */
- if (!(Flags & TPM_NONOTIFY))
- SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0);
+ if (MenuShowPopup(hWnd, hMenu, 0, wFlags, x, y, 0, 0 ))
+ ret = MenuTrackMenu(hMenu, wFlags | TPM_POPUPMENU, 0, 0, hWnd,
+ lpTpm ? &lpTpm->rcExclude : NULL);
+ MenuExitTracking(hWnd, TRUE);
- if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 ))
- ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd,
- Tpm ? &Tpm->rcExclude : NULL);
- MenuExitTracking(Wnd, TRUE);
+ if (menu->hWnd)
+ {
+ ROSMENUINFO MenuInfo;
+ if (IsWindow( menu->hWnd )) // wine hack around this with their destroy function.
+ DestroyWindow( menu->hWnd ); // Fix wrong error return.
+ //menu->hWnd = 0;
+ MenuGetRosMenuInfo(&MenuInfo, menu->head.h);
+ MenuInfo.Wnd = 0;
+ MenuSetRosMenuInfo(&MenuInfo);
+
+ if (!(wFlags & TPM_NONOTIFY))
+ SendMessageW( hWnd, WM_UNINITMENUPOPUP, (WPARAM)hMenu,
+ MAKELPARAM(0, IS_SYSTEM_MENU(menu)) );
+ }
+ }
return ret;
}
return TrackPopupMenuEx( Menu, Flags, x, y, Wnd, NULL);
}
-/*
- * From MSDN:
- * The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined
- * with one another. Also MFT_OWNERDRAW. Set fMask to MIIM_TYPE to use fType.
- *
- * Windows 2K/XP: fType is used only if fMask has a value of MIIM_FTYPE.
- *
- * MIIM_TYPE: Retrieves or sets the fType and dwTypeData members. Windows
- * 2K/XP: MIIM_TYPE is replaced by MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING.
- * MFT_STRING is replaced by MIIM_STRING.
- * (So, I guess we should use MIIM_STRING only for strings?)
- *
- * MIIM_FTYPE: Windows 2K/Windows XP: Retrieves or sets the fType member.
- *
- * Based on wine, SetMenuItemInfo_common:
- * 1) set MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP any one with MIIM_TYPE,
- * it will result in a error.
- * 2) set menu mask to MIIM_FTYPE and MFT_BITMAP ftype it will result in a error.
- * These conditions are addressed in Win32k IntSetMenuItemInfo.
+/**********************************************************************
+ * MENU_mnu2mnuii
*
+ * Uses flags, id and text ptr, passed by InsertMenu() and
+ * ModifyMenu() to setup a MenuItemInfo structure.
*/
-static
-BOOL
-FASTCALL
-MenuSetItemData(
- LPMENUITEMINFOW mii,
- UINT Flags,
- UINT_PTR IDNewItem,
- LPCWSTR NewItem,
- BOOL Unicode)
+static void MENU_mnu2mnuii( UINT flags, UINT_PTR id, LPCWSTR str, LPMENUITEMINFOW pmii, BOOL Unicode)
{
-/*
- * Let us assume MIIM_FTYPE is set and building a new menu item structure.
- */
- if(Flags & MF_BITMAP)
- {
- mii->fMask |= MIIM_BITMAP; /* Use the new way of seting hbmpItem.*/
- mii->hbmpItem = (HBITMAP) NewItem;
-
- if (Flags & MF_HELP)
- {
- /* increase ident */
- mii->fType |= MF_HELP;
- }
- }
- else if(Flags & MF_OWNERDRAW)
- {
- mii->fType |= MFT_OWNERDRAW;
- mii->fMask |= MIIM_DATA;
- mii->dwItemData = (DWORD_PTR) NewItem;
- }
- else if (Flags & MF_SEPARATOR)
- {
- mii->fType |= MFT_SEPARATOR;
- if (!(Flags & (MF_GRAYED|MF_DISABLED)))
- Flags |= MF_GRAYED|MF_DISABLED;
- }
- else /* Default action MF_STRING. */
- {
- /* Item beginning with a backspace is a help item */
- if (NewItem != NULL)
- {
- if (Unicode)
- {
- if (*NewItem == '\b')
- {
- mii->fType |= MF_HELP;
- NewItem++;
- }
- }
- else
- {
- LPCSTR NewItemA = (LPCSTR) NewItem;
- if (*NewItemA == '\b')
- {
- mii->fType |= MF_HELP;
- NewItemA++;
- NewItem = (LPCWSTR) NewItemA;
- }
- }
-
- if (Flags & MF_HELP)
- mii->fType |= MF_HELP;
- mii->fMask |= MIIM_STRING;
- mii->fType |= MFT_STRING; /* Zero */
- mii->dwTypeData = (LPWSTR)NewItem;
- if (Unicode)
- mii->cch = (NULL == NewItem ? 0 : strlenW(NewItem));
- else
- mii->cch = (NULL == NewItem ? 0 : strlen((LPCSTR)NewItem));
- }
- else
- {
- mii->fType |= MFT_SEPARATOR;
- if (!(Flags & (MF_GRAYED|MF_DISABLED)))
- Flags |= MF_GRAYED|MF_DISABLED;
- }
- }
-
- if(Flags & MF_RIGHTJUSTIFY) /* Same as MF_HELP */
- {
- mii->fType |= MFT_RIGHTJUSTIFY;
- }
-
- if(Flags & MF_MENUBREAK)
- {
- mii->fType |= MFT_MENUBREAK;
- }
- else if(Flags & MF_MENUBARBREAK)
- {
- mii->fType |= MFT_MENUBARBREAK;
- }
-
- if(Flags & MF_GRAYED || Flags & MF_DISABLED)
- {
- if (Flags & MF_GRAYED)
- mii->fState |= MF_GRAYED;
-
- if (Flags & MF_DISABLED)
- mii->fState |= MF_DISABLED;
-
- mii->fMask |= MIIM_STATE;
- }
- else if (Flags & MF_HILITE)
- {
- mii->fState |= MF_HILITE;
- mii->fMask |= MIIM_STATE;
- }
- else /* default state */
- {
- mii->fState |= MFS_ENABLED;
- mii->fMask |= MIIM_STATE;
- }
-
- if(Flags & MF_POPUP && IsMenu((HMENU)IDNewItem))
- {
- mii->fMask |= MIIM_SUBMENU;
- mii->hSubMenu = (HMENU)IDNewItem;
- }
- mii->fMask |= MIIM_ID;
- mii->wID = (UINT)IDNewItem;
- return TRUE;
-}
-
-NTSTATUS WINAPI
-User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength)
-{
- PLOADMENU_CALLBACK_ARGUMENTS Common;
- LRESULT Result;
-
- Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments;
-
- Result = (LRESULT)LoadMenuW( Common->hModule,
- IS_INTRESOURCE(Common->MenuName[0]) ?
- MAKEINTRESOURCE(Common->MenuName[0]) :
- (LPCWSTR)&Common->MenuName);
-
- return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
+ RtlZeroMemory( pmii, sizeof( MENUITEMINFOW));
+ pmii->cbSize = sizeof( MENUITEMINFOW);
+ pmii->fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE;
+ /* setting bitmap clears text and vice versa */
+ if( IS_STRING_ITEM(flags)) {
+ pmii->fMask |= MIIM_STRING | MIIM_BITMAP;
+ if( !str)
+ flags |= MF_SEPARATOR;
+ /* Item beginning with a backspace is a help item */
+ /* FIXME: wrong place, this is only true in win16 */
+ else
+ {
+ if (Unicode)
+ {
+ if (*str == '\b')
+ {
+ flags |= MF_HELP;
+ str++;
+ }
+ }
+ else
+ {
+ LPCSTR NewItemA = (LPCSTR) str;
+ if (*NewItemA == '\b')
+ {
+ flags |= MF_HELP;
+ NewItemA++;
+ str = (LPCWSTR) NewItemA;
+ }
+ TRACE("A cch %d\n",strlen(NewItemA));
+ }
+ }
+ pmii->dwTypeData = (LPWSTR)str;
+ } else if( flags & MFT_BITMAP){
+ pmii->fMask |= MIIM_BITMAP | MIIM_STRING;
+ pmii->hbmpItem = (HBITMAP)str;
+ }
+ if( flags & MF_OWNERDRAW){
+ pmii->fMask |= MIIM_DATA;
+ pmii->dwItemData = (ULONG_PTR) str;
+ }
+ if( flags & MF_POPUP && MENU_GetMenu((HMENU)id)) {
+ pmii->fMask |= MIIM_SUBMENU;
+ pmii->hSubMenu = (HMENU)id;
+ }
+ if( flags & MF_SEPARATOR) flags |= MF_GRAYED | MF_DISABLED;
+ pmii->fState = flags & MENUITEMINFO_STATE_MASK & ~MFS_DEFAULT;
+ pmii->fType = flags & MENUITEMINFO_TYPE_MASK;
+ pmii->wID = (UINT)id;
}
/**********************************************************************
return TRUE;
}
+BOOL
+MenuInit(VOID)
+{
+ NONCLIENTMETRICSW ncm;
+
+ /* get the menu font */
+ if(!hMenuFont || !hMenuFontBold)
+ {
+ ncm.cbSize = sizeof(ncm);
+ if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
+ {
+ ERR("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n");
+ return FALSE;
+ }
+
+ hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont);
+ if(hMenuFont == NULL)
+ {
+ ERR("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n");
+ return FALSE;
+ }
+
+ ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000);
+ hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont);
+ if(hMenuFontBold == NULL)
+ {
+ ERR("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n");
+ DeleteObject(hMenuFont);
+ hMenuFont = NULL;
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+VOID
+MenuCleanup(VOID)
+{
+ if (hMenuFont)
+ {
+ DeleteObject(hMenuFont);
+ hMenuFont = NULL;
+ }
+
+ if (hMenuFontBold)
+ {
+ DeleteObject(hMenuFontBold);
+ hMenuFontBold = NULL;
+ }
+}
+
+NTSTATUS WINAPI
+User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength)
+{
+ HMENU hmenu = LoadMenuW(User32Instance, L"SYSMENU");
+ LRESULT Result = (LRESULT)hmenu;
+ MENUINFO menuinfo = {0};
+ MENUITEMINFOW info = {0};
+
+ // removing space for checkboxes from menu
+ menuinfo.cbSize = sizeof(menuinfo);
+ menuinfo.fMask = MIM_STYLE;
+ GetMenuInfo(hmenu, &menuinfo);
+ menuinfo.dwStyle |= MNS_CHECKORBMP; // test_menu_bmp_and_string MNS_CHECKORBMP
+ SetMenuInfo(hmenu, &menuinfo);
+
+ // adding bitmaps to menu items
+ info.cbSize = sizeof(info);
+ info.fMask |= MIIM_BITMAP;
+ info.hbmpItem = HBMMENU_POPUP_MINIMIZE;
+ SetMenuItemInfoW(hmenu, SC_MINIMIZE, FALSE, &info);
+ info.hbmpItem = HBMMENU_POPUP_RESTORE;
+ SetMenuItemInfoW(hmenu, SC_RESTORE, FALSE, &info);
+ info.hbmpItem = HBMMENU_POPUP_MAXIMIZE;
+ SetMenuItemInfoW(hmenu, SC_MAXIMIZE, FALSE, &info);
+ info.hbmpItem = HBMMENU_POPUP_CLOSE;
+ SetMenuItemInfoW(hmenu, SC_CLOSE, FALSE, &info);
+
+ return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
+}
+
+NTSTATUS WINAPI
+User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength)
+{
+ PLOADMENU_CALLBACK_ARGUMENTS Common;
+ LRESULT Result;
+
+ Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments;
+
+ Result = (LRESULT)LoadMenuW( Common->hModule,
+ IS_INTRESOURCE(Common->MenuName[0]) ?
+ MAKEINTRESOURCE(Common->MenuName[0]) :
+ (LPCWSTR)&Common->MenuName);
+
+ return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
+}
+
/* FUNCTIONS *****************************************************************/
UINT_PTR uIDNewItem,
LPCSTR lpNewItem)
{
- return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, lpNewItem));
+ MENUITEMINFOW mii;
+ UNICODE_STRING UnicodeString;
+ BOOL res;
+
+ RtlInitUnicodeString(&UnicodeString, 0);
+
+ MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE);
+
+ /* copy the text string, it wll be one or the other */
+ if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+ {
+ if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData))
+ {
+ SetLastError (ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ mii.dwTypeData = UnicodeString.Buffer;
+ mii.cch = UnicodeString.Length / sizeof(WCHAR);
+ }
+ else
+ {
+ TRACE("AMA Handle bitmaps\n");
+ }
+ ////// Answer a question, why a -1? To hunt for the end of the item list. Get it, to Append?
+ res = NtUserThunkedMenuItemInfo(hMenu, -1, TRUE, TRUE, &mii, &UnicodeString);
+ if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
+ return res;
}
/*
UINT_PTR uIDNewItem,
LPCWSTR lpNewItem)
{
- return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, lpNewItem));
+ MENUITEMINFOW mii;
+ UNICODE_STRING MenuText;
+ BOOL res;
+
+ RtlInitUnicodeString(&MenuText, 0);
+
+ MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE);
+
+ /* copy the text string, it wll be one or the other */
+ if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+ {
+ RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData);
+ mii.dwTypeData = MenuText.Buffer;
+ mii.cch = MenuText.Length / sizeof(WCHAR);
+ }
+ res = NtUserThunkedMenuItemInfo(hMenu, -1, TRUE, TRUE, &mii, &MenuText);
+ return res;
}
/*
return NtUserCheckMenuItem(hmenu, uIDCheckItem, uCheck);
}
-
/*
* @implemented
*/
/* don't end up with an orphaned menu */
PostMessageW( top_popup, WM_CANCELMODE, 0, 0);
}
- return TRUE;
+ return fEndMenu;
}
BOOL WINAPI HiliteMenuItem( HWND hWnd, HMENU hMenu, UINT wItemID,
return UlongToHandle(Wnd->IDMenu);
}
-
/*
* @implemented
*/
GetMenuItemID(HMENU hMenu,
int nPos)
{
- PMENU pMenu;
- PITEM pItem;
- INT i = 0;
-
- if (!(pMenu = ValidateHandle(hMenu, TYPE_MENU)))
- return -1;
-
- pItem = pMenu->rgItems ? DesktopPtrToUser(pMenu->rgItems) : NULL;
- if ( nPos >= 0 )
- {
- //pItem = &menu->rgItems[nPos]; or pItem[nPos]; after dptu.
- while(pItem) // Do this for now.
- {
- if (i < (INT)pMenu->cItems)
- {
- if ( nPos == i && !pItem->spSubMenu) return pItem->wID;
- }
- pItem = pItem->Next ? DesktopPtrToUser(pItem->Next) : NULL;
- i++;
- }
- }
- return -1;
+ ITEM * lpmi;
+ if (!(lpmi = MENU_FindItem(&hMenu,(UINT*)&nPos,MF_BYPOSITION))) return -1;
+ if (lpmi->spSubMenu) return -1;
+ return lpmi->wID;
}
/*
UINT uFlags)
{
PITEM pItem;
+ UINT Type = 0;
TRACE("(menu=%p, id=%04x, flags=%04x);\n", hMenu, uId, uFlags);
if (!(pItem = MENU_FindItem( &hMenu, &uId, uFlags ))) return -1;
+ if (!pItem->Xlpstr && pItem->hbmp) Type = MFT_BITMAP;
+
if (pItem->spSubMenu)
{
PMENU pSubMenu = DesktopPtrToUser(pItem->spSubMenu);
HMENU hsubmenu = UserHMGetHandle(pSubMenu);
if (!IsMenu(hsubmenu)) return (UINT)-1;
- else return (pSubMenu->cItems << 8) | ((pItem->fState|pItem->fType) & 0xff);
+ else return (pSubMenu->cItems << 8) | ((pItem->fState|pItem->fType|Type) & 0xff);
}
else
- return (pItem->fType | pItem->fState);
+ return (pItem->fType | pItem->fState | Type);
}
/*
int nMaxCount,
UINT uFlag)
{
-/* MENUITEMINFOA mii;
- memset( &mii, 0, sizeof(mii) );
- mii.dwTypeData = lpString;
- mii.fMask = MIIM_STRING;
- mii.cbSize = sizeof(MENUITEMINFOA);
- mii.cch = nMaxCount;
-
- if(!(GetMenuItemInfoA( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&mii)))
- return 0;
- else
- return mii.cch;
-*/
ITEM *item;
LPWSTR text;
////// wine Code, seems to be faster.
if (!lpString || !nMaxCount) return WideCharToMultiByte( CP_ACP, 0, text, -1, NULL, 0, NULL, NULL );
if (!WideCharToMultiByte( CP_ACP, 0, text, -1, lpString, nMaxCount, NULL, NULL ))
lpString[nMaxCount-1] = 0;
- ERR("returning %s\n", lpString);
+ TRACE("A returning %s\n", lpString);
return strlen(lpString);
}
int nMaxCount,
UINT uFlag)
{
-/* MENUITEMINFOW miiW;
- memset( &miiW, 0, sizeof(miiW) );
- miiW.dwTypeData = lpString;
- miiW.fMask = MIIM_STRING | MIIM_FTYPE;
- miiW.fType = MFT_STRING;
- miiW.cbSize = sizeof(MENUITEMINFOW);
- miiW.cch = nMaxCount;
-
- if(!(GetMenuItemInfoW( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&miiW)))
- return 0;
- else
- return miiW.cch;
-*/
ITEM *item;
LPWSTR text;
return 0;
}
lstrcpynW( lpString, text, nMaxCount );
- ERR("returning %S\n", lpString);
+ TRACE("W returning %S\n", lpString);
return strlenW(lpString);
}
UINT_PTR uIDNewItem,
LPCSTR lpNewItem)
{
- MENUITEMINFOA mii;
- memset( &mii, 0, sizeof(mii) );
- mii.cbSize = sizeof(MENUITEMINFOA);
- mii.fMask = MIIM_FTYPE;
-
- MenuSetItemData((LPMENUITEMINFOW) &mii,
- uFlags,
- uIDNewItem,
- (LPCWSTR) lpNewItem,
- FALSE);
-
- return InsertMenuItemA(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
+ MENUITEMINFOW mii;
+ UNICODE_STRING UnicodeString;
+ BOOL res;
+
+ RtlInitUnicodeString(&UnicodeString, 0);
+
+ MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE);
+
+ /* copy the text string, it wll be one or the other */
+ if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+ {
+ if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData))
+ {
+ SetLastError (ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ mii.dwTypeData = UnicodeString.Buffer;
+ mii.cch = UnicodeString.Length / sizeof(WCHAR);
+ }
+ else
+ {
+ TRACE("Handle bitmaps\n");
+ }
+ res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), TRUE, &mii, &UnicodeString);
+ if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
+ return res;
}
/*
}
else
{
- UnicodeString.Buffer = NULL;
+ TRACE("Handle bitmaps\n");
}
res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mii, &UnicodeString);
if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
LPCWSTR lpNewItem)
{
MENUITEMINFOW mii;
- memset( &mii, 0, sizeof(mii) );
- mii.cbSize = sizeof(MENUITEMINFOW);
- mii.fMask = MIIM_FTYPE;
+ UNICODE_STRING MenuText;
+ BOOL res;
- MenuSetItemData( &mii,
- uFlags,
- uIDNewItem,
- lpNewItem,
- TRUE);
+ RtlInitUnicodeString(&MenuText, 0);
- return InsertMenuItemW(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii);
+ MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE);
+
+ /* copy the text string, it wll be one or the other */
+ if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+ {
+ RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData);
+ mii.dwTypeData = MenuText.Buffer;
+ mii.cch = MenuText.Length / sizeof(WCHAR);
+ }
+ res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), TRUE, &mii, &MenuText);
+ return res;
}
/*
BOOL
WINAPI
ModifyMenuA(
- HMENU hMnu,
+ HMENU hMenu,
UINT uPosition,
UINT uFlags,
UINT_PTR uIDNewItem,
LPCSTR lpNewItem)
{
- MENUITEMINFOA mii;
- memset( &mii, 0, sizeof(mii) );
- mii.cbSize = sizeof(MENUITEMINFOA);
- mii.fMask = MIIM_FTYPE;
-
- MenuSetItemData((LPMENUITEMINFOW) &mii,
- uFlags,
- uIDNewItem,
- (LPCWSTR) lpNewItem,
- FALSE);
-
- //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
- // NtUserDestroyMenu( mii.hSubMenu ); /* ModifyMenu() spec */
-
- return SetMenuItemInfoA( hMnu,
- uPosition,
- (BOOL)(MF_BYPOSITION & uFlags),
- &mii);
+ MENUITEMINFOW mii;
+ UNICODE_STRING UnicodeString;
+ BOOL res;
+
+ RtlInitUnicodeString(&UnicodeString, 0);
+
+ MENU_mnu2mnuii( uFlags, uIDNewItem, (LPCWSTR)lpNewItem, &mii, FALSE);
+
+ /* copy the text string, it wll be one or the other */
+ if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+ {
+ if (!RtlCreateUnicodeStringFromAsciiz(&UnicodeString, (LPSTR)mii.dwTypeData))
+ {
+ SetLastError (ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ mii.dwTypeData = UnicodeString.Buffer;
+ mii.cch = UnicodeString.Length / sizeof(WCHAR);
+ }
+ else
+ {
+ TRACE("Handle bitmaps\n");
+ }
+ res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), FALSE, &mii, &UnicodeString);
+ if ( UnicodeString.Buffer ) RtlFreeUnicodeString ( &UnicodeString );
+ return res;
}
/*
BOOL
WINAPI
ModifyMenuW(
- HMENU hMnu,
+ HMENU hMenu,
UINT uPosition,
UINT uFlags,
UINT_PTR uIDNewItem,
LPCWSTR lpNewItem)
{
MENUITEMINFOW mii;
- memset ( &mii, 0, sizeof(mii) );
- mii.cbSize = sizeof(MENUITEMINFOW);
- mii.fMask = MIIM_FTYPE;
-
- /* Init new data for this menu item */
- MenuSetItemData( &mii,
- uFlags,
- uIDNewItem,
- lpNewItem,
- TRUE);
-
- //if (mii.hSubMenu && (uFlags & MF_POPUP) && (mii.hSubMenu != (HMENU)uIDNewItem))
- // NtUserDestroyMenu( mii.hSubMenu ); /* ModifyMenu() spec */
-
- return SetMenuItemInfoW( hMnu,
- uPosition,
- (BOOL)(MF_BYPOSITION & uFlags),
- &mii);
+ UNICODE_STRING MenuText;
+ BOOL res;
+
+ RtlInitUnicodeString(&MenuText, 0);
+
+ MENU_mnu2mnuii( uFlags, uIDNewItem, lpNewItem, &mii, TRUE);
+
+ /* copy the text string, it wll be one or the other */
+ if (lpNewItem && mii.fMask & MIIM_STRING && !mii.hbmpItem && mii.dwTypeData)
+ {
+ RtlInitUnicodeString(&MenuText, (PWSTR)mii.dwTypeData);
+ mii.dwTypeData = MenuText.Buffer;
+ mii.cch = MenuText.Length / sizeof(WCHAR);
+ }
+ else
+ {
+ TRACE("Handle bitmaps\n");
+ }
+ res = NtUserThunkedMenuItemInfo(hMenu, uPosition, (BOOL)(uFlags & MF_BYPOSITION), FALSE, &mii, &MenuText);
+ return res;
}
/*
NULL); // LPTPMPARAMS is null
}
-
-
/*
* @unimplemented
*/
return FALSE;
}
return NtUserMessageCall(hWnd, Msg, wParam, lParam, Result, FNID_MENU, TRUE);
-
}
/*