/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2002-2004 Hiroyuki Ikezoe
 *  Copyright (C) 2003 Takuro Ashie
 *
 *  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 "kz-actions.h"

#include "string.h"

#include "gtk24backports.h"
#include "gtk-utils.h"
#include "intl.h"
#include "utils.h"
#include "kazehakase.h"
#include "kz-window.h"
#include "kz-tab-label.h"
#include "kz-prefs-win.h"
#include "kz-links-dialog.h"
#include "kz-password-manager-dialog.h"
#include "mozilla.h"
#include "kz-bookmark-editor.h"
#include "kz-bookmark-edit-win.h"
#include "kz-bookmark-filter.h"
#include "kz-entry-action.h"
#include "kz-location-entry-action.h"
#include "kz-stop-reload-action.h"
#include "kz-scrap-bookmark-action.h"
#include "kz-smart-bookmark-action.h"
#include "kz-mozembed.h"
#include "kz-actions-download.h"
#include "kz-about-dialog.h"
#include "kz-paned.h"
#include "kz-bookmark-menu.h"
#include "eggregex.h"

#include <time.h>

#define HTTP_REGEX "(https?://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+)"
enum {
	UI_BEGINNER,
	UI_MEDIUM,
	UI_EXPERT,
	UI_CUSTOM
};


static GQuark bookmark_quark = 0;


static void
act_save (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	KzMozEmbed *kzembed;
	const gchar *filename;

	g_return_if_fail(KZ_IS_WINDOW(kz));
	g_return_if_fail(KZ_IS_MOZ_EMBED(widget));
	
	kzembed = KZ_MOZ_EMBED(widget);
	
	filename = kz_actions_download_open_save_dialog(kz_moz_embed_get_location(kzembed), TRUE);
	if (filename)
		kz_moz_embed_save_with_content(kzembed, filename);
}


static void
act_close_window (GtkAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));

	kz_window_store_state(kz);
	kz_window_close_all_tab(kz);
	gtk_widget_destroy(GTK_WIDGET(kz));
}


static void
act_close_tab (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	if (widget)
		kz_window_close_tab(kz, widget);
}


static void
act_new_window (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	widget = kz_window_new(NULL);
	gtk_widget_show(widget);
}


static void
cb_remove_idle(KzWindow* kz)
{
	g_idle_remove_by_data(kz);
}


static gboolean
idle_focus_to_loc_ent(gpointer data)
{
	GtkAction *action;
	KzWindow *kz;

	g_return_val_if_fail(KZ_IS_WINDOW(data), FALSE);
	
	kz = KZ_WINDOW(data);
	action = gtk_action_group_get_action(kz->actions,"FocusLocationEntry");

	gtk_action_activate(action);
	g_signal_handlers_disconnect_by_func(G_OBJECT(kz),
					     G_CALLBACK(cb_remove_idle), NULL);
	return FALSE;
}

static void
act_new_tab (GtkAction *action, KzWindow *kz)
{
	gboolean focus;
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW(kz));
	widget = kz_window_open_new_tab(kz, NULL);

   	KZ_CONF_GET("Tab", "focus_open_new", focus, BOOL);
	if(focus && widget)
	{
		int num = gtk_notebook_page_num(GTK_NOTEBOOK(kz->notebook),
						widget);
		if(num != -1)
			gtk_notebook_set_current_page(GTK_NOTEBOOK(kz->notebook),
						      num);

		KZ_CONF_GET("Tab","focus_loc_ent_new", focus, BOOL);
		if(focus)
		{
			g_idle_add(idle_focus_to_loc_ent, kz);
			g_signal_connect(G_OBJECT(kz), "destroy",
					 G_CALLBACK(cb_remove_idle), NULL);
		}
	}
}


static void
act_focus_loc_ent (GtkAction *action, KzWindow *kz)
{
	GtkAction *loc_ent =
		gtk_action_group_get_action(kz->actions,"LocationEntry");
	GtkWidget *proxy = NULL;
	GSList *proxies;

	if(loc_ent)
	{
		proxies = gtk_action_get_proxies(loc_ent);
		proxy = GTK_COMBO(gtk_bin_get_child(GTK_BIN(proxies->data)))->entry;
	}
	if(proxy && GTK_IS_ENTRY(proxy))
		gtk_widget_grab_focus(proxy);
}

static void
act_clear_loc_ent (GtkAction *action, KzWindow *kz)
{
	GtkAction *loc_ent = gtk_action_group_get_action(kz->actions, "LocationEntry");
	GtkAction *focus_action  = gtk_action_group_get_action(kz->actions,
							       "FocusLocationEntry");

	kz_entry_action_set_text(KZ_ENTRY_ACTION(loc_ent), "");
	gtk_action_activate(focus_action);
}

static void
act_open_file (GtkAction *action, KzWindow *kz)
{
	GtkFileSelection *file_selector;
	const gchar *filename = NULL;
	gchar *uri = NULL;
	gint result;
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	KzMozEmbed *kzembed;

	g_return_if_fail(KZ_IS_WINDOW(kz));
	g_return_if_fail(KZ_IS_MOZ_EMBED(widget));
	
	file_selector = GTK_FILE_SELECTION(gtk_file_selection_new ("Open file"));

	result = gtk_dialog_run(GTK_DIALOG(file_selector));
	
	switch (result)
	{
	 case GTK_RESPONSE_OK:
		filename = gtk_file_selection_get_filename(file_selector);
		break;
	 default:
		break;
	}
	if (filename)
		uri = g_strdup_printf("file://%s", filename);

	gtk_widget_destroy(GTK_WIDGET(file_selector));

	kzembed = KZ_MOZ_EMBED(widget);
	
	if (uri)
	{
		kz_moz_embed_load_url(kzembed, uri);
		g_free(uri);
	}
}


static void
act_open_selected_links (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	GList *list = NULL, *node;

	if (!KZ_IS_MOZ_EMBED(widget)) return;

	kz_moz_embed_get_links(KZ_MOZ_EMBED(widget), &list, TRUE);

	for (node = list; node; node = g_list_next(node))
	{
		KzBookmark *link = node->data;
		const gchar *uri;

		if (!link) continue;

		uri = kz_bookmark_get_link(link);
		if (!uri) continue;

		if (kz_bookmark_filter_out(link)) continue;

		kz_window_open_new_tab_with_parent(KZ_WINDOW(kz), uri,
						   widget);
	}

	g_list_foreach(list, (GFunc) g_object_unref, NULL);
	g_list_free(list);
}


#warning FIXME! we should unify act_open_selection().
static void
act_open_selected_text (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	gchar *text;
	EggRegex *egg_regex;
	gint n_match, i = 1;
	GError *error = NULL;

 	g_return_if_fail (KZ_IS_WINDOW((kz)));
 
	if (!KZ_IS_MOZ_EMBED(widget)) return;
	
	egg_regex = egg_regex_new(HTTP_REGEX, 
				  0,
				  0, &error);

	if (error)
	{
		g_error_free(error);
		return;
	}

	text = kz_moz_embed_get_selection_string(KZ_MOZ_EMBED(widget));
	if (!text) return;

	n_match = egg_regex_match(egg_regex, text, -1, 0);
	
	if (n_match > 0)
	{
		gchar **uri;
		uri = egg_regex_fetch_all (egg_regex, text);

		while (uri[i])
		{
			kz_window_open_new_tab_with_parent(KZ_WINDOW(kz),
							   uri[i],
							   widget);
			i++;
		}
		if (uri)
			g_strfreev(uri);
	}

	egg_regex_free(egg_regex);
	g_free(text);
}


static void
act_back (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_back(KZ_MOZ_EMBED(widget));
}


static void
act_forward (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_forward(KZ_MOZ_EMBED(widget));
}

#if 0
static void
act_show_history_menu (GtkAction *action, KzWindow *kz)
{
	int pos, count;
	int i;
	GtkWidget *menu;
	KzBookmark *history;
	KzMozEmbed *kzembed = KZ_MOZ_EMBED(KZ_WINDOW_CURRENT_PAGE(kz));
	guint32 activate_time;

	history = kz_bookmark_pure_folder_new();
	kz_bookmark_set_title(history, _("History"));

	kz_moz_embed_shistory_get_pos(kzembed, &pos, &count);

	menu = kz_bookmark_menu_create_submenu(history,
					       kz);
	
	for (i = 0; i < count; i++)
	{
		KzBookmark *bookmark;
		gchar *title, *uri;
	
		kz_moz_embed_shistory_get_nth (kzembed, i, FALSE,
					       &uri, &title);
		bookmark = kz_bookmark_new_with_attrs(title, uri, NULL);
		kz_bookmark_prepend(history, bookmark);
		g_object_unref(bookmark);	
	}
	gtk_widget_show(menu);
	activate_time = gtk_get_current_event_time();
	kz_actions_popup_bookmark_menu_modal(kz, history,
					     0,
					     activate_time);
}
#endif

static void
act_go_up (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_up(KZ_MOZ_EMBED(widget));
}


static void
act_open_selection (GtkAction *action, KzWindow *kz)
{
 	GtkAction *entry;
	GtkClipboard *clipboard;
	gchar *text;
 
 	g_return_if_fail (KZ_IS_WINDOW((kz)));
 
 	entry = gtk_action_group_get_action(kz->actions, "LocationEntry");
 
	clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);

	text = gtk_clipboard_wait_for_text(clipboard);
 	if (text)
	{
 		kz_entry_action_set_text (KZ_ENTRY_ACTION (entry), text);
 		gtk_action_activate(entry);
 		g_free (text);
 	}
}


