Index: tests/unicode-collate.c
===================================================================
--- tests/unicode-collate.c	(revision 6871)
+++ tests/unicode-collate.c	(working copy)
@@ -8,7 +8,7 @@
 #include <locale.h>
 
 typedef struct {
-  const char *key;
+  GCollationKey *key;
   const char *str;
 } Line;
   
@@ -28,7 +28,7 @@ compare_key (const void *a, const void *
   const Line *line_a = a;
   const Line *line_b = b;
 
-  return strcmp (line_a->key, line_b->key);
+  return g_collation_key_cmp (line_a->key, line_b->key);
 }
 
 int main (int argc, char **argv)
@@ -100,9 +100,9 @@ int main (int argc, char **argv)
       str[term_pos] = '\0';
 
       if (do_file)
-	line.key = g_utf8_collate_key_for_filename (str, -1);
+	line.key = g_utf8_get_collation_key_for_filename (str, -1);
       else
-	line.key = g_utf8_collate_key (str, -1);
+	line.key = g_utf8_get_collation_key (str, -1);
       line.str = str;
 
       g_array_append_val (line_array, line);
Index: glib/glib.symbols
===================================================================
--- glib/glib.symbols	(revision 6871)
+++ glib/glib.symbols	(working copy)
@@ -1371,6 +1371,11 @@ g_unichar_break_type G_GNUC_CONST
 g_utf8_collate
 g_utf8_collate_key G_GNUC_MALLOC
 g_utf8_collate_key_for_filename G_GNUC_MALLOC
+g_utf8_get_collation_key
+g_utf8_get_collation_key_for_filename
+g_collation_key_cmp
+g_collation_key_copy
+g_collation_key_free
 #endif
 #endif
 
