big patch from Roumen Petrov finishing xsl:sort lang support with many
authorDaniel Veillard <veillard@src.gnome.org>
Fri, 1 Aug 2008 08:27:18 +0000 (08:27 +0000)
committerDaniel Veillard <veillard@src.gnome.org>
Fri, 1 Aug 2008 08:27:18 +0000 (08:27 +0000)
* libxslt/xsltconfig.h.in libxslt/xslt.c libxslt/extensions.c
  libxslt/xsltlocale.c libxslt/preproc.c libxslt/xsltutils.c
  libxslt/xsltlocale.h libxslt/win32config.h configure.in
  config.h.in win32/configure.js: big patch from Roumen Petrov
  finishing xsl:sort lang support with many portability issues
  fixed and feedback from Nick Wellnhofer and Rob Richards
Daniel

svn path=/trunk/; revision=1488

12 files changed:
ChangeLog
config.h.in
configure.in
libxslt/extensions.c
libxslt/preproc.c
libxslt/win32config.h
libxslt/xslt.c
libxslt/xsltconfig.h.in
libxslt/xsltlocale.c
libxslt/xsltlocale.h
libxslt/xsltutils.c
win32/configure.js

index d3236ea..cbdaa49 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Fri Aug  1 10:16:48 CEST 2008 Daniel Veillard <veillard@redhat.com>
+
+       * libxslt/xsltconfig.h.in libxslt/xslt.c libxslt/extensions.c
+         libxslt/xsltlocale.c libxslt/preproc.c libxslt/xsltutils.c
+         libxslt/xsltlocale.h libxslt/win32config.h configure.in
+         config.h.in win32/configure.js: big patch from Roumen Petrov
+         finishing xsl:sort lang support with many portability issues
+         fixed and feedback from Nick Wellnhofer and Rob Richards
+
 Fri Aug  1 07:54:02 CEST 2008 Daniel Veillard <veillard@redhat.com>
 
        * libexslt/crypto.c: fix for CVE-2008-2935 libexslt RC4
@@ -39,7 +48,8 @@ Tue Jun 24 23:55:48 PST 2008 William Brack <wbrack@mmm.com.hk>
 Fri Jun 13 10:58:52 CEST 2008 Daniel Veillard <daniel@veillard.com>
 
        * libxslt/libxslt.h libexslt/libexslt.h libexslt/exslt.h: patch
-         from Roumen Petrov fixing include path when compiling with MinGW
+         from Roumen Petrov fixing include path when compiling outside
+         source tree
 
 Thu Jun 12 11:23:23 CEST 2008 Daniel Veillard <daniel@veillard.com>
 
index 83448e3..7b8783d 100644 (file)
@@ -42,6 +42,9 @@
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
 /* Define to 1 if you have the `localtime' function. */
 #undef HAVE_LOCALTIME
 
index 28fb1ff..6439edc 100644 (file)
@@ -107,31 +107,48 @@ AC_STDC_HEADERS
 AM_PROG_LIBTOOL
 
 
+AC_CHECK_HEADERS(sys/types.h sys/time.h stdlib.h unistd.h string.h)
+
 dnl
 dnl Detect supported locale
 dnl
 
 XSLT_LOCALE_XLOCALE=0
-XSLT_LOCALE_MSVCRT=0
+XSLT_LOCALE_WINAPI=0
 
-AC_CHECK_HEADERS([xlocale.h])
+AC_CHECK_HEADERS([locale.h xlocale.h])
 if test $ac_cv_header_xlocale_h = yes; then
