Fixed sorting order on mac

master
Yevgen Muntyan 2008-05-05 10:22:38 -05:00
parent 594b905a8a
commit dc3c71ac57
4 changed files with 216 additions and 12 deletions

View File

@ -38,6 +38,7 @@ typedef GTime MooFileTime;
#endif
typedef gint64 MooFileSize;
typedef struct MooCollationKey MooCollationKey;
struct _MooFile
{
@ -45,7 +46,7 @@ struct _MooFile
char *link_target;
char *display_name; /* normalized */
char *case_display_name;
char *collation_key;
MooCollationKey *collation_key;
MooFileInfo info;
MooFileFlags flags;
guint8 icon;
@ -74,7 +75,11 @@ GdkPixbuf *_moo_file_get_icon (const MooFile *file,
GtkWidget *widget,
GtkIconSize size);
const char *_moo_file_collation_key (const MooFile *file);
gsize _moo_collation_key_size (MooCollationKey *key);
int _moo_collation_key_cmp (const MooCollationKey *key1,
const MooCollationKey *key2);
const MooCollationKey *_moo_file_collation_key (const MooFile *file);
const char *_moo_file_case_display_name(const MooFile *file);
#ifndef __WIN32__

View File

@ -37,6 +37,9 @@
#endif
#include <errno.h>
#include <time.h>
#if defined(HAVE_CARBON)
#include <CoreServices/CoreServices.h>
#endif
#include <gtk/gtkicontheme.h>
#include <gtk/gtkiconfactory.h>
#include <gtk/gtkstock.h>
@ -91,6 +94,166 @@ _moo_file_find_mime_type (MooFile *file,
}
#if defined(HAVE_CARBON)
struct MooCollationKey {
guint len;
UCCollationValue buf[1];
};
static MooCollationKey *
create_collation_key (CollatorRef collator,
const gchar *str,
gssize len)
{
MooCollationKey *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 (MooCollationKey) + (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 (MooCollationKey) + (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 (MooCollationKey) + (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 (MooCollationKey, 1);
key->len = 0;
return key;
}
G_GNUC_UNUSED static MooCollationKey *
moo_get_collation_key (const char *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);
}
static MooCollationKey *
moo_get_collation_key_for_filename (const char *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);
}
int
_moo_collation_key_cmp (const MooCollationKey *key1,
const MooCollationKey *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;
}
gsize
_moo_collation_key_size (MooCollationKey *key)
{
return key ?
sizeof (MooCollationKey) +
key->len * sizeof (UCCollationValue) -
sizeof (UCCollationValue) :
0;
}
#else
#define moo_get_collation_key_for_filename(fn,len) ((MooCollationKey*)g_utf8_collate_key_for_filename(fn,len))
int
_moo_collation_key_cmp (const MooCollationKey *key1,
const MooCollationKey *key2)
{
return strcmp ((const char*) key1, (const char*) key2);
}
gsize
_moo_collation_key_size (MooCollationKey *key)
{
return key ? strlen ((char*) key) + 1 : 0;
}
#endif
/********************************************************************/
/* MooFile
*/
@ -125,7 +288,7 @@ _moo_file_new (const char *dirname,
file->display_name = g_utf8_normalize (display_name, -1, G_NORMALIZE_ALL);
file->case_display_name = g_utf8_casefold (file->display_name, -1);
file->collation_key = g_utf8_collate_key_for_filename (file->display_name, -1);
file->collation_key = moo_get_collation_key_for_filename (file->display_name, -1);
g_free (path);
g_free (display_name);
@ -333,7 +496,7 @@ _moo_file_display_name (const MooFile *file)
return file->display_name;
}
const char *
const MooCollationKey *
_moo_file_collation_key (const MooFile *file)
{
g_return_val_if_fail (file != NULL, NULL);

View File

@ -240,7 +240,7 @@ add_file_size (G_GNUC_UNUSED const char *filename,
*mem += STRING_SIZE (file->link_target);
*mem += STRING_SIZE (file->display_name);
*mem += STRING_SIZE (file->case_display_name);
*mem += STRING_SIZE (file->collation_key);
*mem += _moo_collation_key_size (file->collation_key);
#undef STRING_SIZE
}

View File

@ -336,7 +336,42 @@ static GList *_list_find (FileList *flist,
}
static int moo_file_case_cmp (MooFile *f1,
static int
moo_file_case_cmp (MooFile *f1,
MooFile *f2)
{
if (!strcmp (_moo_file_name (f1), ".."))
return strcmp (_moo_file_name (f2), "..") ? -1 : 0;
else if (!strcmp (_moo_file_name (f2), ".."))
return 1;
else if (MOO_FILE_IS_DIR (f1) && !MOO_FILE_IS_DIR (f2))
return -1;
else if (!MOO_FILE_IS_DIR (f1) && MOO_FILE_IS_DIR (f2))
return 1;
else
return _moo_collation_key_cmp (_moo_file_collation_key (f1),
_moo_file_collation_key (f2));
}
static int
moo_file_cmp (MooFile *f1,
MooFile *f2)
{
if (!strcmp (_moo_file_name (f1), ".."))
return strcmp (_moo_file_name (f2), "..") ? -1 : 0;
else if (!strcmp (_moo_file_name (f2), ".."))
return 1;
else if (MOO_FILE_IS_DIR (f1) && !MOO_FILE_IS_DIR (f2))
return -1;
else if (!MOO_FILE_IS_DIR (f1) && MOO_FILE_IS_DIR (f2))
return 1;
else
return strcmp (_moo_file_display_name (f1),
_moo_file_display_name (f2));
}
static int
moo_file_case_cmp_fi (MooFile *f1,
MooFile *f2)
{
if (!strcmp (_moo_file_name (f1), ".."))
@ -344,11 +379,12 @@ static int moo_file_case_cmp (MooFile *f1,
else if (!strcmp (_moo_file_name (f2), ".."))
return 1;
else
return strcmp (_moo_file_collation_key (f1),
return _moo_collation_key_cmp (_moo_file_collation_key (f1),
_moo_file_collation_key (f2));
}
static int moo_file_cmp (MooFile *f1,
static int
moo_file_cmp_fi (MooFile *f1,
MooFile *f2)
{
if (!strcmp (_moo_file_name (f1), ".."))