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