]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/menu.cpp
A little clarification
[wxWidgets.git] / src / mac / menu.cpp
index b22001b870b32f575de8fcda9122758d5177a9f4..046f7e0166fbb7097e0611b2f72ff99a260d74dd 100644 (file)
@@ -1,14 +1,18 @@
 /////////////////////////////////////////////////////////////////////////////
 // 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
 /////////////////////////////////////////////////////////////////////////////
 
 /////////////////////////////////////////////////////////////////////////////
 
+#ifdef __GNUG__
+#pragma implementation "menu.h"
+#pragma implementation "menuitem.h"
+#endif
 
 // ============================================================================
 // headers & declarations
 
 // ============================================================================
 // headers & declarations
 // wxWindows headers
 // -----------------
 
 // wxWindows headers
 // -----------------
 
-#ifdef __GNUG__
-#pragma implementation "menu.h"
-#pragma implementation "menuitem.h"
-#endif
-
+#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"
 
@@ -40,7 +42,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
 
 // the (popup) menu title has this special id
 static const int idMenuTitle = -2;
 
 // the (popup) menu title has this special id
 static const int idMenuTitle = -2;
-static int formerHelpMenuItems = 0 ;
+static MenuItemIndex firstUserHelpMenuItem = 0 ;
 
 const short kwxMacMenuBarResource = 1 ;
 const short kwxMacAppleMenuId = 1 ;
 
 const short kwxMacMenuBarResource = 1 ;
 const short kwxMacAppleMenuId = 1 ;
@@ -48,657 +50,379 @@ const short kwxMacAppleMenuId = 1 ;
 // ============================================================================
 // implementation
 // ============================================================================
 // ============================================================================
 // implementation
 // ============================================================================
-
-//
-// Helper Functions to get Mac Menus the way they should be ;-)
-//
-
-void wxMacCtoPString(const char* theCString, Str255 thePString);
-
-// remove inappropriate characters, if useShortcuts is false, the ampersand will not auto-generate a mac menu-shortcut
-
-static void wxMacBuildMenuString(StringPtr outMacItemText, char *outMacShortcutChar , short *outMacModifiers , const char *inItemName , bool useShortcuts )
-{
-       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, 5) == 0) 
-                                               {
-                                                       inItemName = inItemName + 5;
-                                                       macShortCut = *inItemName;
-                                               }
-                                               else if (strncmp("Alt+", inItemName, 4) == 0) 
-                                               {
-                                                       inItemName = inItemName + 4;
-                                                       macModifiers |= kMenuOptionModifier ;
-                                                       macShortCut = *inItemName ;
-                                               }
-                                               else if (strncmp("Shift+", inItemName, 6) == 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 ;
-       }
-}
+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
 
 
-wxMenu::wxMenu(const wxString& title, const wxFunction func)
+void wxMenu::Init()
 {
 {
-    m_title = title;
-    m_parent = NULL;
-    m_eventHandler = this;
-    m_noItems = 0;
-    m_menuBar = NULL;
-    m_pInvokingWindow = NULL ;
-    m_clientData = (void*) NULL;
-    if (m_title != "")
+    m_doBreak = FALSE;
+    m_startRadioGroup = -1;
+
+    // create the menu
+    m_macMenuId = s_macNextMenuId++;
+    m_hMenu = UMANewMenu(m_macMenuId, m_title);
+
+    if ( !m_hMenu )
+    {
+        wxLogLastError(wxT("UMANewMenu failed"));
+    }
+
+    // if we have a title, insert it in the beginning of the menu
+    if ( !!m_title )
     {
         Append(idMenuTitle, m_title) ;
         AppendSeparator() ;
     }
     {
         Append(idMenuTitle, m_title) ;
         AppendSeparator() ;
     }
-
-    Callback(func);
-
-       Str255  label;
-       wxMacBuildMenuString( label, NULL , NULL , title , false );
-       m_macMenuId = s_macNextMenuId++; 
-    wxCHECK_RET( s_macNextMenuId < 236 , "menu ids > 235 cannot be used for submenus on mac" );
-       m_macMenuHandle = ::NewMenu(m_macMenuId, label);
-       m_macMenuEnabled = true ;
 }
 
 }
 
