#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <gtk/gtk.h>
#include <glib.h>
#include <glib/gprintf.h>
#include <glib/gstdio.h>
#include <string.h>
#include <signal.h>
#include <math.h>

#include "callbacks.h"
#include "interface.h"
#include "support.h"


gchar **argv;
GPid rsync_pid;
gchar **groups = NULL;
gint session_last = -1;
// gint height_expander;
gsize session_number = 0;
gboolean had_error, paused, channel_closed, first_load_groups = TRUE;
gchar *argv_session, *error_list;
gboolean cmdline_session = FALSE, cmdline_execute = FALSE, dryrunning = FALSE;
GtkWidget *main_window, *rsync = NULL;
gchar config_command[MAXPATH];
gboolean config_output = FALSE, config_remember = TRUE, config_errorlist = TRUE, config_log = FALSE;
GTimeVal startime, pausedtime;
gchar *grsync_dir, *rsync_help = NULL, *rsync_man = NULL;
FILE *log_file = NULL;


gboolean get_checkbox(void* main, gchar* name) {
	return gtk_toggle_button_get_active((GtkToggleButton*) lookup_widget((GtkWidget*) main, name));
}


void set_checkbox(void* main, gchar* name, gboolean val) {
	gtk_toggle_button_set_active((GtkToggleButton*) lookup_widget((GtkWidget*) main, name), val);
}


void set_main_title(gchar* session, gchar* extra) {
	gchar *stmp;
	stmp = g_strconcat("Grsync: ", session, " ", extra, NULL);
	gtk_window_set_title((GtkWindow*) main_window, stmp);
	g_free(stmp);
}


void load_settings(GtkWidget* main, gchar* session, gchar *filename) {
	gchar settings_file_path[MAXPATH];
	GError *error_handler = NULL;
	GKeyFile *settings_file;
	gchar *stmp;
	gboolean btmp;
	gint root_x, root_y, width, height;

	if (filename == NULL) g_sprintf(settings_file_path, "%s/%s", grsync_dir, "grsync.ini");
	else strncpy(settings_file_path, filename, MAXPATH-1);

	// initializes config_command before other functions which may use it
	if (filename == NULL) strcpy(config_command, "rsync");

	if (!g_file_test(settings_file_path, G_FILE_TEST_EXISTS)) {
		g_printf (_("(ERROR) Can't open config file! Maybe this is the first run?\n"));
		if (session != NULL) {
			save_settings(main, session, NULL);
			load_groups(main, session);
		}
	}

	settings_file = g_key_file_new();
	g_key_file_load_from_file(settings_file, settings_file_path, G_KEY_FILE_NONE, NULL);
	if (session == NULL) {
		session = g_key_file_get_start_group(settings_file);
		save_settings(main, session, NULL);
		load_groups(main, session);
	}
	set_main_title(session, NULL);

	if (filename == NULL) {
		// load configuration (preferences)
		stmp = g_key_file_get_string(settings_file, CONFIG_GROUP, "command", NULL);
		if (stmp != NULL) strncpy(config_command, stmp, MAXPATH - 1);
		
		btmp = g_key_file_get_boolean(settings_file, CONFIG_GROUP, "output", &error_handler);
		if (error_handler != NULL) g_clear_error (&error_handler);
		else config_output = btmp;
		btmp = g_key_file_get_boolean(settings_file, CONFIG_GROUP, "remember", &error_handler);
		if (error_handler != NULL) g_clear_error (&error_handler);
		else config_remember = btmp;
		btmp = g_key_file_get_boolean(settings_file, CONFIG_GROUP, "errorlist", &error_handler);
		if (error_handler != NULL) g_clear_error (&error_handler);
		else config_errorlist = btmp;
		btmp = g_key_file_get_boolean(settings_file, CONFIG_GROUP, "logging", &error_handler);
		if (error_handler != NULL) g_clear_error (&error_handler);
		else config_log = btmp;

		// load window position and size
		root_x = g_key_file_get_integer(settings_file, CONFIG_GROUP, "root_x", NULL);
		root_y = g_key_file_get_integer(settings_file, CONFIG_GROUP, "root_y", NULL);
		width  = g_key_file_get_integer(settings_file, CONFIG_GROUP, "width", NULL);
		height = g_key_file_get_integer(settings_file, CONFIG_GROUP, "height", NULL);
		gtk_window_move((GtkWindow*) main_window, root_x, root_y);
		if (width > 0 && height > 0) gtk_window_resize((GtkWindow*) main_window, width, height);
	}

	// load specific session
	stmp = g_key_file_get_string(settings_file, session, "text_source", NULL);
	gtk_entry_set_text((GtkEntry*) lookup_widget((GtkWidget*) main, "text_source"), stmp);
	g_free(stmp);
	stmp = g_key_file_get_string(settings_file, session, "text_dest", NULL);
	gtk_entry_set_text((GtkEntry*) lookup_widget((GtkWidget*) main, "text_dest"), stmp);
	g_free(stmp);

	stmp = g_key_file_get_string(settings_file, session, "text_addit", NULL);
	if (stmp == NULL) stmp = g_strconcat("", NULL);
	gtk_entry_set_text((GtkEntry*) lookup_widget((GtkWidget*) main, "entry_additional"), stmp);
	g_free(stmp);

	stmp = g_key_file_get_string(settings_file, session, "text_com_before", NULL);
	if (stmp == NULL) stmp = g_strconcat("", NULL);
	gtk_entry_set_text((GtkEntry*) lookup_widget((GtkWidget*) main, "entry_com_before"), stmp);
	g_free(stmp);
	stmp = g_key_file_get_string(settings_file, session, "text_com_after", NULL);
	if (stmp == NULL) stmp = g_strconcat("", NULL);
	gtk_entry_set_text((GtkEntry*) lookup_widget((GtkWidget*) main, "entry_com_after"), stmp);
	g_free(stmp);

	set_checkbox(main, "check_time", g_key_file_get_boolean(settings_file, session, "check_time", NULL));
	set_checkbox(main, "check_perm", g_key_file_get_boolean(settings_file, session, "check_perm", NULL));
	set_checkbox(main, "check_owner", g_key_file_get_boolean(settings_file, session, "check_owner", NULL));
	set_checkbox(main, "check_group", g_key_file_get_boolean(settings_file, session, "check_group", NULL));
	set_checkbox(main, "check_onefs", g_key_file_get_boolean(settings_file, session, "check_onefs", NULL));
	set_checkbox(main, "check_verbose", g_key_file_get_boolean(settings_file, session, "check_verbose", NULL));
	set_checkbox(main, "check_progr", g_key_file_get_boolean(settings_file, session, "check_progr", NULL));
	set_checkbox(main, "check_delete", g_key_file_get_boolean(settings_file, session, "check_delete", NULL));
	set_checkbox(main, "check_exist", g_key_file_get_boolean(settings_file, session, "check_exist", NULL));
	set_checkbox(main, "check_size", g_key_file_get_boolean(settings_file, session, "check_size", NULL));
	set_checkbox(main, "check_skipnew", g_key_file_get_boolean(settings_file, session, "check_skipnew", NULL));
	set_checkbox(main, "check_windows", g_key_file_get_boolean(settings_file, session, "check_windows", NULL));

	set_checkbox(main, "check_sum", g_key_file_get_boolean(settings_file, session, "check_sum", NULL));
	set_checkbox(main, "check_symlink", g_key_file_get_boolean(settings_file, session, "check_symlink", NULL));
	set_checkbox(main, "check_dev", g_key_file_get_boolean(settings_file, session, "check_dev", NULL));
	set_checkbox(main, "check_update", g_key_file_get_boolean(settings_file, session, "check_update", NULL));
	set_checkbox(main, "check_keepart", g_key_file_get_boolean(settings_file, session, "check_keepart", NULL));
	set_checkbox(main, "check_mapuser", g_key_file_get_boolean(settings_file, session, "check_mapuser", NULL));
	set_checkbox(main, "check_compr", g_key_file_get_boolean(settings_file, session, "check_compr", NULL));
	set_checkbox(main, "check_backup", g_key_file_get_boolean(settings_file, session, "check_backup", NULL));

	set_checkbox(main, "check_com_before", g_key_file_get_boolean(settings_file, session, "check_com_before", NULL));
	set_checkbox(main, "check_com_after", g_key_file_get_boolean(settings_file, session, "check_com_after", NULL));
	set_checkbox(main, "check_browse_files", g_key_file_get_boolean(settings_file, session, "check_browse_files", NULL));

	g_key_file_free (settings_file);
}


