]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/mnemonics.cpp
Make wxMSW stack walking methods work with Unicode identifiers.
[wxWidgets.git] / src / gtk / mnemonics.cpp
CommitLineData
b1f17bf0
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/gtk/mnemonics.cpp
3// Purpose: implementation of GTK mnemonics conversion functions
4// Author: Vadim Zeitlin
5// Created: 2007-11-12
b1f17bf0
VZ
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
0c606d12 25#include "wx/log.h"
b1f17bf0
VZ
26#include "wx/gtk/private/mnemonics.h"
27
0d0fdaac
VZ
28namespace
29{
30
31// ----------------------------------------------------------------------------
32// constants
33// ----------------------------------------------------------------------------
34
35// Names of the standard XML entities.
36const char *const entitiesNames[] =
37{
38 "&amp;", "&lt;", "&gt;", "&apos;", "&quot;"
39};
40
41} // anonymous namespace
42
b1f17bf0
VZ
43// ============================================================================
44// implementation
45// ============================================================================
46
47// ----------------------------------------------------------------------------
48// internal helper: apply the operation indicated by flag
49// ----------------------------------------------------------------------------
50
51enum MnemonicsFlag
52{
53 MNEMONICS_REMOVE,
54 MNEMONICS_CONVERT,
55 MNEMONICS_CONVERT_MARKUP
56};
57
58static 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?
0d0fdaac 82 for (size_t j=0; j < WXSIZEOF(entitiesNames); j++)
b1f17bf0 83 {
0d0fdaac 84 const char *entity = entitiesNames[j];
b1f17bf0
VZ
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
154wxString wxGTKRemoveMnemonics(const wxString& label)
155{
156 return GTKProcessMnemonics(label, MNEMONICS_REMOVE);
157}
158
159wxString wxConvertMnemonicsToGTK(const wxString& label)
160{
161 return GTKProcessMnemonics(label, MNEMONICS_CONVERT);
162}
163
164wxString wxConvertMnemonicsToGTKMarkup(const wxString& label)
165{
166 return GTKProcessMnemonics(label, MNEMONICS_CONVERT_MARKUP);
167}
168
169wxString 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