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