/* -*- 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 <glib/gi18n.h>

#include "gtk-utils.h"
#include "glib-utils.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 "kz-copy-format-dialog.h"
#include "kz-smart-bookmark.h"
#include "kz-bookmark.h"
#include "kz-bookmark-editor.h"
#include "kz-bookmark-edit-win.h"
#include "kz-bookmark-filter.h"
#include "kz-bookmark-file.h"
#include "kz-bookmark-folder.h"
#include "kz-entry-action.h"
#include "kz-location-entry-action.h"
#include "kz-navigation-action.h"
#include "kz-stop-reload-action.h"
#include "kz-smart-bookmark-action.h"
#include "kz-zoom-action.h"
#include "kz-web.h"
#include "kz-actions-download.h"
#include "kz-actions-popup.h"
#include "kz-actions-dynamic.h"
#include "kz-about-dialog.h"
#include "kz-paned.h"
#include "kz-bookmark-menu.h"
#include "kz-autoscroller.h"
#include "kz-popup-tablist.h"
#include "kz-proxy-folder.h"
#include "kz-icons.h"
#include "kz-statusbar.h"
#include "kz-notebook.h"
#include "kz-session.h"
#include "glib-utils.h"

#include <time.h>

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

enum {
	UI_BEGINNER,
	UI_MEDIUM,
	UI_EXPERT,
	UI_CUSTOM
};

enum {
#ifdef WITH_GECKO
	KZ_LAYOUT_ENGINE_GECKO,
#endif
#ifdef WITH_WEBKIT_GTK
	KZ_LAYOUT_ENGINE_WEBKIT_GTK,
#endif
#ifdef WITH_GTK_IE_EMBED
	KZ_LAYOUT_ENGINE_GTK_IE_EMBED,
#endif
};

static GQuark bookmark_quark = 0;

static void
act_save (GtkAction *action, KzWindow *kz)
{
	KzWeb *kzweb;
	gchar *filename;

	g_return_if_fail(KZ_IS_WINDOW(kz));
	kzweb = KZ_WINDOW_CURRENT_WEB(kz);
        if (!kzweb)
                return;
	
	filename = kz_actions_download_open_save_dialog(GTK_WINDOW(kz),
							kz_web_get_location(kzweb),
							TRUE);
	if (filename)
	{
		kz_web_save_with_content(kzweb, filename);
		g_free(filename);
	}	
}


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

	gtk_widget_destroy(GTK_WIDGET(kz));
}


static void
act_close_tab (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	if (web)
		kz_window_close_tab(kz, web);
}


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

	g_return_if_fail(KZ_IS_WINDOW(kz));

	widget = KZ_CREATE_NEW_WINDOW(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(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 = kz_notebook_page_num(KZ_NOTEBOOK(kz->notebook),
					       widget);
		if(num != -1)
			kz_notebook_set_current_page(KZ_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(kz, "destroy",
					 G_CALLBACK(cb_remove_idle), NULL);
		}
	}
}


static void
act_focus_loc_ent (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = NULL;
	GtkAction *ent_ac;

	widget = gtk_ui_manager_get_widget(kz->menu_merge, 
					   "/MainToolBar/LocationEntry");

	ent_ac = gtk_action_group_get_action(kz->actions, "LocationEntry");

	if(widget)
	{
		GtkEntry *entry;
		entry = kz_entry_action_get_entry_widget(KZ_ENTRY_ACTION(ent_ac),
							 widget);
		gtk_widget_grab_focus(GTK_WIDGET(entry));
	}
}

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

	kz_window_set_location_entry_text(kz, NULL);
	gtk_action_activate(focus_action);
}

static void
act_open_file (GtkAction *action, KzWindow *kz)
{
	GtkWidget *file_dialog;
	gchar *filename = NULL;
	gchar *uri = NULL;
	gint result;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	file_dialog = gtk_file_chooser_dialog_new (_("Open file"),
						   GTK_WINDOW(kz),
						   GTK_FILE_CHOOSER_ACTION_OPEN,
						   GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
						   GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
						   NULL);

	result = gtk_dialog_run(GTK_DIALOG(file_dialog));
	
	switch (result)
	{
	 case GTK_RESPONSE_ACCEPT:
		filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_dialog));
		break;
	 default:
		break;
	}

	if (filename)
        {
		uri = g_filename_to_uri(filename, NULL, NULL);
		g_free(filename);
        }

	gtk_widget_destroy(file_dialog);

	if (uri)
	{
		kz_window_load_url(kz, uri);
		g_free(uri);
	}
}


static void
act_open_selected_links (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	GList *list = NULL, *node;

	if (!web)
		return;

	kz_web_get_links(web, &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,
						   GTK_WIDGET(web));
	}

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


static void
act_open_selected_text (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	gchar *text;
	GRegex *regex;
	GMatchInfo *match_info;
	gint i = 1;
	gboolean match;
	GError *error = NULL;

 	g_return_if_fail (KZ_IS_WINDOW((kz)));
 
	text = kz_web_get_selection_string(web);
	if (!text)
		return;

	regex = g_regex_new(HTTP_REGEX, 
			    0,
			    0, &error);

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

	match = g_regex_match(regex, text, 0, &match_info);
	
	if (match)
	{
		gchar **uri;
		uri = g_match_info_fetch_all(match_info);

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

	g_match_info_free(match_info);
	g_regex_unref(regex);
	g_free(text);
}


static void
act_back (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);

	kz_web_go_back(web);
}


static void
act_forward (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);

	kz_web_go_forward(web);
}


static void
act_go_up (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);

	kz_web_go_up(web);
}


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)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);

	kz_web_go_nav_link(web, KZ_WEB_LINK_INDEX);
}


static void
act_contents (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);

	kz_web_go_nav_link(web, KZ_WEB_LINK_CONTENTS);
}


static void
act_start (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);

	kz_web_go_nav_link(web, KZ_WEB_LINK_START);
}


static void
act_prev (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);

	kz_web_go_nav_link(web, KZ_WEB_LINK_PREV);
}


static void
act_next (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);

	kz_web_go_nav_link(web, KZ_WEB_LINK_NEXT);
}


static void 
act_stop (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);

	kz_web_stop_load(web);
}


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

	g_return_if_fail(KZ_IS_WINDOW(kz));

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

	kz_web_reload(web,
			(state & GDK_SHIFT_MASK) ?
			KZ_WEB_RELOAD_BYPASS_PROXY_AND_CACHE :
			KZ_WEB_RELOAD_NORMAL);
}


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

	g_return_if_fail(KZ_IS_WINDOW (kz));

	num = kz_notebook_get_n_pages(KZ_NOTEBOOK(kz->notebook));

	for (i = num - 1; i >= 0; i--)
	{
		KzWeb *web = KZ_WINDOW_NTH_WEB(kz, i);

		kz_web_stop_load(web);
	}
}

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 = kz_notebook_get_n_pages(KZ_NOTEBOOK(kz->notebook));

	for (i = num - 1; i >= 0; i--)
	{
		KzWeb *web = KZ_WINDOW_NTH_WEB(kz, i);

		kz_web_reload(web,
				(state & GDK_SHIFT_MASK) ?
				KZ_WEB_RELOAD_BYPASS_CACHE :
				KZ_WEB_RELOAD_NORMAL);
	}
}


static void 
act_view_source (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	GtkWidget *newtab;
	if (!web) return;

	newtab = kz_window_open_new_tab(kz, NULL);

	kz_web_view_current_page_source_in_new(web, KZ_WEB(newtab));
}

static void 
act_show_page_certificate (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	if (!web) return;

	kz_web_show_page_certificate(web);
}

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

	kz_actions_popup_menu_modal(kz, 0, 0);
}

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

	kz_statusbar_set_focus_to_find_area(KZ_STATUSBAR(kz->statusbar));
}

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

	kz_notebook_prev_tab(KZ_NOTEBOOK(kz->notebook));
}


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

	kz_notebook_next_tab(KZ_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 = kz_notebook_page_num(KZ_NOTEBOOK(kz->notebook), widget);
	kz_notebook_set_current_page(KZ_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_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
        {
		KzWeb *kzweb;

		kzweb = KZ_WINDOW_CURRENT_WEB(kz);
		if (!kzweb)
			return;
		kz_web_cut_selection(kzweb);
        }
}


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
        {
		KzWeb *kzweb;

		kzweb = KZ_WINDOW_CURRENT_WEB(kz);
		if (!kzweb)
			return;

		kz_web_copy_selection(kzweb);
        }
}

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
        {
		KzWeb *kzweb;

		kzweb = KZ_WINDOW_CURRENT_WEB(kz);
		if (!kzweb)
			return;

		kz_web_paste(kzweb);
        }
}


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
        {
		KzWeb *kzweb;

		kzweb = KZ_WINDOW_CURRENT_WEB(kz);
		if (!kzweb)
			return;

		kz_web_select_all(kzweb);
        }
}


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

	g_return_if_fail(KZ_IS_WINDOW (kz));

	kzweb = KZ_WINDOW_CURRENT_WEB(kz);
	if (!kzweb)
		return;

	text = kz_web_get_title(kzweb);
	gtkutil_copy_text(text);
}


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

	g_return_if_fail(KZ_IS_WINDOW (kz));

	kzweb = KZ_WINDOW_CURRENT_WEB(kz);
	if (!kzweb)
		return;

	text = kz_web_get_location(kzweb);
	gtkutil_copy_text(text);
}

static void
act_get_body_text (GtkAction *action, KzWindow *kz)
{
	KzWeb *kzweb;
	gchar *text;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	kzweb = KZ_WINDOW_CURRENT_WEB(kz);
	if (!kzweb)
		return;

	text = kz_web_get_body_text(kzweb);
}


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_switch_layout_engine (GtkRadioAction *action, GtkRadioAction *cur_action, KzWindow *kz)
{
	gint value;
	const gchar *engine_name = NULL;

	value = gtk_radio_action_get_current_value(action);
	switch (value)
	{
#ifdef WITH_GECKO
	case KZ_LAYOUT_ENGINE_GECKO:
		engine_name = "gecko";
		break;
#endif
#ifdef WITH_WEBKIT_GTK
	case KZ_LAYOUT_ENGINE_WEBKIT_GTK:
		engine_name = "webkit_gtk";
		break;
#endif
#ifdef WITH_GTK_IE_EMBED
	case KZ_LAYOUT_ENGINE_GTK_IE_EMBED:
		engine_name = "ie";
		break;
#endif
	default:
		break;
	}

	if (!engine_name)
		return;

        kz_window_switch_layout_engine(kz, engine_name);
}

static void
close_tabs (KzNotebook *notebook, KzNotebookCloseCondition condition)
{
	gint pos;

	pos = kz_notebook_get_current_page(notebook);

	kz_notebook_close_tabs(notebook, condition, pos);
}

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

	close_tabs(KZ_NOTEBOOK(kz->notebook), KZ_NOTEBOOK_CLOSE_BACKWARD);
}


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

	close_tabs(KZ_NOTEBOOK(kz->notebook), KZ_NOTEBOOK_CLOSE_FORWARD);
}


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

	close_tabs(KZ_NOTEBOOK(kz->notebook), KZ_NOTEBOOK_CLOSE_INACTIVE);
}

static void
act_tab_close_all (GtkAction *action, KzWindow *kz)
{
	kz_window_close_all_tab(kz);
}

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_folder_get_children(KZ_BOOKMARK_FOLDER(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 *bookmark, *sibling = NULL;
	KzBookmark *file;
        KzBookmark *folder;
        KzWeb *web;
	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_IS_BOOKMARK_FOLDER(folder))
	{
		sibling = folder;
		folder = KZ_BOOKMARK(kz_bookmark_get_parent(folder));
		g_return_if_fail(KZ_IS_BOOKMARK_FOLDER(folder));
	}

	web = KZ_WINDOW_CURRENT_WEB(kz);
	if (!web) return;

	title = kz_web_ensure_title(web);
	uri   = kz_web_get_location(web);
	desc  = kz_web_get_selection_string(web);

	if (!uri) return;

	bookmark = kz_bookmark_new_with_attrs(title, uri, desc);
	/* FIXME! show dialog */
	if (sibling)
		kz_bookmark_folder_insert_before(KZ_BOOKMARK_FOLDER(folder), bookmark, sibling);
	else
		kz_bookmark_folder_append(KZ_BOOKMARK_FOLDER(folder), bookmark);
	
	if (KZ_IS_BOOKMARK_FILE(folder))
		file = folder;
	else
		file = kz_bookmark_get_parent_file(folder);
	
	if (kz_bookmark_file_has_xmlrpc(KZ_BOOKMARK_FILE(file)))
	{
		kz_bookmark_file_xmlrpc_insert(KZ_BOOKMARK_FILE(file),
					       folder,
					       sibling,
					       bookmark);
	}

	g_free(desc);
	g_object_unref(bookmark);
}

