/* Bluefish HTML Editor
 * images.c - anything dealing with images
 *
 * Copyright (C) 1998-2001 Olivier Sessink
 *
 * 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
 */
#include "default_include.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gdk/gdk.h>

#include "cap.h"
#include "bluefish.h"
#include "bf_lib.h"
#include "init.h"
#include "gtk_easy.h"
#include "html_diag.h" /* parse_html_for_dialogvalues() */
#include "document.h"
#include "rpopup.h"
#include "images.h"
#ifdef WIN32
#define DIRSTR "\\"
#define DIRCHR 92
#else
#define DIRSTR "/"
#define DIRCHR '/'
#endif
#ifdef USE_GDK_PIXBUF
#include <gdk-pixbuf/gdk-pixbuf.h>
int create_thumbnail(gchar *filename, GdkPixbuf * pb, gint w, gint h);
#endif /* USE_GDK_PIXBUF  */

#ifdef USE_LIBGDK_IMLIB
#include <gdk_imlib.h>
#endif /* USE_LIBGDK_IMLIB */

#ifdef HAVE_IMAGE_LIBS
typedef struct {
	GtkWidget *pixwin;
	GtkWidget *pixmap;
	GtkWidget *width;
	GtkWidget *width_perc;
	GtkWidget *height;
	GtkWidget *height_perc;
	GtkWidget *alt;
	GtkWidget *border;
	GtkWidget *location;
	GtkWidget *hspace;
	GtkWidget *vspace;
	GtkWidget *align;
	GtkWidget *frame;
	GtkWidget *custom;
	GtkWidget *usemap;
	GtkWidget *name;
	Treplacerange range;
	gint tnH;
	gint tnW;
	gint h;
	gint w;
	GdkPixmap *p;
	GdkBitmap *m;
	gboolean thumbnail;
	GtkAdjustment *adjustment;
#ifdef USE_GDK_PIXBUF
	GdkPixbuf *im;
#else
	GdkImlibImage *im;
#endif
	Tdocument *doc;
} Timagewin;

/************************************************************************/
/* function declarations */
void image_thumbnail_dialog_cb(GtkWidget * widget, gpointer data);
void image_insert_dialog_cb(GtkWidget * widget, gpointer data);
void image_insert_dialog_cb(GtkWidget * widget, gpointer data);
void image_thumbnail_dialog_cb(GtkWidget * widget, gpointer data);
static void image_filename_changed(GtkWidget * widget, Timagewin * image_win);
static void image_dialog(GtkWidget * widget, gpointer data, gboolean thumb);
static void insert_image_html(GtkWidget * widget, Timagewin * win);
static void destroy_image_win(GtkWidget * w, Timagewin * image_win);
static void image_adjust_changed(GtkAdjustment * adj, Timagewin * image_win);
/************************************************************************/

void image_thumbnail_dialog_cb(GtkWidget * widget, gpointer data)
{
	DEBUG_MSG("image_thumbnail_dialog_cb, widget=%p, data=%p\n", widget, data);
	image_dialog(widget, data, 1);
}

/************************************************************************/
void image_insert_dialog_cb(GtkWidget * widget, gpointer data)
{
	DEBUG_MSG("image_insert_dialog_cb, widget=%p, data=%p\n", widget, data);
	image_dialog(widget, data, 0);
}

/************************************************************************/
#ifdef USE_GDK_PIXBUF
static void image_filename_changed(GtkWidget * widget, Timagewin * image_win) {
	gfloat toobig;
	gfloat temp;
	GdkPixbuf *tmp_im;

	if (image_win->im) {
		gdk_pixbuf_unref(image_win->im);
	}
	image_win->im = gdk_pixbuf_new_from_file(gtk_entry_get_text(GTK_ENTRY(image_win->location)));
	DEBUG_MSG("image_filename_changed, loaded using gdk_pixbuf\n");
	if (!image_win->im) {
		return;
	}
	toobig = 1;
	image_win->w = gdk_pixbuf_get_width(image_win->im);
	temp = (gfloat) image_win->w / 250;
	DEBUG_MSG("width, temp = %f\n", temp);
	if (temp > toobig) {
		toobig = temp;
	}
	image_win->h = gdk_pixbuf_get_height(image_win->im);
	temp = (gfloat) image_win->h / 300;
	DEBUG_MSG("height, temp = %f\n", temp);
	if (temp > toobig) {
		toobig = temp;
	}
	DEBUG_MSG("Image size -> width = %d, height = %d. Toobig = %f\n", image_win->w, image_win->h, toobig);

 	tmp_im = gdk_pixbuf_scale_simple(image_win->im, (image_win->w / toobig), (image_win->h / toobig), GDK_INTERP_NEAREST);

	if (image_win->thumbnail) {
		gtk_adjustment_set_value(GTK_ADJUSTMENT(image_win->adjustment), 1.0 / toobig);
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(image_win->width), image_win->w / toobig);
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(image_win->height), image_win->h / toobig);
	} else {
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(image_win->width), image_win->w);
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(image_win->height), image_win->h);
	}

	gdk_pixbuf_render_pixmap_and_mask(tmp_im
			,&image_win->p,&image_win->m,128);

	gdk_pixbuf_unref (tmp_im);

	if (image_win->pixmap) {
		DEBUG_MSG("image_filename_changed, pimap re-set\n");
		gtk_pixmap_set(GTK_PIXMAP(image_win->pixmap), image_win->p, image_win->m);
	} else {
		DEBUG_MSG("image_filename_changed, pximap first time set\n");
		image_win->pixmap = gtk_pixmap_new(image_win->p, image_win->m);
		gtk_container_add(GTK_CONTAINER(image_win->frame), image_win->pixmap);
		gtk_widget_show(image_win->pixmap);
	}
	if (image_win->p) gdk_pixmap_unref (image_win->p);
	if (image_win->m) gdk_bitmap_unref (image_win->m);
}
#else

