/*
 *  Copyright (C) 2000 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.
 */

/* Galeon includes */
#include "galeon.h"
#include "toolbar.h"
#include "spinner.h"
#include "misc.h"
#include "window.h"
#include "bookmarks.h"
#include "eel-gconf-extensions.h"
#include "themes.h"

#include <string.h>
#include <gtk/gtkspinbutton.h>
#include <gtk/gtktoolbar.h>
#include <gtk/gtkdnd.h>
#include <libgnome/gnome-util.h>
#include <libgnome/gnome-config.h>
#include <libgnome/gnome-i18n.h>
#include <libgnomeui/gnome-stock.h>
#include <libgnomeui/gnome-app.h>
#include <libgnomeui/gnome-preferences.h>
#include <libgnomeui/gnome-dock.h>
#include <libgnomeui/gnome-entry.h>
#include <gdk-pixbuf/gdk-pixbuf.h>

/* local function prototypes */
static void toolbar_update (GaleonWindow *window);
static void toolbar_create_widgets (GaleonWindow *window, 
				    GtkWidget *hbox, GtkWidget *toolbar,
				    gboolean location_on_main_toolbar);
static void toolbar_create_location_toolbar (GaleonWindow *window,
					     gboolean show);
static void toolbar_create_location_widgets (GaleonWindow *window, 
					     GtkWidget *hbox, 
					     GtkWidget *toolbar);
static void toolbar_create_find_entry (GaleonWindow *window,
				       GtkWidget *toolbar,
				       ToolbarItemType type);
static void toolbar_create_zoom_spin (GaleonWindow *window, 
				      GtkWidget *toolbar);
static void toolbar_create_drag_handle (GaleonWindow *window, 
					GtkWidget *toolbar);
static void toolbar_create_button (GaleonWindow *window, GtkWidget *toolbar,
				   ToolbarItemType type);
static GtkWidget *toolbar_add_docked (GaleonWindow *window, GtkWidget *hbox, 
				      gchar *name, gint band_num);
static void toolbar_set_style (GtkWidget *toolbar, GtkToolbarStyle final_style,
			       GtkReliefStyle relief, GtkToolbarSpaceStyle sep);
static GtkWidget *toolbar_get_theme_pixmap (const ToolbarItem *item);
static void toolbar_create_separator (GtkWidget *toolbar);

/* directory where to load theme pixmaps from */
static gchar *theme = NULL;

/* the widgets created with horizontal styling which size we want to sync
 * later on */
static GList *resized_later = NULL;
static gint button_height = 0;