static void
act_add_first_feed_bookmark (GtkAction *action, KzWindow *kz)
{
	KzWeb *web;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	web = KZ_WEB(KZ_WINDOW_CURRENT_WEB(kz));
	
	kz_navi_add_bookmark(kz_web_get_nth_nav_link(web,
						       KZ_WEB_LINK_RSS,
						       0));
}

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

	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(kz_bookmark_get_parent(bookmark));
	g_return_if_fail(KZ_IS_BOOKMARK(folder));

	if (KZ_IS_BOOKMARK_FILE(folder))
		file = folder;
	else
		file = kz_bookmark_get_parent_file(folder);

	has_xmlrpc = kz_bookmark_file_has_xmlrpc(KZ_BOOKMARK_FILE(file));
	if (has_xmlrpc)
	{
		kz_bookmark_file_xmlrpc_remove(KZ_BOOKMARK_FILE(file),
					       bookmark);
	}

	kz_bookmark_folder_remove(KZ_BOOKMARK_FOLDER(folder), bookmark);
}


static void
act_edit_bookmark (GtkAction *action, KzWindow *kz)
{
	KzBookmark *bookmark;
	GtkWidget *widget;
	gboolean is_folder, is_file, 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_IS_BOOKMARK_FILE(bookmark);
	children_is_editable = is_file ?
		kz_bookmark_file_is_editable(KZ_BOOKMARK_FILE(bookmark)) : TRUE;

	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_GET_BAR_BOOKMARK;
	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_GET_SMART_BOOKMARK;
	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_file_load_start(KZ_BOOKMARK_FILE(folder));
}