-// The wxWindow destructor will take care of deleting the submenus.
 wxMenu::~wxMenu()
 {
 wxMenu::~wxMenu()
 {
-    wxNode *node = m_menuItems.First();
-    while (node)
-    {
-        wxMenuItem *item = (wxMenuItem *)node->Data();
-
-        // Delete child menus.
-        // Beware: they must not be appended to children list!!!
-        // (because order of delete is significant)
-        if (item->GetSubMenu())
-            item->DeleteSubMenu();
-
-        wxNode *next = node->Next();
-        delete item;
-        delete node;
-        node = next;
-    }
-       if (m_macMenuHandle)
-               ::DisposeMenu(m_macMenuHandle);
+    if (MAC_WXHMENU(m_hMenu))
+        ::DisposeMenu(MAC_WXHMENU(m_hMenu));
 }
 
 void wxMenu::Break()
 {
 }
 
 void wxMenu::Break()
 {
-       // not available on the mac platform
-}
-
-// function appends a new item or submenu to the menu
-void wxMenu::Append(wxMenuItem *pItem)
-{
-    wxCHECK_RET( pItem != NULL, "can't append NULL item to the menu" );
-
-    m_menuItems.Append(pItem);
-
-       if ( pItem->IsSeparator() )
-       {
-               MacAppendMenu(m_macMenuHandle, "\p-");
-       }
-       else 
-       {
-               wxMenu *pSubMenu = pItem->GetSubMenu() ;
-               if ( pSubMenu != NULL )
-               {
-                       Str255 label;
-                       wxCHECK_RET( pSubMenu->m_macMenuHandle != NULL , "invalid submenu added");
-                   pSubMenu->m_parent = this ;
-                       wxMacBuildMenuString( label , NULL , NULL , pItem->GetName() ,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::s_macInstalledMenuBar == m_menuBar) 
-                       {
-                               ::InsertMenu( pSubMenu->m_macMenuHandle , -1 ) ;
-                       }
-                       
-                       ::AppendMenu(m_macMenuHandle, label);
-               }
-               else
-               {
-                       Str255 label ;
-                       wxMacBuildMenuString( label , NULL , NULL , pItem->GetName(), pItem->GetId() == wxApp::s_macAboutMenuItemId);
-                       if ( label[0] == 0 )
-                       {
-                               // we cannot add empty menus on mac
-                               label[0] = 1 ;
-                               label[1] = ' ' ;
-                       }
-                       ::AppendMenu(m_macMenuHandle, label );
-                       if ( pItem->GetId() == idMenuTitle ) 
-                       {
-                                       UMADisableMenuItem( m_macMenuHandle , CountMItems( m_macMenuHandle ) ) ;
-                       }
-               }
-       }
-
-    m_noItems++;
-}
-
-void wxMenu::AppendSeparator()
-{
-    Append(new wxMenuItem(this, ID_SEPARATOR));
+    // not available on the mac platform
 }
 
 }
 
-// Pullright item
-void wxMenu::Append(int Id, const wxString& label, wxMenu *SubMenu, 
-                    const wxString& helpString)
+void wxMenu::Attach(wxMenuBarBase *menubar)
 {
 {
-    Append(new wxMenuItem(this, Id, label, helpString, FALSE, SubMenu));
-}
+    wxMenuBase::Attach(menubar);
 
 
-// Ordinary menu item
-void wxMenu::Append(int Id, const wxString& label, 
-                    const wxString& helpString, bool checkable)
-{
-  // 'checkable' parameter is useless for Windows.
-    Append(new wxMenuItem(this, Id, label, helpString, checkable));
+    EndRadioGroup();
 }
 
 }
 
-void wxMenu::Delete(int id)
+// 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)
 {
 {
-    wxNode *node;
-    wxMenuItem *item;
-    int pos;
+    wxASSERT_MSG( pItem != NULL, wxT("can't append NULL item to the menu") );
 
 
-    for (pos = 0, node = m_menuItems.First(); node; node = node->Next(), pos++) {
-        item = (wxMenuItem *)node->Data();
-        if (item->GetId() == id)
-               break;
+    if ( pItem->IsSeparator() )
+    {
+        if ( pos == (size_t)-1 )
+            MacAppendMenu(MAC_WXHMENU(m_hMenu), "\p-");
+        else
+            MacInsertMenuItem(MAC_WXHMENU(m_hMenu), "\p-" , pos);
     }
     }
-
-    if (!node)
-               return;
-
-    int index = pos + 1 ;
-
-    if (index < 1)
-               return;
-
-       wxMenu *pSubMenu = item->GetSubMenu();
-       if ( pSubMenu != NULL ) 
-       {
-               ::DeleteMenuItem( m_macMenuHandle , index);
-               pSubMenu->m_parent = NULL;
-               // TODO: Why isn't subMenu deleted here???
-               // Will put this in for now. Assuming this is supposed
-               // to delete the menu, not just remove it.
-               item->DeleteSubMenu();
-       }
-       else 
-       {
-               ::DeleteMenuItem( m_macMenuHandle , index);
-       }
-
-    m_menuItems.DeleteNode(node);
-       // TODO shouldn't we do this ? \8e_m_noItems--; 
-    delete item;
-}
-
-void wxMenu::Enable(int Id, bool Flag)
-{
-    wxMenuItem *item = FindItemForId(Id);
-    wxCHECK_RET( item != NULL, "can't enable non-existing menu item" );
-
-    item->Enable(Flag);
-}
-
-bool wxMenu::Enabled(int Id) const
-{
-    wxMenuItem *item = FindItemForId(Id);
-    wxCHECK( item != NULL, FALSE );
-
-    return item->IsEnabled();
+    else
+    {
+        wxMenu *pSubMenu = pItem->GetSubMenu() ;
+        if ( pSubMenu != NULL )
+        {
+               wxASSERT_MSG( pSubMenu->m_hMenu != NULL , wxT("invalid submenu added"));
+            pSubMenu->m_menuParent = this ;
+
+            if (wxMenuBar::MacGetInstalledMenuBar() == m_menuBar)
+            {
+                pSubMenu->MacBeforeDisplay( true ) ;
+             }
+
+            if ( pos == (size_t)-1 )
+                UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu), pItem->GetText(), pSubMenu->m_macMenuId);
+            else
+                UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu), pItem->GetText() , pos, pSubMenu->m_macMenuId);
+            pItem->UpdateItemBitmap() ;
+            pItem->UpdateItemStatus() ;
+        }
+        else
+        {
+            if ( pos == (size_t)-1 )
+            {
+                UMAAppendMenuItem(MAC_WXHMENU(m_hMenu), wxT("a") );
+                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") , pos);
+                pos += 1 ;
+            }
+
+            SetMenuItemCommandID( MAC_WXHMENU(m_hMenu) , pos , pItem->GetId() ) ;
+            pItem->UpdateItemText() ;
+            pItem->UpdateItemBitmap() ;
+            pItem->UpdateItemStatus() ;
+
+              if ( pItem->GetId() == idMenuTitle )
+              {
+                UMAEnableMenuItem(MAC_WXHMENU(m_hMenu) , pos , false ) ;
+              }
+        }
+    }
+    // if we're already attached to the menubar, we must update it
+    if ( IsAttached() )
+    {
+        m_menuBar->Refresh();
+    }
+    return TRUE ;
 }
 
 }
 
