]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/menu.cpp
wxPalmOS build fix.
[wxWidgets.git] / src / mac / carbon / menu.cpp
index b52790b67d5df2d952388f1a470e8e8edc17a0af..a5bf7019b13b6d2412bd49e648b123a2084c7426 100644 (file)
@@ -1,31 +1,30 @@
 /////////////////////////////////////////////////////////////////////////////
 // Name:        menu.cpp
 // Purpose:     wxMenu, wxMenuBar, wxMenuItem
 /////////////////////////////////////////////////////////////////////////////
 // Name:        menu.cpp
 // Purpose:     wxMenu, wxMenuBar, wxMenuItem
-// Author:      AUTHOR
+// Author:      Stefan Csomor
 // Modified by:
 // Modified by:
-// Created:     ??/??/98
+// Created:     1998-01-01
 // RCS-ID:      $Id$
 // RCS-ID:      $Id$
-// Copyright:   (c) AUTHOR
-// Licence:    wxWindows licence
+// Copyright:   (c) Stefan Csomor
+// Licence:       wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 /////////////////////////////////////////////////////////////////////////////
 
-
 // ============================================================================
 // headers & declarations
 // ============================================================================
 
 // ============================================================================
 // headers & declarations
 // ============================================================================
 
-// wxWindows headers
+// wxWidgets headers
 // -----------------
 
 // -----------------
 
-#ifdef __GNUG__
-#pragma implementation "menu.h"
-#pragma implementation "menuitem.h"
-#endif
+#include "wx/wxprec.h"
 
 
+#include "wx/app.h"
 #include "wx/menu.h"
 #include "wx/menuitem.h"
 #include "wx/menu.h"
 #include "wx/menuitem.h"
+#include "wx/window.h"
 #include "wx/log.h"
 #include "wx/utils.h"
 #include "wx/log.h"
 #include "wx/utils.h"
+#include "wx/frame.h"
 
 #include "wx/mac/uma.h"
 
 
 #include "wx/mac/uma.h"
 
@@ -37,163 +36,96 @@ IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
 
 // the (popup) menu title has this special id
 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
 
 // the (popup) menu title has this special id
-static const int idMenuTitle = -2;
-static int formerHelpMenuItems = 0 ;
+static const int idMenuTitle = -3;
 
 const short kwxMacMenuBarResource = 1 ;
 const short kwxMacAppleMenuId = 1 ;
 
 
 const short kwxMacMenuBarResource = 1 ;
 const short kwxMacAppleMenuId = 1 ;
 
-// ============================================================================
-// implementation
-// ============================================================================
 
 
-//
-// Helper Functions to get Mac Menus the way they should be ;-)
-//
+// Find an item given the Macintosh Menu Reference
 
 
-void wxMacCtoPString(const char* theCString, Str255 thePString);
+WX_DECLARE_HASH_MAP(MenuRef, wxMenu*, wxPointerHash, wxPointerEqual, MacMenuMap);
 
 
-// remove inappropriate characters, if useShortcuts is false, the ampersand will not auto-generate a mac menu-shortcut
+static MacMenuMap wxWinMacMenuList;
 
 
-void wxMacBuildMenuString(StringPtr outMacItemText, char *outMacShortcutChar , short *outMacModifiers , const char *inItemName , bool useShortcuts )
+wxMenu *wxFindMenuFromMacMenu(MenuRef inMenuRef)
 {
 {
-       char *p = (char *) &outMacItemText[1] ;
-       short macModifiers = 0 ;
-       char macShortCut = 0 ;
-       
-       if ( useShortcuts && !wxApp::s_macSupportPCMenuShortcuts )
-               useShortcuts = false ;
-       
-       // we have problems with a leading hypen - it will be taken as a separator
-       
-       while ( *inItemName == '-' )
-               inItemName++ ;
-               
-       while( *inItemName )
-       {
-               switch ( *inItemName )
-               {
-                       // special characters for macintosh menus -> use some replacement
-                       case ';' :
-                               *p++ = ',' ;
-                               break ;
-                       case '^' :
-                               *p++ = ' ' ;
-                               break ;
-                       case '!' :
-                               *p++ = ' ' ;
-                               break ;
-                       case '<' :
-                               *p++ = ' ' ;
-                               break ;
-                       case '/' :
-                               *p++ = '|' ;
-                               break ;
-                       case '(' :
-                               *p++ = '[' ;
-                               break ;
-                       case ')' :      
-                               *p++ = ']' ;
-                               break ;
-                       // shortcuts
-                       case '&' :
-                               {
-                                       ++inItemName ;
-                                       if ( *inItemName )
-                                       {
-                                               *p++ = *inItemName ;
-                                               if ( useShortcuts )
-                                                       macShortCut = *inItemName ;
-                                       }
-                                       else
-                                               --inItemName ;
-                               }
-                               break ;
-                       // win-like accelerators
-                       case '\t' :
-                               {
-                                       ++inItemName ;
-                                       while( *inItemName )
-                                       {
-                                               if (strncmp("Ctrl", inItemName, 4) == 0) 
-                                               {
-                                                       inItemName = inItemName + 5;
-                                                       macShortCut = *inItemName;
-                                               }
-                                               else if (strncmp("Alt", inItemName, 3) == 0) 
-                                               {
-                                                       inItemName = inItemName + 4;
-                                                       macModifiers |= kMenuOptionModifier ;
-                                                       macShortCut = *inItemName ;
-                                               }
-                                               else if (strncmp("Shift", inItemName, 5) == 0) 
-                                               {
-                                                       inItemName = inItemName + 6;
-                                                       macModifiers |= kMenuShiftModifier ;
-                                                       macShortCut = *inItemName ;
-                                               }
-                                               else if (strncmp("F", inItemName, 1) == 0) 
-                                               {
-                                                       inItemName += strlen( inItemName ) ;
-                                                       // no function keys at the moment
-                                                       // macModifiers |= kMenuShiftModifier ;
-                                                       // macShortCut = *inItemName ;
-                                               }
-                                               else
-                                               {
-                                                       break ;
-                                               }
-                                       }
-
-                                       if ( *inItemName == 0 )
-                                               --inItemName ;
-                                               
-                               }
-                               break ;
-                       default :
-                               *p++ = *inItemName ;
-               }
-               ++inItemName ;
-       }
-
-       outMacItemText[0] = (p - (char *)outMacItemText) - 1;
-       if ( outMacShortcutChar )
-               *outMacShortcutChar = macShortCut ;
-       if ( outMacModifiers )
-               *outMacModifiers = macModifiers ;
-       if ( macShortCut )
-       {
-                       int pos = outMacItemText[0] ;
-                       outMacItemText[++pos] = '/';
-                       outMacItemText[++pos] = toupper( macShortCut );
-                       outMacItemText[0] = pos ;
-       }
+    MacMenuMap::iterator node = wxWinMacMenuList.find(inMenuRef);
+
+    return (node == wxWinMacMenuList.end()) ? NULL : node->second;
+}
+
+void wxAssociateMenuWithMacMenu(MenuRef inMenuRef, wxMenu *menu) ;
+void wxAssociateMenuWithMacMenu(MenuRef inMenuRef, wxMenu *menu)
+{
+    // adding NULL MenuRef is (first) surely a result of an error and
+    // (secondly) breaks menu command processing
+    wxCHECK_RET( inMenuRef != (MenuRef) NULL, wxT("attempt to add a NULL MenuRef to menu list") );
+
+    wxWinMacMenuList[inMenuRef] = menu;
 }
 
 }
 
+void wxRemoveMacMenuAssociation(wxMenu *menu) ;
+void wxRemoveMacMenuAssociation(wxMenu *menu)
+{
+   // iterate over all the elements in the class
+    MacMenuMap::iterator it;
+    for ( it = wxWinMacMenuList.begin(); it != wxWinMacMenuList.end(); ++it )
+    {
+        if ( it->second == menu )
+        {
+            wxWinMacMenuList.erase(it);
+            break;
+        }
+    }
+}
+
+// ============================================================================
+// implementation
+// ============================================================================
+static void wxMenubarUnsetInvokingWindow( wxMenu *menu ) ;
+static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win );
+
 // Menus
 
 // Construct a menu with optional title (then use append)
 
 // Menus
 
 // Construct a menu with optional title (then use append)
 