static void
act_clip_selection (GtkAction *action, KzWindow *kz)
{
	KzBookmark *clip, *bookmark;
	KzWeb *web;
	const gchar *title, *uri;
	gchar *source = NULL;
	GTimeVal now;
	struct tm *date = NULL;
	time_t t;
	gchar time_string[20];
	gchar *filename, *htmlname = NULL, *link, *name;
	gchar *dir_name, *clip_dir_name;
	gchar *pos, *full_htmlname;
	GIOChannel *io;

	if (!KZ_IS_WINDOW(kz)) return;

	web = KZ_WINDOW_CURRENT_WEB(kz);
	if (!web) return;

	clip = KZ_GET_CLIP_BOOKMARK;
	g_get_current_time(&now);

	title = kz_window_get_title(kz);
	uri   = kz_window_get_uri(kz);
	
	/* create dir */
	t = (time_t)now.tv_sec;
	date = localtime(&t);
	strftime(time_string, 20, "%Y%m%d%H%M%S", date);

	name = create_filename_from_uri(uri);
	pos = strchr(name, '?');
	if (pos)
		htmlname = g_strndup(name, pos - name);
	else
		htmlname = g_strdup(name);
	g_free(name);
	name = htmlname;

	pos = strchr(name, '#');
	if (pos)
		htmlname = g_strndup(name, pos - name);
	else
		htmlname = g_strdup(name);
	g_free(name);

	full_htmlname = g_strconcat(htmlname, ".html", NULL);

	dir_name = g_strconcat(htmlname, time_string, NULL);
	clip_dir_name = g_build_filename(KZ_GET_CLIPS_DIR, dir_name, NULL);
	g_mkdir_with_parents(clip_dir_name, 0700);

	source = kz_web_get_html_with_contents(web, dir_name);

	filename = g_build_filename(clip_dir_name,
				    full_htmlname,
			       	    NULL);
	
	/* save */
	io = g_io_channel_new_file(filename, "w", NULL);
	g_io_channel_set_encoding(io, NULL, NULL);
	g_io_channel_write_chars(io, source, g_strlen(source),
				 NULL, NULL);
	g_io_channel_shutdown(io, TRUE, NULL);
	g_io_channel_unref(io);

	g_free(source);
	link = g_strconcat("file://", filename, NULL);
	bookmark = kz_bookmark_new_with_attrs(title, link, NULL);
	
	/* set the original URI */
	kz_bookmark_file_set_location(KZ_BOOKMARK_FILE(bookmark), uri);
	
	kz_bookmark_folder_prepend(KZ_BOOKMARK_FOLDER(clip), bookmark);
	
	g_free(link);
	g_free(filename);
	g_free(dir_name);
	g_free(clip_dir_name);
	g_free(htmlname);
	g_free(full_htmlname);
}

static void
act_extract_links (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	GtkWidget *dialog;

	if (!web) return;

	dialog = kz_links_dialog_new(GTK_WINDOW(kz), web, FALSE);
	gtk_widget_show(dialog);
}


static void
act_extract_selected_links (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	GtkWidget *dialog;

	if (!web) return;
	dialog = kz_links_dialog_new(GTK_WINDOW(kz), web, TRUE);
	gtk_widget_show(dialog);
}


static void
act_save_session (GtkAction *action, KzWindow *kz)
{
	KZ_SAVE_SESSION;
}


