/*
** 1999-01-28 -	Configuration of the automounting system. Pretty straight forward.
**		Note: part of the configuration data (paths to database files) is
**		handled by the paths config.
*/

#include "gentoo.h"

#include "guiutil.h"
#include "strutil.h"
#include "cfg_gui.h"
#include "cfg_module.h"

#include "cfg_mount.h"

#define	NODE	"Mounting"

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

typedef struct {
	GtkWidget	*vbox;

	GtkWidget	*mframe;		/* Mode frame. */
	GtkWidget	*mmode[3];		/* Mode radio buttons. */
	GSList		*mgroup;		/* Grouping list for radio buttons. */

	GtkWidget	*oframe;		/* Options frame. */
	GtkWidget	*octab;			/* Command table. */
	GtkWidget	*ocmount, *ocumount;	/* Entry widgets for mount & umount command names. */
	GtkWidget	*oflag[3];		/* Flag check buttons. */

	MainInfo	*main;
	gint		modified;
	MountInfo	mount;
} P_Mount;

static P_Mount	the_page;

static char	*mode_name[] = { "never", "rarely", "often" };
static MntMode	mode_mode[] = { MNT_NEVER, MNT_RARELY, MNT_OFTEN };

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

/* 1999-01-28 -	Convert an internal name of a mounting mode to the numeral code for it. */
static MntMode str_to_mode(char *str)
{
	guint	i;

	for(i = 0; i < sizeof mode_name / sizeof mode_name[0]; i++)
	{
		if(strcmp(str, mode_name[i]) == 0)
			return mode_mode[i];
	}
	return -1;
}

/* 1999-01-28 -	Convert a numeric mode to a string. */
static char * mode_to_str(MntMode mode)
{
	return mode_name[mode];
}

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

static void set_widgets(P_Mount *page)
{
	GtkWidget	*mw = NULL, *dw = NULL;

	switch(page->mount.mode)
	{
		case MNT_NEVER:
			mw = page->mmode[0];
			dw = page->oframe;
			break;
		case MNT_RARELY:
			mw = page->mmode[1];
			break;
		case MNT_OFTEN:
			mw = page->mmode[2];
			break;
		default:
			fprintf(stderr, "CFGMOUNT: Unsupported mode %d!\n", page->mount.mode);
	}
	if(mw != NULL)
		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mw), TRUE);
	if(dw != NULL)
		gtk_widget_set_sensitive(dw, FALSE);

	gtk_entry_set_text(GTK_ENTRY(page->ocmount), page->mount.cmd_mount);
	gtk_entry_set_text(GTK_ENTRY(page->ocumount), page->mount.cmd_umount);
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->oflag[0]), page->mount.check_nlink);
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->oflag[1]), page->mount.show_stderr);
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->oflag[2]), page->mount.umount_exit);
}

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

/* 1999-01-28 -	User changed the mounting mode. Let the world know. */
static gint evt_mode_clicked(GtkWidget *wid, gpointer user)
{
	P_Mount	*page = gtk_object_get_user_data(GTK_OBJECT(wid));

	page->mount.mode = (MntMode) user;
	gtk_widget_set_sensitive(page->oframe, page->mount.mode != MNT_NEVER);
	page->modified = TRUE;

	return TRUE;
}

/* 1999-01-28 -	User is editing the mount command. Get new string. */
static gint evt_cmd_mount_changed(GtkWidget *wid, gpointer user)
{
	P_Mount	*page = user;

	str_strncpy(page->mount.cmd_mount, gtk_entry_get_text(GTK_ENTRY(wid)), sizeof page->mount.cmd_mount);
	page->modified = TRUE;

	return TRUE;
}

/* 1999-01-28 -	User is editing the umount command. Get new string. */
static gint evt_cmd_umount_changed(GtkWidget *wid, gpointer user)
{
	P_Mount	*page = user;

	str_strncpy(page->mount.cmd_umount, gtk_entry_get_text(GTK_ENTRY(wid)), sizeof page->mount.cmd_umount);
	page->modified = TRUE;

	return TRUE;
}

/* 1999-01-28 -	Grab a flag. */
static gint evt_nlink_changed(GtkWidget *wid, gpointer user)
{
	P_Mount	*page = user;

	page->mount.check_nlink = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid));

	page->modified = TRUE;

	return TRUE;
}

