/*
 *  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.
 */

#include "galeon-shell.h"
#include "galeon-embed-shell.h"
#include "galeon-embed-prefs.h"
#include "eel-gconf-extensions.h"
#include "prefs-strings.h"
#include "bookmarks.h"
#include "xbel.h"
#include "galeon-config.h"
#include "gul-general.h"
#include "galeon-favicon-cache.h"
#include "pixbuf-cache.h"
#include "galeon-bookmarks-icon-provider.h"
#include "gul-filesystem-autocompletion.h"
#include "galeon-window.h"
#include "galeon-automation.h"
#include "hig-alert.h"
#include "migrate.h"
#include "galeon-debug.h"

#include <libgnomeui/gnome-client.h>
#include <bonobo/bonobo-main.h>
#include <glib/gi18n.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkmain.h>
#include <gtk/gtkmessagedialog.h>
#include <gconf/gconf-client.h>

#ifdef ENABLE_NAUTILUS_VIEW

#include <bonobo/bonobo-generic-factory.h>
#include "galeon-nautilus-view.h"

#define GALEON_NAUTILUS_VIEW_OAFIID "OAFIID:GNOME_Galeon_NautilusViewFactory"

#endif

struct GaleonShellPrivate
{
	GbBookmarkSet *bookmark_set;
	GaleonEmbedShell *embed_shell;
	Session *session;
	GaleonFaviconCache *favicon_cache;
	GaleonAutocompletion *autocompletion;
	GaleonWindow *active_window;
	EggToolbarsModel *toolbars_model;
	gboolean server_mode;
	BonoboGenericFactory *automation_factory;
};

enum
{
        STARTPAGE_HOME,
        STARTPAGE_LAST,
        STARTPAGE_BLANK,
};

static void
galeon_shell_class_init (GaleonShellClass *klass);
static void
galeon_shell_init (GaleonShell *gs);
static void
galeon_shell_finalize (GObject *object);
static void 
galeon_init_services (GaleonShell *gs);

#ifdef ENABLE_NAUTILUS_VIEW

static void 
galeon_nautilus_view_init_factory (GaleonShell *gs);
static BonoboObject *
galeon_nautilus_view_new (BonoboGenericFactory *factory, 
			  const char *id, 
			  GaleonShell *gs);

#endif

static void bookmarks_init (GaleonShell *gs);

static GObjectClass *parent_class = NULL;

GaleonShell *galeon_shell;

GType 
galeon_shell_get_type (void)
{
        static GType galeon_shell_type = 0;

        if (galeon_shell_type == 0)
        {
                static const GTypeInfo our_info =
                {
                        sizeof (GaleonShellClass),
                        NULL, /* base_init */
                        NULL, /* base_finalize */
                        (GClassInitFunc) galeon_shell_class_init,
                        NULL,
                        NULL, /* class_data */
                        sizeof (GaleonShell),
                        0, /* n_preallocs */
                        (GInstanceInitFunc) galeon_shell_init
                };

                galeon_shell_type = g_type_register_static (G_TYPE_OBJECT,
							    "GaleonShell",
							    &our_info, 0);
        }

        return galeon_shell_type;

}

static void
galeon_shell_class_init (GaleonShellClass *klass)
{
        GObjectClass *object_class = G_OBJECT_CLASS (klass);

        parent_class = g_type_class_peek_parent (klass);

        object_class->finalize = galeon_shell_finalize;
}

static void
galeon_shell_new_window_cb (GaleonEmbedShell *shell, 
			    GaleonEmbed **new_embed,
                            EmbedChromeMask chromemask,
			    gpointer data)
{
	GaleonTab *new_tab;
        GaleonWindow *window;
	gboolean open_in_tab;

	g_assert (new_embed != NULL);

	open_in_tab = (chromemask & EMBED_CHROME_OPENASCHROME) ?
		      FALSE :
		      eel_gconf_get_boolean (CONF_TABS_TABBED_POPUPS);

	if (open_in_tab)
	{
		window = galeon_shell_get_active_window (galeon_shell);
	}
	else
	{
		window = galeon_window_new ();
		galeon_window_set_chrome (window, chromemask);
	}
	
	new_tab = galeon_tab_new ();
	galeon_window_add_tab (window, new_tab,
			       GALEON_WINDOW_ADD_TAB_LAST, FALSE);
	*new_embed = galeon_tab_get_embed (new_tab);
}