static void
act_restore_session (GtkAction *action, KzWindow *kz)
{
	KZ_RESTORE_SESSION;
}


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

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

	g_return_if_fail(KZ_IS_WINDOW(kz));

	widget = kz_window_open_new_tab(kz, KAZEHAKASE_URI);
	num = kz_notebook_page_num(KZ_NOTEBOOK(kz->notebook), widget);
	kz_notebook_set_current_page(KZ_NOTEBOOK(kz->notebook), num);
}

static void
act_copy_tab (GtkAction *action, KzWindow *kz)
{
	KzWeb *src_web, *dest_web;

	src_web = KZ_WINDOW_CURRENT_WEB(kz);
	dest_web = KZ_WEB(kz_window_open_new_tab(kz, NULL));

	kz_web_copy_page(src_web, dest_web);
}


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)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);

	if (!web)
		return;

	kz_web_print(web);
}

static void
act_print_preview (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);

	if (!web)
		return;

	kz_web_print_preview(web);
}


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

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

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

	dialog = kz_copy_format_dialog_new(GTK_WINDOW(kz));
	gtk_widget_show(dialog);
}

static void
act_decrease_text_size (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	gdouble ratio;

	if (!web)
		return;

	ratio = kz_web_get_text_size(web);
	ratio = ratio * 0.9;

	if (ratio > 0)
	{
		GtkAction *zoom;
		kz_web_set_text_size(web, ratio);

		zoom = gtk_action_group_get_action(kz->actions, "Zoom");
	        kz_zoom_action_set_ratio(KZ_ZOOM_ACTION(zoom),
					 ratio);
	}
}

static void
act_increase_text_size (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	gdouble ratio;

	if (!web)
		return;

	ratio = kz_web_get_text_size(web);
	ratio = ratio * 1.1;

	if (ratio < 10)
	{
		GtkAction *zoom;
		kz_web_set_text_size(web, ratio);

		zoom = gtk_action_group_get_action(kz->actions, "Zoom");
	        kz_zoom_action_set_ratio(KZ_ZOOM_ACTION(zoom),
					 ratio);
	}
}


static void
act_normal_text_size (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	GtkAction *zoom;

	if (!web)
		return;

	kz_web_set_text_size(web, 100);
	
	zoom = gtk_action_group_get_action(kz->actions, "Zoom");
        kz_zoom_action_set_ratio(KZ_ZOOM_ACTION(zoom), 100);
}


static void
act_zoom_out (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	gdouble ratio;

	if (!web)
		return;

	ratio = kz_web_get_zoom_ratio(web);
	ratio = ratio * 0.9;

	if (ratio > 0)
	{
		GtkAction *zoom;
		kz_web_zoom(web, ratio);

		zoom = gtk_action_group_get_action(kz->actions, "Zoom");
	        kz_zoom_action_set_ratio(KZ_ZOOM_ACTION(zoom),
					 ratio);
	}
}

static void
act_zoom_in (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	gdouble ratio;

	if (!web)
		return;

	ratio = kz_web_get_zoom_ratio(web);
	ratio = ratio * 1.1;

	if (ratio < 10)
	{
		GtkAction *zoom;
		kz_web_zoom(web, ratio);

		zoom = gtk_action_group_get_action(kz->actions, "Zoom");
	        kz_zoom_action_set_ratio(KZ_ZOOM_ACTION(zoom),
					 ratio);
	}
}


static void
act_zoom_100 (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
	GtkAction *zoom;

	if (!web)
		return;

	kz_web_zoom(web, 1.0);
	
	zoom = gtk_action_group_get_action(kz->actions, "Zoom");
        kz_zoom_action_set_ratio(KZ_ZOOM_ACTION(zoom),
				 100);
}


static void
act_page_up (GtkAction *action, KzWindow *kz)
{
	KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);

	if (!web)
		return;

	kz_web_page_up(web);
}

static void
act_page_down (GtkAction *action, KzWindow *kz)
{
	GtkAccelKey key;
	GtkWidget *widget;

	widget = gtk_window_get_focus(GTK_WINDOW(kz));

        if (GTK_IS_EDITABLE(widget))
        {
		GdkEvent *event;
		event = gdk_event_new(GDK_KEY_PRESS);
		gtk_accel_map_lookup_entry("<Actions>/KzWindow/PageDown", &key);
		event->key.keyval = key.accel_key;
		gtk_propagate_event(widget, event);
		gdk_event_free(event);
        }
        else
        {
		KzWeb *web = KZ_WINDOW_CURRENT_WEB(kz);
		kz_web_page_down(web);
        }
}

static void
act_auto_scroll_mode (GtkAction *action, KzWindow *kz)
{
	gint x, y;
	GdkDisplay *display;
	KzWeb *web;
	KzAutoscroller *as;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	web = KZ_WINDOW_CURRENT_WEB(kz);
	if (!web)
		return;

	display = gtk_widget_get_display(GTK_WIDGET(web));
	as = kz_autoscroller_new ();
	gdk_display_get_pointer (display, NULL, &x, &y, NULL);
	kz_autoscroller_set_web (as, web);
	kz_autoscroller_start_scroll (as, GTK_WIDGET(kz), x, y);
	g_object_unref (as);
}


static void
cb_thumbnail_tablist_selected (KzPopupTablist *popup, 
			       KzBookmark* tab, gint index,
			       KzWindow* kz)
{
	kz_notebook_set_current_page(KZ_NOTEBOOK(kz->notebook), index);

	gtk_widget_destroy(GTK_WIDGET(popup));
	kz->popup_tablist = NULL;
}

static void
act_thumbnail_tablist (GtkAction *action, KzWindow *kz)
{
	KzBookmark *proxy;
	
	if (!kz->popup_tablist)
		kz->popup_tablist = kz_popup_tablist_new(kz);

	proxy = kz_proxy_folder_new(KZ_BOOKMARK_FOLDER(kz->tabs));
	g_signal_connect(kz->popup_tablist, "selected",
			 G_CALLBACK(cb_thumbnail_tablist_selected), kz);
/* to keep KzPopupTablist from adhering to KzWindow, I can't pass KzWindow to KzPopupTablist directly... */
	kz_popup_tablist_show(KZ_POPUP_TABLIST(kz->popup_tablist), proxy);
	g_object_unref(proxy);
}