+#ifdef __DARWIN__
+short wxMenu::s_macNextMenuId = 3 ;
+#else
 short wxMenu::s_macNextMenuId = 2 ;
 short wxMenu::s_macNextMenuId = 2 ;
+#endif
+
+static
+wxMenu *
+_wxMenuAt(const wxMenuList &menuList, size_t pos)
+{
+    wxMenuList::compatibility_iterator menuIter = menuList.GetFirst();
+
+    while (pos-- > 0)
+        menuIter = menuIter->GetNext();
+
+    return menuIter->GetData() ;
+}
 
 void wxMenu::Init()
 {
 
 void wxMenu::Init()
 {
-    m_doBreak = FALSE;
+    m_doBreak = false;
+    m_startRadioGroup = -1;
 
     // create the menu
 
     // create the menu
-       Str255  label;
-       wxMacBuildMenuString( label, NULL , NULL , m_title , false );
-       m_macMenuId = s_macNextMenuId++; 
-    wxCHECK_RET( s_macNextMenuId < 236 , "menu ids > 235 cannot be used for submenus on mac" );
-       m_hMenu = ::NewMenu(m_macMenuId, label);
+    m_macMenuId = s_macNextMenuId++;
+    m_hMenu = UMANewMenu(m_macMenuId, m_title, wxFont::GetDefaultEncoding() );
 
     if ( !m_hMenu )
     {
 
     if ( !m_hMenu )
     {
-        wxLogLastError("CreatePopupMenu");
+        wxLogLastError(wxT("UMANewMenu failed"));
     }
 
     }
 
+    wxAssociateMenuWithMacMenu( (MenuRef)m_hMenu , this ) ;
+
     // if we have a title, insert it in the beginning of the menu
     // if we have a title, insert it in the beginning of the menu
-    if ( !!m_title )
+    if ( !m_title.empty() )
     {
         Append(idMenuTitle, m_title) ;
         AppendSeparator() ;
     {
         Append(idMenuTitle, m_title) ;
         AppendSeparator() ;
@@ -202,367 +134,199 @@ void wxMenu::Init()
 
 wxMenu::~wxMenu()
 {
 
 wxMenu::~wxMenu()
 {
-       if (m_hMenu)
-               ::DisposeMenu(m_hMenu);
-
-#if wxUSE_ACCEL
-    // delete accels
-    WX_CLEAR_ARRAY(m_accels);
-#endif // wxUSE_ACCEL
+    wxRemoveMacMenuAssociation( this ) ;
+    if (MAC_WXHMENU(m_hMenu))
+        ::DisposeMenu(MAC_WXHMENU(m_hMenu));
 }
 
 void wxMenu::Break()
 {
 }
 
 void wxMenu::Break()
 {
-       // not available on the mac platform
+    // not available on the mac platform
 }
 
 }
 
-#if wxUSE_ACCEL
-
-int wxMenu::FindAccel(int id) const
+void wxMenu::Attach(wxMenuBarBase *menubar)
 {
 {
-    size_t n, count = m_accels.GetCount();
-    for ( n = 0; n < count; n++ )
-    {
-        if ( m_accels[n]->m_command == id )
-            return n;
-    }
+    wxMenuBase::Attach(menubar);
 
 
-    return wxNOT_FOUND;
+    EndRadioGroup();
 }
 
 }
 
-void wxMenu::UpdateAccel(wxMenuItem *item)
+// function appends a new item or submenu to the menu
+// append a new item or submenu to the menu
+bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
 {
 {
-    // find the (new) accel for this item
-    wxAcceleratorEntry *accel = wxGetAccelFromString(item->GetText());
-    if ( accel )
-        accel->m_command = item->GetId();
-
-    // find the old one
-    int n = FindAccel(item->GetId());
-    if ( n == wxNOT_FOUND )
+    wxASSERT_MSG( pItem != NULL, wxT("can't append NULL item to the menu") );
+
+    if ( pItem->IsSeparator() )
     {
     {
-        // no old, add new if any
-        if ( accel )
-            m_accels.Add(accel);
+        if ( pos == (size_t)-1 )
+            MacAppendMenu(MAC_WXHMENU(m_hMenu), "\p-");
         else
         else
-            return;     // skipping RebuildAccelTable() below
+            MacInsertMenuItem(MAC_WXHMENU(m_hMenu), "\p-" , pos);
     }
     else
     {
     }
     else
     {
-        // replace old with new or just remove the old one if no new
-        delete m_accels[n];
-        if ( accel )
-            m_accels[n] = accel;
-        else
-            m_accels.Remove(n);
-    }
+        wxMenu *pSubMenu = pItem->GetSubMenu() ;
+        if ( pSubMenu != NULL )
+        {
+            wxASSERT_MSG( pSubMenu->m_hMenu != NULL , wxT("invalid submenu added"));
+            pSubMenu->m_menuParent = this ;
 
 
-    if ( IsAttached() )
-    {
-        m_menuBar->RebuildAccelTable();
-    }
-}
+            if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar())
+                pSubMenu->MacBeforeDisplay( true ) ;
 
 
-#endif // wxUSE_ACCEL
+            if ( pos == (size_t)-1 )
+                UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu), wxStripMenuCodes(pItem->GetText()), wxFont::GetDefaultEncoding(), pSubMenu->m_macMenuId);
+            else
+                UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu), wxStripMenuCodes(pItem->GetText()), wxFont::GetDefaultEncoding(), pos, pSubMenu->m_macMenuId);
 
 
-// function appends a new item or submenu to the menu
-// append a new item or submenu to the menu
-bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
-{
-    wxASSERT_MSG( pItem != NULL, "can't append NULL item to the menu" );
-#if wxUSE_ACCEL
-    UpdateAccel(pItem);
-#endif // wxUSE_ACCEL
-
-       if ( pItem->IsSeparator() )
-       {
-               if ( pos == (size_t)-1 )
-               {
-                       MacAppendMenu(m_hMenu, "\p-");
-               }
-               else
-               {
-                       MacInsertMenuItem(m_hMenu, "\p-" , pos);
-               }
-       }
-       else 
-       {
-               wxMenu *pSubMenu = pItem->GetSubMenu() ;
-               if ( pSubMenu != NULL )
-               {
-                       Str255 label;
-                       wxASSERT_MSG( pSubMenu->m_hMenu != NULL , "invalid submenu added");
-                   pSubMenu->m_menuParent = this ;
-                       wxMacBuildMenuString( label , NULL , NULL , pItem->GetText() ,false);
-               
-                       // hardcoded adding of the submenu combination for mac
-               
-                       int theEnd = label[0] + 1; 
-                       if (theEnd > 251) 
-                               theEnd = 251; // mac allows only 255 characters
-                       label[theEnd++] = '/';
-                       label[theEnd++] = hMenuCmd; 
-                       label[theEnd++] = '!';
-                       label[theEnd++] = pSubMenu->m_macMenuId; 
-                       label[theEnd] = 0x00;
-                       label[0] = theEnd;
-
-                       if (wxMenuBar::MacGetInstalledMenuBar() == m_menuBar) 
-                       {
-                               ::InsertMenu( pSubMenu->m_hMenu , -1 ) ;
-                       }
-                       
-                       if ( pos == (size_t)-1 )
-                       {
-                               MacAppendMenu(m_hMenu, label);
-                       }
-                       else
-                       {
-                               MacInsertMenuItem(m_hMenu, label , pos);
-                       }
-               }
-               else
-               {
-                       Str255 label ;
-                       wxMacBuildMenuString( label , NULL , NULL , pItem->GetText(), pItem->GetId() == wxApp::s_macAboutMenuItemId);
-                       if ( label[0] == 0 )
-                       {
-                               // we cannot add empty menus on mac
-                               label[0] = 1 ;
-                               label[1] = ' ' ;
-                       }
-                       if ( pos == (size_t)-1 )
-                       {
-                               MacAppendMenu(m_hMenu, label);
-                       }
-                       else
-                       {
-                               MacInsertMenuItem(m_hMenu, label , pos);
-                       }
-                       if ( pItem->GetId() == idMenuTitle ) 
-                       {
-                               if ( pos == (size_t)-1 )
-                               {
-                                       UMADisableMenuItem( m_hMenu , CountMItems( m_hMenu ) ) ;
-                               }
-                               else
-                               {
-                                       UMADisableMenuItem( m_hMenu , pos + 1 ) ;
-                               }
-                       }
-               }
-       }
-    // if we're already attached to the menubar, we must update it
-    if ( IsAttached() )
-    {
-        m_menuBar->Refresh();
+            pItem->UpdateItemBitmap() ;
+            pItem->UpdateItemStatus() ;
+        }
+        else
+        {
+            if ( pos == (size_t)-1 )
+            {
+                UMAAppendMenuItem(MAC_WXHMENU(m_hMenu), wxT("a") , wxFont::GetDefaultEncoding() );
+                pos = CountMenuItems(MAC_WXHMENU(m_hMenu)) ;
+            }
+            else
+            {
+                // MacOS counts menu items from 1 and inserts after, therefore having the
+                // same effect as wx 0 based and inserting before, we must correct pos
+                // after however for updates to be correct
+                UMAInsertMenuItem(MAC_WXHMENU(m_hMenu), wxT("a"), wxFont::GetDefaultEncoding(), pos);
+                pos += 1 ;
+            }
+            
+            SetMenuItemCommandID( MAC_WXHMENU(m_hMenu) , pos , wxIdToMacCommand ( pItem->GetId() ) ) ;
+            SetMenuItemRefCon( MAC_WXHMENU(m_hMenu) , pos , (UInt32) pItem ) ;
+            pItem->UpdateItemText() ;
+            pItem->UpdateItemBitmap() ;
+            pItem->UpdateItemStatus() ;
+
+            if ( pItem->GetId() == idMenuTitle )
+                UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , pos , false ) ;
+        }
     }
     }
