/*
 * gsdlg.c - Simple GTK dialog wrapper
 *
 * Copyright 2007-2008 Jeff Pohlmeyer <yetanothergeek(at)gmail(dot)com>
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#ifndef GSDLG_ALL_IN_ONE
#include "gsdlg.h"
#endif

#include <stdlib.h>

#include "geanyplugin.h"
/* we need tm_get_real_path(), and we can't include glspi.h for those, so hack */
extern GeanyFunctions *glspi_geany_functions;
#define geany_functions glspi_geany_functions


#define TextKey "gsdlg_TextKey_bc4871f4e3478ab5234e28432460a6b8"
#define DataKey "gsdlg_DataKey_bc4871f4e3478ab5234e28432460a6b8"


static void destroy_slist_and_data(gpointer list)
{
	GSList*p;
	for (p=list; p ; p=p->next) {
		if (p->data) g_free(p->data);
		p->data=NULL;
	}
	g_slist_free(list);
}



void gsdlg_textarea(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
{
	GtkWidget*tv;
	GtkWidget*sw;
	GtkWidget*frm;
	g_return_if_fail(dlg);
	tv=gtk_text_view_new();
	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(tv),GTK_WRAP_WORD_CHAR);
	gtk_text_view_set_accepts_tab(GTK_TEXT_VIEW(tv),FALSE);
	if (value) {
		GtkTextBuffer *tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tv));
		gtk_text_buffer_set_text (tb, value, -1);
	}
	sw=gtk_scrolled_window_new(NULL, NULL);
	gtk_widget_set_size_request(sw, gdk_screen_get_width(gdk_screen_get_default())/3,
		gdk_screen_get_height(gdk_screen_get_default())/10);
	gtk_container_add(GTK_CONTAINER(sw),tv);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
	frm=gtk_frame_new(label);
	gtk_frame_set_shadow_type(GTK_FRAME(frm), GTK_SHADOW_ETCHED_IN);
	gtk_container_add(GTK_CONTAINER(frm),sw);
	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dlg)),frm);
	g_object_set_data_full(G_OBJECT(tv), TextKey, g_strdup(key), g_free);
}



static void make_modal(GtkWidget *w, GtkWidget*p)
{
	gtk_window_set_modal(GTK_WINDOW(w), TRUE);
	gtk_window_set_transient_for(GTK_WINDOW(w),GTK_WINDOW(p));
}



static void  file_dlg_map(GtkWidget *w, gpointer user_data)
{
	GtkWidget* entry=gtk_window_get_focus (GTK_WINDOW(w));
	if (entry && GTK_IS_ENTRY(entry)) {
		gtk_entry_set_text(GTK_ENTRY(entry), (gchar*)user_data);
	}
}



static void file_btn_clicked(GtkButton *button, gpointer user_data)
{
	GtkWidget*dlg;
	const gchar *fn=NULL;
	gchar *bn=NULL;
	gint resp;
	dlg=gtk_file_chooser_dialog_new(_("Open file"),
				gsdlg_toplevel,	GTK_FILE_CHOOSER_ACTION_OPEN,
				GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
				GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,	NULL);
	gtk_window_set_title(GTK_WINDOW(dlg), _("Select file"));
	make_modal(dlg, gtk_widget_get_toplevel(GTK_WIDGET(user_data)));
	fn=gtk_entry_get_text(GTK_ENTRY(user_data));
	if (fn && *fn) {
		if (g_file_test(fn,G_FILE_TEST_IS_REGULAR)) {
			gchar *rp=tm_get_real_path(fn);
			gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dlg), rp);
			if (rp) g_free(rp);
		} else {
			if (g_file_test(fn,G_FILE_TEST_IS_DIR)) {
				gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dlg), fn);
			} else {
				gchar *dn=g_path_get_dirname(fn);
				if (g_file_test(dn,G_FILE_TEST_IS_DIR)) {
					gchar *rp=tm_get_real_path(dn);
					gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dlg), rp);
					if (rp) g_free(rp);
					bn=g_path_get_basename(fn);
					g_signal_connect(G_OBJECT(dlg), "map", G_CALLBACK(file_dlg_map), bn);
				}
				g_free(dn);
			}
		}
	}
	resp=gtk_dialog_run(GTK_DIALOG(dlg));
	if (resp == GTK_RESPONSE_ACCEPT) {
		gchar *fcfn=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg));
		if (fcfn) {
			gtk_entry_set_text(GTK_ENTRY(user_data), fcfn);
			g_free(fcfn);
		}
	}
	gtk_widget_destroy(dlg);
	if (bn) { g_free(bn); }
}