-AC_MSG_CHECKING([for working xlocale])
-AC_RUN_IFELSE(AC_LANG_PROGRAM([[
+dnl
+dnl Check for generic locale_t declaration
+dnl
+AC_MSG_CHECKING([if xlocale program link])
+AC_LINK_IFELSE(AC_LANG_PROGRAM([[
+#ifdef HAVE_LOCALE_H
 #include <locale.h>
+#endif
+#ifdef HAVE_XLOCALE_H
 #include <xlocale.h>
+#endif
+#ifdef HAVE_STRING_H
 #include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
 #include <stdlib.h>
+#endif
 
+#ifdef __GLIBC__
+typedef __locale_t xsltLocale;
+#else
+typedef locale_t xsltLocale;
+#endif
 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 2
-#define locale_t __locale_t
 #define newlocale __newlocale
 #define freelocale __freelocale
 #define strxfrm_l __strxfrm_l
 #define LC_COLLATE_MASK (1 << LC_COLLATE)
 #endif
 ]],[[
-    locale_t locale;
+    xsltLocale locale;
     const char *src[[2]] = { "\xc3\x84rger", "Zeppelin" };
     char *dst[[2]];
     size_t len, r;
@@ -152,24 +169,23 @@ AC_RUN_IFELSE(AC_LANG_PROGRAM([[
     return(0);
 ]]),
   [AC_MSG_RESULT(yes); XSLT_LOCALE_XLOCALE=1],
-  [AC_MSG_RESULT(no)],
-  [AC_MSG_WARN([cross compiling: assuming no])]
+  [AC_MSG_RESULT(no)]
 )
 else
-  dnl defined in msvcrt
-  AC_CHECK_FUNC(_create_locale,
-    [XSLT_LOCALE_MSVCRT=1]
-  )
+  case "$host" in
+    *-*-mingw*)
+      AC_MSG_NOTICE([using winapi locale])
+      XSLT_LOCALE_WINAPI=1;;
+  esac
 fi
 
 AC_SUBST(XSLT_LOCALE_XLOCALE)
-AC_SUBST(XSLT_LOCALE_MSVCRT)
+AC_SUBST(XSLT_LOCALE_WINAPI)
 
 dnl
 dnl Math detection
 dnl
 
-AC_CHECK_HEADERS(sys/types.h sys/time.h stdlib.h unistd.h string.h)
 AC_CHECK_HEADERS(ieeefp.h nan.h math.h fp_class.h float.h ansidecl.h)
 AC_CHECK_HEADERS(sys/timeb.h time.h sys/stat.h sys/select.h stdarg.h)
 AC_CHECK_FUNCS(stat _stat)
index 2c1b239..87eefb4 100644 (file)
 
 #ifdef _WIN32
 #include <stdlib.h>             /* for _MAX_PATH */
+#ifndef PATH_MAX
 #define PATH_MAX _MAX_PATH
 #endif
+#endif
 
 #ifdef WITH_XSLT_DEBUG
 #define WITH_XSLT_DEBUG_EXTENSIONS
index 4290838..9a5e9d6 100644 (file)
@@ -391,7 +391,7 @@ xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
             break;
         case XSLT_FUNC_SORT: {
                xsltStyleItemSortPtr item = (xsltStyleItemSortPtr) comp;
-               if (item->locale != NULL)
+               if (item->locale != (xsltLocale)0)
                    xsltFreeLocale(item->locale);
                if (item->comp != NULL)
                    xmlXPathFreeCompExpr(item->comp);
@@ -489,7 +489,7 @@ xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
            break;
     }
 #else    
-    if (comp->locale != NULL)
+    if (comp->locale != (xsltLocale)0)
        xsltFreeLocale(comp->locale);
     if (comp->comp != NULL)
        xmlXPathFreeCompExpr(comp->comp);
@@ -736,7 +736,7 @@ xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) {
        comp->locale = xsltNewLocale(comp->lang);
     }
     else {
-        comp->locale = NULL;
+        comp->locale = (xsltLocale)0;
     }
 
     comp->select = xsltGetCNsProp(style, inst,(const xmlChar *)"select", XSLT_NAMESPACE);
index 169b03d..00ba2a0 100644 (file)
@@ -95,5 +95,7 @@ static int isnan (double d) {
 #define ATTRIBUTE_UNUSED
 #endif
 
+#define _WINSOCKAPI_
+
 #endif /* __LIBXSLT_WIN32_CONFIG__ */
 
index 071658b..f35ad23 100644 (file)
@@ -83,6 +83,9 @@ const xmlChar *xsltXSLTAttrMarker = (const xmlChar *) "LRE XSLT Attr";
 
 #endif
 
+#ifdef XSLT_LOCALE_WINAPI
+extern xmlRMutexPtr xsltLocaleMutex;
+#endif
 /*
  * Harmless but avoiding a problem when compiling against a
  * libxml <= 2.3.11 without LIBXML_DEBUG_ENABLED
@@ -222,6 +225,9 @@ void
 xsltInit (void) {
     if (initialized == 0) {
        initialized = 1;
+#ifdef XSLT_LOCALE_WINAPI
+       xsltLocaleMutex = xmlNewRMutex();
+#endif
         xsltRegisterAllExtras();
     }
 }
index e9a3c56..b4cac6d 100644 (file)
@@ -130,9 +130,9 @@ extern "C" {
 #ifndef XSLT_LOCALE_XLOCALE
 #define XSLT_LOCALE_XLOCALE
 #endif
-#elif @XSLT_LOCALE_MSVCRT@
-#ifndef XSLT_LOCALE_MSVCRT
-#define XSLT_LOCALE_MSVCRT
+#elif @XSLT_LOCALE_WINAPI@
+#ifndef XSLT_LOCALE_WINAPI
+#define XSLT_LOCALE_WINAPI
 #endif
 #endif
 
index 0b76ec0..9c57805 100644 (file)
@@ -7,6 +7,7 @@
  * ISO 639-1, ISO 3166-1
  *
  * Author: Nick Wellnhofer
+ * winapi port: Roumen Petrov
  */
 
 #define IN_LIBXSLT
 #define TOUPPER(c) (c & ~0x20)
 #define TOLOWER(c) (c | 0x20)
 
+/*without terminating null character*/
+#define XSLTMAX_ISO639LANGLEN          8
+#define XSLTMAX_ISO3166CNTRYLEN                8
+                                       /* <lang>-<cntry> */
+#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; k<xsltLocaleListSize; k++, p++)
+       if (xmlStrcmp(p->tag, languageTag) == 0) return p->lcid;
+    return((xsltLocale)0);
+}
+
+static void xsltEnumSupportedLocales(void);
+#endif
+
 /**
  * xsltNewLocale:
  * @languageTag: RFC 3066 language tag
@@ -43,7 +80,7 @@ xsltLocale
 xsltNewLocale(const xmlChar *languageTag) {
 #ifdef XSLT_LOCALE_XLOCALE
     xsltLocale locale;
-    char localeName[23]; /* 8*lang + "-" + 8*region + ".utf8\0" */
+    char localeName[XSLTMAX_LANGTAGLEN+6]; /* 8*lang + "-" + 8*region + ".utf8\0" */
     const xmlChar *p = languageTag;
     const char *region = NULL;
     char *q = localeName;
@@ -54,7 +91,7 @@ xsltNewLocale(const xmlChar *languageTag) {
     if (languageTag == NULL)
        return(NULL);
     
-    for (i=0; i<8 && ISALPHA(*p); ++i)
+    for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i)
        *q++ = TOLOWER(*p++);
     
     if (i == 0)
@@ -67,7 +104,7 @@ xsltNewLocale(const xmlChar *languageTag) {
        if (*p++ != '-')
            return(NULL);
        
-       for (i=0; i<8 && ISALPHA(*p); ++i)
+       for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i)
            *q++ = TOUPPER(*p++);
     
        if (i == 0 || *p)
@@ -86,8 +123,70 @@ xsltNewLocale(const xmlChar *languageTag) {
     if (llen != 2)
         return(NULL);
 
-    c = localeName[1];
+    region = xsltDefaultRegion(localeName);
+    if (region == NULL)
+        return(NULL);
+     
+    *q++ = region[0];
+    *q++ = region[1];
+    memcpy(q, ".utf8", 6);
+    locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
+    
+    return(locale);
+#endif
+
+#ifdef XSLT_LOCALE_WINAPI
+{
+    xsltLocale    locale = (xsltLocale)0;
+    xmlChar       localeName[XSLTMAX_LANGTAGLEN+1];
+    xmlChar       *q = localeName;
+    const xmlChar *p = languageTag;
+    int           i, llen;
+    const xmlChar *region = NULL;
+
+    if (languageTag == NULL) goto end;
+
+    xsltEnumSupportedLocales();
+
+    for (i=0; i<XSLTMAX_ISO639LANGLEN && ISALPHA(*p); ++i)
+       *q++ = TOLOWER(*p++);
+    if (i == 0) goto end;
+
+    llen = i;
+    *q++ = '-';
+    if (*p) { /*if country tag is given*/
+       if (*p++ != '-') goto end;
+       
+       for (i=0; i<XSLTMAX_ISO3166CNTRYLEN && ISALPHA(*p); ++i)
+           *q++ = TOUPPER(*p++);
+       if (i == 0 || *p) goto end;
+
+       *q = '\0';
+       locale = xslt_locale_WINAPI(localeName);
+       if (locale != (xsltLocale)0) goto end;
+    }
+    /* Try to find most common country for language */
+    region = xsltDefaultRegion(localeName);
+    if (region == NULL) goto end;
+
+    strcpy(localeName + llen + 1, region);
+    locale = xslt_locale_WINAPI(localeName);
+end:
+    return(locale);
+}
+#endif
+
+#ifdef XSLT_LOCALE_NONE
+    return(NULL);
+#endif
+}
+
+static const xmlChar*
+xsltDefaultRegion(const xmlChar *localeName) {
+    xmlChar c;
+    const xmlChar *region = NULL;
     
+    c = localeName[1];
     /* This is based on the locales from glibc 2.3.3 */
     
     switch (localeName[0]) {
@@ -216,95 +315,7 @@ xsltNewLocale(const xmlChar *languageTag) {
             else if (c == 'u') region = "ZA";
             break;
     }
-    
-    if (region == NULL)
-        return(NULL);
-    
-    *q++ = region[0];
-    *q++ = region[1];
-    memcpy(q, ".utf8", 6);
-    locale = newlocale(LC_COLLATE_MASK, localeName, NULL);
-    
-    return(locale);
-#endif
-
-#ifdef XSLT_LOCALE_MSVCRT
-    const char *localeName = NULL;
-    int c;
-    
-    /* We only look at the language and ignore the region. I think Windows
-       doesn't care about the region for LC_COLLATE anyway. */
-    
-    if (languageTag == NULL ||
-        !languageTag[0] ||
-        !languageTag[1] ||
-        languageTag[2] && languageTag[2] != '-')
-       return(NULL);
-    
-    c = TOLOWER(languageTag[1]);
-    
-    switch (TOLOWER(languageTag[0])) {
-        case 'c':
-            if (c == 's') localeName = "csy"; /* Czech */
-            break;
-        case 'd':
-            if (c == 'a') localeName = "dan"; /* Danish */
-            else if (c == 'e') localeName = "deu"; /* German */
-            break;
-        case 'e':
-            if (c == 'l') localeName = "ell"; /* Greek */
-            else if (c == 'n') localeName = "english";
-            else if (c == 's') localeName = "esp"; /* Spanish */
-            break;
-        case 'f':
-            if (c == 'i') localeName = "fin"; /* Finnish */
-            else if (c == 'r') localeName = "fra"; /* French */
-            break;
-        case 'h':
-            if (c == 'u') localeName = "hun"; /* Hungarian */
-            break;
-        case 'i':
-            if (c == 's') localeName = "isl"; /* Icelandic */
-            else if (c == 't') localeName = "ita"; /* Italian */
-            break;
-        case 'j':
-            if (c == 'a') localeName = "jpn"; /* Japanese */
-            break;
-        case 'k':
-            if (c == 'o') localeName = "kor"; /* Korean */
-            break;
-        case 'n':
-            if (c == 'l') localeName = "nld"; /* Dutch */
-            else if (c == 'o') localeName = "norwegian";
-            break;
-        case 'p':
-            if (c == 'l') localeName = "plk"; /* Polish */
-            else if (c == 't') localeName = "ptg"; /* Portuguese */
-            break;
-        case 'r':
-            if (c == 'u') localeName = "rus"; /* Russian */
-            break;
-        case 's':
-            if (c == 'k') localeName = "sky"; /* Slovak */
-            else if (c == 'v') localeName = "sve"; /* Swedish */
-            break;
-        case 't':
-            if (c == 'r') localeName = "trk"; /* Turkish */
-            break;
-        case 'z':
-            if (c == 'h') localeName = "chinese";
-            break;
-    }
-    
-    if (localeName == NULL)
-        return(NULL);
-
-    return(_create_locale(LC_COLLATE, localeName));
-#endif
-
-#ifdef XSLT_LOCALE_NONE
-    return(NULL);
-#endif
+    return(region);
 }
 
 /**
@@ -317,10 +328,6 @@ xsltFreeLocale(xsltLocale locale) {
 #ifdef XSLT_LOCALE_XLOCALE
     freelocale(locale);
 #endif
-
-#ifdef XSLT_LOCALE_MSVCRT
-    _free_locale(locale);
-#endif
 }
 
 /**
@@ -354,71 +361,26 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string)
     r = strxfrm_l((char *)xstr, (const char *)string, xstrlen, locale);
 #endif
 
-#ifdef XSLT_LOCALE_MSVCRT
-    wchar_t *wcs;
-    wchar_t dummy;
-    int wcslen;
-    int i, j;
-    
-    /* convert UTF8 to Windows wide chars (UTF16) */
-    
-    wcslen = xmlUTF8Strlen(string);
-    if (wcslen < 0) {
-       xsltTransformError(NULL, NULL, NULL,
-           "xsltStrxfrm : invalid UTF-8 string\n");
+#ifdef XSLT_LOCALE_WINAPI
+    xstrlen = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
+    if (xstrlen == 0) {
+        xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar check failed\n");
         return(NULL);
     }
-    wcs = (wchar_t *) xmlMalloc(sizeof(wchar_t) * (wcslen + 1));
-    if (wcs == NULL) {
-       xsltTransformError(NULL, NULL, NULL,
-           "xsltStrxfrm : out of memory error\n");
-       return(NULL);
-    }
-
-    for (i=0, j=0; i<wcslen; ++i) {
-        int len = 4; /* not really, but string is already checked */
-        int c = xmlGetUTF8Char(string, &len);
-#if 0        
-        if (c < 0) {
-           xsltTransformError(NULL, NULL, NULL,
-               "xsltStrxfrm : invalid UTF-8 string\n");
-            xmlFree(wcs);
-            return(NULL);
-        }
-#endif
-
-        if (c == (wchar_t)c) {
-            wcs[j] = (wchar_t)c;
-            ++j;
-        }
-        
-        string += len;
-    }
-    
-    wcs[j] = 0;
-    
-    /* _wcsxfrm_l needs a dummy strDest because it always writes at least one
-       terminating zero wchar */
-    xstrlen = _wcsxfrm_l(&dummy, wcs, 0, locale);
-    if (xstrlen == INT_MAX) {
-       xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : strxfrm failed\n");
-        xmlFree(wcs);
+    xstr = (xsltLocaleChar*) xmlMalloc(xstrlen * sizeof(xsltLocaleChar));
+    if (xstr == NULL) {
+        xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : out of memory\n");
         return(NULL);
     }
-    ++xstrlen;
-    xstr = (wchar_t *) xmlMalloc(sizeof(wchar_t) * xstrlen);
-    if (xstr == NULL) {
-       xsltTransformError(NULL, NULL, NULL,
-           "xsltStrxfrm : out of memory error\n");
-        xmlFree(wcs);
-       return(NULL);
+    r = MultiByteToWideChar(CP_UTF8, 0, string, -1, xstr, xstrlen);
+    if (r == 0) {
+        xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : MultiByteToWideChar failed\n");
+        xmlFree(xstr);
+        return(NULL);
     }
+    return(xstr);
+#endif /* XSLT_LOCALE_WINAPI */
 
-    r = _wcsxfrm_l(xstr, wcs, xstrlen, locale);
-    
-    xmlFree(wcs);
-#endif /* XSLT_LOCALE_MSVCRT */
-    
     if (r >= xstrlen) {
        xsltTransformError(NULL, NULL, NULL, "xsltStrxfrm : strxfrm failed\n");
         xmlFree(xstr);
@@ -431,6 +393,7 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string)
 
 /**
  * xsltLocaleStrcmp:
+ * @locale: a locale identifier
  * @str1: a string transformed with xsltStrxfrm
  * @str2: a string transformed with xsltStrxfrm
  *
@@ -441,13 +404,79 @@ xsltStrxfrm(xsltLocale locale, const xmlChar *string)
  *         0 if str1 and str2 are equal wrt sorting
  */
 int
-xsltLocaleStrcmp(const xsltLocaleChar *str1, const xsltLocaleChar *str2) {
-#ifdef XSLT_LOCALE_MSVCRT
+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);
-    return(wcscmp(str1, str2));
+    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
+BOOL CALLBACK
+xsltCountSupportedLocales(LPSTR lcid) {
+    (void) lcid;
+    ++xsltLocaleListSize;
+    return(TRUE);
+}
+
+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 , iso639lang , sizeof(iso639lang ));
+    if (--k < 1) goto end;
+    l = GetLocaleInfoA(p->lcid, LOCALE_SISO3166CTRYNAME, 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*/
index c700df4..2f20d63 100644 (file)
 #include <locale.h>
 #include <xlocale.h>
 
-#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ <= 2
+#ifdef __GLIBC__
+/*locale_t is defined only if _GNU_SOURCE is defined*/
 typedef __locale_t xsltLocale;
 #else
 typedef locale_t xsltLocale;
 #endif
 typedef xmlChar xsltLocaleChar;
 
-#elif defined(XSLT_LOCALE_MSVCRT)
+#elif defined(XSLT_LOCALE_WINAPI)
 
-#include <locale.h>
+#include <windows.h>
+#include <winnls.h>
 
-typedef _locale_t xsltLocale;
+typedef LCID xsltLocale;
 typedef wchar_t xsltLocaleChar;
 
 #else
@@ -46,6 +48,6 @@ typedef xmlChar xsltLocaleChar;
 xsltLocale xsltNewLocale(const xmlChar *langName);
 void xsltFreeLocale(xsltLocale locale);
 xsltLocaleChar *xsltStrxfrm(xsltLocale locale, const xmlChar *string);
-int xsltLocaleStrcmp(const xsltLocaleChar *str1, const xsltLocaleChar *str2);
+int xsltLocaleStrcmp(xsltLocale locale, const xsltLocaleChar *str1, const xsltLocaleChar *str2);
 
 #endif /* __XML_XSLTLOCALE_H__ */
index 4650215..9565e15 100644 (file)
@@ -1039,7 +1039,7 @@ xsltComputeSortResult(xsltTransformContextPtr ctxt, xmlNodePtr sort) {
                }
            } else {
                if (res->type == XPATH_STRING) {
-                   if (comp->locale != NULL) {
+                   if (comp->locale != (xsltLocale)0) {
                        xmlChar *str = res->stringval;
                        res->stringval = (xmlChar *) xsltStrxfrm(comp->locale, str);
                        xmlFree(str);
@@ -1197,8 +1197,9 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
                                results[j + incr]->floatval)
                            tst = 1;
                        else tst = -1;
-                   } else if(comp->locale != NULL) {
+                   } else if(comp->locale != (xsltLocale)0) {
                        tst = xsltLocaleStrcmp(
+                           comp->locale,
                            (xsltLocaleChar *) results[j]->stringval,
                            (xsltLocaleChar *) results[j + incr]->stringval); 
                    } else {
@@ -1255,8 +1256,9 @@ xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
                                        res[j + incr]->floatval)
                                    tst = 1;
                                else tst = -1;
-                           } else if(comp->locale != NULL) {
+                           } else if(comp->locale != (xsltLocale)0) {
                                tst = xsltLocaleStrcmp(
+                                   comp->locale,
                                    (xsltLocaleChar *) res[j]->stringval,
                                    (xsltLocaleChar *) res[j + incr]->stringval); 
                            } else {
index 4feb4b2..7f2f854 100644 (file)
@@ -107,7 +107,7 @@ function usage()
        txt += "  zlib:       Use zlib library (" + (withZlib? "yes" : "no") + ")\n";
        txt += "  crypto:     Enable Crypto support (" + (withCrypto? "yes" : "no") + ")\n";
        txt += "  modules:    Enable Module support (" + (withModules? "yes" : "no") + ")\n";
-       txt += "  locale:     Enable Locale support, requires msvcr80.dll (" + (withLocale? "yes" : "no") + ")\n";
+       txt += "  locale:     Enable Locale support, requires unicode OS support (" + (withLocale? "yes" : "no") + ")\n";
        txt += "\nWin32 build options, default value given in parentheses:\n\n";
        txt += "  compiler:   Compiler to be used [msvc|mingw] (" + compiler + ")\n";
        txt += "  cruntime:   C-runtime compiler option (only msvc) (" + cruntime + ")\n";
@@ -244,8 +244,8 @@ function configureXslt()
                        of.WriteLine(s.replace(/\@WITH_MODULES\@/, withModules? "1" : "0"));
                } else if (s.search(/\@XSLT_LOCALE_XLOCALE\@/) != -1) {
                        of.WriteLine(s.replace(/\@XSLT_LOCALE_XLOCALE\@/, "0"));
-               } else if (s.search(/\@XSLT_LOCALE_MSVCRT\@/) != -1) {
-                       of.WriteLine(s.replace(/\@XSLT_LOCALE_MSVCRT\@/, withLocale? "1" : "0"));
+               } else if (s.search(/\@XSLT_LOCALE_WINAPI\@/) != -1) {
+                       of.WriteLine(s.replace(/\@XSLT_LOCALE_WINAPI\@/, withLocale? "1" : "0"));
                } else if (s.search(/\@LIBXSLT_DEFAULT_PLUGINS_PATH\@/) != -1) {
                        of.WriteLine(s.replace(/\@LIBXSLT_DEFAULT_PLUGINS_PATH\@/, "NULL"));
                } else