diff src/filelist.c @ 1:b3e0e515fabf

Initial revision
author gqview
date Mon, 03 Apr 2000 18:24:05 +0000
parents
children c0e337a01cb7
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/filelist.c	Mon Apr 03 18:24:05 2000 +0000
@@ -0,0 +1,1074 @@
+/*
+ * GQview image viewer
+ * (C)1999 John Ellis
+ *
+ * Author: John Ellis
+ *
+ */
+
+#include "gqview.h"
+
+static gint filelist_click_row = -1;
+
+static void update_progressbar(gfloat val);
+
+static gint file_is_hidden(gchar *name);
+static gint file_is_in_filter(gchar *name);
+static void add_to_filter(gchar *text, gint add);
+
+static gint sort_list_cb(void *a, void *b);
+static void filelist_read(gchar *path);
+
+static gint file_find_closest_unaccounted(gint row, gint count, GList *ignore_list);
+
+static void history_menu_select_cb(GtkWidget *widget, gpointer data);
+static gchar *truncate_hist_text(gchar *t, gint l);
+static void filelist_set_history(gchar *path);
+
+/*
+ *-----------------------------------------------------------------------------
+ * file status information (private)
+ *-----------------------------------------------------------------------------
+ */
+
+static void update_progressbar(gfloat val)
+{
+	gtk_progress_bar_update (GTK_PROGRESS_BAR(info_progress_bar), val);
+}
+
+void update_status_label(gchar *text)
+{
+	gchar *buf;
+	gint count;
+	gchar *ss = "";
+
+	if (text)
+		{
+		gtk_label_set(GTK_LABEL(info_status), text);
+		return;
+		}
+
+	if (slideshow_is_running()) ss = _(" Slideshow");
+
+	count = file_selection_count();
+	if (count > 0)
+		buf = g_strdup_printf(_("%d files (%d)%s"), file_count(), count, ss);
+	else
+		buf = g_strdup_printf(_("%d files%s"), file_count(), ss);
+
+	gtk_label_set(GTK_LABEL(info_status), buf);
+	g_free(buf);
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * file filtering
+ *-----------------------------------------------------------------------------
+ */
+
+static gint file_is_hidden(gchar *name)
+{
+	if (name[0] != '.') return FALSE;
+	if (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) return FALSE;
+	return TRUE;
+}
+
+static gint file_is_in_filter(gchar *name)
+{
+	GList *work;
+	if (!filename_filter || file_filter_disable) return TRUE;
+
+	work = filename_filter;
+	while (work)
+		{
+		gchar *filter = work->data;
+		gint lf = strlen(filter);
+		gint ln = strlen(name);
+		if (ln >= lf)
+			{
+			if (strncasecmp(name + ln - lf, filter, lf) == 0) return TRUE;
+			}
+		work = work->next;
+		}
+
+	return FALSE;
+}
+
+static void add_to_filter(gchar *text, gint add)
+{
+	if (add) filename_filter = g_list_append(filename_filter, g_strdup(text));
+}
+
+void rebuild_file_filter()
+{
+	if (filename_filter)
+		{
+		g_list_foreach(filename_filter,(GFunc)g_free,NULL);
+		g_list_free(filename_filter);
+		filename_filter = NULL;
+		}
+
+	add_to_filter(".jpg", filter_include_jpg);
+	add_to_filter(".jpeg", filter_include_jpg);
+	add_to_filter(".xpm", filter_include_xpm);
+	add_to_filter(".tif", filter_include_tif);
+	add_to_filter(".tiff", filter_include_tif);
+	add_to_filter(".gif", filter_include_gif);
+	add_to_filter(".png", filter_include_png);
+	add_to_filter(".ppm", filter_include_ppm);
+	add_to_filter(".pgm", filter_include_pgm);
+	add_to_filter(".pcx", filter_include_pcx);
+	add_to_filter(".bmp", filter_include_bmp);
+
+	if (custom_filter)
+		{
+		gchar *buf = g_strdup(custom_filter);
+		gchar *pos_ptr_b;
+		gchar *pos_ptr_e = custom_filter;
+		while(pos_ptr_e[0] != '\0')
+			{
+			pos_ptr_b = pos_ptr_e;
+			while (pos_ptr_e[0] != ';' && pos_ptr_e[0] != '\0') pos_ptr_e++;
+			if (pos_ptr_e[0] == ';')
+				{
+				pos_ptr_e[0] = '\0';
+				pos_ptr_e++;
+				}
+			add_to_filter(pos_ptr_b, TRUE);
+			}
+		g_free(buf);
+		}
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * load file list (private)
+ *-----------------------------------------------------------------------------
+ */
+
+static gint sort_list_cb(void *a, void *b)
+{
+	return strcmp((gchar *)a, (gchar *)b);
+}
+
+static void filelist_read(gchar *path)
+{
+	DIR *dp;
+	struct dirent *dir;
+	struct stat ent_sbuf;
+
+	if((dp = opendir(path))==NULL)
+		{
+		/* dir not found */
+		return;
+		}
+	
+	g_list_foreach(dir_list,(GFunc)g_free,NULL);
+	g_list_free(dir_list);
+	dir_list = NULL;
+
+	g_list_foreach(file_list,(GFunc)g_free,NULL);
+	g_list_free(file_list);
+	file_list = NULL;
+
+	while ((dir = readdir(dp)) != NULL)
+		{
+		/* skips removed files */
+		if (dir->d_ino > 0)
+			{
+			gchar *name = dir->d_name;
+			if (show_dot_files || !file_is_hidden(name))
+				{
+				gchar *filepath = g_strconcat(path, "/", name, NULL);
+				if (stat(filepath,&ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode))
+					{
+					dir_list = g_list_prepend(dir_list, g_strdup(name));
+					}
+				else
+					{
+					if (file_is_in_filter(name))
+						file_list = g_list_prepend(file_list, g_strdup(name));
+					}
+				g_free(filepath);
+				}
+			}
+		}
+
+	closedir(dp);
+
+	dir_list = g_list_sort(dir_list, (GCompareFunc) sort_list_cb);
+	file_list = g_list_sort(file_list, (GCompareFunc) sort_list_cb);
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * file list utilities to retrieve information (public)
+ *-----------------------------------------------------------------------------
+ */
+
+gint file_count()
+{
+	return g_list_length(file_list);
+}
+
+gint file_selection_count()
+{
+	gint count = 0;
+	GList *work = GTK_CLIST(file_clist)->selection;
+	while(work)
+		{
+		count++;
+		if (debug) printf("s = %d\n", GPOINTER_TO_INT(work->data));
+		work = work->next;
+		}
+
+	if (debug) printf("files selected = %d\n", count);
+
+	return count;
+}
+
+gint find_file_in_list(gchar *path)
+{
+	GList *work = file_list;
+	gchar *buf;
+	gchar *name;
+	gint count = -1;
+
+	if (!path) return -1;
+
+	buf = remove_level_from_path(path);
+	if (strcmp(buf, current_path) != 0)
+		{
+		g_free(buf);
+		return -1;
+		}
+	g_free(buf);
+
+	name = filename_from_path(path);
+	while(work)
+		{
+		count++;
+		if (strcmp(name, work->data) == 0) return count;
+		work = work->next;
+		}
+
+	return -1;
+}
+
+gchar *file_get_path(gint row)
+{
+	gchar *path = NULL;
+	gchar *name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
+
+	if (name) path = g_strconcat(current_path, "/", name, NULL);
+
+	return path;
+}
+
+gint file_is_selected(gint row)
+{
+	GList *work = GTK_CLIST(file_clist)->selection;
+
+	while(work)
+		{
+		if (GPOINTER_TO_INT(work->data) == row) return TRUE;
+		work = work->next;
+		}
+
+	return FALSE;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * utilities to retrieve list of selected files (public)
+ *-----------------------------------------------------------------------------
+ */
+
+GList *file_get_selected_list()
+{
+	GList *list = NULL;
+	GList *work = GTK_CLIST(file_clist)->selection;
+
+	while(work)
+		{
+		gchar *name = gtk_clist_get_row_data(GTK_CLIST(file_clist),
+			GPOINTER_TO_INT(work->data));
+		list = g_list_prepend(list, g_strconcat(current_path, "/", name, NULL));
+		work = work->next;
+		}
+
+	list = g_list_reverse(list);
+
+	return list;
+}
+
+void free_selected_list(GList *list)
+{
+	g_list_foreach(list, (GFunc)g_free, NULL);
+	g_list_free(list);
+}
+
+gint file_clicked_is_selected()
+{
+	return file_is_selected(filelist_click_row);
+}
+
+gchar *file_clicked_get_path()
+{
+	return file_get_path(filelist_click_row);
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * image change routines
+ *-----------------------------------------------------------------------------
+ */
+
+void file_image_change_to(gint row)
+{
+	gtk_clist_unselect_all(GTK_CLIST(file_clist));
+	gtk_clist_select_row(GTK_CLIST(file_clist), row, -1);
+	if (gtk_clist_row_is_visible(GTK_CLIST(file_clist), row) != GTK_VISIBILITY_FULL)
+		{
+		gtk_clist_moveto(GTK_CLIST(file_clist), row, -1, 0.5, 0.0);
+		}
+}
+
+void file_next_image()
+{
+	gint current = find_file_in_list(image_get_path());
+	gint total = file_count();
+
+	if (current >= 0)
+		{
+		if (current < total - 1)
+			{
+			file_image_change_to(current + 1);
+			}
+		}
+	else
+		{
+		file_image_change_to(0);
+		}
+}
+
+void file_prev_image()
+{
+	gint current = find_file_in_list(image_get_path());
+
+	if (current >= 0)
+		{
+		if (current > 0)
+			{
+			file_image_change_to(current - 1);
+			}
+		}
+	else
+		{
+		file_image_change_to(file_count() - 1);
+		}
+}
+
+void file_first_image()
+{
+	gint current = find_file_in_list(image_get_path());
+	if (current != 0 && file_count() > 0)
+		{
+		file_image_change_to(0);
+		}
+}
+
+void file_last_image()
+{
+	gint current = find_file_in_list(image_get_path());
+	gint count = file_count();
+	if (current != count - 1 && count > 0)
+		{
+		file_image_change_to(count - 1);
+		}
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * file delete/rename update routines
+ *-----------------------------------------------------------------------------
+ */
+
+static gint file_find_closest_unaccounted(gint row, gint count, GList *ignore_list)
+{
+	GList *list = NULL;
+	GList *work;
+	gint rev = row - 1;
+	row ++;
+
+	work = ignore_list;
+	while(work)
+		{
+		gint f = find_file_in_list(work->data);
+		if (f >= 0) list = g_list_append(list, GINT_TO_POINTER(f));
+		work = work->next;
+		}
+
+	while(list)
+		{
+		gint c = TRUE;
+		work = list;
+		while(work && c)
+			{
+			gpointer p = work->data;
+			work = work->next;
+			if (row == GPOINTER_TO_INT(p))
+				{
+				row++;
+				c = FALSE;
+				}
+			if (rev == GPOINTER_TO_INT(p))
+				{
+				rev--;
+				c = FALSE;
+				}
+			if (!c) list = g_list_remove(list, p);
+			}
+		if (c && list)
+			{
+			g_list_free(list);
+			list = NULL;
+			}
+		}
+	if (row > count - 1)
+		{
+		if (rev < 0)
+			return -1;
+		else
+			return rev;
+		}
+	else
+		{
+		return row;
+		}
+}
+
+void file_is_gone(gchar *path, GList *ignore_list)
+{
+	GList *list;
+	gchar *name;
+	gint row;
+	gint new_row = -1;
+	row = find_file_in_list(path);
+	if (row < 0) return;
+
+	if (file_is_selected(row) /* && file_selection_count() == 1 */)
+		{
+		gint n = file_count();
+		if (ignore_list)
+			{
+			new_row = file_find_closest_unaccounted(row, n, ignore_list);
+			if (debug) printf("row = %d, closest is %d\n", row, new_row);
+			}
+		else
+			{
+			if (row + 1 < n)
+				{
+				new_row = row + 1;
+				}
+			else if (row > 0)
+				{
+				new_row = row - 1;
+				}
+			}
+		gtk_clist_unselect_all(GTK_CLIST(file_clist));
+		if (new_row >= 0)
+			{
+			gtk_clist_select_row(GTK_CLIST(file_clist), new_row, -1);
+			file_image_change_to(new_row);
+			}
+		else
+			{
+			image_change_to(NULL);
+			}
+		}
+
+	gtk_clist_remove(GTK_CLIST(file_clist), row);
+	list = g_list_nth(file_list, row);
+	name = list->data;
+	file_list = g_list_remove(file_list, name);
+	g_free(name);
+	update_status_label(NULL);
+}
+
+void file_is_renamed(gchar *source, gchar *dest)
+{
+	gint row;
+	gchar *source_base;
+	gchar *dest_base;
+
+	if (image_get_path() && !strcmp(source, image_get_path()))
+		{
+		image_set_path(dest);
+		}
+
+	row = find_file_in_list(source);
+	if (row < 0) return;
+
+	source_base = remove_level_from_path(source);
+	dest_base = remove_level_from_path(dest);
+
+	if (strcmp(source_base, dest_base) == 0)
+		{
+		gchar *name;
+		gint n;
+		GList *work = g_list_nth(file_list, row);
+		name = work->data;
+		file_list = g_list_remove(file_list, name);
+		g_free(name);
+		name = g_strdup(filename_from_path(dest));
+		file_list = g_list_insert_sorted(file_list, name, (GCompareFunc) sort_list_cb);
+		n = g_list_index(file_list, name);
+
+		if (gtk_clist_get_cell_type(GTK_CLIST(file_clist), row, 0) != GTK_CELL_PIXTEXT)
+			{
+			gtk_clist_set_text (GTK_CLIST(file_clist), row, 0, name);
+			}
+		else
+			{
+			guint8 spacing = 0;
+			GdkPixmap *pixmap = NULL;
+			GdkBitmap *mask = NULL;
+			gtk_clist_get_pixtext(GTK_CLIST(file_clist), row, 0,
+				NULL, &spacing, &pixmap, &mask);
+			gtk_clist_set_pixtext(GTK_CLIST(file_clist), row, 0,
+				name, spacing, pixmap, mask);
+			}
+
+		gtk_clist_set_row_data(GTK_CLIST(file_clist), row, name);
+		gtk_clist_row_move(GTK_CLIST(file_clist), row, n);
+		}
+	else
+		{
+		GList *work = g_list_nth(file_list, row);
+		gchar *name = work->data;
+		file_list = g_list_remove(file_list, name);
+		gtk_clist_remove(GTK_CLIST(file_clist), row);
+		g_free(name);
+		update_status_label(NULL);
+		}
+
+	g_free(source_base);
+	g_free(dest_base);
+	
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * directory list callbacks
+ *-----------------------------------------------------------------------------
+ */
+
+void dir_select_cb(GtkWidget *widget, gint row, gint col,
+		   GdkEvent *event, gpointer data)
+{
+	gchar *name;
+	gchar *new_path;
+	name = gtk_clist_get_row_data (GTK_CLIST(dir_clist), row);
+	if (strcmp(name, ".") == 0)
+		{
+		new_path = g_strdup(current_path);
+		}
+	else if (strcmp(name, "..") == 0)
+		{
+		new_path = remove_level_from_path(current_path);
+		}
+	else
+		{
+		if (strcmp(current_path, "/") == 0)
+			new_path = g_strconcat(current_path, name, NULL);
+		else
+			new_path = g_strconcat(current_path, "/", name, NULL);
+		}
+	filelist_change_to(new_path);
+	g_free(new_path);
+}
+
+void dir_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
+{
+	gint row = -1;
+	gint col = -1;
+
+	gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &col);
+
+	if (bevent->button == 2)
+		{
+		gtk_object_set_user_data(GTK_OBJECT(dir_clist), GINT_TO_POINTER(row));
+		}
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * file list callbacks
+ *-----------------------------------------------------------------------------
+ */
+
+void file_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
+{
+	gint row = -1;
+	gint col = -1;
+
+	gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &col);
+	if (row == -1 || col == -1)
+		{
+		filelist_click_row = -1;
+		return;
+		}
+
+	filelist_click_row = row;
+
+	if (bevent->button == 3)
+		{
+		file_clist_highlight_set();
+		gtk_menu_popup (GTK_MENU(menu_file_popup), NULL, NULL, NULL, NULL,
+				bevent->button, bevent->time);
+		}
+}
+
+void file_select_cb(GtkWidget *widget, gint row, gint col,
+		   GdkEvent *event, gpointer data)
+{
+	gchar *name;
+	gchar *path;
+
+	if (file_selection_count() != 1)
+		{
+		update_status_label(NULL);
+		return;
+		}
+
+	name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
+	path = g_strconcat(current_path, "/", name, NULL);
+	image_change_to(path);
+	update_status_label(NULL);
+	g_free(path);
+}
+
+void file_unselect_cb(GtkWidget *widget, gint row, gint col,
+		   GdkEvent *event, gpointer data)
+{
+#if 0
+	gchar *name;
+	gchar *path;
+
+	name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
+	path = g_strconcat(current_path, "/", name, NULL);
+
+	if (strcmp(path, image_get_path()) == 0)
+		{
+		if (file_selection_count() > 0 && !file_is_selected(find_file_in_list(image_get_path())) )
+			{
+			gint new_row = GPOINTER_TO_INT(GTK_CLIST(file_clist)->selection->data);
+			gchar *new_name = gtk_clist_get_row_data(GTK_CLIST(file_clist), new_row);
+			gchar *new_path = g_strconcat(current_path, "/", new_name, NULL);
+			image_change_to(new_path);
+			g_free(new_path);
+			}
+		}
+	g_free(path);
+#endif
+	update_status_label(NULL);
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * file list highlight utils
+ *-----------------------------------------------------------------------------
+ */
+
+void file_clist_highlight_set()
+{
+	if (file_clicked_is_selected()) return;
+
+	gtk_clist_set_background(GTK_CLIST(file_clist), filelist_click_row,
+		&GTK_WIDGET (file_clist)->style->bg[GTK_STATE_PRELIGHT]);
+	gtk_clist_set_foreground(GTK_CLIST(file_clist), filelist_click_row,
+		&GTK_WIDGET (file_clist)->style->fg[GTK_STATE_PRELIGHT]);
+}
+
+void file_clist_highlight_unset()
+{
+	if (file_clicked_is_selected()) return;
+
+	gtk_clist_set_background(GTK_CLIST(file_clist), filelist_click_row, NULL);
+	gtk_clist_set_foreground(GTK_CLIST(file_clist), filelist_click_row, NULL);
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * path entry and history menu
+ *-----------------------------------------------------------------------------
+ */
+
+void path_entry_cb(gchar *newdir, gpointer data)
+{
+	gchar *new_path = g_strdup(newdir);
+	parse_out_relatives(new_path);
+	if (isdir(new_path))
+		filelist_change_to(new_path);
+	else if (isfile(new_path))
+		{
+		gchar *path = remove_level_from_path(new_path);
+		filelist_change_to(path);
+		g_free(path);
+		image_change_to(new_path);
+		}
+	g_free(new_path);
+}
+
+static void history_menu_select_cb(GtkWidget *widget, gpointer data)
+{
+	gchar *new_path = data;
+	filelist_change_to(new_path);
+}
+
+static gchar *truncate_hist_text(gchar *t, gint l)
+{
+	gchar *tp;
+	gchar *tbuf;
+	if (l >= strlen(t)) return g_strdup(t);
+	tp = t + strlen(t) - l;
+	while (tp[0] != '/' && tp < t + strlen(t)) tp++;
+                /* this checks to see if directory name is longer than l, if so
+                 * reset the length of name to l, it's better to have a partial
+                 * name than no name at all.
+		 */
+	if (tp >= t + strlen(t)) tp = t + strlen(t) - l;
+	tbuf = g_strconcat("/...", tp, NULL);
+	return tbuf;
+}
+
+static void filelist_set_history(gchar *path)
+{
+	static GList *history_list = NULL;
+	gchar *buf;
+	gchar *buf_ptr;
+	GtkWidget *menu;
+	GtkWidget *item;
+
+	if (!path) return;
+
+	gtk_entry_set_text(GTK_ENTRY(path_entry), current_path);
+
+	if (history_list)
+                {
+                g_list_foreach(history_list, (GFunc)g_free, NULL);
+                g_list_free(history_list);
+                history_list = NULL;
+                }
+
+	menu = gtk_menu_new();
+
+	buf = g_strdup(path);
+	buf_ptr = buf + strlen(buf) - 1 ;
+	while (buf_ptr > buf)
+		{
+		gchar *full_path;
+		gchar *truncated;
+		truncated = truncate_hist_text(buf, 32);
+
+		full_path = g_strdup(buf);
+		history_list = g_list_append(history_list, full_path);
+
+		item = gtk_menu_item_new_with_label (truncated);
+		gtk_signal_connect (GTK_OBJECT (item), "activate",
+			(GtkSignalFunc) history_menu_select_cb, full_path);
+
+		gtk_menu_append (GTK_MENU (menu), item);
+		gtk_widget_show (item);
+
+		g_free(truncated);
+
+		while (buf_ptr[0] != '/' && buf_ptr > buf) buf_ptr--;
+		buf_ptr[0] = '\0';
+		}
+	g_free(buf);
+
+	item = gtk_menu_item_new_with_label ("/");
+
+	gtk_signal_connect (GTK_OBJECT (item), "activate",
+		(GtkSignalFunc) history_menu_select_cb, "/");
+
+	gtk_menu_append (GTK_MENU (menu), item);
+	gtk_widget_show (item);
+
+	gtk_option_menu_set_menu(GTK_OPTION_MENU(history_menu), menu);
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * list update routines (public)
+ *-----------------------------------------------------------------------------
+ */
+
+static gint thumbs_running = 0;
+
+void interrupt_thumbs()
+{
+        if (thumbs_running > 0) thumbs_running ++;
+}
+
+void filelist_populate_clist()
+{
+	GList *work;
+	gint width;
+	gint tmp_width;
+	gint row;
+	gchar *image_name = NULL;
+	gchar *buf;
+
+	gint row_p = 0;
+	gchar *text;
+	guint8 spacing;
+	GdkPixmap *nopixmap;
+	GdkBitmap *nomask;
+
+	interrupt_thumbs();
+
+	filelist_set_history(current_path);
+
+	gtk_clist_freeze (GTK_CLIST (dir_clist));
+	gtk_clist_clear (GTK_CLIST (dir_clist));
+
+	width = 0;
+	work = dir_list;
+	while(work)
+		{
+		gchar *buf[2];
+		buf[0] = work->data;
+		buf[1] = NULL;
+		row = gtk_clist_append(GTK_CLIST(dir_clist), buf);
+		gtk_clist_set_row_data (GTK_CLIST(dir_clist), row, work->data);
+		tmp_width = gdk_string_width(dir_clist->style->font, buf[0]);
+		if (tmp_width > width) width = tmp_width;
+		work = work->next;
+		}
+
+	gtk_clist_set_column_width(GTK_CLIST(dir_clist), 0, width);
+	gtk_clist_thaw(GTK_CLIST (dir_clist));
+
+	buf = remove_level_from_path(image_get_path());
+	if (buf && strcmp(buf, current_path) == 0)
+		{
+		image_name = image_get_name();
+		}
+	g_free(buf);
+
+	gtk_clist_freeze (GTK_CLIST (file_clist));
+
+	if (!thumbnails_enabled)
+		{
+		gtk_clist_set_row_height (GTK_CLIST(file_clist),
+			GTK_WIDGET(file_clist)->style->font->ascent +
+			GTK_WIDGET(file_clist)->style->font->descent + 1);
+		}
+	else
+		{
+		gtk_clist_set_row_height (GTK_CLIST(file_clist), thumb_max_height + 2);
+		maintain_thumbnail_dir(current_path, FALSE);
+		}
+
+	width = 0;
+	work = file_list;
+
+	while(work)
+		{
+		gint has_pixmap;
+		gint match;
+		gchar *name = work->data;
+		gint done = FALSE;
+
+		while (!done)
+			{
+			if (GTK_CLIST(file_clist)->rows > row_p)
+				{
+				if (gtk_clist_get_cell_type(GTK_CLIST(file_clist),row_p, 0) == GTK_CELL_PIXTEXT)
+					{
+					gtk_clist_get_pixtext(GTK_CLIST(file_clist), row_p, 0, &text, &spacing, &nopixmap, &nomask);
+					has_pixmap = TRUE;
+					}
+				else
+					{
+					gtk_clist_get_text(GTK_CLIST(file_clist), row_p, 0, &text);
+					has_pixmap = FALSE;
+					}
+				match = strcmp(name, text);
+				}
+			else
+				{
+				match = -1;
+				}
+
+			if (match < 0)
+				{
+				gchar *buf[2];
+				buf[0] = name;
+				buf[1] = NULL;
+				row = gtk_clist_insert(GTK_CLIST(file_clist), row_p, buf);
+				gtk_clist_set_row_data (GTK_CLIST(file_clist), row, name);
+				if (thumbnails_enabled)
+					gtk_clist_set_shift(GTK_CLIST(file_clist), row, 0, 0, 5 + thumb_max_width);
+				done = TRUE;
+				if (image_name && strcmp(name, image_name) == 0)
+					gtk_clist_select_row(GTK_CLIST(file_clist), row, 0);
+				}
+			else if (match > 0)
+				{
+				gtk_clist_remove(GTK_CLIST(file_clist), row_p);
+				}
+			else
+				{
+				if (thumbnails_enabled && !has_pixmap)
+					gtk_clist_set_shift(GTK_CLIST(file_clist), row_p, 0, 0, 5 + thumb_max_width);
+				if (!thumbnails_enabled/* && has_pixmap*/)
+					{
+					gtk_clist_set_text(GTK_CLIST(file_clist), row_p, 0, name);
+					gtk_clist_set_shift(GTK_CLIST(file_clist), row_p, 0, 0, 0);
+					}
+				gtk_clist_set_row_data (GTK_CLIST(file_clist), row_p, name);
+				done = TRUE;
+				}
+			}
+		row_p++;
+
+		if (thumbnails_enabled)
+			tmp_width = gdk_string_width(file_clist->style->font, name) + thumb_max_width + 5;
+		else
+			tmp_width = gdk_string_width(file_clist->style->font, name);
+		if (tmp_width > width) width = tmp_width;
+		work = work->next;
+		}
+
+	while (GTK_CLIST(file_clist)->rows > row_p)
+		gtk_clist_remove(GTK_CLIST(file_clist), row_p);
+
+	gtk_clist_set_column_width(GTK_CLIST(file_clist), 0, width);
+	gtk_clist_thaw(GTK_CLIST (file_clist));
+
+	if (thumbnails_enabled)
+		{
+		GList *done_list = NULL;
+		gint past_run;
+		gint finished = FALSE;
+		gint j;
+		gint count = 0;
+		update_status_label(_("Loading thumbs..."));
+
+		for (j = 0; j < GTK_CLIST(file_clist)->rows; j++)
+			{
+			done_list = g_list_prepend(done_list, GINT_TO_POINTER(FALSE));
+			}
+
+		/* load thumbs */
+
+		while (!finished && done_list)
+			{
+			gint p = -1;
+			gint r = -1;
+			gint c = -1;
+			gtk_clist_get_selection_info (GTK_CLIST(file_clist), 1, 1, &r, &c);
+			if (r != -1)
+				{
+				work = g_list_nth(done_list, r);
+				while (work)
+					{
+					if (gtk_clist_row_is_visible(GTK_CLIST(file_clist), r))
+						{
+						if (!GPOINTER_TO_INT(work->data))
+							{
+							work->data = GINT_TO_POINTER(TRUE);
+							p = r;
+							work = NULL;
+							}
+						else
+							{
+							r++;
+							work = work->next;
+							}
+						}
+					else
+						{
+						work = NULL;
+						}
+					}
+				}
+			if (p == -1)
+				{
+				work = done_list;
+				r = 0;
+				while(work && p == -1)
+					{
+					if (!GPOINTER_TO_INT(work->data))
+						{
+						p = r;
+						work->data = GINT_TO_POINTER(TRUE);
+						}
+					else
+						{
+						r++;
+						work = work->next;
+						if (!work) finished = TRUE;
+						}
+					}
+				}
+
+			count++;
+
+			if (!finished && gtk_clist_get_cell_type(GTK_CLIST(file_clist), p, 0) != GTK_CELL_PIXTEXT)
+				{
+				GdkPixmap *pixmap = NULL;
+				GdkBitmap *mask = NULL;
+				gchar *name;
+				gchar *path;
+
+				thumbs_running ++;
+				past_run = thumbs_running;
+				while(gtk_events_pending()) gtk_main_iteration();
+				if (thumbs_running > past_run)
+					{
+					thumbs_running -= 2;
+					update_progressbar(0.0);
+					update_status_label(NULL);
+					g_list_free(done_list);
+					return;
+					}
+				thumbs_running --;
+
+				name = gtk_clist_get_row_data(GTK_CLIST(file_clist), p);
+				path = g_strconcat (current_path, "/", name, NULL);
+				spacing = create_thumbnail(path, &pixmap, &mask);
+				g_free(path);
+				gtk_clist_set_pixtext (GTK_CLIST(file_clist), p, 0, name, spacing + 5, pixmap, mask);
+				gtk_clist_set_shift(GTK_CLIST(file_clist), p, 0, 0, 0);
+
+				update_progressbar((gfloat)(count) / GTK_CLIST(file_clist)->rows);
+				}
+			}
+		update_progressbar(0.0);
+		g_list_free(done_list);
+		}
+
+	update_status_label(NULL);
+}
+
+void filelist_refresh()
+{
+	filelist_read(current_path);
+	filelist_populate_clist();
+	filelist_click_row = -1;
+}
+
+void filelist_change_to(gchar *path)
+{
+	if (!isdir(path)) return;
+
+	g_free(current_path);
+	current_path = g_strdup(path);
+
+	filelist_refresh();
+}