/* array of available toolbar items */
const ToolbarItem toolbar_items[TOOLBAR_ITEM_COUNT] =
{
	{
		N_("New"), 
		N_("Open new browser"), 
		GNOME_STOCK_PIXMAP_NEW, 
		"New",
		FALSE, /* priority? */
		FALSE,
		100,
		NULL, /* clicked */
		window_new_button_press_cb,
		window_new_button_release_cb,
		window_new_button_drag_data_received_cb
	},
	{
		N_("Back"), 
		N_("Go back - Right button: History"), 
		GNOME_STOCK_PIXMAP_BACK, 
		"Back",
		TRUE, /* priority? */
		FALSE,
		200,
		NULL, /* clicked */
		window_back_forward_button_press_cb,
		window_back_forward_button_release_cb,
		NULL /* drag_data_received */
	},
	{
		N_("Up"), 
		N_("Go up a level from the current location"), 
		GNOME_STOCK_PIXMAP_UP, 
		"Up",
		FALSE, /* priority? */
		FALSE,
		300,
		NULL, /* clicked */
		window_up_button_press_event_cb,
		window_up_button_release_event_cb,
		NULL /* drag_data_received */
	},
	{
		N_("Forward"), 
		N_("Go forward - Right button: History"), 
		GNOME_STOCK_PIXMAP_FORWARD,
		"Forward",
		FALSE, /* priority? */
		FALSE,
		400,
		NULL, /* clicked */
		window_back_forward_button_press_cb,
		window_back_forward_button_release_cb,
		NULL /* drag_data_received */
	},
	{
		N_("Reload"), 
		N_("Display the latest content of the current page"), 
		GNOME_STOCK_PIXMAP_REFRESH, 
		"Refresh",
		FALSE, /* priority? */
		FALSE,
		700,
		NULL,
		window_refresh_button_press_event_cb,
		window_refresh_button_release_event_cb,
		NULL /* drag_data_received */
	},
	{
		N_("Home"), 
		N_("Go to your home page"), 
		GNOME_STOCK_PIXMAP_HOME, 
		"Home",
		TRUE, /* priority? */
		FALSE,
		500,
		NULL, /* clicked */
		window_home_button_press_event_cb,
		window_home_button_release_event_cb,
		NULL /* drag_data_received */
	},
	{
		N_("Stop"), 
		N_("Stop current data transfer"), 
		GNOME_STOCK_PIXMAP_STOP, 
		"Stop",
		TRUE, /* priority? */
		FALSE,
		600,
		window_stop_button_clicked_cb,
		window_generic_button_press_event_cb,
		NULL /* release_event */,
		NULL /* drag_data_received */
	},
	{
		N_("Go"), 
		N_("Go to specified location"), 
		GNOME_STOCK_PIXMAP_JUMP_TO, 
		"Go",
		FALSE, /* priority? */
		FALSE,
		1400,
		NULL /* clicked */,
		window_generic_button_press_event_cb,
		window_go_button_release_cb,
		NULL /* drag_data_received */
	},
	{
		N_("Zoom control"), 
		NULL, 
		NULL, /* pixmap */ 
		NULL,
		FALSE, /* priority? */
		FALSE,
		1100,
		NULL /* clicked */,
		NULL,
		NULL,
		NULL /* drag_data_received */
	},
	{
		N_("Drag handle"), 
		NULL, 
		NULL, /* pixmap */
		NULL,
		FALSE, /* priority? */
		FALSE,
		1200,
		NULL /* clicked */,
		NULL,
		NULL,
		NULL /* drag_data_received */
	},
	{
		N_("Location entry"),
		NULL,
		NULL, /* pixmap */
		NULL,
		FALSE, /* priority? */
		FALSE,
		1300,
		NULL /* clicked */,
		NULL,
		NULL,
		NULL /* drag_data_received */
	},
	{
		N_("Spinner"), 
		NULL, 
		NULL, /* pixmap */
		NULL,
		FALSE, /* priority? */
		FALSE,
		1500,
		NULL /* clicked */,
		NULL,
		NULL,
		NULL /* drag_data_received */
	},
	{
		"------", 
		NULL, 
		NULL, /* pixmap */
		NULL,
		FALSE, /* priority? */
		FALSE,
		1600,
		NULL /* clicked */,
		NULL,
		NULL,
		NULL /* drag_data_received */
	},
	{
		N_("Find entry"), 
		N_("Find in page"), 
		GNOME_STOCK_PIXMAP_SEARCH, 
		"Search",
		FALSE, /* priority? */
		FALSE,
		800,
		NULL,
		NULL,
		NULL,
		NULL /* drag_data_received */
	},
	{
		N_("Bookmarks"), 
		N_("Toggle bookmarks sidebar"), 
		GNOME_STOCK_PIXMAP_BOOK_OPEN, 
		"Bookmarks",
		FALSE, /* priority? */
		TRUE,
		1000,
		window_bookmarks_button_clicked_cb,
		window_generic_button_press_event_cb,
		NULL,
		NULL /* drag_data_received */
	},
	{
		N_("History"), 
		N_("Toggle history sidebar"), 
		GNOME_STOCK_PIXMAP_INDEX, 
		"History",
		FALSE, /* priority? */
		TRUE,
		900,
		window_history_button_clicked_cb,
		window_generic_button_press_event_cb,
		NULL,
		NULL /* drag_data_received */
	},
	{
		N_("Print"), 
		N_("Print current page"), 
		GNOME_STOCK_PIXMAP_PRINT, 
		"Print",
		FALSE, /* priority? */
		FALSE,
		550,
		window_print_button_clicked_cb,
		window_generic_button_press_event_cb,
		NULL,
		NULL /* drag_data_received */
	},
	{
		N_("Back history"), 
		N_("Go back several pages"), 
		NULL,  /* no stock pixmap */
		"BackHistory",
		FALSE, /* priority? */
		TRUE,
		201,
		NULL, /* clicked */
		window_back_history_button_press_cb,
		NULL,
		NULL /* drag_data_received */
	},
	{
		N_("Forward history"), 
		N_("Go forward several pages"), 
		NULL, /* no stock pixmap */
		"ForwardHistory",
		FALSE, /* priority? */
		TRUE,
		401,
		NULL, /* clicked */
		window_forward_history_button_press_cb,
		NULL,
		NULL /* drag_data_received */
	},
	{
		N_("Clear location"), 
		N_("Clear the location entry field"), 
		GNOME_STOCK_PIXMAP_CLEAR,
		"ClearLocation",
		FALSE, /* priority? */
		FALSE,
		1250,
		NULL, /* clicked */
		window_generic_button_press_event_cb,
		window_clear_location_button_release_cb,
		NULL /* drag_data_received */
	}
};

/**
 * toolbar_create: create main toolbar
 */
void
toolbar_create (GaleonWindow *window, gboolean show)
{
	gboolean location_on_main_toolbar;
	GtkWidget *hbox, *toolbar;

	/* read prefs */
	location_on_main_toolbar = eel_gconf_get_boolean
		(CONF_TOOLBAR_URL_LOCATION);
	theme = get_theme_dir ();

	/* build the overall box to pack the toolbar into */
	hbox = gtk_hbox_new (FALSE, 2);

	/* dock the box into the window */
	window->main_dockitem = 
		toolbar_add_docked (window, hbox, GNOME_APP_TOOLBAR_NAME, 1);

	/* create items toolbar */
	window->main_toolbar = toolbar =
		gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_BOTH);

	/* pack it into the box */
	gtk_box_pack_start (GTK_BOX (hbox), toolbar, FALSE, FALSE, 0);

	/* setup the toolbar context menu */
	gtk_signal_connect (GTK_OBJECT (window->main_dockitem), 
			    "button-press-event", GTK_SIGNAL_FUNC
			    (window_generic_button_press_event_cb), window);

	/* create all the buttons and widgets */
	toolbar_create_widgets (window, hbox, toolbar, 
				location_on_main_toolbar);

	/* show the box and all its contents */
	gtk_widget_show_all (hbox);
	if (show) gtk_widget_show (window->main_dockitem);

	/* create location toolbar, if necessary */
	if (!location_on_main_toolbar)
	{
		/* create it's own toolbar */
		toolbar_create_location_toolbar (window, show);
	}

	/* update the toolbar appearance */
	toolbar_update (window);

	if (theme) g_free (theme);
}