static void image_filename_changed(GtkWidget * widget, Timagewin * image_win)
{
	gfloat toobig;
	gfloat temp;

	if (image_win->im) {
		gdk_imlib_destroy_image(image_win->im);
	}
	
	image_win->im = gdk_imlib_load_image(gtk_entry_get_text(GTK_ENTRY(image_win->location)));
	DEBUG_MSG("image_filename_changed, loaded using imlib\n");
	if (!image_win->im) {
		return;
	}

	toobig = 1;
	image_win->w = image_win->im->rgb_width;
	temp = (gfloat) image_win->w / 250;
	DEBUG_MSG("width, temp = %f\n", temp);
	if (temp > toobig) {
		toobig = temp;
	}
	image_win->h = image_win->im->rgb_height;
	temp = (gfloat) image_win->h / 300;
	DEBUG_MSG("height, temp = %f\n", temp);
	if (temp > toobig) {
		toobig = temp;
	}
	DEBUG_MSG("Image size -> width = %d, height = %d. Toobig = %f\n", image_win->w, image_win->h, toobig);
	gdk_imlib_render(image_win->im, (image_win->w / toobig), (image_win->h / toobig));
	if (image_win->thumbnail) {
		gtk_adjustment_set_value(GTK_ADJUSTMENT(image_win->adjustment), 1.0 / toobig);
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(image_win->width), image_win->w / toobig);
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(image_win->height), image_win->h / toobig);
	} else {
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(image_win->width), image_win->w);
		gtk_spin_button_set_value(GTK_SPIN_BUTTON(image_win->height), image_win->h);
	}

	image_win->p = gdk_imlib_move_image(image_win->im);
	image_win->m = gdk_imlib_move_mask(image_win->im);

	if (image_win->pixmap) {
		DEBUG_MSG("image_filename_changed, pimap re-set\n");
		gtk_pixmap_set(GTK_PIXMAP(image_win->pixmap), image_win->p, image_win->m);
	} else {
		DEBUG_MSG("image_filename_changed, pximap first time set\n");
		image_win->pixmap = gtk_pixmap_new(image_win->p, image_win->m);
		gtk_container_add(GTK_CONTAINER(image_win->frame), image_win->pixmap);
		gtk_widget_show(image_win->pixmap);
	}
	gdk_imlib_free_pixmap(image_win->p);
	gdk_imlib_free_bitmap(image_win->m);

}
#endif

