changeset 138:71e1ebee420e

replaced gchar* path with FileData *fd
author nadvornik
date Tue, 11 Sep 2007 20:06:29 +0000
parents be3328a58875
children 754c1e4349b6
files src/bar_exif.c src/bar_exif.h src/bar_info.c src/bar_info.h src/bar_sort.c src/cache-loader.c src/cache-loader.h src/cache_maint.c src/cache_maint.h src/collect-io.c src/collect-io.h src/collect-table.c src/collect-table.h src/collect.c src/collect.h src/dupe.c src/dupe.h src/editors.c src/editors.h src/exif.c src/exif.h src/filelist.c src/filelist.h src/format_canon.c src/format_fuji.c src/format_nikon.c src/format_olympus.c src/format_raw.c src/format_raw.h src/fullscreen.c src/image-load.c src/image-load.h src/image.c src/image.h src/img-view.c src/img-view.h src/info.c src/info.h src/layout.c src/layout.h src/layout_image.c src/layout_image.h src/layout_util.c src/main.c src/pan-calendar.c src/pan-item.c src/pan-timeline.c src/pan-types.h src/pan-util.c src/pan-view.c src/print.c src/print.h src/search.c src/search.h src/slideshow.c src/slideshow.h src/thumb.c src/thumb_standard.c src/typedefs.h src/ui_bookmark.c src/ui_bookmark.h src/ui_fileops.c src/ui_fileops.h src/ui_pathsel.c src/ui_tabcomp.c src/ui_utildlg.c src/ui_utildlg.h src/utilops.c src/utilops.h src/view_dir_list.c src/view_dir_tree.c src/view_file_icon.c src/view_file_icon.h src/view_file_list.c src/view_file_list.h
diffstat 75 files changed, 2817 insertions(+), 2012 deletions(-) [+]
line wrap: on
line diff
--- a/src/bar_exif.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/bar_exif.c	Tue Sep 11 20:06:29 2007 +0000
@@ -16,6 +16,7 @@
 #include "exif.h"
 #include "ui_bookmark.h"
 #include "ui_misc.h"
+#include "filelist.h"
 
 #include <math.h>
 
@@ -119,7 +120,7 @@
 	GtkWidget *custom_name[EXIF_BAR_CUSTOM_COUNT];
 	GtkWidget *custom_value[EXIF_BAR_CUSTOM_COUNT];
 
-	gchar *path;
+	FileData *fd;
 
 	gint allow_search;
 };
@@ -171,7 +172,7 @@
 	ExifData *exif;
 	gint len, i;
 
-	exif = exif_read(eb->path, FALSE);
+	exif = exif_read(eb->fd, FALSE);
 
 	if (!exif)
 		{
@@ -310,7 +311,7 @@
 		}
 }
 
-void bar_exif_set(GtkWidget *bar, const gchar *path)
+void bar_exif_set(GtkWidget *bar, FileData *fd)
 {
 	ExifBar *eb;
 
@@ -318,8 +319,8 @@
 	if (!eb) return;
 
 	/* store this, advanced view toggle needs to reload data */
-	g_free(eb->path);
-	eb->path = g_strdup(path);
+	file_data_unref(eb->fd);
+	eb->fd = file_data_ref(fd);
 
 	bar_exif_clear(eb);
 	bar_exif_update(eb);
@@ -520,11 +521,11 @@
 	ExifBar *eb = data;
 
 	g_free(eb->labels);
-	g_free(eb->path);
+	file_data_unref(eb->fd);
 	g_free(eb);
 }
 
-GtkWidget *bar_exif_new(gint show_title, const gchar *path, gint advanced, GtkWidget *bounding_widget)
+GtkWidget *bar_exif_new(gint show_title, FileData *fd, gint advanced, GtkWidget *bounding_widget)
 {
 	ExifBar *eb;
 	GtkWidget *table;
@@ -652,7 +653,7 @@
 		gtk_widget_show(eb->scrolled);
 		}
 
-	eb->path = g_strdup(path);
+	eb->fd = file_data_ref(fd);
 	bar_exif_update(eb);
 
 	return eb->vbox;
--- a/src/bar_exif.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/bar_exif.h	Tue Sep 11 20:06:29 2007 +0000
@@ -14,10 +14,10 @@
 #define BAR_EXIF_H
 
 
-GtkWidget *bar_exif_new(gint show_title, const gchar *path, gint advanced, GtkWidget *bounding_widget);
+GtkWidget *bar_exif_new(gint show_title, FileData *fd, gint advanced, GtkWidget *bounding_widget);
 void bar_exif_close(GtkWidget *bar);
 
-void bar_exif_set(GtkWidget *bar, const gchar *path);
+void bar_exif_set(GtkWidget *bar, FileData *fd);
 
 gint bar_exif_is_advanced(GtkWidget *bar);
 
--- a/src/bar_info.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/bar_info.c	Tue Sep 11 20:06:29 2007 +0000
@@ -47,7 +47,7 @@
  *-------------------------------------------------------------------
  */
 
-gint comment_write(const gchar *path, GList *keywords, const gchar *comment)
+gint comment_write(gchar *path, GList *keywords, const gchar *comment)
 {
 	FILE *f;
 
@@ -76,7 +76,7 @@
 	return TRUE;
 }
 
-gint comment_cache_write(const gchar *path, GList *keywords, const gchar *comment)
+gint comment_cache_write(FileData *fd, GList *keywords, const gchar *comment)
 {
 	gchar *comment_path;
 	gint success = FALSE;
@@ -84,7 +84,7 @@
 	/* If an existing metadata file exists, we will try writing to
 	 * it's location regardless of the user's preference.
 	 */
-	comment_path = cache_find_location(CACHE_TYPE_METADATA, path);
+	comment_path = cache_find_location(CACHE_TYPE_METADATA, fd->path);
 	if (comment_path && !access_file(comment_path, W_OK))
 		{
 		g_free(comment_path);
@@ -96,10 +96,10 @@
 		gchar *comment_dir;
 		mode_t mode = 0755;
 
-		comment_dir = cache_get_location(CACHE_TYPE_METADATA, path, FALSE, &mode);
+		comment_dir = cache_get_location(CACHE_TYPE_METADATA, fd->path, FALSE, &mode);
 		if (cache_ensure_dir_exists(comment_dir, mode))
 			{
-			comment_path = g_strconcat(comment_dir, "/", filename_from_path(path),
+			comment_path = g_strconcat(comment_dir, "/", fd->name,
 						   GQVIEW_CACHE_EXT_METADATA, NULL);
 			}
 		g_free(comment_dir);
@@ -122,7 +122,7 @@
 	return success;
 }
 
-gint comment_read(const gchar *path, GList **keywords, gchar **comment)
+gint comment_read(gchar *path, GList **keywords, gchar **comment)
 {
 	FILE *f;
 	gchar s_buf[1024];
@@ -184,13 +184,14 @@
 	return TRUE;
 }
 
-gint comment_cache_read(const gchar *path, GList **keywords, gchar **comment)
+gint comment_cache_read(FileData *fd, GList **keywords, gchar **comment)
 {
 	gchar *comment_path;
 	gchar *comment_pathl;
 	gint success = FALSE;
+	if (!fd) return FALSE;
 
-	comment_path = cache_find_location(CACHE_TYPE_METADATA, path);
+	comment_path = cache_find_location(CACHE_TYPE_METADATA, fd->path);
 	if (!comment_path) return FALSE;
 
 	comment_pathl = path_from_utf8(comment_path);
@@ -283,13 +284,13 @@
 		}
 }
 
-static void metadata_set_keywords(const gchar *path, GList *list, gint add)
+static void metadata_set_keywords(FileData *fd, GList *list, gint add)
 {
 	gchar *comment = NULL;
 	GList *keywords = NULL;
 	GList *save_list = NULL;
 
-	comment_cache_read(path, &keywords, &comment);
+	comment_cache_read(fd, &keywords, &comment);
 
 	if (add)
 		{
@@ -322,9 +323,9 @@
 		save_list = list;
 		}
 
-	comment_cache_write(path, save_list, comment);
+	comment_cache_write(fd, save_list, comment);
 
-	path_list_free(keywords);
+	string_list_free(keywords);
 	g_free(comment);
 }
 
@@ -601,7 +602,7 @@
 	GtkWidget *button_set_add;
 	GtkWidget *button_set_replace;
 
-	gchar *path;
+	FileData *fd;
 
 	gint changed;
 	gint save_timeout_id;
@@ -619,14 +620,14 @@
 	GList *list;
 	gchar *comment;
 
-	if (!bd->path) return;
+	if (!bd->fd) return;
 
 	list = keyword_list_pull(bd->keyword_view);
 	comment = comment_pull(bd->comment_view);
 
-	comment_cache_write(bd->path, list, comment);
+	comment_cache_write(bd->fd, list, comment);
 
-	path_list_free(list);
+	string_list_free(list);
 	g_free(comment);
 
 	bd->changed = FALSE;
@@ -725,7 +726,7 @@
 
 		keywords = keyword_list_pull(bd->keyword_view);
 		bar_keyword_list_sync(bd, keywords);
-		path_list_free(keywords);
+		string_list_free(keywords);
 		}
 }
 
@@ -736,14 +737,14 @@
 
 	if (bd->label_file_name)
 		{
-		gtk_label_set_text(GTK_LABEL(bd->label_file_name), (bd->path) ? filename_from_path(bd->path) : "");
+		gtk_label_set_text(GTK_LABEL(bd->label_file_name), (bd->fd) ? bd->fd->name : "");
 		}
 	if (bd->label_file_time)
 		{
-		gtk_label_set_text(GTK_LABEL(bd->label_file_time), (bd->path) ? text_from_time(filetime(bd->path)) : "");
+		gtk_label_set_text(GTK_LABEL(bd->label_file_time), (bd->fd) ? text_from_time(bd->fd->date) : "");
 		}
 
-	if (comment_cache_read(bd->path, &keywords, &comment))
+	if (comment_cache_read(bd->fd, &keywords, &comment))
 		{
 		keyword_list_push(bd->keyword_view, keywords);
 		gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->comment_view)),
@@ -751,7 +752,7 @@
 
 		bar_keyword_list_sync(bd, keywords);
 
-		path_list_free(keywords);
+		string_list_free(keywords);
 		g_free(comment);
 		}
 	else
@@ -766,10 +767,10 @@
 	bd->changed = FALSE;
 	gtk_widget_set_sensitive(bd->button_save, FALSE);
 
-	gtk_widget_set_sensitive(bd->group_box, (bd->path != NULL));
+	gtk_widget_set_sensitive(bd->group_box, (bd->fd != NULL));
 }
 
-void bar_info_set(GtkWidget *bar, const gchar *path)
+void bar_info_set(GtkWidget *bar, FileData *fd)
 {
 	BarInfoData *bd;
 
@@ -778,25 +779,25 @@
 
 	if (bd->changed) bar_info_write(bd);
 
-	g_free(bd->path);
-	bd->path = g_strdup(path);
+	file_data_unref(bd->fd);
+	bd->fd = file_data_ref(fd);
 
 	bar_info_update(bd);
 }
 
-void bar_info_maint_renamed(GtkWidget *bar, const gchar *path)
+void bar_info_maint_renamed(GtkWidget *bar, FileData *fd)
 {
 	BarInfoData *bd;
 
 	bd = g_object_get_data(G_OBJECT(bar), "bar_info_data");
 	if (!bd) return;
 
-	g_free(bd->path);
-	bd->path = g_strdup(path);
+	file_data_unref(bd->fd);
+	bd->fd = file_data_ref(fd);
 
 	if (bd->label_file_name)
 		{
-		gtk_label_set_text(GTK_LABEL(bd->label_file_name), (bd->path) ? filename_from_path(bd->path) : "");
+		gtk_label_set_text(GTK_LABEL(bd->label_file_name), (bd->fd) ? bd->fd->name : "");
 		}
 }
 
@@ -849,7 +850,7 @@
 		keyword_list_push(bd->keyword_view, list);
 		}
 
-	path_list_free(list);
+	string_list_free(list);
 }
 
 static void bar_info_keyword_toggle(GtkCellRendererToggle *toggle, const gchar *path, gpointer data)
@@ -899,14 +900,14 @@
 	work = list;
 	while (work)
 		{
-		const gchar *path = work->data;
+		FileData *fd = work->data;
 		work = work->next;
 
-		metadata_set_keywords(path, keywords, add);
+		metadata_set_keywords(fd, keywords, add);
 		}
 
-	path_list_free(list);
-	path_list_free(keywords);
+	filelist_free(list);
+	string_list_free(keywords);
 }
 
 static void bar_info_set_add(GtkWidget *button, gpointer data)
@@ -952,12 +953,12 @@
 
 	bar_list = g_list_remove(bar_list, bd);
 
-	g_free(bd->path);
+	file_data_unref(bd->fd);
 
 	g_free(bd);
 }
 
-GtkWidget *bar_info_new(const gchar *path, gint metadata_only, GtkWidget *bounding_widget)
+GtkWidget *bar_info_new(FileData *fd, gint metadata_only, GtkWidget *bounding_widget)
 {
 	BarInfoData *bd;
 	GtkWidget *box;
@@ -1132,7 +1133,7 @@
 
 	bd->save_timeout_id = -1;
 
-	bd->path = g_strdup(path);
+	bd->fd = file_data_ref(fd);
 	bar_info_update(bd);
 
 	bar_info_selection(bd->vbox, 0);
--- a/src/bar_info.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/bar_info.h	Tue Sep 11 20:06:29 2007 +0000
@@ -14,10 +14,10 @@
 #define BAR_INFO_H
 
 
-GtkWidget *bar_info_new(const gchar *path, gint metadata_only, GtkWidget *bounding_widget);
+GtkWidget *bar_info_new(FileData *fd, gint metadata_only, GtkWidget *bounding_widget);
 void bar_info_close(GtkWidget *bar);
 
-void bar_info_set(GtkWidget *bar, const gchar *path);
+void bar_info_set(GtkWidget *bar, FileData *fd);
 gint bar_info_event(GtkWidget *bar, GdkEvent *event);
 
 void bar_info_set_selection_func(GtkWidget *bar, GList *(*list_func)(gpointer data), gpointer data);
@@ -25,13 +25,13 @@
 
 void bar_info_size_request(GtkWidget *bar, gint width);
 
-void bar_info_maint_renamed(GtkWidget *bar, const gchar *path);
+void bar_info_maint_renamed(GtkWidget *bar, FileData *fd);
 
-gint comment_write(const gchar *path, GList *keywords, const gchar *comment);
-gint comment_cache_write(const gchar *path, GList *keywords, const gchar *comment);
+gint comment_write(gchar *path, GList *keywords, const gchar *comment);
+gint comment_cache_write(FileData *fd, GList *keywords, const gchar *comment);
 
-gint comment_read(const gchar *path, GList **keywords, gchar **comment);
-gint comment_cache_read(const gchar *path, GList **keywords, gchar **comment);
+gint comment_read(gchar *path, GList **keywords, gchar **comment);
+gint comment_cache_read(FileData *fd, GList **keywords, gchar **comment);
 
 GList *keyword_list_pull(GtkWidget *text_widget);
 void keyword_list_push(GtkWidget *textview, GList *list);
--- a/src/bar_sort.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/bar_sort.c	Tue Sep 11 20:06:29 2007 +0000
@@ -82,7 +82,7 @@
 static gint bar_sort_selection_state = BAR_SORT_SELECTION_IMAGE;
 
 
-static void bar_sort_undo_set(SortData *sd, GList *src_list, const gchar *src, const gchar *dest);
+static void bar_sort_undo_set(SortData *sd, GList *src_list, FileData *src, const gchar *dest);
 static void bar_sort_add_close(SortData *sd);
 
 
@@ -122,7 +122,7 @@
 		g_free(name);
 		}
 
-	path_list_free(list);
+	string_list_free(list);
 }
 
 static void bar_sort_mode_sync(SortData *sd, SortModeType mode)
@@ -170,13 +170,13 @@
 }
 
 /* this takes control of src_list */
-static void bar_sort_undo_set(SortData *sd, GList *src_list, const gchar *src, const gchar *dest)
+static void bar_sort_undo_set(SortData *sd, GList *src_list, FileData *src, const gchar *dest)
 {
-	path_list_free(sd->undo_src_list);
-	sd->undo_src_list = src_list;
+	string_list_free(sd->undo_src_list);
+	sd->undo_src_list = filelist_to_path_list(src_list);
 
 	g_free(sd->undo_src);
-	sd->undo_src = g_strdup(src);
+	sd->undo_src = src ? g_strdup(src->path) : NULL;
 	g_free(sd->undo_dest);
 	sd->undo_dest = g_strdup(dest);
 
@@ -200,14 +200,14 @@
 			GList *list;
 			gchar *src_dir;
 
-			list = g_list_append(NULL, g_strdup(sd->undo_dest));
+			list = g_list_append(NULL, file_data_new_simple(sd->undo_dest));
 			src_dir = remove_level_from_path(sd->undo_src);
 			file_util_move_simple(list, src_dir);
 			g_free(src_dir);
 			}
 			break;
 		case BAR_SORT_COPY:
-			file_util_delete(sd->undo_dest, NULL, button);
+			file_util_delete(file_data_new_simple(sd->undo_dest), NULL, button);
 			break;
 		case BAR_SORT_LINK:
 			if (!unlink_file(sd->undo_dest))
@@ -225,7 +225,7 @@
 
 	if (isfile(sd->undo_src))
 		{
-		layout_image_set_path(sd->lw, sd->undo_src);
+		layout_image_set_fd(sd->lw, file_data_new_simple(sd->undo_src));
 		}
 
 	bar_sort_undo_set(sd, NULL, NULL, NULL);
@@ -242,7 +242,7 @@
 
 		source = work->data;
 		work = work->next;
-		collect_manager_remove(source, sd->undo_dest);
+		collect_manager_remove(file_data_new_simple(source), sd->undo_dest);
 		}
 
 	bar_sort_undo_set(sd, NULL, NULL, NULL);
@@ -262,17 +262,17 @@
 		}
 }
 
-static void bar_sort_bookmark_select_folder(SortData *sd, const gchar *source, const gchar *path)
+static void bar_sort_bookmark_select_folder(SortData *sd, FileData *source, const gchar *path)
 {
 	GList *list;
 	gchar *dest_path;
 
 	if (!isdir(path)) return;
 
-	dest_path = concat_dir_and_file(path, filename_from_path(source));
+	dest_path = concat_dir_and_file(path, source->name);
 	bar_sort_undo_set(sd, NULL, source, dest_path);
 
-	list = g_list_append(NULL, g_strdup(source));
+	list = g_list_append(NULL, file_data_ref(source));
 
 	switch (sd->action)
 		{
@@ -286,7 +286,7 @@
 			list = NULL;
 			break;
 		case BAR_SORT_LINK:
-			if (symlink_utf8(source, dest_path))
+			if (symlink_utf8(source->path, dest_path))
 				{
 				layout_image_next(sd->lw);
 				}
@@ -306,14 +306,14 @@
 	g_free(dest_path);
 }
 
-static void bar_sort_bookmark_select_collection(SortData *sd, const gchar *source, const gchar *path)
+static void bar_sort_bookmark_select_collection(SortData *sd, FileData *source, const gchar *path)
 {
 	GList *list = NULL;
 
 	switch (sd->selection)
 		{
 		case BAR_SORT_SELECTION_IMAGE:
-			list = g_list_append(NULL, g_strdup(source));
+			list = g_list_append(NULL, file_data_ref(source));
 			break;
 		case BAR_SORT_SELECTION_SELECTED:
 			list = layout_selection_list(sd->lw);
@@ -330,20 +330,20 @@
 
 	while (list)
 		{
-		gchar *image_path;
+		FileData *image_fd;
 
-		image_path = list->data;
+		image_fd = list->data;
 		list = list->next;
-		collect_manager_add(image_path, path);
+		collect_manager_add(image_fd, path);
 		}
 }
 
 static void bar_sort_bookmark_select(const gchar *path, gpointer data)
 {
 	SortData *sd = data;
-	const gchar *source;
+	FileData *source;
 
-	source = layout_image_get_path(sd->lw);
+	source = layout_image_get_fd(sd->lw);
 	if (!path || !source) return;
 
 	if (sd->mode == BAR_SORT_MODE_FOLDER)
--- a/src/cache-loader.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/cache-loader.c	Tue Sep 11 20:06:29 2007 +0000
@@ -11,7 +11,9 @@
 
 #include "gqview.h"
 #include "cache-loader.h"
+#include "cache.h"
 
+#include "filelist.h"
 #include "exif.h"
 #include "md5-util.h"
 #include "ui_fileops.h"
@@ -44,7 +46,7 @@
 
 		if (!cl->il && !cl->error)
 			{
-			cl->il = image_loader_new(cl->path);
+			cl->il = image_loader_new(cl->fd);
 			image_loader_set_error_func(cl->il, cache_loader_error_cb, cl);
 			if (image_loader_start(cl->il, cache_loader_done_cb, cl))
 				{
@@ -90,7 +92,7 @@
 		 !cl->cd->dimensions)
 		{
 		if (!cl->error &&
-		    image_load_dimensions(cl->path, &cl->cd->width, &cl->cd->height))
+		    image_load_dimensions(cl->fd, &cl->cd->width, &cl->cd->height))
 			{
 			cl->cd->dimensions = TRUE;
 			cl->done_mask |= CACHE_LOADER_DIMENSIONS;
@@ -105,7 +107,7 @@
 	else if (cl->todo_mask & CACHE_LOADER_MD5SUM &&
 		 !cl->cd->have_md5sum)
 		{
-		if (md5_get_digest_from_file_utf8(cl->path, cl->cd->md5sum))
+		if (md5_get_digest_from_file_utf8(cl->fd->path, cl->cd->md5sum))
 			{
 			cl->cd->have_md5sum = TRUE;
 			cl->done_mask |= CACHE_LOADER_MD5SUM;
@@ -123,7 +125,7 @@
 		time_t date = -1;
 		ExifData *exif;
 
-		exif = exif_read(cl->path, FALSE);
+		exif = exif_read(cl->fd, FALSE);
 		if (exif)
 			{
 			gchar *text;
@@ -161,14 +163,14 @@
 			gchar *base;
 			mode_t mode = 0755;
 
-			base = cache_get_location(CACHE_TYPE_SIM, cl->path, FALSE, &mode);
+			base = cache_get_location(CACHE_TYPE_SIM, cl->fd->path, FALSE, &mode);
 			if (cache_ensure_dir_exists(base, mode))
 				{
 				g_free(cl->cd->path);
-				cl->cd->path = cache_get_location(CACHE_TYPE_SIM, cl->path, TRUE, NULL);
+				cl->cd->path = cache_get_location(CACHE_TYPE_SIM, cl->fd->path, TRUE, NULL);
 				if (cache_sim_data_save(cl->cd))
 					{
-					filetime_set(cl->cd->path, filetime(cl->path));
+					filetime_set(cl->cd->path, filetime(cl->fd->path));
 					}
 				}
 			g_free(base);
@@ -194,22 +196,22 @@
 	return cache_loader_process(cl);
 }
 
-CacheLoader *cache_loader_new(const gchar *path, CacheDataType load_mask,
+CacheLoader *cache_loader_new(FileData *fd, CacheDataType load_mask,
 			      CacheLoaderDoneFunc done_func, gpointer done_data)
 {
 	CacheLoader *cl;
 	gchar *found;
 
-	if (!path || !isfile(path)) return NULL;
+	if (!fd || !isfile(fd->path)) return NULL;
 
 	cl = g_new0(CacheLoader, 1);
-	cl->path = g_strdup(path);
+	cl->fd = file_data_ref(fd);
 
 	cl->done_func = done_func;
 	cl->done_data = done_data;
 
-	found = cache_find_location(CACHE_TYPE_SIM, path);
-	if (found && filetime(found) == filetime(path))
+	found = cache_find_location(CACHE_TYPE_SIM, cl->fd->path);
+	if (found && filetime(found) == filetime(cl->fd->path))
 		{
 		cl->cd = cache_sim_data_load(found);
 		}
@@ -241,7 +243,7 @@
 	image_loader_free(cl->il);
 	cache_sim_data_free(cl->cd);
 
-	g_free(cl->path);
+	file_data_unref(cl->fd);
 	g_free(cl);
 }
 
--- a/src/cache-loader.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/cache-loader.h	Tue Sep 11 20:06:29 2007 +0000
@@ -32,7 +32,7 @@
 } CacheDataType;
 
 struct _CacheLoader {
-	gchar *path;
+	FileData *fd;
 	CacheData *cd;
 
 	CacheDataType todo_mask;
@@ -48,7 +48,7 @@
 };
 
 
-CacheLoader *cache_loader_new(const gchar *path, CacheDataType load_mask,
+CacheLoader *cache_loader_new(FileData *fd, CacheDataType load_mask,
 			      CacheLoaderDoneFunc done_func, gpointer done_data);
 
 void cache_loader_free(CacheLoader *cl);
--- a/src/cache_maint.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/cache_maint.c	Tue Sep 11 20:06:29 2007 +0000
@@ -500,10 +500,12 @@
 		}
 }
 
-void cache_maint_moved(const gchar *src, const gchar *dest)
+void cache_maint_moved(FileData *fd)
 {
 	gchar *base;
 	mode_t mode = 0755;
+	const gchar *src = fd->change->source;
+	const gchar *dest = fd->change->dest;
 
 	if (!src || !dest) return;
 
@@ -556,40 +558,40 @@
 		}
 }
 
-void cache_maint_removed(const gchar *source)
+void cache_maint_removed(FileData *fd)
 {
 	gchar *buf;
 
-	buf = cache_find_location(CACHE_TYPE_THUMB, source);
+	buf = cache_find_location(CACHE_TYPE_THUMB, fd->path);
 	cache_file_remove(buf);
 	g_free(buf);
 
-	buf = cache_find_location(CACHE_TYPE_SIM, source);
+	buf = cache_find_location(CACHE_TYPE_SIM, fd->path);
 	cache_file_remove(buf);
 	g_free(buf);
 
-	buf = cache_find_location(CACHE_TYPE_METADATA, source);
+	buf = cache_find_location(CACHE_TYPE_METADATA, fd->path);
 	cache_file_remove(buf);
 	g_free(buf);
 
-	if (enable_thumb_caching && thumbnail_spec_standard) thumb_std_maint_removed(source);
+	if (enable_thumb_caching && thumbnail_spec_standard) thumb_std_maint_removed(fd->path);
 }
 
-void cache_maint_copied(const gchar *src, const gchar *dest)
+void cache_maint_copied(FileData *fd)
 {
 	gchar *dest_base;
 	gchar *src_cache;
 	mode_t mode = 0755;
 
-	src_cache = cache_find_location(CACHE_TYPE_METADATA, src);
+	src_cache = cache_find_location(CACHE_TYPE_METADATA, fd->change->source);
 	if (!src_cache) return;
 
-	dest_base = cache_get_location(CACHE_TYPE_METADATA, dest, FALSE, &mode);
+	dest_base = cache_get_location(CACHE_TYPE_METADATA, fd->change->dest, FALSE, &mode);
 	if (cache_ensure_dir_exists(dest_base, mode))
 		{
 		gchar *path;
                                                                                                                     
-		path = cache_get_location(CACHE_TYPE_METADATA, dest, TRUE, NULL);
+		path = cache_get_location(CACHE_TYPE_METADATA, fd->change->dest, TRUE, NULL);
 		if (!copy_file(src_cache, path))
 			{
 			if (debug) printf("failed to copy metadata %s to %s\n", src_cache, path);
--- a/src/cache_maint.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/cache_maint.h	Tue Sep 11 20:06:29 2007 +0000
@@ -19,9 +19,9 @@
 gint cache_maintain_home_dir(const gchar *dir, gint recursive, gint clear);
 gint cache_maintain_dir(const gchar *dir, gint recursive, gint clear);
 
-void cache_maint_moved(const gchar *src, const gchar *dest);
-void cache_maint_removed(const gchar *source);
-void cache_maint_copied(const gchar *src, const gchar *dest);
+void cache_maint_moved(FileData *fd);
+void cache_maint_removed(FileData *fd);
+void cache_maint_copied(FileData *fd);
 
 
 void cache_manager_gqview_clear_confirm(GtkWidget *parent);
--- a/src/collect-io.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/collect-io.c	Tue Sep 11 20:06:29 2007 +0000
@@ -18,6 +18,7 @@
 #include "rcfile.h"
 #include "thumb.h"
 #include "ui_fileops.h"
+#include "filelist.h"
 
 
 #define GQVIEW_COLLECTION_MARKER "#GQview"
@@ -25,8 +26,14 @@
 #define GQVIEW_COLLECTION_FAIL_MIN     300
 #define GQVIEW_COLLECTION_FAIL_PERCENT 98
 
+typedef struct _CollectManagerEntry CollectManagerEntry;
 
 static void collection_load_thumb_step(CollectionData *cd);
+static gint collection_save_private(CollectionData *cd, const gchar *path);
+
+static CollectManagerEntry *collect_manager_get_entry(const gchar *path);
+static void collect_manager_entry_reset(CollectManagerEntry *entry);
+
 
 
 static gint scan_geometry(gchar *buffer, gint *x, gint *y, gint *w, gint *h)
@@ -52,10 +59,15 @@
 	gint success = TRUE;
 	guint total = 0;
 	guint fail = 0;
+	gboolean changed = FALSE;
+	CollectManagerEntry *entry = NULL;
 
 	collection_load_stop(cd);
 
-	if (flush) collect_manager_flush();
+	if (flush) 
+		collect_manager_flush();
+	else
+		entry = collect_manager_get_entry(path);
 
 	if (!append)
 		{
@@ -104,8 +116,11 @@
 		if (buf)
 			{
 			gint valid;
-
-			valid = (buf[0] == '/' && collection_add_check(cd, buf, FALSE, flush));
+			
+			if (!flush)
+				changed |= collect_manager_process_action(entry, &buf);
+			
+			valid = (buf[0] == '/' && collection_add_check(cd, file_data_new_simple(buf), FALSE, TRUE));
 			g_free(buf);
 
 			total++;
@@ -124,8 +139,26 @@
 		}
 
 	fclose(f);
+	
+	if (!flush)
+		{
+		gchar *buf = NULL;
+		while (collect_manager_process_action(entry, &buf))
+			{
+			collection_add_check(cd, file_data_new_simple(buf), FALSE, TRUE);
+			changed = TRUE;
+			g_free(buf);
+			}
+		}
 
 	cd->list = collection_list_sort(cd->list, cd->sort_method);
+	
+	if (!flush && changed && success)
+		collection_save_private(cd, path);
+		
+	if (!flush)
+		collect_manager_entry_reset(entry);
+	
 	if (!append) cd->changed = FALSE;
 
 	return success;
@@ -214,10 +247,10 @@
 				   cd);
 
 	/* start it */
-	if (!thumb_loader_start(cd->thumb_loader, ci->path))
+	if (!thumb_loader_start(cd->thumb_loader, ci->fd->path))
 		{
 		/* error, handle it, do next */
-		if (debug) printf("error loading thumb for %s\n", ci->path);
+		if (debug) printf("error loading thumb for %s\n", ci->fd->path);
 		collection_load_thumb_do(cd);
 		collection_load_thumb_step(cd);
 		}
@@ -290,7 +323,7 @@
 	while (work)
 		{
 		CollectInfo *ci = work->data;
-		if (fprintf(f, "\"%s\"\n", ci->path) < 0)
+		if (fprintf(f, "\"%s\"\n", ci->fd->path) < 0)
 			{
 			fclose(f);
 			printf("Error writing to %s\n", tmp_path);
@@ -386,11 +419,13 @@
 #define COLLECT_MANAGER_ACTIONS_PER_IDLE 1000
 #define COLLECT_MANAGER_FLUSH_DELAY      10000
 
-typedef struct _CollectManagerEntry CollectManagerEntry;
 struct _CollectManagerEntry
 {
 	gchar *path;
-	GList *action_list;
+	GList *add_list;
+	GHashTable *oldpath_hash;
+	GHashTable *newpath_hash;
+	gboolean empty;
 };
 
 typedef enum {
@@ -449,26 +484,11 @@
 	g_free(action);
 }
 
-static CollectManagerEntry *collect_manager_entry_new(const gchar *path)
-{
-	CollectManagerEntry *entry;
-
-	entry = g_new0(CollectManagerEntry, 1);
-	entry->path = g_strdup(path);
-	entry->action_list = NULL;
-
-	collection_manager_entry_list = g_list_append(collection_manager_entry_list, entry);
-
-	return entry;
-}
-
-static void collect_manager_entry_free(CollectManagerEntry *entry)
+static void collect_manager_entry_free_data(CollectManagerEntry *entry)
 {
 	GList *work;
 
-	collection_manager_entry_list = g_list_remove(collection_manager_entry_list, entry);
-
-	work = entry->action_list;
+	work = entry->add_list;
 	while (work)
 		{
 		CollectManagerAction *action;
@@ -478,12 +498,179 @@
 
 		collect_manager_action_unref(action);
 		}
-	g_list_free(entry->action_list);
+	g_list_free(entry->add_list);
+	g_hash_table_destroy(entry->oldpath_hash);
+	g_hash_table_destroy(entry->newpath_hash);
+}
+
+static void collect_manager_entry_init_data(CollectManagerEntry *entry)
+{
+	entry->add_list = NULL;
+	entry->oldpath_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify) collect_manager_action_unref);
+	entry->newpath_hash = g_hash_table_new(g_str_hash, g_str_equal);
+	entry->empty = TRUE;
+
+}
+
+static CollectManagerEntry *collect_manager_entry_new(const gchar *path)
+{
+	CollectManagerEntry *entry;
+
+	entry = g_new0(CollectManagerEntry, 1);
+	entry->path = g_strdup(path);
+	collect_manager_entry_init_data(entry);
+
+	collection_manager_entry_list = g_list_append(collection_manager_entry_list, entry);
+
+	return entry;
+}
+
+
+static void collect_manager_entry_free(CollectManagerEntry *entry)
+{
+	GList *work;
+
+	collection_manager_entry_list = g_list_remove(collection_manager_entry_list, entry);
+
+	collect_manager_entry_free_data(entry);
 
 	g_free(entry->path);
 	g_free(entry);
 }
 
+static void collect_manager_entry_reset(CollectManagerEntry *entry)
+{
+	collect_manager_entry_free_data(entry);
+	collect_manager_entry_init_data(entry);
+}
+
+static CollectManagerEntry *collect_manager_get_entry(const gchar *path)
+{
+	GList *work;
+
+	work = collection_manager_entry_list;
+	while (work)
+		{
+		CollectManagerEntry *entry;
+
+		entry = work->data;
+		work = work->next;
+		if (strcmp(entry->path, path) == 0) 
+			{
+			return entry;
+			}
+		}
+	return NULL;
+
+}
+
+static void collect_manager_entry_add_action(CollectManagerEntry *entry, CollectManagerAction *action)
+{
+
+	CollectManagerAction *orig_action;
+	
+	entry->empty = FALSE; 
+	
+	if (action->oldpath == NULL)
+		{
+		/* add file */
+		if (action->newpath == NULL)
+			{
+			return;
+			}
+		
+		orig_action = g_hash_table_lookup(entry->newpath_hash, action->newpath);
+		if (orig_action)
+			{
+			/* target already exists */
+			printf("collection manager failed to add another action for target %s in collection %s\n",
+				action->newpath, entry->path);
+			return;
+			}
+		entry->add_list = g_list_append(entry->add_list, action);
+		g_hash_table_insert(entry->newpath_hash, action->newpath, action);
+		collect_manager_action_ref(action);
+		return;
+		}
+
+	orig_action = g_hash_table_lookup(entry->newpath_hash, action->oldpath);
+	if (orig_action)
+		{
+		/* new action with the same file */
+		CollectManagerAction *new_action = collect_manager_action_new(orig_action->oldpath, action->newpath, action->type);
+		
+		if (new_action->oldpath)
+			{
+			g_hash_table_steal(entry->oldpath_hash, orig_action->oldpath);
+			g_hash_table_insert(entry->oldpath_hash, new_action->oldpath, new_action);
+			}
+		else
+			{
+			GList *work = g_list_find(entry->add_list, orig_action);
+			work->data = new_action;
+			}
+		
+		g_hash_table_steal(entry->newpath_hash, orig_action->newpath);
+		if (new_action->newpath) 
+			{
+			g_hash_table_insert(entry->newpath_hash, new_action->newpath, new_action); 
+			}
+		collect_manager_action_unref(orig_action);
+		return;
+		}
+
+
+	orig_action = g_hash_table_lookup(entry->oldpath_hash, action->oldpath);
+	if (orig_action)
+		{
+		/* another action for the same source, ignore */
+		printf("collection manager failed to add another action for source %s in collection %s\n",
+			action->oldpath, entry->path);
+		return;
+		}
+	
+	g_hash_table_insert(entry->oldpath_hash, action->oldpath, action);
+	if (action->newpath)
+		{
+		g_hash_table_insert(entry->newpath_hash, action->newpath, action); 
+		}
+	collect_manager_action_ref(action);
+}
+
+gint collect_manager_process_action(CollectManagerEntry *entry, gchar **path_ptr)
+{
+	gchar *path = *path_ptr;
+	CollectManagerAction *action;
+	
+	if (path == NULL)
+		{
+		/* get new files */
+		if (entry->add_list)
+			{
+			action = entry->add_list->data;
+			g_assert(action->oldpath == NULL);
+			entry->add_list = g_list_remove(entry->add_list, action);
+			path = g_strdup(action->newpath);
+			g_hash_table_remove(entry->newpath_hash, path);
+			collect_manager_action_unref(action);
+			}
+		*path_ptr = path;
+		return (path != NULL);
+		}
+		
+	action = g_hash_table_lookup(entry->oldpath_hash, path);
+	
+	if (action)
+		{
+		g_free(path);
+		path = g_strdup(action->newpath);
+		*path_ptr = path;
+		return TRUE;
+		}
+
+	return FALSE; /* no change */
+}
+
 static void collect_manager_refresh(void)
 {
 	GList *list = NULL;
@@ -563,8 +750,7 @@
 
 			if (action->type == COLLECTION_MANAGER_UPDATE)
 				{
-				entry->action_list = g_list_prepend(entry->action_list, action);
-				collect_manager_action_ref(action);
+				collect_manager_entry_add_action(entry, action);
 				}
 			else if (action->oldpath && action->newpath &&
 				 strcmp(action->newpath, entry->path) == 0)
@@ -580,9 +766,7 @@
 					{
 					action->newpath = NULL;
 					}
-
-				entry->action_list = g_list_prepend(entry->action_list, action);
-				collect_manager_action_ref(action);
+				collect_manager_entry_add_action(entry, action);
 				}
 
 			max--;
@@ -609,52 +793,14 @@
 {
 	CollectionData *cd;
 	gint success;
-	GList *work;
 
-	if (!entry->action_list) return FALSE;
+	if (entry->empty) return FALSE;
 
 	cd = collection_new(entry->path);
 	success = collection_load_private(cd, entry->path, FALSE, FALSE);
 
-	work = g_list_last(entry->action_list);
-	while (work)
-		{
-		CollectManagerAction *action;
-
-		action = work->data;
-		work = work->prev;
-
-		if (!action->oldpath)
-			{
-			/* add image */
-			if (collection_list_find(cd->list, action->newpath) == NULL)
-				{
-				collection_add_check(cd, action->newpath, FALSE, FALSE);
-				}
-			}
-		else if (action->newpath)
-			{
-			/* rename image */
-			while (collection_rename(cd, action->oldpath, action->newpath));
-			}
-		else
-			{
-			/* remove image */
-			while (collection_remove(cd, action->oldpath));
-			}
-		collect_manager_action_unref(action);
-		}
-
-	if (success && cd->changed)
-		{
-		collection_save_private(cd, entry->path);
-		if (debug) printf("collection manager updated: %s\n", entry->path);
-		}
 	collection_unref(cd);
 
-	g_list_free(entry->action_list);
-	entry->action_list = NULL;
-
 	return TRUE;
 }
 
@@ -675,6 +821,8 @@
 	return FALSE;
 }
 
+
+
 static gint collect_manager_process_cb(gpointer data)
 {
 	if (collection_manager_action_list) collect_manager_refresh();
@@ -735,50 +883,52 @@
 	collect_manager_timer_push(FALSE);
 }
 
-void collect_manager_moved(const gchar *oldpath, const gchar *newpath)
+void collect_manager_moved(FileData *fd)
 {
 	CollectManagerAction *action;
+	const gchar *oldpath = fd->change->source;
+	const gchar *newpath = fd->change->dest;
 
 	action = collect_manager_action_new(oldpath, newpath, COLLECTION_MANAGER_UPDATE);
 	collect_manager_add_action(action);
 }
 
-void collect_manager_add(const gchar *path, const gchar *collection)
+void collect_manager_add(FileData *fd, const gchar *collection)
 {
 	CollectManagerAction *action;
 	CollectWindow *cw;
 
-	if (!path || !collection) return;
+	if (!fd || !collection) return;
 
 	cw = collection_window_find_by_path(collection);
 	if (cw)
 		{
-		if (collection_list_find(cw->cd->list, path) == NULL)
+		if (collection_list_find(cw->cd->list, fd->path) == NULL)
 			{
-			collection_add(cw->cd, path, FALSE);
+			collection_add(cw->cd, fd, FALSE);
 			}
 		return;
 		}
 
-	action = collect_manager_action_new(path, collection, COLLECTION_MANAGER_ADD);
+	action = collect_manager_action_new(fd->path, collection, COLLECTION_MANAGER_ADD);
 	collect_manager_add_action(action);
 }
 
-void collect_manager_remove(const gchar *path, const gchar *collection)
+void collect_manager_remove(FileData *fd, const gchar *collection)
 {
 	CollectManagerAction *action;
 	CollectWindow *cw;
 
-	if (!path || !collection) return;
+	if (!fd || !collection) return;
 
 	cw = collection_window_find_by_path(collection);
 	if (cw)
 		{
-		while (collection_remove(cw->cd, path));
+		while (collection_remove(cw->cd, fd));
 		return;
 		}
 
-	action = collect_manager_action_new(path, collection, COLLECTION_MANAGER_REMOVE);
+	action = collect_manager_action_new(fd->path, collection, COLLECTION_MANAGER_REMOVE);
 	collect_manager_add_action(action);
 }
 
--- a/src/collect-io.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/collect-io.h	Tue Sep 11 20:06:29 2007 +0000
@@ -32,11 +32,11 @@
  *   deletes file when newpath == NULL
  *   adds file when oldpath == NULL
  */
-void collect_manager_moved(const gchar *oldpath, const gchar *newpath);
+void collect_manager_moved(FileData *fd);
 
 /* add or removing from a specific collection */
-void collect_manager_add(const gchar *path, const gchar *collection);
-void collect_manager_remove(const gchar *path, const gchar *collection);
+void collect_manager_add(FileData *fd, const gchar *collection);
+void collect_manager_remove(FileData *fd, const gchar *collection);
 
 /* commit pending operations to disk */
 void collect_manager_flush(void);
--- a/src/collect-table.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/collect-table.c	Tue Sep 11 20:06:29 2007 +0000
@@ -418,12 +418,12 @@
 
 GList *collection_table_selection_get_list(CollectTable *ct)
 {
-	return collection_list_to_path_list(ct->selection);
+	return collection_list_to_filelist(ct->selection);
 }
 
 static GList *collection_table_get_list(CollectTable *ct)
 {
-	return collection_list_to_path_list(ct->cd->list);
+	return collection_list_to_filelist(ct->cd->list);
 }
 
 /*
@@ -448,7 +448,7 @@
 	gtk_window_set_resizable(GTK_WINDOW(ct->tip_window), FALSE);
 	gtk_container_set_border_width(GTK_CONTAINER(ct->tip_window), 2);
 
-	label = gtk_label_new(filename_from_path(ct->tip_info->path));
+	label = gtk_label_new(ct->tip_info->fd->name);
 
 	g_object_set_data(G_OBJECT(ct->tip_window), "tip_label", label);
 	gtk_container_add(GTK_CONTAINER(ct->tip_window), label);
@@ -526,7 +526,7 @@
 				}
 
 			label = g_object_get_data(G_OBJECT(ct->tip_window), "tip_label");
-			gtk_label_set_text(GTK_LABEL(label), filename_from_path(ct->tip_info->path));
+			gtk_label_set_text(GTK_LABEL(label), ct->tip_info->fd->name);
 			}
 		}
 	else
@@ -573,7 +573,7 @@
 		return collection_table_selection_get_list(ct);
 		}
 
-	return g_list_append(NULL, g_strdup(ct->click_info->path));
+	return g_list_append(NULL, g_strdup(ct->click_info->fd->path));
 }
 
 static void collection_table_popup_edit_cb(GtkWidget *widget, gpointer data)
@@ -590,8 +590,8 @@
 	list = collection_table_popup_file_list(ct);
 	if (list)
 		{
-		start_editor_from_path_list(n, list);
-		path_list_free(list);
+		start_editor_from_filelist(n, list);
+		filelist_free(list);
 		}
 }
 
@@ -709,8 +709,8 @@
 
 	if (list)
 		{
-		collection_table_add_path_list(ct, list);
-		path_list_free(list);
+		collection_table_add_filelist(ct, list);
+		filelist_free(list);
 		}
 }
 
@@ -733,11 +733,11 @@
 static void collection_table_popup_print_cb(GtkWidget *widget, gpointer data)
 {
 	CollectTable *ct = data;
-	const gchar *path;
-
-	path = (ct->click_info) ? ct->click_info->path : NULL;
-
-	print_window_new(path, collection_table_selection_get_list(ct), collection_table_get_list(ct), ct->listview);
+	FileData *fd;
+
+	fd = (ct->click_info) ? ct->click_info->fd : NULL;
+
+	print_window_new(fd, collection_table_selection_get_list(ct), collection_table_get_list(ct), ct->listview);
 }
 
 static void collection_table_popup_show_names_cb(GtkWidget *widget, gpointer data)
@@ -1737,7 +1737,7 @@
 		}
 }
 
-void collection_table_add_path_list(CollectTable *ct, GList *list)
+void collection_table_add_filelist(CollectTable *ct, GList *list)
 {
 	GList *work;
 
@@ -1746,12 +1746,12 @@
 	work = list;
 	while (work)
 		{
-		collection_add(ct->cd, (gchar *)work->data, FALSE);
+		collection_add(ct->cd, (FileData *)work->data, FALSE);
 		work = work->next;
 		}
 }
 
-static void collection_table_insert_path_list(CollectTable *ct, GList *list, CollectInfo *insert_info)
+static void collection_table_insert_filelist(CollectTable *ct, GList *list, CollectInfo *insert_info)
 {
 	GList *work;
 
@@ -1760,7 +1760,7 @@
 	work = list;
 	while (work)
 		{
-		collection_insert(ct->cd, (gchar *)work->data, insert_info, FALSE);
+		collection_insert(ct->cd, (FileData *)work->data, insert_info, FALSE);
 		work = work->next;
 		}
 
@@ -1904,26 +1904,26 @@
 	GList *d = NULL;
 	GList *f = NULL;
 
-	if (path_list(path, &f, recursive ? &d : NULL))
+	if (filelist_read(path, &f, recursive ? &d : NULL))
 		{
 		GList *work;
 
-		f = path_list_filter(f, FALSE);
-		d = path_list_filter(d, TRUE);
-
-		f = path_list_sort(f);
-		d = path_list_sort(d);
-
-		collection_table_insert_path_list(ct, f, ct->marker_info);
+		f = filelist_filter(f, FALSE);
+		d = filelist_filter(d, TRUE);
+
+		f = filelist_sort_path(f);
+		d = filelist_sort_path(d);
+
+		collection_table_insert_filelist(ct, f, ct->marker_info);
 
 		work = g_list_last(d);
 		while (work)
 			{
-			collection_table_add_dir_recursive(ct, (gchar *)work->data, TRUE);
+			collection_table_add_dir_recursive(ct, ((FileData *)work->data)->path, TRUE);
 			work = work->prev;
 			}
-		path_list_free(f);
-		path_list_free(d);
+		filelist_free(f);
+		filelist_free(d);
 		}
 }
 
@@ -1932,11 +1932,11 @@
 	GList *work = list;
 	while (work)
 		{
-		gchar *path = work->data;
+		FileData *fd = work->data;
 		work = work->next;
-		if (isdir(path)) collection_table_add_dir_recursive(ct, path, recursive);
+		if (isdir(fd->path)) collection_table_add_dir_recursive(ct, fd->path, recursive);
 		}
-	collection_table_insert_path_list(ct, list, ct->marker_info);
+	collection_table_insert_filelist(ct, list, ct->marker_info);
 }
 
 
@@ -1958,7 +1958,7 @@
 {
 	CollectTable *ct = data;
 
-	collection_table_insert_path_list(ct, ct->drop_list, ct->marker_info);
+	collection_table_insert_filelist(ct, ct->drop_list, ct->marker_info);
 }
 
 static GtkWidget *collection_table_drop_menu(CollectTable *ct)
@@ -2040,14 +2040,12 @@
 				}
 			else
 				{
-				const gchar *path = ct->click_info->path;
-
-				list = g_list_append(NULL, g_strdup(path));
+				list = g_list_append(NULL, file_data_ref(ct->click_info->fd));
 				}
 			if (!list) return;
 
-			uri_text = uri_text_from_list(list, &total, (info == TARGET_TEXT_PLAIN));
-			path_list_free(list);
+			uri_text = uri_text_from_filelist(list, &total, (info == TARGET_TEXT_PLAIN));
+			filelist_free(list);
 			break;
 		}
 
@@ -2088,7 +2086,7 @@
 					gint col = -1;
 
 					/* it is a move within a collection */
-					path_list_free(list);
+					filelist_free(list);
 					list = NULL;
 
 					if (!drop_info)
@@ -2112,11 +2110,12 @@
 				}
 			break;
 		case TARGET_URI_LIST:
-			list = uri_list_from_text((gchar *)selection_data->data, TRUE);
+			list = uri_filelist_from_text((gchar *)selection_data->data, TRUE);
 			work = list;
 			while (work)
 				{
-				if (isdir((gchar *)work->data))
+				FileData *fd = work->data;
+				if (isdir(fd->path))
 					{
 					GtkWidget *menu;
 
@@ -2136,8 +2135,8 @@
 
 	if (list)
 		{
-		collection_table_insert_path_list(ct, list, drop_info);
-		path_list_free(list);
+		collection_table_insert_filelist(ct, list, drop_info);
+		filelist_free(list);
 		}
 }
 
@@ -2263,7 +2262,7 @@
 		if (info)
 			{
 			g_object_set(cell,	"pixbuf", info->pixbuf,
-						"text", filename_from_path(info->path),
+						"text", info->fd->name,
 						"cell-background-gdk", &color_bg,
 						"cell-background-set", TRUE,
 						"foreground-gdk", &color_fg,
--- a/src/collect-table.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/collect-table.h	Tue Sep 11 20:06:29 2007 +0000
@@ -18,7 +18,7 @@
 void collection_table_select_all(CollectTable *ct);
 void collection_table_unselect_all(CollectTable *ct);
 
-void collection_table_add_path_list(CollectTable *ct, GList *list);
+void collection_table_add_filelist(CollectTable *ct, GList *list);
 
 void collection_table_file_update(CollectTable *ct, CollectInfo *ci);
 void collection_table_file_add(CollectTable *ct, CollectInfo *ci);
--- a/src/collect.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/collect.c	Tue Sep 11 20:06:29 2007 +0000
@@ -53,16 +53,14 @@
  *-------------------------------------------------------------------
  */
 
-CollectInfo *collection_info_new(const gchar *path, struct stat *st, GdkPixbuf *pixbuf)
+CollectInfo *collection_info_new(FileData *fd, struct stat *st, GdkPixbuf *pixbuf)
 {
 	CollectInfo *ci;
 
-	if (!path) return NULL;
+	if (!fd) return NULL;
 
 	ci = g_new0(CollectInfo, 1);
-	ci->path = g_strdup(path);
-	ci->size = st->st_size;
-	ci->date = st->st_mtime;
+	ci->fd = file_data_ref(fd);
 
 	ci->pixbuf = pixbuf;
 	if (ci->pixbuf) g_object_ref(ci->pixbuf);
@@ -80,7 +78,7 @@
 {
 	if (!ci) return;
 
-	g_free(ci->path);
+	file_data_unref(ci->fd);
 	collection_info_free_thumb(ci);
 	g_free(ci);
 }
@@ -101,7 +99,7 @@
 	printf("collection_info_load_thumb not implemented!\n(because an instant thumb loader not implemented)");
 	return FALSE;
 #if 0	
-	if (create_thumbnail(ci->path, &ci->pixmap, &ci->mask) < 0) return FALSE;
+	if (create_thumbnail(ci->fd->path, &ci->pixmap, &ci->mask) < 0) return FALSE;
 
 	if (ci->pixmap) gdk_pixmap_ref(ci->pixmap);
 	if (ci->mask) gdk_bitmap_ref(ci->mask);
@@ -136,26 +134,26 @@
 			return 0;
 			break;
 		case SORT_SIZE:
-			if (cia->size < cib->size) return -1;
-			if (cia->size > cib->size) return 1;
+			if (cia->fd->size < cib->fd->size) return -1;
+			if (cia->fd->size > cib->fd->size) return 1;
 			return 0;
 			break;
 		case SORT_TIME:
-			if (cia->date < cib->date) return -1;
-			if (cia->date > cib->date) return 1;
+			if (cia->fd->date < cib->fd->date) return -1;
+			if (cia->fd->date > cib->fd->date) return 1;
 			return 0;
 			break;
 		case SORT_PATH:
-			return CASE_SORT(cia->path, cib->path);
+			return CASE_SORT(cia->fd->path, cib->fd->path);
 			break;
 #ifdef HAVE_STRVERSCMP
 		case SORT_NUMBER:
-			return strverscmp(filename_from_path(cia->path), filename_from_path(cib->path));
+			return strverscmp(cia->fd->name, cib->fd->name);
 			break;
 #endif
 		case SORT_NAME:
 		default:
-			return CASE_SORT(filename_from_path(cia->path), filename_from_path(cib->path));
+			return CASE_SORT(cia->fd->name, cib->fd->name);
 			break;
 		}
 
@@ -218,7 +216,7 @@
 	while(work)
 		{
 		CollectInfo *ci = work->data;
-		if (strcmp(ci->path, path) == 0) return ci;
+		if (strcmp(ci->fd->path, path) == 0) return ci;
 		work = work->next;
 		}
 
@@ -233,7 +231,7 @@
 	while(work)
 		{
 		CollectInfo *ci = work->data;
-		if (strcmp(ci->path, path) == 0) return work;
+		if (strcmp(ci->fd->path, path) == 0) return work;
 		work = work->next;
 		}
 
@@ -248,7 +246,7 @@
 	while(work)
 		{
 		CollectInfo *ci = work->data;
-		if (strcmp(ci->path, path) == 0) return c;
+		if (strcmp(ci->fd->path, path) == 0) return c;
 		work = work->next;
 		c++;
 		}
@@ -257,20 +255,20 @@
 }
 #endif
 
-GList *collection_list_to_path_list(GList *list)
+GList *collection_list_to_filelist(GList *list)
 {
-	GList *pathlist = NULL;
+	GList *filelist = NULL;
 	GList *work = list;
 
 	while (work)
 		{
 		CollectInfo *info = work->data;
-		pathlist = g_list_prepend(pathlist, g_strdup(info->path));
+		filelist = g_list_prepend(filelist, file_data_ref(info->fd));
 		work = work->next;
 		}
 
-	pathlist = g_list_reverse(pathlist);
-	return pathlist;
+	filelist = g_list_reverse(filelist);
+	return filelist;
 }
 
 CollectWindow *collection_window_find(CollectionData *cd)
@@ -444,7 +442,7 @@
 			n = (gint)strtol(data + b, NULL, 10);
 
 			info = g_list_nth_data(cd->list, n);
-			if (info && list) work = g_list_append(work, g_strdup(info->path));
+			if (info && list) work = g_list_append(work, file_data_ref(info->fd));
 			if (info && info_list) infol = g_list_append(infol, info);
 
 			while (data[e] == '\n') e++;
@@ -512,7 +510,7 @@
 
 	ptr[0] = '\0';
 
-	path_list_free(temp);
+	string_list_free(temp);
 
 	*length = total;
 
@@ -588,14 +586,14 @@
 	cd->info_updated_data = data;
 }
 
-gint collection_add_check(CollectionData *cd, const gchar *path, gint sorted, gint must_exist)
+gint collection_add_check(CollectionData *cd, FileData *fd, gint sorted, gint must_exist)
 {
 	struct stat st;
 	gint valid;
 
 	if (must_exist)
 		{
-		valid = (stat_utf8(path, &st) && !S_ISDIR(st.st_mode));
+		valid = (stat_utf8(fd->path, &st) && !S_ISDIR(st.st_mode));
 		}
 	else
 		{
@@ -607,7 +605,7 @@
 	if (valid)
 		{
 		CollectInfo *ci;
-		ci = collection_info_new(path, &st, NULL);
+		ci = collection_info_new(fd, &st, NULL);
 		cd->list = collection_list_add(cd->list, ci, sorted ? cd->sort_method : SORT_NONE);
 		cd->changed = TRUE;
 
@@ -624,21 +622,21 @@
 	return valid;
 }
 
-gint collection_add(CollectionData *cd, const gchar *path, gint sorted)
+gint collection_add(CollectionData *cd, FileData *fd, gint sorted)
 {
-	return collection_add_check(cd, path, sorted, TRUE);
+	return collection_add_check(cd, fd, sorted, TRUE);
 }
 
-gint collection_insert(CollectionData *cd, const gchar *path, CollectInfo *insert_ci, gint sorted)
+gint collection_insert(CollectionData *cd, FileData *fd, CollectInfo *insert_ci, gint sorted)
 {
 	struct stat st;
 
-	if (!insert_ci) return collection_add(cd, path, sorted);
+	if (!insert_ci) return collection_add(cd, fd, sorted);
 
-	if (stat_utf8(path, &st) >= 0 && !S_ISDIR(st.st_mode))
+	if (stat_utf8(fd->path, &st) >= 0 && !S_ISDIR(st.st_mode))
 		{
 		CollectInfo *ci;
-		ci = collection_info_new(path, &st, NULL);
+		ci = collection_info_new(fd, &st, NULL);
 		cd->list = collection_list_insert(cd->list, ci, insert_ci, sorted ? cd->sort_method : SORT_NONE);
 		cd->changed = TRUE;
 
@@ -650,11 +648,11 @@
 	return FALSE;
 }
 
-gint collection_remove(CollectionData *cd, const gchar *path)
+gint collection_remove(CollectionData *cd, FileData *fd)
 {
 	CollectInfo *ci;
 
-	ci = collection_list_find(cd->list, path);
+	ci = collection_list_find(cd->list, fd->path);
 
 	if (!ci) return FALSE;
 
@@ -702,16 +700,17 @@
 	collection_window_refresh(collection_window_find(cd));
 }
 
-gint collection_rename(CollectionData *cd, const gchar *source, const gchar *dest)
+gint collection_rename(CollectionData *cd, FileData *fd)
 {
 	CollectInfo *ci;
-
+	const gchar *source = fd->change->source;
+	const gchar *dest = fd->change->dest;
 	ci = collection_list_find(cd->list, source);
 
 	if (!ci) return FALSE;
 
-	g_free(ci->path);
-	ci->path = g_strdup(dest);
+//	g_free(ci->path);
+//	ci->path = g_strdup(dest); FIXME
 	cd->changed = TRUE;
 
 	collection_window_update(collection_window_find(cd), ci);
@@ -730,7 +729,7 @@
  *-------------------------------------------------------------------
  */
 
-void collection_maint_removed(const gchar *path)
+void collection_maint_removed(FileData *fd)
 {
 	GList *work;
 
@@ -740,17 +739,17 @@
 		CollectionData *cd = work->data;
 		work = work->next;
 
-		while(collection_remove(cd, path));
+		while(collection_remove(cd, fd));
 		}
 #if 0
 	/* Do we really need to do this? removed files are
 	 * automatically ignored when loading a collection.
 	 */
-	collect_manager_moved(path, NULL);
+	collect_manager_moved(fd, NULL);
 #endif
 }
 
-void collection_maint_renamed(const gchar *source, const gchar *dest)
+void collection_maint_renamed(FileData *fd)
 {
 	GList *work;
 
@@ -760,10 +759,10 @@
 		CollectionData *cd = work->data;
 		work = work->next;
 
-		while(collection_rename(cd, source, dest));
+		while(collection_rename(cd, fd));
 		}
 
-	collect_manager_moved(source, dest);
+	collect_manager_moved(fd);
 }
 
 /*
@@ -828,8 +827,8 @@
 				list = layout_list(NULL);
 				if (list)
 					{
-					collection_table_add_path_list(cw->table, list);
-					path_list_free(list);
+					collection_table_add_filelist(cw->table, list);
+					filelist_free(list);
 					}
 				break;
 			case 'C': case 'c':
@@ -902,13 +901,11 @@
 				if (event->state & GDK_SHIFT_MASK)
 					{
 					CollectInfo *info;
-					const gchar *path;
 
 					info = collection_table_get_focus_info(cw->table);
-					path = (info) ? info->path : NULL;
 
-					print_window_new(path, collection_table_selection_get_list(cw->table),
-							 collection_list_to_path_list(cw->cd->list), cw->window);
+					print_window_new(info->fd, collection_table_selection_get_list(cw->table),
+							 collection_list_to_filelist(cw->cd->list), cw->window);
 					}
 				else
 					{
@@ -936,8 +933,8 @@
 	if (edit_val != -1)
 		{
 		list = collection_table_selection_get_list(cw->table);
-		start_editor_from_path_list(edit_val, list);
-		path_list_free(list);
+		start_editor_from_filelist(edit_val, list);
+		filelist_free(list);
 		}
 
 	return stop_signal;
--- a/src/collect.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/collect.h	Tue Sep 11 20:06:29 2007 +0000
@@ -14,7 +14,7 @@
 #define COLLECT_H
 
 
-CollectInfo *collection_info_new(const gchar *path, struct stat *st, GdkPixbuf *pixbuf);
+CollectInfo *collection_info_new(FileData *fd, struct stat *st, GdkPixbuf *pixbuf);
 
 void collection_info_free_thumb(CollectInfo *ci);
 void collection_info_free(CollectInfo *ci);
@@ -29,7 +29,7 @@
 GList *collection_list_insert(GList *list, CollectInfo *ci, CollectInfo *insert_ci, SortType method);
 GList *collection_list_remove(GList *list, CollectInfo *ci);
 CollectInfo *collection_list_find(GList *list, const gchar *path);
-GList *collection_list_to_path_list(GList *list);
+GList *collection_list_to_filelist(GList *list);
 
 CollectionData *collection_new(const gchar *path);
 void collection_free(CollectionData *cd);
@@ -61,17 +61,17 @@
 void collection_set_update_info_func(CollectionData *cd,
 				     void (*func)(CollectionData *, CollectInfo *, gpointer), gpointer data);
 
-gint collection_add(CollectionData *cd, const gchar *path, gint sorted);
-gint collection_add_check(CollectionData *cd, const gchar *path, gint sorted, gint must_exist);
-gint collection_insert(CollectionData *cd, const gchar *path, CollectInfo *insert_ci, gint sorted);
-gint collection_remove(CollectionData *cd, const gchar *path);
+gint collection_add(CollectionData *cd, FileData *fd, gint sorted);
+gint collection_add_check(CollectionData *cd, FileData *fd, gint sorted, gint must_exist);
+gint collection_insert(CollectionData *cd, FileData *fd, CollectInfo *insert_ci, gint sorted);
+gint collection_remove(CollectionData *cd, FileData *fd);
 void collection_remove_by_info_list(CollectionData *cd, GList *list);
-gint collection_rename(CollectionData *cd, const gchar *source, const gchar *dest);
+gint collection_rename(CollectionData *cd, FileData *fd);
 
 void collection_update_geometry(CollectionData *cd);
 
-void collection_maint_removed(const gchar *path);
-void collection_maint_renamed(const gchar *source, const gchar *dest);
+void collection_maint_removed(FileData *fd);
+void collection_maint_renamed(FileData *fd);
 
 CollectWindow *collection_window_new(const gchar *path);
 void collection_window_close_by_collection(CollectionData *cd);
--- a/src/dupe.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/dupe.c	Tue Sep 11 20:06:29 2007 +0000
@@ -277,16 +277,13 @@
  * ------------------------------------------------------------------
  */
 
-static DupeItem *dupe_item_new(const gchar *path, gint64 size, time_t date)
+static DupeItem *dupe_item_new(FileData *fd)
 {
 	DupeItem *di;
 
 	di = g_new0(DupeItem, 1);
 
-	di->path = g_strdup(path);
-	di->name = filename_from_path(di->path);
-	di->size = size;
-	di->date = date;
+	di->fd = file_data_ref(fd);
 
 	di->group = NULL;
 	di->group_rank = 0.0;
@@ -304,7 +301,7 @@
 
 static void dupe_item_free(DupeItem *di)
 {
-	g_free(di->path);
+	file_data_unref(di->fd);
 	image_sim_free(di->simd);
 	g_free(di->md5sum);
 	if (di->pixbuf) g_object_unref(di->pixbuf);
@@ -324,13 +321,37 @@
 	g_list_free(list);
 }
 
+static DupeItem *dupe_item_find_fd_by_list(FileData *fd, GList *work)
+{
+	while (work)
+		{
+		DupeItem *di = work->data;
+
+		if (di->fd == fd) return di;
+
+		work = work->next;
+		}
+
+	return NULL;
+}
+
+static DupeItem *dupe_item_find_fd(DupeWindow *dw, FileData *fd)
+{
+	DupeItem *di;
+
+	di = dupe_item_find_fd_by_list(fd, dw->list);
+	if (!di && dw->second_set) di = dupe_item_find_fd_by_list(fd, dw->second_list);
+
+	return di;
+}
+
 static DupeItem *dupe_item_find_path_by_list(const gchar *path, GList *work)
 {
 	while (work)
 		{
 		DupeItem *di = work->data;
 
-		if (strcmp(di->path, path) == 0) return di;
+		if (strcmp(di->fd->path, path) == 0) return di;
 
 		work = work->next;
 		}
@@ -361,10 +382,10 @@
 
 	if (!di) return;
 
-	path = cache_find_location(CACHE_TYPE_SIM, di->path);
+	path = cache_find_location(CACHE_TYPE_SIM, di->fd->path);
 	if (!path) return;
 
-	if (filetime(di->path) != filetime(path))
+	if (filetime(di->fd->path) != filetime(path))
 		{
 		g_free(path);
 		return;
@@ -404,13 +425,13 @@
 
 	if (!di) return;
 
-	base = cache_get_location(CACHE_TYPE_SIM, di->path, FALSE, &mode);
+	base = cache_get_location(CACHE_TYPE_SIM, di->fd->path, FALSE, &mode);
 	if (cache_ensure_dir_exists(base, mode))
 		{
 		CacheData *cd;
 
 		cd = cache_sim_data_new();
-		cd->path = cache_get_location(CACHE_TYPE_SIM, di->path, TRUE, NULL);
+		cd->path = cache_get_location(CACHE_TYPE_SIM, di->fd->path, TRUE, NULL);
 
 		if (di->width != 0) cache_sim_data_set_dimensions(cd, di->width, di->height);
 		if (di->checksum != 0) cache_sim_data_set_checksum(cd, di->checksum);
@@ -423,7 +444,7 @@
 
 		if (cache_sim_data_save(cd))
 			{
-			filetime_set(cd->path, filetime(di->path));
+			filetime_set(cd->path, filetime(di->fd->path));
 			}
 		cache_sim_data_free(cd);
 		}
@@ -520,9 +541,9 @@
 		}
 
 	text[DUPE_COLUMN_THUMB] = "";
-	text[DUPE_COLUMN_NAME] = (gchar *)di->name;
-	text[DUPE_COLUMN_SIZE] = text_from_size(di->size);
-	text[DUPE_COLUMN_DATE] = (gchar *)text_from_time(di->date);
+	text[DUPE_COLUMN_NAME] = (gchar *)di->fd->name;
+	text[DUPE_COLUMN_SIZE] = text_from_size(di->fd->size);
+	text[DUPE_COLUMN_DATE] = (gchar *)text_from_time(di->fd->date);
 	if (di->width > 0 && di->height > 0)
 		{
 		text[DUPE_COLUMN_DIMENSIONS] = g_strdup_printf("%d x %d", di->width, di->height);
@@ -531,7 +552,7 @@
 		{
 		text[DUPE_COLUMN_DIMENSIONS] = g_strdup("");
 		}
-	text[DUPE_COLUMN_PATH] = di->path;
+	text[DUPE_COLUMN_PATH] = di->fd->path;
 	text[DUPE_COLUMN_COLOR] = NULL;
 
 	gtk_list_store_insert(store, &iter, row);
@@ -609,7 +630,7 @@
 }
 
 
-static GList *dupe_listview_get_path_list(DupeWindow *dw, GtkWidget *listview)
+static GList *dupe_listview_get_filelist(DupeWindow *dw, GtkWidget *listview)
 {
 	GtkTreeModel *store;
 	GtkTreeIter iter;
@@ -622,7 +643,7 @@
 		{
 		DupeItem *di;
 		gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &di, -1);
-		list = g_list_prepend(list, g_strdup(di->path));
+		list = g_list_prepend(list, file_data_ref(di->fd));
 
 		valid = gtk_tree_model_iter_next(store, &iter);
 		}
@@ -652,7 +673,7 @@
 		gtk_tree_model_get(store, &iter, DUPE_COLUMN_POINTER, &di, -1);
 		if (di)
 			{
-			list = g_list_prepend(list, g_strdup(di->path));
+			list = g_list_prepend(list, file_data_ref(di->fd));
 			}
 		work = work->next;
 		}
@@ -901,7 +922,7 @@
 {
 	GList *work;
 
-	printf("+ %f %s\n", di->group_rank, di->name);
+	printf("+ %f %s\n", di->group_rank, di->fd->name);
 
 	work = di->group;
 	while (work)
@@ -909,7 +930,7 @@
 		DupeMatch *dm = work->data;
 		work = work->next;
 
-		printf("  %f %s\n", dm->rank, dm->di->name);
+		printf("  %f %s\n", dm->rank, dm->di->fd->name);
 		}
 
 	printf("\n");
@@ -939,7 +960,7 @@
 		GList *work;
 		gdouble rank;
 
-		if (debug > 1) printf("link found %s to %s [%d]\n", child->name, parent->name, g_list_length(parent->group));
+		if (debug > 1) printf("link found %s to %s [%d]\n", child->fd->name, parent->fd->name, g_list_length(parent->group));
 
 		work = parent->group;
 		while (work)
@@ -968,7 +989,7 @@
 		}
 	else
 		{
-		if (debug > 1) printf("unlinking %s and %s\n", child->name, parent->name);
+		if (debug > 1) printf("unlinking %s and %s\n", child->fd->name, parent->fd->name);
 		
 		dupe_match_unlink(child, parent);
 		}
@@ -1101,32 +1122,32 @@
 
 	if (mask & DUPE_MATCH_PATH)
 		{
-		if (strcmp(a->path, b->path) != 0) return FALSE;
+		if (strcmp(a->fd->path, b->fd->path) != 0) return FALSE;
 		}
 	if (mask & DUPE_MATCH_NAME)
 		{
-		if (strcmp(a->name, b->name) != 0) return FALSE;
+		if (strcmp(a->fd->name, b->fd->name) != 0) return FALSE;
 		}
 	if (mask & DUPE_MATCH_SIZE)
 		{
-		if (a->size != b->size) return FALSE;
+		if (a->fd->size != b->fd->size) return FALSE;
 		}
 	if (mask & DUPE_MATCH_DATE)
 		{
-		if (a->date != b->date) return FALSE;
+		if (a->fd->date != b->fd->date) return FALSE;
 		}
 	if (mask & DUPE_MATCH_SUM)
 		{
-		if (!a->md5sum) a->md5sum = md5_text_from_file_utf8(a->path, "");
-		if (!b->md5sum) b->md5sum = md5_text_from_file_utf8(b->path, "");
+		if (!a->md5sum) a->md5sum = md5_text_from_file_utf8(a->fd->path, "");
+		if (!b->md5sum) b->md5sum = md5_text_from_file_utf8(b->fd->path, "");
 		if (a->md5sum[0] == '\0' ||
 		    b->md5sum[0] == '\0' ||
 		    strcmp(a->md5sum, b->md5sum) != 0) return FALSE;
 		}
 	if (mask & DUPE_MATCH_DIM)
 		{
-		if (a->width == 0) image_load_dimensions(a->path, &a->width, &a->height);
-		if (b->width == 0) image_load_dimensions(b->path, &b->width, &b->height);
+		if (a->width == 0) image_load_dimensions(a->fd, &a->width, &a->height);
+		if (b->width == 0) image_load_dimensions(b->fd, &b->width, &b->height);
 		if (a->width != b->width || a->height != b->height) return FALSE;
 		}
 	if (mask & DUPE_MATCH_SIM_HIGH ||
@@ -1155,7 +1176,7 @@
 
 		if (f < m) return FALSE;
 
-		if (debug > 2) printf("similar: %32s %32s = %f\n", a->name, b->name, f);
+		if (debug > 2) printf("similar: %32s %32s = %f\n", a->fd->name, b->fd->name, f);
 		}
 
 	return TRUE;
@@ -1307,10 +1328,10 @@
 				   dw);
 
 	/* start it */
-	if (!thumb_loader_start(dw->thumb_loader, di->path))
+	if (!thumb_loader_start(dw->thumb_loader, di->fd->path))
 		{
 		/* error, handle it, do next */
-		if (debug) printf("error loading thumb for %s\n", di->path);
+		if (debug) printf("error loading thumb for %s\n", di->fd->path);
 		dupe_thumb_do(dw);
 		dupe_thumb_step(dw);
 		}
@@ -1428,7 +1449,7 @@
 						if (di->md5sum) return TRUE;
 						}
 
-					di->md5sum = md5_text_from_file_utf8(di->path, "");
+					di->md5sum = md5_text_from_file_utf8(di->fd->path, "");
 					if (enable_thumb_caching)
 						{
 						dupe_item_write_cache(di);
@@ -1461,7 +1482,7 @@
 						if (di->width != 0 || di->height != 0) return TRUE;
 						}
 
-					image_load_dimensions(di->path, &di->width, &di->height);
+					image_load_dimensions(di->fd, &di->width, &di->height);
 					if (enable_thumb_caching)
 						{
 						dupe_item_write_cache(di);
@@ -1499,7 +1520,7 @@
 							}
 						}
 
-					dw->img_loader = image_loader_new(di->path);
+					dw->img_loader = image_loader_new(di->fd);
 					image_loader_set_buffer_size(dw->img_loader, 8);
 					image_loader_set_error_func(dw->img_loader, dupe_loader_done_cb, dw);
 
@@ -1685,44 +1706,44 @@
 }
 
 static void dupe_files_add(DupeWindow *dw, CollectionData *collection, CollectInfo *info,
-			   const gchar *path, gint recurse)
+			   FileData *fd, gint recurse)
 {
 	DupeItem *di = NULL;
 
 	if (info)
 		{
-		di = dupe_item_new(info->path, info->size, info->date);
+		di = dupe_item_new(info->fd);
 		}
-	else if (path)
+	else if (fd)
 		{
-		if (isfile(path))
+		if (isfile(fd->path))
 			{
-			di = dupe_item_new(path, filesize(path), filetime(path));
+			di = dupe_item_new(fd);
 			}
-		else if (isdir(path) && recurse)
+		else if (isdir(fd->path) && recurse)
 			{
 			GList *f, *d;
-			if (path_list(path, &f, &d))
+			if (filelist_read(fd->path, &f, &d))
 				{
 				GList *work;
 
-				f = path_list_filter(f, FALSE);
-				d = path_list_filter(d, TRUE);
+				f = filelist_filter(f, FALSE);
+				d = filelist_filter(d, TRUE);
 
 				work = f;
 				while(work)
 					{
-					dupe_files_add(dw, NULL, NULL, (gchar *)work->data, TRUE);
+					dupe_files_add(dw, NULL, NULL, (FileData *)work->data, TRUE);
 					work = work->next;
 					}
-				path_list_free(f);
+				filelist_free(f);
 				work = d;
 				while(work)
 					{
-					dupe_files_add(dw, NULL, NULL, (gchar *)work->data, TRUE);
+					dupe_files_add(dw, NULL, NULL, (FileData *)work->data, TRUE);
 					work = work->next;
 					}
-				path_list_free(d);
+				filelist_free(d);
 				}
 			}
 		}
@@ -1760,34 +1781,33 @@
 	work = list;
 	while(work)
 		{
-		gchar *path = work->data;
+		FileData *fd = work->data;
 		work = work->next;
 
-		dupe_files_add(dw, NULL, NULL, path, recurse);
+		dupe_files_add(dw, NULL, NULL, fd, recurse);
 		}
 
 	dupe_check_start(dw);
 }
 
-static gint dupe_item_set_path(DupeWindow *dw, const gchar *source, const gchar *dest)
+static void dupe_item_update(DupeWindow *dw, DupeItem *di)
 {
-	DupeItem *di;
-
-	di = dupe_item_find_path(dw, source);
-	if (!di) return FALSE;
-
 	if ( (dw->match_mask & DUPE_MATCH_NAME) || (dw->match_mask & DUPE_MATCH_PATH) )
 		{
 		/* only effects matches on name or path */
+/*
+		FileData *fd = file_data_ref(di->fd);
 		gint second;
 
 		second = di->second;
 		dupe_item_remove(dw, di);
 
 		dw->second_drop = second;
-		dupe_files_add(dw, NULL, NULL, dest, FALSE);
+		dupe_files_add(dw, NULL, NULL, fd, FALSE);
 		dw->second_drop = FALSE;
-
+		
+		file_data_unref(fd);
+*/
 		dupe_check_start(dw);
 		}
 	else
@@ -1795,11 +1815,6 @@
 		GtkListStore *store;
 		GtkTreeIter iter;
 		gint row;
-
-		g_free(di->path);
-		di->path = g_strdup(dest);
-		di->name = filename_from_path(di->path);
-
 		/* update the listview(s) */
 
 		store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->listview)));
@@ -1807,8 +1822,8 @@
 		if (row >= 0)
 			{
 			gtk_list_store_set(store, &iter,
-					   DUPE_COLUMN_NAME, di->name,
-					   DUPE_COLUMN_PATH, di->path, -1);
+					   DUPE_COLUMN_NAME, di->fd->name,
+					   DUPE_COLUMN_PATH, di->fd->path, -1);
 			}
 
 		if (dw->second_listview)
@@ -1817,14 +1832,33 @@
 			row = dupe_listview_find_item(store, di, &iter);
 			if (row >= 0)
 				{
-				gtk_list_store_set(store, &iter, 1, di->path, -1);
+				gtk_list_store_set(store, &iter, 1, di->fd->path, -1);
 				}
 			}
 		}
 
-	return TRUE;
 }
 
+static void dupe_item_update_fd_in_list(DupeWindow *dw, FileData *fd, GList *work)
+{
+	while (work)
+		{
+		DupeItem *di = work->data;
+
+		if (di->fd == fd) 
+			dupe_item_update(dw, di);
+
+		work = work->next;
+		}
+}
+
+static void dupe_item_update_fd(DupeWindow *dw, FileData *fd)
+{
+	dupe_item_update_fd_in_list(dw, fd, dw->list);
+	if (dw->second_set) dupe_item_update_fd_in_list(dw, fd, dw->second_list);
+}
+
+
 /*
  * ------------------------------------------------------------------
  * Misc.
@@ -1864,11 +1898,11 @@
 			       NULL, NULL);
 	generic_dialog_add_button(gd, GTK_STOCK_CLOSE, NULL, NULL, TRUE);
 
-	dupe_display_label(gd->vbox, "name:", di->name);
-	buf = text_from_size(di->size);
+	dupe_display_label(gd->vbox, "name:", di->fd->name);
+	buf = text_from_size(di->fd->size);
 	dupe_display_label(gd->vbox, "size:", buf);
 	g_free(buf);
-	dupe_display_label(gd->vbox, "date:", text_from_time(di->date));
+	dupe_display_label(gd->vbox, "date:", text_from_time(di->fd->date));
 	buf = g_strdup_printf("%d x %d", di->width, di->height);
 	dupe_display_label(gd->vbox, "dimensions:", buf);
 	g_free(buf);
@@ -1952,11 +1986,11 @@
 
 			list = dupe_listview_get_selection(dw, listview);
 			view_window_new_from_list(list);
-			path_list_free(list);
+			filelist_free(list);
 			}
 		else
 			{
-			layout_image_set_path(NULL, di->path);
+			layout_image_set_fd(NULL, di->fd);
 			}
 		}
 }
@@ -2009,9 +2043,9 @@
 
 	list = dupe_listview_get_selection(dw, dw->listview);
 
-	start_editor_from_path_list(n, list);
-
-	path_list_free(list);
+	start_editor_from_filelist(n, list);
+
+	filelist_free(list);
 }
 
 static void dupe_window_collection_from_selection(DupeWindow *dw)
@@ -2021,8 +2055,8 @@
 
 	list = dupe_listview_get_selection(dw, dw->listview);
 	w = collection_window_new(NULL);
-	collection_table_add_path_list(w->table, list);
-	path_list_free(list);
+	collection_table_add_filelist(w->table, list);
+	filelist_free(list);
 }
 
 static void dupe_window_append_file_list(DupeWindow *dw, gint on_second)
@@ -2033,7 +2067,7 @@
 
 	list = layout_list(NULL);
 	dupe_window_add_files(dw, list, FALSE);
-	path_list_free(list);
+	filelist_free(list);
 }
 
 /*
@@ -2117,13 +2151,13 @@
 static void dupe_menu_print_cb(GtkWidget *widget, gpointer data)
 {
 	DupeWindow *dw = data;
-	const gchar *path;
-
-	path = (dw->click_item) ? dw->click_item->path : NULL;
-
-	print_window_new(path,
+	FileData *fd;
+
+	fd = (dw->click_item) ? dw->click_item->fd : NULL;
+
+	print_window_new(fd,
 			 dupe_listview_get_selection(dw, dw->listview),
-			 dupe_listview_get_path_list(dw, dw->listview), dw->window);
+			 dupe_listview_get_filelist(dw, dw->listview), dw->window);
 }
 
 static void dupe_menu_copy_cb(GtkWidget *widget, gpointer data)
@@ -2396,7 +2430,7 @@
 
 	store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(dw->second_listview)));
 	gtk_list_store_append(store, &iter);
-	gtk_list_store_set(store, &iter, DUPE_COLUMN_POINTER, di, 1, di->path, -1);
+	gtk_list_store_set(store, &iter, DUPE_COLUMN_POINTER, di, 1, di->fd->path, -1);
 
 	dupe_second_update_status(dw);
 }
@@ -3248,18 +3282,18 @@
 	work = d->list;
 	while (work)
 		{
-		gchar *path = work->data;
+		FileData *fd = work->data;
 		work = work->next;
-		if (isdir(path))
+		if (isdir(fd->path))
 			{
 			GList *list = NULL;
 
-			path_list(path, &list, NULL);
-			list = path_list_filter(list, FALSE);
+			filelist_read(fd->path, &list, NULL);
+			list = filelist_filter(list, FALSE);
 			if (list)
 				{
 				dupe_window_add_files(d->dw, list, FALSE);
-				path_list_free(list);
+				filelist_free(list);
 				}
 			}
 		}
@@ -3280,7 +3314,7 @@
 static void confirm_dir_list_destroy(GtkWidget *widget, gpointer data)
 {
 	CDupeConfirmD *d = data;
-	path_list_free(d->list);
+	filelist_free(d->list);
 	g_free(d);
 }
 
@@ -3341,8 +3375,8 @@
 		case TARGET_TEXT_PLAIN:
 			list = dupe_listview_get_selection(dw, widget);
 			if (!list) return;
-			uri_text = uri_text_from_list(list, &length, (info == TARGET_TEXT_PLAIN));
-			path_list_free(list);
+			uri_text = uri_text_from_filelist(list, &length, (info == TARGET_TEXT_PLAIN));
+			filelist_free(list);
 			break;
 		default:
 			uri_text = NULL;
@@ -3375,11 +3409,12 @@
 			collection_from_dnd_data((gchar *)selection_data->data, &list, NULL);
 			break;
 		case TARGET_URI_LIST:
-			list = uri_list_from_text((gchar *)selection_data->data, TRUE);
+			list = uri_filelist_from_text((gchar *)selection_data->data, TRUE);
 			work = list;
 			while(work)
 				{
-				if (isdir((gchar *)work->data))
+				FileData *fd = work->data;
+				if (isdir(fd->path))
 					{
 					GtkWidget *menu;
 					menu = dupe_confirm_dir_list(dw, list);
@@ -3397,7 +3432,7 @@
 	if (list)
 		{
 		dupe_window_add_files(dw, list, FALSE);
-		path_list_free(list);
+		filelist_free(list);
 		}
 }
 
@@ -3501,7 +3536,7 @@
  *-------------------------------------------------------------------
  */
 
-void dupe_maint_removed(const gchar *path)
+void dupe_maint_removed(FileData *fd)
 {
 	GList *work;
 
@@ -3511,11 +3546,11 @@
 		DupeWindow *dw = work->data;
 		work = work->next;
 
-		while (dupe_item_remove_by_path(dw, path));
+		while (dupe_item_remove_by_path(dw, fd->path));
 		}
 }
 
-void dupe_maint_renamed(const gchar *source, const gchar *dest)
+void dupe_maint_renamed(FileData *fd)
 {
 	GList *work;
 
@@ -3525,7 +3560,7 @@
 		DupeWindow *dw = work->data;
 		work = work->next;
 
-		while (dupe_item_set_path(dw, source, dest));
+		dupe_item_update_fd(dw, fd);
 		}
 
 }
--- a/src/dupe.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/dupe.h	Tue Sep 11 20:06:29 2007 +0000
@@ -37,12 +37,7 @@
 	CollectionData *collection;	/* NULL if from DupeWindow->files */
 	CollectInfo *info;
 
-	gchar *path;
-	const gchar *name;		/* we store the pointer into path for the name,
-					 * so that we only need to calculate this once,
-					 * which significantly speeds up comparing names */
-	gint64 size;
-	time_t date;
+	FileData *fd;
 
 	long checksum;
 	gchar *md5sum;
@@ -123,8 +118,8 @@
 void dupe_window_add_collection(DupeWindow *dw, CollectionData *collection);
 void dupe_window_add_files(DupeWindow *dw, GList *list, gint recurse);
 
-void dupe_maint_removed(const gchar *path);
-void dupe_maint_renamed(const gchar *source, const gchar *dest);
+void dupe_maint_removed(FileData *fd);
+void dupe_maint_renamed(FileData *fd);
 
 
 /* cell max with/height hack utility */
--- a/src/editors.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/editors.c	Tue Sep 11 20:06:29 2007 +0000
@@ -60,9 +60,9 @@
 	/* special slots */
 #if 1
 	/* for testing */
-	"External Copy command", "%vset -x;cp %f",
-	"External Move command", "%vset -x;mv %f",
-	"External Rename command", "%vset -x;mv %f",
+	"External Copy command", "%vset -x;cp %p %t",
+	"External Move command", "%vset -x;mv %p %t",
+	"External Rename command", "%vset -x;mv %p %t",
 	"External Delete command", "%vset -x;rm %f",
 	"External New Folder command", NULL
 #else
@@ -110,7 +110,7 @@
 {
 	EditorVerboseData *vd = data;
 
-	path_list_free(vd->list);
+	filelist_free(vd->list);
 	vd->list = NULL;
 
 	vd->count = 0;
@@ -334,14 +334,31 @@
 	return TRUE;
 }
 
-static gchar *editor_command_path_parse(const gchar *path)
+typedef enum {
+	PATH_FILE,
+	PATH_TARGET
+} PathType;
+
+
+static gchar *editor_command_path_parse(const FileData *fd, PathType type)
 {
 	GString *string;
 	gchar *pathl;
 	const gchar *p;
 
 	string = g_string_new("");
-	p = path;
+	
+	if (type == PATH_FILE)
+		{
+		p = fd->path;
+		}
+	else if (type == PATH_TARGET)
+		{
+		if (fd->change && fd->change->dest)
+			p = fd->change->dest;
+		else
+			p = "";
+		}
 	while (*p != '\0')
 		{
 		/* must escape \, ", `, and $ to avoid problems,
@@ -361,10 +378,10 @@
 	return pathl;
 }
 
-static gint editor_command_one(const gchar *template, const gchar *path, EditorVerboseData *vd)
+static gint editor_command_one(const gchar *template, const FileData *fd, EditorVerboseData *vd)
 {
 	GString *result = NULL;
-	gchar *pathl;
+	gchar *pathl, *targetl;
 	gchar *found;
 	const gchar *ptr;
 	gchar path_buffer[512];
@@ -375,16 +392,32 @@
 	current_path = getcwd(path_buffer, sizeof(path_buffer));
 
 	result = g_string_new("");
-	pathl = editor_command_path_parse(path);
+	pathl = editor_command_path_parse(fd, PATH_FILE);
+	targetl = editor_command_path_parse(fd, PATH_TARGET);
 
 	ptr = template;
-	while ( (found = strstr(ptr, "%p")) )
+	while ( (found = strstr(ptr, "%")) )
 		{
 		result = g_string_append_len(result, ptr, found - ptr);
 		ptr = found + 2;
-		result = g_string_append_c(result, '"');
-		result = g_string_append(result, pathl);
-		result = g_string_append_c(result, '"');
+		switch (found[1])
+			{
+			case 'p':
+				result = g_string_append_c(result, '"');
+				result = g_string_append(result, pathl);
+				result = g_string_append_c(result, '"');
+				break;
+			case 't':
+				result = g_string_append_c(result, '"');
+				result = g_string_append(result, targetl);
+				result = g_string_append_c(result, '"');
+				break;
+			case '%':
+				result = g_string_append_c(result, '%');
+				break;
+			default:
+				break;
+			}
 		}
 	result = g_string_append(result, ptr);
 
@@ -393,7 +426,7 @@
 	if (current_path)
 		{
 		gchar *base;
-		base = remove_level_from_path(path);
+		base = remove_level_from_path(fd->path);
 		if (chdir(base) == 0) path_change = TRUE;
 		g_free(base);
 		}
@@ -412,6 +445,7 @@
 
 	g_string_free(result, TRUE);
 	g_free(pathl);
+	g_free(targetl);
 
 	return ret;
 }
@@ -424,24 +458,24 @@
 
 	while (vd->list)
 		{
-		gchar *path;
+		FileData *fd;
 		gint success;
 
-		path = vd->list->data;
-		vd->list = g_list_remove(vd->list, path);
+		fd = vd->list->data;
+		vd->list = g_list_remove(vd->list, fd);
 
-		editor_verbose_window_progress(vd, path);
+		editor_verbose_window_progress(vd, fd->path);
 
 		vd->count++;
-		success = editor_command_one(vd->command_template, path, vd);
+		success = editor_command_one(vd->command_template, fd, vd);
 		if (success)
 			{
 			gtk_widget_set_sensitive(vd->button_stop, (vd->list != NULL) );
-			editor_verbose_window_fill(vd, path, strlen(path));
+			editor_verbose_window_fill(vd, fd->path, strlen(fd->path));
 			editor_verbose_window_fill(vd, "\n", 1);
 			}
 
-		g_free(path);
+		file_data_unref(fd);
 		if (success) return TRUE;
 		}
 
@@ -464,7 +498,7 @@
 	EditorVerboseData *vd;
 
 	vd = editor_verbose_window(template, text);
-	vd->list = path_list_copy(list);
+	vd->list = filelist_copy(list);
 	vd->total = g_list_length(list);
 
 	return editor_command_next(vd);
@@ -552,8 +586,8 @@
 			work = list;
 			while (work)
 				{
-				gchar *path = work->data;
-				ret = editor_command_one(template, path, NULL);
+				FileData *fd = work->data;
+				ret = editor_command_one(template, fd, NULL);
 				work = work->next;
 				}
 			}
@@ -572,12 +606,12 @@
 		work = list;
 		while (work)
 			{
-			gchar *path = work->data;
+			FileData *fd = work->data;
 			gchar *pathl;
 
 			if (work != list) g_string_append_c(result, ' ');
 			result = g_string_append_c(result, '"');
-			pathl = editor_command_path_parse(path);
+			pathl = editor_command_path_parse(fd, PATH_FILE);
 			result = g_string_append(result, pathl);
 			g_free(pathl);
 			result = g_string_append_c(result, '"');
@@ -610,7 +644,7 @@
 	return ret;
 }
 
-gint start_editor_from_path_list(gint n, GList *list)
+gint start_editor_from_filelist(gint n, GList *list)
 {
 	gchar *command;
 	gint ret;
@@ -625,15 +659,15 @@
 	return ret;
 }
 
-gint start_editor_from_file(gint n, const gchar *path)
+gint start_editor_from_file(gint n, FileData *fd)
 {
 	GList *list;
 	gint ret;
 
-	if (!path) return FALSE;
+	if (!fd) return FALSE;
 
-	list = g_list_append(NULL, (gchar *)path);
-	ret = start_editor_from_path_list(n, list);
+	list = g_list_append(NULL, fd);
+	ret = start_editor_from_filelist(n, list);
 	g_list_free(list);
 	return ret;
 }
@@ -648,7 +682,7 @@
 
 	list = g_list_append(NULL, (gchar *)source);
 	list = g_list_append(list, (gchar *)target);
-	ret = start_editor_from_path_list(n, list);
+	ret = start_editor_from_filelist(n, list);
 	g_list_free(list);
 	return ret;
 }
--- a/src/editors.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/editors.h	Tue Sep 11 20:06:29 2007 +0000
@@ -15,9 +15,8 @@
 
 
 void editor_reset_defaults(void);
-gint start_editor_from_file(gint n, const gchar *path);
-gint start_editor_from_path_list(gint n, GList *list);
-gint start_editor_from_pair(gint n, const gchar *source, const gchar *target);
+gint start_editor_from_file(gint n, FileData *fd);
+gint start_editor_from_file_list(gint n, GList *list);
 
 gint editor_window_flag_set(gint n);
 
--- a/src/exif.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/exif.c	Tue Sep 11 20:06:29 2007 +0000
@@ -67,6 +67,7 @@
 
 #include "intl.h"
 
+#include "gqview.h"
 #include "exif.h"
 
 #include "format_raw.h"
@@ -1181,16 +1182,16 @@
 	g_free(exif);
 }
 
-ExifData *exif_read(const gchar *path, gint parse_color_profile)
+ExifData *exif_read(FileData *fd, gint parse_color_profile)
 {
 	ExifData *exif;
 	void *f;
 	int size, res;
 	gchar *pathl;
 
-	if (!path) return NULL;
+	if (!fd) return NULL;
 
-	pathl = path_from_utf8(path);
+	pathl = path_from_utf8(fd->path);
 	if (map_file(pathl, &f, &size) == -1)
 		{
 		g_free(pathl);
--- a/src/exif.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/exif.h	Tue Sep 11 20:06:29 2007 +0000
@@ -176,7 +176,7 @@
  *-----------------------------------------------------------------------------
  */
 
-ExifData *exif_read(const gchar *path, gint parse_color_profile);
+ExifData *exif_read(FileData *fd, gint parse_color_profile);
 void exif_free(ExifData *exif);
 
 gchar *exif_get_data_as_text(ExifData *exif, const gchar *key);
--- a/src/filelist.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/filelist.c	Tue Sep 11 20:06:29 2007 +0000
@@ -571,34 +571,96 @@
 SidecarFileData *sidecar_file_data_new_from_file_data(const FileData *fd);
 void sidecar_file_data_free(SidecarFileData *fd);
 
+static void file_data_set_path(FileData *fd, const gchar *path)
+{
 
-FileData *file_data_new(const gchar *path, struct stat *st)
+	if (strcmp(path, "/") == 0)
+		{
+		fd->path = g_strdup(path);
+		fd->name = fd->path;
+		fd->extension = fd->name + 1;
+		return;
+		}
+
+	fd->path = g_strdup(path);
+	fd->name = filename_from_path(fd->path);
+
+	if (strcmp(fd->name, "..") == 0)
+		{
+		gchar *dir = remove_level_from_path(path); 
+		g_free(fd->path);
+		fd->path = remove_level_from_path(dir);
+		g_free(dir);
+		fd->name = "..";
+		fd->extension = fd->name + 2;
+		return;		
+		}
+	else if (strcmp(fd->name, ".") == 0)
+		{
+		g_free(fd->path);
+		fd->path = remove_level_from_path(path);
+		fd->name = ".";
+		fd->extension = fd->name + 1;
+		return;
+		}
+
+	fd->extension = extension_from_path(fd->path);
+}
+
+static GHashTable *file_data_pool = NULL;
+
+FileData *file_data_new(const gchar *path_utf8, struct stat *st)
 {
 	FileData *fd;
 
+	printf("file_data_new: '%s'\n", path_utf8);
+	
+	if (!file_data_pool)
+		file_data_pool = g_hash_table_new (g_str_hash, g_str_equal);
+	
+	fd = g_hash_table_lookup(file_data_pool, path_utf8);
+	if (fd)
+		{
+		printf("file_data_pool hit: '%s'\n", fd->path);
+		return file_data_ref(fd);
+		}
+	
 	fd = g_new0(FileData, 1);
-	fd->path = path_to_utf8(path);
-	fd->name = filename_from_path(fd->path);
-	fd->extension = extension_from_path(fd->path);
 
+	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;
 	fd->sidecar_files = NULL;
+	fd->ref = 1;
+	fd->magick = 0x12345678;
+	
+	g_hash_table_insert(file_data_pool, fd->original_path, fd);
+	
 	return fd;
 }
 
-FileData *file_data_new_simple(const gchar *path)
+FileData *file_data_new_local(const gchar *path, struct stat *st)
+{
+	gchar *path_utf8 = path_to_utf8(path);
+	FileData *ret = file_data_new(path_utf8, st);
+	g_free(path_utf8);
+	return ret;
+}
+
+FileData *file_data_new_simple(const gchar *path_utf8)
 {
 	struct stat st;
 
-	if (!stat(path, &st))
+	if (!stat_utf8(path_utf8, &st))
 		{
 		st.st_size = 0;
 		st.st_mtime = 0;
 		}
 
-	return file_data_new(path, &st);
+	return file_data_new(path_utf8, &st);
 }
 
 FileData *file_data_add_sidecar_file(FileData *target, SidecarFileData *sfd)
@@ -625,7 +687,14 @@
 void file_data_free(FileData *fd)
 {
 	GList *work;
+
+	g_assert(fd->magick == 0x12345678);
+	g_assert(fd->ref == 0 || fd->ref == 1);
+	
+	g_hash_table_remove(file_data_pool, fd->original_path);
+
 	g_free(fd->path);
+	g_free(fd->original_path);
 	if (fd->pixbuf) g_object_unref(fd->pixbuf);
 
 	work = fd->sidecar_files;
@@ -636,10 +705,29 @@
 		}
 
 	g_list_free(fd->sidecar_files);
-	
+
+	file_data_change_info_free(NULL, fd);	
 	g_free(fd);
 }
 
+FileData *file_data_ref(FileData *fd)
+{
+	if (fd == NULL) return NULL;
+
+//	return g_memdup(fd, sizeof(FileData));
+	g_assert(fd->magick == 0x12345678);
+	fd->ref++;
+	return fd;
+}
+void file_data_unref(FileData *fd)
+{
+	if (fd == NULL) return;
+	g_assert(fd->magick == 0x12345678);
+	fd->ref--;
+	if (fd->ref == 0)
+		file_data_free(fd);
+}
+
 /* compare name without extension */
 gint file_data_compare_name_without_ext(FileData *fd1, FileData *fd2)
 {
@@ -652,6 +740,53 @@
 	return strncmp(fd1->name, fd2->name, len1);
 }
 
+FileData *file_data_do_change(FileData *fd)
+{
+	g_assert(fd->change);
+	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);
+
+}
+
+FileDataChangeInfo *file_data_change_info_new(const gchar *src, const gchar *dest, FileData *fd)
+{
+	FileDataChangeInfo *fdci = g_new0(FileDataChangeInfo, 1);
+
+	if (src)
+		fdci->source = g_strdup(src);
+	if (dest)
+		fdci->dest = g_strdup(dest);
+		
+	if (fd)
+		{
+		if (fd->change)
+			file_data_change_info_free(fd->change, NULL);
+		fd->change = fdci;
+		}
+	return fdci;
+}
+
+void file_data_change_info_free(FileDataChangeInfo *fdci, FileData *fd)
+{
+	if (!fdci && fd)
+		fdci = fd->change;
+	
+	if (!fdci)
+		return;
+	
+	g_free(fdci->source);
+	g_free(fdci->dest);
+	
+	g_free(fdci);
+	
+	if (fd)
+		fd->change = NULL;
+}
+	
 /*
  *-----------------------------------------------------------------------------
  * sidecar file info struct
@@ -738,15 +873,14 @@
 static SortType filelist_sort_method = SORT_NONE;
 static gint filelist_sort_ascend = TRUE;
 
-static gint sort_file_cb(void *a, void *b)
+
+gint filelist_sort_compare_filedata(FileData *fa, FileData *fb)
 {
-	FileData *fa = a;
-	FileData *fb = b;
-
 	if (!filelist_sort_ascend)
 		{
-		fa = b;
-		fb = a;
+		FileData *tmp = fa;
+		fa = fb;
+		fb = tmp;
 		}
 
 	switch (filelist_sort_method)
@@ -773,22 +907,37 @@
 		}
 }
 
-GList *filelist_sort(GList *list, SortType method, gint ascend)
+static gint filelist_sort_file_cb(void *a, void *b)
+{
+	return filelist_sort_compare_filedata(a, b);
+}
+
+GList *filelist_sort_full(GList *list, SortType method, gint ascend, GCompareFunc cb)
 {
 	filelist_sort_method = method;
 	filelist_sort_ascend = ascend;
-	return g_list_sort(list, (GCompareFunc) sort_file_cb);
+	return g_list_sort(list, cb);
+}
+
+GList *filelist_insert_sort_full(GList *list, void *data, SortType method, gint ascend, GCompareFunc cb)
+{
+	filelist_sort_method = method;
+	filelist_sort_ascend = ascend;
+	return g_list_insert_sorted(list, data, cb);
+}
+
+GList *filelist_sort(GList *list, SortType method, gint ascend)
+{
+	return filelist_sort_full(list, method, ascend, (GCompareFunc) filelist_sort_file_cb);
 }
 
 GList *filelist_insert_sort(GList *list, FileData *fd, SortType method, gint ascend)
 {
-	filelist_sort_method = method;
-	filelist_sort_ascend = ascend;
-	return g_list_insert_sorted(list, fd, (GCompareFunc) sort_file_cb);
+	return filelist_insert_sort_full(list, fd, method, ascend, (GCompareFunc) filelist_sort_file_cb);
 }
 
 
-gint filelist_read(const gchar *path, GList **files, GList **dirs)
+static gint filelist_read_real(const gchar *path, GList **files, GList **dirs, gint follow_symlinks)
 {
 	DIR *dp;
 	struct dirent *dir;
@@ -822,7 +971,9 @@
 		if (show_dot_files || !ishidden(name))
 			{
 			gchar *filepath = g_strconcat(pathl, "/", name, NULL);
-			if (stat(filepath, &ent_sbuf) >= 0)
+			if ((follow_symlinks ? 
+				stat(filepath, &ent_sbuf) :
+				lstat(filepath, &ent_sbuf)) >= 0)
 				{
 				if (S_ISDIR(ent_sbuf.st_mode))
 					{
@@ -833,16 +984,16 @@
 					    strcmp(name, GQVIEW_CACHE_LOCAL_METADATA) != 0 &&
 					    strcmp(name, THUMB_FOLDER_LOCAL) != 0)
 						{
-						dlist = g_list_prepend(dlist, file_data_new(filepath, &ent_sbuf));
+						dlist = g_list_prepend(dlist, file_data_new_local(filepath, &ent_sbuf));
 						}
 					}
 				else
 					{
 					if ((files) && filter_name_exists(name))
 						{
-						FileData *fd = file_data_new(filepath, &ent_sbuf);
+						FileData *fd = file_data_new_local(filepath, &ent_sbuf);
 						
-						GList *same = g_list_find_custom(flist, fd, file_data_compare_name_without_ext);
+						GList *same = g_list_find_custom(flist, fd, (GCompareFunc) file_data_compare_name_without_ext);
 						
 						int p1 = 0; 
 						int p2 = 0; 
@@ -888,6 +1039,16 @@
 	return TRUE;
 }
 
+gint filelist_read(const gchar *path, GList **files, GList **dirs)
+{
+	return filelist_read_real(path, files, dirs, TRUE);
+}
+
+gint filelist_read_lstat(const gchar *path, GList **files, GList **dirs)
+{
+	return filelist_read_real(path, files, dirs, FALSE);
+}
+
 void filelist_free(GList *list)
 {
 	GList *work;
@@ -895,7 +1056,7 @@
 	work = list;
 	while (work)
 		{
-		file_data_free((FileData *)work->data);
+		file_data_unref((FileData *)work->data);
 		work = work->next;
 		}
 
@@ -903,3 +1064,152 @@
 }
 
 
+GList *filelist_copy(GList *list)
+{
+	GList *new_list = NULL;
+	GList *work;
+
+	work = list;
+	while (work)
+		{
+		FileData *fd;
+ 
+		fd = work->data;
+		work = work->next;
+ 
+		new_list = g_list_prepend(new_list, file_data_ref(fd));
+		}
+ 
+	return g_list_reverse(new_list);
+}
+
+GList *filelist_from_path_list(GList *list)
+{
+	GList *new_list = NULL;
+	GList *work;
+
+	work = list;
+	while (work)
+		{
+		gchar *path;
+ 
+		path = work->data;
+		work = work->next;
+ 
+		new_list = g_list_prepend(new_list, file_data_new_simple(path));
+		}
+ 
+	return g_list_reverse(new_list);
+}
+
+GList *filelist_to_path_list(GList *list)
+{
+	GList *new_list = NULL;
+	GList *work;
+
+	work = list;
+	while (work)
+		{
+		FileData *fd;
+ 
+		fd = work->data;
+		work = work->next;
+ 
+		new_list = g_list_prepend(new_list, g_strdup(fd->path));
+		}
+ 
+	return g_list_reverse(new_list);
+}
+
+GList *filelist_filter(GList *list, gint is_dir_list)
+{
+	GList *work;
+
+	if (!is_dir_list && file_filter_disable && show_dot_files) return list;
+
+	work = list;
+	while (work)
+		{
+		FileData *fd = (FileData *)(work->data);
+		const gchar *name = fd->name;
+
+		if ((!show_dot_files && ishidden(name)) ||
+		    (!is_dir_list && !filter_name_exists(name)) ||
+		    (is_dir_list && name[0] == '.' && (strcmp(name, GQVIEW_CACHE_LOCAL_THUMB) == 0 ||
+						       strcmp(name, GQVIEW_CACHE_LOCAL_METADATA) == 0)) )
+			{
+			GList *link = work;
+			work = work->next;
+			list = g_list_remove_link(list, link);
+			file_data_unref(fd);
+			g_list_free(link);
+			}
+		else
+			{
+			work = work->next;
+			}
+		}
+
+	return list;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * filelist recursive
+ *-----------------------------------------------------------------------------
+ */
+
+static gint filelist_sort_path_cb(gconstpointer a, gconstpointer b)
+{
+	return CASE_SORT(((FileData *)a)->path, ((FileData *)b)->path);
+}
+
+GList *filelist_sort_path(GList *list)
+{
+	return g_list_sort(list, filelist_sort_path_cb);
+}
+
+static void filelist_recursive_append(GList **list, GList *dirs)
+{
+	GList *work;
+
+	work = dirs;
+	while (work)
+		{
+		FileData *fd = (FileData *)(work->data);
+		const gchar *path = fd->path;
+		GList *f = NULL;
+		GList *d = NULL;
+
+		if (filelist_read(path, &f, &d))
+			{
+			f = filelist_filter(f, FALSE);
+			f = filelist_sort_path(f);
+			*list = g_list_concat(*list, f);
+
+			d = filelist_filter(d, TRUE);
+			d = filelist_sort_path(d);
+			filelist_recursive_append(list, d);
+			filelist_free(d);
+			}
+
+		work = work->next;
+		}
+}
+
+GList *filelist_recursive(const gchar *path)
+{
+	GList *list = NULL;
+	GList *d = NULL;
+
+	if (!filelist_read(path, &list, &d)) return NULL;
+	list = filelist_filter(list, FALSE);
+	list = filelist_sort_path(list);
+
+	d = filelist_filter(d, TRUE);
+	d = filelist_sort_path(d);
+	filelist_recursive_append(&list, d);
+	filelist_free(d);
+
+	return list;
+}
--- a/src/filelist.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/filelist.h	Tue Sep 11 20:06:29 2007 +0000
@@ -50,16 +50,36 @@
 const gchar *text_from_time(time_t t);
 
 /* this expects a locale encoded path */
-FileData *file_data_new(const gchar *path, struct stat *st);
+FileData *file_data_new_local(const gchar *path, struct stat *st);
+/* this expects a utf-8 path */
+FileData *file_data_new(const gchar *path_utf8, struct stat *st);
 /* this expects a utf-8 path */
-FileData *file_data_new_simple(const gchar *path);
+FileData *file_data_new_simple(const gchar *path_utf8);
 void file_data_free(FileData *fd);
+FileData *file_data_ref(FileData *fd);
+void file_data_unref(FileData *fd);
 
+FileData *file_data_do_change(FileData *fd);
+FileDataChangeInfo *file_data_change_info_new(const gchar *src, const gchar *dest, FileData *fd);
+void file_data_change_info_free(FileDataChangeInfo *fdci, FileData *fd);
+
+gint filelist_sort_compare_filedata(FileData *fa, FileData *fb);
 GList *filelist_sort(GList *list, SortType method, gint ascend);
 GList *filelist_insert_sort(GList *list, FileData *fd, SortType method, gint ascend);
+GList *filelist_sort_full(GList *list, SortType method, gint ascend, GCompareFunc cb);
+GList *filelist_insert_sort_full(GList *list, void *data, SortType method, gint ascend, GCompareFunc cb);
 
 gint filelist_read(const gchar *path, GList **files, GList **dirs);
+gint filelist_read_lstat(const gchar *path, GList **files, GList **dirs);
 void filelist_free(GList *list);
+GList *filelist_copy(GList *list);
+GList *filelist_from_path_list(GList *list);
+GList *filelist_to_path_list(GList *list);
+
+GList *filelist_filter(GList *list, gint is_dir_list);
+
+GList *filelist_sort_path(GList *list);
+GList *filelist_recursive(const gchar *path);
 
 #endif
 
--- a/src/format_canon.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/format_canon.c	Tue Sep 11 20:06:29 2007 +0000
@@ -28,6 +28,7 @@
 
 #include "intl.h"
 
+#include "gqview.h"
 #include "format_canon.h"
 #include "format_raw.h"
 
--- a/src/format_fuji.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/format_fuji.c	Tue Sep 11 20:06:29 2007 +0000
@@ -23,6 +23,7 @@
 
 #include "intl.h"
 
+#include "gqview.h"
 #include "format_fuji.h"
 #include "format_raw.h"
 
--- a/src/format_nikon.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/format_nikon.c	Tue Sep 11 20:06:29 2007 +0000
@@ -24,6 +24,7 @@
 
 #include "intl.h"
 
+#include "gqview.h"
 #include "format_nikon.h"
 
 #include "exif.h"
--- a/src/format_olympus.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/format_olympus.c	Tue Sep 11 20:06:29 2007 +0000
@@ -20,6 +20,7 @@
 
 #include "intl.h"
 
+#include "gqview.h"
 #include "format_olympus.h"
 #include "format_raw.h"
 
--- a/src/format_raw.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/format_raw.c	Tue Sep 11 20:06:29 2007 +0000
@@ -26,6 +26,7 @@
 
 #include "intl.h"
 
+#include "gqview.h"
 #include "format_raw.h"
 
 #include "format_canon.h"
--- a/src/format_raw.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/format_raw.h	Tue Sep 11 20:06:29 2007 +0000
@@ -13,7 +13,6 @@
 #ifndef __FORMAT_RAW_H
 #define __FORMAT_RAW_H
 
-
 #include "exif.h"
 
 
--- a/src/fullscreen.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/fullscreen.c	Tue Sep 11 20:06:29 2007 +0000
@@ -327,7 +327,7 @@
 #ifdef HIDE_WINDOW_IN_FULLSCREEN
 	gtk_widget_hide(fs->normal_window);
 #endif
-	image_change_path(fs->normal_imd, NULL, image_zoom_get(fs->normal_imd));
+	image_change_fd(fs->normal_imd, NULL, image_zoom_get(fs->normal_imd));
 
 	return fs;
 }
--- a/src/image-load.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/image-load.c	Tue Sep 11 20:06:29 2007 +0000
@@ -12,6 +12,7 @@
 
 #include "gqview.h"
 #include "image-load.h"
+#include "filelist.h"
 
 #include "format_raw.h"
 #include "ui_fileops.h"
@@ -25,6 +26,13 @@
 /* the number of bytes to read per idle call (define x IMAGE_LOADER_BUFFER_SIZE) */
 #define IMAGE_LOADER_BUFFER_DEFAULT_COUNT 1
 
+static const gchar *image_loader_path(ImageLoader *il)
+{
+	if (il->fd)
+		return il->fd->path;
+	return il->path;
+}
+
 static void image_loader_sync_pixbuf(ImageLoader *il)
 {
 	GdkPixbuf *pb;
@@ -161,7 +169,7 @@
 {
 	image_loader_stop(il);
 
-	if (debug) printf("pixbuf_loader reported load error for: %s\n", il->path);
+	if (debug) printf("pixbuf_loader reported load error for: %s\n", image_loader_path(il));
 
 	if (il->func_error) il->func_error(il, il->data_error);
 }
@@ -218,9 +226,9 @@
 	b = read(il->load_fd, &buf, sizeof(buf));
 
 	if (b > 0 &&
-	    format_raw_img_exif_offsets_fd(il->load_fd, il->path, buf, b, &offset, NULL))
+	    format_raw_img_exif_offsets_fd(il->load_fd, image_loader_path(il), buf, b, &offset, NULL))
 		{
-		if (debug) printf("Raw file %s contains embedded image\n", il->path);
+		if (debug) printf("Raw file %s contains embedded image\n", image_loader_path(il));
 
 		b = read(il->load_fd, &buf, sizeof(buf));
 		}
@@ -282,7 +290,7 @@
 
 	if (!il || il->load_fd != -1 || il->loader) return FALSE;
 
-	pathl = path_from_utf8(il->path);
+	pathl = path_from_utf8(image_loader_path(il));
 	il->load_fd = open(pathl, O_RDONLY | O_NONBLOCK);
 	g_free(pathl);
 	if (il->load_fd == -1) return FALSE;
@@ -303,13 +311,14 @@
 	return image_loader_begin(il);
 }
 
-ImageLoader *image_loader_new(const gchar *path)
+static ImageLoader *image_loader_new_real(FileData *fd, const gchar *path)
 {
 	ImageLoader *il;
 
-	if (!path) return NULL;
+	if (!fd && !path) return NULL;
 
 	il = g_new0(ImageLoader, 1);
+	if (fd) il->fd = file_data_ref(fd);
 	if (path) il->path = g_strdup(path);
 	il->pixbuf = NULL;
 	il->idle_id = -1;
@@ -332,6 +341,16 @@
 	return il;
 }
 
+ImageLoader *image_loader_new(FileData *fd)
+{
+	return image_loader_new_real(fd, NULL);
+}
+
+ImageLoader *image_loader_new_from_path(const gchar *path)
+{
+	return image_loader_new_real(NULL, path);
+}
+
 void image_loader_free(ImageLoader *il)
 {
 	if (!il) return;
@@ -339,7 +358,8 @@
 	image_loader_stop(il);
 	if (il->idle_done_id != -1) g_source_remove(il->idle_done_id);
 	if (il->pixbuf) gdk_pixbuf_unref(il->pixbuf);
-	g_free(il->path);
+	if (il->fd) file_data_unref(il->fd);
+	if (il->path) g_free(il->path);
 	g_free(il);
 }
 
@@ -428,7 +448,7 @@
 {
 	if (!il) return FALSE;
 
-	if (!il->path) return FALSE;
+	if (!image_loader_path(il)) return FALSE;
 
 	il->func_done = func_done;
 	il->data_done = data_done;
@@ -450,12 +470,12 @@
 	return il->done;
 }
 
-gint image_load_dimensions(const gchar *path, gint *width, gint *height)
+gint image_load_dimensions(FileData *fd, gint *width, gint *height)
 {
 	ImageLoader *il;
 	gint success;
 
-	il = image_loader_new(path);
+	il = image_loader_new(fd);
 
 	success = image_loader_start(il, NULL, NULL);
 
--- a/src/image-load.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/image-load.h	Tue Sep 11 20:06:29 2007 +0000
@@ -14,7 +14,10 @@
 #define IMAGE_LOAD_H
 
 
-ImageLoader *image_loader_new(const gchar *path);
+ImageLoader *image_loader_new(FileData *fd);
+
+/* we don't want full FileData for thumbnails */
+ImageLoader *image_loader_new_from_path(const gchar *path);
 void image_loader_free(ImageLoader *il);
 
 void image_loader_set_area_ready_func(ImageLoader *il,
@@ -48,7 +51,7 @@
 gdouble image_loader_get_percent(ImageLoader *il);
 gint image_loader_get_is_done(ImageLoader *il);
 
-gint image_load_dimensions(const gchar *path, gint *width, gint *height);
+gint image_load_dimensions(FileData *fd, gint *width, gint *height);
 
 #endif
 
--- a/src/image.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/image.c	Tue Sep 11 20:06:29 2007 +0000
@@ -22,6 +22,8 @@
 #include "pixbuf_util.h"
 #include "ui_fileops.h"
 
+#include "filelist.h"
+
 #include <math.h>
 
 
@@ -113,7 +115,7 @@
 	if (imd->il && image_get_pixbuf(imd) != image_loader_get_pixbuf(imd->il)) return;
 
 	if (debug) printf("image load completed \"%s\" (%s)\n",
-			  (preload) ? imd->read_ahead_path : imd->image_path,
+			  (preload) ? imd->read_ahead_fd->path : imd->image_fd->path,
 			  (preload) ? "preload" : "current");
 
 	if (!preload) imd->completed = TRUE;
@@ -177,10 +179,10 @@
 
 	title = g_strdup_printf("%s%s%s%s%s%s",
 		imd->title ? imd->title : "",
-		imd->image_name ? imd->image_name : "",
+		imd->image_fd ? imd->image_fd->name : "",
 		zoom ? zoom : "",
 		collection ? collection : "",
-		imd->image_name ? " - " : "",
+		imd->image_fd ? " - " : "",
 		imd->title_right ? imd->title_right : "");
 
 	gtk_window_set_title(GTK_WINDOW(imd->top_window), title);
@@ -418,7 +420,7 @@
 	if (exif_rotate_enable ||
 	    (imd->color_profile_enable && imd->color_profile_use_image) )
 		{
-		exif = exif_read(imd->image_path, (imd->color_profile_enable && imd->color_profile_use_image));
+		exif = exif_read(imd->image_fd, (imd->color_profile_enable && imd->color_profile_use_image));
 		}
 
 	if (exif_rotate_enable && exif)
@@ -504,7 +506,7 @@
 
 static void image_read_ahead_cancel(ImageWindow *imd)
 {
-	if (debug) printf("read ahead cancelled for :%s\n", imd->read_ahead_path);
+	if (debug) printf("read ahead cancelled for :%s\n", imd->read_ahead_fd->path);
 
 	image_loader_free(imd->read_ahead_il);
 	imd->read_ahead_il = NULL;
@@ -512,15 +514,15 @@
 	if (imd->read_ahead_pixbuf) g_object_unref(imd->read_ahead_pixbuf);
 	imd->read_ahead_pixbuf = NULL;
 
-	g_free(imd->read_ahead_path);
-	imd->read_ahead_path = NULL;
+	file_data_unref(imd->read_ahead_fd);
+	imd->read_ahead_fd = NULL;
 }
 
 static void image_read_ahead_done_cb(ImageLoader *il, gpointer data)
 {
 	ImageWindow *imd = data;
 
-	if (debug) printf("read ahead done for :%s\n", imd->read_ahead_path);
+	if (debug) printf("read ahead done for :%s\n", imd->read_ahead_fd->path);
 
 	imd->read_ahead_pixbuf = image_loader_get_pixbuf(imd->read_ahead_il);
 	if (imd->read_ahead_pixbuf)
@@ -546,14 +548,14 @@
 static void image_read_ahead_start(ImageWindow *imd)
 {
 	/* already started ? */
-	if (!imd->read_ahead_path || imd->read_ahead_il || imd->read_ahead_pixbuf) return;
+	if (!imd->read_ahead_fd || imd->read_ahead_il || imd->read_ahead_pixbuf) return;
 
 	/* still loading ?, do later */
 	if (imd->il || imd->cm) return;
 
-	if (debug) printf("read ahead started for :%s\n", imd->read_ahead_path);
+	if (debug) printf("read ahead started for :%s\n", imd->read_ahead_fd->path);
 
-	imd->read_ahead_il = image_loader_new(imd->read_ahead_path);
+	imd->read_ahead_il = image_loader_new(imd->read_ahead_fd);
 
 	image_loader_set_error_func(imd->read_ahead_il, image_read_ahead_error_cb, imd);
 	if (!image_loader_start(imd->read_ahead_il, image_read_ahead_done_cb, imd))
@@ -563,15 +565,15 @@
 		}
 }
 
-static void image_read_ahead_set(ImageWindow *imd, const gchar *path)
+static void image_read_ahead_set(ImageWindow *imd, FileData *fd)
 {
-	if (imd->read_ahead_path && path && strcmp(imd->read_ahead_path, path) == 0) return;
+	if (imd->read_ahead_fd && fd && imd->read_ahead_fd == fd) return;
 
 	image_read_ahead_cancel(imd);
 
-	imd->read_ahead_path = g_strdup(path);
+	imd->read_ahead_fd = file_data_ref(fd);
 
-	if (debug) printf("read ahead set to :%s\n", imd->read_ahead_path);
+	if (debug) printf("read ahead set to :%s\n", imd->read_ahead_fd->path);
 
 	image_read_ahead_start(imd);
 }
@@ -582,14 +584,14 @@
  *-------------------------------------------------------------------
  */
 
-static void image_post_buffer_set(ImageWindow *imd, const gchar *path, GdkPixbuf *pixbuf, gint color_row)
+static void image_post_buffer_set(ImageWindow *imd, FileData *fd, GdkPixbuf *pixbuf, gint color_row)
 {
-	g_free(imd->prev_path);
+	file_data_unref(imd->prev_fd);
 	if (imd->prev_pixbuf) g_object_unref(imd->prev_pixbuf);
 
-	if (path && pixbuf)
+	if (fd && pixbuf)
 		{
-		imd->prev_path = g_strdup(path);
+		imd->prev_fd = file_data_ref(fd);
 			
 		g_object_ref(pixbuf);
 		imd->prev_pixbuf = pixbuf;
@@ -597,12 +599,12 @@
 		}
 	else
 		{
-		imd->prev_path = NULL;
+		imd->prev_fd = NULL;
 		imd->prev_pixbuf = NULL;
 		imd->prev_color_row = -1;
 		}
 
-	if (debug) printf("post buffer set: %s\n", path);
+	if (debug) printf("post buffer set: %s\n", fd->path);
 }
 
 static gint image_post_buffer_get(ImageWindow *imd)
@@ -610,14 +612,14 @@
 	gint success;
 
 	if (imd->prev_pixbuf &&
-	    imd->image_path && imd->prev_path && strcmp(imd->image_path, imd->prev_path) == 0)
+	    imd->image_fd && imd->prev_fd && imd->image_fd == imd->prev_fd)
 		{
 		image_change_pixbuf(imd, imd->prev_pixbuf, image_zoom_get(imd));
 		if (imd->prev_color_row >= 0)
 			{
 			ExifData *exif = NULL;
 
-			if (imd->color_profile_use_image) exif = exif_read(imd->image_path, TRUE);
+			if (imd->color_profile_use_image) exif = exif_read(imd->image_fd, TRUE);
 			image_post_process_color(imd, imd->prev_color_row, exif);
 			exif_free(exif);
 			}
@@ -631,8 +633,8 @@
 	if (imd->prev_pixbuf) g_object_unref(imd->prev_pixbuf);
 	imd->prev_pixbuf = NULL;
 
-	g_free(imd->prev_path);
-	imd->prev_path = NULL;
+	file_data_unref(imd->prev_fd);
+	imd->prev_fd = NULL;
 
 	return success;
 }
@@ -720,10 +722,10 @@
 
 static gint image_read_ahead_check(ImageWindow *imd)
 {
-	if (!imd->read_ahead_path) return FALSE;
+	if (!imd->read_ahead_fd) return FALSE;
 	if (imd->il) return FALSE;
 
-	if (!imd->image_path || strcmp(imd->read_ahead_path, imd->image_path) != 0)
+	if (!imd->image_fd || imd->read_ahead_fd != imd->image_fd)
 		{
 		image_read_ahead_cancel(imd);
 		return FALSE;
@@ -773,7 +775,7 @@
 	return FALSE;
 }
 
-static gint image_load_begin(ImageWindow *imd, const gchar *path)
+static gint image_load_begin(ImageWindow *imd, FileData *fd)
 {
 	if (debug) printf ("image begin \n");
 
@@ -784,13 +786,13 @@
 
 	if (image_post_buffer_get(imd))
 		{
-		if (debug) printf("from post buffer: %s\n", imd->image_path);
+		if (debug) printf("from post buffer: %s\n", imd->image_fd->path);
 		return TRUE;
 		}
 
 	if (image_read_ahead_check(imd))
 		{
-		if (debug) printf("from read ahead buffer: %s\n", imd->image_path);
+		if (debug) printf("from read ahead buffer: %s\n", imd->image_fd->path);
 		return TRUE;
 		}
 
@@ -805,7 +807,7 @@
 
 	g_object_set(G_OBJECT(imd->pr), "loading", TRUE, NULL);
 
-	imd->il = image_loader_new(path);
+	imd->il = image_loader_new(fd);
 
 	image_loader_set_area_ready_func(imd->il, image_load_area_cb, imd);
 	image_loader_set_error_func(imd->il, image_load_error_cb, imd);
@@ -865,14 +867,14 @@
 {
 	image_reset(imd);
 
-	if (imd->image_path && isfile(imd->image_path))
+	if (imd->image_fd && isfile(imd->image_fd->path))
 		{
 		PixbufRenderer *pr;
 
 		pr = PIXBUF_RENDERER(imd->pr);
 		pr->zoom = zoom;	/* store the zoom, needed by the loader */
 
-		if (image_load_begin(imd, imd->image_path))
+		if (image_load_begin(imd, imd->image_fd))
 			{
 			imd->unknown = FALSE;
 			}
@@ -886,19 +888,19 @@
 
 			imd->unknown = TRUE;
 			}
-		imd->size = filesize(imd->image_path);
-		imd->mtime = filetime(imd->image_path);
+		imd->size = filesize(imd->image_fd->path);
+		imd->mtime = filetime(imd->image_fd->path);
 		}
 	else
 		{
-		if (imd->image_path)
+		if (imd->image_fd)
 			{
 			GdkPixbuf *pixbuf;
 
 			pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN);
 			image_change_pixbuf(imd, pixbuf, zoom);
 			g_object_unref(pixbuf);
-			imd->mtime = filetime(imd->image_path);
+			imd->mtime = filetime(imd->image_fd->path);
 			}
 		else
 			{
@@ -912,12 +914,12 @@
 	image_update_util(imd);
 }
 
-static void image_change_real(ImageWindow *imd, const gchar *path,
+static void image_change_real(ImageWindow *imd, FileData *fd,
 			      CollectionData *cd, CollectInfo *info, gdouble zoom)
 {
 	GdkPixbuf *pixbuf;
 	GdkPixbuf *prev_pixbuf = NULL;
-	gchar *prev_path = NULL;
+	FileData *prev_fd = NULL;
 	gint prev_clear = FALSE;
 	gint prev_color_row = -1;
 
@@ -926,7 +928,7 @@
 
 	pixbuf = image_get_pixbuf(imd);
 
-	if (enable_read_ahead && imd->image_path && pixbuf)
+	if (enable_read_ahead && imd->image_fd && pixbuf)
 		{
 		if (imd->il)
 			{
@@ -935,7 +937,7 @@
 			}
 		else
 			{
-			prev_path = g_strdup(imd->image_path);
+			prev_fd = file_data_ref(imd->image_fd);
 			prev_pixbuf = pixbuf;
 			g_object_ref(prev_pixbuf);
 
@@ -949,16 +951,15 @@
 			}
 		}
 
-	g_free(imd->image_path);
-	imd->image_path = g_strdup(path);
-	imd->image_name = filename_from_path(imd->image_path);
+	file_data_unref(imd->image_fd);
+	imd->image_fd = file_data_ref(fd);
 
 	image_change_complete(imd, zoom, TRUE);
 
 	if (prev_pixbuf)
 		{
-		image_post_buffer_set(imd, prev_path, prev_pixbuf, prev_color_row);
-		g_free(prev_path);
+		image_post_buffer_set(imd, prev_fd, prev_pixbuf, prev_color_row);
+		file_data_unref(prev_fd);
 		g_object_unref(prev_pixbuf);
 		}
 	else if (prev_clear)
@@ -1147,20 +1148,26 @@
 
 const gchar *image_get_path(ImageWindow *imd)
 {
-	return imd->image_path;
+	if (imd->image_fd == NULL) return NULL;
+	return imd->image_fd->path;
 }
 
 const gchar *image_get_name(ImageWindow *imd)
 {
-	return imd->image_name;
+	if (imd->image_fd == NULL) return NULL;
+	return imd->image_fd->name;
+}
+
+FileData *image_get_fd(ImageWindow *imd)
+{
+	return imd->image_fd;
 }
 
 /* merely changes path string, does not change the image! */
-void image_set_path(ImageWindow *imd, const gchar *newpath)
+void image_set_fd(ImageWindow *imd, FileData *fd)
 {
-	g_free(imd->image_path);
-	imd->image_path = g_strdup(newpath);
-	imd->image_name = filename_from_path(imd->image_path);
+	file_data_unref(imd->image_fd);
+	imd->image_fd = file_data_ref(fd);
 
 	image_update_title(imd);
 	image_state_set(imd, IMAGE_STATE_IMAGE);
@@ -1168,12 +1175,11 @@
 
 /* load a new image */
 
-void image_change_path(ImageWindow *imd, const gchar *path, gdouble zoom)
+void image_change_fd(ImageWindow *imd, FileData *fd, gdouble zoom)
 {
-	if (imd->image_path == path ||
-	    (path && imd->image_path && !strcmp(path, imd->image_path)) ) return;
+	if (imd->image_fd == fd) return;
 
-	image_change_real(imd, path, NULL, NULL, zoom);
+	image_change_real(imd, fd, NULL, NULL, zoom);
 }
 
 GdkPixbuf *image_get_pixbuf(ImageWindow *imd)
@@ -1191,7 +1197,7 @@
 {
 	if (!cd || !info || !g_list_find(cd->list, info)) return;
 
-	image_change_real(imd, info->path, cd, info, zoom);
+	image_change_real(imd, info->fd, cd, info, zoom);
 }
 
 CollectionData *image_get_collection(ImageWindow *imd, CollectInfo **info)
@@ -1237,7 +1243,7 @@
 	imd->size = source->size;
 	imd->mtime = source->mtime;
 
-	image_set_path(imd, image_get_path(source));
+	image_set_fd(imd, image_get_fd(source));
 
 	image_loader_free(imd->il);
 	imd->il = NULL;
@@ -1280,9 +1286,9 @@
 	imd->read_ahead_pixbuf = source->read_ahead_pixbuf;
 	source->read_ahead_pixbuf = NULL;
 
-	g_free(imd->read_ahead_path);
-	imd->read_ahead_path = source->read_ahead_path;
-	source->read_ahead_path = NULL;
+	file_data_unref(imd->read_ahead_fd);
+	imd->read_ahead_fd = source->read_ahead_fd;
+	source->read_ahead_fd = NULL;
 
 	if (imd->prev_pixbuf) g_object_unref(imd->prev_pixbuf);
 	imd->prev_pixbuf = source->prev_pixbuf;
@@ -1290,9 +1296,9 @@
 	imd->prev_color_row = source->prev_color_row;
 	source->prev_color_row = -1;
 
-	g_free(imd->prev_path);
-	imd->prev_path = source->prev_path;
-	source->prev_path = NULL;
+	file_data_unref(imd->prev_fd);
+	imd->prev_fd = source->prev_fd;
+	source->prev_fd = NULL;
 
 	imd->completed = source->completed;
 	imd->state = source->state;
@@ -1485,13 +1491,13 @@
 
 /* read ahead */
 
-void image_prebuffer_set(ImageWindow *imd, const gchar *path)
+void image_prebuffer_set(ImageWindow *imd, FileData *fd)
 {
 	if (pixbuf_renderer_get_tiles((PixbufRenderer *)imd->pr)) return;
 
-	if (path)
+	if (fd)
 		{
-		image_read_ahead_set(imd, path);
+		image_read_ahead_set(imd, fd);
 		}
 	else
 		{
@@ -1505,10 +1511,10 @@
 	time_t newtime;
 	
 	if (!imd || !image_get_pixbuf(imd) ||
-	    imd->il || !imd->image_path ||
+	    imd->il || !imd->image_fd ||
 	    !update_on_time_change) return TRUE;
 
-	newtime = filetime(imd->image_path);
+	newtime = filetime(imd->image_fd->path);
 	if (newtime > 0 && newtime != imd->mtime)
 		{
 		imd->mtime = newtime;
@@ -1735,7 +1741,7 @@
 	image_post_buffer_set(imd, NULL, NULL, -1);
 	image_auto_refresh(imd, -1);
 
-	g_free(imd->image_path);
+	file_data_unref(imd->image_fd);
 	g_free(imd->title);
 	g_free(imd->title_right);
 
@@ -1768,7 +1774,7 @@
 
 	imd->read_ahead_il = NULL;
 	imd->read_ahead_pixbuf = NULL;
-	imd->read_ahead_path = NULL;
+	imd->read_ahead_fd = NULL;
 
 	imd->completed = FALSE;
 	imd->state = IMAGE_STATE_NONE;
--- a/src/image.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/image.h	Tue Sep 11 20:06:29 2007 +0000
@@ -46,12 +46,13 @@
 /* path, name */
 const gchar *image_get_path(ImageWindow *imd);
 const gchar *image_get_name(ImageWindow *imd);
+FileData *image_get_fd(ImageWindow *imd);
 
 /* merely changes path string, does not change the image! */
-void image_set_path(ImageWindow *imd, const gchar *newpath);
+void image_set_fd(ImageWindow *imd, FileData *fd);
 
 /* load a new image */
-void image_change_path(ImageWindow *imd, const gchar *path, gdouble zoom);
+void image_change_fd(ImageWindow *imd, FileData *fd, gdouble zoom);
 void image_change_pixbuf(ImageWindow *imd, GdkPixbuf *pixbuf, gdouble zoom);
 void image_change_from_collection(ImageWindow *imd, CollectionData *cd, CollectInfo *info, gdouble zoom);
 CollectionData *image_get_collection(ImageWindow *imd, CollectInfo **info);
@@ -81,7 +82,7 @@
 gdouble image_zoom_get_default(ImageWindow *imd, gint mode);
 
 /* read ahead, pass NULL to cancel */
-void image_prebuffer_set(ImageWindow *imd, const gchar *path);
+void image_prebuffer_set(ImageWindow *imd, FileData *fd);
 
 /* auto refresh, interval is 1/1000 sec, 0 uses default, -1 disables */
 void image_auto_refresh(ImageWindow *imd, gint interval);
--- a/src/img-view.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/img-view.c	Tue Sep 11 20:06:29 2007 +0000
@@ -81,11 +81,11 @@
 static void view_window_set_list(ViewWindow *vw, GList *list)
 {
 
-	path_list_free(vw->list);
+	filelist_free(vw->list);
 	vw->list = NULL;
 	vw->list_pointer = NULL;
 
-	vw->list = path_list_copy(list);
+	vw->list = filelist_copy(list);
 }
 
 static gint view_window_contains_collection(ViewWindow *vw)
@@ -132,7 +132,7 @@
 		{
 		image_change_from_collection(imd, cd, info, image_zoom_get_default(imd, zoom_mode));
 
-		if (read_ahead_info) image_prebuffer_set(imd, read_ahead_info->path);
+		if (read_ahead_info) image_prebuffer_set(imd, read_ahead_info->fd);
 		}
 	
 }
@@ -162,21 +162,21 @@
 	if (info)
 		{
 		image_change_from_collection(imd, cd, info, image_zoom_get_default(imd, zoom_mode));
-		if (read_ahead_info) image_prebuffer_set(imd, read_ahead_info->path);
+		if (read_ahead_info) image_prebuffer_set(imd, read_ahead_info->fd);
 		}
 }
 
 static void view_list_step(ViewWindow *vw, gint next)
 {
 	ImageWindow *imd = view_window_active_image(vw);
-	const gchar *path;
+	FileData *fd;
 	GList *work;
 	GList *work_ahead;
 
 	if (!vw->list) return;
 
-	path = image_get_path(imd);
-	if (!path) return;
+	fd = image_get_fd(imd);
+	if (!fd) return;
 
 	if (g_list_position(vw->list, vw->list_pointer) >= 0)
 		{
@@ -189,11 +189,11 @@
 		work = vw->list;
 		while (work && !found)
 			{
-			gchar *temp;
+			FileData *temp;
 
 			temp = work->data;
 
-			if (strcmp(path, temp) == 0)
+			if (fd == temp)
 				{
 				found = TRUE;
 				}
@@ -220,20 +220,20 @@
 	if (!work) return;
 
 	vw->list_pointer = work;
-	path = work->data;
-	image_change_path(imd, path, image_zoom_get_default(imd, zoom_mode));
+	fd = work->data;
+	image_change_fd(imd, fd, image_zoom_get_default(imd, zoom_mode));
 
 	if (enable_read_ahead && work_ahead)
 		{
-		const gchar *next_path = work_ahead->data;
-		image_prebuffer_set(imd, next_path);
+		FileData *next_fd = work_ahead->data;
+		image_prebuffer_set(imd, next_fd);
 		}
 }
 
 static void view_list_step_to_end(ViewWindow *vw, gint last)
 {
 	ImageWindow *imd = view_window_active_image(vw);
-	const gchar *path;
+	FileData *fd;
 	GList *work;
 	GList *work_ahead;
 
@@ -251,13 +251,13 @@
 		}
 
 	vw->list_pointer = work;
-	path = work->data;
-	image_change_path(imd, path, image_zoom_get_default(imd, zoom_mode));
+	fd = work->data;
+	image_change_fd(imd, fd, image_zoom_get_default(imd, zoom_mode));
 
 	if (enable_read_ahead && work_ahead)
 		{
-		const gchar *next_path = work_ahead->data;
-		image_prebuffer_set(imd, next_path);
+		FileData *next_fd = work_ahead->data;
+		image_prebuffer_set(imd, next_fd);
 		}
 }
 
@@ -404,19 +404,19 @@
 				n = 9;
 				break;
 			case 'C': case 'c':
-				file_util_copy(image_get_path(imd), NULL, NULL, imd->widget);
+				file_util_copy(image_get_fd(imd), NULL, NULL, imd->widget);
 				break;
 			case 'M': case 'm':
-				file_util_move(image_get_path(imd), NULL, NULL, imd->widget);
+				file_util_move(image_get_fd(imd), NULL, NULL, imd->widget);
 				break;
 			case 'R': case 'r':
-				file_util_rename(image_get_path(imd), NULL, imd->widget);
+				file_util_rename(image_get_fd(imd), NULL, imd->widget);
 				break;
 			case 'D': case 'd':
-				file_util_delete(image_get_path(imd), NULL, imd->widget);
+				file_util_delete(image_get_fd(imd), NULL, imd->widget);
 				break;
 			case 'P': case 'p':
-				info_window_new(image_get_path(imd), NULL);
+				info_window_new(image_get_fd(imd), NULL);
 				break;
 			case 'W': case 'w':
 				view_window_close(vw);
@@ -432,7 +432,7 @@
 				view_fullscreen_toggle(vw, TRUE);
 				}
 			imd = view_window_active_image(vw);
-			start_editor_from_file(n, image_get_path(imd));
+			start_editor_from_file(n, image_get_fd(imd));
 			}
 		}
 	else if (event->state & GDK_SHIFT_MASK)
@@ -454,14 +454,14 @@
 				break;
 			case 'P': case 'p':
 				{
-				const gchar *path;
+				FileData *fd;
 
 				view_fullscreen_toggle(vw, TRUE);
 				imd = view_window_active_image(vw);
-				path = image_get_path(imd);
-				print_window_new(path,
-						 (path) ? g_list_append(NULL, g_strdup(path)) : NULL,
-						 path_list_copy(vw->list), vw->window);
+				fd = image_get_fd(imd);
+				print_window_new(fd,
+						 fd ? g_list_append(NULL, file_data_ref(fd)) : NULL,
+						 filelist_copy(vw->list), vw->window);
 				}
 				break;
 			default:
@@ -559,7 +559,7 @@
 			case GDK_Delete: case GDK_KP_Delete:
 				if (enable_delete_key)
 					{
-					file_util_delete(image_get_path(imd), NULL, imd->widget);
+					file_util_delete(image_get_fd(imd), NULL, imd->widget);
 					}
 				break;
 			case GDK_Escape:
@@ -748,18 +748,18 @@
 {
 	ViewWindow *vw = data;
 	GList *work;
-	const gchar *path;
+	FileData *fd;
 
 	vw->ss = NULL;
 
 	work = vw->list;
-	path = image_get_path(view_window_active_image(vw));
+	fd = image_get_fd(view_window_active_image(vw));
 	while (work)
 		{
-		gchar *temp;
+		FileData *temp;
 
 		temp = work->data;
-		if (strcmp(path, temp) == 0)
+		if (fd == temp)
 			{
 			vw->list_pointer = work;
 			work = NULL;
@@ -780,8 +780,8 @@
 
 		if (vw->list)
 			{
-			vw->ss = slideshow_start_from_path_list(view_window_active_image(vw),
-								path_list_copy(vw->list),
+			vw->ss = slideshow_start_from_filelist(view_window_active_image(vw),
+								filelist_copy(vw->list),
 								view_slideshow_stop_func, vw);
 			vw->list_pointer = NULL;
 			return;
@@ -810,7 +810,7 @@
 	view_slideshow_stop(vw);
 	fullscreen_stop(vw->fs);
 
-	path_list_free(vw->list);
+	filelist_free(vw->list);
 	g_free(vw);
 }
 
@@ -829,14 +829,14 @@
 	return TRUE;
 }
 
-static ViewWindow *real_view_window_new(const gchar *path, GList *list, CollectionData *cd, CollectInfo *info)
+static ViewWindow *real_view_window_new(FileData *fd, GList *list, CollectionData *cd, CollectInfo *info)
 {
 	ViewWindow *vw;
 	GtkAllocation req_size;
 	GdkGeometry geometry;
 	gint w, h;
 
-	if (!path && !list && (!cd || !info)) return NULL;
+	if (!fd && !list && (!cd || !info)) return NULL;
 
 	vw = g_new0(ViewWindow, 1);
 	vw->fs = NULL;
@@ -886,24 +886,24 @@
 			{
 			CollectInfo * r_info = collection_next_by_info(cd, info);
 			if (!r_info) r_info = collection_prev_by_info(cd, info);
-			if (r_info) image_prebuffer_set(vw->imd, r_info->path);
+			if (r_info) image_prebuffer_set(vw->imd, r_info->fd);
 			}
 		}
 	else if (list)
 		{
 		view_window_set_list(vw, list);
 		vw->list_pointer = vw->list;
-		image_change_path(vw->imd, (gchar *)vw->list->data, image_zoom_get_default(NULL, zoom_mode));
+		image_change_fd(vw->imd, (FileData *)vw->list->data, image_zoom_get_default(NULL, zoom_mode));
 
 		if (enable_read_ahead)
 			{
 			GList *work = vw->list->next;
-			if (work) image_prebuffer_set(vw->imd, (gchar *)work->data);
+			if (work) image_prebuffer_set(vw->imd, (FileData *)work->data);
 			}
 		}
 	else
 		{
-		image_change_path(vw->imd, path, image_zoom_get_default(NULL, zoom_mode));
+		image_change_fd(vw->imd, fd, image_zoom_get_default(NULL, zoom_mode));
 		}
 
 	if (image_zoom_get(vw->imd) == 0.0)
@@ -945,16 +945,16 @@
 	collection_unref(cd);
 }
 
-void view_window_new(const gchar *path)
+void view_window_new(FileData *fd)
 {
-	if (file_extension_match(path, ".gqv"))
+	if (file_extension_match(fd->path, ".gqv"))
 		{
 		ViewWindow *vw;
 		CollectionData *cd;
 		CollectInfo *info;
 
-		cd = collection_new(path);
-		if (collection_load(cd, path, FALSE))
+		cd = collection_new(fd->path);
+		if (collection_load(cd, fd->path, FALSE))
 			{
 			info = collection_get_first(cd);
 			}
@@ -971,21 +971,21 @@
 					 G_CALLBACK(view_window_collection_unref_cb), cd);
 			}
 		}
-	else if (isdir(path))
+	else if (isdir(fd->path)) 
 		{
 		GList *list = NULL;
 
-		if (path_list(path, &list, NULL))
+		if (filelist_read(fd->path, &list, NULL))
 			{
-			list = path_list_sort(list);
-			list = path_list_filter(list, FALSE);
+			list = filelist_sort_path(list);
+			list = filelist_filter(list, FALSE);
 			}
 		real_view_window_new(NULL, list, NULL, NULL);
-		path_list_free(list);
+		filelist_free(list);
 		}
 	else
 		{
-		real_view_window_new(path, NULL, NULL, NULL);
+		real_view_window_new(fd, NULL, NULL, NULL);
 		}
 }
 
@@ -1075,7 +1075,7 @@
 		}
 	else
 		{
-		view_window_new(image_get_path(vw->imd));
+		view_window_new(image_get_fd(vw->imd));
 		}
 }
 
@@ -1095,7 +1095,7 @@
 		}
 
 	imd = view_window_active_image(vw);
-	start_editor_from_file(n, image_get_path(imd));
+	start_editor_from_file(n, image_get_fd(imd));
 }
 
 static void view_alter_cb(GtkWidget *widget, gpointer data)
@@ -1116,7 +1116,7 @@
 	ImageWindow *imd;
 
 	imd = view_window_active_image(vw);
-	info_window_new(image_get_path(imd), NULL);
+	info_window_new(image_get_fd(imd), NULL);
 }
 
 static void view_wallpaper_cb(GtkWidget *widget, gpointer data)
@@ -1162,7 +1162,7 @@
 	ImageWindow *imd;
 
 	imd = view_window_active_image(vw);
-	file_util_copy(image_get_path(imd), NULL, NULL, imd->widget);
+	file_util_copy(image_get_fd(imd), NULL, NULL, imd->widget);
 }
 
 static void view_move_cb(GtkWidget *widget, gpointer data)
@@ -1171,7 +1171,7 @@
 	ImageWindow *imd;
 
 	imd = view_window_active_image(vw);
-	file_util_move(image_get_path(imd), NULL, NULL, imd->widget);
+	file_util_move(image_get_fd(imd), NULL, NULL, imd->widget);
 }
 
 static void view_rename_cb(GtkWidget *widget, gpointer data)
@@ -1180,7 +1180,7 @@
 	ImageWindow *imd;
 
 	imd = view_window_active_image(vw);
-	file_util_rename(image_get_path(imd), NULL, imd->widget);
+	file_util_rename(image_get_fd(imd), NULL, imd->widget);
 }
 
 static void view_delete_cb(GtkWidget *widget, gpointer data)
@@ -1189,7 +1189,7 @@
 	ImageWindow *imd;
 
 	imd = view_window_active_image(vw);
-	file_util_delete(image_get_path(imd), NULL, imd->widget);
+	file_util_delete(image_get_fd(imd), NULL, imd->widget);
 }
 
 static void view_fullscreen_cb(GtkWidget *widget, gpointer data)
@@ -1320,10 +1320,10 @@
 	work = list;
 	while (work)
 		{
-		gchar *path = work->data;
+		FileData *fd = work->data;
 		work = work->next;
 
-		if (isdir(path))
+		if (isdir(fd->path))
 			{
 			if (!skip)
 				{
@@ -1331,13 +1331,13 @@
 
 				if (recurse)
 					{
-					list = path_list_recursive(path);
+					list = filelist_recursive(fd->path);
 					}
 				else
-					{
-					path_list(path, &list, NULL);
-					list = path_list_sort(list);
-					list = path_list_filter(list, FALSE);
+					{ /*FIXME */
+					filelist_read(fd->path, &list, NULL);
+					list = filelist_sort_path(list);
+					list = filelist_filter(list, FALSE);
 					}
 				if (list) vw->list = g_list_concat(vw->list, list);
 				}
@@ -1345,28 +1345,28 @@
 		else
 			{
 			/* FIXME: no filtering here */
-			vw->list = g_list_append(vw->list, g_strdup(path));
+			vw->list = g_list_append(vw->list, file_data_ref(fd));
 			}
 		}
 
 	if (vw->list)
 		{
-		gchar *path;
+		FileData *fd;
 
 		vw->list_pointer = vw->list;
-		path = vw->list->data;
-		image_change_path(vw->imd, path, image_zoom_get_default(vw->imd, zoom_mode));
+		fd = vw->list->data;
+		image_change_fd(vw->imd, fd, image_zoom_get_default(vw->imd, zoom_mode));
 
 		work = vw->list->next;
 		if (enable_read_ahead && work)
 			{
-			path = work->data;
-			image_prebuffer_set(vw->imd, path);
+			fd = work->data;
+			image_prebuffer_set(vw->imd, fd);
 			}
 		}
 	else
 		{
-		image_change_path(vw->imd, NULL, image_zoom_get_default(vw->imd, zoom_mode));
+		image_change_fd(vw->imd, NULL, image_zoom_get_default(vw->imd, zoom_mode));
 		}
 }
 
@@ -1391,7 +1391,7 @@
 static void view_dir_list_destroy(GtkWidget *widget, gpointer data)
 {
 	CViewConfirmD *d = data;
-        path_list_free(d->list);
+        filelist_free(d->list);
         g_free(d);
 }
 
@@ -1447,12 +1447,13 @@
 			{
 			GList *work;
 
-			list = uri_list_from_text((gchar *)selection_data->data, TRUE);
+			list = uri_filelist_from_text((gchar *)selection_data->data, TRUE);
 
 			work = list;
 			while (work)
 				{
-				if (isdir((gchar *)work->data))
+				FileData *fd = work->data;
+				if (isdir(fd->path))
 					{
 					GtkWidget *menu;
 					menu = view_confirm_dir_list(vw, list);
@@ -1462,7 +1463,7 @@
 				work = work->next;
 				}
 
-			list = path_list_filter(list, FALSE);
+			list = filelist_filter(list, FALSE);
 
 			source = NULL;
 			info_list = NULL;
@@ -1474,10 +1475,10 @@
 
 		if (list)
 			{
-			gchar *path;
+			FileData *fd;
 
-			path = list->data;
-			if (isfile(path))
+			fd = list->data;
+			if (isfile(fd->path))
 				{
 				view_slideshow_stop(vw);
 				view_window_set_list(vw, NULL);
@@ -1495,11 +1496,11 @@
 
 						vw->list_pointer = vw->list;
 						}
-					image_change_path(imd, path, image_zoom_get_default(imd, zoom_mode));
+					image_change_fd(imd, fd, image_zoom_get_default(imd, zoom_mode));
 					}
 				}
 			}
-		path_list_free(list);
+		filelist_free(list);
 		g_list_free(info_list);
 		}
 }
@@ -1509,11 +1510,11 @@
 				     guint time, gpointer data)
 {
 	ViewWindow *vw = data;
-	const gchar *path;
+	FileData *fd;
 
-	path = image_get_path(vw->imd);
+	fd = image_get_fd(vw->imd);
 
-	if (path)
+	if (fd)
 		{
 		gchar *text = NULL;
 		gint len;
@@ -1530,8 +1531,8 @@
 				plain_text = TRUE;
 				break;
 			}
-		list = g_list_append(NULL, (gchar *)path);
-		text = uri_text_from_list(list, &len, plain_text);
+		list = g_list_append(NULL, fd);
+		text = uri_text_from_filelist(list, &len, plain_text);
 		g_list_free(list);
 		if (text)
 			{
@@ -1573,20 +1574,20 @@
  *-----------------------------------------------------------------------------
  */
 
-static void view_real_removed(ViewWindow *vw, const gchar *path, GList *ignore_list)
+static void view_real_removed(ViewWindow *vw, FileData *fd, GList *ignore_list)
 {
 	ImageWindow *imd;
-	const gchar *image_path;
+	FileData *image_fd;
 
 	imd = view_window_active_image(vw);
-	image_path = image_get_path(imd);
+	image_fd = image_get_fd(imd);
 
-	if (image_path && strcmp(image_path, path) == 0)
+	if (image_fd && image_fd == fd)
 		{
 		if (vw->list)
 			{
 			view_list_step(vw, TRUE);
-			if (image_get_path(imd) == image_path)
+			if (image_get_fd(imd) == image_fd)
 				{
 				view_list_step(vw, FALSE);
 				}
@@ -1594,14 +1595,14 @@
 		else if (view_window_contains_collection(vw))
 			{
 			view_collection_step(vw, TRUE);
-			if (image_get_path(imd) == image_path)
+			if (image_get_fd(imd) == image_fd)
 				{
 				view_collection_step(vw, FALSE);
 				}
 			}
-		if (image_get_path(imd) == image_path)
+		if (image_get_fd(imd) == image_fd)
 			{
-			image_change_path(imd, NULL, image_zoom_get_default(imd, zoom_mode));
+			image_change_fd(imd, NULL, image_zoom_get_default(imd, zoom_mode));
 			}
 		}
 
@@ -1615,58 +1616,62 @@
 		work = vw->list;
 		while (work)
 			{
-			gchar *chk_path;
+			FileData *chk_fd;
 			GList *chk_link;
 
-			chk_path = work->data;
+			chk_fd = work->data;
 			chk_link = work;
 			work = work->next;
 
-			if (strcmp(chk_path, path) == 0)
+			if (chk_fd == fd)
 				{
 				if (vw->list_pointer == chk_link)
 					{
 					vw->list_pointer = (chk_link->next) ? chk_link->next : chk_link->prev;
 					}
-				vw->list = g_list_remove(vw->list, chk_path);
-				g_free(chk_path);
+				vw->list = g_list_remove(vw->list, chk_fd);
+				file_data_unref(chk_fd);
 				}
 			}
 
 		/* handles stepping correctly when same image is in the list more than once */
 		if (old && old != vw->list_pointer)
 			{
-			gchar *path;
+			FileData *fd;
 
 			if (vw->list_pointer)
 				{
-				path = vw->list_pointer->data;
+				fd = vw->list_pointer->data;
 				}
 			else
 				{
-				path = NULL;
+				fd = NULL;
 				}
 
-			image_change_path(imd, path, image_zoom_get_default(imd, zoom_mode));
+			image_change_fd(imd, fd, image_zoom_get_default(imd, zoom_mode));
 			}
 		}
 
 	image_osd_update(imd);
 }
 
-static void view_real_moved(ViewWindow *vw, const gchar *source, const gchar *dest)
+static void view_real_moved(ViewWindow *vw, FileData *fd)
 {
+/*
 	ImageWindow *imd;
 	const gchar *image_path;
 
 	imd = view_window_active_image(vw);
+*/
+/*
 	image_path = image_get_path(imd);
 
-	if (image_path && strcmp(image_path, source) == 0)
+	if (image_path && strcmp(image_path, fd->change->source) == 0)
 		{
-		image_set_path(imd, dest);
+		image_set_fd(imd, dest);
 		}
-
+*/
+/*
 	if (vw->list)
 		{
 		GList *work;
@@ -1686,9 +1691,10 @@
 			work = work->next;
 			}
 		}
+*/
 }
 
-void view_window_maint_removed(const gchar *path, GList *ignore_list)
+void view_window_maint_removed(FileData *fd, GList *ignore_list)
 {
 	GList *work = view_window_list;
 	while (work)
@@ -1696,11 +1702,11 @@
 		ViewWindow *vw = work->data;
 		work = work->next;
 
-		view_real_removed(vw, path, ignore_list);
+		view_real_removed(vw, fd, ignore_list);
 		}
 }
 
-void view_window_maint_moved(const gchar *source, const gchar *dest)
+void view_window_maint_moved(FileData *fd)
 {
 	GList *work = view_window_list;
 	while (work)
@@ -1708,7 +1714,7 @@
 		ViewWindow *vw = work->data;
 		work = work->next;
 
-		view_real_moved(vw, source, dest);
+		view_real_moved(vw, fd);
 		}
 }
 
--- a/src/img-view.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/img-view.h	Tue Sep 11 20:06:29 2007 +0000
@@ -14,7 +14,7 @@
 #define IMG_VIEW_H
 
 
-void view_window_new(const gchar *path);
+void view_window_new(FileData *fd);
 void view_window_new_from_list(GList *list);
 void view_window_new_from_collection(CollectionData *cd, CollectInfo *info);
 
@@ -22,8 +22,8 @@
 
 gint view_window_find_image(ImageWindow *imd, gint *index, gint *total);
 
-void view_window_maint_removed(const gchar *path, GList *ignore_list);
-void view_window_maint_moved(const gchar *source, const gchar *dest);
+void view_window_maint_removed(FileData *fd, GList *ignore_list);
+void view_window_maint_moved(FileData *fd);
 
 
 #endif
--- a/src/info.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/info.c	Tue Sep 11 20:06:29 2007 +0000
@@ -73,18 +73,18 @@
 static void info_tab_exif_image(InfoData *id, gpointer data)
 {
 	GtkWidget *bar = data;
-	const gchar *path;
+	FileData *fd;
 
 	if (id->image->unknown)
 		{
-		path = NULL;
+		fd = NULL;
 		}
 	else
        		{
-		path = id->image->image_path;
+		fd = id->image->image_fd;
 		}
 
-	bar_exif_set(bar, path);
+	bar_exif_set(bar, fd);
 }
 
 static void info_tab_exif_sync(InfoData *id, gpointer data)
@@ -140,7 +140,7 @@
 {
 	InfoTabMeta *tab = data;
 
-	bar_info_set(tab->bar_info, id->path);
+	bar_info_set(tab->bar_info, id->fd);
 }
 
 static GList *info_tab_meta_list_cb(gpointer data)
@@ -280,7 +280,7 @@
 {
 	struct stat st;
 
-	if (!stat_utf8(id->path, &st))
+	if (!stat_utf8(id->fd->path, &st))
 		{
 		gtk_label_set_text(GTK_LABEL(tab->label_user), "");
 		gtk_label_set_text(GTK_LABEL(tab->label_group), "");
@@ -324,9 +324,9 @@
 	InfoTabGeneral *tab = data;
 	gchar *buf;
 
-	gtk_label_set_text(GTK_LABEL(tab->label_file_time), text_from_time(filetime(id->path)));
+	gtk_label_set_text(GTK_LABEL(tab->label_file_time), text_from_time(id->fd->date));
 
-	tab->byte_size = filesize(id->path);
+	tab->byte_size = id->fd->size;
 
 	buf = text_from_size(tab->byte_size);
 	gtk_label_set_text(GTK_LABEL(tab->label_file_size), buf);
@@ -448,18 +448,18 @@
  *-------------------------------------------------------------------
  */
 
-static void info_window_sync(InfoData *id, const gchar *path)
+static void info_window_sync(InfoData *id, FileData *fd)
 {
 
-	if (!path) return;
+	if (!fd) return;
 
-	gtk_entry_set_text(GTK_ENTRY(id->name_entry), filename_from_path(path));
+	gtk_entry_set_text(GTK_ENTRY(id->name_entry), fd->name);
 
 	if (id->label_count)
 		{
 		gchar *buf;
 		buf = g_strdup_printf(_("Image %d of %d"),
-				      g_list_index(id->list, (gpointer)path) + 1,
+				      g_list_index(id->list, (gpointer)fd->path) + 1,
 				      g_list_length(id->list));
 		gtk_label_set_text(GTK_LABEL(id->label_count), buf);
 		g_free(buf);
@@ -468,7 +468,7 @@
 	info_tabs_sync(id, FALSE);
 
 	id->updated = FALSE;
-	image_change_path(id->image, path, 0.0);
+	image_change_fd(id->image, fd, 0.0);
 }
 
 /*
@@ -482,10 +482,10 @@
 				     guint time, gpointer data)
 {
 	InfoData *id = data;
-	const gchar *path;
+	FileData *fd;
 
-	path = image_get_path(id->image);
-	if (path)
+	fd = image_get_fd(id->image);
+	if (fd)
 		{
 		gchar *text;
 		gint len;
@@ -502,8 +502,8 @@
 				plain_text = TRUE;
 				break;
 			}
-		list = g_list_append(NULL, (gchar *)path);
-		text = uri_text_from_list(list, &len, plain_text);
+		list = g_list_append(NULL, fd);
+		text = uri_text_from_filelist(list, &len, plain_text);
 		g_list_free(list);
 
 		gtk_selection_data_set(selection_data, selection_data->target,
@@ -565,13 +565,13 @@
 	InfoData *id = data;
 	GList *work;
 
-	work = g_list_find(id->list, (gpointer)id->path);
+	work = g_list_find(id->list, (gpointer)id->fd);
 	if (!work || !work->prev) return;
 
 	work = work->prev;
-	id->path = work->data;
+	id->fd = work->data;
 
-	info_window_sync(id, id->path);
+	info_window_sync(id, id->fd);
 
 	gtk_widget_set_sensitive(id->button_back, (work->prev != NULL));
 	gtk_widget_set_sensitive(id->button_next, TRUE);
@@ -582,13 +582,13 @@
 	InfoData *id = data;
 	GList *work;
 
-	work = g_list_find(id->list, (gpointer)id->path);
+	work = g_list_find(id->list, (gpointer)id->fd);
 	if (!work || !work->next) return;
 
 	work = work->next;
-	id->path = work->data;
+	id->fd = work->data;
 
-	info_window_sync(id, id->path);
+	info_window_sync(id, id->fd);
 
 	gtk_widget_set_sensitive(id->button_next, (work->next != NULL));
 	gtk_widget_set_sensitive(id->button_back, TRUE);
@@ -649,11 +649,11 @@
 	InfoData *id = data;
 
 	info_tabs_free(id);
-	path_list_free(id->list);
+	filelist_free(id->list);
 	g_free(id);
 }
 
-void info_window_new(const gchar *path, GList *list)
+void info_window_new(FileData *fd, GList *list)
 {
 	InfoData *id;
 	GtkWidget *main_vbox;
@@ -663,17 +663,17 @@
 	GtkWidget *label;
 	GdkGeometry geometry;
 
-	if (!path && !list) return;
+	if (!fd && !list) return;
 
 	if (!list)
 		{
-		list = g_list_append(NULL, g_strdup(path));
+		list = g_list_append(NULL, file_data_ref(fd));
 		}
 
 	id = g_new0(InfoData, 1);
 
 	id->list = list;
-	id->path = (gchar *)id->list->data;
+	id->fd = (FileData *)id->list->data;
 	id->updated = FALSE;
 
 	id->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
@@ -760,7 +760,7 @@
 
 	/* fill it */
 
-	info_window_sync(id, id->path);
+	info_window_sync(id, id->fd);
 
 	/* finish */
 
--- a/src/info.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/info.h	Tue Sep 11 20:06:29 2007 +0000
@@ -22,7 +22,7 @@
 
 	GList *list;
 
-	const gchar *path;
+	FileData *fd;
 
 	GtkWidget *notebook;
 	GtkWidget *name_entry;
@@ -37,7 +37,7 @@
 };
 
 
-void info_window_new(const gchar *path, GList *list);
+void info_window_new(FileData *fd, GList *list);
 
 GtkWidget *table_add_line(GtkWidget *table, gint x, gint y,
 			  const gchar *description, const gchar *text);
--- a/src/layout.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/layout.c	Tue Sep 11 20:06:29 2007 +0000
@@ -810,6 +810,16 @@
 	return NULL;
 }
 
+FileData *layout_list_get_fd(LayoutWindow *lw, gint index)
+{
+	if (!layout_valid(&lw)) return NULL;
+
+	if (lw->vfl) return vflist_index_get_data(lw->vfl, index);
+	if (lw->vfi) return vficon_index_get_data(lw->vfi, index);
+
+	return NULL;
+}
+
 gint layout_list_get_index(LayoutWindow *lw, const gchar *path)
 {
 	if (!layout_valid(&lw)) return -1;
@@ -820,12 +830,12 @@
 	return -1;
 }
 
-void layout_list_sync_path(LayoutWindow *lw, const gchar *path)
+void layout_list_sync_fd(LayoutWindow *lw, FileData *fd)
 {
 	if (!layout_valid(&lw)) return;
 
-	if (lw->vfl) vflist_select_by_path(lw->vfl, path);
-	if (lw->vfi) vficon_select_by_path(lw->vfi, path);
+	if (lw->vfl) vflist_select_by_fd(lw->vfl, fd);
+	if (lw->vfi) vficon_select_by_fd(lw->vfi, fd);
 }
 
 static void layout_list_sync_sort(LayoutWindow *lw)
@@ -842,10 +852,10 @@
 
 	if (layout_image_get_collection(lw, NULL))
 		{
-		const gchar *path;
+		FileData *fd;
 
-		path = layout_image_get_path(lw);
-		if (path) return g_list_append(NULL, g_strdup(path));
+		fd = layout_image_get_fd(lw);
+		if (fd) return g_list_append(NULL, file_data_ref(fd));
 		return NULL;
 		}
 
@@ -970,7 +980,7 @@
 			}
 		else
 			{
-			layout_image_set_path(lw, path);
+			layout_image_set_fd(lw, file_data_new_simple(path));
 			}
 		}
 	else if (!lazy_image_sync)
@@ -2002,43 +2012,43 @@
 	if (lw->path) lw->last_time = filetime(lw->path);
 }
 
-static void layout_real_renamed(LayoutWindow *lw, const gchar *source, const gchar *dest)
+static void layout_real_renamed(LayoutWindow *lw, FileData *fd)
 {
 	gint update = FALSE;
 
-	if (lw->image) layout_image_maint_renamed(lw, source, dest);
+	if (lw->image) layout_image_maint_renamed(lw, fd);
 
-	if (lw->vfl) update |= vflist_maint_renamed(lw->vfl, source, dest);
-	if (lw->vfi) update |= vficon_maint_renamed(lw->vfi, source, dest);
+	if (lw->vfl) update |= vflist_maint_renamed(lw->vfl, fd);
+	if (lw->vfi) update |= vficon_maint_renamed(lw->vfi, fd);
 
 	if (update) layout_real_time_update(lw);
 }
 
-static void layout_real_removed(LayoutWindow *lw, const gchar *path, GList *ignore_list)
+static void layout_real_removed(LayoutWindow *lw, FileData *fd, GList *ignore_list)
 {
 	gint update = FALSE;
 
-	if (lw->image) layout_image_maint_removed(lw, path);
+	if (lw->image) layout_image_maint_removed(lw, fd);
 
-	if (lw->vfl) update |= vflist_maint_removed(lw->vfl, path, ignore_list);
-	if (lw->vfi) update |= vficon_maint_removed(lw->vfi, path, ignore_list);
+	if (lw->vfl) update |= vflist_maint_removed(lw->vfl, fd, ignore_list);
+	if (lw->vfi) update |= vficon_maint_removed(lw->vfi, fd, ignore_list);
 
 	if (update) layout_real_time_update(lw);
 }
 
-static void layout_real_moved(LayoutWindow *lw, const gchar *source, const gchar *dest, GList *ignore_list)
+static void layout_real_moved(LayoutWindow *lw, FileData *fd, GList *ignore_list)
 {
 	gint update = FALSE;
 
-	if (lw->image) layout_image_maint_moved(lw, source, dest);
+	if (lw->image) layout_image_maint_moved(lw, fd);
 
-	if (lw->vfl) update |= vflist_maint_moved(lw->vfl, source, dest, ignore_list);
-	if (lw->vfi) update |= vficon_maint_moved(lw->vfi, source, dest, ignore_list);
+	if (lw->vfl) update |= vflist_maint_moved(lw->vfl, fd, ignore_list);
+	if (lw->vfi) update |= vficon_maint_moved(lw->vfi, fd, ignore_list);
 
 	if (update) layout_real_time_update(lw);
 }
 
-void layout_maint_renamed(const gchar *source, const gchar *dest)
+void layout_maint_renamed(FileData *fd)
 {
 	GList *work = layout_window_list;
 	while (work)
@@ -2046,11 +2056,11 @@
 		LayoutWindow *lw = work->data;
 		work = work->next;
 
-		layout_real_renamed(lw, source, dest);
+		layout_real_renamed(lw, fd);
 		}
 }
 
-void layout_maint_removed(const gchar *path, GList *ignore_list)
+void layout_maint_removed(FileData *fd, GList *ignore_list)
 {
 	GList *work = layout_window_list;
 	while (work)
@@ -2058,11 +2068,11 @@
 		LayoutWindow *lw = work->data;
 		work = work->next;
 
-		layout_real_removed(lw, path, ignore_list);
+		layout_real_removed(lw, fd, ignore_list);
 		}
 }
 
-void layout_maint_moved(const gchar *source, const gchar *dest, GList *ignore_list)
+void layout_maint_moved(FileData *fd, GList *ignore_list)
 {
 	GList *work = layout_window_list;
 	while (work)
@@ -2070,6 +2080,6 @@
 		LayoutWindow *lw = work->data;
 		work = work->next;
 
-		layout_real_moved(lw, source, dest, ignore_list);
+		layout_real_moved(lw, fd, ignore_list);
 		}
 }
--- a/src/layout.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/layout.h	Tue Sep 11 20:06:29 2007 +0000
@@ -38,8 +38,9 @@
 GList *layout_list(LayoutWindow *lw);
 gint layout_list_count(LayoutWindow *lw, gint64 *bytes);
 const gchar *layout_list_get_path(LayoutWindow *lw, gint index);
+FileData *layout_list_get_fd(LayoutWindow *lw, gint index);
 gint layout_list_get_index(LayoutWindow *lw, const gchar *path);
-void layout_list_sync_path(LayoutWindow *lw, const gchar *path);
+void layout_list_sync_fd(LayoutWindow *lw, FileData *fd);
 
 GList *layout_selection_list(LayoutWindow *lw);
 /* return list of pointers to int for selection */
@@ -86,9 +87,9 @@
 
 void layout_split_change(LayoutWindow *lw, ImageSplitMode mode);
 
-void layout_maint_renamed(const gchar *source, const gchar *dest);
-void layout_maint_removed(const gchar *path, GList *ignore_list);
-void layout_maint_moved(const gchar *source, const gchar *dest, GList *ignore_list);
+void layout_maint_renamed(FileData *fd);
+void layout_maint_removed(FileData *fd, GList *ignore_list);
+void layout_maint_moved(FileData *fd, GList *ignore_list);
 
 
 #endif
--- a/src/layout_image.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/layout_image.c	Tue Sep 11 20:06:29 2007 +0000
@@ -166,19 +166,19 @@
 				n = 9;
 				break;
 			case 'C': case 'c':
-				file_util_copy(layout_image_get_path(lw), NULL, NULL, widget);
+				file_util_copy(layout_image_get_fd(lw), NULL, NULL, widget);
 				break;
 			case 'M': case 'm':
-				file_util_move(layout_image_get_path(lw), NULL, NULL, widget);
+				file_util_move(layout_image_get_fd(lw), NULL, NULL, widget);
 				break;
 			case 'R': case 'r':
-				file_util_rename(layout_image_get_path(lw), NULL, widget);
+				file_util_rename(layout_image_get_fd(lw), NULL, widget);
 				break;
 			case 'D': case 'd':
-				file_util_delete(layout_image_get_path(lw), NULL, widget);
+				file_util_delete(layout_image_get_fd(lw), NULL, widget);
 				break;
 			case 'P': case 'p':
-				info_window_new(layout_image_get_path(lw), NULL);
+				info_window_new(layout_image_get_fd(lw), NULL);
 				break;
 			case 'Q': case 'q':
 				exit_gqview();
@@ -194,7 +194,7 @@
 				{
 				layout_image_full_screen_stop(lw);
 				}
-			start_editor_from_file(n, layout_image_get_path(lw));
+			start_editor_from_file(n, layout_image_get_fd(lw));
 			}
 		}
 	else if (event->state & GDK_SHIFT_MASK)
@@ -286,7 +286,7 @@
 			case GDK_Delete: case GDK_KP_Delete:
 				if (enable_delete_key)
 					{
-					file_util_delete(layout_image_get_path(lw), NULL, widget);
+					file_util_delete(layout_image_get_fd(lw), NULL, widget);
 					}
 				break;
 			case GDK_Escape:
@@ -464,11 +464,11 @@
 
 	if (lw->slideshow || !list)
 		{
-		path_list_free(list);
+		filelist_free(list);
 		return;
 		}
 
-	lw->slideshow = slideshow_start_from_path_list(lw->image, list,
+	lw->slideshow = slideshow_start_from_filelist(lw->image, list,
 						       layout_image_slideshow_stop_func, lw);
 
 	layout_status_update_info(lw, NULL);
@@ -583,7 +583,7 @@
 		{
 		layout_image_full_screen_stop(lw);
 		}
-	start_editor_from_file(n, layout_image_get_path(lw));
+	start_editor_from_file(n, layout_image_get_fd(lw));
 }
 
 static void li_pop_menu_wallpaper_cb(GtkWidget *widget, gpointer data)
@@ -608,14 +608,14 @@
 {
 	LayoutWindow *lw = data;
 
-	info_window_new(layout_image_get_path(lw), NULL);
+	info_window_new(layout_image_get_fd(lw), NULL);
 }
 
 static void li_pop_menu_new_cb(GtkWidget *widget, gpointer data)
 {
 	LayoutWindow *lw = data;
 
-	view_window_new(layout_image_get_path(lw));
+	view_window_new(layout_image_get_fd(lw));
 }
 
 static GtkWidget *li_pop_menu_click_parent(GtkWidget *widget, LayoutWindow *lw)
@@ -640,7 +640,7 @@
 {
 	LayoutWindow *lw = data;
 
-	file_util_copy(layout_image_get_path(lw), NULL, NULL,
+	file_util_copy(layout_image_get_fd(lw), NULL, NULL,
 		       li_pop_menu_click_parent(widget, lw));
 }
 
@@ -648,7 +648,7 @@
 {
 	LayoutWindow *lw = data;
 
-	file_util_move(layout_image_get_path(lw), NULL, NULL,
+	file_util_move(layout_image_get_fd(lw), NULL, NULL,
 		       li_pop_menu_click_parent(widget, lw));
 }
 
@@ -656,7 +656,7 @@
 {
 	LayoutWindow *lw = data;
 
-	file_util_rename(layout_image_get_path(lw), NULL,
+	file_util_rename(layout_image_get_fd(lw), NULL,
 			 li_pop_menu_click_parent(widget, lw));
 }
 
@@ -664,7 +664,7 @@
 {
 	LayoutWindow *lw = data;
 
-	file_util_delete(layout_image_get_path(lw), NULL,
+	file_util_delete(layout_image_get_fd(lw), NULL,
 			 li_pop_menu_click_parent(widget, lw));
 }
 
@@ -887,7 +887,7 @@
 
 		if (info == TARGET_URI_LIST)
 			{
-			list = uri_list_from_text((gchar *)selection_data->data, TRUE);
+			list = uri_filelist_from_text((gchar *)selection_data->data, TRUE);
 			source = NULL;
 			info_list = NULL;
 			}
@@ -898,44 +898,42 @@
 
 		if (list)
 			{
-			gchar *path;
+			FileData *fd = list->data;
 
-			path = list->data;
-
-			if (isfile(path))
+			if (isfile(fd->path))
 				{
 				gchar *base;
 				gint row;
 
-				base = remove_level_from_path(path);
+				base = remove_level_from_path(fd->path);
 				if (strcmp(base, layout_get_path(lw)) != 0)
 					{
 					layout_set_path(lw, base);
 					}
 				g_free(base);
 
-				row = layout_list_get_index(lw, path);
+				row = layout_list_get_index(lw, fd->path);
 				if (source && info_list)
 					{
 					layout_image_set_collection(lw, source, info_list->data);
 					}
 				else if (row == -1)
 					{
-					layout_image_set_path(lw, path);
+					layout_image_set_fd(lw, fd);
 					}
 				else
 					{
 					layout_image_set_index(lw, row);
 					}
 				}
-			else if (isdir(path))
+			else if (isdir(fd->path))
 				{
-				layout_set_path(lw, path);
-				layout_image_set_path(lw, NULL);
+				layout_set_path(lw, fd->path);
+				layout_image_set_fd(lw, NULL);
 				}
 			}
 
-		path_list_free(list);
+		filelist_free(list);
 		g_list_free(info_list);
 		}
 }
@@ -945,7 +943,7 @@
 				 guint time, gpointer data)
 {
 	LayoutWindow *lw = data;
-	const gchar *path;
+	FileData *fd;
 	gint i;
 	
 	
@@ -957,12 +955,12 @@
 	if (i < MAX_SPLIT_IMAGES)
 		{
 		printf("dnd get from %d\n", i);
-		path = image_get_path(lw->split_images[i]);
+		fd = image_get_fd(lw->split_images[i]);
 		}
 	else
-		path = layout_image_get_path(lw);
+		fd = layout_image_get_fd(lw);
 
-	if (path)
+	if (fd)
 		{
 		gchar *text = NULL;
 		gint len;
@@ -979,8 +977,8 @@
 				plain_text = TRUE;
 				break;
 			}
-		list = g_list_append(NULL, (gchar *)path);
-		text = uri_text_from_list(list, &len, plain_text);
+		list = g_list_append(NULL, fd);
+		text = uri_text_from_filelist(list, &len, plain_text);
 		g_list_free(list);
 		if (text)
 			{
@@ -1124,6 +1122,13 @@
 	return image_get_name(lw->image);
 }
 
+FileData *layout_image_get_fd(LayoutWindow *lw)
+{
+	if (!layout_valid(&lw)) return NULL;
+
+	return image_get_fd(lw->image);
+}
+
 CollectionData *layout_image_get_collection(LayoutWindow *lw, CollectInfo **info)
 {
 	if (!layout_valid(&lw)) return NULL;
@@ -1142,23 +1147,23 @@
  *----------------------------------------------------------------------------
  */
 
-void layout_image_set_path(LayoutWindow *lw, const gchar *path)
+void layout_image_set_fd(LayoutWindow *lw, FileData *fd)
 {
 	gdouble sx, sy;
 	if (!layout_valid(&lw)) return;
 
 	image_get_scroll_center(lw->image, &sx, &sy);
 
-	image_change_path(lw->image, path, image_zoom_get_default(lw->image, zoom_mode));
+	image_change_fd(lw->image, fd, image_zoom_get_default(lw->image, zoom_mode));
 
 	image_set_scroll_center(lw->image, sx, sy);
 
-	layout_list_sync_path(lw, path);
+	layout_list_sync_fd(lw, fd);
 	layout_image_slideshow_continue_check(lw);
 	layout_bars_new_image(lw);
 }
 
-void layout_image_set_with_ahead(LayoutWindow *lw, const gchar *path, const gchar *read_ahead_path)
+void layout_image_set_with_ahead(LayoutWindow *lw, FileData *fd, FileData *read_ahead_fd)
 {
 	if (!layout_valid(&lw)) return;
 
@@ -1170,31 +1175,31 @@
 		if (old_path && strcmp(path, old_path) == 0) return;
 		}
 */
-	layout_image_set_path(lw, path);
-	if (enable_read_ahead) image_prebuffer_set(lw->image, read_ahead_path);
+	layout_image_set_fd(lw, fd);
+	if (enable_read_ahead) image_prebuffer_set(lw->image, read_ahead_fd);
 }
 
 void layout_image_set_index(LayoutWindow *lw, gint index)
 {
-	const gchar *path;
-	const gchar *read_ahead_path;
+	FileData *fd;
+	FileData *read_ahead_fd;
 	gint old;
 
 	if (!layout_valid(&lw)) return;
 
 	old = layout_list_get_index(lw, layout_image_get_path(lw));
-	path = layout_list_get_path(lw, index);
+	fd = layout_list_get_fd(lw, index);
 
 	if (old > index)
 		{
-		read_ahead_path = layout_list_get_path(lw, index - 1);
+		read_ahead_fd = layout_list_get_fd(lw, index - 1);
 		}
 	else
 		{
-		read_ahead_path = layout_list_get_path(lw, index + 1);
+		read_ahead_fd = layout_list_get_fd(lw, index + 1);
 		}
 
-	layout_image_set_with_ahead(lw, path, read_ahead_path);
+	layout_image_set_with_ahead(lw, fd, read_ahead_fd);
 }
 
 static void layout_image_set_collection_real(LayoutWindow *lw, CollectionData *cd, CollectInfo *info, gint forward)
@@ -1215,7 +1220,7 @@
 			r_info = collection_prev_by_info(cd, info);
 			if (!r_info) r_info = collection_next_by_info(cd, info);
 			}
-		if (r_info) image_prebuffer_set(lw->image, r_info->path);
+		if (r_info) image_prebuffer_set(lw->image, r_info->fd);
 		}
 
 	layout_image_slideshow_continue_check(lw);
@@ -1225,7 +1230,7 @@
 void layout_image_set_collection(LayoutWindow *lw, CollectionData *cd, CollectInfo *info)
 {
 	layout_image_set_collection_real(lw, cd, info, TRUE);
-	layout_list_sync_path(lw, layout_image_get_path(lw));
+	layout_list_sync_fd(lw, layout_image_get_fd(lw));
 }
 
 void layout_image_refresh(LayoutWindow *lw)
@@ -1680,7 +1685,7 @@
 
 void layout_image_activate(LayoutWindow *lw, gint i)
 {
-	const gchar *path;
+	FileData *fd;
 
 	gchar *base;
 	gint row;
@@ -1703,12 +1708,12 @@
 
 	image_select(lw->split_images[i], TRUE);
 
-	path = image_get_path(lw->image);
+	fd = image_get_fd(lw->image);
 
-        if (path)
+        if (fd)
 		{
 //		layout_list_sync_path(lw, path);
-		layout_set_path(lw, path);
+		layout_set_path(lw, fd->path);
 		}
 }
 
@@ -1760,8 +1765,8 @@
 		{
 		layout_image_new(lw, 1);
 		if (lw->image)
-			image_change_path(lw->split_images[1], 
-				image_get_path(lw->image), image_zoom_get_real(lw->image));
+			image_change_fd(lw->split_images[1], 
+				image_get_fd(lw->image), image_zoom_get_real(lw->image));
 		layout_image_deactivate(lw, 1);
 		}
 
@@ -1817,8 +1822,8 @@
 			{
 			layout_image_new(lw, i);
 			if (lw->image)
-				image_change_path(lw->split_images[i], 
-					image_get_path(lw->image), image_zoom_get_real(lw->image));
+				image_change_fd(lw->split_images[i], 
+					image_get_fd(lw->image), image_zoom_get_real(lw->image));
 			layout_image_deactivate(lw, i);
 			}
 
@@ -1886,24 +1891,24 @@
  *-----------------------------------------------------------------------------
  */
 
-void layout_image_maint_renamed(LayoutWindow *lw, const gchar *source, const gchar *dest)
+void layout_image_maint_renamed(LayoutWindow *lw, FileData *fd)
 {
-	const gchar *img_path;
+	FileData *img_fd;
 
-	img_path = layout_image_get_path(lw);
-	if (img_path && strcmp(img_path, source) == 0)
+	img_fd = layout_image_get_fd(lw);
+	if (img_fd == fd)
 		{
-		image_set_path(lw->image, dest);
+		image_set_fd(lw->image, fd);
 		layout_bars_maint_renamed(lw);
 		}
 }
 
-void layout_image_maint_removed(LayoutWindow *lw, const gchar *path)
+void layout_image_maint_removed(LayoutWindow *lw, FileData *fd)
 {
-	const gchar *img_path;
+	FileData *img_fd;
 
-	img_path = layout_image_get_path(lw);
-	if (img_path && strcmp(img_path, path) == 0)
+	img_fd = layout_image_get_fd(lw);
+	if (img_fd == fd)
 		{
 		CollectionData *cd;
 		CollectInfo *info;
@@ -1923,12 +1928,12 @@
 				}
 			}
 
-		layout_image_set_path(lw, NULL);
+		layout_image_set_fd(lw, NULL);
 		}
 }
 
-void layout_image_maint_moved(LayoutWindow *lw, const gchar *source, const gchar *dest)
+void layout_image_maint_moved(LayoutWindow *lw, FileData *fd)
 {
-	layout_image_maint_renamed(lw, source, dest);
+	layout_image_maint_renamed(lw, fd);
 }
 
--- a/src/layout_image.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/layout_image.h	Tue Sep 11 20:06:29 2007 +0000
@@ -19,8 +19,8 @@
 GtkWidget *layout_image_setup_split_hv(LayoutWindow *lw, gboolean horizontal);
 GtkWidget *layout_image_setup_split(LayoutWindow *lw, ImageSplitMode mode);
 
-void layout_image_set_path(LayoutWindow *lw, const gchar *path);
-void layout_image_set_with_ahead(LayoutWindow *lw, const gchar *path, const gchar *read_ahead_path);
+void layout_image_set_fd(LayoutWindow *lw, FileData *fd);
+void layout_image_set_with_ahead(LayoutWindow *lw, FileData *fd, FileData *read_ahead_fd);
 
 void layout_image_set_index(LayoutWindow *lw, gint index);
 void layout_image_set_collection(LayoutWindow *lw, CollectionData *cd, CollectInfo *info);
@@ -39,6 +39,7 @@
 
 const gchar *layout_image_get_path(LayoutWindow *lw);
 const gchar *layout_image_get_name(LayoutWindow *lw);
+FileData *layout_image_get_fd(LayoutWindow *lw);
 CollectionData *layout_image_get_collection(LayoutWindow *lw, CollectInfo **info);
 gint layout_image_get_index(LayoutWindow *lw);
 
@@ -76,9 +77,9 @@
 void layout_image_overlay_update(LayoutWindow *lw);
 
 
-void layout_image_maint_renamed(LayoutWindow *lw, const gchar *source, const gchar *dest);
-void layout_image_maint_removed(LayoutWindow *lw, const gchar *path);
-void layout_image_maint_moved(LayoutWindow *lw, const gchar *source, const gchar *dest);
+void layout_image_maint_renamed(LayoutWindow *lw, FileData *fd);
+void layout_image_maint_removed(LayoutWindow *lw, FileData *fd);
+void layout_image_maint_moved(LayoutWindow *lw, FileData *fd);
 
 
 #endif
--- a/src/layout_util.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/layout_util.c	Tue Sep 11 20:06:29 2007 +0000
@@ -168,7 +168,7 @@
 		switch (event->keyval)
 			{
 			case 'v' : case 'V':
-				view_window_new(layout_image_get_path(lw));
+				view_window_new(layout_image_get_fd(lw));
 				break;
 			default:
 				stop_signal = FALSE;
@@ -326,7 +326,7 @@
 {
 	LayoutWindow *lw = data;
 
-	print_window_new(layout_image_get_path(lw), layout_selection_list(lw), layout_list(lw), lw->window);
+	print_window_new(layout_image_get_fd(lw), layout_selection_list(lw), layout_list(lw), lw->window);
 }
 
 static void layout_menu_dir_cb(GtkAction *action, gpointer data)
@@ -422,12 +422,12 @@
 {
 	LayoutWindow *lw = data;
 	GList *list;
-	const gchar *path = NULL;
+	FileData *fd = NULL;
 
 	list = layout_selection_list(lw);
-	if (!list) path = layout_image_get_path(lw);
+	if (!list) fd = layout_image_get_fd(lw);
 
-	info_window_new(path, list);
+	info_window_new(fd, list);
 }
 
 static void layout_menu_select_all_cb(GtkAction *action, gpointer data)
@@ -630,8 +630,8 @@
 	n = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(action), "edit_index"));
 
 	list = layout_selection_list(lw);
-	start_editor_from_path_list(n, list);
-	path_list_free(list);
+	start_editor_from_filelist(n, list);
+	filelist_free(list);
 }
 
 static void layout_menu_edit_update(LayoutWindow *lw)
@@ -1239,7 +1239,7 @@
 {
 	if (!lw->utility_box) return;
                                                                                                                     
-	lw->bar_info = bar_info_new(layout_image_get_path(lw), FALSE, lw->utility_box);
+	lw->bar_info = bar_info_new(layout_image_get_fd(lw), FALSE, lw->utility_box);
 	bar_info_set_selection_func(lw->bar_info, layout_bar_info_list_cb, lw);
 	bar_info_selection(lw->bar_info, layout_selection_count(lw, NULL) - 1);
 	bar_info_size_request(lw->bar_info, SIDEBAR_WIDTH * 3 / 4);
@@ -1277,7 +1277,7 @@
 {
 	if (!lw->bar_info || !lw->bar_info_enabled) return;
 
-	bar_info_set(lw->bar_info, layout_image_get_path(lw));
+	bar_info_set(lw->bar_info, layout_image_get_fd(lw));
 }
 
 static void layout_bar_info_new_selection(LayoutWindow *lw, gint count)
@@ -1291,7 +1291,7 @@
 {
 	if (!lw->bar_info || !lw->bar_info_enabled) return;
 
-	bar_info_maint_renamed(lw->bar_info, layout_image_get_path(lw));
+	bar_info_maint_renamed(lw->bar_info, layout_image_get_fd(lw));
 }
 
 static void layout_bar_exif_destroyed(GtkWidget *widget, gpointer data)
@@ -1326,7 +1326,7 @@
 {
 	if (!lw->utility_box) return;
 
-	lw->bar_exif = bar_exif_new(TRUE, layout_image_get_path(lw),
+	lw->bar_exif = bar_exif_new(TRUE, layout_image_get_fd(lw),
 				    lw->bar_exif_advanced, lw->utility_box);
 	g_signal_connect(G_OBJECT(lw->bar_exif), "destroy",
 			 G_CALLBACK(layout_bar_exif_destroyed), lw);
@@ -1367,7 +1367,7 @@
 {
 	if (!lw->bar_exif || !lw->bar_exif_enabled) return;
 
-	bar_exif_set(lw->bar_exif, layout_image_get_path(lw));
+	bar_exif_set(lw->bar_exif, layout_image_get_fd(lw));
 }
 
 static void layout_bar_sort_destroyed(GtkWidget *widget, gpointer data)
--- a/src/main.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/main.c	Tue Sep 11 20:06:29 2007 +0000
@@ -435,7 +435,7 @@
 
 static void gr_file_view(const gchar *text, gpointer data)
 {
-	view_window_new(text);
+	view_window_new(file_data_new_simple(text));
 }
 
 static void gr_list_clear(const gchar *text, gpointer data)
@@ -466,7 +466,7 @@
 		new = (!collection_get_first(gqview_command_collection));
 		}
 
-	if (collection_add(gqview_command_collection, text, FALSE) && new)
+	if (collection_add(gqview_command_collection, file_data_new_simple(text), FALSE) && new)
 		{
 		layout_image_set_collection(NULL, gqview_command_collection,
 					    collection_get_first(gqview_command_collection));
@@ -1380,7 +1380,7 @@
 		work = cmd_list;
 		while (work)
 			{
-			collection_add(cd, (gchar *)work->data, FALSE);
+			collection_add(cd, file_data_new_simple((gchar *)work->data), FALSE);
 			work = work->next;
 			}
 
--- a/src/pan-calendar.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/pan-calendar.c	Tue Sep 11 20:06:29 2007 +0000
@@ -142,7 +142,7 @@
 				{
 				PanItem *pimg;
 
-				pimg = pan_item_thumb_new(pw, file_data_new_simple(dot->fd->path), x, y);
+				pimg = pan_item_thumb_new(pw, file_data_ref(dot->fd), x, y);
 				pan_item_set_key(pimg, "day_bubble");
 
 				pan_item_size_by_item(pbox, pimg, PAN_BOX_BORDER);
@@ -204,12 +204,12 @@
 
 	if (pw->cache_list && pw->exif_date_enable)
 		{
-		pw->cache_list = filelist_sort(pw->cache_list, SORT_NAME, TRUE);
+		pw->cache_list = pan_cache_sort(pw->cache_list, SORT_NAME, TRUE);
 		list = filelist_sort(list, SORT_NAME, TRUE);
 		pan_cache_sync_date(pw, list);
 		}
 
-	pw->cache_list = filelist_sort(pw->cache_list, SORT_TIME, TRUE);
+	pw->cache_list = pan_cache_sort(pw->cache_list, SORT_TIME, TRUE);
 	list = filelist_sort(list, SORT_TIME, TRUE);
 
 	day_max = 0;
--- a/src/pan-item.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/pan-item.c	Tue Sep 11 20:06:29 2007 +0000
@@ -25,7 +25,7 @@
 	if (!pi) return;
 
 	if (pi->pixbuf) g_object_unref(pi->pixbuf);
-	if (pi->fd) file_data_free(pi->fd);
+	if (pi->fd) file_data_unref(pi->fd);
 	g_free(pi->text);
 	g_free(pi->key);
 	g_free(pi->data);
@@ -607,22 +607,20 @@
 	while (work)
 		{
 		PanCacheData *pc;
-		gchar *path;
 
 		pc = work->data;
 		work = work->next;
 
-		path = ((FileData *)pc)->path;
-
 		if (pc->cd && pc->cd->dimensions &&
-		    path && strcmp(path, pi->fd->path) == 0)
+		    pc->fd && pc->fd == pi->fd)
 			{
 			pi->width = MAX(1, pc->cd->width * pw->image_size / 100);
 			pi->height = MAX(1, pc->cd->height * pw->image_size / 100);
 
 			pw->cache_list = g_list_remove(pw->cache_list, pc);
 			cache_sim_data_free(pc->cd);
-			file_data_free((FileData *)pc);
+			file_data_unref(pc->fd);
+			g_free(pc);
 			return;
 			}
 		}
--- a/src/pan-timeline.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/pan-timeline.c	Tue Sep 11 20:06:29 2007 +0000
@@ -33,12 +33,12 @@
 
 	if (pw->cache_list && pw->exif_date_enable)
 		{
-		pw->cache_list = filelist_sort(pw->cache_list, SORT_NAME, TRUE);
+		pw->cache_list = pan_cache_sort(pw->cache_list, SORT_NAME, TRUE);
 		list = filelist_sort(list, SORT_NAME, TRUE);
 		pan_cache_sync_date(pw, list);
 		}
 
-	pw->cache_list = filelist_sort(pw->cache_list, SORT_TIME, TRUE);
+	pw->cache_list = pan_cache_sort(pw->cache_list, SORT_TIME, TRUE);
 	list = filelist_sort(list, SORT_TIME, TRUE);
 
 	*width = PAN_BOX_BORDER * 2;
--- a/src/pan-types.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/pan-types.h	Tue Sep 11 20:06:29 2007 +0000
@@ -239,7 +239,7 @@
 
 typedef struct _PanCacheData PanCacheData;
 struct _PanCacheData {
-	FileData fd;
+	FileData *fd;
 	CacheData *cd;
 };
 
@@ -251,7 +251,7 @@
 
 void pan_cache_sync_date(PanWindow *pw, GList *list);
 
-
+GList *pan_cache_sort(GList *list, SortType method, gint ascend);
 /* pan-item.c */
 
 void pan_item_free(PanItem *pi);
--- a/src/pan-util.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/pan-util.c	Tue Sep 11 20:06:29 2007 +0000
@@ -244,7 +244,7 @@
 			folders = g_list_concat(dlist, folders);
 			}
 
-		file_data_free(fd);
+		file_data_unref(fd);
 		}
 
 	return result;
--- a/src/pan-view.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/pan-view.c	Tue Sep 11 20:06:29 2007 +0000
@@ -196,7 +196,7 @@
 
 	if (pi->type == PAN_ITEM_IMAGE)
 		{
-		pw->il = image_loader_new(pi->fd->path);
+		pw->il = image_loader_new(pi->fd);
 
 		if (pw->size != PAN_IMAGE_SIZE_100)
 			{
@@ -520,6 +520,18 @@
  *-----------------------------------------------------------------------------
  */
 
+static gint pan_cache_sort_file_cb(void *a, void *b)
+{
+	PanCacheData *pca = a;
+	PanCacheData *pcb = b;
+	return filelist_sort_compare_filedata(pca->fd, pcb->fd);
+}
+GList *pan_cache_sort(GList *list, SortType method, gint ascend)
+{
+	return filelist_sort_full(list, method, ascend, (GCompareFunc) pan_cache_sort_file_cb);
+}
+
+
 static void pan_cache_free(PanWindow *pw)
 {
 	GList *work;
@@ -533,7 +545,8 @@
 		work = work->next;
 
 		cache_sim_data_free(pc->cd);
-		file_data_free((FileData *)pc);
+		file_data_unref(pc->fd);
+		g_free(pc);
 		}
 
 	g_list_free(pw->cache_list);
@@ -612,7 +625,7 @@
 
 	if (!cd->dimensions)
 		{
-		cd->dimensions = image_load_dimensions(fd->path, &cd->width, &cd->height);
+		cd->dimensions = image_load_dimensions(fd, &cd->width, &cd->height);
 		if (enable_thumb_caching &&
 		    cd->dimensions)
 			{
@@ -636,8 +649,7 @@
 		}
 #endif
 	pc = g_new0(PanCacheData, 1);
-	memcpy(pc, fd, sizeof(FileData));
-	g_free(fd);
+	pc->fd = file_data_ref(fd);
 
 	pc->cd = NULL;
 
@@ -648,7 +660,7 @@
 	load_mask = CACHE_LOADER_NONE;
 	if (pw->size > PAN_IMAGE_SIZE_THUMB_LARGE) load_mask |= CACHE_LOADER_DIMENSIONS;
 	if (pw->exif_date_enable) load_mask |= CACHE_LOADER_DATE;
-	pw->cache_cl = cache_loader_new(((FileData *)pc)->path, load_mask,
+	pw->cache_cl = cache_loader_new(pc->fd, load_mask,
 					pan_cache_step_done_cb, pw);
 	return (pw->cache_cl == NULL);
 }
@@ -677,8 +689,7 @@
 			gchar *path;
 
 			pc = needle->data;
-			path = ((FileData *)pc)->path;
-			if (path && strcmp(path, fd->path) == 0)
+			if (pc->fd == fd)
 				{
 				if (pc->cd && pc->cd->have_date && pc->cd->date >= 0)
 					{
@@ -1169,9 +1180,9 @@
  *-----------------------------------------------------------------------------
  */
 
-static const gchar *pan_menu_click_path(PanWindow *pw)
+FileData *pan_menu_click_fd(PanWindow *pw)
 {
-	if (pw->click_pi && pw->click_pi->fd) return pw->click_pi->fd->path;
+	if (pw->click_pi && pw->click_pi->fd) return pw->click_pi->fd;
 	return NULL;
 }
 
@@ -1187,7 +1198,7 @@
 {
 	PanWindow *pw = data;
 	PixbufRenderer *pr;
-	const gchar *path;
+	FileData *fd;
 	gint stop_signal = FALSE;
 	GtkWidget *menu;
 	gint x = 0;
@@ -1196,7 +1207,7 @@
 	gint on_entry;
 
 	pr = PIXBUF_RENDERER(pw->imd->pr);
-	path = pan_menu_click_path(pw);
+	fd = pan_menu_click_fd(pw);
 
 	focused = (pw->fs || GTK_WIDGET_HAS_FOCUS(GTK_WIDGET(pw->imd->widget)));
 	on_entry = (GTK_WIDGET_HAS_FOCUS(pw->path_entry) ||
@@ -1288,19 +1299,19 @@
 				n = 9;
 				break;
 			case 'C': case 'c':
-				if (path) file_util_copy(path, NULL, NULL, GTK_WIDGET(pr));
+				if (fd) file_util_copy(fd, NULL, NULL, GTK_WIDGET(pr));
 				break;
 			case 'M': case 'm':
-				if (path) file_util_move(path, NULL, NULL, GTK_WIDGET(pr));
+				if (fd) file_util_move(fd, NULL, NULL, GTK_WIDGET(pr));
 				break;
 			case 'R': case 'r':
-				if (path) file_util_rename(path, NULL, GTK_WIDGET(pr));
+				if (fd) file_util_rename(fd, NULL, GTK_WIDGET(pr));
 				break;
 			case 'D': case 'd':
-				if (path) file_util_delete(path, NULL, GTK_WIDGET(pr));
+				if (fd) file_util_delete(fd, NULL, GTK_WIDGET(pr));
 				break;
 			case 'P': case 'p':
-				if (path) info_window_new(path, NULL);
+				if (fd) info_window_new(fd, NULL);
 				break;
 			case 'F': case 'f':
 				pan_search_toggle_visible(pw, TRUE);
@@ -1316,13 +1327,13 @@
 				break;
 			}
 
-		if (n != -1 && path)
+		if (n != -1 && fd)
 			{
 			if (!editor_window_flag_set(n))
 				{
 				pan_fullscreen_toggle(pw, TRUE);
 				}
-			start_editor_from_file(n, path);
+			start_editor_from_file(n, fd);
 			}
 		}
 	else
@@ -1423,7 +1434,7 @@
 	gint i;
 
 	if (!fd) return;
-	exif = exif_read(fd->path, FALSE);
+	exif = exif_read(fd, FALSE);
 	if (!exif) return;
 
 	pan_text_alignment_add(ta, NULL, NULL);
@@ -1541,7 +1552,7 @@
 	if (pw->info_image_size > PAN_IMAGE_SIZE_THUMB_NONE)
 		{
 		gint iw, ih;
-		if (image_load_dimensions(pi->fd->path, &iw, &ih))
+		if (image_load_dimensions(pi->fd, &iw, &ih))
 			{
 			gint scale = 25;
 
@@ -2625,44 +2636,44 @@
 static void pan_new_window_cb(GtkWidget *widget, gpointer data)
 {
 	PanWindow *pw = data;
-	const gchar *path;
-
-	path = pan_menu_click_path(pw);
-	if (path)
+	FileData *fd;
+
+	fd = pan_menu_click_fd(pw);
+	if (fd)
 		{
 		pan_fullscreen_toggle(pw, TRUE);
-		view_window_new(path);
+		view_window_new(fd);
 		}
 }
 
 static void pan_edit_cb(GtkWidget *widget, gpointer data)
 {
 	PanWindow *pw;
-	const gchar *path;
+	FileData *fd;
 	gint n;
 
 	pw = submenu_item_get_data(widget);
 	n = GPOINTER_TO_INT(data);
 	if (!pw) return;
 
-	path = pan_menu_click_path(pw);
-	if (path)
+	fd = pan_menu_click_fd(pw);
+	if (fd)
 		{
 		if (!editor_window_flag_set(n))
 			{
 			pan_fullscreen_toggle(pw, TRUE);
 			}
-		start_editor_from_file(n, path);
+		start_editor_from_file(n, fd);
 		}
 }
 
 static void pan_info_cb(GtkWidget *widget, gpointer data)
 {
 	PanWindow *pw = data;
-	const gchar *path;
-
-	path = pan_menu_click_path(pw);
-	if (path) info_window_new(path, NULL);
+	FileData *fd;
+
+	fd = pan_menu_click_fd(pw);
+	if (fd) info_window_new(fd, NULL);
 }
 
 static void pan_zoom_in_cb(GtkWidget *widget, gpointer data)
@@ -2689,37 +2700,37 @@
 static void pan_copy_cb(GtkWidget *widget, gpointer data)
 {
 	PanWindow *pw = data;
-	const gchar *path;
-
-	path = pan_menu_click_path(pw);
-	if (path) file_util_copy(path, NULL, NULL, pw->imd->widget);
+	FileData *fd;
+
+	fd = pan_menu_click_fd(pw);
+	if (fd) file_util_copy(fd, NULL, NULL, pw->imd->widget);
 }
 
 static void pan_move_cb(GtkWidget *widget, gpointer data)
 {
 	PanWindow *pw = data;
-	const gchar *path;
-
-	path = pan_menu_click_path(pw);
-	if (path) file_util_move(path, NULL, NULL, pw->imd->widget);
+	FileData *fd;
+
+	fd = pan_menu_click_fd(pw);
+	if (fd) file_util_move(fd, NULL, NULL, pw->imd->widget);
 }
 
 static void pan_rename_cb(GtkWidget *widget, gpointer data)
 {
 	PanWindow *pw = data;
-	const gchar *path;
-
-	path = pan_menu_click_path(pw);
-	if (path) file_util_rename(path, NULL, pw->imd->widget);
+	FileData *fd;
+
+	fd = pan_menu_click_fd(pw);
+	if (fd) file_util_rename(fd, NULL, pw->imd->widget);
 }
 
 static void pan_delete_cb(GtkWidget *widget, gpointer data)
 {
 	PanWindow *pw = data;
-	const gchar *path;
-
-	path = pan_menu_click_path(pw);
-	if (path) file_util_delete(path, NULL, pw->imd->widget);
+	FileData *fd;
+
+	fd = pan_menu_click_fd(pw);
+	if (fd) file_util_delete(fd, NULL, pw->imd->widget);
 }
 
 static void pan_exif_date_toggle_cb(GtkWidget *widget, gpointer data)
@@ -2874,15 +2885,15 @@
 		{
 		GList *list;
 
-		list = uri_list_from_text((gchar *)selection_data->data, TRUE);
-		if (list && isdir((gchar *)list->data))
+		list = uri_filelist_from_text((gchar *)selection_data->data, TRUE);
+		if (list && isdir(((FileData *)list->data)->path))
 			{
-			gchar *path = list->data;
-
-			pan_layout_set_path(pw, path);
+			FileData *fd = list->data;
+
+			pan_layout_set_path(pw, fd->path);
 			}
 
-		path_list_free(list);
+		filelist_free(list);
 		}
 }
 
@@ -2891,10 +2902,10 @@
 				    guint time, gpointer data)
 {
 	PanWindow *pw = data;
-	const gchar *path;
-
-	path = pan_menu_click_path(pw);
-	if (path)
+	FileData *fd;
+
+	fd = pan_menu_click_fd(pw);
+	if (fd)
 		{
 		gchar *text = NULL;
 		gint len;
@@ -2911,8 +2922,8 @@
 				plain_text = TRUE;
 				break;
 			}
-		list = g_list_append(NULL, (gchar *)path);
-		text = uri_text_from_list(list, &len, plain_text);
+		list = g_list_append(NULL, fd);
+		text = uri_text_from_filelist(list, &len, plain_text);
 		g_list_free(list);
 		if (text)
 			{
--- a/src/print.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/print.c	Tue Sep 11 20:06:29 2007 +0000
@@ -180,7 +180,7 @@
 {
 	GenericDialog *dialog;
 
-	gchar *source_path;
+	FileData *source_fd;
 	GList *source_selection;
 	GList *source_list;
 
@@ -654,7 +654,7 @@
 			break;
 		case PRINT_SOURCE_IMAGE:
 		default:
-			images = (pw->source_path) ? 1 : 0;
+			images = (pw->source_fd) ? 1 : 0;
 			break;
 		}
 
@@ -2030,7 +2030,7 @@
 	if (pw->text_fields == 0) return TRUE;
 
 	string = g_string_new("");
-	path = pw->job_loader->path;
+	path = pw->job_loader->fd->path;
 
 	if (pw->text_fields & TEXT_INFO_FILENAME)
 		{
@@ -2048,7 +2048,7 @@
 		{
 		if (newline)  g_string_append(string, "\n");
 		if (space) g_string_append(string, " - ");
-		g_string_append(string, text_from_time(filetime(pw->job_loader->path)));
+		g_string_append(string, text_from_time(filetime(pw->job_loader->fd->path)));
 		newline = proof;
 		space = !proof;
 		}
@@ -2058,7 +2058,7 @@
 
 		if (newline)  g_string_append(string, "\n");
 		if (space) g_string_append(string, " - ");
-		size = text_from_size_abrev(filesize(pw->job_loader->path));
+		size = text_from_size_abrev(filesize(pw->job_loader->fd->path));
 		g_string_append(string, size);
 		g_free(size);
 		}
@@ -2139,7 +2139,7 @@
 		y = y + h + PRINT_TEXT_PADDING;
 
 		success = (success &&
-			   print_job_text_image(pw, pw->job_loader->path, x, y, dw, sw, sh, FALSE));
+			   print_job_text_image(pw, pw->job_loader->fd->path, x, y, dw, sw, sh, FALSE));
 		}
 
 	image_loader_free(pw->job_loader);
@@ -2173,28 +2173,28 @@
 
 static gint print_job_render_image(PrintWindow *pw)
 {
-	gchar *path = NULL;
+	FileData *fd = NULL;
 
 	switch (pw->source)
 		{
 		case PRINT_SOURCE_SELECTION:
-			path = g_list_nth_data(pw->source_selection, pw->job_page);
+			fd = g_list_nth_data(pw->source_selection, pw->job_page);
 			break;
 		case PRINT_SOURCE_ALL:
-			path = g_list_nth_data(pw->source_list, pw->job_page);
+			fd = g_list_nth_data(pw->source_list, pw->job_page);
 			break;
 		case PRINT_SOURCE_IMAGE:
 		default:
-			if (pw->job_page == 0) path = pw->source_path;
+			if (pw->job_page == 0) fd = pw->source_fd;
 			break;
 		}
 
 	image_loader_free(pw->job_loader);
 	pw->job_loader = NULL;
 
-	if (!path) return FALSE;
-
-	pw->job_loader = image_loader_new(path);
+	if (!fd) return FALSE;
+
+	pw->job_loader = image_loader_new(fd);
 	if (!image_loader_start(pw->job_loader, print_job_render_image_loader_done, pw))
 		{
 		image_loader_free(pw->job_loader);
@@ -2260,7 +2260,7 @@
 	y = y + icon_h + (pw->proof_height - icon_h) / 2 + PRINT_TEXT_PADDING;
 
 	success = (success && 
-		   print_job_text_image(pw, pw->job_loader->path, x, y, icon_w + PRINT_PROOF_MARGIN * 2, w, h, TRUE));
+		   print_job_text_image(pw, pw->job_loader->fd->path, x, y, icon_w + PRINT_PROOF_MARGIN * 2, w, h, TRUE));
 
 	if (!success)
 		{
@@ -2323,24 +2323,24 @@
 
 static gint print_job_render_proof(PrintWindow *pw)
 {
-	gchar *path = NULL;
+	FileData *fd = NULL;
 
 	if (pw->proof_columns < 1 || pw->proof_rows < 1) return FALSE;
 
 	if (!pw->proof_point && pw->proof_position == 0 && pw->source == PRINT_SOURCE_IMAGE)
 		{
-		path = pw->source_path;
+		fd = pw->source_fd;
 		}
 	else if (pw->proof_point &&
 		 pw->proof_position < pw->proof_columns * pw->proof_rows)
 		{
-		path = pw->proof_point->data;
+		fd = pw->proof_point->data;
 		}
 
-	if (!path) return FALSE;
+	if (!fd) return FALSE;
 
 	image_loader_free(pw->job_loader);
-	pw->job_loader = image_loader_new(path);
+	pw->job_loader = image_loader_new(fd);
 	if (!image_loader_start(pw->job_loader, print_job_render_proof_loader_done, pw))
 		{
 		image_loader_free(pw->job_loader);
@@ -2989,7 +2989,7 @@
 		gtk_combo_box_append_text(GTK_COMBO_BOX(combo), buf);
 		g_free(buf);
 		}
-	path_list_free(list);
+	string_list_free(list);
 
 	if (pref_list_string_get(PRINT_PREF_GROUP, PRINT_PREF_PRINTERC, &text))
 		{
@@ -3239,9 +3239,9 @@
 
 	print_job_close(pw, FALSE);
 
-	g_free(pw->source_path);
-	path_list_free(pw->source_selection);
-	path_list_free(pw->source_list);
+	file_data_unref(pw->source_fd);
+	filelist_free(pw->source_selection);
+	filelist_free(pw->source_list);
 
 	g_free(pw->output_path);
 	g_free(pw->output_custom);
@@ -3295,7 +3295,7 @@
 	return fallback;
 }
 
-void print_window_new(const gchar *path, GList *selection, GList *list, GtkWidget *parent)
+void print_window_new(FileData *fd, GList *selection, GList *list, GtkWidget *parent)
 {
 	PrintWindow *pw;
 	GdkGeometry geometry;
@@ -3308,7 +3308,7 @@
 
 	pw = g_new0(PrintWindow, 1);
 
-	pw->source_path = g_strdup(path);
+	pw->source_fd = file_data_ref(fd);
 	pw->source_selection = selection;
 	pw->source_list = list;
 
--- a/src/print.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/print.h	Tue Sep 11 20:06:29 2007 +0000
@@ -15,7 +15,7 @@
 
 
 /* do not free selection or list, the print window takes control of them */
-void print_window_new(const gchar *path, GList *selection, GList *list, GtkWidget *parent);
+void print_window_new(FileData *fd, GList *selection, GList *list, GtkWidget *parent);
 
 
 #endif
--- a/src/search.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/search.c	Tue Sep 11 20:06:29 2007 +0000
@@ -183,7 +183,7 @@
 typedef struct _MatchFileData MatchFileData;
 struct _MatchFileData
 {
-	FileData fd;
+	FileData *fd;
 	gint width;
 	gint height;
 	gint rank;
@@ -333,11 +333,11 @@
 	valid = gtk_tree_model_get_iter_first(store, iter);
 	while (valid)
 		{
-		FileData *fd_n;
+		MatchFileData *mfd;
 		n++;
 
-		gtk_tree_model_get(store, iter, SEARCH_COLUMN_POINTER, &fd_n, -1);
-		if (fd_n == fd) return n;
+		gtk_tree_model_get(store, iter, SEARCH_COLUMN_POINTER, &mfd, -1);
+		if (mfd->fd == fd) return n;
 		valid = gtk_tree_model_iter_next(store, iter);
 		}
 
@@ -358,12 +358,12 @@
 	while (!found && work)
 		{
 		GtkTreePath *tpath = work->data;
-		FileData *fd_n;
+		MatchFileData *mfd_n;
 		GtkTreeIter iter;
 
 		gtk_tree_model_get_iter(store, &iter, tpath);
-		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &fd_n, -1);
-		if (fd_n == fd) found = TRUE;
+		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd_n, -1);
+		if (mfd_n->fd == fd) found = TRUE;
 		work = work->next;
 		}
 	g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
@@ -393,14 +393,14 @@
 		if (bytes || list)
 			{
 			GtkTreePath *tpath = work->data;
-			FileData *fd;
+			MatchFileData *mfd;
 			GtkTreeIter iter;
 
 			gtk_tree_model_get_iter(store, &iter, tpath);
-			gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &fd, -1);
-			total += fd->size;
-
-			if (list) plist = g_list_prepend(plist, g_strdup(fd->path));
+			gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1);
+			total += mfd->fd->size;
+
+			if (list) plist = g_list_prepend(plist, file_data_ref(mfd->fd));
 			}
 			
 		work = work->next;
@@ -444,12 +444,12 @@
 		n++;
 		if (bytes || list)
 			{
-			FileData *fd;
-
-			gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &fd, -1);
-			total += fd->size;
-
-			if (list) plist = g_list_prepend(plist, g_strdup(fd->path));
+			MatchFileData *mfd;
+
+			gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1);
+			total += mfd->fd->size;
+
+			if (list) plist = g_list_prepend(plist, file_data_ref(mfd->fd));
 			}
 		valid = gtk_tree_model_iter_next(store, &iter);
 		}
@@ -460,7 +460,7 @@
 	return n;
 }
 
-static GList *search_result_get_path_list(SearchData *sd)
+static GList *search_result_get_filelist(SearchData *sd)
 {
 	GList *list = NULL;
 
@@ -481,7 +481,7 @@
 	gchar *text_size;
 	gchar *text_dim = NULL;
 
-	fd = (FileData *)mfd;
+	fd = mfd->fd;
 
 	if (!fd) return;
 
@@ -491,7 +491,7 @@
 	store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view)));
 	gtk_list_store_append(store, &iter);
 	gtk_list_store_set(store, &iter,
-				SEARCH_COLUMN_POINTER, fd,
+				SEARCH_COLUMN_POINTER, mfd,
 				SEARCH_COLUMN_RANK, mfd->rank,
 				SEARCH_COLUMN_THUMB, fd->pixbuf,
 				SEARCH_COLUMN_NAME, fd->name,
@@ -517,10 +517,10 @@
 	valid = gtk_tree_model_get_iter_first(store, &iter);
 	while (valid)
 		{
-		FileData *fd;
-
-		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &fd, -1);
-		list = g_list_prepend(list, fd);
+		MatchFileData *mfd;
+
+		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1);
+		list = g_list_prepend(list, mfd->fd);
 
 		valid = gtk_tree_model_iter_next(store, &iter);
 		}
@@ -534,10 +534,11 @@
 static gboolean search_result_free_node(GtkTreeModel *store, GtkTreePath *tpath,
 					GtkTreeIter *iter, gpointer data)
 {
-	FileData *fd;
-
-	gtk_tree_model_get(store, iter, SEARCH_COLUMN_POINTER, &fd, -1);
-	file_data_free(fd);
+	MatchFileData *mfd;
+
+	gtk_tree_model_get(store, iter, SEARCH_COLUMN_POINTER, &mfd, -1);
+	file_data_unref(mfd->fd);
+	g_free(mfd);
 
 	return FALSE;
 }
@@ -560,20 +561,21 @@
 	search_status_update(sd);
 }
 
-static void search_result_remove_item(SearchData *sd, FileData *fd, GtkTreeIter *iter)
+static void search_result_remove_item(SearchData *sd, MatchFileData *mfd, GtkTreeIter *iter)
 {
 	GtkTreeModel *store;
 
-	if (!fd || !iter) return;
+	if (!mfd || !iter) return;
 
 	store = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view));
 
 	tree_view_move_cursor_away(GTK_TREE_VIEW(sd->result_view), iter, TRUE);
 
 	gtk_list_store_remove(GTK_LIST_STORE(store), iter);
-	if (sd->click_fd == fd) sd->click_fd = NULL;
-	if (sd->thumb_fd == fd) sd->thumb_fd = NULL;
-	file_data_free(fd);
+	if (sd->click_fd == mfd->fd) sd->click_fd = NULL;
+	if (sd->thumb_fd == mfd->fd) sd->thumb_fd = NULL;
+	file_data_unref(mfd->fd);
+	g_free(mfd);
 }
 
 static void search_result_remove(SearchData *sd, FileData *fd)
@@ -586,12 +588,12 @@
 	valid = gtk_tree_model_get_iter_first(store, &iter);
 	while (valid)
 		{
-		FileData *fd_n;
-
-		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &fd_n, -1);
-		if (fd_n == fd)
+		MatchFileData *mfd;
+
+		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1);
+		if (mfd->fd == fd)
 			{
-			search_result_remove_item(sd, fd_n, &iter);
+			search_result_remove_item(sd, mfd, &iter);
 			return;
 			}
 
@@ -614,11 +616,11 @@
 		{
 		GtkTreePath *tpath = work->data;
 		GtkTreeIter iter;
-		FileData *fd;
+		MatchFileData *mfd;
 
 		gtk_tree_model_get_iter(store, &iter, tpath);
-		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &fd, -1);
-		flist = g_list_prepend(flist, fd);
+		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1);
+		flist = g_list_prepend(flist, mfd->fd);
 		work = work->next;
 		}
 	g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
@@ -642,8 +644,8 @@
 	GList *list;
 
 	list = search_result_selection_list(sd);
-	start_editor_from_path_list(n, list);
-	path_list_free(list);
+	start_editor_from_filelist(n, list);
+	filelist_free(list);
 }
 
 static void search_result_collection_from_selection(SearchData *sd)
@@ -653,8 +655,8 @@
 
 	list = search_result_selection_list(sd);
 	w = collection_window_new(NULL);
-	collection_table_add_path_list(w->table, list);
-	path_list_free(list);
+	collection_table_add_filelist(w->table, list);
+	filelist_free(list);
 }
 
 static gint search_result_update_idle_cb(gpointer data)
@@ -734,7 +736,7 @@
 {
 	GtkTreeModel *store;
 	GtkTreeIter iter;
-	FileData *fd = NULL;
+	MatchFileData *mfd = NULL;
 	gint valid;
 	gint row = 0;
 	gint length = 0;
@@ -744,17 +746,17 @@
 	store = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->result_view));
 
 	valid = gtk_tree_model_get_iter_first(store, &iter);
-	while (!fd && valid)
+	while (!mfd && valid)
 		{
 		GdkPixbuf *pixbuf;
 
 		length++;
-		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &fd, SEARCH_COLUMN_THUMB, &pixbuf, -1);
-		if (pixbuf || fd->pixbuf)
+		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, SEARCH_COLUMN_THUMB, &pixbuf, -1);
+		if (pixbuf || mfd->fd->pixbuf)
 			{
-			if (!pixbuf) gtk_list_store_set(GTK_LIST_STORE(store), &iter, SEARCH_COLUMN_THUMB, fd->pixbuf, -1);
+			if (!pixbuf) gtk_list_store_set(GTK_LIST_STORE(store), &iter, SEARCH_COLUMN_THUMB, mfd->fd->pixbuf, -1);
 			row++;
-			fd = NULL;
+			mfd = NULL;
 			}
 		valid = gtk_tree_model_iter_next(store, &iter);
 		}
@@ -763,7 +765,7 @@
 		while (gtk_tree_model_iter_next(store, &iter)) length++;
 		}
 
-	if (!fd)
+	if (!mfd)
 		{
 		sd->thumb_fd = NULL;
 		thumb_loader_free(sd->thumb_loader);
@@ -775,7 +777,7 @@
 
 	search_progress_update(sd, FALSE, (gdouble)row/length);
 
-	sd->thumb_fd = fd;
+	sd->thumb_fd = mfd->fd;
 	thumb_loader_free(sd->thumb_loader);
 	sd->thumb_loader = thumb_loader_new(thumb_max_width, thumb_max_height);
 
@@ -784,7 +786,7 @@
 				   search_result_thumb_done_cb,
 				   NULL,
 				   sd);
-	if (!thumb_loader_start(sd->thumb_loader, fd->path))
+	if (!thumb_loader_start(sd->thumb_loader, mfd->fd->path))
 		{
 		search_result_thumb_do(sd);
 		search_result_thumb_step(sd);
@@ -850,7 +852,7 @@
 {
 	SearchData *sd = data;
 
-	if (sd->click_fd) layout_image_set_path(NULL, sd->click_fd->path);
+	if (sd->click_fd) layout_image_set_fd(NULL, sd->click_fd);
 }
 
 static void sr_menu_viewnew_cb(GtkWidget *widget, gpointer data)
@@ -860,7 +862,7 @@
 
 	list = search_result_selection_list(sd);
 	view_window_new_from_list(list);
-	path_list_free(list);
+	filelist_free(list);
 }
 
 static void sr_menu_select_all_cb(GtkWidget *widget, gpointer data)
@@ -910,12 +912,10 @@
 static void sr_menu_print_cb(GtkWidget *widget, gpointer data)
 {
 	SearchData *sd = data;
-	const gchar *path;
-
-	path = (sd->click_fd) ? sd->click_fd->path : NULL;
-
-	print_window_new(path, search_result_selection_list(sd),
-			 search_result_get_path_list(sd), sd->window);
+	FileData *fd;
+
+	print_window_new(sd->click_fd, search_result_selection_list(sd),
+			 search_result_get_filelist(sd), sd->window);
 }
 
 static void sr_menu_copy_cb(GtkWidget *widget, gpointer data)
@@ -1032,7 +1032,7 @@
 	GtkTreeModel *store;
 	GtkTreePath *tpath;
 	GtkTreeIter iter;
-	FileData *fd = NULL;
+	MatchFileData *mfd = NULL;
 
 	store = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
 
@@ -1040,32 +1040,32 @@
 					  &tpath, NULL, NULL, NULL))
 		{
 		gtk_tree_model_get_iter(store, &iter, tpath);
-		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &fd, -1);
+		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1);
 		gtk_tree_path_free(tpath);
 		}
 
-	sd->click_fd = fd;
+	sd->click_fd = mfd ? mfd->fd : NULL;
 
 	if (bevent->button == 3)
 		{
 		GtkWidget *menu;
 
-		menu = search_result_menu(sd, (fd != NULL), (search_result_count(sd, NULL) == 0));
+		menu = search_result_menu(sd, (mfd != NULL), (search_result_count(sd, NULL) == 0));
 		gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, bevent->button, bevent->time);
 		}
 
-	if (!fd) return FALSE;
+	if (!mfd) return FALSE;
 
 	if (bevent->button == 1 && bevent->type == GDK_2BUTTON_PRESS)
 		{
-		layout_image_set_path(NULL, fd->path);
+		layout_image_set_fd(NULL, mfd->fd);
 		}
 
 	if (bevent->button == 2) return TRUE;
 
 	if (bevent->button == 3)
 		{
-		if (!search_result_row_selected(sd, fd))
+		if (!search_result_row_selected(sd, mfd->fd))
 			{
 			GtkTreeSelection *selection;
 
@@ -1083,7 +1083,7 @@
 	if (bevent->button == 1 && bevent->type == GDK_BUTTON_PRESS &&
 	    !(bevent->state & GDK_SHIFT_MASK ) &&
 	    !(bevent->state & GDK_CONTROL_MASK ) &&
-	    search_result_row_selected(sd, fd))
+	    search_result_row_selected(sd, mfd->fd))
 		{
 		/* this selection handled on release_cb */
 		gtk_widget_grab_focus(widget);
@@ -1100,7 +1100,7 @@
 	GtkTreePath *tpath;
 	GtkTreeIter iter;
 
-	FileData *fd = NULL;
+	MatchFileData *mfd = NULL;
 
 	if (bevent->button != 1 && bevent->button != 2) return TRUE;
 
@@ -1111,18 +1111,18 @@
 					  &tpath, NULL, NULL, NULL))
 		{
 		gtk_tree_model_get_iter(store, &iter, tpath);
-		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &fd, -1);
+		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1);
 		gtk_tree_path_free(tpath);
 		}
 
 	if (bevent->button == 2)
 		{
-		if (fd && sd->click_fd == fd)
+		if (mfd && sd->click_fd == mfd->fd)
 			{
 			GtkTreeSelection *selection;
 
 			selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
-			if (search_result_row_selected(sd, fd))
+			if (search_result_row_selected(sd, mfd->fd))
 				{
 				gtk_tree_selection_unselect_iter(selection, &iter);
 				}
@@ -1134,10 +1134,10 @@
 		return TRUE;
 		}
 
-	if (fd && sd->click_fd == fd &&
+	if (mfd && sd->click_fd == mfd->fd &&
 	    !(bevent->state & GDK_SHIFT_MASK ) &&
 	    !(bevent->state & GDK_CONTROL_MASK ) &&
-	    search_result_row_selected(sd, fd))
+	    search_result_row_selected(sd, mfd->fd))
 		{
 		GtkTreeSelection *selection;
 
@@ -1162,7 +1162,7 @@
 	GtkTreeModel *store;
 	GtkTreeSelection *selection;
 	GList *slist;
-	FileData *fd = NULL;
+	MatchFileData *mfd = NULL;
 
 	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(sd->result_view));
 	slist = gtk_tree_selection_get_selected_rows(selection, &store);
@@ -1177,7 +1177,7 @@
 
 		/* last is newest selected file */
 		gtk_tree_model_get_iter(store, &iter, tpath);
-		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &fd, -1);
+		gtk_tree_model_get(store, &iter, SEARCH_COLUMN_POINTER, &mfd, -1);
 		}
 	g_list_foreach(slist, (GFunc)gtk_tree_path_free, NULL);
 	g_list_free(slist);
@@ -1263,7 +1263,7 @@
 		switch (event->keyval)
 			{
 			case GDK_Return: case GDK_KP_Enter:
-				if (fd) layout_image_set_path(NULL, fd->path);
+				if (mfd) layout_image_set_fd(NULL, mfd->fd);
 				break;
 			case 'V': case 'v':
 				{
@@ -1271,7 +1271,7 @@
 
 				list = search_result_selection_list(sd);
 				view_window_new_from_list(list);
-				path_list_free(list);
+				filelist_free(list);
 				}
 				break;
 			case GDK_Delete: case GDK_KP_Delete:
@@ -1285,8 +1285,8 @@
 				{
 				GtkWidget *menu;
 
-				sd->click_fd = fd;
-				menu = search_result_menu(sd, (fd != NULL), (search_result_count(sd, NULL) > 0));
+				sd->click_fd = mfd->fd;
+				menu = search_result_menu(sd, (mfd != NULL), (search_result_count(sd, NULL) > 0));
 				gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
 					       search_result_menu_pos_cb, sd, 0, GDK_CURRENT_TIME);
 				}
@@ -1353,8 +1353,8 @@
 		case TARGET_TEXT_PLAIN:
 			list = search_result_selection_list(sd);
 			if (!list) return;
-			uri_text = uri_text_from_list(list, &length, (info == TARGET_TEXT_PLAIN));
-			path_list_free(list);
+			uri_text = uri_text_from_filelist(list, &length, (info == TARGET_TEXT_PLAIN));
+			filelist_free(list);
 			break;
 		default:
 			uri_text = NULL;
@@ -1502,13 +1502,13 @@
 			}
 
 		if (enable_thumb_caching &&
-		    sd->img_loader && sd->img_loader->path)
+		    sd->img_loader && sd->img_loader->fd)
 			{
 			gchar *base;
 			const gchar *path;
 			mode_t mode = 0755;
 
-			path = sd->img_loader->path;
+			path = sd->img_loader->fd->path;
 			base = cache_get_location(CACHE_TYPE_SIM, path, FALSE, &mode);
 			if (cache_ensure_dir_exists(base, mode))
 				{
@@ -1516,7 +1516,7 @@
 				cd->path = cache_get_location(CACHE_TYPE_SIM, path, TRUE, NULL);
 				if (cache_sim_data_save(cd))
 					{
-					filetime_set(cd->path, filetime(sd->img_loader->path));
+					filetime_set(cd->path, filetime(sd->img_loader->fd->path));
 					}
 				}
 			g_free(base);
@@ -1566,7 +1566,7 @@
 		if ((sd->match_dimensions_enable && !sd->img_cd->dimensions) ||
 		    (sd->match_similarity_enable && !sd->img_cd->similarity))
 			{
-			sd->img_loader = image_loader_new(fd->path);
+			sd->img_loader = image_loader_new(fd);
 			image_loader_set_error_func(sd->img_loader, search_file_load_done_cb, sd);
 			if (image_loader_start(sd->img_loader, search_file_load_done_cb, sd))
 				{
@@ -1772,7 +1772,7 @@
 		tested = TRUE;
 		match = FALSE;
 
-		if (comment_cache_read(fd->path, &list, NULL))
+		if (comment_cache_read(fd, &list, NULL))
 			{
 			GList *needle;
 			GList *haystack;
@@ -1835,7 +1835,7 @@
 
 				match = !found;
 				}
-			path_list_free(list);
+			string_list_free(list);
 			}
 		else
 			{
@@ -1862,8 +1862,7 @@
 		MatchFileData *mfd;
 
 		mfd = g_new(MatchFileData, 1);
-		memcpy(mfd, fd, sizeof(FileData));
-		g_free(fd);
+		mfd->fd = fd;
 
 		mfd->width = width;
 		mfd->height = height;
@@ -1876,7 +1875,7 @@
 		}
 	else
 		{
-		file_data_free(fd);
+		file_data_unref(fd);
 		sd->search_buffer_count += SEARCH_BUFFER_MATCH_MISS;
 		}
 
@@ -1956,7 +1955,7 @@
 					if (!meta_path)
 						{
 						list = g_list_delete_link(list, link);
-						file_data_free(fdp);
+						file_data_unref(fdp);
 						}
 					g_free(meta_path);
 					}
@@ -1983,7 +1982,7 @@
 		{
 		sd->search_folder_list = g_list_remove(sd->search_folder_list, fd);
 		sd->search_done_list = g_list_remove(sd->search_done_list, fd);
-		file_data_free(fd);
+		file_data_unref(fd);
 		}
 
 	return TRUE;
@@ -2043,7 +2042,7 @@
 				sd->search_similarity_cd = cache_sim_data_new();
 				}
 
-			sd->img_loader = image_loader_new(sd->search_similarity_path);
+			sd->img_loader = image_loader_new(file_data_new_simple(sd->search_similarity_path));
 			image_loader_set_error_func(sd->img_loader, search_similarity_load_done_cb, sd);
 			if (image_loader_start(sd->img_loader, search_similarity_load_done_cb, sd))
 				{
@@ -2089,7 +2088,7 @@
 		tab_completion_append_to_history(sd->entry_similarity, sd->search_similarity_path);
 		}
 
-	path_list_free(sd->search_keyword_list);
+	string_list_free(sd->search_keyword_list);
 	sd->search_keyword_list = keyword_list_pull(sd->entry_keywords);
 
 	date_selection_get(sd->date_sel, &sd->search_date_d, &sd->search_date_m, &sd->search_date_y);
@@ -2194,8 +2193,8 @@
 static gint search_result_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
 {
 	gint n = GPOINTER_TO_INT(data);
-	FileData *fda;
-	FileData *fdb;
+	MatchFileData *fda;
+	MatchFileData *fdb;
 
 	gtk_tree_model_get(model, a, SEARCH_COLUMN_POINTER, &fda, -1);
 	gtk_tree_model_get(model, b, SEARCH_COLUMN_POINTER, &fdb, -1);
@@ -2205,28 +2204,28 @@
 	switch (n)
 		{
 		case SEARCH_COLUMN_RANK:
-			if (((MatchFileData *)fda)->rank > ((MatchFileData *)fdb)->rank) return 1;
-			if (((MatchFileData *)fda)->rank < ((MatchFileData *)fdb)->rank) return -1;
+			if (((MatchFileData *)fda)->rank > (fdb)->rank) return 1;
+			if (((MatchFileData *)fda)->rank < (fdb)->rank) return -1;
 			return 0;
 			break;
 		case SEARCH_COLUMN_NAME:
-			return CASE_SORT(fda->name, fdb->name);
+			return CASE_SORT(fda->fd->name, fdb->fd->name);
 			break;
 		case SEARCH_COLUMN_SIZE:
-			if (fda->size > fdb->size) return 1;
-			if (fda->size < fdb->size) return -1;
+			if (fda->fd->size > fdb->fd->size) return 1;
+			if (fda->fd->size < fdb->fd->size) return -1;
 			return 0;
 			break;
 		case SEARCH_COLUMN_DATE:
-			if (fda->date > fdb->date) return 1;
-			if (fda->date < fdb->date) return -1;
+			if (fda->fd->date > fdb->fd->date) return 1;
+			if (fda->fd->date < fdb->fd->date) return -1;
 			return 0;
 			break;
 		case SEARCH_COLUMN_DIMENSIONS:
-			return sort_matchdata_dimensions((MatchFileData *)fda, (MatchFileData *)fdb);
+			return sort_matchdata_dimensions(fda, fdb);
 			break;
 		case SEARCH_COLUMN_PATH:
-			return CASE_SORT(fda->path, fdb->path);
+			return CASE_SORT(fda->fd->path, fdb->fd->path);
 			break;
 		default:
 			break;
@@ -2500,7 +2499,7 @@
 	g_free(sd->search_path);
 	g_free(sd->search_name);
 	g_free(sd->search_similarity_path);
-	path_list_free(sd->search_keyword_list);
+	string_list_free(sd->search_keyword_list);
 
 	g_free(sd);
 }
@@ -2801,7 +2800,7 @@
  *-------------------------------------------------------------------
  */
 
-static void search_result_change_path(SearchData *sd, const gchar *path, const gchar *newpath)
+static void search_result_change_path(SearchData *sd, FileData *fd)
 {
 	GtkTreeModel *store;
 	GtkTreeIter iter;
@@ -2812,33 +2811,29 @@
 	while (valid)
 		{
 		GtkTreeIter current;
-		FileData *fd;
+		MatchFileData *mfd;
 
 		current = iter;
 		valid = gtk_tree_model_iter_next(store, &iter);
 
-		gtk_tree_model_get(store, &current, SEARCH_COLUMN_POINTER, &fd, -1);
-		if (strcmp(fd->path, path) == 0)
+		gtk_tree_model_get(store, &current, SEARCH_COLUMN_POINTER, &mfd, -1);
+		if (mfd->fd == fd)
 			{
-			if (newpath)
+			if (fd->change && fd->change->dest)
 				{
-				g_free(fd->path);
-				fd->path = g_strdup(newpath);
-				fd->name = filename_from_path(fd->path);
-
 				gtk_list_store_set(GTK_LIST_STORE(store), &current,
-						   SEARCH_COLUMN_NAME, fd->name,
-						   SEARCH_COLUMN_PATH, fd->path, -1);
+						   SEARCH_COLUMN_NAME, mfd->fd->name,
+						   SEARCH_COLUMN_PATH, mfd->fd->path, -1);
 				}
 			else
 				{
-				search_result_remove_item(sd, fd, &current);
+				search_result_remove_item(sd, mfd, &current);
 				}
 			}
 		}
 }
 
-void search_maint_renamed(const gchar *source, const gchar *dest)
+void search_maint_renamed(FileData *fd)
 {
 	GList *work;
 
@@ -2848,12 +2843,12 @@
 		SearchData *sd = work->data;
 		work = work->next;
 
-		search_result_change_path(sd, source, dest);
+		search_result_change_path(sd, fd);
 		}
 }
 
-void search_maint_removed(const gchar *path)
+void search_maint_removed(FileData *fd)
 {
-	search_maint_renamed(path, NULL);
+	search_maint_renamed(fd);
 }
 
--- a/src/search.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/search.h	Tue Sep 11 20:06:29 2007 +0000
@@ -17,8 +17,8 @@
 void search_new(const gchar *path, const gchar *example_file);
 
 
-void search_maint_renamed(const gchar *source, const gchar *dest);
-void search_maint_removed(const gchar *path);
+void search_maint_renamed(FileData *fd);
+void search_maint_removed(FileData *fd);
 
 
 #endif
--- a/src/slideshow.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/slideshow.c	Tue Sep 11 20:06:29 2007 +0000
@@ -14,6 +14,7 @@
 #include "collect.h"
 #include "image.h"
 #include "slideshow.h"
+#include "filelist.h"
 
 #include "layout.h"
 #include "layout_image.h"
@@ -31,14 +32,14 @@
 
 	if (ss->stop_func) ss->stop_func(ss, ss->stop_data);
 
-	if (ss->path_list) path_list_free(ss->path_list);
+	if (ss->filelist) filelist_free(ss->filelist);
 	if (ss->cd) collection_unref(ss->cd);
 	g_free(ss->layout_path);
 
 	g_list_free(ss->list);
 	g_list_free(ss->list_done);
 
-	g_free(ss->slide_path);
+	file_data_unref(ss->slide_fd);
 
 	g_free(ss);
 }
@@ -117,17 +118,17 @@
 
 gint slideshow_should_continue(SlideShowData *ss)
 {
-	const gchar *imd_path;
+	FileData *imd_fd;
 	const gchar *path;
 
 	if (!ss) return FALSE;
 
-	imd_path = image_get_path(ss->imd);
+	imd_fd = image_get_fd(ss->imd);
 
-	if ( ((imd_path == NULL) != (ss->slide_path == NULL)) ||
-	    (imd_path && ss->slide_path && strcmp(imd_path, ss->slide_path) != 0) ) return FALSE;
+	if ( ((imd_fd == NULL) != (ss->slide_fd == NULL)) ||
+	    (imd_fd && ss->slide_fd && imd_fd != ss->slide_fd) ) return FALSE;
 
-	if (ss->path_list) return TRUE;
+	if (ss->filelist) return TRUE;
 
 	if (ss->cd)
 		{
@@ -176,30 +177,30 @@
 		row = GPOINTER_TO_INT(ss->list_done->data);
 		}
 
-	g_free(ss->slide_path);
-	ss->slide_path = NULL;
+	file_data_unref(ss->slide_fd);
+	ss->slide_fd = NULL;
 
-	if (ss->path_list)
+	if (ss->filelist)
 		{
-		ss->slide_path = g_strdup(g_list_nth_data(ss->path_list, row));
-		image_change_path(ss->imd, ss->slide_path, image_zoom_get_default(ss->imd, zoom_mode));
+		ss->slide_fd = file_data_ref((FileData *)g_list_nth_data(ss->filelist, row));
+		image_change_fd(ss->imd, ss->slide_fd, image_zoom_get_default(ss->imd, zoom_mode));
 		}
 	else if (ss->cd)
 		{
 		CollectInfo *info;
 
 		info = g_list_nth_data(ss->cd->list, row);
-		ss->slide_path = g_strdup(info->path);
+		ss->slide_fd = file_data_ref(info->fd);
 
 		image_change_from_collection(ss->imd, ss->cd, info, image_zoom_get_default(ss->imd, zoom_mode));
 		}
 	else
 		{
-		ss->slide_path = g_strdup(layout_list_get_path(ss->layout, row));
+		ss->slide_fd = file_data_ref(layout_list_get_fd(ss->layout, row));
 
 		if (ss->from_selection)
 			{
-			image_change_path(ss->imd, ss->slide_path, image_zoom_get_default(ss->imd, zoom_mode));
+			image_change_fd(ss->imd, ss->slide_fd, image_zoom_get_default(ss->imd, zoom_mode));
 			layout_status_update_info(ss->layout, NULL);
 			}
 		else
@@ -234,19 +235,19 @@
 			r = GPOINTER_TO_INT(ss->list_done->next->data);
 			}
 
-		if (ss->path_list)
+		if (ss->filelist)
 			{
-			image_prebuffer_set(ss->imd, g_list_nth_data(ss->path_list, r));
+			image_prebuffer_set(ss->imd, g_list_nth_data(ss->filelist, r));
 			}
 		else if (ss->cd)
 			{
 			CollectInfo *info;
 			info = g_list_nth_data(ss->cd->list, r);
-			if (info) image_prebuffer_set(ss->imd, info->path);
+			if (info) image_prebuffer_set(ss->imd, info->fd);
 			}
 		else if (ss->from_selection)
 			{
-			image_prebuffer_set(ss->imd, layout_list_get_path(ss->layout, r));
+			image_prebuffer_set(ss->imd, layout_list_get_fd(ss->layout, r));
 			}
 		}
 
@@ -313,20 +314,20 @@
 }
 
 static SlideShowData *real_slideshow_start(ImageWindow *imd, LayoutWindow *lw,
-					   GList *path_list, gint start_point,
+					   GList *filelist, gint start_point,
 					   CollectionData *cd, CollectInfo *start_info,
 					   void (*stop_func)(SlideShowData *, gpointer), gpointer stop_data)
 {
 	SlideShowData *ss;
 	gint start_index = -1;
 
-	if (!path_list && !cd && layout_list_count(lw, NULL) < 1) return NULL;
+	if (!filelist && !cd && layout_list_count(lw, NULL) < 1) return NULL;
 
 	ss = g_new0(SlideShowData, 1);
 
 	ss->imd = imd;
 
-	ss->path_list = path_list;
+	ss->filelist = filelist;
 	ss->cd = cd;
 	ss->layout = lw;
 	ss->layout_path = NULL;
@@ -341,9 +342,9 @@
 	ss->timeout_id = -1;
 	ss->paused = FALSE;
 
-	if (ss->path_list)
+	if (ss->filelist)
 		{
-		ss->slide_count = g_list_length(ss->path_list);
+		ss->slide_count = g_list_length(ss->filelist);
 		}
 	else if (ss->cd)
 		{
@@ -376,7 +377,7 @@
 
 	slideshow_list_init(ss, start_index);
 
-	ss->slide_path = g_strdup(image_get_path(ss->imd));
+	ss->slide_fd = file_data_ref(image_get_fd(ss->imd));
 	if (slideshow_step(ss, TRUE))
 		{
 		slideshow_timer_reset(ss, TRUE);
@@ -393,7 +394,7 @@
 	return ss;
 }
 
-SlideShowData *slideshow_start_from_path_list(ImageWindow *imd, GList *list,
+SlideShowData *slideshow_start_from_filelist(ImageWindow *imd, GList *list,
 					      void (*stop_func)(SlideShowData *, gpointer), gpointer stop_data)
 {
 	return real_slideshow_start(imd, NULL, list, -1, NULL, NULL, stop_func, stop_data);
--- a/src/slideshow.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/slideshow.h	Tue Sep 11 20:06:29 2007 +0000
@@ -30,7 +30,7 @@
 void slideshow_next(SlideShowData *ss);
 void slideshow_prev(SlideShowData *ss);
 
-SlideShowData *slideshow_start_from_path_list(ImageWindow *imd, GList *list,
+SlideShowData *slideshow_start_from_filelist(ImageWindow *imd, GList *list,
 					      void (*stop_func)(SlideShowData *, gpointer), gpointer stop_data);
 SlideShowData *slideshow_start_from_collection(ImageWindow *imd, CollectionData *cd,
 					       void (*stop_func)(SlideShowData *, gpointer), gpointer stop_data,
--- a/src/thumb.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/thumb.c	Tue Sep 11 20:06:29 2007 +0000
@@ -252,7 +252,7 @@
 static void thumb_loader_setup(ThumbLoader *tl, gchar *path)
 {
 	image_loader_free(tl->il);
-	tl->il = image_loader_new(path);
+	tl->il = image_loader_new(file_data_new_simple(path));
 
 	if (thumbnail_fast)
 		{
--- a/src/thumb_standard.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/thumb_standard.c	Tue Sep 11 20:06:29 2007 +0000
@@ -542,7 +542,7 @@
 	if (debug)
 		{
 		printf("thumb image done: %s\n", tl->source_path);
-		printf("            from: %s\n", tl->il->path);
+		printf("            from: %s\n", tl->il->fd->path);
 		}
 
 	pixbuf = image_loader_get_pixbuf(tl->il);
@@ -582,7 +582,7 @@
 	if (debug)
 		{
 		printf("thumb image error: %s\n", tl->source_path);
-		printf("             from: %s\n", tl->il->path);
+		printf("             from: %s\n", tl->il->fd->path);
 		}
 
 	if (thumb_loader_std_next_source(tl, TRUE)) return;
@@ -601,7 +601,7 @@
 
 static gint thumb_loader_std_setup(ThumbLoaderStd *tl, const gchar *path)
 {
-	tl->il = image_loader_new(path);
+	tl->il = image_loader_new_from_path(path);
 
 	if (thumbnail_fast)
 		{
--- a/src/typedefs.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/typedefs.h	Tue Sep 11 20:06:29 2007 +0000
@@ -82,6 +82,7 @@
 
 typedef struct _FileData FileData;
 typedef struct _SidecarFileData SidecarFileData;
+typedef struct _FileDataChangeInfo FileDataChangeInfo;
 
 typedef struct _LayoutWindow LayoutWindow;
 typedef struct _ViewDirList ViewDirList;
@@ -98,6 +99,7 @@
 struct _ImageLoader
 {
 	GdkPixbuf *pixbuf;
+	FileData *fd;
 	gchar *path;
 
 	gint bytes_read;
@@ -157,10 +159,7 @@
 
 struct _CollectInfo
 {
-	gchar *path;
-	gint64 size;
-	time_t date;
-
+	FileData *fd;
 	GdkPixbuf *pixbuf;
 	gint flag_mask;
 };
@@ -253,8 +252,7 @@
 	GtkWidget *frame;
 	GtkWidget *inner_frame;
 
-	gchar *image_path;
-	const gchar *image_name;
+	FileData *image_fd;
 
 	gint64 size;		/* file size (bytes) */
 	time_t mtime;		/* file modified time stamp */
@@ -317,10 +315,10 @@
 
 	ImageLoader *read_ahead_il;
 	GdkPixbuf *read_ahead_pixbuf;
-	gchar *read_ahead_path;
+	FileData *read_ahead_fd;
 
 	GdkPixbuf *prev_pixbuf;
-	gchar *prev_path;
+	FileData *prev_fd;
 	gint prev_color_row;
 
 	gint auto_refresh_id;
@@ -340,9 +338,15 @@
 	time_t date;
 };
 
+struct _FileDataChangeInfo {
+	gchar *source;
+	gchar *dest;
+};
 
 struct _FileData {
+	gint magick;
 	gint type;
+	gchar *original_path; /* key to file_data_pool hash table */
 	gchar *path;
 	const gchar *name;
 	const gchar *extension;
@@ -350,8 +354,9 @@
 	time_t date;
 	gboolean marks[FILEDATA_MARKS_SIZE];
 	GList *sidecar_files;
-	gchar *target; /* for rename, move ... */
+	FileDataChangeInfo *change; /* for rename, move ... */
 	GdkPixbuf *pixbuf;
+	gint ref;
 };
 
 struct _LayoutWindow
@@ -541,7 +546,7 @@
 	FileData *select_fd;
 
 	gint thumbs_enabled;
-    gint marks_enabled;
+	gint marks_enabled;
     
 	/* thumb updates */
 	gint thumbs_running;
@@ -562,6 +567,8 @@
 	GtkWidget *popup;
 };
 
+struct _IconData;
+
 struct _ViewFileIcon
 {
 	GtkWidget *widget;
@@ -576,15 +583,15 @@
 	gint rows;
 
 	GList *selection;
-	FileData *prev_selection;
+	struct _IconData *prev_selection;
 
 	GtkWidget *tip_window;
 	gint tip_delay_id;
-	FileData *tip_fd;
+	struct _IconData *tip_id;
 
-	FileData *click_fd;
+	struct _IconData *click_id;
 
-	FileData *focus_fd;
+	struct _IconData *focus_id;
 	gint focus_row;
 	gint focus_column;
 
@@ -619,7 +626,7 @@
 {
 	ImageWindow *imd;
 
-	GList *path_list;
+	GList *filelist;
 	CollectionData *cd;
 	gchar *layout_path;
 	LayoutWindow *layout;
@@ -627,7 +634,7 @@
 	GList *list;
 	GList *list_done;
 
-	gchar *slide_path;
+	FileData *slide_fd;
 
 	gint slide_count;
 	gint timeout_id;
--- a/src/ui_bookmark.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/ui_bookmark.c	Tue Sep 11 20:06:29 2007 +0000
@@ -22,6 +22,9 @@
 
 #include <gdk/gdkkeysyms.h> /* for key values */
 
+#include "gqview.h"
+#include "filelist.h"
+
 #include "ui_bookmark.h"
 
 #include "ui_fileops.h"
@@ -1020,7 +1023,7 @@
 		work = work->next;
 		}
 
-	path_list_free(list);
+	string_list_free(list);
 
 	bookmark_populate_all(bm->key);
 }
@@ -1444,6 +1447,14 @@
 	return list;
 }
 
+GList *uri_filelist_from_text(gchar *data, gint files_only)
+{
+	GList *path_list = uri_list_from_text(data, files_only);
+	GList *filelist = filelist_from_path_list(path_list);
+	string_list_free(path_list);
+	return filelist;
+}
+
 gchar *uri_text_from_list(GList *list, gint *len, gint plain_text)
 {
 	gchar *uri_text = NULL;
@@ -1492,3 +1503,11 @@
 	return uri_text;
 }
 
+gchar *uri_text_from_filelist(GList *list, gint *len, gint plain_text)
+{
+	GList *path_list = filelist_to_path_list(list);
+	gchar *ret = uri_text_from_list(path_list, len, plain_text);
+	string_list_free(path_list);
+	return ret;
+}
+
--- a/src/ui_bookmark.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/ui_bookmark.h	Tue Sep 11 20:06:29 2007 +0000
@@ -59,7 +59,9 @@
 void uri_text_decode(gchar *text);
 
 GList *uri_list_from_text(gchar *data, gint files_only);
+GList *uri_filelist_from_text(gchar *data, gint files_only);
 gchar *uri_text_from_list(GList *list, gint *len, gint plain_text);
+gchar *uri_text_from_filelist(GList *list, gint *len, gint plain_text);
 
 
 #endif
--- a/src/ui_fileops.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/ui_fileops.c	Tue Sep 11 20:06:29 2007 +0000
@@ -25,6 +25,7 @@
 #include <glib.h>
 #include <gtk/gtk.h>	/* for locale warning dialog */
 
+#include "gqview.h"
 #include "ui_fileops.h"
 
 #include "ui_utildlg.h"	/* for locale warning dialog */
--- a/src/ui_fileops.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/ui_fileops.h	Tue Sep 11 20:06:29 2007 +0000
@@ -51,12 +51,14 @@
 gchar *get_current_dir(void);
 
 /* return True on success, it is up to you to free
- * the lists with path_list_free()
+ * the lists with string_list_free()
  */
 gint path_list(const gchar *path, GList **files, GList **dirs);
 gint path_list_lstat(const gchar *path, GList **files, GList **dirs);
-void path_list_free(GList *list);
-GList *path_list_copy(GList *list);
+void string_list_free(GList *list);
+#define path_list_free string_list_free
+GList *string_list_copy(GList *list);
+#define path_list_copy string_list_copy
 
 long checksum_simple(const gchar *path);
 
--- a/src/ui_pathsel.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/ui_pathsel.c	Tue Sep 11 20:06:29 2007 +0000
@@ -28,6 +28,7 @@
 
 #include <gdk/gdkkeysyms.h> /* for key values */
 
+#include "gqview.h"
 #include "ui_pathsel.h"
 
 #include "ui_bookmark.h"
--- a/src/ui_tabcomp.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/ui_tabcomp.c	Tue Sep 11 20:06:29 2007 +0000
@@ -25,6 +25,7 @@
 #include <gtk/gtk.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
+#include "gqview.h"
 #include "ui_tabcomp.h"
 
 #include "ui_bookmark.h"
--- a/src/ui_utildlg.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/ui_utildlg.c	Tue Sep 11 20:06:29 2007 +0000
@@ -22,6 +22,7 @@
 
 #include <gdk/gdkkeysyms.h> /* for keyboard values */
 
+#include "gqview.h"
 #include "ui_utildlg.h"
 
 #include "ui_fileops.h"
@@ -322,13 +323,13 @@
  *-----------------------------------------------------------------------------
  */ 
 
-void file_dialog_close(FileDialog *fd)
+void file_dialog_close(FileDialog *fdlg)
 {
-	g_free(fd->source_path);
-	g_free(fd->dest_path);
-	if (fd->source_list) path_list_free(fd->source_list);
+	file_data_unref(fdlg->source_fd);
+	g_free(fdlg->dest_path);
+	if (fdlg->source_list) filelist_free(fdlg->source_list);
 
-	generic_dialog_close(GENERIC_DIALOG(fd));
+	generic_dialog_close(GENERIC_DIALOG(fdlg));
 }
 
 FileDialog *file_dialog_new(const gchar *title,
@@ -336,29 +337,29 @@
 			    GtkWidget *parent,
 			    void (*cancel_cb)(FileDialog *, gpointer), gpointer data)
 {
-	FileDialog *fd = NULL;
+	FileDialog *fdlg = NULL;
 
-	fd = g_new0(FileDialog, 1);
+	fdlg = g_new0(FileDialog, 1);
 
-	generic_dialog_setup(GENERIC_DIALOG(fd), title,
+	generic_dialog_setup(GENERIC_DIALOG(fdlg), title,
 			     wmclass, wmsubclass, parent, FALSE,
 			     (void *)cancel_cb, data);
 
-	return fd;
+	return fdlg;
 }
 
-GtkWidget *file_dialog_add_button(FileDialog *fd, const gchar *stock_id, const gchar *text,
+GtkWidget *file_dialog_add_button(FileDialog *fdlg, const gchar *stock_id, const gchar *text,
 				  void (*func_cb)(FileDialog *, gpointer), gint is_default)
 {
-	return generic_dialog_add_button(GENERIC_DIALOG(fd), stock_id, text,
+	return generic_dialog_add_button(GENERIC_DIALOG(fdlg), stock_id, text,
 					 (void *)func_cb, is_default);
 }
 
 static void file_dialog_entry_cb(GtkWidget *widget, gpointer data)
 {
-	FileDialog *fd = data;
-	g_free(fd->dest_path);
-	fd->dest_path = remove_trailing_slash(gtk_entry_get_text(GTK_ENTRY(fd->entry)));
+	FileDialog *fdlg = data;
+	g_free(fdlg->dest_path);
+	fdlg->dest_path = remove_trailing_slash(gtk_entry_get_text(GTK_ENTRY(fdlg->entry)));
 }
 
 static void file_dialog_entry_enter_cb(const gchar *path, gpointer data)
@@ -370,84 +371,84 @@
 	if (gd->default_cb) gd->default_cb(gd, gd->data);
 }
 
-void file_dialog_add_path_widgets(FileDialog *fd, const gchar *default_path, const gchar *path,
+void file_dialog_add_path_widgets(FileDialog *fdlg, const gchar *default_path, const gchar *path,
 				  const gchar *history_key, const gchar *filter, const gchar *filter_desc)
 {
 	GtkWidget *tabcomp;
 	GtkWidget *list;
 
-	if (fd->entry) return;
+	if (fdlg->entry) return;
 
-	tabcomp = tab_completion_new_with_history(&fd->entry, NULL,
-		  history_key, -1, file_dialog_entry_enter_cb, fd);
-	gtk_box_pack_end(GTK_BOX(GENERIC_DIALOG(fd)->vbox), tabcomp, FALSE, FALSE, 0);
-	generic_dialog_attach_default(GENERIC_DIALOG(fd), fd->entry);
+	tabcomp = tab_completion_new_with_history(&fdlg->entry, NULL,
+		  history_key, -1, file_dialog_entry_enter_cb, fdlg);
+	gtk_box_pack_end(GTK_BOX(GENERIC_DIALOG(fdlg)->vbox), tabcomp, FALSE, FALSE, 0);
+	generic_dialog_attach_default(GENERIC_DIALOG(fdlg), fdlg->entry);
 	gtk_widget_show(tabcomp);
 
 	if (path && path[0] == '/')
 		{
-		fd->dest_path = g_strdup(path);
+		fdlg->dest_path = g_strdup(path);
 		}
 	else
 		{
 		const gchar *base;
 
-		base = tab_completion_set_to_last_history(fd->entry);
+		base = tab_completion_set_to_last_history(fdlg->entry);
 
 		if (!base) base = default_path;
 		if (!base) base = homedir();
 
 		if (path)
 			{
-			fd->dest_path = concat_dir_and_file(base, path);
+			fdlg->dest_path = concat_dir_and_file(base, path);
 			}
 		else
 			{
-			fd->dest_path = g_strdup(base);
+			fdlg->dest_path = g_strdup(base);
 			}
 		}
 
-	list = path_selection_new_with_files(fd->entry, fd->dest_path, filter, filter_desc);
-	path_selection_add_select_func(fd->entry, file_dialog_entry_enter_cb, fd);
-	gtk_box_pack_end(GTK_BOX(GENERIC_DIALOG(fd)->vbox), list, TRUE, TRUE, 0);
+	list = path_selection_new_with_files(fdlg->entry, fdlg->dest_path, filter, filter_desc);
+	path_selection_add_select_func(fdlg->entry, file_dialog_entry_enter_cb, fdlg);
+	gtk_box_pack_end(GTK_BOX(GENERIC_DIALOG(fdlg)->vbox), list, TRUE, TRUE, 0);
 	gtk_widget_show(list);
 
-	gtk_widget_grab_focus(fd->entry);
-	if (fd->dest_path)
+	gtk_widget_grab_focus(fdlg->entry);
+	if (fdlg->dest_path)
 		{
-		gtk_entry_set_text(GTK_ENTRY(fd->entry), fd->dest_path);
-		gtk_editable_set_position(GTK_EDITABLE(fd->entry), strlen(fd->dest_path));
+		gtk_entry_set_text(GTK_ENTRY(fdlg->entry), fdlg->dest_path);
+		gtk_editable_set_position(GTK_EDITABLE(fdlg->entry), strlen(fdlg->dest_path));
 		}
 
-	g_signal_connect(G_OBJECT(fd->entry), "changed",
-			 G_CALLBACK(file_dialog_entry_cb), fd);
+	g_signal_connect(G_OBJECT(fdlg->entry), "changed",
+			 G_CALLBACK(file_dialog_entry_cb), fdlg);
 }
 
-void file_dialog_add_filter(FileDialog *fd, const gchar *filter, const gchar *filter_desc, gint set)
+void file_dialog_add_filter(FileDialog *fdlg, const gchar *filter, const gchar *filter_desc, gint set)
 {
-	if (!fd->entry) return;
-	path_selection_add_filter(fd->entry, filter, filter_desc, set);
+	if (!fdlg->entry) return;
+	path_selection_add_filter(fdlg->entry, filter, filter_desc, set);
 }
 
-void file_dialog_clear_filter(FileDialog *fd)
+void file_dialog_clear_filter(FileDialog *fdlg)
 {
-	if (!fd->entry) return;
-	path_selection_clear_filter(fd->entry);
+	if (!fdlg->entry) return;
+	path_selection_clear_filter(fdlg->entry);
 }
 
-void file_dialog_sync_history(FileDialog *fd, gint dir_only)
+void file_dialog_sync_history(FileDialog *fdlg, gint dir_only)
 {
-	if (!fd->dest_path) return;
+	if (!fdlg->dest_path) return;
 
 	if (!dir_only ||
-	    (dir_only && isdir(fd->dest_path)) )
+	    (dir_only && isdir(fdlg->dest_path)) )
 		{
-		tab_completion_append_to_history(fd->entry, fd->dest_path);
+		tab_completion_append_to_history(fdlg->entry, fdlg->dest_path);
 		}
 	else
 		{
-		gchar *buf = remove_level_from_path(fd->dest_path);
-		tab_completion_append_to_history(fd->entry, buf);
+		gchar *buf = remove_level_from_path(fdlg->dest_path);
+		tab_completion_append_to_history(fdlg->entry, buf);
 		g_free(buf);
 		}
 }
--- a/src/ui_utildlg.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/ui_utildlg.h	Tue Sep 11 20:06:29 2007 +0000
@@ -43,7 +43,7 @@
 	gint type;
 	gint multiple_files;
 
-	gchar *source_path;
+	FileData *source_fd;
 	GList *source_list;
 
 	gchar *dest_path;
--- a/src/utilops.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/utilops.c	Tue Sep 11 20:06:29 2007 +0000
@@ -29,7 +29,6 @@
 #include "ui_misc.h"
 #include "ui_tabcomp.h"
 
-
 /*
  *--------------------------------------------------------------------------
  * call these when names change, files move, deleted, etc.
@@ -37,44 +36,45 @@
  *--------------------------------------------------------------------------
  */
 
-void file_maint_renamed(const gchar *source, const gchar *dest)
+
+void file_maint_renamed(FileData *fd)
 {
-	cache_maint_moved(source, dest);
-	collection_maint_renamed(source, dest);
-
-	layout_maint_renamed(source, dest);
-	view_window_maint_moved(source, dest);
-	dupe_maint_renamed(source, dest);
-	search_maint_renamed(source, dest);
+	cache_maint_moved(fd);
+	collection_maint_renamed(fd);
+
+	layout_maint_renamed(fd);
+	view_window_maint_moved(fd);
+	dupe_maint_renamed(fd);
+	search_maint_renamed(fd);
 }
 
 /* under most cases ignore_list should be NULL */
-void file_maint_removed(const gchar *path, GList *ignore_list)
+void file_maint_removed(FileData *fd, GList *ignore_list)
 {
-	layout_maint_removed(path, ignore_list);
-	view_window_maint_removed(path, ignore_list);
-	dupe_maint_removed(path);
-	search_maint_removed(path);
-
-	collection_maint_removed(path);
-	cache_maint_removed(path);
+	layout_maint_removed(fd, ignore_list);
+	view_window_maint_removed(fd, ignore_list);
+	dupe_maint_removed(fd);
+	search_maint_removed(fd);
+
+	collection_maint_removed(fd);
+	cache_maint_removed(fd);
 }
 
 /* special case for correct main window behavior */
-void file_maint_moved(const gchar *source, const gchar *dest, GList *ignore_list)
+void file_maint_moved(FileData *fd, GList *ignore_list)
 {
-	cache_maint_moved(source, dest);
-	collection_maint_renamed(source, dest);
-
-	layout_maint_moved(source, dest, ignore_list);
-	view_window_maint_moved(source, dest);
-	dupe_maint_renamed(source, dest);
-	search_maint_renamed(source, dest);
+	cache_maint_moved(fd);
+	collection_maint_renamed(fd);
+
+	layout_maint_moved(fd, ignore_list);
+	view_window_maint_moved(fd);
+	dupe_maint_renamed(fd);
+	search_maint_renamed(fd);
 }
 
-void file_maint_copied(const gchar *source, const gchar *dest)
+void file_maint_copied(FileData *fd)
 {
-	cache_maint_copied(source, dest);
+	cache_maint_copied(fd);
 }
 
 /*
@@ -101,7 +101,7 @@
 	GList *source_list;
 	GList *source_next;
 	gchar *dest_base;
-	gchar *source;
+	FileData *source_fd;
 	gchar *dest;
 	gint copy;
 
@@ -120,7 +120,7 @@
 struct _FileDataSingle
 {
 	gint confirmed;
-	gchar *source;
+	FileData *source_fd;
 	gchar *dest;
 	gint copy;
 
@@ -142,8 +142,8 @@
 #define DIALOG_DEF_IMAGE_DIM_Y 150
 
 static void generic_dialog_add_image(GenericDialog *gd, GtkWidget *box,
-				     const gchar *path1, const gchar *header1,
-				     const gchar *path2, const gchar *header2,
+				     FileData *fd1, const gchar *header1,
+				     FileData *fd2, const gchar *header2,
 				     gint show_filename)
 {
 	ImageWindow *imd;
@@ -153,7 +153,7 @@
 
 	if (!box) box = gd->vbox;
 
-	if (path2)
+	if (fd2)
 		{
 		hbox = pref_box_new(box, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
 		}
@@ -190,12 +190,12 @@
 	g_object_set(G_OBJECT(imd->pr), "zoom_expand", FALSE, NULL);
 	gtk_widget_set_size_request(imd->widget, DIALOG_DEF_IMAGE_DIM_X, DIALOG_DEF_IMAGE_DIM_Y);
 	gtk_box_pack_start(GTK_BOX(vbox), imd->widget, TRUE, TRUE, 0);
-	image_change_path(imd, path1, 0.0);
+	image_change_fd(imd, fd1, 0.0);
 	gtk_widget_show(imd->widget);
 
 	if (show_filename)
 		{
-		label = pref_label_new(vbox, (path1 == NULL) ? "" : filename_from_path(path1));
+		label = pref_label_new(vbox, (fd1 == NULL) ? "" : fd1->name);
 		}
 
 	/* only the first image is stored (for use in gd_image_set) */
@@ -205,7 +205,7 @@
 
 	/* image 2 */
 
-	if (hbox && path2)
+	if (hbox && fd2)
 		{
 		vbox = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
 
@@ -222,14 +222,14 @@
 		g_object_set(G_OBJECT(imd->pr), "zoom_expand", FALSE, NULL);
 		gtk_widget_set_size_request(imd->widget, DIALOG_DEF_IMAGE_DIM_X, DIALOG_DEF_IMAGE_DIM_Y);
 		gtk_box_pack_start(GTK_BOX(vbox), imd->widget, TRUE, TRUE, 0);
-		image_change_path(imd, path2, 0.0);
+		image_change_fd(imd, fd2, 0.0);
 		gtk_widget_show(imd->widget);
 
-		pref_label_new(vbox, filename_from_path(path2));
+		pref_label_new(vbox, fd2->name);
 		}
 }
 
-static void generic_dialog_image_set(GenericDialog *gd, const gchar *path)
+static void generic_dialog_image_set(GenericDialog *gd, FileData *fd)
 {
 	ImageWindow *imd;
 	GtkWidget *label;
@@ -239,8 +239,8 @@
 
 	if (!imd) return;
 
-	image_change_path(imd, path, 0.0);
-	if (label) gtk_label_set_text(GTK_LABEL(label), filename_from_path(path));
+	image_change_fd(imd, fd, 0.0);
+	if (label) gtk_label_set_text(GTK_LABEL(label), fd->name);
 }
 
 /*
@@ -270,15 +270,15 @@
 			       GtkWidget *parent,
 			       void (*cancel_cb)(FileDialog *, gpointer), gpointer data)
 {
-	FileDialog *fd;
-
-	fd = file_dialog_new(title, wmclass, wmsubclass, parent, cancel_cb, data);
+	FileDialog *fdlg;
+
+	fdlg = file_dialog_new(title, wmclass, wmsubclass, parent, cancel_cb, data);
 	if (place_dialogs_under_mouse)
 		{
-		gtk_window_set_position(GTK_WINDOW(GENERIC_DIALOG(fd)->dialog), GTK_WIN_POS_MOUSE);
+		gtk_window_set_position(GTK_WINDOW(GENERIC_DIALOG(fdlg)->dialog), GTK_WIN_POS_MOUSE);
 		}
 
-	return fd;
+	return fdlg;
 }
 
 /* this warning dialog is copied from SLIK's ui_utildg.c,
@@ -333,25 +333,63 @@
  *--------------------------------------------------------------------------
  */
 
-static gint copy_file_ext(const gchar *s, const gchar *t)
+gint copy_file_ext(FileData *fd)
 {
+	gint ret;
+	g_assert(fd->change);
 	if (editor_command[CMD_COPY])
-		return start_editor_from_pair(CMD_COPY, s, t);
-	return copy_file(s, t);
+		ret = start_editor_from_file(CMD_COPY, fd);
+	else
+		ret = copy_file(fd->change->source, fd->change->dest);
+
+	if (ret)
+		{
+		file_maint_copied(fd);
+		}
+
+	file_data_change_info_free(NULL, fd);
+		
+	return ret;
 }
 
-static gint move_file_ext(const gchar *s, const gchar *t)
+gint move_file_ext(FileData *fd)
 {
+	gint ret;
+	g_assert(fd->change);
 	if (editor_command[CMD_MOVE])
-		return start_editor_from_pair(CMD_MOVE, s, t);
-	return move_file(s, t);
+		ret = start_editor_from_file(CMD_MOVE, fd);
+	else
+		ret = move_file(fd->change->source, fd->change->dest);
+
+	if (ret)
+		{
+		file_data_do_change(fd);
+		file_maint_moved(fd, NULL);
+		}
+
+	file_data_change_info_free(NULL, fd);
+		
+	return ret;
 }
 
-static gint rename_file_ext(const gchar *s, const gchar *t)
+gint rename_file_ext(FileData *fd)
 {
+	gint ret;
+	g_assert(fd->change);
 	if (editor_command[CMD_RENAME])
-		return start_editor_from_pair(CMD_RENAME, s, t);
-	return rename_file(s, t);
+		ret = start_editor_from_file(CMD_RENAME, fd);
+	else
+		ret = rename_file(fd->change->source, fd->change->dest);
+			
+	if (ret)
+		{
+		file_data_do_change(fd);
+		file_maint_renamed(fd);
+		}
+		
+	file_data_change_info_free(NULL, fd);
+		
+	return ret;
 }
 
 
@@ -368,7 +406,7 @@
 	fdm->source_list = source_list;
 	fdm->source_next = fdm->source_list;
 	fdm->dest_base = g_strdup(dest);
-	fdm->source = NULL;
+	fdm->source_fd = NULL;
 	fdm->dest = NULL;
 	fdm->copy = copy;
 	return fdm;
@@ -376,7 +414,7 @@
 
 static void file_data_multiple_free(FileDataMult *fdm)
 {
-	path_list_free(fdm->source_list);
+	filelist_free(fdm->source_list);
 	g_free(fdm->dest_base);
 	g_free(fdm->dest);
 	g_free(fdm);
@@ -412,7 +450,7 @@
 
 		name = gtk_entry_get_text(GTK_ENTRY(fdm->rename_entry));
 		if (strlen(name) == 0 ||
-		    strcmp(name, filename_from_path(fdm->source)) == 0)
+		    strcmp(name, fdm->source_fd->name) == 0)
 			{
 			fdm->confirmed = FALSE;
 			}
@@ -538,7 +576,7 @@
 							file_util_move_multiple_all_cb, FALSE);
 	generic_dialog_add_button(gd, GTK_STOCK_GOTO_LAST, _("S_kip all"), file_util_move_multiple_skip_all_cb, FALSE);
 	generic_dialog_add_button(gd, GTK_STOCK_GO_FORWARD, _("_Skip"), file_util_move_multiple_skip_cb, FALSE);
-	generic_dialog_add_image(gd, NULL, fdm->dest, _("Existing file"), fdm->source, _("New file"), TRUE);
+	generic_dialog_add_image(gd, NULL, file_data_new_simple(fdm->dest), _("Existing file"), fdm->source_fd, _("New file"), TRUE);
 
 	/* rename option */
 
@@ -581,13 +619,13 @@
 		if (!fdm->dest)
 			{
 			GList *work = fdm->source_next;
-			fdm->source = work->data;
-			fdm->dest = concat_dir_and_file(fdm->dest_base, filename_from_path(fdm->source));
+			fdm->source_fd = work->data;
+			fdm->dest = concat_dir_and_file(fdm->dest_base, fdm->source_fd->name);
 			fdm->source_next = work->next;
 			fdm->confirmed = FALSE;
 			}
 
-		if (fdm->dest && fdm->source && strcmp(fdm->dest, fdm->source) == 0)
+		if (fdm->dest && fdm->source_fd && strcmp(fdm->dest, fdm->source_fd->name) == 0)
 			{
 			if (!fdm->confirmed)
 				{
@@ -657,25 +695,24 @@
 				}
 			if (try)
 				{
+				file_data_change_info_new(fdm->source_fd->path, fdm->dest, fdm->source_fd);
 				if (fdm->copy)
 					{
-					if (copy_file_ext(fdm->source, fdm->dest))
+					if (copy_file_ext(fdm->source_fd))
 						{
 						success = TRUE;
-						file_maint_copied(fdm->source, fdm->dest);
 						}
 					}
 				else
 					{
-					if (move_file_ext(fdm->source, fdm->dest))
+					if (move_file_ext(fdm->source_fd))
 						{
 						success = TRUE;
-						file_maint_moved(fdm->source, fdm->dest, fdm->source_list);
 						}
 					}
+
 				}
 			}
-
 		if (!success)
 			{
 			GenericDialog *gd;
@@ -685,12 +722,12 @@
 			if (fdm->copy)
 				{
 				title = _("Error copying file");
-				text = g_strdup_printf(_("Unable to copy file:\n%s\nto:\n%s\nduring multiple file copy."), fdm->source, fdm->dest);
+				text = g_strdup_printf(_("Unable to copy file:\n%s\nto:\n%s\nduring multiple file copy."), fdm->source_fd->path, fdm->dest);
 				}
 			else
 				{
 				title = _("Error moving file");
-				text = g_strdup_printf(_("Unable to move file:\n%s\nto:\n%s\nduring multiple file move."), fdm->source, fdm->dest);
+				text = g_strdup_printf(_("Unable to move file:\n%s\nto:\n%s\nduring multiple file move."), fdm->source_fd->path, fdm->dest);
 				}
 			gd = file_util_gen_dlg(title, "GQview", "dlg_confirm",
 						NULL, TRUE,
@@ -708,7 +745,16 @@
 
 		if (!success) return;
 		}
-
+/*
+	if (fdm->source_list)
+		file_util_do_move_list(fdm->source_list, fdm->copy);
+	else
+		{
+		GList *list = g_list_append(NULL, file_data_ref(fdm->source_fd));
+		file_util_do_move_list(list, fdm->copy);
+		filelist_free(list);
+		}
+*/
 	file_data_multiple_free(fdm);
 }
 
@@ -716,11 +762,11 @@
  * Single file move
  */
 
-static FileDataSingle *file_data_single_new(const gchar *source, const gchar *dest, gint copy)
+static FileDataSingle *file_data_single_new(FileData *source_fd, const gchar *dest, gint copy)
 {
 	FileDataSingle *fds = g_new0(FileDataSingle, 1);
 	fds->confirmed = FALSE;
-	fds->source = g_strdup(source);
+	fds->source_fd = file_data_ref(source_fd);
 	fds->dest = g_strdup(dest);
 	fds->copy = copy;
 	return fds;
@@ -728,7 +774,7 @@
 
 static void file_data_single_free(FileDataSingle *fds)
 {
-	g_free(fds->source);
+	file_data_unref(fds->source_fd);
 	g_free(fds->dest);
 	g_free(fds);
 }
@@ -763,7 +809,7 @@
 
 		name = gtk_entry_get_text(GTK_ENTRY(fds->rename_entry));
 		if (strlen(name) == 0 ||
-		    strcmp(name, filename_from_path(fds->source)) == 0)
+		    strcmp(name, fds->source_fd->name) == 0)
 			{
 			fds->confirmed = FALSE;
 			}
@@ -834,7 +880,7 @@
 
 static void file_util_move_single(FileDataSingle *fds)
 {
-	if (fds->dest && fds->source && strcmp(fds->dest, fds->source) == 0)
+	if (fds->dest && fds->source_fd && strcmp(fds->dest, fds->source_fd->name) == 0)
 		{
 		file_util_warning_dialog(_("Source matches destination"),
 					 _("Source and destination are the same, operation cancelled."),
@@ -855,7 +901,7 @@
 		pref_spacer(gd->vbox, 0);
 
 		generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), file_util_move_single_ok_cb, TRUE);
-		generic_dialog_add_image(gd, NULL, fds->dest, _("Existing file"), fds->source, _("New file"), TRUE);
+		generic_dialog_add_image(gd, NULL, file_data_new_simple(fds->dest), _("Existing file"), fds->source_fd, _("New file"), TRUE);
 
 		/* rename option */
 
@@ -890,20 +936,19 @@
 	else
 		{
 		gint success = FALSE;
+		file_data_change_info_new(fds->source_fd->path, fds->dest, fds->source_fd);
 		if (fds->copy)
 			{
-			if (copy_file_ext(fds->source, fds->dest))
+			if (copy_file_ext(fds->source_fd))
 				{
 				success = TRUE;
-				file_maint_copied(fds->source, fds->dest);
 				}
 			}
 		else
 			{
-			if (move_file_ext(fds->source, fds->dest))
+			if (move_file_ext(fds->source_fd))
 				{
 				success = TRUE;
-				file_maint_moved(fds->source, fds->dest, NULL);
 				}
 			}
 		if (!success)
@@ -913,12 +958,12 @@
 			if (fds->copy)
 				{
 				title = _("Error copying file");
-				text = g_strdup_printf(_("Unable to copy file:\n%s\nto:\n%s"), fds->source, fds->dest);
+				text = g_strdup_printf(_("Unable to copy file:\n%s\nto:\n%s"), fds->source_fd->name, fds->dest);
 				}
 			else
 				{
 				title = _("Error moving file");
-				text = g_strdup_printf(_("Unable to move file:\n%s\nto:\n%s"), fds->source, fds->dest);
+				text = g_strdup_printf(_("Unable to move file:\n%s\nto:\n%s"), fds->source_fd->name, fds->dest);
 				}
 			file_util_warning_dialog(title, text, GTK_STOCK_DIALOG_ERROR, NULL);
 			g_free(text);
@@ -932,39 +977,39 @@
  * file move dialog
  */
 
-static void file_util_move_do(FileDialog *fd)
+static void file_util_move_do(FileDialog *fdlg)
 {
-	file_dialog_sync_history(fd, TRUE);
-
-	if (fd->multiple_files)
+	file_dialog_sync_history(fdlg, TRUE);
+
+	if (fdlg->multiple_files)
 		{
-		file_util_move_multiple(file_data_multiple_new(fd->source_list, fd->dest_path, fd->type));
-		fd->source_list = NULL;
+		file_util_move_multiple(file_data_multiple_new(fdlg->source_list, fdlg->dest_path, fdlg->type));
+		fdlg->source_list = NULL;
 		}
 	else
 		{
-		if (isdir(fd->dest_path))
+		if (isdir(fdlg->dest_path))
 			{
-			gchar *buf = concat_dir_and_file(fd->dest_path, filename_from_path(fd->source_path));
-			gtk_entry_set_text(GTK_ENTRY(fd->entry), buf);
+			gchar *buf = concat_dir_and_file(fdlg->dest_path, fdlg->source_fd->name);
+			gtk_entry_set_text(GTK_ENTRY(fdlg->entry), buf);
 			g_free(buf);
 			}
-		file_util_move_single(file_data_single_new(fd->source_path, fd->dest_path, fd->type));
+		file_util_move_single(file_data_single_new(fdlg->source_fd, fdlg->dest_path, fdlg->type));
 		}
 
-	file_dialog_close(fd);
+	file_dialog_close(fdlg);
 }
 
-static void file_util_move_check(FileDialog *fd)
+static void file_util_move_check(FileDialog *fdlg)
 {
-	if (fd->dest_path && strcmp(fd->dest_path, "~") == 0)
+	if (fdlg->dest_path && strcmp(fdlg->dest_path, "~") == 0)
 		{
-		gtk_entry_set_text(GTK_ENTRY(fd->entry), homedir());
+		gtk_entry_set_text(GTK_ENTRY(fdlg->entry), homedir());
 		}
 
-	if (fd->multiple_files && !isdir(fd->dest_path))
+	if (fdlg->multiple_files && !isdir(fdlg->dest_path))
 		{
-		if (isfile(fd->dest_path))
+		if (isfile(fdlg->dest_path))
 			{
 			file_util_warning_dialog(_("Invalid destination"),
 						 _("When operating with multiple files, please select\na folder, not a file."),
@@ -977,17 +1022,17 @@
 		return;
 		}
 
-	if (!fd->dest_path || fd->dest_path[0] != '/')
+	if (!fdlg->dest_path || fdlg->dest_path[0] != '/')
 		{
-		if (fd->source_path)
+		if (fdlg->source_fd)
 			{
 			gchar *base;
 			gchar *path;
 
-			base = remove_level_from_path(fd->source_path);
-			path = concat_dir_and_file(base, fd->dest_path);
-
-			gtk_entry_set_text(GTK_ENTRY(fd->entry), path);
+			base = remove_level_from_path(fdlg->source_fd->path);
+			path = concat_dir_and_file(base, fdlg->dest_path);
+
+			gtk_entry_set_text(GTK_ENTRY(fdlg->entry), path);
 
 			g_free(path);
 			g_free(base);
@@ -995,36 +1040,36 @@
 		return;
 		}
 
-	file_util_move_do(fd);
+	file_util_move_do(fdlg);
 }
 
-static void file_util_move_cb(FileDialog *fd, gpointer data)
+static void file_util_move_cb(FileDialog *fdlg, gpointer data)
 {
-	file_util_move_check(fd);
+	file_util_move_check(fdlg);
 }
 
-static void file_util_move_cancel_cb(FileDialog *fd, gpointer data)
+static void file_util_move_cancel_cb(FileDialog *fdlg, gpointer data)
 {
-	file_dialog_close(fd);
+	file_dialog_close(fdlg);
 }
 
-static void real_file_util_move(const gchar *source_path, GList *source_list,
+static void real_file_util_move(FileData *source_fd, GList *source_list,
 				const gchar *dest_path, gint copy, GtkWidget *parent)
 {
-	FileDialog *fd;
+	FileDialog *fdlg;
 	GtkWidget *label;
-	gchar *path = NULL;
+	FileData *fd = NULL;
 	gint multiple;
 	const gchar *text;
 	const gchar *title;
 	const gchar *op_text;
 	const gchar *stock_id;
 
-	if (!source_path && !source_list) return;
-
-	if (source_path)
+	if (!source_fd && !source_list) return;
+
+	if (source_fd)
 		{
-		path = g_strdup(source_path);
+		fd = file_data_ref(source_fd);
 		multiple = FALSE;
 		}
 	else if (source_list->next)
@@ -1033,8 +1078,8 @@
 		}
 	else
 		{
-		path = g_strdup(source_list->data);
-		path_list_free(source_list);
+		fd = file_data_ref(source_list->data);
+		filelist_free(source_list);
 		source_list = NULL;
 		multiple = FALSE;
 		}
@@ -1043,7 +1088,7 @@
 		{
 		title = _("Copy - GQview");
 		op_text = _("_Copy");
-		if (path)
+		if (fd)
 			{
 			text = _("Copy file");
 			}
@@ -1057,7 +1102,7 @@
 		{
 		title = _("Move - GQview");
 		op_text = _("_Move");
-		if (path)
+		if (fd)
 			{
 			text = _("Move file");
 			}
@@ -1068,43 +1113,43 @@
 		stock_id = GTK_STOCK_OK;
 		}
 
-	fd = file_util_file_dlg(title, "GQview", "dlg_copymove", parent,
+	fdlg = file_util_file_dlg(title, "GQview", "dlg_copymove", parent,
 				file_util_move_cancel_cb, NULL);
-	generic_dialog_add_message(GENERIC_DIALOG(fd), NULL, text, NULL);
-
-	if (path)
+	generic_dialog_add_message(GENERIC_DIALOG(fdlg), NULL, text, NULL);
+
+	if (fd)
 		{
 		GtkWidget *box;
 
-		box = pref_box_new(GENERIC_DIALOG(fd)->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+		box = pref_box_new(GENERIC_DIALOG(fdlg)->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
 		pref_label_new(box, _("File name:"));
-		pref_label_new(box, filename_from_path(path));
+		pref_label_new(box, fd->name);
 		}
 
-	label = pref_label_new(GENERIC_DIALOG(fd)->vbox, _("Choose the destination folder."));
+	label = pref_label_new(GENERIC_DIALOG(fdlg)->vbox, _("Choose the destination folder."));
 	gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
-	pref_spacer(GENERIC_DIALOG(fd)->vbox, 0);
-
-	file_dialog_add_button(fd, stock_id, op_text, file_util_move_cb, TRUE);
-
-	file_dialog_add_path_widgets(fd, NULL, dest_path, "move_copy", NULL, NULL);
-
-	fd->type = copy;
-	fd->source_path = path;
-	fd->source_list = source_list;
-	fd->multiple_files = multiple;
-
-	gtk_widget_show(GENERIC_DIALOG(fd)->dialog);
+	pref_spacer(GENERIC_DIALOG(fdlg)->vbox, 0);
+
+	file_dialog_add_button(fdlg, stock_id, op_text, file_util_move_cb, TRUE);
+
+	file_dialog_add_path_widgets(fdlg, NULL, dest_path, "move_copy", NULL, NULL);
+
+	fdlg->type = copy;
+	fdlg->source_fd = fd;
+	fdlg->source_list = source_list;
+	fdlg->multiple_files = multiple;
+
+	gtk_widget_show(GENERIC_DIALOG(fdlg)->dialog);
 }
 
-void file_util_move(const gchar *source_path, GList *source_list, const gchar *dest_path, GtkWidget *parent)
+void file_util_move(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent)
 {
-	real_file_util_move(source_path, source_list, dest_path, FALSE, parent);
+	real_file_util_move(source_fd, source_list, dest_path, FALSE, parent);
 }
 
-void file_util_copy(const gchar *source_path, GList *source_list, const gchar *dest_path, GtkWidget *parent)
+void file_util_copy(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent)
 {
-	real_file_util_move(source_path, source_list, dest_path, TRUE, parent);
+	real_file_util_move(source_fd, source_list, dest_path, TRUE, parent);
 }
 
 void file_util_move_simple(GList *list, const gchar *dest_path)
@@ -1112,21 +1157,21 @@
 	if (!list) return;
 	if (!dest_path)
 		{
-		path_list_free(list);
+		filelist_free(list);
 		return;
 		}
 
 	if (!list->next)
 		{
-		const gchar *source;
+		FileData *source_fd;
 		gchar *dest;
 
-		source = list->data;
-		dest = concat_dir_and_file(dest_path, filename_from_path(source));
-
-		file_util_move_single(file_data_single_new(source, dest, FALSE));
+		source_fd = list->data;
+		dest = concat_dir_and_file(dest_path, source_fd->name);
+
+		file_util_move_single(file_data_single_new(source_fd, dest, FALSE));
 		g_free(dest);
-		path_list_free(list);
+		filelist_free(list);
 		return;
 		}
 
@@ -1138,21 +1183,21 @@
 	if (!list) return;
 	if (!dest_path)
 		{
-		path_list_free(list);
+		filelist_free(list);
 		return;
 		}
 
 	if (!list->next)
 		{
-		const gchar *source;
+		FileData *source_fd;
 		gchar *dest;
 
-		source = list->data;
-		dest = concat_dir_and_file(dest_path, filename_from_path(source));
-
-		file_util_move_single(file_data_single_new(source, dest, TRUE));
+		source_fd = list->data;
+		dest = concat_dir_and_file(dest_path, source_fd->name);
+
+		file_util_move_single(file_data_single_new(source_fd, dest, TRUE));
 		g_free(dest);
-		path_list_free(list);
+		filelist_free(list);
 		return;
 		}
 
@@ -1214,7 +1259,7 @@
 			warned = TRUE;
 			}
 		total -= fd->size;
-		file_data_free(fd);
+		file_data_unref(fd);
 		}
 
 	filelist_free(list);
@@ -1247,18 +1292,18 @@
 	*gd = NULL;
 }
 
-static gint file_util_unlink(const gchar *path)
+static gint file_util_unlink(FileData *fd)
 {
 	static GenericDialog *gd = NULL;
 	gchar *result = NULL;
 	gint success = TRUE;
 
-	if (!isfile(path)) return FALSE;
+	if (!isfile(fd->path)) return FALSE;
 
 
 	if (!safe_delete_enable)
 		{
-		return unlink_file(path);
+		return unlink_file(fd->path);
 		}
 
 	if (!isdir(safe_delete_path))
@@ -1275,18 +1320,18 @@
 		{
 		gchar *dest;
 
-		dest = file_util_safe_dest(path);
+		dest = file_util_safe_dest(fd->path);
 		if (dest)
 			{
-			if (debug) printf("safe deleting %s to %s\n", path, dest);
-			success = move_file(path, dest);
+			if (debug) printf("safe deleting %s to %s\n", fd->path, dest);
+			success = move_file(fd->path, dest);
 			}
 		else
 			{
 			success = FALSE;
 			}
 
-		if (!success && !access_file(path, W_OK))
+		if (!success && !access_file(fd->path, W_OK))
 			{
 			result = _("Permission denied");
 			}
@@ -1347,7 +1392,7 @@
 
 	if (editor_command[CMD_DELETE])
 		{
-		if (!start_editor_from_path_list(CMD_DELETE, source_list))
+		if (!start_editor_from_filelist(CMD_DELETE, source_list))
 			{
 			file_util_warning_dialog(_("File deletion failed"), _("Unable to delete files by external command\n"), GTK_STOCK_DIALOG_ERROR, NULL);
 			}
@@ -1355,10 +1400,10 @@
 			{
 			while (source_list)
 				{
-				gchar *path = source_list->data;
-				source_list = g_list_remove(source_list, path);
-				file_maint_removed(path, source_list);
-				g_free(path);
+				FileData *fd = source_list->data;
+				source_list = g_list_remove(source_list, fd);
+				file_maint_removed(fd, source_list);
+				file_data_unref(fd);
 				}
 			}
 		return;
@@ -1367,11 +1412,11 @@
 
 	while (source_list)
 		{
-		gchar *path = source_list->data;
-
-		source_list = g_list_remove(source_list, path);
-
-		if (!file_util_unlink(path))
+		FileData *fd = source_list->data;
+
+		source_list = g_list_remove(source_list, fd);
+
+		if (!file_util_unlink(fd))
 			{
 			if (source_list)
 				{
@@ -1382,7 +1427,7 @@
 						      NULL, TRUE,
 						      file_util_delete_multiple_cancel_cb, source_list);
 
-				text = g_strdup_printf(_("Unable to delete file:\n %s\n Continue multiple delete operation?"), path);
+				text = g_strdup_printf(_("Unable to delete file:\n %s\n Continue multiple delete operation?"), fd->path);
 				generic_dialog_add_message(d, GTK_STOCK_DIALOG_WARNING, NULL, text);
 				g_free(text);
 
@@ -1394,18 +1439,18 @@
 				{
 				gchar *text;
 				
-				text = g_strdup_printf(_("Unable to delete file:\n%s"), path);
+				text = g_strdup_printf(_("Unable to delete file:\n%s"), fd->path);
 				file_util_warning_dialog(_("Delete failed"), text, GTK_STOCK_DIALOG_ERROR, NULL);
 				g_free(text);
 				}
-			g_free(path);
+			file_data_unref(fd);
 			return;
 			}
 		else
 			{
-			file_maint_removed(path, source_list);
+			file_maint_removed(fd, source_list);
 			}
-		g_free(path);
+		file_data_unref(fd);
 		}
 }
 
@@ -1413,7 +1458,7 @@
 {
 	GList *source_list = data;
 
-	path_list_free(source_list);
+	filelist_free(source_list);
 }
 
 static void file_util_delete_multiple_review_skip(GenericDialog *gd, gint next)
@@ -1423,7 +1468,7 @@
 	GtkWidget *button_label;
 	GList *list;
 	GList *list_point;
-	const gchar *path;
+	FileData *fd;
 	gchar *buf;
 
 	list = gd->data;
@@ -1452,9 +1497,9 @@
 
 	if (!list_point) return;
 
-	path = list_point->data;
+	fd = list_point->data;
 	buf = g_strdup_printf(_("File %d of %d"),
-			      g_list_index(list, (gpointer)path) + 1,
+			      g_list_index(list, (gpointer)fd) + 1,
 			      g_list_length(list));
 	gtk_label_set_text(GTK_LABEL(button_label), buf);
 	g_free(buf);
@@ -1462,7 +1507,7 @@
 	gtk_widget_set_sensitive(button_back, (list_point->prev != NULL) );
 	gtk_widget_set_sensitive(button_next, (list_point->next != NULL) );
 
-	generic_dialog_image_set(gd, path);
+	generic_dialog_image_set(gd, fd);
 
 	g_object_set_data(G_OBJECT(gd->dialog), "list_point", list_point);
 }
@@ -1563,49 +1608,47 @@
 
 static void file_util_delete_ok_cb(GenericDialog *gd, gpointer data)
 {
-	gchar *path = data;
+	FileData *fd = data;
 
 	if (editor_command[CMD_DELETE])
 		{
-		if (!start_editor_from_file(CMD_DELETE, path))
+		if (!start_editor_from_file(CMD_DELETE, fd))
 			{
-			gchar *text = g_strdup_printf(_("Unable to delete file by external command:\n%s"), path);
+			gchar *text = g_strdup_printf(_("Unable to delete file by external command:\n%s"), fd->path);
 			file_util_warning_dialog(_("File deletion failed"), text, GTK_STOCK_DIALOG_ERROR, NULL);
 			g_free(text);
 			}
 		else
 			{
-			file_maint_removed(path, NULL);
+			file_maint_removed(fd, NULL);
 			}
 		}
-	else if (!file_util_unlink(path))
+	else if (!file_util_unlink(fd))
 		{
-		gchar *text = g_strdup_printf(_("Unable to delete file:\n%s"), path);
+		gchar *text = g_strdup_printf(_("Unable to delete file:\n%s"), fd->path);
 		file_util_warning_dialog(_("File deletion failed"), text, GTK_STOCK_DIALOG_ERROR, NULL);
 		g_free(text);
 		}
 	else
 		{
-		file_maint_removed(path, NULL);
+		file_maint_removed(fd, NULL);
 		}
 
-	g_free(path);
+	file_data_unref(fd);
 }
 
 static void file_util_delete_cancel_cb(GenericDialog *gd, gpointer data)
 {
-	gchar *path = data;
-
-	g_free(path);
+	FileData *fd = data;
+
+	file_data_unref(fd);
 }
 
-static void file_util_delete_single(const gchar *path, GtkWidget *parent)
+static void file_util_delete_single(FileData *fd, GtkWidget *parent)
 {
-	gchar *buf = g_strdup(path);
-
 	if (!confirm_delete)
 		{
-		file_util_delete_ok_cb(NULL, buf);
+		file_util_delete_ok_cb(NULL, file_data_ref(fd));
 		}
 	else
 		{
@@ -1615,22 +1658,22 @@
 
 		gd = file_util_gen_dlg(_("Delete file - GQview"), "GQview", "dlg_confirm",
 					parent, TRUE,
-					file_util_delete_cancel_cb, buf);
+					file_util_delete_cancel_cb, file_data_ref(fd));
 
 		generic_dialog_add_message(gd, NULL, _("Delete file?"), NULL);
 
 		table = pref_table_new(gd->vbox, 2, 2, FALSE, FALSE);
 
 		pref_table_label(table, 0, 0, _("File name:"), 1.0);
-		pref_table_label(table, 1, 0, filename_from_path(path), 0.0);
+		pref_table_label(table, 1, 0, fd->name, 0.0);
 
 		pref_table_label(table, 0, 1, _("Location:"), 1.0);
 
-		base = remove_level_from_path(path);
+		base = remove_level_from_path(fd->path);
 		pref_table_label(table, 1, 1, base, 0.0);
 		g_free(base);
 
-		generic_dialog_add_image(gd, NULL, path, NULL, NULL, NULL, FALSE);
+		generic_dialog_add_image(gd, NULL, fd, NULL, NULL, NULL, FALSE);
 
 		box_append_safe_delete_status(gd);
 
@@ -1640,18 +1683,18 @@
 		}
 }
 
-void file_util_delete(const gchar *source_path, GList *source_list, GtkWidget *parent)
+void file_util_delete(FileData *source_fd, GList *source_list, GtkWidget *parent)
 {
-	if (!source_path && !source_list) return;
-
-	if (source_path)
+	if (!source_fd && !source_list) return;
+
+	if (source_fd)
 		{
-		file_util_delete_single(source_path, parent);
+		file_util_delete_single(source_fd, parent);
 		}
 	else if (!source_list->next)
 		{
 		file_util_delete_single(source_list->data, parent);
-		path_list_free(source_list);
+		filelist_free(source_list);
 		}
 	else
 		{
@@ -1670,7 +1713,8 @@
  */
 
 enum {
-	RENAME_COLUMN_PATH = 0,
+	RENAME_COLUMN_FD = 0,
+	RENAME_COLUMN_PATH,
 	RENAME_COLUMN_NAME,
 	RENAME_COLUMN_PREVIEW,
 	RENAME_COLUMN_COUNT
@@ -1685,7 +1729,7 @@
 typedef struct _RenameDataMult RenameDataMult;
 struct _RenameDataMult
 {
-	FileDialog *fd;
+	FileDialog *fdlg;
 
 	RenameType rename_type;
 
@@ -1718,10 +1762,10 @@
 	RenameDataMult *rd = data;
 	GtkWidget *dialog;
 
-	dialog = GENERIC_DIALOG(rd->fd)->dialog;
+	dialog = GENERIC_DIALOG(rd->fdlg)->dialog;
 	if (!GTK_WIDGET_VISIBLE(dialog)) gtk_widget_show(dialog);
 
-	rd->fd->type = TRUE;
+	rd->fdlg->type = TRUE;
 	file_util_rename_multiple(rd);
 }
 
@@ -1730,11 +1774,11 @@
 	RenameDataMult *rd = data;
 	GtkWidget *dialog;
 
-	dialog = GENERIC_DIALOG(rd->fd)->dialog;
+	dialog = GENERIC_DIALOG(rd->fdlg)->dialog;
 	if (!GTK_WIDGET_VISIBLE(dialog)) gtk_widget_show(dialog);
 }
 
-static gint file_util_rename_multiple_find_row(RenameDataMult *rd, const gchar *path, GtkTreeIter *iter)
+static gint file_util_rename_multiple_find_row(RenameDataMult *rd, FileData *fd, GtkTreeIter *iter)
 {
 	GtkTreeModel *store;
 	gint valid;
@@ -1744,12 +1788,12 @@
 	valid = gtk_tree_model_get_iter_first(store, iter);
 	while (valid)
 		{
-		gchar *path_n;
+		FileData *fd_n;
 		gint ret;
 
-		gtk_tree_model_get(GTK_TREE_MODEL(store), iter, RENAME_COLUMN_PATH, &path_n, -1);
-		ret = (strcmp(path_n, path) == 0);
-		g_free(path_n);
+		gtk_tree_model_get(GTK_TREE_MODEL(store), iter, RENAME_COLUMN_FD, &fd_n, -1);
+		ret = (fd_n == fd);
+//		file_data_unref(fd_n);
 		if (ret) return row;
 
 		valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), iter);
@@ -1761,11 +1805,11 @@
 
 static void file_util_rename_multiple(RenameDataMult *rd)
 {
-	FileDialog *fd;
-
-	fd = rd->fd;
-
-	if (isfile(fd->dest_path) && !fd->type)
+	FileDialog *fdlg;
+
+	fdlg = rd->fdlg;
+
+	if (isfile(fdlg->dest_path) && !fdlg->type)
 		{
 		GenericDialog *gd;
 
@@ -1780,21 +1824,22 @@
 
 		generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), file_util_rename_multiple_ok_cb, TRUE);
 		generic_dialog_add_image(gd, NULL,
-					 fd->dest_path, _("Existing file"),
-					 fd->source_path, _("New file"), TRUE);
-
-		gtk_widget_hide(GENERIC_DIALOG(fd)->dialog);
+					 file_data_new_simple(fdlg->dest_path), _("Existing file"),
+					 fdlg->source_fd, _("New file"), TRUE);
+
+		gtk_widget_hide(GENERIC_DIALOG(fdlg)->dialog);
 
 		gtk_widget_show(gd->dialog);
 		return;
 		}
 	else
 		{
-		if (!rename_file_ext(fd->source_path, fd->dest_path))
+		file_data_change_info_new(fdlg->source_fd->path, fdlg->dest_path, fdlg->source_fd);
+		if (!rename_file_ext(fdlg->source_fd))
 			{
 			gchar *text = g_strdup_printf(_("Unable to rename file:\n%s\n to:\n%s"),
-						      filename_from_path(fd->source_path),
-						      filename_from_path(fd->dest_path));
+						      fdlg->source_fd->name,
+						      filename_from_path(fdlg->dest_path));
 			file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, NULL);
 			g_free(text);
 			}
@@ -1805,10 +1850,8 @@
 			GtkTreeIter next;
 			gint row;
 
-			file_maint_renamed(fd->source_path, fd->dest_path);
-
 			store = gtk_tree_view_get_model(GTK_TREE_VIEW(rd->listview));
-			row = file_util_rename_multiple_find_row(rd, rd->fd->source_path, &iter);
+			row = file_util_rename_multiple_find_row(rd, rd->fdlg->source_fd, &iter);
 
 			if (row >= 0 &&
 			    (gtk_tree_model_iter_nth_child(store, &next, NULL, row + 1) ||
@@ -1824,7 +1867,7 @@
 				{
 				if (debug) printf("closed by #%d\n", row);
 
-				file_dialog_close(rd->fd);
+				file_dialog_close(rd->fdlg);
 				}
 			}
 		}
@@ -1941,16 +1984,16 @@
 		{
 		gchar *dest;
 		gchar *base;
-		gchar *path;
-
-		gtk_tree_model_get(store, &iter, RENAME_COLUMN_PATH, &path, -1);
-		base = remove_level_from_path(path);
+		FileData *fd;
+
+		gtk_tree_model_get(store, &iter, RENAME_COLUMN_FD, &fd, -1);
+		base = remove_level_from_path(fd->path);
 
 		if (rd->rename_type == RENAME_TYPE_FORMATTED)
 			{
 			gchar *new_name;
 
-			new_name = file_util_rename_multiple_auto_format_name(format, filename_from_path(path), n);
+			new_name = file_util_rename_multiple_auto_format_name(format, fd->name, n);
 			dest = g_strconcat(base, "/", new_name, NULL);
 			g_free(new_name);
 			}
@@ -1963,7 +2006,7 @@
 
 		g_free(dest);
 		g_free(base);
-		g_free(path);
+//		file_data_unref(fd);
 
 		n++;
 		valid = gtk_tree_model_iter_next(store, &iter);
@@ -1993,16 +2036,16 @@
 		{
 		gchar *dest;
 		gchar *base;
-		gchar *path;
-
-		gtk_tree_model_get(store, &iter, RENAME_COLUMN_PATH, &path, -1);
-		base = remove_level_from_path(path);
+		FileData *fd;
+
+		gtk_tree_model_get(store, &iter, RENAME_COLUMN_FD, &fd, -1);
+		base = remove_level_from_path(fd->path);
 
 		if (rd->rename_type == RENAME_TYPE_FORMATTED)
 			{
 			gchar *new_name;
 
-			new_name = file_util_rename_multiple_auto_format_name(format, filename_from_path(path), n);
+			new_name = file_util_rename_multiple_auto_format_name(format, fd->name, n);
 			dest = g_strconcat(base, "/", new_name, NULL);
 			g_free(new_name);
 			}
@@ -2010,19 +2053,16 @@
 			{
 			dest = g_strdup_printf("%s/%s%0*d%s", base, front, padding, n, end);
 			}
-
-		if (!rename_file_ext(path, dest))
+			
+		file_data_change_info_new(fd->path, dest, fd);
+		if (!rename_file_ext(fd))
 			{
 			success = FALSE;
 			}
-		else
-			{
-			file_maint_renamed(path, dest);
-			}
 
 		g_free(dest);
 		g_free(base);
-		g_free(path);
+//		file_data_unref(fd);
 
 		if (success)
 			{
@@ -2046,17 +2086,17 @@
 		n--;
 		gtk_spin_button_set_value(GTK_SPIN_BUTTON(rd->auto_spin_start), (gdouble)n);
 
-		buf = g_strdup_printf(_("Failed to rename\n%s\nThe number was %d."), filename_from_path(rd->fd->source_path), n);
+		buf = g_strdup_printf(_("Failed to rename\n%s\nThe number was %d."), rd->fdlg->source_fd->name, n);
 		file_util_warning_dialog(_("Auto rename"), buf, GTK_STOCK_DIALOG_ERROR, NULL);
 		g_free(buf);
 
 		return;
 		}
 
-	file_dialog_close(rd->fd);
+	file_dialog_close(rd->fdlg);
 }
 
-static void file_util_rename_multiple_cb(FileDialog *fd, gpointer data)
+static void file_util_rename_multiple_cb(FileDialog *fdlg, gpointer data)
 {
 	RenameDataMult *rd = data;
 	gchar *base;
@@ -2069,26 +2109,26 @@
 		}
 
 	name = gtk_entry_get_text(GTK_ENTRY(rd->rename_entry));
-	base = remove_level_from_path(fd->source_path);
-
-	g_free(fd->dest_path);
-	fd->dest_path = concat_dir_and_file(base, name);
+	base = remove_level_from_path(fdlg->source_fd->path);
+
+	g_free(fdlg->dest_path);
+	fdlg->dest_path = concat_dir_and_file(base, name);
 	g_free(base);
 
-	if (strlen(name) == 0 || strcmp(fd->source_path, fd->dest_path) == 0)
+	if (strlen(name) == 0 || strcmp(fdlg->source_fd->path, fdlg->dest_path) == 0)
 		{
 		return;
 		}
 
-	fd->type = FALSE;
+	fdlg->type = FALSE;
 	file_util_rename_multiple(rd);
 }
 
-static void file_util_rename_multiple_close_cb(FileDialog *fd, gpointer data)
+static void file_util_rename_multiple_close_cb(FileDialog *fdlg, gpointer data)
 {
 	RenameDataMult *rd = data;
 
-	file_dialog_close(rd->fd);
+	file_dialog_close(rd->fdlg);
 }
 
 static gboolean file_util_rename_multiple_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath,
@@ -2097,20 +2137,20 @@
 	RenameDataMult *rd = data;
 	GtkTreeIter iter;
 	const gchar *name;
-	gchar *path = NULL;
+	FileData *fd = NULL;
 
 	if (path_currently_selected ||
 	    !gtk_tree_model_get_iter(store, &iter, tpath)) return TRUE;
-	gtk_tree_model_get(store, &iter, RENAME_COLUMN_PATH, &path, -1);
-
-	g_free(rd->fd->source_path);
-	rd->fd->source_path = path;
-
-	name = filename_from_path(rd->fd->source_path);
+	gtk_tree_model_get(store, &iter, RENAME_COLUMN_FD, &fd, -1);
+
+	file_data_unref(rd->fdlg->source_fd);
+	rd->fdlg->source_fd = file_data_ref(fd);
+
+	name = rd->fdlg->source_fd->name;
 	gtk_label_set_text(GTK_LABEL(rd->rename_label), name);
 	gtk_entry_set_text(GTK_ENTRY(rd->rename_entry), name);
 
-	image_change_path(rd->imd, rd->fd->source_path, 0.0);
+	image_change_fd(rd->imd, rd->fdlg->source_fd, 0.0);
 
 	if (GTK_WIDGET_VISIBLE(rd->rename_box))
 		{
@@ -2157,11 +2197,11 @@
 
 		if (rd->rename_type == RENAME_TYPE_FORMATTED)
 			{
-			gchar *path;
+			FileData *fd;
 	
-			gtk_tree_model_get(store, &iter, RENAME_COLUMN_PATH, &path, -1);
-			dest = file_util_rename_multiple_auto_format_name(format, filename_from_path(path), n);
-			g_free(path);
+			gtk_tree_model_get(store, &iter, RENAME_COLUMN_FD, &fd, -1);
+			dest = file_util_rename_multiple_auto_format_name(format, fd->name, n);
+//		        file_data_unref(fd);
 			}
 		else
 			{
@@ -2302,20 +2342,20 @@
 
 	rd = g_new0(RenameDataMult, 1);
 
-	rd->fd = file_util_file_dlg(_("Rename - GQview"),
+	rd->fdlg = file_util_file_dlg(_("Rename - GQview"),
 				    "GQview", "dlg_rename", parent,
 				    file_util_rename_multiple_close_cb, rd);
-	generic_dialog_add_message(GENERIC_DIALOG(rd->fd), NULL, _("Rename multiple files"), NULL);
-	file_dialog_add_button(rd->fd, GTK_STOCK_OK, _("_Rename"), file_util_rename_multiple_cb, TRUE);
-
-	rd->fd->source_path = g_strdup(source_list->data);
-	rd->fd->dest_path = NULL;
+	generic_dialog_add_message(GENERIC_DIALOG(rd->fdlg), NULL, _("Rename multiple files"), NULL);
+	file_dialog_add_button(rd->fdlg, GTK_STOCK_OK, _("_Rename"), file_util_rename_multiple_cb, TRUE);
+
+	rd->fdlg->source_fd = file_data_ref(source_list->data);
+	rd->fdlg->dest_path = NULL;
 
 	rd->rename_type = RENAME_TYPE_MANUAL;
 
 	rd->update_idle_id = -1;
 
-	vbox = GENERIC_DIALOG(rd->fd)->vbox;
+	vbox = GENERIC_DIALOG(rd->fdlg)->vbox;
 
 	pane = gtk_hpaned_new();
 	gtk_box_pack_start(GTK_BOX(vbox), pane, TRUE, TRUE, 0);
@@ -2328,7 +2368,7 @@
 	gtk_paned_pack1(GTK_PANED(pane), scrolled, TRUE, TRUE);
 	gtk_widget_show(scrolled);
 
-	store = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+	store = gtk_list_store_new(4, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
 	rd->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
 	g_object_unref(store);
 
@@ -2354,16 +2394,16 @@
 	work = source_list;
 	while (work)
 		{
-		gchar *path = work->data;
+		FileData *fd = work->data;
 		GtkTreeIter iter;
 
 		gtk_list_store_append(store, &iter);
-		gtk_list_store_set(store, &iter, RENAME_COLUMN_PATH, path, RENAME_COLUMN_NAME, filename_from_path(path), -1);
+		gtk_list_store_set(store, &iter, RENAME_COLUMN_FD, fd, RENAME_COLUMN_PATH, fd->path, RENAME_COLUMN_NAME, fd->name, -1);
 
 		work = work->next;
 		}
 
-	path_list_free(source_list);
+	filelist_free(source_list);
 
 	rd->imd = image_new(TRUE);
 	g_object_set(G_OBJECT(rd->imd->pr), "zoom_expand", FALSE, NULL);
@@ -2392,16 +2432,16 @@
 	table = pref_table_new(rd->rename_box, 2, 2, FALSE, FALSE);
 
 	pref_table_label(table, 0, 0, _("Original name:"), 1.0);
-	rd->rename_label = pref_table_label(table, 1, 0, filename_from_path(rd->fd->source_path), 0.0);
+	rd->rename_label = pref_table_label(table, 1, 0, rd->fdlg->source_fd->name, 0.0);
 
 	pref_table_label(table, 0, 1, _("New name:"), 1.0);
 
 	rd->rename_entry = gtk_entry_new();
 	gtk_table_attach(GTK_TABLE(table), rd->rename_entry, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0);
-	generic_dialog_attach_default(GENERIC_DIALOG(rd->fd), rd->rename_entry);
+	generic_dialog_attach_default(GENERIC_DIALOG(rd->fdlg), rd->rename_entry);
 	gtk_widget_grab_focus(rd->rename_entry);
 
-	name = filename_from_path(rd->fd->source_path);
+	name = rd->fdlg->source_fd->name;
 	gtk_entry_set_text(GTK_ENTRY(rd->rename_entry), name);
 	gtk_editable_select_region(GTK_EDITABLE(rd->rename_entry), 0, filename_base_length(name));
 	gtk_widget_show(rd->rename_entry);
@@ -2458,12 +2498,12 @@
 					0.0, 1000000.0, 1.0, 0, 1.0,
 					G_CALLBACK(file_util_rename_multiple_preview_adj_cb), rd);
 
-	image_change_path(rd->imd, rd->fd->source_path, 0.0);
-
-	g_signal_connect(G_OBJECT(GENERIC_DIALOG(rd->fd)->dialog), "destroy",
+	image_change_fd(rd->imd, rd->fdlg->source_fd, 0.0);
+
+	g_signal_connect(G_OBJECT(GENERIC_DIALOG(rd->fdlg)->dialog), "destroy",
 			 G_CALLBACK(file_util_rename_multiple_destroy_cb), rd);
 
-	gtk_widget_show(GENERIC_DIALOG(rd->fd)->dialog);
+	gtk_widget_show(GENERIC_DIALOG(rd->fdlg)->dialog);
 }
 
 /*
@@ -2502,8 +2542,8 @@
 
 		generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), file_util_rename_single_ok_cb, TRUE);
 		generic_dialog_add_image(gd, NULL,
-					 fds->dest, _("Existing file"),
-					 fds->source, _("New file"), TRUE);
+					 file_data_new_simple(fds->dest), _("Existing file"),
+					 fds->source_fd, _("New file"), TRUE);
 
 		gtk_widget_show(gd->dialog);
 
@@ -2511,94 +2551,97 @@
 		}
 	else
 		{
-		if (!rename_file_ext(fds->source, fds->dest))
+/*
+		GList *list = g_list_append(NULL, file_data_ref(fds->source_fd));
+		file_util_do_move_list(list, FALSE, TRUE);
+		filelist_free(list);
+*/
+		file_data_change_info_new(fds->source_fd->path, fds->dest, fds->source_fd);
+		if (!rename_file_ext(fds->source_fd))
 			{
-			gchar *text = g_strdup_printf(_("Unable to rename file:\n%s\nto:\n%s"), filename_from_path(fds->source), filename_from_path(fds->dest));
+			gchar *text = g_strdup_printf(_("Unable to rename file:\n%s\nto:\n%s"), fds->source_fd->name, filename_from_path(fds->dest));
 			file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, NULL);
 			g_free(text);
 			}
-		else
-			{
-			file_maint_renamed(fds->source, fds->dest);
-			}
+
 		}
 	file_data_single_free(fds);
 }
 
-static void file_util_rename_single_cb(FileDialog *fd, gpointer data)
+static void file_util_rename_single_cb(FileDialog *fdlg, gpointer data)
 {
 	const gchar *name;
 	gchar *path;
 
-	name = gtk_entry_get_text(GTK_ENTRY(fd->entry));
-	path = concat_dir_and_file(fd->dest_path, name);
-
-	if (strlen(name) == 0 || strcmp(fd->source_path, path) == 0)
+	name = gtk_entry_get_text(GTK_ENTRY(fdlg->entry));
+	path = concat_dir_and_file(fdlg->dest_path, name);
+
+	if (strlen(name) == 0 || strcmp(fdlg->source_fd->path, path) == 0)
 		{
 		g_free(path);
 		return;
 		}
 
-	file_util_rename_single(file_data_single_new(fd->source_path, path, fd->type));
+	file_util_rename_single(file_data_single_new(fdlg->source_fd, path, fdlg->type));
 
 	g_free(path);
-	file_dialog_close(fd);
+	file_dialog_close(fdlg);
 }
 
-static void file_util_rename_single_close_cb(FileDialog *fd, gpointer data)
+static void file_util_rename_single_close_cb(FileDialog *fdlg, gpointer data)
 {
-	file_dialog_close(fd);
+	file_dialog_close(fdlg);
 }
 
-static void file_util_rename_single_do(const gchar *source_path, GtkWidget *parent)
+static void file_util_rename_single_do(FileData *source_fd, GtkWidget *parent)
 {
-	FileDialog *fd;
+	FileDialog *fdlg;
 	GtkWidget *table;
 	const gchar *name;
 
-	fd = file_util_file_dlg(_("Rename - GQview"), "GQview", "dlg_rename", parent,
+	fdlg = file_util_file_dlg(_("Rename - GQview"), "GQview", "dlg_rename", parent,
 			     file_util_rename_single_close_cb, NULL);
 
-	generic_dialog_add_message(GENERIC_DIALOG(fd), NULL, _("Rename file"), NULL);
-	generic_dialog_add_image(GENERIC_DIALOG(fd), NULL, source_path, NULL, NULL, NULL, FALSE);
-
-	file_dialog_add_button(fd, GTK_STOCK_OK, _("_Rename"), file_util_rename_single_cb, TRUE);
-
-	fd->source_path = g_strdup(source_path);
-	fd->dest_path = remove_level_from_path(source_path);
-
-	table = pref_table_new(GENERIC_DIALOG(fd)->vbox, 2, 2, FALSE, FALSE);
+	generic_dialog_add_message(GENERIC_DIALOG(fdlg), NULL, _("Rename file"), NULL);
+	generic_dialog_add_image(GENERIC_DIALOG(fdlg), NULL, source_fd, NULL, NULL, NULL, FALSE);
+
+	file_dialog_add_button(fdlg, GTK_STOCK_OK, _("_Rename"), file_util_rename_single_cb, TRUE);
+
+	fdlg->source_fd = file_data_ref(source_fd);
+	fdlg->dest_path = remove_level_from_path(source_fd->path);
+
+	table = pref_table_new(GENERIC_DIALOG(fdlg)->vbox, 2, 2, FALSE, FALSE);
 
 	pref_table_label(table, 0, 0, _("Original name:"), 1.0);
-	pref_table_label(table, 1, 0, filename_from_path(fd->source_path), 0.0);
+	pref_table_label(table, 1, 0, fdlg->source_fd->name, 0.0);
 
 	pref_table_label(table, 0, 1, _("New name:"), 1.0);
 
-	fd->entry = gtk_entry_new();
-	gtk_table_attach(GTK_TABLE(table), fd->entry, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0);
-	generic_dialog_attach_default(GENERIC_DIALOG(fd), fd->entry);
-	gtk_widget_grab_focus(fd->entry);
-
-	name = filename_from_path(fd->source_path);
-	gtk_entry_set_text(GTK_ENTRY(fd->entry), name);
-	gtk_editable_select_region(GTK_EDITABLE(fd->entry), 0, filename_base_length(name));
-	gtk_widget_show(fd->entry);
-
-	gtk_widget_show(GENERIC_DIALOG(fd)->dialog);
+	fdlg->entry = gtk_entry_new();
+	gtk_table_attach(GTK_TABLE(table), fdlg->entry, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0);
+	generic_dialog_attach_default(GENERIC_DIALOG(fdlg), fdlg->entry);
+	gtk_widget_grab_focus(fdlg->entry);
+
+	name = fdlg->source_fd->name;
+	gtk_entry_set_text(GTK_ENTRY(fdlg->entry), name);
+	gtk_editable_select_region(GTK_EDITABLE(fdlg->entry), 0, filename_base_length(name));
+	gtk_widget_show(fdlg->entry);
+
+	gtk_widget_show(GENERIC_DIALOG(fdlg)->dialog);
 }
 
-void file_util_rename(const gchar *source_path, GList *source_list, GtkWidget *parent)
+void file_util_rename(FileData *source_fd, GList *source_list, GtkWidget *parent)
 {
-	if (!source_path && !source_list) return;
-
-	if (source_path)
+	if (!source_fd && !source_list) return;
+
+	if (source_fd)
 		{
-		file_util_rename_single_do(source_path, parent);
+		file_util_rename_single_do(source_fd, parent);
 		}
 	else if (!source_list->next)
 		{
 		file_util_rename_single_do(source_list->data, parent);
-		path_list_free(source_list);
+		filelist_free(source_list);
 		}
 	else
 		{
@@ -2643,11 +2686,11 @@
 	g_free(path);
 }
 
-static void file_util_create_dir_cb(FileDialog *fd, gpointer data)
+static void file_util_create_dir_cb(FileDialog *fdlg, gpointer data)
 {
 	const gchar *name;
 
-	name = gtk_entry_get_text(GTK_ENTRY(fd->entry));
+	name = gtk_entry_get_text(GTK_ENTRY(fdlg->entry));
 
 	if (strlen(name) == 0) return;
 
@@ -2660,52 +2703,52 @@
 		}
 	else
 		{
-		file_util_create_dir_do(fd->dest_path, name);
+		file_util_create_dir_do(fdlg->dest_path, name);
 		}
 
-	file_dialog_close(fd);
+	file_dialog_close(fdlg);
 }
 
-static void file_util_create_dir_close_cb(FileDialog *fd, gpointer data)
+static void file_util_create_dir_close_cb(FileDialog *fdlg, gpointer data)
 {
-	file_dialog_close(fd);
+	file_dialog_close(fdlg);
 }
 
 void file_util_create_dir(const gchar *path, GtkWidget *parent)
 {
-	FileDialog *fd;
+	FileDialog *fdlg;
 	gchar *text;
 
 	if (!isdir(path)) return;
 
-	fd = file_util_file_dlg(_("New folder - GQview"), "GQview", "dlg_newdir", parent,
+	fdlg = file_util_file_dlg(_("New folder - GQview"), "GQview", "dlg_newdir", parent,
 			     file_util_create_dir_close_cb, NULL);
 
 	text = g_strdup_printf(_("Create folder in:\n%s\nnamed:"), path);
-	generic_dialog_add_message(GENERIC_DIALOG(fd), NULL, NULL, text);
+	generic_dialog_add_message(GENERIC_DIALOG(fdlg), NULL, NULL, text);
 	g_free(text);
 
-	file_dialog_add_button(fd, GTK_STOCK_OK, NULL, file_util_create_dir_cb, TRUE);
-
-	fd->dest_path = g_strdup(path);
-
-	fd->entry = gtk_entry_new();
-	gtk_box_pack_start(GTK_BOX(GENERIC_DIALOG(fd)->vbox), fd->entry, FALSE, FALSE, 0);
-	generic_dialog_attach_default(GENERIC_DIALOG(fd), fd->entry);
-	gtk_widget_grab_focus(fd->entry);
-	gtk_widget_show(fd->entry);
-
-	gtk_widget_show(GENERIC_DIALOG(fd)->dialog);
+	file_dialog_add_button(fdlg, GTK_STOCK_OK, NULL, file_util_create_dir_cb, TRUE);
+
+	fdlg->dest_path = g_strdup(path);
+
+	fdlg->entry = gtk_entry_new();
+	gtk_box_pack_start(GTK_BOX(GENERIC_DIALOG(fdlg)->vbox), fdlg->entry, FALSE, FALSE, 0);
+	generic_dialog_attach_default(GENERIC_DIALOG(fdlg), fdlg->entry);
+	gtk_widget_grab_focus(fdlg->entry);
+	gtk_widget_show(fdlg->entry);
+
+	gtk_widget_show(GENERIC_DIALOG(fdlg)->dialog);
 }
 
-gint file_util_rename_dir(const gchar *old_path, const gchar *new_path, GtkWidget *parent)
+gint file_util_rename_dir(FileData *old_fd, const gchar *new_path, GtkWidget *parent)
 {
 	const gchar *old_name;
 	const gchar *new_name;
 
-	if (!old_path || !new_path || !isdir(old_path)) return FALSE;
-
-	old_name = filename_from_path(old_path);
+	if (!old_fd || !new_path || !isdir(old_fd->path)) return FALSE;
+
+	old_name = old_fd->name;
 	new_name = filename_from_path(new_path);
 
 	if (isdir(new_path))
@@ -2725,8 +2768,8 @@
 
 		return FALSE;
 		}
-
-	if (!rename_file_ext(old_path, new_path))
+	file_data_change_info_new(old_fd->path, new_path, old_fd);
+	if (!rename_file_ext(old_fd))
 		{
 		gchar *text = g_strdup_printf(_("Failed to rename %s to %s."), old_name, new_name);
 		file_util_warning_dialog(_("Rename failed"), text, GTK_STOCK_DIALOG_ERROR, parent);
@@ -2762,13 +2805,21 @@
 typedef struct _UtilityData UtilityData;
 struct _UtilityData {
 	UtilityType type;
-	gchar *source_path;
+	FileData *source_fd;
 	GList *dlist;
 	GList *flist;
 
 	GenericDialog *gd;
 };
 
+enum {
+	UTILITY_COLUMN_FD = 0,
+	UTILITY_COLUMN_PATH,
+	UTILITY_COLUMN_NAME,
+	UTILITY_COLUMN_COUNT
+};
+
+
 #define UTILITY_LIST_MIN_WIDTH  250
 #define UTILITY_LIST_MIN_HEIGHT 150
 
@@ -2780,9 +2831,9 @@
 {
 	if (!ud) return;
 
-	g_free(ud->source_path);
-	path_list_free(ud->dlist);
-	path_list_free(ud->flist);
+	file_data_unref(ud->source_fd);
+	filelist_free(ud->dlist);
+	filelist_free(ud->flist);
 
 	if (ud->gd) generic_dialog_close(ud->gd);
 
@@ -2819,7 +2870,7 @@
 	gtk_box_pack_start(GTK_BOX(box), scrolled, TRUE, TRUE, 0);
 	gtk_widget_show(scrolled);
 
-	store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
+	store = gtk_list_store_new(UTILITY_COLUMN_COUNT, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
 	view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
 	g_object_unref(store);
 
@@ -2828,11 +2879,11 @@
 
 	if (full_paths)
 		{
-		file_util_dialog_add_list_column(view, _("Location"), 0);
+		file_util_dialog_add_list_column(view, _("Location"), UTILITY_COLUMN_PATH);
 		}
 	else
 		{
-		file_util_dialog_add_list_column(view, _("Name"), 1);
+		file_util_dialog_add_list_column(view, _("Name"), UTILITY_COLUMN_NAME);
 		}
 
 	gtk_widget_set_size_request(view, UTILITY_LIST_MIN_WIDTH, UTILITY_LIST_MIN_HEIGHT);
@@ -2841,12 +2892,13 @@
 
 	while (list)
 		{
-		gchar *path = list->data;
+		FileData *fd = list->data;
 		GtkTreeIter iter;
 
 		gtk_list_store_append(store, &iter);
-		gtk_list_store_set(store, &iter, 0, path,
-						 1, filename_from_path(path), -1);
+		gtk_list_store_set(store, &iter, UTILITY_COLUMN_FD, fd,
+						 UTILITY_COLUMN_PATH, fd->path,
+						 UTILITY_COLUMN_NAME, fd->name, -1);
 
 		list = list->next;
 		}
@@ -2860,14 +2912,14 @@
 {
 	UtilityData *ud = data;
 	GtkTreeIter iter;
-	gchar *path = NULL;
+	FileData *fd = NULL;
 
 	if (path_currently_selected ||
 	    !gtk_tree_model_get_iter(store, &iter, tpath)) return TRUE;
 
-	gtk_tree_model_get(store, &iter, 0, &path, -1);
-	generic_dialog_image_set(ud->gd, path);
-	g_free(path);
+	gtk_tree_model_get(store, &iter, UTILITY_COLUMN_FD, &fd, -1);
+	generic_dialog_image_set(ud->gd, fd);
+//	file_data_unref(fd);
 
 	return TRUE;
 }
@@ -2880,64 +2932,64 @@
 	file_util_data_free(ud);
 }
 
-static gchar *file_util_delete_dir_empty_path(const gchar *path, gint real_content, gint level)
+FileData *file_util_delete_dir_empty_path(FileData *fd, gint real_content, gint level)
 {
 	GList *dlist = NULL;
 	GList *flist = NULL;
 	GList *work;
-	gchar *fail = NULL;
-
-	if (debug) printf("deltree into: %s\n", path);
+	FileData *fail = NULL;
+
+	if (debug) printf("deltree into: %s\n", fd->path);
 
 	level++;
 	if (level > UTILITY_DELETE_MAX_DEPTH)
 		{
 		printf("folder recursion depth past %d, giving up\n", UTILITY_DELETE_MAX_DEPTH);
-		return g_strdup(path);
+		return file_data_ref(fd);
 		}
 
-	if (!path_list_lstat(path, &flist, &dlist)) return g_strdup(path);
+	if (!filelist_read_lstat(fd->path, &flist, &dlist)) file_data_ref(fd);
 
 	work = dlist;
 	while (work && !fail)
 		{
-		gchar *name;
-
-		name = work->data;
+		FileData *lfd;
+
+		lfd = work->data;
 		work = work->next;
 
-		fail = file_util_delete_dir_empty_path(name, real_content, level);
+		fail = file_util_delete_dir_empty_path(lfd, real_content, level);
 		}
 
 	work = flist;
 	while (work && !fail)
 		{
-		gchar *name;
-
-		name = work->data;
+		FileData *lfd;
+
+		lfd = work->data;
 		work = work->next;
 
-		if (debug) printf("deltree child: %s\n", name);
-
-		if (real_content && !islink(name))
+		if (debug) printf("deltree child: %s\n", lfd->path);
+
+		if (real_content && !islink(lfd->path))
 			{
-			if (!file_util_unlink(name)) fail = g_strdup(name);
+			if (!file_util_unlink(lfd)) fail = file_data_ref(lfd);
 			}
 		else
 			{
-			if (!unlink_file(name)) fail = g_strdup(name);
+			if (!unlink_file(lfd->path)) fail = file_data_ref(lfd);
 			}
 		}
 
-	path_list_free(dlist);
-	path_list_free(flist);
-
-	if (!fail && !rmdir_utf8(path))
+	filelist_free(dlist);
+	filelist_free(flist);
+
+	if (!fail && !rmdir_utf8(fd->path))
 		{
-		fail = g_strdup(path);
+		fail = file_data_ref(fd);
 		}
 
-	if (debug) printf("deltree done: %s\n", path);
+	if (debug) printf("deltree done: %s\n", fd->path);
 
 	return fail;
 }
@@ -2950,11 +3002,11 @@
 
 	if (ud->type == UTILITY_TYPE_DELETE_LINK)
 		{
-		if (!unlink_file(ud->source_path))
+		if (!unlink_file(ud->source_fd->path))
 			{
 			gchar *text;
 
-			text = g_strdup_printf("Unable to remove symbolic link:\n %s", ud->source_path);
+			text = g_strdup_printf("Unable to remove symbolic link:\n %s", ud->source_fd->path);
 			file_util_warning_dialog(_("Delete failed"), text,
 						 GTK_STOCK_DIALOG_ERROR, NULL);
 			g_free(text);
@@ -2962,63 +3014,63 @@
 		}
 	else
 		{
-		gchar *fail = NULL;
+		FileData *fail = NULL;
 		GList *work;
 
 		work = ud->dlist;
 		while (work && !fail)
 			{
-			gchar *path;
-
-			path = work->data;
+			FileData *fd;
+
+			fd = work->data;
 			work = work->next;
 
-			fail = file_util_delete_dir_empty_path(path, FALSE, 0);
+			fail = file_util_delete_dir_empty_path(fd, FALSE, 0);
 			}
 
 		work = ud->flist;
 		while (work && !fail)
 			{
-			gchar *path;
-
-			path = work->data;
+			FileData *fd;
+
+			fd = work->data;
 			work = work->next;
 
-			if (debug) printf("deltree unlink: %s\n", path);
-
-			if (islink(path))
+			if (debug) printf("deltree unlink: %s\n", fd->path);
+
+			if (islink(fd->path))
 				{
-				if (!unlink_file(path)) fail = g_strdup(path);
+				if (!unlink_file(fd->path)) fail = file_data_ref(fd);
 				}
 			else
 				{
-				if (!file_util_unlink(path)) fail = g_strdup(path);
+				if (!file_util_unlink(fd)) fail = file_data_ref(fd);
 				}
 			}
 
 		if (!fail)
 			{
-			if (!rmdir_utf8(ud->source_path)) fail = g_strdup(ud->source_path);
+			if (!rmdir_utf8(ud->source_fd->path)) fail = file_data_ref(ud->source_fd);
 			}
 
 		if (fail)
 			{
 			gchar *text;
 
-			text = g_strdup_printf(_("Unable to delete folder:\n\n%s"), ud->source_path);
+			text = g_strdup_printf(_("Unable to delete folder:\n\n%s"), ud->source_fd->path);
 			gd = file_util_warning_dialog(_("Delete failed"), text, GTK_STOCK_DIALOG_ERROR, NULL);
 			g_free(text);
 
-			if (strcmp(fail, ud->source_path) != 0)
+			if (fail != ud->source_fd)
 				{
 				pref_spacer(gd->vbox, PREF_PAD_GROUP);
 				text = g_strdup_printf(_("Removal of folder contents failed at this file:\n\n%s"),
-							fail);
+							fail->path);
 				pref_label_new(gd->vbox, text);
 				g_free(text);
 				}
 
-			g_free(fail);
+			file_data_unref(fail);
 			}
 		}
 
@@ -3031,41 +3083,39 @@
 
 	while (dlist)
 		{
-		gchar *path;
-		const gchar *name;
-
-		path = dlist->data;
+		FileData *fd;
+
+		fd = dlist->data;
 		dlist = dlist->next;
 
-		name = filename_from_path(path);
-		if (!name ||
-		    (strcmp(name, THUMB_FOLDER_GLOBAL) != 0 &&
-		     strcmp(name, THUMB_FOLDER_LOCAL) != 0 &&
-		     strcmp(name, GQVIEW_CACHE_LOCAL_METADATA) != 0) )
+		if (!fd->name ||
+		    (strcmp(fd->name, THUMB_FOLDER_GLOBAL) != 0 &&
+		     strcmp(fd->name, THUMB_FOLDER_LOCAL) != 0 &&
+		     strcmp(fd->name, GQVIEW_CACHE_LOCAL_METADATA) != 0) )
 			{
-			rlist = g_list_prepend(rlist, path);
+			rlist = g_list_prepend(rlist, fd);
 			}
 		}
 
 	return g_list_reverse(rlist);
 }
 
-void file_util_delete_dir(const gchar *path, GtkWidget *parent)
+void file_util_delete_dir(FileData *fd, GtkWidget *parent)
 {
 	GList *dlist = NULL;
 	GList *flist = NULL;
 	GList *rlist;
 
-	if (!isdir(path)) return;
-
-	if (islink(path))
+	if (!isdir(fd->path)) return;
+
+	if (islink(fd->path))
 		{
 		UtilityData *ud;
 		gchar *text;
 
 		ud = g_new0(UtilityData, 1);
 		ud->type = UTILITY_TYPE_DELETE_LINK;
-		ud->source_path = g_strdup(path);
+		ud->source_fd = file_data_ref(fd);
 		ud->dlist = NULL;
 		ud->flist = NULL;
 
@@ -3075,7 +3125,7 @@
 
 		text = g_strdup_printf(_("This will delete the symbolic link:\n\n%s\n\n"
 					 "The folder this link points to will not be deleted."),
-					path);
+					fd->path);
 		generic_dialog_add_message(ud->gd, GTK_STOCK_DIALOG_QUESTION,
 					   _("Delete symbolic link to folder?"),
 					   text);
@@ -3088,23 +3138,23 @@
 		return;
 		}
 
-	if (!access_file(path, W_OK | X_OK))
+	if (!access_file(fd->path, W_OK | X_OK))
 		{
 		gchar *text;
 
 		text = g_strdup_printf(_("Unable to remove folder %s\n"
-					 "Permissions do not allow writing to the folder."), path);
+					 "Permissions do not allow writing to the folder."), fd->path);
 		file_util_warning_dialog(_("Delete failed"), text, GTK_STOCK_DIALOG_ERROR, parent);
 		g_free(text);
 
 		return;
 		}
 
-	if (!path_list_lstat(path, &flist, &dlist))
+	if (!filelist_read_lstat(fd->path, &flist, &dlist))
 		{
 		gchar *text;
 
-		text = g_strdup_printf(_("Unable to list contents of folder %s"), path);
+		text = g_strdup_printf(_("Unable to list contents of folder %s"), fd->path);
 		file_util_warning_dialog(_("Delete failed"), text, GTK_STOCK_DIALOG_ERROR, parent);
 		g_free(text);
 
@@ -3124,7 +3174,7 @@
 
 		text = g_strdup_printf(_("Unable to delete the folder:\n\n%s\n\n"
 					 "This folder contains subfolders which must be moved before it can be deleted."),
-					path);
+					fd->path);
 		box = generic_dialog_add_message(gd, GTK_STOCK_DIALOG_WARNING,
 						 _("Folder contains subfolders"),
 						 text);
@@ -3132,7 +3182,7 @@
 
 		box = pref_group_new(box, TRUE, _("Subfolders:"), GTK_ORIENTATION_VERTICAL);
 
-		rlist = path_list_sort(rlist);
+		rlist = filelist_sort_path(rlist);
 		file_util_dialog_add_list(box, rlist, FALSE);
 
 		gtk_widget_show(gd->dialog);
@@ -3147,10 +3197,10 @@
 
 		ud = g_new0(UtilityData, 1);
 		ud->type = UTILITY_TYPE_DELETE_FOLDER;
-		ud->source_path = g_strdup(path);
+		ud->source_fd = file_data_ref(fd);
 		ud->dlist = dlist;
 		dlist = NULL;
-		ud->flist = path_list_sort(flist);
+		ud->flist = filelist_sort_path(flist);
 		flist = NULL;
 
 		ud->gd = file_util_gen_dlg(_("Delete folder"), "GQview", "dlg_confirm",
@@ -3159,7 +3209,7 @@
 
 		text = g_strdup_printf(_("This will delete the folder:\n\n%s\n\n"
 					 "The contents of this folder will also be deleted."),
-					path);
+					fd->path);
 		box = generic_dialog_add_message(ud->gd, GTK_STOCK_DIALOG_QUESTION,
 						 _("Delete folder?"),
 						 text);
@@ -3180,7 +3230,7 @@
 		}
 
 	g_list_free(rlist);
-	path_list_free(dlist);
-	path_list_free(flist);
+	filelist_free(dlist);
+	filelist_free(flist);
 }
 
--- a/src/utilops.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/utilops.h	Tue Sep 11 20:06:29 2007 +0000
@@ -17,10 +17,10 @@
 #include "ui_utildlg.h"
 
 
-void file_maint_renamed(const gchar *source, const gchar *dest);
-void file_maint_removed(const gchar *path, GList *ignore_list);
-void file_maint_moved(const gchar *source, const gchar *dest, GList *ignore_list);
-void file_maint_copied(const gchar *source, const gchar *dest);
+void file_maint_renamed(FileData *fd);
+void file_maint_removed(FileData *fd, GList *ignore_list);
+void file_maint_moved(FileData *fd, GList *ignore_list);
+void file_maint_copied(FileData *fd);
 
 GenericDialog *file_util_gen_dlg(const gchar *title,
 				 const gchar *wmclass, const gchar *wmsubclass,
@@ -35,13 +35,13 @@
 
 void file_util_trash_clear(void);
 
-void file_util_delete(const gchar *source_path, GList *source_list, GtkWidget *parent);
-void file_util_move(const gchar *source_path, GList *source_list, const gchar *dest_path, GtkWidget *parent);
-void file_util_copy(const gchar *source_path, GList *source_list, const gchar *dest_path, GtkWidget *parent);
-void file_util_rename(const gchar *source_path, GList *source_list, GtkWidget *parent);
+void file_util_delete(FileData *source_fd, GList *source_list, GtkWidget *parent);
+void file_util_move(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent);
+void file_util_copy(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent);
+void file_util_rename(FileData *source_fd, GList *source_list, GtkWidget *parent);
 
 void file_util_create_dir(const gchar *path, GtkWidget *parent);
-gint file_util_rename_dir(const gchar *old_path, const gchar *new_path, GtkWidget *parent);
+gint file_util_rename_dir(FileData *source_fd, const gchar *new_path, GtkWidget *parent);
 
 /* these avoid the location entry dialog, list must be files only and
  * dest_path must be a valid directory path
@@ -50,7 +50,7 @@
 void file_util_copy_simple(GList *list, const gchar *dest_path);
 
 
-void file_util_delete_dir(const gchar *path, GtkWidget *parent);
+void file_util_delete_dir(FileData *source_fd, GtkWidget *parent);
 
 
 #endif
--- a/src/view_dir_list.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/view_dir_list.c	Tue Sep 11 20:06:29 2007 +0000
@@ -90,7 +90,7 @@
 	new_path = concat_dir_and_file(base, new);
 	g_free(base);
 
-	if (file_util_rename_dir(old_path, new_path, vdl->listview))
+	if (file_util_rename_dir(fd, new_path, vdl->listview))
 		{
 		if (vdl->layout && strcmp(vdl->path, old_path) == 0)
 			{
@@ -265,7 +265,7 @@
 
 	path = g_strdup(vdl->click_fd->path);
 
-	list = path_list_recursive(path);
+	list = filelist_recursive(path);
 
 	layout_image_slideshow_stop(vdl->layout);
 	layout_image_slideshow_start_from_list(vdl->layout, list);
@@ -280,22 +280,21 @@
 	GList *list = NULL;
 
 	if (!vdl->click_fd) return;
-	path = vdl->click_fd->path;
 
 	if (recursive)
 		{
-		list = g_list_append(list, g_strdup(path));
+		list = g_list_append(list, file_data_ref(vdl->click_fd));
 		}
 	else
 		{
-		path_list(path, &list, NULL);
-		list = path_list_filter(list, FALSE);
+		filelist_read(vdl->click_fd->path, &list, NULL);
+		list = filelist_filter(list, FALSE);
 		}
 
 	dw = dupe_window_new(DUPE_MATCH_NAME);
 	dupe_window_add_files(dw, list, recursive);
 
-	path_list_free(list);
+	filelist_free(list);
 }
 
 static void vdlist_pop_menu_dupe_cb(GtkWidget *widget, gpointer data)
@@ -356,7 +355,7 @@
 	ViewDirList *vdl = data;
 
 	if (!vdl->click_fd) return;
-	file_util_delete_dir(vdl->click_fd->path, vdl->widget);
+	file_util_delete_dir(vdl->click_fd, vdl->widget);
 }
 
 static void vdlist_pop_menu_tree_cb(GtkWidget *widget, gpointer data)
@@ -435,7 +434,7 @@
 	vdl->popup = NULL;
 
 	vdlist_color_set(vdl, vdl->drop_fd, FALSE);
-	path_list_free(vdl->drop_list);
+	filelist_free(vdl->drop_list);
 	vdl->drop_list = NULL;
 	vdl->drop_fd = NULL;
 }
@@ -477,14 +476,13 @@
 	gint length = 0;
 
 	if (!vdl->click_fd) return;
-	path = vdl->click_fd->path;
 
 	switch (info)
 		{
 		case TARGET_URI_LIST:
 		case TARGET_TEXT_PLAIN:
-			list = g_list_prepend(NULL, path);
-			text = uri_text_from_list(list, &length, (info == TARGET_TEXT_PLAIN));
+			list = g_list_prepend(NULL, vdl->click_fd);
+			text = uri_text_from_filelist(list, &length, (info == TARGET_TEXT_PLAIN));
 			g_list_free(list);
 			break;
 		}
@@ -547,7 +545,7 @@
 		GList *list;
 		gint active;
 
-		list = uri_list_from_text((gchar *)selection_data->data, TRUE);
+		list = uri_filelist_from_text((gchar *)selection_data->data, TRUE);
 		if (!list) return;
 
 		active = access_file(fd->path, W_OK | X_OK);
@@ -818,6 +816,7 @@
 	gint ret;
 	FileData *fd;
 	gchar *old_path = NULL;
+	gchar *filepath;
 
 	if (!path) return FALSE;
 	if (vdl->path && strcmp(path, vdl->path) == 0) return TRUE;
@@ -848,16 +847,15 @@
 
 	if (strcmp(vdl->path, "/") != 0)
 		{
-		fd = g_new0(FileData, 1);
-		fd->path = remove_level_from_path(vdl->path);
-		fd->name = "..";
+		filepath = g_strconcat(vdl->path, "/", "..", NULL); 
+		fd = file_data_new_simple(filepath);
 		vdl->list = g_list_prepend(vdl->list, fd);
+		g_free(filepath);
 		}
-
-	fd = g_new0(FileData, 1);
-	fd->path = g_strdup(vdl->path);
-	fd->name = ".";
+	filepath = g_strconcat(vdl->path, "/", ".", NULL); 
+	fd = file_data_new_simple(filepath);
 	vdl->list = g_list_prepend(vdl->list, fd);
+	g_free(filepath);
 
 	vdlist_populate(vdl);
 
@@ -1070,7 +1068,7 @@
 	vdlist_dnd_drop_scroll_cancel(vdl);
 	widget_auto_scroll_stop(vdl->listview);
 
-	path_list_free(vdl->drop_list);
+	filelist_free(vdl->drop_list);
 
 	folder_icons_free(vdl->pf);
 
--- a/src/view_dir_tree.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/view_dir_tree.c	Tue Sep 11 20:06:29 2007 +0000
@@ -197,7 +197,7 @@
 	new_path = concat_dir_and_file(base, new);
 	g_free(base);
 
-	if (file_util_rename_dir(old_path, new_path, vdt->treeview))
+	if (file_util_rename_dir(nd->fd, new_path, vdt->treeview))
 		{
 		vdtree_populate_path(vdt, new_path, TRUE, TRUE);
 
@@ -234,7 +234,7 @@
 {
 	if (!nd) return;
 
-	file_data_free(nd->fd);
+	file_data_unref(nd->fd);
 	g_free(nd);
 }
 
@@ -247,7 +247,7 @@
 	vdt->popup = NULL;
 
 	vdtree_color_set(vdt, vdt->drop_fd, FALSE);
-	path_list_free(vdt->drop_list);
+	filelist_free(vdt->drop_list);
 	vdt->drop_list = NULL;
 	vdt->drop_fd = NULL;
 }
@@ -338,14 +338,12 @@
 	if (!vdt->layout) return;
 
 	if (!vdt->click_fd) return;
-	path = g_strdup(vdt->click_fd->path);
+	path = vdt->click_fd->path;
 
 	layout_set_path(vdt->layout, path);
 	layout_select_none(vdt->layout);
 	layout_image_slideshow_stop(vdt->layout);
 	layout_image_slideshow_start(vdt->layout);
-
-	g_free(path);
 }
 
 static void vdtree_pop_menu_slide_rec_cb(GtkWidget *widget, gpointer data)
@@ -357,39 +355,35 @@
 	if (!vdt->layout) return;
 
 	if (!vdt->click_fd) return;
-	path = g_strdup(vdt->click_fd->path);
+	path = vdt->click_fd->path;
 
-	list = path_list_recursive(path);
+	list = filelist_recursive(path);
 
 	layout_image_slideshow_stop(vdt->layout);
 	layout_image_slideshow_start_from_list(vdt->layout, list);
-
-	g_free(path);
 }
 
 static void vdtree_pop_menu_dupe(ViewDirTree *vdt, gint recursive)
 {
 	DupeWindow *dw;
-	const gchar *path;
 	GList *list = NULL;
 
 	if (!vdt->click_fd) return;
-	path = vdt->click_fd->path;
 
 	if (recursive)
 		{
-		list = g_list_append(list, g_strdup(path));
+		list = g_list_append(list, file_data_ref(vdt->click_fd));
 		}
 	else
 		{
-		path_list(path, &list, NULL);
-		list = path_list_filter(list, FALSE);
+		filelist_read(vdt->click_fd->path, &list, NULL);
+		list = filelist_filter(list, FALSE);
 		}
 
 	dw = dupe_window_new(DUPE_MATCH_NAME);
 	dupe_window_add_files(dw, list, recursive);
 
-	path_list_free(list);
+	filelist_free(list);
 }
 
 static void vdtree_pop_menu_dupe_cb(GtkWidget *widget, gpointer data)
@@ -451,7 +445,7 @@
 	ViewDirTree *vdt = data;
 
 	if (!vdt->click_fd) return;
-	file_util_delete_dir(vdt->click_fd->path, vdt->widget);
+	file_util_delete_dir(vdt->click_fd, vdt->widget);
 }
 
 static void vdtree_pop_menu_tree_cb(GtkWidget *widget, gpointer data)
@@ -563,14 +557,13 @@
 	gint length = 0;
 
 	if (!vdt->click_fd) return;
-	path = vdt->click_fd->path;
 
 	switch (info)
 		{
 		case TARGET_URI_LIST:
 		case TARGET_TEXT_PLAIN:
-			list = g_list_prepend(NULL, path);
-			uri_text = uri_text_from_list(list, &length, (info == TARGET_TEXT_PLAIN));
+			list = g_list_prepend(NULL, vdt->click_fd);
+			uri_text = uri_text_from_filelist(list, &length, (info == TARGET_TEXT_PLAIN));
 			g_list_free(list);
 			break;
 		}
@@ -632,7 +625,7 @@
 		GList *list;
 		gint active;
 
-		list = uri_list_from_text((gchar *)selection_data->data, TRUE);
+		list = uri_filelist_from_text((gchar *)selection_data->data, TRUE);
 		if (!list) return;
 
 		active = access_file(fd->path, W_OK | X_OK);
@@ -929,7 +922,7 @@
 
 	if (!nd) return;
 
-	file_data_free(nd->fd);
+	file_data_unref(nd->fd);
 	g_free(nd);
 }
 #endif
@@ -1007,9 +1000,7 @@
 	/* all nodes are created with an "empty" node, so that the expander is shown
 	 * this is removed when the child is populated */
 	end = g_new0(NodeData, 1);
-	end->fd = g_new0(FileData, 1);
-	end->fd->path = g_strdup("");
-	end->fd->name = end->fd->path;
+	end->fd = file_data_new_simple("");
 	end->expanded = TRUE;
 
 	gtk_tree_store_append(store, &empty, &child);
@@ -1093,7 +1084,7 @@
 
 			if (stat_utf8(name8, &sbuf))
 				{
-				list = g_list_prepend(list, file_data_new(namel, &sbuf));
+				list = g_list_prepend(list, file_data_new_local(namel, &sbuf));
 				}
 
 			g_free(namel);
@@ -1122,7 +1113,7 @@
 
 		if (strcmp(fd->name, ".") == 0 || strcmp(fd->name, "..") == 0)
 			{
-			file_data_free(fd);
+			file_data_unref(fd);
 			}
 		else
 			{
@@ -1139,7 +1130,7 @@
 					cnd->fd->date = fd->date;
 					}
 
-				file_data_free(fd);
+				file_data_unref(fd);
 				}
 			else
 				{
@@ -1564,11 +1555,8 @@
 	const gchar *path = "/";
 	FileData *fd;
 
-	fd = g_new0(FileData, 1);
-	fd->path = g_strdup(path);
-	fd->name = fd->path;
-	fd->size = 0;
-	fd->date = filetime(path);
+
+	fd = file_data_new_simple(path);
 	vdtree_add_by_data(vdt, fd, NULL);
 
 	vdtree_expand_by_data(vdt, fd, TRUE);
@@ -1648,7 +1636,7 @@
 	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vdt->treeview));
 	gtk_tree_model_foreach(store, vdtree_destroy_node_cb, vdt);
 
-	path_list_free(vdt->drop_list);
+	filelist_free(vdt->drop_list);
 
 	folder_icons_free(vdt->pf);
 
--- a/src/view_file_icon.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/view_file_icon.c	Tue Sep 11 20:06:29 2007 +0000
@@ -43,10 +43,6 @@
 
 #define VFICON_TIP_DELAY 500
 
-#define ICON_DATA(x) ((IconData *)x)
-#define FILE_DATA(x) ((FileData *)x)
-
-
 enum {
 	FILE_COLUMN_POINTER = 0,
 	FILE_COLUMN_COUNT
@@ -62,11 +58,29 @@
 typedef struct _IconData IconData;
 struct _IconData
 {
-	FileData fd;
 	SelectionType selected;
 	gint row;
+	FileData *fd;
 };
 
+static gint vficon_index_by_id(ViewFileIcon *vfi, IconData *in_id);
+
+static IconData *vficon_icon_data(ViewFileIcon *vfi, FileData *fd)
+{
+	IconData *id = NULL;
+	GList *work;
+
+	if (!fd) return NULL;
+	work = vfi->list;
+	while (work && !id)
+		{
+		IconData *chk = work->data;
+		work = work->next;
+		if (chk->fd == fd) id = chk;
+		}
+	return id;
+}
+
 
 static gint iconlist_read(const gchar *path, GList **list)
 {
@@ -82,15 +96,14 @@
 		IconData *id;
 
 		fd = work->data;
+		g_assert(fd->magick == 0x12345678); 
 		id = g_new0(IconData, 1);
 
-		memcpy(id, fd, sizeof(FileData));
 		id->selected = SELECTION_NONE;
 		id->row = -1;
+		id->fd = fd;
 
 		work->data = id;
-		g_free(fd);
-
 		work = work->next;
 		}
 
@@ -101,14 +114,40 @@
 
 static void iconlist_free(GList *list)
 {
-	filelist_free(list);
+	GList *work = list;
+	while (work)
+		{
+		IconData *id = work->data;
+		file_data_unref(id->fd);
+		g_free(id);
+                work = work->next;                                                                                                    
+                }                                                                                                                     
+                                                                                                                                      
+        g_list_free(list);                                                                                                            
+
+}
+
+gint iconlist_sort_file_cb(void *a, void *b)
+{
+	IconData *ida = a;
+	IconData *idb = b;
+	return filelist_sort_compare_filedata(ida->fd, idb->fd);
+}
+GList *iconlist_sort(GList *list, SortType method, gint ascend)
+{
+	return filelist_sort_full(list, method, ascend, (GCompareFunc) iconlist_sort_file_cb);
+}
+
+GList *iconlist_insert_sort(GList *list, IconData *id, SortType method, gint ascend)
+{
+	return filelist_insert_sort_full(list, id, method, ascend, (GCompareFunc) iconlist_sort_file_cb);
 }
 
 
 static void vficon_toggle_filenames(ViewFileIcon *vfi);
-static void vficon_selection_remove(ViewFileIcon *vfi, FileData *fd, SelectionType mask, GtkTreeIter *iter);
+static void vficon_selection_remove(ViewFileIcon *vfi, IconData *id, SelectionType mask, GtkTreeIter *iter);
 static void vficon_move_focus(ViewFileIcon *vfi, gint row, gint col, gint relative);
-static void vficon_set_focus(ViewFileIcon *vfi, FileData *fd);
+static void vficon_set_focus(ViewFileIcon *vfi, IconData *id);
 static void vficon_thumb_update(ViewFileIcon *vfi);
 static void vficon_populate_at_new_size(ViewFileIcon *vfi, gint w, gint h, gint force);
 
@@ -121,14 +160,14 @@
 
 static GList *vficon_pop_menu_file_list(ViewFileIcon *vfi)
 {
-	if (!vfi->click_fd) return NULL;
-
-	if (ICON_DATA(vfi->click_fd)->selected & SELECTION_SELECTED)
+	if (!vfi->click_id) return NULL;
+
+	if (vfi->click_id->selected & SELECTION_SELECTED)
 		{
 		return vficon_selection_get_list(vfi);
 		}
 
-	return g_list_append(NULL, g_strdup(vfi->click_fd->path));
+	return g_list_append(NULL, file_data_ref(vfi->click_id->fd));
 }
 
 static void vficon_pop_menu_edit_cb(GtkWidget *widget, gpointer data)
@@ -143,8 +182,8 @@
 	if (!vfi) return;
 
 	list = vficon_pop_menu_file_list(vfi);
-	start_editor_from_path_list(n, list);
-	path_list_free(list);
+	start_editor_from_filelist(n, list);
+	filelist_free(list);
 }
 
 static void vficon_pop_menu_info_cb(GtkWidget *widget, gpointer data)
@@ -158,19 +197,19 @@
 {
 	ViewFileIcon *vfi = data;
 
-	if (!vfi->click_fd) return;
-
-	if (ICON_DATA(vfi->click_fd)->selected & SELECTION_SELECTED)
+	if (!vfi->click_id) return;
+
+	if (vfi->click_id->selected & SELECTION_SELECTED)
 		{
 		GList *list;
 		
 		list = vficon_selection_get_list(vfi);
 		view_window_new_from_list(list);
-		path_list_free(list);
+		filelist_free(list);
 		}
 	else
 		{
-		view_window_new(vfi->click_fd->path);
+		view_window_new(vfi->click_id->fd);
 		}
 }
 
@@ -262,8 +301,8 @@
 static void vficon_popup_destroy_cb(GtkWidget *widget, gpointer data)
 {
 	ViewFileIcon *vfi = data;                                                                                                                               
-	vficon_selection_remove(vfi, vfi->click_fd, SELECTION_PRELIGHT, NULL);
-	vfi->click_fd = NULL;
+	vficon_selection_remove(vfi, vfi->click_id, SELECTION_PRELIGHT, NULL);
+	vfi->click_id = NULL;
 	vfi->popup = NULL;
 }
 
@@ -328,18 +367,21 @@
 	if (vfi->func_status) vfi->func_status(vfi, vfi->data_status);
 }
 
-static void vficon_send_layout_select(ViewFileIcon *vfi, FileData *fd)
+static void vficon_send_layout_select(ViewFileIcon *vfi, IconData *id)
 {
-	const gchar *read_ahead_path = NULL;
-
-	if (!vfi->layout || !fd) return;
-
+	FileData *read_ahead_fd = NULL;
+	FileData *fd;
+
+	if (!vfi->layout || !id) return;
+
+	fd = id->fd;
+	 
 	if (enable_read_ahead)
 		{
 		FileData *fd_n;
 		gint row;
 
-		row = g_list_index(vfi->list, fd);
+		row = g_list_index(vfi->list, id);
 		if (row > vficon_index_by_path(vfi, layout_image_get_path(vfi->layout)) &&
 		    row + 1 < vficon_count(vfi, NULL))
 			{
@@ -353,10 +395,10 @@
 			{
 			fd_n = NULL;
 			}
-		if (fd_n) read_ahead_path = fd_n->path;
+		if (fd_n) read_ahead_fd = fd_n;
 		}
 
-	layout_image_set_with_ahead(vfi->layout, fd->path, read_ahead_path);
+	layout_image_set_with_ahead(vfi->layout, fd, read_ahead_fd);
 }
 
 static void vficon_toggle_filenames(ViewFileIcon *vfi)
@@ -386,11 +428,11 @@
  *-------------------------------------------------------------------
  */
 
-static gint vficon_find_position(ViewFileIcon *vfi, FileData *fd, gint *row, gint *col)
+static gint vficon_find_position(ViewFileIcon *vfi, IconData *id, gint *row, gint *col)
 {
 	gint n;
 
-	n = g_list_index(vfi->list, fd);
+	n = g_list_index(vfi->list, id);
 
 	if (n < 0) return FALSE;
 
@@ -400,20 +442,20 @@
 	return TRUE;
 }
 
-static gint vficon_find_iter(ViewFileIcon *vfi, FileData *fd, GtkTreeIter *iter, gint *column)
+static gint vficon_find_iter(ViewFileIcon *vfi, IconData *id, GtkTreeIter *iter, gint *column)
 {
 	GtkTreeModel *store;
 	gint row, col;
 
 	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview));
-	if (!vficon_find_position(vfi, fd, &row, &col)) return FALSE;
+	if (!vficon_find_position(vfi, id, &row, &col)) return FALSE;
 	if (!gtk_tree_model_iter_nth_child(store, iter, NULL, row)) return FALSE;
 	if (column) *column = col;
 
 	return TRUE;
 }
 
-static FileData *vficon_find_data(ViewFileIcon *vfi, gint row, gint col, GtkTreeIter *iter)
+static IconData *vficon_find_data(ViewFileIcon *vfi, gint row, gint col, GtkTreeIter *iter)
 {
 	GtkTreeModel *store;
 	GtkTreeIter p;
@@ -436,7 +478,7 @@
 	return NULL;
 }
 
-static FileData *vficon_find_data_by_coord(ViewFileIcon *vfi, gint x, gint y, GtkTreeIter *iter)
+static IconData *vficon_find_data_by_coord(ViewFileIcon *vfi, gint x, gint y, GtkTreeIter *iter)
 {
 	GtkTreePath *tpath;
 	GtkTreeViewColumn *column;
@@ -481,14 +523,14 @@
 
 	gdk_window_get_pointer(gtk_tree_view_get_bin_window(GTK_TREE_VIEW(vfi->listview)), &x, &y, NULL);
 
-	vfi->tip_fd = vficon_find_data_by_coord(vfi, x, y, NULL);
-	if (!vfi->tip_fd) return;
+	vfi->tip_id = vficon_find_data_by_coord(vfi, x, y, NULL);
+	if (!vfi->tip_id) return;
 
 	vfi->tip_window = gtk_window_new(GTK_WINDOW_POPUP);
 	gtk_window_set_resizable(GTK_WINDOW(vfi->tip_window), FALSE);
 	gtk_container_set_border_width(GTK_CONTAINER(vfi->tip_window), 2);
 
-	label = gtk_label_new(vfi->tip_fd->name);
+	label = gtk_label_new(vfi->tip_id->fd->name);
 
 	g_object_set_data(G_OBJECT(vfi->tip_window), "tip_label", label);
 	gtk_container_add(GTK_CONTAINER(vfi->tip_window), label);
@@ -550,7 +592,7 @@
 	vfi->tip_delay_id = -1;
 }
 
-static void tip_update(ViewFileIcon *vfi, FileData *fd)
+static void tip_update(ViewFileIcon *vfi, IconData *id)
 {
 	if (vfi->tip_window)
 		{
@@ -559,13 +601,13 @@
 		gdk_window_get_pointer(NULL, &x, &y, NULL);
 		gtk_window_move(GTK_WINDOW(vfi->tip_window), x + 16, y + 16);
 
-		if (fd != vfi->tip_fd)
+		if (id != vfi->tip_id)
 			{
 			GtkWidget *label;
 
-			vfi->tip_fd = fd;
-
-			if (!vfi->tip_fd)
+			vfi->tip_id = id;
+
+			if (!vfi->tip_id)
 				{
 				tip_hide(vfi);
 				tip_schedule(vfi);
@@ -573,7 +615,7 @@
 				}
 
 			label = g_object_get_data(G_OBJECT(vfi->tip_window), "tip_label");
-			gtk_label_set_text(GTK_LABEL(label), vfi->tip_fd->name);
+			gtk_label_set_text(GTK_LABEL(label), vfi->tip_id->fd->name);
 			}
 		}
 	else
@@ -597,22 +639,20 @@
 	gchar *uri_text = NULL;
 	gint total;
 
-	if (!vfi->click_fd) return;
-
-	if (ICON_DATA(vfi->click_fd)->selected & SELECTION_SELECTED)
+	if (!vfi->click_id) return;
+
+	if (vfi->click_id->selected & SELECTION_SELECTED)
 		{
 		list = vficon_selection_get_list(vfi);
 		}
 	else
 		{
-		const gchar *path = vfi->click_fd->path;
-
-		list = g_list_append(NULL, g_strdup(path));
+		list = g_list_append(NULL, file_data_ref(vfi->click_id->fd));
 		}
 
 	if (!list) return;
-	uri_text = uri_text_from_list(list, &total, (info == TARGET_TEXT_PLAIN));
-	path_list_free(list);
+	uri_text = uri_text_from_filelist(list, &total, (info == TARGET_TEXT_PLAIN));
+	filelist_free(list);
 
 	if (debug) printf(uri_text);
 
@@ -627,16 +667,16 @@
 
 	tip_unschedule(vfi);
 
-	if (vfi->click_fd && vfi->click_fd->pixbuf)
+	if (vfi->click_id && vfi->click_id->fd->pixbuf)
 		{
 		gint items;
 
-		if (ICON_DATA(vfi->click_fd)->selected & SELECTION_SELECTED)
+		if (vfi->click_id->selected & SELECTION_SELECTED)
 			items = g_list_length(vfi->selection);
 		else
 			items = 1;
 
-		dnd_set_drag_icon(widget, context, vfi->click_fd->pixbuf, items);
+		dnd_set_drag_icon(widget, context, vfi->click_id->fd->pixbuf, items);
 		}
 }
 
@@ -644,7 +684,7 @@
 {
 	ViewFileIcon *vfi = data;
 
-	vficon_selection_remove(vfi, vfi->click_fd, SELECTION_PRELIGHT, NULL);
+	vficon_selection_remove(vfi, vfi->click_id, SELECTION_PRELIGHT, NULL);
 
 	if (context->action == GDK_ACTION_MOVE)
 		{
@@ -673,15 +713,13 @@
  *-------------------------------------------------------------------
  */
 
-static void vficon_selection_set(ViewFileIcon *vfi, FileData *fd, SelectionType value, GtkTreeIter *iter)
+static void vficon_selection_set(ViewFileIcon *vfi, IconData *id, SelectionType value, GtkTreeIter *iter)
 {
-	IconData *id;
 	GtkTreeModel *store;
 	GList *list;
 
-	if (!fd) return;
-
-	id = ICON_DATA(fd);
+	if (!id) return;
+
 
 	if (id->selected == value) return;
 	id->selected = value;
@@ -696,7 +734,7 @@
 		{
 		GtkTreeIter row;
 
-		if (vficon_find_iter(vfi, fd, &row, NULL))
+		if (vficon_find_iter(vfi, id, &row, NULL))
 			{
 			gtk_tree_model_get(store, &row, FILE_COLUMN_POINTER, &list, -1);
 			if (list) gtk_list_store_set(GTK_LIST_STORE(store), &row, FILE_COLUMN_POINTER, list, -1);
@@ -704,18 +742,18 @@
 		}
 }
 
-static void vficon_selection_add(ViewFileIcon *vfi, FileData *fd, SelectionType mask, GtkTreeIter *iter)
+static void vficon_selection_add(ViewFileIcon *vfi, IconData *id, SelectionType mask, GtkTreeIter *iter)
 {
-	if (!fd) return;
-
-	vficon_selection_set(vfi, fd, ICON_DATA(fd)->selected | mask, iter);
+	if (!id) return;
+
+	vficon_selection_set(vfi, id, id->selected | mask, iter);
 }
 
-static void vficon_selection_remove(ViewFileIcon *vfi, FileData *fd, SelectionType mask, GtkTreeIter *iter)
+static void vficon_selection_remove(ViewFileIcon *vfi, IconData *id, SelectionType mask, GtkTreeIter *iter)
 {
-	if (!fd) return;
-
-	vficon_selection_set(vfi, fd, ICON_DATA(fd)->selected & ~mask, iter);
+	if (!id) return;
+
+	vficon_selection_set(vfi, id, id->selected & ~mask, iter);
 }
 
 /*
@@ -731,11 +769,11 @@
 	work = vfi->selection;
 	while (work)
 		{
-		FileData *fd = work->data;
+		IconData *id = work->data;
 		work = work->next;
-		if (!g_list_find(vfi->list, fd))
+		if (vficon_index_by_id(vfi, id) < 0)
 			{
-			vfi->selection = g_list_remove(vfi->selection, fd);
+			vfi->selection = g_list_remove(vfi->selection, id);
 			}
 		}
 }
@@ -750,7 +788,8 @@
 	work = vfi->list;
 	while (work)
 		{
-		vfi->selection = g_list_append(vfi->selection, work->data);
+		IconData *id = work->data;
+		vfi->selection = g_list_append(vfi->selection, id);
 		vficon_selection_add(vfi, work->data, SELECTION_SELECTED, NULL);
 		work = work->next;
 		}
@@ -775,43 +814,43 @@
 	vficon_send_update(vfi);
 }
 
-static void vficon_select(ViewFileIcon *vfi, FileData *fd)
+static void vficon_select(ViewFileIcon *vfi, IconData *id)
 {
-	vfi->prev_selection = fd;
-
-	if (!fd || ICON_DATA(fd)->selected & SELECTION_SELECTED) return;
-
-	vfi->selection = g_list_append(vfi->selection, fd);
-	vficon_selection_add(vfi, fd, SELECTION_SELECTED, NULL);
+	vfi->prev_selection = id;
+
+	if (!id || id->selected & SELECTION_SELECTED) return;
+
+	vfi->selection = g_list_append(vfi->selection, id);
+	vficon_selection_add(vfi, id, SELECTION_SELECTED, NULL);
 
 	vficon_send_update(vfi);
 }
 
-static void vficon_unselect(ViewFileIcon *vfi, FileData *fd)
+static void vficon_unselect(ViewFileIcon *vfi, IconData *id)
 {
-	vfi->prev_selection = fd;
-
-	if (!fd || !(ICON_DATA(fd)->selected & SELECTION_SELECTED) ) return;
-
-	vfi->selection = g_list_remove(vfi->selection, fd);
-	vficon_selection_remove(vfi, fd, SELECTION_SELECTED, NULL);
+	vfi->prev_selection = id;
+
+	if (!id || !(id->selected & SELECTION_SELECTED) ) return;
+
+	vfi->selection = g_list_remove(vfi->selection, id);
+	vficon_selection_remove(vfi, id, SELECTION_SELECTED, NULL);
 
 	vficon_send_update(vfi);
 }
 
-static void vficon_select_util(ViewFileIcon *vfi, FileData *fd, gint select)
+static void vficon_select_util(ViewFileIcon *vfi, IconData *id, gint select)
 {
 	if (select)
 		{
-		vficon_select(vfi, fd);
+		vficon_select(vfi, id);
 		}
 	else
 		{
-		vficon_unselect(vfi, fd);
+		vficon_unselect(vfi, id);
 		}
 }
 
-static void vficon_select_region_util(ViewFileIcon *vfi, FileData *start, FileData *end, gint select)
+static void vficon_select_region_util(ViewFileIcon *vfi, IconData *start, IconData *end, gint select)
 {
 	gint row1, col1;
 	gint row2, col2;
@@ -826,20 +865,20 @@
 	if (!collection_rectangular_selection)
 		{
 		GList *work;
-		FileData *fd;
+		IconData *id;
 
 		if (g_list_index(vfi->list, start) > g_list_index(vfi->list, end))
 			{
-			fd = start;
+			id = start;
 			start = end;
-			end = fd;
+			end = id;
 			}
 
 		work = g_list_find(vfi->list, start);
 		while (work)
 			{
-			fd = work->data;
-			vficon_select_util(vfi, fd, select);
+			id = work->data;
+			vficon_select_util(vfi, id, select);
 			
 			if (work->data != end)
 				work = work->next;
@@ -868,19 +907,19 @@
 		{
 		for (j = col1; j <= col2; j++)
 			{
-			FileData *fd = vficon_find_data(vfi, i, j, NULL);
-			if (fd) vficon_select_util(vfi, fd, select);
+			IconData *id = vficon_find_data(vfi, i, j, NULL);
+			if (id) vficon_select_util(vfi, id, select);
 			}
 		}
 }
 
 gint vficon_index_is_selected(ViewFileIcon *vfi, gint row)
 {
-	FileData *fd = g_list_nth_data(vfi->list, row);
-
-	if (!fd) return FALSE;
-
-	return (ICON_DATA(fd)->selected & SELECTION_SELECTED);
+	IconData *id = g_list_nth_data(vfi->list, row);
+
+	if (!id) return FALSE;
+
+	return (id->selected & SELECTION_SELECTED);
 }
 
 gint vficon_selection_count(ViewFileIcon *vfi, gint64 *bytes)
@@ -893,7 +932,9 @@
 		work = vfi->selection;
 		while (work)
 			{
-			FileData *fd = work->data;
+			IconData *id = work->data;
+			FileData *fd = id->fd;
+			g_assert(fd->magick == 0x12345678); 
 			b += fd->size;
 
 			work = work->next;
@@ -913,9 +954,11 @@
 	work = vfi->selection;
 	while (work)
 		{
-		FileData *fd = work->data;
-
-		list = g_list_prepend(list, g_strdup(fd->path));
+		IconData *id = work->data;
+		FileData *fd = id->fd;
+		g_assert(fd->magick == 0x12345678); 
+
+		list = g_list_prepend(list, file_data_ref(fd));
 
 		work = work->next;
 		}
@@ -940,33 +983,55 @@
 	return g_list_reverse(list);
 }
 
+static void vficon_select_by_id(ViewFileIcon *vfi, IconData *id)
+{
+	if (!id) return;
+
+	if (!(id->selected & SELECTION_SELECTED))
+		{
+		vficon_select_none(vfi);
+		vficon_select(vfi, id);
+		}
+
+	vficon_set_focus(vfi, id);
+}
+
+
 void vficon_select_by_path(ViewFileIcon *vfi, const gchar *path)
 {
-	FileData *fd;
+	IconData *id = NULL;
 	GList *work;
 
 	if (!path) return;
 
-	fd = NULL;
 	work = vfi->list;
-	while (work && !fd)
+	while (work && !id)
 		{
-		FileData *chk = work->data;
+		IconData *chk = work->data;
 		work = work->next;
-		if (strcmp(chk->path, path) == 0) fd = chk;
+		if (strcmp(chk->fd->path, path) == 0) id = chk;
 		}
+	vficon_select_by_id(vfi, id);
+}
+
+void vficon_select_by_fd(ViewFileIcon *vfi, FileData *fd)
+{
+	IconData *id = NULL;
+	GList *work;
 
 	if (!fd) return;
-
-	if (!(ICON_DATA(fd)->selected & SELECTION_SELECTED))
+	work = vfi->list;
+	while (work && !id)
 		{
-		vficon_select_none(vfi);
-		vficon_select(vfi, fd);
+		IconData *chk = work->data;
+		work = work->next;
+		if (chk->fd == fd) id = chk;
 		}
-
-	vficon_set_focus(vfi, fd);
+	vficon_select_by_id(vfi, id);
 }
 
+
+
 /*
  *-------------------------------------------------------------------
  * focus
@@ -1056,36 +1121,36 @@
 	vficon_set_focus(vfi, vficon_find_data(vfi, new_row, new_col, NULL));
 }
 
-static void vficon_set_focus(ViewFileIcon *vfi, FileData *fd)
+static void vficon_set_focus(ViewFileIcon *vfi, IconData *id)
 {
 	GtkTreeIter iter;
 	gint row, col;
 
-	if (g_list_find(vfi->list, vfi->focus_fd))
+	if (g_list_find(vfi->list, vfi->focus_id))
 		{
-		if (fd == vfi->focus_fd)
+		if (id == vfi->focus_id)
 			{
 			/* ensure focus row col are correct */
-			vficon_find_position(vfi, vfi->focus_fd, &vfi->focus_row, &vfi->focus_column);
+			vficon_find_position(vfi, vfi->focus_id, &vfi->focus_row, &vfi->focus_column);
 			return;
 			}
-		vficon_selection_remove(vfi, vfi->focus_fd, SELECTION_FOCUS, NULL);
+		vficon_selection_remove(vfi, vfi->focus_id, SELECTION_FOCUS, NULL);
 		}
 
-	if (!vficon_find_position(vfi, fd, &row, &col))
+	if (!vficon_find_position(vfi, id, &row, &col))
 		{
-		vfi->focus_fd = NULL;
+		vfi->focus_id = NULL;
 		vfi->focus_row = -1;
 		vfi->focus_column = -1;
 		return;
 		}
 
-	vfi->focus_fd = fd;
+	vfi->focus_id = id;
 	vfi->focus_row = row;
 	vfi->focus_column = col;
-	vficon_selection_add(vfi, vfi->focus_fd, SELECTION_FOCUS, NULL);
-
-	if (vficon_find_iter(vfi, vfi->focus_fd, &iter, NULL))
+	vficon_selection_add(vfi, vfi->focus_id, SELECTION_FOCUS, NULL);
+
+	if (vficon_find_iter(vfi, vfi->focus_id, &iter, NULL))
 		{
 		GtkTreePath *tpath;
 		GtkTreeViewColumn *column;
@@ -1107,7 +1172,7 @@
 	gint new_row = 0;
 	gint new_col = 0;
 
-	if (vfi->focus_fd && vficon_find_position(vfi, vfi->focus_fd, &new_row, &new_col))
+	if (vfi->focus_id && vficon_find_position(vfi, vfi->focus_id, &new_row, &new_col))
 		{
 		/* first find the old focus, if it exists and is valid */
 		}
@@ -1156,7 +1221,7 @@
 	GtkTreePath *tpath;
 	gint cw, ch;
 
-	if (!vficon_find_iter(vfi, vfi->click_fd, &iter, &column)) return;
+	if (!vficon_find_iter(vfi, vfi->click_id, &iter, &column)) return;
 	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview));
 	tpath = gtk_tree_model_get_path(store, &iter);
 	tree_view_get_cell_clamped(GTK_TREE_VIEW(vfi->listview), tpath, column, FALSE, x, y, &cw, &ch);
@@ -1170,7 +1235,7 @@
 	ViewFileIcon *vfi = data;
 	gint focus_row = 0;
 	gint focus_col = 0;
-	FileData *fd;
+	IconData *id;
 	gint stop_signal;
 
 	stop_signal = TRUE;
@@ -1203,41 +1268,41 @@
 			focus_col = vfi->columns - 1 - vfi->focus_column;
 			break;
 		case GDK_space:
-			fd = vficon_find_data(vfi, vfi->focus_row, vfi->focus_column, NULL);
-			if (fd)
+			id = vficon_find_data(vfi, vfi->focus_row, vfi->focus_column, NULL);
+			if (id)
 				{
-				vfi->click_fd = fd;
+				vfi->click_id = id;
 				if (event->state & GDK_CONTROL_MASK)
 					{
 					gint selected;
 
-					selected = ICON_DATA(fd)->selected & SELECTION_SELECTED;
+					selected = id->selected & SELECTION_SELECTED;
 					if (selected)
 						{
-						vficon_unselect(vfi, fd);
+						vficon_unselect(vfi, id);
 						}
 					else
 						{
-						vficon_select(vfi, fd);
-						vficon_send_layout_select(vfi, fd);
+						vficon_select(vfi, id);
+						vficon_send_layout_select(vfi, id);
 						}
 					}
 				else
 					{
 					vficon_select_none(vfi);
-					vficon_select(vfi, fd);
-					vficon_send_layout_select(vfi, fd);
+					vficon_select(vfi, id);
+					vficon_send_layout_select(vfi, id);
 					}
 				}
 			break;
 		case GDK_Menu:
-			fd = vficon_find_data(vfi, vfi->focus_row, vfi->focus_column, NULL);
-			vfi->click_fd = fd;
-
-			vficon_selection_add(vfi, vfi->click_fd, SELECTION_PRELIGHT, NULL);
+			id = vficon_find_data(vfi, vfi->focus_row, vfi->focus_column, NULL);
+			vfi->click_id = id;
+
+			vficon_selection_add(vfi, vfi->click_id, SELECTION_PRELIGHT, NULL);
 			tip_unschedule(vfi);
 
-			vfi->popup = vficon_pop_menu(vfi, (fd != NULL));
+			vfi->popup = vficon_pop_menu(vfi, (id != NULL));
 			gtk_menu_popup(GTK_MENU(vfi->popup), NULL, NULL, vfi_menu_position_cb, vfi, 0, GDK_CURRENT_TIME);
 			break;
 		default:
@@ -1247,38 +1312,38 @@
 
 	if (focus_row != 0 || focus_col != 0)
 		{
-		FileData *new_fd;
-		FileData *old_fd;
-
-		old_fd = vficon_find_data(vfi, vfi->focus_row, vfi->focus_column, NULL);
+		IconData *new_id;
+		IconData *old_id;
+
+		old_id = vficon_find_data(vfi, vfi->focus_row, vfi->focus_column, NULL);
 		vficon_move_focus(vfi, focus_row, focus_col, TRUE);
-		new_fd = vficon_find_data(vfi, vfi->focus_row, vfi->focus_column, NULL);
-
-		if (new_fd != old_fd)
+		new_id = vficon_find_data(vfi, vfi->focus_row, vfi->focus_column, NULL);
+
+		if (new_id != old_id)
 			{
 			if (event->state & GDK_SHIFT_MASK)
 				{
 				if (!collection_rectangular_selection)
 					{
-					vficon_select_region_util(vfi, old_fd, new_fd, FALSE);
+					vficon_select_region_util(vfi, old_id, new_id, FALSE);
 					}
 				else
 					{
-					vficon_select_region_util(vfi, vfi->click_fd, old_fd, FALSE);
+					vficon_select_region_util(vfi, vfi->click_id, old_id, FALSE);
 					}
-				vficon_select_region_util(vfi, vfi->click_fd, new_fd, TRUE);
-				vficon_send_layout_select(vfi, new_fd);
+				vficon_select_region_util(vfi, vfi->click_id, new_id, TRUE);
+				vficon_send_layout_select(vfi, new_id);
 				}
 			else if (event->state & GDK_CONTROL_MASK)
 				{
-				vfi->click_fd = new_fd;
+				vfi->click_id = new_id;
 				}
 			else
 				{
-				vfi->click_fd = new_fd;
+				vfi->click_id = new_id;
 				vficon_select_none(vfi);
-				vficon_select(vfi, new_fd);
-				vficon_send_layout_select(vfi, new_fd);
+				vficon_select(vfi, new_id);
+				vficon_send_layout_select(vfi, new_id);
 				}
 			}
 		}
@@ -1303,10 +1368,10 @@
 static gint vficon_motion_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
 {
 	ViewFileIcon *vfi = data;
-	FileData *fd;
-
-	fd = vficon_find_data_by_coord(vfi, (gint)bevent->x, (gint)bevent->y, NULL);
-	tip_update(vfi, fd);
+	IconData *id;
+
+	id = vficon_find_data_by_coord(vfi, (gint)bevent->x, (gint)bevent->y, NULL);
+	tip_update(vfi, id);
 
 	return FALSE;
 }
@@ -1315,14 +1380,14 @@
 {
 	ViewFileIcon *vfi = data;
 	GtkTreeIter iter;
-	FileData *fd;
+	IconData *id;
 
 	tip_unschedule(vfi);
 	
-	fd = vficon_find_data_by_coord(vfi, (gint)bevent->x, (gint)bevent->y, &iter);
-
-	vfi->click_fd = fd;
-	vficon_selection_add(vfi, vfi->click_fd, SELECTION_PRELIGHT, &iter);
+	id = vficon_find_data_by_coord(vfi, (gint)bevent->x, (gint)bevent->y, &iter);
+
+	vfi->click_id = id;
+	vficon_selection_add(vfi, vfi->click_id, SELECTION_PRELIGHT, &iter);
 
 	switch (bevent->button)
 		{
@@ -1335,13 +1400,13 @@
 			if (bevent->type == GDK_2BUTTON_PRESS &&
 			    vfi->layout)
 				{
-				vficon_selection_remove(vfi, vfi->click_fd, SELECTION_PRELIGHT, &iter);
+				vficon_selection_remove(vfi, vfi->click_id, SELECTION_PRELIGHT, &iter);
 				layout_image_full_screen_start(vfi->layout);
 				}
 #endif
 			break;
 		case 3:
-			vfi->popup = vficon_pop_menu(vfi, (fd != NULL));
+			vfi->popup = vficon_pop_menu(vfi, (id != NULL));
 			gtk_menu_popup(GTK_MENU(vfi->popup), NULL, NULL, NULL, NULL, bevent->button, bevent->time);
 			break;
 		default:
@@ -1355,40 +1420,40 @@
 {
 	ViewFileIcon *vfi = data;
 	GtkTreeIter iter;
-	FileData *fd = NULL;
+	IconData *id = NULL;
 	gint was_selected = FALSE;
 
 	tip_schedule(vfi);
 
 	if ((gint)bevent->x != 0 || (gint) bevent->y != 0)
 		{
-		fd = vficon_find_data_by_coord(vfi, (gint)bevent->x, (gint)bevent->y, &iter);
+		id = vficon_find_data_by_coord(vfi, (gint)bevent->x, (gint)bevent->y, &iter);
 		}
 
-	if (vfi->click_fd)
+	if (vfi->click_id)
 		{
-		vficon_selection_remove(vfi, vfi->click_fd, SELECTION_PRELIGHT, NULL);
+		vficon_selection_remove(vfi, vfi->click_id, SELECTION_PRELIGHT, NULL);
 		}
 
-	if (fd) was_selected = (ICON_DATA(fd)->selected & SELECTION_SELECTED);
+	if (id) was_selected = (id->selected & SELECTION_SELECTED);
 
 	if (bevent->button == 1 &&
-	    fd && vfi->click_fd == fd)
+	    id && vfi->click_id == id)
 		{
-		vficon_set_focus(vfi, fd);
+		vficon_set_focus(vfi, id);
 		
 		if (bevent->state & GDK_CONTROL_MASK)
 			{
 			gint select;
 
-			select = !(ICON_DATA(fd)->selected & SELECTION_SELECTED);
+			select = !(id->selected & SELECTION_SELECTED);
 			if ((bevent->state & GDK_SHIFT_MASK) && vfi->prev_selection)
 				{
-				vficon_select_region_util(vfi, vfi->prev_selection, fd, select);
+				vficon_select_region_util(vfi, vfi->prev_selection, id, select);
 				}
 			else
 				{
-				vficon_select_util(vfi, fd, select);
+				vficon_select_util(vfi, id, select);
 				}
 			}
 		else
@@ -1398,25 +1463,25 @@
 			if ((bevent->state & GDK_SHIFT_MASK) &&
 			    vfi->prev_selection)
 				{
-				vficon_select_region_util(vfi, vfi->prev_selection, fd, TRUE);
+				vficon_select_region_util(vfi, vfi->prev_selection, id, TRUE);
 				}
 			else
 				{
-				vficon_select_util(vfi, fd, TRUE);
+				vficon_select_util(vfi, id, TRUE);
 				was_selected = FALSE;
 				}
 			}
 		}
 	else if (bevent->button == 2 &&
-		 fd && vfi->click_fd == fd)
+		 id && vfi->click_id == id)
 		{
-		vficon_select_util(vfi, fd, !(ICON_DATA(fd)->selected & SELECTION_SELECTED));
+		vficon_select_util(vfi, id, !(id->selected & SELECTION_SELECTED));
 		}
 
-	if (fd && !was_selected &&
-	    (ICON_DATA(fd)->selected & SELECTION_SELECTED))
+	if (id && !was_selected &&
+	    (id->selected & SELECTION_SELECTED))
 		{
-		vficon_send_layout_select(vfi, fd);
+		vficon_send_layout_select(vfi, id);
 		}
 
 	return TRUE;
@@ -1462,7 +1527,7 @@
 	GtkTreeIter iter;
 	GList *list;
 
-	if (!vficon_find_iter(vfi, fd, &iter, NULL)) return;
+	if (!vficon_find_iter(vfi, vficon_icon_data(vfi, fd), &iter, NULL)) return;
 
 	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview));
 
@@ -1495,7 +1560,7 @@
 	GtkTreePath *tpath;
 	gint row;
 	GList *work;
-	FileData *visible_fd = NULL;
+	IconData *visible_id = NULL;
 
 	vficon_verify_selections(vfi);
 
@@ -1511,7 +1576,7 @@
 		gtk_tree_path_free(tpath);
 
 		gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &list, -1);
-		if (list) visible_fd = list->data;
+		if (list) visible_id = list->data;
 		}
 
 	vficon_clear_store(vfi);
@@ -1559,10 +1624,10 @@
 		list = vficon_add_row(vfi, &iter);
 		while (work && list)
 			{
-			FileData *fd;
-
-			fd = work->data;
-			ICON_DATA(fd)->row = row;
+			IconData *id;
+
+			id = work->data;
+			id->row = row;
 
 			list->data = work->data;
 			list = list->next;
@@ -1570,7 +1635,7 @@
 			}
 		}
 
-	if (visible_fd &&
+	if (visible_id &&
 	    gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vfi->listview), 0, 0, &tpath, NULL, NULL, NULL))
 		{
 		GtkTreeIter iter;
@@ -1580,8 +1645,8 @@
 		gtk_tree_path_free(tpath);
 
 		gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &list, -1);
-		if (g_list_find(list, visible_fd) == NULL &&
-		    vficon_find_iter(vfi, visible_fd, &iter, NULL))
+		if (g_list_find(list, visible_id) == NULL &&
+		    vficon_find_iter(vfi, visible_id, &iter, NULL))
 			{
 			tree_view_row_make_visible(GTK_TREE_VIEW(vfi->listview), &iter, FALSE);
 			}
@@ -1644,22 +1709,22 @@
 		
 		while (list)
 			{
-			FileData *fd;
+			IconData *id;
 
 			if (work)
 				{
-				fd = work->data;
+				id = work->data;
 				work = work->next;
 				c++;
 
-				ICON_DATA(fd)->row = r;
+				id->row = r;
 				}
 			else
 				{
-				fd = NULL;
+				id = NULL;
 				}
 
-			list->data = fd;
+			list->data = id;
 			list = list->next;
 			}
 		}
@@ -1723,7 +1788,7 @@
 
 	if (!vfi->list) return;
 
-	vfi->list = filelist_sort(vfi->list, vfi->sort_method, vfi->sort_ascend);
+	vfi->list = iconlist_sort(vfi->list, vfi->sort_method, vfi->sort_ascend);
 	vficon_sync(vfi);
 }
 
@@ -1829,8 +1894,8 @@
 
 			while (!fd && list)
 				{
-				FileData *tfd = list->data;
-				if (tfd && !tfd->pixbuf) fd = tfd;
+				IconData *id = list->data;
+				if (id && !id->fd->pixbuf) fd = id->fd;
 				list = list->next;
 				}
 
@@ -1845,7 +1910,8 @@
 		GList *work = vfi->list;
 		while (work && !fd)
 			{
-			FileData *fd_p = work->data;
+			IconData *id = work->data;
+			FileData *fd_p = id->fd;
 			work = work->next;
 
 			if (!fd_p->pixbuf) fd = fd_p;
@@ -1902,14 +1968,19 @@
 
 FileData *vficon_index_get_data(ViewFileIcon *vfi, gint row)
 {
-	return FILE_DATA(g_list_nth_data(vfi->list, row));
+	IconData *id;
+	
+	id = g_list_nth_data(vfi->list, row);
+	return id ? id->fd : NULL;
 }
 
 gchar *vficon_index_get_path(ViewFileIcon *vfi, gint row)
 {
 	FileData *fd;
-
-	fd = g_list_nth_data(vfi->list, row);
+	IconData *id;
+	
+	id = g_list_nth_data(vfi->list, row);
+	fd = id ? id->fd : NULL;
 
 	return (fd ? fd->path : NULL);
 }
@@ -1924,7 +1995,8 @@
 	work = vfi->list;
 	while (work)
 		{
-		FileData *fd = work->data;
+		IconData *id = work->data;
+		FileData *fd = id->fd;
 		if (strcmp(path, fd->path) == 0) return p;
 		work = work->next;
 		p++;
@@ -1933,6 +2005,45 @@
 	return -1;
 }
 
+gint vficon_index_by_fd(ViewFileIcon *vfi, FileData *in_fd)
+{
+	gint p = 0;
+	GList *work;
+
+	if (!in_fd) return -1;
+
+	work = vfi->list;
+	while (work)
+		{
+		IconData *id = work->data;
+		FileData *fd = id->fd;
+		if (fd == in_fd) return p;
+		work = work->next;
+		p++;
+		}
+
+	return -1;
+}
+
+static gint vficon_index_by_id(ViewFileIcon *vfi, IconData *in_id)
+{
+	gint p = 0;
+	GList *work;
+
+	if (!in_id) return -1;
+
+	work = vfi->list;
+	while (work)
+		{
+		IconData *id = work->data;
+		if (id == in_id) return p;
+		work = work->next;
+		p++;
+		}
+
+	return -1;
+}
+
 gint vficon_count(ViewFileIcon *vfi, gint64 *bytes)
 {
 	if (bytes)
@@ -1943,7 +2054,9 @@
 		work = vfi->list;
 		while (work)
 			{
-			FileData *fd = work->data;
+			
+			IconData *id = work->data;
+			FileData *fd = id->fd;
 			work = work->next;
 			b += fd->size;
 			}
@@ -1962,10 +2075,11 @@
 	work = vfi->list;
 	while (work)
 		{
-		FileData *fd = work->data;
+		IconData *id = work->data;
+		FileData *fd = id->fd;
 		work = work->next;
 
-		list = g_list_prepend(list, g_strdup(fd->path));
+		list = g_list_prepend(list, file_data_ref(fd));
 		}
 
 	return g_list_reverse(list);
@@ -1982,9 +2096,9 @@
 	gint ret = TRUE;
 	GList *old_list;
 	GList *work;
-	FileData *focus_fd;
-
-	focus_fd = vfi->focus_fd;
+	IconData *focus_id;
+
+	focus_id = vfi->focus_id;
 
 	old_list = vfi->list;
 	vfi->list = NULL;
@@ -1998,27 +2112,34 @@
 	work = old_list;
 	while (work)
 		{
+		IconData *id;
 		FileData *fd;
+		
 		GList *needle;
 
-		fd = work->data;
+		id = work->data;
+		fd = id->fd;
+		
 		needle = vfi->list;
 		while (needle)
 			{
-			FileData *fdn = needle->data;
+			IconData *idn = needle->data;
+			FileData *fdn = idn->fd;
 			if (strcmp(fd->name, fdn->name) == 0)
 				{
 				/* swap, to retain old thumb, selection */
-				needle->data = fd;
-				work->data = fdn;
+				needle->data = id;
+				work->data = idn;
 				needle = NULL;
 
 				if (fd->date != fdn->date || fd->size != fdn->size)
 					{
 					/* file changed, update */
+					/* FIXME
 					fd->date = fdn->date;
 					fd->size = fdn->size;
 					vficon_set_thumb(vfi, fd, NULL);
+					*/
 					}
 				}
 			else
@@ -2030,24 +2151,25 @@
 		work = work->next;
 		}
 
-	vfi->list = filelist_sort(vfi->list, vfi->sort_method, vfi->sort_ascend);
+	vfi->list = iconlist_sort(vfi->list, vfi->sort_method, vfi->sort_ascend);
 
 	work = old_list;
 	while (work)
 		{
-		FileData *fd = work->data;
+		IconData *id = work->data;
+		FileData *fd = id->fd;
 		work = work->next;
 
-		if (fd == vfi->prev_selection) vfi->prev_selection = NULL;
-		if (fd == vfi->click_fd) vfi->click_fd = NULL;
+		if (id == vfi->prev_selection) vfi->prev_selection = NULL;
+		if (id == vfi->click_id) vfi->click_id = NULL;
 		}
 
 	vficon_populate(vfi, TRUE, keep_position);
 
 	/* attempt to keep focus on same icon when refreshing */
-	if (focus_fd && g_list_find(vfi->list, focus_fd))
+	if (focus_id && g_list_find(vfi->list, focus_id))
 		{
-		vficon_set_focus(vfi, focus_fd);
+		vficon_set_focus(vfi, focus_id);
 		}
 
 	iconlist_free(old_list);
@@ -2080,17 +2202,20 @@
 	ViewFileIcon *vfi;
 	GtkStyle *style;
 	GList *list;
-	FileData *fd;
 	GdkColor color_fg;
 	GdkColor color_bg;
+	IconData *id;
 
 	vfi = cd->vfi;
 
 	gtk_tree_model_get(tree_model, iter, FILE_COLUMN_POINTER, &list, -1);
-	fd = g_list_nth_data(list, cd->number);
-
+	
+	id = g_list_nth_data(list, cd->number);
+	
+	if (id) g_assert(id->fd->magick == 0x12345678);
+	
 	style = gtk_widget_get_style(vfi->listview);
-	if (fd && ICON_DATA(fd)->selected & SELECTION_SELECTED)
+	if (id && id->selected & SELECTION_SELECTED)
 		{
 		memcpy(&color_fg, &style->text[GTK_STATE_SELECTED], sizeof(color_fg));
 		memcpy(&color_bg, &style->base[GTK_STATE_SELECTED], sizeof(color_bg));
@@ -2101,7 +2226,7 @@
 		memcpy(&color_bg, &style->base[GTK_STATE_NORMAL], sizeof(color_bg));
 		}
 
-	if (fd && ICON_DATA(fd)->selected & SELECTION_PRELIGHT)
+	if (id && id->selected & SELECTION_PRELIGHT)
 		{
 #if 0
 		shift_color(&color_fg, -1, 0);
@@ -2111,15 +2236,15 @@
 
 	if (GQV_IS_CELL_RENDERER_ICON(cell))
                 {
-		if (fd)
+		if (id)
 			{
-			g_object_set(cell,	"pixbuf", fd->pixbuf,
-						"text", fd->name,
+			g_object_set(cell,	"pixbuf", id->fd->pixbuf,
+						"text", id->fd->name,
 						"cell-background-gdk", &color_bg,
 						"cell-background-set", TRUE,
 						"foreground-gdk", &color_fg,
 						"foreground-set", TRUE,
-						"has-focus", (vfi->focus_fd == fd), NULL);
+						"has-focus", (vfi->focus_id == id), NULL);
 			}
 		else
 			{
@@ -2185,7 +2310,7 @@
 	/* NOTE: populate will clear the store for us */
 	ret = vficon_refresh_real(vfi, FALSE);
 
-	vfi->focus_fd = NULL;
+	vfi->focus_id = NULL;
 	vficon_move_focus(vfi, 0, 0, FALSE);
 
 	return ret;
@@ -2236,7 +2361,7 @@
 
 	vfi->focus_row = 0;
 	vfi->focus_column = 0;
-	vfi->focus_fd = NULL;
+	vfi->focus_id = NULL;
 
 	vfi->show_text = show_icon_names;
 
@@ -2336,7 +2461,9 @@
 	work = ignore_list;
 	while (work)
 		{
-		gint f = vficon_index_by_path(vfi, work->data);
+		FileData *fd = work->data;
+		gint f = vficon_index_by_fd(vfi, work->data);
+		g_assert(fd->magick == 0x12345678);
 		if (f >= 0) list = g_list_prepend(list, GINT_TO_POINTER(f));
 		work = work->next;
 		}
@@ -2380,40 +2507,33 @@
 		}
 }
 
-gint vficon_maint_renamed(ViewFileIcon *vfi, const gchar *source, const gchar *dest)
+gint vficon_maint_renamed(ViewFileIcon *vfi, FileData *fd)
 {
 	gint ret = FALSE;
 	gint row;
 	gchar *source_base;
 	gchar *dest_base;
-	GList *work;
-	FileData *fd;
-
-	row = vficon_index_by_path(vfi, source);
+	IconData *id = vficon_icon_data(vfi, fd);
+
+	if (!id) return FALSE;
+
+	row = vficon_index_by_id(vfi, id);
 	if (row < 0) return FALSE;
 
-	source_base = remove_level_from_path(source);
-	dest_base = remove_level_from_path(dest);
-
-	work = g_list_nth(vfi->list, row);
-	fd = work->data;
+	source_base = remove_level_from_path(fd->change->source);
+	dest_base = remove_level_from_path(fd->change->dest);
 
 	if (strcmp(source_base, dest_base) == 0)
 		{
-		vfi->list = g_list_remove(vfi->list, fd);
-		g_free(fd->path);
-
-		fd->path = g_strdup(dest);
-		fd->name = filename_from_path(fd->path);
-
-		vfi->list = filelist_insert_sort(vfi->list, fd, vfi->sort_method, vfi->sort_ascend);
+		vfi->list = g_list_remove(vfi->list, id);
+		vfi->list = iconlist_insert_sort(vfi->list, id, vfi->sort_method, vfi->sort_ascend);
 
 		vficon_sync_idle(vfi);
 		ret = TRUE;
 		}
 	else
 		{
-		ret = vficon_maint_removed(vfi, source, NULL);
+		ret = vficon_maint_removed(vfi, fd, NULL);
 		}
 
 	g_free(source_base);
@@ -2422,24 +2542,23 @@
 	return ret;
 }
 
-gint vficon_maint_removed(ViewFileIcon *vfi, const gchar *path, GList *ignore_list)
+gint vficon_maint_removed(ViewFileIcon *vfi, FileData *fd, GList *ignore_list)
 {
-	FileData *fd;
 	gint row;
 	gint new_row = -1;
 	GtkTreeModel *store;
 	GtkTreeIter iter;
-
-	row = vficon_index_by_path(vfi, path);
+	IconData *id = vficon_icon_data(vfi, fd);
+
+	if (!id) return FALSE;
+
+	row = g_list_index(vfi->list, id);
 	if (row < 0) return FALSE;
 
-	fd = g_list_nth_data(vfi->list, row);
-	if (!fd) return FALSE;
-
-	if ((ICON_DATA(fd)->selected & SELECTION_SELECTED) &&
+	if ((id->selected & SELECTION_SELECTED) &&
 	    layout_image_get_collection(vfi->layout, NULL) == NULL)
 		{
-		vficon_unselect(vfi, fd);
+		vficon_unselect(vfi, id);
 
 		if (!vfi->selection)
 			{
@@ -2470,29 +2589,31 @@
 			work = vfi->selection;
 			while (work)
 				{
+				IconData *ignore_id;
 				FileData *ignore_fd;
 				GList *tmp;
 				gint match = FALSE;
 
-				ignore_fd = work->data;
+				ignore_id = work->data;
+				ignore_fd = ignore_id->fd;
+				g_assert(ignore_fd->magick == 0x12345678); 
 				work = work->next;
 
 				tmp = ignore_list;
 				while (tmp && !match)
 					{
-					const gchar *ignore_path;
-
-					ignore_path = tmp->data;
+					FileData *ignore_list_fd = tmp->data;
+					g_assert(ignore_list_fd->magick == 0x12345678); 
 					tmp = tmp->next;
 
-					if (strcmp(ignore_fd->path, ignore_path) == 0)
+					if (ignore_list_fd == ignore_fd)
 						{
 						match = TRUE;
 						}
 					}
 				if (!match)
 					{
-					new_row = g_list_index(vfi->list, ignore_fd);
+					new_row = g_list_index(vfi->list, ignore_id);
 					work = NULL;
 					}
 				}
@@ -2509,10 +2630,11 @@
 		if (new_row >= 0)
 			{
 			FileData *fdn;
+			IconData *idn = vficon_icon_data(vfi,fdn);
 
 			fdn = g_list_nth_data(vfi->list, new_row);
-			vficon_select(vfi, fdn);
-			vficon_send_layout_select(vfi, fdn);
+			vficon_select(vfi, idn);
+			vficon_send_layout_select(vfi, idn);
 			}
 		}
 
@@ -2520,23 +2642,24 @@
 	if (fd == vfi->thumbs_fd) vfi->thumbs_fd = NULL;
 	if (vfi->thumbs_count > 0) vfi->thumbs_count--;
 
-	if (vfi->prev_selection == fd) vfi->prev_selection = NULL;
-	if (vfi->click_fd == fd) vfi->click_fd = NULL;
+	if (vfi->prev_selection == id) vfi->prev_selection = NULL;
+	if (vfi->click_id == id) vfi->click_id = NULL;
 
 	/* remove pointer to this fd from grid */
 	store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview));
-	if (ICON_DATA(fd)->row >= 0 &&
-	    gtk_tree_model_iter_nth_child(store, &iter, NULL, ICON_DATA(fd)->row))
+	if (id->row >= 0 &&
+	    gtk_tree_model_iter_nth_child(store, &iter, NULL, id->row))
 		{
 		GList *list;
 
 		gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &list, -1);
-		list = g_list_find(list, fd);
+		list = g_list_find(list, id);
 		if (list) list->data = NULL;
 		}
 
-	vfi->list = g_list_remove(vfi->list, fd);
-	file_data_free(fd);
+	vfi->list = g_list_remove(vfi->list, id);
+	file_data_unref(fd);
+	g_free(id);
 
 	vficon_sync_idle(vfi);
 	vficon_send_update(vfi);
@@ -2544,18 +2667,18 @@
 	return TRUE;
 }
 
-gint vficon_maint_moved(ViewFileIcon *vfi, const gchar *source, const gchar *dest, GList *ignore_list)
+gint vficon_maint_moved(ViewFileIcon *vfi, FileData *fd, GList *ignore_list)
 {
 	gint ret = FALSE;
 	gchar *buf;
 
-	if (!source || !vfi->path) return FALSE;
-
-	buf = remove_level_from_path(source);
+	if (!fd->change->source || !vfi->path) return FALSE;
+
+	buf = remove_level_from_path(fd->change->source);
 
 	if (strcmp(buf, vfi->path) == 0)
 		{
-		ret = vficon_maint_removed(vfi, source, ignore_list);
+		ret = vficon_maint_removed(vfi, fd, ignore_list);
 		}
 
 	g_free(buf);
--- a/src/view_file_icon.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/view_file_icon.h	Tue Sep 11 20:06:29 2007 +0000
@@ -43,11 +43,12 @@
 void vficon_select_all(ViewFileIcon *vfi);
 void vficon_select_none(ViewFileIcon *vfi);
 void vficon_select_by_path(ViewFileIcon *vfi, const gchar *path);
+void vficon_select_by_fd(ViewFileIcon *vfi, FileData *fd);
 
 
-gint vficon_maint_renamed(ViewFileIcon *vfi, const gchar *source, const gchar *dest);
-gint vficon_maint_removed(ViewFileIcon *vfi, const gchar *path, GList *ignore_list);
-gint vficon_maint_moved(ViewFileIcon *vfi, const gchar *source, const gchar *dest, GList *ignore_list);
+gint vficon_maint_renamed(ViewFileIcon *vfi, FileData *fd);
+gint vficon_maint_removed(ViewFileIcon *vfi, FileData *fd, GList *ignore_list);
+gint vficon_maint_moved(ViewFileIcon *vfi, FileData *fd, GList *ignore_list);
 
 
 #endif
--- a/src/view_file_list.c	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/view_file_list.c	Tue Sep 11 20:06:29 2007 +0000
@@ -130,13 +130,13 @@
 		}
 	else
 		{
-		list = g_list_append(NULL, g_strdup(vfl->click_fd->path));
+		list = g_list_append(NULL, file_data_ref(vfl->click_fd));
 		}
 
 	if (!list) return;
 
-	uri_text = uri_text_from_list(list, &total, (info == TARGET_TEXT_PLAIN));
-	path_list_free(list);
+	uri_text = uri_text_from_filelist(list, &total, (info == TARGET_TEXT_PLAIN));
+	filelist_free(list);
 
 	if (debug) printf(uri_text);
 
@@ -205,7 +205,7 @@
 		return vflist_selection_get_list(vfl);
 		}
 
-	return g_list_append(NULL, g_strdup(vfl->click_fd->path));
+	return g_list_append(NULL, file_data_ref(vfl->click_fd));
 }
 
 static void vflist_pop_menu_edit_cb(GtkWidget *widget, gpointer data)
@@ -220,8 +220,8 @@
 	if (!vfl) return;
 
 	list = vflist_pop_menu_file_list(vfl);
-	start_editor_from_path_list(n, list);
-	path_list_free(list);
+	start_editor_from_filelist(n, list);
+	filelist_free(list);
 }
 
 static void vflist_pop_menu_info_cb(GtkWidget *widget, gpointer data)
@@ -241,14 +241,11 @@
 
 		list = vflist_selection_get_list(vfl);
 		view_window_new_from_list(list);
-		path_list_free(list);
+		filelist_free(list);
 		}
 	else
 		{
-		const gchar *path;
-		
-		path = vfl->click_fd->path;
-		view_window_new(path);
+		view_window_new(vfl->click_fd);
 		}
 }
 
@@ -278,7 +275,7 @@
 		GtkTreeModel *store;
 		GtkTreeIter iter;
 
-		path_list_free(list);
+		filelist_free(list);
 
 		store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfl->listview));
 		if (vflist_find_row(vfl, vfl->click_fd, &iter) >= 0)
@@ -459,17 +456,23 @@
 		file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vfl->listview);
 		g_free(text);
 		}
-	else if (!rename_file(old_path, new_path))
+	else 
 		{
-		gchar *text = g_strdup_printf(_("Unable to rename file:\n%s\nto:\n%s"), old, new);
-		file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vfl->listview);
-		g_free(text);
+		gint row = vflist_index_by_path(vfl, old_path);
+		if (row >= 0) 
+			{
+			GList *work = g_list_nth(vfl->list, row);
+			FileData *fd = work->data;
+			file_data_change_info_new(old_path, new_path, fd);
+			if (!rename_file_ext(fd))
+				{
+				gchar *text = g_strdup_printf(_("Unable to rename file:\n%s\nto:\n%s"), old, new);
+				file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, vfl->listview);
+				g_free(text);
+				}
+			}
+
 		}
-	else
-		{
-		file_maint_renamed(old_path, new_path);
-		}
-
 	g_free(old_path);
 	g_free(new_path);
 
@@ -658,10 +661,10 @@
 
 static void vflist_select_image(ViewFileList *vfl, gint row)
 {
-	const gchar *path;
-	const gchar *read_ahead_path = NULL;
+	FileData *path;
+	FileData *read_ahead_fd = NULL;
 
-	path = vflist_index_get_path(vfl, row);
+	path = vflist_index_get_data(vfl, row);
 	if (!path) return;
 
 	if (path && enable_read_ahead)
@@ -680,10 +683,10 @@
 			{
 			fd = NULL;
 			}
-		if (fd) read_ahead_path = fd->path;
+		if (fd) read_ahead_fd = fd;
 		}
 
-	layout_image_set_with_ahead(vfl->layout, path, read_ahead_path);
+	layout_image_set_with_ahead(vfl->layout, path, read_ahead_fd);
 }
 
 static gint vflist_select_idle_cb(gpointer data)
@@ -1118,7 +1121,7 @@
 		FileData *fd = work->data;
 		work = work->next;
 
-		list = g_list_prepend(list, g_strdup(fd->path));
+		list = g_list_prepend(list, file_data_ref(fd));
 		}
 
 	return g_list_reverse(list);
@@ -1225,7 +1228,7 @@
 		gtk_tree_model_get_iter(store, &iter, tpath);
 		gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &fd, -1);
 
-		list = g_list_prepend(list, g_strdup(fd->path));
+		list = g_list_prepend(list, file_data_ref(fd));
 
 		work = work->next;
 		}
@@ -1286,9 +1289,16 @@
 void vflist_select_by_path(ViewFileList *vfl, const gchar *path)
 {
 	FileData *fd;
+
+	if (vflist_row_by_path(vfl, path, &fd) < 0) return;
+
+	vflist_select_by_fd(vfl, fd);
+}
+
+void vflist_select_by_fd(ViewFileList *vfl, FileData *fd)
+{
 	GtkTreeIter iter;
 
-	if (vflist_row_by_path(vfl, path, &fd) < 0) return;
 	if (vflist_find_row(vfl, fd, &iter) < 0) return;
 
 	tree_view_row_make_visible(GTK_TREE_VIEW(vfl->listview), &iter, TRUE);
@@ -1865,23 +1875,20 @@
 		}
 }
 
-gint vflist_maint_renamed(ViewFileList *vfl, const gchar *source, const gchar *dest)
+gint vflist_maint_renamed(ViewFileList *vfl, FileData *fd)
 {
 	gint ret = FALSE;
 	gint row;
 	gchar *source_base;
 	gchar *dest_base;
 	GList *work;
-	FileData *fd;
 
-	row = vflist_index_by_path(vfl, source);
+	row = g_list_index(vfl->list, fd);
 	if (row < 0) return FALSE;
 
-	source_base = remove_level_from_path(source);
-	dest_base = remove_level_from_path(dest);
+	source_base = remove_level_from_path(fd->change->source);
+	dest_base = remove_level_from_path(fd->change->dest);
 
-	work = g_list_nth(vfl->list, row);
-	fd = work->data;
 
 	if (strcmp(source_base, dest_base) == 0)
 		{
@@ -1894,10 +1901,6 @@
 		old_row = g_list_index(vfl->list, fd);
 
 		vfl->list = g_list_remove(vfl->list, fd);
-		g_free(fd->path);
-
-		fd->path = g_strdup(dest);
-		fd->name = filename_from_path(fd->path);
 
 		vfl->list = filelist_insert_sort(vfl->list, fd, vfl->sort_method, vfl->sort_ascend);
 		n = g_list_index(vfl->list, fd);
@@ -1922,7 +1925,7 @@
 		}
 	else
 		{
-		ret = vflist_maint_removed(vfl, source, NULL);
+		ret = vflist_maint_removed(vfl, fd, NULL);
 		}
 
 	g_free(source_base);
@@ -1931,15 +1934,14 @@
 	return ret;
 }
 
-gint vflist_maint_removed(ViewFileList *vfl, const gchar *path, GList *ignore_list)
+gint vflist_maint_removed(ViewFileList *vfl, FileData *fd, GList *ignore_list)
 {
 	GtkTreeIter iter;
 	GList *list;
-	FileData *fd;
 	gint row;
 	gint new_row = -1;
 
-	row = vflist_index_by_path(vfl, path);
+	row = g_list_index(vfl->list, fd);
 	if (row < 0) return FALSE;
 
 	if (vflist_index_is_selected(vfl, row) &&
@@ -1994,25 +1996,25 @@
 	if (vfl->thumbs_count > 0) vfl->thumbs_count--;
 
 	vfl->list = g_list_remove(vfl->list, fd);
-	file_data_free(fd);
+	file_data_unref(fd);
 
 	vflist_send_update(vfl);
 
 	return TRUE;
 }
 
-gint vflist_maint_moved(ViewFileList *vfl, const gchar *source, const gchar *dest, GList *ignore_list)
+gint vflist_maint_moved(ViewFileList *vfl, FileData *fd, GList *ignore_list)
 {
 	gint ret = FALSE;
 	gchar *buf;
 
-	if (!source || !vfl->path) return FALSE;
+	if (!fd->change->source || !vfl->path) return FALSE;
 
-	buf = remove_level_from_path(source);
+	buf = remove_level_from_path(fd->change->source);
 
 	if (strcmp(buf, vfl->path) == 0)
 		{
-		ret = vflist_maint_removed(vfl, source, ignore_list);
+		ret = vflist_maint_removed(vfl, fd, ignore_list);
 		}
 
 	g_free(buf);
--- a/src/view_file_list.h	Thu Aug 23 20:45:59 2007 +0000
+++ b/src/view_file_list.h	Tue Sep 11 20:06:29 2007 +0000
@@ -47,11 +47,12 @@
 void vflist_select_all(ViewFileList *vfl);
 void vflist_select_none(ViewFileList *vfl);
 void vflist_select_by_path(ViewFileList *vfl, const gchar *path);
+void vflist_select_by_fd(ViewFileList *vfl, FileData *fd);
 
 
-gint vflist_maint_renamed(ViewFileList *vfl, const gchar *source, const gchar *dest);
-gint vflist_maint_removed(ViewFileList *vfl, const gchar *path, GList *ignore_list);
-gint vflist_maint_moved(ViewFileList *vfl, const gchar *source, const gchar *dest, GList *ignore_list);
+gint vflist_maint_renamed(ViewFileList *vfl, FileData *fd);
+gint vflist_maint_removed(ViewFileList *vfl, FileData *fd, GList *ignore_list);
+gint vflist_maint_moved(ViewFileList *vfl, FileData *fd, GList *ignore_list);
 
 
 #endif