void save_settings(GtkWidget* main, gchar *session, gchar *filename) {
	gchar settings_file_name[MAXPATH];
	gchar *key_data;
	FILE *key_file;
	GError *error_handler = NULL;
	GKeyFile *settings_file;
	const gchar *stmp;
	gint root_x, root_y, width, height;

	if (filename == NULL) g_sprintf(settings_file_name, "%s/%s", grsync_dir, "grsync.ini");
	else strncpy(settings_file_name, filename, MAXPATH-1);

//	g_printf(_("Saving settings to %s...\n"), settings_file_name);
	g_mkdir(grsync_dir, 0700);
	settings_file = g_key_file_new();
	
	if (filename == NULL) {
		g_key_file_load_from_file(settings_file, settings_file_name, G_KEY_FILE_NONE, NULL);

		// save configuration (preferences)
		g_key_file_set_string(settings_file, CONFIG_GROUP, "command", config_command);
		g_key_file_set_boolean(settings_file, CONFIG_GROUP, "output", config_output);
		g_key_file_set_boolean(settings_file, CONFIG_GROUP, "remember", config_remember);
		g_key_file_set_boolean(settings_file, CONFIG_GROUP, "errorlist", config_errorlist);
		g_key_file_set_boolean(settings_file, CONFIG_GROUP, "logging", config_log);
		if (session_last != -1) g_key_file_set_string(settings_file, CONFIG_GROUP, "last_session", groups[session_last]);

		// window position and size
		gtk_window_get_position((GtkWindow*) main_window, &root_x, &root_y);
		gtk_window_get_size((GtkWindow*) main_window, &width, &height);
		g_key_file_set_integer(settings_file, CONFIG_GROUP, "root_x", root_x);
		g_key_file_set_integer(settings_file, CONFIG_GROUP, "root_y", root_y);
		g_key_file_set_integer(settings_file, CONFIG_GROUP, "width", width);
		g_key_file_set_integer(settings_file, CONFIG_GROUP, "height", height);
	}

	// save specific session
	stmp = gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) main, "text_source"));
	g_key_file_set_string(settings_file, session, "text_source", stmp);
	stmp = gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) main, "text_dest"));
	g_key_file_set_string(settings_file, session, "text_dest", stmp);
	stmp = gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) main, "entry_additional"));
	g_key_file_set_string(settings_file, session, "text_addit", stmp);
	stmp = gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) main, "entry_com_before"));
	g_key_file_set_string(settings_file, session, "text_com_before", stmp);
	stmp = gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) main, "entry_com_after"));
	g_key_file_set_string(settings_file, session, "text_com_after", stmp);

	g_key_file_set_boolean(settings_file, session, "check_time", get_checkbox(main, "check_time"));
	g_key_file_set_boolean(settings_file, session, "check_perm", get_checkbox(main, "check_perm"));
	g_key_file_set_boolean(settings_file, session, "check_owner", get_checkbox(main, "check_owner"));
	g_key_file_set_boolean(settings_file, session, "check_group", get_checkbox(main, "check_group"));
	g_key_file_set_boolean(settings_file, session, "check_onefs", get_checkbox(main, "check_onefs"));
	g_key_file_set_boolean(settings_file, session, "check_verbose", get_checkbox(main, "check_verbose"));
	g_key_file_set_boolean(settings_file, session, "check_progr", get_checkbox(main, "check_progr"));
	g_key_file_set_boolean(settings_file, session, "check_delete", get_checkbox(main, "check_delete"));
	g_key_file_set_boolean(settings_file, session, "check_exist", get_checkbox(main, "check_exist"));
	g_key_file_set_boolean(settings_file, session, "check_size", get_checkbox(main, "check_size"));
	g_key_file_set_boolean(settings_file, session, "check_skipnew", get_checkbox(main, "check_skipnew"));
	g_key_file_set_boolean(settings_file, session, "check_windows", get_checkbox(main, "check_windows"));

	g_key_file_set_boolean(settings_file, session, "check_sum", get_checkbox(main, "check_sum"));
	g_key_file_set_boolean(settings_file, session, "check_symlink", get_checkbox(main, "check_symlink"));
	g_key_file_set_boolean(settings_file, session, "check_dev", get_checkbox(main, "check_dev"));
	g_key_file_set_boolean(settings_file, session, "check_update", get_checkbox(main, "check_update"));
	g_key_file_set_boolean(settings_file, session, "check_keepart", get_checkbox(main, "check_keepart"));
	g_key_file_set_boolean(settings_file, session, "check_mapuser", get_checkbox(main, "check_mapuser"));
	g_key_file_set_boolean(settings_file, session, "check_compr", get_checkbox(main, "check_compr"));
	g_key_file_set_boolean(settings_file, session, "check_backup", get_checkbox(main, "check_backup"));

	g_key_file_set_boolean(settings_file, session, "check_com_before", get_checkbox(main, "check_com_before"));
	g_key_file_set_boolean(settings_file, session, "check_com_after", get_checkbox(main, "check_com_after"));
	g_key_file_set_boolean(settings_file, session, "check_browse_files", get_checkbox(main, "check_browse_files"));

	key_data = g_key_file_to_data(settings_file, NULL, &error_handler);
	key_file = fopen(settings_file_name, "w");
	if (key_file != NULL) {
		fputs(key_data, key_file);
		fclose(key_file);
	} else {
		g_printf(_("\tUnable to save settings!\n"));
	}

	g_key_file_free(settings_file);
	g_clear_error(&error_handler);
}


