diff src/gtkimhtml.c @ 2993:7239a392486c

[gaim-migrate @ 3006] 0.53 :) committer: Tailor Script <tailor@pidgin.im>
author Rob Flynn <gaim@robflynn.com>
date Sat, 02 Mar 2002 04:52:21 +0000
parents 73f303cb91c1
children 60018f862a51
line wrap: on
line diff
--- a/src/gtkimhtml.c	Sat Mar 02 01:37:01 2002 +0000
+++ b/src/gtkimhtml.c	Sat Mar 02 04:52:21 2002 +0000
@@ -24,6 +24,7 @@
 #endif
 #include "gtkimhtml.h"
 #include <X11/Xlib.h>
+#include <stdlib.h>
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 #include <string.h>
@@ -35,6 +36,11 @@
 #include <locale.h>
 #endif
 
+#if USE_PIXBUF
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gdk-pixbuf/gdk-pixbuf-loader.h>
+#endif
+
 #if GTK_CHECK_VERSION(1,3,0)
 #  define GTK_IMHTML_GET_STYLE_FONT(style) gtk_style_get_font (style)
 #else
@@ -248,10 +254,28 @@
 	imhtml->smiley_data = gtk_smiley_tree_new ();
 }
 
+#if USE_PIXBUF
+struct im_image {
+	gchar *filename;
+	
+	gint len;
+	gpointer data;
+	GdkPixbuf *pb;
+
+	gint x,y;
+	gint width,height;
+	GtkIMHtml *imhtml;
+	GtkIMHtmlBit *bit;
+};
+#endif
+
 struct _GtkIMHtmlBit {
 	gint type;
 
 	gchar *text;
+#if USE_PIXBUF
+	struct im_image *img;
+#endif
 	GdkPixmap *pm;
 	GdkBitmap *bm;
 
@@ -337,7 +361,11 @@
 		gdk_color_free (imhtml->default_fg_color);
 	if (imhtml->default_bg_color)
 		gdk_color_free (imhtml->default_bg_color);
-
+	if (imhtml->default_hl_color)
+		gdk_color_free (imhtml->default_hl_color);
+	if (imhtml->default_hlfg_color)
+		gdk_color_free (imhtml->default_hlfg_color);
+	
 	gdk_cursor_destroy (imhtml->hand_cursor);
 	gdk_cursor_destroy (imhtml->arrow_cursor);
 
@@ -409,6 +437,8 @@
 
 	imhtml->default_fg_color = gdk_color_copy (&GTK_WIDGET (imhtml)->style->fg [GTK_STATE_NORMAL]);
 	imhtml->default_bg_color = gdk_color_copy (&GTK_WIDGET (imhtml)->style->base [GTK_STATE_NORMAL]);
+	imhtml->default_hl_color = gdk_color_copy (&GTK_WIDGET (imhtml)->style->bg [GTK_STATE_SELECTED]);
+	imhtml->default_hlfg_color=gdk_color_copy (&GTK_WIDGET (imhtml)->style->fg [GTK_STATE_SELECTED]);
 
 	gdk_window_show (GTK_LAYOUT (imhtml)->bin_window);
 }
@@ -441,6 +471,7 @@
 	GdkWindow *window = GTK_LAYOUT (imhtml)->bin_window;
 	gfloat xoff, yoff;
 	GdkColor *bg, *fg;
+	gchar *start = NULL, *end = NULL;
 
 	if (GTK_LAYOUT (imhtml)->freeze_count)
 		return;