static void
act_go_location (GtkAction *action, KzWindow *kz)
{
	GtkAction *entry;

	g_return_if_fail(KZ_IS_WINDOW(kz));	

	entry = gtk_action_group_get_action(kz->actions, "LocationEntry");
        gtk_action_activate(entry);
}


static void
act_index (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_index(KZ_MOZ_EMBED(widget));
}


static void
act_contents (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_contents(KZ_MOZ_EMBED(widget));
}


static void
act_start (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_start(KZ_MOZ_EMBED(widget));
}


static void
act_prev (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_prev(KZ_MOZ_EMBED(widget));
}


static void
act_next (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_go_next(KZ_MOZ_EMBED(widget));
}


static void 
act_stop (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_stop_load(KZ_MOZ_EMBED(widget));
}


static void
act_reload  (GtkAction *action, KzWindow *kz)
{
	GdkModifierType state = (GdkModifierType)0;
	gint x, y;
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	gdk_window_get_pointer(NULL, &x, &y, &state);

	widget = KZ_WINDOW_CURRENT_PAGE(kz);

	if (KZ_IS_MOZ_EMBED(widget))
		kz_moz_embed_reload(KZ_MOZ_EMBED(widget),
				    (state & GDK_SHIFT_MASK) ?
				    GTK_MOZ_EMBED_FLAG_RELOADBYPASSPROXYANDCACHE : 
				    GTK_MOZ_EMBED_FLAG_RELOADNORMAL);
}


static void 
act_stop_all (GtkAction *action, KzWindow *kz)
{
	gint i, num;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));

	for (i = num - 1; i >= 0; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);

		if (KZ_IS_MOZ_EMBED(widget))
			kz_moz_embed_stop_load(KZ_MOZ_EMBED(widget));
	}
}

static void
act_reload_all  (GtkAction *action, KzWindow *kz)
{
	GdkModifierType state = (GdkModifierType)0;
	gint x, y;
	gint i, num;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	gdk_window_get_pointer(NULL, &x, &y, &state);

	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));

	for (i = num - 1; i >= 0; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);

		if (KZ_IS_MOZ_EMBED(widget))
			kz_moz_embed_reload(KZ_MOZ_EMBED(widget),
					    (state & GDK_SHIFT_MASK) ?
					    GTK_MOZ_EMBED_FLAG_RELOADBYPASSCACHE : 
					    GTK_MOZ_EMBED_FLAG_RELOADNORMAL);
	}
}


static void 
act_view_source (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	GtkWidget *newtab;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
	{
		newtab = kz_window_open_new_tab(kz, NULL);

		kz_moz_embed_copy_page(KZ_MOZ_EMBED(widget),
				       KZ_MOZ_EMBED(newtab));
		kz_moz_embed_view_source(KZ_MOZ_EMBED(newtab),
					 kz_moz_embed_get_location(KZ_MOZ_EMBED(widget)));
	}
}


static void
act_find (GtkAction *action, KzWindow *kz)
{
	g_return_if_fail(GTK_IS_ACTION(action));
	g_return_if_fail(KZ_IS_WINDOW(kz));

	gtk_widget_grab_focus(kz->find_area);
}


static void
act_prev_tab (GtkAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));

	gtk_notebook_prev_page(GTK_NOTEBOOK(kz->notebook));
}


static void
act_next_tab (GtkAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));

	gtk_notebook_next_page(GTK_NOTEBOOK(kz->notebook));
}


static void
act_preference (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = kz_prefs_win_get_instance();
	gtk_window_set_transient_for (GTK_WINDOW(widget), GTK_WINDOW(kz));
	gtk_widget_show (widget);
	gdk_window_raise(widget->window);
}


static void
act_detaild_preference (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;
	gint num;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	widget = kz_window_open_new_tab(kz, "about:config");
	num = gtk_notebook_page_num(GTK_NOTEBOOK(kz->notebook), widget);
	gtk_notebook_set_current_page(GTK_NOTEBOOK(kz->notebook), num);
}


static void
act_ui_level (GtkRadioAction *action, GtkRadioAction *cur_action, KzWindow *kz)
{
	gint value;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	value = gtk_radio_action_get_current_value(action);

	switch (value) {
	case UI_BEGINNER:
		KZ_CONF_SET_STR("Global", "ui_level", "beginner");
		break;
	case UI_MEDIUM:
		KZ_CONF_SET_STR("Global", "ui_level", "medium");
		break;
	case UI_EXPERT:
		KZ_CONF_SET_STR("Global", "ui_level", "expert");
		break;
	case UI_CUSTOM:
		KZ_CONF_SET_STR("Global", "ui_level", "custom");
		break;
	default:
		break;
	}
}


static void
act_undo (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	widget = gtk_window_get_focus(GTK_WINDOW(kz));
	
	if (GTK_IS_EDITABLE (widget))
        {
        }
	else
	{
                KzMozEmbed *kzembed;

                kzembed = KZ_MOZ_EMBED(KZ_WINDOW_CURRENT_PAGE (kz));
                if (!KZ_IS_MOZ_EMBED(kzembed)) return;
		kz_moz_embed_do_command(kzembed,
				        "cmd_undo");
	}
}


static void
act_redo (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	widget = gtk_window_get_focus(GTK_WINDOW(kz));
	
	if (GTK_IS_EDITABLE (widget))
        {
        }
	else
	{
                KzMozEmbed *kzembed;

                kzembed = KZ_MOZ_EMBED(KZ_WINDOW_CURRENT_PAGE (kz));
                if (!KZ_IS_MOZ_EMBED(kzembed)) return;
		kz_moz_embed_do_command(kzembed,
				        "cmd_redo");
	}
}


static void
act_cut (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = gtk_window_get_focus(GTK_WINDOW(kz));

        if (GTK_IS_EDITABLE (widget))
        {
                gtk_editable_cut_clipboard (GTK_EDITABLE (widget));
        }
        else
        {
                KzMozEmbed *kzembed;

                kzembed = KZ_MOZ_EMBED(KZ_WINDOW_CURRENT_PAGE (kz));
                if (!KZ_IS_MOZ_EMBED(kzembed)) return;
                kz_moz_embed_cut_selection (kzembed);
        }
}


static void
act_copy (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = gtk_window_get_focus(GTK_WINDOW(kz));

        if (GTK_IS_EDITABLE (widget))
        {
                gtk_editable_copy_clipboard (GTK_EDITABLE (widget));
        }
        else
        {
                KzMozEmbed *kzembed;

                kzembed = KZ_MOZ_EMBED(KZ_WINDOW_CURRENT_PAGE (kz));
                if (!KZ_IS_MOZ_EMBED(kzembed)) return;
                kz_moz_embed_copy_selection (kzembed);
        }
}


static void
act_paste (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = gtk_window_get_focus(GTK_WINDOW(kz));

        if (GTK_IS_EDITABLE (widget))
        {
                gtk_editable_paste_clipboard (GTK_EDITABLE (widget));
        }
        else
        {
                KzMozEmbed *kzembed;

                kzembed = KZ_MOZ_EMBED(KZ_WINDOW_CURRENT_PAGE (kz));
                if (!KZ_IS_MOZ_EMBED(kzembed)) return;
                kz_moz_embed_paste (kzembed);
        }
}


static void
act_select_all (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = gtk_window_get_focus(GTK_WINDOW(kz));

        if (GTK_IS_EDITABLE (widget))
        {
                gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
        }
        else
        {
                KzMozEmbed *kzembed;

                kzembed = KZ_MOZ_EMBED(KZ_WINDOW_CURRENT_PAGE (kz));
                if (!KZ_IS_MOZ_EMBED(kzembed)) return;
                kz_moz_embed_select_all (kzembed);
        }
}


static void
act_copy_title (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;
	const gchar *text;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = KZ_WINDOW_CURRENT_PAGE(kz);
	if (!KZ_IS_MOZ_EMBED(widget)) return;

	text = kz_moz_embed_get_title(KZ_MOZ_EMBED(widget));
	gtkutil_copy_text(text);
}


static void
act_copy_url (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;
	const gchar *text;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = KZ_WINDOW_CURRENT_PAGE(kz);
	if (!KZ_IS_MOZ_EMBED(widget)) return;

	text = kz_moz_embed_get_location(KZ_MOZ_EMBED(widget));
	gtkutil_copy_text(text);
}


static void
act_get_body_text (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	g_return_if_fail(KZ_IS_WINDOW(kz));

	if (KZ_IS_MOZ_EMBED(widget))
	{
		gchar *text = kz_moz_embed_get_body_text(KZ_MOZ_EMBED(widget));
		g_free(text);
	}
}


static void
act_tab_pos (GtkRadioAction *action, GtkRadioAction *cur_action, KzWindow *kz)
{
	gint value;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	value = gtk_radio_action_get_current_value(cur_action);

	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(kz->notebook), value);
}


static void
act_tab_close_backward_all (GtkAction *action, KzWindow *kz)
{
	gint i, pos, num;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	pos = gtk_notebook_get_current_page(GTK_NOTEBOOK(kz->notebook));
	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));

	for (i = pos - 1; i >= 0; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);

		kz_window_close_tab(kz, widget);
	}
}


static void
act_tab_close_forward_all (GtkAction *action, KzWindow *kz)
{
	gint i, pos, num;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	pos = gtk_notebook_get_current_page(GTK_NOTEBOOK(kz->notebook));
	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));

	for (i = num - 1; i > pos; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);

		kz_window_close_tab(kz, widget);
	}
}


