]> git.saurik.com Git - wxWidgets.git/commitdiff
refactor wxGTK mnemonics conversion functions in a separate file to be able to reuse...
authorVadim Zeitlin <vadim@wxwidgets.org>
Mon, 12 Nov 2007 19:41:38 +0000 (19:41 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Mon, 12 Nov 2007 19:41:38 +0000 (19:41 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@49869 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

Makefile.in
build/bakefiles/files.bkl
include/wx/gtk/private/mnemonics.h [new file with mode: 0644]
include/wx/private/stattext.h
src/common/stattextcmn.cpp
src/gtk/control.cpp
src/gtk/menu.cpp
src/gtk/mnemonics.cpp [new file with mode: 0644]

index d025e6cd4fd52a6ef3f86baa0c8545151b6cacb1..d260788331314000fb2825c82605e8d2def10cd4 100644 (file)
@@ -4524,6 +4524,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___GUI_SRC_OBJECTS =  \
        monodll_listbox.o \
        monodll_mdi.o \
        monodll_menu.o \
+       monodll_mnemonics.o \
        monodll_msgdlg.o \
        monodll_notebook.o \
        monodll_radiobox.o \
@@ -6403,6 +6404,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___GUI_SRC_OBJECTS_1 =  \
        monolib_listbox.o \
        monolib_mdi.o \
        monolib_menu.o \
+       monolib_mnemonics.o \
        monolib_msgdlg.o \
        monolib_notebook.o \
        monolib_radiobox.o \
@@ -8559,6 +8561,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___GUI_SRC_OBJECTS_2 =  \
        coredll_listbox.o \
        coredll_mdi.o \
        coredll_menu.o \
+       coredll_mnemonics.o \
        coredll_msgdlg.o \
        coredll_notebook.o \
        coredll_radiobox.o \
@@ -10053,6 +10056,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION_2___GUI_SRC_OBJECTS_3 =  \
        corelib_listbox.o \
        corelib_mdi.o \
        corelib_menu.o \
+       corelib_mnemonics.o \
        corelib_msgdlg.o \
        corelib_notebook.o \
        corelib_radiobox.o \
@@ -13735,6 +13739,9 @@ monodll_gprint.o: $(srcdir)/src/gtk/gnome/gprint.cpp $(MONODLL_ODEP)
 monodll_gvfs.o: $(srcdir)/src/gtk/gnome/gvfs.cpp $(MONODLL_ODEP)
        $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk/gnome/gvfs.cpp
 
+monodll_mnemonics.o: $(srcdir)/src/gtk/mnemonics.cpp $(MONODLL_ODEP)
+       $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk/mnemonics.cpp
+
 monodll_treeentry_gtk.o: $(srcdir)/src/gtk/treeentry_gtk.c $(MONODLL_ODEP)
        $(CCC) -c -o $@ $(MONODLL_CFLAGS) $(srcdir)/src/gtk/treeentry_gtk.c
 
@@ -18187,6 +18194,9 @@ monolib_gprint.o: $(srcdir)/src/gtk/gnome/gprint.cpp $(MONOLIB_ODEP)
 monolib_gvfs.o: $(srcdir)/src/gtk/gnome/gvfs.cpp $(MONOLIB_ODEP)
        $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/gtk/gnome/gvfs.cpp
 
+monolib_mnemonics.o: $(srcdir)/src/gtk/mnemonics.cpp $(MONOLIB_ODEP)
+       $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/gtk/mnemonics.cpp
+
 monolib_treeentry_gtk.o: $(srcdir)/src/gtk/treeentry_gtk.c $(MONOLIB_ODEP)
        $(CCC) -c -o $@ $(MONOLIB_CFLAGS) $(srcdir)/src/gtk/treeentry_gtk.c
 
@@ -23965,6 +23975,9 @@ coredll_gprint.o: $(srcdir)/src/gtk/gnome/gprint.cpp $(COREDLL_ODEP)
 coredll_gvfs.o: $(srcdir)/src/gtk/gnome/gvfs.cpp $(COREDLL_ODEP)
        $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/gtk/gnome/gvfs.cpp
 
+coredll_mnemonics.o: $(srcdir)/src/gtk/mnemonics.cpp $(COREDLL_ODEP)
+       $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/gtk/mnemonics.cpp
+
 coredll_treeentry_gtk.o: $(srcdir)/src/gtk/treeentry_gtk.c $(COREDLL_ODEP)
        $(CCC) -c -o $@ $(COREDLL_CFLAGS) $(srcdir)/src/gtk/treeentry_gtk.c
 
@@ -27034,6 +27047,9 @@ corelib_gprint.o: $(srcdir)/src/gtk/gnome/gprint.cpp $(CORELIB_ODEP)
 corelib_gvfs.o: $(srcdir)/src/gtk/gnome/gvfs.cpp $(CORELIB_ODEP)
        $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/gtk/gnome/gvfs.cpp
 
+corelib_mnemonics.o: $(srcdir)/src/gtk/mnemonics.cpp $(CORELIB_ODEP)
+       $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/gtk/mnemonics.cpp
+
 corelib_treeentry_gtk.o: $(srcdir)/src/gtk/treeentry_gtk.c $(CORELIB_ODEP)
        $(CCC) -c -o $@ $(CORELIB_CFLAGS) $(srcdir)/src/gtk/treeentry_gtk.c
 
index cde7bbdadc5faf154771094ce8452c44695716f1..db58e7dcf8718f7fd14b4f1c75f8ec7f32da7abd 100644 (file)
@@ -1056,6 +1056,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
     src/gtk/listbox.cpp
     src/gtk/mdi.cpp
     src/gtk/menu.cpp
+    src/gtk/mnemonics.cpp
     src/gtk/msgdlg.cpp
     src/gtk/notebook.cpp
     src/gtk/radiobox.cpp
diff --git a/include/wx/gtk/private/mnemonics.h b/include/wx/gtk/private/mnemonics.h
new file mode 100644 (file)
index 0000000..651a58e
--- /dev/null
@@ -0,0 +1,39 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        gtk/private/mnemonics.h
+// Purpose:     helper functions for dealing with GTK+ mnemonics
+// Author:      Vadim Zeitlin
+// Created:     2007-11-12
+// RCS-ID:      $Id$
+// Copyright:   (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _GTK_PRIVATE_MNEMONICS_H_
+#define _GTK_PRIVATE_MNEMONICS_H_
+
+#if wxUSE_CONTROLS || wxUSE_MENUS
+
+#include "wx/string.h"
+
+// ----------------------------------------------------------------------------
+// functions to convert between wxWidgets and GTK+ string containing mnemonics
+// ----------------------------------------------------------------------------
+
+// remove all mnemonics from a string
+wxString wxGTKRemoveMnemonics(const wxString& label);
+
+// convert a wx string with '&' to GTK+ string with '_'s
+wxString wxConvertMnemonicsToGTK(const wxString& label);
+
+// convert a wx string with '&' to indicate mnemonics as well as HTML entities
+// to a GTK+ string with "&amp;" used instead of '&', i.e. suitable for use
+// with GTK+ functions using markup strings
+wxString wxConvertMnemonicsToGTKMarkup(const wxString& label);
+
+// convert GTK+ string with '_'s to wx string with '&'s
+wxString wxConvertMnemonicsFromGTK(const wxString& label);
+
+#endif // wxUSE_CONTROLS || wxUSE_MENUS
+
+#endif // _GTK_PRIVATE_MNEMONICS_H_
+
index be8f89c0929cd753d0e6f0e5ce55ad0654006d6a..1618315881677a379574e5044c30315da7cfc516 100644 (file)
@@ -67,6 +67,8 @@ private:
     bool m_eol;
 };
 
+#endif // wxUSE_STATTEXT
+
 enum
 {
     wxMARKUP_ENTITY_AMP,
@@ -92,6 +94,4 @@ enum
 //
 extern const wxChar *wxMarkupEntities[wxMARKUP_ELEMENT_MAX][wxMARKUP_ENTITY_MAX];
 
-#endif // wxUSE_STATTEXT
-
 #endif // _WX_PRIVATE_STATTEXT_H_
index b4b6acee004d9a96183e4a34931bf9f8c1555ac3..f7b6a787ddfac3f539310f5fafc7c7e731820923 100644 (file)
@@ -37,8 +37,6 @@
     #include "wx/containr.h"
 #endif
 
-#if wxUSE_STATTEXT
-
 const wxChar *wxMarkupEntities[][wxMARKUP_ENTITY_MAX] =
 {
     // the entities handled by SetLabel() when wxST_MARKUP is used and their referenced string
@@ -47,6 +45,7 @@ const wxChar *wxMarkupEntities[][wxMARKUP_ENTITY_MAX] =
     { wxT("&"),     wxT("<"),    wxT(">"),    wxT("'"),      wxT("\"")     }
 };
 
+#if wxUSE_STATTEXT
 
 // ----------------------------------------------------------------------------
 // wxTextWrapper
index 7369e8cd9e27678fba6c4d3dfd37e57c62b52707..ea16fae76ada5c3137eb01bf789742f0555d309b 100644 (file)
@@ -22,8 +22,7 @@
 #include "wx/fontutil.h"
 #include "wx/gtk/private.h"
 
-#include "wx/private/stattext.h"
-
+#include "wx/gtk/private/mnemonics.h"
 
 // ============================================================================
 // wxControl implementation
@@ -151,121 +150,22 @@ void wxControl::GTKFrameSetMnemonicWidget(GtkFrame* w, GtkWidget* widget)
 // worker function implementing GTK*Mnemonics() functions
 // ----------------------------------------------------------------------------
 
-enum MnemonicsFlag
-{
-    MNEMONICS_REMOVE,
-    MNEMONICS_CONVERT,
-    MNEMONICS_CONVERT_MARKUP
-};
-
-static wxString GTKProcessMnemonics(const wxString& label, MnemonicsFlag flag)
-{
-    wxString labelGTK;
-    labelGTK.reserve(label.length());
-    for ( wxString::const_iterator i = label.begin(); i != label.end(); ++i )
-    {
-        wxChar ch = *i;
-
-        switch ( ch )
-        {
-            case wxT('&'):
-                if ( i + 1 == label.end() )
-                {
-                    // "&" at the end of string is an error
-                    wxLogDebug(wxT("Invalid label \"%s\"."), label);
-                    break;
-                }
-
-                if ( flag == MNEMONICS_CONVERT_MARKUP )
-                {
-                    bool isMnemonic = true;
-                    size_t distanceFromEnd = label.end() - i;
-
-                    // is this ampersand introducing a mnemonic or rather an entity?
-                    for (size_t j=0; j < wxMARKUP_ENTITY_MAX; j++)
-                    {
-                        const wxChar *entity = wxMarkupEntities[wxMARKUP_ELEMENT_NAME][j];
-                        size_t entityLen = wxStrlen(entity);
-
-                        if (distanceFromEnd >= entityLen &&
-                            wxString(i, i + entityLen) == entity)
-                        {
-                            labelGTK << entity;
-                            i += entityLen - 1;     // the -1 is because main for()
-                                                    // loop already increments i
-                            isMnemonic = false;
-
-                            break;
-                        }
-                    }
-
-                    if (!isMnemonic)
-                        continue;
-                }
-
-                ch = *(++i); // skip '&' itself
-                switch ( ch )
-                {
-                    case wxT('&'):
-                        // special case: "&&" is not a mnemonic at all but just
-                        // an escaped "&"
-                        if ( flag == MNEMONICS_CONVERT_MARKUP )
-                            labelGTK += wxT("&amp;");
-                        else
-                            labelGTK += wxT('&');
-                        break;
-
-                    case wxT('_'):
-                        if ( flag != MNEMONICS_REMOVE )
-                        {
-                            // '_' can't be a GTK mnemonic apparently so
-                            // replace it with something similar
-                            labelGTK += wxT("_-");
-                            break;
-                        }
-                        //else: fall through
-
-                    default:
-                        if ( flag != MNEMONICS_REMOVE )
-                            labelGTK += wxT('_');
-                        labelGTK += ch;
-                }
-                break;
-
-            case wxT('_'):
-                if ( flag != MNEMONICS_REMOVE )
-                {
-                    // escape any existing underlines in the string so that
-                    // they don't become mnemonics accidentally
-                    labelGTK += wxT("__");
-                    break;
-                }
-                //else: fall through
-
-            default:
-                labelGTK += ch;
-        }
-    }
-
-    return labelGTK;
-}
-
 /* static */
 wxString wxControl::GTKRemoveMnemonics(const wxString& label)
 {
-    return GTKProcessMnemonics(label, MNEMONICS_REMOVE);
+    return wxGTKRemoveMnemonics(label);
 }
 
 /* static */
 wxString wxControl::GTKConvertMnemonics(const wxString& label)
 {
-    return GTKProcessMnemonics(label, MNEMONICS_CONVERT);
+    return wxConvertMnemonicsToGTK(label);
 }
 
 /* static */
 wxString wxControl::GTKConvertMnemonicsWithMarkup(const wxString& label)
 {
-    return GTKProcessMnemonics(label, MNEMONICS_CONVERT_MARKUP);
+    return wxConvertMnemonicsToGTKMarkup(label);
 }
 
 // ----------------------------------------------------------------------------
index 6e1d23f4c3a1524bd3cbbbb3890686ccb7232a76..7f04189b925a1cd22920a753460131a0574845c8 100644 (file)
@@ -25,6 +25,7 @@
 #include "wx/accel.h"
 #include "wx/stockitem.h"
 #include "wx/gtk/private.h"
+#include "wx/gtk/private/mnemonics.h"
 
 // FIXME: is this right? somehow I don't think so (VZ)
 
@@ -47,79 +48,6 @@ static const int wxGTK_TITLE_ID = -3;
 static wxString GetGtkHotKey( const wxMenuItem& item );
 #endif
 
-//-----------------------------------------------------------------------------
-// idle system
-//-----------------------------------------------------------------------------
-
-static wxString wxReplaceUnderscore( const wxString& title )
-{
-    // GTK 1.2 wants to have "_" instead of "&" for accelerators
-    wxString str;
-
-    for ( wxString::const_iterator pc = title.begin(); pc != title.end(); ++pc )
-    {
-        if ((*pc == wxT('&')) && (pc+1 != title.end()) && (*(pc+1) == wxT('&')))
-        {
-            // "&" is doubled to indicate "&" instead of accelerator
-            ++pc;
-            str << wxT('&');
-        }
-        else if (*pc == wxT('&'))
-        {
-            str << wxT('_');
-        }
-        else
-        {
-            if ( *pc == wxT('_') )
-            {
-                // underscores must be doubled to prevent them from being
-                // interpreted as accelerator character prefix by GTK
-                str << *pc;
-            }
-
-            str << *pc;
-        }
-    }
-
-    // wxPrintf( wxT("before %s after %s\n"), title.c_str(), str.c_str() );
-
-    return str;
-}
-
-static wxString wxConvertFromGTKToWXLabel(const wxString& gtkLabel)
-{
-    wxString label;
-    for ( const wxChar *pc = gtkLabel.c_str(); *pc; pc++ )
-    {
-        // '_' is the escape character for GTK+.
-
-        if ( *pc == wxT('_') && *(pc+1) == wxT('_'))
-        {
-            // An underscore was escaped.
-            label += wxT('_');
-            pc++;
-        }
-        else if ( *pc == wxT('_') )
-        {
-            // Convert GTK+ hotkey symbol to wxWidgets/Windows standard
-            label += wxT('&');
-        }
-        else if ( *pc == wxT('&') )
-        {
-            // Double the ampersand to escape it as far as wxWidgets is concerned
-            label += wxT("&&");
-        }
-        else
-        {
-            // don't remove ampersands '&' since if we have them in the menu title
-            // it means that they were doubled to indicate "&" instead of accelerator
-            label += *pc;
-        }
-    }
-
-    return label;
-}
-
 //-----------------------------------------------------------------------------
 // activate message from GTK
 //-----------------------------------------------------------------------------
@@ -367,7 +295,7 @@ bool wxMenuBar::Append( wxMenu *menu, const wxString &title )
 
 bool wxMenuBar::GtkAppend(wxMenu *menu, const wxString& title, int pos)
 {
-    wxString str( wxReplaceUnderscore( title ) );
+    const wxString str(wxConvertMnemonicsToGTK(title));
 
     // This doesn't have much effect right now.
     menu->SetTitle( str );
@@ -443,7 +371,7 @@ wxMenu *wxMenuBar::Remove(size_t pos)
 
 static int FindMenuItemRecursive( const wxMenu *menu, const wxString &menuString, const wxString &itemString )
 {
-    if (wxMenuItem::GetLabelText(wxConvertFromGTKToWXLabel(menu->GetTitle())) == wxMenuItem::GetLabelText(menuString))
+    if (wxMenuItem::GetLabelText(wxConvertMnemonicsFromGTK(menu->GetTitle())) == wxMenuItem::GetLabelText(menuString))
     {
         int res = menu->FindItem( itemString );
         if (res != wxNOT_FOUND)
@@ -536,7 +464,7 @@ wxString wxMenuBar::GetMenuLabel( size_t pos ) const
 
     wxMenu* menu = node->GetData();
 
-    return wxConvertFromGTKToWXLabel(menu->GetTitle());
+    return wxConvertMnemonicsFromGTK(menu->GetTitle());
 }
 
 void wxMenuBar::SetMenuLabel( size_t pos, const wxString& label )
@@ -547,7 +475,7 @@ void wxMenuBar::SetMenuLabel( size_t pos, const wxString& label )
 
     wxMenu* menu = node->GetData();
 
-    const wxString str( wxReplaceUnderscore( label ) );
+    const wxString str(wxConvertMnemonicsToGTK(label));
 
     menu->SetTitle( str );
 
@@ -785,9 +713,9 @@ wxString wxMenuItemBase::GetLabelText(const wxString& text)
 
 wxString wxMenuItem::GetItemLabel() const
 {
-    wxString label = wxConvertFromGTKToWXLabel(m_text);
+    wxString label = wxConvertMnemonicsFromGTK(m_text);
     if (!m_hotKey.IsEmpty())
-        label = label + wxT("\t") + m_hotKey;
+        label << "\t" << m_hotKey;
     return label;
 }
 
diff --git a/src/gtk/mnemonics.cpp b/src/gtk/mnemonics.cpp
new file mode 100644 (file)
index 0000000..e78bd5d
--- /dev/null
@@ -0,0 +1,189 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        src/gtk/mnemonics.cpp
+// Purpose:     implementation of GTK mnemonics conversion functions
+// Author:      Vadim Zeitlin
+// Created:     2007-11-12
+// RCS-ID:      $Id$
+// Copyright:   (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#include "wx/private/stattext.h"        // for wxMarkupEntities
+
+#include "wx/gtk/private/mnemonics.h"
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// internal helper: apply the operation indicated by flag
+// ----------------------------------------------------------------------------
+
+enum MnemonicsFlag
+{
+    MNEMONICS_REMOVE,
+    MNEMONICS_CONVERT,
+    MNEMONICS_CONVERT_MARKUP
+};
+
+static wxString GTKProcessMnemonics(const wxString& label, MnemonicsFlag flag)
+{
+    wxString labelGTK;
+    labelGTK.reserve(label.length());
+    for ( wxString::const_iterator i = label.begin(); i != label.end(); ++i )
+    {
+        wxChar ch = *i;
+
+        switch ( ch )
+        {
+            case wxT('&'):
+                if ( i + 1 == label.end() )
+                {
+                    // "&" at the end of string is an error
+                    wxLogDebug(wxT("Invalid label \"%s\"."), label);
+                    break;
+                }
+
+                if ( flag == MNEMONICS_CONVERT_MARKUP )
+                {
+                    bool isMnemonic = true;
+                    size_t distanceFromEnd = label.end() - i;
+
+                    // is this ampersand introducing a mnemonic or rather an entity?
+                    for (size_t j=0; j < wxMARKUP_ENTITY_MAX; j++)
+                    {
+                        const wxChar *entity = wxMarkupEntities[wxMARKUP_ELEMENT_NAME][j];
+                        size_t entityLen = wxStrlen(entity);
+
+                        if (distanceFromEnd >= entityLen &&
+                            wxString(i, i + entityLen) == entity)
+                        {
+                            labelGTK << entity;
+                            i += entityLen - 1;     // the -1 is because main for()
+                                                    // loop already increments i
+                            isMnemonic = false;
+
+                            break;
+                        }
+                    }
+
+                    if (!isMnemonic)
+                        continue;
+                }
+
+                ch = *(++i); // skip '&' itself
+                switch ( ch )
+                {
+                    case wxT('&'):
+                        // special case: "&&" is not a mnemonic at all but just
+                        // an escaped "&"
+                        if ( flag == MNEMONICS_CONVERT_MARKUP )
+                            labelGTK += wxT("&amp;");
+                        else
+                            labelGTK += wxT('&');
+                        break;
+
+                    case wxT('_'):
+                        if ( flag != MNEMONICS_REMOVE )
+                        {
+                            // '_' can't be a GTK mnemonic apparently so
+                            // replace it with something similar
+                            labelGTK += wxT("_-");
+                            break;
+                        }
+                        //else: fall through
+
+                    default:
+                        if ( flag != MNEMONICS_REMOVE )
+                            labelGTK += wxT('_');
+                        labelGTK += ch;
+                }
+                break;
+
+            case wxT('_'):
+                if ( flag != MNEMONICS_REMOVE )
+                {
+                    // escape any existing underlines in the string so that
+                    // they don't become mnemonics accidentally
+                    labelGTK += wxT("__");
+                    break;
+                }
+                //else: fall through
+
+            default:
+                labelGTK += ch;
+        }
+    }
+
+    return labelGTK;
+}
+
+// ----------------------------------------------------------------------------
+// public functions
+// ----------------------------------------------------------------------------
+
+wxString wxGTKRemoveMnemonics(const wxString& label)
+{
+    return GTKProcessMnemonics(label, MNEMONICS_REMOVE);
+}
+
+wxString wxConvertMnemonicsToGTK(const wxString& label)
+{
+    return GTKProcessMnemonics(label, MNEMONICS_CONVERT);
+}
+
+wxString wxConvertMnemonicsToGTKMarkup(const wxString& label)
+{
+    return GTKProcessMnemonics(label, MNEMONICS_CONVERT_MARKUP);
+}
+
+wxString wxConvertMnemonicsFromGTK(const wxString& gtkLabel)
+{
+    wxString label;
+    for ( const wxChar *pc = gtkLabel.c_str(); *pc; pc++ )
+    {
+        // '_' is the escape character for GTK+.
+
+        if ( *pc == wxT('_') && *(pc+1) == wxT('_'))
+        {
+            // An underscore was escaped.
+            label += wxT('_');
+            pc++;
+        }
+        else if ( *pc == wxT('_') )
+        {
+            // Convert GTK+ hotkey symbol to wxWidgets/Windows standard
+            label += wxT('&');
+        }
+        else if ( *pc == wxT('&') )
+        {
+            // Double the ampersand to escape it as far as wxWidgets is concerned
+            label += wxT("&&");
+        }
+        else
+        {
+            // don't remove ampersands '&' since if we have them in the menu title
+            // it means that they were doubled to indicate "&" instead of accelerator
+            label += *pc;
+        }
+    }
+
+    return label;
+}
+