/* 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)
	{
		if (!kz_paned_is_showing_all_children(KZ_PANED(kz->pane)))
		{
			gint width;
			gtk_widget_get_size_request(kz->sidebar, &width, NULL);
			kz_paned_set_separator_position(KZ_PANED(kz->pane),
							MAX(1, width));
		}
		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);
}


static void
act_show_hide_bookmarkbars (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->bookmark_bars_area));

	active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action));
	g_object_set(kz->bookmark_bars_area, "visible", active, NULL);
}

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

	active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action));
	if (active)
	{
		gtk_window_fullscreen(GTK_WINDOW(kz));
		gtk_widget_hide(kz->bookmark_bars_area);
		gtk_widget_hide(kz->statusbar);
		gtk_widget_hide(kz->menu_box);
		gtk_notebook_set_show_tabs(GTK_NOTEBOOK(kz->notebook), FALSE);
	
	}
	else
	{
		GtkAction *toggle_action;
		gboolean toggle_active;

		gtk_window_unfullscreen(GTK_WINDOW(kz));
		gtk_widget_show(kz->statusbar);
		gtk_widget_show(kz->menu_box);
		gtk_notebook_set_show_tabs(GTK_NOTEBOOK(kz->notebook), TRUE);
		
		toggle_action = gtk_action_group_get_action(kz->actions,
						     	    "ShowHideBookmarkbars");
		toggle_active = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(toggle_action));
		if (toggle_active)
			gtk_widget_show(kz->bookmark_bars_area);
	}
}

#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},
  {"StockExtensionMenu",      NULL, N_("Extension"),   NULL, NULL, NULL},
  {"StockProxyMenu",          NULL, N_("Proxy"),             NULL, NULL, NULL},
  {"StockRecentCloseTabMenu", NULL, N_("Recent closed tabs"), NULL, NULL, NULL},
  {"StockClipMenu",           NULL, N_("Clip"),        NULL, NULL, NULL},
  {"StockSwitchLayoutEngineMenu", NULL, N_("Switch layout engine"),  NULL, NULL, NULL},

  {"NewWindow", KZ_STOCK_NEW_WINDOW, N_("_New Window"), CTRL"N",  N_("Open a new window"), 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 selected 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)},

  {"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",		 GTK_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)},
  {"CopyInUserFormat",          NULL          ,        N_("Copy _In User Format"),    NULL,    N_("Copy Title, URI and Selected text in user format"), NULL}, 
  {"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)},

  {"PageUp",      NULL,                   N_("Page Up"),       NULL,       NULL, G_CALLBACK(act_page_up)},
  {"PageDown",      NULL,                 N_("Page Down"),       NULL,       NULL, G_CALLBACK(act_page_down)},

  {"NormalTextSize",   NULL, N_("Normal text size"), NULL, N_("Use the normal text size"), G_CALLBACK(act_normal_text_size)},
  {"IncreaseTextSize", KZ_STOCK_FONT_INCREASE,  N_("Increase text size"),     NULL, N_("Increase the text size"),   G_CALLBACK(act_increase_text_size)},
  {"DecreaseTextSize", KZ_STOCK_FONT_DECREASE, N_("Decrease text size"),    NULL, N_("Decrease the text size"),   G_CALLBACK(act_decrease_text_size)},

  {"NormalSize", GTK_STOCK_ZOOM_100, N_("Normal size"), NULL, N_("Normal size"), G_CALLBACK(act_zoom_100)},
  {"ZoomIn",    GTK_STOCK_ZOOM_IN,  N_("Zoom in"),     NULL, N_("Zoom in this page"),   G_CALLBACK(act_zoom_in)},
  {"ZoomOut",   GTK_STOCK_ZOOM_OUT, N_("Zoom out"),    NULL, N_("Zoom out this page"),  G_CALLBACK(act_zoom_out)},

  {"ViewPageSource", KZ_STOCK_VIEW_SOURCE, N_("View page source"), NULL, N_("View the source code of the page"), G_CALLBACK(act_view_source)},
  {"ShowPageCertificate", NULL, N_("Show page certificate"), NULL, N_("Show the certificate of the page"), G_CALLBACK(act_show_page_certificate)},
  {"AutoScrollMode", NULL,          N_("Autoscroll mode"), NULL, N_("Set auto-scroll mode"), G_CALLBACK(act_auto_scroll_mode)},
  {"ThumbnailTabList", NULL,          N_("ThumbnailTabList"), NULL, N_("Display the tab list with thumbnail"), G_CALLBACK(act_thumbnail_tablist)},
/*
  {"EditMode", KZ_STOCK_VIEW_SOURCE, N_("EditMode"), NULL, N_("View the source code of the page"), G_CALLBACK(act_set_edit_mode)},
  {"ViewMode", KZ_STOCK_VIEW_SOURCE, N_("EditMode"), NULL, N_("View the source code of the page"), G_CALLBACK(act_set_view_mode)},
*/
  {"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)},
  {"CloseAllInactiveTabs", NULL, N_("Close all _inactive tabs"), NULL, NULL, G_CALLBACK(act_tab_close_all_inactive_active)},
  {"CloseAllTabs", NULL, N_("Clos_e all tabs"), NULL, NULL, G_CALLBACK(act_tab_close_all)},

  {"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)},
  {"AddFirstFeedBookmark",      NULL, N_("Add _1st feed to bookmarks"),      NULL,  NULL, G_CALLBACK(act_add_first_feed_bookmark)},
  {"AddFeedBookmark",           NULL, N_("Add _feed to bookmarks"),          NULL,  NULL, NULL},
  {"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)},

  {"ClipSelection",          NULL, N_("C_lip Selection"),        NULL,  N_("Clip the current selection"), G_CALLBACK(act_clip_selection)},

  {"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)},
  {"ShowCopyFormat", NULL, N_("_Show Copy Format"), NULL,  NULL, G_CALLBACK(act_show_copy_format)},
  {"About",        GTK_STOCK_ABOUT, N_("About Kazehakase"),       NULL,  N_("Display credits"), G_CALLBACK(act_about)},
  {"OpenKazehakaseWebsite",        NULL, N_("Open Kazehakase Website"),       NULL,  N_("Open Kazehakase website in new tab"), G_CALLBACK(act_open_kazehakase_website)},
  
  {"PopupContextMenu", NULL, N_("Popup context menu"), SHFT"F10",  N_("Popup context menu"), G_CALLBACK(act_popup_context_menu)},
};
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)},
  {"ShowHideBookmarkbars", NULL, N_("Bookmarkbar"), NULL, NULL, G_CALLBACK(act_show_hide_bookmarkbars)},
  {"ToggleProxyUse",  NULL, N_("Toggle Proxy Use"), NULL, NULL, G_CALLBACK(act_toggle_proxy_use)}, 
  {"ToggleFullScreen",NULL, N_("Toggle Full Screen Mode"), "F11", NULL, G_CALLBACK(act_view_fullscreen)}, 
};
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 GtkRadioActionEntry kz_switch_layout_engine_radio_actions[] =
{
#ifdef WITH_GECKO
  {"Gecko", NULL, N_("Gecko"), NULL, NULL, KZ_LAYOUT_ENGINE_GECKO},
#endif
#ifdef WITH_WEBKIT_GTK
  {"WebKit/GTK+", NULL, N_("WebKit/GTK+"), NULL, NULL, KZ_LAYOUT_ENGINE_WEBKIT_GTK},
#endif
#ifdef WITH_GTK_IE_EMBED
  {"IE", NULL, N_("InternetExplorer"), NULL, NULL, KZ_LAYOUT_ENGINE_GTK_IE_EMBED},
#endif
};
static const gint kz_switch_layout_engine_radio_actions_len = G_N_ELEMENTS(kz_switch_layout_engine_radio_actions);

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

	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_IS_BOOKMARK_FILE(bookmark);
	if (is_folder)
		has_children = kz_bookmark_folder_has_children(KZ_BOOKMARK_FOLDER(bookmark));
	is_editable = kz_bookmark_is_editable(bookmark);
	if (is_file)
		children_is_editable = kz_bookmark_file_is_editable(KZ_BOOKMARK_FILE(bookmark));
	else if (is_folder && is_editable)
		children_is_editable = TRUE;
	else
		children_is_editable = FALSE;
	kzweb = KZ_WINDOW_CURRENT_WEB(kz);
	if (kzweb && kz_web_get_nav_link(kzweb, KZ_WEB_LINK_RSS))
		has_feed = TRUE;
	else
		has_feed = FALSE;

	action = gtk_action_group_get_action(kz->actions,
					     "OpenBookmarkInNewTab");
	gtk_action_set_sensitive(action, has_link);

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

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

	action = gtk_action_group_get_action(kz->actions,
					     "AddFeedBookmark");
	gtk_action_set_sensitive(action, has_feed);

	action = gtk_action_group_get_action(kz->actions,
					     "RemoveBookmark");
	gtk_action_set_sensitive(action, is_editable);

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

	action = gtk_action_group_get_action(kz->actions,
					     "UpdateBookmarkFolder");
	gtk_action_set_sensitive(action, is_file);
}