static void
act_tab_close_all_without_active (GtkAction *action, KzWindow *kz)
{
	gint i, pos, num;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	pos = gtk_notebook_get_current_page(GTK_NOTEBOOK(kz->notebook));
	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));

	for (i = num - 1; i >= 0; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);

		if (i == pos) continue;
		kz_window_close_tab(kz, widget);
	}
}


static void
act_bookmark_in_new_tab (GtkAction *action, KzWindow *kz)
{
	KzBookmark *bookmark;
	const gchar *uri;

	bookmark = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(bookmark));

	uri = kz_bookmark_get_link(bookmark);
	if (uri)
		kz_window_open_new_tab(kz, uri);
}


static void
open_all_bookmarks(KzWindow *kz, KzBookmark *folder, GtkWidget *parent,
		   gboolean recurse)
{
	GList *children, *node;
	const gchar *uri;

	folder = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));
	g_return_if_fail(kz_bookmark_is_folder(folder));

	children = kz_bookmark_get_children(folder);
	for (node = children; node; node = g_list_next(node))
	{
		KzBookmark *item = node->data;
		GtkWidget *widget = parent;

		uri = kz_bookmark_get_link(item);
		if (uri)
			widget = kz_window_open_new_tab_with_parent(kz, uri,
								    parent);

		if (kz_bookmark_is_folder(item) && recurse)
			open_all_bookmarks(kz, item, widget, recurse);
	}
	g_list_free(children);
}


static void
act_open_all_bookmarks (GtkAction *action, KzWindow *kz)
{
	KzBookmark *folder;
	GtkWidget *parent = NULL;
	const gchar *uri;
	gboolean confirm;
	
	folder = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));
	g_return_if_fail(kz_bookmark_is_folder(folder));

	/* confirmation */
	KZ_CONF_GET("Global", "confirm_open_bookmarks", confirm, BOOL);
	if (confirm)
	{
		GtkWidget *dialog;
		gint res;
		dialog = gtk_message_dialog_new(GTK_WINDOW(kz),
						GTK_DIALOG_DESTROY_WITH_PARENT,
						GTK_MESSAGE_QUESTION,
						GTK_BUTTONS_YES_NO,
						_("Open all bookmarks in this bookmark folder ?"));
		gtk_dialog_set_default_response(GTK_DIALOG(dialog),
						GTK_RESPONSE_YES);
		res = gtk_dialog_run(GTK_DIALOG(dialog));
		gtk_widget_destroy(dialog);
	
		if (res == GTK_RESPONSE_NO) return;
	}


	uri = kz_bookmark_get_link(folder);
	if (uri)
		parent = kz_window_open_new_tab_with_parent(kz, uri, parent);

	open_all_bookmarks(kz, folder, parent, FALSE);
}


static void
act_open_all_bookmarks_recursive (GtkAction *action, KzWindow *kz)
{
	KzBookmark *folder;
	GtkWidget *parent = NULL;
	const gchar *uri;

	folder = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));
	g_return_if_fail(kz_bookmark_is_folder(folder));

	uri = kz_bookmark_get_link(folder);
	if (uri)
		parent = kz_window_open_new_tab_with_parent(kz, uri, parent);

	open_all_bookmarks(kz, folder, parent, TRUE);
}


static void
act_add_bookmark (GtkAction *action, KzWindow *kz)
{
	KzBookmark *folder, *bookmark, *sibling = NULL;
	GtkWidget *widget;
	const gchar *title, *uri;
	gchar *desc;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	folder = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));

	if (!kz_bookmark_is_folder(folder))
	{
		sibling = folder;
		folder = kz_bookmark_get_parent(folder);
		g_return_if_fail(KZ_IS_BOOKMARK(folder));
	}

	widget = KZ_WINDOW_CURRENT_PAGE(kz);
	if (!KZ_IS_MOZ_EMBED(widget)) return;

	title = kz_moz_embed_ensure_title(KZ_MOZ_EMBED(widget));
	uri   = kz_moz_embed_get_location(KZ_MOZ_EMBED(widget));
	desc  = kz_moz_embed_get_selection_string(KZ_MOZ_EMBED(widget));

	if (!uri) return;

	bookmark = kz_bookmark_new_with_attrs(title, uri, desc);
	/* FIXME! show dialog */
	if (sibling)
		kz_bookmark_insert_before(folder, bookmark, sibling);
	else
		kz_bookmark_append(folder, bookmark);
	if (kz_bookmark_is_file(folder))
		kz_bookmark_save(folder);
	if (desc)
		g_free(desc);

	g_object_unref(G_OBJECT(bookmark));
}


static void
act_remove_bookmark (GtkAction *action, KzWindow *kz)
{
	KzBookmark *folder, *bookmark;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	bookmark = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(bookmark));

	folder = kz_bookmark_get_parent(bookmark);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));

	kz_bookmark_remove(folder, bookmark);
	if (kz_bookmark_is_file(folder))
		kz_bookmark_save(folder);
}


static void
act_edit_bookmark (GtkAction *action, KzWindow *kz)
{
	KzBookmark *bookmark;
	GtkWidget *widget;
	gboolean is_folder, is_file, is_editable, children_is_editable;

	bookmark = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(bookmark));

	is_folder = kz_bookmark_is_folder(bookmark);
	is_file   = kz_bookmark_is_file(bookmark);
	is_editable = kz_bookmark_is_editable(bookmark);
	if (is_file)
		children_is_editable = kz_bookmark_file_is_editable(bookmark);
	else if (is_folder && is_editable)
		children_is_editable = TRUE;
	else
		children_is_editable = FALSE;

	if (is_folder && children_is_editable)
	{
		widget = kz_bookmark_editor_new(bookmark);
		gtk_window_set_transient_for(GTK_WINDOW(widget), GTK_WINDOW(kz));
		gtk_widget_show (widget);
		gdk_window_raise(widget->window);
	}
	else
	{
		widget = kz_bookmark_edit_win_new(bookmark);
		gtk_widget_show(widget);
	}
}


static void
act_edit_bookmark_bars (GtkAction *action, KzWindow *kz)
{
	KzBookmark *bookmark;
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	bookmark = kz_bookmarks->bookmark_bars;
	g_return_if_fail(KZ_IS_BOOKMARK(bookmark));
	g_return_if_fail(kz_bookmark_is_folder(bookmark));

	widget = kz_bookmark_editor_new(bookmark);
	gtk_window_set_transient_for(GTK_WINDOW(widget), GTK_WINDOW(kz));
	gtk_widget_show (widget);
	gdk_window_raise(widget->window);
}

static void
act_edit_smart_bookmarks (GtkAction *action, KzWindow *kz)
{
	KzBookmark *bookmark;
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	bookmark = kz_bookmarks->smarts;
	g_return_if_fail(KZ_IS_BOOKMARK(bookmark));
	g_return_if_fail(kz_bookmark_is_folder(bookmark));

	widget = kz_bookmark_editor_new(bookmark);
	gtk_window_set_transient_for(GTK_WINDOW(widget), GTK_WINDOW(kz));
	gtk_widget_show (widget);
	gdk_window_raise(widget->window);
}


static void
act_update_bookmark (GtkAction *action, KzWindow *kz)
{
	KzBookmark *folder;

	folder = kz_actions_get_bookmark_for_action(kz);
	g_return_if_fail(KZ_IS_BOOKMARK(folder));
	g_return_if_fail(kz_bookmark_is_folder(folder));

	kz_bookmark_load_start(folder);
}


static void
act_add_scrap_bookmark (GtkAction *action, KzWindow *kz)
{
	KzBookmark *scrap = kz_bookmarks->scrap, *child;
	GtkWidget *embed;
	const gchar *title, *uri;
	gchar *desc = NULL;
	GTimeVal now;
	struct tm *date = NULL;
	time_t t;
	gchar link_string[20];
	gchar *link;

	if (!KZ_IS_WINDOW(kz)) return;

	embed = KZ_WINDOW_CURRENT_PAGE(kz);
	if (!KZ_IS_MOZ_EMBED(embed)) return;

	g_get_current_time(&now);

	title = kz_window_get_title(kz);
	uri   = kz_window_get_uri(kz);
	desc  = kz_moz_embed_get_selection_source(KZ_MOZ_EMBED(embed));

	child = kz_bookmark_new_with_attrs(title, uri, desc);
	kz_bookmark_set_location(child, uri);

	kz_bookmark_set_last_modified(child, now.tv_sec);
	
	t = (time_t)now.tv_sec;
	date = localtime(&t);

	/* link */
	strftime(link_string, 20, "#%Y%m%d%H%M%S", date);
	link = g_strdup_printf("file://%s%s",
			       kz_bookmark_get_location(scrap),
			       link_string);
	kz_bookmark_set_link(child, link);


	kz_bookmark_prepend(scrap, child);
	g_object_unref(child);

	if (desc)
		g_free(desc);
	/* save scrap.html */
	kz_bookmark_save(scrap);
}

static void
act_extract_links (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	GtkWidget *dialog;

	if (!GTK_IS_MOZ_EMBED(widget)) return;

	dialog = kz_links_dialog_new(kz, KZ_MOZ_EMBED(widget), FALSE);
	gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(kz));
	gtk_widget_show(dialog);
}


