ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

xsltlocale.c
Go to the documentation of this file.
00001 /*
00002  * xsltlocale.c: locale handling
00003  *
00004  * Reference:
00005  * RFC 3066: Tags for the Identification of Languages
00006  * http://www.ietf.org/rfc/rfc3066.txt
00007  * ISO 639-1, ISO 3166-1
00008  *
00009  * Author: Nick Wellnhofer
00010  * winapi port: Roumen Petrov
00011  */
00012 
00013 #define IN_LIBXSLT
00014 #include "libxslt.h"
00015 
00016 #include <string.h>
00017 #include <libxml/xmlmemory.h>
00018 
00019 #include "xsltlocale.h"
00020 #include "xsltutils.h"
00021 
00022 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 2
00023 #define newlocale __newlocale
00024 #define freelocale __freelocale
00025 #define strxfrm_l __strxfrm_l
00026 #define LC_COLLATE_MASK (1 << LC_COLLATE)
00027 #endif
00028 
00029 #define ISALPHA(c) ((c & 0xc0) == 0x40 && (unsigned)((c & 0x1f) - 1) < 26)
00030 #define TOUPPER(c) (c & ~0x20)
00031 #define TOLOWER(c) (c | 0x20)
00032 
00033 /*without terminating null character*/
00034 #define XSLTMAX_ISO639LANGLEN       8
00035 #define XSLTMAX_ISO3166CNTRYLEN     8
00036                     /* <lang>-<cntry> */
00037 #define XSLTMAX_LANGTAGLEN      (XSLTMAX_ISO639LANGLEN+1+XSLTMAX_ISO3166CNTRYLEN)
00038 
00039 static const xmlChar* xsltDefaultRegion(const xmlChar *localeName);
00040 
00041 #ifdef XSLT_LOCALE_WINAPI
00042 xmlRMutexPtr xsltLocaleMutex = NULL;
00043 
00044 struct xsltRFC1766Info_s {
00045       /*note typedef unsigned char xmlChar !*/
00046     xmlChar    tag[XSLTMAX_LANGTAGLEN+1];
00047       /*note typedef LCID xsltLocale !*/
00048     xsltLocale lcid;
00049 };
00050 typedef struct xsltRFC1766Info_s xsltRFC1766Info;
00051 
00052 static int xsltLocaleListSize = 0;
00053 static xsltRFC1766Info *xsltLocaleList = NULL;
00054 
00055 
00056 static xsltLocale
00057 xslt_locale_WINAPI(const xmlChar *languageTag) {
00058     int k;
00059     xsltRFC1766Info *p = xsltLocaleList;
00060 
00061     for (k=0; k<xsltLocaleListSize; k++, p++)
00062     if (xmlStrcmp(p->tag, languageTag) == 0) return p->lcid;
00063     return((xsltLocale)0);
00064 }
00065 
00066 static void xsltEnumSupportedLocales(void);
00067 #endif
00068 
00078 xsltLocale
00079 xsltNewLocale(const xmlChar *languageTag) {
00080 #ifdef XSLT_LOCALE_XLOCALE
00081     xsltLocale locale;
00082     char localeName[XSLTMAX_LANGTAGLEN+6]; /* 6 chars for ".utf8\0" */
00083     const xmlChar *p = languageTag;
00084     const char *region = NULL;
00085     char *q = localeName;
00086     int i, llen;
00087     
00088     /* Convert something like "pt-br" to "pt_BR.utf8" */
00089     
00090     if (languageTag == NULL)
00091         return(NULL);
00092     
00093     for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i)
00094     *q++ = TOLOWER(*p++);
00095     
00096     if (i == 0)
00097         return(NULL);
00098     
00099     llen = i;
00100     *q++ = '_';
00101     
00102     if (*p) {
00103         if (*p++ != '-')
00104             return(NULL);
00105     
00106     for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i)
00107         *q++ = TOUPPER(*p++);
00108     
00109         if (i == 0 || *p)
00110             return(NULL);
00111         
00112         memcpy(q, ".utf8", 6);
00113         locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
00114         if (locale != NULL)
00115             return(locale);
00116         
00117         /* Continue without using country code */
00118         
00119         q = localeName + llen + 1;
00120     }
00121     
00122     /* Try locale without territory, e.g. for Esperanto (eo) */
00123 
00124     memcpy(q, ".utf8", 6);
00125     locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
00126     if (locale != NULL)
00127         return(locale);
00128 
00129     /* Try to find most common country for language */
00130     
00131     if (llen != 2)
00132         return(NULL);
00133 
00134     region = (char *)xsltDefaultRegion((xmlChar *)localeName);
00135     if (region == NULL)
00136         return(NULL);
00137      
00138     q = localeName + llen + 1;
00139     *q++ = region[0];
00140     *q++ = region[1];
00141     memcpy(q, ".utf8", 6);
00142     locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
00143     
00144     return(locale);
00145 #endif
00146 
00147 #ifdef XSLT_LOCALE_WINAPI
00148 {
00149     xsltLocale    locale = (xsltLocale)0;
00150     xmlChar       localeName[XSLTMAX_LANGTAGLEN+1];
00151     xmlChar       *q = localeName;
00152     const xmlChar *p = languageTag;
00153     int           i, llen;
00154     const xmlChar *region = NULL;
00155 
00156     if (languageTag == NULL) goto end;
00157 
00158     xsltEnumSupportedLocales();
00159 
00160     for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i)
00161     *q++ = TOLOWER(*p++);
00162     if (i == 0) goto end;
00163 
00164     llen = i;
00165     *q++ = '-';
00166     if (*p) { /*if country tag is given*/
00167     if (*p++ != '-') goto end;
00168     
00169     for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i)
00170         *q++ = TOUPPER(*p++);
00171     if (i == 0 || *p) goto end;
00172 
00173     *q = '\0';
00174     locale = xslt_locale_WINAPI(localeName);
00175     if (locale != (xsltLocale)0) goto end;
00176     }
00177     /* Try to find most common country for language */
00178     region = xsltDefaultRegion(localeName);
00179     if (region == NULL) goto end;
00180 
00181     strcpy(localeName + llen + 1, region);
00182     locale = xslt_locale_WINAPI(localeName);
00183 end:
00184     return(locale);
00185 }
00186 #endif
00187 
00188 #ifdef XSLT_LOCALE_NONE
00189     return(NULL);
00190 #endif
00191 }
00192 
00193 static const xmlChar*
00194 xsltDefaultRegion(const xmlChar *localeName) {
00195     xmlChar c;
00196     /* region should be xmlChar, but gcc warns on all string assignments */
00197     const char *region = NULL;
00198     
00199     c = localeName[1];
00200     /* This is based on the locales from glibc 2.3.3 */
00201     
00202     switch (localeName[0]) {
00203         case 'a':
00204             if (c == 'a' || c == 'm') region = "ET";
00205             else if (c == 'f') region = "ZA";
00206             else if (c == 'n') region = "ES";
00207             else if (c == 'r') region = "AE";
00208             else if (c == 'z') region = "AZ";
00209             break;
00210         case 'b':
00211             if (c == 'e') region = "BY";
00212             else if (c == 'g') region = "BG";
00213             else if (c == 'n') region = "BD";
00214             else if (c == 'r') region = "FR";
00215             else if (c == 's') region = "BA";
00216             break;
00217         case 'c':
00218             if (c == 'a') region = "ES";
00219             else if (c == 's') region = "CZ";
00220             else if (c == 'y') region = "GB";
00221             break;
00222         case 'd':
00223             if (c == 'a') region = "DK";
00224             else if (c == 'e') region = "DE";
00225             break;
00226         case 'e':
00227             if (c == 'l') region = "GR";
00228             else if (c == 'n' || c == 'o') region = "US";
00229             else if (c == 's' || c == 'u') region = "ES";
00230             else if (c == 't') region = "EE";
00231             break;
00232         case 'f':
00233             if (c == 'a') region = "IR";
00234             else if (c == 'i') region = "FI";
00235             else if (c == 'o') region = "FO";
00236             else if (c == 'r') region = "FR";
00237             break;
00238         case 'g':
00239             if (c == 'a') region = "IE";
00240             else if (c == 'l') region = "ES";
00241             else if (c == 'v') region = "GB";
00242             break;
00243         case 'h':
00244             if (c == 'e') region = "IL";
00245             else if (c == 'i') region = "IN";
00246             else if (c == 'r') region = "HT";
00247             else if (c == 'u') region = "HU";
00248             break;
00249         case 'i':
00250             if (c == 'd') region = "ID";
00251             else if (c == 's') region = "IS";
00252             else if (c == 't') region = "IT";
00253             else if (c == 'w') region = "IL";
00254             break;
00255         case 'j':
00256             if (c == 'a') region = "JP";
00257             break;
00258         case 'k':
00259             if (c == 'l') region = "GL";
00260             else if (c == 'o') region = "KR";
00261             else if (c == 'w') region = "GB";
00262             break;
00263         case 'l':
00264             if (c == 't') region = "LT";
00265             else if (c == 'v') region = "LV";
00266             break;
00267         case 'm':
00268             if (c == 'k') region = "MK";
00269             else if (c == 'l' || c == 'r') region = "IN";
00270             else if (c == 'n') region = "MN";
00271             else if (c == 's') region = "MY";
00272             else if (c == 't') region = "MT";
00273             break;
00274         case 'n':
00275             if (c == 'b' || c == 'n' || c == 'o') region = "NO";
00276             else if (c == 'e') region = "NP";
00277             else if (c == 'l') region = "NL";
00278             break;
00279         case 'o':
00280             if (c == 'm') region = "ET";
00281             break;
00282         case 'p':
00283             if (c == 'a') region = "IN";
00284             else if (c == 'l') region = "PL";
00285             else if (c == 't') region = "PT";
00286             break;
00287         case 'r':
00288             if (c == 'o') region = "RO";
00289             else if (c == 'u') region = "RU";
00290             break;
00291         case 's':
00292             switch (c) {
00293                 case 'e': region = "NO"; break;
00294                 case 'h': region = "YU"; break;
00295                 case 'k': region = "SK"; break;
00296                 case 'l': region = "SI"; break;
00297                 case 'o': region = "ET"; break;
00298                 case 'q': region = "AL"; break;
00299                 case 't': region = "ZA"; break;
00300                 case 'v': region = "SE"; break;
00301             }
00302             break;
00303         case 't':
00304             if (c == 'a' || c == 'e') region = "IN";
00305             else if (c == 'h') region = "TH";
00306             else if (c == 'i') region = "ER";
00307             else if (c == 'r') region = "TR";
00308             else if (c == 't') region = "RU";
00309             break;
00310         case 'u':
00311             if (c == 'k') region = "UA";
00312             else if (c == 'r') region = "PK";
00313             break;
00314         case 'v':
00315             if (c == 'i') region = "VN";
00316             break;
00317         case 'w':
00318             if (c == 'a') region = "BE";
00319             break;
00320         case 'x':
00321             if (c == 'h') region = "ZA";
00322             break;
00323         case 'z':
00324             if (c == 'h') region = "CN";
00325             else if (c == 'u') region = "ZA";
00326             break;
00327     }
00328     return((xmlChar *)region);
00329 }
00330 
00337 void
00338 xsltFreeLocale(xsltLocale locale) {
00339 #ifdef XSLT_LOCALE_XLOCALE
00340     freelocale(locale);
00341 #endif
00342 }
00343 
00354 xsltLocaleChar *
00355 xsltStrxfrm(xsltLocale locale, const xmlChar *string)
00356 {
00357 #ifdef XSLT_LOCALE_NONE
00358     return(NULL);
00359 #else
00360     size_t xstrlen, r;
00361     xsltLocaleChar *xstr;
00362     
00363 #ifdef XSLT_LOCALE_XLOCALE
00364     xstrlen = strxfrm_l(NULL, (const char *)string, 0, locale) + 1;
00365     xstr = (xsltLocaleChar *) xmlMalloc(xstrlen);
00366     if (xstr == NULL) {
00367     xsltTransformError(NULL, NULL, NULL,
00368         "xsltStrxfrm : out of memory error\n");
00369     return(NULL);
00370     }
00371 
00372     r = strxfrm_l((char *)xstr, (const char *)string, xstrlen, locale);
00373 #endif
00374 
00375 #ifdef XSLT_LOCALE_WINAPI
00376     xstrlen = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
00377     if (xstrlen == 0) {
00378         xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar check failed\n");
00379         return(NULL);
00380     }
00381     xstr = (xsltLocaleChar*) xmlMalloc(xstrlen * sizeof(xsltLocaleChar));
00382     if (xstr == NULL) {
00383         xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
00384         return(NULL);
00385     }
00386     r = MultiByteToWideChar(CP_UTF8, 0, string, -1, xstr, xstrlen);
00387     if (r == 0) {
00388         xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar failed\n");
00389         xmlFree(xstr);
00390         return(NULL);
00391     }
00392     return(xstr);
00393 #endif /* XSLT_LOCALE_WINAPI */
00394 
00395     if (r >= xstrlen) {
00396     xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : strxfrm failed\n");
00397         xmlFree(xstr);
00398         return(NULL);
00399     }
00400 
00401     return(xstr);
00402 #endif /* XSLT_LOCALE_NONE */
00403 }
00404 
00417 int
00418 xsltLocaleStrcmp(xsltLocale locale, const xsltLocaleChar *str1, const xsltLocaleChar *str2) {
00419     (void)locale;
00420 #ifdef XSLT_LOCALE_WINAPI
00421 {
00422     int ret;
00423     if (str1 == str2) return(0);
00424     if (str1 == NULL) return(-1);
00425     if (str2 == NULL) return(1);
00426     ret = CompareStringW(locale, 0, str1, -1, str2, -1);
00427     if (ret == 0) {
00428         xsltTransformError(NULL, NULL, NULL, "xsltLocaleStrcmp : CompareStringW fail\n");
00429         return(0);
00430     }
00431     return(ret - 2);
00432 }
00433 #else
00434     return(xmlStrcmp(str1, str2));
00435 #endif
00436 }
00437 
00438 #ifdef XSLT_LOCALE_WINAPI
00439 
00447 BOOL CALLBACK
00448 xsltCountSupportedLocales(LPSTR lcid) {
00449     (void) lcid;
00450     ++xsltLocaleListSize;
00451     return(TRUE);
00452 }
00453 
00462 BOOL CALLBACK
00463 xsltIterateSupportedLocales(LPSTR lcid) {
00464     static int count = 0;
00465     xmlChar    iso639lang [XSLTMAX_ISO639LANGLEN  +1];
00466     xmlChar    iso3136ctry[XSLTMAX_ISO3166CNTRYLEN+1];
00467     int        k, l;
00468     xsltRFC1766Info *p = xsltLocaleList + count;
00469 
00470     k = sscanf(lcid, "%lx", (long*)&p->lcid);
00471     if (k < 1) goto end;
00472     /*don't count terminating null character*/
00473     k = GetLocaleInfoA(p->lcid, LOCALE_SISO639LANGNAME , iso639lang , sizeof(iso639lang ));
00474     if (--k < 1) goto end;
00475     l = GetLocaleInfoA(p->lcid, LOCALE_SISO3166CTRYNAME, iso3136ctry, sizeof(iso3136ctry));
00476     if (--l < 1) goto end;
00477 
00478     {  /*fill results*/
00479     xmlChar    *q = p->tag;
00480     memcpy(q, iso639lang, k);
00481     q += k;
00482     *q++ = '-';
00483     memcpy(q, iso3136ctry, l);
00484     q += l;
00485     *q = '\0';
00486     }
00487     ++count;
00488 end:
00489     return((count < xsltLocaleListSize) ? TRUE : FALSE);
00490 }
00491 
00492 
00493 static void
00494 xsltEnumSupportedLocales(void) {
00495     xmlRMutexLock(xsltLocaleMutex);
00496     if (xsltLocaleListSize <= 0) {
00497     size_t len;
00498 
00499     EnumSystemLocalesA(xsltCountSupportedLocales, LCID_SUPPORTED);
00500 
00501     len = xsltLocaleListSize * sizeof(xsltRFC1766Info);
00502     xsltLocaleList = xmlMalloc(len);
00503     memset(xsltLocaleList, 0, len);
00504     EnumSystemLocalesA(xsltIterateSupportedLocales, LCID_SUPPORTED);
00505     }
00506     xmlRMutexUnlock(xsltLocaleMutex);
00507 }
00508 
00509 #endif /*def XSLT_LOCALE_WINAPI*/

Generated on Fri May 25 2012 04:17:49 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.