/**
 * toolbar_recreate: recreate main toolbar (e.g. on prefs apply)
 */
void
toolbar_recreate (GaleonWindow *window)
{
	gchar *text = NULL;
	gboolean show = FALSE;

	/* get current text in url entry if any */
	/* NB: this MUST be strdup'd here since it's only a reference
	 * and we're about to destroy the toolbar (D'Oh! -- MattA) */
	if (window->location_gnomeentry && window->location_entry)
	{
		text = g_strdup (gtk_entry_get_text 
				 (GTK_ENTRY (window->location_entry)));

		/* also store history */
		gnome_entry_save_history 
			(GNOME_ENTRY (window->location_gnomeentry));
	}

	/* destroy spinner, this prevents crashes with timeouts */
	spinner_destroy (window);

	/* destroy main toolbar */
	if (window->main_dockitem != NULL)
	{
		show = GTK_WIDGET_VISIBLE (window->main_dockitem);
		gtk_widget_destroy (window->main_dockitem->parent);
		window->main_dockitem = NULL;
		window->main_toolbar = NULL;
		window->right_toolbar = NULL;
	}

	/* destroy location toolbar */
	if (window->location_dockitem != NULL)
	{
		gtk_widget_destroy (window->location_dockitem->parent);
		window->location_dockitem = NULL;
		window->location_toolbar = NULL;
	}

	/* zero out the toolbar widgets, these should have already
	 * been destroyed by the destruction of the toolbars */
	window->new_button             = NULL;
	window->back_button            = NULL;
	window->up_button              = NULL;
	window->forward_button         = NULL;
	window->refresh_button         = NULL;
	window->home_button            = NULL;
	window->stop_button            = NULL;
	window->go_button              = NULL;
	window->zoom_spin              = NULL;
	window->drag_event_box         = NULL;
	window->drag_pixmap            = NULL;
	window->location_gnomeentry    = NULL;
	window->location_entry         = NULL;
	window->history_button         = NULL;
	window->bookmarks_button       = NULL;
	window->back_history_button    = NULL;
	window->forward_history_button = NULL;
	window->clear_location_button  = NULL;
	window->find_entry             = NULL;

	/* create new toolbar */
	toolbar_create (window, show);
	
	/* set the controls properly for this window */
	window_update_nav_controls (window);

	/* restore location entry text and history */
	if (window->location_gnomeentry && window->location_entry)
	{
		gnome_entry_load_history  
			(GNOME_ENTRY (window->location_gnomeentry));
		if (text != NULL)
		{
			window_set_url_entry (window, text);
			g_free (text);
		}
	}

	/* set bookmarks and history togglebuttons */
	window_update_bm_and_hist_buttons (window,
		(window->dock_type == DOCK_BOOKMARKS),
		(window->dock_type == DOCK_HISTORY));

	/* get spinner going if necessary */
	window->spinner_running = FALSE;
	if (window->active_embed->load_started)
	{
		spinner_start (window);
	}
}

/**
 * toolbar_update: update the toolbar appearance
 */
static void
toolbar_update (GaleonWindow *window)
{
	ToolbarStyle style;
	GtkReliefStyle relief;
	GtkToolbarStyle final_style;
	GtkToolbarSpaceStyle sep;
	gboolean toolbar_button_relief, toolbar_space_style;

	/* get relief */
	toolbar_button_relief = gnome_preferences_get_toolbar_relief_btn ();
	relief = (toolbar_button_relief ? GTK_RELIEF_NORMAL : GTK_RELIEF_NONE);

	/* get space style */
	toolbar_space_style = gnome_preferences_get_toolbar_lines ();
	sep = (toolbar_space_style ? GTK_TOOLBAR_SPACE_LINE : 
	       GTK_TOOLBAR_SPACE_EMPTY);
	
	/* get real style */
	style = eel_gconf_get_integer (CONF_TOOLBAR_STYLE);

	/* convert to GTK+ style for setting in buttons */
	final_style = GTK_TOOLBAR_BOTH; /* only to stop a warning */
	switch (style)
	{
	case TOOLBAR_STYLE_HORIZONTAL:
	case TOOLBAR_STYLE_TEXT_ONLY:
		final_style = GTK_TOOLBAR_TEXT;
		break;

	case TOOLBAR_STYLE_ICONS_ONLY:
		final_style = GTK_TOOLBAR_ICONS;
		break;

	case TOOLBAR_STYLE_VERTICAL:
		final_style = GTK_TOOLBAR_BOTH;
		break;
	}

	/* set toolbar styles */
	toolbar_set_style (window->main_toolbar,     final_style, relief, sep);
	toolbar_set_style (window->right_toolbar,    final_style, relief, sep);
	toolbar_set_style (window->location_toolbar, final_style, relief, sep);
}