static void
act_extract_selected_links (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	GtkWidget *dialog;

	if (!GTK_IS_MOZ_EMBED(widget)) return;

	dialog = kz_links_dialog_new(kz, KZ_MOZ_EMBED(widget), TRUE);
	gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(kz));
	gtk_widget_show(dialog);
}


static gchar *
get_current_session_name (void)
{
	gchar *current_session;

	current_session = KZ_CONF_GET_STR("Session", "current_session");
	if (!current_session)
	{
		current_session = g_strdup("DefaultSession");
	}
	else if (!*current_session)
	{
		g_free(current_session);
		current_session = g_strdup("DefaultSession");
	}

	return current_session;
}


static void
act_save_session (GtkAction *action, KzWindow *kz)
{
	GList *list, *node;
	gchar *current_session;
	gint n_pages, i, pos;

	/* get current session name */
	current_session = get_current_session_name();

	/* clean saved session */
	list = kz_profile_enum_key(kz_session, current_session, TRUE);
	for (node = list; node; node = g_list_next(node))
		kz_profile_delete_key(kz_session, current_session, node->data);
	g_list_free(list);

	/* save opened URIs */
	n_pages = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));
	for (i = 0; i < n_pages; i++)
	{
		GtkWidget *widget = GTK_WIDGET(KZ_WINDOW_NTH_PAGE(kz, i));
		KzTabLabel *kztab;
		const gchar *uri;
		gboolean locked;
		gchar key[32], lockkey[32];

		if (!KZ_IS_MOZ_EMBED(widget)) continue;
		
		g_snprintf(key, G_N_ELEMENTS(key), "tab%d", i);

		uri = kz_moz_embed_get_location(KZ_MOZ_EMBED(widget));
		kz_profile_set_value(kz_session, current_session,
				     key, uri, sizeof(uri),
				     KZ_PROFILE_VALUE_TYPE_STRING);
		
		/* tab lock state */
		kztab = KZ_TAB_LABEL(gtk_notebook_get_tab_label(GTK_NOTEBOOK(kz->notebook),
								widget));
		locked = kz_tab_label_get_lock(kztab);
		g_snprintf(lockkey, G_N_ELEMENTS(lockkey), "lock%d", i);
		kz_profile_set_value(kz_session, current_session,
				     lockkey, &locked, sizeof(locked),
				     KZ_PROFILE_VALUE_TYPE_BOOL);
	}

	pos = gtk_notebook_get_current_page(GTK_NOTEBOOK(kz->notebook));
	kz_profile_set_value(kz_session, current_session,
			     "current_tab", &pos, sizeof(pos),
			     KZ_PROFILE_VALUE_TYPE_INT);

	g_free(current_session);
}


static void
act_restore_session (GtkAction *action, KzWindow *kz)
{
	GList *list, *node;
	gchar *current_session;
	gint i, num, pos = 0;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));
	for (i = num - 1; i >= 0; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);
		kz_window_close_tab(kz, widget);
	}

	/* get current session name */
	current_session = get_current_session_name();

	/* open saved URIs */
	list = kz_profile_enum_key(kz_session, current_session, TRUE);
	
	for (node = list; node; node = g_list_next(node))
	{
		const gchar *key = node->data;
		gchar *uri;

		if (!key_seems_sequential(key, "tab")) continue;

		uri = kz_profile_get_string(kz_session, current_session, key);
		kz_window_open_new_tab_at_tail(kz, uri);
		g_free(uri);
	}
	i = 0;
	/* set locked tab */
	for (node = list; node; node = g_list_next(node))
	{
		const gchar *key = node->data;
		gboolean locked;

		if (!key_seems_sequential(key, "lock")) continue;

		kz_profile_get_value(kz_session, current_session, key,
				     &locked, sizeof(locked),
				     KZ_PROFILE_VALUE_TYPE_BOOL);
		if (locked)
		{
			GtkWidget *child;
			KzTabLabel *kztab;
			child = KZ_WINDOW_NTH_PAGE(kz, i);
			kztab = KZ_TAB_LABEL(gtk_notebook_get_tab_label(GTK_NOTEBOOK(kz->notebook),
									child));
			kz_tab_label_set_lock(kztab, TRUE);
		}
		i++;
	}
	g_list_free(list);

	kz_profile_get_value(kz_session, current_session,
			     "current_tab", &pos, sizeof(pos),
			     KZ_PROFILE_VALUE_TYPE_INT);
	gtk_notebook_set_current_page(GTK_NOTEBOOK(kz->notebook), pos);

	g_free(current_session);
}


static void
act_about (GtkAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));
	kz_about_dialog_new(kz);
}


static void
act_copy_tab (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	KzMozEmbed *kzembed, *dkzembed;

	g_return_if_fail(KZ_IS_WINDOW(kz));
	g_return_if_fail(KZ_IS_MOZ_EMBED(widget));
	
	kzembed  = KZ_MOZ_EMBED(widget);	
	dkzembed = KZ_MOZ_EMBED(kz_window_open_new_tab(kz, NULL));

	kz_moz_embed_copy_page(kzembed, dkzembed);
	kz_moz_embed_shistory_copy(kzembed, dkzembed, TRUE, TRUE, TRUE);
}


static void
act_sidebar_pos (GtkRadioAction *action, GtkRadioAction *cur_action, KzWindow *kz)
{
	gint value;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	value = gtk_radio_action_get_current_value(action);
	kz_paned_set_position(KZ_PANED(kz->pane), value);
}


static void
act_print (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = KZ_WINDOW_CURRENT_PAGE(kz);
	if (!KZ_IS_MOZ_EMBED(widget)) return;

	kz_moz_embed_print(KZ_MOZ_EMBED(widget));
}

static void
act_print_preview (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	widget = KZ_WINDOW_CURRENT_PAGE(kz);
	if (!KZ_IS_MOZ_EMBED(widget)) return;

	kz_moz_embed_print_preview(KZ_MOZ_EMBED(widget));
}


static void
act_show_password_manager (GtkAction *action, KzWindow *kz)
{
	GtkWidget *dialog;

	dialog = kz_password_manager_dialog_new(kz);
	gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(kz));
	gtk_widget_show(dialog);
}

/* toggle actios */
static void
act_show_hide_sidebar(GtkAction *action, KzWindow *kz)
{
	gboolean active;
	g_return_if_fail(GTK_IS_TOGGLE_ACTION(action));
	g_return_if_fail(KZ_IS_WINDOW(kz));
	g_return_if_fail(GTK_IS_WIDGET(kz->sidebar));

	active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action));
	if (active)
		gtk_widget_show(kz->sidebar);
	else
		gtk_widget_hide(kz->sidebar);

	KZ_WINDOW_SET_VISIBLE(kz, "StockSidebarPosMenu", active);
}

static void
act_toggle_proxy_use(GtkAction *action, KzWindow *kz)
{
	gboolean use;
	g_return_if_fail(GTK_IS_TOGGLE_ACTION(action));
	g_return_if_fail(KZ_IS_WINDOW(kz));

	use = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action));
	KZ_CONF_SET("Global", "use_proxy", use, BOOL);
	KZ_WINDOW_SET_VISIBLE(kz, "StockProxyMenu", use);
}

