Bug 531403 - g_utf8_collate broken on Mac.

2008-06-02  Yevgen Muntyan  <muntyan@tamu.edu>

	Bug 531403 - g_utf8_collate broken on Mac.

	* glib/gunicollate.c:  (g_utf8_collate): use UCCompareTextDefault;
        (collate_key_to_string), (carbon_collate_key_with_collator),
        (carbon_collate_key), (carbon_collate_key_for_filename): new
        functions using Carbon API to get collate key for g_utf8_collate_key()
        and g_utf8_collate_key_for_filename();
        (g_utf8_collate_key), (g_utf8_collate_key_for_filename): use those.


svn path=/trunk/; revision=6969
This commit is contained in:
Yevgen Muntyan 2008-06-02 19:35:15 +00:00 committed by Yevgen Muntyan
parent 9d3834b708
commit c5df5e88d9
2 changed files with 196 additions and 7 deletions

View File

@ -1,3 +1,14 @@
2008-06-02 Yevgen Muntyan <muntyan@tamu.edu>
Bug 531403 g_utf8_collate broken on Mac.
* glib/gunicollate.c: (g_utf8_collate): use UCCompareTextDefault;
(collate_key_to_string), (carbon_collate_key_with_collator),
(carbon_collate_key), (carbon_collate_key_for_filename): new
functions using Carbon API to get collate key for g_utf8_collate_key()
and g_utf8_collate_key_for_filename();
(g_utf8_collate_key), (g_utf8_collate_key_for_filename): use those.
2008-05-30 Michael Natterer <mitch@imendio.com> 2008-05-30 Michael Natterer <mitch@imendio.com>
Bug 535628 - test/patterntest.c still includes gpattern.h Bug 535628 - test/patterntest.c still includes gpattern.h

View File