int compare_strings (char **p1, char **p2) {
	return strcoll (*p1, *p2);
}


gboolean load_groups(GtkWidget* main, gchar *session) {
	gchar settings_file_path[MAXPATH], *stmp;
	g_sprintf(settings_file_path, "%s/%s", grsync_dir, "grsync.ini");

	if (g_file_test(settings_file_path, G_FILE_TEST_EXISTS)) {
		GError *error_handler = NULL;
		GKeyFile *settings_file;
		GtkComboBox *combo;
		gint i;
		gboolean flag = FALSE;

		combo = (GtkComboBox*) lookup_widget(main, "combo_session");
//		while (i = gtk_combo_box_get_active(combo) != -1) gtk_combo_box_remove_text(combo, i);
		for (i = 0; i < session_number; i++) gtk_combo_box_remove_text(combo, 0);

		settings_file = g_key_file_new();
		g_key_file_load_from_file(settings_file, settings_file_path, 	G_KEY_FILE_NONE, &error_handler);
		groups = g_key_file_get_groups(settings_file, &session_number);

		if (!cmdline_session && first_load_groups && g_key_file_get_boolean(settings_file, CONFIG_GROUP, "remember", NULL)) {
			stmp = g_key_file_get_string(settings_file, CONFIG_GROUP, "last_session", NULL);
			if (stmp != NULL) {
				session = stmp;
				g_free(argv_session);
				argv_session = g_strconcat(session, NULL);
			}
			first_load_groups = FALSE;
		}

		i = 0;
		while (groups[i] != NULL) {
			if (strcmp(groups[i], CONFIG_GROUP) == 0) {
				session_number--;
				g_free(groups[i]);
				flag = TRUE;
			} else {
				if (i > 0 && flag) groups[i - 1] = groups[i];
			}
			i++;
		}
		groups[session_number] = NULL;
		qsort(groups, session_number, sizeof(gchar*), compare_strings);

		i = 0;
		while (groups[i] != NULL) {
			gtk_combo_box_insert_text(combo, i, groups[i]);
			if (strcmp(groups[i], session) == 0) {
				gtk_combo_box_set_active(combo, i);
				session_last = i;
			}
			i++;
		}

		g_key_file_free (settings_file);
		g_clear_error (&error_handler);
		if (session_last == -1) return FALSE;
	}
/*
	 else {
		g_printf (_("(ERROR) Can't open config file! Maybe this is the first run?\n"));
//		return FALSE;
	}
*/
	return TRUE;
}


void show_browse_source(GtkButton *button, gpointer user_data) {
	GtkWidget *dialog;
	gint retval;
	gboolean browse_files = get_checkbox((GtkWidget*) main_window, "check_browse_files");
	GtkFileChooserAction action = browse_files ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
	gchar *curr_path = (gchar*) gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) button, "text_source"));
	gchar *curr_folder = g_path_get_dirname(curr_path);
		
	dialog = gtk_file_chooser_dialog_new (_("Browse"), (GtkWindow*) main_window, action,
		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), curr_folder);
	if (browse_files) gtk_file_chooser_select_filename(GTK_FILE_CHOOSER (dialog), curr_path);

	retval = gtk_dialog_run (GTK_DIALOG (dialog));
	if (retval == GTK_RESPONSE_ACCEPT || retval == GTK_RESPONSE_OK) {
		gchar *filename, *tmp;
		filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
		tmp = g_strconcat(filename, browse_files ? "" : "/", NULL);
		gtk_entry_set_text((GtkEntry*) lookup_widget((GtkWidget*) button, "text_source"), tmp);
		g_free(filename);
		g_free(tmp);
	}
	gtk_widget_destroy (dialog);
	g_free(curr_folder);
}


void show_browse_dest(GtkButton *button, gpointer user_data) {
	GtkWidget *dialog;
	gint retval;
	gboolean browse_files = get_checkbox((GtkWidget*) main_window, "check_browse_files");
	GtkFileChooserAction action = browse_files ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
	gchar *curr_path = (gchar*) gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) button, "text_dest"));
	gchar *curr_folder = g_path_get_dirname(curr_path);
		
	dialog = gtk_file_chooser_dialog_new (_("Browse"), (GtkWindow*) main_window, action,
		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), curr_folder);
	if (browse_files) gtk_file_chooser_select_filename(GTK_FILE_CHOOSER (dialog), curr_path);

	retval = gtk_dialog_run (GTK_DIALOG (dialog));
	if (retval == GTK_RESPONSE_ACCEPT || retval == GTK_RESPONSE_OK) {
		gchar *filename, *tmp;
		filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
		tmp = g_strconcat(filename, browse_files ? "" : "/", NULL);
		gtk_entry_set_text((GtkEntry*) lookup_widget((GtkWidget*) button, "text_dest"), tmp);
		g_free (filename);
		g_free(tmp);
	}
	gtk_widget_destroy (dialog);
	g_free(curr_folder);
}