/**
 * toolbar_create_widgets: create the widgets on the main toolbar
 */
static void
toolbar_create_widgets (GaleonWindow *window, 
			GtkWidget *hbox, GtkWidget *toolbar,
			gboolean location_on_main_toolbar)
{
	GtkWidget *spinner;
	GSList *icon_list, *tmp;
	GList *l;
	gint toolbars = 0;
	
	icon_list = eel_gconf_get_integer_list(CONF_TOOLBAR_ICON_LIST);
	tmp = icon_list;
	
	while (tmp!=NULL) 
	{
		ToolbarItemType type;

		/* get toolbar item type */
		type = GPOINTER_TO_INT(tmp->data);
	
		/* build the right thing */
		switch (type)
		{
		case TOOLBAR_ITEM_ZOOM_SPIN:
			/* create zoom spin entry */
			toolbar_create_zoom_spin (window, toolbar);
			break;

		case TOOLBAR_ITEM_DRAG_HANDLE:
			/* create drag handle if location widgets here */
			if (location_on_main_toolbar)
			{
				toolbar_create_drag_handle (window, toolbar);
			}
			break;

		case TOOLBAR_ITEM_LOCATION_ENTRY:
			/* create location widgets if on this toolbar */
			if (location_on_main_toolbar)
			{
				toolbar_create_location_widgets 
					(window, hbox, toolbar);

				/* use continuation toolbar */
				toolbar = window->right_toolbar;
			}
			break;

		case TOOLBAR_ITEM_SPINNER:
			/* create the spinner */
			spinner = spinner_create (window);
			if (!spinner) break;
			
			/* if not the last item... */
			if (g_slist_next(tmp)!=NULL)
			{
				/* pack it normally */
				gtk_toolbar_append_element 
					(GTK_TOOLBAR (toolbar), 
					 GTK_TOOLBAR_CHILD_WIDGET,
					 GTK_WIDGET (spinner),
					 NULL, NULL, NULL, NULL, NULL, NULL);
			}
			else
			{
				/* otherwise use hbox to right justify */
				gtk_box_pack_end (GTK_BOX (hbox), spinner,
						  FALSE, FALSE, 0);
			}
			break;

		case TOOLBAR_ITEM_SEPARATOR:
			/* append separator */
			toolbar_create_separator (toolbar);
			break;

		case TOOLBAR_ITEM_GO:
			/* create go button if location widgets here */
			if (location_on_main_toolbar)
			{
				toolbar_create_button (window, toolbar, type);
			}
			break;

		case TOOLBAR_ITEM_FIND:
			/* create find entry */
			toolbar_create_find_entry (window, toolbar, type);
			break;
			
		default:
			/* create a normal button */
			toolbar_create_button (window, toolbar, type);
			break;
		}
		tmp = g_slist_next(tmp);
	}

	g_slist_free(icon_list);

	/* fetch the size of the highest button, and resize all horizontally
	 * styled buttons to match this size */
	l = GTK_TOOLBAR (window->main_toolbar)->children;
	while (l)
	{
		GtkWidget *icon = ((GtkToolbarChild *) l->data)->icon;
		GtkWidget *label = ((GtkToolbarChild *) l->data)->label;
		GtkWidget *button;
		GtkRequisition r;
		GtkRequisition iconr;
		GtkRequisition labelr;
		gint height = 0;

		/* skip any non-buttons */
		if (!GTK_IS_BUTTON (((GtkToolbarChild *) l->data)->widget))
		{
			l = g_list_next (l); 
			continue;
		}

		button = GTK_BIN (((GtkToolbarChild *) l->data)->widget)->child;
		if (button) gtk_widget_size_request (button, &r);
		if (icon) gtk_widget_size_request (icon, &iconr);
		if (label) gtk_widget_size_request (label, &labelr);
		switch (eel_gconf_get_integer (CONF_TOOLBAR_STYLE))
		{
		case TOOLBAR_STYLE_HORIZONTAL:
			if (button) height = r.height;
			break;
		case TOOLBAR_STYLE_ICONS_ONLY:
			if (icon) height = iconr.height;
			break;
		case TOOLBAR_STYLE_TEXT_ONLY:
			if (label) height = labelr.height;
			break;
		case TOOLBAR_STYLE_VERTICAL:
			if (icon && label) height =
				iconr.height + labelr.height;
			break;
		}

		if (height > button_height) button_height = height;

		l = g_list_next (l);

		if (!l && toolbars == 0 &&
		    GTK_IS_TOOLBAR (window->right_toolbar))
		{
			l = GTK_TOOLBAR (window->right_toolbar)->children;
			toolbars++;
		}
	}

	/* sync sizes */
	for (l = resized_later; l; l = g_list_next (l))
	{
		GtkWidget *w = GTK_WIDGET (l->data);
		GtkRequisition r;
		gtk_widget_size_request (w, &r);
		gtk_widget_set_usize (w, r.width, button_height);
	}

	g_list_free (resized_later);
	resized_later = NULL;
	button_height = 0;
}

