/*
 * GQmpeg
 * (C)1998, 1999 John Ellis
 *
 * Author: John Ellis
 *
 * This software is released under the GNU General Public License.
 * Please read the included file COPYING for more information.
 * This software comes with no warranty of any kind, use at you own risk!
 */

#include "gqmpeg.h"
#include "utildlg.h"

enum {
	DIALOG_NEW_DIR,
	DIALOG_COPY,
	DIALOG_MOVE,
	DIALOG_DELETE,
	DIALOG_RENAME
};

typedef struct _FileDataMult FileDataMult;
struct _FileDataMult
{
	gint confirm_all;
	gint confirmed;
	gint skip;
	GList *source_list;
	GList *source_next;
	gchar *dest_base;
	gchar *source;
	gchar *dest;
	gint copy;
	gchar *op_text;
};

typedef struct _FileDataSingle FileDataSingle;
struct _FileDataSingle
{
	gint confirmed;
	gchar *source;
	gchar *dest;
	gint copy;
	gchar *op_text;
};

static gint confirm_delete = TRUE; /* hard coded for now... */

static FileDataMult *file_data_multiple_new(GList *source_list, gchar *dest, gint copy);
static void file_data_multiple_free(FileDataMult *fdm);
static void file_util_move_multiple(FileDataMult *fdm);
static void file_util_move_multiple_ok_cb(GtkWidget *widget, gpointer data);
static void file_util_move_multiple_all_cb(GtkWidget *widget, gpointer data);
static void file_util_move_multiple_skip_cb(GtkWidget *widget, gpointer data);
static void file_util_move_multiple_cancel_cb(GtkWidget *widget, gpointer data);
static void file_util_move_multiple(FileDataMult *fdm);

static FileDataSingle *file_data_single_new(gchar *source, gchar *dest, gint copy);
static void file_data_single_free(FileDataSingle *fds);
static void file_util_move_single_ok_cb(GtkWidget *widget, gpointer data);
static void file_util_move_single(FileDataSingle *fds);
static void file_util_move_single_cancel_cb(GtkWidget *widget, gpointer data);
static void file_util_move_do(FileDialog *fd);
static void file_util_move_check(FileDialog *fd);
static void file_util_move_cb(GtkWidget *widget, gpointer data);
static void file_util_move_enter_cb(gchar *path, gpointer data);
static void file_util_move_completion_sync_cb(gchar *path, gpointer data);
static void real_file_util_move(gchar *source_path, GList *source_list, gchar *dest_path, gint copy);

static void file_util_delete_multiple_ok_cb(GtkWidget *w, gpointer data);
static void file_util_delete_multiple_cancel_cb(GtkWidget *w, gpointer data);
static void file_util_delete_multiple(GList *source_list);
static void file_util_delete_ok_cb(GtkWidget *w, gpointer data);
static void file_util_delete_cancel_cb(GtkWidget *w, gpointer data);
static void file_util_delete_single(gchar *path);

static void file_util_rename_multiple_ok_cb(GtkWidget *w, gpointer data);
static void file_util_rename_multiple_cancel_cb(GtkWidget *w, gpointer data);
static void file_util_rename_multiple(FileDialog *fd);
static void file_util_rename_multiple_cb(GtkWidget *w, gpointer data);
static void file_util_rename_multiple_select_cb(GtkWidget *clist,
		gint row, gint column, GdkEventButton *bevent, gpointer data);
static void file_util_rename_multiple_do(GList *source_list);

static void file_util_rename_single_ok_cb(GtkWidget *w, gpointer data);
static void file_util_rename_single_cancel_cb(GtkWidget *w, gpointer data);
static void file_util_rename_single(FileDataSingle *fds);
static void file_util_rename_single_cb(GtkWidget *w, gpointer data);
static void file_util_rename_single_do(gchar *source_path);

static void file_util_create_dir_do(gchar *source, gchar *path);
static void file_util_create_dir_cb(GtkWidget *w, gpointer data);

/*
 *--------------------------------------------------------------------------
 * Move and Copy routines
 *--------------------------------------------------------------------------
 */

/*
 * Multi file move
 */

