Coverage Report

Created: 2025-11-16 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wxwidgets/include/wx/xlocale.h
Line
Count
Source
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 defined(__VISUALC__)
40
        typedef _locale_t wxXLocale_t;
41
        #define wxXLOCALE_IDENT(name) _ ## name
42
    #elif defined(HAVE_LOCALE_T)
43
        // Some systems (notably macOS) require including a separate header for
44
        // locale_t and related functions.
45
        #ifdef HAVE_XLOCALE_H
46
            #include <xlocale.h>
47
        #endif
48
        #include <locale.h>
49
        #include <ctype.h>
50
        #include <stdlib.h>
51
        #include <wctype.h>
52
53
        // Locale type and identifier name
54
        typedef locale_t wxXLocale_t;
55
56
0
        #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
2
    wxXLocale() { m_locale = nullptr; }
79
80
#if wxUSE_INTL
81
    // Construct from a symbolic language constant
82
    wxXLocale(wxLanguage lang);
83
#endif
84
85
    // Construct from the given language string
86
0
    wxXLocale(const char *loc) { Init(loc); }
87
88
    // Destroy the locale
89
0
    ~wxXLocale() { Free(); }
90
91
92
    // Get the global "C" locale object
93
    static wxXLocale& GetCLocale();
94
95
    // Check if the object represents a valid locale (notice that without
96
    // wxHAS_XLOCALE_SUPPORT the only valid locale is the "C" one)
97
0
    bool IsOk() const { return m_locale != nullptr; }
98
99
    // Get the type
100
0
    wxXLocale_t Get() const { return m_locale; }
101
102
    bool operator== (const wxXLocale& loc) const
103
0
        { return m_locale == loc.m_locale; }
104
105
private:
106
    // Special ctor for the "C" locale, it's only used internally as the user
107
    // code is supposed to use GetCLocale()
108
0
    wxXLocale(struct wxXLocaleCTag * WXUNUSED(dummy)) { Init("C"); }
109
110
    // Create from the given language string (called from ctors)
111
    void Init(const char *loc);
112
113
    // Free the locale if it's non-null
114
    void Free();
115
116
117
    // The corresponding locale handle, nullptr if invalid
118
    wxXLocale_t m_locale;
119
120
121
    // POSIX xlocale API provides a duplocale() function but MSVC locale API
122
    // doesn't give us any means to copy a _locale_t object so we reduce the
123
    // functionality to least common denominator here -- it shouldn't be a
124
    // problem as copying the locale objects shouldn't be often needed
125
    wxDECLARE_NO_COPY_CLASS(wxXLocale);