void on_play_clicked(GtkButton *button, gpointer user_data) {
	gint i = 0, j, argc_tmp;
	gchar **argv_tmp, *gtmp;

	argv = g_new(gchar *, MAXOPT);
	argv_tmp = g_new(gchar *, MAXOPT);
	argv[i++] = config_command;
	argv[i++] = "-r";

	if (dryrunning) argv[i++] = "-n";
	if (get_checkbox(button, "check_time")) argv[i++] = "-t";
	if (get_checkbox(button, "check_perm")) argv[i++] = "-p";
	if (get_checkbox(button, "check_owner")) argv[i++] = "-o";
	if (get_checkbox(button, "check_group")) argv[i++] = "-g";
	if (get_checkbox(button, "check_onefs")) argv[i++] = "-x";
	if (get_checkbox(button, "check_verbose")) argv[i++] = "-v";
	if (get_checkbox(button, "check_progr")) argv[i++] = "--progress";
	if (get_checkbox(button, "check_delete")) argv[i++] = "--delete";
	if (get_checkbox(button, "check_exist")) argv[i++] = "--ignore-existing";
	if (get_checkbox(button, "check_size")) argv[i++] = "--size-only";
	if (get_checkbox(button, "check_skipnew")) argv[i++] = "-u";
	if (get_checkbox(button, "check_windows")) argv[i++] = "--modify-window=1";

	if (get_checkbox(button, "check_sum")) argv[i++] = "-c";
	if (get_checkbox(button, "check_symlink")) argv[i++] = "-l";
	if (get_checkbox(button, "check_dev")) argv[i++] = "-D";
	if (get_checkbox(button, "check_update")) argv[i++] = "--existing";
	if (get_checkbox(button, "check_keepart")) argv[i++] = "--partial";
	if (get_checkbox(button, "check_mapuser")) argv[i++] = "--numeric-ids";
	if (get_checkbox(button, "check_compr")) argv[i++] = "-z";
	if (get_checkbox(button, "check_backup")) argv[i++] = "-b";

	gtmp = (gchar*) gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) button, "entry_additional"));
	if (gtmp[0]) {
		g_shell_parse_argv(gtmp, &argc_tmp, &argv_tmp, NULL);
		for (j = 0; j < argc_tmp && i + 3 < MAXOPT; j++) argv[i++] = g_strconcat(argv_tmp[j], NULL);
		g_strfreev(argv_tmp);
	}
	// source, dest and NULL must follow only, or change the previous for cicle ending condition.

	argv[i++] = (gchar*) gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) button, "text_source"));
	argv[i++] = (gchar*) gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) button, "text_dest"));
	argv[i++] = NULL;

	paused = FALSE;
	rsync = create_dialog_rsync();
	gtk_window_set_transient_for((GtkWindow*) rsync, (GtkWindow*) main_window);
	if (config_output || dryrunning) {
		gtk_expander_set_expanded((GtkExpander*) lookup_widget((GtkWidget*) rsync, "expander_rsync"), TRUE);
	}
	if (config_errorlist) error_list = g_strconcat("", NULL);
	if (config_log) {
		gtmp = g_strconcat(grsync_dir, "/", groups[session_last], ".log", NULL);
		log_file = fopen(gtmp, "w");
		g_free(gtmp);
	}

	gtk_widget_show(rsync);
	gtk_window_set_title((GtkWindow*)rsync, "rsync: running");
	if (dryrunning) gtk_label_set_text((GtkLabel*)lookup_widget((GtkWidget*) rsync, "label_file"), _("Simulation in progress"));
}


void on_dryrun_clicked (GtkButton *button, gpointer user_data) {
	dryrunning = TRUE;
	on_play_clicked(button, NULL);
}


void set_tooltip(GtkTooltips *tooltips, gchar *long_opt, gchar *widget_str) {
	gchar *tmpc, *tmpc2, *out, *opt;
	GtkWidget *widget;
	GtkTooltipsData *oldtip;

	opt = rsync_man != NULL ? g_strconcat(long_opt, "\n", NULL) : g_strconcat(long_opt, " ", NULL);
	out = rsync_man != NULL ? g_strconcat(rsync_man, NULL) : g_strconcat(rsync_help, NULL);
	tmpc = g_strrstr(out, opt);
//	tmpc = g_strstr_len(out, strlen(out), opt);

	if (tmpc != NULL && *tmpc) {
		while (*tmpc != '\n') tmpc--;
		tmpc++;
		tmpc2 = rsync_man != NULL ? strstr(tmpc, "\n\n\n") : strchr(tmpc, '\n');
		*tmpc2 = '\0';
		g_strstrip(tmpc);

		widget = (GtkWidget*) lookup_widget((GtkWidget*) main_window, widget_str);
		oldtip = gtk_tooltips_data_get(widget);

		if (oldtip != NULL) tmpc2 = g_strconcat(tmpc, "\n\n", oldtip->tip_text, NULL);
		else tmpc2 = g_strconcat(tmpc, NULL);
		gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), widget, tmpc2, "");
		g_free(tmpc2);
	}
	g_free(opt);
	g_free(out);
}


