/*
 *  Copyright (C) 2000, 2001, 2002 Marco Pesenti Gritti
 *
 *  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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "prefs-dialog.h"
#include "ephy-dialog.h"
#include "ephy-prefs.h"
#include "ephy-embed-prefs.h"
#include "ephy-shell.h"
#include "ephy-gui.h"
#include "eel-gconf-extensions.h"
#include "language-editor.h"

#include <libgnome/gnome-i18n.h>
#include <gtk/gtkframe.h>
#include <gtk/gtkhbox.h>
#include <gtk/gtkvbox.h>
#include <gtk/gtkradiobutton.h>
#include <gtk/gtktogglebutton.h>
#include <gtk/gtkimage.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkstock.h>
#include <string.h>

static void
prefs_dialog_class_init (PrefsDialogClass *klass);
static void
prefs_dialog_init (PrefsDialog *pd);
static void
prefs_dialog_finalize (GObject *object);

/* Glade callbacks */
void
prefs_proxy_auto_url_reload_cb (GtkWidget *button,
			        EphyDialog *dialog);
void
prefs_clear_memory_cache_button_clicked_cb (GtkWidget *button,
					    gpointer data);
void
prefs_clear_disk_cache_button_clicked_cb (GtkWidget *button,
					  gpointer data);
void
prefs_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer data);
void
fonts_language_optionmenu_changed_cb (GtkWidget *optionmenu, EphyDialog *dialog);
void
prefs_homepage_current_button_clicked_cb (GtkWidget *button,
					  EphyDialog *dialog);
void
prefs_homepage_blank_button_clicked_cb (GtkWidget *button,
					EphyDialog *dialog);
void
prefs_language_more_button_clicked_cb (GtkWidget *button,
				       EphyDialog *dialog);

/* FIXME duped in mozilla/ */
const
char *lang_encode[] =
{
        "x-western",
        "x-central-euro",
        "ja",
        "zh-TW",
        "zh-CN",
        "ko",
        "x-cyrillic",
        "x-baltic",
        "el",
        "tr",
        "x-unicode",
        "th",
        "he",
        "ar"
};

static const
struct
{
	char *name;
	char *code;
}
languages [] =
{
	{ N_("Afrikaans"), "ak" },
	{ N_("Albanian"), "sq" },
	{ N_("Arabic"), "ar" },
	{ N_("Azerbaijani"), "az" },
	{ N_("Basque"), "eu" },
	{ N_("Breton"), "br" },
	{ N_("Bulgarian"), "bg" },
	{ N_("Byelorussian"), "be" },
	{ N_("Catalan"), "ca" },
	{ N_("Chinese"), "zh" },
	{ N_("Croatian"), "hr" },
	{ N_("Czech"), "cs" },
	{ N_("Danish"), "da" },
	{ N_("Dutch"), "nl" },
	{ N_("English"), "en" },
	{ N_("Esperanto"), "eo" },
	{ N_("Estonian"), "et" },
	{ N_("Faeroese"), "fo" },
	{ N_("Finnish"), "fi" },
	{ N_("French"), "fr" },
	{ N_("Galician"), "gl" },
	{ N_("German"), "de" },
	{ N_("Greek"), "el" },
	{ N_("Hebrew"), "he" },
	{ N_("Hungarian"), "hu" },
	{ N_("Icelandic"), "is" },
	{ N_("Indonesian"), "id" },
	{ N_("Irish"), "ga" },
	{ N_("Italian"), "it" },
	{ N_("Japanese"), "ja" },
	{ N_("Korean"), "ko" },
	{ N_("Latvian"), "lv" },
	{ N_("Lithuanian"), "lt" },
	{ N_("Macedonian"), "mk" },
	{ N_("Malay"), "ms" },
	{ N_("Norwegian/Nynorsk"), "nn" },
	{ N_("Norwegian/Bokmaal"), "nb" },
	{ N_("Norwegian"), "no" },
	{ N_("Polish"), "pl" },
	{ N_("Portuguese"), "pt" },
	{ N_("Portuguese of Brazil"), "pt-BR" },
	{ N_("Romanian"), "ro" },
	{ N_("Russian"), "ru" },
	{ N_("Scottish"), "gd" },
	{ N_("Serbian"), "sr" },
	{ N_("Slovak"), "sk" },
	{ N_("Slovenian"), "sl" },
	{ N_("Spanish"), "es" },
	{ N_("Swedish"), "sv" },
	{ N_("Tamil"), "ta" },
	{ N_("Turkish"), "tr" },
	{ N_("Ukrainian"), "uk" },
	{ N_("Vietnamian"), "vi" },
	{ N_("Walloon"), "wa" },
	{ NULL, NULL }
};