/************************************************************************/
static void image_dialog(GtkWidget * widget, gpointer data, gboolean thumb)
{

	Timagewin *image_win = NULL;
	GtkWidget *table, *scale, *hbox, *but;
	GtkObject *adj;
	gint count=0;
	static gchar *tagitems[] = { "width", "height", "alt", "border", "src", "hspace", "vspace", "align", "name", "usemap", NULL };
	gchar *tagvalues[11];
	gchar *custom = NULL;

	DEBUG_MSG("image_dialog, started\n");

#ifdef USE_GDK_PIXBUF
	/* do we need a gdk_pixbuf version of setting colormaps or is that integrated? */

#else 
	/* switch colormap to Imlib colormap, so image preview works */
	{
		GdkVisual	*gdkvisual;
		GdkColormap	*gdkcmap;

		gdkvisual = gdk_imlib_get_visual ();
		gdkcmap   = gdk_imlib_get_colormap ();

		if (gdkvisual && gdkcmap) {
			gtk_widget_push_visual (gdkvisual);
			gtk_widget_push_colormap (gdkcmap);
		}
	}
#endif

	image_win = g_malloc0(sizeof(Timagewin));
	image_win->doc = main_v->current_document;

	/* this is for the right click menu */
	while (tagitems[count]) {
		tagvalues[count] = NULL;
		count++;
	}
	if ((data != NULL) && (widget == NULL)) {
		parse_html_for_dialogvalues(tagitems, tagvalues, &custom, ((Ttagpopup *)data));
		image_win->range.pos = ((Ttagpopup *)data)->pos;
		image_win->range.len = ((Ttagpopup *)data)->len;
	} else {
		image_win->range.pos = -1;
		image_win->range.len = -1;	
	}
	/* end for the right click menu */

	image_win->thumbnail = thumb;
	if (thumb == 1) {
		image_win->pixwin = window_with_title(_("Insert image as thumbnail"), GTK_WIN_POS_CENTER, GTK_WINDOW_TOPLEVEL, 10);
	} else {
		image_win->pixwin = window_with_title(_("Insert image"), GTK_WIN_POS_CENTER, GTK_WINDOW_TOPLEVEL, 10);
	}

	hbox = gtk_hbox_new(FALSE, 1);
	gtk_container_add(GTK_CONTAINER(image_win->pixwin), hbox);

	image_win->frame = gtk_frame_new(_("Preview"));
/*	gtk_widget_set_usize(image_win->frame, 200, 0); */
	gtk_box_pack_start(GTK_BOX(hbox), image_win->frame, TRUE, TRUE, 5);

	table = gtk_table_new(14, 10, 0);
	gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 5);

	gtk_widget_realize(image_win->pixwin);
	image_win->location = entry_with_text(tagvalues[4], 0);
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->location, 0, 3, 1, 2);
	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new(_("Image location")), 0, 2, 0, 1);
	gtk_table_attach_defaults(GTK_TABLE(table), file_but_new(image_win->location, image_win->pixwin, 0), 3, 4, 1, 2);
	gtk_signal_connect(GTK_OBJECT(image_win->location), "activate", image_filename_changed, image_win);
	DEBUG_MSG("image_dialog, image_win->location=%p\n", image_win->location);

	adj = gtk_adjustment_new((gfloat) 0, 0.0, 10000.0, 1.0, 5.0, 0.0);
	image_win->width = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0);
	image_win->width_perc = gtk_check_button_new_with_label("%");
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->width_perc, 1, 2, 3, 4);
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->width, 0, 1, 3, 4);
	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new(_("Width")), 0, 2, 2, 3);
	parse_integer_for_dialog(tagvalues[0], image_win->width, NULL, image_win->width_perc);

	adj = gtk_adjustment_new((gfloat) 0, 0.0, 10000.0, 1.0, 5.0, 0.0);
	image_win->height = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0);
	image_win->height_perc = gtk_check_button_new_with_label("%");
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->height_perc, 3, 4, 3, 4);
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->height, 2, 3, 3, 4);
	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new(_("Height")), 2, 4, 2, 3);
	parse_integer_for_dialog(tagvalues[1], image_win->height, NULL, image_win->height_perc);

	image_win->alt = entry_with_text(tagvalues[2], 0);
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->alt, 0, 4, 5, 6);
	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new(_("Alternate text")), 0, 4, 4, 5);

	adj = gtk_adjustment_new((gfloat) 0, 0.0, 600.0, 1.0, 5.0, 0.0);
	image_win->border = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0);
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->border, 1, 2, 6, 7);
	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new(_("Border")), 0, 1, 6, 7);
	parse_integer_for_dialog(tagvalues[3], image_win->border, NULL, NULL);

	image_win->align = combo_with_popdown(tagvalues[7], positionlist, 1);
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->align, 3, 4, 6, 7);
	gtk_widget_set_usize(GTK_WIDGET(image_win->align), GTK_WIDGET(image_win->border)->allocation.width, 0);
	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new(_("Align")), 2, 3, 6, 7);

	adj = gtk_adjustment_new((gfloat) 0, 0.0, 600.0, 1.0, 5.0, 0.0);
	image_win->hspace = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0);
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->hspace, 1, 2, 7, 8);
	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new(_("Hspace")), 0, 1, 7, 8);
	parse_integer_for_dialog(tagvalues[5], image_win->hspace, NULL, NULL);

	adj = gtk_adjustment_new((gfloat) 0, 0.0, 600.0, 1.0, 5.0, 0.0);
	image_win->vspace = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0);
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->vspace, 3, 4, 7, 8);
	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new(_("Vspace")), 2, 3, 7, 8);
	parse_integer_for_dialog(tagvalues[6], image_win->vspace, NULL, NULL);

	image_win->name = entry_with_text(tagvalues[8], 0);
	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new(_("Name")), 0, 2, 8, 9);
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->name, 2, 4, 8, 9);

	image_win->usemap = entry_with_text(tagvalues[9], 0);
	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new(_("Usemap")), 0, 2, 9, 10);
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->usemap, 2, 4, 9, 10);

	image_win->custom = entry_with_text(custom, 0);
	gtk_table_attach_defaults(GTK_TABLE(table), image_win->custom, 0, 4, 11, 12);
	gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new(_("Custom")), 0, 4, 10, 11);

	if (image_win->thumbnail) {
		image_win->adjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0.5, 0.001, 1.1, 0.001, 0.1, 0.1));
		scale = gtk_hscale_new(image_win->adjustment);
		gtk_signal_connect(GTK_OBJECT(image_win->adjustment), "value_changed", GTK_SIGNAL_FUNC(image_adjust_changed), image_win);
		gtk_scale_set_digits(GTK_SCALE(scale), 3);
		gtk_range_set_update_policy(GTK_RANGE(scale), GTK_UPDATE_DISCONTINUOUS);
		gtk_table_attach_defaults(GTK_TABLE(table), scale, 0, 4, 12, 13);
	}

	DEBUG_MSG("image_dialog, calling activate on location entry\n");
	gtk_signal_emit_by_name(GTK_OBJECT(image_win->location), "activate");

	but = bf_stock_ok_button(insert_image_html, image_win);
	gtk_window_set_default(GTK_WINDOW(image_win->pixwin), but);
	gtk_table_attach_defaults(GTK_TABLE(table), but , 0, 2, 13, 14);

	gtk_table_attach_defaults(GTK_TABLE(table), bf_stock_cancel_button(destroy_image_win, image_win), 2, 4, 13, 14);
	gtk_widget_show_all(image_win->pixwin);

	gtk_widget_realize(GTK_WIDGET(image_win->pixwin));
	gtk_window_set_transient_for(GTK_WINDOW(image_win->pixwin), GTK_WINDOW(main_v->main_window));

	g_free(custom);

            /* switch colormap back to GdkRgb colormap */
        gtk_widget_pop_visual ();
        gtk_widget_pop_colormap ();
        
	/* DEBUG_MSG("image_dialog, finished, image_win->replace_range=%p\n", image_win->replace_range);*/
}