-void wxMenu::Check(int Id, bool Flag)
+void wxMenu::EndRadioGroup()
 {
 {
-    wxMenuItem *item = FindItemForId(Id);
-    wxCHECK_RET( item != NULL, "can't get status of non-existing menu item" );
-
-    item->Check(Flag);
+    // we're not inside a radio group any longer
+    m_startRadioGroup = -1;
 }
 
 }
 
-bool wxMenu::Checked(int Id) const
+bool wxMenu::DoAppend(wxMenuItem *item)
 {
 {
-    wxMenuItem *item = FindItemForId(Id);
-    wxCHECK( item != NULL, FALSE );
+    wxCHECK_MSG( item, FALSE, _T("NULL item in wxMenu::DoAppend") );
 
 
-    return item->IsChecked();
-}
+    bool check = FALSE;
 
 
-void wxMenu::SetTitle(const wxString& label)
-{
-       Str255 title ;
-    m_title = label ;
-       wxMacBuildMenuString( title, NULL , NULL , label , false );
-       UMASetMenuTitle( m_macMenuHandle , title ) ;
-       if (wxMenuBar::s_macInstalledMenuBar == m_menuBar) // are we currently installed ?
-       {
-               ::SetMenuBar( GetMenuBar() ) ;
-               ::InvalMenuBar() ;
-       }
-       // TODO:for submenus -> their parent item text must be corrected
-}
+    if ( item->GetKind() == wxITEM_RADIO )
+    {
+        int count = GetMenuItemCount();
 
 
-const wxString wxMenu::GetTitle() const
-{
-    return m_title;
-}
+        if ( m_startRadioGroup == -1 )
+        {
+            // start a new radio group
+            m_startRadioGroup = count;
 
 
-void wxMenu::SetLabel(int id, const wxString& label)
-{
-    Str255 maclabel ;
-   int index ;
-    wxMenuItem *item = FindItemForId(id) ;
-    if (item==NULL)
-        return;
+            // for now it has just one element
+            item->SetAsRadioGroupStart();
+            item->SetRadioGroupEnd(m_startRadioGroup);
 
 
-    index = MacGetIndexFromItem( item ) ;
-    if (index < 1)
-               return;
+            // 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::Node *node = GetMenuItems().Item(m_startRadioGroup);
+
+            if ( node )
+            {
+                node->GetData()->SetRadioGroupEnd(count);
+            }
+            else
+            {
+                wxFAIL_MSG( _T("where is the radio group start item?") );
+            }
+        }
+    }
+    else // not a radio item
+    {
+        EndRadioGroup();
+    }
 
 
-    if (item->GetSubMenu()==NULL)
+    if ( !wxMenuBase::DoAppend(item) || !DoInsertOrAppend(item) )
     {
     {
-               wxMacBuildMenuString( maclabel , NULL , NULL , label , false );
-               ::SetMenuItemText( m_macMenuHandle , index , maclabel ) ;
+        return FALSE;
     }
     }
-    else
+
+    if ( check )
     {
     {
-               wxMacBuildMenuString( maclabel , NULL , NULL , label , false );
-               ::SetMenuItemText( m_macMenuHandle , index , maclabel ) ;
+        // check the item initially
+        item->Check(TRUE);
     }
     }
-    item->SetName(label);
+
+    return TRUE;
 }
 
 }
 
-wxString wxMenu::GetLabel(int Id) const
+bool wxMenu::DoInsert(size_t pos, wxMenuItem *item)
 {
 {
-    wxMenuItem *pItem = FindItemForId(Id) ;
-    return pItem->GetName() ;
+    return wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos);
 }
 
 }
 
-// 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);
-
-    for (wxNode * node = m_menuItems.First (); node; node = node->Next ())
+    // we need to find the items position in the child list
+    size_t pos;
+    wxMenuItemList::Node *node = GetMenuItems().GetFirst();
+    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();
-      }
-    }
+        if ( node->GetData() == item )
+            break;
 
 
-    return -1;
-}
+        node = node->GetNext();
+    }
 
 
-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 ();
+    // DoRemove() (unlike Remove) can only be called for existing item!
+    wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
 
 
-        if (item->GetId() == itemId)
-        {
-            if (itemMenu)
-                *itemMenu = (wxMenu *) this;
-            return item;
-        }
+    ::DeleteMenuItem(MAC_WXHMENU(m_hMenu) , pos + 1);
 
 
-        if (item->GetSubMenu())
-        {
-            wxMenuItem *ans = item->GetSubMenu()->FindItemForId (itemId, itemMenu);
-            if (ans)
-                return ans;
-        }
+    if ( IsAttached() )
+    {
+        // otherwise, the change won't be visible
+        m_menuBar->Refresh();
     }
 
     }
 