enum
{
	FONT_TYPE_SERIF,
	FONT_TYPE_SANSSERIF,
	FONT_TYPE_MONOSPACE
};

const
char *fonts_types[] =
{
	"serif",
	"sans-serif",
	"monospace"
};

enum
{
	FONT_SIZE_FIXED,
	FONT_SIZE_VAR,
	FONT_SIZE_MIN
};

const
char *size_prefs[] =
{
	CONF_RENDERING_FONT_FIXED_SIZE,
	CONF_RENDERING_FONT_VAR_SIZE,
	CONF_RENDERING_FONT_MIN_SIZE
};

enum
{
	WINDOW_PROP,
	NOTEBOOK_PROP,

	/* General */
	OPEN_IN_TABS_PROP,
	HOMEPAGE_ENTRY_PROP,
	NEW_PAGE_PROP,
	AUTOCHARSET_PROP,
	DEFAULT_CHARSET_PROP,
	LANGUAGE_PROP,

	/* Appeareance */
	SERIF_PROP,
	SANSSERIF_PROP,
	MONOSPACE_PROP,
	FIXED_SIZE_PROP,
	VARIABLE_SIZE_PROP,
	MIN_SIZE_PROP,
	PROPORTIONAL_PROP,
	BACKGROUND_PROP,
	TEXT_PROP,
	UNVISITED_PROP,
	VISITED_PROP,
	USE_SYSCOLORS_PROP,
	USE_COLORS_PROP,
	USE_FONTS_PROP,

	/* Security */
	ALLOW_POPUPS_PROP,
	ALLOW_JAVA_PROP,
	ALLOW_JS_PROP,
	ACCEPT_COOKIES_PROP,

	/* Advanced */
	CACHE_COMPARE_PROP,
	DISK_CACHE_PROP,
	MEMORY_CACHE_PROP
};