-       return TRUE ;
-}
 
 
-bool wxMenu::DoAppend(wxMenuItem *item)
-{
-    return wxMenuBase::DoAppend(item) && DoInsertOrAppend(item);
+    // if we're already attached to the menubar, we must update it
+    if ( IsAttached() && GetMenuBar()->IsAttached() )
+        GetMenuBar()->Refresh();
+
+    return true ;
 }
 
 }
 
-bool wxMenu::DoInsert(size_t pos, wxMenuItem *item)
+void wxMenu::EndRadioGroup()
 {
 {
-    return wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos);
+    // we're not inside a radio group any longer
+    m_startRadioGroup = -1;
 }
 
 }
 
-wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
+wxMenuItem* wxMenu::DoAppend(wxMenuItem *item)
 {
 {
-    // we need to find the items position in the child list
-    size_t pos;
-    wxMenuItemList::Node *node = GetMenuItems().GetFirst();
-    for ( pos = 0; node; pos++ )
-    {
-        if ( node->GetData() == item )
-            break;
+    wxCHECK_MSG( item, NULL, _T("NULL item in wxMenu::DoAppend") );
 
 
-        node = node->GetNext();
-    }
+    bool check = false;
 
 
-    // DoRemove() (unlike Remove) can only be called for existing item!
-    wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
-
-#if wxUSE_ACCEL
-    // remove the corresponding accel from the accel table
-    int n = FindAccel(item->GetId());
-    if ( n != wxNOT_FOUND )
+    if ( item->GetKind() == wxITEM_RADIO )
     {
     {
-        delete m_accels[n];
+        int count = GetMenuItemCount();
 
 
-        m_accels.Remove(n);
-    }
-    //else: this item doesn't have an accel, nothing to do
-#endif // wxUSE_ACCEL
+        if ( m_startRadioGroup == -1 )
+        {
+            // start a new radio group
+            m_startRadioGroup = count;
 
 
-       ::DeleteMenuItem( m_hMenu , pos + 1);
+            // for now it has just one element
+            item->SetAsRadioGroupStart();
+            item->SetRadioGroupEnd(m_startRadioGroup);
 
 
-    if ( IsAttached() )
-    {
-        // otherwise, the chane won't be visible
-        m_menuBar->Refresh();
+            // ensure that we have a checked item in the radio group
+            check = true;
+        }
+        else // extend the current radio group
+        {
+            // we need to update its end item
+            item->SetRadioGroupStart(m_startRadioGroup);
+            wxMenuItemList::compatibility_iterator node = GetMenuItems().Item(m_startRadioGroup);
+
+            if ( node )
+            {
+                node->GetData()->SetRadioGroupEnd(count);
+            }
+            else
+            {
+                wxFAIL_MSG( _T("where is the radio group start item?") );
+            }
+        }
     }
     }
-
-    // and from internal data structures
-    return wxMenuBase::DoRemove(item);
-}
-
-// ---------------------------------------------------------------------------
-// accelerator helpers
-// ---------------------------------------------------------------------------
-
-#if wxUSE_ACCEL
-
-// create the wxAcceleratorEntries for our accels and put them into provided
-// array - return the number of accels we have
-size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const
-{
-    size_t count = GetAccelCount();
-    for ( size_t n = 0; n < count; n++ )
+    else // not a radio item
     {
     {
-        *accels++ = *m_accels[n];
+        EndRadioGroup();
     }
 
     }
 
-    return count;
-}
+    if ( !wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item) )
+        return NULL;
 
 
-#endif // wxUSE_ACCEL
+    if ( check )
+        // check the item initially
+        item->Check(true);
 
 
-void wxMenu::SetTitle(const wxString& label)
-{
-       Str255 title ;
-    m_title = label ;
-       wxMacBuildMenuString( title, NULL , NULL , label , false );
-       UMASetMenuTitle( m_hMenu , title ) ;
+    return item;
 }
 
 }
 
