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

/*
 *  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-popup.h"

#include <string.h>
#include <unistd.h>
#include "gtk24backports.h"
#include "kz-entry-action.h"
#include "gtk-utils.h"
#include "intl.h"
#include "kazehakase.h"
#include "kz-window.h"
#include "kz-tab-label.h"
#include "kz-actions-download.h"
#include "mozilla-prefs.h"
#include "kz-mozembed.h"
#include "kz-favicon.h"
#include "glib-utils.h"

#define KZ_ACTIONS_POPUP_LANGUAGE_KEY "KzActionsPopup::Language"
#define KZ_ACTIONS_POPUP_TAB_KEY "KzActionsPopup::Tab"

typedef enum {
	LOCATION_LINK,
	LOCATION_IMAGE,
	LOCATION_FRAME		
} LocationType;

typedef enum {
	CURRENT_TAB,
	NEW_TAB,
	NEW_WINDOW
} WindowType;


typedef struct
{
	KzMozEmbed *kzembed;
	gchar *filename;  /* file name for edior */
	gpointer element; /* pointer indicated textarea */
} EditorInfo;

static const gchar *label_color[] =
{
	"#000000",
	"#ff0000",
	"#22aa44",
};

static void kz_actions_popup_append_tablist_menuitem (KzWindow *kz, GtkWidget *tablist_menu);

static void
open_location (GtkAction *action, KzWindow *kz, LocationType location, WindowType window)
{
	const KzEmbedEventMouse *event;
	const gchar *uri = NULL;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	event = kz_window_get_mouse_event_info(kz);
	g_return_if_fail(event);

	switch (location) {
	case LOCATION_LINK:
		uri = event->cinfo.link;
		break;
	case LOCATION_IMAGE:
		uri = event->cinfo.img;
		break;
	case LOCATION_FRAME:
		uri = event->cinfo.frame_src;
		break;
	default:
		g_return_if_reached();
		break;
	}

	if (!uri) return;

	switch (window) {
	case CURRENT_TAB:
		kz_window_load_url(kz, uri);
		break;
	case NEW_TAB:
		kz_window_open_new_tab_with_parent (kz, uri,
						    KZ_WINDOW_CURRENT_PAGE(kz));
		break;
	case NEW_WINDOW:
	{
		GtkWidget *widget = kz_window_new(uri);
		gtk_widget_show(widget);
		break;
	}
	default:
		g_return_if_reached();
		break;
	}
}

static void
act_popup_open (GtkAction *action, KzWindow *kz)
{
	open_location(action, kz, LOCATION_LINK, CURRENT_TAB);
}

static void
act_popup_open_in_new_tab (GtkAction *action, KzWindow *kz)
{
	open_location(action, kz, LOCATION_LINK, NEW_TAB);
}

static void
act_popup_open_in_new_win (GtkAction *action, KzWindow *kz)
{
	open_location(action, kz, LOCATION_LINK, NEW_WINDOW);
}

static void
act_popup_copy_link_location (GtkAction *action, KzWindow *kz)
{
	const KzEmbedEventMouse *event;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	event = kz_window_get_mouse_event_info(kz);
	g_return_if_fail(event);

	gtkutil_copy_text(event->cinfo.link);
}

static void
act_popup_open_image (GtkAction *action, KzWindow *kz)
{
	open_location(action, kz, LOCATION_IMAGE, CURRENT_TAB);
}

static void
act_popup_open_image_in_new_tab (GtkAction *action, KzWindow *kz)
{
	open_location(action, kz, LOCATION_IMAGE, NEW_TAB);
}

static void
act_popup_open_image_in_new_win (GtkAction *action, KzWindow *kz)
{
	open_location(action, kz, LOCATION_IMAGE, NEW_WINDOW);
}

static void
act_popup_save_link (GtkAction *action, KzWindow *kz)
{
	const KzEmbedEventMouse *event;
	const gchar *uri = NULL;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	event = kz_window_get_mouse_event_info(kz);
	g_return_if_fail(event);

	uri = event->cinfo.link;
	kz_actions_download_open_save_dialog(uri, FALSE);
}