static FileDataMult *file_data_multiple_new(GList *source_list, gchar *dest, gint copy)
{
	FileDataMult *fdm = g_new0(FileDataMult, 1);
	fdm->confirm_all = FALSE;
	fdm->confirmed = FALSE;
	fdm->skip = FALSE;
	fdm->source_list = source_list;
	fdm->source_next = fdm->source_list;
	fdm->dest_base = g_strdup(dest);
	fdm->source = NULL;
	fdm->dest = NULL;
	fdm->copy = copy;
	if (copy)
		fdm->op_text = "copy";
	else
		fdm->op_text = "move";
	return fdm;
}

static void file_data_multiple_free(FileDataMult *fdm)
{
	free_selection_list(fdm->source_list);
	g_free(fdm->dest_base);
	g_free(fdm->dest);
	g_free(fdm);
}

static void file_util_move_multiple_ok_cb(GtkWidget *widget, gpointer data)
{
	FileDataMult *fdm = data;
	fdm->confirmed = TRUE;
	file_util_move_multiple(fdm);
}

static void file_util_move_multiple_all_cb(GtkWidget *widget, gpointer data)
{
	FileDataMult *fdm = data;
	fdm->confirm_all = TRUE;
	file_util_move_multiple(fdm);
}

static void file_util_move_multiple_skip_cb(GtkWidget *widget, gpointer data)
{
	FileDataMult *fdm = data;
	fdm->skip = TRUE;
	file_util_move_multiple(fdm);
}

static void file_util_move_multiple_cancel_cb(GtkWidget *widget, gpointer data)
{
	FileDataMult *fdm = data;
	file_data_multiple_free(fdm);
}

static void file_util_move_multiple(FileDataMult *fdm)
{
	while (fdm->dest || fdm->source_next)
		{
		if (!fdm->dest)
			{
			GList *work = fdm->source_next;
			fdm->source = work->data;
			fdm->dest = g_strconcat(fdm->dest_base, "/", filename_from_path(fdm->source), NULL);
			fdm->source_next = work->next;
			}

		if (isfile(fdm->dest) && !fdm->confirmed && !fdm->confirm_all && !fdm->skip)
			{
			ConfirmDialog *cd;
			gchar *text = g_strconcat("Overwrite file:\n", fdm->dest, "\n with:\n", fdm->source, NULL);
			cd = confirm_dialog_new("Overwrite file", text, file_util_move_multiple_cancel_cb, fdm);
			confirm_dialog_add(cd, "Skip", file_util_move_multiple_skip_cb);
			confirm_dialog_add(cd, "Yes to all", file_util_move_multiple_all_cb);
			confirm_dialog_add(cd, "Yes", file_util_move_multiple_ok_cb);
			g_free(text);
			return;
			}
		else
			{
			gint success = FALSE;
			if (fdm->skip)
				{
				success = TRUE;
				fdm->skip = FALSE;
				}
			else
				{
				if (fdm->copy)
					{
					success = copy_file(fdm->source, fdm->dest);
					}
				else
					{
					if (move_file(fdm->source, fdm->dest))
						{
						success = TRUE;
/* --------- */					playlist_replace(fdm->source, fdm->dest);
						filelist_refresh();
						}
					}
				}
			if (!success)
				{
				ConfirmDialog *cd;
				gchar *title = g_strconcat("Error ", fdm->op_text, "ing file", NULL);
				gchar *text = g_strconcat("Unable to ", fdm->op_text, " file:\n", fdm->source, "\n to:\n", fdm->dest, "\n during multiple file move.", NULL);
				cd = confirm_dialog_new(title, text, file_util_move_multiple_cancel_cb, fdm);
				confirm_dialog_add(cd, "Continue", file_util_move_multiple_skip_cb);
				g_free(title);
				g_free(text);
				return;
				}
			fdm->confirmed = FALSE;
			g_free(fdm->dest);
			fdm->dest = NULL;
			}
		}

	file_data_multiple_free(fdm);
}

/*
 * Single file move
 */

static FileDataSingle *file_data_single_new(gchar *source, gchar *dest, gint copy)
{
	FileDataSingle *fds = g_new0(FileDataSingle, 1);
	fds->confirmed = FALSE;
	fds->source = g_strdup(source);
	fds->dest = g_strdup(dest);
	fds->copy = copy;
	if (copy)
		fds->op_text = "copy";
	else
		fds->op_text = "move";
	return fds;
}