void gsdlg_file(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
{
	GtkWidget *hbox;
	GtkWidget *input;
	GtkWidget*frm;
	GtkWidget*btn;
	g_return_if_fail(dlg);
	input=gtk_entry_new();
	if (value) { gtk_entry_set_text(GTK_ENTRY(input),value); }
	btn=gtk_button_new_with_label(_("Browse..."));
	g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(file_btn_clicked), input);
	hbox=gtk_hbox_new(FALSE,FALSE);
	gtk_box_pack_start(GTK_BOX(hbox), input,TRUE,TRUE,1);
	gtk_box_pack_start(GTK_BOX(hbox), btn,FALSE,FALSE,1);
	frm=gtk_frame_new(label);
	gtk_frame_set_shadow_type(GTK_FRAME(frm), GTK_SHADOW_ETCHED_IN);
	gtk_container_add(GTK_CONTAINER(frm),hbox);
	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dlg)),frm);
	g_object_set_data_full(G_OBJECT(input), TextKey, g_strdup(key), g_free);
}



static void color_btn_clicked(GtkButton *button, gpointer user_data)
{
	GtkWidget*dlg;
	GtkColorSelectionDialog *csdlg;
	const gchar *cn=NULL;
	gint resp;
	GdkColor rgb;

	dlg=gtk_color_selection_dialog_new (_("Select Color"));
	csdlg=GTK_COLOR_SELECTION_DIALOG(dlg);
	make_modal(dlg, gtk_widget_get_toplevel(GTK_WIDGET(user_data)));
	cn=gtk_entry_get_text(GTK_ENTRY(user_data));
	if (cn && *cn && gdk_color_parse(cn,&rgb)) {
		gtk_color_selection_set_current_color(
			GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(csdlg)), &rgb);
	}
	resp=gtk_dialog_run(GTK_DIALOG(dlg));
	if (resp == GTK_RESPONSE_OK) {
		gchar *rv=NULL;
		gtk_color_selection_get_current_color(
			GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(csdlg)), &rgb);
		rv=g_strdup_printf("#%2.2X%2.2X%2.2X",rgb.red/256,rgb.green/256,rgb.blue/256);
		gtk_entry_set_text(GTK_ENTRY(user_data), rv);
		g_free(rv);
	}
	gtk_widget_destroy(dlg);
}



void gsdlg_color(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr prompt)
{
	GtkWidget *hbox;
	GtkWidget *input;
	GtkWidget *label;
	GtkWidget*btn;
	g_return_if_fail(dlg);
	input=gtk_entry_new();
	if (value) { gtk_entry_set_text(GTK_ENTRY(input),value); }
	btn=gtk_button_new_with_label(_("Choose..."));
	g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(color_btn_clicked), input);
	hbox=gtk_hbox_new(FALSE,FALSE);
	if (prompt) {
		label=gtk_label_new(prompt);
		gtk_box_pack_start(GTK_BOX(hbox), label,FALSE,FALSE,1);
	}
	gtk_box_pack_start(GTK_BOX(hbox), input,TRUE,TRUE,1);
	gtk_box_pack_start(GTK_BOX(hbox), btn,FALSE,FALSE,1);
	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dlg)),hbox);
	g_object_set_data_full(G_OBJECT(input), TextKey, g_strdup(key), g_free);
}



static void font_btn_clicked(GtkButton *button, gpointer user_data)
{
	GtkWidget*dlg;
	const gchar *fn=NULL;
	gint resp;
	fn=gtk_entry_get_text(GTK_ENTRY(user_data));
	dlg=gtk_font_selection_dialog_new(_("Select Font"));
	make_modal(dlg, gtk_widget_get_toplevel(GTK_WIDGET(user_data)));
	if (fn && *fn) {
		gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dlg),fn);
	}
	resp=gtk_dialog_run(GTK_DIALOG(dlg));
	if (resp==GTK_RESPONSE_OK) {
		gchar *gfn=gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dlg));
		if (gfn) {
			gtk_entry_set_text(GTK_ENTRY(user_data), gfn);
			g_free(gfn);
		}
	}
	gtk_widget_destroy(dlg);
}