static void
act_popup_save_image (GtkAction *action, KzWindow *kz)
{
	const KzEmbedEventMouse *event;
	const gchar *uri = NULL;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	event = kz_window_get_mouse_event_info(kz);
	g_return_if_fail(event);

	uri = event->cinfo.img;
	kz_actions_download_open_save_dialog(uri, FALSE);
}

static void
act_popup_copy_image_location (GtkAction *action, KzWindow *kz)
{
	const KzEmbedEventMouse *event;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	event = kz_window_get_mouse_event_info(kz);
	g_return_if_fail(event);

	gtkutil_copy_text(event->cinfo.img);
}

static void
act_popup_open_frame (GtkAction *action, KzWindow *kz)
{
	open_location(action, kz, LOCATION_FRAME, CURRENT_TAB);
}

static void
cb_editor_exit (GPid pid, gint status, gpointer data)
{
	gchar *text;
	gsize size;
	EditorInfo *einfo;
	
	GIOChannel *io;
	
	/* close editor process */
#if (GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION > 3)
	g_spawn_close_pid(pid);
#endif
	if (!data)
		return;
	einfo = (EditorInfo*)data;

	/* get text from temporary file */
	io = g_io_channel_new_file(einfo->filename, "r", NULL);
	g_io_channel_read_to_end(io, &text, &size, NULL);
	g_io_channel_unref(io);
	
	/* set text into textarea */
	if (text)
	{
		kz_moz_embed_set_text_into_textarea(einfo->kzembed,
						    einfo->element,
						    text);
		g_free(text);
	}

	g_free(einfo->filename);
	einfo->filename = NULL;
	einfo->kzembed  = NULL;
	einfo->element  = NULL;
	
	g_free(einfo);
}


static void
act_popup_launch_editor (GtkAction *action, KzWindow *kz)
{
	const KzEmbedEventMouse *event;
	GtkWidget *widget;

	GPid pid;
	GSpawnFlags flags;
	gint argc;
	gchar **argv = NULL;
	gchar *editor_command, *command, *text;
	EditorInfo *einfo = NULL;
	
	g_return_if_fail(KZ_IS_WINDOW(kz));
	widget = KZ_WINDOW_CURRENT_PAGE(kz);
	g_return_if_fail(KZ_IS_MOZ_EMBED(widget));

	event = kz_window_get_mouse_event_info(kz);
	g_return_if_fail(event);

	editor_command = KZ_CONF_GET_STR("Global", "editor_command");
	if (!editor_command)
		return;

	if (event->cinfo.context & KZ_CONTEXT_TEXTAREA)
	{
		einfo = g_new0(EditorInfo, 1);
		einfo->kzembed  = KZ_MOZ_EMBED(widget);
		einfo->element  = event->cinfo.element;
		text = kz_moz_embed_get_text_from_textarea(KZ_MOZ_EMBED(widget),
							   einfo->element);
		/* text in textare store in temporary file */
		if (text)
		{
			gint fd = g_file_open_tmp("kzXXXXXX",
						  &einfo->filename,
						  NULL);
			write(fd, text, strlen(text));
			close(fd);
			g_free(text);
		}

		command = g_strdup_printf(editor_command, einfo->filename);
	}
	else
	{
		command = g_strdup_printf(editor_command, "");
	}

	/* launch editor */
	g_shell_parse_argv(command,
			   &argc,
			   &argv,
			   NULL);

	flags = G_SPAWN_SEARCH_PATH |
		G_SPAWN_DO_NOT_REAP_CHILD;
	g_spawn_async(NULL,
		      argv,
		      NULL,
		      flags,
		      NULL,
		      NULL,
		      &pid,
		      NULL);
	g_free(editor_command);
	g_free(command);
	g_strfreev(argv);

	g_child_watch_add(pid,
			  cb_editor_exit,
			  einfo);

}

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

