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

/*
 *  Copyright (C) 2003 Hiroyuki Ikezoe
 *  Copyright (C) 2003 Takuro Ashie <ashie@homa.ne.jp>
 *
 *  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 "gtk-utils.h"
#include <string.h>
#include <glib/gi18n.h>

#define ICON_TRANS 192

/**
 * menu_position_under_widget:
 * this function from galeon-1.2.7
 */
void
gtkutil_menu_position_under_widget (GtkMenu *menu, gint *x, gint *y,
				    gboolean *push_in, gpointer user_data)
{
	GtkWidget *w = GTK_WIDGET(user_data);
	gint wheight;
	gint wx, wy;

	gdk_window_get_origin(w->window, x, y);
	wheight = w->requisition.height;
	wx = w->allocation.x;
	wy = w->allocation.y;
	
	*y = *y + wy + wheight;
	*x = *x + wx;
}


gboolean
gtkutil_confirm_file_replace (GtkWindow *parent, const gchar *filename)
{
	GtkWidget *dialog;
	gint res;

	dialog = gtk_message_dialog_new(parent,
					GTK_DIALOG_DESTROY_WITH_PARENT,
					GTK_MESSAGE_WARNING,
					GTK_BUTTONS_NONE,
					_("%s is already exist.\n\n Replace it?"),
					filename);
	gtk_dialog_add_buttons(GTK_DIALOG(dialog),
			       _("Cancel"), GTK_RESPONSE_REJECT,
			       _("Replace"), GTK_RESPONSE_ACCEPT,
			       NULL);
	res = gtk_dialog_run(GTK_DIALOG(dialog));
	gtk_widget_destroy(dialog);
	
	return (res == GTK_RESPONSE_ACCEPT);
}
#if 0
GList *
gtkutil_tree_selection_get_selected_references(GtkTreeSelection *selection,
					       GtkTreeModel **tree_model)
{
	GtkTreeModel *model;
	GList *list, *ref_list = NULL;

	g_return_val_if_fail(GTK_IS_TREE_SELECTION(selection), NULL);

	list = gtk_tree_selection_get_selected_rows(selection, &model);

	for (; list; list = g_list_next(list)) {
		GtkTreeRowReference *ref = NULL;
		if (list->data != NULL)
			ref = gtk_tree_row_reference_new(model, list->data);
		if (ref != NULL)
			ref_list = g_list_append(ref_list, ref);
	}

	if (list) {
		g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
		g_list_free(list);
	}

	if (tree_model != NULL)
		*tree_model = model;

	return ref_list;
}
#endif
void
gtkutil_copy_text (const gchar *text)
{
	if (text && *text)
	{
		GtkClipboard *clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
		gtk_clipboard_set_text(clipboard, text, strlen(text));
		clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
		gtk_clipboard_set_text(clipboard, text, strlen(text));
	}
}


static GHashTable *popup_menu_table;

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


void
gtkutil_append_im_menuitem (GtkMenuShell *shell)
{
	static GtkIMMulticontext *im_context = NULL;
	GtkWidget *immenu, *menuitem;

	if (!im_context)
		im_context = GTK_IM_MULTICONTEXT(gtk_im_multicontext_new());

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

	menuitem = g_hash_table_lookup(popup_menu_table, shell);
	if (menuitem)
	{
		gtk_menu_item_remove_submenu(GTK_MENU_ITEM(menuitem));
	}
	else
	{
		/* separator */
		menuitem = gtk_separator_menu_item_new();
		gtk_menu_shell_append(shell, menuitem);
		gtk_widget_show(menuitem);

		/* input methods menuitem */
		menuitem = gtk_menu_item_new_with_label(_("Input Methods"));
		gtk_menu_shell_append(shell, menuitem);
		gtk_widget_show(menuitem);

		/* reference */
		g_hash_table_insert(popup_menu_table, shell, menuitem);
		g_signal_connect(G_OBJECT(shell), "destroy",
				 G_CALLBACK(cb_popup_destroy), NULL);
	}

	/* input methods submenu */
	immenu = gtk_menu_new();
	gtk_im_multicontext_append_menuitems
		(im_context, GTK_MENU_SHELL(immenu));
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), immenu);
}