-/*
-
-void wxMenu::SetLabel(int id, const wxString& label)
+wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item)
 {
 {
-    Str255 maclabel ;
-   int index ;
-    wxMenuItem *item = FindItemForId(id) ;
-    if (item==NULL)
-        return;
-
-    index = MacGetIndexFromItem( item ) ;
-    if (index < 1)
-               return;
-
-    if (item->GetSubMenu()==NULL)
-    {
-               wxMacBuildMenuString( maclabel , NULL , NULL , label , false );
-               ::SetMenuItemText( m_hMenu , index , maclabel ) ;
-    }
-    else
-    {
-               wxMacBuildMenuString( maclabel , NULL , NULL , label , false );
-               ::SetMenuItemText( m_hMenu , index , maclabel ) ;
-    }
-    item->SetName(label);
-}
+    if (wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos))
+        return item;
 
 
-wxString wxMenu::GetLabel(int Id) const
-{
-    wxMenuItem *pItem = FindItemForId(Id) ;
-    return pItem->GetName() ;
+    return NULL;
 }
 
 }
 
-// Finds the item id matching the given string, -1 if not found.
-int wxMenu::FindItem (const wxString& itemString) const
+wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
 {
 {
-    char buf1[200];
-    char buf2[200];
-    wxStripMenuCodes ((char *)(const char *)itemString, buf1);
+    // we need to find the items position in the child list
+    size_t pos;
+    wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
 
 
-    for (wxNode * node = m_menuItems.First (); node; node = node->Next ())
+    for ( pos = 0; node; pos++ )
     {
     {
-      wxMenuItem *item = (wxMenuItem *) node->Data ();
-      if (item->GetSubMenu())
-      {
-        int ans = item->GetSubMenu()->FindItem(itemString);
-        if (ans > -1)
-          return ans;
-      }
-      if ( !item->IsSeparator() )
-      {
-        wxStripMenuCodes((char *)item->GetName().c_str(), buf2);
-        if (strcmp(buf1, buf2) == 0)
-          return item->GetId();
-      }
-    }
-
-    return -1;
-}
+        if ( node->GetData() == item )
+            break;
 
 
-wxMenuItem *wxMenu::FindItemForId(int itemId, wxMenu ** itemMenu) const
-{
-    if (itemMenu)
-        *itemMenu = NULL;
-    for (wxNode * node = m_menuItems.First (); node; node = node->Next ())
-    {
-        wxMenuItem *item = (wxMenuItem *) node->Data ();
+        node = node->GetNext();
+    }
 
 
-        if (item->GetId() == itemId)
-        {
-            if (itemMenu)
-                *itemMenu = (wxMenu *) this;
-            return item;
-        }
+    // DoRemove() (unlike Remove) can only be called for existing item!
+    wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
 
 
-        if (item->GetSubMenu())
-        {
-            wxMenuItem *ans = item->GetSubMenu()->FindItemForId (itemId, itemMenu);
-            if (ans)
-                return ans;
-        }
-    }
+    ::DeleteMenuItem(MAC_WXHMENU(m_hMenu) , pos + 1);
 
 
-    if (itemMenu)
-        *itemMenu = NULL;
-    return NULL;
-}
+    if ( IsAttached() && GetMenuBar()->IsAttached() )
+        // otherwise, the change won't be visible
+        GetMenuBar()->Refresh();
 
 
-void wxMenu::SetHelpString(int itemId, const wxString& helpString)
-{
-    wxMenuItem *item = FindItemForId (itemId);
-    if (item)
-        item->SetHelp(helpString);
+    // and from internal data structures
+    return wxMenuBase::DoRemove(item);
 }
 
 }
 
-wxString wxMenu::GetHelpString (int itemId) const
+void wxMenu::SetTitle(const wxString& label)
 {
 {
-    wxMenuItem *item = FindItemForId (itemId);
-    wxString str("");
-    return (item == NULL) ? str : item->GetHelp();
+    m_title = label ;
+    UMASetMenuTitle(MAC_WXHMENU(m_hMenu) , label , wxFont::GetDefaultEncoding() ) ;
 }
 }
-*/
 
 bool wxMenu::ProcessCommand(wxCommandEvent & event)
 {
 
 bool wxMenu::ProcessCommand(wxCommandEvent & event)
 {
-    bool processed = FALSE;
-
-#if WXWIN_COMPATIBILITY
-    // Try a callback
-    if (m_callback)
-    {
-        (void)(*(m_callback))(*this, event);
-        processed = TRUE;
-    }
-#endif WXWIN_COMPATIBILITY
+    bool processed = false;
 
     // Try the menu's event handler
 
     // Try the menu's event handler
-    if ( !processed && GetEventHandler())
-    {
+    if ( /* !processed && */ GetEventHandler())
         processed = GetEventHandler()->ProcessEvent(event);
         processed = GetEventHandler()->ProcessEvent(event);
-    }
 
 
-    // Try the window the menu was popped up from (and up through the
-    // hierarchy)
+    // Try the window the menu was popped up from
+    // (and up through the hierarchy)
     wxWindow *win = GetInvokingWindow();
     if ( !processed && win )
         processed = win->GetEventHandler()->ProcessEvent(event);
     wxWindow *win = GetInvokingWindow();
     if ( !processed && win )
         processed = win->GetEventHandler()->ProcessEvent(event);
@@ -570,44 +334,27 @@ bool wxMenu::ProcessCommand(wxCommandEvent & event)
     return processed;
 }
 
     return processed;
 }
 
-
 // ---------------------------------------------------------------------------
 // other
 // ---------------------------------------------------------------------------
 
 // ---------------------------------------------------------------------------
 // other
 // ---------------------------------------------------------------------------
 
-void wxMenu::Attach(wxMenuBar *menubar)
-{
-    // menu can be in at most one menubar because otherwise they would both
-    // delete the menu pointer
-    wxASSERT_MSG( !m_menuBar, wxT("menu belongs to 2 menubars, expect a crash") );
-
-    m_menuBar = menubar;
-}
-
-void wxMenu::Detach()
-{
-    wxASSERT_MSG( m_menuBar, wxT("can't detach menu if it's not attached") );
-
-    m_menuBar = NULL;
-}
-
 wxWindow *wxMenu::GetWindow() const
 {
     if ( m_invokingWindow != NULL )
         return m_invokingWindow;
 wxWindow *wxMenu::GetWindow() const
 {
     if ( m_invokingWindow != NULL )
         return m_invokingWindow;
-    else if ( m_menuBar != NULL)
-        return m_menuBar->GetFrame();
+    else if ( GetMenuBar() != NULL)
+        return (wxWindow *) GetMenuBar()->GetFrame();
 
     return NULL;
 }
 
 
     return NULL;
 }
 
-// helper functions returning the mac menu position for a certain item, note that this is 
+// helper functions returning the mac menu position for a certain item, note that this is
 // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
 
 // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0
 
-int wxMenu::MacGetIndexFromId( int id ) 
+int wxMenu::MacGetIndexFromId( int id )
 {
     size_t pos;
 {
     size_t pos;
-    wxMenuItemList::Node *node = GetMenuItems().GetFirst();
+    wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
     for ( pos = 0; node; pos++ )
     {
         if ( node->GetData()->GetId() == id )
     for ( pos = 0; node; pos++ )
     {
         if ( node->GetData()->GetId() == id )
@@ -615,17 +362,17 @@ int wxMenu::MacGetIndexFromId( int id )
 
         node = node->GetNext();
     }
 
         node = node->GetNext();
     }
-       
+
     if (!node)
     if (!node)
-               return 0;
-               
-       return pos + 1 ;
+        return 0;
+
+    return pos + 1 ;
 }
 
 }
 
-int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem ) 
+int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem )
 {
     size_t pos;
 {
     size_t pos;
-    wxMenuItemList::Node *node = GetMenuItems().GetFirst();
+    wxMenuItemList::compatibility_iterator node = GetMenuItems().GetFirst();
     for ( pos = 0; node; pos++ )
     {
         if ( node->GetData() == pItem )
     for ( pos = 0; node; pos++ )
     {
         if ( node->GetData() == pItem )
@@ -635,129 +382,134 @@ int wxMenu::MacGetIndexFromItem( wxMenuItem *pItem )
     }
 
     if (!node)
     }
 
     if (!node)
-               return 0;
-               
-       return pos + 1 ;
+        return 0;
+
+    return pos + 1 ;
 }
 
 }
 
-void wxMenu::MacEnableMenu( bool bDoEnable ) 
+void wxMenu::MacEnableMenu( bool bDoEnable )
 {
 {
-       if ( bDoEnable )
-               UMAEnableMenuItem( m_hMenu , 0 ) ;
-       else
-               UMADisableMenuItem( m_hMenu , 0 ) ;
-               
-       ::DrawMenuBar() ;
+    UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , 0 , bDoEnable ) ;
+
+    ::DrawMenuBar() ;
 }
 
 }
 