static void
combine_favicon(GtkAction *action, const gchar *uri, KzWindow *kz)
{
	GSList *node, *proxies;

	proxies = gtk_action_get_proxies(action);
	for (node = proxies; node; node = g_slist_next(node))
	{
		GtkWidget *image = NULL;
		gchar *stock_id;
		GtkIconSize size = GTK_ICON_SIZE_MENU;
		KzFavicon *kzfav = KZ_GET_FAVICON;
		GdkPixbuf *favicon = NULL;

		if (!GTK_IS_WIDGET(node->data) ||
		    (!GTK_IS_IMAGE_MENU_ITEM(node->data) &&
		     !GTK_IS_TOOL_BUTTON(node->data))) 
		{
			continue;
		}

		g_object_get(action,
			     "stock_id", &stock_id,
			     NULL);
		if (GTK_IS_IMAGE_MENU_ITEM(node->data))
		{
			size = GTK_ICON_SIZE_MENU;
			image = gtk_image_menu_item_get_image(GTK_IMAGE_MENU_ITEM(node->data));
		}
		else if (GTK_IS_TOOL_BUTTON(node->data))
		{
			size = GTK_ICON_SIZE_BUTTON;
			image = gtk_image_new();
			gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(node->data), image);
			gtk_widget_show(image);
		}
		favicon = kz_favicon_get_pixbuf(kzfav, uri, size);
		gtkutil_superpose_pixbuf(image, favicon,
					 stock_id, size);
		g_free(stock_id);

		if (favicon)
			g_object_unref(favicon);
	}
}


void
kz_actions_set_selection_sensitive (KzWindow *kz, KzWeb *kzweb)
{
	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 Embed's selection
	if (kzweb && !kz_web_selection_is_collapsed(kzweb))
	{
		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_WEB(kzweb))
	{
		can_cut   = kz_web_can_cut_selection(kzweb);
		can_copy  = kz_web_can_copy_selection(kzweb);
		can_paste = kz_web_can_paste(kzweb);
	}
	
	can_cut  = TRUE;
	can_copy  = TRUE;
	can_paste = TRUE;

	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, "ClipSelection", can_copy);
}