126
};
127
128
#else // !wxHAS_XLOCALE_SUPPORT
129
130
// Skeleton version supporting only the "C" locale for the systems without
131
// xlocale support
132
class WXDLLIMPEXP_BASE wxXLocale
133
{
134
public:
135
    // Construct an uninitialized locale
136
    wxXLocale() { m_isC = false; }
137
138
    // Construct from a symbolic language constant: unless the language is
139
    // wxLANGUAGE_ENGLISH_US (which we assume to be the same as "C" locale)
140
    // the object will be invalid
141
    wxXLocale(wxLanguage lang)
142
    {
143
        m_isC = lang == wxLANGUAGE_ENGLISH_US;
144
    }
145
146
    // Construct from the given language string: unless the string is "C" or
147
    // "POSIX" the object will be invalid
148
    wxXLocale(const char *loc)
149
    {
150
        m_isC = loc && (strcmp(loc, "C") == 0 || strcmp(loc, "POSIX") == 0);
151
    }
152
153
    // Default copy ctor, assignment operator and dtor are ok (or would be if
154
    // we didn't use wxDECLARE_NO_COPY_CLASS() for consistency with the
155
    // xlocale version)
156
157
158
    // Get the global "C" locale object
159
    static wxXLocale& GetCLocale();
160
161
    // Check if the object represents a valid locale (notice that without
162
    // wxHAS_XLOCALE_SUPPORT the only valid locale is the "C" one)
163
    bool IsOk() const { return m_isC; }
164
165
private:
166
    // Special ctor for the "C" locale, it's only used internally as the user
167
    // code is supposed to use GetCLocale()
168
    wxXLocale(struct wxXLocaleCTag * WXUNUSED(dummy)) { m_isC = true; }
169
170
    // Without xlocale support this class can only represent "C" locale, if
171
    // this is false the object is invalid
172
    bool m_isC;
173
174
175
    // although it's not a problem to copy the objects of this class, we use
176
    // this macro in this implementation for consistency with the xlocale-based
177
    // one which can't be copied when using MSVC locale API
178
    wxDECLARE_NO_COPY_CLASS(wxXLocale);
179
};
180
181
#endif // wxHAS_XLOCALE_SUPPORT/!wxHAS_XLOCALE_SUPPORT
182
183
184
// A shorter synonym for the most commonly used locale object
185
0
#define wxCLocale (wxXLocale::GetCLocale())
186
extern WXDLLIMPEXP_DATA_BASE(wxXLocale) wxNullXLocale;
187
188
// Wrappers for various functions:
189
#ifdef wxHAS_XLOCALE_SUPPORT
190
191
    // ctype functions
192
    #define wxCRT_Isalnum_lA wxXLOCALE_IDENT(isalnum_l)
193
    #define wxCRT_Isalpha_lA wxXLOCALE_IDENT(isalpha_l)
194
    #define wxCRT_Iscntrl_lA wxXLOCALE_IDENT(iscntrl_l)
195
    #define wxCRT_Isdigit_lA wxXLOCALE_IDENT(isdigit_l)
196
    #define wxCRT_Isgraph_lA wxXLOCALE_IDENT(isgraph_l)
197
    #define wxCRT_Islower_lA wxXLOCALE_IDENT(islower_l)
198
    #define wxCRT_Isprint_lA wxXLOCALE_IDENT(isprint_l)
199
    #define wxCRT_Ispunct_lA wxXLOCALE_IDENT(ispunct_l)
200
    #define wxCRT_Isspace_lA wxXLOCALE_IDENT(isspace_l)
201
    #define wxCRT_Isupper_lA wxXLOCALE_IDENT(isupper_l)
202
    #define wxCRT_Isxdigit_lA wxXLOCALE_IDENT(isxdigit_l)
203
    #define wxCRT_Tolower_lA wxXLOCALE_IDENT(tolower_l)
204
    #define wxCRT_Toupper_lA wxXLOCALE_IDENT(toupper_l)
205
206
    inline int wxIsalnum_l(char c, const wxXLocale& loc)
207
0
        { return wxCRT_Isalnum_lA(static_cast<unsigned char>(c), loc.Get()); }
208
    inline int wxIsalpha_l(char c, const wxXLocale& loc)
209
0
        { return wxCRT_Isalpha_lA(static_cast<unsigned char>(c), loc.Get()); }
210
    inline int wxIscntrl_l(char c, const wxXLocale& loc)
211
0
        { return wxCRT_Iscntrl_lA(static_cast<unsigned char>(c), loc.Get()); }
212
    inline int wxIsdigit_l(char c, const wxXLocale& loc)
213
0
        { return wxCRT_Isdigit_lA(static_cast<unsigned char>(c), loc.Get()); }
214
    inline int wxIsgraph_l(char c, const wxXLocale& loc)
215
0
        { return wxCRT_Isgraph_lA(static_cast<unsigned char>(c), loc.Get()); }
216
    inline int wxIslower_l(char c, const wxXLocale& loc)
217
0
        { return wxCRT_Islower_lA(static_cast<unsigned char>(c), loc.Get()); }
218
    inline int wxIsprint_l(char c, const wxXLocale& loc)