static void
galeon_shell_init (GaleonShell *gs)
{
	gboolean ret;
	GConfSchema *schema;

	galeon_shell = gs;
	g_object_add_weak_pointer (G_OBJECT(galeon_shell),
				   (gpointer)&galeon_shell);
	
	gul_pixbuf_cache_register_stocks ();
	
        gs->priv = g_new0 (GaleonShellPrivate, 1);
	gs->priv->session     = NULL;
	gs->priv->server_mode = FALSE;

	gs->priv->automation_factory = galeon_automation_factory_new ();
	if (gs->priv->automation_factory == NULL)
	{
		GtkWidget *dialog;
		char * text;

		dialog = hig_alert_new (NULL,
					GTK_DIALOG_MODAL,
					HIG_ALERT_ERROR,
					_("Galeon failed to start."),
					NULL,
					GTK_STOCK_OK,
					GTK_RESPONSE_OK,
					NULL);
		text = g_strdup_printf (_("Bonobo couldn't locate the file %s."),
			                "<tt>\"GNOME_Galeon_Automation.server\"</tt>");
		hig_alert_set_secondary_printf (HIG_ALERT (dialog), "%s\n\n%s", text,
			      _("Usually this is an indication of an incomplete installation. "
				"See the INSTALL document for more details."));
		g_free (text);

		gtk_dialog_run (GTK_DIALOG (dialog));
		exit (1);
	}

	/* Check the gconf installation */
	schema = gconf_client_get_schema (eel_gconf_client_get_global (),
					  "/schemas" CONF_TABS_TABBED_EDGE, NULL);
	if (!schema)
	{
		GtkWidget *dialog;
		dialog = hig_alert_new (NULL,
					GTK_DIALOG_MODAL,
					HIG_ALERT_ERROR,
					_("Galeon failed to start."),
					_("The gconf schema couldn't be found.\n\n"
					  "This shouldn't generally happen, but can usually "
					  "be fixed by running <tt>\"galeon-config-tool "
					  "--install-schemas\"</tt>."),
					GTK_STOCK_OK,
					GTK_RESPONSE_OK,
					NULL);
		gtk_dialog_run (GTK_DIALOG (dialog));
		gtk_widget_destroy (GTK_WIDGET (dialog));
		exit(1);
	}
	gconf_schema_free (schema);


#ifdef ENABLE_GTKHTML_EMBED
	gs->priv->embed_shell = galeon_embed_shell_new ("gtkhtml");	
#elif ENABLE_MOZILLA_EMBED
	gs->priv->embed_shell = galeon_embed_shell_new ("mozilla");	
#endif
	g_assert (gs->priv->embed_shell != NULL);

	/* Now that we have all the important stuff created, migrate any
	 * preferences, this MUST be done before the shell_initialize, as the
	 * font migrations need the embed_shell, but need to happen before the
	 * shell is initialized, when they will get used */
	migrate_gconf_settings ();

	ret = galeon_embed_shell_initialize (gs->priv->embed_shell);
	if (ret == FALSE)
	{
		GtkWidget *dialog;

		dialog = hig_alert_new (NULL, GTK_DIALOG_MODAL,
					HIG_ALERT_ERROR,
					_("Galeon failed to start."),
					NULL,
					GTK_STOCK_OK, GTK_RESPONSE_OK,
					NULL);
		
		hig_alert_set_secondary_printf (HIG_ALERT (dialog),
				_("Ensure the %s environment variable is set "
				  "to the correct Mozilla installation "
				  "directory."),
				"<tt>\"MOZILLA_FIVE_HOME\"</tt>");

		gtk_dialog_run (GTK_DIALOG (dialog));
		exit (1);
	}

	g_signal_connect (G_OBJECT(embed_shell),
			  "new_window_orphan",
			  G_CALLBACK(galeon_shell_new_window_cb),
			  NULL);
	
	gs->priv->favicon_cache = galeon_favicon_cache_new ();

	galeon_init_services (gs);
}