void on_main_create(GtkWindow *window, gpointer user_data) {
	GtkWidget *error;
	gchar *stmp, *tmpc;
	GtkTooltips *rsync_tips;

	grsync_dir = g_strconcat(g_get_home_dir(), "/.grsync", NULL);

	if (!load_groups((GtkWidget*) window, argv_session)) {
		error = gtk_message_dialog_new(window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CANCEL,
			_("The session you specified on the command line doesn't exists"));
		gtk_dialog_run(GTK_DIALOG(error));
		gtk_widget_destroy(error);
		g_free(argv_session);
		argv_session = g_strconcat("default", NULL);
		load_groups((GtkWidget*) window, argv_session);
	}
	load_settings((GtkWidget*) window, argv_session, NULL);

	stmp = g_strconcat(config_command, " --help", NULL);
	if (!g_spawn_command_line_sync(stmp, &rsync_help, NULL, NULL, NULL)) {
		error = gtk_message_dialog_new(window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CANCEL,
			_("Unable to execute the rsync command line tool. It is needed by this program. You may need to install the rsync package or make it available in the default executable search PATH. See file/preferences to change the default rsync executable command."));
		gtk_dialog_run(GTK_DIALOG(error));
		gtk_widget_destroy(error);
	} else {
//		g_spawn_command_line_sync("man rsync", &rsync_man, NULL, NULL, NULL);
		rsync_tips = gtk_tooltips_new();
		set_tooltip(rsync_tips, "--times", "check_time");
		set_tooltip(rsync_tips, "--perms", "check_perm");
		set_tooltip(rsync_tips, "--owner", "check_owner");
		set_tooltip(rsync_tips, "--group", "check_group");
		set_tooltip(rsync_tips, "--one-file-system", "check_onefs");
		set_tooltip(rsync_tips, "--verbose", "check_verbose");
		set_tooltip(rsync_tips, "--progress", "check_progr");
		set_tooltip(rsync_tips, "--delete", "check_delete");
		set_tooltip(rsync_tips, "--ignore-existing", "check_exist");
		set_tooltip(rsync_tips, "--size-only", "check_size");
		set_tooltip(rsync_tips, "--update", "check_skipnew");
		set_tooltip(rsync_tips, "--modify-window=NUM", "check_windows");

		set_tooltip(rsync_tips, "--checksum", "check_sum");
		set_tooltip(rsync_tips, "--links", "check_symlink");
		set_tooltip(rsync_tips, "-D", "check_dev");
		set_tooltip(rsync_tips, "--existing", "check_update");
		set_tooltip(rsync_tips, "--partial", "check_keepart");
		set_tooltip(rsync_tips, "--numeric-ids", "check_mapuser");
		set_tooltip(rsync_tips, "--compress", "check_compr");
		set_tooltip(rsync_tips, "--backup", "check_backup");
	}
	g_free(stmp);
	if (cmdline_execute) on_play_clicked((GtkButton*) window, NULL);
}


void on_main_destroy(GtkObject *object, gpointer user_data) {
	gint sel = gtk_combo_box_get_active((GtkComboBox*) lookup_widget((GtkWidget*) object, "combo_session"));
	save_settings((GtkWidget*) object, groups[sel], NULL);
	g_strfreev(groups);
	if (rsync_help != NULL) g_free(rsync_help);
	if (rsync_man != NULL) g_free(rsync_man);
	gtk_main_quit();
}


void on_close_clicked(GtkButton *button, gpointer user_data) {
	if (rsync_pid) {
		if (paused) kill(rsync_pid, SIGCONT);
		kill(rsync_pid, SIGTERM);
		gtk_widget_set_sensitive(lookup_widget((GtkWidget*) button, "button_pause"), FALSE);
	} else {
		gtk_widget_destroy(rsync);
		set_main_title(groups[session_last], NULL);
		rsync = NULL;
	}
	if (cmdline_execute) on_main_destroy((GtkObject*) main_window, NULL);
}


void set_global_progress(GtkProgressBar* progr, gdouble fraction) {
	GTimeVal curtime;
	glong elapsed, remaining;
	gchar tmps[50];

	gtk_progress_bar_set_fraction(progr, fraction);
	g_get_current_time(&curtime);
	elapsed = curtime.tv_sec - startime.tv_sec;
	remaining = elapsed / fraction - elapsed;
	snprintf(tmps, 49, _("%.f%% (%li:%02li elapsed, %li:%02li remaining)"), round(fraction * 100), elapsed / 60, elapsed % 60,
		remaining / 60, remaining % 60);
	gtk_progress_bar_set_text(progr, tmps);

	set_main_title(groups[session_last], tmps);
}


void scroll_to_end(GtkTextView* view) {
	GtkTextBuffer *buffer;
	GtkTextIter iter;
	GtkTextMark *mark;

	buffer = gtk_text_view_get_buffer(view);
	gtk_text_buffer_get_end_iter(buffer, &iter);
	mark = gtk_text_buffer_create_mark(buffer, "end_mark", &iter, TRUE);
	gtk_text_view_scroll_mark_onscreen(view, mark);
	gtk_text_buffer_delete_mark(buffer, mark);
}


void rsync_cleanup(gpointer data) {
	gchar tmps[50];
	GTimeVal curtime;
	glong elapsed;
	GtkWidget *errors;
	GtkTextBuffer *buffer;
	GtkTextView *view;
	GtkTextIter iter;
	GtkTextTag *tag;
	gchar *comm_str, *comm_out, *comm_err, *comm_after;

	if (channel_closed) {
		view = (GtkTextView*) lookup_widget((GtkWidget*) data, "textview_output");

		if (get_checkbox((GtkWidget*) main_window, "check_com_after")) {
			comm_str = (gchar*) gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) main_window, "entry_com_after"));
			if (!g_spawn_command_line_sync(comm_str, &comm_out, &comm_err, NULL, NULL)) {
				comm_out = g_strconcat("", NULL);
				comm_err = g_strconcat("Error launching command!\n", NULL);
			}
			comm_after = g_strconcat("\n", _("*** Launching AFTER command:\n"), comm_str, "\n", comm_out, comm_err, NULL);
			g_free(comm_out);
			g_free(comm_err);

			buffer = gtk_text_view_get_buffer(view);
			gtk_text_buffer_insert_at_cursor(buffer, comm_after, -1);
			scroll_to_end(view);
			if (config_log) fputs(comm_after, log_file);
			g_free(comm_after);
		}	

		gtk_button_set_label((GtkButton*) lookup_widget((GtkWidget*) data, "close"), "gtk-close");

		GtkLabel *tmpl = (GtkLabel*) lookup_widget((GtkWidget*) data, "label_file");
		if (had_error) {
			gtk_label_set_markup(tmpl, _("<span foreground=\"red\" weight=\"bold\">Completed with errors!</span>"));
		} else {
			gtk_label_set_markup(tmpl, _("<span foreground=\"darkgreen\" weight=\"bold\">Completed successfully!</span>"));
			set_global_progress((GtkProgressBar*) lookup_widget((GtkWidget*) data, "progress_global"), 1);
		}
		gtk_widget_set_sensitive(lookup_widget((GtkWidget*) data, "button_pause"), FALSE);
		gtk_widget_set_sensitive((GtkWidget*) view, TRUE);
		gtk_window_set_title((GtkWindow*) rsync, "rsync: stopped");

		g_spawn_close_pid(rsync_pid);
		rsync_pid = 0;
		g_free(argv);

		if (config_errorlist && had_error) {
			errors = create_dialog_errors();
			gtk_window_set_transient_for((GtkWindow*) errors, (GtkWindow*) rsync);
			buffer = gtk_text_view_get_buffer((GtkTextView*) lookup_widget(errors, "textview_errors"));
			tag = gtk_text_buffer_create_tag(buffer, "fore-red", "foreground", "red", NULL);
			gtk_text_buffer_get_start_iter(buffer, &iter);
			gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, error_list, -1, "fore-red", NULL);
			gtk_widget_show(errors);
			g_free(error_list);
		}
		dryrunning = FALSE;
		
		if (cmdline_execute) on_close_clicked((GtkButton*) data, NULL);
	} else {
		channel_closed = TRUE;
	}
}