#define CTRL "<control>"
#define SHFT "<shift>"
#define SFCT "<shift><control>"
#define ALT  "<alt>"
GtkActionEntry kz_actions[] =
{
  {"StockFileMenu",           NULL, N_("_File"),       NULL, NULL, NULL},
  {"StockEditMenu",           NULL, N_("_Edit"),       NULL, NULL, NULL},
  {"StockViewMenu",           NULL, N_("_View"),       NULL, NULL, NULL},
  {"StockTabMenu",            NULL, N_("_Tab"),        NULL, NULL, NULL},
  {"StockGoMenu",             NULL, N_("_Go"),         NULL, NULL, NULL},
  {"StockBookmarksMenu",      NULL, N_("_Bookmarks"),  NULL, NULL, NULL},
  {"StockOtherBookmarksMenu", NULL, N_("Other Bookmarks"),   NULL, NULL, NULL},
  {"StockToolsMenu",          NULL, N_("Too_ls"),      NULL, NULL, NULL},
  {"StockHelpMenu",           NULL, N_("_Help"),       NULL, NULL, NULL},
  {"StockUILevelMenu",        NULL, N_("UI Level"),    NULL, NULL, NULL},
  {"StockTabPosMenu",         NULL, N_("Tab _position"),     NULL, NULL, NULL},
  {"StockSidebarPosMenu",     NULL, N_("Sidebar position"),  NULL, NULL, NULL},
  {"StockInputMethodMenu",    NULL, N_("Input Methods"),     NULL, NULL, NULL},
  {"StockSessionMenu",        NULL, N_("Session"),           NULL, NULL, NULL},
  {"StockProxyMenu",          NULL, N_("Proxy"),             NULL, NULL, NULL},
  {"StockRecentCloseTabMenu", NULL, N_("Recent closed tabs"), NULL, NULL, NULL},

  {"NewWindow", KZ_STOCK_NEW_WINDOW, N_("_New Window"), CTRL"N",  N_("Open a new windw"), G_CALLBACK(act_new_window)},
  {"NewTab",    GTK_STOCK_NEW,       N_("New _Tab"),    CTRL"T",  N_("Open a new tab"), G_CALLBACK(act_new_tab)},

  {"FocusLocationEntry",        NULL, N_("Focus to location entry"),  NULL, N_("Move keyboard focus to location entry"), G_CALLBACK(act_focus_loc_ent)},
  {"ClearLocationEntry",        NULL, N_("Clear location entry and move keyboard focus to location entry"),  NULL, N_("Clear location entry and move keyboard focus to location entry"), G_CALLBACK(act_clear_loc_ent)},
  {"OpenSelection",         NULL,           N_("Open selection"),     NULL,     N_("Open selected text with smart bookmark of location entry"), G_CALLBACK(act_open_selection)},
  {"OpenSelectedText",         NULL,           N_("Open selected text"),     NULL,     N_("Open URIs extracted from selected text "), G_CALLBACK(act_open_selected_text)},
  {"Open",              GTK_STOCK_OPEN,     N_("_Open File"),          CTRL"O",  N_("Open a local file"), G_CALLBACK(act_open_file)},

  {"OpenSelectedLinks", KZ_STOCK_OPEN_SELECTED_LINK, N_("Open selected links"), CTRL"G",  N_("Open slected links"), G_CALLBACK(act_open_selected_links)},

  {"CloseWindow",    KZ_STOCK_CLOSE_WINDOW, N_("_Close Window"),       CTRL"Q",  N_("Close the current window"), G_CALLBACK(act_close_window)},
  {"CloseTab",          GTK_STOCK_CLOSE,    N_("Close Ta_b"),          CTRL"W",  N_("Close the current tab"), G_CALLBACK(act_close_tab)},

  {"SavePage",          GTK_STOCK_SAVE_AS,  N_("Save A_s"),            CTRL"S",  N_("Save the current page with a different name"), G_CALLBACK(act_save)},
	
  {"PrintPreview",     GTK_STOCK_PRINT_PREVIEW, N_("Print Preview"),  NULL,    N_("Print preview"), G_CALLBACK(act_print_preview)},
  {"Print",             GTK_STOCK_PRINT,        N_("_Print"),         CTRL"P", N_("Print the current page"), G_CALLBACK(act_print)},

  {"Undo",               GTK_STOCK_UNDO,        N_("_Undo"),          CTRL"Z", N_("Undo the last action"), G_CALLBACK(act_undo)},
  {"Redo",               GTK_STOCK_REDO,        N_("_Redo"),           SFCT"Z", N_("Redo the last undone action"), G_CALLBACK(act_redo)},
  {"Cut",                GTK_STOCK_CUT,         N_("C_ut"),           CTRL"X", N_("Cut the selection"), G_CALLBACK(act_cut)},
  {"Copy",               GTK_STOCK_COPY,        N_("_Copy"),          CTRL"C", N_("Copy the selection"), G_CALLBACK(act_copy)},
  {"Paste",              GTK_STOCK_PASTE,       N_("_Paste"),         CTRL"V", N_("Paste the clipboard"), G_CALLBACK(act_paste)},
  {"SelectAll", KZ_STOCK_SELECT_ALL,            N_("Select _All"),    CTRL"A", N_("Select the entire page"), G_CALLBACK(act_select_all)},
  {"CopyTitle",          NULL          ,        N_("Copy _Title"),    NULL,    N_("Copy the title of the current page"), G_CALLBACK(act_copy_title)},
  {"CopyURL",            KZ_STOCK_COPY_URL,     N_("Copy _URL"),      NULL,    N_("Copy the URL of the current page"), G_CALLBACK(act_copy_url)},
  {"Preference",         GTK_STOCK_PREFERENCES, N_("_Preference..."), NULL,    N_("Preference"), G_CALLBACK(act_preference)},
  {"DetailedPreference", NULL                 , N_("_Detailed Preference"), NULL, N_("Detailed preference"), G_CALLBACK(act_detaild_preference)},

  {"Back",          GTK_STOCK_GO_BACK,    N_("_Back"),          ALT"Left",  N_("Go to the previous visited page"), G_CALLBACK(act_back)},
  {"Forward",       GTK_STOCK_GO_FORWARD, N_("_Forward"),       ALT"Right", N_("Go to the next visited page"), G_CALLBACK(act_forward)},
  {"Reload",        GTK_STOCK_REFRESH,    N_("_Reload"),        CTRL"R",    N_("Display the latest content of the current page"), G_CALLBACK(act_reload)},
		                          
  {"GoUp",          GTK_STOCK_GO_UP,      N_("Go _Up"),         ALT"Up",    N_("Go up one level"), G_CALLBACK(act_go_up)},
  {"GotoLocation",  GTK_STOCK_JUMP_TO,    N_("Go to _Location"),NULL,       N_("Go to a specified location"), G_CALLBACK(act_go_location)},
		                          
  {"Index",         GTK_STOCK_INDEX,      N_("Index"),          NULL,       N_("Go to the index page"), G_CALLBACK(act_index)},
  {"Contents",      GTK_STOCK_GOTO_TOP,   N_("Contents"),       NULL,       N_("Go to the contents"), G_CALLBACK(act_contents)},
  {"Start",         GTK_STOCK_GOTO_FIRST, N_("Start"),          NULL,       N_("Go to the start page"), G_CALLBACK(act_start)},
  {"Prev",          GTK_STOCK_GO_BACK,    N_("Prev"),           NULL,       N_("Go to the previous page"), G_CALLBACK(act_prev)},
  {"Next",          GTK_STOCK_GO_FORWARD, N_("Next"),           NULL,       N_("Go to the next page"), G_CALLBACK(act_next)},
		                          
  {"Stop",          GTK_STOCK_STOP,       N_("_Stop"),          "Escape",   N_("Stop current data transfer"), G_CALLBACK(act_stop)},
  {"ReloadAll",     GTK_STOCK_REFRESH,    N_("Reload all"),     NULL,       NULL, G_CALLBACK(act_reload_all)},
  {"StopAll",       NULL,                 N_("Stop all"),       NULL,       NULL, G_CALLBACK(act_stop_all)},

  {"ViewPageSource", KZ_STOCK_VIEW_SOURCE, N_("ViewPageSource"), NULL, N_("View the source code of the page"), G_CALLBACK(act_view_source)},

  {"GetBodyText",    NULL, N_("Get Body Text"), NULL, NULL, G_CALLBACK(act_get_body_text)},

/*
  {"LocationEntry", N_("Location Entry"), GTK_STOCK_NEW,        NULL,     NULL, G_CALLBACK(act_location_enter), NULL, HISTORY_ACTION},
*/

  {"Find",          NULL,                 N_("Find"),         CTRL"F",  N_("Find a word or phrase in the page"), G_CALLBACK(act_find)},
  {"PrevTab", KZ_STOCK_TAB_PREV,    N_("_Previous Tab"),  ALT"L",   N_("Activate previous tab"), G_CALLBACK(act_prev_tab)},
  {"NextTab", KZ_STOCK_TAB_NEXT,    N_("_Next Tab"),      ALT"R",   N_("Activate next tab"), G_CALLBACK(act_next_tab)},

  {"CopyTab",       NULL, N_("_Copy Tab"),   NULL, N_("Duplicate the current tab"), G_CALLBACK(act_copy_tab)},

  {"CloseAllBackwardTab", KZ_STOCK_CLOSE_BACKWARD, N_("Close all _backward tabs"), NULL, NULL, G_CALLBACK(act_tab_close_backward_all)},
  {"CloseAllForwardTab", KZ_STOCK_CLOSE_FORWARD, N_("Close all _forward tabs"),  NULL, NULL, G_CALLBACK(act_tab_close_forward_all)},
  {"CloseAllTabWithoutActive", NULL, N_("Close all tabs without _active"), NULL, NULL, G_CALLBACK(act_tab_close_all_without_active)},

  {"OpenBookmarkInNewTab",      NULL, N_("Open the bookmark in new _tab"),   NULL,  NULL, G_CALLBACK(act_bookmark_in_new_tab)},
  {"OpenAllBookmarks",          NULL, N_("Open a_ll bookmarks"),             NULL,  NULL, G_CALLBACK(act_open_all_bookmarks)},
  {"OpenAllBookmarksRecursive", NULL, N_("Open all bookmarks _recursively"), NULL,  NULL, G_CALLBACK(act_open_all_bookmarks_recursive)},
  {"AddBookmark",               NULL, N_("_Add to bookmarks"),               NULL,  NULL, G_CALLBACK(act_add_bookmark)},
  {"RemoveBookmark",            NULL, N_("_Remove the bookmark"),            NULL,  NULL, G_CALLBACK(act_remove_bookmark)},
  {"EditBookmarks",             NULL, N_("_Edit bookmarks"),                 NULL,  NULL, G_CALLBACK(act_edit_bookmark)},
  {"EditBookmarkBars",          NULL, N_("Edit bookmark _bars"),             NULL,  NULL, G_CALLBACK(act_edit_bookmark_bars)},
  {"EditSmartBookmarks",        NULL, N_("Edit _smart bookmarks"),           NULL,  NULL, G_CALLBACK(act_edit_smart_bookmarks)},
  {"UpdateBookmarkFolder",      NULL, N_("_Update bookmark folder"),         NULL,  NULL, G_CALLBACK(act_update_bookmark)},
				      
  {"AddScrapBookmark",          NULL, N_("_Add scrap bookmark"),             NULL,  NULL, G_CALLBACK(act_add_scrap_bookmark)},

  {"ExtractLinks",         NULL, N_("_Extract links"), NULL,  NULL, G_CALLBACK(act_extract_links)},
  {"ExtractSelectedLinks", NULL, N_("E_xtract selected links"), NULL,  NULL, G_CALLBACK(act_extract_selected_links)},

  {"SaveSession",    NULL, N_("Save session"),    NULL, NULL, G_CALLBACK(act_save_session)},
  {"RestoreSession", NULL, N_("Restore session"), NULL, NULL, G_CALLBACK(act_restore_session)},
  /* {"SaveSessionAs", NULL, N_("Save session as ..."),        NULL, NULL, G_CALLBACK(act_save_session)}, */
  /* {"DeleteSession", NULL, N_("Delete current session"),     NULL, NULL, G_CALLBACK(act_save_session)}, */
  /* {"SwitchSession", NULL, N_("Switch current session ..."), NULL, NULL, G_CALLBACK(act_switch_session)}, */
  {"ShowPassword", NULL, N_("_Show Password Manager"), NULL,  NULL, G_CALLBACK(act_show_password_manager)},
  {"About",        NULL, N_("About Kazehakase"),       NULL,  N_("Display credits"), G_CALLBACK(act_about)},
};
const gint kz_actions_len = G_N_ELEMENTS(kz_actions);