static const
EphyDialogProperty properties [] =
{
	{ WINDOW_PROP, "prefs_dialog", NULL, PT_NORMAL, NULL },
	{ NOTEBOOK_PROP, "prefs_notebook", NULL, PT_NORMAL, NULL },

	/* General */
	{ OPEN_IN_TABS_PROP, "open_in_tabs_checkbutton", CONF_TABS_TABBED, PT_AUTOAPPLY, NULL },
	{ HOMEPAGE_ENTRY_PROP, "homepage_entry", CONF_GENERAL_HOMEPAGE, PT_AUTOAPPLY, NULL },
	{ NEW_PAGE_PROP, "new_page_show_homepage", CONF_GENERAL_NEWPAGE_TYPE, PT_AUTOAPPLY, NULL },
	{ AUTOCHARSET_PROP, "autocharset_optionmenu", CONF_LANGUAGE_AUTODETECT_CHARSET, PT_AUTOAPPLY, NULL },
	{ DEFAULT_CHARSET_PROP, "default_charset_optionmenu", NULL, PT_NORMAL, NULL },
	{ LANGUAGE_PROP, "language_optionmenu", NULL, PT_NORMAL, NULL },

	/* Appeareance */
	{ SERIF_PROP, "serif_combo", NULL, PT_NORMAL, NULL },
	{ SANSSERIF_PROP, "sansserif_combo", NULL, PT_NORMAL, NULL },
	{ MONOSPACE_PROP, "monospace_combo", NULL, PT_NORMAL, NULL },
	{ FIXED_SIZE_PROP, "fixed_size_spinbutton", NULL, PT_NORMAL, NULL },
	{ VARIABLE_SIZE_PROP, "variable_size_spinbutton", NULL, PT_NORMAL, NULL },
	{ MIN_SIZE_PROP, "min_size_spinbutton", NULL, PT_NORMAL, NULL },
	{ PROPORTIONAL_PROP, "proportional_optionmenu", CONF_RENDERING_DEFAULT_FONT, PT_AUTOAPPLY, NULL },
	{ BACKGROUND_PROP, "background_cpick", CONF_RENDERING_BG_COLOR, PT_AUTOAPPLY, NULL },
	{ TEXT_PROP, "text_cpick", CONF_RENDERING_TEXT_COLOR, PT_AUTOAPPLY, NULL },
	{ UNVISITED_PROP, "unvisited_cpick", CONF_RENDERING_UNVISITED_LINKS, PT_AUTOAPPLY, NULL },
	{ VISITED_PROP, "visited_cpick", CONF_RENDERING_VISITED_LINKS, PT_AUTOAPPLY, NULL },
	{ USE_SYSCOLORS_PROP, "use_syscolors_checkbutton", CONF_RENDERING_USE_SYSTEM_COLORS, PT_AUTOAPPLY, NULL },
	{ USE_COLORS_PROP, "use_colors_checkbutton", CONF_RENDERING_USE_OWN_COLORS, PT_AUTOAPPLY, NULL },
	{ USE_FONTS_PROP, "use_fonts_checkbutton", CONF_RENDERING_USE_OWN_FONTS, PT_AUTOAPPLY, NULL },

	/* Security */
	{ ALLOW_POPUPS_PROP, "popups_allow_checkbutton", CONF_SECURITY_ALLOW_POPUPS, PT_AUTOAPPLY, NULL },
	{ ALLOW_JAVA_PROP, "enable_java_checkbutton", CONF_SECURITY_JAVA_ENABLED, PT_AUTOAPPLY, NULL },
	{ ALLOW_JS_PROP, "enable_javascript_checkbutton", CONF_SECURITY_JAVASCRIPT_ENABLED, PT_AUTOAPPLY, NULL },
	{ ACCEPT_COOKIES_PROP, "cookies_radiobutton", CONF_SECURITY_COOKIES_ACCEPT, PT_AUTOAPPLY, NULL },

	/* Advanced */
	{ CACHE_COMPARE_PROP, "cache_compare_radiobutton", CONF_NETWORK_CACHE_COMPARE, PT_AUTOAPPLY, NULL },
	{ DISK_CACHE_PROP, "disk_cache_spin", CONF_NETWORK_DISK_CACHE, PT_AUTOAPPLY, NULL },
	{ MEMORY_CACHE_PROP, "memory_cache_spin", CONF_NETWORK_MEMORY_CACHE, PT_AUTOAPPLY, NULL },

	{ -1, NULL, NULL }
};

struct PrefsDialogPrivate
{
	GtkWidget *notebook;
	GtkWidget *window;

	int language;
	gboolean switching;
};

static GObjectClass *parent_class = NULL;

GType
prefs_dialog_get_type (void)
{
        static GType prefs_dialog_type = 0;

        if (prefs_dialog_type == 0)
        {
                static const GTypeInfo our_info =
                {
                        sizeof (PrefsDialogClass),
                        NULL, /* base_init */
                        NULL, /* base_finalize */
                        (GClassInitFunc) prefs_dialog_class_init,
                        NULL,
                        NULL, /* class_data */
                        sizeof (PrefsDialog),
                        0, /* n_preallocs */
                        (GInstanceInitFunc) prefs_dialog_init
                };

                prefs_dialog_type = g_type_register_static (EPHY_DIALOG_TYPE,
							    "PrefsDialog",
							    &our_info, 0);
        }

        return prefs_dialog_type;

}