static void file_data_single_free(FileDataSingle *fds)
{
	g_free(fds->source);
	g_free(fds->dest);
	g_free(fds);
}

static void file_util_move_single_ok_cb(GtkWidget *widget, gpointer data)
{
	FileDataSingle *fds = data;
	fds->confirmed = TRUE;
	file_util_move_single(fds);
}

static void file_util_move_single_cancel_cb(GtkWidget *widget, gpointer data)
{
	FileDataSingle *fds = data;
	file_data_single_free(fds);
}

static void file_util_move_single(FileDataSingle *fds)
{
	if (isfile(fds->dest) && !fds->confirmed)
		{
		ConfirmDialog *cd;
		gchar *text = g_strconcat("Overwrite file:\n", fds->dest, "\n with:\n", fds->source, NULL);
		cd = confirm_dialog_new("Overwrite file", text, file_util_move_single_cancel_cb, fds);
		confirm_dialog_add(cd, "Overwrite", file_util_move_single_ok_cb);
		g_free(text);
		return;
		}
	else
		{
		gint success = FALSE;
		if (fds->copy)
			{
			success = copy_file(fds->source, fds->dest);
			}
		else
			{
			if (move_file(fds->source, fds->dest))
				{
				success = TRUE;
/* --------- */			playlist_replace(fds->source, fds->dest);
				filelist_refresh();
				}
			}
		if (!success)
			{
			gchar *title = g_strconcat("Error ", fds->op_text, "ing file", NULL);
			gchar *text = g_strconcat("Unable to ", fds->op_text, " file:\n", fds->source, "\n to:\n", fds->dest, NULL);
			warning_dialog(title, text);
			g_free(title);
			g_free(text);
			}
		file_data_single_free(fds);
		}
}

/*
 * file move dialog
 */

static void file_util_move_do(FileDialog *fd)
{
	if (fd->multiple_files)
		{
		file_util_move_multiple(file_data_multiple_new(fd->source_list, fd->dest_path, fd->type));
		fd->source_list = NULL;
		}
	else
		{
		if (isdir(fd->dest_path))
			{
			gchar *buf = g_strconcat(fd->dest_path, "/", filename_from_path(fd->source_path), NULL);
			g_free(fd->dest_path);
			fd->dest_path = buf;
			}
		file_util_move_single(file_data_single_new(fd->source_path, fd->dest_path, fd->type));
		}

	generic_dialog_close(NULL, fd);
}

static void file_util_move_check(FileDialog *fd)
{
	g_free(fd->dest_path);
	fd->dest_path = remove_trailing_slash(gtk_entry_get_text(GTK_ENTRY(fd->entry)));

	if (fd->multiple_files && !isdir(fd->dest_path))
		{
		if (isfile(fd->dest_path))
			warning_dialog("Invalid destination", "When operating with multiple files, please select\n a directory, not file.");
		else
			warning_dialog("Invalid directory", "Please select an existing directory");
		return;
		}

	file_util_move_do(fd);
}

static void file_util_move_cb(GtkWidget *widget, gpointer data)
{
	FileDialog *fd = data;
	file_util_move_check(fd);
}

static void file_util_move_enter_cb(gchar *path, gpointer data)
{
	FileDialog *fd = data;
	file_util_move_check(fd);
}

static void file_util_move_completion_sync_cb(gchar *path, gpointer data)
{
	FileDialog *fd = data;
	destination_widget_sync_to_entry(fd->entry);
}

