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