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