static void
galeon_shell_finalize (GObject *object)
{
        GaleonShell *gs;

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

	gs = GALEON_SHELL (object);

        g_return_if_fail (gs->priv != NULL);

	g_assert (galeon_shell == NULL);
	
	g_return_if_fail (IS_GALEON_EMBED_SHELL (gs->priv->embed_shell));
	g_object_unref (G_OBJECT (gs->priv->embed_shell));

	if (gs->priv->session)
	{
		g_return_if_fail (IS_SESSION(gs->priv->session));
		g_object_remove_weak_pointer 
			(G_OBJECT(gs->priv->session),
                         (gpointer *)&gs->priv->session);
		g_object_unref (G_OBJECT (gs->priv->session));
	}

	if (gs->priv->autocompletion)
	{
		g_object_unref (gs->priv->autocompletion);
	}

	if (gs->priv->toolbars_model)
	{
		gchar *tb_file = g_build_filename (g_get_home_dir (), GALEON_DIR, "toolbars.xml", NULL);
		egg_toolbars_model_save (gs->priv->toolbars_model, tb_file, "0");
		g_free (tb_file);
		g_object_unref (gs->priv->toolbars_model);
	}

	g_return_if_fail (GALEON_IS_FAVICON_CACHE(gs->priv->favicon_cache));
	g_object_unref (G_OBJECT (gs->priv->favicon_cache));

	g_return_if_fail (GB_IS_BOOKMARK_SET(gs->priv->bookmark_set));
	gb_bookmark_set_check_save (gs->priv->bookmark_set);
	g_object_unref (G_OBJECT (gs->priv->bookmark_set));
	
        G_OBJECT_CLASS (parent_class)->finalize (object);

	LOG ("Galeon shell finalized");

	if (gs->priv->automation_factory)
	{
		bonobo_object_unref (gs->priv->automation_factory);
	}
	
	g_free (gs->priv);

	bonobo_main_quit ();

	LOG ("Bonobo quit done");
}

GaleonShell *
galeon_shell_new (void)
{
	return GALEON_SHELL (g_object_new (GALEON_SHELL_TYPE, NULL));
}

/**
 * galeon_shell_get_embed_shell:
 * @gs: a #GaleonShell
 *
 * Returns the embed shell created by the #GaleonShell
 *
 * Return value: the embed shell
 **/
GaleonEmbedShell *
galeon_shell_get_embed_shell (GaleonShell *gs)
{
	g_return_val_if_fail (IS_GALEON_SHELL (gs), NULL);

	return gs->priv->embed_shell;
}


static void
galeon_init_services (GaleonShell *gs)
{
	/* preload the prefs */
	/* it also enables notifiers support */
	eel_gconf_monitor_add ("/apps/galeon");
	eel_gconf_monitor_add ("/apps/nautilus/preferences");
	eel_gconf_monitor_add ("/system/proxy");

	bookmarks_init (gs);

#ifdef ENABLE_NAUTILUS_VIEW
	
	galeon_nautilus_view_init_factory (gs);
	
#endif

}