/* 1999-01-28 -	Grab a flag. */
static gint evt_stderr_changed(GtkWidget *wid, gpointer user)
{
	P_Mount	*page = user;

	page->mount.show_stderr = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid));

	page->modified = TRUE;

	return TRUE;
}

/* 1999-01-28 -	Grab a flag. */
static gint evt_umount_changed(GtkWidget *wid, gpointer user)
{
	P_Mount	*page = user;

	page->mount.umount_exit = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid));

	page->modified = TRUE;

	return TRUE;
}

/* 1999-01-28 -	Open up the mount configuration GUI. */
static GtkWidget * cmn_init(MainInfo *min, char **name)
{
	const gchar	*mlab[] = { "Never", "On Double-Click and Shortcut Only", "On Every Access" };
	MntMode		mmode[] = { MNT_NEVER, MNT_RARELY, MNT_OFTEN };
	P_Mount	*page = &the_page;
	GtkWidget	*vbox, *label;
	guint		i;

	if(name == NULL)
		return NULL;

	*name = "Mounting";

	page->main = min;
	page->modified = FALSE;

	page->vbox = gtk_vbox_new(FALSE, 0);

	page->mframe = gtk_frame_new("Mount When?");
	vbox = gtk_vbox_new(FALSE, 0);
	page->mgroup = gui_radio_group_new(sizeof mlab / sizeof mlab[0], mlab, page->mmode);
	for(i = 0; i < sizeof mlab / sizeof mlab[0]; i++)
	{
		gtk_object_set_user_data(GTK_OBJECT(page->mmode[i]), page);
		gtk_signal_connect(GTK_OBJECT(page->mmode[i]), "clicked", GTK_SIGNAL_FUNC(evt_mode_clicked), (gpointer) mmode[i]);
		gtk_box_pack_start(GTK_BOX(vbox), page->mmode[i], FALSE, FALSE, 0);
		gtk_widget_show(page->mmode[i]);
	}
	gtk_container_add(GTK_CONTAINER(page->mframe), vbox);
	gtk_widget_show(vbox);
	gtk_box_pack_start(GTK_BOX(page->vbox), page->mframe, FALSE, FALSE, 0);
	gtk_widget_show(page->mframe);


	page->oframe = gtk_frame_new("Mount Options");
	vbox = gtk_vbox_new(FALSE, 0);
	page->octab = gtk_table_new(2, 2, FALSE);
	label = gtk_label_new("Mount Command");
	gtk_table_attach(GTK_TABLE(page->octab), label, 0, 1, 0, 1,  0,0,0,0);
	gtk_widget_show(label);
	page->ocmount = gtk_entry_new_with_max_length(sizeof page->mount.cmd_mount - 1);
	gtk_signal_connect(GTK_OBJECT(page->ocmount), "changed", GTK_SIGNAL_FUNC(evt_cmd_mount_changed), page);
	gtk_table_attach(GTK_TABLE(page->octab), page->ocmount, 1, 2, 0, 1,  GTK_FILL|GTK_EXPAND,0,0,0);
	gtk_widget_show(page->ocmount);
	label = gtk_label_new("Unmount Command");
	gtk_table_attach(GTK_TABLE(page->octab), label, 0, 1, 1, 2,  0,0,0,0);
	gtk_widget_show(label);
	page->ocumount = gtk_entry_new_with_max_length(sizeof page->mount.cmd_umount - 1);
	gtk_signal_connect(GTK_OBJECT(page->ocumount), "changed", GTK_SIGNAL_FUNC(evt_cmd_umount_changed), page);
	gtk_table_attach(GTK_TABLE(page->octab), page->ocumount, 1, 2, 1, 2,  GTK_FILL|GTK_EXPAND,0,0,0);
	gtk_widget_show(page->ocumount);
	gtk_box_pack_start(GTK_BOX(vbox), page->octab, FALSE, FALSE, 0);
	gtk_widget_show(page->octab);

	page->oflag[0] = gtk_check_button_new_with_label("Only Mount on Toplevel Directories?");
	gtk_signal_connect(GTK_OBJECT(page->oflag[0]), "clicked", GTK_SIGNAL_FUNC(evt_nlink_changed), page);
	gtk_box_pack_start(GTK_BOX(vbox), page->oflag[0], TRUE, TRUE, 0);
	gtk_widget_show(page->oflag[0]);
	page->oflag[1] = gtk_check_button_new_with_label("Use Command Error Dialog?");
	gtk_signal_connect(GTK_OBJECT(page->oflag[1]), "clicked", GTK_SIGNAL_FUNC(evt_stderr_changed), page);
	gtk_box_pack_start(GTK_BOX(vbox), page->oflag[1], TRUE, TRUE, 0);
	gtk_widget_show(page->oflag[1]);
	page->oflag[2] = gtk_check_button_new_with_label("Unmount When gentoo Quits?");
	gtk_signal_connect(GTK_OBJECT(page->oflag[2]), "clicked", GTK_SIGNAL_FUNC(evt_umount_changed), page);
	gtk_box_pack_start(GTK_BOX(vbox), page->oflag[2], TRUE, TRUE, 0);
	gtk_widget_show(page->oflag[2]);

	gtk_container_add(GTK_CONTAINER(page->oframe), vbox);
	gtk_widget_show(vbox);
	gtk_box_pack_start(GTK_BOX(page->vbox), page->oframe, FALSE, FALSE, 10);
	gtk_widget_show(page->oframe);

	gtk_widget_show(page->vbox);
	return page->vbox;
}

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