@@ -481,7 +512,6 @@
 
 	if (line->selected) {
 		gint width, x;
-		gchar *start, *end;
 		GdkColor col;
 
 		if ((line->sel_start > line->sel_end) && (line->sel_end != NULL)) {
@@ -498,18 +528,17 @@
 			x = gdk_text_width (bit->font, line->text, start - line->text);
 
 		if (end == NULL)
-			width = gdk_string_width (bit->font, line->text) - x;
-		else
-			width = gdk_text_width (bit->font, line->text, end - line->text) - x;
-
-		col.red = col.green = col.blue = 0xc000;
-		gdk_color_alloc (cmap, &col);
-		gdk_gc_set_foreground (gc, &col);
-
+			end = strchr(line->text, '\0');
+		
+		width = gdk_text_width (bit->font, line->text, end - line->text) - x;
+
+		gdk_gc_set_foreground (gc, imhtml->default_hl_color);
+		
 		gdk_draw_rectangle (window, gc, TRUE, x + line->x - xoff, line->y - yoff,
 				    width, line->height);
+		gdk_gc_set_foreground (gc, imhtml->default_hlfg_color);
+		fg = gdk_color_copy(imhtml->default_hlfg_color);
 	}
-
 	if (bit->url) {
 		GdkColor *tc = gtk_imhtml_get_color ("#0000a0");
 		gdk_color_alloc (cmap, tc);
@@ -530,19 +559,60 @@
 		gdk_color_alloc (cmap, fg);
 		gdk_gc_set_foreground (gc, fg);
 	}
+
+	if (start) {
+		int offset = 0;
+		gdk_draw_text (window, bit->font, gc, line->x - xoff,
+			       line->y - yoff + line->ascent, line->text, start - line->text);
+		offset = gdk_text_width(bit->font, line->text, start - line->text);
+		if (bit->underline || bit->url)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, 
+					    line->y - yoff + line->ascent + 1,
+					    offset, 1);
+		if (bit->strike)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff,
+					    line->y - yoff + line->ascent - (bit->font->ascent / 2),
+					    offset, 1);
+		gdk_gc_set_foreground (gc, imhtml->default_hlfg_color);
+		gdk_draw_text (window, bit->font, gc, line->x - xoff + offset,
+			       line->y - yoff + line->ascent, start, end - start);
+		if (bit->underline || bit->url)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset, 
+					    line->y - yoff + line->ascent + 1,
+					    gdk_text_width(bit->font, line->text, end - start), 1);
+		if (bit->strike)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset,
+					    line->y - yoff + line->ascent - (bit->font->ascent / 2),
+					    gdk_text_width(bit->font, line->text, end - start), 1);
+		offset = gdk_text_width(bit->font, line->text, end - line->text);
+		gdk_gc_set_foreground (gc, fg);
+		gdk_draw_string (window, bit->font, gc, line->x - xoff + offset,
+			       line->y - yoff + line->ascent, end);
+		if (bit->underline || bit->url)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset, 
+					    line->y - yoff + line->ascent + 1,
+					    gdk_string_width(bit->font, end), 1);
+		if (bit->strike)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset,
+					    line->y - yoff + line->ascent - (bit->font->ascent / 2),
+					    gdk_string_width(bit->font, end), 1);
+	} else {
+		gdk_draw_string (window, bit->font, gc, line->x - xoff,
+				 line->y - yoff + line->ascent, line->text);
+		
+		if (bit->underline || bit->url)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff + line->ascent + 1,
+					    gdk_string_width (bit->font, line->text), 1);
+		if (bit->strike)
+			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff,
+					    line->y - yoff + line->ascent - (bit->font->ascent / 2),
+					    gdk_string_width (bit->font, line->text), 1);
+	}
+		
 	gdk_color_free (bg);
 	gdk_color_free (fg);
 
-	gdk_draw_string (window, bit->font, gc, line->x - xoff,
-			 line->y - yoff + line->ascent, line->text);
-
-	if (bit->underline || bit->url)
-		gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff + line->ascent + 1,
-				    gdk_string_width (bit->font, line->text), 1);
-	if (bit->strike)
-		gdk_draw_rectangle (window, gc, TRUE, line->x - xoff,
-				    line->y - yoff + line->ascent - (bit->font->ascent / 2),
-				    gdk_string_width (bit->font, line->text), 1);
+	
 
 	gdk_gc_unref (gc);
 }
@@ -586,6 +656,10 @@
 				    width, line->height);
 	}
 
+	if (bit->bm) {
+		gdk_gc_set_clip_mask(gc, bit->bm);
+		gdk_gc_set_clip_origin(gc, line->x - xoff, line->y - yoff + hoff);
+	}
 	gdk_draw_pixmap (window, gc, bit->pm, 0, 0, line->x - xoff, line->y - yoff + hoff, -1, -1);
 
 	gdk_gc_unref (gc);
@@ -1323,8 +1397,12 @@
 			   NULL, imhtml->tip_window, "tooltip", 0, 0, -1, -1);
 
 	y = font->ascent + 4;
-	gtk_paint_string (style, imhtml->tip_window->window, GTK_STATE_NORMAL, NULL,
-			  imhtml->tip_window, "tooltip", 4, y, imhtml->tip_bit->url);
+	if (imhtml->tip_bit->url)
+		gtk_paint_string (style, imhtml->tip_window->window, GTK_STATE_NORMAL, NULL,
+				  imhtml->tip_window, "tooltip", 4, y, imhtml->tip_bit->url);
+	else if (imhtml->tip_bit->img)
+		gtk_paint_string (style, imhtml->tip_window->window, GTK_STATE_NORMAL, NULL,
+				  imhtml->tip_window, "tooltip", 4, y, imhtml->tip_bit->img->filename);
 
 	return FALSE;
 }