static void
load_homepage (GaleonShell *gs, 
	       GaleonEmbed *embed, 
	       GaleonEmbed *previous_embed)
{
        const gchar *last_page_url;
        gint page_type;
	char *result = NULL;
	
        /* find out where we're supposed to start */
	page_type = eel_gconf_get_integer (CONF_GENERAL_NEWPAGE_TYPE);

        /* return the appropriate page */
        if (page_type == STARTPAGE_HOME)
        {
                /* get location of home page */
                result = eel_gconf_get_string(CONF_GENERAL_HOMEPAGE);
		if (result != NULL)
		{
			result = g_strstrip (result);
		}
        }
	else if (page_type == STARTPAGE_LAST)
	{
		GlobalHistory *gh;

		if (previous_embed != NULL)
		{
			galeon_embed_copy_page (embed, previous_embed, 
					        DISPLAY_NORMAL);
			return;
		}

		/* get location of last page */
		gh = galeon_embed_shell_get_global_history 
			(gs->priv->embed_shell);
		last_page_url = global_history_get_last_page (gh);
		result = g_strdup (last_page_url);
	}

	/* empty URL equals to about:blank */
	if (result != NULL && *result == '\0')
	{
		g_free (result);
		result = NULL;
	}

	if (result == NULL)
	{
		/* even in case of error, it's a good default */
        	result = g_strdup ("about:blank");
	}

	galeon_embed_load_url (embed, result);

	g_free (result);
}

/**
 * galeon_shell_set_active_window:
 * @gs: a #GaleonShell
 * @window: the active #GaleonWindow
 *
 * Set the active window. Not really useful standalone, but called
 * from a focus handler in GaleonWindow so the active window is
 * always tracked
 **/

void
galeon_shell_set_active_window (GaleonShell *gs, GaleonWindow *window)
{
	gs->priv->active_window = window;
}

/**
 * galeon_shell_get_active_window:
 * @gs: a #GaleonShell
 *
 * Get the current active window. Use it when you
 * need to take an action (like opening an url) on
 * a window but you dont have a target window.
 * Ex. open a new tab from command line.
 *
 * Return value: the current active window 
 **/
GaleonWindow *
galeon_shell_get_active_window (GaleonShell *gs)
{
	GList *windows = session_get_windows(gs->priv->session);
	if (windows &&
	    !g_list_find(windows, gs->priv->active_window))
	{
		gs->priv->active_window = GALEON_WINDOW(windows->data);
	}
	else if (!windows)
	{
		/* The case where we're in server mode with
		 * no windows open
		 */
		gs->priv->active_window = NULL;
	}

	return gs->priv->active_window;
}

/**
 * galeon_shell_new_tab:
 * @shell: a #GaleonShell
 * @parent_window: the target #GaleonWindow or %NULL
 * @previous_tab: the referrer tab or %NULL
 * @url: an url to load or %NULL
 *
 * Create a new tab and the parent window when necessary.
 * Ever use this function to open urls in new window/tabs.
 *
 * ReturnValue: the created #GaleonTab
 **/
GaleonTab *
galeon_shell_new_tab (GaleonShell *shell,
		      GaleonWindow *parent_window,
		      GaleonTab *previous_tab,
		      const char *url,
		      GaleonNewTabFlags flags)
{
	GaleonEmbed * previous_embed = NULL;

	if (previous_tab)
	{
		previous_embed = galeon_tab_get_embed (previous_tab);
	}
	
	return galeon_shell_new_tab_from_embed
		(shell, parent_window, previous_embed, url, flags);
}


/**
 * galeon_shell_new_tab_from_embed:
 * @shell: a #GaleonShell
 * @parent_window: the target #GaleonWindow or %NULL
 * @previous_embed: the referrer embed or %NULL
 * @url: an url to load or %NULL
 *
 * Create a new tab and the parent window when necessary.
 * Ever use this function to open urls in new window/tabs.
 *
 * ReturnValue: the created #GaleonTab
 **/