-    if (itemMenu)
-        *itemMenu = NULL;
-    return NULL;
-}
-
-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 ) ;
 }
 }
-
-void wxMenu::ProcessCommand(wxCommandEvent & event)
+bool wxMenu::ProcessCommand(wxCommandEvent & event)
 {
     bool processed = FALSE;
 
 {
     bool processed = FALSE;
 
-    // Try a callback
-    if (m_callback)
-    {
-            (void) (*(m_callback)) (*this, event);
-            processed = TRUE;
-    }
-
     // Try the menu's event handler
     if ( !processed && GetEventHandler())
     {
     // Try the menu's event handler
     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)
-  if ( !processed && GetInvokingWindow())
-    processed = GetInvokingWindow()->GetEventHandler()->ProcessEvent(event);
+    // 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);
+
+    return processed;
 }
 
 }
 
-bool wxWindow::PopupMenu(wxMenu *menu, int x, int y)
-{
-       menu->SetInvokingWindow(this);
-       ClientToScreen( &x , &y ) ;
 
 
-       ::InsertMenu( menu->m_macMenuHandle , -1 ) ;
-  long menuResult = ::PopUpMenuSelect(menu->m_macMenuHandle ,y,x, 0) ;
-  menu->MacMenuSelect( this , TickCount() , HiWord(menuResult) , LoWord(menuResult) ) ;
-       ::DeleteMenu( menu->m_macMenuId ) ;
-  menu->SetInvokingWindow(NULL);
+// ---------------------------------------------------------------------------
+// other
+// ---------------------------------------------------------------------------
 
 
-  return TRUE;
+wxWindow *wxMenu::GetWindow() const
+{
+    if ( m_invokingWindow != NULL )
+        return m_invokingWindow;
+    else if ( m_menuBar != NULL)
+        return (wxWindow *) m_menuBar->GetFrame();
+
+    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 )
 {
 {
-    wxNode *node;
-    wxMenuItem *item;
-    int pos;
-       
-    for (pos = 0, node = m_menuItems.First(); node; node = node->Next(), pos++) 
+    size_t pos;
+    wxMenuItemList::Node *node = GetMenuItems().GetFirst();
+    for ( pos = 0; node; pos++ )
     {
     {
-               item = (wxMenuItem *)node->Data();
-               if (item->GetId() == id)
-                       break;
+        if ( node->GetData()->GetId() == id )
+            break;
+
+        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 )
 {
 {
-    wxNode *node;
-    int pos;
-
-    for (pos = 0, node = m_menuItems.First(); node; node = node->Next(), pos++) 
+    size_t pos;
+    wxMenuItemList::Node *node = GetMenuItems().GetFirst();
+    for ( pos = 0; node; pos++ )
     {
     {
-               if ((wxMenuItem *)node->Data() == pItem)
-                       break;
+        if ( node->GetData() == pItem )
+            break;
+
+        node = node->GetNext();
     }
 
     if (!node)
     }
 
     if (!node)
-               return 0;
-               
-       return pos + 1 ;
+        return 0;
+
+    return pos + 1 ;
 }
 
 }
 
-void wxMenu::MacEnableMenu( bool bDoEnable ) 
+void wxMenu::MacEnableMenu( bool bDoEnable )
 {
 {
-       m_macMenuEnabled = bDoEnable ;
-       if ( bDoEnable )
-               UMAEnableMenuItem( m_macMenuHandle , 0 ) ;
-       else
-               UMADisableMenuItem( m_macMenuHandle , 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 )
+{
+    wxMenuItem* previousItem = NULL ;
+    size_t pos ;
+    wxMenuItemList::Node *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
+        {
+            #if TARGET_CARBON
+            if ( UMAGetSystemVersion() >= 0x1000 )
+            {
+                if ( item->GetId() == wxApp::s_macPreferencesMenuItemId || item->GetId() == wxApp::s_macExitMenuItemId)
+                {
+                    ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos + 1, kMenuItemAttrHidden, 0 );
+                    if ( GetMenuItems().GetCount() == pos + 1 &&
+                            previousItem != NULL &&
+                                previousItem->IsSeparator() )
+                    {
+                        ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ) , pos , kMenuItemAttrHidden, 0 );
+                    }
+                }
+            }
+            #endif
+        }
+        previousItem = item ;
+    }
+
+    if ( isSubMenu )
+        ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1);
+
+}
+// undo all changes from the MacBeforeDisplay call
+void wxMenu::MacAfterDisplay( bool isSubMenu )
 {
 {
-  int pos;
-  wxNode *node;
-
-       if ( m_macMenuId == macMenuId )
-       {
-               node = m_menuItems.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 ;
-
-                   // Try a callback
-                   if (m_callback)
-                   {
-                           (void) (*(m_callback)) (*this, event);
-                           processed = TRUE;
-                   }
-               
-                   // 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 = m_menuItems.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 ;
-                                   // Try a callback
-                                   if (m_callback)
-                                   {
-                                           (void) (*(m_callback)) (*this, event);
-                                           processed = TRUE;
-                                   }
-                               
-                                   // 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 = m_menuItems.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 ;
+    if ( isSubMenu )
+        ::DeleteMenu(MacGetMenuId());
+
+    wxMenuItem* previousItem = NULL ;
+    int pos ;
+    wxMenuItemList::Node *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->MacAfterDisplay( true ) ;
+        }
+        else
+        {
+            // no need to undo hidings
+        }
+        previousItem = item ;
+    }
 }
 
 // Menu Bar
 
 }
 
 // Menu Bar
 