gboolean out_watch(GIOChannel *source, GIOCondition condition, gpointer data) {
	GtkTextBuffer *buffer;
	GtkTextIter iter, iter2;
	GString *str;
	GtkProgressBar *tmpp;
	static gchar *carriage = NULL, *oldfile = NULL;
	gchar *file, tmps[50];
	gdouble fraction, done, total;

	if (condition & G_IO_IN) {
		buffer = gtk_text_view_get_buffer((GtkTextView*)data);

		if (carriage != NULL) {
			gtk_text_buffer_get_iter_at_line(buffer, &iter, gtk_text_buffer_get_line_count(buffer) - 2);
			gtk_text_buffer_get_end_iter(buffer, &iter2);
			gtk_text_buffer_delete(buffer, &iter, &iter2);
		}

		str = g_string_new("");
		g_io_channel_read_line_string(source, str, NULL, NULL);
		carriage = strchr(str->str, '\r');

		gtk_text_buffer_insert_at_cursor(buffer, (gchar*)str->str, -1);
		scroll_to_end((GtkTextView*)data);
		if (config_log) fputs((gchar*)str->str, log_file);

		if (!dryrunning) {
			if (strchr(str->str, '%') && str->str[0] == ' ') {
				if (oldfile != NULL) file = g_strconcat(oldfile, NULL);
				else file = g_strconcat(str->str, NULL);
	
				fraction = g_ascii_strtod(strchr(strchr(str->str, '%') - 4, ' '), NULL) / 100;
				tmpp = (GtkProgressBar*)lookup_widget((GtkWidget*) data, "progress_file");
				gtk_progress_bar_set_fraction(tmpp, fraction);
				snprintf(tmps, 5, "%.f%%", round(fraction * 100));
				gtk_progress_bar_set_text(tmpp, tmps);

				fraction = 0;
				if (strchr(str->str, '%') != strrchr(str->str, '%')) fraction = g_ascii_strtod(strchr(strrchr(str->str, '%') - 6, ' '), NULL) / 100;
				else if (strchr(str->str, '=')) {
					total = g_ascii_strtod(strrchr(str->str, '/') + 1, NULL);
					done = total - g_ascii_strtod(strrchr(str->str, '=') + 1, NULL);
					fraction = done / total;
				}

				if (fraction) set_global_progress((GtkProgressBar*)lookup_widget((GtkWidget*) data, "progress_global"), fraction);
			} else {
				file = g_strconcat(str->str, NULL);
				if (oldfile != NULL) g_free(oldfile);
				oldfile = g_strconcat(str->str, NULL);
			}
			g_strchomp(file);
			if (file[0] != 0) gtk_label_set_text((GtkLabel*)lookup_widget((GtkWidget*) data, "label_file"), file);
			g_free(file);
		}

		g_string_free(str, TRUE);
	} else {
//	if (condition & G_IO_HUP || condition & G_IO_ERR) {
		g_io_channel_shutdown (source, FALSE, NULL);
		g_io_channel_unref (source);
		rsync_cleanup(data);

		if (oldfile != NULL) g_free(oldfile);
		oldfile = NULL;
		return FALSE;
	}
	return TRUE;
}


gboolean err_watch(GIOChannel *source, GIOCondition condition, gpointer data) {
	GtkTextBuffer *buffer;
	GtkTextIter iter;
//	GIOStatus status;
	GString *str;
	gchar *tmpc;

	if (condition & G_IO_IN) {
		buffer = gtk_text_view_get_buffer((GtkTextView*)data);
		str = g_string_new("");

		g_io_channel_read_line_string(source, str, NULL, NULL);
		if (str->len > 2) had_error = TRUE;

	//	if (status == G_IO_STATUS_NORMAL) {
		gtk_text_buffer_get_end_iter(buffer, &iter);
		gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, (gchar*)str->str, -1, "fore-red", NULL);
		scroll_to_end((GtkTextView*)data);
	//	}

		if (config_log) {
			// fputs("*ERROR* ", log_file);
			fputs((gchar*)str->str, log_file);
		}

		tmpc = g_strconcat(error_list, str->str, NULL);
		g_free(error_list);
		error_list = tmpc;
		g_string_free(str, TRUE);
	} else {
//	if (condition & G_IO_HUP || condition & G_IO_ERR) {
		g_io_channel_shutdown (source, FALSE, NULL);
		g_io_channel_unref (source);
		rsync_cleanup(data);
		return FALSE;
	}
	return TRUE;
}


void on_rsync_show(GtkWidget *widget, gpointer user_data) {
	gint out, err, i;
//	gint bogus;
	GtkTextBuffer *buffer;
	GtkTextView *view;
	GIOChannel *chout, *cherr;
	GtkTextTag *tag;
	GtkWidget *error;
	gchar *comm_str, *comm_text, *comm_out, *comm_err, *comm_before, *tmpc;

	rsync_pid = 0;
	had_error = FALSE;
	gtk_label_set_ellipsize((GtkLabel*)lookup_widget(widget, "label_file"), PANGO_ELLIPSIZE_MIDDLE);
	
	if (get_checkbox((GtkWidget*) main_window, "check_com_before")) {
		comm_str = (gchar*) gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) main_window, "entry_com_before"));
		if (!g_spawn_command_line_sync(comm_str, &comm_out, &comm_err, NULL, NULL)) {
			comm_out = g_strconcat("", NULL);
			comm_err = g_strconcat("Error launching command!\n", NULL);
		}
		comm_before = g_strconcat(_("*** Launching BEFORE command:\n"), comm_str, "\n", comm_out, comm_err, "\n", NULL);
		g_free(comm_out);
		g_free(comm_err);
	} else {
		comm_before = g_strconcat("", NULL);
	}
	
	comm_str = g_strjoinv(" ", argv);
	if (dryrunning) tmpc =_("*** Launching RSYNC command (simulation mode):\n");
	else tmpc = _("*** Launching RSYNC command:\n");
	comm_text = g_strconcat(comm_before, tmpc, comm_str, "\n\n", NULL);
	g_free(comm_before);
	g_free(comm_str);

	view = (GtkTextView*)lookup_widget(widget, "textview_output");
	buffer = gtk_text_view_get_buffer(view);
	gtk_text_buffer_insert_at_cursor(buffer, comm_text, -1);
	if (config_log) fputs(comm_text, log_file);
	g_free(comm_text);