static void real_file_util_move(gchar *source_path, GList *source_list, gchar *dest_path, gint copy)
{
	FileDialog *fd;
	gchar *path = NULL;
	gint multiple;
	gchar *text;
	gchar *title;
	gchar *op_text;
	GtkWidget *tabcomp;
	GtkWidget *dest;

	if (!source_path && !source_list) return;

	if (source_path)
		{
		path = g_strdup(source_path);
		multiple = FALSE;
		}
	else if (source_list->next)
		{
		multiple = TRUE;
		}
	else
		{
		path = g_strdup(source_list->data);
		free_selection_list(source_list);
		source_list = NULL;
		multiple = FALSE;
		}

	if (copy)
		{
		title = "GQmpeg - copy";
		op_text = "Copy";
		}
	else
		{
		title = "GQmpeg - move";
		op_text = "Move";
		}

	if (path)
		text = g_strconcat(op_text, " file:\n", path, "\nto:", NULL);
	else
		text = g_strconcat(op_text, " multiple files from:\n", dest_path, "\nto:", NULL);

	fd = generic_dialog_new(title, text, op_text, "Cancel",
		file_util_move_cb, generic_dialog_close);

	g_free(text);

	fd->type = copy;
	fd->source_path = path;
	fd->source_list = source_list;
	fd->multiple_files = multiple;
	fd->dest_path = g_strdup(dest_path);

	tabcomp = tab_completion_new(&fd->entry, fd->dialog, fd->dest_path, file_util_move_enter_cb, fd);
	gtk_box_pack_start(GTK_BOX(fd->vbox), tabcomp, FALSE, FALSE, 0);
	gtk_widget_show(tabcomp);

	gtk_widget_grab_focus(fd->entry);

	dest = destination_widget_new(fd->dest_path, fd->entry);

	tab_completion_add_tab_func(fd->entry, file_util_move_completion_sync_cb, fd);

	gtk_box_pack_start(GTK_BOX(fd->vbox), dest, TRUE, TRUE, 0);
}

void file_util_move(gchar *source_path, GList *source_list, gchar *dest_path)
{
	real_file_util_move(source_path, source_list, dest_path, FALSE);
}

void file_util_copy(gchar *source_path, GList *source_list, gchar *dest_path)
{
	real_file_util_move(source_path, source_list, dest_path, TRUE);
}

/*
 *--------------------------------------------------------------------------
 * Delete routines
 *--------------------------------------------------------------------------
 */

/*
 * delete multiple files
 */

static void file_util_delete_multiple_ok_cb(GtkWidget *w, gpointer data)
{
	GList *source_list = data;

	while(source_list)
		{
		gchar *path = source_list->data;
		source_list = g_list_remove(source_list, path);
		if (unlink (path) < 0)
			{
			ConfirmDialog *cd;
			gchar *text;
			if (source_list)
				{
				text = g_strconcat("Unable to delete file:\n", path, "\nContinue multiple delete operation?", NULL);
				cd = confirm_dialog_new("Delete failed", text, file_util_delete_multiple_cancel_cb, source_list);
				confirm_dialog_add(cd, "Continue", file_util_delete_multiple_ok_cb);
				}
			else
				{
				text = g_strconcat("Unable to delete file:\n", path, NULL);
				warning_dialog("Delete failed", text);
				}
			g_free(text);
			g_free(path);
			return;
			}
		else
			{
/* --------- */		playlist_remove(path, 0, TRUE);
			filelist_refresh();
			}
		g_free(path);
		}
}

static void file_util_delete_multiple_cancel_cb(GtkWidget *w, gpointer data)
{
	GList *source_list = data;
	free_selection_list(source_list);
}

static void file_util_delete_multiple(GList *source_list)
{
	if (!confirm_delete)
		{
		file_util_delete_multiple_ok_cb(NULL, source_list);
		}
	else
		{
		ConfirmDialog *cd;
		cd = confirm_dialog_new("Delete files", "About to delete multiple files...", file_util_delete_multiple_cancel_cb, source_list);
		confirm_dialog_add(cd, "Delete", file_util_delete_multiple_ok_cb);
		}
}

/*
 * delete single file
 */

static void file_util_delete_ok_cb(GtkWidget *w, gpointer data)
{
	gchar *path = data;

	if (unlink (path) < 0)
		{
		gchar *text = g_strconcat("Unable to delete file:\n", path, NULL);
		warning_dialog("File deletion failed", text);
		g_free(text);
		}
	else
		{
/* --------- */	playlist_remove(path, 0, TRUE);
		filelist_refresh();
		}

	g_free(path);
}

static void file_util_delete_cancel_cb(GtkWidget *w, gpointer data)
{
	gchar *path = data;
	g_free(path);
}

static void file_util_delete_single(gchar *path)
{
	gchar *buf = g_strdup(path);

	if (!confirm_delete)
		{
		file_util_delete_ok_cb(NULL, buf);
		}
	else
		{
		ConfirmDialog *cd;
		gchar *text = g_strconcat("About to delete the file:\n", buf, NULL);
		cd = confirm_dialog_new("Delete file", text, file_util_delete_cancel_cb, buf);
		confirm_dialog_add(cd, "Delete", file_util_delete_ok_cb);
		g_free(text);
		}
}

