diff --git a/Makefile.in b/Makefile.in index b1a6785731..6c0a7a3409 100644 --- a/Makefile.in +++ b/Makefile.in @@ -5218,6 +5218,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION____GUI_SRC_OBJECTS = \ monodll_gtk1_listbox.o \ monodll_gtk1_mdi.o \ monodll_gtk1_menu.o \ + monodll_gtk1_mnemonics.o \ monodll_gtk1_notebook.o \ monodll_gtk1_radiobox.o \ monodll_gtk1_radiobut.o \ @@ -7094,6 +7095,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION____GUI_SRC_OBJECTS_1 = \ monolib_gtk1_listbox.o \ monolib_gtk1_mdi.o \ monolib_gtk1_menu.o \ + monolib_gtk1_mnemonics.o \ monolib_gtk1_notebook.o \ monolib_gtk1_radiobox.o \ monolib_gtk1_radiobut.o \ @@ -9154,6 +9156,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION____GUI_SRC_OBJECTS_2 = \ coredll_gtk1_listbox.o \ coredll_gtk1_mdi.o \ coredll_gtk1_menu.o \ + coredll_gtk1_mnemonics.o \ coredll_gtk1_notebook.o \ coredll_gtk1_radiobox.o \ coredll_gtk1_radiobut.o \ @@ -10698,6 +10701,7 @@ COND_TOOLKIT_GTK_TOOLKIT_VERSION____GUI_SRC_OBJECTS_3 = \ corelib_gtk1_listbox.o \ corelib_gtk1_mdi.o \ corelib_gtk1_menu.o \ + corelib_gtk1_mnemonics.o \ corelib_gtk1_notebook.o \ corelib_gtk1_radiobox.o \ corelib_gtk1_radiobut.o \ @@ -15733,6 +15737,9 @@ monodll_gtk1_mdi.o: $(srcdir)/src/gtk1/mdi.cpp $(MONODLL_ODEP) monodll_gtk1_menu.o: $(srcdir)/src/gtk1/menu.cpp $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk1/menu.cpp +monodll_gtk1_mnemonics.o: $(srcdir)/src/gtk1/mnemonics.cpp $(MONODLL_ODEP) + $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk1/mmnemonics.cpp + monodll_gtk1_notebook.o: $(srcdir)/src/gtk1/notebook.cpp $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk1/notebook.cpp @@ -20962,6 +20969,9 @@ monolib_gtk1_mdi.o: $(srcdir)/src/gtk1/mdi.cpp $(MONOLIB_ODEP) monolib_gtk1_menu.o: $(srcdir)/src/gtk1/menu.cpp $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/gtk1/menu.cpp +monolib_gtk1_mnemonics.o: $(srcdir)/src/gtk1/mnemonics.cpp $(MONODLL_ODEP) + $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk1/mmnemonics.cpp + monolib_gtk1_notebook.o: $(srcdir)/src/gtk1/notebook.cpp $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/gtk1/notebook.cpp @@ -26908,6 +26918,9 @@ coredll_gtk1_mdi.o: $(srcdir)/src/gtk1/mdi.cpp $(COREDLL_ODEP) coredll_gtk1_menu.o: $(srcdir)/src/gtk1/menu.cpp $(COREDLL_ODEP) $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/gtk1/menu.cpp +coredll_gtk1_mnemonics.o: $(srcdir)/src/gtk1/mnemonics.cpp $(MONODLL_ODEP) + $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk1/mmnemonics.cpp + coredll_gtk1_notebook.o: $(srcdir)/src/gtk1/notebook.cpp $(COREDLL_ODEP) $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/gtk1/notebook.cpp @@ -30829,6 +30842,9 @@ corelib_gtk1_mdi.o: $(srcdir)/src/gtk1/mdi.cpp $(CORELIB_ODEP) corelib_gtk1_menu.o: $(srcdir)/src/gtk1/menu.cpp $(CORELIB_ODEP) $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/gtk1/menu.cpp +corelib_gtk1_mnemonics.o: $(srcdir)/src/gtk1/mnemonics.cpp $(MONODLL_ODEP) + $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/gtk1/mmnemonics.cpp + corelib_gtk1_notebook.o: $(srcdir)/src/gtk1/notebook.cpp $(CORELIB_ODEP) $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/gtk1/notebook.cpp diff --git a/include/wx/gtk1/private/mnemonics.h b/include/wx/gtk1/private/mnemonics.h new file mode 100644 index 0000000000..04f6e49f69 --- /dev/null +++ b/include/wx/gtk1/private/mnemonics.h @@ -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: mnemonics.h 49869 2007-11-12 19:41:38Z VZ $ +// Copyright: (c) 2007 Vadim Zeitlin +// 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 "&" 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_ + diff --git a/src/gtk1/descrip.mms b/src/gtk1/descrip.mms index b0c323cbad..b775626f19 100644 --- a/src/gtk1/descrip.mms +++ b/src/gtk1/descrip.mms @@ -2,7 +2,7 @@ # * # Make file for VMS * # Author : J.Jansen (joukj@hrem.nano.tudelft.nl) * -# Date : 2 December 2008 * +# Date : 29 Novemer 2010 * # * #***************************************************************************** .first @@ -90,7 +90,7 @@ OBJECTS0= \ toolbar.obj,\ textctrl.obj,\ tglbtn.obj,\ - msgdlg.obj + msgdlg.obj,mnemonics.obj SOURCES =\ app.cpp,\ @@ -154,7 +154,7 @@ SOURCES =\ utilsgtk.cpp,\ utilsres.cpp,\ win_gtk.c,\ - window.cpp + window.cpp,mnemonics.cpp all : $(SOURCES) $(MMS)$(MMSQUALIFIERS) $(OBJECTS) @@ -230,3 +230,4 @@ utilsgtk.obj : utilsgtk.cpp utilsres.obj : utilsres.cpp win_gtk.obj : win_gtk.c window.obj : window.cpp +mnemonics.obj : mnemonics.cpp diff --git a/src/gtk1/menu.cpp b/src/gtk1/menu.cpp index c0e9ffe315..062d90778f 100644 --- a/src/gtk1/menu.cpp +++ b/src/gtk1/menu.cpp @@ -25,6 +25,7 @@ #endif // wxUSE_ACCEL #include "wx/gtk1/private.h" +#include "wx/gtk1/private/mnemonics.h" #include diff --git a/src/gtk1/mnemonics.cpp b/src/gtk1/mnemonics.cpp new file mode 100644 index 0000000000..4dd60f9e91 --- /dev/null +++ b/src/gtk1/mnemonics.cpp @@ -0,0 +1,190 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/gtk/mnemonics.cpp +// Purpose: implementation of GTK mnemonics conversion functions +// Author: Vadim Zeitlin +// Created: 2007-11-12 +// RCS-ID: $Id: mnemonics.cpp 49885 2007-11-13 02:21:12Z PC $ +// Copyright: (c) 2007 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// for compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#include "wx/log.h" +#include "wx/private/stattext.h" // for wxMarkupEntities + +#include "wx/gtk1/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("&"); + 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; +} +