
user: even more menu item client changes


Thomas Kho

---

 dlls/user/menu.c |  153 +++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 105 insertions(+), 48 deletions(-)

diff --git a/dlls/user/menu.c b/dlls/user/menu.c
index a0b70d1..7cfd934 100644
--- a/dlls/user/menu.c
+++ b/dlls/user/menu.c
@@ -2277,32 +2277,42 @@ static void MENU_MoveSelection( HWND hwn
     POPUPMENU tmpmenu;
     POPUPMENU *menu = &tmpmenu;
     LOCALPOPUPMENU *lpm;
+    MENUITEM *items;
 
     TRACE("hwnd=%p hmenu=%p off=0x%04x\n", hwndOwner, hmenu, offset);
 
-    if ((MENU_GetMenu(hmenu, menu)) || (!menu->items)) return;
+    if ((MENU_GetMenu(hmenu, menu))
+        || (MENU_GetAllMenuItems(hmenu, &items)) || (!items)) return;
 
     lpm = MENU_GetLocalMenu(hmenu);
 
     if ( lpm->FocusedItem != NO_SELECTED_ITEM )
     {
-	if( menu->nItems == 1 ) return; else
+	if( menu->nItems == 1 )
+        {
+            MENU_ReleaseMenuItem(items);
+            return;
+        }
+        else
 	for (i = lpm->FocusedItem + offset ; i >= 0 && i < menu->nItems
 					    ; i += offset)
-	    if (!(menu->items[i].fType & MF_SEPARATOR))
+	    if (!(items[i].fType & MF_SEPARATOR))
 	    {
 		MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 );
+                MENU_ReleaseMenuItem(items);
 		return;
 	    }
     }
 
     for ( i = (offset > 0) ? 0 : menu->nItems - 1;
 		  i >= 0 && i < menu->nItems ; i += offset)
-	if (!(menu->items[i].fType & MF_SEPARATOR))
+	if (!(items[i].fType & MF_SEPARATOR))
 	{
 	    MENU_SelectItem( hwndOwner, hmenu, i, TRUE, 0 );
+            MENU_ReleaseMenuItem(items);
 	    return;
 	}
+    MENU_ReleaseMenuItem(items);
 }
 
 
