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