static void
cb_tablist_menuitem_activate (GtkWidget *menuitem, KzWindow *kz)
{
	gint page_num;
	GtkWidget *widget = g_object_get_data (G_OBJECT(menuitem),
					       KZ_ACTIONS_POPUP_TAB_KEY);

	page_num = gtk_notebook_page_num(GTK_NOTEBOOK(kz->notebook),
					 GTK_WIDGET(widget));

	gtk_notebook_set_current_page(GTK_NOTEBOOK(kz->notebook), page_num);
}


static void
act_popup_tab_list (GtkAction *action, KzWindow *kz)
{
	GtkWidget *popup_menu = NULL;
	gchar path[64] = {0};
	GList *children, *node;

	g_snprintf(path, sizeof(path), "/TabListPopup%s",
		   kz_ui_level_to_suffix(kz_ui_level()));

	popup_menu = gtk_ui_manager_get_widget(kz->menu_merge, path);
	if (!popup_menu) return;

	/* remove previous menu item */
	children = g_list_copy(GTK_MENU_SHELL(popup_menu)->children);
	
	for (node = children; node; node = g_list_next(node))
	{
		GtkWidget *menuitem = node->data;
		gtk_widget_destroy(menuitem);
	}
	g_list_free(children);

	kz_actions_popup_append_tablist_menuitem (kz, popup_menu);
	
	g_signal_connect(G_OBJECT(popup_menu), "hide",
			 G_CALLBACK(cb_popup_menu_hide), kz);
	gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL,
		       NULL, NULL, 0, 0);
	gtk_main();

	g_signal_handlers_disconnect_by_func(G_OBJECT(popup_menu),
					     G_CALLBACK(cb_popup_menu_hide), kz);
}


GtkActionEntry kz_actions_popup[] =
{
        /* Toplevel */

	{"OpenLink",            NULL, N_("_Open"),
	 NULL, N_("Open link"), G_CALLBACK(act_popup_open)},
	{"OpenLinkInNewTab",    NULL, N_("Open in new _tab"),
	 NULL, N_("Open link in a new tab"), G_CALLBACK(act_popup_open_in_new_tab)},
	{"OpenLinkInNewWindow", KZ_STOCK_OPEN_LINK_WINDOW, N_("Open in new _window"),
	 NULL, N_("Open link in a new window"), G_CALLBACK(act_popup_open_in_new_win)},
	{"CopyLinkLocation", KZ_STOCK_COPY_URL, N_("Copy _link location"),
	 NULL, N_("Copy the location of the link"), G_CALLBACK(act_popup_copy_link_location)},
	{"SaveLink", KZ_STOCK_SAVE_LINK, N_("Save lin_k to disk"),
	 NULL, N_("Save the object to disk"), G_CALLBACK(act_popup_save_link)},

	{"OpenImage",           NULL, N_("Open _image"),
	 NULL, N_("Open the image"), G_CALLBACK(act_popup_open_image)},
	{"OpenImageInNewTab",   NULL, N_("Open image in new ta_b"),
	 NULL, N_("Open the image in a new tab"), G_CALLBACK(act_popup_open_image_in_new_tab)},
	{"OpenImageInNewWindow",KZ_STOCK_OPEN_IMAGE_WINDOW, N_("Open image in _new window"),
	 NULL, N_("Open the image in a new window"), G_CALLBACK(act_popup_open_image_in_new_win)},
	{"CopyImageLocation", KZ_STOCK_COPY_IMAGE_URL, N_("Copy image l_ocation"),
	 NULL, N_("Copy the location of the image"), G_CALLBACK(act_popup_copy_image_location)},
	{"SaveImage",           NULL, N_("Sa_ve image as"),
	 NULL, N_("Save the image to disk"), G_CALLBACK(act_popup_save_image)},

	{"OpenThisFrame",        NULL, N_("Open this _frame"),
	NULL, N_("Open the frame in the current tab"),  G_CALLBACK(act_popup_open_frame)},

	{"LaunchEditor",         KZ_STOCK_EDITOR, N_("_Launch Editor"),
	 NULL, N_("Launch external editor"), G_CALLBACK(act_popup_launch_editor)},
	{"PopupTabList",         NULL, N_("_Popup TabList"),
	 NULL, N_("Display tab list"), G_CALLBACK(act_popup_tab_list)},

	{"StockEncodingMenu", NULL, N_("_Encoding"), NULL, NULL, NULL},
	{"StockTabList",      NULL, N_("_TabList"),  NULL, NULL, NULL},
};