@@ -2312,9 +2322,12 @@ static void MENU_MoveSelection( HWND hwn
  * Set an item's flags, id and text ptr. Called by InsertMenu() and
  * ModifyMenu().
  */
-static BOOL MENU_SetItemData( MENUITEM *item, UINT flags, UINT_PTR id,
+static BOOL MENU_SetItemData( HMENU hmenu, UINT pos, UINT flags, UINT_PTR id,
                                 LPCWSTR str )
 {
+    MENUITEM *item;
+    if (MENU_GetMenuItem(hmenu, pos, &item))
+        return FALSE;
     debug_print_menuitem("MENU_SetItemData from: ", item, "");
     TRACE("flags=%x str=%p\n", flags, str);
 
@@ -2336,7 +2349,10 @@ static BOOL MENU_SetItemData( MENUITEM *
                 str++;
             }
             if (!(text = HeapAlloc( GetProcessHeap(), 0, (strlenW(str)+1) * sizeof(WCHAR) )))
+            {
+                MENU_ReleaseMenuItem(item);
                 return FALSE;
+            }
             strcpyW( text, str );
             item->text = text;
         }
@@ -2373,6 +2389,8 @@ static BOOL MENU_SetItemData( MENUITEM *
             item->hSubMenu = 0;
             item->fType = 0;
             item->fState = 0;
+            MENU_UpdateMenuItem(hmenu, pos, item);
+            MENU_ReleaseMenuItem(item);
 	    return FALSE;
         }
     }
@@ -2390,6 +2408,8 @@ static BOOL MENU_SetItemData( MENUITEM *
     /* Don't call SetRectEmpty here! */
 
     debug_print_menuitem("MENU_SetItemData to  : ", item, "");
+    MENU_UpdateMenuItem(hmenu, pos, item);
+    MENU_ReleaseMenuItem(item);
     return TRUE;
 }
 
@@ -3259,13 +3279,16 @@ static void MENU_KeyRight( MTRACKER* pmt
     POPUPMENU tmpmenu, tmpcurmenu;
     POPUPMENU *menu = &tmpmenu, *curmenu = &tmpcurmenu;
     UINT  nextcol;
+    MENUITEM *item;
     MENU_GetMenu( pmt->hTopMenu, menu);
 
     MENU_GetMenu(pmt->hCurrentMenu, curmenu);
+    MENU_GetMenuItem(pmt->hCurrentMenu, 0, &item);
     TRACE("MENU_KeyRight called, cur %p (%s), top %p (%s).\n",
           pmt->hCurrentMenu,
-          debugstr_w(curmenu->items[0].text),
-          pmt->hTopMenu, debugstr_w(menu->items[0].text) );
+          debugstr_w(item->text),
+          pmt->hTopMenu, debugstr_w(item->text) );
+    MENU_ReleaseMenuItem(item);
 
     if ( (menu->wFlags & MF_POPUP) || (pmt->hCurrentMenu != pmt->hTopMenu))
     {
@@ -3508,12 +3531,18 @@ static BOOL MENU_TrackMenu( HMENU hmenu,
 		case VK_F1:
 		    {
 			HELPINFO hi;
+                        UINT focuseditem = MENU_GetLocalMenu(hmenu)->FocusedItem;
 			hi.cbSize = sizeof(HELPINFO);
 			hi.iContextType = HELPINFO_MENUITEM;
-			if (MENU_GetLocalMenu(hmenu)->FocusedItem == NO_SELECTED_ITEM)
+			if (focuseditem == NO_SELECTED_ITEM)
 			    hi.iCtrlId = 0;
 		        else
-			    hi.iCtrlId = menu->items[MENU_GetLocalMenu(hmenu)->FocusedItem].wID;
+                        {
+                            MENUITEM *item;
+                            MENU_GetMenuItem(hmenu, focuseditem, &item);
+			    hi.iCtrlId = item->wID;
+                            MENU_ReleaseMenuItem(item);
+                        }
 			hi.hItemHandle = hmenu;
 			hi.dwContextId = menu->dwContextHelpID;
 			hi.MousePos = msg.pt;
@@ -4092,27 +4121,36 @@ UINT WINAPI GetMenuState( HMENU hMenu, U
 {
     MENUITEM *item;
     UINT pos;
-    POPUPMENU menu;
     TRACE("(menu=%p, id=%04x, flags=%04x);\n", hMenu, wItemID, wFlags);
     if ((pos = MENU_FindItem( &hMenu, &wItemID, wFlags )) == ITEM_NOT_FOUND)
         return -1;
-    MENU_GetMenu(hMenu, &menu);
-    item = &menu.items[pos];
+    MENU_GetMenuItem(hMenu, pos, &item);
 
     debug_print_menuitem ("  item: ", item, "");
     if (item->fType & MF_POPUP)
     {
         POPUPMENU tmpmenu;
 	POPUPMENU *menu = &tmpmenu;
-        if (MENU_GetMenu( item->hSubMenu, menu )) return -1;
-	else return (menu->nItems << 8) | ((item->fState|item->fType) & 0xff);
+        if (MENU_GetMenu( item->hSubMenu, menu ))
+        {
+            MENU_ReleaseMenuItem(item);
+            return -1;
+        }
+	else
+        {
+            UINT ret = (menu->nItems << 8) | ((item->fState|item->fType) & 0xff);
+            MENU_ReleaseMenuItem(item);
+            return ret;
+        }
     }
     else
     {
 	/* We used to (from way back then) mask the result to 0xff.  */
 	/* I don't know why and it seems wrong as the documented */
 	/* return flag MF_SEPARATOR is outside that mask.  */
-	return (item->fType | item->fState);
+	UINT ret = (item->fType | item->fState);
+        MENU_ReleaseMenuItem(item);
+	return ret;
     }
 }
 
@@ -4170,14 +4208,8 @@ BOOL WINAPI InsertMenuW( HMENU hMenu, UI
 
     if ((i = MENU_InsertItem( hMenu, pos, flags )) == ITEM_NOT_FOUND)
         return FALSE;
-    else
-    {
-        POPUPMENU menu;
-        MENU_GetMenu(hMenu, &menu);
-        item = &menu.items[i];
-    }
 
-    if (!(MENU_SetItemData( item, flags, id, str )))
+    if (!(MENU_SetItemData( hMenu, i, flags, id, str )))
     {
         RemoveMenu( hMenu, pos, flags );
         return FALSE;
@@ -4192,7 +4224,10 @@ BOOL WINAPI InsertMenuW( HMENU hMenu, UI
         MENU_UpdateMenu((HMENU)id, menu, SET_MI_FLAGS);
     }
 
+    MENU_GetMenuItem(hMenu, i, &item);
     item->hCheckBit = item->hUnCheckBit = 0;
+    MENU_UpdateMenuItem(hMenu, i, item);
+    MENU_ReleaseMenuItem(item);
     return TRUE;
 }
 
@@ -4293,9 +4328,10 @@ BOOL WINAPI DeleteMenu( HMENU hMenu, UIN
     if ((pos = MENU_FindItem( &hMenu, &nPos, wFlags )) == ITEM_NOT_FOUND)
         return FALSE;
     MENU_GetMenu(hMenu, &menu);
-    item = &menu.items[pos];
+    MENU_GetMenuItem(hMenu, pos, &item);
     if (item->fType & MF_POPUP) DestroyMenu( item->hSubMenu );
       /* nPos is now the position of the item */
+    MENU_ReleaseMenuItem(item);
     RemoveMenu( hMenu, nPos, wFlags | MF_BYPOSITION );
     return TRUE;
 }
@@ -4307,7 +4343,6 @@ BOOL WINAPI DeleteMenu( HMENU hMenu, UIN
 BOOL WINAPI ModifyMenuW( HMENU hMenu, UINT pos, UINT flags,
                          UINT_PTR id, LPCWSTR str )
 {
-    MENUITEM *item;
     POPUPMENU tmpmenu;
     POPUPMENU *menu = &tmpmenu;
     UINT i;
@@ -4320,10 +4355,9 @@ BOOL WINAPI ModifyMenuW( HMENU hMenu, UI
     if ((i = MENU_FindItem( &hMenu, &pos, flags )) == ITEM_NOT_FOUND)
         return FALSE;
     MENU_GetMenu(hMenu, menu);
-    item = &menu->items[i];
     menu->Height = 0; /* force size recalculate */
     MENU_UpdateMenu(hMenu, menu, SET_MI_HEIGHT);
-    return MENU_SetItemData( item, flags, id, str );
+    return MENU_SetItemData( hMenu, i, flags, id, str );
 }
 
 
@@ -4386,14 +4420,12 @@ BOOL WINAPI SetMenuItemBitmaps( HMENU hM
                                     HBITMAP hNewUnCheck, HBITMAP hNewCheck)
 {
     MENUITEM *item;
-    POPUPMENU menu;
     UINT pos;
     TRACE("(%p, %04x, %04x, %p, %p)\n",
           hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
     if ((pos = MENU_FindItem( &hMenu, &nPos, wFlags )) == ITEM_NOT_FOUND)
         return FALSE;
-    MENU_GetMenu(hMenu, &menu);
-    item = &menu.items[pos];
+    MENU_GetMenuItem(hMenu, pos, &item);
 
     if (!hNewCheck && !hNewUnCheck)
     {
@@ -4405,6 +4437,7 @@ BOOL WINAPI SetMenuItemBitmaps( HMENU hM
 	item->hUnCheckBit = hNewUnCheck;
 	item->fState |= MF_USECHECKBITMAPS;
     }
+    MENU_ReleaseMenuItem(item);
     return TRUE;
 }
 
@@ -4918,7 +4951,10 @@ static BOOL GetMenuItemInfo_common ( HME
     
     pos = MENU_FindItem (&hmenu, &item, bypos? MF_BYPOSITION : 0);
     MENU_GetMenu(hmenu, &pm);
-    menu = (pos == ITEM_NOT_FOUND) ? NULL : &pm.items[pos];
+    if (pos == ITEM_NOT_FOUND)
+        menu = NULL;
+    else
+        MENU_GetMenuItem(hmenu, pos, &menu);
 
     debug_print_menuitem("GetMenuItemInfo_common: ", menu, "");
 
@@ -4928,6 +4964,7 @@ static BOOL GetMenuItemInfo_common ( HME
     if( lpmii->fMask & MIIM_TYPE) {
         if( lpmii->fMask & ( MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP)) {
             WARN("invalid combination of fMask bits used\n");
+            MENU_ReleaseMenuItem(menu);
             /* this does not happen on Win9x/ME */
             SetLastError( ERROR_INVALID_PARAMETER);
             return FALSE;
@@ -5013,6 +5050,7 @@ static BOOL GetMenuItemInfo_common ( HME
     if (lpmii->fMask & MIIM_DATA)
 	lpmii->dwItemData = menu->dwItemData;
 
+  MENU_ReleaseMenuItem(menu);
   return TRUE;
 }
 
@@ -5088,12 +5126,10 @@ static BOOL SetMenuItemInfo_common(HMENU
 				       const MENUITEMINFOW *lpmii,
 				       BOOL unicode)
 {
-    POPUPMENU pm;
     MENUITEM *menu;
     if (pos == ITEM_NOT_FOUND) return FALSE;
-    if (MENU_GetMenu(hmenu, &pm)) return FALSE;
-    if (!pm.items) return FALSE;
-    menu = &pm.items[pos];
+    if (MENU_GetMenuItem(hmenu, pos, &menu)) return FALSE;
+    if (!menu) return FALSE;
 
     debug_print_menuitem("SetmenuItemInfo_common from: ", menu, "");
 
@@ -5102,7 +5138,7 @@ static BOOL SetMenuItemInfo_common(HMENU
             WARN("invalid combination of fMask bits used\n");
             /* this does not happen on Win9x/ME */
             SetLastError( ERROR_INVALID_PARAMETER);
-            return FALSE;
+            goto returnfalse;
         }
 	/* make only MENU_ITEM_TYPE bits in menu->fType equal lpmii->fType */
 	menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
@@ -5118,7 +5154,7 @@ static BOOL SetMenuItemInfo_common(HMENU
     if (lpmii->fMask & MIIM_FTYPE ) {
         if(( lpmii->fType & MFT_BITMAP)) {
             SetLastError( ERROR_INVALID_PARAMETER);
-            return FALSE;
+            goto returnfalse;
         }
 	menu->fType &= ~MENU_ITEM_TYPE(menu->fType);
 	menu->fType |= MENU_ITEM_TYPE(lpmii->fType);
@@ -5151,7 +5187,7 @@ static BOOL SetMenuItemInfo_common(HMENU
 	    }
 	    else {
                 SetLastError( ERROR_INVALID_PARAMETER);
-                return FALSE;
+                goto returnfalse;
             }
 	}
 	else
@@ -5176,7 +5212,14 @@ static BOOL SetMenuItemInfo_common(HMENU
         menu->fType |= MFT_SEPARATOR;
 
     debug_print_menuitem("SetMenuItemInfo_common to : ", menu, "");
+    MENU_UpdateMenuItem(hmenu, pos, menu);
+    MENU_ReleaseMenuItem(menu);
     return TRUE;
+
+returnfalse:
+    MENU_UpdateMenuItem(hmenu, pos, menu);
+    MENU_ReleaseMenuItem(menu);
+    return FALSE;
 }
 
 /**********************************************************************
@@ -5233,30 +5276,39 @@ BOOL WINAPI SetMenuDefaultItem(HMENU hme
 	UINT i;
         POPUPMENU tmpmenu;
 	POPUPMENU *menu = &tmpmenu;
-	MENUITEM *item;
+	MENUITEM *item, *items;
 
 	TRACE("(%p,%d,%d)\n", hmenu, uItem, bypos);
 
 	if (MENU_GetMenu(hmenu, menu)) return FALSE;
 
 	/* reset all default-item flags */
-	item = menu->items;
+        MENU_GetAllMenuItems(hmenu, &items);
+        item = items;
 	for (i = 0; i < menu->nItems; i++, item++)
 	{
 	    item->fState &= ~MFS_DEFAULT;
+            MENU_UpdateMenuItem(hmenu, i, item);
 	}
 
 	/* no default item */
 	if ( -1 == uItem)
 	{
+            MENU_ReleaseMenuItem(items);
 	    return TRUE;
 	}
 
-	item = menu->items;
+        item = items;
 	if ( bypos )
 	{
-	    if ( uItem >= menu->nItems ) return FALSE;
+	    if ( uItem >= menu->nItems )
+            {
+                MENU_ReleaseMenuItem(items);
+                return FALSE;
+            }
 	    item[uItem].fState |= MFS_DEFAULT;
+            MENU_UpdateMenuItem(hmenu, uItem, &item[uItem]);
+            MENU_ReleaseMenuItem(items);
 	    return TRUE;
 	}
 	else
@@ -5266,11 +5318,14 @@ BOOL WINAPI SetMenuDefaultItem(HMENU hme
 		if (item->wID == uItem)
 		{
 		     item->fState |= MFS_DEFAULT;
+                     MENU_UpdateMenuItem(hmenu, i, item);
+                     MENU_ReleaseMenuItem(items);
 		     return TRUE;
 		}
 	    }
 
 	}
+        MENU_ReleaseMenuItem(items);
 	return FALSE;
 }
 
@@ -5397,7 +5452,7 @@ BOOL WINAPI CheckMenuRadioItem(HMENU hMe
 {
      UINT posfirst, poslast, poscheck;
      HMENU mfirst = hMenu, mlast = hMenu, mcheck = hMenu;
-     POPUPMENU menu;
+     MENUITEM *items;
 
      TRACE("%p: %d-%d, check %d, bypos=%d\n", hMenu, first, last, check, bypos);
 
@@ -5411,19 +5466,21 @@ BOOL WINAPI CheckMenuRadioItem(HMENU hMe
          || poscheck > poslast || poscheck < posfirst)
 	  return FALSE;
 
-     MENU_GetMenu(mfirst, &menu);
+     MENU_GetAllMenuItems(mfirst, &items);
      while (posfirst <= poslast)
      {
 	  if (posfirst == poscheck)
 	  {
-               menu.items[posfirst].fType |= MFT_RADIOCHECK;
-               menu.items[posfirst].fState |= MFS_CHECKED;
+               items[posfirst].fType |= MFT_RADIOCHECK;
+               items[posfirst].fState |= MFS_CHECKED;
 	  } else {
-               menu.items[posfirst].fType &= ~MFT_RADIOCHECK;
-               menu.items[posfirst].fState &= ~MFS_CHECKED;
-	  }
+               items[posfirst].fType &= ~MFT_RADIOCHECK;
+               items[posfirst].fState &= ~MFS_CHECKED;
+          }
+          MENU_UpdateMenuItem(mfirst, posfirst, &items[posfirst]);
 	  posfirst++;
      }
+     MENU_ReleaseMenuItem(items);
 
      return TRUE;
 }