EphyDialog *
prefs_dialog_new (GtkWidget *parent)
{
        EphyDialog *dialog;

        dialog = EPHY_DIALOG (g_object_new (PREFS_DIALOG_TYPE,
					    "ParentWindow", parent,
					    NULL));

        return dialog;
}

static void
prefs_dialog_class_init (PrefsDialogClass *klass)
{
        GObjectClass *object_class = G_OBJECT_CLASS (klass);

        parent_class = g_type_class_peek_parent (klass);

        object_class->finalize = prefs_dialog_finalize;
}

static void
prefs_dialog_finalize (GObject *object)
{
        PrefsDialog *pd;

        g_return_if_fail (object != NULL);
        g_return_if_fail (IS_PREFS_DIALOG (object));

	pd = PREFS_DIALOG (object);

        g_return_if_fail (pd->priv != NULL);

        g_free (pd->priv);

        G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
prefs_dialog_show_help (PrefsDialog *pd)
{
	gint id;

	/* FIXME: Once we actually have documentation we
	 * should point these at the correct links.
	 */
	gchar *help_preferences[] = {
		"setting-preferences",
		"setting-preferences",
		"setting-preferences",
		"setting-preferences"
	};

	id = gtk_notebook_get_current_page (GTK_NOTEBOOK (pd->priv->notebook));

	ephy_gui_help (GTK_WINDOW (pd), "epiphany", help_preferences[id]);
}

static void
setup_font_menu (PrefsDialog *dialog,
		 const char *type,
		 GtkWidget *combo)
{
	char *default_font;
	GList *fonts;
	const char *name;
	char key[255];
	int pos;
	GtkWidget *entry = GTK_COMBO(combo)->entry;
	EphyEmbedSingle *single;

	single = ephy_embed_shell_get_embed_single
		(EPHY_EMBED_SHELL (ephy_shell));

	ephy_embed_single_get_font_list (single,
					 lang_encode[dialog->priv->language],
					 type, &fonts, &default_font);

	/* Get the default font */
	sprintf (key, "%s_%s_%s", CONF_RENDERING_FONT, type,
		 lang_encode[dialog->priv->language]);
	name = eel_gconf_get_string (key);
	if (name == NULL)
	{
		name = default_font;
	}

	/* set popdown doesnt like NULL */
	if (fonts == NULL)
	{
		fonts = g_list_alloc ();
	}

	gtk_combo_set_popdown_strings (GTK_COMBO(combo), fonts);

	/* set the default value */
	if (name != NULL)
	{
		gtk_editable_delete_text (GTK_EDITABLE(entry), 0, -1);
		gtk_editable_insert_text (GTK_EDITABLE(entry),
					  name, g_utf8_strlen (name, -1),
					  &pos);
	}

	g_free (default_font);

	g_list_foreach (fonts, (GFunc)g_free, NULL);
	g_list_free (fonts);
}

static void
save_font_menu (PrefsDialog *dialog,
		int type,
		GtkWidget *entry)
{
	char *name;
	char key[255];

	name = gtk_editable_get_chars
		(GTK_EDITABLE(entry), 0, -1);

	/* do not save empty fonts */
	if (!name || *name == '\0')
	{
		g_free (name);
		return;
	}

	sprintf (key, "%s_%s_%s", CONF_RENDERING_FONT,
		 fonts_types[type],
		 lang_encode[dialog->priv->language]);
	eel_gconf_set_string (key, name);
	g_free (name);
}

static void
font_entry_changed_cb (GtkWidget *entry, PrefsDialog *dialog)
{
	int type;

	if (dialog->priv->switching) return;

	type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT(entry),
						    "type"));
	save_font_menu (dialog, type, entry);
}