void file_util_delete(gchar *source_path, GList *source_list)
{
	if (!source_path && !source_list) return;

	if (source_path)
		{
		file_util_delete_single(source_path);
		}
	else if (!source_list->next)
		{
		file_util_delete_single(source_list->data);
		free_selection_list(source_list);
		}
	else
		{
		file_util_delete_multiple(source_list);
		}
}

/*
 *--------------------------------------------------------------------------
 * Rename routines
 *--------------------------------------------------------------------------
 */

/*
 * rename multiple files
 */

static void file_util_rename_multiple_ok_cb(GtkWidget *w, gpointer data)
{
	FileDialog *fd = data;
	if (!GTK_WIDGET_VISIBLE(fd->dialog)) gtk_widget_show(fd->dialog);
	fd->type = TRUE;
	file_util_rename_multiple(fd);
}

static void file_util_rename_multiple_cancel_cb(GtkWidget *w, gpointer data)
{
	FileDialog *fd = data;
	if (!GTK_WIDGET_VISIBLE(fd->dialog)) gtk_widget_show(fd->dialog);
	return;
}

static void file_util_rename_multiple(FileDialog *fd)
{
	if (isfile(fd->dest_path) && !fd->type)
		{
		ConfirmDialog *cd;
		gchar *text = g_strconcat("Overwrite file:\n", fd->dest_path, "\n by renaming:\n", fd->source_path, NULL);
		cd = confirm_dialog_new("Overwrite file", text, file_util_rename_multiple_cancel_cb, fd);
		confirm_dialog_add(cd, "Overwrite", file_util_rename_multiple_ok_cb);
		g_free(text);
		gtk_widget_hide(fd->dialog);
		return;
		}
	else
		{
		if (rename (fd->source_path, fd->dest_path) < 0)
			{
                        gchar *text = g_strconcat("Unable to rename file:\n", filename_from_path(fd->source_path), "\n to:\n", filename_from_path(fd->dest_path), NULL);
                        warning_dialog("Error renaming file", text);
                        g_free(text);
			}
		else
			{
			gint row;
			gint n;
			GtkWidget *clist;
			gchar *path;

/* --------- */		playlist_replace(fd->source_path, fd->dest_path);
			filelist_refresh();

			clist = gtk_object_get_user_data(GTK_OBJECT(fd->entry));
			path = gtk_object_get_user_data(GTK_OBJECT(clist));
			row = gtk_clist_find_row_from_data(GTK_CLIST(clist), path);

			n = g_list_length(GTK_CLIST(clist)->row_list);
			if (debug_mode) printf("r=%d n=%d\n", row, n);
			if (n - 1 > row)
				n = row;
			else if (n > 1)
				n = row - 1;
			else
				n = -1;

			if (n >= 0)
				{
				gtk_object_set_user_data(GTK_OBJECT(clist), NULL);
				gtk_clist_remove(GTK_CLIST(clist), row);
				gtk_clist_select_row(GTK_CLIST(clist), n, -1);
				}
			else
				{
				if (debug_mode) printf("closed by #%d\n", n);
				generic_dialog_close(NULL, fd);
				}
			}
		}
}

static void file_util_rename_multiple_cb(GtkWidget *w, gpointer data)
{
	FileDialog *fd = data;
	gchar *base;
	gchar *name;

	name = gtk_entry_get_text(GTK_ENTRY(fd->entry));
	base = remove_level_from_path(fd->source_path);
	g_free(fd->dest_path);
	fd->dest_path = g_strconcat(base, "/", name, NULL);
	g_free(base);

	if (strlen(name) == 0 || strcmp(fd->source_path, fd->dest_path) == 0)
		{
		return;
		}

	fd->type = FALSE;
	file_util_rename_multiple(fd);
}