const gint kz_actions_popup_len = G_N_ELEMENTS(kz_actions_popup);


GtkActionGroup *
kz_actions_popup_create_group (KzWindow *kz, GtkAccelGroup *accel_group)
{
	GtkActionGroup *action_group;
	GList *node, *action_list;

	action_group = gtk_action_group_new("KzWindowPopup");

	gtk_action_group_set_translation_domain(action_group, NULL);

	gtk_action_group_add_actions (action_group,
				      kz_actions_popup,
				      kz_actions_popup_len,
				      kz);

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

static GHashTable *popup_menu_table = NULL;

static void
cb_popup_destroy (GtkWidget *extra_menu)
{
	if (popup_menu_table) 
	{
		g_hash_table_remove(popup_menu_table, extra_menu);
	}
	return;
}

static void
cb_encoding_menuitem_activate (GtkWidget *menuitem, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);

	if (GTK_CHECK_MENU_ITEM(menuitem)->active && KZ_IS_MOZ_EMBED(widget))
	{
		const gchar* code = g_object_get_data (G_OBJECT(menuitem),
						       KZ_ACTIONS_POPUP_LANGUAGE_KEY);

		GtkAction *action;

		kz_moz_embed_set_encoding(KZ_MOZ_EMBED(widget), code);

		action = gtk_action_group_get_action(kz->actions, "Reload");

		gtk_action_activate(action);
	}
	return;
}

static void
kz_actions_popup_append_encoding_menuitem (KzWindow *kz, GtkMenuItem *encoding_menu)
{
	GtkWidget *encoding_submenu;

	if (!popup_menu_table) {
		popup_menu_table = g_hash_table_new(g_direct_hash,
						    g_direct_equal);
	}

	encoding_submenu = g_hash_table_lookup(popup_menu_table, encoding_menu);
	if (!encoding_submenu) 
	{
		GtkWidget *menuitem;
		GSList *group = NULL;
		GtkWidget *page = KZ_WINDOW_CURRENT_PAGE(kz);
		guint  i;
		gchar *current_encoding = NULL;
		gboolean forced = FALSE;
		
                /* append encodings menuitem */
		encoding_submenu = gtk_menu_new();
		
                /* get current charset */
		if(KZ_IS_MOZ_EMBED(page))
		{
			kz_moz_embed_get_encoding (KZ_MOZ_EMBED(page), &current_encoding, &forced);
		}
		
		menuitem = gtk_radio_menu_item_new_with_label (group,_("Auto"));
		if(!forced) {
			gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
							TRUE);
		}
		
		group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
		g_object_set_data (G_OBJECT (menuitem), KZ_ACTIONS_POPUP_LANGUAGE_KEY, "");
		
		g_signal_connect (G_OBJECT(menuitem), "activate",
				  G_CALLBACK (cb_encoding_menuitem_activate), kz);
		
		gtk_menu_shell_append (GTK_MENU_SHELL(encoding_submenu), menuitem);
		gtk_widget_show (menuitem);

                /* separator */
		menuitem = gtk_separator_menu_item_new();
		gtk_menu_shell_append(GTK_MENU_SHELL(encoding_submenu), menuitem);
		gtk_widget_show(menuitem);
	
		for (i = 0; i < n_languages; ++i)
		{
			menuitem = gtk_radio_menu_item_new_with_label (group,_(languages[i].name));
			
			if (forced && !strcmp(current_encoding, languages[i].code))
			{
				gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
								TRUE);
			}
			
			group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
			
			g_object_set_data (G_OBJECT (menuitem), KZ_ACTIONS_POPUP_LANGUAGE_KEY,
					   (gchar*)languages[i].code);
			
			g_signal_connect (G_OBJECT(menuitem), "activate",
					  G_CALLBACK (cb_encoding_menuitem_activate), kz);
		
			gtk_menu_shell_append (GTK_MENU_SHELL(encoding_submenu), menuitem);
			gtk_widget_show (menuitem);
		}
		gtk_menu_item_set_submenu(GTK_MENU_ITEM(encoding_menu), encoding_submenu);
		
		g_free(current_encoding);
		
                /* reference */
		g_hash_table_insert(popup_menu_table, encoding_menu, encoding_submenu);
		g_signal_connect(G_OBJECT(encoding_menu), "destroy",
				 G_CALLBACK(cb_popup_destroy), NULL);
	}
	return;
}