/************************************************************************/
static void insert_image_html(GtkWidget * widget, Timagewin * win)
{

	gchar *tempstring, *finalstring, *tnfilename;
#ifdef USE_LIBGDK_IMLIB
	GdkImlibImage *tmp_image;
#endif
	DEBUG_MSG("insert_image_html, started\n");
	if (win->thumbnail) {
		tnfilename = g_malloc0(strlen(gtk_entry_get_text(GTK_ENTRY(win->location))) + strlen(main_v->props.cfg_thumbnailstring) + 5);
		/* copy everythging except for the last 4 chars */
		/* FIXME: and what be if i using .jpeg not .jpg extension???? 
		--> you'll get two dots in your filename (Olivier) */
		strncpy(tnfilename, gtk_entry_get_text(GTK_ENTRY(win->location)), strlen(gtk_entry_get_text(GTK_ENTRY(win->location))) - 4);
		strcat(tnfilename, "\0");

		DEBUG_MSG("insert_image_html, halfway, tnfilename = %s\n", tnfilename);
		/* add the thumbnailstring and extension */
		strcat(tnfilename, main_v->props.cfg_thumbnailstring);
		strcat(tnfilename, ".");
		strcat(tnfilename, main_v->props.cfg_thumbnailtype);
		DEBUG_MSG("insert_image_html, final, tnfilename = %s\n", tnfilename);

		win->tnW = atoi(gtk_entry_get_text(GTK_ENTRY(win->width)));
		win->tnH = atoi(gtk_entry_get_text(GTK_ENTRY(win->height)));

#ifdef USE_GDK_PIXBUF
		create_thumbnail(tnfilename, win->im, win->tnW, win->tnH);
#else
		tmp_image = gdk_imlib_clone_scaled_image(win->im, win->tnW, win->tnH);
		gdk_imlib_save_image(tmp_image, tnfilename, NULL);
		gdk_imlib_destroy_image(tmp_image);
#endif
		DEBUG_MSG("insert_image_html, thumbnail created\n");

		tempstring =
			g_strdup_printf("%s%s%s%s%s", cap("<A HREF=\""), gtk_entry_get_text(GTK_ENTRY(win->location)), cap("\"><IMG SRC=\""),
							tnfilename, "\"");
		g_free(tnfilename);
		tempstring = insert_integer_if_spin(win->width, cap("WIDTH"), tempstring, NULL);
		tempstring = insert_integer_if_spin(win->height, cap("HEIGHT"), tempstring, NULL);
	} else {
		tempstring = g_strdup_printf("%s%s%s", cap("<IMG SRC=\""), gtk_entry_get_text(GTK_ENTRY(win->location)), "\"");
		tempstring = insert_integer_if_spin(win->width, cap("WIDTH"), tempstring, win->width_perc);
		tempstring = insert_integer_if_spin(win->height, cap("HEIGHT"), tempstring, win->height_perc);
	}
	tempstring = insert_integer_if_spin(win->border, cap("BORDER"), tempstring, NULL);
	tempstring = insert_integer_if_spin(win->vspace, cap("VSPACE"), tempstring, NULL);
	tempstring = insert_integer_if_spin(win->hspace, cap("HSPACE"), tempstring, NULL);
	tempstring = insert_string_if_entry(win->custom, NULL, tempstring, NULL);
	tempstring = insert_string_if_entry(win->alt, cap("ALT"), tempstring, (main_v->props.xhtml == 1 ? "No description" : NULL));
	tempstring = insert_string_if_entry(win->name, cap("NAME"), tempstring, NULL);
	tempstring = insert_string_if_entry(win->usemap, cap("USEMAP"), tempstring, NULL);
	tempstring = insert_string_if_entry(GTK_COMBO(win->align)->entry, cap("ALIGN"), tempstring, NULL);
	DEBUG_MSG("insert_image_html, 3, tempstring=%s\n", tempstring);
	if (win->thumbnail) {
		finalstring = g_strdup_printf(main_v->props.xhtml == 1 ? "%s /></%s>" : "%s></%s>", tempstring, cap("A"));
	} else {
		finalstring = g_strdup_printf(main_v->props.xhtml == 1 ? "%s />" : "%s>", tempstring);
	}
	g_free(tempstring);

	if (win->range.len == -1) {
		doc_insert_dbl_text(win->doc, finalstring, NULL);
	} else {
		replace_text(finalstring, win->range.pos, win->range.len);
	}

	g_free(finalstring);
	destroy_image_win(widget, win);

}

/************************************************************************/
static void destroy_image_win(GtkWidget * w, Timagewin * image_win)
{
	DEBUG_MSG("destroy_image_win, started on image_win->pixwin = %p\n", image_win->pixwin);
	gtk_signal_handlers_destroy(GTK_OBJECT(image_win->pixwin));
	DEBUG_MSG("destroy_image_win, signal handlers destroyed\n");
	gtk_widget_destroy(GTK_WIDGET(image_win->pixwin));
	DEBUG_MSG("destroy_image_win, pixwin destroyed\n");

/*
 * probably not complete, watch memory leaks here! 
 */
	if (image_win->im) {
#ifdef USE_GDK_PIXBUF
		gdk_pixbuf_unref(image_win->im);
#else
		gdk_imlib_destroy_image(image_win->im);
#endif
	}
	DEBUG_MSG("destroy_image_win, gdk_image destroyed\n");
	g_free(image_win);
	DEBUG_MSG("destroy_image_win, image_win free-ed\n");
}