@@ -1367,7 +1445,8 @@
 		gap = 2;
 	baseline_skip = font->ascent + font->descent + gap;
 
-	w = 8 + gdk_string_width (font, imhtml->tip_bit->url);
+	w = 8 + gdk_string_width (font, imhtml->tip_bit->img ? imhtml->tip_bit->img->filename : 
+				  imhtml->tip_bit->url);
 	h = 8 - gap + baseline_skip;
 
 	gdk_window_get_pointer (NULL, &x, &y, NULL);
@@ -1452,7 +1531,8 @@
 		while (click) {
 			uw = (struct clickable *) click->data;
 			if ((x > uw->x) && (x < uw->x + uw->width) &&
-			    (y > uw->y) && (y < uw->y + uw->height)) {
+			    (y > uw->y) && (y < uw->y + uw->height) &&
+			    (uw->bit->url || uw->bit->img)) {
 				if (imhtml->tip_bit != uw->bit) {
 					imhtml->tip_bit = uw->bit;
 					if (imhtml->tip_timer != 0)
@@ -1465,8 +1545,9 @@
 									     gtk_imhtml_tip,
 									     imhtml);
 				}
-				gdk_window_set_cursor (GTK_LAYOUT (imhtml)->bin_window,
-						       imhtml->hand_cursor);
+				if (uw->bit->url)
+					gdk_window_set_cursor (GTK_LAYOUT (imhtml)->bin_window,
+							       imhtml->hand_cursor);
 				return TRUE;
 			}
 			click = g_list_next (click);
@@ -1503,9 +1584,61 @@
 		imhtml->tip_window = NULL;
 	}
 	imhtml->tip_bit = NULL;
-
-	return TRUE;
+return TRUE;
 }
+struct imgsv {
+	GtkWidget *savedialog;
+	struct im_image *img;
+};
+
+#if USE_PIXBUF
+static void
+save_img (GtkObject *object,
+	  gpointer data)
+{
+	struct imgsv *is = data;
+	struct im_image *img = is->img;
+	gchar *filename;
+	FILE *f;
+	filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(is->savedialog));
+	g_print("Saving %s\n", filename);
+	if (! (f=fopen(filename, "w"))) {
+		/* There should be some sort of dialog */
+		g_print("Could not open file for writing.\n");
+		gtk_widget_destroy(is->savedialog);
+		g_free(is);
+		return;
+	}
+	
+	fwrite(img->data, 1, img->len, f);
+	fclose(f);
+	gtk_widget_destroy(is->savedialog);
+	g_free(is);
+}
+
+static void
+save_img_dialog (GtkObject *object,
+		 gpointer data)
+{
+	struct imgsv *is = g_malloc(sizeof(struct imgsv)); 
+	struct im_image *img = data;
+	GtkWidget *savedialog = gtk_file_selection_new ("Gaim - Save Image");
+	gtk_file_selection_set_filename (GTK_FILE_SELECTION(savedialog), img->filename);
+	gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(savedialog)->cancel_button),
+				   "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
+				   (gpointer) savedialog);
+	
+	is->img = img;
+	is->savedialog = savedialog;
+	
+	gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(savedialog)->ok_button),
+				   "clicked", GTK_SIGNAL_FUNC (save_img), is);
+	gtk_widget_show (savedialog);
+
+
+}
+#endif
+
 
 static void
 menu_open_url (GtkObject *object,
@@ -1587,6 +1720,14 @@
 					gtk_widget_show (button);
 				}
 
+				if (uw->bit->img) {
+					button = gtk_menu_item_new_with_label ("Save Image");
+					gtk_signal_connect (GTK_OBJECT (button), "activate",
+							    GTK_SIGNAL_FUNC (save_img_dialog), uw->bit->img);
+					gtk_menu_append (GTK_MENU (menu), button);
+					gtk_widget_show (button);
+				}
+				
 				gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, event->time);
 
 				if (imhtml->tip_timer) {
@@ -1876,42 +2017,6 @@
 #endif
 }
 