/**
 * toolbar_create_drag_handle: create a "drag handle", where you can
 * drag the current URL from
 */
static void
toolbar_create_drag_handle (GaleonWindow *window, GtkWidget *toolbar)
{
	GtkWidget *event_box;

	/* build suitable pixmap */
	if (site_pixmap_data != NULL)
	{
		window->drag_pixmap = gtk_pixmap_new (site_pixmap_data->pixmap, 
						      site_pixmap_data->mask);
	}

	/* build event box (for capturing drag signals */
	event_box = window->drag_event_box = gtk_event_box_new ();
	gtk_container_set_border_width (GTK_CONTAINER (event_box), 4);

	/* connect drag signals */
	gtk_signal_connect (GTK_OBJECT (event_box), "drag_data_get",
			    (window_drag_pixmap_drag_data_get_cb), window);
	gtk_drag_source_set (GTK_WIDGET (event_box), GDK_BUTTON1_MASK, 
			     url_drag_types, url_drag_types_num_items,
			     GDK_ACTION_COPY | GDK_ACTION_LINK);

	/* add pixmap into box */
	gtk_container_add (GTK_CONTAINER (event_box), window->drag_pixmap);

	/* add to toolbar */
	gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
				    GTK_TOOLBAR_CHILD_WIDGET,
				    GTK_WIDGET (event_box),
				    NULL, _("Drag page location from here"),
				    NULL, NULL, NULL, NULL);
}

/**
 * toolbar_create_location_widgets: create location related widgets
 */
static void
toolbar_create_location_widgets (GaleonWindow *window, 
				 GtkWidget *hbox, GtkWidget *toolbar) 
{
	GtkWidget *entry;
	GtkWidget *popwin;
	GtkWidget *gnomeentry;
	gboolean location_on_main_toolbar;
	gboolean build_go = FALSE, build_handle = FALSE;
	GSList *icon_list, *tmp;
	
	/* read prefs */
	icon_list = eel_gconf_get_integer_list(CONF_TOOLBAR_ICON_LIST);
	tmp = icon_list;
	
	while (tmp != NULL) 
	{
		ToolbarItemType item = GPOINTER_TO_INT (tmp->data);
		if (item == TOOLBAR_ITEM_GO) build_go = TRUE;
		if (item == TOOLBAR_ITEM_DRAG_HANDLE) build_handle = TRUE;
		tmp = g_slist_next (tmp);
	}

	g_slist_free (icon_list);

	location_on_main_toolbar = eel_gconf_get_boolean
		(CONF_TOOLBAR_URL_LOCATION);
	

	/* create drag handle if on separate toolbar */
	if (!location_on_main_toolbar && build_handle)
	{
		toolbar_create_drag_handle (window, toolbar);
	}

	/* create location entry and access components */
	gnomeentry = gnome_entry_new ("LocationEntry");
	gnome_entry_load_history (GNOME_ENTRY (gnomeentry));
	entry = gnome_entry_gtk_entry (GNOME_ENTRY (gnomeentry));
	popwin = GTK_COMBO (gnomeentry)->popwin;
	window->location_gnomeentry = gnomeentry;
	window->location_entry = entry;

	/* connect the various signals */
	gtk_signal_connect (GTK_OBJECT (popwin), "show", GTK_SIGNAL_FUNC 
			    (window_location_gnomeentry_popwin_cb), window);
	gtk_signal_connect (GTK_OBJECT (popwin), "hide", GTK_SIGNAL_FUNC
			    (window_location_gnomeentry_popwin_cb), window);
	gtk_signal_connect_after (GTK_OBJECT (entry), "key_press_event", 
				  GTK_SIGNAL_FUNC 
				  (window_location_entry_key_press_cb), 
				  window);
	gtk_signal_connect (GTK_OBJECT (gnomeentry), "drag_data_received", 
			    GTK_SIGNAL_FUNC 
			    (window_location_entry_drag_data_received_cb), 
			    window);
	gtk_signal_connect_after (GTK_OBJECT (entry), "button_press_event", 
				  GTK_SIGNAL_FUNC 
				  (window_location_entry_button_press_cb), 
				  window);

	/* set url entry drop destination */
	gtk_drag_dest_set (gnomeentry, GTK_DEST_DEFAULT_ALL, drop_types, 
			   drop_types_num_items, GDK_ACTION_COPY);

	/* pack into toplevel box */
	gtk_box_pack_start (GTK_BOX (hbox), gnomeentry, TRUE, TRUE, 1);

	/* create continutation toolbar */
	window->right_toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, 
						 GTK_TOOLBAR_BOTH);

        /* pack it in */
	gtk_box_pack_start (GTK_BOX (hbox), window->right_toolbar,
			    FALSE, FALSE, 0);

	/* add in Go button if on separate toolbar */
	if (!location_on_main_toolbar && build_go)
	{
		toolbar_create_button (window, window->right_toolbar,
				       TOOLBAR_ITEM_GO);
	}
}