static void file_util_rename_multiple_select_cb(GtkWidget *clist,
		gint row, gint column, GdkEventButton *bevent, gpointer data)
{
	FileDialog *fd = data;
	GtkWidget *label;
	gchar *name;
	gchar *path;

	label = gtk_object_get_user_data(GTK_OBJECT(fd->dialog));
	path = gtk_clist_get_row_data(GTK_CLIST(clist), row);
	g_free(fd->source_path);
	fd->source_path = g_strdup(path);
	gtk_object_set_user_data(GTK_OBJECT(clist), path);
	name = filename_from_path(fd->source_path);

	gtk_label_set(GTK_LABEL(label), name);
	gtk_entry_set_text(GTK_ENTRY(fd->entry), name);

	gtk_widget_grab_focus(fd->entry);
}

static void file_util_rename_multiple_do(GList *source_list)
{
	FileDialog *fd;
	GtkWidget *scrolled;
	GtkWidget *clist;
	GtkWidget *label;
	GList *work;

	fd = generic_dialog_new("GQmpeg - rename", "Rename multiple files:", "Rename", "Cancel",
		file_util_rename_multiple_cb, generic_dialog_close);

	fd->source_path = g_strdup(source_list->data);
	fd->dest_path = NULL;

	scrolled = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
				GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
	gtk_box_pack_start(GTK_BOX(fd->vbox), scrolled, TRUE, TRUE, 0);
	gtk_widget_show(scrolled);

	clist=gtk_clist_new (1);
	gtk_signal_connect (GTK_OBJECT (clist), "select_row",(GtkSignalFunc) file_util_rename_multiple_select_cb, fd);
	gtk_widget_set_usize(clist, 250, 150);
	gtk_container_add (GTK_CONTAINER (scrolled), clist);
	gtk_widget_show (clist);

	gtk_object_set_user_data(GTK_OBJECT(clist), source_list->data);

	work = source_list;
	while(work)
		{
		gint row;
		gchar *buf[2];
		buf[0] = filename_from_path(work->data);
		buf[1] = NULL;
		row = gtk_clist_append(GTK_CLIST(clist), buf);
		gtk_clist_set_row_data_full(GTK_CLIST(clist), row,
				work->data, (GtkDestroyNotify) g_free);
		work = work->next;
		}

	g_list_free(source_list);

	label = gtk_label_new("Rename:");
	gtk_box_pack_start(GTK_BOX(fd->vbox), label, FALSE, FALSE, 0);
	gtk_widget_show(label);

	label = gtk_label_new(filename_from_path(fd->source_path));
	gtk_box_pack_start(GTK_BOX(fd->vbox), label, FALSE, FALSE, 0);
	gtk_widget_show(label);
	gtk_object_set_user_data(GTK_OBJECT(fd->dialog), label);

	label = gtk_label_new("to:");
	gtk_box_pack_start(GTK_BOX(fd->vbox), label, FALSE, FALSE, 0);
	gtk_widget_show(label);

	fd->entry = gtk_entry_new();
	gtk_entry_set_text(GTK_ENTRY(fd->entry), filename_from_path(fd->source_path));
	gtk_box_pack_start(GTK_BOX(fd->vbox), fd->entry, FALSE, FALSE, 0);
	gtk_widget_grab_focus(fd->entry);
	gtk_widget_show(fd->entry);

	gtk_object_set_user_data(GTK_OBJECT(fd->entry), clist);
}

/*
 * rename single file
 */

static void file_util_rename_single_ok_cb(GtkWidget *w, gpointer data)
{
	FileDataSingle *fds = data;
	fds->confirmed = TRUE;
	file_util_rename_single(fds);
}

static void file_util_rename_single_cancel_cb(GtkWidget *w, gpointer data)
{
	FileDataSingle *fds = data;
	file_data_single_free(fds);
}

static void file_util_rename_single(FileDataSingle *fds)
{
	if (isfile(fds->dest) && !fds->confirmed)
		{
		ConfirmDialog *cd;
		gchar *text = g_strconcat("Overwrite file:\n", fds->dest, "\n with:\n", fds->source, NULL);
		cd = confirm_dialog_new("Overwrite file", text, file_util_rename_single_cancel_cb, fds);
		confirm_dialog_add(cd, "Overwrite", file_util_rename_single_ok_cb);
		g_free(text);
		return;
		}
	else
		{
		if (rename (fds->source, fds->dest) < 0)
			{
                        gchar *text = g_strconcat("Unable to rename file:\n", filename_from_path(fds->source), "\n to:\n", filename_from_path(fds->dest), NULL);
                        warning_dialog("Error renaming file", text);
                        g_free(text);
			}
		else
			{
/* --------- */		playlist_replace(fds->source, fds->dest);
			filelist_refresh();
			}
		}
	file_data_single_free(fds);
}

