ReactOS  0.4.14-dev-55-g2da92ac
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 
27 static const xmlChar* xsltDefaultRegion(const xmlChar *localeName);
28 
29 #ifdef XSLT_LOCALE_WINAPI
30 xmlRMutexPtr xsltLocaleMutex = NULL;
31 
32 struct xsltRFC1766Info_s {
33  /*note typedef unsigned char xmlChar !*/
35  /*note typedef LCID xsltLocale !*/
36  xsltLocale lcid;
37 };
38 typedef struct xsltRFC1766Info_s xsltRFC1766Info;
39 
40 static int xsltLocaleListSize = 0;
41 static xsltRFC1766Info *xsltLocaleList = NULL;
42 
43 
44 static xsltLocale
45 xslt_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 
54 static void xsltEnumSupportedLocales(void);
55 #endif
56 
62 void
64 #ifdef XSLT_LOCALE_WINAPI
65  xmlRMutexLock(xsltLocaleMutex);
66  xmlFree(xsltLocaleList);
67  xsltLocaleList = NULL;
68  xmlRMutexUnlock(xsltLocaleMutex);
69 #endif
70 }
71 
82 xsltNewLocale(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);
187 end:
188  return(locale);
189 }
190 #endif
191 
192 #ifdef XSLT_LOCALE_NONE
193  return(NULL);
194 #endif
195 }
196 
197 static const xmlChar*
198 xsltDefaultRegion(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 
341 void
343 #ifdef XSLT_LOCALE_POSIX
344  freelocale(locale);
345 #endif
346 }
347 
360 {
361 #ifdef XSLT_LOCALE_NONE
362  return(NULL);
363 #else
364  size_t xstrlen, r;
365  xsltLocaleChar *xstr;
366 
367 #ifdef XSLT_LOCALE_POSIX
368  xstrlen = strxfrm_l(NULL, (const char *)string, 0, locale) + 1;
369  xstr = (xsltLocaleChar *) xmlMalloc(xstrlen);
370  if (xstr == NULL) {
372  "xsltStrxfrm : out of memory error\n");
373  return(NULL);
374  }
375 
376  r = strxfrm_l((char *)xstr, (const char *)string, xstrlen, locale);
377 #endif
378 
379 #ifdef XSLT_LOCALE_WINAPI
380  xstrlen = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, NULL, 0);
381  if (xstrlen == 0) {
382  xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar check failed\n");
383  return(NULL);
384  }
385  xstr = (xsltLocaleChar*) xmlMalloc(xstrlen * sizeof(xsltLocaleChar));
386  if (xstr == NULL) {
387  xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
388  return(NULL);
389  }
390  r = MultiByteToWideChar(CP_UTF8, 0, (char *) string, -1, xstr, xstrlen);
391  if (r == 0) {
392  xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar failed\n");
393  xmlFree(xstr);
394  return(NULL);
395  }
396  return(xstr);
397 #endif /* XSLT_LOCALE_WINAPI */
398 
399  if (r >= xstrlen) {
400  xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : strxfrm failed\n");
401  xmlFree(xstr);
402  return(NULL);
403  }
404 
405  return(xstr);
406 #endif /* XSLT_LOCALE_NONE */
407 }
408 
421 int
423  (void)locale;
424 #ifdef XSLT_LOCALE_WINAPI
425 {
426  int ret;
427  if (str1 == str2) return(0);
428  if (str1 == NULL) return(-1);
429  if (str2 == NULL) return(1);
430  ret = CompareStringW(locale, 0, str1, -1, str2, -1);
431  if (ret == 0) {
432  xsltTransformError(NULL, NULL, NULL, "xsltLocaleStrcmp : CompareStringW fail\n");
433  return(0);
434  }
435  return(ret - 2);
436 }
437 #else
438  return(xmlStrcmp(str1, str2));
439 #endif
440 }
441 
442 #ifdef XSLT_LOCALE_WINAPI
443 
452 xsltCountSupportedLocales(LPSTR lcid) {
453  (void) lcid;
454  ++xsltLocaleListSize;
455  return(TRUE);
456 }
457 
467 xsltIterateSupportedLocales(LPSTR lcid) {
468  static int count = 0;
469  xmlChar iso639lang [XSLTMAX_ISO639LANGLEN +1];
470  xmlChar iso3136ctry[XSLTMAX_ISO3166CNTRYLEN+1];
471  int k, l;
472  xsltRFC1766Info *p = xsltLocaleList + count;
473 
474  k = sscanf(lcid, "%lx", (long*)&p->lcid);
475  if (k < 1) goto end;
476  /*don't count terminating null character*/
478  (char *) iso639lang, sizeof(iso639lang));
479  if (--k < 1) goto end;
481  (char *) iso3136ctry, sizeof(iso3136ctry));
482  if (--l < 1) goto end;
483 
484  { /*fill results*/
485  xmlChar *q = p->tag;
486  memcpy(q, iso639lang, k);
487  q += k;
488  *q++ = '-';
489  memcpy(q, iso3136ctry, l);
490  q += l;
491  *q = '\0';
492  }
493  ++count;
494 end:
495  return((count < xsltLocaleListSize) ? TRUE : FALSE);
496 }
497 
498 
499 static void
500 xsltEnumSupportedLocales(void) {
501  xmlRMutexLock(xsltLocaleMutex);
502  if (xsltLocaleListSize <= 0) {
503  size_t len;
504 
505  EnumSystemLocalesA(xsltCountSupportedLocales, LCID_SUPPORTED);
506 
507  len = xsltLocaleListSize * sizeof(xsltRFC1766Info);
508  xsltLocaleList = xmlMalloc(len);
509  memset(xsltLocaleList, 0, len);
510  EnumSystemLocalesA(xsltIterateSupportedLocales, LCID_SUPPORTED);
511  }
512  xmlRMutexUnlock(xsltLocaleMutex);
513 }
514 
515 #endif /*def XSLT_LOCALE_WINAPI*/
#define TRUE
Definition: types.h:120
#define TOLOWER(c)
Definition: xsltlocale.c:18
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define LOCALE_SISO639LANGNAME
Definition: winnls.h:127
XMLPUBFUN void XMLCALL xmlRMutexLock(xmlRMutexPtr tok)
Definition: threads.c:343
xsltLocaleChar * xsltStrxfrm(xsltLocale locale, const xmlChar *string)
Definition: xsltlocale.c:359
int xsltLocaleStrcmp(xsltLocale locale, const xsltLocaleChar *str1, const xsltLocaleChar *str2)
Definition: xsltlocale.c:422
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: lang.c:1018
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define TOUPPER(c)
Definition: xsltlocale.c:17
#define CALLBACK
Definition: compat.h:27
void * xsltLocale
Definition: xsltlocale.h:63
Definition: ecma_167.h:138
GLuint GLuint end
Definition: gl.h:1545
char * LPSTR
Definition: xmlstorage.h:182
void xsltFreeLocales(void)
Definition: xsltlocale.c:63
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 CP_UTF8
Definition: nls.h:20
Definition: _locale.h:75
unsigned int BOOL
Definition: ntddk_ex.h:94
smooth NULL
Definition: ftsmooth.c:416
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
r l[0]
Definition: byte_order.h:167
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: lang.c:2275
void xsltFreeLocale(xsltLocale locale)
Definition: xsltlocale.c:342
const GLubyte * c
Definition: glext.h:8905
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:250
xmlChar xsltLocaleChar
Definition: xsltlocale.h:64
XMLPUBFUN void XMLCALL xmlRMutexUnlock(xmlRMutexPtr tok)
Definition: threads.c:388
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
#define XSLTMAX_ISO3166CNTRYLEN
Definition: xsltlocale.c:23
int ret
unsigned char xmlChar
Definition: xmlstring.h:28
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
static const wchar_t void * locale
Definition: printf.c:73
#define LOCALE_SISO3166CTRYNAME
Definition: winnls.h:128
BOOL WINAPI EnumSystemLocalesA(LOCALE_ENUMPROCA lpfnLocaleEnum, DWORD dwFlags)
Definition: lang.c:1589
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:247
xsltLocale xsltNewLocale(const xmlChar *languageTag)
Definition: xsltlocale.c:82
#define XSLTMAX_ISO639LANGLEN
Definition: xsltlocale.c:22
#define MultiByteToWideChar
Definition: compat.h:100
#define XSLTMAX_LANGTAGLEN
Definition: xsltlocale.c:25
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define c
Definition: ke_i.h:80
GLfloat GLfloat p
Definition: glext.h:8902
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:678
#define ISALPHA(c)
Definition: xsltlocale.c:19
#define memset(x, y, z)
Definition: compat.h:39
int k
Definition: mpi.c:3369
static const xmlChar * xsltDefaultRegion(const xmlChar *localeName)
Definition: xsltlocale.c:198
#define LCID_SUPPORTED
Definition: winnls.h:199
XMLPUBFUN int XMLCALL xmlStrcmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:132