changeset 785:548b193c084c

Use uft8_collate_key() to sort utf8 strings. Modify file_data_set_path() to sync collate keys and file_data_pool on path change. Partially fix bug 1959854.
author zas_
date Thu, 05 Jun 2008 08:41:02 +0000
parents 16b3a5c8aedc
children a20ff446347e
files src/collect.c src/dupe.c src/filedata.c src/search.c src/typedefs.h src/view_dir_tree.c
diffstat 6 files changed, 79 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/collect.c	Wed Jun 04 21:12:47 2008 +0000
+++ b/src/collect.c	Thu Jun 05 08:41:02 2008 +0000
@@ -132,6 +132,8 @@
 
 	switch(collection_list_sort_method)
 		{
+		case SORT_NAME:
+			break;
 		case SORT_NONE:
 			return 0;
 			break;
@@ -146,20 +148,21 @@
 			return 0;
 			break;
 		case SORT_PATH:
-			return CASE_SORT(cia->fd->path, cib->fd->path);
+			return CASE_SORT(cia->fd->path, cib->fd->path); /* FIXME: utf8_collate */
 			break;
 #ifdef HAVE_STRVERSCMP
 		case SORT_NUMBER:
 			return strverscmp(cia->fd->name, cib->fd->name);
 			break;
 #endif
-		case SORT_NAME:
 		default:
-			return CASE_SORT(cia->fd->name, cib->fd->name);
 			break;
 		}
 
-	return 0;
+	if (options->file_sort.case_sensitive)
+		return strcmp(cia->fd->collate_key_name, cib->fd->collate_key_name);
+	else
+		return strcmp(cia->fd->collate_key_name_nocase, cib->fd->collate_key_name_nocase);
 }
 
 GList *collection_list_sort(GList *list, SortType method)
--- a/src/dupe.c	Wed Jun 04 21:12:47 2008 +0000
+++ b/src/dupe.c	Thu Jun 05 08:41:02 2008 +0000
@@ -1132,11 +1132,11 @@
 		}
 	if (mask & DUPE_MATCH_NAME)
 		{
-		if (strcmp(a->fd->name, b->fd->name) != 0) return FALSE;
+		if (strcmp(a->fd->collate_key_name, b->fd->collate_key_name) != 0) return FALSE;
 		}
 	if (mask & DUPE_MATCH_NAME_CI)
 		{
-		if (strcasecmp(a->fd->name, b->fd->name) != 0) return FALSE;
+		if (strcmp(a->fd->collate_key_name_nocase, b->fd->collate_key_name_nocase) != 0) return FALSE;
 		}
 	if (mask & DUPE_MATCH_SIZE)
 		{
--- a/src/filedata.c	Wed Jun 04 21:12:47 2008 +0000
+++ b/src/filedata.c	Thu Jun 05 08:41:02 2008 +0000
@@ -22,6 +22,8 @@
 #include "ui_fileops.h"
 
 
+static GHashTable *file_data_pool = NULL;
+
 static gint sidecar_file_priority(const gchar *path);
 
 
@@ -144,15 +146,48 @@
 	file_data_send_notification(fd); /* FIXME there are probably situations when we don't want to call this  */
 }
 
