15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltlocale.c: locale handling
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Reference:
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * RFC 3066: Tags for the Identification of Languages
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://www.ietf.org/rfc/rfc3066.txt
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ISO 639-1, ISO 3166-1
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Author: Nick Wellnhofer
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * winapi port: Roumen Petrov
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IN_LIBXSLT
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "libxslt.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xmlmemory.h>
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xsltlocale.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xsltutils.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 2
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define newlocale __newlocale
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define freelocale __freelocale
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define strxfrm_l __strxfrm_l
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LC_COLLATE_MASK (1 << LC_COLLATE)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ISALPHA(c) ((c & 0xc0) == 0x40 && (unsigned)((c & 0x1f) - 1) < 26)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TOUPPER(c) (c & ~0x20)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TOLOWER(c) (c | 0x20)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*without terminating null character*/
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define XSLTMAX_ISO639LANGLEN		8
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define XSLTMAX_ISO3166CNTRYLEN		8
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					/* <lang>-<cntry> */
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define XSLTMAX_LANGTAGLEN		(XSLTMAX_ISO639LANGLEN+1+XSLTMAX_ISO3166CNTRYLEN)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const xmlChar* xsltDefaultRegion(const xmlChar *localeName);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_LOCALE_WINAPI
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlRMutexPtr xsltLocaleMutex = NULL;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct xsltRFC1766Info_s {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /*note typedef unsigned char xmlChar !*/
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar    tag[XSLTMAX_LANGTAGLEN+1];
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /*note typedef LCID xsltLocale !*/
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltLocale lcid;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct xsltRFC1766Info_s xsltRFC1766Info;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int xsltLocaleListSize = 0;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xsltRFC1766Info *xsltLocaleList = NULL;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xsltLocale
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xslt_locale_WINAPI(const xmlChar *languageTag) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int k;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRFC1766Info *p = xsltLocaleList;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (k=0; k<xsltLocaleListSize; k++, p++)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlStrcmp(p->tag, languageTag) == 0) return p->lcid;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return((xsltLocale)0);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void xsltEnumSupportedLocales(void);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltNewLocale:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @languageTag: RFC 3066 language tag
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates a new locale of an opaque system dependent type based on the
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * language tag.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the locale or NULL on error or if no matching locale was found
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltLocale
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltNewLocale(const xmlChar *languageTag) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_LOCALE_XLOCALE
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltLocale locale;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char localeName[XSLTMAX_LANGTAGLEN+6]; /* 6 chars for ".utf8\0" */
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *p = languageTag;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *region = NULL;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *q = localeName;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i, llen;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Convert something like "pt-br" to "pt_BR.utf8" */
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (languageTag == NULL)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	return(NULL);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*q++ = TOLOWER(*p++);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i == 0)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	return(NULL);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    llen = i;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *q++ = '_';
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*p) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	if (*p++ != '-')
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	    return(NULL);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *q++ = TOUPPER(*p++);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	if (i == 0 || *p)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	    return(NULL);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(q, ".utf8", 6);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (locale != NULL)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return(locale);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Continue without using country code */
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        q = localeName + llen + 1;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Try locale without territory, e.g. for Esperanto (eo) */
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(q, ".utf8", 6);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (locale != NULL)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(locale);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Try to find most common country for language */
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (llen != 2)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(NULL);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    region = (char *)xsltDefaultRegion((xmlChar *)localeName);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (region == NULL)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(NULL);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    q = localeName + llen + 1;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *q++ = region[0];
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *q++ = region[1];
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(q, ".utf8", 6);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(locale);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_LOCALE_WINAPI
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltLocale    locale = (xsltLocale)0;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar       localeName[XSLTMAX_LANGTAGLEN+1];
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar       *q = localeName;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *p = languageTag;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int           i, llen;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *region = NULL;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (languageTag == NULL) goto end;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltEnumSupportedLocales();
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*q++ = TOLOWER(*p++);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i == 0) goto end;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    llen = i;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *q++ = '-';
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*p) { /*if country tag is given*/
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (*p++ != '-') goto end;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *q++ = TOUPPER(*p++);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (i == 0 || *p) goto end;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*q = '\0';
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	locale = xslt_locale_WINAPI(localeName);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (locale != (xsltLocale)0) goto end;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Try to find most common country for language */
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    region = xsltDefaultRegion(localeName);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (region == NULL) goto end;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strcpy(localeName + llen + 1, region);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    locale = xslt_locale_WINAPI(localeName);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)end:
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(locale);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_LOCALE_NONE
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(NULL);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const xmlChar*
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltDefaultRegion(const xmlChar *localeName) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar c;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* region should be xmlChar, but gcc warns on all string assignments */
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *region = NULL;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = localeName[1];
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* This is based on the locales from glibc 2.3.3 */
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (localeName[0]) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'a':
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'a' || c == 'm') region = "ET";
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'f') region = "ZA";
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'n') region = "ES";
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'r') region = "AE";
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'z') region = "AZ";
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'b':
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'e') region = "BY";
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'g') region = "BG";
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'n') region = "BD";
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'r') region = "FR";
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 's') region = "BA";
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'c':
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'a') region = "ES";
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 's') region = "CZ";
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'y') region = "GB";
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'd':
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'a') region = "DK";
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'e') region = "DE";
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'e':
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'l') region = "GR";
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'n' || c == 'o') region = "US";
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 's' || c == 'u') region = "ES";
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 't') region = "EE";
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'f':
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'a') region = "IR";
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'i') region = "FI";
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'o') region = "FO";
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'r') region = "FR";
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'g':
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'a') region = "IE";
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'l') region = "ES";
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'v') region = "GB";
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'h':
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'e') region = "IL";
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'i') region = "IN";
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'r') region = "HT";
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'u') region = "HU";
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'i':
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'd') region = "ID";
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 's') region = "IS";
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 't') region = "IT";
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'w') region = "IL";
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'j':
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'a') region = "JP";
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'k':
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'l') region = "GL";
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'o') region = "KR";
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'w') region = "GB";
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'l':
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 't') region = "LT";
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'v') region = "LV";
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'm':
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'k') region = "MK";
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'l' || c == 'r') region = "IN";
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'n') region = "MN";
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 's') region = "MY";
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 't') region = "MT";
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'n':
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'b' || c == 'n' || c == 'o') region = "NO";
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'e') region = "NP";
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'l') region = "NL";
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'o':
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'm') region = "ET";
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'p':
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'a') region = "IN";
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'l') region = "PL";
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 't') region = "PT";
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'r':
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'o') region = "RO";
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'u') region = "RU";
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 's':
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            switch (c) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                case 'e': region = "NO"; break;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                case 'h': region = "YU"; break;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                case 'k': region = "SK"; break;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                case 'l': region = "SI"; break;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                case 'o': region = "ET"; break;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                case 'q': region = "AL"; break;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                case 't': region = "ZA"; break;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                case 'v': region = "SE"; break;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 't':
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'a' || c == 'e') region = "IN";
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'h') region = "TH";
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'i') region = "ER";
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'r') region = "TR";
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 't') region = "RU";
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'u':
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'k') region = "UA";
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'r') region = "PK";
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'v':
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'i') region = "VN";
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'w':
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'a') region = "BE";
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'x':
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'h') region = "ZA";
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case 'z':
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == 'h') region = "CN";
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (c == 'u') region = "ZA";
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return((xmlChar *)region);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltFreeLocale:
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @locale: the locale to free
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Frees a locale created with xsltNewLocale
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltFreeLocale(xsltLocale locale) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_LOCALE_XLOCALE
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    freelocale(locale);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltStrxfrm:
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @locale: locale created with xsltNewLocale
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @string: UTF-8 string to transform
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Transforms a string according to locale. The transformed string must then be
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * compared with xsltLocaleStrcmp and freed with xmlFree.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the transformed string or NULL on error
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltLocaleChar *
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltStrxfrm(xsltLocale locale, const xmlChar *string)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_LOCALE_NONE
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(NULL);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t xstrlen, r;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltLocaleChar *xstr;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_LOCALE_XLOCALE
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xstrlen = strxfrm_l(NULL, (const char *)string, 0, locale) + 1;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xstr = (xsltLocaleChar *) xmlMalloc(xstrlen);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xstr == NULL) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(NULL, NULL, NULL,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    "xsltStrxfrm : out of memory error\n");
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return(NULL);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r = strxfrm_l((char *)xstr, (const char *)string, xstrlen, locale);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_LOCALE_WINAPI
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xstrlen = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xstrlen == 0) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar check failed\n");
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(NULL);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xstr = (xsltLocaleChar*) xmlMalloc(xstrlen * sizeof(xsltLocaleChar));
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xstr == NULL) {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(NULL);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r = MultiByteToWideChar(CP_UTF8, 0, string, -1, xstr, xstrlen);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (r == 0) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar failed\n");
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlFree(xstr);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(NULL);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(xstr);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* XSLT_LOCALE_WINAPI */
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (r >= xstrlen) {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : strxfrm failed\n");
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlFree(xstr);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(NULL);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(xstr);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* XSLT_LOCALE_NONE */
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltLocaleStrcmp:
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @locale: a locale identifier
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @str1: a string transformed with xsltStrxfrm
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @str2: a string transformed with xsltStrxfrm
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Compares two strings transformed with xsltStrxfrm
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a value < 0 if str1 sorts before str2,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *         a value > 0 if str1 sorts after str2,
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *         0 if str1 and str2 are equal wrt sorting
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltLocaleStrcmp(xsltLocale locale, const xsltLocaleChar *str1, const xsltLocaleChar *str2) {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void)locale;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_LOCALE_WINAPI
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (str1 == str2) return(0);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (str1 == NULL) return(-1);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (str2 == NULL) return(1);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = CompareStringW(locale, 0, str1, -1, str2, -1);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == 0) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xsltTransformError(NULL, NULL, NULL, "xsltLocaleStrcmp : CompareStringW fail\n");
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return(0);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(ret - 2);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(xmlStrcmp(str1, str2));
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef XSLT_LOCALE_WINAPI
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltCountSupportedLocales:
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @lcid: not used
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * callback used to count locales
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns TRUE
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL CALLBACK
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltCountSupportedLocales(LPSTR lcid) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void) lcid;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++xsltLocaleListSize;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return(TRUE);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltIterateSupportedLocales:
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @lcid: not used
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * callback used to track locales
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns TRUE if not at the end of the array
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL CALLBACK
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltIterateSupportedLocales(LPSTR lcid) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static int count = 0;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar    iso639lang [XSLTMAX_ISO639LANGLEN  +1];
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar    iso3136ctry[XSLTMAX_ISO3166CNTRYLEN+1];
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int        k, l;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRFC1766Info *p = xsltLocaleList + count;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    k = sscanf(lcid, "%lx", (long*)&p->lcid);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (k < 1) goto end;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*don't count terminating null character*/
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    k = GetLocaleInfoA(p->lcid, LOCALE_SISO639LANGNAME , iso639lang , sizeof(iso639lang ));
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (--k < 1) goto end;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    l = GetLocaleInfoA(p->lcid, LOCALE_SISO3166CTRYNAME, iso3136ctry, sizeof(iso3136ctry));
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (--l < 1) goto end;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {  /*fill results*/
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlChar    *q = p->tag;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memcpy(q, iso639lang, k);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	q += k;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*q++ = '-';
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memcpy(q, iso3136ctry, l);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	q += l;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*q = '\0';
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++count;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)end:
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return((count < xsltLocaleListSize) ? TRUE : FALSE);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltEnumSupportedLocales(void) {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlRMutexLock(xsltLocaleMutex);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xsltLocaleListSize <= 0) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	size_t len;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	EnumSystemLocalesA(xsltCountSupportedLocales, LCID_SUPPORTED);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	len = xsltLocaleListSize * sizeof(xsltRFC1766Info);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltLocaleList = xmlMalloc(len);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	memset(xsltLocaleList, 0, len);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	EnumSystemLocalesA(xsltIterateSupportedLocales, LCID_SUPPORTED);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlRMutexUnlock(xsltLocaleMutex);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /*def XSLT_LOCALE_WINAPI*/
510