void gsdlg_font(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr prompt)
{
	GtkWidget *hbox;
	GtkWidget *input;
	GtkWidget *label;
	GtkWidget*btn;
	g_return_if_fail(dlg);
	input=gtk_entry_new();
	if (value) { gtk_entry_set_text(GTK_ENTRY(input),value); }
	btn=gtk_button_new_with_label(_("Select..."));
	g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(font_btn_clicked), input);
	hbox=gtk_hbox_new(FALSE,FALSE);
	if (prompt) {
		label=gtk_label_new(prompt);
		gtk_box_pack_start(GTK_BOX(hbox), label,FALSE,FALSE,1);
	}
	gtk_box_pack_start(GTK_BOX(hbox), input,TRUE,TRUE,1);
	gtk_box_pack_start(GTK_BOX(hbox), btn,FALSE,FALSE,1);
	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dlg)),hbox);
	g_object_set_data_full(G_OBJECT(input), TextKey, g_strdup(key), g_free);
}



static void gsdlg_entry(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr prompt, gboolean masked)
{
	GtkWidget *hbox;
	GtkWidget *input;
	GtkWidget *label;
	g_return_if_fail(dlg);
	input=gtk_entry_new();
	if (value) { gtk_entry_set_text(GTK_ENTRY(input),value); }
	label=gtk_label_new(prompt);
	hbox=gtk_hbox_new(FALSE,FALSE);
	gtk_box_pack_start(GTK_BOX(hbox), label,FALSE,FALSE,1);
	gtk_box_pack_start(GTK_BOX(hbox), input,TRUE,TRUE,1);
	gtk_entry_set_visibility(GTK_ENTRY(input), !masked);
	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dlg)),hbox);
	g_object_set_data_full(G_OBJECT(input), TextKey, g_strdup(key), g_free);
}


void gsdlg_text(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
{
	gsdlg_entry(dlg, key, value, label, FALSE);
}



void gsdlg_password(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
{
	gsdlg_entry(dlg, key, value, label, TRUE);
}


void gsdlg_checkbox(GtkDialog *dlg, GsDlgStr key, gboolean value, GsDlgStr label)
{
	GtkWidget *cb=NULL;
	g_return_if_fail(dlg);
	cb=gtk_check_button_new_with_label(label);
	g_object_set_data_full(G_OBJECT(cb),TextKey,g_strdup(key), g_free);
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cb),value);
	gtk_container_add(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))),cb);
}



typedef struct _KeySearchData {
	const gchar *key;
	GType type;
	GtkWidget*value;
} KeySearchData;



static void find_widget_by_key_cb(GtkWidget *w, gpointer p)
{
	KeySearchData*kv=p;
	if (kv->value) {return;}

	if (G_OBJECT_TYPE(G_OBJECT(w)) == kv->type) {
		gchar*key=g_object_get_data(G_OBJECT(w), TextKey);
		if (key && g_str_equal(kv->key,key)) { kv->value=w;	}
	}
}


static GtkWidget *find_widget_by_key(GtkDialog *dlg, GType type, GsDlgStr key)
{
	KeySearchData kv={NULL,0,NULL};
	g_return_val_if_fail(dlg, NULL);
	kv.key=key;
	kv.type=type;
	gtk_container_foreach(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))),find_widget_by_key_cb,&kv);
	return kv.value;
}


static void select_radio(GtkWidget*parent, GsDlgStr value)
{
	GList *kids=gtk_container_get_children(GTK_CONTAINER(parent));
	if (!kids) { return;}
	if (kids->data && GTK_IS_RADIO_BUTTON(kids->data)) {
		GList *kid=kids;
		for (kid=kids; kid; kid=kid->next) {
			if (kid->data && GTK_IS_RADIO_BUTTON(kid->data)) {
				gchar*kval=g_object_get_data(G_OBJECT(kid->data),TextKey);
				gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(kid->data),
																				kval && g_str_equal(kval,value));
			}
		}
	}
}



void gsdlg_group(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
{
	GtkWidget*frm;
	GtkWidget*vbox;

	g_return_if_fail(dlg);
	frm=find_widget_by_key(dlg,GTK_TYPE_FRAME,key);
	if (frm) {
		vbox=gtk_bin_get_child(GTK_BIN(frm));
		gtk_frame_set_label(GTK_FRAME(frm), label);
	} else {
		frm=gtk_frame_new(label);
		vbox=gtk_vbox_new(FALSE,FALSE);
		gtk_container_add(GTK_CONTAINER(frm),vbox);
		gtk_container_add(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))),frm);
	}

	/* Frame holds keyname, vbox holds default value */
	g_object_set_data_full(G_OBJECT(frm),  TextKey, g_strdup(key), g_free);
	g_object_set_data_full(G_OBJECT(vbox), TextKey, g_strdup(value), g_free);
	select_radio(vbox,value);
}




