ReactOS 0.4.16-dev-122-g325d74c
xsltlocale.c
Go to the documentation of this file.
1/*
2 * xsltlocale.c: locale handling
3 *
4 * Reference:
5 * RFC 3066: Tags for the Identification of Languages
6 * http://www.ietf.org/rfc/rfc3066.txt
7 * ISO 639-1, ISO 3166-1
8 *
9 * Author: Nick Wellnhofer
10 * winapi port: Roumen Petrov
11 */
12
13#include "precomp.h"
14
15#include "xsltlocale.h"
16
17#define TOUPPER(c) (c & ~0x20)
18#define TOLOWER(c) (c | 0x20)
19#define ISALPHA(c) ((unsigned)(TOUPPER(c) - 'A') < 26)
20
21/*without terminating null character*/
22#define XSLTMAX_ISO639LANGLEN 8
23#define XSLTMAX_ISO3166CNTRYLEN 8
24 /* <lang>-<cntry> */
25#define XSLTMAX_LANGTAGLEN (XSLTMAX_ISO639LANGLEN+1+XSLTMAX_ISO3166CNTRYLEN)
26
27static const xmlChar* xsltDefaultRegion(const xmlChar *localeName);
28
29#ifdef XSLT_LOCALE_WINAPI
30xmlRMutexPtr xsltLocaleMutex = NULL;
31
32struct xsltRFC1766Info_s {
33 /*note typedef unsigned char xmlChar !*/
35 /*note typedef LCID xsltLocale !*/
36 xsltLocale lcid;
37};
38typedef struct xsltRFC1766Info_s xsltRFC1766Info;
39
40static int xsltLocaleListSize = 0;
41static xsltRFC1766Info *xsltLocaleList = NULL;
42
43
44static xsltLocale
45xslt_locale_WINAPI(const xmlChar *languageTag) {
46 int k;
47 xsltRFC1766Info *p = xsltLocaleList;
48
49 for (k=0; k<xsltLocaleListSize; k++, p++)
50 if (xmlStrcmp(p->tag, languageTag) == 0) return p->lcid;
51 return((xsltLocale)0);
52}
53
54static void xsltEnumSupportedLocales(void);
55#endif
56
62void
64#ifdef XSLT_LOCALE_WINAPI
65 xmlRMutexLock(xsltLocaleMutex);
66 xmlFree(xsltLocaleList);
67 xsltLocaleList = NULL;
68 xmlRMutexUnlock(xsltLocaleMutex);
69#endif
70}
71
82xsltNewLocale(const xmlChar *languageTag) {
83#ifdef XSLT_LOCALE_POSIX
85 char localeName[XSLTMAX_LANGTAGLEN+6]; /* 6 chars for ".utf8\0" */
86 const xmlChar *p = languageTag;
87 const char *region = NULL;
88 char *q = localeName;
89 int i, llen;
90
91 /* Convert something like "pt-br" to "pt_BR.utf8" */
92
93 if (languageTag == NULL)
94 return(NULL);
95
96 for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i)
97 *q++ = TOLOWER(*p++);
98
99 if (i == 0)
100 return(NULL);
101
102 llen = i;
103
104 if (*p) {
105 if (*p++ != '-')
106 return(NULL);
107 *q++ = '_';
108
109 for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i)
110 *q++ = TOUPPER(*p++);
111
112 if (i == 0 || *p)
113 return(NULL);
114
115 memcpy(q, ".utf8", 6);
116 locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
117 if (locale != NULL)
118 return(locale);
119
120 /* Continue without using country code */
121
122 q = localeName + llen;
123 }
124
125 /* Try locale without territory, e.g. for Esperanto (eo) */
126
127 memcpy(q, ".utf8", 6);
128 locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
129 if (locale != NULL)
130 return(locale);
131
132 /* Try to find most common country for language */
133
134 if (llen != 2)
135 return(NULL);
136
137 region = (char *)xsltDefaultRegion((xmlChar *)localeName);
138 if (region == NULL)
139 return(NULL);
140
141 q = localeName + llen;
142 *q++ = '_';
143 *q++ = region[0];
144 *q++ = region[1];
145 memcpy(q, ".utf8", 6);
146 locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
147
148 return(locale);
149#endif
150
151#ifdef XSLT_LOCALE_WINAPI
152{
154 xmlChar localeName[XSLTMAX_LANGTAGLEN+1];
155 xmlChar *q = localeName;
156 const xmlChar *p = languageTag;
157 int i, llen;
158 const xmlChar *region = NULL;
159
160 if (languageTag == NULL) goto end;
161
162 xsltEnumSupportedLocales();
163
164 for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i)
165 *q++ = TOLOWER(*p++);
166 if (i == 0) goto end;
167
168 llen = i;
169 *q++ = '-';
170 if (*p) { /*if country tag is given*/
171 if (*p++ != '-') goto end;
172
173 for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i)
174 *q++ = TOUPPER(*p++);
175 if (i == 0 || *p) goto end;
176
177 *q = '\0';
178 locale = xslt_locale_WINAPI(localeName);
179 if (locale != (xsltLocale)0) goto end;
180 }
181 /* Try to find most common country for language */
182 region = xsltDefaultRegion(localeName);
183 if (region == NULL) goto end;
184
185 strcpy((char *) localeName + llen + 1, (char *) region);
186 locale = xslt_locale_WINAPI(localeName);
187end:
188 return(locale);
189}
190#endif
191
192#ifdef XSLT_LOCALE_NONE
193 return(NULL);
194#endif
195}
196
197static const xmlChar*
198xsltDefaultRegion(const xmlChar *localeName) {
199 xmlChar c;
200 /* region should be xmlChar, but gcc warns on all string assignments */
201 const char *region = NULL;
202
203 c = localeName[1];
204 /* This is based on the locales from glibc 2.3.3 */
205
206 switch (localeName[0]) {
207 case 'a':
208 if (c == 'a' || c == 'm') region = "ET";
209 else if (c == 'f') region = "ZA";
210 else if (c == 'n') region = "ES";
211 else if (c == 'r') region = "AE";
212 else if (c == 'z') region = "AZ";
213 break;
214 case 'b':
215 if (c == 'e') region = "BY";
216 else if (c == 'g') region = "BG";
217 else if (c == 'n') region = "BD";
218 else if (c == 'r') region = "FR";
219 else if (c == 's') region = "BA";
220 break;
221 case 'c':
222 if (c == 'a') region = "ES";
223 else if (c == 's') region = "CZ";
224 else if (c == 'y') region = "GB";
225 break;
226 case 'd':
227 if (c == 'a') region = "DK";
228 else if (c == 'e') region = "DE";
229 break;
230 case 'e':
231 if (c == 'l') region = "GR";
232 else if (c == 'n' || c == 'o') region = "US";
233 else if (c == 's' || c == 'u') region = "ES";
234 else if (c == 't') region = "EE";
235 break;
236 case 'f':
237 if (c == 'a') region = "IR";
238 else if (c == 'i') region = "FI";
239 else if (c == 'o') region = "FO";
240 else if (c == 'r') region = "FR";
241 break;
242 case 'g':
243 if (c == 'a') region = "IE";
244 else if (c == 'l') region = "ES";
245 else if (c == 'v') region = "GB";
246 break;
247 case 'h':
248 if (c == 'e') region = "IL";
249 else if (c == 'i') region = "IN";
250 else if (c == 'r') region = "HT";
251 else if (c == 'u') region = "HU";
252 break;
253 case 'i':
254 if (c == 'd') region = "ID";
255 else if (c == 's') region = "IS";
256 else if (c == 't') region = "IT";
257 else if (c == 'w') region = "IL";
258 break;
259 case 'j':
260 if (c == 'a') region = "JP";
261 break;
262 case 'k':
263 if (c == 'l') region = "GL";
264 else if (c == 'o') region = "KR";
265 else if (c == 'w') region = "GB";
266 break;
267 case 'l':
268 if (c == 't') region = "LT";
269 else if (c == 'v') region = "LV";
270 break;
271 case 'm':
272 if (c == 'k') region = "MK";
273 else if (c == 'l' || c == 'r') region = "IN";
274 else if (c == 'n') region = "MN";
275 else if (c == 's') region = "MY";
276 else if (c == 't') region = "MT";
277 break;
278 case 'n':
279 if (c == 'b' || c == 'n' || c == 'o') region = "NO";
280 else if (c == 'e') region = "NP";
281 else if (c == 'l') region = "NL";
282 break;
283 case 'o':
284 if (c == 'm') region = "ET";
285 break;
286 case 'p':
287 if (c == 'a') region = "IN";
288 else if (c == 'l') region = "PL";
289 else if (c == 't') region = "PT";
290 break;
291 case 'r':
292 if (c == 'o') region = "RO";
293 else if (c == 'u') region = "RU";
294 break;
295 case 's':
296 switch (c) {
297 case 'e': region = "NO"; break;
298 case 'h': region = "YU"; break;
299 case 'k': region = "SK"; break;
300 case 'l': region = "SI"; break;
301 case 'o': region = "ET"; break;
302 case 'q': region = "AL"; break;
303 case 't': region = "ZA"; break;
304 case 'v': region = "SE"; break;
305 }
306 break;
307 case 't':
308 if (c == 'a' || c == 'e') region = "IN";
309 else if (c == 'h') region = "TH";
310 else if (c == 'i') region = "ER";
311 else if (c == 'r') region = "TR";
312 else if (c == 't') region = "RU";
313 break;
314 case 'u':
315 if (c == 'k') region = "UA";
316 else if (c == 'r') region = "PK";
317 break;
318 case 'v':
319 if (c == 'i') region = "VN";
320 break;
321 case 'w':
322 if (c == 'a') region = "BE";
323 break;
324 case 'x':
325 if (c == 'h') region = "ZA";
326 break;
327 case 'z':
328 if (c == 'h') region = "CN";
329 else if (c == 'u') region = "ZA";
330 break;
331 }
332 return((xmlChar *)region);
333}
334
341void
343#ifdef XSLT_LOCALE_POSIX
344 if (locale != NULL)
345 freelocale(locale);
346#endif
347}
348
361{
362#ifdef XSLT_LOCALE_NONE
363 return(NULL);
364#else
365 size_t xstrlen, r;
366 xsltLocaleChar *xstr;
367
368#ifdef XSLT_LOCALE_POSIX
369 xstrlen = strxfrm_l(NULL, (const char *)string, 0, locale) + 1;
370 xstr = (xsltLocaleChar *) xmlMalloc(xstrlen);
371 if (xstr == NULL) {
373 "xsltStrxfrm : out of memory error\n");
374 return(NULL);
375 }
376
377 r = strxfrm_l((char *)xstr, (const char *)string, xstrlen, locale);
378#endif
379
380#ifdef XSLT_LOCALE_WINAPI
381 xstrlen = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, NULL, 0);
382 if (xstrlen == 0) {
383 xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar check failed\n");
384 return(NULL);
385 }
386 xstr = (xsltLocaleChar*) xmlMalloc(xstrlen * sizeof(xsltLocaleChar));
387 if (xstr == NULL) {
388 xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
389 return(NULL);
390 }
391 r = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, xstr, xstrlen);
392 if (r == 0) {
393 xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar failed\n");
394 xmlFree(xstr);
395 return(NULL);
396 }
397 return(xstr);
398#endif /* XSLT_LOCALE_WINAPI */
399
400 if (r >= xstrlen) {
401 xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : strxfrm failed\n");
402 xmlFree(xstr);
403 return(NULL);
404 }
405
406 return(xstr);
407#endif /* XSLT_LOCALE_NONE */
408}
409
422int
424 (void)locale;
425#ifdef XSLT_LOCALE_WINAPI
426{
427 int ret;
428 if (str1 == str2) return(0);
429 if (str1 == NULL) return(-1);
430 if (str2 == NULL) return(1);
431 ret = CompareStringW(locale, 0, str1, -1, str2, -1);
432 if (ret == 0) {
433 xsltTransformError(NULL, NULL, NULL, "xsltLocaleStrcmp : CompareStringW fail\n");
434 return(0);
435 }
436 return(ret - 2);
437}
438#else
439 return(xmlStrcmp(str1, str2));
440#endif
441}
442
443#ifdef XSLT_LOCALE_WINAPI
453xsltCountSupportedLocales(LPSTR lcid) {
454 (void) lcid;
455 ++xsltLocaleListSize;
456 return(TRUE);
457}
458
468xsltIterateSupportedLocales(LPSTR lcid) {
469 static int count = 0;
470 xmlChar iso639lang [XSLTMAX_ISO639LANGLEN +1];
471 xmlChar iso3136ctry[XSLTMAX_ISO3166CNTRYLEN+1];
472 int k, l;
473 xsltRFC1766Info *p = xsltLocaleList + count;
474
475 k = sscanf(lcid, "%lx", (long*)&p->lcid);
476 if (k < 1) goto end;
477 /*don't count terminating null character*/
479 (char *) iso639lang, sizeof(iso639lang));
480 if (--k < 1) goto end;
482 (char *) iso3136ctry, sizeof(iso3136ctry));
483 if (--l < 1) goto end;
484
485 { /*fill results*/
486 xmlChar *q = p->tag;
487 memcpy(q, iso639lang, k);
488 q += k;
489 *q++ = '-';
490 memcpy(q, iso3136ctry, l);
491 q += l;
492 *q = '\0';
493 }
494 ++count;
495end:
496 return((count < xsltLocaleListSize) ? TRUE : FALSE);
497}
498
499
500static void
501xsltEnumSupportedLocales(void) {
502 xmlRMutexLock(xsltLocaleMutex);
503 if (xsltLocaleListSize <= 0) {
504 size_t len;
505
506 EnumSystemLocalesA(xsltCountSupportedLocales, LCID_SUPPORTED);
507
508 len = xsltLocaleListSize * sizeof(xsltRFC1766Info);
509 xsltLocaleList = xmlMalloc(len);
510 memset(xsltLocaleList, 0, len);
511 EnumSystemLocalesA(xsltIterateSupportedLocales, LCID_SUPPORTED);
512 }
513 xmlRMutexUnlock(xsltLocaleMutex);
514}
515
516#endif /*def XSLT_LOCALE_WINAPI*/
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
r l[0]
Definition: byte_order.h:168
Definition: _locale.h:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CALLBACK
Definition: compat.h:35
#define MultiByteToWideChar
Definition: compat.h:110
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:4013
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: locale.c:1599
BOOL WINAPI EnumSystemLocalesA(LOCALE_ENUMPROCA lpfnLocaleEnum, DWORD dwFlags)
Definition: locale.c:2983
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
const GLubyte * c
Definition: glext.h:8905
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
#define c
Definition: ke_i.h:80
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
int k
Definition: mpi.c:3369
#define CP_UTF8
Definition: nls.h:20
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:248
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
#define memset(x, y, z)
Definition: compat.h:39
Definition: ecma_167.h:138
XMLPUBFUN void XMLCALL xmlRMutexLock(xmlRMutexPtr tok)
Definition: threads.c:333
XMLPUBFUN void XMLCALL xmlRMutexUnlock(xmlRMutexPtr tok)
Definition: threads.c:377
int ret
#define LOCALE_SISO639LANGNAME
Definition: winnls.h:126
#define LCID_SUPPORTED
Definition: winnls.h:202
#define LOCALE_SISO3166CTRYNAME
Definition: winnls.h:127
char * LPSTR
Definition: xmlstorage.h:182
XMLPUBFUN int XMLCALL xmlStrcmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:133
unsigned char xmlChar
Definition: xmlstring.h:28
void xsltFreeLocales(void)
Definition: xsltlocale.c:63
static const xmlChar * xsltDefaultRegion(const xmlChar *localeName)
Definition: xsltlocale.c:198
#define XSLTMAX_LANGTAGLEN
Definition: xsltlocale.c:25
xsltLocaleChar * xsltStrxfrm(xsltLocale locale, const xmlChar *string)
Definition: xsltlocale.c:360
#define XSLTMAX_ISO3166CNTRYLEN
Definition: xsltlocale.c:23
#define XSLTMAX_ISO639LANGLEN
Definition: xsltlocale.c:22
void xsltFreeLocale(xsltLocale locale)
Definition: xsltlocale.c:342
xsltLocale xsltNewLocale(const xmlChar *languageTag)
Definition: xsltlocale.c:82
int xsltLocaleStrcmp(xsltLocale locale, const xsltLocaleChar *str1, const xsltLocaleChar *str2)
Definition: xsltlocale.c:423
#define TOUPPER(c)
Definition: xsltlocale.c:17
#define TOLOWER(c)
Definition: xsltlocale.c:18
#define ISALPHA(c)
Definition: xsltlocale.c:19
void * xsltLocale
Definition: xsltlocale.h:63
xmlChar xsltLocaleChar
Definition: xsltlocale.h:64
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:678