-bool wxMenu::MacMenuSelect( wxEvtHandler* handler, long when , int macMenuId, int macMenuItemNum )
+// MacOS needs to know about submenus somewhere within this menu
+// before it can be displayed, also hide special menu items
+// like preferences that are handled by the OS
+void wxMenu::MacBeforeDisplay( bool isSubMenu )
 {
 {
-  int pos;
-  wxNode *node;
-
-       if ( m_macMenuId == macMenuId )
-       {
-               node = GetMenuItems().Nth(macMenuItemNum-1);
-               if (node) 
-               {
-                       wxMenuItem *pItem = (wxMenuItem*)node->Data();
-       
-                       wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, pItem->GetId());
-                       event.m_timeStamp = when;
-                       event.SetEventObject(handler);
-               event.SetInt( pItem->GetId() );
-                       {
-                               bool processed = false ;
-
-#if WXWIN_COMPATIBILITY
-                           // Try a callback
-                           if (m_callback)
-                           {
-                                   (void) (*(m_callback)) (*this, event);
-                                   processed = TRUE;
-                           }
-#endif                 
-                           // Try the menu's event handler
-                           if ( !processed && handler)
-                           {
-                                   processed = handler->ProcessEvent(event);
-                           }
-                       
-                               // Try the window the menu was popped up from (and up
-                               // through the hierarchy)
-                               if ( !processed && GetInvokingWindow())
-                               processed = GetInvokingWindow()->GetEventHandler()->ProcessEvent(event);
-                       }
-                       return true ;
-               }
-       }
-       else if ( macMenuId == kHMHelpMenuID )
-       {
-               int menuItem = formerHelpMenuItems ;
-         for (pos = 0, node = GetMenuItems().First(); node; node = node->Next(), pos++) 
-         {     
-               wxMenuItem * pItem = (wxMenuItem *)  node->Data() ;
-               
-               wxMenu *pSubMenu = pItem->GetSubMenu() ;
-                       if ( pSubMenu != NULL )
-                       {
-                       }
-                       else
-                       {
-                               if ( pItem->GetId() != wxApp::s_macAboutMenuItemId )
-                                       ++menuItem ;
-                                       
-                               if ( menuItem == macMenuItemNum )
-                               {
-                                       wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, pItem->GetId());
-                                       event.m_timeStamp = when;
-                                       event.SetEventObject(handler);
-                                       event.SetInt( pItem->GetId() );
-                                       {
-                                               bool processed = false ;
-#if WXWIN_COMPATIBILITY
-                                           // Try a callback
-                                           if (m_callback)
-                                           {
-                                                   (void) (*(m_callback)) (*this, event);
-                                                   processed = TRUE;
-                                           }
-#endif                                 
-                                           // Try the menu's event handler
-                                           if ( !processed && handler)
-                                           {
-                                                   processed = handler->ProcessEvent(event);
-                                           }
-                                       
-                                               // Try the window the menu was popped up from (and up
-                                               // through the hierarchy)
-                                               if ( !processed && GetInvokingWindow())
-                                               processed = GetInvokingWindow()->GetEventHandler()->ProcessEvent(event);
-                                       }
-                                       return true ;
-                               }
-                       }
-         }
-       }
-
-  for (pos = 0, node = GetMenuItems().First(); node; node = node->Next(), pos++) 
-  {    
-               wxMenuItem * pItem = (wxMenuItem *)  node->Data() ;
-       
-               wxMenu *pSubMenu = pItem->GetSubMenu() ;
-               if ( pSubMenu != NULL )
-               {
-                       if ( pSubMenu->MacMenuSelect( handler , when , macMenuId , macMenuItemNum ) )
-                               return true ;
-               }
-  }
-
-       return false ;
+    wxMenuItem* previousItem = NULL ;
+    size_t pos ;
+    wxMenuItemList::compatibility_iterator node;
+    wxMenuItem *item;
+
+    for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
+    {
+        item = (wxMenuItem *)node->GetData();
+        wxMenu* subMenu = item->GetSubMenu() ;
+        if (subMenu)
+        {
+            subMenu->MacBeforeDisplay( true ) ;
+        }
+        else // normal item
+        {
+#if TARGET_CARBON
+            // what we do here is to hide the special items which are
+            // shown in the application menu anyhow -- it doesn't make
+            // sense to show them in their normal place as well
+            if ( item->GetId() == wxApp::s_macAboutMenuItemId ||
+                ( UMAGetSystemVersion() >= 0x1000 && (
+                    item->GetId() == wxApp::s_macPreferencesMenuItemId ||
+                    item->GetId() == wxApp::s_macExitMenuItemId ) ) )
+
+            {
+                ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
+                                          pos + 1, kMenuItemAttrHidden, 0 );
+
+                // also check for a separator which was used just to
+                // separate this item from the others, so don't leave
+                // separator at the menu start or end nor 2 consecutive
+                // separators
+                wxMenuItemList::compatibility_iterator nextNode = node->GetNext();
+                wxMenuItem *next = nextNode ? nextNode->GetData() : NULL;
+
+                size_t posSeptoHide;
+                if ( !previousItem && next && next->IsSeparator() )
+                {
+                    // next (i.e. second as we must be first) item is
+                    // the separator to hide
+                    wxASSERT_MSG( pos == 0, _T("should be the menu start") );
+                    posSeptoHide = 2;
+                }
+                else if ( GetMenuItems().GetCount() == pos + 1 &&
+                            previousItem != NULL &&
+                                previousItem->IsSeparator() )
+                {
+                    // prev item is a trailing separator we want to hide
+                    posSeptoHide = pos;
+                }
+                else if ( previousItem && previousItem->IsSeparator() &&
+                            next && next->IsSeparator() )
+                {
+                    // two consecutive separators, this is one too many
+                    posSeptoHide = pos;
+                }
+                else // no separators to hide
+                {
+                    posSeptoHide = 0;
+                }
+
+                if ( posSeptoHide )
+                {
+                    // hide the separator as well
+                    ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ),
+                                              posSeptoHide,
+                                              kMenuItemAttrHidden,
+                                              0 );
+                }
+            }
+#endif // TARGET_CARBON
+        }
+
+        previousItem = item ;
+    }
+
+    if ( isSubMenu )
+        ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
+}
+
+// undo all changes from the MacBeforeDisplay call
+void wxMenu::MacAfterDisplay( bool isSubMenu )
+{
+    if ( isSubMenu )
+        ::DeleteMenu(MacGetMenuId());
+
+    wxMenuItem* previousItem = NULL ;
+    wxMenuItemList::compatibility_iterator node;
+    wxMenuItem *item;
+    int pos ;
+
+    for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
+    {
+        item = (wxMenuItem *)node->GetData();
+        wxMenu* subMenu = item->GetSubMenu() ;
+        if (subMenu)
+        {
+            subMenu->MacAfterDisplay( true ) ;
+        }
+        else
+        {
+            // no need to undo hidings
+        }
+
+        previousItem = item ;
+    }
 }
 
 // Menu Bar
 
 }
 
 // Menu Bar
 
-/* 
+/*
 
 Mac Implementation note :
 
 
 Mac Implementation note :
 
@@ -765,21 +517,25 @@ The Mac has only one global menubar, so we attempt to install the currently
 active menubar from a frame, we currently don't take into account mdi-frames
 which would ask for menu-merging
 
 active menubar from a frame, we currently don't take into account mdi-frames
 which would ask for menu-merging
 
-Secondly there is no mac api for changing a menubar that is not the current 
+Secondly there is no mac api for changing a menubar that is not the current
 menubar, so we have to wait for preparing the actual menubar until the
 wxMenubar is to be used
 
 menubar, so we have to wait for preparing the actual menubar until the
 wxMenubar is to be used
 
-We can in subsequent versions use MacInstallMenuBar to provide some sort of 
+We can in subsequent versions use MacInstallMenuBar to provide some sort of
 auto-merge for MDI in case this will be necessary
 
 */
 
 wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
 auto-merge for MDI in case this will be necessary
 
 */
 
 wxMenuBar* wxMenuBar::s_macInstalledMenuBar = NULL ;
+wxMenuBar* wxMenuBar::s_macCommonMenuBar = NULL ;
+bool     wxMenuBar::s_macAutoWindowMenu = true ;
+WXHMENU  wxMenuBar::s_macWindowMenuHandle = NULL ;
 
 void wxMenuBar::Init()
 {
     m_eventHandler = this;
     m_menuBarFrame = NULL;
 
 void wxMenuBar::Init()
 {
     m_eventHandler = this;
     m_menuBarFrame = NULL;
+    m_invokingWindow = (wxWindow*) NULL;
 }
 
 wxMenuBar::wxMenuBar()
 }
 
 wxMenuBar::wxMenuBar()
@@ -792,14 +548,13 @@ wxMenuBar::wxMenuBar( long WXUNUSED(style) )
     Init();
 }
 
     Init();
 }
 