/************************************************************************/
#ifdef USE_GDK_PIXBUF
static void image_adjust_changed(GtkAdjustment * adj, Timagewin * image_win)
{
	gchar *tempstr;
        GdkPixbuf *tmp_im;

	DEBUG_MSG("image_adjust_changed, started, adjustment value=%f\n", image_win->adjustment->value);
	if ((!image_win->im) || (!image_win->pixmap)) {
		DEBUG_MSG("image_adjust_changed, no image !!!!!\n");
		return;
	}
	image_win->tnW = image_win->adjustment->value * image_win->w;
	image_win->tnH = image_win->adjustment->value * image_win->h;

	/* if width or height are 1 or lower gdk_pixbuf crashes --> check for that
	and when the requested image is really small the memory usage peeks. A
	resonable minimum value therefore is 10 pixels */
	image_win->tnW = image_win->tnW <= 10 ? 10 : image_win->tnW;
	image_win->tnH = image_win->tnH <= 10 ? 10 : image_win->tnH;

	tempstr = g_strdup_printf("%d", image_win->tnW);
	gtk_entry_set_text(GTK_ENTRY(image_win->width), tempstr);
	g_free(tempstr);

	tempstr = g_strdup_printf("%d", image_win->tnH);
	gtk_entry_set_text(GTK_ENTRY(image_win->height), tempstr);
	g_free(tempstr);
	DEBUG_MSG("image_adjust_changed, tnW=%d, tnH=%d\n", image_win->tnW, image_win->tnH);

	tmp_im = gdk_pixbuf_scale_simple (image_win->im, image_win->tnW,image_win->tnH, GDK_INTERP_NEAREST);
	gdk_pixbuf_render_pixmap_and_mask (tmp_im, &image_win->p, &image_win->m, 128);
	gdk_pixbuf_unref (tmp_im);

	gtk_pixmap_set (GTK_PIXMAP(image_win->pixmap), image_win->p, image_win->m);

	gtk_signal_emit_by_name(GTK_OBJECT(image_win->height), "activate");
	gtk_signal_emit_by_name(GTK_OBJECT(image_win->width), "activate");
}
#else /* ifdef USE_GDK_PIXBUF */

static void image_adjust_changed(GtkAdjustment * adj, Timagewin * image_win)
{
	gchar *tempstr;

	DEBUG_MSG("image_adjust_changed, started, adjustment value=%f\n", image_win->adjustment->value);
	if ((!image_win->im) || (!image_win->pixmap)) {
		DEBUG_MSG("image_adjust_changed, no image !!!!!\n");
		return;
	}
	image_win->tnW = image_win->adjustment->value * image_win->w;
	tempstr = g_strdup_printf("%d", image_win->tnW);
	gtk_entry_set_text(GTK_ENTRY(image_win->width), tempstr);
	g_free(tempstr);

	image_win->tnH = image_win->adjustment->value * image_win->h;
	tempstr = g_strdup_printf("%d", image_win->tnH);
	gtk_entry_set_text(GTK_ENTRY(image_win->height), tempstr);
	g_free(tempstr);
	DEBUG_MSG("image_adjust_changed, tnW=%d, tnH=%d\n", image_win->tnW, image_win->tnH);
	gdk_imlib_render(image_win->im, image_win->tnW, image_win->tnH);
/*
 * Extract the Image and mask pixmaps from the Image 
 */
	image_win->p = gdk_imlib_move_image(image_win->im);
	/*
	 * The mask will be NULL if the image has no transparency 
	 */
	image_win->m = gdk_imlib_move_mask(image_win->im);
	gtk_pixmap_set(GTK_PIXMAP(image_win->pixmap), image_win->p, image_win->m);
	gdk_imlib_free_pixmap(image_win->p);
	gdk_imlib_free_pixmap(image_win->m);
	gtk_signal_emit_by_name(GTK_OBJECT(image_win->height), "activate");
	gtk_signal_emit_by_name(GTK_OBJECT(image_win->width), "activate");
}
#endif /* else USE_GDK_PIXBUF */
/************************************************************************/

/************************************************************************/
/************************************************************************/
#else /* define HAVE_IMAGE_LIBS */
/************************************************************************/
/************************************************************************/
/*
 * touch these and I will kill you Olivier 
 * <evil laugh> 
 */