static void file_util_rename_single_cb(GtkWidget *w, gpointer data)
{
	FileDialog *fd = data;
	gchar *name = gtk_entry_get_text(GTK_ENTRY(fd->entry));
	gchar *buf = g_strconcat(fd->dest_path, "/", name, NULL);

	if (strlen(name) == 0 || strcmp(fd->source_path, buf) == 0)
		{
		g_free(buf);
		return;
		}

	g_free(fd->dest_path);
	fd->dest_path = buf;

	file_util_rename_single(file_data_single_new(fd->source_path, fd->dest_path, fd->type));

	generic_dialog_close(NULL, fd);
}

static void file_util_rename_single_do(gchar *source_path)
{
	FileDialog *fd;
	gchar *text;
	gchar *name = filename_from_path(source_path);

	text = g_strconcat("Rename file:\n", name, "\n to:", NULL);
	fd = generic_dialog_new("GQmpeg - rename", text, "Rename", "Cancel",
		file_util_rename_single_cb, generic_dialog_close);
	g_free(text);

	fd->source_path = g_strdup(source_path);
	fd->dest_path = remove_level_from_path(source_path);

	fd->entry = gtk_entry_new();
	gtk_entry_set_text(GTK_ENTRY(fd->entry), name);
	gtk_box_pack_start(GTK_BOX(fd->vbox), fd->entry, FALSE, FALSE, 0);
	gtk_widget_grab_focus(fd->entry);
	gtk_widget_show(fd->entry);
}

void file_util_rename(gchar *source_path, GList *source_list)
{
	if (!source_path && !source_list) return;

	if (source_path)
		{
		file_util_rename_single_do(source_path);
		}
	else if (!source_list->next)
		{
		file_util_rename_single_do(source_list->data);
		free_selection_list(source_list);
		}
	else
		{
		file_util_rename_multiple_do(source_list);
		}
}

/*
 *--------------------------------------------------------------------------
 * Create directory routines
 *--------------------------------------------------------------------------
 */

static void file_util_create_dir_do(gchar *source, gchar *path)
{
	if (isfile(path))
		{
		gchar *text = g_strconcat("The path:\n", filename_from_path(path), "\n already exists as a file.", NULL);
		warning_dialog("Could not create directory", text);
		g_free(text);
		}
	else if (isdir(path))
		{
		gchar *text = g_strconcat("The directory:\n", filename_from_path(path), "\n already exists.", NULL);
		warning_dialog("Directory exists", text);
		g_free(text);
		}
	else
		{
		if (mkdir (path, 0755) < 0)
			{
                        gchar *text = g_strconcat("Unable to create directory:\n", filename_from_path(path), NULL);
                        warning_dialog("Error creating directory", text);
                        g_free(text);
			}
		else
			{
			if (strcmp(source, current_path) == 0)
				{
				filelist_refresh();
				}
			}
		}
}

static void file_util_create_dir_cb(GtkWidget *w, gpointer data)
{
	FileDialog *fd = data;
	gchar *name = gtk_entry_get_text(GTK_ENTRY(fd->entry));

	if (strlen(name) == 0) return;

	g_free(fd->dest_path);
	fd->dest_path = g_strconcat(fd->source_path, "/", name, NULL);

	file_util_create_dir_do(fd->source_path, fd->dest_path);

	generic_dialog_close(NULL, fd);
}

void file_util_create_dir(gchar *path)
{
	FileDialog *fd;
	gchar *text;
	gchar *name;

	if (!isdir(path)) return;
	name = filename_from_path(path);

	text = g_strconcat("Create directory in:\n", path, "\n named:", NULL);
	fd = generic_dialog_new("GQmpeg - new directory", text, "Create", "Cancel",
		file_util_create_dir_cb, generic_dialog_close);
	g_free(text);

	fd->source_path = g_strdup(path);
	fd->dest_path = NULL;

	fd->entry = gtk_entry_new();
	gtk_box_pack_start(GTK_BOX(fd->vbox), fd->entry, FALSE, FALSE, 0);
	gtk_widget_grab_focus(fd->entry);
	gtk_widget_show(fd->entry);
}