/* 1999-01-28 -	Grab current mount settings and update GUI accordingly. */
static void cmn_update(MainInfo *min)
{
	P_Mount	*page = &the_page;

	/* Mount config data is fully static, and easy to copy. */
	page->mount = min->cfg.mount;
	set_widgets(page);

	page->modified = FALSE;		/* Keep this last! */
}

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

/* 1999-01-28 -	Accept current mount settings. If anything changed, tell the mounting module
**		that it needs to clear its caches of the databases. This is done via the flags
**		managed by the main config module (cfg_gui.c).
*/
static void cmn_accept(MainInfo *min)
{
	P_Mount	*page = &the_page;

	if(page->modified)
	{
		min->cfg.mount = page->mount;
		cfg_set_flags(CFLG_RESET_MOUNT);
		page->modified = FALSE;
	}
}

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

/* 1999-01-28 -	Save out the mount config data, using the XML module. Nothing special. */
static gint cmn_save(MainInfo *min, FILE *out)
{
	xml_put_node_open(out, NODE);

	xml_put_text(out, "mode", mode_to_str(min->cfg.mount.mode));

	xml_put_text(out, "cmd_mount", min->cfg.mount.cmd_mount);
	xml_put_text(out, "cmd_umount", min->cfg.mount.cmd_umount);

	xml_put_boolean(out, "check_nlink", min->cfg.mount.check_nlink);
	xml_put_boolean(out, "show_stderr", min->cfg.mount.show_stderr);
	xml_put_boolean(out, "umount_exit", min->cfg.mount.umount_exit);

	xml_put_node_close(out, NODE);

	return TRUE;
}

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

/* 1999-01-28 -	Load configuration data back in. Trivial. */
static void cmn_load(MainInfo *min, XmlNode *node)
{
	char	*str;
	gint	tmp;

	if(xml_get_text(node, "mode", &str))
		min->cfg.mount.mode = str_to_mode(str);
	xml_get_text_copy(node, "cmd_mount", min->cfg.mount.cmd_mount, sizeof min->cfg.mount.cmd_mount);
	xml_get_text_copy(node, "cmd_umount", min->cfg.mount.cmd_umount, sizeof min->cfg.mount.cmd_umount);

	if(xml_get_boolean(node, "check_nlink", &tmp))
		min->cfg.mount.check_nlink = tmp;
	if(xml_get_boolean(node, "show_stderr", &tmp))
		min->cfg.mount.show_stderr = tmp;
	if(xml_get_boolean(node, "umount_exit", &tmp))
		min->cfg.mount.umount_exit = tmp;
}

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

CfgPage * cmn_describe(MainInfo *min)
{
	static CfgPage	desc = { NODE, cmn_init, cmn_update, cmn_accept, cmn_save, cmn_load, NULL };

	return &desc;
}
