From 6377a1944e13a6cd4a27d07f7dccd74f1d6458dc Mon Sep 17 00:00:00 2001 From: Eric Koegel Date: Mon, 9 Feb 2015 11:18:50 +0300 Subject: [PATCH] Use collate keys to handle filename sorting (Bug #9731) This uses g_utf8_casefold and g_utf8_collate_key_for_filename on the files to perform case insensitive sorting the same way Thunar and Xfdesktop do. --- src/file.c | 32 +++++++++++++++++++++ src/file.h | 3 ++ src/image_list.c | 86 ++------------------------------------------------------ 3 files changed, 38 insertions(+), 83 deletions(-) diff --git a/src/file.c b/src/file.c index faf8740..8491054 100644 --- a/src/file.c +++ b/src/file.c @@ -122,6 +122,7 @@ struct _RsttoFilePriv gchar *uri; gchar *path; + gchar *collate_key; gchar *thumbnail_path; GdkPixbuf *thumbnails[THUMBNAIL_SIZE_COUNT]; @@ -208,6 +209,11 @@ rstto_file_dispose (GObject *object) g_free (r_file->priv->uri); r_file->priv->uri = NULL; } + if (r_file->priv->collate_key) + { + g_free (r_file->priv->collate_key); + r_file->priv->collate_key = NULL; + } for (i = 0; i < THUMBNAIL_SIZE_COUNT; ++i) { @@ -358,6 +364,32 @@ rstto_file_get_uri ( RsttoFile *r_file ) } const gchar * +rstto_file_get_collate_key ( RsttoFile *r_file ) +{ + if ( NULL == r_file->priv->collate_key ) + { + gchar *basename = g_file_get_basename (rstto_file_get_file (r_file)); + if ( NULL != basename ) + { + /* If we can use casefold for case insenstivie sorting, then + * do so */ + gchar *casefold = g_utf8_casefold (basename, -1); + if ( NULL != casefold ) + { + r_file->priv->collate_key = g_utf8_collate_key_for_filename (casefold, -1); + g_free (casefold); + } + else + { + r_file->priv->collate_key = g_utf8_collate_key_for_filename (basename, -1); + } + g_free (basename); + } + } + return (const gchar *)r_file->priv->collate_key; +} + +const gchar * rstto_file_get_content_type ( RsttoFile *r_file ) { GFileInfo *file_info = NULL; diff --git a/src/file.h b/src/file.h index ba2f80c..844ab98 100644 --- a/src/file.h +++ b/src/file.h @@ -82,6 +82,9 @@ const gchar * rstto_file_get_uri ( RsttoFile * ); const gchar * +rstto_file_get_collate_key ( RsttoFile * ); + +const gchar * rstto_file_get_content_type ( RsttoFile * ); const gchar * diff --git a/src/image_list.c b/src/image_list.c index f4c32fd..8965bc0 100644 --- a/src/image_list.c +++ b/src/image_list.c @@ -1355,90 +1355,10 @@ rstto_image_list_set_sort_by_date (RsttoImageList *image_list) static gint cb_rstto_image_list_image_name_compare_func (RsttoFile *a, RsttoFile *b) { - const gchar *a_base = rstto_file_get_display_name (a); - const gchar *b_base = rstto_file_get_display_name (b); - guint ac; - guint bc; - const gchar *ap = a_base; - const gchar *bp = b_base; - - gint result = 0; - guint64 a_num = 0; - guint64 b_num = 0; - - /* try simple (fast) ASCII comparison first */ - for (;; ++ap, ++bp) - { - /* check if the characters differ or we have a non-ASCII char - */ - ac = *((const guchar *) ap); - bc = *((const guchar *) bp); - if (ac != bc || ac == 0 || ac > 127) - break; - } - - /* fallback to Unicode comparison */ - if (G_UNLIKELY (ac > 127 || bc > 127)) - { - for (;; ap = g_utf8_next_char (ap), bp = g_utf8_next_char (bp)) - { - /* check if characters differ or end of string */ - ac = g_utf8_get_char (ap); - bc = g_utf8_get_char (bp); - if (ac != bc || ac == 0) - break; - } - } - - /* If both strings are equal, we're done */ - if (ac == bc) - { - return 0; - } - else - { - if (G_UNLIKELY (g_ascii_isdigit (ac) || g_ascii_isdigit (bc))) - { - /* if both strings differ in a digit, we use a smarter comparison - * to get sorting 'file1', 'file5', 'file10' done the right way. - */ - if (g_ascii_isdigit (ac) && g_ascii_isdigit (bc)) - { - a_num = strtoull (ap, NULL, 10); - b_num = strtoull (bp, NULL, 10); - - if (a_num < b_num) - result = -1; - if (a_num > b_num) - result = 1; - } - - if (ap > a_base && - bp > b_base && - g_ascii_isdigit (*(ap -1)) && - g_ascii_isdigit (*(bp -1)) ) - { - a_num = strtoull (ap-1, NULL, 10); - b_num = strtoull (bp-1, NULL, 10); - - if (a_num < b_num) - result = -1; - if (a_num > b_num) - result = 1; - } - } - } - - if (result == 0) - { - if (ac > bc) - result = 1; - if (ac < bc) - result = -1; - } - + const gchar *a_collate_key = rstto_file_get_collate_key (a); + const gchar *b_collate_key = rstto_file_get_collate_key (b); - return result; + return g_strcmp0(a_collate_key, b_collate_key); } /** -- 2.3.0