GaleonTab *
galeon_shell_new_tab_from_embed (GaleonShell *shell,
				 GaleonWindow *parent_window,
				 GaleonEmbed *previous_embed,
				 const char *url,
				 GaleonNewTabFlags flags)
{
	GaleonWindow *window;
	GaleonTab *tab;
	GaleonEmbed *embed;
	gboolean in_new_window;
	gboolean jump_to;
	gint position;
	
	in_new_window = !eel_gconf_get_boolean (CONF_TABS_TABBED);

	if (flags & GALEON_NEW_TAB_IN_NEW_WINDOW) in_new_window = TRUE;
	if (flags & GALEON_NEW_TAB_IN_EXISTING_WINDOW) in_new_window = FALSE;
	
	jump_to = eel_gconf_get_boolean (CONF_TABS_TABBED_AUTOJUMP);
	
	if (flags & GALEON_NEW_TAB_JUMP) jump_to = TRUE;
	if (flags & GALEON_NEW_TAB_DONT_JUMP_TO) jump_to = FALSE;

	if (!in_new_window && parent_window != NULL)
	{
		window = parent_window;
	}
	else
	{
        	window = galeon_window_new ();
	}

	position = (flags & GALEON_NEW_TAB_APPEND) ?
		   GALEON_WINDOW_ADD_TAB_LAST :
		   GALEON_WINDOW_ADD_TAB_GROUPED;

	tab = galeon_tab_new ();
	gtk_widget_show (GTK_WIDGET (tab));
	
	galeon_window_add_tab (window, tab,
			       position,
			       jump_to);
	gtk_widget_show (GTK_WIDGET(window));

	embed = galeon_tab_get_embed (tab);
	if (flags & GALEON_NEW_TAB_HOMEPAGE)
	{
		load_homepage (shell, embed, previous_embed);
	}
	else if ((flags & GALEON_NEW_TAB_IS_A_COPY) ||
		 (flags & GALEON_NEW_TAB_VIEW_SOURCE))
	{
		EmbedDisplayType display_type =
			(flags & GALEON_NEW_TAB_VIEW_SOURCE) ?
			 DISPLAY_AS_SOURCE : DISPLAY_NORMAL;
		g_return_val_if_fail (previous_embed != NULL, tab);
		galeon_embed_copy_page (embed, previous_embed, display_type);
	}
	else if (url)
	{
		galeon_embed_load_url (embed, url);
	}

	if (embed && previous_embed)
	{
		galeon_embed_shistory_copy (previous_embed, embed, TRUE, FALSE, FALSE);
	}

	if (flags & GALEON_NEW_TAB_RAISE_WINDOW)
	{
		gtk_window_present (GTK_WINDOW (window));
	}

	if (flags & GALEON_NEW_TAB_FULLSCREEN)
	{
		gtk_window_fullscreen (GTK_WINDOW (window));
	}

        return tab;
}

#ifdef ENABLE_NAUTILUS_VIEW

static void 
galeon_nautilus_view_init_factory (GaleonShell *gs)
{
	BonoboGenericFactory *galeon_nautilusview_factory;
	galeon_nautilusview_factory = bonobo_generic_factory_new
	       	(GALEON_NAUTILUS_VIEW_OAFIID,
		 (BonoboFactoryCallback) galeon_nautilus_view_new, gs);
	if (!BONOBO_IS_GENERIC_FACTORY (galeon_nautilusview_factory))
		g_warning ("Couldn't create the factory!");

}

static BonoboObject *
galeon_nautilus_view_new (BonoboGenericFactory *factory, const char *id, 
			  GaleonShell *gs)
{
	return galeon_nautilus_view_new_component (gs);
}

#endif

