]>
Commit | Line | Data |
---|---|---|
1 | ////////////////////////////////////////////////////////////////////////////// | |
2 | // Name: src/common/xlocale.cpp | |
3 | // Purpose: xlocale wrappers/impl to provide some xlocale wrappers | |
4 | // Author: Brian Vanderburg II, Vadim Zeitlin | |
5 | // Created: 2008-01-07 | |
6 | // RCS-ID: $Id$ | |
7 | // Copyright: (c) 2008 Brian Vanderburg II | |
8 | // 2008 Vadim Zeitlin <vadim@wxwidgets.org> | |
9 | // Licence: wxWindows licence | |
10 | /////////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | // ============================================================================ | |
13 | // declarations | |
14 | // ============================================================================ | |
15 | ||
16 | // ---------------------------------------------------------------------------- | |
17 | // headers | |
18 | // ---------------------------------------------------------------------------- | |
19 | ||
20 | #include "wx/wxprec.h" | |
21 | ||
22 | #ifdef __BORLANDC__ | |
23 | #pragma hdrstop | |
24 | #endif | |
25 | ||
26 | #if wxUSE_XLOCALE | |
27 | ||
28 | #ifndef WX_PRECOMP | |
29 | #include "wx/module.h" | |
30 | #endif | |
31 | ||
32 | #include "wx/xlocale.h" | |
33 | ||
34 | #include <errno.h> | |
35 | #include <locale.h> | |
36 | ||
37 | // ---------------------------------------------------------------------------- | |
38 | // module globals | |
39 | // ---------------------------------------------------------------------------- | |
40 | ||
41 | // This is the C locale object, it is created on demand | |
42 | static wxXLocale *gs_cLocale = NULL; | |
43 | ||
44 | wxXLocale wxNullXLocale; | |
45 | ||
46 | ||
47 | // ============================================================================ | |
48 | // implementation | |
49 | // ============================================================================ | |
50 | ||
51 | // ---------------------------------------------------------------------------- | |
52 | // Module for gs_cLocale cleanup | |
53 | // ---------------------------------------------------------------------------- | |
54 | ||
55 | class wxXLocaleModule : public wxModule | |
56 | { | |
57 | public: | |
58 | virtual bool OnInit() { return true; } | |
59 | virtual void OnExit() { wxDELETE(gs_cLocale); } | |
60 | ||
61 | DECLARE_DYNAMIC_CLASS(wxXLocaleModule) | |
62 | }; | |
63 | ||
64 | IMPLEMENT_DYNAMIC_CLASS(wxXLocaleModule, wxModule) | |
65 | ||
66 | ||
67 | // ============================================================================ | |
68 | // wxXLocale implementation | |
69 | // ============================================================================ | |
70 | ||
71 | // ---------------------------------------------------------------------------- | |
72 | // common parts | |
73 | // ---------------------------------------------------------------------------- | |
74 | ||
75 | // Get the C locale | |
76 | wxXLocale& wxXLocale::GetCLocale() | |
77 | { | |
78 | if ( !gs_cLocale ) | |
79 | { | |
80 | gs_cLocale = new wxXLocale(static_cast<wxXLocaleCTag *>(NULL)); | |
81 | } | |
82 | ||
83 | return *gs_cLocale; | |
84 | } | |
85 | ||
86 | #ifdef wxHAS_XLOCALE_SUPPORT | |
87 | ||
88 | wxXLocale::wxXLocale(wxLanguage lang) | |
89 | { | |
90 | const wxLanguageInfo * const info = wxLocale::GetLanguageInfo(lang); | |
91 | if ( !info ) | |
92 | { | |
93 | m_locale = NULL; | |
94 | } | |
95 | else | |
96 | { | |
97 | Init(info->GetLocaleName().c_str()); | |
98 | } | |
99 | } | |
100 | ||
101 | #if wxCHECK_VISUALC_VERSION(8) | |
102 | ||
103 | // ---------------------------------------------------------------------------- | |
104 | // implementation using MSVC locale API | |
105 | // ---------------------------------------------------------------------------- | |
106 | ||
107 | void wxXLocale::Init(const char *loc) | |
108 | { | |
109 | if (!loc || *loc == '\0') | |
110 | return; | |
111 | ||
112 | m_locale = _create_locale(LC_ALL, loc); | |
113 | } | |
114 | ||
115 | void wxXLocale::Free() | |
116 | { | |
117 | if ( m_locale ) | |
118 | _free_locale(m_locale); | |
119 | } | |
120 | ||
121 | #elif defined(HAVE_LOCALE_T) | |
122 | ||
123 | // ---------------------------------------------------------------------------- | |
124 | // implementation using xlocale API | |
125 | // ---------------------------------------------------------------------------- | |
126 | ||
127 | void wxXLocale::Init(const char *loc) | |
128 | { | |
129 | if (!loc || *loc == '\0') | |
130 | return; | |
131 | ||
132 | m_locale = newlocale(LC_ALL_MASK, loc, NULL); | |
133 | if (!m_locale) | |
134 | { | |
135 | // NOTE: here we do something similar to what wxSetLocaleTryUTF8() does | |
136 | // in wxLocale code (but with newlocale() calls instead of wxSetlocale()) | |
137 | wxString buf(loc); | |
138 | wxString buf2; | |
139 | buf2 = buf + wxS(".UTF-8"); | |
140 | m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL); | |
141 | if ( !m_locale ) | |
142 | { | |
143 | buf2 = buf + wxS(".utf-8"); | |
144 | m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL); | |
145 | } | |
146 | if ( !m_locale ) | |
147 | { | |
148 | buf2 = buf + wxS(".UTF8"); | |
149 | m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL); | |
150 | } | |
151 | if ( !m_locale ) | |
152 | { | |
153 | buf2 = buf + wxS(".utf8"); | |
154 | m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL); | |
155 | } | |
156 | } | |
157 | ||
158 | // TODO: wxLocale performs many more manipulations of the given locale | |
159 | // string in the attempt to set a valid locale; reusing that code | |
160 | // (changing it to take a generic wxTryLocale callback) would be nice | |
161 | } | |
162 | ||
163 | void wxXLocale::Free() | |
164 | { | |
165 | if ( m_locale ) | |
166 | freelocale(m_locale); | |
167 | } | |
168 | ||
169 | #else | |
170 | #error "Unknown xlocale support." | |
171 | #endif | |
172 | ||
173 | #endif // wxHAS_XLOCALE_SUPPORT | |
174 | ||
175 | #ifndef wxHAS_XLOCALE_SUPPORT | |
176 | ||
177 | // ============================================================================ | |
178 | // Implementation of wxFoo_l() functions for "C" locale without xlocale support | |
179 | // ============================================================================ | |
180 | ||
181 | // ---------------------------------------------------------------------------- | |
182 | // character classification and transformation functions | |
183 | // ---------------------------------------------------------------------------- | |
184 | ||
185 | // lookup table and macros for character type functions | |
186 | #define CTYPE_ALNUM 0x0001 | |
187 | #define CTYPE_ALPHA 0x0002 | |
188 | #define CTYPE_CNTRL 0x0004 | |
189 | #define CTYPE_DIGIT 0x0008 | |
190 | #define CTYPE_GRAPH 0x0010 | |
191 | #define CTYPE_LOWER 0x0020 | |
192 | #define CTYPE_PRINT 0x0040 | |
193 | #define CTYPE_PUNCT 0x0080 | |
194 | #define CTYPE_SPACE 0x0100 | |
195 | #define CTYPE_UPPER 0x0200 | |
196 | #define CTYPE_XDIGIT 0x0400 | |
197 | ||
198 | static const unsigned int gs_lookup[] = | |
199 | { | |
200 | 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, | |
201 | 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0004, | |
202 | 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, | |
203 | 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, | |
204 | 0x0140, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, | |
205 | 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, | |
206 | 0x0459, 0x0459, 0x0459, 0x0459, 0x0459, 0x0459, 0x0459, 0x0459, | |
207 | 0x0459, 0x0459, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, | |
208 | 0x00D0, 0x0653, 0x0653, 0x0653, 0x0653, 0x0653, 0x0653, 0x0253, | |
209 | 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, | |
210 | 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, | |
211 | 0x0253, 0x0253, 0x0253, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, | |
212 | 0x00D0, 0x0473, 0x0473, 0x0473, 0x0473, 0x0473, 0x0473, 0x0073, | |
213 | 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, | |
214 | 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, | |
215 | 0x0073, 0x0073, 0x0073, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x0004 | |
216 | }; | |
217 | ||
218 | ||
219 | #define CTYPE_TEST(c, t) ( (c) <= 127 && (gs_lookup[(c)] & (t)) ) | |
220 | ||
221 | ||
222 | // ctype functions | |
223 | #define GEN_ISFUNC(name, test) \ | |
224 | int name(const wxUniChar& c, const wxXLocale& loc) \ | |
225 | { \ | |
226 | wxCHECK(loc.IsOk(), false); \ | |
227 | return CTYPE_TEST(c.GetValue(), test); \ | |
228 | } | |
229 | ||
230 | GEN_ISFUNC(wxIsalnum_l, CTYPE_ALNUM) | |
231 | GEN_ISFUNC(wxIsalpha_l, CTYPE_ALPHA) | |
232 | GEN_ISFUNC(wxIscntrl_l, CTYPE_CNTRL) | |
233 | GEN_ISFUNC(wxIsdigit_l, CTYPE_DIGIT) | |
234 | GEN_ISFUNC(wxIsgraph_l, CTYPE_GRAPH) | |
235 | GEN_ISFUNC(wxIslower_l, CTYPE_LOWER) | |
236 | GEN_ISFUNC(wxIsprint_l, CTYPE_PRINT) | |
237 | GEN_ISFUNC(wxIspunct_l, CTYPE_PUNCT) | |
238 | GEN_ISFUNC(wxIsspace_l, CTYPE_SPACE) | |
239 | GEN_ISFUNC(wxIsupper_l, CTYPE_UPPER) | |
240 | GEN_ISFUNC(wxIsxdigit_l, CTYPE_XDIGIT) | |
241 | ||
242 | int wxTolower_l(const wxUniChar& c, const wxXLocale& loc) | |
243 | { | |
244 | wxCHECK(loc.IsOk(), false); | |
245 | ||
246 | if(CTYPE_TEST(c.GetValue(), CTYPE_UPPER)) | |
247 | { | |
248 | return c - 'A' + 'a'; | |
249 | } | |
250 | ||
251 | return c; | |
252 | } | |
253 | ||
254 | int wxToupper_l(const wxUniChar& c, const wxXLocale& loc) | |
255 | { | |
256 | wxCHECK(loc.IsOk(), false); | |
257 | ||
258 | if(CTYPE_TEST(c.GetValue(), CTYPE_LOWER)) | |
259 | { | |
260 | return c - 'a' + 'A'; | |
261 | } | |
262 | ||
263 | return c; | |
264 | } | |
265 | ||
266 | ||
267 | // ---------------------------------------------------------------------------- | |
268 | // string --> number conversion functions | |
269 | // ---------------------------------------------------------------------------- | |
270 | ||
271 | /* | |
272 | WARNING: the implementation of the wxStrtoX_l() functions below is unsafe | |
273 | in a multi-threaded environment as we temporary change the locale | |
274 | and if in the meanwhile an other thread performs some locale-dependent | |
275 | operation, it may get unexpected results... | |
276 | However this is the best we can do without reinventing the wheel in the | |
277 | case !wxHAS_XLOCALE_SUPPORT... | |
278 | */ | |
279 | ||
280 | /* | |
281 | Note that this code is similar to (a portion of) wxLocale::IsAvailable code | |
282 | */ | |
283 | #define IMPLEMENT_STRTOX_L_START \ | |
284 | wxCHECK(loc.IsOk(), 0); \ | |
285 | \ | |
286 | /* (Try to) temporary set the 'C' locale */ \ | |
287 | const char *oldLocale = wxSetlocale(LC_NUMERIC, "C"); \ | |
288 | if ( !oldLocale ) \ | |
289 | { \ | |
290 | /* the current locale was not changed; no need to */ \ | |
291 | /* restore the previous one... */ \ | |
292 | errno = EINVAL; \ | |
293 | /* signal an error (better than nothing) */ \ | |
294 | return 0; \ | |
295 | } | |
296 | ||
297 | #define IMPLEMENT_STRTOX_L_END \ | |
298 | /* restore the original locale */ \ | |
299 | wxSetlocale(LC_NUMERIC, oldLocale); \ | |
300 | return ret; | |
301 | ||
302 | double wxStrtod_l(const wchar_t* str, wchar_t **endptr, const wxXLocale& loc) | |
303 | { | |
304 | IMPLEMENT_STRTOX_L_START | |
305 | double ret = wxStrtod(str, endptr); | |
306 | IMPLEMENT_STRTOX_L_END | |
307 | } | |
308 | ||
309 | double wxStrtod_l(const char* str, char **endptr, const wxXLocale& loc) | |
310 | { | |
311 | IMPLEMENT_STRTOX_L_START | |
312 | double ret = wxStrtod(str, endptr); | |
313 | IMPLEMENT_STRTOX_L_END | |
314 | } | |
315 | ||
316 | long wxStrtol_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc) | |
317 | { | |
318 | IMPLEMENT_STRTOX_L_START | |
319 | long ret = wxStrtol(str, endptr, base); | |
320 | IMPLEMENT_STRTOX_L_END | |
321 | } | |
322 | ||
323 | long wxStrtol_l(const char* str, char **endptr, int base, const wxXLocale& loc) | |
324 | { | |
325 | IMPLEMENT_STRTOX_L_START | |
326 | long ret = wxStrtol(str, endptr, base); | |
327 | IMPLEMENT_STRTOX_L_END | |
328 | } | |
329 | ||
330 | unsigned long wxStrtoul_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc) | |
331 | { | |
332 | IMPLEMENT_STRTOX_L_START | |
333 | unsigned long ret = wxStrtoul(str, endptr, base); | |
334 | IMPLEMENT_STRTOX_L_END | |
335 | } | |
336 | ||
337 | unsigned long wxStrtoul_l(const char* str, char **endptr, int base, const wxXLocale& loc) | |
338 | { | |
339 | IMPLEMENT_STRTOX_L_START | |
340 | unsigned long ret = wxStrtoul(str, endptr, base); | |
341 | IMPLEMENT_STRTOX_L_END | |
342 | } | |
343 | ||
344 | ||
345 | #endif // !defined(wxHAS_XLOCALE_SUPPORT) | |
346 | ||
347 | #endif // wxUSE_XLOCALE |