1
//////////////////////////////////////////////////////////////////////////////
2
// Name: src/common/xlocale.cpp
3
// Purpose: xlocale wrappers/impl to provide some xlocale wrappers
4
// Author: Brian Vanderburg II, Vadim Zeitlin
6
// Copyright: (c) 2008 Brian Vanderburg II
7
// 2008 Vadim Zeitlin <vadim@wxwidgets.org>
8
// Licence: wxWindows licence
9
///////////////////////////////////////////////////////////////////////////////
11
// ============================================================================
13
// ============================================================================
15
// ----------------------------------------------------------------------------
17
// ----------------------------------------------------------------------------
19
#include "wx/wxprec.h"
28
#include "wx/module.h"
31
#include "wx/xlocale.h"
36
// ----------------------------------------------------------------------------
38
// ----------------------------------------------------------------------------
40
// This is the C locale object, it is created on demand
41
static wxXLocale *gs_cLocale = NULL;
43
wxXLocale wxNullXLocale;
46
// ============================================================================
48
// ============================================================================
50
// ----------------------------------------------------------------------------
51
// Module for gs_cLocale cleanup
52
// ----------------------------------------------------------------------------
54
class wxXLocaleModule : public wxModule
57
virtual bool OnInit() { return true; }
58
virtual void OnExit() { wxDELETE(gs_cLocale); }
60
DECLARE_DYNAMIC_CLASS(wxXLocaleModule)
63
IMPLEMENT_DYNAMIC_CLASS(wxXLocaleModule, wxModule)
66
// ============================================================================
67
// wxXLocale implementation
68
// ============================================================================
70
// ----------------------------------------------------------------------------
72
// ----------------------------------------------------------------------------
75
wxXLocale& wxXLocale::GetCLocale()
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) );
87
#ifdef wxHAS_XLOCALE_SUPPORT
89
wxXLocale::wxXLocale(wxLanguage lang)
91
const wxLanguageInfo * const info = wxLocale::GetLanguageInfo(lang);
98
Init(info->GetLocaleName().c_str());
102
#if wxCHECK_VISUALC_VERSION(8)
104
// ----------------------------------------------------------------------------
105
// implementation using MSVC locale API
106
// ----------------------------------------------------------------------------
108
void wxXLocale::Init(const char *loc)
110
if (!loc || *loc == '\0')
113
m_locale = _create_locale(LC_ALL, loc);
116
void wxXLocale::Free()
119
_free_locale(m_locale);
122
#elif defined(HAVE_LOCALE_T)
124
// ----------------------------------------------------------------------------
125
// implementation using xlocale API
126
// ----------------------------------------------------------------------------
128
void wxXLocale::Init(const char *loc)
130
if (!loc || *loc == '\0')
133
m_locale = newlocale(LC_ALL_MASK, loc, NULL);
136
// NOTE: here we do something similar to what wxSetLocaleTryUTF8() does
137
// in wxLocale code (but with newlocale() calls instead of wxSetlocale())
140
buf2 = buf + wxS(".UTF-8");
141
m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL);
144
buf2 = buf + wxS(".utf-8");
145
m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL);
149
buf2 = buf + wxS(".UTF8");
150
m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL);
154
buf2 = buf + wxS(".utf8");
155
m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL);
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
164
void wxXLocale::Free()
167
freelocale(m_locale);
171
#error "Unknown xlocale support."
174
#endif // wxHAS_XLOCALE_SUPPORT
176
#ifndef wxHAS_XLOCALE_SUPPORT
178
// ============================================================================
179
// Implementation of wxFoo_l() functions for "C" locale without xlocale support
180
// ============================================================================
182
// ----------------------------------------------------------------------------
183
// character classification and transformation functions
184
// ----------------------------------------------------------------------------
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
199
static const unsigned int gs_lookup[] =
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
220
#define CTYPE_TEST(c, t) ( (c) <= 127 && (gs_lookup[(c)] & (t)) )
224
#define GEN_ISFUNC(name, test) \
225
int name(const wxUniChar& c, const wxXLocale& loc) \
227
wxCHECK(loc.IsOk(), false); \
228
return CTYPE_TEST(c.GetValue(), test); \
231
GEN_ISFUNC(wxIsalnum_l, CTYPE_ALNUM)
232
GEN_ISFUNC(wxIsalpha_l, CTYPE_ALPHA)
233
GEN_ISFUNC(wxIscntrl_l, CTYPE_CNTRL)
234
GEN_ISFUNC(wxIsdigit_l, CTYPE_DIGIT)
235
GEN_ISFUNC(wxIsgraph_l, CTYPE_GRAPH)
236
GEN_ISFUNC(wxIslower_l, CTYPE_LOWER)
237
GEN_ISFUNC(wxIsprint_l, CTYPE_PRINT)
238
GEN_ISFUNC(wxIspunct_l, CTYPE_PUNCT)
239
GEN_ISFUNC(wxIsspace_l, CTYPE_SPACE)
240
GEN_ISFUNC(wxIsupper_l, CTYPE_UPPER)
241
GEN_ISFUNC(wxIsxdigit_l, CTYPE_XDIGIT)
243
int wxTolower_l(const wxUniChar& c, const wxXLocale& loc)
245
wxCHECK(loc.IsOk(), false);
247
if(CTYPE_TEST(c.GetValue(), CTYPE_UPPER))
249
return c - 'A' + 'a';
255
int wxToupper_l(const wxUniChar& c, const wxXLocale& loc)
257
wxCHECK(loc.IsOk(), false);
259
if(CTYPE_TEST(c.GetValue(), CTYPE_LOWER))
261
return c - 'a' + 'A';
268
// ----------------------------------------------------------------------------
269
// string --> number conversion functions
270
// ----------------------------------------------------------------------------
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...
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.
286
class CNumericLocaleSetter
289
CNumericLocaleSetter()
290
: m_oldLocale(wxStrdupA(setlocale(LC_NUMERIC, NULL)))
292
if ( !wxSetlocale(LC_NUMERIC, "C") )
294
// Setting locale to "C" should really always work.
295
wxFAIL_MSG( wxS("Couldn't set LC_NUMERIC to \"C\"") );
299
~CNumericLocaleSetter()
301
wxSetlocale(LC_NUMERIC, m_oldLocale);
306
char * const m_oldLocale;
308
wxDECLARE_NO_COPY_CLASS(CNumericLocaleSetter);
311
} // anonymous namespace
313
double wxStrtod_l(const wchar_t* str, wchar_t **endptr, const wxXLocale& loc)
315
wxCHECK( loc.IsOk(), 0. );
317
CNumericLocaleSetter locSetter;
319
return wxStrtod(str, endptr);
322
double wxStrtod_l(const char* str, char **endptr, const wxXLocale& loc)
324
wxCHECK( loc.IsOk(), 0. );
326
CNumericLocaleSetter locSetter;
328
return wxStrtod(str, endptr);
331
long wxStrtol_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc)
333
wxCHECK( loc.IsOk(), 0 );
335
CNumericLocaleSetter locSetter;
337
return wxStrtol(str, endptr, base);
340
long wxStrtol_l(const char* str, char **endptr, int base, const wxXLocale& loc)
342
wxCHECK( loc.IsOk(), 0 );
344
CNumericLocaleSetter locSetter;
346
return wxStrtol(str, endptr, base);
349
unsigned long wxStrtoul_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc)
351
wxCHECK( loc.IsOk(), 0 );
353
CNumericLocaleSetter locSetter;
355
return wxStrtoul(str, endptr, base);
358
unsigned long wxStrtoul_l(const char* str, char **endptr, int base, const wxXLocale& loc)
360
wxCHECK( loc.IsOk(), 0 );
362
CNumericLocaleSetter locSetter;
364
return wxStrtoul(str, endptr, base);
367
#endif // !defined(wxHAS_XLOCALE_SUPPORT)
369
#endif // wxUSE_XLOCALE