static void image_insert_dialogok_lcb(GtkWidget * widget, Thtml_diag *dg) {
	gchar *thestring, *finalstring;

	thestring = g_strdup(cap("<IMG"));
	thestring = insert_string_if_entry(dg->entry[0], cap("SRC"), thestring, NULL);
	thestring = insert_integer_if_spin(dg->spin[0], cap("WIDTH"), thestring, dg->check[0]);
	thestring = insert_integer_if_spin(dg->spin[1], cap("HEIGHT"), thestring, dg->check[1]);
	thestring = insert_integer_if_spin(dg->spin[2], cap("BORDER"), thestring, NULL);
	thestring = insert_integer_if_spin(dg->spin[3], cap("HSPACE"), thestring, NULL);
	thestring = insert_integer_if_spin(dg->spin[4], cap("VSPACE"), thestring, NULL);
	thestring = insert_string_if_entry(dg->entry[1], cap("NAME"), thestring, NULL);
	thestring = insert_string_if_entry(dg->entry[2], cap("ALT"), thestring, NULL);
	thestring = insert_string_if_entry(dg->entry[3], cap("USEMAP"), thestring, NULL);
	thestring = insert_string_if_entry(GTK_WIDGET(GTK_COMBO(dg->combo[0])->entry), cap("ALIGN"), thestring, NULL);
	thestring = insert_string_if_entry(dg->entry[4], NULL, thestring, NULL);

	finalstring = g_strdup_printf(main_v->props.xhtml == 1 ? "%s />" : "%s>", thestring);
	g_free(thestring);

	if (dg->range.len == -1) {
		insert_dbl_text(finalstring, NULL);
	} else {
		replace_text(finalstring, dg->range.pos, dg->range.len);
	}

	g_free(finalstring);
	html_diag_destroy_cb(NULL, NULL, dg);	

}
void image_insert_dialog_cb(GtkWidget * widget, gpointer data) {
	static gchar *tagitems[] = { "width", "height", "alt", "border", "src", "hspace", "vspace", "align", "name", "usemap", NULL };
	gchar *tagvalues[11];
	gchar *custom = NULL;
	Thtml_diag *dg;
	
	GtkWidget *dgtable;

	dg = html_diag_new(_("Insert image"));
	fill_dialogvalues(tagitems, tagvalues, &custom, (Ttagpopup *) data, widget, dg);

	dgtable = gtk_table_new(7, 6, 0);
	gtk_box_pack_start(GTK_BOX(dg->vbox), dgtable, FALSE, FALSE, 0);
	
	dg->entry[0] = entry_with_text(tagvalues[4], 1024);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), gtk_label_new(_("Image location")), 0, 1, 0, 1);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->entry[0], 1, 5, 0, 1);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), file_but_new(dg->entry[0], dg->dialog, 0), 5, 6, 0, 1);

	dg->spin[0] = spinbut_with_value(NULL, 0, 5000, 1.0, 10.0);
	dg->check[0] = gtk_check_button_new_with_label("%");
	parse_integer_for_dialog(tagvalues[0], dg->spin[0] , NULL, dg->check[0]);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), gtk_label_new(_("Width")), 0, 1, 1, 2);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->spin[0], 1, 2, 1, 2);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->check[0], 2, 3, 1, 2);

	dg->spin[1] = spinbut_with_value(NULL, 0, 5000, 1.0, 10.0);
	dg->check[1] = gtk_check_button_new_with_label("%");
	parse_integer_for_dialog(tagvalues[1], dg->spin[1] , NULL, dg->check[1]);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), gtk_label_new(_("Height")), 0, 1, 2, 3);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->spin[1], 1, 2, 2, 3);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->check[1], 2, 3, 2, 3);

	dg->entry[3] = entry_with_text(tagvalues[9], 1024);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), gtk_label_new(_("Usemap")), 0, 1, 3, 4);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->entry[3], 1, 3, 3, 4);

	dg->entry[1] = entry_with_text(tagvalues[8], 1024);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), gtk_label_new(_("Name")), 0, 1, 4, 5);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->entry[1], 1, 3, 4, 5);

	dg->entry[2] = entry_with_text(tagvalues[2], 1024);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), gtk_label_new(_("Alternate text")), 0, 1, 5, 6);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->entry[2], 1, 6, 5, 6);

	dg->entry[4] = entry_with_text(custom, 1024);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), gtk_label_new(_("Custom")), 0, 1, 6, 7);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->entry[3], 1, 6, 6, 7);

	dg->spin[3] = spinbut_with_value(tagvalues[5], 0, 500, 1.0, 5.0);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), gtk_label_new(_("Hspace")), 3, 4, 1, 2);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->spin[3], 4, 6, 1, 2);

	dg->spin[4] = spinbut_with_value(tagvalues[6], 0, 500, 1.0, 5.0);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), gtk_label_new(_("Vspace")), 3, 4, 2, 3);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->spin[4], 4, 6, 2, 3);

	dg->combo[0] = combo_with_popdown_sized(tagvalues[7], positionlist, 1, 90);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), gtk_label_new(_("Align")), 3, 4, 3, 4);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->combo[0], 4, 6, 3, 4);

	dg->spin[2] = spinbut_with_value(tagvalues[3], 0, 500, 1.0, 5.0);
	gtk_table_attach_defaults(GTK_TABLE(dgtable),gtk_label_new(_("Border")) , 3, 4, 4, 5);
	gtk_table_attach_defaults(GTK_TABLE(dgtable), dg->spin[2], 4, 6, 4, 5);

	html_diag_finish(dg, image_insert_dialogok_lcb);
	
	if (custom)	g_free(custom);
}

/************************************************************************/

void image_thumbnail_dialog_cb(GtkWidget * widget, gpointer data) {
	error_dialog(_("Insert image as thumbnail"), _("Bluefish was compiled without\nImlib support. This function is\ntherefore not available"));
}

/************************************************************************/
/************************************************************************/
#endif /* else HAVE_IMAGE_LIBS */
/************************************************************************/
/************************************************************************/


#ifdef HAVE_IMAGE_LIBS

static void img_preview_win_destroy_lcb(GtkWidget * widget, GdkEvent *event,  Timage_preview *ip) {
#ifdef DEVELOPMENT
	if (ip != main_v->img_preview) {
		g_print("img_preview_win_destroy_lcb, ** THIS SHOULD NOT HAPPEN **");
	}
#endif

        if (ip->current_img_filename != NULL) {
             free (ip->current_img_filename);
             ip->current_img_filename = NULL;
        }
        window_destroy(main_v->img_preview->w_img_preview_win);
	g_free(main_v->img_preview);
	main_v->img_preview = NULL;
}

static void img_preview_win (void) {
	if (main_v->img_preview && GTK_IS_OBJECT (main_v->img_preview->w_img_preview_win)) {
		return;
	} else {
		Timage_preview *ip;

		ip = g_malloc0 (sizeof (Timage_preview));
		main_v->img_preview = ip;
		ip->max_width = 300; /* make this configurable */
		ip->max_height = 300; /* make this configurable */

		ip->w_img_preview_win = window_full(_("Image preview")
			, GTK_WIN_POS_NONE, GTK_WINDOW_TOPLEVEL, 5
			, img_preview_win_destroy_lcb, ip);
		gtk_widget_set_usize(ip->w_img_preview_win, 300, 300);
		ip->w_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
		gtk_container_add (GTK_CONTAINER (ip->w_img_preview_win), ip->w_scrolledwin);
		gtk_widget_show_all (ip->w_img_preview_win);
	}
}