/*
 * toolbar_create_location_toolbar: create location toolbar
 */
static void
toolbar_create_location_toolbar (GaleonWindow *window, gboolean show)
{
	GtkWidget *hbox;
	
	/* build the overall box to pack the toolbar into */
	hbox = gtk_hbox_new (FALSE, 2);

	/* dock the box into the window */
	window->location_dockitem = toolbar_add_docked (window, hbox, 
							"location", 2);

	/* create toolbar */
	window->location_toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL,
						    GTK_TOOLBAR_BOTH);

	/* pack it into the box */
	gtk_box_pack_start (GTK_BOX (hbox), window->location_toolbar,
			    FALSE, FALSE, 0);

	/* setup the toolbar context menu */
	gtk_signal_connect (GTK_OBJECT (window->location_dockitem), 
			    "button-press-event", GTK_SIGNAL_FUNC
			    (window_generic_button_press_event_cb), window);

	/* insert the location widgets */
	toolbar_create_location_widgets (window, hbox, 
					 window->location_toolbar);

	/* show everything */
	gtk_widget_show_all (hbox);
	if (show) gtk_widget_show (window->location_dockitem);
}

/**
 * toolbar_create_find_entry: create find in page entry
 */
static void
toolbar_create_find_entry (GaleonWindow *window, GtkWidget *toolbar,
			   ToolbarItemType type)
{
	const ToolbarItem *item;
	GtkWidget *entry, *invisible, *gnomeentry;

	/* get item from array */
	item = &(toolbar_items[type]);

	/* prepend some space */
	invisible = gtk_label_new ("");
	gtk_widget_set_usize (invisible, 3, -2);
	gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
				    GTK_TOOLBAR_CHILD_WIDGET,
				    GTK_WIDGET (invisible), NULL,
				    NULL, NULL, NULL, NULL, NULL);
	
	/* create gnomeentry, pack it */
	gnomeentry = gnome_entry_new ("ToolbarFindEntry");
	entry = gnome_entry_gtk_entry (GNOME_ENTRY (gnomeentry));
	gtk_widget_set_usize (entry, 100, -2);	
	gtk_toolbar_append_element (GTK_TOOLBAR (toolbar), 
				    GTK_TOOLBAR_CHILD_WIDGET,
				    GTK_WIDGET (gnomeentry), NULL, 
				    _(item->tooltip), NULL, NULL, NULL, NULL);

	/* append some space */
	invisible = gtk_label_new ("");
	gtk_widget_set_usize (invisible, 3, -2);
	gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
				    GTK_TOOLBAR_CHILD_WIDGET,
				    GTK_WIDGET (invisible), NULL,
				    NULL, NULL, NULL, NULL, NULL);

	/* connect signal (Return should search for inserted text) */
	gtk_signal_connect (GTK_OBJECT (entry), "activate",
			    GTK_SIGNAL_FUNC (window_find_entry_activate_cb), 
			    window);

	/* update window structure */
	window->find_entry = entry;
}

/**
 * toolbar_create_zoom_spin: create zoom spin button
 */
static void
toolbar_create_zoom_spin (GaleonWindow *window, GtkWidget *toolbar)
{
	GtkObject *adj;

	/* create the adjustment */
	adj = gtk_adjustment_new (100, 1, 999, 10, 25, 10);

	/* build the spin button */
	window->zoom_spin = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1, 0);

	/* setup properties */
	gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (window->zoom_spin),
					 GTK_SHADOW_NONE);

	/* connect signals */
	gtk_signal_connect (GTK_OBJECT (adj), "value_changed", 
			    window_zoom_spin_changed_cb, window);
	gtk_signal_connect (GTK_OBJECT (window->zoom_spin),
			    "key_press_event", GTK_SIGNAL_FUNC 
			    (window_zoom_spin_key_press_cb), window);
	gtk_signal_connect_after (GTK_OBJECT (window->zoom_spin),
				  "button_press_event", GTK_SIGNAL_FUNC 
				  (window_zoom_spin_button_press_cb), window);

	/* append to toolbar */
	gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
				    GTK_TOOLBAR_CHILD_WIDGET,
				    GTK_WIDGET (window->zoom_spin),
				    NULL, NULL, NULL, NULL, NULL, NULL);
}

/*
 * toolbar_button: create and append a button to a toolbar
 */