-/* 
+/*
 
 Mac Implementation note :
 
 
 Mac Implementation note :
 
@@ -706,438 +430,449 @@ 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 ;
 
 
-wxMenuBar::wxMenuBar()
+void wxMenuBar::Init()
 {
     m_eventHandler = this;
 {
     m_eventHandler = this;
-    m_menuCount = 0;
-    m_menus = NULL;
-    m_titles = NULL;
     m_menuBarFrame = NULL;
     m_menuBarFrame = NULL;
+    m_invokingWindow = (wxWindow*) NULL;
 }
 
 }
 
-wxMenuBar::wxMenuBar(int n, wxMenu *menus[], const wxString titles[])
+wxMenuBar::wxMenuBar()
 {
 {
-    m_eventHandler = this;
-    m_menuCount = n;
-    m_menus = menus;
-    m_titles = new wxString[n];
-    int i;
-    for ( i = 0; i < n; i++ )
-                       m_titles[i] = titles[i];
-    m_menuBarFrame = NULL;
+    Init();
+}
+
+wxMenuBar::wxMenuBar( long WXUNUSED(style) )
+{
+    Init();
+}
+
+
+wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[])
+{
+    Init();
+
+    m_titles.Alloc(count);
+
+    for ( int i = 0; i < count; i++ )
+    {
+        m_menus.Append(menus[i]);
+        m_titles.Add(titles[i]);
+
+        menus[i]->Attach(this);
+    }
 }
 
 wxMenuBar::~wxMenuBar()
 {
 }
 
 wxMenuBar::~wxMenuBar()
 {
-       if (s_macInstalledMenuBar == this)
-       {
-               ::ClearMenuBar();
-               s_macInstalledMenuBar = NULL;
-       }
-
-    int i;
-    for (i = 0; i < m_menuCount; i++)
+    if (s_macCommonMenuBar == this)
+        s_macCommonMenuBar = NULL;
+    if (s_macInstalledMenuBar == this)
     {
     {
-        delete m_menus[i];
+        ::ClearMenuBar();
+        s_macInstalledMenuBar = NULL;
     }
     }
-    delete[] m_menus;
-    delete[] m_titles;
 
 }
 
 
 }
 
-void wxMenuBar::MacInstallMenuBar() 
+void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground), const wxRect *WXUNUSED(rect))
 {
 {
-       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_menuCount; 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->m_menuItems.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->GetName(), 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->m_macMenuHandle , label ) ;
-                       for (pos = 0, node = menu->m_menuItems.First(); node; node = node->Next(), pos++) 
-                       {
-                                       item = (wxMenuItem *)node->Data();
-                                       subMenu = item->GetSubMenu() ;
-                                       if (subMenu)                    
-                                       {
-                                               ::InsertMenu( subMenu->m_macMenuHandle , -1 ) ;
-                                       }
-                               }
-                               ::InsertMenu(m_menus[i]->m_macMenuHandle, 0);
-                       }
-               }
-               ::DrawMenuBar() ;
-
-       s_macInstalledMenuBar = this;
-}
+    wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
 
 
+    DrawMenuBar();
+}
 
 
-// Must only be used AFTER menu has been attached to frame,
-// otherwise use individual menus to enable/disable items
-void wxMenuBar::Enable(int id, bool flag)
+void wxMenuBar::MacInstallMenuBar()
 {
 {
-    wxMenu *itemMenu = NULL;
-    wxMenuItem *item = FindItemForId(id, &itemMenu) ;
-    if (!item)
-        return;
+    if ( s_macInstalledMenuBar == this )
+        return ;
+
+    wxStAppResource resload ;
+
+    Handle menubar = ::GetNewMBar( kwxMacMenuBarResource ) ;
+    wxString message ;
+    wxCHECK_RET( menubar != NULL, wxT("can't read MBAR resource") );
+    ::SetMenuBar( menubar ) ;
+#if TARGET_API_MAC_CARBON
+    ::DisposeMenuBar( menubar ) ;
+#else
+    ::DisposeHandle( menubar ) ;
+#endif
+
+#if TARGET_API_MAC_OS8
+    MenuHandle menu = ::GetMenuHandle( kwxMacAppleMenuId ) ;
+    if ( CountMenuItems( menu ) == 2 )
+    {
+        ::AppendResMenu(menu, 'DRVR');
+    }
+#endif
 
 
-       item->Enable( flag ) ;
+    // clean-up the help menu before adding new items
+    MenuHandle mh = NULL ;
+    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)
+    {
+        wxMenuItem *item = FindItem( wxApp::s_macPreferencesMenuItemId , NULL ) ;
+        if ( item == NULL || !(item->IsEnabled()) )
+            DisableMenuCommand( NULL , kHICommandPreferences ) ;
+        else
+            EnableMenuCommand( NULL , kHICommandPreferences ) ;
+    }
+#endif
+       for (size_t i = 0; i < m_menus.GetCount(); i++)
+      {
+        wxMenuItemList::Node *node;
+        wxMenuItem *item;
+        int pos ;
+        wxMenu* menu = m_menus[i] , *subMenu = NULL ;
+
+        if( m_titles[i] == wxT("?") || m_titles[i] == wxT("&?")  || m_titles[i] == wxApp::s_macHelpMenuTitleName )
+        {
+            if ( mh == NULL )
+            {
+                continue ;
+            }
+
+              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->IsSeparator() )
+                    {
+                        if ( mh )
+                            MacAppendMenu(mh, "\p-" );
+                    }
+                    else
+                    {
+                        wxAcceleratorEntry* entry = wxGetAccelFromString( item->GetText() ) ;
+
+                        if ( item->GetId() == wxApp::s_macAboutMenuItemId )
+                        {
+                                UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetText()  );
+                                UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId ) , 1 , true );
+                                SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId ) , 1 , item->GetId() ) ;
+                                UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId ) , 1 , entry ) ;
+                         }
+                        else
+                        {
+                            if ( mh )
+                            {
+                                UMAAppendMenuItem(mh, item->GetText()  , entry );
+                                SetMenuItemCommandID( mh , CountMenuItems(mh) , item->GetId() ) ;
+                            }
+                        }
+
+                        delete entry ;
+                    }
+                }
+            }
+        }
+        else
+        {
+            UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , m_titles[i] ) ;
+            m_menus[i]->MacBeforeDisplay(false) ;
+            ::InsertMenu(MAC_WXHMENU(m_menus[i]->GetHMenu()), 0);
+        }
+    }
+    ::DrawMenuBar() ;
+    s_macInstalledMenuBar = this;
 }
 
 }
 
-void wxMenuBar::EnableTop(int pos, bool flag)
+void wxMenuBar::EnableTop(size_t pos, bool enable)
 {
 {
-       m_menus[pos]->MacEnableMenu( flag ) ;
+    wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
+    m_menus[pos]->MacEnableMenu( enable ) ;
+    Refresh();
 }
 
 }
 
-// Must only be used AFTER menu has been attached to frame,
-// otherwise use individual menus
-void wxMenuBar::Check(int id, bool flag)
+void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
 {
 {
-    wxMenu *itemMenu = NULL;
-    wxMenuItem *item = FindItemForId(id, &itemMenu) ;
-    if (!item)
-        return;
+    wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
 
 
-    if (!item->IsCheckable())
-        return ;
+    m_titles[pos] = label;
+
+    if ( !IsAttached() )
+    {
+        return;
+    }
 
 
-       item->Check( flag ) ;
+    m_menus[pos]->SetTitle( label ) ;
+    if (wxMenuBar::s_macInstalledMenuBar == this) // are we currently installed ?
+    {
+        ::SetMenuBar( GetMenuBar() ) ;
+        ::InvalMenuBar() ;
+    }
 }
 
 }
 
-bool wxMenuBar::Checked(int id) const
+wxString wxMenuBar::GetLabelTop(size_t pos) const
 {
 {
-    wxMenu *itemMenu = NULL;
-    wxMenuItem *item = FindItemForId(id, &itemMenu) ;
-    if (!item)
-        return FALSE;
+    wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
+                 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
 
 
-    if (!item->IsCheckable())
-        return FALSE ;
-
-    return item->IsChecked() ;
+    return m_titles[pos];
 }
 
 }
 
-bool wxMenuBar::Enabled(int id) const
+int wxMenuBar::FindMenu(const wxString& title)
 {
 {
-    wxMenu *itemMenu = NULL;
-    wxMenuItem *item = FindItemForId(id, &itemMenu) ;
-    if (!item)
-        return FALSE;
+    wxString menuTitle = wxStripMenuCodes(title);
+
+    size_t count = GetMenuCount();
+    for ( size_t i = 0; i < count; i++ )
+    {
+        wxString title = wxStripMenuCodes(m_titles[i]);
+        if ( menuTitle == title )
+            return i;
+    }
+
+    return wxNOT_FOUND;
 
 
-       if ( !item->IsEnabled() )
-               return FALSE ;
-       
-       if ( itemMenu->m_macMenuEnabled == false )
-               return FALSE ;
-               
-       while( itemMenu->m_parent )
-       {
-               itemMenu = (wxMenu*) itemMenu->m_parent ;
-               if ( itemMenu->IsKindOf( CLASSINFO( wxMenu ) ) )
-               {
-                       if ( itemMenu->m_macMenuEnabled == false )
-                               return FALSE ;
-               }
-       }
-       
-    return TRUE ;
 }
 
 
 }
 
 
-void wxMenuBar::SetLabel(int id, const wxString& label)
+// ---------------------------------------------------------------------------
+// wxMenuBar construction
+// ---------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+// wxMenuBar construction
+// ---------------------------------------------------------------------------
+
+wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
 {
 {
-    wxMenu *itemMenu = NULL;
-    wxMenuItem *item = FindItemForId(id, &itemMenu) ;
+    wxMenu *menuOld = wxMenuBarBase::Replace(pos, menu, title);
+    if ( !menuOld )
+        return FALSE;
+    m_titles[pos] = title;
 
 
-    if (!item)
-        return;
+    if ( IsAttached() )
+    {
+        if (s_macInstalledMenuBar == this)
+        {
+            menuOld->MacAfterDisplay( false ) ;
+            ::DeleteMenu( menuOld->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
+            {
+                menu->MacBeforeDisplay( false ) ;
+                UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
+                if ( pos == m_menus.GetCount() - 1)
+                {
+                    ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
+                }
+                else
+                {
+                    ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , m_menus[pos+1]->MacGetMenuId() ) ;
+                }
+            }
+        }
 
 
-    itemMenu->SetLabel( id , label ) ;
+        Refresh();
+    }
+
+    return menuOld;
 }
 
 }
 
-wxString wxMenuBar::GetLabel(int id) const
+bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
 {
 {
-    wxMenu *itemMenu = NULL;
-    wxMenuItem *item = FindItemForId(id, &itemMenu) ;
+    if ( !wxMenuBarBase::Insert(pos, menu, title) )
+        return FALSE;
 
 
-    if (!item)
-        return wxString("");
+    m_titles.Insert(title, pos);
 
 
-    return itemMenu->GetLabel( id ) ;
-}
+    UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
 
 
-void wxMenuBar::SetLabelTop(int pos, const wxString& label)
-{
-    m_menus[pos]->SetTitle( label ) ;
-}
+    if ( IsAttached() && s_macInstalledMenuBar == this )
+    {
+        if (s_macInstalledMenuBar == this)
+        {
+            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()) , m_menus[pos+1]->MacGetMenuId() ) ;
+            }
+        }
+        Refresh();
+    }
 
 
-wxString wxMenuBar::GetLabelTop(int pos) const
-{
-   return m_menus[pos]->GetTitle() ;
+    return TRUE;
 }
 
 }
 
-bool wxMenuBar::OnDelete(wxMenu *a_menu, int pos)
+wxMenu *wxMenuBar::Remove(size_t pos)
 {
 {
-       if (s_macInstalledMenuBar == this)
-       {
-               ::DeleteMenu( a_menu->m_macMenuId /* m_menus[pos]->m_macMenuId */ ) ;
-               ::InvalMenuBar() ;
-               return TRUE ;
-       }
-       else
-       {
-               return TRUE ;
-       }
-}
+    wxMenu *menu = wxMenuBarBase::Remove(pos);
+    if ( !menu )
+        return NULL;
 
 
-bool wxMenuBar::OnAppend(wxMenu *a_menu, const char *title)
-{
-       if (!a_menu->m_macMenuHandle)
-               return FALSE;
-
-       if (s_macInstalledMenuBar == this)
-       {
-               Str255  label;
-               wxMacBuildMenuString( label, NULL , NULL , title , false );
-               UMASetMenuTitle( a_menu->m_macMenuHandle , label ) ;
-               ::InsertMenu( a_menu->m_macMenuHandle , 0 ) ;
-               ::InvalMenuBar() ;
-               return TRUE ;
-       }
-       else
-       {
-               return TRUE ;
-       }
+    if ( IsAttached() )
+    {
+        if (s_macInstalledMenuBar == this)
+        {
+            ::DeleteMenu( menu->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ;
+        }
+
+        Refresh();
+    }
+
+    m_titles.RemoveAt(pos);
+
+    return menu;
 }
 
 }
 
