/*
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
 * Copyright (C) 1999-2004 Hiroyuki Yamamoto
 *
 * 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 of the License, 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.
 */

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include <glib.h>
#include <gtk/gtkwidget.h>
#include <gtk/gtkmenu.h>
#include <gtk/gtkmenubar.h>
#include <gtk/gtkcheckmenuitem.h>
#include <gtk/gtkitemfactory.h>
#include <gtk/gtkbutton.h>

#include "intl.h"
#include "menu.h"
#include "utils.h"

static gchar *menu_translate(const gchar *path, gpointer data);

GtkWidget *menubar_create(GtkWidget *window, GtkItemFactoryEntry *entries,
			  guint n_entries, const gchar *path, gpointer data)
{
	GtkItemFactory *factory;

	factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, path, NULL);
	gtk_item_factory_set_translate_func(factory, menu_translate,
					    NULL, NULL);
	gtk_item_factory_create_items(factory, n_entries, entries, data);
	gtk_accel_group_attach(factory->accel_group, GTK_OBJECT(window));

	return gtk_item_factory_get_widget(factory, path);
}

GtkWidget *menu_create_items(GtkItemFactoryEntry *entries,
			     guint n_entries, const gchar *path,
			     GtkItemFactory **factory, gpointer data)
{
	*factory = gtk_item_factory_new(GTK_TYPE_MENU, path, NULL);
	gtk_item_factory_set_translate_func(*factory, menu_translate,
					    NULL, NULL);
	gtk_item_factory_create_items(*factory, n_entries, entries, data);

	return gtk_item_factory_get_widget(*factory, path);
}

static gchar *menu_translate(const gchar *path, gpointer data)
{
	gchar *retval;

	retval = gettext(path);

	return retval;
}

static void factory_print_func(gpointer data, gchar *string)
{
	GString *out_str = data;

	g_string_append(out_str, string);
	g_string_append_c(out_str, '\n');
}

GString *menu_factory_get_rc(const gchar *path)
{
	GString *string;
	GtkPatternSpec *pspec;
	gchar pattern[256];

	pspec = g_new(GtkPatternSpec, 1);
	g_snprintf(pattern, sizeof(pattern), "%s*", path);
	gtk_pattern_spec_init(pspec, pattern);
	string = g_string_new("");
	gtk_item_factory_dump_items(pspec, FALSE, factory_print_func,
				    string);
	gtk_pattern_spec_free_segs(pspec);

	return string;
}

void menu_factory_clear_rc(const gchar *rc_str)
{
	GString *string;
	gchar *p;
	gchar *start, *end;
	guint pos = 0;

	string = g_string_new(rc_str);
	while ((p = strstr(string->str + pos, "(menu-path \"")) != NULL) {
		pos = p + 12 - string->str;
		p = strchr(p + 12, '"');
		if (!p) continue;
		start = strchr(p + 1, '"');
		if (!start) continue;
		end = strchr(start + 1, '"');
		if (!end) continue;
		pos = start + 1 - string->str;
		if (end > start + 1)
			g_string_erase(string, pos, end - (start + 1));
	}

	gtk_item_factory_parse_rc_string(string->str);
	g_string_free(string, TRUE);
}

void menu_factory_copy_rc(const gchar *src_path, const gchar *dest_path)
{
	GString *string;
	gint src_path_len;
	gint dest_path_len;
	gchar *p;
	guint pos = 0;

	string = menu_factory_get_rc(src_path);
	src_path_len = strlen(src_path);
	dest_path_len = strlen(dest_path);

	while ((p = strstr(string->str + pos, src_path)) != NULL) {
		pos = p - string->str;
		g_string_erase(string, pos, src_path_len);
		g_string_insert(string, pos, dest_path);
		pos += dest_path_len;
	}

	pos = 0;
	while ((p = strchr(string->str + pos, ';')) != NULL) {
		pos = p - string->str;
		if (pos == 0 || *(p - 1) == '\n')
			g_string_erase(string, pos, 1);
	}

	menu_factory_clear_rc(string->str);
	gtk_item_factory_parse_rc_string(string->str);
	g_string_free(string, TRUE);
}

void menu_set_sensitive(GtkItemFactory *ifactory, const gchar *path,
			gboolean sensitive)
{
	GtkWidget *widget;

	g_return_if_fail(ifactory != NULL);

	widget = gtk_item_factory_get_item(ifactory, path);
	gtk_widget_set_sensitive(widget, sensitive);
}

void menu_set_sensitive_all(GtkMenuShell *menu_shell, gboolean sensitive)
{
	GList *cur;

	for (cur = menu_shell->children; cur != NULL; cur = cur->next)
		gtk_widget_set_sensitive(GTK_WIDGET(cur->data), sensitive);
}

void menu_set_active(GtkItemFactory *ifactory, const gchar *path,
		     gboolean is_active)
{
	GtkWidget *widget;

	g_return_if_fail(ifactory != NULL);

	widget = gtk_item_factory_get_item(ifactory, path);
	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), is_active);
}

void menu_button_position(GtkMenu *menu, gint *x, gint *y, gpointer user_data)
{
	GtkWidget *button;
	GtkRequisition requisition;
	gint button_xpos, button_ypos;
	gint xpos, ypos;
	gint width, height;
	gint scr_width, scr_height;

	g_return_if_fail(user_data != NULL);
	g_return_if_fail(GTK_IS_BUTTON(user_data));

	button = GTK_WIDGET(user_data);

	gtk_widget_get_child_requisition(GTK_WIDGET(menu), &requisition);
	width = requisition.width;
	height = requisition.height;
	gdk_window_get_origin(button->window, &button_xpos, &button_ypos);

	xpos = button_xpos;
	ypos = button_ypos + button->allocation.height;

	scr_width = gdk_screen_width();
	scr_height = gdk_screen_height();

	if (xpos + width > scr_width)
		xpos -= (xpos + width) - scr_width;
	if (ypos + height > scr_height)
		ypos = button_ypos - height;
	if (xpos < 0)
		xpos = 0;
	if (ypos < 0)
		ypos = 0;

	*x = xpos;
	*y = ypos;
}

gint menu_find_option_menu_index(GtkOptionMenu *optmenu, gpointer data,
				 GCompareFunc func)
{
	GtkWidget *menu;
	GtkWidget *menuitem;
	gpointer menu_data;
	GList *cur;
	gint n;

	menu = gtk_option_menu_get_menu(optmenu);

	for (cur = GTK_MENU_SHELL(menu)->children, n = 0;
	     cur != NULL; cur = cur->next, n++) {
		menuitem = GTK_WIDGET(cur->data);
		menu_data = gtk_object_get_user_data(GTK_OBJECT(menuitem));
		if (func) {
			if (func(menu_data, data) == 0)
				return n;
		} else if (menu_data == data)
			return n;
	}

	return -1;
}

gpointer menu_get_option_menu_active_user_data(GtkOptionMenu *optmenu)
{
	GtkWidget *menu;
	GtkWidget *menuitem;

	menu = gtk_option_menu_get_menu(optmenu);
	menuitem = gtk_menu_get_active(GTK_MENU(menu));

	return gtk_object_get_user_data(GTK_OBJECT(menuitem));
}
