/*
** 1998-05-29 -	A rename command might be useful. Since writing this also caused me
**		to implement the generic command interface in cmd_generic, it was
**		very useful indeed!
** 1998-09-18 -	Did some pretty massive changes/additions to provide overwrite protection.
** 1999-01-30 -	Bug fix: always called ovw_overwrite_end() in closing, regardless of
**		whether the _begin() function was ever called. This caused nesting errors.
** 1999-02-23 -	Um... That "bug fix" was buggy. I think I fixed it this time, though.
** 1999-03-05 -	Altered to comply with new selection handling (and its changes on the
**		generic command invocation parameters).
*/

#include "gentoo.h"
#include "errors.h"
#include "dirpane.h"
#include "overwrite.h"

#include "cmd_generic.h"
#include "cmd_rename.h"

#define	CMD_ID	"rename"

/* ----------------------------------------------------------------------------------------- */

typedef struct {
	GtkWidget	*vbox;
	GtkWidget	*label;
	GtkWidget	*entry;
	MainInfo	*min;
	gint		ovw_open : 1;
} RenInfo;

/* ----------------------------------------------------------------------------------------- */

static void ren_body(MainInfo *min, DirPane *src, DirRow *row, GtkWindow *win, gpointer user)
{
	char	temp[1024], *name;
	RenInfo	*ren = (RenInfo *) user;

	gtk_window_set_title(win, "Rename");

	name = DP_ROW_NAME(row);
	g_snprintf(temp, sizeof temp, "Enter new name for \"%s\":", name);
	gtk_label_set_text(GTK_LABEL(ren->label), temp);
	gtk_entry_set_text(GTK_ENTRY(ren->entry), name);
	gtk_entry_select_region(GTK_ENTRY(ren->entry), 0, strlen(name));
	gtk_widget_grab_focus(ren->entry);

	if(ren->ovw_open == 0)
	{
		ovw_overwrite_begin(ren->min, "\"%s\" already exists - proceed with rename?", OVWF_HIDE);
		ren->ovw_open = TRUE;
	}
}

static int ren_action(MainInfo *min, DirPane *src, DirPane *dst, DirRow *row, gpointer user)
{
	RenInfo	*ren = (RenInfo *) user;
	char	*old_name, *new_name;
	OvwRes	ores;

	old_name = DP_ROW_NAME(row);
	new_name = gtk_entry_get_text(GTK_ENTRY(ren->entry));

	/* Disallow attempts to use rename to move files. */
	if(strchr(new_name, '/'))
	{
		err_set(min, EISDIR, CMD_ID, old_name);		/* Not quite perfect error message, but simple. */
		return 0;
	}
	if(strcmp(old_name, new_name) == 0)			/* Ignore renames to self. */
	{
		dp_unselect(src, DP_ROW_INDEX(src, row));
		return 1;
	}
	ores = ovw_overwrite_file(ren->min, new_name, NULL);
	if(ores == OVW_SKIP)
		return 1;
	else if(ores == OVW_CANCEL)
		return 0;		/* This tells the generic handler to quit. Nice and simple. */

	if(rename(old_name, new_name))
		err_set(min, errno, CMD_ID, old_name);
	else
		dp_unselect(src, DP_ROW_INDEX(src, row));
	return errno == 0;
}

static void ren_free(gpointer user)
{
	if(((RenInfo *) user)->ovw_open)
		ovw_overwrite_end(((RenInfo *) user)->min);
}

/* ----------------------------------------------------------------------------------------- */

int cmd_rename(MainInfo *min, DirPane *src, DirPane *dst, CmdArg *ca)
{
	static RenInfo	ri;

	ri.ovw_open   = FALSE;
	ri.vbox = gtk_vbox_new(FALSE, 0);
	ri.label = gtk_label_new("Rename");
	ri.entry = gtk_entry_new_with_max_length(MAXNAMLEN - 1);
	gtk_box_pack_start(GTK_BOX(ri.vbox), ri.label, FALSE, FALSE, 0);
	gtk_box_pack_start(GTK_BOX(ri.vbox), ri.entry, FALSE, FALSE, 0);
	gtk_widget_show(ri.label);
	gtk_widget_show(ri.entry);

	return cmd_generic(min, CGF_NOALL | CGF_SRC | CGF_NODST, ren_body, ren_action, ren_free, &ri);
}
