extend wxXLocale with wxStrto[d,l,ul] functions; make wxXLocale::Init() a little...
[wxWidgets.git] / include / wx / xlocale.h
1 //////////////////////////////////////////////////////////////////////////////
2 // Name: wx/xlocale.h
3 // Purpose: Header 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 This header defines portable wrappers around xlocale foo_l() functions or
14 their MSVC proprietary _foo_l() equivalents when they are available and
15 implements these functions for the "C" locale [only] if they are not. This
16 allows the program running under the default user locale to still use "C"
17 locale for operations such as reading data from files where they are stored
18 using decimal point &c.
19
20 TODO: Currently only the character classification and transformation
21 functions and number <-> string functions, are implemented,
22 we also need at least
23 - formatted IO: scanf_l(), printf_l() &c
24 - time: strftime_l(), strptime_l()
25 */
26
27 #ifndef _WX_XLOCALE_H_
28 #define _WX_XLOCALE_H_
29
30 #include "wx/defs.h" // wxUSE_XLOCALE
31
32 #if wxUSE_XLOCALE
33
34 #include "wx/crt.h" // Includes wx/chartype.h, wx/wxcrt.h(wx/string.h)
35 #include "wx/intl.h" // wxLanguage
36
37 // The platform-specific locale type
38 // If wxXLocale_t is not defined, then only "C" locale support is provided
39 #ifdef wxHAS_XLOCALE_SUPPORT
40 #if wxCHECK_VISUALC_VERSION(8) && !defined(__WXWINCE__)
41 typedef _locale_t wxXLocale_t;
42 #define wxXLOCALE_IDENT(name) _ ## name
43 #elif defined(HAVE_LOCALE_T)
44 #include <locale.h>
45 #include <xlocale.h>
46 #include <ctype.h>
47 #include <stdlib.h>
48
49 #if wxUSE_UNICODE
50 #include <wctype.h>
51 #endif
52
53 // Locale type and identifier name
54 typedef locale_t wxXLocale_t;
55
56 #define wxXLOCALE_IDENT(name) name
57 #else
58 #error "Unknown xlocale support"
59 #endif
60 #endif // wxHAS_XLOCALE_SUPPORT
61
62
63 // wxXLocale is a wrapper around the native type representing a locale.
64 //
65 // It is not to be confused with wxLocale, which handles actually changing the
66 // locale, loading message catalogs, etc. This just stores a locale value.
67 // The similarity of names is unfortunate, but there doesn't seem to be any
68 // better alternative right now. Perhaps by wxWidgets 4.0 better naming could
69 // be used, or this class could become wxLocale (a wrapper for the value), and
70 // some other class could be used to load the language catalogs or something
71 // that would be clearer
72 #ifdef wxHAS_XLOCALE_SUPPORT
73
74 class WXDLLIMPEXP_BASE wxXLocale
75 {
76 public:
77 // Construct an uninitialized locale
78 wxXLocale() { m_locale = NULL; }
79
80 // Construct from a symbolic language constant
81 wxXLocale(wxLanguage lang);
82
83 // Construct from the given language string
84 wxXLocale(const char *loc) { Init(loc); }
85
86 // Destroy the locale
87 ~wxXLocale() { Free(); }
88
89
90 // Get the global "C" locale object
91 static wxXLocale& GetCLocale();
92
93 // Check if the object represents a valid locale (notice that without
94 // wxHAS_XLOCALE_SUPPORT the only valid locale is the "C" one)
95 bool IsOk() const { return m_locale != NULL; }
96
97 // Get the type
98 wxXLocale_t Get() const { return m_locale; }
99
100 bool operator== (const wxXLocale& loc) const
101 { return m_locale == loc.m_locale; }
102
103 private:
104 // Special ctor for the "C" locale, it's only used internally as the user
105 // code is supposed to use GetCLocale()
106 wxXLocale(struct wxXLocaleCTag * WXUNUSED(dummy)) { Init("C"); }
107
108 // Create from the given language string (called from ctors)
109 void Init(const char *loc);
110
111 // Free the locale if it's non-NULL
112 void Free();
113
114
115 // The corresponding locale handle, NULL if invalid
116 wxXLocale_t m_locale;
117
118
119 // POSIX xlocale API provides a duplocale() function but MSVC locale API
120 // doesn't give us any means to copy a _locale_t object so we reduce the
121 // functionality to least common denominator here -- it shouldn't be a
122 // problem as copying the locale objects shouldn't be often needed
123 wxDECLARE_NO_COPY_CLASS(wxXLocale);
124 };
125
126 #else // !wxHAS_XLOCALE_SUPPORT
127
128 // Skeleton version supporting only the "C" locale for the systems without
129 // xlocale support
130 class WXDLLIMPEXP_BASE wxXLocale
131 {
132 public:
133 // Construct an uninitialized locale
134 wxXLocale() { m_isC = false; }
135
136 // Construct from a symbolic language constant: unless the language is
137 // wxLANGUAGE_ENGLISH_US (which we suppose to be the same as "C" locale)
138 // the object will be invalid
139 wxXLocale(wxLanguage lang)
140 {
141 m_isC = lang == wxLANGUAGE_ENGLISH_US;
142 }
143
144 // Construct from the given language string: unless the string is "C" or
145 // "POSIX" the object will be invalid
146 wxXLocale(const char *loc)
147 {
148 m_isC = loc && (strcmp(loc, "C") == 0 || strcmp(loc, "POSIX") == 0);
149 }
150
151 // Default copy ctor, assignment operator and dtor are ok (or would be if
152 // we didn't use DECLARE_NO_COPY_CLASS() for consistency with the xlocale
153 // version)
154
155
156 // Get the global "C" locale object
157 static wxXLocale& GetCLocale();
158
159 // Check if the object represents a valid locale (notice that without
160 // wxHAS_XLOCALE_SUPPORT the only valid locale is the "C" one)
161 bool IsOk() const { return m_isC; }
162
163 private:
164 // Special ctor for the "C" locale, it's only used internally as the user
165 // code is supposed to use GetCLocale()
166 wxXLocale(struct wxXLocaleCTag * WXUNUSED(dummy)) { m_isC = true; }
167
168 // Without xlocale support this class can only represent "C" locale, if
169 // this is false the object is invalid
170 bool m_isC;
171
172
173 // although it's not a problem to copy the objects of this class, we use
174 // this macro in this implementation for consistency with the xlocale-based
175 // one which can't be copied when using MSVC locale API
176 wxDECLARE_NO_COPY_CLASS(wxXLocale);
177 };
178
179 #endif // wxHAS_XLOCALE_SUPPORT/!wxHAS_XLOCALE_SUPPORT
180
181
182 // A shorter synonym for the most commonly used locale object
183 #define wxCLocale (wxXLocale::GetCLocale())
184 extern WXDLLIMPEXP_DATA_BASE(wxXLocale) wxNullXLocale;
185
186 // Wrappers for various functions:
187 #ifdef wxHAS_XLOCALE_SUPPORT
188
189 // ctype functions
190 #define wxCRT_Isalnum_lA wxXLOCALE_IDENT(isalnum_l)
191 #define wxCRT_Isalpha_lA wxXLOCALE_IDENT(isalpha_l)
192 #define wxCRT_Iscntrl_lA wxXLOCALE_IDENT(iscntrl_l)
193 #define wxCRT_Isdigit_lA wxXLOCALE_IDENT(isdigit_l)
194 #define wxCRT_Isgraph_lA wxXLOCALE_IDENT(isgraph_l)
195 #define wxCRT_Islower_lA wxXLOCALE_IDENT(islower_l)
196 #define wxCRT_Isprint_lA wxXLOCALE_IDENT(isprint_l)
197 #define wxCRT_Ispunct_lA wxXLOCALE_IDENT(ispunct_l)
198 #define wxCRT_Isspace_lA wxXLOCALE_IDENT(isspace_l)
199 #define wxCRT_Isupper_lA wxXLOCALE_IDENT(isupper_l)
200 #define wxCRT_Isxdigit_lA wxXLOCALE_IDENT(isxdigit_l)
201 #define wxCRT_Tolower_lA wxXLOCALE_IDENT(tolower_l)
202 #define wxCRT_Toupper_lA wxXLOCALE_IDENT(toupper_l)
203
204 inline int wxIsalnum_l(char c, const wxXLocale& loc)
205 { return wxCRT_Isalnum_lA(static_cast<unsigned char>(c), loc.Get()); }
206 inline int wxIsalpha_l(char c, const wxXLocale& loc)
207 { return wxCRT_Isalpha_lA(static_cast<unsigned char>(c), loc.Get()); }
208 inline int wxIscntrl_l(char c, const wxXLocale& loc)
209 { return wxCRT_Iscntrl_lA(static_cast<unsigned char>(c), loc.Get()); }
210 inline int wxIsdigit_l(char c, const wxXLocale& loc)
211 { return wxCRT_Isdigit_lA(static_cast<unsigned char>(c), loc.Get()); }
212 inline int wxIsgraph_l(char c, const wxXLocale& loc)
213 { return wxCRT_Isgraph_lA(static_cast<unsigned char>(c), loc.Get()); }
214 inline int wxIslower_l(char c, const wxXLocale& loc)
215 { return wxCRT_Islower_lA(static_cast<unsigned char>(c), loc.Get()); }
216 inline int wxIsprint_l(char c, const wxXLocale& loc)
217 { return wxCRT_Isprint_lA(static_cast<unsigned char>(c), loc.Get()); }
218 inline int wxIspunct_l(char c, const wxXLocale& loc)
219 { return wxCRT_Ispunct_lA(static_cast<unsigned char>(c), loc.Get()); }
220 inline int wxIsspace_l(char c, const wxXLocale& loc)
221 { return wxCRT_Isspace_lA(static_cast<unsigned char>(c), loc.Get()); }
222 inline int wxIsupper_l(char c, const wxXLocale& loc)
223 { return wxCRT_Isupper_lA(static_cast<unsigned char>(c), loc.Get()); }
224 inline int wxIsxdigit_l(char c, const wxXLocale& loc)
225 { return wxCRT_Isxdigit_lA(static_cast<unsigned char>(c), loc.Get()); }
226 inline int wxTolower_l(char c, const wxXLocale& loc)
227 { return wxCRT_Tolower_lA(static_cast<unsigned char>(c), loc.Get()); }
228 inline int wxToupper_l(char c, const wxXLocale& loc)
229 { return wxCRT_Toupper_lA(static_cast<unsigned char>(c), loc.Get()); }
230
231
232 // stdlib functions for numeric <-> string conversion
233 // NOTE: GNU libc does not have ato[fil]_l functions;
234 // MSVC++8 does not have _strto[u]ll_l functions;
235 // thus we take the minimal set of functions provided in both environments:
236
237 #define wxCRT_Strtod_lA wxXLOCALE_IDENT(strtod_l)
238 #define wxCRT_Strtol_lA wxXLOCALE_IDENT(strtol_l)
239 #define wxCRT_Strtoul_lA wxXLOCALE_IDENT(strtoul_l)
240
241 inline double wxStrtod_lA(const char *c, char **endptr, const wxXLocale& loc)
242 { return wxCRT_Strtod_lA(c, endptr, loc.Get()); }
243 inline long wxStrtol_lA(const char *c, char **endptr, int base, const wxXLocale& loc)
244 { return wxCRT_Strtol_lA(c, endptr, base, loc.Get()); }
245 inline unsigned long wxStrtoul_lA(const char *c, char **endptr, int base, const wxXLocale& loc)
246 { return wxCRT_Strtoul_lA(c, endptr, base, loc.Get()); }
247
248 #if wxUSE_UNICODE
249
250 // ctype functions
251 #define wxCRT_Isalnum_lW wxXLOCALE_IDENT(iswalnum_l)
252 #define wxCRT_Isalpha_lW wxXLOCALE_IDENT(iswalpha_l)
253 #define wxCRT_Iscntrl_lW wxXLOCALE_IDENT(iswcntrl_l)
254 #define wxCRT_Isdigit_lW wxXLOCALE_IDENT(iswdigit_l)
255 #define wxCRT_Isgraph_lW wxXLOCALE_IDENT(iswgraph_l)
256 #define wxCRT_Islower_lW wxXLOCALE_IDENT(iswlower_l)
257 #define wxCRT_Isprint_lW wxXLOCALE_IDENT(iswprint_l)
258 #define wxCRT_Ispunct_lW wxXLOCALE_IDENT(iswpunct_l)
259 #define wxCRT_Isspace_lW wxXLOCALE_IDENT(iswspace_l)
260 #define wxCRT_Isupper_lW wxXLOCALE_IDENT(iswupper_l)
261 #define wxCRT_Isxdigit_lW wxXLOCALE_IDENT(iswxdigit_l)
262 #define wxCRT_Tolower_lW wxXLOCALE_IDENT(towlower_l)
263 #define wxCRT_Toupper_lW wxXLOCALE_IDENT(towupper_l)
264
265 inline int wxIsalnum_l(wchar_t c, const wxXLocale& loc)
266 { return wxCRT_Isalnum_lW(c, loc.Get()); }
267 inline int wxIsalpha_l(wchar_t c, const wxXLocale& loc)
268 { return wxCRT_Isalpha_lW(c, loc.Get()); }
269 inline int wxIscntrl_l(wchar_t c, const wxXLocale& loc)
270 { return wxCRT_Iscntrl_lW(c, loc.Get()); }
271 inline int wxIsdigit_l(wchar_t c, const wxXLocale& loc)
272 { return wxCRT_Isdigit_lW(c, loc.Get()); }
273 inline int wxIsgraph_l(wchar_t c, const wxXLocale& loc)
274 { return wxCRT_Isgraph_lW(c, loc.Get()); }
275 inline int wxIslower_l(wchar_t c, const wxXLocale& loc)
276 { return wxCRT_Islower_lW(c, loc.Get()); }
277 inline int wxIsprint_l(wchar_t c, const wxXLocale& loc)
278 { return wxCRT_Isprint_lW(c, loc.Get()); }
279 inline int wxIspunct_l(wchar_t c, const wxXLocale& loc)
280 { return wxCRT_Ispunct_lW(c, loc.Get()); }
281 inline int wxIsspace_l(wchar_t c, const wxXLocale& loc)
282 { return wxCRT_Isspace_lW(c, loc.Get()); }
283 inline int wxIsupper_l(wchar_t c, const wxXLocale& loc)
284 { return wxCRT_Isupper_lW(c, loc.Get()); }
285 inline int wxIsxdigit_l(wchar_t c, const wxXLocale& loc)
286 { return wxCRT_Isxdigit_lW(c, loc.Get()); }
287 inline wchar_t wxTolower_l(wchar_t c, const wxXLocale& loc)
288 { return wxCRT_Tolower_lW(c, loc.Get()); }
289 inline wchar_t wxToupper_l(wchar_t c, const wxXLocale& loc)
290 { return wxCRT_Toupper_lW(c, loc.Get()); }
291
292
293 // stdlib functions for numeric <-> string conversion
294 // (see notes above about missing functions)
295 #define wxCRT_Strtod_lW wxXLOCALE_IDENT(wcstod_l)
296 #define wxCRT_Strtol_lW wxXLOCALE_IDENT(wcstol_l)
297 #define wxCRT_Strtoul_lW wxXLOCALE_IDENT(wcstoul_l)
298
299 inline double wxStrtod_l(const wchar_t *c, wchar_t **endptr, const wxXLocale& loc)
300 { return wxCRT_Strtod_lW(c, endptr, loc.Get()); }
301 inline long wxStrtol_l(const wchar_t *c, wchar_t **endptr, int base, const wxXLocale& loc)
302 { return wxCRT_Strtol_lW(c, endptr, base, loc.Get()); }
303 inline unsigned long wxStrtoul_l(const wchar_t *c, wchar_t **endptr, int base, const wxXLocale& loc)
304 { return wxCRT_Strtoul_lW(c, endptr, base, loc.Get()); }
305
306 #endif // wxUSE_UNICDE (ctype functions)
307 #else // !wxHAS_XLOCALE_SUPPORT
308 // ctype functions
309 int WXDLLIMPEXP_BASE wxIsalnum_l(const wxUniChar& c, const wxXLocale& loc);
310 int WXDLLIMPEXP_BASE wxIsalpha_l(const wxUniChar& c, const wxXLocale& loc);
311 int WXDLLIMPEXP_BASE wxIscntrl_l(const wxUniChar& c, const wxXLocale& loc);
312 int WXDLLIMPEXP_BASE wxIsdigit_l(const wxUniChar& c, const wxXLocale& loc);
313 int WXDLLIMPEXP_BASE wxIsgraph_l(const wxUniChar& c, const wxXLocale& loc);
314 int WXDLLIMPEXP_BASE wxIslower_l(const wxUniChar& c, const wxXLocale& loc);
315 int WXDLLIMPEXP_BASE wxIsprint_l(const wxUniChar& c, const wxXLocale& loc);
316 int WXDLLIMPEXP_BASE wxIspunct_l(const wxUniChar& c, const wxXLocale& loc);
317 int WXDLLIMPEXP_BASE wxIsspace_l(const wxUniChar& c, const wxXLocale& loc);
318 int WXDLLIMPEXP_BASE wxIsupper_l(const wxUniChar& c, const wxXLocale& loc);
319 int WXDLLIMPEXP_BASE wxIsxdigit_l(const wxUniChar& c, const wxXLocale& loc);
320 int WXDLLIMPEXP_BASE wxTolower_l(const wxUniChar& c, const wxXLocale& loc);
321 int WXDLLIMPEXP_BASE wxToupper_l(const wxUniChar& c, const wxXLocale& loc);
322 #endif // wxHAS_XLOCALE_SUPPORT/!wxHAS_XLOCALE_SUPPORT
323
324 #endif // wxUSE_XLOCALE
325
326 #endif // _WX_XLOCALE_H_