void
kz_actions_set_tab_sensitive (KzWindow *kz, KzWeb *kzweb)
{
	gint num, pos = 0;
	GtkAction *action;
	g_return_if_fail (KZ_IS_WINDOW(kz));

	num = kz_notebook_get_n_pages(KZ_NOTEBOOK(kz->notebook));
	
	if (!num) return;

	pos = kz_notebook_page_num(KZ_NOTEBOOK(kz->notebook),
				   GTK_WIDGET(kzweb));
	if (num > 1)
	{
		action = gtk_action_group_get_action(kz->actions,
						     "PrevTab");
		KZ_WINDOW_SET_SENSITIVE(kz, "PrevTab", TRUE);
		if (pos == 0)
		{
			combine_favicon(action, NULL, kz);
			KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllBackwardTab", FALSE);
		}
		else
		{
			KzWeb *prev = KZ_WINDOW_NTH_WEB(kz, pos - 1);
			const gchar* uri = kz_web_get_location(prev);
			/* set favicon */
			combine_favicon(action, uri, kz);
			KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllBackwardTab", TRUE);
		}

		action = gtk_action_group_get_action(kz->actions,
						     "NextTab");
		KZ_WINDOW_SET_SENSITIVE(kz, "NextTab", TRUE);
		if (pos == num - 1)
		{
			combine_favicon(action,	NULL, kz);
			KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllForwardTab", FALSE);
		}
		else
		{
			KzWeb *next = KZ_WINDOW_NTH_WEB(kz, pos + 1);
			const gchar* uri = kz_web_get_location(next);
			/* set favicon */
			combine_favicon(action,	uri, kz);
			KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllForwardTab", TRUE);
		}
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllInactiveTabs", TRUE);
	}
	else
	{
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllBackwardTab",  FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllForwardTab",   FALSE);
		KZ_WINDOW_SET_SENSITIVE(kz, "CloseAllInactiveTabs", FALSE);
	}

	if (kzweb && kz_web_get_nav_link(kzweb, KZ_WEB_LINK_RSS))
	{
		KZ_WINDOW_SET_SENSITIVE(kz, "AddFirstFeedBookmark", TRUE);
	}
	else
	{
		KZ_WINDOW_SET_SENSITIVE(kz, "AddFirstFeedBookmark", FALSE);
	}
}

void
kz_actions_set_sensitive (KzWindow *kz, KzWeb *kzweb)
{
	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;
	gboolean can_add_feed = FALSE;
	gint i, num;
	GtkAction *action;
	gboolean active;

	g_return_if_fail (KZ_IS_WINDOW(kz));
	/* g_return_if_fail (KZ_IS_WEB (kzweb)); */

	num = kz_notebook_get_n_pages(KZ_NOTEBOOK(kz->notebook));

	if (kzweb)
	{
		GtkAction *nav;
		gchar *uri = NULL, *title = NULL;

		can_stop        = kz_web_is_loading(kzweb);
		can_go_back     = kz_web_can_go_back(kzweb);
		can_go_forward  = kz_web_can_go_forward(kzweb);
		can_go_up       = kz_web_can_go_up(kzweb);

		can_go_index    = kz_web_can_go_nav_link(kzweb, KZ_WEB_LINK_INDEX);
		can_go_contents = kz_web_can_go_nav_link(kzweb, KZ_WEB_LINK_CONTENTS);
		can_go_start    = kz_web_can_go_nav_link(kzweb, KZ_WEB_LINK_START);
		can_go_prev     = kz_web_can_go_nav_link(kzweb, KZ_WEB_LINK_PREV);
		can_go_next     = kz_web_can_go_nav_link(kzweb, KZ_WEB_LINK_NEXT);

		can_add_feed    = (kz_web_get_nav_link(kzweb, KZ_WEB_LINK_RSS) != NULL);
		can_close_tab   = !kz_web_get_lock(kzweb);

		for (i = 0; i< num; i++)
		{
			KzWeb *web;

			web = KZ_WINDOW_NTH_WEB(kz, i);
			if (!web)
				continue;
			can_stop_all = kz_web_is_loading(web);
			if (can_stop_all) break;
		}

		kz_web_shistory_get_nth(kzweb, -1, TRUE, &uri, &title);
		action = gtk_action_group_get_action(kz->actions,
						     "Back");
		combine_favicon(action, uri, kz);
		nav = gtk_action_group_get_action(kz->actions,
						  "NavigationBack");
		combine_favicon(nav, uri, kz);
		g_free(uri);
		g_free(title);
		uri = NULL;
		title = NULL;

		kz_web_shistory_get_nth(kzweb, 1, TRUE, &uri, &title);
		action = gtk_action_group_get_action(kz->actions,
						     "Forward");
		combine_favicon(action, uri, kz);
		g_free(uri);
		g_free(title);
	}

	KZ_WINDOW_SET_VISIBLE  (kz, "Stop",     can_stop);
	KZ_WINDOW_SET_VISIBLE  (kz, "Reload",   !can_stop);
	KZ_WINDOW_SET_SENSITIVE(kz, "Back",      can_go_back);
	KZ_WINDOW_SET_SENSITIVE(kz, "Forward",   can_go_forward);
	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, "CloseTab",  can_close_tab);
	KZ_WINDOW_SET_SENSITIVE(kz, "StopAll",   can_stop_all);
	KZ_WINDOW_SET_SENSITIVE(kz, "NavigationBack", can_go_back);
	KZ_WINDOW_SET_SENSITIVE(kz, "ReloadAll", num > 0);
	KZ_WINDOW_SET_SENSITIVE(kz, "Search",    num > 0);
	KZ_WINDOW_SET_SENSITIVE(kz, "ExtractLinks", num > 0);
	KZ_WINDOW_SET_SENSITIVE(kz, "CopyTitle",    num > 0);
	KZ_WINDOW_SET_SENSITIVE(kz, "CopyURL",      num > 0);
	KZ_WINDOW_SET_SENSITIVE(kz, "StopReload",   num > 0);
	KZ_WINDOW_SET_SENSITIVE(kz, "PrevTab",  num > 0);
	KZ_WINDOW_SET_SENSITIVE(kz, "NextTab",  num > 0);
	KZ_WINDOW_SET_SENSITIVE(kz, "AddFirstFeedBookmark", can_add_feed);
	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);
	gtk_action_group_set_sensitive(kz->tabpop_actions, num > 0);

	action = gtk_action_group_get_action(kz->actions, "StopReload");
	kz_stop_reload_action_set_state(
			KZ_STOP_RELOAD_ACTION(action),
			can_stop?KZ_STOP_RELOAD_ACTION_STATE_STOP:KZ_STOP_RELOAD_ACTION_STATE_RELOAD);

	kz_actions_set_selection_sensitive(kz, kzweb);
	
	/* 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_GET_MENU_BOOKMARK);
}


GtkActionGroup *
kz_actions_create_group (KzWindow *kz)
{
	GtkActionGroup *action_group;
	GtkAction *action;

	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);
	gtk_action_group_add_radio_actions(action_group,
					   kz_switch_layout_engine_radio_actions,
					   kz_switch_layout_engine_radio_actions_len,
					   -1,
					   G_CALLBACK(act_switch_layout_engine),
					   kz);

	/* Back and Forward Action */
	{
		action = g_object_new(KZ_TYPE_NAVIGATION_ACTION,
				      "name", "NavigationBack",
				      "label", _("Back"),
				      "stock_id", GTK_STOCK_GO_BACK,
				      "tooltip", _("Go back"),
				      "kz-window", kz,
				      NULL);

		gtk_action_group_add_action(action_group, action);
		g_object_unref(action);
	}

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

	/* Zoom action */
	{
		action = GTK_ACTION(kz_zoom_action_new(kz));
		gtk_action_group_add_action(action_group, action);
		g_object_unref(action);
	}
	
	/* Location Entry action */
	{
		action = GTK_ACTION(kz_location_entry_action_new(kz));
		gtk_action_group_add_action(action_group, action);
		g_object_unref(action);
	}

	return action_group;
}


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_GET_MENU_BOOKMARK;
}


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;
	GtkWidget *extra_menu = NULL;

	g_return_if_fail(KZ_IS_BOOKMARK(bookmark));

	kz_actions_set_bookmark_for_action (kz, bookmark);

	popup_menu = gtk_ui_manager_get_widget(kz->menu_merge, 
					       "/BookmarkPopup");
	if (!popup_menu) return;

	extra_menu = gtk_ui_manager_get_widget(kz->menu_merge,
					       "/BookmarkPopup/AddFeedBookmark");
	if (extra_menu)
	{
		kz_actions_dynamic_append_add_feed_bookmark
			(kz, GTK_MENU_ITEM(extra_menu));
	}
	
	g_signal_connect(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(popup_menu,
					     G_CALLBACK(cb_popup_menu_hide),
					     NULL);

	kz_actions_set_bookmark_for_action(kz, NULL);

	set_popup_menu_sensitive(kz, KZ_GET_MENU_BOOKMARK);
}


