+ Init(text);
+}
+
+wxMenuItem::wxMenuItem(wxMenu *parentMenu,
+ int id,
+ const wxString& text,
+ const wxString& help,
+ bool isCheckable,
+ wxMenu *subMenu)
+ : wxMenuItemBase(parentMenu, id, text, help,
+ isCheckable ? wxITEM_CHECK : wxITEM_NORMAL, subMenu)
+{
+ Init(text);
+}
+
+void wxMenuItem::Init(const wxString& text)
+{
+ m_labelWidget = (GtkWidget *) NULL;
+ m_menuItem = (GtkWidget *) NULL;
+
+ DoSetText(text);
+}
+
+wxMenuItem::~wxMenuItem()
+{
+ // don't delete menu items, the menus take care of that
+}
+
+// return the menu item text without any menu accels
+/* static */
+wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
+{
+ wxString label;
+
+ for ( const wxChar *pc = text.c_str(); *pc; pc++ )
+ {
+ if ( *pc == wxT('_') )
+ {
+ // GTK 1.2 escapes "xxx_xxx" to "xxx__xxx"
+ pc++;
+ label += *pc;
+ continue;
+ }
+
+#if GTK_CHECK_VERSION(2, 0, 0)
+ if ( *pc == wxT('\\') )
+ {
+ // GTK 2.0 escapes "xxx/xxx" to "xxx\/xxx"
+ pc++;
+ label += *pc;
+ continue;
+ }
+#endif
+
+ if ( (*pc == wxT('&')) && (*(pc+1) != wxT('&')) )
+ {
+ // wxMSW escapes "&"
+ // "&" is doubled to indicate "&" instead of accelerator
+ continue;
+ }
+
+ label += *pc;
+ }
+ return label;
+}
+
+void wxMenuItem::SetText( const wxString& str )
+{
+ // Some optimization to avoid flicker
+ wxString oldLabel = m_text;
+ oldLabel = wxStripMenuCodes(oldLabel.BeforeFirst('\t'));
+ oldLabel.Replace(wxT("_"), wxT(""));
+ wxString label1 = wxStripMenuCodes(str.BeforeFirst('\t'));
+ if (oldLabel == label1)
+ return;
+
+ DoSetText(str);
+
+ if (m_menuItem)
+ {
+ GtkLabel *label;
+ if (m_labelWidget)
+ label = (GtkLabel*) m_labelWidget;
+ else
+ label = GTK_LABEL( GTK_BIN(m_menuItem)->child );
+
+#if GTK_CHECK_VERSION(2, 0, 0)
+ // We have to imitate item_factory_unescape_label here
+ wxString tmp;
+ for (size_t n = 0; n < m_text.Len(); n++)
+ {
+ if (m_text[n] != wxT('\\'))
+ tmp += m_text[n];
+ }
+
+ gtk_label_set_text_with_mnemonic( GTK_LABEL(label), wxGTK_CONV(tmp) );
+#else
+ // set new text
+ gtk_label_set( label, wxGTK_CONV( m_text ) );
+
+ // reparse key accel
+ (void)gtk_label_parse_uline (GTK_LABEL(label), wxGTK_CONV(m_text) );
+ gtk_accel_label_refetch( GTK_ACCEL_LABEL(label) );
+#endif
+ }
+}
+
+// it's valid for this function to be called even if m_menuItem == NULL
+void wxMenuItem::DoSetText( const wxString& str )
+{
+ // '\t' is the deliminator indicating a hot key
+ m_text.Empty();
+ const wxChar *pc = str;
+ while ( (*pc != wxT('\0')) && (*pc != wxT('\t')) )
+ {
+ if ((*pc == wxT('&')) && (*(pc+1) == wxT('&')))
+ {
+ // "&" is doubled to indicate "&" instead of accelerator
+ ++pc;
+ m_text << wxT('&');
+ }
+ else if (*pc == wxT('&'))
+ {
+ m_text << wxT('_');
+ }
+#if GTK_CHECK_VERSION(2, 0, 0)
+ else if ( *pc == wxT('_') ) // escape underscores
+ {
+ // m_text << wxT("__"); doesn't work
+ }
+ else if (*pc == wxT('/')) // we have to escape slashes
+ {
+ m_text << wxT("\\/");
+ }
+ else if (*pc == wxT('\\')) // we have to double backslashes
+ {
+ m_text << wxT("\\\\");
+ }
+#else
+ else if ( *pc == wxT('_') ) // escape underscores
+ {
+ m_text << wxT("__");
+ }
+ else if (*pc == wxT('/')) /* we have to filter out slashes ... */
+ {
+ m_text << wxT('\\'); /* ... and replace them with back slashes */
+ }
+#endif
+ else {
+ m_text << *pc;
+ }
+ ++pc;
+ }
+
+ m_hotKey = wxT("");
+
+ if(*pc == wxT('\t'))
+ {