/*
  preview_image_by_position
  Searches for an image-filename somewhere around the cursor position
  and calls preview_image_by_filename.
 */

void preview_image_by_position_cb (GtkWidget *widget, gpointer data)
{
     gint cursorpos, idx, left, right, length;
     gchar *text, *tag, *tmptext, *tmpsrc, *src, *basepath;

     if (data == NULL) {
          cursorpos = gtk_text_get_point (GTK_TEXT (main_v->current_document->textbox));
     } else {
          cursorpos = 0; /* not really */
     }
     idx = cursorpos;

     /* this breaks multibyte support I suppose... */
     length = gtk_text_get_length (GTK_TEXT (main_v->current_document->textbox));
     text = (char *) malloc (length +1);
     text = gtk_editable_get_chars (GTK_EDITABLE (main_v->current_document->textbox), 0, -1);
     
     while ((idx > 0) && (!strchr ("<", text[idx]))) {
          idx --;
     }
     left = idx;
     idx = cursorpos;

     while ((idx < length) && (!strchr (">", text[idx]))) {
          idx ++;
     }
     right = idx + 1;

     tag = (char *) malloc (right - left +1);
     tag = strncpy (tag, &text[left], right - left);
     tag[right - left] = '\0';

     free (text);

     tmptext = strstr (tag, "src"); 
     if (tmptext == NULL) {
           free (tag);
           return;
     }
     
     tmpsrc = strchr(tmptext, '\"') + 1;
     if (tmpsrc != NULL) tmpsrc = strtok (tmpsrc, "\"");
     
     if (main_v->current_document->filename == NULL) {
          basepath = g_get_current_dir ();
     } else {
          basepath = (char *) malloc (strlen (main_v->current_document->filename));
          basepath = strcpy (basepath, (char *)g_dirname (main_v->current_document->filename));
     }
     
     if (tmpsrc != NULL ) {
          src = (char *) malloc (strlen (basepath) + strlen (tmpsrc) +2);
          if (tmpsrc[0] != DIRCHR) {
               src = strcpy (src, basepath);
               src = strcat (src, DIRSTR);
               src = strcat (src, tmpsrc);
          } else {
               src = strcpy (src, tmpsrc);
          }
          
          DEBUG_MSG ("preview_image_by_position: filename: '%s'\n", src);
          preview_image_by_filename (src);
          free (src);
          free (basepath);
     }
     free (tag);
}


void preview_image_by_filename (gchar *filename) {
#ifdef USE_GDK_PIXBUF
	GdkPixbuf *image;
#else
	GdkImlibImage *image;
#endif

	DEBUG_MSG("preview_image_by_filename, started on %s\n", filename);
	
        if (main_v->img_preview == NULL) {
		img_preview_win();
	}


        if (main_v->img_preview->current_img_filename) {
             if (strcmp (main_v->img_preview->current_img_filename, filename) == 0) {
                  img_preview_win_destroy_lcb (NULL,NULL, main_v->img_preview);
                  return;
             } else {
                  free (main_v->img_preview->current_img_filename);
                  main_v->img_preview->current_img_filename = NULL;
             }
        }
        
        main_v->img_preview->current_img_filename = (char *) malloc (strlen (filename)+1);
        strcpy (main_v->img_preview->current_img_filename, filename);
        

#ifdef USE_GDK_PIXBUF
	image = gdk_pixbuf_new_from_file (filename);
	DEBUG_MSG("preview_image_by_filename, loaded using gdk_pixbuf\n");
#else
	image = gdk_imlib_load_image(filename);
	DEBUG_MSG("preview_image_by_filename, loaded using imlib\n");
#endif
	if (image == NULL) {
		DEBUG_MSG("preview_image_by_filename, *** failed ***\n");
		return;
	} else {
		GdkPixmap *ip_pixmap;
		GdkBitmap *ip_bitmap;
#ifdef USE_GDK_PIXBUF
		gdk_pixbuf_render_pixmap_and_mask (image, &ip_pixmap, &ip_bitmap,128);

		/* about 30 px for the scrollbars */
/*		im_width = gdk_pixbuf_get_width (image) + 30;
		im_height = gdk_pixbuf_get_height (image) + 30;
		if (im_width > main_v->img_preview->max_width)
				im_width = main_v->img_preview->max_width;
		if (im_height > main_v->img_preview->max_height)
				im_height = main_v->img_preview->max_height;*/

		gdk_pixbuf_unref (image);
#else
		gdk_imlib_render(image, image->rgb_width, image->rgb_height);
		ip_pixmap = gdk_imlib_move_image(image);
		ip_bitmap = gdk_imlib_move_mask(image);
		gdk_imlib_destroy_image(image);
#endif
		if (!main_v->img_preview->w_image) {
			main_v->img_preview->w_image = gtk_pixmap_new (ip_pixmap, ip_bitmap);
			gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (main_v->img_preview->w_scrolledwin), main_v->img_preview->w_image);
			gtk_widget_show(main_v->img_preview->w_image);
		} else {
			gtk_pixmap_set (GTK_PIXMAP (main_v->img_preview->w_image), ip_pixmap, ip_bitmap);
		}

		gdk_pixmap_unref (ip_pixmap);
		if (ip_bitmap) {
			gdk_bitmap_unref (ip_bitmap);
		}

		gdk_window_raise (main_v->img_preview->w_img_preview_win->window);
	}
}

#endif /* HAVE_IMAGE_LIBS */

#ifdef IMAGEMAP_EDITOR_TEST

