ReactOS 0.4.16-dev-2206-gc56950d
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#define IN_LIBXSLT
14#include "libxslt.h"
15
16#include <string.h>
17#include <libxml/xmlmemory.h>
18#include <libxml/threads.h>
19
20#include "xsltlocale.h"
21#include "xsltutils.h"
22
23#ifdef HAVE_STRXFRM_L
24
25 #define XSLT_LOCALE_POSIX
26
27 #ifdef HAVE_LOCALE_H
28 #include <locale.h>
29 #endif
30 #ifdef HAVE_XLOCALE_H
31 #include <xlocale.h>
32 #endif
33
34#elif defined(_WIN32)
35
36 #define XSLT_LOCALE_WINAPI
37
38 #include <windows.h>
39 #include <winnls.h>
40
41#else
42
43 #define XSLT_LOCALE_NONE
44
45#endif
46
47#define TOUPPER(c) (c & ~0x20)
48#define TOLOWER(c) (c | 0x20)
49#define ISALPHA(c) ((unsigned)(TOUPPER(c) - 'A') < 26)
50
51/*without terminating null character*/
52#define XSLTMAX_ISO639LANGLEN 8
53#define XSLTMAX_ISO3166CNTRYLEN 8
54 /* <lang>-<cntry> */
55#define XSLTMAX_LANGTAGLEN (XSLTMAX_ISO639LANGLEN+1+XSLTMAX_ISO3166CNTRYLEN)
56
57static const xmlChar* xsltDefaultRegion(const xmlChar *localeName);
58
59#ifdef XSLT_LOCALE_WINAPI
60xmlRMutexPtr xsltLocaleMutex = NULL;
61
62struct xsltRFC1766Info_s {
63 /*note typedef unsigned char xmlChar !*/
65 LCID lcid;
66};
67typedef struct xsltRFC1766Info_s xsltRFC1766Info;
68
69static int xsltLocaleListSize = 0;
70static xsltRFC1766Info *xsltLocaleList = NULL;
71
72
73static void *
74xslt_locale_WINAPI(const xmlChar *languageTag) {
75 int k;
76 xsltRFC1766Info *p = xsltLocaleList;
77
78 for (k=0; k<xsltLocaleListSize; k++, p++)
79 if (xmlStrcmp(p->tag, languageTag) == 0)
80 return(&p->lcid);
81 return(NULL);
82}
83
84static void xsltEnumSupportedLocales(void);
85#endif
86
92void
94#ifdef XSLT_LOCALE_WINAPI
95 xmlRMutexLock(xsltLocaleMutex);
96 xmlFree(xsltLocaleList);
97 xsltLocaleList = NULL;
98 xmlRMutexUnlock(xsltLocaleMutex);
99#endif
100}
101
111void *
112xsltNewLocale(const xmlChar *languageTag, int lowerFirst ATTRIBUTE_UNUSED) {
113#ifdef XSLT_LOCALE_POSIX
114 locale_t locale;
115 char localeName[XSLTMAX_LANGTAGLEN+7]; /* 7 chars for ".UTF-8\0" */
116 const xmlChar *p = languageTag;
117 const char *region = NULL;
118 char *q = localeName;
119 int i, llen;
120
121 /* Convert something like "pt-br" to "pt_BR.UTF-8" */
122
123 if (languageTag == NULL)
124 return(NULL);
125
126 for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i)
127 *q++ = TOLOWER(*p++);
128
129 if (i == 0)
130 return(NULL);
131
132 llen = i;
133
134 if (*p) {
135 if (*p++ != '-')
136 return(NULL);
137 *q++ = '_';
138
139 for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i)
140 *q++ = TOUPPER(*p++);
141
142 if (i == 0 || *p)
143 return(NULL);
144
145 memcpy(q, ".UTF-8", 7);
146 locale = newlocale(LC_ALL_MASK, localeName, NULL);
147 if (locale != NULL)
148 return(locale);
149
150 /* Continue without using country code */
151
152 q = localeName + llen;
153 }
154
155 /* Try locale without territory, e.g. for Esperanto (eo) */
156
157 memcpy(q, ".UTF-8", 7);
158 locale = newlocale(LC_ALL_MASK, localeName, NULL);
159 if (locale != NULL)
160 return(locale);
161
162 /* Try to find most common country for language */
163
164 if (llen != 2)
165 return(NULL);
166
167 region = (char *)xsltDefaultRegion((xmlChar *)localeName);
168 if (region == NULL)
169 return(NULL);
170
171 q = localeName + llen;
172 *q++ = '_';
173 *q++ = region[0];
174 *q++ = region[1];
175 memcpy(q, ".UTF-8", 7);
176 locale = newlocale(LC_ALL_MASK, localeName, NULL);
177
178 return(locale);
179#endif
180
181#ifdef XSLT_LOCALE_WINAPI
182{
183 void *locale = NULL;
184 xmlChar localeName[XSLTMAX_LANGTAGLEN+1];
185 xmlChar *q = localeName;
186 const xmlChar *p = languageTag;
187 int i, llen;
188 const xmlChar *region = NULL;
189
190 if (languageTag == NULL) goto end;
191
192 xsltEnumSupportedLocales();
193
194 for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i)
195 *q++ = TOLOWER(*p++);
196 if (i == 0) goto end;
197
198 llen = i;
199 *q++ = '-';
200 if (*p) { /*if country tag is given*/
201 if (*p++ != '-') goto end;
202
203 for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i)
204 *q++ = TOUPPER(*p++);
205 if (i == 0 || *p) goto end;
206
207 *q = '\0';
208 locale = xslt_locale_WINAPI(localeName);
209 if (locale != (xsltLocale)0) goto end;
210 }
211 /* Try to find most common country for language */
212 region = xsltDefaultRegion(localeName);
213 if (region == NULL) goto end;
214
215 strcpy((char *) localeName + llen + 1, (char *) region);
216 locale = xslt_locale_WINAPI(localeName);
217end:
218 return(locale);
219}
220#endif
221
222#ifdef XSLT_LOCALE_NONE
223 return(NULL);
224#endif
225}
226
227static const xmlChar*
228xsltDefaultRegion(const xmlChar *localeName) {
229 xmlChar c;
230 /* region should be xmlChar, but gcc warns on all string assignments */
231 const char *region = NULL;
232
233 c = localeName[1];
234 /* This is based on the locales from glibc 2.3.3 */
235
236 switch (localeName[0]) {
237 case 'a':
238 if (c == 'a' || c == 'm') region = "ET";
239 else if (c == 'f') region = "ZA";
240 else if (c == 'n') region = "ES";
241 else if (c == 'r') region = "AE";
242 else if (c == 'z') region = "AZ";
243 break;
244 case 'b':
245 if (c == 'e') region = "BY";
246 else if (c == 'g') region = "BG";
247 else if (c == 'n') region = "BD";
248 else if (c == 'r') region = "FR";
249 else if (c == 's') region = "BA";
250 break;
251 case 'c':
252 if (c == 'a') region = "ES";
253 else if (c == 's') region = "CZ";
254 else if (c == 'y') region = "GB";
255 break;
256 case 'd':
257 if (c == 'a') region = "DK";
258 else if (c == 'e') region = "DE";
259 break;
260 case 'e':
261 if (c == 'l') region = "GR";
262 else if (c == 'n' || c == 'o') region = "US";
263 else if (c == 's' || c == 'u') region = "ES";
264 else if (c == 't') region = "EE";
265 break;
266 case 'f':
267 if (c == 'a') region = "IR";
268 else if (c == 'i') region = "FI";
269 else if (c == 'o') region = "FO";
270 else if (c == 'r') region = "FR";
271 break;
272 case 'g':
273 if (c == 'a') region = "IE";
274 else if (c == 'l') region = "ES";
275 else if (c == 'v') region = "GB";
276 break;
277 case 'h':
278 if (c == 'e') region = "IL";
279 else if (c == 'i') region = "IN";
280 else if (c == 'r') region = "HT";
281 else if (c == 'u') region = "HU";
282 break;
283 case 'i':
284 if (c == 'd') region = "ID";
285 else if (c == 's') region = "IS";
286 else if (c == 't') region = "IT";
287 else if (c == 'w') region = "IL";
288 break;
289 case 'j':
290 if (c == 'a') region = "JP";
291 break;
292 case 'k':
293 if (c == 'l') region = "GL";
294 else if (c == 'o') region = "KR";
295 else if (c == 'w') region = "GB";
296 break;
297 case 'l':
298 if (c == 't') region = "LT";
299 else if (c == 'v') region = "LV";
300 break;
301 case 'm':
302 if (c == 'k') region = "MK";
303 else if (c == 'l' || c == 'r') region = "IN";
304 else if (c == 'n') region = "MN";
305 else if (c == 's') region = "MY";
306 else if (c == 't') region = "MT";
307 break;
308 case 'n':
309 if (c == 'b' || c == 'n' || c == 'o') region = "NO";
310 else if (c == 'e') region = "NP";
311 else if (c == 'l') region = "NL";
312 break;
313 case 'o':
314 if (c == 'm') region = "ET";
315 break;
316 case 'p':
317 if (c == 'a') region = "IN";
318 else if (c == 'l') region = "PL";
319 else if (c == 't') region = "PT";
320 break;
321 case 'r':
322 if (c == 'o') region = "RO";
323 else if (c == 'u') region = "RU";
324 break;
325 case 's':
326 switch (c) {
327 case 'e': region = "NO"; break;
328 case 'h': region = "YU"; break;
329 case 'k': region = "SK"; break;
330 case 'l': region = "SI"; break;
331 case 'o': region = "ET"; break;
332 case 'q': region = "AL"; break;
333 case 't': region = "ZA"; break;
334 case 'v': region = "SE"; break;
335 }
336 break;
337 case 't':
338 if (c == 'a' || c == 'e') region = "IN";
339 else if (c == 'h') region = "TH";
340 else if (c == 'i') region = "ER";
341 else if (c == 'r') region = "TR";
342 else if (c == 't') region = "RU";
343 break;
344 case 'u':
345 if (c == 'k') region = "UA";
346 else if (c == 'r') region = "PK";
347 break;
348 case 'v':
349 if (c == 'i') region = "VN";
350 break;
351 case 'w':
352 if (c == 'a') region = "BE";
353 break;
354 case 'x':
355 if (c == 'h') region = "ZA";
356 break;
357 case 'z':
358 if (c == 'h') region = "CN";
359 else if (c == 'u') region = "ZA";
360 break;
361 }
362 return((xmlChar *)region);
363}
364
371void
373#ifdef XSLT_LOCALE_POSIX
374 if (locale != NULL)
375 freelocale(locale);
376#else
377 (void) locale;
378#endif
379}
380
391xmlChar *
392xsltStrxfrm(void *vlocale, const xmlChar *string)
393{
394#ifdef XSLT_LOCALE_NONE
395 return(NULL);
396#else
397 xmlChar *xstr;
398
399#ifdef XSLT_LOCALE_POSIX
400 size_t xstrlen, r;
401
402 xstrlen = strxfrm_l(NULL, (const char *)string, 0, vlocale) + 1;
403 xstr = (xmlChar *) xmlMalloc(xstrlen);
404 if (xstr == NULL) {
406 "xsltStrxfrm : out of memory error\n");
407 return(NULL);
408 }
409
410 r = strxfrm_l((char *)xstr, (const char *)string, xstrlen, vlocale);
411
412 if (r >= xstrlen) {
413 xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : strxfrm failed\n");
414 xmlFree(xstr);
415 return(NULL);
416 }
417#endif
418
419#ifdef XSLT_LOCALE_WINAPI
420 int wstrlen, xstrlen, r;
421 wchar_t *wstr;
422 LCID *lcid = vlocale;
423
424 wstrlen = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, NULL, 0);
425 if (wstrlen == 0) {
426 xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar check failed\n");
427 return(NULL);
428 }
429 wstr = (wchar_t *) xmlMalloc(wstrlen * sizeof(wchar_t));
430 if (wstr == NULL) {
431 xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
432 return(NULL);
433 }
434 r = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, wstr, wstrlen);
435 if (r == 0) {
436 xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar failed\n");
437 xmlFree(wstr);
438 return(NULL);
439 }
440 /* This returns the size in bytes. */
441 xstrlen = LCMapStringW(*lcid, LCMAP_SORTKEY, wstr, wstrlen, NULL, 0);
442 if (xstrlen == 0) {
443 xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : LCMapStringW failed\n");
444 xmlFree(wstr);
445 return(NULL);
446 }
447 xstr = (xmlChar*) xmlMalloc(xstrlen);
448 if (xstr == NULL) {
449 xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
450 xmlFree(wstr);
451 return(NULL);
452 }
453 r = LCMapStringW(*lcid, LCMAP_SORTKEY, wstr, wstrlen, (wchar_t *) xstr,
454 xstrlen);
455 xmlFree(wstr);
456 if (r == 0) {
457 xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : LCMapStringW failed\n");
458 xmlFree(xstr);
459 return(NULL);
460 }
461#endif /* XSLT_LOCALE_WINAPI */
462
463 return(xstr);
464#endif /* XSLT_LOCALE_NONE */
465}
466
481int
483 (void)locale;
484 return(xmlStrcmp(str1, str2));
485}
486
487#ifdef XSLT_LOCALE_WINAPI
496static BOOL CALLBACK
497xsltCountSupportedLocales(LPSTR lcid) {
498 (void) lcid;
499 ++xsltLocaleListSize;
500 return(TRUE);
501}
502
511static BOOL CALLBACK
512xsltIterateSupportedLocales(LPSTR lcid) {
513 static int count = 0;
514 xmlChar iso639lang [XSLTMAX_ISO639LANGLEN +1];
515 xmlChar iso3136ctry[XSLTMAX_ISO3166CNTRYLEN+1];
516 int k, l;
517 xsltRFC1766Info *p = xsltLocaleList + count;
518
519 k = sscanf(lcid, "%lx", (unsigned long*)&p->lcid);
520 if (k < 1) goto end;
521 /*don't count terminating null character*/
523 (char *) iso639lang, sizeof(iso639lang));
524 if (--k < 1) goto end;
526 (char *) iso3136ctry, sizeof(iso3136ctry));
527 if (--l < 1) goto end;
528
529 { /*fill results*/
530 xmlChar *q = p->tag;
531 memcpy(q, iso639lang, k);
532 q += k;
533 *q++ = '-';
534 memcpy(q, iso3136ctry, l);
535 q += l;
536 *q = '\0';
537 }
538 ++count;
539end:
540 return((count < xsltLocaleListSize) ? TRUE : FALSE);
541}
542
543
544static void
545xsltEnumSupportedLocales(void) {
546 xmlRMutexLock(xsltLocaleMutex);
547 if (xsltLocaleListSize <= 0) {
548 size_t len;
549
550 EnumSystemLocalesA(xsltCountSupportedLocales, LCID_SUPPORTED);
551
552 len = xsltLocaleListSize * sizeof(xsltRFC1766Info);
553 xsltLocaleList = xmlMalloc(len);
554 memset(xsltLocaleList, 0, len);
555 EnumSystemLocalesA(xsltIterateSupportedLocales, LCID_SUPPORTED);
556 }
557 xmlRMutexUnlock(xsltLocaleMutex);
558}
559
560#endif /*def XSLT_LOCALE_WINAPI*/
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 GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: locale.c:1609
BOOL WINAPI EnumSystemLocalesA(LOCALE_ENUMPROCA lpfnLocaleEnum, DWORD dwFlags)
Definition: locale.c:2986
INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen, LPWSTR dst, INT dstlen)
Definition: locale.c:3808
LCID lcid
Definition: locale.c:5656
_ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl sscanf(const char *, const char *,...) __WINE_CRT_SCANF_ATTR(2
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint end
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
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
#define c
Definition: ke_i.h:80
XMLPUBFUN void xmlRMutexLock(xmlRMutexPtr tok)
Definition: threads.c:297
XMLPUBFUN void xmlRMutexUnlock(xmlRMutexPtr tok)
Definition: threads.c:333
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
int k
Definition: mpi.c:3369
DWORD LCID
Definition: nls.h:13
#define CP_UTF8
Definition: nls.h:20
strcpy
Definition: string.h:131
xmlFreeFunc xmlFree
Definition: globals.c:184
xmlMallocFunc xmlMalloc
Definition: globals.c:193
XML_HIDDEN void xmlParserErrors const char const xmlChar const xmlChar * str2
Definition: parser.h:35
XML_HIDDEN void xmlParserErrors const char const xmlChar * str1
Definition: parser.h:35
#define memset(x, y, z)
Definition: compat.h:39
Definition: ecma_167.h:138
#define LOCALE_SISO639LANGNAME
Definition: winnls.h:133
#define LCMAP_SORTKEY
Definition: winnls.h:199
#define LCID_SUPPORTED
Definition: winnls.h:215
#define LOCALE_SISO3166CTRYNAME
Definition: winnls.h:134
char * LPSTR
Definition: xmlstorage.h:182
XMLPUBFUN int xmlStrcmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:135
unsigned char xmlChar
Definition: xmlstring.h:28
void xsltFreeLocales(void)
Definition: xsltlocale.c:93
int xsltLocaleStrcmp(void *locale, const xmlChar *str1, const xmlChar *str2)
Definition: xsltlocale.c:482
static const xmlChar * xsltDefaultRegion(const xmlChar *localeName)
Definition: xsltlocale.c:228
#define XSLTMAX_LANGTAGLEN
Definition: xsltlocale.c:55
#define XSLTMAX_ISO3166CNTRYLEN
Definition: xsltlocale.c:53
#define XSLTMAX_ISO639LANGLEN
Definition: xsltlocale.c:52
xmlChar * xsltStrxfrm(void *vlocale, const xmlChar *string)
Definition: xsltlocale.c:392
void * xsltNewLocale(const xmlChar *languageTag, int lowerFirst ATTRIBUTE_UNUSED)
Definition: xsltlocale.c:112
void xsltFreeLocale(void *locale)
Definition: xsltlocale.c:372
#define TOUPPER(c)
Definition: xsltlocale.c:47
#define TOLOWER(c)
Definition: xsltlocale.c:48
#define ISALPHA(c)
Definition: xsltlocale.c:49
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:762