From ee0a94cfc2f71e8b770eedda5197a1f4bd62b5cb Mon Sep 17 00:00:00 2001
From: Robert Roebling <robert@roebling.de>
Date: Sun, 3 Sep 2006 12:23:04 +0000
Subject: [PATCH] Commited FRM's stockitem patch (empty stock items).

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@40978 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/menu.tex       |   6 +-
 docs/latex/wx/menuitem.tex   |   6 ++
 docs/latex/wx/stdevtid.tex   |   6 +-
 docs/latex/wx/stockitems.tex |   4 +
 include/wx/accel.h           |  20 ++++
 include/wx/defs.h            |   6 +-
 include/wx/gtk/menuitem.h    |   4 +
 include/wx/menu.h            |   6 +-
 include/wx/stockitem.h       |  26 ++++-
 include/wx/utils.h           |   4 +-
 samples/menu/menu.cpp        | 102 ++++++++++---------
 src/aui/tabmdi.cpp           |   4 +-
 src/common/menucmn.cpp       | 190 +++++++++++++++++++++--------------
 src/common/stockitem.cpp     |  88 +++++++++++++++-
 src/gtk/menu.cpp             | 173 ++++++++++++++++++++++---------
 src/gtk1/menu.cpp            |  10 +-
 src/mac/carbon/menuitem.cpp  |  12 ++-
 src/mac/classic/menuitem.cpp |  12 ++-
 src/motif/menuitem.cpp       |  15 ++-
 src/msw/menuitem.cpp         |  19 +++-
 src/msw/wince/menuce.cpp     |   2 +-
 src/os2/menuitem.cpp         |  12 ++-
 src/palmos/button.cpp        |   2 +-
 src/univ/menu.cpp            |  12 ++-
 24 files changed, 534 insertions(+), 207 deletions(-)

diff --git a/docs/latex/wx/menu.tex b/docs/latex/wx/menu.tex
index fed7774d60..dcec1b5257 100644
--- a/docs/latex/wx/menu.tex
+++ b/docs/latex/wx/menu.tex
@@ -127,7 +127,7 @@ and recreation of internal data structures.
 
 \membersection{wxMenu::Append}\label{wxmenuappend}
 