void
kz_actions_insert_smartbookmark (KzWindow *kz, KzBookmark *bookmark,
				 KzBookmark *child, KzBookmark *sibling)
{
	GtkAction *action;
	const gchar *action_name;
	const gchar *title;
	guint id;
	
	if (!KZ_IS_SMART_BOOKMARK(child) &&
	    !kz_bookmark_is_folder(child)) return;
	
	title = kz_bookmark_get_title(child);
	
	/*
	 * We should unite KzLocationEntry and KzSmartBookmark.
	 */
	if (title && g_str_has_prefix(title, "LocationEntry"))
	{
		action = gtk_action_group_get_action(kz->actions,
						     "LocationEntry");
		if (KZ_IS_LOCATION_ENTRY_ACTION(action))
		{
			kz_location_entry_action_set_bookmark(
				KZ_LOCATION_ENTRY_ACTION(action),
				child);
		}
		return;
	}
	
	action = GTK_ACTION(kz_smart_bookmark_action_new(kz, child));
	if (!action) return;

	id = gtk_ui_manager_new_merge_id(kz->menu_merge);
	action_name = gtk_action_get_name(action);

	gtk_action_group_add_action(kz->actions,
				    action);

	gtk_ui_manager_add_ui(kz->menu_merge,
			      id, 
			      "/MainToolBar/SmartBookmark",
			      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 && g_str_has_prefix(title, "LocationEntry"))
		return;
	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_folder_get_children(KZ_BOOKMARK_FOLDER(bookmark));
	for (node = children; node; node = g_list_next(node))
	{
		gpointer p;
		guint id;
		gchar *action_name;
		const gchar *title;
		GtkAction *action, *new_action = NULL;
		KzBookmark *child= node->data;

		if (!KZ_IS_SMART_BOOKMARK(child) &&
	    	    !kz_bookmark_is_folder(child)) continue;
		
		title = kz_bookmark_get_title(child);
	 
		if (title && g_str_has_prefix(title, "LocationEntry"))
		{
			action = gtk_action_group_get_action(kz->actions,
							     "LocationEntry");
			kz_location_entry_action_set_bookmark(
				KZ_LOCATION_ENTRY_ACTION(action),
				child);
			continue;
		}
		
		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 */
			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);
		gtk_ui_manager_add_ui(kz->menu_merge,
				      id, 
				      "/MainToolBar/SmartBookmark",
				      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);
}


void
kz_actions_remove_smartbookmarks (KzWindow *kz, KzBookmark *bookmark)
{
	GList *children, *node;

	children = kz_bookmark_folder_get_children(KZ_BOOKMARK_FOLDER(bookmark));
	for (node = children; node; node = g_list_next(node))
	{
		gpointer p;
		guint id;
		gchar *action_name;
		const gchar *title;
		GtkAction *action;
		GSList *p_node, *proxies;
		KzBookmark *child= node->data;

		if (!KZ_IS_SMART_BOOKMARK(child) &&
	    	    !kz_bookmark_is_folder(child)) continue;
		
		title = kz_bookmark_get_title(child);
		if (title && g_str_has_prefix(title, "LocationEntry"))
			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) continue;

		proxies = gtk_action_get_proxies(action);
                if (proxies)
		{
			GSList *copy;
	                /* disconenct proxy explicitly */
	                copy = g_slist_copy(proxies);
			for (p_node = copy; p_node; p_node = g_slist_next(p_node))
			{
				if (p_node->data && GTK_IS_WIDGET(p_node->data))
        	                {
                	                gtk_action_disconnect_proxy(action, GTK_WIDGET(p_node->data));
	                        }
        	        }
	                g_slist_free(copy);
		}

		if (title && g_str_has_prefix(title, "LocationEntry"))
		{
			g_free(action_name);
			continue;
		}
		
		/* remove old one */
		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);
		}
		
		g_free(action_name);
	}
	g_list_free(children);
}