static void
toolbar_create_button (GaleonWindow *window, GtkWidget *toolbar, 
		       ToolbarItemType type)
{
	GtkWidget *button, *label, *box;
	GtkWidget *pixmap;
	const ToolbarItem *item;
	gboolean resizable_widget = FALSE;

	/* If the item is too high in number, it must be from a later version of
	 * Galeon.  Gracefully ignore it, instead of crashing */
	if (type >= TOOLBAR_ITEM_COUNT) return;

	/* get item from array */
	item = &(toolbar_items[type]);
	
	pixmap = NULL;
	
	/* use generic icon if no stock (e.g. back/forward history icons) */
	if (pixmap == NULL && item->stock_icon == NULL)
	{
		pixmap = toolbar_get_theme_pixmap (item);
		resizable_widget = TRUE;
	}

	if (pixmap == NULL && theme && item->theme_icon)
	{
		pixmap = toolbar_get_theme_pixmap (item);
	}

	/* use GNOME stock icon if not found or not requested */
	if (pixmap == NULL && item->stock_icon != NULL)
	{
		gint height = get_theme_pixmap_height ();
		
		if (height != 24)
		{ 
			pixmap = gnome_stock_pixmap_widget_at_size 
				 (window->WMain, item->stock_icon, height, 
				  height); /* GNOME stock icons are square */
		}
		else
		{
			pixmap = gnome_stock_pixmap_widget (window->WMain,
							    item->stock_icon);
		}
	}

	/* make the toolbar button and add it to the toolbar */
	if (eel_gconf_get_integer (CONF_TOOLBAR_STYLE) ==
	    TOOLBAR_STYLE_HORIZONTAL || resizable_widget)
	{
		GtkWidget *a = NULL;
		gboolean button_relief;

		if (resizable_widget)
		{
			a = gtk_alignment_new (0.50, 1.00, 1.00, 0.00);
			gtk_container_add (GTK_CONTAINER (a), pixmap);
		}

		/* we create a horizontal toolbar style ourselves */
		box = gtk_hbox_new (FALSE, 2);

		/* pack the pixmap first */
		gtk_box_pack_start (GTK_BOX (box),
				resizable_widget ? a : pixmap, FALSE, FALSE, 0);

		/* if priority text for this button, pack that too */
		if (item->priority)
		{
			label = gtk_label_new (_(item->label));
			gtk_box_pack_start (GTK_BOX (box), label, 
					    TRUE, TRUE, 0);
		}

		/* build button */
		if (item->togglebutton)
		{
			button = gtk_toggle_button_new ();
		}
		else
		{
			button = gtk_button_new ();
		}

		/* insert box into button */
		gtk_container_add (GTK_CONTAINER (button), box);

		/* append button to toolbar */
		gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), button,
					   _(item->tooltip), NULL);

		/* set it up */
		button_relief = gnome_preferences_get_toolbar_relief_btn ();
		gtk_button_set_relief (GTK_BUTTON (button), button_relief ?
				       GTK_RELIEF_NORMAL : GTK_RELIEF_NONE);
		GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_FOCUS);
	
		/* we want to sync sizes of all horizontally-styled buttons
		 * later */
		resized_later = g_list_append (resized_later, box);
	}
	else
	{
		/* insert plain button */
		button = gtk_toolbar_append_element 
			(GTK_TOOLBAR (toolbar), 
			 (item->togglebutton ? 
			  GTK_TOOLBAR_CHILD_TOGGLEBUTTON : 
			  GTK_TOOLBAR_CHILD_BUTTON),
			 NULL, _(item->label), _(item->tooltip),
			 NULL, pixmap, NULL, NULL);
	}

	/* connect appropriate signals */
	if (item->clicked_cb != NULL)
	{
		gtk_signal_connect (GTK_OBJECT (button), "clicked", 
				    item->clicked_cb, window);
	}
	if (item->button_press_event_cb != NULL)
	{
		gtk_signal_connect (GTK_OBJECT (button), "button_press_event", 
				    GTK_SIGNAL_FUNC
				    (item->button_press_event_cb), window);
	}
	if (item->button_release_event_cb != NULL)
	{
		gtk_signal_connect (GTK_OBJECT (button),
				    "button_release_event", GTK_SIGNAL_FUNC
				    (item->button_release_event_cb), window);
	}
	if (item->drag_data_received_cb != NULL)
	{
		gtk_signal_connect (GTK_OBJECT (button), "drag_data_received", 
				    GTK_SIGNAL_FUNC
				    (item->drag_data_received_cb), window);

		/* set drop types */
		gtk_drag_dest_set (GTK_WIDGET (button), GTK_DEST_DEFAULT_ALL,
				   drop_types, drop_types_num_items, 
				   GDK_ACTION_COPY);
	}

	/* connect enter/leave signals for updating prelight icons */
	gtk_object_set_data (GTK_OBJECT (button), "pixmap", pixmap);

	gtk_signal_connect (GTK_OBJECT (button), "enter", GTK_SIGNAL_FUNC
			    (window_toolbar_button_enter_event_cb),
			    (gpointer *) item);
	gtk_signal_connect (GTK_OBJECT (button), "leave", GTK_SIGNAL_FUNC
			    (window_toolbar_button_leave_event_cb),
			    (gpointer *) item);

	/* set the window->XXX_button appropiately */
	switch (type)
	{
	case TOOLBAR_ITEM_NEW:
		window->new_button = button;
		break;
	case TOOLBAR_ITEM_BACK:
		window->back_button = button;
		break;
	case TOOLBAR_ITEM_UP:
		window->up_button = button;
		break;
	case TOOLBAR_ITEM_FORWARD:
		window->forward_button = button;
		break;
	case TOOLBAR_ITEM_REFRESH:
		window->refresh_button = button;
		break;
	case TOOLBAR_ITEM_START:
		window->home_button = button;
		break;
	case TOOLBAR_ITEM_STOP:
		window->stop_button = button;
		break;
	case TOOLBAR_ITEM_GO:
		window->go_button = button;
		break;
	case TOOLBAR_ITEM_HISTORY:
		window->history_button = button;
		break;
	case TOOLBAR_ITEM_BOOKMARKS:
		window->bookmarks_button = button;
		break;
	case TOOLBAR_ITEM_BACK_HISTORY:
		window->back_history_button = button;
		break;
	case TOOLBAR_ITEM_FORWARD_HISTORY:
		window->forward_history_button = button;
		break;
	case TOOLBAR_ITEM_CLEAR_LOCATION:
		window->clear_location_button = button;
		break;
	default:
		break;
	}
}