static void
kz_actions_popup_append_tablist_menuitem (KzWindow *kz, GtkWidget *tablist_menu)
{
	gint i;
	const gint num = gtkutil_notebook_get_n_pages(GTK_NOTEBOOK(kz->notebook));
	GtkWidget *tablist_submenu;
	GtkWidget *page;
	gint current_page_num;
	KzFavicon *kzfav;

	kzfav = kz_favicon_get_instance();

	if (GTK_IS_MENU_ITEM(tablist_menu))
	{
		if (!popup_menu_table)
		{
			popup_menu_table = g_hash_table_new(g_direct_hash,
							    g_direct_equal);
		}

		tablist_submenu = g_hash_table_lookup(popup_menu_table,
						      tablist_menu);

		if (tablist_submenu)
		{
			gtk_menu_item_remove_submenu(GTK_MENU_ITEM(tablist_menu));
		}
        	/* append tablist menuitem */
		tablist_submenu = gtk_menu_new();
	}
	else
	{
		tablist_submenu = tablist_menu;
	}

	page = KZ_WINDOW_CURRENT_PAGE(kz);
	current_page_num = gtk_notebook_page_num(GTK_NOTEBOOK(kz->notebook),
						 GTK_WIDGET(page));

	for (i = 0; i < num; i++)
	{
		KzMozEmbed *kzembed = KZ_MOZ_EMBED(KZ_WINDOW_NTH_PAGE(kz, i));
		GtkWidget *favicon;
		if (KZ_IS_MOZ_EMBED(kzembed))
		{
			gchar *title, *escaped, *markup_title;
			GtkWidget *menuitem;
			GtkWidget *tab;
			KzTabLabelState state;
			
			tab = kz_window_get_tab_label(kz, GTK_WIDGET(kzembed));
			state = kz_tab_label_get_state(KZ_TAB_LABEL(tab));
			title = kz_moz_embed_ensure_title(kzembed);
			escaped = g_markup_escape_text(title,
						       strlen(title));
			menuitem = gtk_image_menu_item_new_with_label (title);

			if (i == current_page_num)
			{
				markup_title = g_strdup_printf("<b>%s</b>",
							       escaped);
			}
			else
			{
				markup_title = g_strdup_printf("<span foreground=\"%s\">%s</span>",
							       label_color[state],
							       escaped);
			}

			gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(menuitem))),
					     markup_title);
			g_free(markup_title);
			g_free(escaped);
			
			/* favicon */
			favicon = kz_favicon_get_widget(kzfav,
							kz_moz_embed_get_location(kzembed),
							KZ_ICON_SIZE_BOOKMARK_MENU);
			if (favicon)
			{
				gtk_widget_show(favicon);
				gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem),
							      favicon);
			}

			g_object_set_data (G_OBJECT (menuitem), KZ_ACTIONS_POPUP_TAB_KEY, kzembed);

			g_signal_connect (G_OBJECT(menuitem), "activate",
					  G_CALLBACK(cb_tablist_menuitem_activate), kz);
			gtk_menu_shell_append (GTK_MENU_SHELL(tablist_submenu), menuitem);
			gtk_widget_show (menuitem);
			g_free(title);
		}
	}
	if (GTK_IS_MENU_ITEM(tablist_menu))
	{
		gtk_menu_item_set_submenu(GTK_MENU_ITEM(tablist_menu),
					  tablist_submenu);

        	/* reference */
		g_hash_table_insert(popup_menu_table,
				    tablist_menu,
				    tablist_submenu);
		g_signal_connect(G_OBJECT(tablist_menu), "destroy",
				 G_CALLBACK(cb_popup_destroy), NULL);
	}
	g_object_unref(kzfav);
	return;
}

