| OLD | NEW |
| 1 /* | 1 /* |
| 2 * xsltlocale.c: locale handling | 2 * xsltlocale.c: locale handling |
| 3 * | 3 * |
| 4 * Reference: | 4 * Reference: |
| 5 * RFC 3066: Tags for the Identification of Languages | 5 * RFC 3066: Tags for the Identification of Languages |
| 6 * http://www.ietf.org/rfc/rfc3066.txt | 6 * http://www.ietf.org/rfc/rfc3066.txt |
| 7 * ISO 639-1, ISO 3166-1 | 7 * ISO 639-1, ISO 3166-1 |
| 8 * | 8 * |
| 9 * Author: Nick Wellnhofer | 9 * Author: Nick Wellnhofer |
| 10 * winapi port: Roumen Petrov | 10 * winapi port: Roumen Petrov |
| 11 */ | 11 */ |
| 12 | 12 |
| 13 #define IN_LIBXSLT | 13 #define IN_LIBXSLT |
| 14 #include "libxslt.h" | 14 #include "libxslt.h" |
| 15 | 15 |
| 16 #include <string.h> | 16 #include <string.h> |
| 17 #include <libxml/xmlmemory.h> | 17 #include <libxml/xmlmemory.h> |
| 18 | 18 |
| 19 #include "xsltlocale.h" | 19 #include "xsltlocale.h" |
| 20 #include "xsltutils.h" | 20 #include "xsltutils.h" |
| 21 | 21 |
| 22 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 2 | 22 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 2 |
| 23 #define newlocale __newlocale | 23 #define newlocale __newlocale |
| 24 #define freelocale __freelocale | 24 #define freelocale __freelocale |
| 25 #define strxfrm_l __strxfrm_l | 25 #define strxfrm_l __strxfrm_l |
| 26 #define LC_COLLATE_MASK (1 << LC_COLLATE) | 26 #define LC_COLLATE_MASK (1 << LC_COLLATE) |
| 27 #endif | 27 #endif |
| 28 | 28 |
| 29 #define ISALPHA(c) ((c & 0xc0) == 0x40 && (unsigned)((c & 0x1f) - 1) < 26) | |
| 30 #define TOUPPER(c) (c & ~0x20) | 29 #define TOUPPER(c) (c & ~0x20) |
| 31 #define TOLOWER(c) (c | 0x20) | 30 #define TOLOWER(c) (c | 0x20) |
| 31 #define ISALPHA(c) ((unsigned)(TOUPPER(c) - 'A') < 26) |
| 32 | 32 |
| 33 /*without terminating null character*/ | 33 /*without terminating null character*/ |
| 34 #define XSLTMAX_ISO639LANGLEN 8 | 34 #define XSLTMAX_ISO639LANGLEN 8 |
| 35 #define XSLTMAX_ISO3166CNTRYLEN 8 | 35 #define XSLTMAX_ISO3166CNTRYLEN 8 |
| 36 /* <lang>-<cntry> */ | 36 /* <lang>-<cntry> */ |
| 37 #define XSLTMAX_LANGTAGLEN (XSLTMAX_ISO639LANGLEN+1+XSLTMAX_ISO3166
CNTRYLEN) | 37 #define XSLTMAX_LANGTAGLEN (XSLTMAX_ISO639LANGLEN+1+XSLTMAX_ISO3166
CNTRYLEN) |
| 38 | 38 |
| 39 static const xmlChar* xsltDefaultRegion(const xmlChar *localeName); | 39 static const xmlChar* xsltDefaultRegion(const xmlChar *localeName); |
| 40 | 40 |
| 41 #ifdef XSLT_LOCALE_WINAPI | 41 #ifdef XSLT_LOCALE_WINAPI |
| (...skipping 18 matching lines...) Expand all Loading... |
| 60 | 60 |
| 61 for (k=0; k<xsltLocaleListSize; k++, p++) | 61 for (k=0; k<xsltLocaleListSize; k++, p++) |
| 62 if (xmlStrcmp(p->tag, languageTag) == 0) return p->lcid; | 62 if (xmlStrcmp(p->tag, languageTag) == 0) return p->lcid; |
| 63 return((xsltLocale)0); | 63 return((xsltLocale)0); |
| 64 } | 64 } |
| 65 | 65 |
| 66 static void xsltEnumSupportedLocales(void); | 66 static void xsltEnumSupportedLocales(void); |
| 67 #endif | 67 #endif |
| 68 | 68 |
| 69 /** | 69 /** |
| 70 * xsltFreeLocales: |
| 71 * |
| 72 * Cleanup function for the locale support on shutdown |
| 73 */ |
| 74 void |
| 75 xsltFreeLocales(void) { |
| 76 #ifdef XSLT_LOCALE_WINAPI |
| 77 xmlRMutexLock(xsltLocaleMutex); |
| 78 xmlFree(xsltLocaleList); |
| 79 xsltLocaleList = NULL; |
| 80 xmlRMutexUnlock(xsltLocaleMutex); |
| 81 #endif |
| 82 } |
| 83 |
| 84 /** |
| 70 * xsltNewLocale: | 85 * xsltNewLocale: |
| 71 * @languageTag: RFC 3066 language tag | 86 * @languageTag: RFC 3066 language tag |
| 72 * | 87 * |
| 73 * Creates a new locale of an opaque system dependent type based on the | 88 * Creates a new locale of an opaque system dependent type based on the |
| 74 * language tag. | 89 * language tag. |
| 75 * | 90 * |
| 76 * Returns the locale or NULL on error or if no matching locale was found | 91 * Returns the locale or NULL on error or if no matching locale was found |
| 77 */ | 92 */ |
| 78 xsltLocale | 93 xsltLocale |
| 79 xsltNewLocale(const xmlChar *languageTag) { | 94 xsltNewLocale(const xmlChar *languageTag) { |
| 80 #ifdef XSLT_LOCALE_XLOCALE | 95 #ifdef XSLT_LOCALE_XLOCALE |
| 81 xsltLocale locale; | 96 xsltLocale locale; |
| 82 char localeName[XSLTMAX_LANGTAGLEN+6]; /* 6 chars for ".utf8\0" */ | 97 char localeName[XSLTMAX_LANGTAGLEN+6]; /* 6 chars for ".utf8\0" */ |
| 83 const xmlChar *p = languageTag; | 98 const xmlChar *p = languageTag; |
| 84 const char *region = NULL; | 99 const char *region = NULL; |
| 85 char *q = localeName; | 100 char *q = localeName; |
| 86 int i, llen; | 101 int i, llen; |
| 87 | 102 |
| 88 /* Convert something like "pt-br" to "pt_BR.utf8" */ | 103 /* Convert something like "pt-br" to "pt_BR.utf8" */ |
| 89 | 104 |
| 90 if (languageTag == NULL) | 105 if (languageTag == NULL) |
| 91 » return(NULL); | 106 » return(NULL); |
| 92 | 107 |
| 93 for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i) | 108 for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i) |
| 94 *q++ = TOLOWER(*p++); | 109 *q++ = TOLOWER(*p++); |
| 95 | 110 |
| 96 if (i == 0) | 111 if (i == 0) |
| 97 » return(NULL); | 112 » return(NULL); |
| 98 | 113 |
| 99 llen = i; | 114 llen = i; |
| 100 *q++ = '_'; | 115 |
| 101 | |
| 102 if (*p) { | 116 if (*p) { |
| 103 » if (*p++ != '-') | 117 » if (*p++ != '-') |
| 104 » return(NULL); | 118 » return(NULL); |
| 105 » | 119 *q++ = '_'; |
| 120 |
| 106 for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i) | 121 for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i) |
| 107 *q++ = TOUPPER(*p++); | 122 *q++ = TOUPPER(*p++); |
| 108 | 123 |
| 109 » if (i == 0 || *p) | 124 » if (i == 0 || *p) |
| 110 » return(NULL); | 125 » return(NULL); |
| 111 » | 126 |
| 112 memcpy(q, ".utf8", 6); | 127 memcpy(q, ".utf8", 6); |
| 113 locale = newlocale(LC_COLLATE_MASK, localeName, NULL); | 128 locale = newlocale(LC_COLLATE_MASK, localeName, NULL); |
| 114 if (locale != NULL) | 129 if (locale != NULL) |
| 115 return(locale); | 130 return(locale); |
| 116 | 131 |
| 117 /* Continue without using country code */ | 132 /* Continue without using country code */ |
| 118 | 133 |
| 119 q = localeName + llen + 1; | 134 q = localeName + llen; |
| 120 } | 135 } |
| 121 | 136 |
| 122 /* Try locale without territory, e.g. for Esperanto (eo) */ | 137 /* Try locale without territory, e.g. for Esperanto (eo) */ |
| 123 | 138 |
| 124 memcpy(q, ".utf8", 6); | 139 memcpy(q, ".utf8", 6); |
| 125 locale = newlocale(LC_COLLATE_MASK, localeName, NULL); | 140 locale = newlocale(LC_COLLATE_MASK, localeName, NULL); |
| 126 if (locale != NULL) | 141 if (locale != NULL) |
| 127 return(locale); | 142 return(locale); |
| 128 | 143 |
| 129 /* Try to find most common country for language */ | 144 /* Try to find most common country for language */ |
| 130 | 145 |
| 131 if (llen != 2) | 146 if (llen != 2) |
| 132 return(NULL); | 147 return(NULL); |
| 133 | 148 |
| 134 region = (char *)xsltDefaultRegion((xmlChar *)localeName); | 149 region = (char *)xsltDefaultRegion((xmlChar *)localeName); |
| 135 if (region == NULL) | 150 if (region == NULL) |
| 136 return(NULL); | 151 return(NULL); |
| 137 | 152 |
| 138 q = localeName + llen + 1; | 153 q = localeName + llen; |
| 154 *q++ = '_'; |
| 139 *q++ = region[0]; | 155 *q++ = region[0]; |
| 140 *q++ = region[1]; | 156 *q++ = region[1]; |
| 141 memcpy(q, ".utf8", 6); | 157 memcpy(q, ".utf8", 6); |
| 142 locale = newlocale(LC_COLLATE_MASK, localeName, NULL); | 158 locale = newlocale(LC_COLLATE_MASK, localeName, NULL); |
| 143 | 159 |
| 144 return(locale); | 160 return(locale); |
| 145 #endif | 161 #endif |
| 146 | 162 |
| 147 #ifdef XSLT_LOCALE_WINAPI | 163 #ifdef XSLT_LOCALE_WINAPI |
| 148 { | 164 { |
| 149 xsltLocale locale = (xsltLocale)0; | 165 xsltLocale locale = (xsltLocale)0; |
| 150 xmlChar localeName[XSLTMAX_LANGTAGLEN+1]; | 166 xmlChar localeName[XSLTMAX_LANGTAGLEN+1]; |
| 151 xmlChar *q = localeName; | 167 xmlChar *q = localeName; |
| 152 const xmlChar *p = languageTag; | 168 const xmlChar *p = languageTag; |
| 153 int i, llen; | 169 int i, llen; |
| 154 const xmlChar *region = NULL; | 170 const xmlChar *region = NULL; |
| 155 | 171 |
| 156 if (languageTag == NULL) goto end; | 172 if (languageTag == NULL) goto end; |
| 157 | 173 |
| 158 xsltEnumSupportedLocales(); | 174 xsltEnumSupportedLocales(); |
| 159 | 175 |
| 160 for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i) | 176 for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i) |
| 161 *q++ = TOLOWER(*p++); | 177 *q++ = TOLOWER(*p++); |
| 162 if (i == 0) goto end; | 178 if (i == 0) goto end; |
| 163 | 179 |
| 164 llen = i; | 180 llen = i; |
| 165 *q++ = '-'; | 181 *q++ = '-'; |
| 166 if (*p) { /*if country tag is given*/ | 182 if (*p) { /*if country tag is given*/ |
| 167 if (*p++ != '-') goto end; | 183 if (*p++ != '-') goto end; |
| 168 » | 184 |
| 169 for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i) | 185 for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i) |
| 170 *q++ = TOUPPER(*p++); | 186 *q++ = TOUPPER(*p++); |
| 171 if (i == 0 || *p) goto end; | 187 if (i == 0 || *p) goto end; |
| 172 | 188 |
| 173 *q = '\0'; | 189 *q = '\0'; |
| 174 locale = xslt_locale_WINAPI(localeName); | 190 locale = xslt_locale_WINAPI(localeName); |
| 175 if (locale != (xsltLocale)0) goto end; | 191 if (locale != (xsltLocale)0) goto end; |
| 176 } | 192 } |
| 177 /* Try to find most common country for language */ | 193 /* Try to find most common country for language */ |
| 178 region = xsltDefaultRegion(localeName); | 194 region = xsltDefaultRegion(localeName); |
| 179 if (region == NULL) goto end; | 195 if (region == NULL) goto end; |
| 180 | 196 |
| 181 strcpy(localeName + llen + 1, region); | 197 strcpy(localeName + llen + 1, region); |
| 182 locale = xslt_locale_WINAPI(localeName); | 198 locale = xslt_locale_WINAPI(localeName); |
| 183 end: | 199 end: |
| 184 return(locale); | 200 return(locale); |
| 185 } | 201 } |
| 186 #endif | 202 #endif |
| 187 | 203 |
| 188 #ifdef XSLT_LOCALE_NONE | 204 #ifdef XSLT_LOCALE_NONE |
| 189 return(NULL); | 205 return(NULL); |
| 190 #endif | 206 #endif |
| 191 } | 207 } |
| 192 | 208 |
| 193 static const xmlChar* | 209 static const xmlChar* |
| 194 xsltDefaultRegion(const xmlChar *localeName) { | 210 xsltDefaultRegion(const xmlChar *localeName) { |
| 195 xmlChar c; | 211 xmlChar c; |
| 196 /* region should be xmlChar, but gcc warns on all string assignments */ | 212 /* region should be xmlChar, but gcc warns on all string assignments */ |
| 197 const char *region = NULL; | 213 const char *region = NULL; |
| 198 | 214 |
| 199 c = localeName[1]; | 215 c = localeName[1]; |
| 200 /* This is based on the locales from glibc 2.3.3 */ | 216 /* This is based on the locales from glibc 2.3.3 */ |
| 201 | 217 |
| 202 switch (localeName[0]) { | 218 switch (localeName[0]) { |
| 203 case 'a': | 219 case 'a': |
| 204 if (c == 'a' || c == 'm') region = "ET"; | 220 if (c == 'a' || c == 'm') region = "ET"; |
| 205 else if (c == 'f') region = "ZA"; | 221 else if (c == 'f') region = "ZA"; |
| 206 else if (c == 'n') region = "ES"; | 222 else if (c == 'n') region = "ES"; |
| 207 else if (c == 'r') region = "AE"; | 223 else if (c == 'r') region = "AE"; |
| 208 else if (c == 'z') region = "AZ"; | 224 else if (c == 'z') region = "AZ"; |
| 209 break; | 225 break; |
| 210 case 'b': | 226 case 'b': |
| 211 if (c == 'e') region = "BY"; | 227 if (c == 'e') region = "BY"; |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 * Returns the transformed string or NULL on error | 368 * Returns the transformed string or NULL on error |
| 353 */ | 369 */ |
| 354 xsltLocaleChar * | 370 xsltLocaleChar * |
| 355 xsltStrxfrm(xsltLocale locale, const xmlChar *string) | 371 xsltStrxfrm(xsltLocale locale, const xmlChar *string) |
| 356 { | 372 { |
| 357 #ifdef XSLT_LOCALE_NONE | 373 #ifdef XSLT_LOCALE_NONE |
| 358 return(NULL); | 374 return(NULL); |
| 359 #else | 375 #else |
| 360 size_t xstrlen, r; | 376 size_t xstrlen, r; |
| 361 xsltLocaleChar *xstr; | 377 xsltLocaleChar *xstr; |
| 362 | 378 |
| 363 #ifdef XSLT_LOCALE_XLOCALE | 379 #ifdef XSLT_LOCALE_XLOCALE |
| 364 xstrlen = strxfrm_l(NULL, (const char *)string, 0, locale) + 1; | 380 xstrlen = strxfrm_l(NULL, (const char *)string, 0, locale) + 1; |
| 365 xstr = (xsltLocaleChar *) xmlMalloc(xstrlen); | 381 xstr = (xsltLocaleChar *) xmlMalloc(xstrlen); |
| 366 if (xstr == NULL) { | 382 if (xstr == NULL) { |
| 367 xsltTransformError(NULL, NULL, NULL, | 383 xsltTransformError(NULL, NULL, NULL, |
| 368 "xsltStrxfrm : out of memory error\n"); | 384 "xsltStrxfrm : out of memory error\n"); |
| 369 return(NULL); | 385 return(NULL); |
| 370 } | 386 } |
| 371 | 387 |
| 372 r = strxfrm_l((char *)xstr, (const char *)string, xstrlen, locale); | 388 r = strxfrm_l((char *)xstr, (const char *)string, xstrlen, locale); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 | 516 |
| 501 len = xsltLocaleListSize * sizeof(xsltRFC1766Info); | 517 len = xsltLocaleListSize * sizeof(xsltRFC1766Info); |
| 502 xsltLocaleList = xmlMalloc(len); | 518 xsltLocaleList = xmlMalloc(len); |
| 503 memset(xsltLocaleList, 0, len); | 519 memset(xsltLocaleList, 0, len); |
| 504 EnumSystemLocalesA(xsltIterateSupportedLocales, LCID_SUPPORTED); | 520 EnumSystemLocalesA(xsltIterateSupportedLocales, LCID_SUPPORTED); |
| 505 } | 521 } |
| 506 xmlRMutexUnlock(xsltLocaleMutex); | 522 xmlRMutexUnlock(xsltLocaleMutex); |
| 507 } | 523 } |
| 508 | 524 |
| 509 #endif /*def XSLT_LOCALE_WINAPI*/ | 525 #endif /*def XSLT_LOCALE_WINAPI*/ |
| OLD | NEW |