static void
attach_font_signal (PrefsDialog *dialog, int prop,
		    gpointer type)
{
	GtkWidget *combo;
	GtkWidget *entry;

	combo = ephy_dialog_get_control (EPHY_DIALOG(dialog),
					   prop);
	entry = GTK_COMBO(combo)->entry;
	g_object_set_data (G_OBJECT(entry), "type", type);
	g_signal_connect (entry, "changed",
			  G_CALLBACK(font_entry_changed_cb),
			  dialog);
}

static void
attach_fonts_signals (PrefsDialog *dialog)
{
	attach_font_signal (dialog, SERIF_PROP,
			    GINT_TO_POINTER(FONT_TYPE_SERIF));
	attach_font_signal (dialog, SANSSERIF_PROP,
			    GINT_TO_POINTER(FONT_TYPE_SANSSERIF));
	attach_font_signal (dialog, MONOSPACE_PROP,
			    GINT_TO_POINTER(FONT_TYPE_MONOSPACE));
}

static void
size_spinbutton_changed_cb (GtkWidget *spin, PrefsDialog *dialog)
{
	int type;
	char key[255];

	if (dialog->priv->switching) return;

	type = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(spin), "type"));

	sprintf (key, "%s_%s",
		 size_prefs[type],
		 lang_encode[dialog->priv->language]);
	eel_gconf_set_integer (key, gtk_spin_button_get_value (GTK_SPIN_BUTTON (spin)));
}

static void
attach_size_controls_signals (PrefsDialog *dialog)
{
	GtkWidget *spin;

	spin = ephy_dialog_get_control (EPHY_DIALOG(dialog),
					  FIXED_SIZE_PROP);
	g_object_set_data (G_OBJECT(spin), "type",
			   GINT_TO_POINTER(FONT_SIZE_FIXED));
	g_signal_connect (spin, "value_changed",
			  G_CALLBACK(size_spinbutton_changed_cb),
			  dialog);

	spin = ephy_dialog_get_control (EPHY_DIALOG(dialog),
					  VARIABLE_SIZE_PROP);
	g_object_set_data (G_OBJECT(spin), "type",
			   GINT_TO_POINTER(FONT_SIZE_VAR));
	g_signal_connect (spin, "value_changed",
			  G_CALLBACK(size_spinbutton_changed_cb),
			  dialog);

	spin = ephy_dialog_get_control (EPHY_DIALOG(dialog),
					  MIN_SIZE_PROP);
	g_object_set_data (G_OBJECT(spin), "type",
			   GINT_TO_POINTER(FONT_SIZE_MIN));
	g_signal_connect (spin, "value_changed",
			  G_CALLBACK(size_spinbutton_changed_cb),
			  dialog);
}

static void
setup_size_control (PrefsDialog *dialog,
		    const char *pref,
		    int default_size,
		    GtkWidget *spin)
{
	char key[255];
	int size;

	sprintf (key, "%s_%s", pref,
		 lang_encode[dialog->priv->language]);
	size = eel_gconf_get_integer (key);

	if (size == 0) size = default_size;

	gtk_spin_button_set_value (GTK_SPIN_BUTTON(spin), size);
}

static void
setup_size_controls (PrefsDialog *dialog)
{
	GtkWidget *spin;

	spin = ephy_dialog_get_control (EPHY_DIALOG(dialog),
					  FIXED_SIZE_PROP);
	setup_size_control (dialog, CONF_RENDERING_FONT_FIXED_SIZE, 12, spin);

	spin = ephy_dialog_get_control (EPHY_DIALOG(dialog),
					  VARIABLE_SIZE_PROP);
	setup_size_control (dialog, CONF_RENDERING_FONT_VAR_SIZE, 16, spin);

	spin = ephy_dialog_get_control (EPHY_DIALOG(dialog),
					  MIN_SIZE_PROP);
	setup_size_control (dialog, CONF_RENDERING_FONT_MIN_SIZE, 0, spin);
}