-#define TRY_FONT	tmp = g_strjoinv ("-", newvals); \
-			if (default_font->type == GDK_FONT_FONT) \
-				ret_font = gdk_font_load (tmp); \
-			else \
-				ret_font = gdk_fontset_load (tmp); \
-			g_free (tmp); \
-			if (ret_font) { \
-				g_free (newvals); \
-				g_strfreev (xnames); \
-				g_strfreev (xflds); \
-				g_strfreev (names); \
-				return ret_font; \
-			} else if (newvals [RGSTRY][0] != '*') { \
-				/* if the registry isn't "*" then try it as "*". this is evil. */ \
-				gchar *reg = newvals [RGSTRY]; \
-				gchar *enc = newvals [ENCDNG]; \
-				newvals [RGSTRY] = "*"; \
-				newvals [ENCDNG] = "*"; \
-				tmp = g_strjoinv ("-", newvals); \
-				if (default_font->type == GDK_FONT_FONT) \
-					ret_font = gdk_font_load (tmp); \
-				else \
-					ret_font = gdk_fontset_load (tmp); \
-				g_free (tmp); \
-				if (ret_font) { \
-					g_free (newvals); \
-					g_strfreev (xnames); \
-					g_strfreev (xflds); \
-					g_strfreev (names); \
-					return ret_font; \
-				} \
-				newvals [RGSTRY] = reg; \
-				newvals [ENCDNG] = enc; \
-			}
-
-
 static GdkFont*
 gtk_imhtml_font_load (GtkIMHtml *imhtml,
 		      gchar     *name,
@@ -1923,142 +2028,162 @@
 	gchar *default_name;
 	gchar **xnames;
 	gchar **pos;
-
+	gchar *tmp = NULL;
+	GdkFont *ret_font;
+	gchar *xname;
+	gchar **xflds;
+	gchar **newvals;
+	gchar **names = NULL;
+
+	char *italicstrings[] = {"i","o","*"};
+	int italicsind = 0, nameind = 0;
+	gboolean usebold = TRUE, usesize = TRUE, useregenc = TRUE;
+	
 	/* if we're not changing anything, use the default. this is the common case */
 	if (!name && !bold && !italics && !fontsize)
 		return gdk_font_ref (default_font);
-
+	
 	/* base things off of the default font name */
 	default_name = gtk_imhtml_get_font_name (default_font);
-
-	/* the default font name can actually be several names separated by ','. */
-	xnames = g_strsplit (default_name, ",", -1);
-	for (pos = xnames; pos && *pos; pos++) {
-		gchar *xname;
-		gchar **xflds;
-
-		gchar **newvals;
-		gint i, j;
-		gchar **names;
-		gchar fs[10];
-
-		gchar *tmp;
-		GdkFont *ret_font;
-
-		xname = *pos;
-		xname = g_strchomp (xname);
-		xname = g_strchug (xname);
-
-		xflds = g_strsplit (xname, "-", -1);
-
-		/* figure out if we have a valid name. i wish there were an
-		 * easier way for determining how many values g_strplit gave */
-		for (i = 0; xflds [i]; i++);
-		if (i != 15) {
-			int tmp;
-			newvals = g_malloc0 (16 * sizeof (gchar *));
-			newvals [0] = "";
-			for (tmp = 1; tmp < 15; tmp++)
-				newvals [tmp] = "*";
-		} else
-			newvals = g_memdup (xflds, 16 * sizeof (xflds));
-
-		/* we force foundry as "*" because i hate them. i should give a better reason. */
-		newvals [FNDRY] = "*";
-
-		/* if it's "*" then it defaults to (nil) anyway. some fonts don't want (nil) */
-		if ((i > ADSTYL) && !xflds [ADSTYL][0])
-			newvals [ADSTYL] = "*";
-
-		/* right. */
-		if (bold)
-			newvals [WGHT] = "bold";
-		if (italics)
-			newvals [SLANT] = "i";
-		if (fontsize) {
-			g_snprintf (fs, sizeof (fs), "%d", POINT_SIZE (fontsize));
-			newvals [PXLSZ] = "*";
-			newvals [PTSZ] = fs;
+	/* the default font name can actually be several names separated by ','.
+	 * This is a fontset... used in foreign encodings. */
+	do {
+		xnames = g_strsplit (default_name, ",", -1);
+		for (pos = xnames; pos && *pos; pos++) {
+			gint i, j;
+			gchar fs[10];
+			gchar *garbage;
+			xname = *pos;
+			xname = g_strchomp (xname);
+			xname = g_strchug (xname);
+			
+			xflds = g_strsplit (xname, "-", -1);
+			
+			/* figure out if we have a valid name. i wish there were an
+			 * easier way for determining how many values g_strplit gave */
+			for (i = 0; xflds [i]; i++);
+			if (i != 15) {
+				int tmp;
+				newvals = g_malloc0 (16 * sizeof (gchar *));
+				newvals [0] = "";
+				for (tmp = 1; tmp < 15; tmp++)
+					newvals [tmp] = "*";
+			} else
+				newvals = g_memdup (xflds, 16 * sizeof (xflds));
+			
+			/* we force foundry as "*" because i hate them. i should give a better reason. */
+			newvals [FNDRY] = "*";
+			
+			/* if it's "*" then it defaults to (nil) anyway. some fonts don't want (nil) */
+			if ((i > ADSTYL) && !xflds [ADSTYL][0])
+				newvals [ADSTYL] = "*";
+			
+			/* If the font doesn't work the first time, we try it with 
+			 * registry and encoding as "*" */
+			if (!useregenc) {
+				newvals [RGSTRY] = "*";
+				newvals [ENCDNG] = "*";
+			}
+			/* right. */
+			if (bold)
+				if (usebold)
+					newvals [WGHT] = "bold";
+				else
+					newvals [WGHT] = "*";
+			if (italics)
+				/* We'll try "i" "o" to get italics and then just use "*" */
+				newvals [SLANT] = italicstrings[italicsind];
+			if (fontsize) {
+				if (usesize) {
+					g_snprintf (fs, sizeof (fs), "%d", POINT_SIZE (fontsize));
+					newvals [PTSZ] = fs;
+				} else 
+					newvals [PTSZ] = "*";
+				newvals [PXLSZ] = "*";
+			}
+			
+			if (name) {
+				/* we got passed a name. it might be a list of names. */
+				gchar **tmp_nms = g_strsplit (name, ",", -1);
+				for (j = 0; tmp_nms [j]; j++);
+				names = g_new0 (char *, j + 2);
+				for (j = 0; tmp_nms [j]; j++)
+					names [j] = tmp_nms [j];
+				g_free (tmp_nms);
+				/* Put the default font on the array. */
+				if (i > FMLY) {
+					names [j] = g_strdup (xflds [FMLY]);
+				}
+				newvals [FMLY] = names[nameind];
+			} else if (i > FMLY) {
+				/* we didn't get a name. we come here if the gtk font name is valid */
+				names = g_new0 (gchar *, 2);
+				names [0] = g_strdup (xflds [FMLY]);
+			} else {
+				/* we got fucked */
+				names = g_new0 (gchar *, 2);
+				names [0] = g_strdup ("*");
+			}
+			if (!tmp)
+				tmp = g_strjoinv("-", newvals);
+			else {
+				/* We have to concat the xlfds in the fontset */ 
+				garbage = tmp;
+				tmp = g_strconcat(garbage, ",", 
+						  g_strjoinv ("-", newvals), NULL); 
+				g_free(garbage);
+			}
+			g_free (newvals);
+			g_strfreev (xflds);
 		}
-
-		if (name) {
-			/* we got passed a name. it might be a list of names. */
-			gchar **tmp_nms = g_strsplit (name, ",", -1);
-			/* we do a bunch of weird things to also use the gtk font name as an option. */
-			for (j = 0; tmp_nms [j]; j++);
-			names = g_new0 (char *, j + 2);
-			for (j = 0; tmp_nms [j]; j++)
-				names [j] = tmp_nms [j];
-			g_free (tmp_nms);
-			if (i > FMLY)
-				names [j] = g_strdup (xflds [FMLY]);
-		} else if (i > FMLY) {
-			/* we didn't get a name. we come here if the gtk font name is valid */
-			names = g_new0 (gchar *, 2);
-			names [0] = g_strdup (xflds [FMLY]);
-		} else {
-			/* we got fucked */
-			names = g_new0 (gchar *, 2);
-			names [0] = g_strdup ("*");
-		}
-
-		/* for each name, try it */
-		for (j = 0; names [j]; j++) {
-			newvals [FMLY] = names [j];
-			TRY_FONT;
+		g_strfreev (xnames);
+		
+		if (default_font->type == GDK_FONT_FONT) 
+			ret_font = gdk_font_load (tmp); 
+		else {
+			/* For some reason, fontsets must end with a single * as an xlfd */
+			gchar *garbage = tmp;
+			tmp = g_strconcat(garbage, ",*", NULL);
+			ret_font = gdk_fontset_load (tmp); 
 		}
-
-		/* if italics is set, try various italics options for each name, including no italics */
-		for (j = 0; italics && names [j]; j++) {
-			newvals [FMLY] = names [j];
-
-			newvals [SLANT] = "o";
-			TRY_FONT;
-
-			if (i > SLANT)
-				newvals [SLANT] = xflds [SLANT];
-			else
-				newvals [SLANT] = "*";
-			TRY_FONT;
+				
+		/* If the font didn't load, we change some of the xlfds one by one
+		 * to get the closest we can.  */
+		if (!ret_font) {
+			if (!useregenc &&
+			    (!italics || italicsind == 2) && 
+			    (!bold || !usebold) && 
+			    (!fontsize || !usesize)) {
+				useregenc = TRUE;
+				usebold = TRUE;
+				italicsind = 0;
+				usesize = TRUE;
+				if (names && !names[nameind++]) {
+					ret_font = gdk_font_ref(default_font);
+					break;
+				}
+			}	
+			if (useregenc)
+				useregenc = FALSE;
+			else if (italics && italicsind != 2) {
+				useregenc = TRUE;
+				italicsind++;
+			}	else if (bold && usebold) {
+				useregenc = TRUE;
+				usebold = FALSE;
+			}	else if (fontsize && usesize)
+			  useregenc = TRUE;        
+			usesize = FALSE;
 		}
-
-		/* if font size was set, try ignoring font size. for each name. */
-		for (j = 0; fontsize && names [j]; j++) {
-			newvals [FMLY] = names [j];
-
-			if (i > PTSZ) {
-				newvals [PXLSZ] = xflds [PXLSZ];
-				newvals [PTSZ] = xflds [PTSZ];
-			} else {
-				newvals [PXLSZ] = "*";
-				newvals [PTSZ] = "*";
-			}
-			TRY_FONT;
-		}
-
-		/* abandon bold */
-		for (j = 0; bold && names [j]; j++) {
-			newvals [FMLY] = names [j];
-
-			if (i > WGHT)
-				newvals [WGHT] = xflds [WGHT];
-			else
-				newvals [WGHT] = "*";
-			TRY_FONT;
-		}
-
-		g_free (newvals);
-		g_strfreev (xflds);
 		g_strfreev (names);
-
-	}
-
-	g_strfreev (xnames);
-
-	/* we couldn't get anything. so, we quit. you get the default. */
-	return gdk_font_ref (default_font);
+		names = NULL;
+		g_free(tmp);
+		tmp=NULL;
+	} while (!ret_font); /* Loop with the new options */
+	
+	return ret_font;
 }
-
+	
 static void
 gtk_imhtml_init (GtkIMHtml *imhtml)
 {
@@ -2144,6 +2269,10 @@
 
 	gtk_imhtml_set_adjustments (imhtml, hadj, vadj);
 
+#if USE_PIXBUF
+	imhtml->im_images = NULL;
+#endif
+
 	imhtml->bits = NULL;
 	imhtml->click = NULL;
 
@@ -2276,7 +2405,8 @@
 	GList *ls = NULL;
 	struct line_info *li;
 	struct clickable *uw;
-
+	struct im_image *img;
+	
 	if (height > imhtml->llheight) {
 		diff = height - imhtml->llheight;
 
@@ -2299,6 +2429,16 @@
 			ls = g_list_next (ls);
 		}
 
+#if USE_PIXBUF		
+		ls = imhtml->im_images;
+		while(ls) {
+			img = ls->data;
+			if (img->y + diff > imhtml->y)
+				img->y += diff;
+			ls = g_list_next(ls);
+		}
+#endif
+
 		imhtml->llheight = height;
 		if (ascent)
 			imhtml->llascent = ascent;
@@ -2366,7 +2506,11 @@
 	li->ascent = 0;
 	li->bit = bit;
 
+#if USE_PIXBUF
+	if (bit->url || bit->img) {
+#else
 	if (bit->url) {
+#endif
 		uw = g_new0 (struct clickable, 1);
 		uw->x = imhtml->x;
 		uw->y = imhtml->y;
@@ -2466,6 +2610,36 @@
 
 		g_free (copy);
 	} else if ((bit->type == TYPE_SMILEY) || (bit->type == TYPE_IMG)) {
+#if USE_PIXBUF
+	  if (bit->img) {
+			GdkPixbuf *imagepb = bit->img->pb;
+			GdkPixbuf *tmp = NULL;
+			if (gdk_pixbuf_get_width(imagepb) > imhtml->xsize - imhtml->x)
+				new_line (imhtml);
+			
+			if (gdk_pixbuf_get_width(imagepb) > imhtml->xsize) {
+				tmp = gdk_pixbuf_scale_simple(imagepb, imhtml->xsize,
+							      gdk_pixbuf_get_height(imagepb) *
+							      imhtml->xsize/
+							      gdk_pixbuf_get_width(imagepb), 
+							      GDK_INTERP_TILES);
+				if (bit->pm)
+					gdk_pixmap_unref (bit->pm);
+				if (bit->bm)
+					gdk_bitmap_unref (bit->bm);
+				gdk_pixbuf_render_pixmap_and_mask(tmp, &(bit->pm), &(bit->bm), 100);
+				gdk_pixbuf_unref(tmp);
+			}
+			else {
+				if (bit->pm)
+					gdk_pixmap_unref (bit->pm);
+				if (bit->bm)
+					gdk_bitmap_unref (bit->bm);
+				gdk_pixbuf_render_pixmap_and_mask(imagepb, &(bit->pm), &(bit->bm), 100);
+			}
+	  }
+#endif
+		
 		gdk_window_get_size (bit->pm, &width, &height);
 
 		if ((imhtml->x != 0) && ((imhtml->x + width) > imhtml->xsize))
@@ -2802,8 +2976,10 @@
 	VALID_TAG ("/BODY");
 	VALID_TAG ("FONT");
 	VALID_TAG ("HEAD");
-	VALID_TAG ("HEAD");
-
+	VALID_TAG ("/HEAD");
+	VALID_TAG ("BINARY");
+	VALID_TAG ("/BINARY");
+	
 	VALID_OPT_TAG ("HR");
 	VALID_OPT_TAG ("FONT");
 	VALID_OPT_TAG ("BODY");
@@ -2851,17 +3027,14 @@
 	if ((*t == '\"') || (*t == '\'')) {
 		e = a = ++t;
 		while (*e && (*e != *(t - 1))) e++;
-		if (*e != '\0') {
-			*e = '\0';
-			return g_strdup (a);
-		} else {
+		if  (*e == '\0') {
 			return NULL;
-		}
+		} else 
+			return g_strndup (a, e - a);
 	} else {
 		e = a = t;
 		while (*e && !isspace ((gint) *e)) e++;
-		*e = '\0';
-		return g_strdup (a);
+		return g_strndup (a, e - a);
 	}
 }
 
@@ -3055,12 +3228,27 @@
 			case 38:	/* HEAD */
 			case 39:	/* /HEAD */
 				break;
-
-			case 40:	/* HR (opt) */
+			case 40:        /* BINARY */
+				
+				NEW_BIT (NEW_TEXT_BIT);
+				while (pos < len) {
+					if (!g_strncasecmp("</BINARY>", c, strlen("</BINARY>"))) 
+						break;
+					else {
+						c++;
+						pos++;
+					}
+				}
+				c = c - tlen; /* Because it will add this later */
+				break;
+			case 41:        /* /BINARY */
+				break;
+				
+			case 42:	/* HR (opt) */
 				NEW_BIT (NEW_TEXT_BIT);
 				NEW_BIT (NEW_SEP_BIT);
 				break;
-			case 41:	/* FONT (opt) */
+			case 43:	/* FONT (opt) */
 			{
 				gchar *color, *back, *face, *size;
 				FontDetail *font;
@@ -3114,7 +3302,7 @@
 				fonts = g_slist_prepend (fonts, font);
 			}
 				break;
-			case 42:	/* BODY (opt) */
+			case 44:	/* BODY (opt) */
 				if (!(options & GTK_IMHTML_NO_COLOURS)) {
 					gchar *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR=");
 					if (bgcolor) {
@@ -3128,7 +3316,7 @@
 					}
 				}
 				break;
-			case 43:	/* A (opt) */
+			case 45:	/* A (opt) */
 			{
 				gchar *href = gtk_imhtml_get_html_opt (tag, "HREF=");
 				if (href) {
@@ -3138,16 +3326,94 @@
 				}
 			}
 				break;
-			case 44:	/* IMG (opt) */
-			{
+			case 46:	/* IMG (opt) */
+				{
 				gchar *src = gtk_imhtml_get_html_opt (tag, "SRC=");
+				gchar *id = gtk_imhtml_get_html_opt (tag, "ID=");
+				gchar *datasize = gtk_imhtml_get_html_opt (tag, "DATASIZE=");
 				gchar **xpm;
 				GdkColor *clr;
 				GtkIMHtmlBit *bit;
 
 				if (!src)
 					break;
-
+				
+				if (!imhtml->img && id && datasize) { /* This is an embedded IM image */
+#if USE_PIXBUF
+					char *tmp, *imagedata, *e;
+					const gchar *alltext;
+					struct im_image *img;
+					GdkPixbufLoader *load;
+					GdkPixbuf *imagepb = NULL;
+					
+#endif
+					NEW_BIT (NEW_TEXT_BIT);
+#if USE_PIXBUF
+					if (!id || !datasize)
+						break;
+					tmp = g_malloc(strlen("<DATA ID=\"\" SIZE=\"\">") + 
+						       strlen(id) + strlen(datasize));
+					g_snprintf(tmp, strlen("<DATA ID=\"\" SIZE=\"\">") + 
+						   strlen(id) + strlen(datasize) + 1, 
+						   "<DATA ID=\"%s\" SIZE=\"%s\">", id, datasize);
+					alltext = c;
+					while (g_strncasecmp(alltext, tmp, strlen(tmp)) && alltext < (c + len))
+						alltext++;
+					alltext = alltext + strlen("<DATA ID=\"\" SIZE=\"\">") + strlen(id) + strlen(datasize);
+					g_free(tmp);
+					imagedata = g_malloc(atoi(datasize));
+					memcpy(imagedata, alltext, atoi(datasize));
+					
+					if (!GTK_WIDGET_REALIZED (imhtml))
+						gtk_widget_realize (GTK_WIDGET (imhtml));
+					
+					img = g_new0 (struct im_image, 1);
+					tmp = e = src;
+					while (*tmp){
+						if (*tmp == '/' || *tmp == '\\') {
+							tmp++;
+							src = tmp;
+						} else
+							tmp++;
+					}
+					
+					*tmp = '\0';
+					
+					img->filename = g_strdup(src);
+					img->len = atoi(datasize);
+					if (img->len) {
+						img->data = g_malloc(img->len);
+						memcpy(img->data, imagedata, img->len);
+						
+						load = gdk_pixbuf_loader_new();
+						if (!gdk_pixbuf_loader_write(load, imagedata, img->len))
+							g_print("IM Image corrupt or unreadable.\n");
+						else 
+							imagepb = gdk_pixbuf_loader_get_pixbuf(load);
+						img->pb = imagepb;
+					}
+					if (imagepb) {
+						bit = g_new0 (GtkIMHtmlBit, 1);
+						bit->type = TYPE_IMG;
+						bit->img = img;
+						if (url)
+							bit->url = g_strdup (url);
+						
+						NEW_BIT (bit);
+					} else {
+						g_free(img->filename);
+						g_free(img->data);
+						gdk_pixbuf_unref(img->pb);
+					}
+					g_free(imagedata);
+					g_free(e);
+					g_free(id);
+					g_free(datasize);
+
+#endif
+					break;
+				}
+				
 				if (!imhtml->img || ((xpm = imhtml->img (src)) == NULL)) {
 					g_free (src);
 					break;
@@ -3171,10 +3437,10 @@
 				g_free (src);
 			}
 				break;
-			case 45:	/* P (opt) */
-			case 46:	/* H3 (opt) */
+			case 47:	/* P (opt) */
+			case 48:	/* H3 (opt) */
 				break;
-			case 47:	/* comment */
+			case 49:	/* comment */
 				NEW_BIT (NEW_TEXT_BIT);
 				wpos = g_snprintf (ws, len, "%s", tag);
 				NEW_BIT (NEW_COMMENT_BIT);
@@ -3335,6 +3601,15 @@
 			gdk_pixmap_unref (bit->pm);
 		if (bit->bm)
 			gdk_bitmap_unref (bit->bm);
+#if USE_PIXBUF
+		if (bit->img) {
+			g_free(bit->img->filename);
+			g_free(bit->img->data);
+			gdk_pixbuf_unref(bit->img->pb);
+			g_free(bit->img);
+		}
+#endif 
+		
 		while (bit->chunks) {
 			struct line_info *li = bit->chunks->data;
 			if (li->text)
@@ -3349,7 +3624,13 @@
 		g_free (imhtml->click->data);
 		imhtml->click = g_list_remove (imhtml->click, imhtml->click->data);
 	}
-
+	
+#if USE_PIXBUF
+	while (imhtml->im_images) {
+		imhtml->im_images = g_list_remove(imhtml->im_images, imhtml->im_images->data);
+	}
+#endif
+	
 	if (imhtml->selected_text) {
 		g_string_free (imhtml->selected_text, TRUE);
 		imhtml->selected_text = g_string_new ("");
@@ -3376,6 +3657,11 @@
 		imhtml->scroll_timer = 0;
 	}
 
+#if USE_PIXBUF
+	g_list_free(imhtml->im_images);
+	imhtml->im_images = NULL;
+#endif
+
 	imhtml->x = 0;
 	imhtml->y = TOP_BORDER;
 	imhtml->xsize = 0;