@ -26,6 +26,10 @@
#include <wchar.h> #include <wchar.h>
#endif #endif
#ifdef HAVE_CARBON
#include <CoreServices/CoreServices.h>
#endif
#include "glib.h" #include "glib.h"
#include "gunicodeprivate.h" #include "gunicodeprivate.h"
#include "galias.h" #include "galias.h"
@ -69,7 +73,29 @@ g_utf8_collate (const gchar *str1,
{ {
gint result; gint result;
#ifdef __STDC_ISO_10646__ #ifdef HAVE_CARBON
UniChar *str1_utf16;
UniChar *str2_utf16;
glong len1;
glong len2;
SInt32 retval = 0;
g_return_val_if_fail (str1 != NULL, 0);
g_return_val_if_fail (str2 != NULL, 0);
str1_utf16 = g_utf8_to_utf16 (str1, -1, NULL, &len1, NULL);
str2_utf16 = g_utf8_to_utf16 (str2, -1, NULL, &len2, NULL);
UCCompareTextDefault (kUCCollateStandardOptions,
str1_utf16, len1, str2_utf16, len2,
NULL, &retval);
result = retval;
g_free (str2_utf16);
g_free (str1_utf16);
#elif defined(__STDC_ISO_10646__)
gunichar *str1_norm; gunichar *str1_norm;
gunichar *str2_norm; gunichar *str2_norm;
@ -127,7 +153,7 @@ g_utf8_collate (const gchar *str1,
return result; return result;
} }
#ifdef __STDC_ISO_10646__ #if defined(__STDC_ISO_10646__) || defined(HAVE_CARBON)
/* We need UTF-8 encoding of numbers to encode the weights if /* We need UTF-8 encoding of numbers to encode the weights if
* we are using wcsxfrm. However, we aren't encoding Unicode * we are using wcsxfrm. However, we aren't encoding Unicode
* characters, so we can't simply use g_unichar_to_utf8. * characters, so we can't simply use g_unichar_to_utf8.
@ -174,7 +200,149 @@ utf8_encode (char *buf, wchar_t val)
return retval; return retval;
} }
#endif /* __STDC_ISO_10646__ */ #endif /* __STDC_ISO_10646__ || HAVE_CARBON */
#ifdef HAVE_CARBON
static gchar *
collate_key_to_string (UCCollationValue *key,
gsize key_len)
{
gchar *result;
gsize result_len;
gsize i;
/* Pretty smart algorithm here: ignore first eight bytes of the
* collation key. It doesn't produce results equivalent to
* UCCompareCollationKeys's, but the difference seems to be only
* that UCCompareCollationKeys in some cases produces 0 where our
* comparison gets -1 or 1. */
if (key_len * sizeof (UCCollationValue) <= 8)
return g_strdup ("");
result_len = 0;
for (i = 8; i < key_len * sizeof (UCCollationValue); i++)
/* there may be nul bytes, encode byteval+1 */
result_len += utf8_encode (NULL, *((guchar*)key + i) + 1);
result = g_malloc (result_len + 1);
result_len = 0;
for (i = 8; i < key_len * sizeof (UCCollationValue); i++)
result_len += utf8_encode (result + result_len, *((guchar*)key + i) + 1);
result[result_len] = 0;
return result;
}
static gchar *
carbon_collate_key_with_collator (const gchar *str,
gssize len,
CollatorRef collator)
{
UniChar *str_utf16 = NULL;
glong len_utf16;
OSStatus ret;
UCCollationValue staticbuf[512];
UCCollationValue *freeme = NULL;
UCCollationValue *buf;
ItemCount buf_len;
ItemCount key_len;
ItemCount try_len;
gchar *result = NULL;
str_utf16 = g_utf8_to_utf16 (str, len, NULL, &len_utf16, NULL);
try_len = len_utf16 * 5 + 2;
if (try_len <= sizeof staticbuf)
{
buf = staticbuf;
buf_len = sizeof staticbuf;
}
else
{
freeme = g_new (UCCollationValue, try_len);
buf = freeme;
buf_len = try_len;
}
ret = UCGetCollationKey (collator, str_utf16, len_utf16,
buf_len, &key_len, buf);
if (ret == kCollateBufferTooSmall)
{
freeme = g_renew (UCCollationValue, freeme, try_len * 2);
buf = freeme;
buf_len = try_len * 2;
ret = UCGetCollationKey (collator, str_utf16, len_utf16,
buf_len, &key_len, buf);
}
if (ret == 0)
result = collate_key_to_string (buf, key_len);
else
result = g_strdup ("");
g_free (freeme);
g_free (str_utf16);
return result;
}
static gchar *
carbon_collate_key (const gchar *str,
gssize len)
{
static CollatorRef collator;
if (G_UNLIKELY (!collator))
{
UCCreateCollator (NULL, 0, kUCCollateStandardOptions, &collator);
if (!collator)
{
static gboolean been_here;
if (!been_here)
g_warning ("%s: UCCreateCollator failed", G_STRLOC);
been_here = TRUE;
return g_strdup ("");
}
}
return carbon_collate_key_with_collator (str, len, collator);
}
static gchar *
carbon_collate_key_for_filename (const gchar *str,
gssize len)
{
static CollatorRef collator;
if (G_UNLIKELY (!collator))
{
/* http://developer.apple.com/qa/qa2004/qa1159.html */
UCCreateCollator (NULL, 0,
kUCCollateComposeInsensitiveMask
| kUCCollateWidthInsensitiveMask
| kUCCollateCaseInsensitiveMask
| kUCCollateDigitsOverrideMask
| kUCCollateDigitsAsNumberMask
| kUCCollatePunctuationSignificantMask,
&collator);
if (!collator)
{
static gboolean been_here;
if (!been_here)
g_warning ("%s: UCCreateCollator failed", G_STRLOC);
been_here = TRUE;
return g_strdup ("");
}
}
return carbon_collate_key_with_collator (str, len, collator);
}
#endif /* HAVE_CARBON */
/** /**
* g_utf8_collate_key: * g_utf8_collate_key:
@ -200,10 +368,15 @@ g_utf8_collate_key (const gchar *str,
gssize len) gssize len)
{ {
gchar *result; gchar *result;
#ifdef HAVE_CARBON
g_return_val_if_fail (str != NULL, NULL);
result = carbon_collate_key (str, len);
#elif defined(__STDC_ISO_10646__)
gsize xfrm_len; gsize xfrm_len;
#ifdef __STDC_ISO_10646__
gunichar *str_norm; gunichar *str_norm;
wchar_t *result_wc; wchar_t *result_wc;
gsize i; gsize i;
@ -233,6 +406,7 @@ g_utf8_collate_key (const gchar *str,
return result; return result;
#else /* !__STDC_ISO_10646__ */ #else /* !__STDC_ISO_10646__ */
gsize xfrm_len;
const gchar *charset; const gchar *charset;
gchar *str_norm; gchar *str_norm;
@ -317,6 +491,7 @@ gchar*
g_utf8_collate_key_for_filename (const gchar *str, g_utf8_collate_key_for_filename (const gchar *str,
gssize len) gssize len)
{ {
#ifndef HAVE_CARBON
GString *result; GString *result;
GString *append; GString *append;
const gchar *p; const gchar *p;
@ -488,6 +663,9 @@ g_utf8_collate_key_for_filename (const gchar *str,
g_string_free (append, TRUE); g_string_free (append, TRUE);
return g_string_free (result, FALSE); return g_string_free (result, FALSE);
#else /* HAVE_CARBON */
return carbon_collate_key_for_filename (str, len);
#endif
} }