/**
 * toolbar_add_docked: add an horizontal box to the toolbar dock
 */
static GtkWidget *
toolbar_add_docked (GaleonWindow *window, GtkWidget *hbox, 
		    gchar *name, gint band_number)
{
	gboolean toolbar_relief;
	gboolean toolbar_detachable;
	gboolean location_on_main_toolbar;
	GnomeDockItemBehavior props;
	GtkReliefStyle relief;

	/* read prefs */
	toolbar_relief = gnome_preferences_get_toolbar_relief ();
	relief = (toolbar_relief ? GTK_SHADOW_OUT : GTK_SHADOW_NONE);
	toolbar_detachable = gnome_preferences_get_toolbar_detachable ();
	location_on_main_toolbar = eel_gconf_get_boolean 
		(CONF_TOOLBAR_URL_LOCATION);

	/* default properties */
	props = (GNOME_DOCK_ITEM_BEH_EXCLUSIVE |
		 GNOME_DOCK_ITEM_BEH_NEVER_VERTICAL);

	/* lock according to gnome prefs */
	if (!toolbar_detachable)
	{
		props |= GNOME_DOCK_ITEM_BEH_LOCKED;
	}

	/* dock into app */
	gnome_app_add_docked (GNOME_APP (window->WMain), hbox, name,
			      props, GNOME_DOCK_TOP, band_number, 0, 0);

	/* set border appropriate to whether or not there's relief */
	gtk_container_set_border_width (GTK_CONTAINER(hbox->parent),
					toolbar_relief ? 2 : 0);

	/* set shadowing follwing gnome pref */
	gnome_dock_item_set_shadow_type (GNOME_DOCK_ITEM (hbox->parent), 
					 relief);

	/* this is a GnomeDockItem */
	return hbox->parent;
}

/**
 * toolbar_set_style: set overall relief and button relief styles
 */	
static void
toolbar_set_style (GtkWidget *toolbar, GtkToolbarStyle final_style,
		   GtkReliefStyle relief, GtkToolbarSpaceStyle sep)
{
	/* skip if not there */
	if (toolbar == NULL)
	{
		return;
	}

	/* otherwise set style */
	gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), final_style);
	gtk_toolbar_set_button_relief (GTK_TOOLBAR (toolbar), relief);
	gtk_toolbar_set_space_style (GTK_TOOLBAR (toolbar), sep);
}

/**
 * toolbar_get_theme_pixmap: retreive appriopate pixmap and build a widget
 * with it.
 */
static GtkWidget *
toolbar_get_theme_pixmap (const ToolbarItem *item)
{
	PixmapData *icon;
	GtkWidget *widget;
	gchar *tmp, *filename;

	filename = g_strconcat (item->theme_icon, ".png", NULL);
	
	tmp = g_concat_dir_and_file (theme, filename);
	if (!g_file_exists (tmp))
	{
		g_free (tmp);
		tmp = g_concat_dir_and_file (SHARE_DIR, filename);
		if (!g_file_exists (tmp) || item->stock_icon != NULL)
		{
			g_free (tmp);
			g_free (filename);
			return NULL;
		}
	}
	g_free (tmp);
	
	icon = get_theme_pixmap (filename, FALSE);
	
	g_free (filename);

	if (icon != NULL)
	{
		widget = gtk_pixmap_new (icon->pixmap, icon->mask);
		return GTK_WIDGET (widget);
	}
	else
	{
		return NULL;
	}
}

static void
toolbar_create_separator (GtkWidget *toolbar)
{
	if (eel_gconf_get_integer (CONF_TOOLBAR_STYLE) ==
	    TOOLBAR_STYLE_HORIZONTAL && gnome_preferences_get_toolbar_lines ())
	{
		/* this is hacky. because horizontal is
		 * our own style, standard gtk toolbar
		 * seps don't know how high they should
		 * be. because of that, we build our own
		 * sep here  -- jorn */
		GtkWidget *sep = gtk_vseparator_new ();
		gint icon_height = get_theme_pixmap_height ();

		gtk_toolbar_append_element 
			(GTK_TOOLBAR (toolbar), 
			 GTK_TOOLBAR_CHILD_WIDGET,
			 GTK_WIDGET (sep),
			 NULL, NULL, NULL, NULL, NULL, NULL);
		gtk_widget_set_usize (sep, 5, icon_height / 2);
	}
	else
	{
		gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
	}
}