-void wxMenuBar::Append (wxMenu * menu, const wxString& title)
+bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
 {
 {
-    if (!OnAppend(menu, title))
-        return;
+    WXHMENU submenu = menu ? menu->GetHMenu() : 0;
+    wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
 
 
-    m_menuCount ++;
-    wxMenu **new_menus = new wxMenu *[m_menuCount];
-    wxString *new_titles = new wxString[m_menuCount];
-    int i;
-
-    for (i = 0; i < m_menuCount - 1; i++)
-       {
-        new_menus[i] = m_menus[i];
-        m_menus[i] = NULL;
-        new_titles[i] = m_titles[i];
-        m_titles[i] = "";
-    }
-    if (m_menus)
+    if ( !wxMenuBarBase::Append(menu, title) )
+        return FALSE;
+
+    m_titles.Add(title);
+
+    UMASetMenuTitle( MAC_WXHMENU(menu->GetHMenu()) , title ) ;
+
+    if ( IsAttached() )
     {
     {
-        delete[]m_menus;
-        delete[]m_titles;
+        if (s_macInstalledMenuBar == this)
+        {
+            ::InsertMenu( MAC_WXHMENU(menu->GetHMenu()) , 0 ) ;
+        }
+
+        Refresh();
     }
     }
-    m_menus = new_menus;
-    m_titles = new_titles;
 
 
-    m_menus[m_menuCount - 1] = (wxMenu *)menu;
-    m_titles[m_menuCount - 1] = title;
+   // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables
+    // adding menu later on.
+    if (m_invokingWindow)
+        wxMenubarSetInvokingWindow( menu, m_invokingWindow );
 
 
-  ((wxMenu *)menu)->m_menuBar = (wxMenuBar *) this;
-  ((wxMenu *)menu)->SetParent(this);
+    return TRUE;
 }
 
 }
 