static GtkToggleActionEntry kz_toggle_actions[] =
{
  {"ShowHideSidebar", NULL, N_("Sidebar"),          NULL, NULL, G_CALLBACK(act_show_hide_sidebar)},
  {"ToggleProxyUse",  NULL, N_("Toggle Proxy Use"), NULL, NULL, G_CALLBACK(act_toggle_proxy_use)}, 
};
static const gint kz_toggle_actions_len = G_N_ELEMENTS(kz_toggle_actions);

static GtkRadioActionEntry kz_sidebar_pos_radio_actions[] =
{
  {"SidebarPosTop",   NULL, N_("Sidebar _Top"),    NULL, NULL, GTK_POS_TOP},
  {"SidebarPosBottom",NULL, N_("Sidebar _Bottom"), NULL, NULL, GTK_POS_BOTTOM},
  {"SidebarPosLeft",  NULL, N_("Sidebar _Left"),   NULL, NULL, GTK_POS_LEFT},
  {"SidebarPosRight", NULL, N_("Sidebar _Right"),  NULL, NULL, GTK_POS_RIGHT},
};
static const gint kz_sidebar_pos_radio_actions_len = G_N_ELEMENTS(kz_sidebar_pos_radio_actions);

static GtkRadioActionEntry kz_ui_level_radio_actions[] =
{
  {"UILevelBeginner", NULL, N_("Beginner"), NULL, NULL, UI_BEGINNER},
  {"UILevelMedium",   NULL, N_("Medium"),   NULL, NULL, UI_MEDIUM},
  {"UILevelExpert",   NULL, N_("Expert"),   NULL, NULL, UI_EXPERT},
  {"UILevelCustom",   NULL, N_("Custom"),   NULL, NULL, UI_CUSTOM},
};
static const gint kz_ui_level_radio_actions_len = G_N_ELEMENTS(kz_ui_level_radio_actions);

static GtkRadioActionEntry kz_tab_pos_radio_actions[] =
{
  {"TabPosTop",     NULL, N_("Tab _Top"),    NULL, NULL, GTK_POS_TOP},
  {"TabPosBottom",  NULL, N_("Tab _Bottom"), NULL, NULL, GTK_POS_BOTTOM},
  {"TabPosLeft",    NULL, N_("Tab _Left"),   NULL, NULL, GTK_POS_LEFT},
  {"TabPosRight",   NULL, N_("Tab _Right"),  NULL, NULL, GTK_POS_RIGHT},
};
static const gint kz_tab_pos_radio_actions_len = G_N_ELEMENTS(kz_tab_pos_radio_actions);


static void
set_popup_menu_sensitive (KzWindow *kz, KzBookmark *bookmark)
{
	KzBookmark *bookmark_file;
	GtkAction *action;
	gboolean has_link, is_folder, is_file, has_children;
	gboolean children_is_editable, is_editable;

	g_return_if_fail(kz && bookmark);

	bookmark_file = kz_bookmark_get_parent_file(bookmark);

	has_link = kz_bookmark_get_link(bookmark) ? TRUE : FALSE;
	is_folder = kz_bookmark_is_folder(bookmark);
	is_file = kz_bookmark_is_file(bookmark);
	has_children = kz_bookmark_has_children(bookmark);
	is_editable = kz_bookmark_is_editable(bookmark);
	if (is_file)
		children_is_editable = kz_bookmark_file_is_editable(bookmark);
	else if (is_folder && is_editable)
		children_is_editable = TRUE;
	else
		children_is_editable = FALSE;

	action = gtk_action_group_get_action(kz->actions,
					     "OpenBookmarkInNewTab");
	g_object_set(action, "sensitive", has_link, NULL);

	action = gtk_action_group_get_action(kz->actions,
					     "OpenAllBookmarks");
	g_object_set(action, "sensitive", is_folder && has_children, NULL);

	action = gtk_action_group_get_action(kz->actions,
					     "AddBookmark");
	g_object_set(action, "sensitive", ((is_file && children_is_editable) ||
					  (!is_file && is_editable)), NULL);

	action = gtk_action_group_get_action(kz->actions,
					     "RemoveBookmark");
	g_object_set(action, "sensitive", is_editable, NULL);

	action = gtk_action_group_get_action(kz->actions,
					     "EditBookmarks");
	g_object_set(action, "sensitive", (is_editable  || children_is_editable)
					, NULL);

	action = gtk_action_group_get_action(kz->actions,
					     "UpdateBookmarkFolder");
	g_object_set(action, "sensitive", is_file, NULL);
}


static void
combine_favicon(GtkAction *action, const gchar *uri, KzWindow *kz)
{
	GtkWidget *widget;
	GSList *node, *proxies;
	KzFavicon *kzfav = kz->kzfav;

	proxies = gtk_action_get_proxies(action);
	for (node = proxies; node; node = g_slist_next(node))
	{
		GtkWidget *image;
		GdkPixbuf *favicon = NULL;
		if (!GTK_IS_WIDGET(node->data))
			continue;

		widget = GTK_WIDGET(node->data);
		
		if (!GTK_IS_IMAGE_MENU_ITEM(widget) && 
		    !GTK_IS_TOOL_BUTTON(widget))
			continue;

		if (GTK_IS_IMAGE_MENU_ITEM(widget))
		{
			gchar *stock_id;
			favicon = kz_favicon_get_pixbuf(kzfav, uri,
							GTK_ICON_SIZE_MENU);
			image = gtk_image_menu_item_get_image(GTK_IMAGE_MENU_ITEM(widget));
			g_object_get(G_OBJECT(action),
				     "stock_id", &stock_id,
				     NULL);
			gtkutil_superpose_pixbuf(image, favicon,
						 stock_id,
						 GTK_ICON_SIZE_MENU);
			g_free(stock_id);
		}
		else if (GTK_IS_TOOL_BUTTON(widget))
		{
			gchar *stock_id;
			favicon = kz_favicon_get_pixbuf(kzfav, uri,
							GTK_ICON_SIZE_BUTTON);
			image = gtk_image_new();
			g_object_get(G_OBJECT(action),
				     "stock_id", &stock_id,
				     NULL);
			gtkutil_superpose_pixbuf(image, favicon,
						 stock_id,
						 GTK_ICON_SIZE_BUTTON);
			gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(widget),
							image);
			gtk_widget_show(image);
			g_free(stock_id);
		}
		if (favicon)
			g_object_unref(favicon);
	}
}


void
kz_actions_set_selection_sensitive (KzWindow *kz, KzMozEmbed *kzembed)
{
	GtkWidget *focus;
	gboolean can_copy = FALSE, can_cut = FALSE, can_paste = FALSE;

	focus = gtk_window_get_focus(GTK_WINDOW(kz));

#warning FIXME! /* should track all GtkEditable's event and Mozilla's selection */
	if (kzembed && !kz_moz_embed_selection_is_collapsed(kzembed))
	{
		KZ_WINDOW_SET_SENSITIVE(kz, "OpenSelectedLinks", TRUE);
	}
	else
	{
		KZ_WINDOW_SET_SENSITIVE(kz, "OpenSelectedLinks", FALSE);
	}

	if (GTK_IS_EDITABLE(focus))
	{
		gboolean selected = FALSE;
		selected = gtk_editable_get_selection_bounds
				(GTK_EDITABLE(focus), NULL, NULL);
		if (selected)
		{
			can_cut   = TRUE;
			can_copy  = TRUE;
		}
		can_paste = TRUE;
	}
	else if (KZ_IS_MOZ_EMBED(kzembed))
	{
		can_cut   = kz_moz_embed_can_cut_selection(kzembed);
		can_copy  = kz_moz_embed_can_copy_selection(kzembed);
		can_paste = kz_moz_embed_can_paste(kzembed);
	}

	KZ_WINDOW_SET_SENSITIVE(kz, "Cut",   can_cut);
	KZ_WINDOW_SET_SENSITIVE(kz, "Copy",  can_copy);
	KZ_WINDOW_SET_SENSITIVE(kz, "Paste", can_paste);	

	KZ_WINDOW_SET_SENSITIVE(kz, "AddScrapBookmark", can_copy);
}