static void
setup_fonts (PrefsDialog *dialog)
{
	GtkWidget *combo;

	dialog->priv->switching = TRUE;

	combo = ephy_dialog_get_control (EPHY_DIALOG(dialog),
					 SERIF_PROP);
	setup_font_menu (dialog, "serif", combo);

	combo = ephy_dialog_get_control (EPHY_DIALOG(dialog),
					 SANSSERIF_PROP);
	setup_font_menu (dialog, "sans-serif", combo);

	combo = ephy_dialog_get_control (EPHY_DIALOG(dialog),
					 MONOSPACE_PROP);
	setup_font_menu (dialog, "monospace", combo);

	dialog->priv->switching = FALSE;
}

static void
default_charset_menu_changed_cb (GtkOptionMenu *option_menu,
				 EphyEmbedShell *shell)
{
	GList *charsets;
	int i;
	CharsetInfo *info;
	EphyEmbedSingle *single;

	single = ephy_embed_shell_get_embed_single
		(EPHY_EMBED_SHELL (ephy_shell));

	ephy_embed_single_get_charset_titles (single, NULL, &charsets);

	i = gtk_option_menu_get_history (option_menu);
	charsets = g_list_nth (charsets, i);
	g_assert (charsets != NULL);
	info = (CharsetInfo *) charsets->data;
	eel_gconf_set_string (CONF_LANGUAGE_DEFAULT_CHARSET,
			      info->name);

	g_list_free (charsets);
}

static gint
find_charset_in_list_cmp (gconstpointer a,
                          gconstpointer b)
{
	CharsetInfo *info = (CharsetInfo *)a;
	const char *value = b;

	return (strcmp (info->name, value));
}

static void
create_default_charset_menu (PrefsDialog *dialog)
{
	GList *l;
	GList *charsets;
	GtkWidget *menu;
	GtkWidget *optionmenu;
	char *value;
	EphyEmbedSingle *single;

	single = ephy_embed_shell_get_embed_single
		(EPHY_EMBED_SHELL (ephy_shell));

	ephy_embed_single_get_charset_titles (single, NULL, &l);

	menu = gtk_menu_new ();

	optionmenu = ephy_dialog_get_control (EPHY_DIALOG (dialog),
					      DEFAULT_CHARSET_PROP);

	for (charsets = l; charsets != NULL; charsets = charsets->next)
	{
		CharsetInfo *info = (CharsetInfo *) charsets->data;
		GtkWidget *item;

		item = gtk_menu_item_new_with_label (info->title);
		gtk_menu_shell_append (GTK_MENU_SHELL(menu),
				       item);
		gtk_widget_show (item);
	}

	gtk_option_menu_set_menu (GTK_OPTION_MENU(optionmenu), menu);

	/* init value */
	charsets = l;
	value = eel_gconf_get_string (CONF_LANGUAGE_DEFAULT_CHARSET);
	g_return_if_fail (value != NULL);
	charsets = g_list_find_custom (charsets, (gconstpointer)value,
				       (GCompareFunc)find_charset_in_list_cmp);
	gtk_option_menu_set_history (GTK_OPTION_MENU(optionmenu),
				     g_list_position (l, charsets));
	g_free (value);

	g_signal_connect (optionmenu, "changed",
			  G_CALLBACK (default_charset_menu_changed_cb),
			  embed_shell);

	g_list_free (l);
}

static GtkWidget *
general_prefs_new_language_menu (PrefsDialog *dialog)
{
	int i;
	GtkWidget *menu;

	menu = gtk_menu_new ();

	for (i = 0; languages[i].name != NULL; i++)
	{
		GtkWidget *item;

		item = gtk_menu_item_new_with_label (languages[i].name);
		gtk_menu_shell_append (GTK_MENU_SHELL(menu),
				       item);
		gtk_widget_show (item);
		g_object_set_data (G_OBJECT(item), "desc",
				   languages[i].name);
	}

	return menu;
}