+static void file_data_set_collate_keys(FileData *fd)
+{
+	gchar *caseless_name;
+
+	g_assert(g_utf8_validate(fd->name, -1, NULL));
+
+	caseless_name = g_utf8_casefold(fd->name, -1);
+
+	g_free(fd->collate_key_name);
+	g_free(fd->collate_key_name_nocase);
+
+#if GLIB_CHECK_VERSION(2, 8, 0)
+	fd->collate_key_name = g_utf8_collate_key_for_filename(fd->name, -1);
+	fd->collate_key_name_nocase = g_utf8_collate_key_for_filename(caseless_name, -1);
+#else
+	fd->collate_key_name = g_utf8_collate_key(fd->name, -1);
+	fd->collate_key_name_nocase = g_utf8_collate_key(caseless_name, -1);
+#endif
+	g_free(caseless_name);
+}
 
 static void file_data_set_path(FileData *fd, const gchar *path)
 {
+	g_assert(path && *path);
+	g_assert(file_data_pool);
+
+	g_free(fd->path);
+
+	if (fd->original_path)
+		{
+		g_hash_table_remove(file_data_pool, fd->original_path);
+		g_free(fd->original_path);
+		}
+	fd->original_path = g_strdup(path);
+	g_hash_table_insert(file_data_pool, fd->original_path, fd);
 
 	if (strcmp(path, G_DIR_SEPARATOR_S) == 0)
 		{
 		fd->path = g_strdup(path);
 		fd->name = fd->path;
 		fd->extension = fd->name + 1;
+		file_data_set_collate_keys(fd);
 		return;
 		}
 
@@ -167,6 +202,7 @@
 		g_free(dir);
 		fd->name = "..";
 		fd->extension = fd->name + 2;
+		file_data_set_collate_keys(fd);
 		return;
 		}
 	else if (strcmp(fd->name, ".") == 0)
@@ -175,12 +211,15 @@
 		fd->path = remove_level_from_path(path);
 		fd->name = ".";
 		fd->extension = fd->name + 1;
+		file_data_set_collate_keys(fd);
 		return;
 		}
 
 	fd->extension = extension_from_path(fd->path);
 	if (fd->extension == NULL)
 		fd->extension = fd->name + strlen(fd->name);
+
+	file_data_set_collate_keys(fd);
 }
 
 static void file_data_check_changed_files(FileData *fd, struct stat *st)
@@ -212,8 +251,6 @@
 		}
 }
 
-static GHashTable *file_data_pool = NULL;
-
 static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean check_sidecars)
 {
 	FileData *fd;
@@ -232,10 +269,13 @@
 		}
 
 	fd = g_new0(FileData, 1);
+	
+	fd->path = NULL;
+	fd->name = NULL;
+	fd->collate_key_name = NULL;
+	fd->collate_key_name_nocase = NULL;
+	fd->original_path = NULL;
 
-	file_data_set_path(fd, path_utf8);
-
-	fd->original_path = g_strdup(path_utf8);
 	fd->size = st->st_size;
 	fd->date = st->st_mtime;
 	fd->pixbuf = NULL;
@@ -243,10 +283,11 @@
 	fd->ref = 1;
 	fd->magick = 0x12345678;
 
-	g_hash_table_insert(file_data_pool, fd->original_path, fd);
+	file_data_set_path(fd, path_utf8); /* set path, name, collate_key_*, original_path */
 
 	if (check_sidecars && sidecar_file_priority(fd->extension))
 		file_data_check_sidecars(fd);
+
 	return fd;
 }
 
@@ -366,6 +407,8 @@
 
 	g_free(fd->path);
 	g_free(fd->original_path);
+	g_free(fd->collate_key_name);
+	g_free(fd->collate_key_name_nocase);
 	if (fd->pixbuf) g_object_unref(fd->pixbuf);
 
 
@@ -446,7 +489,7 @@
 	if (len1 < len2) return -1;
 	if (len1 > len2) return 1;
 
-	return strncmp(fd1->name, fd2->name, len1);
+	return strncmp(fd1->name, fd2->name, len1); /* FIXME: utf8 */
 }
 
 gboolean file_data_add_change_info(FileData *fd, FileDataChangeType type, const gchar *src, const gchar *dest)