-void wxMenuBar::Delete(wxMenu * menu, int i)
+static void wxMenubarUnsetInvokingWindow( wxMenu *menu )
 {
 {
-    int j;
-    int ii = (int) i;
+    menu->SetInvokingWindow( (wxWindow*) NULL );
 
 
-    if (menu != 0)
-    {
-           for (ii = 0; ii < m_menuCount; ii++)
-        {
-            if (m_menus[ii] == menu)
-            break;
-           }
-        if (ii >= m_menuCount)
-            return;
-    } else
+    wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
+    while (node)
     {
     {
-        if (ii < 0 || ii >= m_menuCount)
-            return;
-        menu = m_menus[ii];
+        wxMenuItem *menuitem = node->GetData();
+        if (menuitem->IsSubMenu())
+            wxMenubarUnsetInvokingWindow( menuitem->GetSubMenu() );
+        node = node->GetNext();
     }
     }
+}
 
 
-    if (!OnDelete(menu, ii))
-        return;
+static void wxMenubarSetInvokingWindow( wxMenu *menu, wxWindow *win )
+{
+    menu->SetInvokingWindow( win );
 
 
-    menu->SetParent(NULL);
+    wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst();
+    while (node)
+    {
+        wxMenuItem *menuitem = node->GetData();
+        if (menuitem->IsSubMenu())
+            wxMenubarSetInvokingWindow( menuitem->GetSubMenu() , win );
+        node = node->GetNext();
+    }
+}
 
 
-    -- m_menuCount;
-    for (j = ii; j < m_menuCount; j++)
+void wxMenuBar::UnsetInvokingWindow()
+{
+    m_invokingWindow = (wxWindow*) NULL;
+    wxMenuList::Node *node = m_menus.GetFirst();
+    while (node)
     {
     {
-        m_menus[j] = m_menus[j + 1];
-        m_titles[j] = m_titles[j + 1];
+        wxMenu *menu = node->GetData();
+        wxMenubarUnsetInvokingWindow( menu );
+        node = node->GetNext();
     }
 }
 
     }
 }
 