-
-wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
+wxMenuBar::wxMenuBar(size_t count, wxMenu *menus[], const wxString titles[], long WXUNUSED(style))
 {
     Init();
 
     m_titles.Alloc(count);
 
 {
     Init();
 
     m_titles.Alloc(count);
 
-    for ( int i = 0; i < count; i++ )
+    for ( size_t i = 0; i < count; i++ )
     {
         m_menus.Append(menus[i]);
         m_titles.Add(titles[i]);
     {
         m_menus.Append(menus[i]);
         m_titles.Add(titles[i]);
@@ -810,145 +565,211 @@ wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
 
 wxMenuBar::~wxMenuBar()
 {
 
 wxMenuBar::~wxMenuBar()
 {
-       if (s_macInstalledMenuBar == this)
-       {
-               ::ClearMenuBar();
-               s_macInstalledMenuBar = NULL;
-       }
+    if (s_macCommonMenuBar == this)
+        s_macCommonMenuBar = NULL;
 
 
+    if (s_macInstalledMenuBar == this)
+    {
+        ::ClearMenuBar();
+        s_macInstalledMenuBar = NULL;
+    }
 }
 
 }
 
-void wxMenuBar::Refresh()
+void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect))
 {
     wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
 
     DrawMenuBar();
 }
 
 {
     wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
 
     DrawMenuBar();
 }
 
-#if wxUSE_ACCEL
-
-void wxMenuBar::RebuildAccelTable()
+void wxMenuBar::MacInstallMenuBar()
 {
 {
-    // merge the accelerators of all menus into one accel table
-    size_t nAccelCount = 0;
-    size_t i, count = GetMenuCount();
-    for ( i = 0; i < count; i++ )
+    if ( s_macInstalledMenuBar == this )
+        return ;
+
+    MenuBarHandle menubar = NULL ;
+
+#if TARGET_API_MAC_OSX
+    menubar = NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ;
+#else
+    menubar = NewHandleClear( 12 ) ;
+    (*menubar)[3] = 0x0a ;
+#endif
+
+    ::SetMenuBar( menubar ) ;
+    DisposeMenuBar( menubar ) ;
+    MenuHandle appleMenu = NULL ;
+    char appleMenuTitle[3] = { 01 , kMenuAppleLogoFilledGlyph , 0 } ;
+
+    verify_noerr( CreateNewMenu( kwxMacAppleMenuId , 0 , &appleMenu ) ) ;
+    verify_noerr( SetMenuTitle( appleMenu , (ConstStr255Param) appleMenuTitle ) );
+
+    // Add About/Preferences separator only on OS X
+    // KH/RN: Separator is always present on 10.3 but not on 10.2
+    // However, the change from 10.2 to 10.3 suggests it is preferred
+#if TARGET_API_MAC_OSX
+    MacInsertMenuItem( appleMenu , "\p-" , 0 ) ;
+#endif
+
+    MacInsertMenuItem( appleMenu , "\pAbout..." , 0 ) ;
+    MacInsertMenu( appleMenu , 0 ) ;
+
+    // clean-up the help menu before adding new items
+    static MenuHandle mh = NULL ;
+
+    if ( mh != NULL )
+    {
+        MenuItemIndex firstUserHelpMenuItem ;
+        if ( UMAGetHelpMenu( &mh , &firstUserHelpMenuItem) == noErr )
+        {
+            for ( int i = CountMenuItems( mh ) ; i >= firstUserHelpMenuItem ; --i )
+                DeleteMenuItem( mh , i ) ;
+        }
+        else
+        {
+            mh = NULL ;
+        }
+    }
+
+#if TARGET_CARBON
+    if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId)
     {
     {
-        nAccelCount += m_menus[i]->GetAccelCount();
+        wxMenuItem *item = FindItem( wxApp::s_macPreferencesMenuItemId , NULL ) ;
+        if ( item == NULL || !(item->IsEnabled()) )
+            DisableMenuCommand( NULL , kHICommandPreferences ) ;
+        else
+            EnableMenuCommand( NULL , kHICommandPreferences ) ;
     }
 
     }
 
-    if ( nAccelCount )
+    // Unlike preferences which may or may not exist, the Quit item should be always
+    // enabled unless it is added by the application and then disabled, otherwise
+    // a program would be required to add an item with wxID_EXIT in order to get the
+    // Quit menu item to be enabled, which seems a bit burdensome.
+    if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macExitMenuItemId)
     {
     {
-        wxAcceleratorEntry *accelEntries = new wxAcceleratorEntry[nAccelCount];
+        wxMenuItem *item = FindItem( wxApp::s_macExitMenuItemId , NULL ) ;
+        if ( item != NULL && !(item->IsEnabled()) )
+            DisableMenuCommand( NULL , kHICommandQuit ) ;
+        else
+            EnableMenuCommand( NULL , kHICommandQuit ) ;
+    }
+#endif
 
 
-        nAccelCount = 0;
-        for ( i = 0; i < count; i++ )
+    wxMenuList::compatibility_iterator menuIter = m_menus.GetFirst();
+    for (size_t i = 0; i < m_menus.GetCount(); i++, menuIter = menuIter->GetNext())
+    {
+        wxMenuItemList::compatibility_iterator node;
+        wxMenuItem *item;
+        int pos ;
+        wxMenu* menu = menuIter->GetData() , *subMenu = NULL ;
+
+        if ( m_titles[i] == wxT("?") || m_titles[i] == wxT("&?")  || m_titles[i] == wxApp::s_macHelpMenuTitleName )
         {
         {
-            nAccelCount += m_menus[i]->CopyAccels(&accelEntries[nAccelCount]);
+            for (pos = 0 , node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++)
+            {
+                item = (wxMenuItem *)node->GetData();
+                subMenu = item->GetSubMenu() ;
+                if (subMenu)
+                {
+                    // we don't support hierarchical menus in the help menu yet
+                }
+                else
+                {
+                    if ( item->GetId() != wxApp::s_macAboutMenuItemId )
+                    {
+                        if ( mh == NULL )
+                        {
+                            MenuItemIndex firstUserHelpMenuItem ;
+                            if ( UMAGetHelpMenu( &mh , &firstUserHelpMenuItem) != noErr )
+                            {
+                                mh = NULL ;
+                                break ;
+                            }
+                        }
+                    }
+
+                    if ( item->IsSeparator() )
+                    {
+                        if ( mh )
+                            MacAppendMenu(mh, "\p-" );
+                    }
+                    else
+                    {
+                        wxAcceleratorEntry* entry = wxGetAccelFromString( item->GetText() ) ;
+
+                        if ( item->GetId() == wxApp::s_macAboutMenuItemId )
+                        {
+                            // this will be taken care of below
+                        }
+                        else
+                        {
+                            if ( mh )
+                            {
+                                UMAAppendMenuItem(mh, wxStripMenuCodes(item->GetText()) , wxFont::GetDefaultEncoding(), entry);
+                                SetMenuItemCommandID( mh , CountMenuItems(mh) , wxIdToMacCommand ( item->GetId() ) ) ;
+                                SetMenuItemRefCon( mh , CountMenuItems(mh) , (UInt32)item ) ;
+                            }
+                        }
+
+                        delete entry ;
+                    }
+                }
+            }
         }
         }
+        else
+        {
+            UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i], m_font.GetEncoding()  ) ;
+            menu->MacBeforeDisplay(false) ;
+            ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus, i)->GetHMenu()), 0);
+        }
+    }
 
 
-        m_accelTable = wxAcceleratorTable(nAccelCount, accelEntries);
-
-        delete [] accelEntries;
+    // take care of the about menu item wherever it is
+    {
+        wxMenu* aboutMenu ;
+        wxMenuItem *aboutMenuItem = FindItem(wxApp::s_macAboutMenuItemId , &aboutMenu) ;
+        if ( aboutMenuItem )
+        {
+            wxAcceleratorEntry* entry = wxGetAccelFromString( aboutMenuItem->GetText() ) ;
+            UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , wxStripMenuCodes ( aboutMenuItem->GetText() ) , wxFont::GetDefaultEncoding() );
+            UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true );
+            SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , kHICommandAbout ) ;
+            SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId ) , 1 , (UInt32)aboutMenuItem ) ;
+            UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId ) , 1 , entry ) ;
+        }
     }
     }