219
0
        { return wxCRT_Isprint_lA(static_cast<unsigned char>(c), loc.Get()); }
220
    inline int wxIspunct_l(char c, const wxXLocale& loc)
221
0
        { return wxCRT_Ispunct_lA(static_cast<unsigned char>(c), loc.Get()); }
222
    inline int wxIsspace_l(char c, const wxXLocale& loc)
223
0
        { return wxCRT_Isspace_lA(static_cast<unsigned char>(c), loc.Get()); }
224
    inline int wxIsupper_l(char c, const wxXLocale& loc)
225
0
        { return wxCRT_Isupper_lA(static_cast<unsigned char>(c), loc.Get()); }
226
    inline int wxIsxdigit_l(char c, const wxXLocale& loc)
227
0
        { return wxCRT_Isxdigit_lA(static_cast<unsigned char>(c), loc.Get()); }
228
    inline int wxTolower_l(char c, const wxXLocale& loc)
229
0
        { return wxCRT_Tolower_lA(static_cast<unsigned char>(c), loc.Get()); }
230
    inline int wxToupper_l(char c, const wxXLocale& loc)
231
0
        { return wxCRT_Toupper_lA(static_cast<unsigned char>(c), loc.Get()); }
232
233
234
    // stdlib functions for numeric <-> string conversion
235
    // NOTE: GNU libc does not have ato[fil]_l functions;
236
    //       MSVC++8 does not have _strto[u]ll_l functions;
237
    //       thus we take the minimal set of functions provided in both environments:
238
239
    #define wxCRT_Strtod_lA wxXLOCALE_IDENT(strtod_l)
240
    #define wxCRT_Strtol_lA wxXLOCALE_IDENT(strtol_l)
241
    #define wxCRT_Strtoul_lA wxXLOCALE_IDENT(strtoul_l)
242
243
    inline double wxStrtod_lA(const char *c, char **endptr, const wxXLocale& loc)
244
0
        { return wxCRT_Strtod_lA(c, endptr, loc.Get()); }
245
    inline long wxStrtol_lA(const char *c, char **endptr, int base, const wxXLocale& loc)
246
0
        { return wxCRT_Strtol_lA(c, endptr, base, loc.Get()); }
247
    inline unsigned long wxStrtoul_lA(const char *c, char **endptr, int base, const wxXLocale& loc)
248
0
        { return wxCRT_Strtoul_lA(c, endptr, base, loc.Get()); }
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
0
        { return wxCRT_Isalnum_lW(c, loc.Get()); }
267
    inline int wxIsalpha_l(wchar_t c, const wxXLocale& loc)
268
0
        { return wxCRT_Isalpha_lW(c, loc.Get()); }
269
    inline int wxIscntrl_l(wchar_t c, const wxXLocale& loc)
270
0
        { return wxCRT_Iscntrl_lW(c, loc.Get()); }
271
    inline int wxIsdigit_l(wchar_t c, const wxXLocale& loc)
272
0
        { return wxCRT_Isdigit_lW(c, loc.Get()); }
273
    inline int wxIsgraph_l(wchar_t c, const wxXLocale& loc)
274
0
        { return wxCRT_Isgraph_lW(c, loc.Get()); }
275
    inline int wxIslower_l(wchar_t c, const wxXLocale& loc)
276
0
        { return wxCRT_Islower_lW(c, loc.Get()); }
277
    inline int wxIsprint_l(wchar_t c, const wxXLocale& loc)
278
0
        { return wxCRT_Isprint_lW(c, loc.Get()); }
279
    inline int wxIspunct_l(wchar_t c, const wxXLocale& loc)
280
0
        { return wxCRT_Ispunct_lW(c, loc.Get()); }
281
    inline int wxIsspace_l(wchar_t c, const wxXLocale& loc)
282
0
        { return wxCRT_Isspace_lW(c, loc.Get()); }