-// Find the menu menuString, item itemString, and return the item id.
-// Returns -1 if none found.
-int wxMenuBar::FindMenuItem (const wxString& menuString, const wxString& itemString) const
+void wxMenuBar::SetInvokingWindow(wxFrame *frame)
 {
 {
-    char buf1[200];
-    char buf2[200];
-    wxStripMenuCodes ((char *)(const char *)menuString, buf1);
-    int i;
-    for (i = 0; i < m_menuCount; i++)
+    m_invokingWindow = frame;
+    wxMenuList::Node *node = m_menus.GetFirst();
+    while (node)
     {
     {
-        wxStripMenuCodes ((char *)(const char *)m_titles[i], buf2);
-        if (strcmp (buf1, buf2) == 0)
-            return m_menus[i]->FindItem (itemString);
+        wxMenu *menu = node->GetData();
+        wxMenubarSetInvokingWindow( menu, frame );
+        node = node->GetNext();
     }
     }
-    return -1;
 }
 
 }
 
-wxMenuItem *wxMenuBar::FindItemForId (int Id, wxMenu ** itemMenu) const
+void wxMenuBar::Detach()
 {
 {
-    if (itemMenu)
-        *itemMenu = NULL;
+    wxMenuBarBase::Detach() ;
+}
 
 
-    wxMenuItem *item = NULL;
-    int i;
-    for (i = 0; i < m_menuCount; i++)
-        if ((item = m_menus[i]->FindItemForId (Id, itemMenu)))
-            return item;
-    return NULL;
+void wxMenuBar::Attach(wxFrame *frame)
+{
+    wxMenuBarBase::Attach( frame ) ;
 }
 }
+// ---------------------------------------------------------------------------
+// wxMenuBar searching for menu items
+// ---------------------------------------------------------------------------
 
 
-void wxMenuBar::SetHelpString (int Id, const wxString& helpString)
+// Find the itemString in menuString, and return the item id or wxNOT_FOUND
+int wxMenuBar::FindMenuItem(const wxString& menuString,
+                            const wxString& itemString) const
 {
 {
-    int i;
-    for (i = 0; i < m_menuCount; i++)
+    wxString menuLabel = wxStripMenuCodes(menuString);
+    size_t count = GetMenuCount();
+    for ( size_t i = 0; i < count; i++ )
     {
     {
-        if (m_menus[i]->FindItemForId (Id))
-        {
-            m_menus[i]->SetHelpString (Id, helpString);
-            return;
-        }
+        wxString title = wxStripMenuCodes(m_titles[i]);
+        if ( menuString == title )
+            return m_menus[i]->FindItem(itemString);
     }
     }
+
+    return wxNOT_FOUND;
 }
 
 }
 
-wxString wxMenuBar::GetHelpString (int Id) const
+wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
 {
 {
-    int i;
-    for (i = 0; i < m_menuCount; i++)
+    if ( itemMenu )
+        *itemMenu = NULL;
+
+    wxMenuItem *item = NULL;
+    size_t count = GetMenuCount();
+    for ( size_t i = 0; !item && (i < count); i++ )
     {
     {
-        if (m_menus[i]->FindItemForId (Id))
-            return wxString(m_menus[i]->GetHelpString (Id));
+        item = m_menus[i]->FindItem(id, itemMenu);
     }
     }
-    return wxString("");
-}
 
 
-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_menuCount; i++)
-         {
-               if ( m_menus[i]->m_macMenuId == 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_menuCount; i++)
-         {
-               if ( m_menus[i]->MacMenuSelect( handler , when , macMenuId , macMenuItemNum ) )
-               {
-                       break ;
-               }
-               }
-       }
+    return item;
 }
 
 }
 
+