void
gtkutil_superpose_pixbuf(GtkWidget *widget, GdkPixbuf *pixbuf, 
			 const gchar *stock_id, GtkIconSize size)
{
	gint width, height;
	GdkPixbuf *orig_pixbuf;

	orig_pixbuf = gtk_widget_render_icon(widget, stock_id, 
					     size,
					     NULL);
	gtk_icon_size_lookup(size, &width, &height);

	if (pixbuf)
	{
		gint x, y;
		GdkPixbuf *scaled_pixbuf, *transparent_pixbuf;
		
		x = width / 2;
		y = width / 2;
		scaled_pixbuf = gdk_pixbuf_scale_simple(orig_pixbuf,
							x, y,
							GDK_INTERP_NEAREST);
		transparent_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
						    TRUE,
						    8,
						    width,
						    height);
		gdk_pixbuf_fill(transparent_pixbuf, 0);
		gdk_pixbuf_composite(pixbuf,
				     transparent_pixbuf,
				     0, 0,
				     width, height,
				     0, 0,
				     1, 1,
				     GDK_INTERP_NEAREST,
				     ICON_TRANS);
		gdk_pixbuf_composite(scaled_pixbuf,
				     transparent_pixbuf,
				     x, y,
				     x, y,
				     x, y,
				     1, 1,
				     GDK_INTERP_NEAREST,
				     255);
				     
		gtk_image_set_from_pixbuf(GTK_IMAGE(widget), transparent_pixbuf);
		g_object_unref(scaled_pixbuf);
		g_object_unref(transparent_pixbuf);
	}
	else 
		gtk_image_set_from_pixbuf(GTK_IMAGE(widget), orig_pixbuf);

	g_object_unref(orig_pixbuf);
}

#if (GTK_MAJOR_VERSION == 2) && (GTK_MINOR_VERSION < 5)

#define OFFSET(pb, x, y) ((x) * n_channels + (y) * rowstride)
#define DEST_OFFSET(pb, x, y) ((x) * dest_n_channels + (y) * dest_rowstride)

/* this function is taken from GTK+-2.5.x */
GdkPixbuf *
gdk_pixbuf_rotate_simple (const GdkPixbuf   *src,
			  GdkPixbufRotation  angle)
{
	GdkPixbuf *dest;
  	guchar *p, *q;
  	gint x, y;
  	GdkColorspace colorspace;
  	gboolean has_alpha;
  	guchar *pixels, *dest_pixels;
  	int height, width;
  	int rowstride, dest_rowstride;
  	int bits_per_sample;
  	int n_channels, dest_n_channels;

  	colorspace      = gdk_pixbuf_get_colorspace(src);
  	has_alpha       = gdk_pixbuf_get_has_alpha(src);
  	pixels          = gdk_pixbuf_get_pixels(src);
  	height          = gdk_pixbuf_get_height(src);
  	width           = gdk_pixbuf_get_width(src);
  	rowstride       = gdk_pixbuf_get_rowstride(src);
  	bits_per_sample = gdk_pixbuf_get_bits_per_sample(src);
  	n_channels      = gdk_pixbuf_get_n_channels(src);

  	switch (angle % 360)
    	{
    	case 0:
      		dest = gdk_pixbuf_copy (src);
      		break;
    	case 90:
      		dest = gdk_pixbuf_new (colorspace, 
				       has_alpha, 
			     	       bits_per_sample, 
			     	       height,
			     	       width);
      		if (!dest)
			return NULL;
      		dest_pixels = gdk_pixbuf_get_pixels(dest);
      		dest_n_channels = gdk_pixbuf_get_n_channels(dest);
      		dest_rowstride = gdk_pixbuf_get_rowstride(dest);
      		for (y = 0; y < height; y++) 
		{ 
	  		for (x = 0; x < width; x++) 
	    		{ 
	      			p = pixels + OFFSET (src, x, y); 
	      			q = dest_pixels + DEST_OFFSET (dest, y, width - x - 1); 
	      			memcpy (q, p, dest_n_channels);
	    		}
		} 
      		break;
    	case 180:
     		dest = gdk_pixbuf_new (colorspace, 
				       has_alpha, 
			     	       bits_per_sample, 
			    	       width, 
			    	       height);
      		if (!dest)
			return NULL;

      		dest_pixels = gdk_pixbuf_get_pixels(dest);
      		dest_n_channels = gdk_pixbuf_get_n_channels(dest);
      		dest_rowstride = gdk_pixbuf_get_rowstride(dest);
      		for (y = 0; y < height; y++) 
		{ 
	  		for (x = 0; x < width; x++) 
	    		{ 
	      			p = pixels + OFFSET (src, x, y); 
	      			q = dest_pixels + DEST_OFFSET (dest, width - x - 1, height - y - 1); 
	      			memcpy (q, p, n_channels);
	    		}
		} 
      		break;
    	case 270:
      		dest = gdk_pixbuf_new (colorspace, 
				       has_alpha, 
			    	       bits_per_sample, 
			     	       height, 
			     	       width);
      		if (!dest)
			return NULL;
      		dest_pixels = gdk_pixbuf_get_pixels(dest);
      		dest_n_channels = gdk_pixbuf_get_n_channels(dest);
      		dest_rowstride = gdk_pixbuf_get_rowstride(dest);
      		for (y = 0; y < height; y++) 
		{ 
			for (x = 0; x < width; x++) 
			{ 
	      			p = pixels + OFFSET (src, x, y); 
	      			q = dest_pixels + DEST_OFFSET (dest, height - y - 1, x); 
	      			memcpy (q, p, n_channels);
	    		}
		} 
      		break;
    	default:
      		dest = NULL;
      		g_warning ("gdk_pixbuf_rotate_simple() can only rotate "
		 	   "by multiples of 90 degrees");
      		g_assert_not_reached ();
  	} 

  	return dest;
}
#endif
