Fix wxKeyEvent::m_uniChar for EVT_CHAR for native controls in wxGTK.
[wxWidgets.git] / src / gtk / mnemonics.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/mnemonics.cpp
3 // Purpose: implementation of GTK mnemonics conversion functions
4 // Author: Vadim Zeitlin
5 // Created: 2007-11-12
6 // RCS-ID: $Id$
7 // Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #include "wx/log.h"
27 #include "wx/gtk/private/mnemonics.h"
28
29 namespace
30 {
31
32 // ----------------------------------------------------------------------------
33 // constants
34 // ----------------------------------------------------------------------------
35
36 // Names of the standard XML entities.
37 const char *const entitiesNames[] =
38 {
39 "&amp;", "&lt;", "&gt;", "&apos;", "&quot;"
40 };
41
42 } // anonymous namespace
43
44 // ============================================================================
45 // implementation
46 // ============================================================================
47
48 // ----------------------------------------------------------------------------
49 // internal helper: apply the operation indicated by flag
50 // ----------------------------------------------------------------------------
51
52 enum MnemonicsFlag
53 {
54 MNEMONICS_REMOVE,
55 MNEMONICS_CONVERT,
56 MNEMONICS_CONVERT_MARKUP
57 };
58
59 static wxString GTKProcessMnemonics(const wxString& label, MnemonicsFlag flag)
60 {
61 wxString labelGTK;
62 labelGTK.reserve(label.length());
63 for ( wxString::const_iterator i = label.begin(); i != label.end(); ++i )
64 {
65 wxChar ch = *i;
66
67 switch ( ch )
68 {
69 case wxT('&'):
70 if ( i + 1 == label.end() )
71 {
72 // "&" at the end of string is an error
73 wxLogDebug(wxT("Invalid label \"%s\"."), label);
74 break;
75 }
76
77 if ( flag == MNEMONICS_CONVERT_MARKUP )
78 {
79 bool isMnemonic = true;
80 size_t distanceFromEnd = label.end() - i;
81
82 // is this ampersand introducing a mnemonic or rather an entity?
83 for (size_t j=0; j < WXSIZEOF(entitiesNames); j++)
84 {
85 const char *entity = entitiesNames[j];
86 size_t entityLen = wxStrlen(entity);
87
88 if (distanceFromEnd >= entityLen &&
89 wxString(i, i + entityLen) == entity)
90 {
91 labelGTK << entity;
92 i += entityLen - 1; // the -1 is because main for()
93 // loop already increments i
94 isMnemonic = false;
95
96 break;
97 }
98 }
99
100 if (!isMnemonic)
101 continue;
102 }
103
104 ch = *(++i); // skip '&' itself
105 switch ( ch )
106 {
107 case wxT('&'):
108 // special case: "&&" is not a mnemonic at all but just
109 // an escaped "&"
110 if ( flag == MNEMONICS_CONVERT_MARKUP )
111 labelGTK += wxT("&amp;");
112 else
113 labelGTK += wxT('&');
114 break;
115
116 case wxT('_'):
117 if ( flag != MNEMONICS_REMOVE )
118 {
119 // '_' can't be a GTK mnemonic apparently so
120 // replace it with something similar
121 labelGTK += wxT("_-");
122 break;
123 }
124 //else: fall through
125
126 default:
127 if ( flag != MNEMONICS_REMOVE )
128 labelGTK += wxT('_');
129 labelGTK += ch;
130 }
131 break;
132
133 case wxT('_'):
134 if ( flag != MNEMONICS_REMOVE )
135 {
136 // escape any existing underlines in the string so that
137 // they don't become mnemonics accidentally
138 labelGTK += wxT("__");
139 break;
140 }
141 //else: fall through
142
143 default:
144 labelGTK += ch;
145 }
146 }
147
148 return labelGTK;
149 }
150
151 // ----------------------------------------------------------------------------
152 // public functions
153 // ----------------------------------------------------------------------------
154
155 wxString wxGTKRemoveMnemonics(const wxString& label)
156 {
157 return GTKProcessMnemonics(label, MNEMONICS_REMOVE);
158 }
159
160 wxString wxConvertMnemonicsToGTK(const wxString& label)
161 {
162 return GTKProcessMnemonics(label, MNEMONICS_CONVERT);
163 }
164
165 wxString wxConvertMnemonicsToGTKMarkup(const wxString& label)
166 {
167 return GTKProcessMnemonics(label, MNEMONICS_CONVERT_MARKUP);
168 }
169
170 wxString wxConvertMnemonicsFromGTK(const wxString& gtkLabel)
171 {
172 wxString label;
173 for ( const wxChar *pc = gtkLabel.c_str(); *pc; pc++ )
174 {
175 // '_' is the escape character for GTK+.
176
177 if ( *pc == wxT('_') && *(pc+1) == wxT('_'))
178 {
179 // An underscore was escaped.
180 label += wxT('_');
181 pc++;
182 }
183 else if ( *pc == wxT('_') )
184 {
185 // Convert GTK+ hotkey symbol to wxWidgets/Windows standard
186 label += wxT('&');
187 }
188 else if ( *pc == wxT('&') )
189 {
190 // Double the ampersand to escape it as far as wxWidgets is concerned
191 label += wxT("&&");
192 }
193 else
194 {
195 // don't remove ampersands '&' since if we have them in the menu title
196 // it means that they were doubled to indicate "&" instead of accelerator
197 label += *pc;
198 }
199 }
200
201 return label;
202 }
203