-}
 
 
-#endif // wxUSE_ACCEL
+    if ( GetAutoWindowMenu() )
+    {
+        if ( MacGetWindowMenuHMenu() == NULL )
+            CreateStandardWindowMenu( 0 , (MenuHandle*) &s_macWindowMenuHandle ) ;
 
 
+        InsertMenu( (MenuHandle) MacGetWindowMenuHMenu() , 0 ) ;
+    }
 
 
-void wxMenuBar::MacInstallMenuBar() 
-{
-       Handle menubar = ::GetNewMBar( kwxMacMenuBarResource ) ;
-       wxString message ;
-       wxCHECK_RET( menubar != NULL, "can't read MBAR resource" );
-       ::SetMenuBar( menubar ) ;
-       ::DisposeHandle( menubar ) ;
-
-               MenuHandle menu = ::GetMenuHandle( kwxMacAppleMenuId ) ;
-               ::AppendResMenu(menu, 'DRVR');
-       for (int i = 0; i < m_menus.GetCount(); i++)
-       {
-                       Str255  label;
-       wxNode *node;
-       wxMenuItem *item;
-       int pos ;
-                       wxMenu* menu = m_menus[i] , *subMenu = NULL ;
-               
-                       
-                       if( m_titles[i] == "?" || m_titles[i] == wxApp::s_macHelpMenuTitleName )
-                       {
-                               MenuHandle mh = NULL ;
-                               if ( HMGetHelpMenuHandle( &mh ) != noErr )
-                               {
-                                       continue ;
-                               }
-                               if ( formerHelpMenuItems == 0 )
-                               {
-                                       if( mh )
-                                               formerHelpMenuItems = CountMenuItems( mh ) ;
-                               }
-                                       
-                       for (pos = 0 , node = menu->GetMenuItems().First(); node; node = node->Next(), pos++) 
-                       {
-                                       item = (wxMenuItem *)node->Data();
-                                       subMenu = item->GetSubMenu() ;
-                                       if (subMenu)                    
-                                       {
-                                               // we don't support hierarchical menus in the help menu yet
-                                       }
-                                       else            
-                                       {
-                                               Str255 label ;
-                                               wxMacBuildMenuString( label , NULL , NULL , item->GetText(), item->GetId() != wxApp::s_macAboutMenuItemId); // no shortcut in about menu
-                                               if ( label[0] == 0 )
-                                               {
-                                                       // we cannot add empty menus on mac
-                                                       label[0] = 1 ;
-                                                       label[1] = ' ' ;
-                                               }
-                                               if ( item->GetId() == wxApp::s_macAboutMenuItemId )
-                                               { 
-                                                               ::SetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , label );
-               //                                      ::EnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 );
-                                                               ::EnableItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 );
-                                               }
-                                               else
-                                               {
-                                                       if ( mh )
-                                                               ::AppendMenu(mh, label );
-                                               }
-                                       }
-                               }
-                       }
-                       else
-                       {
-                               wxMacBuildMenuString( label, NULL , NULL , m_titles[i] , false );
-                               UMASetMenuTitle( menu->GetHMenu() , label ) ;
-                       for (pos = 0, node = menu->GetMenuItems().First(); node; node = node->Next(), pos++) 
-                       {
-                                       item = (wxMenuItem *)node->Data();
-                                       subMenu = item->GetSubMenu() ;
-                                       if (subMenu)                    
-                                       {
-                                               ::InsertMenu( subMenu->GetHMenu() , -1 ) ;
-                                       }
-                               }
-                               ::InsertMenu(m_menus[i]->GetHMenu(), 0);
-                       }
-               }
-               ::DrawMenuBar() ;
-
-       s_macInstalledMenuBar = this;
+    ::DrawMenuBar() ;
+    s_macInstalledMenuBar = this;
 }
 
 void wxMenuBar::EnableTop(size_t pos, bool enable)
 {
     wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
 }
 
 void wxMenuBar::EnableTop(size_t pos, bool enable)
 {
     wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
-       m_menus[pos]->MacEnableMenu( enable ) ;
+
+    _wxMenuAt(m_menus, pos)->MacEnableMenu( enable ) ;
     Refresh();
 }
 
     Refresh();
 }
 
+bool wxMenuBar::Enable(bool enable)
+{
+    wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") );
+
+    size_t i;
+    for (i = 0; i < GetMenuCount(); i++)
+        EnableTop(i, enable);
+
+    return true;
+}
+
 void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
 {
     wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
 void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
 {
     wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
@@ -956,16 +777,15 @@ void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
     m_titles[pos] = label;
 
     if ( !IsAttached() )
     m_titles[pos] = label;
 
     if ( !IsAttached() )
-    {
         return;
         return;
-    }
 
 
-    m_menus[pos]->SetTitle( label ) ;
-       if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
-       {
-               ::SetMenuBar( GetMenuBar() ) ;
-               ::InvalMenuBar() ;
-       }
+    _wxMenuAt(m_menus, pos)->SetTitle( label ) ;
+
+    if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
+    {
+        ::SetMenuBar( GetMenuBar() ) ;
+        ::InvalMenuBar() ;
+    }
 }
 
 wxString wxMenuBar::GetLabelTop(size_t pos) const
 }
 
 wxString wxMenuBar::GetLabelTop(size_t pos) const
@@ -985,18 +805,12 @@ int wxMenuBar::FindMenu(const wxString& title)
     {
         wxString title = wxStripMenuCodes(m_titles[i]);
         if ( menuTitle == title )
     {
         wxString title = wxStripMenuCodes(m_titles[i]);
         if ( menuTitle == title )
-            return i; 
+            return i;
     }
 
     return wxNOT_FOUND;
     }
 
     return wxNOT_FOUND;
-
 }
 
 }
 
-
-// ---------------------------------------------------------------------------
-// wxMenuBar construction
-// ---------------------------------------------------------------------------
-
 // ---------------------------------------------------------------------------
 // wxMenuBar construction
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 // wxMenuBar construction
 // ---------------------------------------------------------------------------
@@ -1005,116 +819,62 @@ wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
 {
     wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
     if ( !menuOld )
 {
     wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
     if ( !menuOld )
-        return FALSE;
+        return false;
+
     m_titles[pos] = title;
 
     if ( IsAttached() )
     {
     m_titles[pos] = title;
 
     if ( IsAttached() )
     {
-               if (s_macInstalledMenuBar == this)
-               {
-                       ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
-                       {
-                               Str255  label;
-                               wxMacBuildMenuString( label, NULL , NULL , title , false );
-                               UMASetMenuTitle( menu->GetHMenu() , label ) ;
-                               if ( pos == m_menus.GetCount() - 1)
-                               {
-                                       ::InsertMenu( menu->GetHMenu() , 0 ) ;
-                               }
-                               else
-                               {
-                                       ::InsertMenu( menu->GetHMenu() , m_menus[pos+1]->MacGetMenuId() ) ;
-                               }
-                       }
-               }
-
-
-#if wxUSE_ACCEL
-        if ( menuOld->HasAccels() || menu->HasAccels() )
+        if (s_macInstalledMenuBar == this)
         {
         {
-            // need to rebuild accell table
-            RebuildAccelTable();
+            menuOld->MacAfterDisplay( false ) ;
+            ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
+
+            menu->MacBeforeDisplay( false ) ;
+            UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
+            if ( pos == m_menus.GetCount() - 1)
+                ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
+            else
+                ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , _wxMenuAt(m_menus, pos + 1)->MacGetMenuId() ) ;
         }
         }
-#endif // wxUSE_ACCEL
 
         Refresh();
     }
 
 
         Refresh();
     }
 
+    if (m_invokingWindow)
+        wxMenubarSetInvokingWindow( menu, m_invokingWindow );
+
     return menuOld;
 }
 
 bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
 {
     if ( !wxMenuBarBase::Insert(pos, menu, title) )
     return menuOld;
 }
 
 bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
 {
     if ( !wxMenuBarBase::Insert(pos, menu, title) )
-        return FALSE;
+        return false;
 
     m_titles.Insert(title, pos);
 
 
     m_titles.Insert(title, pos);
 
-    menu->Attach(this);
+    UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
 
 
-    if ( IsAttached() )
+    if ( IsAttached() && s_macInstalledMenuBar == this )
     {
     {
-       if ( pos == (size_t) -1 )
-               {
-                       ::InsertMenu( menu->GetHMenu() , 0 ) ;
-               }
-               else
-               {
-                       ::InsertMenu( menu->GetHMenu() , m_menus[pos+1]->MacGetMenuId() ) ;
-               }
-
-#if wxUSE_ACCEL
-        if ( menu->HasAccels() )
+        if (s_macInstalledMenuBar == this)
         {
         {
-            // need to rebuild accell table
-            RebuildAccelTable();
+            menu->MacBeforeDisplay( false ) ;
+
+            if ( pos == (size_t) -1  || pos + 1 == m_menus.GetCount() )
+                ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
+            else
+                ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , _wxMenuAt(m_menus, pos+1)->MacGetMenuId() ) ;
         }
         }
-#endif // wxUSE_ACCEL
 
         Refresh();
     }
 
 
         Refresh();
     }
 