//	gtk_widget_get_size_request((GtkWidget*) lookup_widget(widget, "scrolled1"), &bogus, &height_expander);
	g_get_current_time(&startime);

	if (g_spawn_async_with_pipes(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &rsync_pid, NULL, &out, &err, NULL)) {
		chout = g_io_channel_unix_new (out);
		cherr = g_io_channel_unix_new (err);
		g_io_channel_set_flags(chout, G_IO_FLAG_NONBLOCK, NULL);
		g_io_channel_set_flags(cherr, G_IO_FLAG_NONBLOCK, NULL);
//	g_io_channel_set_buffer_size(chout, 32);
//	g_io_channel_set_encoding(chout, NULL, NULL); g_io_channel_set_buffered(chout, FALSE);

		tag = gtk_text_buffer_create_tag(buffer, "fore-red", "foreground", "red", NULL);
		channel_closed = FALSE;
		g_io_add_watch_full(chout, G_PRIORITY_DEFAULT_IDLE, G_IO_IN | G_IO_HUP | G_IO_ERR, out_watch, view, NULL);
		g_io_add_watch_full(cherr, G_PRIORITY_DEFAULT_IDLE, G_IO_IN | G_IO_HUP | G_IO_ERR, err_watch, view, NULL);
	} else {
		gtk_button_set_label((GtkButton*)lookup_widget(widget, "close"), "gtk-close");
		gtk_widget_set_sensitive(lookup_widget(widget, "button_pause"), FALSE);
		error = gtk_message_dialog_new((GtkWindow*) main_window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CANCEL,
			_("Cannot execute rsync"));
		gtk_dialog_run(GTK_DIALOG(error));
		gtk_widget_destroy(error);
	}
}

void on_rsync_destroy(GtkObject *object, gpointer user_data) {
	if (rsync_pid) {
		if (paused) kill(rsync_pid, SIGCONT);
		kill(rsync_pid, SIGTERM);
	}
	if (log_file != NULL) {
		fclose(log_file);
		log_file = NULL;
	}
}


void on_combo_session_changed (GtkComboBox *combobox, gpointer user_data) {
	gint sel = gtk_combo_box_get_active((GtkComboBox*) lookup_widget((GtkWidget*) combobox, "combo_session"));
	if (session_last != -1 && sel != session_last) {
		save_settings((GtkWidget*) combobox, groups[session_last], NULL);
		session_last = sel;
		load_settings((GtkWidget*) combobox, groups[session_last], NULL);
	}
}


void on_session_add_clicked(GtkButton *button, gpointer user_data) {
	GtkWidget *add, *confirm;
	gint result, i = 0;

	add = create_dialog_new_session();
	gtk_window_set_transient_for((GtkWindow*) add, (GtkWindow*) main_window);
	result = gtk_dialog_run ((GtkDialog*) add);

	if (result == GTK_RESPONSE_OK) {
		gchar *newses;
		newses = (gchar*) gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) add, "entry_session_name"));

		if (strcmp(CONFIG_GROUP, newses) == 0) {
			confirm = gtk_message_dialog_new((GtkWindow*) main_window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
				GTK_BUTTONS_CANCEL, _("This session name is reserved, you cannot call it like this"));
			gtk_dialog_run(GTK_DIALOG(confirm));
			gtk_widget_destroy(confirm);
			gtk_widget_destroy(add);
			return;
		}

		while (groups[i] != NULL && strcmp(groups[i], newses)) i++;
		if (groups[i] != NULL) {
			confirm = gtk_message_dialog_new((GtkWindow*) main_window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
				GTK_BUTTONS_CANCEL, _("A session named like this already exists"));
			gtk_dialog_run(GTK_DIALOG(confirm));
			gtk_widget_destroy(confirm);
			gtk_widget_destroy(add);
			return;
		}

		save_settings((GtkWidget*) button, newses, NULL);
		session_number++;
		load_groups((GtkWidget*) button, newses);
	}
	gtk_widget_destroy(add);
}


void on_session_del_clicked(GtkButton *button, gpointer user_data) {
	gchar settings_file_name[MAXPATH];
	gchar *key_data;
	FILE *key_file;
	GError *error_handler = NULL;
	GKeyFile *settings_file;
	gint i, result;
	GtkWidget *confirm;

	i = gtk_combo_box_get_active((GtkComboBox*) lookup_widget((GtkWidget*) button, "combo_session"));
	if (strcmp(groups[i], "default") == 0) {
		confirm = gtk_message_dialog_new((GtkWindow*) main_window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
			GTK_BUTTONS_CANCEL, _("You cannot delete the default session"));
		gtk_dialog_run(GTK_DIALOG(confirm));
		gtk_widget_destroy(confirm);
		return;
	}

	confirm = gtk_message_dialog_new((GtkWindow*) main_window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
		GTK_BUTTONS_OK_CANCEL, _("Are you sure you want to delete the '%s' session?"), groups[i]);
	result = gtk_dialog_run(GTK_DIALOG(confirm));
	gtk_widget_destroy(confirm);

	if (result == GTK_RESPONSE_OK) {
		g_sprintf(settings_file_name, "%s/%s", grsync_dir, "grsync.ini");
		settings_file = g_key_file_new();
		g_key_file_load_from_file(settings_file, settings_file_name, G_KEY_FILE_NONE, NULL);
		g_key_file_remove_group(settings_file, groups[i], &error_handler);

		key_data = g_key_file_to_data(settings_file, NULL, &error_handler);
		key_file = fopen(settings_file_name, "w");
		if (key_file != NULL) {
			fputs(key_data, key_file);
			fclose(key_file);
		} else {
			g_printf(_("\tUnable to save settings!\n"));
		}

		g_key_file_free(settings_file);
		g_clear_error(&error_handler);
		session_last = -1;
		load_groups((GtkWidget*) button, "default");
		load_settings((GtkWidget*) button, "default", NULL);
	}
}