static void
bookmarks_init (GaleonShell *gs)
{
	/* this is temp code, I need to think about how to properly initialize bookmarks */
	GbXBEL *io = gb_xbel_new ();
	gchar *filename = g_strconcat (g_get_home_dir (), "/",
				       GALEON_DIR "/bookmarks.xbel", NULL);
	
	/* init the bookmark icon provider */
	GbGaleonIconProvider *gip = gb_galeon_icon_provider_new ();
	gb_system_set_icon_provider (GB_ICON_PROVIDER (gip));

	LOG ("trying to load bookmarks from %s", filename);
	gs->priv->bookmark_set = gb_io_load_from_file (GB_IO (io), filename);

	if (gs->priv->bookmark_set == NULL)
	{
		gchar *filename2 = gul_general_user_file ("default-bookmarks.xbel", FALSE);
		g_warning ("I could not load the bookmarks file, "
			   "will load the default bookmarks from %s.", filename2);
		if (filename2)
		{
			gs->priv->bookmark_set = gb_io_load_from_file (GB_IO (io), filename2);
		}
		if (gs->priv->bookmark_set == NULL)
		{
			GbFolder *root;
			g_warning ("I could not load the default bookmarks file, "
				   "will create something myself");
			gs->priv->bookmark_set = gb_bookmark_set_new ();
			root = gb_folder_new (gs->priv->bookmark_set, _("Bookmarks"));
			gb_bookmark_set_set_root (gs->priv->bookmark_set, root);
			gb_bookmark_set_set_io (gs->priv->bookmark_set, GB_IO (io));
		}		
		g_free (filename2);
		gb_bookmark_set_set_filename (gs->priv->bookmark_set, filename);
	}

	LOG ("Detected version of bookmarks file: %s", 
		 gs->priv->bookmark_set->file_format_version == GB_FILE_FORMAT_VERSION_GALEON_1 
		 ? "galeon1" 
		 : (gs->priv->bookmark_set->file_format_version == GB_FILE_FORMAT_VERSION_GALEON_2 
		    ? "galeon2" 
		    : "unknown (galeon1)"));

	if (gs->priv->bookmark_set->file_format_version == GB_FILE_FORMAT_VERSION_UNKNOWN)
	{
		GtkWidget *d = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
						       GTK_BUTTONS_YES_NO, 
						       _("A bookmark file that was probably saved by "
							 "Galeon 1 has been found. Galeon 1 saved "
							 "non-ascii chars incorrectly. Do you want to "
							 "try to fix the bookmarks?"));
		GtkResponseType r = gtk_dialog_run (GTK_DIALOG (d));
		if (r == GTK_RESPONSE_YES)
		{		
			gb_bookmark_set_fix_galeon1_mess (gs->priv->bookmark_set);
		}
		gtk_widget_destroy (d);
	}

	if (gs->priv->bookmark_set->file_format_version == GB_FILE_FORMAT_VERSION_GALEON_1)
	{
		gb_bookmark_set_fix_galeon1_mess (gs->priv->bookmark_set);
	}

	gb_bookmark_set_set_auto_save (gs->priv->bookmark_set, 5 * 60 * 1000);

	gb_galeon_icon_provider_add_bookmark_set (gip, gs->priv->bookmark_set);

	g_object_unref (G_OBJECT (gip));
	g_object_unref (G_OBJECT (io));
	g_free (filename);
		
}

/**
 * galeon_shell_get_bookmark_set:
 * @gs: a #GaleonShell
 *
 * Returns the bookmark set
 *
 * Return value: the bookmark set.
 **/
GbBookmarkSet *
galeon_shell_get_bookmark_set (GaleonShell *gs)
{
	return gs->priv->bookmark_set;
}

/**
 * galeon_shell_get_session:
 * @gs: a #GaleonShell
 * 
 * Returns current session.
 *
 * Return value: the current session.
 **/
Session *
galeon_shell_get_session (GaleonShell *gs)
{
	if (!gs->priv->session)
	{
		gs->priv->session = session_new ();
		g_object_add_weak_pointer 
			(G_OBJECT(gs->priv->session),
                         (gpointer *)&gs->priv->session);
	}
	
	return gs->priv->session;
}


/**
 *  galeon_shell_get_server_mode
 * 
 *  @gs: a #GaleonShell
 * 
 *  Returns whether galeon is running in server mode
 *
 *  Return value: TRUE if we are in server mode, FALSE otherwise
 */