static void
language_menu_changed_cb (GtkOptionMenu *option_menu,
		          gpointer data)
{
	GSList *list;
	GSList *l = NULL;
	int history;

	list = eel_gconf_get_string_list (CONF_RENDERING_LANGUAGE);
	l = g_slist_copy (list);

	/* Subst the first item according to the optionmenu */
	history = gtk_option_menu_get_history (option_menu);
	l->data = languages [history].code;

	eel_gconf_set_string_list (CONF_RENDERING_LANGUAGE, l);

	g_slist_free (l);
}

static void
create_language_menu (PrefsDialog *dialog)
{
	GtkWidget *optionmenu;
	GtkWidget *menu;
	const char *value;
	int i;
	GSList *list;

	optionmenu = ephy_dialog_get_control (EPHY_DIALOG (dialog),
					      LANGUAGE_PROP);

	menu = general_prefs_new_language_menu (dialog);

	gtk_option_menu_set_menu (GTK_OPTION_MENU(optionmenu), menu);

	/* init value */
	list = eel_gconf_get_string_list (CONF_RENDERING_LANGUAGE);
	g_return_if_fail (list != NULL);
	value = (const char *)list->data;

	i = 0;
	while (languages[i].code && strcmp (languages[i].code, value) != 0)
	{
		i++;
	}

	gtk_option_menu_set_history (GTK_OPTION_MENU(optionmenu), i);

	g_signal_connect (optionmenu, "changed",
			  G_CALLBACK (language_menu_changed_cb),
			  NULL);
}

static void
set_homepage_entry (EphyDialog *dialog,
		    const char *new_location)
{
	GtkWidget *entry;
	int pos;

	entry = ephy_dialog_get_control (dialog, HOMEPAGE_ENTRY_PROP);

	gtk_editable_delete_text (GTK_EDITABLE (entry), 0, -1);
	gtk_editable_insert_text (GTK_EDITABLE (entry), new_location,
				  g_utf8_strlen (new_location, -1),
				  &pos);
}


static void
prefs_dialog_init (PrefsDialog *pd)
{
	EphyDialog *dialog = EPHY_DIALOG (pd);
	GdkPixbuf *icon;

	pd->priv = g_new0 (PrefsDialogPrivate, 1);

	ephy_dialog_construct (EPHY_DIALOG (pd),
			       properties,
			       "prefs-dialog.glade",
			       "prefs_dialog");

	pd->priv->window = ephy_dialog_get_control (dialog, WINDOW_PROP);
	pd->priv->notebook = ephy_dialog_get_control (dialog, NOTEBOOK_PROP);


	icon = gtk_widget_render_icon (pd->priv->window,
				       GTK_STOCK_PREFERENCES,
				       GTK_ICON_SIZE_MENU,
				       "prefs_dialog");
	gtk_window_set_icon (GTK_WINDOW (pd->priv->window), icon);
	g_object_unref(icon);

	pd->priv->switching = FALSE;
	setup_fonts (pd);
	setup_size_controls (pd);
	attach_fonts_signals (pd);
	attach_size_controls_signals (pd);
	create_default_charset_menu (pd);
	create_language_menu (pd);
}

/* Network page callbacks */

void
prefs_dialog_response_cb (GtkDialog *dialog, gint response_id, gpointer data)
{
	if (response_id == GTK_RESPONSE_CLOSE)
	{
		gtk_widget_destroy (GTK_WIDGET(dialog));
	}
	else if (response_id == GTK_RESPONSE_HELP)
	{
		PrefsDialog *pd = (PrefsDialog *)data;
		prefs_dialog_show_help (pd);
	}
}