@@ -541,26 +584,31 @@
 
 	switch (filelist_sort_method)
 		{
+		case SORT_NAME:
+			break;
 		case SORT_SIZE:
 			if (fa->size < fb->size) return -1;
 			if (fa->size > fb->size) return 1;
-			return CASE_SORT(fa->name, fb->name); /* fall back to name */
+			/* fall back to name */
 			break;
 		case SORT_TIME:
 			if (fa->date < fb->date) return -1;
 			if (fa->date > fb->date) return 1;
-			return CASE_SORT(fa->name, fb->name); /* fall back to name */
+			/* fall back to name */
 			break;
 #ifdef HAVE_STRVERSCMP
 		case SORT_NUMBER:
 			return strverscmp(fa->name, fb->name);
 			break;
 #endif
-		case SORT_NAME:
 		default:
-			return CASE_SORT(fa->name, fb->name);
 			break;
 		}
+
+	if (options->file_sort.case_sensitive)
+		return strcmp(fa->collate_key_name, fb->collate_key_name);
+	else
+		return strcmp(fa->collate_key_name_nocase, fb->collate_key_name_nocase);
 }
 
 gint filelist_sort_compare_filedata_full(FileData *fa, FileData *fb, SortType method, gint ascend)
@@ -1356,12 +1404,7 @@
 	/* FIXME delete ?*/
 	if (type == FILEDATA_CHANGE_MOVE || type == FILEDATA_CHANGE_RENAME)
 		{
-		g_free(fd->path);
-		g_hash_table_remove(file_data_pool, fd->original_path);
-		g_free(fd->original_path);
 		file_data_set_path(fd, fd->change->dest);
-		fd->original_path = g_strdup(fd->change->dest);
-		g_hash_table_insert(file_data_pool, fd->original_path, fd);
 		}
 	file_data_increment_version(fd);
 }
--- a/src/search.c	Wed Jun 04 21:12:47 2008 +0000
+++ b/src/search.c	Thu Jun 05 08:41:02 2008 +0000
@@ -2234,7 +2234,10 @@
 			return 0;
 			break;
 		case SEARCH_COLUMN_NAME:
-			return CASE_SORT(fda->fd->name, fdb->fd->name);
+			if (options->file_sort.case_sensitive)
+				return strcmp(fda->fd->collate_key_name, fdb->fd->collate_key_name);
+			else
+				return strcmp(fda->fd->collate_key_name_nocase, fdb->fd->collate_key_name_nocase);
 			break;
 		case SEARCH_COLUMN_SIZE:
 			if (fda->fd->size > fdb->fd->size) return 1;
@@ -2250,7 +2253,7 @@
 			return sort_matchdata_dimensions(fda, fdb);
 			break;
 		case SEARCH_COLUMN_PATH:
-			return CASE_SORT(fda->fd->path, fdb->fd->path);
+			return CASE_SORT(fda->fd->path, fdb->fd->path); /* FIXME: utf8_collate */
 			break;
 		default:
 			break;
--- a/src/typedefs.h	Wed Jun 04 21:12:47 2008 +0000
+++ b/src/typedefs.h	Thu Jun 05 08:41:02 2008 +0000
@@ -425,6 +425,8 @@
 	gchar *path;
 	const gchar *name;
 	const gchar *extension;
+	gchar *collate_key_name;
+	gchar *collate_key_name_nocase;
 	gint64 size;
 	time_t date;
 	gboolean marks[FILEDATA_MARKS_SIZE];
--- a/src/view_dir_tree.c	Wed Jun 04 21:12:47 2008 +0000
+++ b/src/view_dir_tree.c	Thu Jun 05 08:41:02 2008 +0000
@@ -883,7 +883,10 @@
 	gtk_tree_model_get(store, a, DIR_COLUMN_POINTER, &nda, -1);
 	gtk_tree_model_get(store, b, DIR_COLUMN_POINTER, &ndb, -1);
 
-	return CASE_SORT(nda->fd->name, ndb->fd->name);
+	if (options->file_sort.case_sensitive)
+		return strcmp(nda->fd->collate_key_name, nda->fd->collate_key_name);
+	else
+		return strcmp(nda->fd->collate_key_name_nocase, nda->fd->collate_key_name_nocase);
 }
 
 /*