void
kz_actions_set_sensitive (KzWindow *kz, KzMozEmbed *kzembed)
{
	KzTabLabel *kztab;
	gboolean can_go_back = FALSE;
	gboolean can_go_forward = FALSE;
	gboolean can_go_up = FALSE;
	gboolean can_stop = FALSE;
	gboolean can_stop_all = FALSE;
	gboolean can_go_index = FALSE, can_go_contents = FALSE,
		 can_go_start = FALSE, can_go_prev = FALSE, can_go_next = FALSE;
	gboolean can_close_tab = TRUE;
	gint i, num, pos = 0;
	GtkAction *action;
	gboolean active;
	KzStopReloadActionState state;
	
	g_return_if_fail (KZ_IS_WINDOW(kz));
	/* g_return_if_fail (KZ_IS_MOZ_EMBED (kzembed)); */

	num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));

	if (kzembed)
	{
		kztab = KZ_TAB_LABEL(kz_window_get_tab_label(kz, GTK_WIDGET(kzembed)));

		can_stop        = kz_moz_embed_is_loading(kzembed);
		can_go_back     = kz_moz_embed_can_go_back(kzembed);
		can_go_forward  = kz_moz_embed_can_go_forward(kzembed);
		can_go_up       = kz_moz_embed_can_go_up(kzembed);
		can_go_index    = kz_moz_embed_can_go_index(kzembed);
		can_go_contents = kz_moz_embed_can_go_contents(kzembed);
		can_go_start    = kz_moz_embed_can_go_start(kzembed);
		can_go_prev     = kz_moz_embed_can_go_prev(kzembed);
		can_go_next     = kz_moz_embed_can_go_next(kzembed);
		
		can_close_tab = !kz_tab_label_get_lock(kztab);

		pos = gtk_notebook_page_num(GTK_NOTEBOOK(kz->notebook),
					    GTK_WIDGET(kzembed));
		for (i = 0; i< num; i++)
		{
			GtkWidget *widget;

			widget = KZ_WINDOW_NTH_PAGE(kz, i);
			if (!KZ_IS_MOZ_EMBED(widget)) continue;
			can_stop_all
				= kz_moz_embed_is_loading(KZ_MOZ_EMBED(widget));
			if (can_stop_all) break;
		}
	}

	if (num > 0)
	{
		KZ_WINDOW_SET_SENSITIVE(kz, "Back",      can_go_back);
		action = gtk_action_group_get_action(kz->actions,
						     "Back");
		if (can_go_back)
		{
			gchar *uri = NULL, *title = NULL;
			kz_moz_embed_shistory_get_nth(kzembed, -1,
						      TRUE, &uri, &title);
			if (uri)
			{
				combine_favicon(action, uri, kz);
				g_free(uri);
			}
			if (title)
				g_free(title);
		}
		else 
			combine_favicon(action, NULL, kz);

		KZ_WINDOW_SET_SENSITIVE(kz, "Forward",   can_go_forward);
		action = gtk_action_group_get_action(kz->actions,
						     "Forward");
		if (can_go_forward)
		{
			gchar *uri = NULL, *title = NULL;
			kz_moz_embed_shistory_get_nth(kzembed, 1,
						      TRUE, &uri, &title);
			if (uri)
			{
				combine_favicon(action, uri, kz);
				g_free(uri);
			}
			if (title)
				g_free(title);
		}
		else 
			combine_favicon(action, NULL, kz);

		KZ_WINDOW_SET_SENSITIVE(kz, "GoUp",      can_go_up);
		KZ_WINDOW_SET_SENSITIVE(kz, "Stop",      can_stop);
		KZ_WINDOW_SET_SENSITIVE(kz, "Reload",    !can_stop);
		KZ_WINDOW_SET_SENSITIVE(kz, "StopAll",   can_stop_all);
		KZ_WINDOW_SET_SENSITIVE(kz, "ReloadAll", TRUE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseTab",  can_close_tab);
		KZ_WINDOW_SET_SENSITIVE(kz, "Search",    TRUE);
		KZ_WINDOW_SET_SENSITIVE(kz, "ExtractLinks", TRUE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CopyTitle",    TRUE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CopyURL",      TRUE);
		KZ_WINDOW_SET_SENSITIVE(kz, "Index",    can_go_index);
		KZ_WINDOW_SET_SENSITIVE(kz, "Contents", can_go_contents);
		KZ_WINDOW_SET_SENSITIVE(kz, "Start",    can_go_start);
		KZ_WINDOW_SET_SENSITIVE(kz, "Prev",     can_go_prev);
		KZ_WINDOW_SET_SENSITIVE(kz, "Next",     can_go_next);
		KZ_WINDOW_SET_VISIBLE  (kz, "Index",    can_go_index);
		KZ_WINDOW_SET_VISIBLE  (kz, "Contents", can_go_contents);
		KZ_WINDOW_SET_VISIBLE  (kz, "Start",    can_go_start);
		KZ_WINDOW_SET_VISIBLE  (kz, "Prev",     can_go_prev);
		KZ_WINDOW_SET_VISIBLE  (kz, "Next",     can_go_next);
		KZ_WINDOW_SET_VISIBLE  (kz, "Stop",     can_stop);
		KZ_WINDOW_SET_VISIBLE  (kz, "Reload",   !can_stop);

		/* Stop/Reload action */
		KZ_WINDOW_SET_SENSITIVE(kz, "StopReload",      TRUE);
		action = gtk_action_group_get_action(kz->actions,
						     "StopReload");
		state = can_stop?KZ_STOP_RELOAD_ACTION_STATE_STOP:KZ_STOP_RELOAD_ACTION_STATE_RELOAD;
		kz_stop_reload_action_set_state(
			KZ_STOP_RELOAD_ACTION(action),
			state);

		action = gtk_action_group_get_action(kz->actions,
						     "PrevTab");
		if (pos == 0)
		{
			KZ_WINDOW_SET_SENSITIVE(kz, "PrevTab", FALSE);
			combine_favicon(action, NULL, kz);
		}
		else
		{
			KzMozEmbed *prev = KZ_MOZ_EMBED(KZ_WINDOW_NTH_PAGE(kz, pos - 1));
			const gchar* uri = kz_moz_embed_get_location(prev);
			/* set favicon */
			combine_favicon(action, uri, kz);
			KZ_WINDOW_SET_SENSITIVE(kz, "PrevTab", TRUE);
		}

		action = gtk_action_group_get_action(kz->actions,
						     "NextTab");
		if (pos == num - 1)
		{
			KZ_WINDOW_SET_SENSITIVE(kz, "NextTab", FALSE);
			combine_favicon(action,	NULL, kz);
		}
		else
		{
			KzMozEmbed *next = KZ_MOZ_EMBED(KZ_WINDOW_NTH_PAGE(kz, pos + 1));
			const gchar* uri = kz_moz_embed_get_location(next);
			/* set favicon */
			combine_favicon(action,	uri, kz);
			KZ_WINDOW_SET_SENSITIVE(kz, "NextTab", TRUE);
		}
	}
	else
	{
		KZ_WINDOW_SET_VISIBLE  (kz, "Stop",      FALSE);
		KZ_WINDOW_SET_VISIBLE  (kz, "Reload",    TRUE);
		KZ_WINDOW_SET_SENSITIVE(kz, "Back",      FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "Forward",   FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "Stop",      FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "Reload",    FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "StopAll",   FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "ReloadAll", FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseTab",  FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "PrevTab",   FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "NextTab",  FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "Search",    FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "ExtractLinks", FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CopyTitle",    FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CopyURL",      FALSE);
		
		/* Stop/Reload action */
		KZ_WINDOW_SET_SENSITIVE(kz, "StopReload",      FALSE);
		action = gtk_action_group_get_action(kz->actions,
						     "StopReload");
		kz_stop_reload_action_set_state(
			KZ_STOP_RELOAD_ACTION(action),
			KZ_STOP_RELOAD_ACTION_STATE_RELOAD);
	}

	if (num > 1)
	{
		if (pos == 0)
		{
			KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllBackwardTab", FALSE);
		}
		else
		{
			KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllBackwardTab", TRUE);
		}

		if (pos == num - 1)
		{
			KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllForwardTab", FALSE);
		}
		else
		{
			KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllForwardTab", TRUE);
		}

		KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllTabWithoutActive", TRUE);
	}
	else
	{
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllBackwardTab",      FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllForwardTab",       FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllTabWithoutActive", FALSE);
	}

	kz_actions_set_selection_sensitive (kz, kzembed);
	
	/* Sidebar position menu */
	action = gtk_action_group_get_action(kz->actions,
					     "ShowHideSidebar");
	active = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
	KZ_WINDOW_SET_VISIBLE(kz, "StockSidebarPosMenu", active);

	set_popup_menu_sensitive(kz, kz_bookmarks->menu);
}


void
add_accel_entry(GtkAction *action, GtkAccelGroup *accel_group,
		const gchar *key)
{
	guint accel_key = 0;
	GdkModifierType accel_mods = 0;
	gchar *accel_path;
	
	accel_path = g_strconcat("<Actions>/KzWindow/",
				 gtk_action_get_name(action),
				 NULL);

	if (accel_group)
		gtk_action_set_accel_path(action,
					  accel_path);
	gtk_accelerator_parse(key,
			      &accel_key,
			      &accel_mods);
	if (accel_key)
		gtk_accel_map_add_entry(accel_path, accel_key, accel_mods);

	g_free(accel_path);
}


GtkActionGroup *
kz_actions_create_group (KzWindow *kz, GtkAccelGroup *accel_group)
{
	GtkActionGroup *action_group;
	GtkAction *action;
	GList *node, *action_list;

	action_group = gtk_action_group_new("KzWindow");
	gtk_action_group_set_translation_domain(action_group, NULL);

	gtk_action_group_add_actions(action_group,
				     kz_actions,
				     kz_actions_len,
				     kz);
	gtk_action_group_add_toggle_actions(action_group,
					    kz_toggle_actions,
					    kz_toggle_actions_len,
					    kz);
	gtk_action_group_add_radio_actions(action_group,
					   kz_sidebar_pos_radio_actions,
					   kz_sidebar_pos_radio_actions_len,
					   0,
					   G_CALLBACK(act_sidebar_pos),
					   kz);
	gtk_action_group_add_radio_actions(action_group,
					   kz_ui_level_radio_actions,
					   kz_ui_level_radio_actions_len,
					   0,
					   G_CALLBACK(act_ui_level),
					   kz);
	gtk_action_group_add_radio_actions(action_group,
					   kz_tab_pos_radio_actions,
					   kz_tab_pos_radio_actions_len,
					   -1,
					   G_CALLBACK(act_tab_pos),
					   kz);

	/* StopReload action */
	{
		action = GTK_ACTION(kz_stop_reload_action_new(kz));
		gtk_action_group_add_action(action_group, action);
		g_object_unref(action);
	}

	/* Scrap Bookmark Action */
	{
		action = GTK_ACTION(kz_scrap_bookmark_action_new(kz_bookmarks->scrap, kz));
		gtk_action_group_add_action_with_accel(action_group,
						       action,
						       "<alt>Home");
		g_object_unref(action);
	}

	action_list = gtk_action_group_list_actions(action_group);
	
	for (node = action_list; node; node = g_list_next(node))
	{
		gtk_action_set_accel_group(GTK_ACTION(node->data),
					   accel_group);
		gtk_action_connect_accelerator(GTK_ACTION(node->data));
	}
	g_list_free(action_list);

	return action_group;
}


GCallback
kz_actions_get_func_from_name (const gchar *name)
{
	gint i;

	if (!name || !*name) return NULL;

	for (i = 0; i < kz_actions_len; i++)
		if (!strcmp(name, kz_actions[i].name))
			return kz_actions[i].callback;

	return NULL;
}


KzBookmark *
kz_actions_get_bookmark_for_action (KzWindow *kz)
{
	KzBookmark *bookmark;

	g_return_val_if_fail(KZ_IS_WINDOW(kz), NULL);

	if (!bookmark_quark)
		bookmark_quark = g_quark_from_string("KzAction::KzBookmark");
	bookmark = g_object_get_qdata(G_OBJECT(kz), bookmark_quark);

	if (KZ_IS_BOOKMARK(bookmark))
		return bookmark;

	return kz_bookmarks->menu;
}


void
kz_actions_set_bookmark_for_action (KzWindow *kz, KzBookmark *bookmark)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));
	g_return_if_fail(!bookmark || KZ_IS_BOOKMARK(bookmark));

	if (!bookmark_quark)
		bookmark_quark = g_quark_from_string("KzAction::KzBookmark");
	g_object_set_qdata(G_OBJECT(kz), bookmark_quark, bookmark);
}


