[RFC] Use ICU in wine ?

Rafał Mużyło galtgendo at o2.pl
Sun Oct 9 19:48:38 CDT 2011


Right now, wine claims to use DUCET data for lingustic sorting, but by
section 1.9.2 of that document (as of version 6.0.0), uses it in a wrong
way. The result of it are bugs such as #10767 and #9583.

A possible way around it would beby using ICU to get language specific
tailoring and applying some of wine-specific for the parts addressed by
#10767. In a way, wine already *indirectly* depends on icu on many
distros (a potential libxml2 dep) - they were quite a few patches
already addressing build failures caused by this in recent past.

I've cooked up a patch, that's unfortunately isn't working properly yet,
it's more of a draft on where to go, if such road were to be taken.

Main issue with this patch ain't it's not ignoring the proper list of
symbols, as this would be easy to fix, if not for one problem:
the part that I put inside 'if (0)' block.

For some reason (threading, perhaps ?), if I pass a non-zero lenght string
to ucol_openRules, wineboot hangs. Oddly, if the string lenght is 0, the
hang doesn't happen.
I can't really tell, what going wrong, as the almost same code works in
native linux testcase.

Also, while in this patch UCOL_ALTERNATE_HANDLING would have been used
for NORM_IGNORESYMBOLS, it would be much better to manipulate some of
the settings by a custom rule and VariableTop value, but to do that,
first such rule would have to be passed and that odd hang prevents it
at the moment.

It would also be nice, if it was possible to initialize the collator
only once for an app instance - after all, in Windows locale change
requires a reboot, so while (AFAIK) one wineserver instance can have
apps in different locales running, locale can't change for an already
running app.

So if you have any idea of why exactly the hang happens and how to get
around it or know any *technical* reasons of why ICU couldn't be used in
wine, CC me with comments.

-------------- next part --------------
--- libs/wine/sortkey.c	2011-10-05 16:44:29.000000000 +0200
+++ libs/wine/sortkey.c	2011-10-05 21:06:51.000000000 +0200
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 #include "wine/unicode.h"
+#include <unicode/ustring.h>
+#include <unicode/ucol.h>
 
 extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen);
 extern const unsigned int collation_table[];
@@ -334,10 +336,56 @@
                         const WCHAR *str2, int len2)
 {
     int ret;
+    UErrorCode status = U_ZERO_ERROR;// status1 = U_ZERO_ERROR;
+    UCollator *coll, *coll2;
+    UParseError parse_error;
+    //U_STRING_DECL(word_sort_rule, "&\\u0000=''='-'", 18);
+    //U_STRING_INIT(word_sort_rule, "&\\u0000=''='-'", 18);
+    const WCHAR word_sort_rule[] = { '&', '\\', 'u', '0', '0',
+        '0', '0', '=', '\'', '\'', '=', '\'', '-', '\'', 0};
 
     len1 = real_length(str1, len1);
     len2 = real_length(str2, len2);
 
+    coll = ucol_open(NULL, &status);
+    if (U_SUCCESS(status))
+    {
+        if (0 & !(flags & SORT_STRINGSORT))
+        {
+            coll2 = ucol_openRules(word_sort_rule, 14,
+                ucol_getAttribute(coll, UCOL_NORMALIZATION_MODE, &status),
+                ucol_getStrength(coll), &parse_error, &status);
+            if (U_SUCCESS(status))
+            {
+                ucol_close(coll);
+                coll = coll2;
+            }
+        }
+        if (flags & NORM_IGNORECASE)
+            ucol_setStrength(coll, UCOL_SECONDARY);
+        if (flags & NORM_IGNORENONSPACE)
+        {
+            ucol_setStrength(coll, UCOL_PRIMARY);
+            if (!(flags & NORM_IGNORECASE))
+                ucol_setAttribute(coll, UCOL_CASE_LEVEL, UCOL_ON, &status);
+        }
+        if (flags & NORM_IGNOREKANATYPE)
+        {
+            if (ucol_getAttribute(coll, UCOL_HIRAGANA_QUATERNARY_MODE, &status)
+                 == UCOL_ON)
+                 ucol_setAttribute(coll, UCOL_HIRAGANA_QUATERNARY_MODE, UCOL_OFF, &status);
+        }
+        if (flags & NORM_IGNORESYMBOLS)
+        {
+            ucol_setAttribute(coll, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, &status);
+        }
+
+        ret = ucol_strcoll(coll, str1, len1, str2, len2) + 2;
+        ucol_close(coll);
+    }
+    else
+        ret = 0;
+#if 0
     ret = compare_unicode_weights(flags, str1, len1, str2, len2);
     if (!ret)
     {
@@ -346,5 +385,6 @@
         if (!ret && !(flags & NORM_IGNORECASE))
             ret = compare_case_weights(flags, str1, len1, str2, len2);
     }
+#endif
     return ret;
 }
