| 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 | #else // !wxUSE_UNICODE |
| 306 | inline double wxStrtod_l(const char *c, char **endptr, const wxXLocale& loc) |
| 307 | { return wxCRT_Strtod_lA(c, endptr, loc.Get()); } |
| 308 | inline long wxStrtol_l(const char *c, char **endptr, int base, const wxXLocale& loc) |
| 309 | { return wxCRT_Strtol_lA(c, endptr, base, loc.Get()); } |
| 310 | inline unsigned long wxStrtoul_l(const char *c, char **endptr, int base, const wxXLocale& loc) |
| 311 | { return wxCRT_Strtoul_lA(c, endptr, base, loc.Get()); } |
| 312 | #endif // wxUSE_UNICODE |
| 313 | #else // !wxHAS_XLOCALE_SUPPORT |
| 314 | // ctype functions |
| 315 | int WXDLLIMPEXP_BASE wxIsalnum_l(const wxUniChar& c, const wxXLocale& loc); |
| 316 | int WXDLLIMPEXP_BASE wxIsalpha_l(const wxUniChar& c, const wxXLocale& loc); |
| 317 | int WXDLLIMPEXP_BASE wxIscntrl_l(const wxUniChar& c, const wxXLocale& loc); |
| 318 | int WXDLLIMPEXP_BASE wxIsdigit_l(const wxUniChar& c, const wxXLocale& loc); |
| 319 | int WXDLLIMPEXP_BASE wxIsgraph_l(const wxUniChar& c, const wxXLocale& loc); |
| 320 | int WXDLLIMPEXP_BASE wxIslower_l(const wxUniChar& c, const wxXLocale& loc); |
| 321 | int WXDLLIMPEXP_BASE wxIsprint_l(const wxUniChar& c, const wxXLocale& loc); |
| 322 | int WXDLLIMPEXP_BASE wxIspunct_l(const wxUniChar& c, const wxXLocale& loc); |
| 323 | int WXDLLIMPEXP_BASE wxIsspace_l(const wxUniChar& c, const wxXLocale& loc); |
| 324 | int WXDLLIMPEXP_BASE wxIsupper_l(const wxUniChar& c, const wxXLocale& loc); |
| 325 | int WXDLLIMPEXP_BASE wxIsxdigit_l(const wxUniChar& c, const wxXLocale& loc); |
| 326 | int WXDLLIMPEXP_BASE wxTolower_l(const wxUniChar& c, const wxXLocale& loc); |
| 327 | int WXDLLIMPEXP_BASE wxToupper_l(const wxUniChar& c, const wxXLocale& loc); |
| 328 | |
| 329 | // stdlib functions |
| 330 | double WXDLLIMPEXP_BASE wxStrtod_l(const wchar_t* str, wchar_t **endptr, const wxXLocale& loc); |
| 331 | double WXDLLIMPEXP_BASE wxStrtod_l(const char* str, char **endptr, const wxXLocale& loc); |
| 332 | long WXDLLIMPEXP_BASE wxStrtol_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc); |
| 333 | long WXDLLIMPEXP_BASE wxStrtol_l(const char* str, char **endptr, int base, const wxXLocale& loc); |
| 334 | unsigned long WXDLLIMPEXP_BASE wxStrtoul_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc); |
| 335 | unsigned long WXDLLIMPEXP_BASE wxStrtoul_l(const char* str, char **endptr, int base, const wxXLocale& loc); |
| 336 | |
| 337 | #endif // wxHAS_XLOCALE_SUPPORT/!wxHAS_XLOCALE_SUPPORT |
| 338 | |
| 339 | #endif // wxUSE_XLOCALE |
| 340 | |
| 341 | #endif // _WX_XLOCALE_H_ |