void on_button_about_clicked(GtkButton *button, gpointer user_data) {
//	GtkWidget *about = gtk_about_dialog_new();
	GdkPixbuf *pixbuf;
	pixbuf = create_pixbuf("grsync.png");
	gtk_show_about_dialog((GtkWindow*) main_window, "name", PACKAGE, "version", VERSION, "logo", pixbuf, "comments", _("A GTK GUI for rsync"),
		"copyright", _("(C) Piero Orsoni and others. Released under the GPL.\nSee AUTHORS and COPYING for details"),
		"website", "http://www.opbyte.it/grsync/", NULL);
	gdk_pixbuf_unref(pixbuf);
}


void on_button_switch_clicked (GtkButton *button, gpointer user_data) {
	const gchar *tmps, *tmpd;
	gchar *tmp;
	tmps = gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) button, "text_source"));
	tmpd = gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) button, "text_dest"));
	tmp = g_strconcat(tmps, NULL);
	gtk_entry_set_text((GtkEntry*) lookup_widget((GtkWidget*) button, "text_source"), tmpd);
	gtk_entry_set_text((GtkEntry*) lookup_widget((GtkWidget*) button, "text_dest"), tmp);
	g_free(tmp);
}


void on_button_pause_clicked(GtkButton *button, gpointer user_data) {
	GtkButton *tmpbutt = (GtkButton*)lookup_widget((GtkWidget*) button, "button_pause");
	GTimeVal tmptime;
	if (paused) {
		if (rsync_pid) kill(rsync_pid, SIGCONT);
		gtk_button_set_label(tmpbutt, "gtk-media-pause");
		gtk_window_set_title((GtkWindow*)rsync, "rsync: running");
		g_get_current_time(&tmptime);
		startime.tv_sec += tmptime.tv_sec - pausedtime.tv_sec;
		startime.tv_usec += tmptime.tv_usec - pausedtime.tv_usec;
	} else {
		if (rsync_pid) kill(rsync_pid, SIGSTOP);
		gtk_button_set_label(tmpbutt, "gtk-media-play");
		gtk_window_set_title((GtkWindow*)rsync, "rsync: paused");
		g_get_current_time(&pausedtime);
	}
	paused = !paused;
}


void on_preferences1_activate(GtkMenuItem *menuitem, gpointer user_data) {
	GtkWidget *config;
	gint result;

	config = create_dialog_config();
	gtk_window_set_transient_for((GtkWindow*) config, (GtkWindow*) main_window);
	gtk_entry_set_text((GtkEntry*) lookup_widget((GtkWidget*) config, "entry_command"), config_command);
	set_checkbox(config, "check_output", config_output);
	set_checkbox(config, "check_remember", config_remember);
	set_checkbox(config, "check_errorlist", config_errorlist);
	set_checkbox(config, "check_log", config_log);

	result = gtk_dialog_run((GtkDialog*) config);
	if (result == GTK_RESPONSE_OK) {
		strncpy(config_command, gtk_entry_get_text((GtkEntry*) lookup_widget((GtkWidget*) config, "entry_command")), MAXPATH - 1);
		config_output = get_checkbox(config, "check_output");
		config_remember = get_checkbox(config, "check_remember");
		config_errorlist = get_checkbox(config, "check_errorlist");
		config_log = get_checkbox(config, "check_log");
	}

	gtk_widget_destroy(config);
}


void on_rsync_info_activate(GtkMenuItem *menuitem, gpointer user_data) {
	GtkWidget *dialog;
	gchar *tmps, *result;

	tmps = g_strconcat(config_command, " --version", NULL);
	g_spawn_command_line_sync(tmps, &result, NULL, NULL, NULL);
	dialog = gtk_message_dialog_new((GtkWindow*) main_window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, result);
	gtk_dialog_run(GTK_DIALOG(dialog));

	gtk_widget_destroy(dialog);
	g_free(tmps);
	g_free(result);
}


void on_import1_activate(GtkMenuItem *menuitem, gpointer user_data) {
	GtkWidget *dialog, *dialog2;
	gint retval, i;
		
	dialog = gtk_file_chooser_dialog_new (_("Browse"), (GtkWindow*) main_window, GTK_FILE_CHOOSER_ACTION_OPEN,
		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
	retval = gtk_dialog_run (GTK_DIALOG (dialog));
	if (retval == GTK_RESPONSE_ACCEPT || retval == GTK_RESPONSE_OK) {
		gchar *filename;
		filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
		load_settings((GtkWidget*) menuitem, NULL, filename);

		dialog2 = gtk_message_dialog_new((GtkWindow*) main_window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
			_("Session imported"));
		gtk_dialog_run(GTK_DIALOG(dialog2));
		gtk_widget_destroy(dialog2);
		g_free(filename);
	}
	gtk_widget_destroy (dialog);
}


void on_export1_activate (GtkMenuItem *menuitem, gpointer user_data) {
	GtkWidget *dialog, *dialog2;
	gchar *filename;
	gint retval, i;
		
	i = gtk_combo_box_get_active((GtkComboBox*) lookup_widget((GtkWidget*) menuitem, "combo_session"));
	dialog = gtk_file_chooser_dialog_new (_("Browse"), (GtkWindow*) main_window, GTK_FILE_CHOOSER_ACTION_SAVE,
		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
	filename = g_strconcat(groups[i], ".grsync", NULL);
	gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), filename);
	g_free(filename);

	retval = gtk_dialog_run (GTK_DIALOG (dialog));
	if (retval == GTK_RESPONSE_ACCEPT || retval == GTK_RESPONSE_OK) {
		filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
		save_settings((GtkWidget*) menuitem, groups[i], filename);

		dialog2 = gtk_message_dialog_new((GtkWindow*) main_window, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
			_("Session exported"));
		gtk_dialog_run(GTK_DIALOG(dialog2));
		gtk_widget_destroy(dialog2);
		g_free(filename);
	}
	gtk_widget_destroy (dialog);
}


syntax highlighted by Code2HTML, v. 0.9.1