void gsdlg_radio(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
{
	GtkWidget *frm=NULL;
	GtkWidget *vbox=NULL;
	GList *kids=NULL;
	GtkWidget *rb=NULL;
	gchar *defval;
	g_return_if_fail(dlg);
	frm=find_widget_by_key(dlg,GTK_TYPE_FRAME,key);
	if (frm) {
		vbox=gtk_bin_get_child(GTK_BIN(frm));
		if (vbox) {
		kids=gtk_container_get_children(GTK_CONTAINER(vbox));
		}
	} else {
		gsdlg_group(dlg,key,value,NULL);
		frm=find_widget_by_key(dlg,GTK_TYPE_FRAME,key);
		vbox=gtk_bin_get_child(GTK_BIN(frm));
	}
	if (kids) {
		rb=gtk_radio_button_new_with_label_from_widget (kids->data,label);
		g_list_free(kids);
	} else {
		rb=gtk_radio_button_new_with_label(NULL, label);
	}
	g_object_set_data_full(G_OBJECT(rb),TextKey, g_strdup(value), g_free);
	gtk_container_add(GTK_CONTAINER(vbox), rb);
	defval=g_object_get_data(G_OBJECT(vbox),TextKey);
	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb),
																value && defval && g_str_equal(defval,value));
}




static void select_combo(GtkWidget*parent, GsDlgStr value)
{
	gint n=0;
	GSList*values=g_object_get_data(G_OBJECT(parent), DataKey);
	GSList*v;
	for (v=values; v; v=v->next) {
		if (v->data && g_str_equal(v->data, value)) {break;}
		n++;
	}
	gtk_combo_box_set_active(GTK_COMBO_BOX(parent), n);
}


typedef struct _ComboWidgets {
	GtkWidget *label;
	GtkWidget *combo;
} ComboWidgets;


void gsdlg_select(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
{
	GtkWidget *hbox=NULL;
	ComboWidgets*cw=NULL;
	g_return_if_fail(dlg);
	hbox=find_widget_by_key(dlg,GTK_TYPE_HBOX, key);
	if (hbox) {
		cw=g_object_get_data(G_OBJECT(hbox), DataKey);
		gtk_label_set_text(GTK_LABEL(cw->label), label);
	} else {
		hbox=gtk_hbox_new(FALSE,FALSE);
		cw=g_malloc0(sizeof(ComboWidgets));
		g_object_set_data_full(G_OBJECT(hbox),DataKey,cw,g_free);
		cw->combo=gtk_combo_box_text_new();
		cw->label=gtk_label_new(label);
		gtk_box_pack_start(GTK_BOX(hbox), cw->label,FALSE,FALSE,4);
		gtk_box_pack_start(GTK_BOX(hbox), cw->combo,TRUE,TRUE,1);
		gtk_container_add(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))),hbox);
	}
	/* Hbox holds keyname, combo holds default value */
	g_object_set_data_full(G_OBJECT(hbox),  TextKey, g_strdup(key), g_free);
	g_object_set_data_full(G_OBJECT(cw->combo), TextKey, g_strdup(value), g_free);
	select_combo(cw->combo,value);
}



void gsdlg_option(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
{
	GtkWidget *hbox=NULL;
	GSList *values=NULL;
	ComboWidgets*cw=NULL;
	gchar*defval=NULL;
	g_return_if_fail(dlg);

	hbox=find_widget_by_key(dlg,GTK_TYPE_HBOX, key);
	if (!hbox) {
		gsdlg_select(dlg,key,value,NULL);
		hbox=find_widget_by_key(dlg,GTK_TYPE_HBOX, key);
	}
	cw=g_object_get_data(G_OBJECT(hbox), DataKey);
	values=g_object_steal_data(G_OBJECT(cw->combo), DataKey);
	values=g_slist_append(values, g_strdup(value));
	g_object_set_data_full(G_OBJECT(cw->combo), DataKey, values, destroy_slist_and_data);
	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cw->combo), label);
	defval=g_object_get_data(G_OBJECT(cw->combo), TextKey);
	if (value && defval && g_str_equal(value,defval)) {
		select_combo(cw->combo,value);
	}
}




