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