283
    inline int wxIsupper_l(wchar_t c, const wxXLocale& loc)
284
0
        { return wxCRT_Isupper_lW(c, loc.Get()); }
285
    inline int wxIsxdigit_l(wchar_t c, const wxXLocale& loc)
286
0
        { return wxCRT_Isxdigit_lW(c, loc.Get()); }
287
    inline wchar_t wxTolower_l(wchar_t c, const wxXLocale& loc)
288
0
        { return wxCRT_Tolower_lW(c, loc.Get()); }
289
    inline wchar_t wxToupper_l(wchar_t c, const wxXLocale& loc)
290
0
        { return wxCRT_Toupper_lW(c, loc.Get()); }
291
292
293
    // stdlib functions for numeric <-> string conversion
294
    // (see notes above about missing functions)
295
0
    #define wxCRT_Strtod_lW wxXLOCALE_IDENT(wcstod_l)
296
0
    #define wxCRT_Strtol_lW wxXLOCALE_IDENT(wcstol_l)
297
0
    #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
0
        { 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
0
        { 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
0
        { return wxCRT_Strtoul_lW(c, endptr, base, loc.Get()); }
305
#else // !wxHAS_XLOCALE_SUPPORT
306
    // ctype functions
307
    int WXDLLIMPEXP_BASE wxIsalnum_l(const wxUniChar& c, const wxXLocale& loc);
308
    int WXDLLIMPEXP_BASE wxIsalpha_l(const wxUniChar& c, const wxXLocale& loc);
309
    int WXDLLIMPEXP_BASE wxIscntrl_l(const wxUniChar& c, const wxXLocale& loc);
310
    int WXDLLIMPEXP_BASE wxIsdigit_l(const wxUniChar& c, const wxXLocale& loc);
311
    int WXDLLIMPEXP_BASE wxIsgraph_l(const wxUniChar& c, const wxXLocale& loc);
312
    int WXDLLIMPEXP_BASE wxIslower_l(const wxUniChar& c, const wxXLocale& loc);
313
    int WXDLLIMPEXP_BASE wxIsprint_l(const wxUniChar& c, const wxXLocale& loc);
314
    int WXDLLIMPEXP_BASE wxIspunct_l(const wxUniChar& c, const wxXLocale& loc);
315
    int WXDLLIMPEXP_BASE wxIsspace_l(const wxUniChar& c, const wxXLocale& loc);
316
    int WXDLLIMPEXP_BASE wxIsupper_l(const wxUniChar& c, const wxXLocale& loc);
317
    int WXDLLIMPEXP_BASE wxIsxdigit_l(const wxUniChar& c, const wxXLocale& loc);
318
    int WXDLLIMPEXP_BASE wxTolower_l(const wxUniChar& c, const wxXLocale& loc);
319
    int WXDLLIMPEXP_BASE wxToupper_l(const wxUniChar& c, const wxXLocale& loc);
320
321
    // stdlib functions
322
    double WXDLLIMPEXP_BASE wxStrtod_l(const wchar_t* str, wchar_t **endptr, const wxXLocale& loc);
323
    double WXDLLIMPEXP_BASE wxStrtod_l(const char* str, char **endptr, const wxXLocale& loc);
324
    long WXDLLIMPEXP_BASE wxStrtol_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc);
325
    long WXDLLIMPEXP_BASE wxStrtol_l(const char* str, char **endptr, int base, const wxXLocale& loc);
326
    unsigned long WXDLLIMPEXP_BASE wxStrtoul_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc);
327
    unsigned long WXDLLIMPEXP_BASE wxStrtoul_l(const char* str, char **endptr, int base, const wxXLocale& loc);
328
329
#endif // wxHAS_XLOCALE_SUPPORT/!wxHAS_XLOCALE_SUPPORT
330
331
#endif // wxUSE_XLOCALE
332
333
#endif // _WX_XLOCALE_H_