void
prefs_clear_memory_cache_button_clicked_cb (GtkWidget *button,
					    gpointer data)
{
	EphyEmbedSingle *single;

	single = ephy_embed_shell_get_embed_single
		(EPHY_EMBED_SHELL (ephy_shell));

	ephy_embed_single_clear_cache (single, MEMORY_CACHE);
}

void
prefs_clear_disk_cache_button_clicked_cb (GtkWidget *button,
					  gpointer data)
{
	EphyEmbedSingle *single;

	single = ephy_embed_shell_get_embed_single
		(EPHY_EMBED_SHELL (ephy_shell));

	ephy_embed_single_clear_cache (single, DISK_CACHE);
}

void
fonts_language_optionmenu_changed_cb (GtkWidget *optionmenu,
				      EphyDialog *dialog)
{
	int i;
	PrefsDialog *pd = PREFS_DIALOG (dialog);

	i = gtk_option_menu_get_history
		(GTK_OPTION_MENU (optionmenu));

	pd->priv->language = i;

	setup_fonts (pd);
	setup_size_controls (pd);
}

void
prefs_homepage_current_button_clicked_cb (GtkWidget *button,
					  EphyDialog *dialog)
{
	EphyWindow *window;
	EphyTab *tab;

	window = ephy_shell_get_active_window (ephy_shell);
	g_return_if_fail (window != NULL);

	tab = ephy_window_get_active_tab (window);
	g_return_if_fail (tab != NULL);

	set_homepage_entry (dialog, ephy_tab_get_location (tab));
}

void
prefs_homepage_blank_button_clicked_cb (GtkWidget *button,
					EphyDialog *dialog)
{
	set_homepage_entry (dialog, "about:blank");
}

static void
fill_language_editor (LanguageEditor *le)
{
	GSList *strings;
	GSList *tmp;
	int i;

	/* Fill the list */
	strings = eel_gconf_get_string_list (CONF_RENDERING_LANGUAGE);

	for (tmp = strings; tmp != NULL; tmp = g_slist_next (tmp))
	{
		char *value = (char *)tmp->data;

		i = 0;
		while (languages[i].code && strcmp (languages[i].code, value) != 0)
		{
			i++;
		}

		/* FIXME unsafe, bad prefs could cause it to access random memory */
		language_editor_add (le, languages[i].name, i);
	}
}

static void
language_dialog_changed_cb (LanguageEditor *le,
			    GSList *list,
			    PrefsDialog *dialog)
{
	GtkWidget *optionmenu;
	const GSList *l;
	GSList *langs = NULL;

	optionmenu = ephy_dialog_get_control (EPHY_DIALOG (dialog),
						LANGUAGE_PROP);
	gtk_option_menu_set_history (GTK_OPTION_MENU(optionmenu),
				     GPOINTER_TO_INT(list->data));

	for (l = list; l != NULL; l = l->next)
	{
		int i = GPOINTER_TO_INT (l->data);
		langs = g_slist_append (langs, languages[i].code);
	}

	eel_gconf_set_string_list (CONF_RENDERING_LANGUAGE, langs);
	g_slist_free (langs);
}

void
prefs_language_more_button_clicked_cb (GtkWidget *button,
				       EphyDialog *dialog)
{
	LanguageEditor *editor;
	GtkWidget *menu;
	GtkWidget *toplevel;

	menu = general_prefs_new_language_menu (PREFS_DIALOG (dialog));

	toplevel = gtk_widget_get_toplevel (button);
	editor = language_editor_new (toplevel);
	language_editor_set_menu (editor, menu);
	fill_language_editor (editor);
	ephy_dialog_set_modal (EPHY_DIALOG(editor), TRUE);

	g_signal_connect (editor, "changed",
			  G_CALLBACK(language_dialog_changed_cb),
			  dialog);

	ephy_dialog_show (EPHY_DIALOG(editor));
}