-\func{wxMenuItem*}{Append}{\param{int}{ id}, \param{const wxString\& }{ item}, \param{const wxString\& }{helpString = ""},\rtfsp
+\func{wxMenuItem*}{Append}{\param{int}{ id}, \param{const wxString\& }{ item = ""}, \param{const wxString\& }{helpString = ""},\rtfsp
 \param{wxItemKind}{ kind = wxITEM\_NORMAL}}
 
 Adds a string item to the end of the menu.
@@ -475,7 +475,7 @@ menubar.
 \func{wxMenuItem*}{Insert}{\param{size\_t }{pos}, \param{wxMenuItem *}{item}}
 
 \func{wxMenuItem*}{Insert}{\param{size\_t }{pos}, \param{int}{ id},\rtfsp
-\param{const wxString\& }{ item}, \param{const wxString\& }{helpString = ""},\rtfsp
+\param{const wxString\& }{ item = ""}, \param{const wxString\& }{helpString = ""},\rtfsp
 \param{wxItemKind}{ kind = wxITEM\_NORMAL}}
 
 Inserts the given {\it item} before the position {\it pos}. Inserting the item
@@ -569,7 +569,7 @@ true if the menu item is enabled, false otherwise.
 \func{wxMenuItem*}{Prepend}{\param{wxMenuItem *}{item}}
 
 \func{wxMenuItem*}{Prepend}{\param{int}{ id},\rtfsp
-\param{const wxString\& }{ item}, \param{const wxString\& }{helpString = ""},\rtfsp
+\param{const wxString\& }{ item = ""}, \param{const wxString\& }{helpString = ""},\rtfsp
 \param{wxItemKind}{ kind = wxITEM\_NORMAL}}
 
 Inserts the given {\it item} at position $0$, i.e. before all the other
diff --git a/docs/latex/wx/menuitem.tex b/docs/latex/wx/menuitem.tex
index a3e9a9a620..c80fea13a9 100644
--- a/docs/latex/wx/menuitem.tex
+++ b/docs/latex/wx/menuitem.tex
@@ -42,6 +42,12 @@ only implemented for Windows and GTK+.
 
 Constructs a wxMenuItem object.
 
+The preferred way to create standard menu items is to use default value of
+\arg{text}. If no text is supplied and \arg{id} is one of standard IDs from
+\helpref{this list}{stockitems}, a standard label and a standard accelerator
+will be used. In addition to that, the button will be decorated with stock
+icons under GTK+ 2.
+
 \wxheading{Parameters}
 
 \docparam{parentMenu}{Menu that the menu item belongs to.}
diff --git a/docs/latex/wx/stdevtid.tex b/docs/latex/wx/stdevtid.tex
index 1ec3eba9d1..5e288682df 100644
--- a/docs/latex/wx/stdevtid.tex
+++ b/docs/latex/wx/stdevtid.tex
@@ -47,7 +47,8 @@ own constants in this range.
     wxID_HELP_CONTEXT,
     wxID_CLOSE_ALL,
 
-    wxID_CUT = 5030,
+    wxID_EDIT = 5030,
+    wxID_CUT,
     wxID_COPY,
     wxID_PASTE,
     wxID_CLEAR,
@@ -68,7 +69,8 @@ own constants in this range.
     wxID_VIEW_SORTSIZE,
     wxID_VIEW_SORTTYPE,
 
-    wxID_FILE1 = 5050,
+    wxID_FILE = 5050,
+    wxID_FILE1,
     wxID_FILE2,
     wxID_FILE3,
     wxID_FILE4,
diff --git a/docs/latex/wx/stockitems.tex b/docs/latex/wx/stockitems.tex
index 5c1b1f2eba..9c335b8099 100644
--- a/docs/latex/wx/stockitems.tex
+++ b/docs/latex/wx/stockitems.tex
@@ -4,6 +4,7 @@ Window IDs for which stock buttons are created
 (see \helpref{wxButton constructor}{wxbuttonctor}):
 
 \begin{twocollist}\itemsep=0pt
+\twocolitem{wxID\_ABOUT}{"\&About"}
 \twocolitem{wxID\_ADD}{"Add"}
 \twocolitem{wxID\_APPLY}{"\&Apply"}
 \twocolitem{wxID\_BOLD}{"\&Bold"}
@@ -13,7 +14,9 @@ Window IDs for which stock buttons are created
 \twocolitem{wxID\_COPY}{"\&Copy"}
 \twocolitem{wxID\_CUT}{"Cu\&t"}
 \twocolitem{wxID\_DELETE}{"\&Delete"}
+\twocolitem{wxID\_EDIT}{"\&Edit"}
 \twocolitem{wxID\_FIND}{"\&Find"}
+\twocolitem{wxID\_FILE}{"\&File"}
 \twocolitem{wxID\_REPLACE}{"Find and rep\&lace"}
 \twocolitem{wxID\_BACKWARD}{"\&Back"}
 \twocolitem{wxID\_DOWN}{"\&Down"}
@@ -44,6 +47,7 @@ Window IDs for which stock buttons are created
 \twocolitem{wxID\_REVERT\_TO\_SAVED}{"Revert to Saved"}
 \twocolitem{wxID\_SAVE}{"\&Save"}
 \twocolitem{wxID\_SAVEAS}{"Save \&As..."}
+\twocolitem{wxID\_SELECTALL}{"Select all"}
 \twocolitem{wxID\_STOP}{"\&Stop"}
 \twocolitem{wxID\_UNDELETE}{"Undelete"}
 \twocolitem{wxID\_UNDERLINE}{"\&Underline"}
diff --git a/include/wx/accel.h b/include/wx/accel.h
index 8ce5622370..02135de643 100644
--- a/include/wx/accel.h
+++ b/include/wx/accel.h
@@ -100,6 +100,26 @@ public:
     bool MatchesEvent(const wxKeyEvent& event) const;
 #endif
 
+    bool IsOk() const
+    {
+        return m_flags != 0 &&
+               m_keyCode != 0;
+    }
+
+
+    // string <-> wxAcceleratorEntry conversion
+    // ----------------------------------------
+
+    // returns a wxString for the this accelerator.
+    // this function formats it using the <flags>-<keycode> format
+    // where <flags> maybe a hyphen-separed list of "shift|alt|ctrl"
+    wxString ToString() const;
+
+    // returns true if the given string correctly initialized this object
+    // (i.e. if IsOk() returns true after this call)
+    bool FromString(const wxString &str);
+
+
 private:
     int m_flags;    // combination of wxACCEL_XXX constants
     int m_keyCode;  // ASCII or virtual keycode
diff --git a/include/wx/defs.h b/include/wx/defs.h
index fae61c24ed..ce6b9e9575 100644
--- a/include/wx/defs.h
+++ b/include/wx/defs.h
@@ -1759,7 +1759,8 @@ enum
     wxID_CLOSE_ALL,
     wxID_PREFERENCES,
 
-    wxID_CUT = 5030,
+    wxID_EDIT = 5030,
+    wxID_CUT,
     wxID_COPY,
     wxID_PASTE,
     wxID_CLEAR,
@@ -1780,7 +1781,8 @@ enum
     wxID_VIEW_SORTSIZE,
     wxID_VIEW_SORTTYPE,
 
-    wxID_FILE1 = 5050,
+    wxID_FILE = 5050,
+    wxID_FILE1,
     wxID_FILE2,
     wxID_FILE3,
     wxID_FILE4,
diff --git a/include/wx/gtk/menuitem.h b/include/wx/gtk/menuitem.h
index e732318285..b6f403e0a2 100644
--- a/include/wx/gtk/menuitem.h
+++ b/include/wx/gtk/menuitem.h
@@ -48,6 +48,10 @@ public:
 
     wxString GetHotKey() const { return m_hotKey; }
 
+    // splits given string in the label, doing & => _ translation, which is returned,
+    // and in the hotkey which is used to set given pointer
+    static wxString GTKProcessMenuItemLabel(const wxString& str, wxString *hotKey);
+
     // compatibility only, don't use in new code
     wxMenuItem(wxMenu *parentMenu,
                int id,
diff --git a/include/wx/menu.h b/include/wx/menu.h
index f03dc59acb..9967d81d0d 100644
--- a/include/wx/menu.h
+++ b/include/wx/menu.h
@@ -60,7 +60,7 @@ public:
 
     // append any kind of item (normal/check/radio/separator)
     wxMenuItem* Append(int itemid,
-                       const wxString& text,
+                       const wxString& text = wxEmptyString,
                        const wxString& help = wxEmptyString,
                        wxItemKind kind = wxITEM_NORMAL)
     {
@@ -108,7 +108,7 @@ public:
     // insert an item before given position
     wxMenuItem* Insert(size_t pos,
                        int itemid,
-                       const wxString& text,
+                       const wxString& text = wxEmptyString,
                        const wxString& help = wxEmptyString,
                        wxItemKind kind = wxITEM_NORMAL)
     {
@@ -158,7 +158,7 @@ public:
 
     // prepend any item to the menu
     wxMenuItem* Prepend(int itemid,
-                        const wxString& text,
+                        const wxString& text = wxEmptyString,
                         const wxString& help = wxEmptyString,
                         wxItemKind kind = wxITEM_NORMAL)
     {
diff --git a/include/wx/stockitem.h b/include/wx/stockitem.h
index 7d2b214297..a7480db878 100644
--- a/include/wx/stockitem.h
+++ b/include/wx/stockitem.h
@@ -15,6 +15,7 @@
 #include "wx/defs.h"
 #include "wx/wxchar.h"
 #include "wx/string.h"
+#include "wx/accel.h"
 
 // ----------------------------------------------------------------------------
 // Helper functions for stock items handling:
@@ -27,15 +28,34 @@ WXDLLEXPORT bool wxIsStockID(wxWindowID id);
 // given ID
 WXDLLEXPORT bool wxIsStockLabel(wxWindowID id, const wxString& label);
 
+enum wxStockLabelQueryFlag
+{
+    wxSTOCK_NOFLAGS = 0,
+
+    wxSTOCK_WITH_MNEMONIC = 1,
+    wxSTOCK_WITH_ACCELERATOR = 2
+};
+
 // Returns label that should be used for given stock UI element (e.g. "&OK"
-// for wxSTOCK_OK):
+// for wxSTOCK_OK); if wxSTOCK_WITH_MNEMONIC is given, the & character
+// is included; if wxSTOCK_WITH_ACCELERATOR is given, the stock accelerator
+// for given ID is concatenated to the label using \t as separator
 WXDLLEXPORT wxString wxGetStockLabel(wxWindowID id,
-                                     bool withCodes = true,
-                                     const wxString& accelerator = wxEmptyString);
+                                     long flags = wxSTOCK_WITH_MNEMONIC);
+
+// Returns the accelerator that should be used for given stock UI element
+// (e.g. "Ctrl+x" for wxSTOCK_EXIT)
+WXDLLEXPORT wxAcceleratorEntry wxGetStockAccelerator(wxWindowID id);
 
 #ifdef __WXGTK20__
+
+#include <gdk/gdktypes.h>
+
 // Translates stock ID to GTK+'s stock item string indentifier:
 WXDLLEXPORT const char *wxGetStockGtkID(wxWindowID id);
+
+// Returns stock accelerator modifier and key code for the given ID
+WXDLLEXPORT bool wxGetStockGtkAccelerator(const char *id, GdkModifierType *mod, guint *key);
 #endif
 
 #endif // _WX_STOCKITEM_H_
diff --git a/include/wx/utils.h b/include/wx/utils.h
index 549899ae7c..75426eca32 100644
--- a/include/wx/utils.h
+++ b/include/wx/utils.h
@@ -567,7 +567,9 @@ wxDEPRECATED(
 
 #if wxUSE_ACCEL
 class WXDLLEXPORT wxAcceleratorEntry;
-WXDLLEXPORT wxAcceleratorEntry *wxGetAccelFromString(const wxString& label);
+wxDEPRECATED(
+    WXDLLEXPORT wxAcceleratorEntry *wxGetAccelFromString(const wxString& label)
+);
 #endif // wxUSE_ACCEL
 
 // ----------------------------------------------------------------------------
diff --git a/samples/menu/menu.cpp b/samples/menu/menu.cpp
index 6d19fa4af4..82a5864d3c 100644
--- a/samples/menu/menu.cpp
+++ b/samples/menu/menu.cpp
@@ -360,6 +360,8 @@ bool MyApp::OnInit()
 // MyFrame
 // ----------------------------------------------------------------------------
 
+#include <wx/gtk/private.h>
+
 // Define my frame constructor
 MyFrame::MyFrame()
        : wxFrame((wxFrame *)NULL, wxID_ANY, _T("wxWidgets menu sample"))
@@ -379,56 +381,56 @@ MyFrame::MyFrame()
     wxMenu *fileMenu = new wxMenu;
 
     wxMenu *stockSubMenu = new wxMenu;
-    stockSubMenu->Append(wxID_ADD,              "wxID_ADD");
-    stockSubMenu->Append(wxID_APPLY,            "wxID_APPLY");
-    stockSubMenu->Append(wxID_BOLD,             "wxID_BOLD");
-    stockSubMenu->Append(wxID_CANCEL,           "wxID_CANCEL");
-    stockSubMenu->Append(wxID_CLEAR,            "wxID_CLEAR");
-    stockSubMenu->Append(wxID_CLOSE,            "wxID_CLOSE");
-    stockSubMenu->Append(wxID_COPY,             "wxID_COPY");
-    stockSubMenu->Append(wxID_CUT,              "wxID_CUT");
-    stockSubMenu->Append(wxID_DELETE,           "wxID_DELETE");
-    stockSubMenu->Append(wxID_FIND,             "wxID_FIND");
-    stockSubMenu->Append(wxID_REPLACE,          "wxID_REPLACE");
-    stockSubMenu->Append(wxID_BACKWARD,         "wxID_BACKWARD");
-    stockSubMenu->Append(wxID_DOWN,             "wxID_DOWN");
-    stockSubMenu->Append(wxID_FORWARD,          "wxID_FORWARD");
-    stockSubMenu->Append(wxID_UP,               "wxID_UP");
-    stockSubMenu->Append(wxID_HELP,             "wxID_HELP");
-    stockSubMenu->Append(wxID_HOME,             "wxID_HOME");
-    stockSubMenu->Append(wxID_INDENT,           "wxID_INDENT");
-    stockSubMenu->Append(wxID_INDEX,            "wxID_INDEX");
-    stockSubMenu->Append(wxID_ITALIC,           "wxID_ITALIC");
-    stockSubMenu->Append(wxID_JUSTIFY_CENTER,   "wxID_JUSTIFY_CENTER");
-    stockSubMenu->Append(wxID_JUSTIFY_FILL,     "wxID_JUSTIFY_FILL");
-    stockSubMenu->Append(wxID_JUSTIFY_LEFT,     "wxID_JUSTIFY_LEFT");
-    stockSubMenu->Append(wxID_JUSTIFY_RIGHT,    "wxID_JUSTIFY_RIGHT");
-    stockSubMenu->Append(wxID_NEW,              "wxID_NEW");
-    stockSubMenu->Append(wxID_NO,               "wxID_NO");
-    stockSubMenu->Append(wxID_OK,               "wxID_OK");
-    stockSubMenu->Append(wxID_OPEN,             "wxID_OPEN");
-    stockSubMenu->Append(wxID_PASTE,            "wxID_PASTE");
-    stockSubMenu->Append(wxID_PREFERENCES,      "wxID_PREFERENCES");
-    stockSubMenu->Append(wxID_PRINT,            "wxID_PRINT");
-    stockSubMenu->Append(wxID_PREVIEW,          "wxID_PREVIEW");
-    stockSubMenu->Append(wxID_PROPERTIES,       "wxID_PROPERTIES");
-    stockSubMenu->Append(wxID_EXIT,             "wxID_EXIT");
-    stockSubMenu->Append(wxID_REDO,             "wxID_REDO");
-    stockSubMenu->Append(wxID_REFRESH,          "wxID_REFRESH");
-    stockSubMenu->Append(wxID_REMOVE,           "wxID_REMOVE");
-    stockSubMenu->Append(wxID_REVERT_TO_SAVED,  "wxID_REVERT_TO_SAVED");
-    stockSubMenu->Append(wxID_SAVE,             "wxID_SAVE");
-    stockSubMenu->Append(wxID_SAVEAS,           "wxID_SAVEAS");
-    stockSubMenu->Append(wxID_STOP,             "wxID_STOP");
-    stockSubMenu->Append(wxID_UNDELETE,         "wxID_UNDELETE");
-    stockSubMenu->Append(wxID_UNDERLINE,        "wxID_UNDERLINE");
-    stockSubMenu->Append(wxID_UNDO,             "wxID_UNDO");
-    stockSubMenu->Append(wxID_UNINDENT,         "wxID_UNINDENT");
-    stockSubMenu->Append(wxID_YES,              "wxID_YES");
-    stockSubMenu->Append(wxID_ZOOM_100,         "wxID_ZOOM_100");
-    stockSubMenu->Append(wxID_ZOOM_FIT,         "wxID_ZOOM_FIT");
-    stockSubMenu->Append(wxID_ZOOM_IN,          "wxID_ZOOM_IN");
-    stockSubMenu->Append(wxID_ZOOM_OUT,         "wxID_ZOOM_OUT");
+    stockSubMenu->Append(wxID_ADD);
+    stockSubMenu->Append(wxID_APPLY);
+    stockSubMenu->Append(wxID_BOLD);
+    stockSubMenu->Append(wxID_CANCEL);
+    stockSubMenu->Append(wxID_CLEAR);
+    stockSubMenu->Append(wxID_CLOSE);
+    stockSubMenu->Append(wxID_COPY);
+    stockSubMenu->Append(wxID_CUT);
+    stockSubMenu->Append(wxID_DELETE);
+    stockSubMenu->Append(wxID_FIND);
+    stockSubMenu->Append(wxID_REPLACE);
+    stockSubMenu->Append(wxID_BACKWARD);
+    stockSubMenu->Append(wxID_DOWN);
+    stockSubMenu->Append(wxID_FORWARD);
+    stockSubMenu->Append(wxID_UP);
+    stockSubMenu->Append(wxID_HELP);
+    stockSubMenu->Append(wxID_HOME);
+    stockSubMenu->Append(wxID_INDENT);
+    stockSubMenu->Append(wxID_INDEX);
+    stockSubMenu->Append(wxID_ITALIC);
+    stockSubMenu->Append(wxID_JUSTIFY_CENTER);
+    stockSubMenu->Append(wxID_JUSTIFY_FILL);
+    stockSubMenu->Append(wxID_JUSTIFY_LEFT);
+    stockSubMenu->Append(wxID_JUSTIFY_RIGHT);
+    stockSubMenu->Append(wxID_NEW);
+    stockSubMenu->Append(wxID_NO);
+    stockSubMenu->Append(wxID_OK);
+    stockSubMenu->Append(wxID_OPEN);
+    stockSubMenu->Append(wxID_PASTE);
+    stockSubMenu->Append(wxID_PREFERENCES);
+    stockSubMenu->Append(wxID_PRINT);
+    stockSubMenu->Append(wxID_PREVIEW);
+    stockSubMenu->Append(wxID_PROPERTIES);
+    stockSubMenu->Append(wxID_EXIT);
+    stockSubMenu->Append(wxID_REDO);
+    stockSubMenu->Append(wxID_REFRESH);
+    stockSubMenu->Append(wxID_REMOVE);
+    stockSubMenu->Append(wxID_REVERT_TO_SAVED);
+    stockSubMenu->Append(wxID_SAVE);
+    stockSubMenu->Append(wxID_SAVEAS);
+    stockSubMenu->Append(wxID_STOP);
+    stockSubMenu->Append(wxID_UNDELETE);
+    stockSubMenu->Append(wxID_UNDERLINE);
+    stockSubMenu->Append(wxID_UNDO);
+    stockSubMenu->Append(wxID_UNINDENT);
+    stockSubMenu->Append(wxID_YES);
+    stockSubMenu->Append(wxID_ZOOM_100);
+    stockSubMenu->Append(wxID_ZOOM_FIT);
+    stockSubMenu->Append(wxID_ZOOM_IN);
+    stockSubMenu->Append(wxID_ZOOM_OUT);
     fileMenu->AppendSubMenu(stockSubMenu, _T("&Standard items demo"));
 
 #if USE_LOG_WINDOW
diff --git a/src/aui/tabmdi.cpp b/src/aui/tabmdi.cpp
index a995ee8462..71f53429d4 100644
--- a/src/aui/tabmdi.cpp
+++ b/src/aui/tabmdi.cpp
@@ -161,7 +161,7 @@ void wxTabMDIParentFrame::SetChildMenuBar(wxTabMDIChildFrame* pChild)
     {
         if (pChild->GetMenuBar() == NULL)
             return;
-            
+
         // Do we need to save the current bar?
         if (m_pMyMenuBar == NULL)
             m_pMyMenuBar = GetMenuBar();
@@ -283,7 +283,7 @@ void wxTabMDIParentFrame::AddWindowMenu(wxMenuBar *pMenuBar)
 {
     if (pMenuBar && m_pWindowMenu)
     {
-        int pos = pMenuBar->FindMenu(wxGetStockLabel(wxID_HELP,false));
+        int pos = pMenuBar->FindMenu(wxGetStockLabel(wxID_HELP,wxSTOCK_NOFLAGS));
         if (pos == wxNOT_FOUND)
             pMenuBar->Append(m_pWindowMenu, _("&Window"));
              else
diff --git a/src/common/menucmn.cpp b/src/common/menucmn.cpp
index bbee944250..09251fcb4d 100644
--- a/src/common/menucmn.cpp
+++ b/src/common/menucmn.cpp
@@ -48,36 +48,9 @@ WX_DEFINE_LIST(wxMenuItemList)
 // ============================================================================
 
 // ----------------------------------------------------------------------------
-// wxMenuItem
+// wxAcceleratorEntry
 // ----------------------------------------------------------------------------
 
-wxMenuItemBase::wxMenuItemBase(wxMenu *parentMenu,
-                               int id,
-                               const wxString& text,
-                               const wxString& help,
-                               wxItemKind kind,
-                               wxMenu *subMenu)
-              : m_text(text),
-                m_help(help)
-{
-    wxASSERT_MSG( parentMenu != NULL, wxT("menuitem should have a menu") );
-
-    m_parentMenu  = parentMenu;
-    m_subMenu     = subMenu;
-    m_isEnabled   = true;
-    m_isChecked   = false;
-    m_id          = id;
-    m_kind        = kind;
-    if (m_id == wxID_ANY)
-        m_id = wxNewId();
-    if (m_id == wxID_SEPARATOR)
-        m_kind = wxITEM_SEPARATOR;
-}
-
-wxMenuItemBase::~wxMenuItemBase()
-{
-    delete m_subMenu;
-}
 
 #if wxUSE_ACCEL
 
@@ -172,11 +145,11 @@ static inline bool CompareAccelString(const wxString& str, const wxChar *accel)
 //
 // first and last parameter specify the valid domain for "number" part
 static int
-IsNumberedAccelKey(const wxString& str,
-                   const wxChar *prefix,
-                   wxKeyCode prefixCode,
-                   unsigned first,
-                   unsigned last)
+        IsNumberedAccelKey(const wxString& str,
+                           const wxChar *prefix,
+                           wxKeyCode prefixCode,
+                           unsigned first,
+                           unsigned last)
 {
     const size_t lenPrefix = wxStrlen(prefix);
     if ( !CompareAccelString(str.Left(lenPrefix), prefix) )
@@ -197,13 +170,19 @@ IsNumberedAccelKey(const wxString& str,
     return prefixCode + num - first;
 }
 
-// return wxAcceleratorEntry for the given menu string or NULL if none
-wxAcceleratorEntry *wxGetAccelFromString(const wxString& label)
+bool wxAcceleratorEntry::FromString(const wxString& text)
 {
+    // the parser won't like leading/trailing spaces
+    wxString label = text.Strip(wxString::both);
+
+    // set to invalid state:
+    m_flags = 0;
+    m_keyCode = 0;
+
     // check for accelerators: they are given after '\t'
     int posTab = label.Find(wxT('\t'));
     if ( posTab == wxNOT_FOUND )
-        return NULL;
+        return false;
 
     // parse the accelerator string
     int accelFlags = wxACCEL_NORMAL;
@@ -252,7 +231,7 @@ wxAcceleratorEntry *wxGetAccelFromString(const wxString& label)
     {
         case 0:
             wxLogDebug(wxT("No accel key found, accel string ignored."));
-            return NULL;
+            return false;
 
         case 1:
             // it's just a letter
@@ -267,7 +246,7 @@ wxAcceleratorEntry *wxGetAccelFromString(const wxString& label)
 
         default:
             keyCode = IsNumberedAccelKey(current, wxTRANSLATE("F"),
-                                            WXK_F1, 1, 12);
+                                         WXK_F1, 1, 12);
             if ( !keyCode )
             {
                 for ( size_t n = 0; n < WXSIZEOF(wxKeyNames); n++ )
@@ -283,25 +262,116 @@ wxAcceleratorEntry *wxGetAccelFromString(const wxString& label)
 
             if ( !keyCode )
                 keyCode = IsNumberedAccelKey(current, wxTRANSLATE("KP_"),
-                                                WXK_NUMPAD0, 0, 9);
+                                             WXK_NUMPAD0, 0, 9);
             if ( !keyCode )
                 keyCode = IsNumberedAccelKey(current, wxTRANSLATE("SPECIAL"),
-                                                WXK_SPECIAL1, 1, 20);
+                                             WXK_SPECIAL1, 1, 20);
 
             if ( !keyCode )
             {
                 wxLogDebug(wxT("Unrecognized accel key '%s', accel string ignored."),
                            current.c_str());
-                return NULL;
+                return false;
             }
     }
 
 
     wxASSERT_MSG( keyCode, _T("logic error: should have key code here") );
 
-    return new wxAcceleratorEntry(accelFlags, keyCode);
+    m_flags = accelFlags;
+    m_keyCode = keyCode;
+    return true;
 }
 
+wxString wxAcceleratorEntry::ToString() const
+{
+    wxString text;
+
+    int flags = GetFlags();
+    if ( flags & wxACCEL_ALT )
+        text += _("Alt-");
+    if ( flags & wxACCEL_CTRL )
+        text += _("Ctrl-");
+    if ( flags & wxACCEL_SHIFT )
+        text += _("Shift-");
+
+    const int code = GetKeyCode();
+
+    if ( wxIsalnum(code) )
+        text << (wxChar)code;
+    else if ( code >= WXK_F1 && code <= WXK_F12 )
+        text << _("F") << code - WXK_F1 + 1;
+    else if ( code >= WXK_NUMPAD0 && code <= WXK_NUMPAD9 )
+        text << _("KP_") << code - WXK_NUMPAD0;
+    else if ( code >= WXK_SPECIAL1 && code <= WXK_SPECIAL20 )
+        text << _("SPECIAL") << code - WXK_SPECIAL1 + 1;
+    else // check the named keys
+    {
+        size_t n;
+        for ( n = 0; n < WXSIZEOF(wxKeyNames); n++ )
+        {
+            const wxKeyName& kn = wxKeyNames[n];
+            if ( code == kn.code )
+            {
+                text << wxGetTranslation(kn.name);
+                break;
+            }
+        }
+
+        wxASSERT_MSG( n != WXSIZEOF(wxKeyNames),
+                      wxT("unknown keyboard accelerator code") );
+    }
+
+    return text;
+}
+
+wxAcceleratorEntry *wxGetAccelFromString(const wxString& label)
+{
+    wxAcceleratorEntry *ret = new wxAcceleratorEntry();
+    if (ret->FromString(label))
+        return ret;
+
+    wxDELETE(ret);
+    return NULL;
+}
+
+#endif      // wxUSE_ACCEL
+
+
+// ----------------------------------------------------------------------------
+// wxMenuItem
+// ----------------------------------------------------------------------------
+
+wxMenuItemBase::wxMenuItemBase(wxMenu *parentMenu,
+                               int id,
+                               const wxString& text,
+                               const wxString& help,
+                               wxItemKind kind,
+                               wxMenu *subMenu)
+              : m_text(text),
+                m_help(help)
+{
+    wxASSERT_MSG( parentMenu != NULL, wxT("menuitem should have a menu") );
+
+    m_parentMenu  = parentMenu;
+    m_subMenu     = subMenu;
+    m_isEnabled   = true;
+    m_isChecked   = false;
+    m_id          = id;
+    m_kind        = kind;
+    if (m_id == wxID_ANY)
+        m_id = wxNewId();
+    if (m_id == wxID_SEPARATOR)
+        m_kind = wxITEM_SEPARATOR;
+}
+
+wxMenuItemBase::~wxMenuItemBase()
+{
+    delete m_subMenu;
+}
+
+#if wxUSE_ACCEL
+
 wxAcceleratorEntry *wxMenuItemBase::GetAccel() const
 {
     return wxGetAccelFromString(GetText());
@@ -313,41 +383,7 @@ void wxMenuItemBase::SetAccel(wxAcceleratorEntry *accel)
     if ( accel )
     {
         text += wxT('\t');
-
-        int flags = accel->GetFlags();
-        if ( flags & wxACCEL_ALT )
-            text += _("Alt-");
-        if ( flags & wxACCEL_CTRL )
-            text += _("Ctrl-");
-        if ( flags & wxACCEL_SHIFT )
-            text += _("Shift-");
-
-        const int code = accel->GetKeyCode();
-
-        if ( wxIsalnum(code) )
-            text << (wxChar)code;
-        else if ( code >= WXK_F1 && code <= WXK_F12 )
-            text << _("F") << code - WXK_F1 + 1;
-        else if ( code >= WXK_NUMPAD0 && code <= WXK_NUMPAD9 )
-            text << _("KP_") << code - WXK_NUMPAD0;
-        else if ( code >= WXK_SPECIAL1 && code <= WXK_SPECIAL20 )
-            text << _("SPECIAL") << code - WXK_SPECIAL1 + 1;
-        else // check the named keys
-        {
-            size_t n;
-            for ( n = 0; n < WXSIZEOF(wxKeyNames); n++ )
-            {
-                const wxKeyName& kn = wxKeyNames[n];
-                if ( code == kn.code )
-                {
-                    text << wxGetTranslation(kn.name);
-                    break;
-                }
-            }
-
-            wxASSERT_MSG( n != WXSIZEOF(wxKeyNames),
-                            wxT("unknown keyboard accelerator code") );
-        }
+        text += accel->ToString();
     }
 
     SetText(text);
diff --git a/src/common/stockitem.cpp b/src/common/stockitem.cpp
index 9b2d4e2b1e..bac9c10c1f 100644
--- a/src/common/stockitem.cpp
+++ b/src/common/stockitem.cpp
@@ -35,6 +35,7 @@ bool wxIsStockID(wxWindowID id)
 {
     switch (id)
     {
+        case wxID_ABOUT:
         case wxID_ADD:
         case wxID_APPLY:
         case wxID_BOLD:
@@ -44,7 +45,9 @@ bool wxIsStockID(wxWindowID id)
         case wxID_COPY:
         case wxID_CUT:
         case wxID_DELETE:
+        case wxID_EDIT:
         case wxID_FIND:
+        case wxID_FILE:
         case wxID_REPLACE:
         case wxID_BACKWARD:
         case wxID_DOWN:
@@ -75,6 +78,7 @@ bool wxIsStockID(wxWindowID id)
         case wxID_REVERT_TO_SAVED:
         case wxID_SAVE:
         case wxID_SAVEAS:
+        case wxID_SELECTALL:
         case wxID_STOP:
         case wxID_UNDELETE:
         case wxID_UNDERLINE:
@@ -92,7 +96,7 @@ bool wxIsStockID(wxWindowID id)
     }
 }
 
-wxString wxGetStockLabel(wxWindowID id, bool withCodes, const wxString& accelerator)
+wxString wxGetStockLabel(wxWindowID id, long flags)
 {
     wxString stockLabel;
 
@@ -103,6 +107,7 @@ wxString wxGetStockLabel(wxWindowID id, bool withCodes, const wxString& accelera
 
     switch (id)
     {
+        STOCKITEM(wxID_ABOUT,               _("&About"))
         STOCKITEM(wxID_ADD,                 _("Add"))
         STOCKITEM(wxID_APPLY,               _("&Apply"))
         STOCKITEM(wxID_BOLD,                _("&Bold"))
@@ -112,7 +117,9 @@ wxString wxGetStockLabel(wxWindowID id, bool withCodes, const wxString& accelera
         STOCKITEM(wxID_COPY,                _("&Copy"))
         STOCKITEM(wxID_CUT,                 _("Cu&t"))
         STOCKITEM(wxID_DELETE,              _("&Delete"))
+        STOCKITEM(wxID_EDIT,                _("&Edit"))
         STOCKITEM(wxID_FIND,                _("&Find"))
+        STOCKITEM(wxID_FILE,                _("&File"))
         STOCKITEM(wxID_REPLACE,             _("Rep&lace"))
         STOCKITEM(wxID_BACKWARD,            _("&Back"))
         STOCKITEM(wxID_DOWN,                _("&Down"))
@@ -143,6 +150,7 @@ wxString wxGetStockLabel(wxWindowID id, bool withCodes, const wxString& accelera
         STOCKITEM(wxID_REVERT_TO_SAVED,     _("Revert to Saved"))
         STOCKITEM(wxID_SAVE,                _("&Save"))
         STOCKITEM(wxID_SAVEAS,              _("Save &As..."))
+        STOCKITEM(wxID_SELECTALL,           _("Select all"))
         STOCKITEM(wxID_STOP,                _("&Stop"))
         STOCKITEM(wxID_UNDELETE,            _("Undelete"))
         STOCKITEM(wxID_UNDERLINE,           _("&Underline"))
@@ -161,19 +169,57 @@ wxString wxGetStockLabel(wxWindowID id, bool withCodes, const wxString& accelera
 
     #undef STOCKITEM
 
-    if(!withCodes)
+    if(flags & wxSTOCK_WITH_MNEMONIC)
     {
         stockLabel = wxStripMenuCodes( stockLabel );
     }
-    else if (!stockLabel.empty() && !accelerator.empty())
+
+    if (!stockLabel.empty() && (flags & wxSTOCK_WITH_ACCELERATOR))
     {
         stockLabel += _T("\t");
-        stockLabel += accelerator;
+
+        wxAcceleratorEntry accel = wxGetStockAccelerator(id);
+        if (accel.IsOk())
+            stockLabel += accel.ToString();
     }
 
     return stockLabel;
 }
 
+wxAcceleratorEntry wxGetStockAccelerator(wxWindowID id)
+{
+    wxAcceleratorEntry ret;
+
+    #define STOCKITEM(stockid, flags, keycode)      \
+        case stockid:                               \
+            ret.Set(flags, keycode, stockid);       \
+            break;
+
+    switch (id)
+    {
+        STOCKITEM(wxID_COPY,                wxACCEL_CTRL,'C')
+        STOCKITEM(wxID_CUT,                 wxACCEL_CTRL,'X')
+        STOCKITEM(wxID_FIND,                wxACCEL_CTRL,'F')
+        STOCKITEM(wxID_REPLACE,             wxACCEL_CTRL,'R')
+        STOCKITEM(wxID_HELP,                wxACCEL_CTRL,'H')
+        STOCKITEM(wxID_NEW,                 wxACCEL_CTRL,'N')
+        STOCKITEM(wxID_OPEN,                wxACCEL_CTRL,'O')
+        STOCKITEM(wxID_PASTE,               wxACCEL_CTRL,'V')
+        STOCKITEM(wxID_SAVE,                wxACCEL_CTRL,'S')
+
+        default:
+            // set the wxAcceleratorEntry to return into an invalid state:
+            // there's no stock accelerator for that.
+            ret.Set(0, 0, id);
+            break;
+    };
+
+    #undef STOCKITEM
+
+    // always use wxAcceleratorEntry::IsOk on returned value !
+    return ret;
+}
+
 bool wxIsStockLabel(wxWindowID id, const wxString& label)
 {
     if (label.empty())
@@ -212,8 +258,22 @@ const char *wxGetStockGtkID(wxWindowID id)
         #define STOCKITEM_24(wx,gtk) STOCKITEM_MISSING(wx)
     #endif
 
+    #if GTK_CHECK_VERSION(2,6,0)
+        #define STOCKITEM_26(wx,gtk) STOCKITEM(wx,gtk)
+    #else
+        #define STOCKITEM_26(wx,gtk) STOCKITEM_MISSING(wx)
+    #endif
+
+    #if GTK_CHECK_VERSION(2,10,0)
+        #define STOCKITEM_210(wx,gtk) STOCKITEM(wx,gtk)
+    #else
+        #define STOCKITEM_210(wx,gtk) STOCKITEM_MISSING(wx)
+    #endif
+
+
     switch (id)
     {
+        STOCKITEM_26(wxID_ABOUT,         GTK_STOCK_ABOUT)
         STOCKITEM(wxID_ADD,              GTK_STOCK_ADD)
         STOCKITEM(wxID_APPLY,            GTK_STOCK_APPLY)
         STOCKITEM(wxID_BOLD,             GTK_STOCK_BOLD)
@@ -223,7 +283,9 @@ const char *wxGetStockGtkID(wxWindowID id)
         STOCKITEM(wxID_COPY,             GTK_STOCK_COPY)
         STOCKITEM(wxID_CUT,              GTK_STOCK_CUT)
         STOCKITEM(wxID_DELETE,           GTK_STOCK_DELETE)
+        STOCKITEM_26(wxID_EDIT,          GTK_STOCK_EDIT)
         STOCKITEM(wxID_FIND,             GTK_STOCK_FIND)
+        STOCKITEM_26(wxID_FILE,          GTK_STOCK_FILE)
         STOCKITEM(wxID_REPLACE,          GTK_STOCK_FIND_AND_REPLACE)
         STOCKITEM(wxID_BACKWARD,         GTK_STOCK_GO_BACK)
         STOCKITEM(wxID_DOWN,             GTK_STOCK_GO_DOWN)
@@ -254,6 +316,7 @@ const char *wxGetStockGtkID(wxWindowID id)
         STOCKITEM(wxID_REVERT_TO_SAVED,  GTK_STOCK_REVERT_TO_SAVED)
         STOCKITEM(wxID_SAVE,             GTK_STOCK_SAVE)
         STOCKITEM(wxID_SAVEAS,           GTK_STOCK_SAVE_AS)
+        STOCKITEM_210(wxID_SELECTALL,    GTK_STOCK_SELECT_ALL)
         STOCKITEM(wxID_STOP,             GTK_STOCK_STOP)
         STOCKITEM(wxID_UNDELETE,         GTK_STOCK_UNDELETE)
         STOCKITEM(wxID_UNDERLINE,        GTK_STOCK_UNDERLINE)
@@ -275,4 +338,21 @@ const char *wxGetStockGtkID(wxWindowID id)
     return NULL;
 }
 
+bool wxGetStockGtkAccelerator(const char *id, GdkModifierType *mod, guint *key)
+{
+    GtkStockItem stock_item;
+    if (gtk_stock_lookup (id, &stock_item))
+    {
+        if (key) *key = stock_item.keyval;
+        if (mod) *mod = stock_item.modifier;
+
+        // some GTK stock items have zero values for the keyval;
+        // it means that they do not have an accelerator...
+        if (stock_item.keyval)
+            return true;
+    }
+
+    return false;
+}
+
 #endif // __WXGTK20__
diff --git a/src/gtk/menu.cpp b/src/gtk/menu.cpp
index ff08f83f5a..e38027d8e2 100644
--- a/src/gtk/menu.cpp
+++ b/src/gtk/menu.cpp
@@ -733,6 +733,12 @@ wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
 
 void wxMenuItem::SetText( const wxString& str )
 {
+    // cache some data which must be used later
+    bool isstock = wxIsStockID(GetId());
+    const char *stockid = NULL;
+    if (isstock)
+        stockid = wxGetStockGtkID(GetId());
+
     // Some optimization to avoid flicker
     wxString oldLabel = m_text;
     oldLabel = wxStripMenuCodes(oldLabel);
@@ -744,7 +750,7 @@ void wxMenuItem::SetText( const wxString& str )
     DoSetText(str);
 
     if (oldLabel == label1 &&
-             oldhotkey == GetHotKey())    // Make sure we can change a hotkey even if the label is unaltered
+        oldhotkey == GetHotKey())    // Make sure we can change a hotkey even if the label is unaltered
         return;
 
     if (m_menuItem)
@@ -755,38 +761,78 @@ void wxMenuItem::SetText( const wxString& str )
         else
             label = GTK_LABEL( GTK_BIN(m_menuItem)->child );
 
-        gtk_label_set_text_with_mnemonic( GTK_LABEL(label), wxGTK_CONV_SYS(m_text) );
+        // stock menu items can have empty labels:
+        wxString text = m_text;
+        if (text.IsEmpty() && !IsSeparator())
+        {
+            wxASSERT_MSG(isstock, wxT("A non-stock menu item with an empty label?"));
+            text = wxGetStockLabel(GetId());
+
+            // need & => _ conversion
+            text = GTKProcessMenuItemLabel(text, NULL);
+        }
+
+        gtk_label_set_text_with_mnemonic( GTK_LABEL(label), wxGTK_CONV_SYS(text) );
     }
 
+    // remove old accelerator from our parent's accelerator group, if present
     guint accel_key;
     GdkModifierType accel_mods;
-    gtk_accelerator_parse( (const char*) oldbuf, &accel_key, &accel_mods);
-    if (accel_key != 0)
+    if (oldbuf[(size_t)0] != '\0')
     {
-        gtk_widget_remove_accelerator( GTK_WIDGET(m_menuItem),
-                                       m_parentMenu->m_accel,
-                                       accel_key,
-                                       accel_mods );
+        gtk_accelerator_parse( (const char*) oldbuf, &accel_key, &accel_mods);
+        if (accel_key != 0)
+        {
+            gtk_widget_remove_accelerator( GTK_WIDGET(m_menuItem),
+                                        m_parentMenu->m_accel,
+                                        accel_key,
+                                        accel_mods );
+        }
+    }
+    else if (isstock)
+    {
+        // if the accelerator was taken from a stock ID, just get it back from GTK+ stock
+        if (wxGetStockGtkAccelerator(stockid, &accel_mods, &accel_key))
+            gtk_widget_remove_accelerator( GTK_WIDGET(m_menuItem),
+                                           m_parentMenu->m_accel,
+                                           accel_key,
+                                           accel_mods );
     }
 
+    // add new accelerator to our parent's accelerator group
     wxCharBuffer buf = wxGTK_CONV_SYS( GetGtkHotKey(*this) );
-    gtk_accelerator_parse( (const char*) buf, &accel_key, &accel_mods);
-    if (accel_key != 0)
+    if (buf[(size_t)0] != '\0')
     {
-        gtk_widget_add_accelerator( GTK_WIDGET(m_menuItem),
-                                    "activate",
-                                    m_parentMenu->m_accel,
-                                    accel_key,
-                                    accel_mods,
-                                    GTK_ACCEL_VISIBLE);
+        gtk_accelerator_parse( (const char*) buf, &accel_key, &accel_mods);
+        if (accel_key != 0)
+        {
+            gtk_widget_add_accelerator( GTK_WIDGET(m_menuItem),
+                                        "activate",
+                                        m_parentMenu->m_accel,
+                                        accel_key,
+                                        accel_mods,
+                                        GTK_ACCEL_VISIBLE);
+        }
+    }
+    else if (isstock)
+    {
+        // if the accelerator was taken from a stock ID, just get it back from GTK+ stock
+        if (wxGetStockGtkAccelerator(stockid, &accel_mods, &accel_key))
+            gtk_widget_remove_accelerator( GTK_WIDGET(m_menuItem),
+                                           m_parentMenu->m_accel,
+                                           accel_key,
+                                           accel_mods );
     }
 }
 
-// it's valid for this function to be called even if m_menuItem == NULL
-void wxMenuItem::DoSetText( const wxString& str )
+// NOTE: this function is different from the similar functions GTKProcessMnemonics()
+//       implemented in control.cpp and from wxMenuItemBase::GetLabelFromText...
+//       so there's no real code duplication
+wxString wxMenuItem::GTKProcessMenuItemLabel(const wxString& str, wxString *hotKey)
 {
+    wxString text;
+
     // '\t' is the deliminator indicating a hot key
-    m_text.Empty();
     const wxChar *pc = str;
     while ( (*pc != wxT('\0')) && (*pc != wxT('\t')) )
     {
@@ -794,31 +840,41 @@ void wxMenuItem::DoSetText( const wxString& str )
         {
             // "&" is doubled to indicate "&" instead of accelerator
             ++pc;
-            m_text << wxT('&');
+            text << wxT('&');
         }
         else if (*pc == wxT('&'))
         {
-            m_text << wxT('_');
+            text << wxT('_');
         }
         else if ( *pc == wxT('_') )    // escape underscores
         {
-            m_text << wxT("__");
+            text << wxT("__");
         }
         else
         {
-            m_text << *pc;
+            text << *pc;
         }
         ++pc;
     }
 
-    m_hotKey = wxT("");
-
-    if(*pc == wxT('\t'))
+    if (hotKey)
     {
-       pc++;
-       m_hotKey = pc;
+        hotKey->Empty();
+        if(*pc == wxT('\t'))
+        {
+            pc++;
+            *hotKey = pc;
+        }
     }
 
+    return text;
+}
+
+// it's valid for this function to be called even if m_menuItem == NULL
+void wxMenuItem::DoSetText( const wxString& str )
+{
+    m_text.Empty();
+    m_text = GTKProcessMenuItemLabel(str, &m_hotKey);
     // wxPrintf( wxT("DoSetText(): str %s m_text %s hotkey %s\n"), str.c_str(), m_text.c_str(), m_hotKey.c_str() );
 }
 
@@ -935,17 +991,31 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
 {
     GtkWidget *menuItem;
 
-    wxString text;
+    // cache some data used later
+    wxString text = mitem->GetText();
+    int id = mitem->GetId();
+    bool isstock = wxIsStockID(id);
+    const char *stockid = NULL;
+    if (isstock)
+        stockid = wxGetStockGtkID(mitem->GetId());
+
+    // stock menu items can have an empty label
+    if (text.IsEmpty() && !mitem->IsSeparator())
+    {
+        wxASSERT_MSG(isstock, wxT("A non-stock menu item with an empty label?"));
+        text = wxGetStockLabel(id);
+
+        // need & => _ conversion
+        text = wxMenuItem::GTKProcessMenuItemLabel(text, NULL);
+    }
 
     if ( mitem->IsSeparator() )
     {
         menuItem = gtk_separator_menu_item_new();
     }
     else if ( mitem->GetBitmap().Ok() ||
-                (mitem->GetKind() == wxITEM_NORMAL &&
-                    wxIsStockID(mitem->GetId())) )
+                (mitem->GetKind() == wxITEM_NORMAL && isstock) )
     {
-        text = mitem->GetText();
         wxBitmap bitmap(mitem->GetBitmap());
 
         menuItem = gtk_image_menu_item_new_with_mnemonic( wxGTK_CONV_SYS( text ) );
@@ -955,9 +1025,8 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
         {
             // use stock bitmap for this item if available on the assumption
             // that it never hurts to follow GTK+ conventions more closely
-            const char *stock = wxGetStockGtkID(mitem->GetId());
-            image = stock ? gtk_image_new_from_stock(stock, GTK_ICON_SIZE_MENU)
-                          : NULL;
+            image = stockid ? gtk_image_new_from_stock(stockid, GTK_ICON_SIZE_MENU)
+                            : NULL;
         }
         else // we have a custom bitmap
         {
@@ -989,8 +1058,8 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
     }
     else // a normal item
     {
-        // text has "_" instead of "&" after mitem->SetText() so don't use it
-        text = mitem->GetText() ;
+        // NB: 'text' variable has "_" instead of "&" after mitem->SetText()
+        //     so don't use it
 
         switch ( mitem->GetKind() )
         {
@@ -1038,15 +1107,29 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
     wxCharBuffer buf = wxGTK_CONV_SYS( GetGtkHotKey(*mitem) );
 
     // wxPrintf( wxT("item: %s hotkey %s\n"), mitem->GetText().c_str(), GetGtkHotKey(*mitem).c_str() );
-    gtk_accelerator_parse( (const char*) buf, &accel_key, &accel_mods);
-    if (accel_key != 0)
+    if (buf[(size_t)0] != '\0')
+    {
+        gtk_accelerator_parse( (const char*) buf, &accel_key, &accel_mods);
+        if (accel_key != 0)
+        {
+            gtk_widget_add_accelerator (GTK_WIDGET(menuItem),
+                                        "activate",
+                                        m_accel,
+                                        accel_key,
+                                        accel_mods,
+                                        GTK_ACCEL_VISIBLE);
+        }
+    }
+    else if (isstock)
     {
-        gtk_widget_add_accelerator (GTK_WIDGET(menuItem),
-                                    "activate",
-                                    m_accel,
-                                    accel_key,
-                                    accel_mods,
-                                    GTK_ACCEL_VISIBLE);
+        // if the accelerator was taken from a stock ID, just get it back from GTK+ stock
+        if (wxGetStockGtkAccelerator(stockid, &accel_mods, &accel_key))
+            gtk_widget_add_accelerator( GTK_WIDGET(menuItem),
+                                        "activate",
+                                        m_accel,
+                                        accel_key,
+                                        accel_mods,
+                                        GTK_ACCEL_VISIBLE);
     }
 
     if (pos == -1)
diff --git a/src/gtk1/menu.cpp b/src/gtk1/menu.cpp
index f19e78a481..016f700872 100644
--- a/src/gtk1/menu.cpp
+++ b/src/gtk1/menu.cpp
@@ -11,6 +11,7 @@
 #include "wx/wxprec.h"
 
 #include "wx/menu.h"
+#include "wx/stockitem.h"
 
 #ifndef WX_PRECOMP
     #include "wx/intl.h"
@@ -765,8 +766,15 @@ wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
     return label;
 }
 
-void wxMenuItem::SetText( const wxString& str )
+void wxMenuItem::SetText( const wxString& string )
 {
+    wxString str = string;
+    if (str.IsEmpty())
+    {
+        wxASSERT_MSG(wxIsStockId(GetId()), wxT("A non-stock menu item with an empty label?"));
+        str = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
+    }
+
     // Some optimization to avoid flicker
     wxString oldLabel = m_text;
     oldLabel = wxStripMenuCodes(oldLabel);
diff --git a/src/mac/carbon/menuitem.cpp b/src/mac/carbon/menuitem.cpp
index 7929831fb4..de6298870b 100644
--- a/src/mac/carbon/menuitem.cpp
+++ b/src/mac/carbon/menuitem.cpp
@@ -12,6 +12,7 @@
 #include "wx/wxprec.h"
 
 #include "wx/menuitem.h"
+#include "wx/stockitem.h"
 
 #ifndef WX_PRECOMP
     #include "wx/app.h"
@@ -136,8 +137,15 @@ void wxMenuItem::UpdateItemText()
     if (mhandle == NULL || index == 0)
         return ;
 
-    UMASetMenuItemText( mhandle , index , wxStripMenuCodes(m_text) , wxFont::GetDefaultEncoding() ) ;
-    wxAcceleratorEntry *entry = wxGetAccelFromString( m_text ) ;
+    wxString text = m_text;
+    if (text.IsEmpty() && !IsSeparator())
+    {
+        wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
+        text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
+    }
+
+    UMASetMenuItemText( mhandle , index , wxStripMenuCodes(text) , wxFont::GetDefaultEncoding() ) ;
+    wxAcceleratorEntry *entry = wxGetAccelFromString( text ) ;
     UMASetMenuItemShortcut( mhandle , index , entry ) ;
     delete entry ;
 }
diff --git a/src/mac/classic/menuitem.cpp b/src/mac/classic/menuitem.cpp
index 615f4c0c29..f541a795a2 100644
--- a/src/mac/classic/menuitem.cpp
+++ b/src/mac/classic/menuitem.cpp
@@ -16,6 +16,7 @@
 #include "wx/wxprec.h"
 
 #include "wx/menuitem.h"
+#include "wx/stockitem.h"
 
 #ifndef WX_PRECOMP
     #include "wx/app.h"
@@ -150,8 +151,15 @@ void wxMenuItem::UpdateItemText()
     if( mhandle == NULL || index == 0)
         return ;
 
-    UMASetMenuItemText( mhandle , index , m_text , wxFont::GetDefaultEncoding() ) ;
-    wxAcceleratorEntry *entry = wxGetAccelFromString( m_text ) ;
+    wxString text = m_text;
+    if (text.IsEmpty() && !IsSeparator())
+    {
+        wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
+        text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
+    }
+
+    UMASetMenuItemText( mhandle , index , text , wxFont::GetDefaultEncoding() ) ;
+    wxAcceleratorEntry *entry = wxGetAccelFromString( text ) ;
     UMASetMenuItemShortcut( mhandle , index , entry ) ;
     delete entry ;
 }
diff --git a/src/motif/menuitem.cpp b/src/motif/menuitem.cpp
index 08bf34a5ff..9d096e847f 100644
--- a/src/motif/menuitem.cpp
+++ b/src/motif/menuitem.cpp
@@ -21,6 +21,7 @@
 #include "wx/wxprec.h"
 
 #include "wx/menuitem.h"
+#include "wx/stockitem.h"
 
 #ifndef WX_PRECOMP
     #include "wx/utils.h"
@@ -172,9 +173,17 @@ void wxMenuItem::CreateItem (WXWidget menu, wxMenuBar * menuBar,
             (wxStripMenuCodes(m_text),
             xmLabelGadgetClass, (Widget) menu, NULL);
     }
-    else if (!m_text.empty() && !m_subMenu)
+    else if (!IsSeparator() && !m_subMenu)
     {
-        wxString strName = wxStripMenuCodes(m_text);
+        wxString txt = m_text;
+
+        if (m_text.IsEmpty())
+        {
+            wxASSERT_MSG(wxIsStockId(GetId()), wxT("A non-stock menu item with an empty label?"));
+            txt = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
+        }
+
+        wxString strName = wxStripMenuCodes(txt);
         if (IsCheckable())
         {
             m_buttonWidget = (WXWidget) XtVaCreateManagedWidget (strName,
@@ -230,7 +239,7 @@ void wxMenuItem::CreateItem (WXWidget menu, wxMenuBar * menuBar,
             (XtCallbackProc) wxMenuItemDisarmCallback,
             (XtPointer) this);
     }
-    else if (GetId() == wxID_SEPARATOR)
+    else if (IsSeparator())
     {
         m_buttonWidget = (WXWidget) XtVaCreateManagedWidget ("separator",
             xmSeparatorGadgetClass, (Widget) menu,
diff --git a/src/msw/menuitem.cpp b/src/msw/menuitem.cpp
index 25958f2c6e..5307cd148e 100644
--- a/src/msw/menuitem.cpp
+++ b/src/msw/menuitem.cpp
@@ -27,6 +27,7 @@
 #if wxUSE_MENUS
 
 #include "wx/menuitem.h"
+#include "wx/stockitem.h"
 
 #ifndef WX_PRECOMP
     #include "wx/font.h"
@@ -153,6 +154,12 @@ wxMenuItem::wxMenuItem(wxMenu *parentMenu,
 
 void wxMenuItem::Init()
 {
+    if (m_text.IsEmpty())
+    {
+        wxASSERT_MSG(wxIsStockId(GetId()), wxT("A non-stock menu item with an empty label?"));
+        m_text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
+    }
+
     m_radioGroup.start = -1;
     m_isRadioGroupStart = false;
 
@@ -336,12 +343,20 @@ void wxMenuItem::Check(bool check)
     wxMenuItemBase::Check(check);
 }
 
-void wxMenuItem::SetText(const wxString& text)
+void wxMenuItem::SetText(const wxString& txt)
 {
+    wxString text = txt;
+
     // don't do anything if label didn't change
-    if ( m_text == text )
+    if ( m_text == txt )
         return;
 
+    if (text.IsEmpty())
+    {
+        wxASSERT_MSG(wxIsStockId(GetId()), wxT("A non-stock menu item with an empty label?"));
+        text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
+    }
+
     wxMenuItemBase::SetText(text);
     OWNER_DRAWN_ONLY( wxOwnerDrawn::SetName(text) );
 #if wxUSE_OWNER_DRAWN
diff --git a/src/msw/wince/menuce.cpp b/src/msw/wince/menuce.cpp
index 477b00dac1..238e2f0f95 100644
--- a/src/msw/wince/menuce.cpp
+++ b/src/msw/wince/menuce.cpp
@@ -78,7 +78,7 @@ void wxTopLevelWindowMSW::ButtonMenu::SetButton(int id, const wxString& label, w
     m_assigned = true;
     m_id = id;
     if(label.empty() && wxIsStockID(id))
-        m_label = wxGetStockLabel(id, false);
+        m_label = wxGetStockLabel(id, wxSTOCK_NOFLAGS);
     else
         m_label = label;
     m_menu = subMenu;
diff --git a/src/os2/menuitem.cpp b/src/os2/menuitem.cpp
index f72deae3e1..055d634f55 100644
--- a/src/os2/menuitem.cpp
+++ b/src/os2/menuitem.cpp
@@ -17,6 +17,7 @@
 #include "wx/wxprec.h"
 
 #include "wx/menuitem.h"
+#include "wx/stockitem.h"
 
 #ifndef WX_PRECOMP
     #include "wx/font.h"
@@ -372,10 +373,19 @@ void wxMenuItem::SetText( const wxString& rText )
     if (m_text == sText)
         return;
 
+    if (sText.IsEmpty())
+    {
+        wxASSERT_MSG(wxIsStockId(GetId()), wxT("A non-stock menu item with an empty label?"));
+        sText = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
+    }
+
     wxMenuItemBase::SetText(sText);
     OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(sText));
 #if  wxUSE_OWNER_DRAWN
-    SetAccelString(rText.AfterFirst(_T('\t')));
+    if (rText.IsEmpty())
+        SetAccelString(sText.AfterFirst(_T('\t')));
+    else
+        SetAccelString(rText.AfterFirst(_T('\t')));
 #endif // wxUSE_OWNER_DRAWN
 
     HWND                            hMenu = GetHmenuOf(m_parentMenu);
diff --git a/src/palmos/button.cpp b/src/palmos/button.cpp
index 2e036b19aa..fc794449ad 100644
--- a/src/palmos/button.cpp
+++ b/src/palmos/button.cpp
@@ -169,7 +169,7 @@ bool wxButton::Create(wxWindow *parent,
     // take the stock label
     wxString palmLabel = label;
     if( palmLabel.empty() && wxIsStockID(id) )
-        palmLabel = wxGetStockLabel(id, false);
+        palmLabel = wxGetStockLabel(id, wxSTOCK_NOFLAGS);
 
     if(!wxControl::Create(parent, id, palmPos, palmSize, style, validator, name))
         return false;
diff --git a/src/univ/menu.cpp b/src/univ/menu.cpp
index e25a936355..c3170fa2d9 100644
--- a/src/univ/menu.cpp
+++ b/src/univ/menu.cpp
@@ -26,6 +26,7 @@
 #if wxUSE_MENUS
 
 #include "wx/menu.h"
+#include "wx/stockitem.h"
 
 #ifndef WX_PRECOMP
     #include "wx/dynarray.h"
@@ -1537,10 +1538,17 @@ void wxMenuItem::UpdateAccelInfo()
     m_strAccel = m_text.AfterFirst(_T('\t'));
 }
 
-void wxMenuItem::SetText(const wxString& text)
+void wxMenuItem::SetText(const wxString& txt)
 {
-    if ( text != m_text )
+    if ( txt != m_text )
     {
+        wxString text = txt;
+        if (text.IsEmpty())
+        {
+            wxASSERT_MSG(wxIsStockId(GetId()), wxT("A non-stock menu item with an empty label?"));
+            text = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR|wxSTOCK_WITH_MNEMONIC);
+        }
+
         // first call the base class version to change m_text
         wxMenuItemBase::SetText(text);
 
-- 
2.50.0