gboolean
galeon_shell_get_server_mode (GaleonShell *gs)
{
	return gs->priv->server_mode;
}

/**
 *  galeon_shell_set_server_mode
 * 
 *  @gs: a #GaleonShell
 *  mode: Whether to run in server mode.
 * 
 *  Sets galeon server mode to be true or false
 *
 */
void
galeon_shell_set_server_mode (GaleonShell *gs, gboolean mode)
{
	if (mode && !gs->priv->server_mode)
	{
		g_object_ref (G_OBJECT(gs));
	}
	else if (!mode && gs->priv->server_mode)
	{
		g_object_unref (G_OBJECT(gs));
	}

	gs->priv->server_mode = mode;
}

/**
 * galeon_shell_get_favicon_cache:
 * @gs: a #GaleonShell
 *
 * Returns the favicons cache.
 *
 * Return value: the favicons cache
 **/
GaleonFaviconCache *
galeon_shell_get_favicon_cache (GaleonShell *gs)
{
	return gs->priv->favicon_cache;
}

GaleonAutocompletion *
galeon_shell_get_autocompletion (GaleonShell *gs)
{
	GaleonShellPrivate *p = gs->priv;

	if (!p->autocompletion)
	{
		static const gchar *prefixes[] = {
			GALEON_AUTOCOMPLETION_USUAL_WEB_PREFIXES, 
			NULL 
		};

		GlobalHistory *gh = galeon_embed_shell_get_global_history (gs->priv->embed_shell);
		GulFilesystemAutocompletion *fa = gul_filesystem_autocompletion_new ();
		p->autocompletion = galeon_autocompletion_new ();
		galeon_autocompletion_set_prefixes (p->autocompletion, prefixes);
		
		galeon_autocompletion_add_source (p->autocompletion, 
						  GALEON_AUTOCOMPLETION_SOURCE (gh));
		galeon_autocompletion_add_source (p->autocompletion, 
						  GALEON_AUTOCOMPLETION_SOURCE (p->bookmark_set));
		galeon_autocompletion_add_source (p->autocompletion, 
						  GALEON_AUTOCOMPLETION_SOURCE (fa));
		g_object_unref (fa);
	}
	return p->autocompletion;
}

GaleonNewTabFlags
galeon_shell_modifier_flags (GdkModifierType modifier)
{
	GaleonNewTabFlags flags;
	gboolean jump_to = eel_gconf_get_boolean (CONF_TABS_TABBED_AUTOJUMP);
	gboolean new_tab = eel_gconf_get_boolean (CONF_TABS_TABBED);

	if (modifier & GDK_CONTROL_MASK) jump_to = !jump_to;
	if (modifier & GDK_SHIFT_MASK)   new_tab = !new_tab;

	flags = 0;
	flags |= jump_to ? GALEON_NEW_TAB_JUMP : GALEON_NEW_TAB_DONT_JUMP_TO;
	flags |= new_tab ? GALEON_NEW_TAB_IN_EXISTING_WINDOW : GALEON_NEW_TAB_IN_NEW_WINDOW;

	return flags;
}

EggToolbarsModel *
galeon_shell_get_toolbars_model  (GaleonShell *gs)
{
	if (!gs->priv->toolbars_model)
	{
		gboolean loaded = FALSE;
		EggToolbarsModel *tm = egg_toolbars_model_new ();
		gchar *user_file = gul_general_user_file ("toolbars.xml", FALSE);
		if (user_file)
		{
			loaded = egg_toolbars_model_load (tm, user_file);
			g_free (user_file);
		}

		if (loaded == FALSE)
		{
			gchar *default_file = gul_general_user_file ("galeon-egg-ui-toolbar.xml", TRUE);
			egg_toolbars_model_load (tm, default_file);
			g_free (default_file);
		}
		gs->priv->toolbars_model = tm;
	}
	return gs->priv->toolbars_model;
}