Index: glib/gunicode.h
===================================================================
--- glib/gunicode.h	(revision 6871)
+++ glib/gunicode.h	(working copy)
@@ -389,6 +389,15 @@ gchar *g_utf8_collate_key (const gchar *
 gchar *g_utf8_collate_key_for_filename (const gchar *str,
 			                gssize       len) G_GNUC_MALLOC;
 
+typedef struct _GCollationKey GCollationKey;
+GCollationKey *g_utf8_get_collation_key (const gchar *str,
+                                         gssize       len);
+GCollationKey *g_utf8_get_collation_key_for_filename (const gchar *str,
+                                                      gssize       len);
+gint g_collation_key_cmp (GCollationKey *key1, GCollationKey *key2);
+GCollationKey *g_collation_key_copy (const GCollationKey *key);
+void g_collation_key_free (GCollationKey *key);
+
 gboolean g_unichar_get_mirror_char (gunichar ch,
                                     gunichar *mirrored_ch);
 
Index: glib/gunicollate.c
===================================================================
--- glib/gunicollate.c	(revision 6871)
+++ glib/gunicollate.c	(working copy)
@@ -26,6 +26,10 @@
 #include <wchar.h>
 #endif
 
+#ifdef HAVE_CARBON
+#include <CoreServices/CoreServices.h>
+#endif
+
 #include "glib.h"
 #include "gunicodeprivate.h"
 #include "galias.h"
@@ -68,8 +72,33 @@ g_utf8_collate (const gchar *str1,
 		const gchar *str2)
 {
   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);
+
+  g_return_val_if_fail (str1_utf16 != NULL, 0);
+  g_return_val_if_fail (str2_utf16 != NULL, 0);
+
+  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 *str2_norm;
@@ -85,7 +114,7 @@ g_utf8_collate (const gchar *str1,
   g_free (str1_norm);
   g_free (str2_norm);
 
-#else /* !__STDC_ISO_10646__ */
+#else /* !HAVE_CARBON && !__STDC_ISO_10646__ */
 
   const gchar *charset;
   gchar *str1_norm;
@@ -201,7 +230,7 @@ g_utf8_collate_key (const gchar *str,
 {
   gchar *result;
   gsize xfrm_len;
-  
+
 #ifdef __STDC_ISO_10646__
 
   gunichar *str_norm;
@@ -283,6 +312,185 @@ g_utf8_collate_key (const gchar *str,
   return result;
 }
 
+#ifdef HAVE_CARBON
+
+struct _GCollationKey {
+    guint len;
+    UCCollationValue buf[1];
+};
+
+static GCollationKey *
+create_collation_key (CollatorRef  collator,
+                      const gchar *str,
+                      gssize       len)
+{
+  GCollationKey *key = NULL;
+  UniChar *str_utf16 = NULL;
+  ItemCount actual_len;
+  ItemCount try_len;
+  glong len_utf16;
+  OSStatus ret;
+  UCCollationValue buf[512];
+
+  if (!collator)
+    goto error;
+
+  str_utf16 = g_utf8_to_utf16 (str, len, NULL, &len_utf16, NULL);
+  try_len = len_utf16 * 5 + 2;
+
+  if (try_len <= sizeof buf)
+    {
+      ret = UCGetCollationKey (collator, str_utf16, len_utf16, 
+                               sizeof buf, &actual_len, buf);
+
+      if (ret == 0)
+        {
+          key = g_malloc (sizeof (GCollationKey) + (actual_len - 1) * sizeof (UCCollationValue));
+          memcpy (key->buf, buf, actual_len * sizeof (UCCollationValue));
+        }
+      else if (ret == kCollateBufferTooSmall)
+        try_len *= 2;
+      else
+        goto error;
+    }
+
+  if (!key)
+    {
+      key = g_malloc (sizeof (GCollationKey) + (try_len - 1) * sizeof (UCCollationValue));
+      ret = UCGetCollationKey (collator, str_utf16, len_utf16, 
+                               try_len, &actual_len, key->buf);
+
+      if (ret == kCollateBufferTooSmall)
+        {
+          try_len *= 2;
+          key = g_realloc (key, sizeof (GCollationKey) + (actual_len - 1) * sizeof (UCCollationValue));
+          ret = UCGetCollationKey (collator, str_utf16, len_utf16,
+                                   try_len, &actual_len, key->buf);
+        }
+
+      if (ret != 0)
+        goto error;
+    }
+
+  key->len = actual_len;
+
+  g_free (str_utf16);
+  return key;
+
+error:
+  g_free (str_utf16);
+  g_free (key);
+  key = g_new (GCollationKey, 1);
+  key->len = 0;
+  return key;
+}
+
+GCollationKey *
+g_utf8_get_collation_key (const gchar *str,
+                          gssize       len)
+{
+  static CollatorRef collator;
+
+  if (G_UNLIKELY (!collator))
+    {
+      UCCreateCollator (NULL, 0, kUCCollateStandardOptions, &collator);
+
+      if (!collator)
+        g_warning ("%s: UCCreateCollator failed", G_STRLOC);
+    }
+
+  return create_collation_key (collator, str, len);
+}
+
+GCollationKey *
+g_utf8_get_collation_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)
+        g_warning ("%s: UCCreateCollator failed", G_STRLOC);
+    }
+
+  return create_collation_key (collator, str, len);
+}
+
+gint
+g_collation_key_cmp (GCollationKey *key1,
+                     GCollationKey *key2)
+{
+  SInt32 order = 0;
+
+  g_return_val_if_fail (key1 != NULL, 0);
+  g_return_val_if_fail (key2 != NULL, 0);
+
+  UCCompareCollationKeys (key1->buf, key1->len,
+                          key2->buf, key2->len,
+                          NULL, &order);
+  return order;
+}
+
+GCollationKey *
+g_collation_key_copy (const GCollationKey *key)
+{
+  gsize sz;
+
+  if (!key)
+    return NULL;
+
+  sz = sizeof (GCollationKey) + key->len * sizeof (UCCollationValue) - sizeof (UCCollationValue);
+  return g_memdup (key, sz);
+}
+
+#else /* !HAVE_CARBON */
+
+GCollationKey *
+g_utf8_get_collation_key (const gchar *str,
+                          gssize       len)
+{
+  return (GCollationKey*) g_utf8_collate_key (str, len);
+}
+
+GCollationKey *
+g_utf8_get_collation_key_for_filename (const gchar *str,
+                                       gssize       len)
+{
+  return (GCollationKey*) g_utf8_collate_key_for_filename (str, len);
+}
+
+gint
+g_collation_key_cmp (GCollationKey *key1,
+                     GCollationKey *key2)
+{
+  return strcmp ((gchar*) key1, (gchar*) key2);
+}
+
+GCollationKey *
+g_collation_key_copy (const GCollationKey *key)
+{
+  return g_strdup ((const gchar*) key);
+}
+
+#endif
+
+void
+g_collation_key_free (GCollationKey *key)
+{
+  g_free (key);
+}
+
 /* This is a collation key that is very very likely to sort before any
    collation key that libc strxfrm generates. We use this before any
    special case (dot or number) to make sure that its sorted before