typedef struct {
	GtkWidget *win;
	GtkWidget *img;
	GtkWidget *table;
	GdkPixmap *dr; /* the drawing area */
	GdkPixmap *image_cache; /* cache the rendered image, it can be re-used */
	GdkGC *gc; /* graphics context for drawing */
	GdkColormap* cmap; /* the colormap to use */
} Timgmap_editor;

#define TEST_SIZE 300

static void draw_on_image(Timgmap_editor *ie) {
	GdkColor color;
	
	color.pixel=-1;
	color.red=65535;
	color.green=65535;
	color.blue=65535;
	color.red=0;
	color.green=0;
	color.blue=0;
	gdk_colormap_alloc_color(ie->cmap, &color, FALSE, TRUE);
	gdk_gc_set_foreground (ie->gc, &color);
	gdk_draw_rectangle(ie->dr,ie->gc
		,FALSE
		,1,10,60,40);
/*	gdk_draw_line(ie->dr,ie->gc
		,1,1
		,200,200);*/
}
/*
to link on Olivier's box using gdk_pixbuf instead of imlib:
gcc -DLOCALEDIR=\"/usr/local/share/locale\" -DGNULOCALEDIR=\"/usr/local/share/locale\" -DLOCALE_ALIAS_PATH=\"/usr/local/share/locale:.\" -DPKGDATADIR=\"/usr/local/share/bluefish\" -DHAVE_CONFIG_H -o bluefish html_diag.o bf_lib.o document.o project.o pixmaps.o gtk_easy.o rpopup.o html2.o stringlist.o undo2.o configure.o ref_dialog.o init.o snr2.o callbacks.o interface.o toolbars.o html.o wizards.o images.o coloursel.o network.o bluefish.o cap.o menu.o highlight.o filter.o wml.o html_table.o html_form.o spell.o spell_gui.o javascript.o char_table.o gdk_pixbuf_save.o perl.o complet.o parsedtd.o attrpage.o perl_ezembed.o  -L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmodule -lglib -ldl -lXi -lXext -lX11 -lm -lrt -L/usr/lib -lgdk_imlib -L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmodule -lglib -ldl -lXi -lXext -lX11 -lm  -rdynamic -L/usr/lib -L/usr/X11R6/lib -lgdk_pixbuf -lgtk -lgdk -lgmodule -lglib -ldl -lXi -lXext -lX11 -lm -L/usr/lib -lImlib -ljpeg -ltiff -lungif -lpng -lz -lm -lXext -L/usr/X11R6/lib -lSM -lICE -lXext -lX11
*/
static void imgmap_editor_cleanup(Timgmap_editor *ie) {
	gdk_gc_unref(ie->gc);
	gdk_colormap_unref(ie->cmap);
	gdk_pixmap_unref(ie->image_cache);
	gdk_pixmap_unref(ie->dr);
}
static void imgmap_editor_destroy_lcb(GtkWidget * widget, GdkEvent *event,  Timgmap_editor *ie) {
	window_destroy(ie->win);
	imgmap_editor_cleanup(ie);
	g_free(ie);
}

static Timgmap_editor *imgmap_editor_new (gchar *filename) {
		Timgmap_editor *ie;
		GtkWidget *vruler, *hruler;

	ie = g_malloc(sizeof (Timgmap_editor));
	ie->win = window_full(_("Imagemap editor")
			, GTK_WIN_POS_MOUSE, GTK_WINDOW_TOPLEVEL, 5
			, imgmap_editor_destroy_lcb, ie);
	ie->table = gtk_table_new(3, 3, FALSE);
	gtk_container_add (GTK_CONTAINER (ie->win), ie->table);
	vruler = gtk_vruler_new();
	gtk_table_attach_defaults(GTK_TABLE(ie->table), vruler, 0, 1, 1, 2);
	hruler = gtk_vruler_new();
	gtk_table_attach_defaults(GTK_TABLE(ie->table), hruler, 1, 2, 0, 1);
	gtk_widget_realize(ie->win);
	ie->dr = gdk_pixmap_new(ie->win->window, TEST_SIZE,TEST_SIZE, 16);
	ie->gc = gdk_gc_new(ie->win->window);
	ie->cmap = gdk_colormap_get_system();
#ifdef USE_GDK_PIXBUF
	{
	GdkPixbuf *image;
	GdkBitmap *bitmap;
	image = gdk_pixbuf_new_from_file (filename);
	gdk_pixbuf_render_pixmap_and_mask (image, &ie->image_cache, &bitmap,128);
	gdk_pixbuf_unref(image);
	if (bitmap) gdk_bitmap_unref(bitmap);
	}
#endif
	ie->img = NULL;
	return ie;
}

/** this function can be called multiple times to change something */

static void imgmap_editor_render(Timgmap_editor *ie) {
	gdk_draw_pixmap(ie->dr, ie->gc, ie->image_cache, 0, 0, 0, 0, -1, -1);
	/* do all drawing here */
	
	draw_on_image(ie);

	/* end of drawing */
	if (ie->img == NULL) {
		ie->img = gtk_pixmap_new(ie->dr, NULL);
		gtk_table_attach_defaults(GTK_TABLE(ie->table), ie->img, 1, 2, 1, 2);
		gtk_widget_show_all (ie->win);
	}
}

static void parse_buf_for_imgmap(Timgmap_editor *ie, gchar *buf, gchar *mapname) {
	int i;

}

void make_imagemap_win(GtkWidget * widget, gpointer data) {
	Timgmap_editor *ie = imgmap_editor_new ("/home/olivier/bluefish/tmp/index.gif");
	imgmap_editor_render(ie);
}

#endif /* IMAGEMAP_EDITOR_TEST */