static void
cb_popup_menu_hide (void)
{
	gtk_main_quit();
}


void
kz_actions_popup_bookmark_menu_modal (KzWindow *kz, KzBookmark *bookmark,
				      guint button, guint time)
{
	GtkWidget *popup_menu = NULL;
	gchar path[64];

	g_return_if_fail(KZ_IS_BOOKMARK(bookmark));

	kz_actions_set_bookmark_for_action (kz, bookmark);

	g_snprintf(path, sizeof(path), "/BookmarkPopup%s",
		   kz_ui_level_to_suffix(kz_ui_level()));
	popup_menu = gtk_ui_manager_get_widget(kz->menu_merge, path);
	if (!popup_menu) return;

	g_signal_connect(G_OBJECT(popup_menu), "hide",
			 G_CALLBACK(cb_popup_menu_hide), NULL);
	set_popup_menu_sensitive (kz, bookmark);
	gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL,
		       NULL, NULL, button, time);
	gtk_main();
	g_signal_handlers_disconnect_by_func(G_OBJECT(popup_menu),
					     G_CALLBACK(cb_popup_menu_hide),
					     NULL);

	kz_actions_set_bookmark_for_action (kz, NULL);

	set_popup_menu_sensitive (kz, kz_bookmarks->menu);
}


void
kz_actions_insert_smartbookmark (KzWindow *kz, KzBookmark *bookmark,
				 KzBookmark *child, KzBookmark *sibling)
{
	GtkAction *action;
	const gchar *action_name;
	const gchar *title;
	guint id;
	gchar path[64] = {0};
	
	if (!kz_bookmark_is_smart(child) &&
	    !kz_bookmark_is_folder(child)) return;
	
	id = gtk_ui_manager_new_merge_id(kz->menu_merge);
	
	title = kz_bookmark_get_title(child);
	/*
	 * We should unite KzLocationEntry and KzSmartBookmark.
	 */
	if (title && !strncmp(title, "LocationEntry", 13))
	{
		action = GTK_ACTION(kz_location_entry_action_new
				   (kz, child));
	}
	else
	{
		action = GTK_ACTION(kz_smart_bookmark_action_new
				   (kz, child));
	}

	if (!action) return;

	action_name = gtk_action_get_name(action);

	gtk_action_group_add_action(kz->actions,
				    action);
	if (title && !strncmp(title, "LocationEntry", 13))
	{
		g_snprintf(path, sizeof(path), "/MainToolBar%s/LocationEntry",
			   kz_ui_level_to_suffix(kz_ui_level()));
	}
	else
	{
		g_snprintf(path, sizeof(path), "/MainToolBar%s/SmartBookmark",
			   kz_ui_level_to_suffix(kz_ui_level()));
	}
	gtk_ui_manager_add_ui(kz->menu_merge,
			      id, path,
			      action_name, 
			      action_name,
			      GTK_UI_MANAGER_TOOLITEM, FALSE);
	g_object_set_data(G_OBJECT(action), action_name, 
			  GUINT_TO_POINTER(id));
	g_object_unref(action);
}

void
kz_actions_remove_smartbookmark (KzWindow *kz, KzBookmark *bookmark,
				 KzBookmark *child)
{
	GtkAction *action;
	gpointer p;
	guint id;
	gchar *action_name;
	const gchar *title;

	title = kz_bookmark_get_title(child);
	 
	if (title && !strncmp(title, "LocationEntry", 13))
		action_name = g_strdup("LocationEntry");
	else
		action_name = g_strdup_printf("SmartBookmark:%p", child);

	action = gtk_action_group_get_action(kz->actions,
					     action_name);
	
	if (action)
	{
		p = g_object_get_data(G_OBJECT(action),
				      action_name);
		if (p)
		{
			id = GPOINTER_TO_UINT(p);
			gtk_ui_manager_remove_ui(kz->menu_merge, id);
			id = 0;
			g_object_set_data(G_OBJECT(action),
					  action_name,
					  GUINT_TO_POINTER(id));
		}
		gtk_action_group_remove_action(kz->actions,
					       action);
	}
	g_free(action_name);
}

void
kz_actions_update_smartbookmarks (KzWindow *kz, KzBookmark *bookmark)
{
	GList *children, *node;
	
	children = kz_bookmark_get_children(bookmark);
	for (node = children; node; node = g_list_next(node))
	{
		gchar path[64] = {0};
		gpointer p;
		guint id;
		gchar *action_name;
		const gchar *title;
		GtkAction *action, *new_action = NULL;
		KzBookmark *child= node->data;


		if (!kz_bookmark_is_smart(child) &&
	    	    !kz_bookmark_is_folder(child)) continue;
		
		title = kz_bookmark_get_title(child);
	 
		if (title && !strncmp(title, "LocationEntry", 13))
			action_name = g_strdup("LocationEntry");
		else
			action_name = g_strdup_printf("SmartBookmark:%p", child);

		/* remove old one */
		action = gtk_action_group_get_action(kz->actions,
						     action_name);
		if (action)
		{
			p = g_object_get_data(G_OBJECT(action),
					      action_name);
			if (p)
			{
				id = GPOINTER_TO_UINT(p);
				gtk_ui_manager_remove_ui(kz->menu_merge,
							 id);
			}
		}
		else
		{
			/* add new one */
			if (title && !strncmp(title, "LocationEntry", 13))
			{
				new_action = GTK_ACTION(kz_location_entry_action_new
					   (kz, child));
			}
			else
			{
				new_action = GTK_ACTION(kz_smart_bookmark_action_new
						   (kz, child));
			}
			
			if (new_action)
			{
				gtk_action_group_add_action(kz->actions,
							    new_action);
			}
			action = new_action;
		}
		
		if (!action)
		{
			g_free(action_name);
			continue;
		}

		id = gtk_ui_manager_new_merge_id(kz->menu_merge);
		if (title && !strncmp(title, "LocationEntry", 13))
		{
			g_snprintf(path, sizeof(path), "/MainToolBar%s/LocationEntry",
				   kz_ui_level_to_suffix(kz_ui_level()));
		}
		else
		{
			g_snprintf(path, sizeof(path), "/MainToolBar%s/SmartBookmark",
				   kz_ui_level_to_suffix(kz_ui_level()));
		}
		gtk_ui_manager_add_ui(kz->menu_merge,
				      id, path,
				      action_name, 
				      action_name,
				      GTK_UI_MANAGER_TOOLITEM, FALSE);
		g_object_set_data(G_OBJECT(action), 
				  action_name, 
				  GUINT_TO_POINTER(id));
		if (new_action)
			g_object_unref(new_action);
		g_free(action_name);
	}
	g_list_free(children);
}


