extend wxXLocale with wxStrto[d,l,ul] functions; make wxXLocale::Init() a little...
[wxWidgets.git] / src / common / xlocale.cpp
1 //////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/xlocale.cpp
3 // Purpose: xlocale wrappers/impl 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 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #if wxUSE_XLOCALE
27
28 #ifndef WX_PRECOMP
29 #include "wx/module.h"
30 #endif
31
32 #include "wx/xlocale.h"
33
34 // ----------------------------------------------------------------------------
35 // module globals
36 // ----------------------------------------------------------------------------
37
38 // This is the C locale object, it is created on demand
39 static wxXLocale *gs_cLocale = NULL;
40
41 wxXLocale wxNullXLocale;
42
43
44 // ============================================================================
45 // implementation
46 // ============================================================================
47
48 // ----------------------------------------------------------------------------
49 // Module for gs_cLocale cleanup
50 // ----------------------------------------------------------------------------
51
52 class wxXLocaleModule : public wxModule
53 {
54 public:
55 virtual bool OnInit() { return true; }
56 virtual void OnExit() { wxDELETE(gs_cLocale); }
57
58 DECLARE_DYNAMIC_CLASS(wxXLocaleModule)
59 };
60
61 IMPLEMENT_DYNAMIC_CLASS(wxXLocaleModule, wxModule)
62
63
64 // ============================================================================
65 // wxXLocale implementation
66 // ============================================================================
67
68 // ----------------------------------------------------------------------------
69 // common parts
70 // ----------------------------------------------------------------------------
71
72 // Get the C locale
73 wxXLocale& wxXLocale::GetCLocale()
74 {
75 if ( !gs_cLocale )
76 {
77 gs_cLocale = new wxXLocale(static_cast<wxXLocaleCTag *>(NULL));
78 }
79
80 return *gs_cLocale;
81 }
82
83 #ifdef wxHAS_XLOCALE_SUPPORT
84
85 wxXLocale::wxXLocale(wxLanguage lang)
86 {
87 const wxLanguageInfo * const info = wxLocale::GetLanguageInfo(lang);
88 if ( !info )
89 {
90 m_locale = NULL;
91 }
92 else
93 {
94 Init(info->GetLocaleName().c_str());
95 }
96 }
97
98 #if wxCHECK_VISUALC_VERSION(8)
99
100 // ----------------------------------------------------------------------------
101 // implementation using MSVC locale API
102 // ----------------------------------------------------------------------------
103
104 void wxXLocale::Init(const char *loc)
105 {
106 if (!loc || *loc == '\0')
107 return;
108
109 m_locale = _create_locale(LC_ALL, loc);
110 }
111
112 void wxXLocale::Free()
113 {
114 if ( m_locale )
115 _free_locale(m_locale);
116 }
117
118 #elif defined(HAVE_LOCALE_T)
119
120 // ----------------------------------------------------------------------------
121 // implementation using xlocale API
122 // ----------------------------------------------------------------------------
123
124 void wxXLocale::Init(const char *loc)
125 {
126 if (!loc || *loc == '\0')
127 return;
128
129 m_locale = newlocale(LC_ALL_MASK, loc, NULL);
130 if (!m_locale)
131 {
132 // NOTE: here we do something similar to what wxSetLocaleTryUTF8() does
133 // in wxLocale code (but with newlocale() calls instead of wxSetlocale())
134 wxString buf(loc);
135 wxString buf2;
136 buf2 = buf + wxS(".UTF-8");
137 m_locale = newlocale(LC_ALL_MASK, buf2, NULL);
138 if ( !m_locale )
139 {
140 buf2 = buf + wxS(".utf-8");
141 m_locale = newlocale(LC_ALL_MASK, buf2, NULL);
142 }
143 if ( !m_locale )
144 {
145 buf2 = buf + wxS(".UTF8");
146 m_locale = newlocale(LC_ALL_MASK, buf2, NULL);
147 }
148 if ( !m_locale )
149 {
150 buf2 = buf + wxS(".utf8");
151 m_locale = newlocale(LC_ALL_MASK, buf2, NULL);
152 }
153 }
154
155 // TODO: wxLocale performs many more manipulations of the given locale
156 // string in the attempt to set a valid locale; reusing that code
157 // (changing it to take a generic wxTryLocale callback) would be nice
158 }
159
160 void wxXLocale::Free()
161 {
162 if ( m_locale )
163 freelocale(m_locale);
164 }
165
166 #else
167 #error "Unknown xlocale support."
168 #endif
169
170 #endif // wxHAS_XLOCALE_SUPPORT
171
172 #ifndef wxHAS_XLOCALE_SUPPORT
173
174 // ============================================================================
175 // Implementation of wxFoo_l() functions for "C" locale without xlocale support
176 // ============================================================================
177
178 // ----------------------------------------------------------------------------
179 // character classification and transformation functions
180 // ----------------------------------------------------------------------------
181
182 // lookup table and macros for character type functions
183 #define CTYPE_ALNUM 0x0001
184 #define CTYPE_ALPHA 0x0002
185 #define CTYPE_CNTRL 0x0004
186 #define CTYPE_DIGIT 0x0008
187 #define CTYPE_GRAPH 0x0010
188 #define CTYPE_LOWER 0x0020
189 #define CTYPE_PRINT 0x0040
190 #define CTYPE_PUNCT 0x0080
191 #define CTYPE_SPACE 0x0100
192 #define CTYPE_UPPER 0x0200
193 #define CTYPE_XDIGIT 0x0400
194
195 static unsigned int gs_lookup[] =
196 {
197 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
198 0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0004,
199 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
200 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
201 0x0140, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0,
202 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0,
203 0x0459, 0x0459, 0x0459, 0x0459, 0x0459, 0x0459, 0x0459, 0x0459,
204 0x0459, 0x0459, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0,
205 0x00D0, 0x0653, 0x0653, 0x0653, 0x0653, 0x0653, 0x0653, 0x0253,
206 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, 0x0253,
207 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, 0x0253, 0x0253,
208 0x0253, 0x0253, 0x0253, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x00D0,
209 0x00D0, 0x0473, 0x0473, 0x0473, 0x0473, 0x0473, 0x0473, 0x0073,
210 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073,
211 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073, 0x0073,
212 0x0073, 0x0073, 0x0073, 0x00D0, 0x00D0, 0x00D0, 0x00D0, 0x0004
213 };
214
215
216 #define CTYPE_TEST(c, t) ( (c) <= 127 && (gs_lookup[(c)] & (t)) )
217
218
219 // ctype functions
220 #define GEN_ISFUNC(name, test) \
221 int name(const wxUniChar& c, const wxXLocale& loc) \
222 { \
223 wxCHECK(loc.IsOk(), false); \
224 return CTYPE_TEST(c.GetValue(), test); \
225 }
226
227 GEN_ISFUNC(wxIsalnum_l, CTYPE_ALNUM)
228 GEN_ISFUNC(wxIsalpha_l, CTYPE_ALPHA)
229 GEN_ISFUNC(wxIscntrl_l, CTYPE_CNTRL)
230 GEN_ISFUNC(wxIsdigit_l, CTYPE_DIGIT)
231 GEN_ISFUNC(wxIsgraph_l, CTYPE_GRAPH)
232 GEN_ISFUNC(wxIslower_l, CTYPE_LOWER)
233 GEN_ISFUNC(wxIsprint_l, CTYPE_PRINT)
234 GEN_ISFUNC(wxIspunct_l, CTYPE_PUNCT)
235 GEN_ISFUNC(wxIsspace_l, CTYPE_SPACE)
236 GEN_ISFUNC(wxIsupper_l, CTYPE_UPPER)
237 GEN_ISFUNC(wxIsxdigit_l, CTYPE_XDIGIT)
238
239 int wxTolower_l(const wxUniChar& c, const wxXLocale& loc)
240 {
241 wxCHECK(loc.IsOk(), false);
242
243 if(CTYPE_TEST(c.GetValue(), CTYPE_UPPER))
244 {
245 return c - 'A' + 'a';
246 }
247
248 return c;
249 }
250
251 int wxToupper_l(const wxUniChar& c, const wxXLocale& loc)
252 {
253 wxCHECK(loc.IsOk(), false);
254
255 if(CTYPE_TEST(c.GetValue(), CTYPE_LOWER))
256 {
257 return c - 'a' + 'A';
258 }
259
260 return c;
261 }
262
263 #endif // !defined(wxHAS_XLOCALE_SUPPORT)
264
265 #endif // wxUSE_XLOCALE