--- configure.ac	2011-10-04 21:46:40.000000000 +0200
+++ configure.ac	2011-10-05 21:35:57.000000000 +0200
@@ -913,6 +913,29 @@
 WINE_ERROR_WITH(pthread,[test "x$LIBPTHREAD" = "x"],[pthread ${notice_platform}development files not found.
 Wine cannot support threads without libpthread.])
 
+dnl **** Check for icu ****
+
+AC_SUBST(ICUINCL,"")
+AC_SUBST(ICULIBS,"")
+ac_save_CPPFLAGS="$CPPFLAGS"
+if test "$PKG_CONFIG" != "false"
+then
+    ac_icu_libs="`$PKG_CONFIG --libs icu-i18n 2>/dev/null`"
+    ac_icu_cflags="`$PKG_CONFIG --cflags icu-i18n 2>/dev/null`"
+    CPPFLAGS="$CPPFLAGS $ac_icu_cflags"
+fi
+AC_CHECK_HEADERS([unicode/ustring.h unicode/ucol.h])
+if test "$ac_cv_header_unicode_ustring_h" = "yes" -a "$ac_cv_header_unicode_ucol_h" = "yes";
+then
+if test x"$ac_icu_libs" != x; then
+   AC_DEFINE(HAVE_LIBICUI18N, 1, [Define if you have the libicui18n library])
+   ICULIBS="$ac_icu_libs"
+   ICUINCL="$ac_icu_cflags"
+fi
+fi
+CPPFLAGS="$ac_save_CPPFLAGS"
+
+
 dnl **** Check for X11 ****
 
 AC_PATH_XTRA
--- libs/wine/Makefile.in	2010-12-09 11:17:18.000000000 +0100
+++ libs/wine/Makefile.in	2011-10-06 21:14:53.000000000 +0200
@@ -1,7 +1,7 @@
 DLLFLAGS  = @DLLFLAGS@
 MODULE    = libwine.$(LIBEXT)
 VERSCRIPT = $(srcdir)/wine.map
-EXTRALIBS = $(LIBPORT) @LIBDL@ @CRTLIBS@ @COREFOUNDATIONLIB@
+EXTRALIBS = $(LIBPORT) @LIBDL@ @CRTLIBS@ @COREFOUNDATIONLIB@ @ICULIBS@
 DEFS      = -D__WINESRC__ -DWINE_UNICODE_API=""
 
 VERSION   = 1.0
--- dlls/kernel32/locale.c	2011-10-04 21:46:41.000000000 +0200
+++ dlls/kernel32/locale.c	2011-10-07 16:13:25.000000000 +0200
@@ -2823,6 +2823,8 @@
 
     ret = wine_compare_string(style, str1, len1, str2, len2);
 
+    if (!ret) SetLastError(ERROR_INVALID_PARAMETER);
+    return ret;
     if (ret) /* need to translate result */
         return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
     return CSTR_EQUAL;


More information about the wine-devel mailing list