/* * xsltlocale.c: locale handling * * Reference: * RFC 3066: Tags for the Identification of Languages * http://www.ietf.org/rfc/rfc3066.txt * ISO 639-1, ISO 3166-1 * * Author: Nick Wellnhofer * winapi port: Roumen Petrov */ #include "precomp.h" #include "xsltlocale.h" #define TOUPPER(c) (c & ~0x20) #define TOLOWER(c) (c | 0x20) #define ISALPHA(c) ((unsigned)(TOUPPER(c) - 'A') < 26) /*without terminating null character*/ #define XSLTMAX_ISO639LANGLEN 8 #define XSLTMAX_ISO3166CNTRYLEN 8 /* - */ #define XSLTMAX_LANGTAGLEN (XSLTMAX_ISO639LANGLEN+1+XSLTMAX_ISO3166CNTRYLEN) static const xmlChar* xsltDefaultRegion(const xmlChar *localeName); #ifdef XSLT_LOCALE_WINAPI xmlRMutexPtr xsltLocaleMutex = NULL; struct xsltRFC1766Info_s { /*note typedef unsigned char xmlChar !*/ xmlChar tag[XSLTMAX_LANGTAGLEN+1]; /*note typedef LCID xsltLocale !*/ xsltLocale lcid; }; typedef struct xsltRFC1766Info_s xsltRFC1766Info; static int xsltLocaleListSize = 0; static xsltRFC1766Info *xsltLocaleList = NULL; static xsltLocale xslt_locale_WINAPI(const xmlChar *languageTag) { int k; xsltRFC1766Info *p = xsltLocaleList; for (k=0; ktag, languageTag) == 0) return p->lcid; return((xsltLocale)0); } static void xsltEnumSupportedLocales(void); #endif /** * xsltFreeLocales: * * Cleanup function for the locale support on shutdown */ void xsltFreeLocales(void) { #ifdef XSLT_LOCALE_WINAPI xmlRMutexLock(xsltLocaleMutex); xmlFree(xsltLocaleList); xsltLocaleList = NULL; xmlRMutexUnlock(xsltLocaleMutex); #endif } /** * xsltNewLocale: * @languageTag: RFC 3066 language tag * * Creates a new locale of an opaque system dependent type based on the * language tag. * * Returns the locale or NULL on error or if no matching locale was found */ xsltLocale xsltNewLocale(const xmlChar *languageTag) { #ifdef XSLT_LOCALE_POSIX xsltLocale locale; char localeName[XSLTMAX_LANGTAGLEN+6]; /* 6 chars for ".utf8\0" */ const xmlChar *p = languageTag; const char *region = NULL; char *q = localeName; int i, llen; /* Convert something like "pt-br" to "pt_BR.utf8" */ if (languageTag == NULL) return(NULL); for (i=0; i= xstrlen) { xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : strxfrm failed\n"); xmlFree(xstr); return(NULL); } return(xstr); #endif /* XSLT_LOCALE_NONE */ } /** * xsltLocaleStrcmp: * @locale: a locale identifier * @str1: a string transformed with xsltStrxfrm * @str2: a string transformed with xsltStrxfrm * * Compares two strings transformed with xsltStrxfrm * * Returns a value < 0 if str1 sorts before str2, * a value > 0 if str1 sorts after str2, * 0 if str1 and str2 are equal wrt sorting */ int xsltLocaleStrcmp(xsltLocale locale, const xsltLocaleChar *str1, const xsltLocaleChar *str2) { (void)locale; #ifdef XSLT_LOCALE_WINAPI { int ret; if (str1 == str2) return(0); if (str1 == NULL) return(-1); if (str2 == NULL) return(1); ret = CompareStringW(locale, 0, str1, -1, str2, -1); if (ret == 0) { xsltTransformError(NULL, NULL, NULL, "xsltLocaleStrcmp : CompareStringW fail\n"); return(0); } return(ret - 2); } #else return(xmlStrcmp(str1, str2)); #endif } #ifdef XSLT_LOCALE_WINAPI /** * xsltCountSupportedLocales: * @lcid: not used * * callback used to count locales * * Returns TRUE */ BOOL CALLBACK xsltCountSupportedLocales(LPSTR lcid) { (void) lcid; ++xsltLocaleListSize; return(TRUE); } /** * xsltIterateSupportedLocales: * @lcid: not used * * callback used to track locales * * Returns TRUE if not at the end of the array */ BOOL CALLBACK xsltIterateSupportedLocales(LPSTR lcid) { static int count = 0; xmlChar iso639lang [XSLTMAX_ISO639LANGLEN +1]; xmlChar iso3136ctry[XSLTMAX_ISO3166CNTRYLEN+1]; int k, l; xsltRFC1766Info *p = xsltLocaleList + count; k = sscanf(lcid, "%lx", (long*)&p->lcid); if (k < 1) goto end; /*don't count terminating null character*/ k = GetLocaleInfoA(p->lcid, LOCALE_SISO639LANGNAME, (char *) iso639lang, sizeof(iso639lang)); if (--k < 1) goto end; l = GetLocaleInfoA(p->lcid, LOCALE_SISO3166CTRYNAME, (char *) iso3136ctry, sizeof(iso3136ctry)); if (--l < 1) goto end; { /*fill results*/ xmlChar *q = p->tag; memcpy(q, iso639lang, k); q += k; *q++ = '-'; memcpy(q, iso3136ctry, l); q += l; *q = '\0'; } ++count; end: return((count < xsltLocaleListSize) ? TRUE : FALSE); } static void xsltEnumSupportedLocales(void) { xmlRMutexLock(xsltLocaleMutex); if (xsltLocaleListSize <= 0) { size_t len; EnumSystemLocalesA(xsltCountSupportedLocales, LCID_SUPPORTED); len = xsltLocaleListSize * sizeof(xsltRFC1766Info); xsltLocaleList = xmlMalloc(len); memset(xsltLocaleList, 0, len); EnumSystemLocalesA(xsltIterateSupportedLocales, LCID_SUPPORTED); } xmlRMutexUnlock(xsltLocaleMutex); } #endif /*def XSLT_LOCALE_WINAPI*/