#define GET_MENU(kz, path) \
	(gtk_ui_manager_get_widget(kz->menu_merge, path))


void
kz_actions_popup_menu_modal (KzWindow *kz, guint button, guint time)
{
	GtkWidget *popup_menu = NULL;
	GtkWidget *extra_menu = NULL;
	const KzEmbedEventMouse *event;
	gboolean is_selection, is_doc, is_link, is_image, is_input, is_frame;
	gchar path[64] = {0};
	gchar extra_menu_path[64] = {0};

	event = kz_window_get_mouse_event_info(kz);
	if (!event) return;

	is_selection = event->cinfo.context & KZ_CONTEXT_SELECTION;
	is_doc       = event->cinfo.context & KZ_CONTEXT_DOCUMENT;
	is_link      = event->cinfo.context & KZ_CONTEXT_LINK;
	is_image     = event->cinfo.context & KZ_CONTEXT_IMAGE;
	is_input     = event->cinfo.context & KZ_CONTEXT_INPUT;
	is_frame     = event->cinfo.context & KZ_CONTEXT_FRAME;

#if 0
	if (is_selection)
		/*
		 * FIXME!! We should merge this menu items to other context's
		 * menu.
		 */
		popup_menu = GET_MENU(kz, "/SelectionPopup");
	else
#endif
	if (is_doc)
	{
		if (is_frame)
			g_snprintf(path, sizeof(path), "/DocumentPopupinFrame%s",
				   kz_ui_level_to_suffix(kz_ui_level()));
		else
			g_snprintf(path, sizeof(path), "/DocumentPopup%s",
				   kz_ui_level_to_suffix(kz_ui_level()));
	}
	if (is_link && is_image)
		g_snprintf(path, sizeof(path), "/LinkImagePopup%s",
			   kz_ui_level_to_suffix(kz_ui_level()));
	else if (is_link)
		g_snprintf(path, sizeof(path), "/LinkPopup%s",
			   kz_ui_level_to_suffix(kz_ui_level()));
	else if (is_image)
		g_snprintf(path, sizeof(path), "/ImagePopup%s",
			   kz_ui_level_to_suffix(kz_ui_level()));
	else if (is_input)
		g_snprintf(path, sizeof(path), "/InputPopup%s",
			   kz_ui_level_to_suffix(kz_ui_level()));

	if (!*path) return;

	popup_menu = GET_MENU(kz, path);
	if (!popup_menu) return;

	if (is_input) {
		gtkutil_append_im_menuitem(GTK_MENU_SHELL(popup_menu));
	}

        /* add encoding menu */
	g_snprintf(extra_menu_path, sizeof(extra_menu_path), "%s/EncodingMenu", path);

	extra_menu = GET_MENU(kz, extra_menu_path);
	if(extra_menu) 
	{
		kz_actions_popup_append_encoding_menuitem(kz, GTK_MENU_ITEM(extra_menu));
	}

        /* add tablist */
	g_snprintf(extra_menu_path, sizeof(extra_menu_path), "%s/TabList", path);
	extra_menu = GET_MENU(kz, extra_menu_path);
	if(extra_menu) 
	{
		kz_actions_popup_append_tablist_menuitem (kz, extra_menu);
	}

	g_signal_connect(G_OBJECT(popup_menu), "hide",
			 G_CALLBACK(cb_popup_menu_hide), kz);
	gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL,
		       NULL, NULL, 0, time);
	gtk_main();

	g_signal_handlers_disconnect_by_func(G_OBJECT(popup_menu),
					     G_CALLBACK(cb_popup_menu_hide), kz);
}