-    return TRUE;
-}
+    if (m_invokingWindow)
+        wxMenubarSetInvokingWindow( menu, m_invokingWindow );
 
 
-void wxMenuBar::MacMenuSelect(wxEvtHandler* handler, long when , int macMenuId, int macMenuItemNum)
-{
-       // first scan fast for direct commands, i.e. menus which have these commands directly in their own list
-
-       if ( macMenuId == kwxMacAppleMenuId && macMenuItemNum == 1 )
-       {
-                       wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, wxApp::s_macAboutMenuItemId );
-                       event.m_timeStamp = when;
-                       event.SetEventObject(handler);
-       event.SetInt( wxApp::s_macAboutMenuItemId );
-                       handler->ProcessEvent(event);
-       }
-       else
-       {               
-         for (int i = 0; i < m_menus.GetCount() ; i++)
-         {
-               if ( m_menus[i]->MacGetMenuId() == macMenuId || 
-                       ( macMenuId == kHMHelpMenuID && ( m_titles[i] == "?" || m_titles[i] == wxApp::s_macHelpMenuTitleName ) )
-                       )
-               {
-                       if ( m_menus[i]->MacMenuSelect( handler , when , macMenuId , macMenuItemNum ) )
-                               return ;
-                       else
-                       {
-                               //TODO flag this as an error since it must contain the item
-                               return ;
-                       }
-               }
-               }
-       
-         for (int i = 0; i < m_menus.GetCount(); i++)
-         {
-               if ( m_menus[i]->MacMenuSelect( handler , when , macMenuId , macMenuItemNum ) )
-               {
-                       break ;
-               }
-         }
-       }
+    return true;
 }
 
 wxMenu *wxMenuBar::Remove(size_t pos)
 }
 
 wxMenu *wxMenuBar::Remove(size_t pos)
@@ -1125,25 +885,13 @@ wxMenu *wxMenuBar::Remove(size_t pos)
 
     if ( IsAttached() )
     {
 
     if ( IsAttached() )
     {
-               if (s_macInstalledMenuBar == this)
-               {
-                       ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
-               }
-
-        menu->Detach();
-
-#if wxUSE_ACCEL
-        if ( menu->HasAccels() )
-        {
-            // need to rebuild accell table
-            RebuildAccelTable();
-        }
-#endif // wxUSE_ACCEL
+        if (s_macInstalledMenuBar == this)
+            ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
 
         Refresh();
     }
 
 
         Refresh();
     }
 
-    m_titles.Remove(pos);
+    m_titles.RemoveAt(pos);
 
     return menu;
 }
 
     return menu;
 }
@@ -1151,34 +899,103 @@ wxMenu *wxMenuBar::Remove(size_t pos)
 bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
 {
     WXHMENU submenu = menu ? menu->GetHMenu() : 0;
 bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
 {
     WXHMENU submenu = menu ? menu->GetHMenu() : 0;
-    wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
+        wxCHECK_MSG( submenu, false, wxT("can't append invalid menu to menubar") );
 
     if ( !wxMenuBarBase::Append(menu, title) )
 
     if ( !wxMenuBarBase::Append(menu, title) )
-        return FALSE;
-
-    menu->Attach(this);
+        return false;
 
     m_titles.Add(title);
 
 
     m_titles.Add(title);
 
+    UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title , m_font.GetEncoding() ) ;
+
     if ( IsAttached() )
     {
     if ( IsAttached() )
     {
-               if (s_macInstalledMenuBar == this)
-               {
-                       ::InsertMenu( menu->GetHMenu() , 0 ) ;
-               }
-
-#if wxUSE_ACCEL
-        if ( menu->HasAccels() )
+        if (s_macInstalledMenuBar == this)
         {
         {
-            // need to rebuild accell table
-            RebuildAccelTable();
+            menu->MacBeforeDisplay( false ) ;
+            ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
         }
         }
-#endif // wxUSE_ACCEL
 
         Refresh();
     }
 
 
         Refresh();
     }
 
-    return TRUE;
+    // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
+    // adding menu later on.
+    if (m_invokingWindow)
+        wxMenubarSetInvokingWindow( menu, m_invokingWindow );
+
+    return true;
+}
+
+static void wxMenubarUnsetInvokingWindow( wxMenu *menu )
+{
+    menu->SetInvokingWindow( (wxWindow*) NULL );
+    wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
+
+    while (node)
+    {
+        wxMenuItem *menuitem = node->GetData();
+        if (menuitem->IsSubMenu())
+            wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu() );
+
+        node = node->GetNext();
+    }
+}
+
+static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
+{
+    menu->SetInvokingWindow( win );
+    wxMenuItem *menuitem;
+    wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
+
+    while (node)
+    {
+        menuitem = node->GetData();
+        if (menuitem->IsSubMenu())
+            wxMenubarSetInvokingWindow( menuitem->GetSubMenu() , win );
+
+        node = node->GetNext();
+    }
+}
+
+void wxMenuBar::UnsetInvokingWindow()
+{
+    m_invokingWindow = (wxWindow*) NULL;
+    wxMenu *menu;
+    wxMenuList::compatibility_iterator node = m_menus.GetFirst();
+
+    while (node)
+    {
+        menu = node->GetData();
+        wxMenubarUnsetInvokingWindow( menu );
+
+        node = node->GetNext();
+    }
+}
+
+void wxMenuBar::SetInvokingWindow(wxFrame *frame)
+{
+    m_invokingWindow = frame;
+    wxMenu *menu;
+    wxMenuList::compatibility_iterator node = m_menus.GetFirst();
+
+    while (node)
+    {
+        menu = node->GetData();
+        wxMenubarSetInvokingWindow( menu, frame );
+
+        node = node->GetNext();
+    }
+}
+
+void wxMenuBar::Detach()
+{
+    wxMenuBarBase::Detach() ;
+}
+
+void wxMenuBar::Attach(wxFrame *frame)
+{
+    wxMenuBarBase::Attach( frame ) ;
 }
 
 // ---------------------------------------------------------------------------
 }
 
 // ---------------------------------------------------------------------------
@@ -1194,8 +1011,8 @@ int wxMenuBar::FindMenuItem(const wxString& menuString,
     for ( size_t i = 0; i < count; i++ )
     {
         wxString title = wxStripMenuCodes(m_titles[i]);
     for ( size_t i = 0; i < count; i++ )
     {
         wxString title = wxStripMenuCodes(m_titles[i]);
-        if ( menuString == title )
-            return m_menus[i]->FindItem(itemString);
+        if ( menuLabel == title )
+            return _wxMenuAt(m_menus, i)->FindItem(itemString);
     }
 
     return wxNOT_FOUND;
     }
 
     return wxNOT_FOUND;
@@ -1209,11 +1026,7 @@ wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
     wxMenuItem *item = NULL;
     size_t count = GetMenuCount();
     for ( size_t i = 0; !item && (i < count); i++ )
     wxMenuItem *item = NULL;
     size_t count = GetMenuCount();
     for ( size_t i = 0; !item && (i < count); i++ )
-    {
-        item = m_menus[i]->FindItem(id, itemMenu);
-    }
+        item = _wxMenuAt(m_menus, i)->FindItem(id, itemMenu);
 
     return item;
 }
 
     return item;
 }
-
-