1 //////////////////////////////////////////////////////////////////////////////
3 // Purpose: Header to provide some xlocale wrappers
4 // Author: Brian Vanderburg II, Vadim Zeitlin
7 // Copyright: (c) 2008 Brian Vanderburg II
8 // 2008 Vadim Zeitlin <vadim@wxwidgets.org>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
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.
20 TODO: Currently only the character classification and transformation
21 functions and number <-> string functions, are implemented,
23 - formatted IO: scanf_l(), printf_l() &c
24 - time: strftime_l(), strptime_l()
27 #ifndef _WX_XLOCALE_H_
28 #define _WX_XLOCALE_H_
30 #include "wx/defs.h" // wxUSE_XLOCALE
34 #include "wx/crt.h" // Includes wx/chartype.h, wx/wxcrt.h(wx/string.h)
35 #include "wx/intl.h" // wxLanguage
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)
53 // Locale type and identifier name
54 typedef locale_t wxXLocale_t
;
56 #define wxXLOCALE_IDENT(name) name
58 #error "Unknown xlocale support"
60 #endif // wxHAS_XLOCALE_SUPPORT
63 // wxXLocale is a wrapper around the native type representing a locale.
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
74 class WXDLLIMPEXP_BASE wxXLocale
77 // Construct an uninitialized locale
78 wxXLocale() { m_locale
= NULL
; }
80 // Construct from a symbolic language constant
81 wxXLocale(wxLanguage lang
);
83 // Construct from the given language string
84 wxXLocale(const char *loc
) { Init(loc
); }
87 ~wxXLocale() { Free(); }
90 // Get the global "C" locale object
91 static wxXLocale
& GetCLocale();
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
; }
98 wxXLocale_t
Get() const { return m_locale
; }
100 bool operator== (const wxXLocale
& loc
) const
101 { return m_locale
== loc
.m_locale
; }
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"); }
108 // Create from the given language string (called from ctors)
109 void Init(const char *loc
);
111 // Free the locale if it's non-NULL
115 // The corresponding locale handle, NULL if invalid
116 wxXLocale_t m_locale
;
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
);
126 #else // !wxHAS_XLOCALE_SUPPORT
128 // Skeleton version supporting only the "C" locale for the systems without
130 class WXDLLIMPEXP_BASE wxXLocale
133 // Construct an uninitialized locale
134 wxXLocale() { m_isC
= false; }
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
)
141 m_isC
= lang
== wxLANGUAGE_ENGLISH_US
;
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
)
148 m_isC
= loc
&& (strcmp(loc
, "C") == 0 || strcmp(loc
, "POSIX") == 0);
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
156 // Get the global "C" locale object
157 static wxXLocale
& GetCLocale();
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
; }
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; }
168 // Without xlocale support this class can only represent "C" locale, if
169 // this is false the object is invalid
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
);
179 #endif // wxHAS_XLOCALE_SUPPORT/!wxHAS_XLOCALE_SUPPORT
182 // A shorter synonym for the most commonly used locale object
183 #define wxCLocale (wxXLocale::GetCLocale())
184 extern WXDLLIMPEXP_DATA_BASE(wxXLocale
) wxNullXLocale
;
186 // Wrappers for various functions:
187 #ifdef wxHAS_XLOCALE_SUPPORT
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)
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()); }
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:
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)
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()); }
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)
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()); }
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)
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()); }
306 #endif // wxUSE_UNICDE (ctype functions)
307 #else // !wxHAS_XLOCALE_SUPPORT
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
);
324 double WXDLLIMPEXP_BASE
wxStrtod_l(const wchar_t* str
, wchar_t **endptr
, const wxXLocale
& loc
);
325 double WXDLLIMPEXP_BASE
wxStrtod_l(const char* str
, char **endptr
, const wxXLocale
& loc
);
326 long WXDLLIMPEXP_BASE
wxStrtol_l(const wchar_t* str
, wchar_t **endptr
, int base
, const wxXLocale
& loc
);
327 long WXDLLIMPEXP_BASE
wxStrtol_l(const char* str
, char **endptr
, int base
, const wxXLocale
& loc
);
328 unsigned long WXDLLIMPEXP_BASE
wxStrtoul_l(const wchar_t* str
, wchar_t **endptr
, int base
, const wxXLocale
& loc
);
329 unsigned long WXDLLIMPEXP_BASE
wxStrtoul_l(const char* str
, char **endptr
, int base
, const wxXLocale
& loc
);
331 #endif // wxHAS_XLOCALE_SUPPORT/!wxHAS_XLOCALE_SUPPORT
333 #endif // wxUSE_XLOCALE
335 #endif // _WX_XLOCALE_H_