void gsdlg_label(GtkDialog *dlg, GsDlgStr text)
{
	GtkWidget *lab=NULL;
	g_return_if_fail(dlg);
	lab=gtk_label_new(text);
	gtk_container_add(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))), lab);
	gtk_misc_set_alignment(GTK_MISC(lab), 0.0f, 0.0f);
}



void gsdlg_hr(GtkDialog *dlg)
{
	g_return_if_fail(dlg);
	gtk_container_add(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))), gtk_hseparator_new());
}



void gsdlg_heading(GtkDialog *dlg, GsDlgStr text)
{
	g_return_if_fail(dlg);
	gsdlg_hr(dlg);
	gsdlg_label(dlg,text);
}

GSDLG_API GtkWindow* gsdlg_toplevel=NULL;



GtkDialog *gsdlg_new(GsDlgStr title, GsDlgStr*btns)
{
	gint i;
	GtkDialog *dlg;
	dlg=GTK_DIALOG(gtk_dialog_new());
	if (gsdlg_toplevel) {
		gtk_window_set_destroy_with_parent(GTK_WINDOW(dlg), TRUE);
		gtk_window_set_transient_for(GTK_WINDOW(dlg),gsdlg_toplevel);
		gtk_window_set_modal(GTK_WINDOW(dlg), TRUE);
	}
	for (i=0; btns[i]; i++) {
		gtk_dialog_add_button(GTK_DIALOG(dlg),btns[i],i);
	}
	gtk_box_set_spacing(GTK_BOX(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))), 4);
	gtk_container_set_border_width(GTK_CONTAINER(dlg), 4);
	gtk_window_set_title(GTK_WINDOW(dlg),title);
	return dlg;
}



static void widgets_foreach(GtkWidget *w, gpointer p)
{
	gchar*key=g_object_get_data(G_OBJECT(w),TextKey);
	if (key && *key) {
		const gchar*value=NULL;
		if (GTK_IS_ENTRY(w)) {
			value=gtk_entry_get_text(GTK_ENTRY(w));
		} else if (GTK_IS_RADIO_BUTTON(w)) {
			if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){
				value=key;
				key=g_object_get_data(
						G_OBJECT(gtk_widget_get_parent(gtk_widget_get_parent(w))), TextKey);
			}
		} else if (GTK_IS_CHECK_BUTTON(w)) {
			value=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))?"1":"0";
		} else if (GTK_IS_COMBO_BOX(w)) {
			GSList*values=g_object_get_data(G_OBJECT(w),DataKey);
			key=g_object_get_data(G_OBJECT(gtk_widget_get_parent(w)), TextKey);
			if (values) {
				gint n=gtk_combo_box_get_active(GTK_COMBO_BOX(w));
				if (n>=0) { value=g_slist_nth_data(values, n); }
			}
		} else if (GTK_IS_TEXT_VIEW(w)) {
			GtkTextBuffer *tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w));
			GtkTextIter a,z;
			gtk_text_buffer_get_start_iter(tb,&a);
			gtk_text_buffer_get_end_iter(tb,&z);
			value=gtk_text_buffer_get_text (tb,&a,&z,TRUE);
		}
		if (value&&*value) {
			GHashTable*h=p;
			g_hash_table_insert(h,g_strdup(key),g_strdup(value));
		}
	}
	if (GTK_IS_CONTAINER(w)) {
		gtk_container_foreach(GTK_CONTAINER(w),widgets_foreach,p);
	}
}


static GsDlgRunHook gsdlg_run_hook=NULL;


#ifndef DIALOG_LIB
void gsdlg_set_run_hook(GsDlgRunHook cb)
{
	gsdlg_run_hook=cb;
}
#endif


GHashTable* gsdlg_run(GtkDialog *dlg, gint *btn, gpointer user_data)
{
	GHashTable* results=NULL;
	gint dummy;
	g_return_val_if_fail(dlg, NULL);
	gtk_widget_show_all(GTK_WIDGET(dlg));
	if (!btn) { btn=&dummy; }
	if (gsdlg_run_hook) { gsdlg_run_hook(TRUE,user_data); }
	*btn=gtk_dialog_run(GTK_DIALOG(dlg));
	if (gsdlg_run_hook) { gsdlg_run_hook(FALSE,user_data); }
	if (*btn<0) *btn=-1;
	results=g_hash_table_new_full(g_str_hash,g_str_equal,g_free,g_free);
	gtk_container_foreach(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))),widgets_foreach,results);
	gtk_widget_hide(GTK_WIDGET(dlg));
	return results;
}



