changeset 1428:00b3d02a2168

[gaim-migrate @ 1438] gtkhtml has gotten replaced by gtkimhtml. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Fri, 26 Jan 2001 02:02:36 +0000
parents 28278bd61403
children 865a6ead3258
files ChangeLog po/POTFILES.in src/Makefile.am src/buddy_chat.c src/conversation.c src/dialogs.c src/gaim.h src/gtkhtml.c src/gtkhtml.h src/gtkimhtml.c src/gtkimhtml.h src/prefs.c
diffstat 12 files changed, 3210 insertions(+), 4797 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Jan 25 20:31:12 2001 +0000
+++ b/ChangeLog	Fri Jan 26 02:02:36 2001 +0000
@@ -10,6 +10,7 @@
 	* Can use all away states for ICQ, Yahoo (N/A, Be Right Back, etc.)
 	* Fixed hanging trees
 	* Can close windows by hitting 'Esc' (optional)
+	* Better HTML Widget
 
 version 0.11.0-pre4:
 	* ICQ upgraded to use icqlib 1.1.0
--- a/po/POTFILES.in	Thu Jan 25 20:31:12 2001 +0000
+++ b/po/POTFILES.in	Fri Jan 26 02:02:36 2001 +0000
@@ -6,7 +6,7 @@
 src/buddy_chat.c
 src/conversation.c
 src/dialogs.c
-src/gtkhtml.c
+src/gtkimhtml.c
 src/html.c
 src/multi.c
 src/oscar.c
--- a/src/Makefile.am	Thu Jan 25 20:31:12 2001 +0000
+++ b/src/Makefile.am	Fri Jan 26 02:02:36 2001 +0000
@@ -10,7 +10,7 @@
 			conversation.c \
 			dialogs.c \
 			gaimrc.c \
-			gtkhtml.c \
+			gtkimhtml.c \
 			gtkspell.c \
 			gtkticker.c \
 			html.c \
@@ -42,7 +42,7 @@
 		conversation.c \
 		dialogs.c \
 		gaimrc.c \
-		gtkhtml.c \
+		gtkimhtml.c \
 		gtkspell.c \
 		gtkticker.c \
 		html.c \
@@ -86,7 +86,7 @@
 		getopt.c \
 		getopt.h \
 		getopt1.c \
-		gtkhtml.h \
+		gtkimhtml.h \
 		gtkspell.h \
 		gtkticker.h \
 		multi.h \
--- a/src/buddy_chat.c	Thu Jan 25 20:31:12 2001 +0000
+++ b/src/buddy_chat.c	Fri Jan 26 02:02:36 2001 +0000
@@ -28,7 +28,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <gtk/gtk.h>
-#include "gtkhtml.h"
+#include "gtkimhtml.h"
 #include "gtkspell.h"
 #include <gdk/gdkkeysyms.h>
 
@@ -39,6 +39,9 @@
 #include "pixmaps/join.xpm"
 #include "pixmaps/close.xpm"
 
+#include "pixmaps/luke03.xpm"
+#include "pixmaps/oneeye.xpm"
+
 static GtkWidget *joinchat;
 static struct gaim_connection *joinchatgc;
 static GtkWidget *entry;
@@ -696,12 +699,20 @@
 	gtk_widget_set_usize(sw, 320, 160);
 	gtk_widget_show(sw);
 
-	text = gtk_html_new(NULL, NULL);
+	text = gtk_imhtml_new(NULL, NULL);
 	b->text = text;
 	gtk_container_add(GTK_CONTAINER(sw), text);
+	GTK_LAYOUT(text)->hadjustment->step_increment = 10.0;
+	GTK_LAYOUT(text)->vadjustment->step_increment = 10.0;
+	if (!(display_options & OPT_DISP_SHOW_SMILEY))
+		gtk_imhtml_show_smileys(GTK_IMHTML(text), FALSE);
+	if (display_options & OPT_DISP_SHOW_TIME)
+		gtk_imhtml_show_comments(GTK_IMHTML(text), TRUE);
+	gtk_signal_connect(GTK_OBJECT(text), "url_clicked", GTK_SIGNAL_FUNC(open_url_nw), NULL);
+	gtk_imhtml_associate_smiley(GTK_IMHTML(text), "C:)", luke03_xpm);
+	gtk_imhtml_associate_smiley(GTK_IMHTML(text), "C:-)", luke03_xpm);
+	gtk_imhtml_associate_smiley(GTK_IMHTML(text), "O-)", oneeye_xpm);
 	gtk_widget_show(text);
-	GTK_HTML(text)->hadj->step_increment = 10.0;
-	GTK_HTML(text)->vadj->step_increment = 10.0;
 
 	lbox = gtk_vbox_new(FALSE, 5);
 	gtk_paned_pack2(GTK_PANED(hpaned), lbox, TRUE, TRUE);
--- a/src/conversation.c	Thu Jan 25 20:31:12 2001 +0000
+++ b/src/conversation.c	Fri Jan 26 02:02:36 2001 +0000
@@ -31,7 +31,7 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <gtk/gtk.h>
-#include "gtkhtml.h"
+#include "gtkimhtml.h"
 #include <gdk/gdkkeysyms.h>
 #include "convo.h"
 #include "gtkspell.h"
@@ -52,22 +52,6 @@
 #include "pixmaps/fgcolor.xpm"
 #include "pixmaps/bgcolor.xpm"
 
-#include "pixmaps/angel.xpm"
-#include "pixmaps/bigsmile.xpm"
-#include "pixmaps/burp.xpm"
-#include "pixmaps/crossedlips.xpm"
-#include "pixmaps/cry.xpm"
-#include "pixmaps/embarrassed.xpm"
-#include "pixmaps/kiss.xpm"
-#include "pixmaps/moneymouth.xpm"
-#include "pixmaps/sad.xpm"
-#include "pixmaps/scream.xpm"
-#include "pixmaps/smile.xpm"
-#include "pixmaps/smile8.xpm"
-#include "pixmaps/think.xpm"
-#include "pixmaps/tongue.xpm"
-#include "pixmaps/wink.xpm"
-#include "pixmaps/yell.xpm"
 #include "pixmaps/luke03.xpm"
 #include "pixmaps/oneeye.xpm"
 
@@ -485,6 +469,8 @@
 			gtk_signal_emit_stop_by_name(GTK_OBJECT(entry), "key_press_event");
 			close_callback(c->window, c);
 		}
+	} else if (event->keyval == GDK_F2) {
+		gtk_imhtml_show_comments(GTK_IMHTML(c->text), !(GTK_IMHTML(c->text))->comments);
 	} else if (event->keyval == GDK_Return) {
 		if (!(event->state & GDK_SHIFT_MASK)
 		    && (general_options & OPT_GEN_ENTER_SENDS)) {
@@ -1120,130 +1106,6 @@
 /*------------------------------------------------------------------------*/
 
 
-static GdkPixmap *is_smiley(GtkWidget *window, char *m, int *len, GdkColor * trans)
-{
-	GdkBitmap *mask;
-	GdkPixmap *face = NULL;
-
-	if (strlen(m) < 2)
-		return face;
-	*len = 2;
-	if (!strncmp(m, ":)", 2)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, smile_xpm);
-	} else if (!strncmp(m, ":(", 2)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, sad_xpm);
-	} else if (!strncmp(m, ";)", 2)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, wink_xpm);
-	}
-
-	if (face || strlen(m) < 3)
-		return face;
-	*len = 3;
-	if (!strncmp(m, ":-)", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, smile_xpm);
-	} else if (!strncmp(m, "O-)", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, oneeye_xpm);
-	} else if (!strncmp(m, "C:)", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, luke03_xpm);
-	} else if (!strncmp(m, ":-(", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, sad_xpm);
-	} else if (!strncmp(m, ";-)", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, wink_xpm);
-	} else if (!strncmp(m, ":-p", 3) || !strncmp(m, ":-P", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, tongue_xpm);
-	} else if (!strncmp(m, "=-O", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, scream_xpm);
-	} else if (!strncmp(m, ":-*", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, kiss_xpm);
-	} else if (!strncmp(m, ">:o", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, yell_xpm);
-	} else if (!strncmp(m, "8-)", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, smile8_xpm);
-	} else if (!strncmp(m, ":-$", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, moneymouth_xpm);
-	} else if (!strncmp(m, ":-!", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, burp_xpm);
-	} else if (!strncmp(m, ":-[", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, embarrassed_xpm);
-	} else if (!strncmp(m, ":'(", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, cry_xpm);
-	} else if (!strncmp(m, ":-\\", 3) || !strncmp(m, ":-/", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, think_xpm);
-	} else if (!strncmp(m, ":-X", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, crossedlips_xpm);
-	} else if (!strncmp(m, ":-D", 3)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, bigsmile_xpm);
-	}
-
-	if (face || strlen(m) < 4)
-		return face;
-	*len = 4;
-	if (!strncmp(m, "O:-)", 4)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, angel_xpm);
-	} else if (!strncmp(m, "C:-)", 4)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, luke03_xpm);
-	}
-
-	if (face || strlen(m) < 6)
-		return face;
-	*len = 6;
-	if (!strncmp(m, "&gt;:o", 6)) {
-		face = gdk_pixmap_create_from_xpm_d(window->window, &mask, trans, yell_xpm);
-	}
-
-	return face;
-}
-
-void write_html_with_smileys(GtkWidget *window, GtkWidget *html, char *what)
-{
-	int y = 0;
-	char *buf2 = g_strdup(what);
-	int i;
-	GdkPixmap *face;
-	/* hopefully we can later use this for bgcolors in smileys */
-	GdkColor *trans = &window->style->base[GTK_STATE_NORMAL];
-	gboolean in_tag = FALSE;
-	int gtk_font_options = 0;
-
-	if (display_options & OPT_DISP_IGNORE_COLOUR)
-		gtk_font_options = gtk_font_options ^ HTML_OPTION_NO_COLOURS;
-
-	if (display_options & OPT_DISP_IGNORE_FONTS)
-		gtk_font_options = gtk_font_options ^ HTML_OPTION_NO_FONTS;
-
-	for (i = 0; i < strlen(what); i++) {
-		if (!in_tag) {
-			int len;
-			if (what[i] == '<') {
-				buf2[y] = what[i];
-				y++;
-				in_tag = TRUE;
-			} else if ((face = is_smiley(window, &what[i], &len, trans)) != NULL) {
-
-				buf2[y] = 0;
-				gtk_html_append_text(GTK_HTML(html), buf2, gtk_font_options);
-				gtk_html_add_pixmap(GTK_HTML(html), face, 0, 0);
-				y = 0;
-				i += len - 1;
-			} else {
-				buf2[y] = what[i];
-				y++;
-			}
-		} else {
-			buf2[y] = what[i];
-			y++;
-			if (what[i] == '>')
-				in_tag = FALSE;
-		}
-	}
-
-	if (y) {
-		buf2[y] = 0;
-		gtk_html_append_text(GTK_HTML(html), buf2, gtk_font_options);
-	}
-	g_free(buf2);
-}
-
 /* this is going to be interesting since the conversation could either be a
  * normal IM conversation or a chat window. but hopefully it won't matter */
 void write_to_conv(struct conversation *c, char *what, int flags, char *who)
@@ -1260,10 +1122,16 @@
 	int gtk_font_options = 0;
 
 	if (display_options & OPT_DISP_IGNORE_COLOUR)
-		gtk_font_options = gtk_font_options ^ HTML_OPTION_NO_COLOURS;
+		gtk_font_options = gtk_font_options ^ GTK_IMHTML_NO_COLOURS;
 
 	if (display_options & OPT_DISP_IGNORE_FONTS)
-		gtk_font_options = gtk_font_options ^ HTML_OPTION_NO_FONTS;
+		gtk_font_options = gtk_font_options ^ GTK_IMHTML_NO_FONTS;
+
+	gtk_font_options = gtk_font_options ^ GTK_IMHTML_NO_COMMENTS;
+	gtk_font_options = gtk_font_options ^ GTK_IMHTML_NO_TITLE;
+
+	if (display_options & OPT_DISP_IGNORE_SIZES)
+		gtk_font_options = gtk_font_options ^ GTK_IMHTML_NO_SIZES;
 
 
 	if (!who) {
@@ -1288,11 +1156,9 @@
 
 	if (flags & WFLAG_SYSTEM) {
 
-		gtk_html_freeze(GTK_HTML(c->text));
+		gtk_imhtml_append_text(GTK_IMHTML(c->text), what, 0);
 
-		gtk_html_append_text(GTK_HTML(c->text), what, 0);
-
-		gtk_html_append_text(GTK_HTML(c->text), "<BR>", 0);
+		gtk_imhtml_append_text(GTK_IMHTML(c->text), "<BR>", 0);
 
 		if ((general_options & OPT_GEN_LOG_ALL) || find_log_info(c->name)) {
 			char *t1;
@@ -1358,34 +1224,16 @@
 			}
 		}
 
-		if (display_options & OPT_DISP_SHOW_TIME)
-			g_snprintf(buf, BUF_LONG, "<FONT COLOR=\"%s\"><B>%s %s</B></FONT> ", colour,
-				   date(), str);
-		else
-			g_snprintf(buf, BUF_LONG, "<FONT COLOR=\"%s\"><B>%s</B></FONT>", colour, str);
+		g_snprintf(buf, BUF_LONG, "<FONT COLOR=\"%s\"><FONT SIZE=\"2\"><!--(%s) --></FONT>"
+				"<B>%s</B></FONT> ", colour, date(), str);
 
 		g_free(str);
 
-		gtk_html_freeze(GTK_HTML(c->text));
-
-		if (colorv != -1) {
-			sprintf(buf2, "<BODY BGCOLOR=\"#%x\">", colorv);
-			gtk_html_append_text(GTK_HTML(c->text), buf2, gtk_font_options);
-		}
-
-		gtk_html_append_text(GTK_HTML(c->text), buf, 0);
+		gtk_imhtml_append_text(GTK_IMHTML(c->text), buf, 0);
 
-		if (display_options & OPT_DISP_SHOW_SMILEY) {
-			write_html_with_smileys(c->window, c->text, what);
-		} else {
-			gtk_html_append_text(GTK_HTML(c->text), what, gtk_font_options);
-		}
+		gtk_imhtml_append_text(GTK_IMHTML(c->text), what, gtk_font_options);
 
-		if (colorv != -1) {
-			gtk_html_append_text(GTK_HTML(c->text), "</BODY>", gtk_font_options);
-		}
-		gtk_html_append_text(GTK_HTML(c->text), "<BR>", gtk_font_options);
-
+		gtk_imhtml_append_text(GTK_IMHTML(c->text), "<BR>", 0);
 
 		if ((general_options & OPT_GEN_LOG_ALL) || find_log_info(c->name)) {
 			char *t1, *t2;
@@ -1430,8 +1278,6 @@
 	    (!c->is_chat && (general_options & OPT_GEN_POPUP_WINDOWS)))
 		    gdk_window_show(c->window->window);
 
-	gtk_html_thaw(GTK_HTML(c->text));
-
 	g_free(smiley);
 	g_free(buf);
 }
@@ -1866,12 +1712,19 @@
 	gtk_widget_set_usize(sw, 320, 175);
 	gtk_widget_show(sw);
 
-	text = gtk_html_new(NULL, NULL);
+	text = gtk_imhtml_new(NULL, NULL);
 	c->text = text;
-	gtk_html_set_editable(GTK_HTML(text), FALSE);
 	gtk_container_add(GTK_CONTAINER(sw), text);
-	GTK_HTML(text)->hadj->step_increment = 10.0;
-	GTK_HTML(text)->vadj->step_increment = 10.0;
+	GTK_LAYOUT(text)->hadjustment->step_increment = 10.0;
+	GTK_LAYOUT(text)->vadjustment->step_increment = 10.0;
+	if (!(display_options & OPT_DISP_SHOW_SMILEY))
+		gtk_imhtml_show_smileys(GTK_IMHTML(text), FALSE);
+	if (display_options & OPT_DISP_SHOW_TIME)
+		gtk_imhtml_show_comments(GTK_IMHTML(text), TRUE);
+	gtk_signal_connect(GTK_OBJECT(text), "url_clicked", GTK_SIGNAL_FUNC(open_url_nw), NULL);
+	gtk_imhtml_associate_smiley(GTK_IMHTML(text), "C:)", luke03_xpm);
+	gtk_imhtml_associate_smiley(GTK_IMHTML(text), "C:-)", luke03_xpm);
+	gtk_imhtml_associate_smiley(GTK_IMHTML(text), "O-)", oneeye_xpm);
 	gtk_widget_show(text);
 
 	vbox2 = gtk_vbox_new(FALSE, 5);
@@ -2005,3 +1858,67 @@
 		con = con->next;
 	}
 }
+
+void toggle_timestamps()
+{
+	GList *cnv = conversations;
+	GSList *cht;
+	struct conversation *c;
+	GSList *con = connections;
+	struct gaim_connection *gc;
+
+	while (cnv) {
+		c = (struct conversation *)cnv->data;
+		if (display_options & OPT_DISP_SHOW_TIME)
+			gtk_imhtml_show_comments(GTK_IMHTML(c->text), TRUE);
+		else
+			gtk_imhtml_show_comments(GTK_IMHTML(c->text), FALSE);
+		cnv = cnv->next;
+	}
+
+	while (con) {
+		gc = (struct gaim_connection *)con->data;
+		cht = gc->buddy_chats;
+		while (cht) {
+			c = (struct conversation *)cht->data;
+			if (display_options & OPT_DISP_SHOW_TIME)
+				gtk_imhtml_show_comments(GTK_IMHTML(c->text), TRUE);
+			else
+				gtk_imhtml_show_comments(GTK_IMHTML(c->text), FALSE);
+			cht = cht->next;
+		}
+		con = con->next;
+	}
+}
+
+void toggle_smileys()
+{
+	GList *cnv = conversations;
+	GSList *cht;
+	struct conversation *c;
+	GSList *con = connections;
+	struct gaim_connection *gc;
+
+	while (cnv) {
+		c = (struct conversation *)cnv->data;
+		if (display_options & OPT_DISP_SHOW_SMILEY)
+			gtk_imhtml_show_smileys(GTK_IMHTML(c->text), TRUE);
+		else
+			gtk_imhtml_show_smileys(GTK_IMHTML(c->text), FALSE);
+		cnv = cnv->next;
+	}
+
+	while (con) {
+		gc = (struct gaim_connection *)con->data;
+		cht = gc->buddy_chats;
+		while (cht) {
+			c = (struct conversation *)cht->data;
+			if (display_options & OPT_DISP_SHOW_SMILEY)
+				gtk_imhtml_show_smileys(GTK_IMHTML(c->text), TRUE);
+			else
+				gtk_imhtml_show_smileys(GTK_IMHTML(c->text), FALSE);
+			cht = cht->next;
+		}
+		con = con->next;
+	}
+}
--- a/src/dialogs.c	Thu Jan 25 20:31:12 2001 +0000
+++ b/src/dialogs.c	Fri Jan 26 02:02:36 2001 +0000
@@ -39,7 +39,7 @@
 
 #include <gtk/gtk.h>
 #include "gaim.h"
-#include "gtkhtml.h"
+#include "gtkimhtml.h"
 #include "prpl.h"
 
 #include "pixmaps/gnome_preferences.xpm"
@@ -56,7 +56,9 @@
 #include "pixmaps/cry.xpm"
 #include "pixmaps/embarrassed.xpm"
 #include "pixmaps/kiss.xpm"
+#include "pixmaps/luke03.xpm"
 #include "pixmaps/moneymouth.xpm"
+#include "pixmaps/oneeye.xpm"
 #include "pixmaps/sad.xpm"
 #include "pixmaps/scream.xpm"
 #include "pixmaps/smile.xpm"
@@ -66,6 +68,11 @@
 #include "pixmaps/wink.xpm"
 #include "pixmaps/yell.xpm"
 
+#include "pixmaps/aol_icon.xpm"
+#include "pixmaps/free_icon.xpm"
+#include "pixmaps/dt_icon.xpm"
+#include "pixmaps/admin_icon.xpm"
+
 #define DEFAULT_FONT_NAME "-adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1"
 
 #define PATHSIZE 1024
@@ -1756,6 +1763,19 @@
 	g_free(d);
 }
 
+gchar **info_img_handler(gchar *url)
+{
+	if (!g_strcasecmp(url, "free_icon.gif"))
+		return free_icon_xpm;
+	if (!g_strcasecmp(url, "aol_icon.gif"))
+		return aol_icon_xpm;
+	if (!g_strcasecmp(url, "dt_icon.gif"))
+		return dt_icon_xpm;
+	if (!g_strcasecmp(url, "admin_icon.gif"))
+		return admin_icon_xpm;
+	return NULL;
+}
+
 void g_show_info_text(char *info)
 {
         GtkWidget *ok;
@@ -1763,6 +1783,7 @@
 	GtkWidget *text;
         GtkWidget *bbox;
         GtkWidget *sw;
+	gint options = 0;
 
         struct info_dlg *b = g_new0(struct info_dlg, 1);
 
@@ -1790,13 +1811,20 @@
 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
 					GTK_POLICY_NEVER,
 					GTK_POLICY_ALWAYS);
-	text = gtk_html_new(NULL, NULL);
+	text = gtk_imhtml_new(NULL, NULL);
 	b->text = text;
 	gtk_container_add(GTK_CONTAINER(sw), text);
 
-	GTK_HTML (text)->hadj->step_increment = 10.0;
-	GTK_HTML (text)->vadj->step_increment = 10.0;
+	GTK_LAYOUT(text)->hadjustment->step_increment = 10.0;
+	GTK_LAYOUT(text)->vadjustment->step_increment = 10.0;
 	gtk_widget_set_usize(sw, 300, 250);
+	gtk_imhtml_set_img_handler(GTK_IMHTML(text), info_img_handler);
+	if (!(display_options & OPT_DISP_SHOW_SMILEY))
+		gtk_imhtml_show_smileys(GTK_IMHTML(b->text), FALSE);
+	gtk_signal_connect(GTK_OBJECT(text), "url_clicked", GTK_SIGNAL_FUNC(open_url_nw), NULL);
+	gtk_imhtml_associate_smiley(GTK_IMHTML(text), "C:)", luke03_xpm);
+	gtk_imhtml_associate_smiley(GTK_IMHTML(text), "C:-)", luke03_xpm);
+	gtk_imhtml_associate_smiley(GTK_IMHTML(text), "O-)", oneeye_xpm);
 
 	gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 0);
 	gtk_box_pack_start(GTK_BOX(bbox), sw, TRUE, TRUE, 0);
@@ -1805,11 +1833,16 @@
 	aol_icon(b->window->window);
 	gtk_widget_show_all(b->window);
 
-	if (display_options & OPT_DISP_SHOW_SMILEY)
-		write_html_with_smileys(b->window, b->text, info);
-	else
-		gtk_html_append_text(GTK_HTML(b->text), info, (display_options & OPT_DISP_IGNORE_COLOUR) ? HTML_OPTION_NO_COLOURS : 0);
-	gtk_html_append_text(GTK_HTML(b->text), "</BODY>", 0);
+	if (display_options & OPT_DISP_IGNORE_COLOUR)
+		options ^= GTK_IMHTML_NO_COLOURS;
+	if (display_options & OPT_DISP_IGNORE_FONTS)
+		options ^= GTK_IMHTML_NO_FONTS;
+	options ^= GTK_IMHTML_NO_COMMENTS;
+	options ^= GTK_IMHTML_NO_TITLE;
+	options ^= GTK_IMHTML_NO_NEWLINE;
+	options ^= GTK_IMHTML_NO_SCROLL;
+	gtk_imhtml_append_text(GTK_IMHTML(b->text), info, options);
+	gtk_imhtml_append_text(GTK_IMHTML(b->text), "<BR>", 0);
 
 	gtk_adjustment_set_value(gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(sw)), 0);
 }
--- a/src/gaim.h	Thu Jan 25 20:31:12 2001 +0000
+++ b/src/gaim.h	Fri Jan 26 02:02:36 2001 +0000
@@ -486,6 +486,7 @@
 #define OPT_DISP_CHAT_BUTTON_XPM  0x00100000
 #define OPT_DISP_SHOW_WARN        0x00200000
 #define OPT_DISP_IGNORE_FONTS     0x00400000
+#define OPT_DISP_IGNORE_SIZES     0x00800000
 
 extern int sound_options;
 #define OPT_SOUND_LOGIN          0x00000001
--- a/src/gtkhtml.c	Thu Jan 25 20:31:12 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4448 +0,0 @@
-
-/*
- * gaim
- *
- * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include <gdk/gdkprivate.h>
-#include <gdk/gdkx.h>
-#include <gdk/gdkkeysyms.h>
-#include <ctype.h>
-
-#ifndef _WIN32
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#endif
-
-#include "gaim.h"
-#include "gtkhtml.h"
-
-#include "pixmaps/aol_icon.xpm"
-#include "pixmaps/admin_icon.xpm"
-#include "pixmaps/free_icon.xpm"
-#include "pixmaps/dt_icon.xpm"
-#define MAX_SIZE                 7
-#define MIN_HTML_WIDTH_LINES     20
-#define MIN_HTML_HEIGHT_LINES    10
-#define BORDER_WIDTH             2
-#define SCROLL_TIME              100
-#define SCROLL_PIXELS            5
-#define KEY_SCROLL_PIXELS        10
-
-int font_sizes[] = { 80, 100, 120, 140, 200, 300, 400 };
-
-/*
-GdkFont *fixed_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-GdkFont *fixed_bold_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-GdkFont *fixed_italic_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-GdkFont *fixed_bold_italic_font[] =
-	{ NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-GdkFont *prop_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-GdkFont *prop_bold_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-GdkFont *prop_italic_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-GdkFont *prop_bold_italic_font[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-*/
-
-GData * font_cache;
-static gboolean cache_init = FALSE;
-
-struct font_state
-{
-	int size;
-	int owncolor;
-	int ownbg;
-	gchar font[1024];
-	GdkColor *color;
-	GdkColor *bgcol;
-	struct font_state *next;
-};
-
-struct font_state *push_state(struct font_state *current)
-{
-	struct font_state *tmp;
-	tmp = (struct font_state *) g_new0(struct font_state, 1);
-	tmp->next = current;
-	tmp->color = current->color;
-	tmp->bgcol = current->bgcol;
-	tmp->size = current->size;
-	tmp->owncolor = 0;
-	tmp->ownbg = 0;
-	strcpy( tmp->font, current->font );
-	return tmp;
-}
-
-enum
-{
-	ARG_0,
-	ARG_HADJUSTMENT,
-	ARG_VADJUSTMENT,
-};
-
-
-enum
-{
-	TARGET_STRING,
-	TARGET_TEXT,
-	TARGET_COMPOUND_TEXT
-};
-
-
-static void gtk_html_class_init(GtkHtmlClass * klass);
-static void gtk_html_set_arg(GtkObject * object, GtkArg * arg, guint arg_id);
-static void gtk_html_get_arg(GtkObject * object, GtkArg * arg, guint arg_id);
-static void gtk_html_init(GtkHtml * html);
-static void gtk_html_destroy(GtkObject * object);
-static void gtk_html_finalize(GtkObject * object);
-static void gtk_html_realize(GtkWidget * widget);
-static void gtk_html_unrealize(GtkWidget * widget);
-static void gtk_html_style_set(GtkWidget * widget, GtkStyle * previous_style);
-static void gtk_html_draw_focus(GtkWidget * widget);
-static void gtk_html_size_request(GtkWidget * widget,
-								  GtkRequisition * requisition);
-static void gtk_html_size_allocate(GtkWidget * widget,
-								   GtkAllocation * allocation);
-static void gtk_html_adjustment(GtkAdjustment * adjustment, GtkHtml * html);
-static void gtk_html_disconnect(GtkAdjustment * adjustment, GtkHtml * html);
-static void gtk_html_add_seperator(GtkHtml *, GdkFont *, GdkColor *, GdkColor *);
-static void gtk_html_add_text(GtkHtml * html,
-							  GdkFont * font,
-							  GdkColor * fore,
-							  GdkColor * back,
-							  gchar * chars,
-							  gint length,
-							  gint uline, gint strike, gchar * url);
-static void gtk_html_draw_bit(GtkHtml * html,
-							  GtkHtmlBit * htmlbit, gint redraw);
-static void gtk_html_selection_get(GtkWidget * widget,
-								   GtkSelectionData * selection_data,
-								   guint sel_info, guint32 time);
-static gint gtk_html_selection_clear(GtkWidget * widget,
-									 GdkEventSelection * event);
-static gint gtk_html_visibility_notify(GtkWidget * widget,
-									   GdkEventVisibility * event);
-
-
-/* Event handlers */
-static void gtk_html_draw(GtkWidget * widget, GdkRectangle * area);
-static gint gtk_html_expose(GtkWidget * widget, GdkEventExpose * event);
-static gint gtk_html_button_press(GtkWidget * widget, GdkEventButton * event);
-static gint gtk_html_button_release(GtkWidget * widget, GdkEventButton * event);
-static gint gtk_html_motion_notify(GtkWidget * widget, GdkEventMotion * event);
-static gint gtk_html_key_press(GtkWidget * widget, GdkEventKey * event);
-static gint gtk_html_leave_notify(GtkWidget * widget, GdkEventCrossing * event);
-
-static gint gtk_html_tooltip_timeout(gpointer data);
-
-
-static void clear_area(GtkHtml * html, GdkRectangle * area);
-static void expose_html(GtkHtml * html, GdkRectangle * area, gboolean cursor);
-static void scroll_down(GtkHtml * html, gint diff0);
-static void scroll_up(GtkHtml * html, gint diff0);
-
-static void adjust_adj(GtkHtml * html, GtkAdjustment * adj);
-static void resize_html(GtkHtml * html);
-static gint html_bit_is_onscreen(GtkHtml * html, GtkHtmlBit * hb);
-static void draw_cursor(GtkHtml * html);
-static void undraw_cursor(GtkHtml * html);
-
-static int get_line_height(GtkHtml *, GtkHtmlBit *);
-
-static GtkWidgetClass *parent_class = NULL;
-
-GtkType gtk_html_get_type(void)
-{
-	static GtkType html_type = 0;
-
-	if (!html_type)
-	{
-		static const GtkTypeInfo html_info = {
-			"GtkHtml",
-			sizeof(GtkHtml),
-			sizeof(GtkHtmlClass),
-			(GtkClassInitFunc) gtk_html_class_init,
-			(GtkObjectInitFunc) gtk_html_init,
-			NULL,
-			NULL,
-			NULL,
-		};
-		html_type = gtk_type_unique(GTK_TYPE_WIDGET, &html_info);
-	}
-	return html_type;
-}
-
-
-static void gtk_html_class_init(GtkHtmlClass * class)
-{
-	GtkObjectClass *object_class;
-	GtkWidgetClass *widget_class;
-
-	object_class = (GtkObjectClass *) class;
-	widget_class = (GtkWidgetClass *) class;
-	parent_class = gtk_type_class(GTK_TYPE_WIDGET);
-
-
-	gtk_object_add_arg_type("GtkHtml::hadjustment",
-							GTK_TYPE_ADJUSTMENT,
-							GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
-							ARG_HADJUSTMENT);
-
-	gtk_object_add_arg_type("GtkHtml::vadjustment",
-							GTK_TYPE_ADJUSTMENT,
-							GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
-							ARG_VADJUSTMENT);
-
-	object_class->set_arg = gtk_html_set_arg;
-	object_class->get_arg = gtk_html_get_arg;
-	object_class->destroy = gtk_html_destroy;
-	object_class->finalize = gtk_html_finalize;
-
-	widget_class->realize = gtk_html_realize;
-	widget_class->unrealize = gtk_html_unrealize;
-	widget_class->style_set = gtk_html_style_set;
-	widget_class->draw_focus = gtk_html_draw_focus;
-	widget_class->size_request = gtk_html_size_request;
-	widget_class->size_allocate = gtk_html_size_allocate;
-	widget_class->draw = gtk_html_draw;
-	widget_class->expose_event = gtk_html_expose;
-	widget_class->button_press_event = gtk_html_button_press;
-	widget_class->button_release_event = gtk_html_button_release;
-	widget_class->motion_notify_event = gtk_html_motion_notify;
-	widget_class->leave_notify_event = gtk_html_leave_notify;
-	widget_class->selection_get = gtk_html_selection_get;
-	widget_class->selection_clear_event = gtk_html_selection_clear;
-	widget_class->key_press_event = gtk_html_key_press;
-	widget_class->visibility_notify_event = gtk_html_visibility_notify;
-
-
-	widget_class->set_scroll_adjustments_signal =
-		gtk_signal_new("set_scroll_adjustments",
-					   GTK_RUN_LAST,
-					   object_class->type,
-					   GTK_SIGNAL_OFFSET(GtkHtmlClass, set_scroll_adjustments),
-					   gtk_marshal_NONE__POINTER_POINTER,
-					   GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT,
-					   GTK_TYPE_ADJUSTMENT);
-
-
-	class->set_scroll_adjustments = gtk_html_set_adjustments;
-
-}
-
-static void gtk_html_set_arg(GtkObject * object, GtkArg * arg, guint arg_id)
-{
-	GtkHtml *html;
-
-	html = GTK_HTML(object);
-
-	switch (arg_id)
-	{
-	case ARG_HADJUSTMENT:
-		gtk_html_set_adjustments(html, GTK_VALUE_POINTER(*arg), html->vadj);
-		break;
-	case ARG_VADJUSTMENT:
-		gtk_html_set_adjustments(html, html->hadj, GTK_VALUE_POINTER(*arg));
-		break;
-	default:
-		break;
-	}
-}
-
-static void gtk_html_get_arg(GtkObject * object, GtkArg * arg, guint arg_id)
-{
-	GtkHtml *html;
-
-	html = GTK_HTML(object);
-
-	switch (arg_id)
-	{
-	case ARG_HADJUSTMENT:
-		GTK_VALUE_POINTER(*arg) = html->hadj;
-		break;
-	case ARG_VADJUSTMENT:
-		GTK_VALUE_POINTER(*arg) = html->vadj;
-		break;
-	default:
-		arg->type = GTK_TYPE_INVALID;
-		break;
-	}
-}
-
-static void gtk_html_init(GtkHtml * html)
-{
-	static const GtkTargetEntry targets[] = {
-		{"STRING", 0, TARGET_STRING},
-		{"TEXT", 0, TARGET_TEXT},
-		{"COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT}
-	};
-
-	static const gint n_targets = sizeof(targets) / sizeof(targets[0]);
-
-	GTK_WIDGET_SET_FLAGS(html, GTK_CAN_FOCUS);
-
-	html->html_area = NULL;
-	html->hadj = NULL;
-	html->vadj = NULL;
-	html->current_x = 0;
-	html->current_y = 0;
-	html->start_sel = html->end_sel = NULL;
-	html->start_sel_x = html->start_sel_y = -1;
-	html->num_end = html->num_start = -1;
-
-	html->html_bits = NULL;
-	html->urls = NULL;
-	html->selected_text = NULL;
-	html->tooltip_hb = NULL;
-	html->tooltip_timer = -1;
-	html->tooltip_window = NULL;
-	html->cursor_hb = NULL;
-	html->cursor_pos = 0;
-
-	html->pm = NULL;
-
-	html->editable = 0;
-	html->transparent = 0;
-
-	html->frozen = 0;
-
-	gtk_selection_add_targets(GTK_WIDGET(html), GDK_SELECTION_PRIMARY,
-							  targets, n_targets);
-
-
-
-}
-
-
-GtkWidget *gtk_html_new(GtkAdjustment * hadj, GtkAdjustment * vadj)
-{
-	GtkWidget *html;
-	if(!cache_init)
-	{
-		g_datalist_init(&font_cache);
-		cache_init = TRUE;
-	}
-
-	if (hadj)
-		g_return_val_if_fail(GTK_IS_ADJUSTMENT(hadj), NULL);
-	if (vadj)
-		g_return_val_if_fail(GTK_IS_ADJUSTMENT(vadj), NULL);
-
-	html = gtk_widget_new(GTK_TYPE_HTML,
-						  "hadjustment", hadj, "vadjustment", vadj, NULL);
-
-	return html;
-}
-
-
-void gtk_html_set_editable(GtkHtml * html, gboolean is_editable)
-{
-	g_return_if_fail(html != NULL);
-	g_return_if_fail(GTK_IS_HTML(html));
-
-
-	html->editable = (is_editable != FALSE);
-
-	if (is_editable)
-		draw_cursor(html);
-	else
-		undraw_cursor(html);
-
-}
-
-void gtk_html_set_transparent(GtkHtml * html, gboolean is_transparent)
-{
-	GdkRectangle rect;
-	gint width,
-	  height;
-	GtkWidget *widget;
-
-	g_return_if_fail(html != NULL);
-	g_return_if_fail(GTK_IS_HTML(html));
-
-
-	widget = GTK_WIDGET(html);
-	html->transparent = (is_transparent != FALSE);
-
-	if (!GTK_WIDGET_REALIZED(widget))
-		return;
-
-	html->bg_gc = NULL;
-	gdk_window_get_size(widget->window, &width, &height);
-	rect.x = 0;
-	rect.y = 0;
-	rect.width = width;
-	rect.height = height;
-	gdk_window_clear_area(widget->window, rect.x, rect.y, rect.width,
-						  rect.height);
-
-	expose_html(html, &rect, FALSE);
-	gtk_html_draw_focus((GtkWidget *) html);
-}
-
-
-void gtk_html_set_adjustments(GtkHtml * html,
-							  GtkAdjustment * hadj, GtkAdjustment * vadj)
-{
-	g_return_if_fail(html != NULL);
-	g_return_if_fail(GTK_IS_HTML(html));
-	if (hadj)
-		g_return_if_fail(GTK_IS_ADJUSTMENT(hadj));
-	else
-		hadj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
-	if (vadj)
-		g_return_if_fail(GTK_IS_ADJUSTMENT(vadj));
-	else
-		vadj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
-
-	if (html->hadj && (html->hadj != hadj))
-	{
-		gtk_signal_disconnect_by_data(GTK_OBJECT(html->hadj), html);
-		gtk_object_unref(GTK_OBJECT(html->hadj));
-	}
-
-	if (html->vadj && (html->vadj != vadj))
-	{
-		gtk_signal_disconnect_by_data(GTK_OBJECT(html->vadj), html);
-		gtk_object_unref(GTK_OBJECT(html->vadj));
-	}
-
-	if (html->hadj != hadj)
-	{
-		html->hadj = hadj;
-		gtk_object_ref(GTK_OBJECT(html->hadj));
-		gtk_object_sink(GTK_OBJECT(html->hadj));
-
-		gtk_signal_connect(GTK_OBJECT(html->hadj), "changed",
-						   (GtkSignalFunc) gtk_html_adjustment, html);
-		gtk_signal_connect(GTK_OBJECT(html->hadj), "value_changed",
-						   (GtkSignalFunc) gtk_html_adjustment, html);
-		gtk_signal_connect(GTK_OBJECT(html->hadj), "disconnect",
-						   (GtkSignalFunc) gtk_html_disconnect, html);
-		gtk_html_adjustment(hadj, html);
-	}
-
-	if (html->vadj != vadj)
-	{
-		html->vadj = vadj;
-		gtk_object_ref(GTK_OBJECT(html->vadj));
-		gtk_object_sink(GTK_OBJECT(html->vadj));
-
-		gtk_signal_connect(GTK_OBJECT(html->vadj), "changed",
-						   (GtkSignalFunc) gtk_html_adjustment, html);
-		gtk_signal_connect(GTK_OBJECT(html->vadj), "value_changed",
-						   (GtkSignalFunc) gtk_html_adjustment, html);
-		gtk_signal_connect(GTK_OBJECT(html->vadj), "disconnect",
-						   (GtkSignalFunc) gtk_html_disconnect, html);
-		gtk_html_adjustment(vadj, html);
-	}
-}
-
-
-
-GdkColor *get_color(int colorv, GdkColormap * map)
-{
-	GdkColor *color;
-#if 0
-	fprintf(stdout, "color is %x\n", colorv);
-#endif
-	color = (GdkColor *) g_new0(GdkColor, 1);
-	color->red = ((colorv & 0xff0000) >> 16) * 256;
-	color->green = ((colorv & 0xff00) >> 8) * 256;
-	color->blue = ((colorv & 0xff)) * 256;
-#if 0
-	fprintf(stdout, "Colors are %d, %d, %d\n", color->red, color->green,
-			color->blue);
-#endif
-	gdk_color_alloc(map, color);
-	return color;
-}
-
-
-int load_font_with_cache(const char *name, const char *weight, char slant,
-	int size, GdkFont **font_return)
-{
-	gchar font_spec[1024];
-
-	if (size > 0)
-		g_snprintf(font_spec, sizeof font_spec,
-			"-*-%s-%s-%c-*-*-*-%d-*-*-*-*-*-*",
-			name, weight, slant, size);
-	else
-		g_snprintf(font_spec, sizeof font_spec,
-			"-*-%s-%s-%c-*-*-*-*-*-*-*-*-*-*",
-			name, weight, slant);
-
-	if((*font_return = g_datalist_id_get_data(&font_cache,
-				g_quark_from_string(font_spec)))) {
-		return TRUE;
-	} else if ((*font_return = gdk_font_load(font_spec))) {
-		g_datalist_id_set_data(&font_cache,
-			g_quark_from_string(font_spec), *font_return);
-		return TRUE;
-	} else {
-		return FALSE;
-	}
-}
-
-
-GdkFont *getfont(const char *font, int bold, int italic, int fixed, int size)
-{
-	GdkFont *my_font = NULL;
-	gchar *weight, slant;
-
-	if (!font || !strlen(font)) font = fixed ? "courier" : "helvetica";
-	weight = bold ? "bold" : "medium";
-	slant = italic ? 'i' : 'r';
-
-	if (size > MAX_SIZE) size = MAX_SIZE;
-	if (size < 1) size = 1;
-	size = font_sizes[size-1];
-	
-	/* try both 'i'talic and 'o'blique for italic fonts */
-
-	if (load_font_with_cache(font, weight, slant, size, &my_font))
-		return my_font;
-	if (load_font_with_cache(font, weight, 'o', size, &my_font))
-		return my_font;
-	if (italic && load_font_with_cache(font, weight, slant, 0, &my_font))
-		return my_font;
-	if (italic && load_font_with_cache(font, weight, 'o', 0, &my_font))
-		return my_font;
-
-	/* since we couldn't get the right font, fall back to the default fonts. */
-
-	font = fixed ? "courier" : "helvetica";
-	if (load_font_with_cache(font, weight, slant, size, &my_font))
-		return my_font;
-	if (load_font_with_cache(font, weight, slant, 0, &my_font))
-		return my_font;
-	
-	font = fixed ? "helvetica" : "courier";
-	if (load_font_with_cache(font, weight, slant, size, &my_font))
-		return my_font;
-	if (load_font_with_cache(font, weight, slant, 0, &my_font))
-		return my_font;
-
-	/* whoops, couldn't do any of those. maybe they have a default outgoing
-	 * font? maybe we can use that. */
-	if (fontface[0]) {
-		/* woohoo! */
-		if (load_font_with_cache(fontface, "medium", 'r', size, &my_font))
-			return my_font;
-		if (load_font_with_cache(fontface, "medium", 'r', 0, &my_font))
-			return my_font;
-	}
-
-	/* ok, now we're in a pickle. if we can't do any of the above, let's
-	 * try doing the most boring font we can find. */
-	if (load_font_with_cache("helvetica", "medium", 'r', size, &my_font))
-		return my_font;
-	if (load_font_with_cache("helvetica", "medium", 'r', 0, &my_font))
-		return my_font;
-
-	if (load_font_with_cache("courier", "medium", 'r', size, &my_font))
-		return my_font;
-	if (load_font_with_cache("courier", "medium", 'r', 0, &my_font))
-		return my_font;
-
-	if (load_font_with_cache("times", "medium", 'r', size, &my_font))
-		return my_font;
-	if (load_font_with_cache("times", "medium", 'r', 0, &my_font))
-		return my_font;
-
-	/* my god, how did we end up here. is there a 'generic font' function
-	 * in gdk? that would be incredibly useful here. there's gotta be a
-	 * better way to do this. */
-	
-	/* well, if they can't do any of the fonts above, they'll take whatever
-	 * they can get, and be happy about it, damn it. :) */
-	load_font_with_cache("*", "*", '*', 0, &my_font);
-	return my_font;
-}
-
-
-/* 'Borrowed' from ETerm */
-GdkWindow *get_desktop_window(GtkWidget * widget)
-{
-#ifndef _WIN32
-	GdkAtom prop,
-	  type,
-	  prop2;
-	int format;
-	gint length;
-	guchar *data;
-	GtkWidget *w;
-
-	prop = gdk_atom_intern("_XROOTPMAP_ID", 1);
-	prop2 = gdk_atom_intern("_XROOTCOLOR_PIXEL", 1);
-
-	if (prop == None && prop2 == None)
-	{
-		return NULL;
-	}
-
-
-
-	for (w = widget; w; w = w->parent)
-	{
-
-		if (prop != None)
-		{
-			gdk_property_get(w->window, prop, AnyPropertyType, 0L, 1L, 0,
-							 &type, &format, &length, &data);
-		}
-		else if (prop2 != None)
-		{
-			gdk_property_get(w->window, prop2, AnyPropertyType, 0L, 1L, 0,
-							 &type, &format, &length, &data);
-		}
-		else
-		{
-			continue;
-		}
-		if (type != None)
-		{
-			return (w->window);
-		}
-	}
-#endif
-	return NULL;
-
-}
-
-
-
-GdkPixmap *get_desktop_pixmap(GtkWidget * widget)
-{
-#ifndef _WIN32
-	GdkPixmap *p;
-	GdkAtom prop,
-	  type,
-	  prop2;
-	int format;
-	gint length;
-	guint32 id;
-	guchar *data;
-
-	prop = gdk_atom_intern("_XROOTPMAP_ID", 1);
-	prop2 = gdk_atom_intern("_XROOTCOLOR_PIXEL", 1);
-
-
-	if (prop == None && prop2 == None)
-	{
-		return NULL;
-	}
-
-	if (prop != None)
-	{
-		gdk_property_get(get_desktop_window(widget), prop, AnyPropertyType, 0L,
-						 1L, 0, &type, &format, &length, &data);
-		if (type == XA_PIXMAP)
-		{
-			id = data[0];
-			id += data[1] << 8;
-			id += data[2] << 16;
-			id += data[3] << 24;
-			p = gdk_pixmap_foreign_new(id);
-			return p;
-		}
-	}
-	if (prop2 != None)
-	{
-
-/*                XGetWindowProperty(Xdisplay, desktop_window, prop2, 0L, 1L, False, AnyPropertyType,
-                                   &type, &format, &length, &after, &data);*/
-
-/*                if (type == XA_CARDINAL) {*/
-		/*
-		 * D_PIXMAP(("  Solid color not yet supported.\n"));
-		 */
-
-/*                        return NULL;
-                }*/
-	}
-	/*
-	 * D_PIXMAP(("No suitable attribute found.\n"));
-	 */
-#endif
-	return NULL;
-}
-
-
-static void clear_focus_area(GtkHtml * html,
-							 gint area_x,
-							 gint area_y, gint area_width, gint area_height)
-{
-	GtkWidget *widget = GTK_WIDGET(html);
-	gint x,
-	  y;
-
-	gint ythick = BORDER_WIDTH + widget->style->klass->ythickness;
-	gint xthick = BORDER_WIDTH + widget->style->klass->xthickness;
-
-	gint width,
-	  height;
-
-	if (html->frozen > 0)
-		return;
-
-	if (html->transparent)
-	{
-		if (html->pm == NULL)
-			html->pm = get_desktop_pixmap(widget);
-
-		if (html->pm == NULL)
-			return;
-
-		if (html->bg_gc == NULL)
-		{
-			GdkGCValues values;
-
-			values.tile = html->pm;
-			values.fill = GDK_TILED;
-
-			html->bg_gc = gdk_gc_new_with_values(html->html_area, &values,
-												 GDK_GC_FILL | GDK_GC_TILE);
-
-		}
-
-		gdk_window_get_deskrelative_origin(widget->window, &x, &y);
-
-		gdk_draw_pixmap(widget->window, html->bg_gc, html->pm,
-						x + area_x, y + area_y, area_x, area_y, area_width,
-						area_height);
-
-
-	}
-	else
-	{
-		gdk_window_get_size(widget->style->bg_pixmap[GTK_STATE_NORMAL], &width,
-							&height);
-
-		gdk_gc_set_ts_origin(html->bg_gc,
-							 (-html->xoffset + xthick) % width,
-							 (-html->yoffset + ythick) % height);
-
-		gdk_draw_rectangle(widget->window, html->bg_gc, TRUE,
-						   area_x, area_y, area_width, area_height);
-	}
-}
-
-static void gtk_html_draw_focus(GtkWidget * widget)
-{
-	GtkHtml *html;
-	gint width,
-	  height;
-	gint x,
-	  y;
-
-	g_return_if_fail(widget != NULL);
-	g_return_if_fail(GTK_IS_HTML(widget));
-
-	html = GTK_HTML(widget);
-
-	if (GTK_WIDGET_DRAWABLE(widget))
-	{
-		gint ythick = widget->style->klass->ythickness;
-		gint xthick = widget->style->klass->xthickness;
-		gint xextra = BORDER_WIDTH;
-		gint yextra = BORDER_WIDTH;
-
-		x = 0;
-		y = 0;
-		width = widget->allocation.width;
-		height = widget->allocation.height;
-
-		if (GTK_WIDGET_HAS_FOCUS(widget))
-		{
-			x += 1;
-			y += 1;
-			width -= 2;
-			height -= 2;
-			xextra -= 1;
-			yextra -= 1;
-
-			gtk_paint_focus(widget->style, widget->window,
-							NULL, widget, "text",
-							0, 0,
-							widget->allocation.width - 1,
-							widget->allocation.height - 1);
-		}
-
-		gtk_paint_shadow(widget->style, widget->window,
-						 GTK_STATE_NORMAL, GTK_SHADOW_IN,
-						 NULL, widget, "text", x, y, width, height);
-
-		x += xthick;
-		y += ythick;
-		width -= 2 * xthick;
-		height -= 2 * ythick;
-
-
-		if (widget->style->bg_pixmap[GTK_STATE_NORMAL] || html->transparent)
-		{
-			/*
-			 * top rect 
-			 */
-			clear_focus_area(html, x, y, width, yextra);
-			/*
-			 * left rect 
-			 */
-			clear_focus_area(html, x, y + yextra,
-							 xextra, y + height - 2 * yextra);
-			/*
-			 * right rect 
-			 */
-			clear_focus_area(html, x + width - xextra, y + yextra,
-							 xextra, height - 2 * ythick);
-			/*
-			 * bottom rect 
-			 */
-			clear_focus_area(html, x, x + height - yextra, width, yextra);
-		}
-	}
-}
-
-static void gtk_html_size_request(GtkWidget * widget,
-								  GtkRequisition * requisition)
-{
-	gint xthickness;
-	gint ythickness;
-	gint char_height;
-	gint char_width;
-
-	g_return_if_fail(widget != NULL);
-	g_return_if_fail(GTK_IS_HTML(widget));
-	g_return_if_fail(requisition != NULL);
-
-	xthickness = widget->style->klass->xthickness + BORDER_WIDTH;
-	ythickness = widget->style->klass->ythickness + BORDER_WIDTH;
-
-	char_height = MIN_HTML_HEIGHT_LINES * (widget->style->font->ascent +
-										   widget->style->font->descent);
-
-	char_width = MIN_HTML_WIDTH_LINES * (gdk_text_width(widget->style->font,
-														"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
-														26) / 26);
-
-	requisition->width = char_width + xthickness * 2;
-	requisition->height = char_height + ythickness * 2;
-}
-
-static void gtk_html_size_allocate(GtkWidget * widget,
-								   GtkAllocation * allocation)
-{
-	GtkHtml *html;
-
-	g_return_if_fail(widget != NULL);
-	g_return_if_fail(GTK_IS_HTML(widget));
-	g_return_if_fail(allocation != NULL);
-
-	html = GTK_HTML(widget);
-
-	widget->allocation = *allocation;
-	if (GTK_WIDGET_REALIZED(widget))
-	{
-		gdk_window_move_resize(widget->window,
-							   allocation->x, allocation->y,
-							   allocation->width, allocation->height);
-
-		gdk_window_move_resize(html->html_area,
-							   widget->style->klass->xthickness + BORDER_WIDTH,
-							   widget->style->klass->ythickness + BORDER_WIDTH,
-							   MAX(1, (gint) widget->allocation.width -
-								   (gint) (widget->style->klass->xthickness +
-										   (gint) BORDER_WIDTH) * 2),
-							   MAX(1, (gint) widget->allocation.height -
-								   (gint) (widget->style->klass->ythickness +
-										   (gint) BORDER_WIDTH) * 2));
-
-		resize_html(html);
-	}
-}
-
-static void gtk_html_draw(GtkWidget * widget, GdkRectangle * area)
-{
-	g_return_if_fail(widget != NULL);
-	g_return_if_fail(GTK_IS_HTML(widget));
-	g_return_if_fail(area != NULL);
-
-	if (GTK_WIDGET_DRAWABLE(widget))
-	{
-		expose_html(GTK_HTML(widget), area, TRUE);
-		gtk_widget_draw_focus(widget);
-	}
-}
-
-
-static gint gtk_html_expose(GtkWidget * widget, GdkEventExpose * event)
-{
-	GtkHtml *html;
-
-	g_return_val_if_fail(widget != NULL, FALSE);
-	g_return_val_if_fail(GTK_IS_HTML(widget), FALSE);
-	g_return_val_if_fail(event != NULL, FALSE);
-
-	html = GTK_HTML(widget);
-
-	if (event->window == html->html_area)
-	{
-		expose_html(html, &event->area, TRUE);
-	}
-	else if (event->count == 0)
-	{
-		gtk_widget_draw_focus(widget);
-	}
-
-	return FALSE;
-
-}
-
-
-static gint gtk_html_selection_clear(GtkWidget * widget,
-									 GdkEventSelection * event)
-{
-	GtkHtml *html;
-
-	g_return_val_if_fail(widget != NULL, FALSE);
-	g_return_val_if_fail(GTK_IS_HTML(widget), FALSE);
-	g_return_val_if_fail(event != NULL, FALSE);
-
-	/*
-	 * Let the selection handling code know that the selection
-	 * * has been changed, since we've overriden the default handler 
-	 */
-	if (!gtk_selection_clear(widget, event))
-		return FALSE;
-
-	html = GTK_HTML(widget);
-
-	if (event->selection == GDK_SELECTION_PRIMARY)
-	{
-		if (html->selected_text)
-		{
-			GList *hbits = html->html_bits;
-			GtkHtmlBit *hb;
-
-			g_free(html->selected_text);
-			html->selected_text = NULL;
-			html->start_sel = NULL;
-			html->end_sel = NULL;
-			html->num_start = 0;
-			html->num_end = 0;
-			while (hbits)
-			{
-				hb = (GtkHtmlBit *) hbits->data;
-				if (hb->was_selected)
-					gtk_html_draw_bit(html, hb, 1);
-				hbits = hbits->prev;
-			}
-			hbits = g_list_last(html->html_bits);
-		}
-	}
-
-	return TRUE;
-}
-
-
-
-static void gtk_html_selection_get(GtkWidget * widget,
-								   GtkSelectionData * selection_data,
-								   guint sel_info, guint32 time)
-{
-	gchar *str;
-	gint len;
-	GtkHtml *html;
-
-	g_return_if_fail(widget != NULL);
-	g_return_if_fail(GTK_IS_HTML(widget));
-
-	html = GTK_HTML(widget);
-
-
-	if (selection_data->selection != GDK_SELECTION_PRIMARY)
-		return;
-
-	str = html->selected_text;
-
-	if (!str)
-		return;
-
-	len = strlen(str);
-
-	if (sel_info == TARGET_STRING)
-	{
-		gtk_selection_data_set(selection_data,
-							   GDK_SELECTION_TYPE_STRING,
-							   8 * sizeof(gchar), (guchar *) str, len);
-	}
-	else if ((sel_info == TARGET_TEXT) || (sel_info == TARGET_COMPOUND_TEXT))
-	{
-		guchar *text;
-		GdkAtom encoding;
-		gint format;
-		gint new_length;
-
-		gdk_string_to_compound_text(str, &encoding, &format, &text,
-									&new_length);
-		gtk_selection_data_set(selection_data, encoding, format, text,
-							   new_length);
-		gdk_free_compound_text(text);
-	}
-
-
-
-}
-
-static void do_select(GtkHtml * html, int x, int y)
-{
-	GList *hbits = g_list_last(html->html_bits);
-	int epos,
-	  spos;
-	GtkHtmlBit *hb;
-
-	if (!hbits)
-		return;
-
-	hb = (GtkHtmlBit *) hbits->data;
-
-	while (hbits)
-	{
-		hb = (GtkHtmlBit *) hbits->data;
-		if (hb->type == HTML_BIT_TEXT)
-			break;
-		hbits = hbits->prev;
-	}
-
-	if (!hb)
-		return;
-
-
-	if (y > hb->y)
-	{
-		html->num_end = strlen(hb->text) - 1;
-		html->end_sel = hb;
-	}
-	else if (y < 0)
-	{
-		html->num_end = 0;
-		html->end_sel = (GtkHtmlBit *) html->html_bits->data;
-	}
-	else
-		while (hbits)
-		{
-			hb = (GtkHtmlBit *) hbits->data;
-			if ((y < hb->y && y > (hb->y - hb->height)) &&
-				(x > hb->x + hb->width))
-			{
-				if (hb->type != HTML_BIT_TEXT)
-				{
-					html->num_end = 0;
-					html->end_sel = hb;
-					break;
-				}
-
-				html->num_end = strlen(hb->text) - 1;
-				html->end_sel = hb;
-				break;
-			}
-			else if ((x > hb->x && x < (hb->x + hb->width)) &&
-					 (y < hb->y && y > (hb->y - hb->height)))
-			{
-				int i,
-				  len;
-				int w = x - hb->x;
-
-				if (hb->type != HTML_BIT_TEXT)
-				{
-					html->num_end = 0;
-					html->end_sel = hb;
-					break;
-				}
-
-				len = strlen(hb->text);
-
-				for (i = 1; i <= len; i++)
-				{
-					if (gdk_text_measure(hb->font, hb->text, i) > w)
-					{
-						html->num_end = i - 1;
-						html->end_sel = hb;
-						break;
-					}
-				}
-				break;
-			}
-			hbits = hbits->prev;
-		}
-
-	if (html->end_sel == NULL)
-		return;
-	if (html->start_sel == NULL)
-	{
-		html->start_sel = html->end_sel;
-		html->num_start = html->num_end;
-	}
-
-	epos = g_list_index(html->html_bits, html->end_sel);
-	spos = g_list_index(html->html_bits, html->start_sel);
-	g_free(html->selected_text);
-	html->selected_text = NULL;
-
-	if (epos == spos)
-	{
-		char *str;
-		if (html->start_sel->type != HTML_BIT_TEXT)
-		{
-			html->selected_text = NULL;
-			return;
-		}
-		if (html->num_end == html->num_start)
-		{
-			str = g_malloc(2);
-			if (strlen(html->start_sel->text))
-				str[0] = html->start_sel->text[html->num_end];
-			else
-				str[0] = 0;
-			str[1] = 0;
-			gtk_html_draw_bit(html, html->start_sel, 0);
-			html->selected_text = str;
-		}
-		else
-		{
-			size_t st,
-			  en;
-			char *str;
-			if (html->num_end > html->num_start)
-			{
-				en = html->num_end;
-				st = html->num_start;
-			}
-			else
-			{
-				en = html->num_start;
-				st = html->num_end;
-			}
-
-			str = g_malloc(en - st + 2);
-			strncpy(str, html->start_sel->text + st, (en - st + 1));
-			str[en - st + 1] = 0;
-			gtk_html_draw_bit(html, html->start_sel, 0);
-			html->selected_text = str;
-
-		}
-	}
-	else
-	{
-		GtkHtmlBit *shb,
-		 *ehb;
-		size_t en,
-		  st;
-		int len,
-		  nlen;
-		char *str;
-		if (epos > spos)
-		{
-			shb = html->start_sel;
-			ehb = html->end_sel;
-			en = html->num_end;
-			st = html->num_start;
-		}
-		else
-		{
-			shb = html->end_sel;
-			ehb = html->start_sel;
-			en = html->num_start;
-			st = html->num_end;
-		}
-
-		hbits = g_list_find(html->html_bits, shb);
-
-		if (!hbits)
-			return;
-
-		if (shb->type == HTML_BIT_TEXT)
-		{
-			len = strlen(shb->text) - st + 1;
-			str = g_malloc(len);
-			strcpy(str, shb->text + st);
-			str[len - 1] = 0;
-			gtk_html_draw_bit(html, shb, 0);
-			if (shb->newline)
-			{
-				len += 1;
-				str = g_realloc(str, len);
-				str[len - 2] = '\n';
-				str[len - 1] = 0;
-			}
-		}
-		else
-		{
-			len = 1;
-			str = g_malloc(1);
-			str[0] = 0;
-		}
-		if (hbits->next == NULL)
-		{
-			html->selected_text = str;
-			return;
-		}
-
-
-		hbits = hbits->next;
-		while (1)
-		{						/*
-								 * Yah I know is dangerous :P 
-								 */
-			hb = (GtkHtmlBit *) hbits->data;
-			if (hb->type != HTML_BIT_TEXT)
-			{
-				if (hb == ehb)
-					break;
-				hbits = hbits->next;
-				continue;
-			}
-			if (hb != ehb)
-			{
-				nlen = len + strlen(hb->text);
-				str = g_realloc(str, nlen);
-				strcpy(str + (len - 1), hb->text);
-				len = nlen;
-				str[len - 1] = 0;
-				gtk_html_draw_bit(html, hb, 0);
-				if (hb->newline)
-				{
-					len += 1;
-					str = g_realloc(str, len);
-					str[len - 2] = '\n';
-					str[len - 1] = 0;
-				}
-			}
-			else
-			{
-				nlen = len + en + 1;
-				str = g_realloc(str, nlen);
-				strncpy(str + (len - 1), hb->text, en + 1);
-				len = nlen;
-				str[len - 1] = 0;
-
-				gtk_html_draw_bit(html, hb, 0);
-				if (hb->newline && en == strlen(hb->text))
-				{
-					len += 1;
-					str = g_realloc(str, len);
-					str[len - 2] = '\n';
-					str[len - 1] = 0;
-				}
-				break;
-			}
-			hbits = hbits->next;
-		}
-		html->selected_text = str;
-	}
-
-}
-
-static gint scroll_timeout(GtkHtml * html)
-{
-	GdkEventMotion event;
-	gint x,
-	  y;
-	GdkModifierType mask;
-
-	html->timer = 0;
-	gdk_window_get_pointer(html->html_area, &x, &y, &mask);
-
-	if (mask & GDK_BUTTON1_MASK)
-	{
-		event.is_hint = 0;
-		event.x = x;
-		event.y = y;
-		event.state = mask;
-
-		gtk_html_motion_notify(GTK_WIDGET(html), &event);
-	}
-
-	return FALSE;
-
-}
-
-
-static gint gtk_html_tooltip_paint_window(GtkHtml * html)
-{
-	GtkStyle *style;
-	gint y,
-	  baseline_skip,
-	  gap;
-
-	style = html->tooltip_window->style;
-
-	gap = (style->font->ascent + style->font->descent) / 4;
-	if (gap < 2)
-		gap = 2;
-	baseline_skip = style->font->ascent + style->font->descent + gap;
-
-	if (!html->tooltip_hb)
-		return FALSE;
-
-	gtk_paint_flat_box(style, html->tooltip_window->window,
-					   GTK_STATE_NORMAL, GTK_SHADOW_OUT,
-					   NULL, GTK_WIDGET(html->tooltip_window), "tooltip",
-					   0, 0, -1, -1);
-
-	y = style->font->ascent + 4;
-
-	gtk_paint_string(style, html->tooltip_window->window,
-					 GTK_STATE_NORMAL,
-					 NULL, GTK_WIDGET(html->tooltip_window), "tooltip",
-					 4, y, "HTML Link:");
-	y += baseline_skip;
-	gtk_paint_string(style, html->tooltip_window->window,
-					 GTK_STATE_NORMAL,
-					 NULL, GTK_WIDGET(html->tooltip_window), "tooltip",
-					 4, y, html->tooltip_hb->url);
-
-	return FALSE;
-
-
-}
-
-static gint gtk_html_tooltip_timeout(gpointer data)
-{
-	GtkHtml *html = (GtkHtml *) data;
-
-
-	GDK_THREADS_ENTER();
-
-	if (html->tooltip_hb && GTK_WIDGET_DRAWABLE(GTK_WIDGET(html)))
-	{
-		GtkWidget *widget;
-		GtkStyle *style;
-		gint gap,
-		  x,
-		  y,
-		  w,
-		  h,
-		  scr_w,
-		  scr_h,
-		  baseline_skip;
-
-		if (html->tooltip_window)
-			gtk_widget_destroy(html->tooltip_window);
-
-		html->tooltip_window = gtk_window_new(GTK_WINDOW_POPUP);
-		gtk_widget_set_app_paintable(html->tooltip_window, TRUE);
-		gtk_window_set_policy(GTK_WINDOW(html->tooltip_window), FALSE, FALSE,
-							  TRUE);
-		gtk_widget_set_name(html->tooltip_window, "gtk-tooltips");
-		gtk_signal_connect_object(GTK_OBJECT(html->tooltip_window),
-								  "expose_event",
-								  GTK_SIGNAL_FUNC
-								  (gtk_html_tooltip_paint_window),
-								  GTK_OBJECT(html));
-		gtk_signal_connect_object(GTK_OBJECT(html->tooltip_window), "draw",
-								  GTK_SIGNAL_FUNC
-								  (gtk_html_tooltip_paint_window),
-								  GTK_OBJECT(html));
-
-		gtk_widget_ensure_style(html->tooltip_window);
-		style = html->tooltip_window->style;
-
-		widget = GTK_WIDGET(html);
-
-		scr_w = gdk_screen_width();
-		scr_h = gdk_screen_height();
-
-		gap = (style->font->ascent + style->font->descent) / 4;
-		if (gap < 2)
-			gap = 2;
-		baseline_skip = style->font->ascent + style->font->descent + gap;
-
-		w = 8 + MAX(gdk_string_width(style->font, _("HTML Link:")),
-					gdk_string_width(style->font, html->tooltip_hb->url));
-		;
-		h = 8 - gap;
-		h += (baseline_skip * 2);
-
-		gdk_window_get_pointer(NULL, &x, &y, NULL);
-		/*
-		 * gdk_window_get_origin (widget->window, NULL, &y);
-		 */
-		if (GTK_WIDGET_NO_WINDOW(widget))
-			y += widget->allocation.y;
-
-		x -= ((w >> 1) + 4);
-
-		if ((x + w) > scr_w)
-			x -= (x + w) - scr_w;
-		else if (x < 0)
-			x = 0;
-
-		if (html->tooltip_hb->font) {
-			if ((y + h + 4) > scr_h)
-				y =
-					y - html->tooltip_hb->font->ascent +
-					html->tooltip_hb->font->descent;
-			else
-				y =
-					y + html->tooltip_hb->font->ascent +
-					html->tooltip_hb->font->descent;
-		} else {
-			if ((y + h + 4) > scr_h)
-				y = y - 10 + 4;
-			else
-				y = y + 10 + 4;
-		}
-
-		gtk_widget_set_usize(html->tooltip_window, w, h);
-		gtk_widget_popup(html->tooltip_window, x, y);
-
-	}
-
-	html->tooltip_timer = -1;
-
-	GDK_THREADS_LEAVE();
-
-	return FALSE;
-}
-
-
-static gint gtk_html_leave_notify(GtkWidget * widget, GdkEventCrossing * event)
-{
-	GtkHtml *html;
-
-	html = GTK_HTML(widget);
-
-	if (html->tooltip_timer != -1)
-		gtk_timeout_remove(html->tooltip_timer);
-	if (html->tooltip_window)
-	{
-		gtk_widget_destroy(html->tooltip_window);
-		html->tooltip_window = NULL;
-	}
-
-
-	html->tooltip_hb = NULL;
-	return TRUE;
-}
-
-
-static gint gtk_html_motion_notify(GtkWidget * widget, GdkEventMotion * event)
-{
-	int x,
-	  y;
-	gint width,
-	  height;
-	GdkModifierType state;
-	int realx,
-	  realy;
-	GtkHtml *html = GTK_HTML(widget);
-
-	if (event->is_hint)
-		gdk_window_get_pointer(event->window, &x, &y, &state);
-	else
-	{
-		x = event->x;
-		y = event->y;
-		state = event->state;
-	}
-
-	gdk_window_get_size(html->html_area, &width, &height);
-
-	realx = x;
-	realy = y + html->yoffset;
-
-
-	if (state & GDK_BUTTON1_MASK)
-	{
-		if (realx != html->start_sel_x || realy != html->start_sel_y)
-		{
-			char *tmp = NULL;
-
-			if (y < 0 || y > height)
-			{
-				int diff;
-				if (html->timer == 0)
-				{
-					html->timer = gtk_timeout_add(100,
-												  (GtkFunction) scroll_timeout,
-												  html);
-					if (y < 0)
-						diff = y / 2;
-					else
-						diff = (y - height) / 2;
-
-					if (html->vadj->value + diff >
-						html->vadj->upper - height + 20)
-						gtk_adjustment_set_value(html->vadj,
-												 html->vadj->upper - height +
-												 20);
-					else
-						gtk_adjustment_set_value(html->vadj,
-												 html->vadj->value + diff);
-
-				}
-			}
-
-			if (html->selected_text != NULL)
-				tmp = g_strdup(html->selected_text);
-			do_select(html, realx, realy);
-			if (tmp)
-			{
-				if (!html->selected_text || strcmp(tmp, html->selected_text))
-				{
-					GtkHtmlBit *hb;
-					GList *hbits = html->html_bits;
-					while (hbits)
-					{
-						hb = (GtkHtmlBit *) hbits->data;
-						if (hb->was_selected)
-							gtk_html_draw_bit(html, hb, 0);
-						hbits = hbits->next;
-					}
-				}
-				g_free(tmp);
-			}
-		}
-	}
-	else
-	{
-		GtkHtmlBit *hb;
-		GList *urls;
-
-		urls = html->urls;
-		while (urls)
-		{
-			hb = (GtkHtmlBit *) urls->data;
-			if ((realx > hb->x && realx < (hb->x + hb->width)) &&
-				(realy < hb->y && realy > (hb->y - hb->height)))
-			{
-				GdkCursor *cursor = NULL;
-
-				if (html->tooltip_hb != hb)
-				{
-					html->tooltip_hb = hb;
-					if (html->tooltip_timer != -1)
-						gtk_timeout_remove(html->tooltip_timer);
-					if (html->tooltip_window)
-					{
-						gtk_widget_destroy(html->tooltip_window);
-						html->tooltip_window = NULL;
-					}
-					html->tooltip_timer =
-						gtk_timeout_add(HTML_TOOLTIP_DELAY,
-										gtk_html_tooltip_timeout, html);
-				}
-
-				cursor = gdk_cursor_new(GDK_HAND2);
-				gdk_window_set_cursor(html->html_area, cursor);
-				gdk_cursor_destroy(cursor);
-
-				return TRUE;
-			}
-			urls = urls->next;
-		}
-		if (html->tooltip_timer != -1)
-			gtk_timeout_remove(html->tooltip_timer);
-		if (html->tooltip_window)
-		{
-			gtk_widget_destroy(html->tooltip_window);
-			html->tooltip_window = NULL;
-		}
-
-
-		html->tooltip_hb = NULL;
-		gdk_window_set_cursor(html->html_area, NULL);
-
-
-	}
-
-	return TRUE;
-}
-
-static gint gtk_html_button_release(GtkWidget * widget, GdkEventButton * event)
-{
-	GtkHtml *html;
-
-	html = GTK_HTML(widget);
-
-	if (html->frozen > 0)
-		return TRUE;
-
-	if (event->button == 1)
-	{
-		int realx,
-		  realy;
-		GtkHtmlBit *hb;
-		GList *urls = html->urls;
-
-		realx = event->x;
-		realy = event->y + html->yoffset;
-		if (realx != html->start_sel_x || realy != html->start_sel_y)
-		{
-			if (gtk_selection_owner_set(widget,
-										GDK_SELECTION_PRIMARY, event->time))
-			{
-			}
-			else
-			{
-			}
-		}
-		else
-		{
-			if (gdk_selection_owner_get(GDK_SELECTION_PRIMARY) ==
-				widget->window)
-				gtk_selection_owner_set(NULL, GDK_SELECTION_PRIMARY,
-										event->time);
-
-
-			while (urls)
-			{
-				void open_url_nw(GtkWidget * w, char *url);
-				hb = (GtkHtmlBit *) urls->data;
-				if ((realx > hb->x && realx < (hb->x + hb->width)) &&
-					(realy < hb->y && realy > (hb->y - hb->height)))
-				{
-					open_url_nw(NULL, hb->url);
-					// else
-					//         open_url(NULL, hb->url);
-					break;
-				}
-				urls = urls->next;
-			}
-		}
-	}
-	return TRUE;
-}
-
-
-
-static gint gtk_html_button_press(GtkWidget * widget, GdkEventButton * event)
-{
-	GtkHtml *html;
-	gfloat value;
-
-
-	html = GTK_HTML(widget);
-	value = html->vadj->value;
-
-	if (html->frozen > 0)
-		return TRUE;
-
-	if (event->button == 4)
-	{
-		value -= html->vadj->step_increment;
-		if (value < html->vadj->lower)
-			value = html->vadj->lower;
-		gtk_adjustment_set_value(html->vadj, value);
-	}
-	else if (event->button == 5)
-	{
-		value += html->vadj->step_increment;
-		if (value > html->vadj->upper)
-			value = html->vadj->upper;
-		gtk_adjustment_set_value(html->vadj, value);
-
-	}
-	else if (event->button == 1)
-	{
-		GList *hbits = g_list_last(html->html_bits);
-		int realx,
-		  realy;
-		GtkHtmlBit *hb;
-
-		realx = event->x;
-		realy = event->y + html->yoffset;
-
-		html->start_sel_x = realx;
-		html->start_sel_y = realy;
-
-		if (!hbits)
-			return TRUE;
-
-		if (html->selected_text)
-		{
-			gboolean forcedraw = FALSE;
-			hbits = html->html_bits;
-			g_free(html->selected_text);
-			html->selected_text = NULL;
-			html->start_sel = NULL;
-			html->end_sel = NULL;
-			html->num_start = 0;
-			html->num_end = 0;
-			while (hbits)
-			{
-				hb = (GtkHtmlBit *) hbits->data;
-				if (hb->was_selected || forcedraw) {
-					gtk_html_draw_bit(html, hb, 1);
-					forcedraw = TRUE;
-				}
-				hbits = hbits->next;
-			}
-			hbits = g_list_last(html->html_bits);
-		}
-
-		hb = (GtkHtmlBit *) hbits->data;
-		if (realy > hb->y)
-		{
-			if (hb->text)
-				html->num_start = strlen(hb->text) - 1;
-			else
-				html->num_start = 0;
-			html->start_sel = hb;
-		}
-		else
-			while (hbits)
-			{
-				hb = (GtkHtmlBit *) hbits->data;
-				if ((realy < hb->y && realy > (hb->y - hb->height)) &&
-					(realx > hb->x + hb->width))
-				{
-					if (hb->type != HTML_BIT_TEXT)
-					{
-						html->num_end = 0;
-						html->end_sel = hb;
-						break;
-					}
-
-					if (hb->text)
-						html->num_start = strlen(hb->text) - 1;
-					else
-						html->num_start = 0;
-
-					html->start_sel = hb;
-					break;
-				}
-				else if ((realx > hb->x && realx < (hb->x + hb->width)) &&
-						 (realy < hb->y && realy > (hb->y - hb->height)))
-				{
-					int i,
-					  len;
-					int w = realx - hb->x;
-
-					if (hb->type != HTML_BIT_TEXT)
-					{
-						html->num_end = 0;
-						html->end_sel = hb;
-						break;
-					}
-
-					if (hb->text)
-						len = strlen(hb->text);
-					else
-						len = 0;
-
-					for (i = 1; i <= len; i++)
-					{
-						if (gdk_text_measure(hb->font, hb->text, i) > w)
-						{
-							html->num_start = i - 1;
-							html->start_sel = hb;
-							break;
-						}
-					}
-					break;
-				}
-				hbits = hbits->prev;
-			}
-	}
-	else if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
-	{
-		GtkHtmlBit *hb = NULL;
-		int realx,
-		  realy;
-		GList *urls;
-
-		realx = event->x;
-		realy = event->y + html->yoffset;
-
-		urls = html->urls;
-		while (urls)
-		{
-			hb = (GtkHtmlBit *) urls->data;
-			if ((realx > hb->x && realx < (hb->x + hb->width)) &&
-				(realy < hb->y && realy > (hb->y - hb->height)))
-			{
-				break;
-			}
-			urls = urls->next;
-			hb = NULL;
-		}
-
-		if (hb != NULL)
-		{
-			
-			  GtkWidget *menu, *button;
-			   
-			   menu = gtk_menu_new();
-			   
-			   if (web_browser == BROWSER_NETSCAPE) {
-			   
-			   button = gtk_menu_item_new_with_label(_("Open URL in existing window"));
-			   gtk_signal_connect(GTK_OBJECT(button), "activate",
-			   GTK_SIGNAL_FUNC(open_url), hb->url);
-			   gtk_menu_append(GTK_MENU(menu), button);
-			   gtk_widget_show(button);
-			   
-			   }
-			   
-			   
-			   button = gtk_menu_item_new_with_label(_("Open URL in new window"));
-			   gtk_signal_connect(GTK_OBJECT(button), "activate",
-			   GTK_SIGNAL_FUNC(open_url_nw), hb->url);
-			   gtk_menu_append(GTK_MENU(menu), button);
-			   gtk_widget_show(button);
-			   
-			   if (web_browser == BROWSER_NETSCAPE) {
-			   
-			   button = gtk_menu_item_new_with_label(_("Add URL as bookmark"));
-			   gtk_signal_connect(GTK_OBJECT(button), "activate",
-			   GTK_SIGNAL_FUNC(add_bookmark), hb->url);
-			   gtk_menu_append(GTK_MENU(menu), button);
-			   gtk_widget_show(button);
-			   
-			   }
-			   
-			   gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
-			   event->button, event->time);                 
-			   
-		}
-	}
-
-	return TRUE;
-}
-
-
-static void gtk_html_draw_bit(GtkHtml * html, GtkHtmlBit * hb, int redraw)
-{
-	int mypos,
-	  epos,
-	  spos;
-	GdkGC *gc = html->gc;
-	int shift;
-	GtkStateType selected_state;
-	GtkWidget *widget = GTK_WIDGET(html);
-	GdkRectangle area;
-	GList *hbits;
-	
-	if (html->frozen > 0)
-		return;
-
-	hbits = g_list_find(html->html_bits, hb);
-	
-	if (hb->type == HTML_BIT_TEXT)
-	{
-
-		if (!(hb->text))
-			return;
-		/* this is possible, don't comment it out >:P */
-		if (!strlen(hb->text))
-			return;
-
-		mypos = g_list_index(html->html_bits, hb);
-		epos = g_list_index(html->html_bits, html->end_sel);
-		spos = g_list_index(html->html_bits, html->start_sel);
-
-		if (((html->end_sel == NULL) || (html->start_sel == NULL)) ||
-			((epos < mypos) && (spos < mypos)) ||
-			((epos > mypos) && (spos > mypos)))
-		{
-			selected_state = GTK_STATE_NORMAL;
-		}
-		else
-		{
-			selected_state = GTK_STATE_SELECTED;
-		}
-
-		gdk_text_extents(hb->font, hb->text, 1, &shift, NULL, NULL, NULL, NULL);
-
-		if (selected_state == GTK_STATE_SELECTED)
-		{
-			int schar = 0,
-			  echar = 0;
-			int startx = 0,
-			  xwidth = 0;
-
-			if (epos > spos ||
-				(epos == spos && html->num_end >= html->num_start))
-			{
-				if (mypos == epos)
-				{
-					echar = html->num_end;
-					xwidth =
-						gdk_text_width(hb->font, hb->text, html->num_end + 1);
-				}
-				else
-				{
-					echar = strlen(hb->text);
-					xwidth = hb->width;
-				}
-				if (mypos == spos)
-				{
-					schar = html->num_start;
-					startx =
-						gdk_text_width(hb->font, hb->text, html->num_start);
-					xwidth -= startx;
-				}
-			}
-			else
-			{
-				if (mypos == spos)
-				{
-					echar = html->num_start;
-					xwidth =
-						gdk_text_width(hb->font, hb->text,
-										 html->num_start + 1);
-				}
-				else
-				{
-					echar = strlen(hb->text);
-					xwidth = hb->width;
-				}
-				if (mypos == epos)
-				{
-					schar = html->num_end;
-					startx =
-						gdk_text_width(hb->font, hb->text, html->num_end);
-					xwidth -= startx;
-				}
-			}
-
-			if (!redraw && echar == hb->sel_e && schar == hb->sel_s)
-				return;
-
-			hb->sel_e = echar;
-			hb->sel_s = schar;
-
-			startx += hb->x;
-
-			area.x = hb->x - html->xoffset;
-			area.y = hb->y - hb->height + 3 - html->yoffset;
-			area.width = hb->width + 2;
-			area.height = hb->height;
-			clear_area(html, &area);
-
-			gtk_paint_flat_box(widget->style, html->html_area,
-							   selected_state, GTK_SHADOW_NONE,
-							   NULL, widget, "text",
-							   startx,
-							   hb->y - hb->height + 3 - html->yoffset,
-							   xwidth + 2, hb->height);
-			hb->was_selected = 1;
-		}
-		else if (hb->was_selected)
-		{
-			area.x = hb->x - html->xoffset;
-			area.y = hb->y - hb->height + 3 - html->yoffset;
-			area.width = hb->width + 2;
-			area.height = hb->height;
-			clear_area(html, &area);
-
-			hb->sel_e = -1;
-			hb->sel_s = -1;
-
-			hb->was_selected = 0;
-		}
-
-		if (selected_state == GTK_STATE_SELECTED && (mypos == epos
-													 || mypos == spos))
-		{
-			char *s = hb->text;
-			int num = 0,
-			  width = 0,
-			  fsel = 0,
-			  esel = strlen(hb->text);
-			int lbearing,
-			  rbearing,
-			  w;
-
-			if (epos > spos ||
-				(epos == spos && html->num_end >= html->num_start))
-			{
-				if (mypos == epos)
-					esel = html->num_end;
-				if (mypos == spos)
-					fsel = html->num_start;
-			}
-			else
-			{
-				if (mypos == spos)
-					esel = html->num_start;
-				if (mypos == epos)
-					fsel = html->num_end;
-			}
-
-			while (*s)
-			{
-
-				if (num < fsel || num > esel)
-					selected_state = GTK_STATE_NORMAL;
-				else
-					selected_state = GTK_STATE_SELECTED;
-				if (hb->fore != NULL)
-					gdk_gc_set_foreground(gc, hb->fore);
-				else
-					gdk_gc_set_foreground(gc,
-										  &widget->style->fg[selected_state]);
-
-				gdk_gc_set_font(gc, hb->font);
-
-				gdk_text_extents(hb->font, s, 1, &lbearing, &rbearing, &w, NULL,
-								 NULL);
-
-				gdk_draw_text(html->html_area, hb->font, gc,
-							  shift + hb->x + width, hb->y - html->yoffset, s,
-							  1);
-
-				if (hb->uline)
-					gdk_draw_line(html->html_area, gc, shift + hb->x + width,
-								  hb->y - html->yoffset,
-								  shift + hb->x + width + w,
-								  hb->y - html->yoffset);
-
-				if (hb->strike)
-					gdk_draw_line(html->html_area, gc, shift + hb->x + width,
-								  hb->y - html->yoffset - (hb->height / 3),
-								  shift + hb->x + width + w,
-								  hb->y - html->yoffset - (hb->height / 3));
-
-				width += w;
-
-				s++;
-				num++;
-			}
-
-
-		}
-		else
-		{
-			/*my stuff here*/
-			
-			if(!hb->was_selected)
-			{
-				area.x = hb->x - html->xoffset;
-				area.y = hb->y - hb->height + 3 - html->yoffset;
-				area.width = hb->width + 2;
-				area.height = hb->height;
-				clear_area(html, &area);
-			}
-
-			/*end my stuff*/
-
-			if (hb->text && hb->back != NULL) {
-				int hwidth, hheight, hei, tmpcnt;
-				hei = get_line_height(html, hb);
-				gdk_window_get_size(html->html_area, &hwidth, &hheight);
-				gdk_gc_set_foreground(gc, hb->back);
-				/* we use a 2-pixel window border */
-				if (hb->x < 2)
-					hb->x = 2;
-				gdk_draw_rectangle(html->html_area, gc, TRUE /* filled */,
-							hb->x, hb->y - html->yoffset - hei - 6,
-							hwidth - shift - hb->x + 1, hei + hei + 2);
-				for (tmpcnt = 1; tmpcnt < hb->newline; tmpcnt++) {
-					int eoff = hei + hei + 2;
-					eoff *= tmpcnt;
-					gdk_draw_rectangle(html->html_area, gc, TRUE,
-							2, hb->y - html->yoffset - hei - 6 + eoff,
-							hwidth, hei + hei + 2);
-				}
-			}
-
-			if (hb->fore != NULL)
-				gdk_gc_set_foreground(gc, hb->fore);
-			else
-				gdk_gc_set_foreground(gc, &widget->style->fg[selected_state]);
-
-			gdk_gc_set_font(gc, hb->font);
-
-			gdk_draw_string(html->html_area, hb->font, gc, shift + hb->x,
-							hb->y - html->yoffset, hb->text);
-			if (hb->uline)
-				gdk_draw_line(html->html_area, gc, shift + hb->x,
-							  hb->y - html->yoffset,
-							  hb->x + gdk_string_measure(hb->font, hb->text),
-							  hb->y - html->yoffset);
-
-			if (hb->strike)
-				gdk_draw_line(html->html_area, gc, shift + hb->x,
-							  hb->y - html->yoffset - (hb->height / 3),
-							  hb->x + gdk_string_measure(hb->font, hb->text),
-							  hb->y - html->yoffset - (hb->height / 3));
-
-		}
-	}
-	else if (hb->type == HTML_BIT_SEP)
-	{
-		if (hb->back != NULL) {
-			int hwidth, hheight, hei, tmpcnt;
-			hei = get_line_height(html, hb);
-			gdk_window_get_size(html->html_area, &hwidth, &hheight);
-			gdk_gc_set_foreground(gc, hb->back);
-			gdk_draw_rectangle(html->html_area, gc, TRUE,
-						2, hb->y - html->yoffset,
-						hwidth, 5);
-			for (tmpcnt = 0; tmpcnt < hb->newline; tmpcnt++) {
-				int eoff = hei + hei + 2;
-				eoff *= tmpcnt;
-				eoff += 5;
-				gdk_draw_rectangle(html->html_area, gc, TRUE,
-						2, hb->y - html->yoffset + eoff,
-						hwidth, hei + hei + 2);
-			}
-		}
-
-		if (hb->fore != NULL)
-			gdk_gc_set_foreground(gc, hb->fore);
-		else
-			gdk_gc_set_foreground(gc, &widget->style->fg[GTK_STATE_NORMAL]);
-
-		gdk_draw_line(html->html_area, gc, hb->x + 2,
-					  hb->y - html->yoffset - (hb->height / 2 - 1),
-					  hb->x + hb->width,
-					  hb->y - html->yoffset - (hb->height / 2 - 1));
-
-	}
-	else if (hb->type == HTML_BIT_PIXMAP)
-	{
-		area.x = hb->x - html->xoffset;
-		area.y = hb->y - hb->height + 5 - html->yoffset;
-		area.width = hb->width;
-		area.height = hb->height;
-		clear_area(html, &area);
-		if (hb->back != NULL) {
-			int hwidth, hheight, hei, tmpcnt;
-			hei = get_line_height(html, hb);
-			gdk_window_get_size(html->html_area, &hwidth, &hheight);
-			gdk_gc_set_foreground(gc, hb->back);
-			for (tmpcnt = 0; tmpcnt < hb->newline; tmpcnt++) {
-				int eoff = hei + hei + 2;
-				eoff *= tmpcnt;
-				eoff += 5;
-				gdk_draw_rectangle(html->html_area, gc, TRUE,
-						2, hb->y - html->yoffset + eoff,
-						hwidth, hei + hei + 2);
-			}
-		}
-
-		if (hb->fore != NULL)
-			gdk_gc_set_foreground(gc, hb->fore);
-		else
-			gdk_gc_set_foreground(gc, &widget->style->fg[GTK_STATE_NORMAL]);
-
-		gdk_draw_pixmap(html->html_area, gc, hb->pm, 0, 0, hb->x,
-						hb->y - html->yoffset - (hb->height) + 4, -1, -1);
-	}
-}
-
-
-
-gint compare_types(GtkHtmlBit * hb, GtkHtmlBit * hb2)
-{
-	/*
-	 * In this function, it's OK to accidently return a
-	 * * 0, but will cause problems on an accidental 1 
-	 */
-
-	if (!hb || !hb2)
-		return 0;
-
-
-	if (hb->uline != hb2->uline)
-		return 0;
-	if (hb->strike != hb2->strike)
-		return 0;
-	if (hb->font && hb2->font)
-	{
-		if (!gdk_font_equal(hb->font, hb2->font))
-			return 0;
-	}
-	else if (hb->font && !hb2->font)
-	{
-		return 0;
-	}
-	else if (!hb->font && hb2->font)
-	{
-		return 0;
-	}
-	if (hb->type != hb2->type)
-		return 0;
-
-	if (hb->fore && hb2->fore)
-	{
-		if (!gdk_color_equal(hb->fore, hb2->fore))
-			return 0;
-	}
-	else if (hb->fore && !hb2->fore)
-	{
-		return 0;
-	}
-	else if (!hb->fore && hb2->fore)
-	{
-		return 0;
-	}
-
-	if (hb->back && hb2->back)
-	{
-		if (!gdk_color_equal(hb->back, hb2->back))
-			return 0;
-	}
-	else if (hb->back && !hb2->back)
-	{
-		return 0;
-	}
-	else if (!hb->back && hb2->back)
-	{
-		return 0;
-	}
-
-	if ((hb->url != NULL && hb2->url == NULL) ||
-		(hb->url == NULL && hb2->url != NULL))
-		return 0;
-
-	if (hb->url != NULL && hb2->url != NULL)
-		if (strcasecmp(hb->url, hb2->url))
-			return 0;
-
-	return 1;
-}
-
-static gint html_bit_is_onscreen(GtkHtml * html, GtkHtmlBit * hb)
-{
-	gint width,
-	  height;
-
-	gdk_window_get_size(html->html_area, &width, &height);
-
-	if (hb->y < html->yoffset)
-	{
-		return 0;
-	}
-
-	if ((hb->y - hb->height) > (html->yoffset + height))
-	{
-		return 0;
-	}
-	return 1;
-}
-
-static void draw_cursor(GtkHtml * html)
-{
-	if (html->editable &&
-		html->cursor_hb &&
-		GTK_WIDGET_DRAWABLE(html) &&
-		html_bit_is_onscreen(html, html->cursor_hb))
-	{
-		gint x,
-		  y;
-		gint width;
-
-		GdkFont *font = html->cursor_hb->font;
-
-		gdk_text_extents(font, html->cursor_hb->text, html->cursor_pos, NULL,
-						 NULL, &width, NULL, NULL);
-
-		gdk_gc_set_foreground(html->gc,
-							  &GTK_WIDGET(html)->style->text[GTK_STATE_NORMAL]);
-
-		y = html->cursor_hb->y - html->yoffset;
-		x = html->cursor_hb->x + width;
-
-
-		gdk_draw_line(html->html_area, html->gc, x, y, x, y - font->ascent);
-
-	}
-}
-
-static void undraw_cursor(GtkHtml * html)
-{
-	if (html->editable &&
-		html->cursor_hb &&
-		GTK_WIDGET_DRAWABLE(html) &&
-		html_bit_is_onscreen(html, html->cursor_hb))
-	{
-		gint x,
-		  y;
-		gint width;
-		GdkRectangle area;
-
-		GdkFont *font = html->cursor_hb->font;
-
-		gdk_text_extents(font, html->cursor_hb->text, html->cursor_pos, NULL,
-						 NULL, &width, NULL, NULL);
-
-		y = html->cursor_hb->y - html->yoffset;
-		x = html->cursor_hb->x + width;
-
-		area.x = x;
-		area.y = y - font->ascent;
-		area.height = font->ascent + 1;
-		area.width = 1;
-
-
-		clear_area(html, &area);
-
-		gtk_html_draw_bit(html, html->cursor_hb, 1);
-
-
-	}
-}
-
-
-static void expose_html(GtkHtml * html, GdkRectangle * area, gboolean cursor)
-{
-	GList *hbits;
-	GtkHtmlBit *hb;
-	gint width,
-	  height;
-	gint realy;
-
-
-	if (html->frozen > 0)
-		return;
-
-
-	hbits = html->html_bits;
-
-	gdk_window_get_size(html->html_area, &width, &height);
-
-	realy = area->y + html->yoffset;
-
-	/* this is needed since background colors draw across the entire window width
-		if anyone knows of a cleaner way to work bg colors, please submit code =) */
-	area->x = 0;
-	area->width = width;
-	
-	clear_area(html, area);
-
-	while (hbits)
-	{
-
-		hb = (GtkHtmlBit *) hbits->data;
-
-		if (html_bit_is_onscreen(html, hb))
-			gtk_html_draw_bit(html, hb, 1);
-
-
-		hbits = hbits->next;
-	}
-}
-
-static void resize_html(GtkHtml * html)
-{
-	GList *hbits = html->html_bits;
-	GList *html_bits = html->html_bits;
-	GtkHtmlBit *hb,
-	 *hb2;
-	char *str;
-	gint height;
-
-	if (!hbits)
-		return;
-
-
-	html->html_bits = NULL;
-
-	html->current_x = 0;
-	html->current_y = 0;
-
-	html->vadj->upper = 0;
-
-	gtk_html_freeze(html);
-
-	while (hbits)
-	{
-		hb = (GtkHtmlBit *) hbits->data;
-		if (hb->type == HTML_BIT_SEP)
-		{
-
-			gtk_html_add_seperator(html, hb->font, hb->fore, hb->back);
-
-			g_free(hb);
-
-			hbits = hbits->next;
-			continue;
-		}
-		if (hb->type == HTML_BIT_PIXMAP)
-		{
-
-			gtk_html_add_pixmap(html, hb->pm, hb->fit, hb->newline);
-
-			g_free(hb);
-
-			hbits = hbits->next;
-			continue;
-		}
-
-		if (hb->newline)
-		{
-			int i;
-
-			if (!hb->text)
-			{
-				hb->text = g_malloc(1);
-				hb->text[0] = 0;
-			}
-			for (i = 0; i < hb->newline; i++)
-			{
-				str = hb->text;
-				hb->text = g_strconcat(str, "\n", NULL);
-				if (str) g_free(str);
-			}
-		}
-
-		if (hbits->next)
-		{
-			hb2 = (GtkHtmlBit *) hbits->next->data;
-		}
-		else
-		{
-			hb2 = NULL;
-		}
-
-
-
-		if (!hb->newline && compare_types(hb, hb2))
-		{
-			str = hb2->text;
-			hb2->text = g_strconcat(hb->text, hb2->text, NULL);
-			if (str) g_free(str);
-			hb2 = NULL;
-		}
-		else if (hb->text)
-		{
-			gtk_html_add_text(html, hb->font, hb->fore, hb->back,
-							  hb->text, strlen(hb->text), hb->uline, hb->strike,
-							  hb->url);
-		}
-
-
-
-		/*
-		 * Font stays, so do colors (segfaults if I free) 
-		 */
-		if (hb->fore)
-			gdk_color_free(hb->fore);
-		if (hb->back)
-			gdk_color_free(hb->back);
-		if (hb->text)
-			g_free(hb->text);
-		if (hb->url)
-			g_free(hb->url);
-
-		g_free(hb);
-
-		hbits = hbits->next;
-	}
-
-	g_list_free(html_bits);
-
-
-	gtk_html_thaw(html);
-
-	gdk_window_get_size(html->html_area, NULL, &height);
-	gtk_adjustment_set_value(html->vadj, html->vadj->upper - height);
-
-}
-
-static GdkGC *create_bg_gc(GtkHtml * html)
-{
-	GdkGCValues values;
-
-	values.tile = GTK_WIDGET(html)->style->bg_pixmap[GTK_STATE_NORMAL];
-	values.fill = GDK_TILED;
-
-	return gdk_gc_new_with_values(html->html_area, &values,
-								  GDK_GC_FILL | GDK_GC_TILE);
-}
-
-static void clear_area(GtkHtml * html, GdkRectangle * area)
-{
-	GtkWidget *widget = GTK_WIDGET(html);
-	gint x,
-	  y;
-
-
-	if (html->transparent)
-	{
-		if (html->pm == NULL)
-			html->pm = get_desktop_pixmap(widget);
-
-		if (html->pm == NULL)
-			return;
-
-		if (html->bg_gc == NULL)
-		{
-			GdkGCValues values;
-
-			values.tile = html->pm;
-			values.fill = GDK_TILED;
-
-			html->bg_gc = gdk_gc_new_with_values(html->html_area, &values,
-												 GDK_GC_FILL | GDK_GC_TILE);
-
-		}
-
-		gdk_window_get_deskrelative_origin(html->html_area, &x, &y);
-
-		gdk_draw_pixmap(html->html_area, html->bg_gc, html->pm,
-						x + area->x, y + area->y, area->x, area->y, area->width,
-						area->height);
-
-		return;
-
-	}
-	if (html->bg_gc)
-	{
-
-		gint width,
-		  height;
-
-		gdk_window_get_size(widget->style->bg_pixmap[GTK_STATE_NORMAL], &width,
-							&height);
-
-		gdk_gc_set_ts_origin(html->bg_gc,
-							 (-html->xoffset) % width,
-							 (-html->yoffset) % height);
-
-		gdk_draw_rectangle(html->html_area, html->bg_gc, TRUE,
-						   area->x, area->y, area->width, area->height);
-	}
-	else
-		gdk_window_clear_area(html->html_area, area->x, area->y, area->width,
-							  area->height);
-}
-
-
-
-
-static void gtk_html_destroy(GtkObject * object)
-{
-	GtkHtml *html;
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(GTK_IS_HTML(object));
-
-	html = (GtkHtml *) object;
-
-
-	gtk_signal_disconnect_by_data(GTK_OBJECT(html->hadj), html);
-	gtk_signal_disconnect_by_data(GTK_OBJECT(html->vadj), html);
-
-	if (html->timer)
-	{
-		gtk_timeout_remove(html->timer);
-		html->timer = 0;
-	}
-
-	if (html->tooltip_timer)
-	{
-		gtk_timeout_remove(html->tooltip_timer);
-		html->tooltip_timer = -1;
-	}
-
-
-	GTK_OBJECT_CLASS(parent_class)->destroy(object);
-
-}
-
-static void gtk_html_finalize(GtkObject * object)
-{
-	GList *hbits;
-	GtkHtml *html;
-	GtkHtmlBit *hb;
-
-
-	g_return_if_fail(object != NULL);
-	g_return_if_fail(GTK_IS_HTML(object));
-
-	html = (GtkHtml *) object;
-
-	gtk_object_unref(GTK_OBJECT(html->hadj));
-	gtk_object_unref(GTK_OBJECT(html->vadj));
-
-	hbits = html->html_bits;
-
-	while (hbits)
-	{
-		hb = (GtkHtmlBit *) hbits->data;
-		if (hb->fore)
-			gdk_color_free(hb->fore);
-		if (hb->back)
-			gdk_color_free(hb->back);
-		if (hb->text)
-			g_free(hb->text);
-		if (hb->url)
-			g_free(hb->url);
-		if (hb->pm)
-			gdk_pixmap_unref(hb->pm);
-
-		g_free(hb);
-		hbits = hbits->next;
-	}
-	if (html->html_bits)
-		g_list_free(html->html_bits);
-
-	if (html->urls)
-		g_list_free(html->urls);
-
-	if (html->selected_text)
-		g_free(html->selected_text);
-
-	if (html->gc)
-		gdk_gc_destroy(html->gc);
-
-	if (html->bg_gc)
-		gdk_gc_destroy(html->bg_gc);
-
-	if (html->tooltip_window)
-		gtk_widget_destroy(html->tooltip_window);
-
-	GTK_OBJECT_CLASS(parent_class)->finalize(object);
-}
-
-static void gtk_html_realize(GtkWidget * widget)
-{
-	GtkHtml *html;
-	GdkWindowAttr attributes;
-	gint attributes_mask;
-
-	g_return_if_fail(widget != NULL);
-	g_return_if_fail(GTK_IS_HTML(widget));
-
-	html = GTK_HTML(widget);
-	GTK_WIDGET_SET_FLAGS(html, GTK_REALIZED);
-
-	attributes.window_type = GDK_WINDOW_CHILD;
-	attributes.x = widget->allocation.x;
-	attributes.y = widget->allocation.y;
-	attributes.width = widget->allocation.width;
-	attributes.height = widget->allocation.height;
-	attributes.wclass = GDK_INPUT_OUTPUT;
-	attributes.visual = gtk_widget_get_visual(widget);
-	attributes.colormap = gtk_widget_get_colormap(widget);
-	attributes.event_mask = gtk_widget_get_events(widget);
-	attributes.event_mask |= (GDK_EXPOSURE_MASK |
-							  GDK_BUTTON_PRESS_MASK |
-							  GDK_BUTTON_RELEASE_MASK |
-							  GDK_BUTTON_MOTION_MASK |
-							  GDK_ENTER_NOTIFY_MASK |
-							  GDK_LEAVE_NOTIFY_MASK |
-							  GDK_POINTER_MOTION_MASK |
-							  GDK_POINTER_MOTION_HINT_MASK |
-							  GDK_VISIBILITY_NOTIFY_MASK | GDK_KEY_PRESS_MASK);
-
-	attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-
-	widget->window =
-		gdk_window_new(gtk_widget_get_parent_window(widget), &attributes,
-					   attributes_mask);
-	gdk_window_set_user_data(widget->window, html);
-
-	attributes.x = (widget->style->klass->xthickness + BORDER_WIDTH);
-	attributes.y = (widget->style->klass->ythickness + BORDER_WIDTH);
-	attributes.width =
-		MAX(1, (gint) widget->allocation.width - (gint) attributes.x * 2);
-	attributes.height =
-		MAX(1, (gint) widget->allocation.height - (gint) attributes.y * 2);
-
-	html->html_area =
-		gdk_window_new(widget->window, &attributes, attributes_mask);
-	gdk_window_set_user_data(html->html_area, html);
-
-	widget->style = gtk_style_attach(widget->style, widget->window);
-
-	/*
-	 * Can't call gtk_style_set_background here because it's handled specially 
-	 */
-	gdk_window_set_background(widget->window,
-							  &widget->style->base[GTK_STATE_NORMAL]);
-	gdk_window_set_background(html->html_area,
-							  &widget->style->base[GTK_STATE_NORMAL]);
-
-	if (widget->style->bg_pixmap[GTK_STATE_NORMAL])
-		html->bg_gc = create_bg_gc(html);
-
-	html->gc = gdk_gc_new(html->html_area);
-	gdk_gc_set_exposures(html->gc, TRUE);
-	gdk_gc_set_foreground(html->gc, &widget->style->text[GTK_STATE_NORMAL]);
-
-	gdk_window_show(html->html_area);
-
-}
-
-static void gtk_html_style_set(GtkWidget * widget, GtkStyle * previous_style)
-{
-	GtkHtml *html;
-
-	g_return_if_fail(widget != NULL);
-	g_return_if_fail(GTK_IS_HTML(widget));
-
-	html = GTK_HTML(widget);
-	if (GTK_WIDGET_REALIZED(widget))
-	{
-		gdk_window_set_background(widget->window,
-								  &widget->style->base[GTK_STATE_NORMAL]);
-		gdk_window_set_background(html->html_area,
-								  &widget->style->base[GTK_STATE_NORMAL]);
-
-		if (html->bg_gc)
-		{
-			gdk_gc_destroy(html->bg_gc);
-			html->bg_gc = NULL;
-		}
-
-		if (widget->style->bg_pixmap[GTK_STATE_NORMAL])
-		{
-			html->bg_gc = create_bg_gc(html);
-		}
-
-	}
-}
-
-static void gtk_html_unrealize(GtkWidget * widget)
-{
-	GtkHtml *html;
-
-	g_return_if_fail(widget != NULL);
-	g_return_if_fail(GTK_IS_HTML(widget));
-
-	html = GTK_HTML(widget);
-
-	gdk_window_set_user_data(html->html_area, NULL);
-	gdk_window_destroy(html->html_area);
-	html->html_area = NULL;
-
-	gdk_gc_destroy(html->gc);
-	html->gc = NULL;
-
-	if (html->bg_gc)
-	{
-		gdk_gc_destroy(html->bg_gc);
-		html->bg_gc = NULL;
-	}
-
-	if (GTK_WIDGET_CLASS(parent_class)->unrealize)
-		(*GTK_WIDGET_CLASS(parent_class)->unrealize) (widget);
-}
-
-
-void gtk_html_add_pixmap(GtkHtml * html, GdkPixmap * pm, int fit, int newline)
-{
-	GtkHtmlBit *last_hb;
-	GtkHtmlBit *hb = g_new0(GtkHtmlBit, 1);
-	GdkWindowPrivate *private = (GdkWindowPrivate *) pm;
-	int width, height;
-
-	last_hb = (GtkHtmlBit *) g_list_last(html->html_bits)->data;
-
-	/* wrap pixmaps */
-	gdk_window_get_size(html->html_area, &width, &height);
-	if ((html->current_x + private->width) >= width) {
-		html->current_x = 0;
-	}
-			
-	hb->fit = fit;
-	html->current_x += 2;
-	hb->x = html->current_x;
-	hb->y = html->current_y;
-	if (fit)
-		hb->height = last_hb->height;
-	else
-		hb->height = private->height;
-	hb->type = HTML_BIT_PIXMAP;
-	hb->width = private->width;
-	hb->text = NULL;
-	hb->url = NULL;
-	if (last_hb->fore) hb->fore = gdk_color_copy(last_hb->fore);
-	else hb->fore = NULL;
-	if (last_hb->back) hb->back = gdk_color_copy(last_hb->back);
-	else hb->back = NULL;
-	hb->font = last_hb->font;
-	hb->uline = 0;
-	hb->strike = 0;
-	hb->was_selected = 0;
-	hb->newline = newline;
-	hb->pm = pm;
-
-	if (html->current_x == BORDER_WIDTH)
-	{
-		html->current_y += hb->height + 3;
-		hb->y += hb->height + 3;
-	}
-
-
-	html->current_x += hb->width + 1;
-
-	gtk_html_draw_bit(html, hb, 1);
-
-	if (hb->newline)
-		html->current_x = 0;
-
-	html->html_bits = g_list_append(html->html_bits, hb);
-
-
-}
-
-static void gtk_html_add_seperator(GtkHtml * html, GdkFont *font, GdkColor *fore, GdkColor *back)
-{
-	GtkHtmlBit *hb = g_new0(GtkHtmlBit, 1);
-	gint width,
-	  height;
-
-	html->current_x = 0;
-	html->current_y += 5;
-
-	gdk_window_get_size(html->html_area, &width, &height);
-
-	hb->x = html->current_x;
-	hb->y = html->current_y;
-	hb->height = 5;
-	hb->type = HTML_BIT_SEP;
-	hb->width =
-		width -
-		GTK_SCROLLED_WINDOW(GTK_WIDGET(html)->parent)->vscrollbar->allocation.
-		width - 10;
-	hb->text = NULL;
-	hb->url = NULL;
-	if (fore)
-		hb->fore = gdk_color_copy(fore);
-	else
-		hb->fore = NULL;
-	
-	if (back)
-		hb->back = gdk_color_copy(back);
-	else
-		hb->back = NULL;
-	hb->font = font;
-	hb->uline = 0;
-	hb->strike = 0;
-	hb->was_selected = 0;
-	hb->newline = 0;
-	hb->pm = NULL;
-
-	gtk_html_draw_bit(html, hb, 1);
-
-	html->html_bits = g_list_append(html->html_bits, hb);
-
-}
-
-static void gtk_html_add_text(GtkHtml * html,
-							  GdkFont * cfont,
-							  GdkColor * fore,
-							  GdkColor * back,
-							  char *chars,
-							  gint length, gint uline, gint strike, char *url)
-{
-	char *nextline = NULL,
-	 *c,
-	 *text,
-	 *tmp;
-	GdkGC *gc;
-	int nl = 0,
-	  nl2 = 0;
-	int maxwidth;
-	gint lb;
-	GList *hbits;
-	size_t num = 0;
-	int i,
-	  height;
-	GtkHtmlBit *hb;
-	gint hwidth,
-	  hheight;
-
-	if (length == 1 && chars[0] == '\n')
-	{
-		GtkHtmlBit *h;
-		hbits = g_list_last(html->html_bits);
-		if (!hbits)
-			return;
-		/*
-		 * I realize this loses a \n sometimes
-		 * * if it's the first thing in the widget.
-		 * * so fucking what. 
-		 */
-
-		h = (GtkHtmlBit *) hbits->data;
-		h->newline++;
-		if (html->current_x > 0)
-			html->current_x = 0;
-		else
-			html->current_y += cfont->ascent + cfont->descent + 5;
-		return;
-	}
-
-
-
-	c = text = g_malloc(length + 2);
-	strncpy(text, chars, length);
-	text[length] = 0;
-
-
-	gc = html->gc;
-
-	if (gc == NULL)
-		gc = html->gc = gdk_gc_new(html->html_area);
-
-	gdk_gc_set_font(gc, cfont);
-
-
-	while (*c)
-	{
-		if (*c == '\n')
-		{
-			if (*(c + 1) == '\0')
-			{
-				nl = 1;
-				length--;
-				c[0] = '\0';
-				break;
-			}
-			if (*c)
-			{
-				gtk_html_add_text(html, cfont, fore, back, text, num + 1, uline,
-								  strike, url);
-				tmp = text;
-				length -= (num + 1);
-				text = g_malloc(length + 2);
-				strncpy(text, (c + 1), length);
-				text[length] = 0;
-				c = text;
-				num = 0;
-				g_free(tmp);
-				continue;
-			}
-		}
-
-		num++;
-		c++;
-	}
-
-	/*
-	 * Note, yG is chosen because G is damn high, and y is damn low, 
-	 */
-	/*
-	 * it should be just fine. :) 
-	 */
-
-	gdk_window_get_size(html->html_area, &hwidth, &hheight);
-
-	num = strlen(text);
-
-	while (GTK_WIDGET(html)->allocation.width < 20)
-	{
-		while (gtk_events_pending())
-			gtk_main_iteration();
-	}
-
-	maxwidth = (hwidth - html->current_x - 8);
-	/*
-	 * HTK_SCROLLED_WINDOW(GTK_WIDGET(layout)->parent)->vscrollbar->allocation.width) - 8; 
-	 */
-
-	if ((maxwidth == (hwidth - 8) && gdk_text_measure(cfont, text, num) > 2 * maxwidth) ||
-	    gdk_text_measure(cfont, text, num) < 0) {
-		int pos = num / 2;
-		static int count = 0;
-		count ++;
-		while (pos < num && (!isspace(text[pos]) || text[pos] == '\n')) pos++;
-		if (pos >= num - 1) {
-			pos = num/2;
-			while (pos > 0 && (!isspace(text[pos]) || text[pos] == '\n')) pos--;
-			if (!pos) pos = num / 2;
-		}
-		gtk_html_add_text(html, cfont, fore, back, text, pos + 1, uline, strike, url);
-		gtk_html_add_text(html, cfont, fore, back, &text[pos+1], 1, uline, strike, url);
-		gtk_html_add_text(html, cfont, fore, back, &text[pos+2], num - pos + 1, uline, strike, url);
-		g_free(text);
-		count--;
-		if (!count) {
-			/* FIXME : sometimes we need to add newline, sometimes we don't */
-			hbits = g_list_last(html->html_bits);
-			if (!hbits) return; /* does this ever happen? */
-			hb = (GtkHtmlBit *)hbits->data;
-			hb->newline++;
-		}
-		return;
-	}
-
-	while (gdk_text_measure(cfont, text, num) > maxwidth)
-	{
-		if (num > 1)
-			num--;
-		else
-		{
-			if (html->current_x != 0) {
-				html->current_x = 0;
-				if (nl) {
-					text[length] = '\n';
-					length++;
-				}
-				gtk_html_add_text(html, cfont, fore, back, text, length, uline, strike, url);
-				g_free(text);
-				return;
-			} else {
-				num = strlen (text);
-				break;
-			}
-		}
-
-	}
-
-	height = cfont->ascent + cfont->descent + 2;
-
-
-	if ((int) (html->vadj->upper - html->current_y) < (int) (height * 2))
-	{
-		int val;
-		val = (height * 2) + html->current_y;
-		html->vadj->upper = val;
-		adjust_adj(html, html->vadj);
-	}
-
-
-	if (html->current_x == 0)
-	{
-		html->current_y += height + 3;
-		gdk_text_extents(cfont, text, 1, &lb, NULL, NULL, NULL, NULL);
-		html->current_x += (2 - lb);
-	}
-	else if ((hbits = g_list_last(html->html_bits)) != NULL)
-	{
-		int diff,
-		  y;
-		hb = (GtkHtmlBit *) hbits->data;
-		if (height > hb->height)
-		{
-			diff = height - hb->height;
-			y = hb->y;
-			html->current_y += diff;
-			while (hbits)
-			{
-				hb = (GtkHtmlBit *) hbits->data;
-				if (hb->y != y)
-					break;
-				if (hb->type != HTML_BIT_PIXMAP)
-					hb->height = height;
-				hb->y += diff;  ////////////my thing here /////////////////
-				gtk_html_draw_bit(html, hb, FALSE);
-
-				hbits = hbits->prev;
-			}
-		}
-	}
-
-
-
-
-	if (num != strlen(text))
-	{
-		/*
-		 * This is kinda cheesy but it may make things
-		 * * much better lookin 
-		 */
-
-		for (i=2; (num > i); i++) {
-			if (text[num - i] == ' ') {
-				num = num - (i - 1);
-				nl2 = 1;
-				break;
-			}
-		}
-
-		nextline = g_malloc(length - num + 2);
-		strncpy(nextline, (char *) (text + num), length - num);
-		nextline[length - num] = 0;
-		if (nl)
-		{
-			nextline[length - num] = '\n';
-			nextline[length - num + 1] = 0;
-			nl = 0;
-		}
-
-
-		text[num] = 0;
-	}
-
-
-	if (url != NULL) {
-		fore = get_color(3355647, gdk_window_get_colormap(html->html_area));
-	}
-
-	hb = g_new0(GtkHtmlBit, 1);
-
-	hb->text = g_strdup(text);
-
-	if (fore)
-		hb->fore = gdk_color_copy(fore);
-	else
-		hb->fore = NULL;
-	
-	if (back)
-		hb->back = gdk_color_copy(back);
-	else
-		hb->back = NULL;
-	hb->font = cfont;
-	hb->uline = uline;
-	hb->strike = strike;
-	hb->height = height;
-	gdk_text_extents(cfont, text, num, &lb, NULL, &hb->width, NULL, NULL);
-	hb->x = html->current_x;
-	hb->y = html->current_y;
-	hb->type = HTML_BIT_TEXT;
-	hb->pm = NULL;
-	if (url != NULL)
-	{
-		uline = 1;
-		hb->uline = 1;
-		hb->url = g_strdup(url);
-	}
-	else
-	{
-		hb->url = NULL;
-	}
-	html->current_x += hb->width;
-
-	html->html_bits = g_list_append(html->html_bits, hb);
-	if (url != NULL)
-	{
-		html->urls = g_list_append(html->urls, hb);
-	}
-
-
-
-	gtk_html_draw_bit(html, hb, 1);
-
-	if (nl || nl2)
-	{
-		if (nl)
-			hb->newline = 1;
-		html->current_x = 0;
-	}
-	else
-		hb->newline = 0;
-
-
-	if (nextline != NULL)
-	{
-		gtk_html_add_text(html, cfont, fore, back, nextline, strlen(nextline),
-						  uline, strike, url);
-		g_free(nextline);
-	}
-
-	g_free(text);
-	if (url != NULL)
-		g_free(fore);
-}
-
-static char * html_strtok( char * input, char delim )
-{
-	static char * end;
-	static char * curr_offset;
-	int i;
-	int num_quotes=0;
-
-	if( input != NULL)
-	{
-		curr_offset = input;
-		end = input+strlen(input);
-	}
-	else
-	{
-		if( curr_offset + strlen(curr_offset) < end )
-		{
-			curr_offset += strlen(curr_offset) + 1;
-		}
-		else
-		{
-			return NULL;
-		}
-	}
-	for( i=0; curr_offset+i < end && 
-			  (curr_offset[i] != delim || num_quotes != 0)
-		  ; i++ )
-	{
-		if( curr_offset[i] == '\"' )
-		{
-			num_quotes = (num_quotes+1)%2;
-		}
-	}
-	curr_offset[i] = '\0';
-	return curr_offset;
-}
-
-
-void gtk_html_append_text(GtkHtml * html, char *text, gint options)
-{
-	GdkColormap *map;
-	GdkFont *cfont;
-	GdkRectangle area;
-	char *ws,
-	  *tag,
-	 *c,
-	 *url = NULL;
-	gint intag = 0,
-	  wpos = 0,
-	  tpos = 0;
-	static gint colorv,
-	  bold = 0,
-	  italic = 0,
-	  fixed = 0,
-	  uline = 0,
-	  strike = 0,
-	  title = 0,
-	  height;
-	static struct font_state *current = NULL,
-	 *tmp;
-	static struct font_state def_state = { 3, 0, 0, "", NULL, NULL, NULL };
-	gboolean scrolldown = TRUE;
-
-	if (html->vadj->upper > (html->vadj->value + html->vadj->page_size))
-		scrolldown = FALSE;
-
-	if (text == NULL) {
-		bold = 0;
-		italic = 0;
-		fixed = 0;
-		uline = 0;
-		strike = 0;
-		title = 0;
-		while (current->next)
-		{
-			if (current->ownbg)
-				g_free(current->bgcol);
-			if (current->owncolor)
-				g_free(current->color);
-			tmp = current;
-			current = current->next;
-			g_free(tmp);
-		}
-		return;
-	}
-
-	if (!current) current = &def_state;
-	map = gdk_window_get_colormap(html->html_area);
-	cfont = getfont(current->font, bold, italic, fixed, current->size);
-	c = text;
-
-	ws = g_malloc(strlen(text) + 2);
-	tag = g_malloc(strlen(text) + 2);
-
-	while (*c)
-	{
-		if (*c == '<')
-		{
-			if (!intag)
-			{
-				ws[wpos] = 0;
-				if (wpos)
-				{
-					if (title)
-					{
-						if (html->title)
-							g_free(html->title);
-						html->title = g_strdup(ws);
-					}
-					else
-						gtk_html_add_text(html, cfont, current->color,
-										  current->bgcol, ws, strlen(ws), uline,
-										  strike, url);
-				}
-				wpos = 0;
-				intag = 1;
-			}
-			else
-			{
-				/*
-				 * Assuming you NEVER have nested tags
-				 * * (and I mean <tag <tag>> by this, not
-				 * * <tag><tag2></tag2><tag>..
-				 */
-				tag[tpos] = 0;
-				gtk_html_add_text(html, cfont, current->color, current->bgcol,
-								  "<", 1, 0, 0, NULL);
-				gtk_html_add_text(html, cfont, current->color, current->bgcol,
-								  tag, strlen(tag), 0, 0, NULL);
-				tpos = 0;
-
-				tag[0] = *c;
-			}
-		}
-		else if (*c == '>')
-		{
-			if (intag)
-			{
-				tag[tpos] = 0;
-				if (!strcasecmp(tag, "B"))
-					bold = 1;
-				else if (!strcasecmp(tag, "STRIKE") || !strcasecmp(tag, "S"))
-					strike = 1;
-				else if (!strcasecmp(tag, "I"))
-					italic = 1;
-				else if (!strcasecmp(tag, "U"))
-					uline = 1;
-				else if (!strcasecmp(tag, "PRE"))
-					fixed = 1;
-				else if (!strcasecmp(tag, "HR"))
-					gtk_html_add_seperator(html, cfont, current->color, current->bgcol);
-				else if (!strcasecmp(tag, "/B"))
-					bold = 0;
-				else if (!strcasecmp(tag, "/STRIKE") || !strcasecmp(tag, "/S"))
-					strike = 0;
-				else if (!strcasecmp(tag, "/I"))
-					italic = 0;
-				else if (!strcasecmp(tag, "/U"))
-					uline = 0;
-				else if (!strcasecmp(tag, "/PRE"))
-					fixed = 0;
-				else if (!strcasecmp(tag, "TITLE"))
-					title = 1;
-				else if (!strcasecmp(tag, "/TITLE"))
-					title = 0;
-				else if (!strncasecmp(tag, "IMG", 3))
-				{
-					GdkPixmap *legend_i;
-					GdkBitmap *legend_m;
-
-					if (strstr(tag, "SRC=\"aol_icon.gif\"") != NULL)
-					{
-						legend_i = gdk_pixmap_create_from_xpm_d(GTK_WIDGET(html)->window, &legend_m, NULL, aol_icon_xpm);
-						gtk_html_add_pixmap(html, legend_i, 0, 0);
-					}
-
-					if (strstr(tag, "SRC=\"admin_icon.gif\"") != NULL)
-					{
-						legend_i = gdk_pixmap_create_from_xpm_d(GTK_WIDGET(html)->window, &legend_m, NULL, admin_icon_xpm);
-						gtk_html_add_pixmap(html, legend_i, 0, 0);
-					}
-					if (strstr(tag, "SRC=\"dt_icon.gif\"") != NULL)
-					{
-						legend_i = gdk_pixmap_create_from_xpm_d(GTK_WIDGET(html)->window, &legend_m, NULL, dt_icon_xpm);
-						gtk_html_add_pixmap(html, legend_i, 0, 0);
-					}
-					if (strstr(tag, "SRC=\"free_icon.gif\"") != NULL)
-					{
-						legend_i = gdk_pixmap_create_from_xpm_d(GTK_WIDGET(html)->window, &legend_m, NULL, free_icon_xpm);
-						gtk_html_add_pixmap(html, legend_i, 0, 0);
-					}
-				}
-				else if (!strcasecmp(tag, "H3"))
-				{
-					current = push_state(current);
-					current->size = 4;
-				}
-				else if (!strcasecmp(tag, "/H3"))
-				{
-					gtk_html_add_text(html, cfont, current->color,
-									  current->bgcol, "\n", 1, 0, 0, NULL);
-
-					if (current->next)
-					{
-						if (current->ownbg)
-							g_free(current->bgcol);
-						if (current->owncolor)
-							g_free(current->color);
-						tmp = current;
-						current = current->next;
-						g_free(tmp);
-					}
-				}
-				else if (!strcasecmp(tag, "TABLE"))
-				{
-				}
-				else if (!strcasecmp(tag, "/TABLE"))
-				{
-				}
-				else if (!strcasecmp(tag, "TR"))
-				{
-				}
-				else if (!strcasecmp(tag, "/TR"))
-				{
-				}
-				else if (!strcasecmp(tag, "/TD"))
-				{
-				}
-				else if (!strcasecmp(tag, "TD"))
-				{
-					gtk_html_add_text(html, cfont, current->color,
-									  current->bgcol, "  ", 2, 0, 0, NULL);
-				}
-				else if (!strncasecmp(tag, "A ", 2))
-				{
-					char *d;
-					char *temp = d = g_strdup(tag);
-					int flag = 0;
-					strtok(tag, " ");
-					while ((d = strtok(NULL, " ")))
-					{
-						if (strlen(d) < 7)
-							break;
-						if (!strncasecmp(d, "HREF=\"", strlen("HREF=\"")))
-						{
-							d += strlen("HREF=\"");
-							d[strlen(d) - 1] = 0;
-							url = g_malloc(strlen(d) + 1);
-							strcpy(url, d);
-							flag = 1;
-						}
-					}
-					g_free(temp);
-					if (!flag)
-					{
-						gtk_html_add_text(html, cfont, current->color,
-										  current->bgcol, "<", 1, 0, 0, NULL);
-						gtk_html_add_text(html, cfont, current->color,
-										  current->bgcol, tag, strlen(tag), 0,
-										  0, NULL);
-						gtk_html_add_text(html, cfont, current->color,
-										  current->bgcol, ">", 1, 0, 0, NULL);
-					}
-				}
-				else if (!strcasecmp(tag, "/A"))
-				{
-					if (url)
-					{
-						g_free(url);
-						url = NULL;
-					}
-				}
-				else if (!strncasecmp(tag, "FONT", strlen("FONT")))
-				{
-					char *d;
-					/*
-					 * Push a new state onto the stack, based on the old state 
-					 */
-					current = push_state(current);
-					html_strtok(tag, ' ');
-					while ((d = html_strtok(NULL, ' ')))
-					{
-						if (!strncasecmp(d, "style=", strlen("style=")))
-						{
-							d += strlen("style=");
-							if (*d == '\"') {
-								d++;
-								while (*d != '\0' && *d != '\"') d++;
-								if (*d == '\0')
-									html_strtok(tag, ' ');
-							}
-						}
-						if (!strncasecmp(d, "COLOR=", strlen("COLOR=")))
-						{
-							d += strlen("COLOR=");
-							if (*d == '\"')
-							{
-								d++;
-							}
-							if (*d == '#')
-								d++;
-							if (d[strlen(d) - 1] == '\"')
-								d[strlen(d) - 1] = 0;
-							if (sscanf(d, "%x", &colorv)
-								&& !(options & HTML_OPTION_NO_COLOURS))
-							{
-								current->color = get_color(colorv, map);
-								current->owncolor = 1;
-							}
-							else
-							{
-							}
-						}
-						if (!strncasecmp(d, "FACE=", strlen("FACE=")))
-						{
-							d += strlen("FACE=");
-							if (*d == '\"')
-							{
-								d++;
-							}
-							if (d[strlen(d) - 1] == '\"')
-								d[strlen(d) - 1] = 0;
-
-							if (!(options & HTML_OPTION_NO_FONTS)) { 
-								strcpy(current->font, d);
-							}
-						}
-						else if (!strncasecmp(d, "BACK=", strlen("BACK=")))
-						{
-							d += strlen("BACK=");
-							if (*d == '\"')
-								d++;
-							if (*d == '#')
-								d++;
-							if (d[strlen(d) - 1] == '\"')
-								d[strlen(d) - 1] = 0;
-							if (sscanf(d, "%x", &colorv)
-								&& !(options & HTML_OPTION_NO_COLOURS))
-							{
-								if (colorv != 0xffffff ||
-								    !(display_options & OPT_DISP_IGN_WHITE)) {
-									current->bgcol = get_color(colorv, map);
-									current->ownbg = 1;
-								}
-							}
-							else
-							{
-							}
-						}
-						else if (!strncasecmp(d, "SIZE=", strlen("SIZE=")))
-						{
-							d += strlen("SIZE=");
-							if (*d == '\"')
-								d++;
-							if (*d == '+')
-								d++;
-							if (sscanf(d, "%d", &colorv))
-							{
-								current->size = colorv;
-							}
-							else
-							{
-							}
-						}
-						else if (strncasecmp(d, "PTSIZE=", strlen("PTSIZE=")))
-						{
-						}
-					}
-				}
-				else if (!strncasecmp(tag, "BODY", strlen("BODY")))
-				{
-
-					char *d;
-					current = push_state(current);
-					html_strtok(tag, ' ');
-					while ((d = html_strtok(NULL, ' ')))
-					{
-						if (!strncasecmp(d, "BGCOLOR=", strlen("BGCOLOR=")))
-						{
-							d += strlen("BGCOLOR=");
-							if (*d == '\"')
-								d++;
-							if (*d == '#')
-								d++;
-							if (d[strlen(d) - 1] == '\"')
-								d[strlen(d) - 1] = 0;
-							if (sscanf(d, "%x", &colorv)
-								&& !(options & HTML_OPTION_NO_COLOURS))
-							{
-								if (colorv != 0xffffff ||
-								    !(display_options & OPT_DISP_IGN_WHITE)) {
-									current->bgcol = get_color(colorv, map);
-									current->ownbg = 1;
-								}
-							}
-						}
-					}
-				}
-				else if (!strncasecmp(tag, "/FONT", strlen("/FONT")))
-				{
-					/*
-					 * Pop a font state off the list if possible, freeing
-					 * any resources it used 
-					 */
-					if (current->next)
-					{
-						if (current->ownbg)
-							g_free(current->bgcol);
-						if (current->owncolor)
-							g_free(current->color);
-						tmp = current;
-						current = current->next;
-						g_free(tmp);
-					}
-
-				}
-				else if (!strcasecmp(tag, "/BODY"))
-				{
-					if (current->next)
-					{
-						if (current->ownbg)
-							g_free(current->bgcol);
-						if (current->owncolor)
-							g_free(current->color);
-						tmp = current;
-						current = current->next;
-						g_free(tmp);
-					}			/*
-								 * tags we ignore below 
-								 */
-				}
-				else if (!strncasecmp(tag, "BR", 2))
-				{
-					gtk_html_add_text(html, cfont, current->color,
-									  current->bgcol, "\n", 1, 0, 0, NULL);
-				}
-				else if (strncasecmp(tag, "HTML", 4)
-						 && strncasecmp(tag, "/HTML", 5)
-						 && strncasecmp(tag, "BODY", 4)
-						 && strncasecmp(tag, "/BODY", 5)
-						 && (strncasecmp(tag, "P", 1) || tag[1] != '>')
-						 && (strncasecmp(tag, "/P", 2) || tag[3] != '>')
-						 && strncasecmp(tag, "HEAD", 4)
-						 && strncasecmp(tag, "/HEAD", 5))
-				{
-					if (tpos)
-					{
-						gtk_html_add_text(html, cfont, current->color,
-										  current->bgcol, "<", 1, 0, 0, NULL);
-						gtk_html_add_text(html, cfont, current->color,
-										  current->bgcol, tag, strlen(tag), 0,
-										  0, NULL);
-						gtk_html_add_text(html, cfont, current->color,
-										  current->bgcol, ">", 1, 0, 0, NULL);
-
-					}
-				}
-				cfont = getfont(current->font, bold, italic, fixed, current->size);
-				tpos = 0;
-				intag = 0;
-			}
-			else
-			{
-				ws[wpos++] = *c;
-			}
-		}
-		else if (!intag && *c == '&')
-		{
-			if (!strncasecmp(c, "&amp;", 5))
-			{
-				ws[wpos++] = '&';
-				c += 4;
-			}
-			else if (!strncasecmp(c, "&lt;", 4))
-			{
-				ws[wpos++] = '<';
-				c += 3;
-			}
-			else if (!strncasecmp(c, "&gt;", 4))
-			{
-				ws[wpos++] = '>';
-				c += 3;
-			}
-			else if (!strncasecmp(c, "&nbsp;", 6))
-			{
-				ws[wpos++] = ' ';
-				c += 5;
-			}
-			else if (!strncasecmp(c, "&copy;", 6))
-			{
-				ws[wpos++] = '©';
-				c += 5;
-			}
-			else if (!strncasecmp(c, "&quot;", 6))
-			{
-				ws[wpos++] = '\"';
-				c += 5;
-			}
-			else if (!strncasecmp(c, "&reg;", 5))
-			{
-				ws[wpos++] = 174;
-				c += 4;
-			}
-			else if (*(c + 1) == '#')
-			{
-				int pound = 0;
-				debug_printf("got &#;\n");
-				if (sscanf(c, "&#%d;", &pound) > 0) {
-					ws[wpos++] = (char)pound;
-					c += 2;
-					while (isdigit(*c)) c++;
-					if (*c != ';') c--;
-				} else {
-					ws[wpos++] = *c;
-				}
-			}
-			else
-			{
-				ws[wpos++] = *c;
-			}
-		}
-		else
-		{
-			if (intag)
-			{
-				tag[tpos++] = *c;
-			}
-			else
-			{
-				ws[wpos++] = *c;
-			}
-		}
-		c++;
-	}
-	ws[wpos] = 0;
-	tag[tpos] = 0;
-	if (wpos)
-	{
-		gtk_html_add_text(html, cfont, current->color, current->bgcol, ws,
-						  strlen(ws), uline, strike, url);
-	}
-	if (tpos)
-	{
-		gtk_html_add_text(html, cfont, current->color, current->bgcol, "<", 1,
-						  0, 0, NULL);
-		gtk_html_add_text(html, cfont, current->color, current->bgcol, tag,
-						  strlen(tag), 0, 0, NULL);
-/*		gtk_html_add_text(html, cfont, current->color, current->bgcol, ">", 1,
-						  0, 0, NULL);
-*/	}
-
-
-	g_free(ws);
-	g_free(tag);
-
-	gdk_window_get_size(html->html_area, NULL, &height);
-	area.height = height;
-	if (scrolldown)
-		gtk_adjustment_set_value(html->vadj, html->vadj->upper - area.height);
-
-	return;
-}
-
-
-static void adjust_adj(GtkHtml * html, GtkAdjustment * adj)
-{
-	gint height;
-
-	gdk_window_get_size(html->html_area, NULL, &height);
-
-	adj->step_increment = MIN(adj->upper, (float) SCROLL_PIXELS);
-	adj->page_increment = MIN(adj->upper, height - (float) KEY_SCROLL_PIXELS);
-	adj->page_size = MIN(adj->upper, height);
-	adj->value = MIN(adj->value, adj->upper - adj->page_size);
-	adj->value = MAX(adj->value, 0.0);
-
-	gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed");
-}
-
-
-static void scroll_down(GtkHtml * html, gint diff0)
-{
-	GdkRectangle rect;
-	gint width,
-	  height;
-
-	html->yoffset += diff0;
-
-	gdk_window_get_size(html->html_area, &width, &height);
-
-	if (html->transparent)
-	{
-		rect.x = 0;
-		rect.y = 0;
-		rect.width = width;
-		rect.height = height;
-	}
-	else
-	{
-
-
-		if (height > diff0 && !html->transparent)
-			gdk_draw_pixmap(html->html_area,
-							html->gc,
-							html->html_area,
-							0, diff0, 0, 0, width, height - diff0);
-
-		rect.x = 0;
-		rect.y = MAX(0, height - diff0);
-		rect.width = width;
-		rect.height = MIN(height, diff0);
-	}
-
-	expose_html(html, &rect, FALSE);
-	gtk_html_draw_focus((GtkWidget *) html);
-
-}
-
-static void scroll_up(GtkHtml * html, gint diff0)
-{
-	GdkRectangle rect;
-	gint width,
-	  height;
-
-	html->yoffset -= diff0;
-
-
-	gdk_window_get_size(html->html_area, &width, &height);
-
-	if (html->transparent)
-	{
-		rect.x = 0;
-		rect.y = 0;
-		rect.width = width;
-		rect.height = height;
-	}
-	else
-	{
-
-		if (height > diff0)
-			gdk_draw_pixmap(html->html_area,
-							html->gc,
-							html->html_area,
-							0, 0, 0, diff0, width, height - diff0);
-
-		rect.x = 0;
-		rect.y = 0;
-		rect.width = width;
-		rect.height = MIN(height, diff0);
-	}
-
-	expose_html(html, &rect, FALSE);
-	gtk_html_draw_focus((GtkWidget *) html);
-
-}
-
-
-
-static void gtk_html_adjustment(GtkAdjustment * adjustment, GtkHtml * html)
-{
-	g_return_if_fail(adjustment != NULL);
-	g_return_if_fail(GTK_IS_ADJUSTMENT(adjustment));
-	g_return_if_fail(html != NULL);
-	g_return_if_fail(GTK_IS_HTML(html));
-
-	/*
-	 * Just ignore it if we haven't been size-allocated and realized yet 
-	 */
-	if (html->html_area == NULL)
-		return;
-
-	if (adjustment == html->hadj)
-	{
-		g_warning("horizontal scrolling not implemented");
-	}
-	else
-	{
-		gint diff = ((gint) adjustment->value) - html->last_ver_value;
-
-		if (diff != 0)
-		{
-			/*
-			 * undraw_cursor (text, FALSE);
-			 */
-
-			if (diff > 0)
-			{
-				scroll_down(html, diff);
-			}
-			else
-			{					/*
-								 * if (diff < 0) 
-								 */
-				scroll_up(html, -diff);
-			}
-			/*
-			 * draw_cursor (text, FALSE); 
-			 */
-
-			html->last_ver_value = adjustment->value;
-		}
-	}
-}
-
-static gint gtk_html_visibility_notify(GtkWidget * widget,
-									   GdkEventVisibility * event)
-{
-	GtkHtml *html;
-	GdkRectangle rect;
-	gint width,
-	  height;
-
-	g_return_val_if_fail(widget != NULL, FALSE);
-	g_return_val_if_fail(GTK_IS_HTML(widget), FALSE);
-
-	html = GTK_HTML(widget);
-
-	if (GTK_WIDGET_REALIZED(widget) && html->transparent)
-	{
-		gdk_window_get_size(html->html_area, &width, &height);
-		rect.x = 0;
-		rect.y = 0;
-		rect.width = width;
-		rect.height = height;
-		expose_html(html, &rect, FALSE);
-		gtk_html_draw_focus((GtkWidget *) html);
-	}
-	else
-	{
-	}
-
-
-	return FALSE;
-}
-
-
-
-static void gtk_html_disconnect(GtkAdjustment * adjustment, GtkHtml * html)
-{
-	g_return_if_fail(adjustment != NULL);
-	g_return_if_fail(GTK_IS_ADJUSTMENT(adjustment));
-	g_return_if_fail(html != NULL);
-	g_return_if_fail(GTK_IS_HTML(html));
-
-	if (adjustment == html->hadj)
-		gtk_html_set_adjustments(html, NULL, html->vadj);
-	if (adjustment == html->vadj)
-		gtk_html_set_adjustments(html, html->hadj, NULL);
-}
-
-static void move_cursor_ver(GtkHtml * html, int count)
-{
-	GList *hbits = g_list_find(html->html_bits, html->cursor_hb);
-	GtkHtmlBit *hb = NULL,
-	 *hb2 = NULL;
-	gint y;
-	size_t len,
-	  len2 = 0;
-
-	undraw_cursor(html);
-
-	if (!html->html_bits)
-		return;
-
-	if (!html->cursor_hb)
-		html->cursor_hb = (GtkHtmlBit *) html->html_bits->data;
-
-	hb = html->cursor_hb;
-
-	len = html->cursor_pos;
-	hbits = hbits->prev;
-	while (hbits)
-	{
-		hb2 = (GtkHtmlBit *) hbits->data;
-
-		if (hb2->y != hb->y)
-			break;
-
-		len += strlen(hb2->text);
-
-		hbits = hbits->prev;
-	}
-
-	hbits = g_list_find(html->html_bits, html->cursor_hb);
-
-	if (count < 0)
-	{
-		while (hbits)
-		{
-			hb2 = (GtkHtmlBit *) hbits->data;
-
-			if (hb2->y != hb->y)
-				break;
-
-			hbits = hbits->prev;
-		}
-		if (!hbits)
-		{
-			draw_cursor(html);
-			return;
-		}
-		y = hb2->y;
-		hb = hb2;
-		while (hbits)
-		{
-			hb2 = (GtkHtmlBit *) hbits->data;
-
-			if (hb2->y != y)
-				break;
-
-			hb = hb2;
-
-			hbits = hbits->prev;
-		}
-		hbits = g_list_find(html->html_bits, hb);
-		while (hbits)
-		{
-			hb2 = (GtkHtmlBit *) hbits->data;
-
-			if (hb->y != hb2->y)
-			{
-				html->cursor_hb = hb;
-				html->cursor_pos = strlen(hb->text);
-				break;
-			}
-
-
-			if (len < len2 + strlen(hb2->text))
-			{
-				html->cursor_hb = hb2;
-				html->cursor_pos = len - len2;
-				break;
-			}
-
-			len2 += strlen(hb2->text);
-
-			hb = hb2;
-
-			hbits = hbits->next;
-		}
-	}
-	else
-	{
-		while (hbits)
-		{
-			hb2 = (GtkHtmlBit *) hbits->data;
-
-			if (hb2->y != hb->y)
-				break;
-
-			hbits = hbits->next;
-		}
-		if (!hbits)
-		{
-			draw_cursor(html);
-			return;
-		}
-		hb = hb2;
-		while (hbits)
-		{
-			hb2 = (GtkHtmlBit *) hbits->data;
-
-			if (hb->y != hb2->y)
-			{
-				html->cursor_hb = hb;
-				html->cursor_pos = strlen(hb->text);
-				break;
-			}
-
-
-			if (len < len2 + strlen(hb2->text))
-			{
-				html->cursor_hb = hb2;
-				html->cursor_pos = len - len2;
-				break;
-			}
-
-			len2 += strlen(hb2->text);
-
-			hb = hb2;
-
-			hbits = hbits->next;
-		}
-	}
-
-	draw_cursor(html);
-
-}
-
-static void move_cursor_hor(GtkHtml * html, int count)
-{
-	GList *hbits = g_list_find(html->html_bits, html->cursor_hb);
-	GtkHtmlBit *hb,
-	 *hb2;
-
-	undraw_cursor(html);
-
-	if (!html->html_bits)
-		return;
-
-	if (!html->cursor_hb)
-		html->cursor_hb = (GtkHtmlBit *) html->html_bits->data;
-
-	html->cursor_pos += count;
-
-	if (html->cursor_pos < 0)
-	{
-		if (hbits->prev)
-		{
-			gint diff;
-			hb = html->cursor_hb;
-			hb2 = (GtkHtmlBit *) hbits->prev->data;
-			diff = html->cursor_pos + strlen(hb2->text) + 1;
-			if (hb->y == hb2->y)
-				--diff;
-
-			html->cursor_pos = diff;
-
-			html->cursor_hb = (GtkHtmlBit *) hbits->prev->data;
-		}
-		else
-		{
-			html->cursor_pos = 0;
-		}
-	}
-	else if ((unsigned) html->cursor_pos > strlen(html->cursor_hb->text))
-	{
-		if (hbits->next)
-		{
-			gint diff;
-			hb = html->cursor_hb;
-			hb2 = (GtkHtmlBit *) hbits->next->data;
-
-			diff = html->cursor_pos - strlen(html->cursor_hb->text) - 1;
-			if (hb->y == hb2->y)
-				++diff;
-			html->cursor_pos = diff;
-			html->cursor_hb = (GtkHtmlBit *) hbits->next->data;
-		}
-		else
-		{
-			html->cursor_pos = strlen(html->cursor_hb->text);
-		}
-
-	}
-
-	draw_cursor(html);
-}
-
-static void move_beginning_of_line(GtkHtml * html)
-{
-	GList *hbits = g_list_find(html->html_bits, html->cursor_hb);
-	GtkHtmlBit *hb = NULL;
-	gint y;
-
-	undraw_cursor(html);
-
-	if (!html->html_bits)
-		return;
-
-	if (!html->cursor_hb)
-		html->cursor_hb = (GtkHtmlBit *) html->html_bits->data;
-
-	y = html->cursor_hb->y;
-
-	while (hbits)
-	{
-		hb = (GtkHtmlBit *) hbits->data;
-
-		if (y != hb->y)
-		{
-			hb = (GtkHtmlBit *) hbits->next->data;
-			break;
-		}
-
-		hbits = hbits->prev;
-	}
-	if (!hbits)
-		html->cursor_hb = (GtkHtmlBit *) html->html_bits->data;
-	else
-		html->cursor_hb = hb;
-
-	html->cursor_pos = 0;
-
-
-	draw_cursor(html);
-
-
-}
-
-static void move_end_of_line(GtkHtml * html)
-{
-	GList *hbits = g_list_find(html->html_bits, html->cursor_hb);
-	GtkHtmlBit *hb = NULL;
-	gint y;
-
-	undraw_cursor(html);
-
-	if (!html->html_bits)
-		return;
-
-	if (!html->cursor_hb)
-		html->cursor_hb = (GtkHtmlBit *) html->html_bits->data;
-
-	y = html->cursor_hb->y;
-
-	while (hbits)
-	{
-		hb = (GtkHtmlBit *) hbits->data;
-
-		if (y != hb->y)
-		{
-			hb = (GtkHtmlBit *) hbits->prev->data;
-			break;
-		}
-
-		hbits = hbits->next;
-	}
-	if (!hbits)
-		html->cursor_hb = (GtkHtmlBit *) g_list_last(html->html_bits)->data;
-	else
-		html->cursor_hb = hb;
-
-	html->cursor_pos = strlen(html->cursor_hb->text);
-
-
-	draw_cursor(html);
-
-
-}
-
-
-
-static gint gtk_html_key_press(GtkWidget * widget, GdkEventKey * event)
-{
-	GtkHtml *html;
-	gchar key;
-	gint return_val;
-
-	g_return_val_if_fail(widget != NULL, FALSE);
-	g_return_val_if_fail(GTK_IS_HTML(widget), FALSE);
-	g_return_val_if_fail(event != NULL, FALSE);
-
-	return_val = FALSE;
-
-	html = GTK_HTML(widget);
-
-	key = event->keyval;
-	return_val = TRUE;
-
-
-	if (html->editable == FALSE)
-	{
-		/*
-		 * switch (event->keyval) {
-		 * case GDK_Home:
-		 * if (event->state & GDK_CONTROL_MASK)
-		 * scroll_int (text, -text->vadj->value);
-		 * else
-		 * return_val = FALSE;
-		 * break;
-		 * case GDK_End:
-		 * if (event->state & GDK_CONTROL_MASK)
-		 * scroll_int (text, +text->vadj->upper);
-		 * else
-		 * return_val = FALSE;
-		 * break;
-		 * case GDK_Page_Up:   scroll_int (text, -text->vadj->page_increment); break;
-		 * case GDK_Page_Down: scroll_int (text, +text->vadj->page_increment); break;
-		 * case GDK_Up:        scroll_int (text, -KEY_SCROLL_PIXELS); break;
-		 * case GDK_Down:      scroll_int (text, +KEY_SCROLL_PIXELS); break;
-		 * case GDK_Return:
-		 * if (event->state & GDK_CONTROL_MASK)
-		 * gtk_signal_emit_by_name (GTK_OBJECT (text), "activate");
-		 * else
-		 * return_val = FALSE;
-		 * break;
-		 * default:
-		 * return_val = FALSE;
-		 * break;
-		 * }
-		 */
-	}
-	else
-	{
-
-		switch (event->keyval)
-		{
-		case GDK_Home:
-			move_beginning_of_line(html);
-			break;
-		case GDK_End:
-			move_end_of_line(html);
-			break;
-			/*
-			 * case GDK_Page_Up:
-			 * move_cursor_page_ver (html, -1);
-			 * break;
-			 * case GDK_Page_Down:
-			 * move_cursor_page_ver (html, +1);
-			 * break;
-			 */
-			/*
-			 * CUA has Ctrl-Up/Ctrl-Down as paragraph up down 
-			 */
-		case GDK_Up:
-			move_cursor_ver(html, -1);
-			break;
-		case GDK_Down:
-			move_cursor_ver(html, +1);
-			break;
-		case GDK_Left:
-			move_cursor_hor(html, -1);
-			break;
-		case GDK_Right:
-			move_cursor_hor(html, +1);
-			break;
-#if 0
-		case GDK_BackSpace:
-			if (event->state & GDK_CONTROL_MASK)
-				gtk_text_delete_backward_word(text);
-			else
-				gtk_text_delete_backward_character(text);
-			break;
-		case GDK_Clear:
-			gtk_text_delete_line(text);
-			break;
-		case GDK_Insert:
-			if (event->state & GDK_SHIFT_MASK)
-			{
-				extend_selection = FALSE;
-				gtk_editable_paste_clipboard(editable);
-			}
-			else if (event->state & GDK_CONTROL_MASK)
-			{
-				gtk_editable_copy_clipboard(editable);
-			}
-			else
-			{
-				/*
-				 * gtk_toggle_insert(text) -- IMPLEMENT 
-				 */
-			}
-			break;
-		case GDK_Delete:
-			if (event->state & GDK_CONTROL_MASK)
-				gtk_text_delete_forward_word(text);
-			else if (event->state & GDK_SHIFT_MASK)
-			{
-				extend_selection = FALSE;
-				gtk_editable_cut_clipboard(editable);
-			}
-			else
-				gtk_text_delete_forward_character(text);
-			break;
-		case GDK_Tab:
-			position = text->point.index;
-			gtk_editable_insert_text(editable, "\t", 1, &position);
-			break;
-		case GDK_Return:
-			if (event->state & GDK_CONTROL_MASK)
-				gtk_signal_emit_by_name(GTK_OBJECT(text), "activate");
-			else
-			{
-				position = text->point.index;
-				gtk_editable_insert_text(editable, "\n", 1, &position);
-			}
-			break;
-		case GDK_Escape:
-			/*
-			 * Don't insert literally 
-			 */
-			return_val = FALSE;
-			break;
-#endif
-		default:
-			return_val = FALSE;
-
-#if 0
-			if (event->state & GDK_CONTROL_MASK)
-			{
-				if ((key >= 'A') && (key <= 'Z'))
-					key -= 'A' - 'a';
-
-				if ((key >= 'a') && (key <= 'z')
-					&& control_keys[(int) (key - 'a')])
-				{
-					(*control_keys[(int) (key - 'a')]) (editable, event->time);
-					return_val = TRUE;
-				}
-
-				break;
-			}
-			else if (event->state & GDK_MOD1_MASK)
-			{
-				if ((key >= 'A') && (key <= 'Z'))
-					key -= 'A' - 'a';
-
-				if ((key >= 'a') && (key <= 'z') && alt_keys[(int) (key - 'a')])
-				{
-					(*alt_keys[(int) (key - 'a')]) (editable, event->time);
-					return_val = TRUE;
-				}
-				break;
-			}
-#endif
-			/*
-			 * if (event->length > 0) {
-			 * html->cursor_pos++;
-			 * gtk_editable_insert_text (editable, event->string, event->length, &position);
-			 * 
-			 * return_val = TRUE;
-			 * }
-			 * else
-			 * return_val = FALSE;
-			 */
-		}
-
-	}
-
-	return return_val;
-}
-
-void gtk_html_freeze(GtkHtml * html)
-{
-	g_return_if_fail(html != NULL);
-	g_return_if_fail(GTK_IS_HTML(html));
-
-	html->frozen++;
-}
-
-void gtk_html_thaw(GtkHtml * html)
-{
-	GdkRectangle area;
-
-	g_return_if_fail(html != NULL);
-	g_return_if_fail(GTK_IS_HTML(html));
-
-	gtk_html_append_text(html, NULL, 0);
-
-	html->frozen--;
-
-	if (html->frozen < 0)
-		html->frozen = 0;
-
-	if (html->frozen == 0)
-	{
-		if (html->html_area)
-		{
-			gint width,
-			  height;
-			area.x = 0;
-			area.y = 0;
-
-			gdk_window_get_size(html->html_area, &width, &height);
-
-			area.width = width;
-			area.height = height;
-
-			expose_html(html, &area, TRUE);
-		}
-	}
-}
-
-static int get_line_height(GtkHtml *html, GtkHtmlBit *start)
-{
-	int height = 1, max_height = 0;
-	GList *hbits = html->html_bits;
-	GtkHtmlBit *hbit = start; /* default this in case hbits is NULL */
-
-	hbits = g_list_find(hbits, start);
-
-	while (hbits)
-	{
-		hbit = hbits->data;	
-		if (hbit->font)
-			height = gdk_text_height(hbit->font, "C", 1);	
-
-		if (max_height < height)
-			max_height = height;
-		if (hbit->newline)
-			break;
-		hbits = hbits->next;
-	}
-
-	if (max_height == 0)
-		max_height = gdk_text_height(hbit->font, "C", 1);	
-		
-	return max_height;
-}
--- a/src/gtkhtml.h	Thu Jan 25 20:31:12 2001 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
- * gaim
- *
- * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
- *
- * 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
- *
- */
-
-#ifndef __GTK_HTML_H__
-#define __GTK_HTML_H__
-
-#include <gdk/gdk.h>
-#include <gtk/gtkwidget.h>
-
-#ifdef __cplusplus
-/*extern "C" {*/
-#endif /* __cplusplus */
-
-#define GTK_TYPE_HTML            (gtk_html_get_type())
-#define GTK_HTML(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_HTML, GtkHtml))
-#define GTK_HTML_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_HTML, GtkHtmlClass))
-#define GTK_IS_HTML(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_HTML))
-#define GTK_IS_HTML_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_HTML)
-        
-typedef struct _GtkHtml          GtkHtml;
-typedef struct _GtkHtmlClass     GtkHtmlClass;
-typedef struct _GtkHtmlBit       GtkHtmlBit;
-
-
-struct _GtkHtmlBit {
-	int type;
-	GdkColor *fore;
-	GdkColor *back;
-	GdkFont *font;
-	int uline;
-	int strike;
-	int width, height;
-	int x, y;
-	char *url;
-	int was_selected;
-	int sel_s, sel_e;
-	int newline;
-	char *text;
-	GdkPixmap *pm;
-	int fit;
-};
-
-
-struct _GtkHtml {
-	GtkWidget widget;
-	
-	GdkWindow *html_area;
-
-	GtkAdjustment *hadj;
-	GtkAdjustment *vadj;
-
-	gint xoffset;
-	gint yoffset;
-	
-	int current_x;
-	int current_y;
-	GdkGC *gc;
-	GdkGC *bg_gc;
-	GList *html_bits;
-	GList *urls;
-	int start_sel_x, start_sel_y;
-	GtkHtmlBit *start_sel, *end_sel;
-	int num_start, num_end;
-	char *selected_text;
-	gint editable;
-	gint transparent;
-	gint timer;
-	gint last_ver_value;
-	char *title;
-	gint frozen;
-	GtkHtmlBit *cursor_hb;
-	GtkWidget *tooltip_window;
-	GtkHtmlBit *tooltip_hb;
-	int tooltip_timer;
-	int cursor_pos;
-	GdkPixmap *pm;        
-};
-
-
-struct _GtkHtmlClass {
-	GtkWidgetClass parent_class;
-
-	void  (*set_scroll_adjustments)   (GtkHtml        *html,
-					   GtkAdjustment  *hadjustment,
-					   GtkAdjustment  *vadjustment);
-
-};
-
-
-#define HTML_BIT_TEXT 0
-#define HTML_BIT_PIXMAP 1
-#define HTML_BIT_SEP 2
-
-#define HTML_OPTION_NO_COLOURS   0x01
-#define HTML_OPTION_NO_FONTS     0x02
-
-#define STYLE_ITALIC 0x01000000
-#define STYLE_BOLD 0x020000000
-
-#define FIXED_FONT "-*-courier-medium-r-*-*-*-%d-*-*-*-*-*-*"
-#define FIXED_BOLD_FONT "-*-courier-bold-r-*-*-*-%d-*-*-*-*-*-*"
-#define FIXED_ITALIC_FONT "-*-courier-medium-o-*-*-*-%d-*-*-*-*-*-*"
-#define FIXED_BOLD_ITALIC_FONT "-*-courier-bold-o-*-*-*-%d-*-*-*-*-*-*"
-#define PROP_FONT "-*-helvetica-medium-r-*-*-*-%d-*-*-*-*-*-*"
-#define PROP_BOLD_FONT "-*-helvetica-bold-r-*-*-*-%d-*-*-*-*-*-*"
-#define PROP_ITALIC_FONT "-*-helvetica-medium-o-*-*-*-%d-*-*-*-*-*-*"
-#define PROP_BOLD_ITALIC_FONT "-*-helvetica-bold-o-*-*-*-%d-*-*-*-*-*-*"
-
-#define HTML_TOOLTIP_DELAY 500
-
-GtkType		gtk_html_get_type		(void);
-GtkWidget*	gtk_html_new			(GtkAdjustment *hadj,
-												GtkAdjustment *vadj);
-void	gtk_html_set_editable			(GtkHtml *html,
-												gboolean is_editable);
-void	gtk_html_set_transparent	(GtkHtml *html,
-												gboolean is_transparent);
-void	gtk_html_set_adjustments	(GtkHtml       *html,
-												GtkAdjustment *hadj,
-												GtkAdjustment *vadj);
-void	gtk_html_append_text		(GtkHtml      *html,
-												char *text, gint options);
-void	gtk_html_freeze					(GtkHtml      *html);
-void	gtk_html_thaw					(GtkHtml      *html);
-void	gtk_html_add_pixmap			(GtkHtml * html, GdkPixmap *pm,
-												gint fint, gint newline);
-
-#ifdef __cplusplus
-/*}*/
-#endif /* __cplusplus */
-
-#endif /* __GTK_HTML_H__ */
-
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gtkimhtml.c	Fri Jan 26 02:02:36 2001 +0000
@@ -0,0 +1,2918 @@
+/*
+ * GtkIMHtml
+ *
+ * Copyright (C) 2000, Eric Warmenhoven <warmenhoven@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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 "gtkimhtml.h"
+#include <gtk/gtk.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "pixmaps/angel.xpm"
+#include "pixmaps/bigsmile.xpm"
+#include "pixmaps/burp.xpm"
+#include "pixmaps/crossedlips.xpm"
+#include "pixmaps/cry.xpm"
+#include "pixmaps/embarrassed.xpm"
+#include "pixmaps/kiss.xpm"
+#include "pixmaps/moneymouth.xpm"
+#include "pixmaps/sad.xpm"
+#include "pixmaps/scream.xpm"
+#include "pixmaps/smile.xpm"
+#include "pixmaps/smile8.xpm"
+#include "pixmaps/think.xpm"
+#include "pixmaps/tongue.xpm"
+#include "pixmaps/wink.xpm"
+#include "pixmaps/yell.xpm"
+
+#define DEFAULT_FONT_NAME "helvetica"
+#define MAX_SIZE 7
+
+gint font_sizes [] = { 80, 100, 120, 140, 200, 300, 400 };
+
+#define BORDER_SIZE 3
+#define MIN_HEIGHT 20
+#define HR_HEIGHT 2
+
+#define TYPE_TEXT     0
+#define TYPE_SMILEY   1
+#define TYPE_IMG      2
+#define TYPE_SEP      3
+#define TYPE_BR       4
+#define TYPE_COMMENT  5
+
+typedef struct _GtkIMHtmlBit GtkIMHtmlBit;
+typedef struct _FontDetail   FontDetail;
+
+struct _GtkIMHtmlBit {
+	gint type;
+
+	gchar *text;
+	GdkPixmap *pm;
+	GdkBitmap *bm;
+
+	GdkFont *font;
+	GdkColor *fore;
+	GdkColor *back;
+	GdkColor *bg;
+	gboolean underline;
+	gboolean strike;
+	gchar *url;
+
+	GList *chunks;
+};
+
+struct _FontDetail {
+	gushort size;
+	gchar *face;
+	GdkColor *fore;
+	GdkColor *back;
+};
+
+struct line_info {
+	gint x;
+	gint y;
+	gint width;
+	gint height;
+	gint ascent;
+
+	gboolean selected;
+	gchar *sel_start;
+	gchar *sel_end;
+
+	gchar *text;
+	GtkIMHtmlBit *bit;
+};
+
+struct url_widget {
+	gint x;
+	gint y;
+	gint width;
+	gint height;
+	gchar *url;
+};
+
+static GtkLayoutClass *parent_class = NULL;
+
+enum {
+	TARGET_STRING,
+	TARGET_TEXT,
+	TARGET_COMPOUND_TEXT
+};
+
+enum {
+	URL_CLICKED,
+	LAST_SIGNAL
+};
+static guint signals [LAST_SIGNAL] = { 0 };
+
+static void      gtk_imhtml_draw_bit            (GtkIMHtml *, GtkIMHtmlBit *);
+static GdkColor *gtk_imhtml_get_color           (const gchar *);
+static gint      gtk_imhtml_motion_notify_event (GtkWidget *, GdkEventMotion *);
+
+static void
+gtk_imhtml_destroy (GtkObject *object)
+{
+	GtkIMHtml *imhtml;
+
+	imhtml = GTK_IMHTML (object);
+
+	while (imhtml->bits) {
+		GtkIMHtmlBit *bit = imhtml->bits->data;
+		imhtml->bits = g_list_remove (imhtml->bits, bit);
+		if (bit->text)
+			g_free (bit->text);
+		if (bit->font)
+			gdk_font_unref (bit->font);
+		if (bit->fore)
+			gdk_color_free (bit->fore);
+		if (bit->back)
+			gdk_color_free (bit->back);
+		if (bit->bg)
+			gdk_color_free (bit->bg);
+		if (bit->url)
+			g_free (bit->url);
+		if (bit->pm)
+			gdk_pixmap_unref (bit->pm);
+		if (bit->bm)
+			gdk_bitmap_unref (bit->bm);
+		while (bit->chunks) {
+			GtkObject *obj = bit->chunks->data;
+			struct line_info *li = gtk_object_get_user_data (obj);
+			if (li->text)
+				g_free (li->text);
+			g_free (li);
+			bit->chunks = g_list_remove (bit->chunks, obj);
+		}
+		g_free (bit);
+	}
+
+	while (imhtml->urls) {
+		g_free (imhtml->urls->data);
+		imhtml->urls = g_list_remove (imhtml->urls, imhtml->urls->data);
+	}
+
+	if (imhtml->selected_text)
+		g_string_free (imhtml->selected_text, TRUE);
+
+	gdk_font_unref (imhtml->default_font);
+	gdk_color_free (imhtml->default_fg_color);
+
+	gdk_cursor_destroy (imhtml->hand_cursor);
+	gdk_cursor_destroy (imhtml->arrow_cursor);
+
+	g_hash_table_destroy (imhtml->smiley_hash);
+
+	if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL)
+		(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_imhtml_realize (GtkWidget *widget)
+{
+	GtkIMHtml *imhtml;
+
+	g_return_if_fail (widget != NULL);
+	g_return_if_fail (GTK_IS_IMHTML (widget));
+
+	imhtml = GTK_IMHTML (widget);
+
+	if (GTK_WIDGET_CLASS (parent_class)->realize)
+		(* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
+
+	widget->style = gtk_style_attach (widget->style, widget->window);
+	gdk_window_set_events (imhtml->layout.bin_window,
+			       (gdk_window_get_events (imhtml->layout.bin_window)
+				| GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
+				| GDK_POINTER_MOTION_MASK | GDK_EXPOSURE_MASK));
+
+	gdk_window_set_cursor (widget->window, imhtml->arrow_cursor);
+
+	gdk_window_set_background (GTK_LAYOUT (imhtml)->bin_window, &GTK_WIDGET (imhtml)->style->white);
+}
+
+static void
+gtk_imhtml_unrealize (GtkWidget *widget)
+{
+	if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+		(* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
+gtk_imhtml_draw (GtkWidget    *widget,
+		 GdkRectangle *area)
+{
+	if (GTK_WIDGET_CLASS (parent_class)->draw)
+		(* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area);
+}
+
+static void
+gtk_imhtml_style_set (GtkWidget *widget,
+		      GtkStyle  *style)
+{
+	GtkIMHtml *imhtml;
+
+	g_return_if_fail (widget != NULL);
+	g_return_if_fail (GTK_IS_IMHTML (widget));
+	if (!GTK_WIDGET_REALIZED (widget))
+		return;
+
+	imhtml = GTK_IMHTML (widget);
+
+	gdk_window_set_background (GTK_LAYOUT (imhtml)->bin_window, &GTK_WIDGET (imhtml)->style->white);
+}
+
+static gint
+gtk_imhtml_expose (GtkWidget      *widget,
+		   GdkEventExpose *event)
+{
+	if (GTK_WIDGET_CLASS (parent_class)->expose_event)
+		(* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
+
+	return TRUE;
+}
+
+static void
+gtk_imhtml_redraw_all (GtkIMHtml *imhtml)
+{
+	GList *b;
+	GtkIMHtmlBit *bit;
+	GtkAdjustment *vadj;
+	gfloat oldvalue;
+
+	vadj = GTK_LAYOUT (imhtml)->vadjustment;
+	oldvalue = vadj->value / vadj->upper;
+
+	b = imhtml->bits;
+	while (b) {
+		bit = b->data;
+		b = g_list_next (b);
+		while (bit->chunks) {
+			GtkObject *obj = bit->chunks->data;
+			struct line_info *li = gtk_object_get_user_data (obj);
+			if (li->text)
+				g_free (li->text);
+			g_free (li);
+			bit->chunks = g_list_remove (bit->chunks, obj);
+		}
+	}
+
+	g_list_free (imhtml->line);
+	imhtml->line = NULL;
+
+	while (imhtml->urls) {
+		g_free (imhtml->urls->data);
+		imhtml->urls = g_list_remove (imhtml->urls, imhtml->urls->data);
+	}
+
+	while (GTK_LAYOUT (imhtml)->children)
+		gtk_container_remove (GTK_CONTAINER (imhtml),
+				*(GtkWidget **)GTK_LAYOUT (imhtml)->children->data);
+
+	imhtml->x = BORDER_SIZE;
+	imhtml->y = BORDER_SIZE + 10;
+	imhtml->llheight = 0;
+	imhtml->llascent = 0;
+
+	b = imhtml->bits;
+	while (b) {
+		gtk_imhtml_draw_bit (imhtml, b->data);
+		b = g_list_next (b);
+	}
+
+	gtk_adjustment_set_value (vadj, vadj->upper * oldvalue);
+}
+
+static void
+gtk_imhtml_size_allocate (GtkWidget     *widget,
+			  GtkAllocation *allocation)
+{
+	GtkIMHtml *imhtml;
+
+	g_return_if_fail (widget != NULL);
+	g_return_if_fail (GTK_IS_IMHTML (widget));
+	g_return_if_fail (allocation != NULL);
+
+	imhtml = GTK_IMHTML (widget);
+
+	if (GTK_WIDGET_CLASS (parent_class)->size_allocate)
+		( *GTK_WIDGET_CLASS (parent_class)->size_allocate) (widget, allocation);
+
+	if (allocation->width == imhtml->xsize)
+		return;
+
+	imhtml->x = BORDER_SIZE;
+	imhtml->y = BORDER_SIZE + 10;
+	imhtml->llheight = 0;
+	imhtml->llascent = 0;
+
+	imhtml->xsize = allocation->width;
+
+	gtk_imhtml_redraw_all (imhtml);
+}
+
+static void
+gtk_imhtml_select_none (GtkIMHtml *imhtml)
+{
+	GList *bits;
+	GList *chunks;
+	GtkIMHtmlBit *bit;
+	struct line_info *chunk;
+	GtkWidget *darea;
+
+	g_return_if_fail (GTK_IS_IMHTML (imhtml));
+
+	bits = imhtml->bits;
+	while (bits) {
+		bit = bits->data;
+		chunks = bit->chunks;
+
+		while (chunks) {
+			darea = chunks->data;
+			chunk = gtk_object_get_user_data (GTK_OBJECT (darea));
+
+			if (chunk->selected)
+				gtk_widget_queue_draw (darea);
+			chunk->selected = FALSE;
+			chunk->sel_start = chunk->sel_end = NULL;
+
+			chunks = g_list_next (chunks);
+		}
+
+		bits = g_list_next (bits);
+	}
+}
+
+static gchar*
+get_position (struct line_info *chunk,
+	      gint              x,
+	      gboolean          smileys)
+{
+	gint width = x - chunk->x;
+	gchar *text;
+	gchar *pos;
+	guint total = 0;
+
+	switch (chunk->bit->type) {
+	case TYPE_TEXT:
+	case TYPE_COMMENT:
+		text = chunk->text;
+		break;
+	case TYPE_SMILEY:
+		if (smileys)
+			return NULL;
+		else
+			text = chunk->text;
+		break;
+	default:
+		return NULL;
+		break;
+	}
+
+	if (width <= 0)
+		return text;
+
+	for (pos = text; *pos != '\0'; pos++) {
+		gint char_width = gdk_text_width (chunk->bit->font, pos, 1);
+		if ((width > total) && (width <= total + char_width)) {
+			if (width < total + (char_width >> 1))
+				return pos;
+			else
+				return ++pos;
+		}
+		total += char_width;
+	}
+
+	return pos;
+}
+
+static GString*
+append_to_sel (GString          *string,
+	       struct line_info *chunk,
+	       gboolean          smileys)
+{
+	GString *new_string;
+	gchar *buf;
+	gchar *start;
+	gint length;
+
+	switch (chunk->bit->type) {
+	case TYPE_TEXT:
+	case TYPE_COMMENT:
+		start = (chunk->sel_start == NULL) ? chunk->text : chunk->sel_start;
+		length = (chunk->sel_end == NULL) ? strlen (start) : chunk->sel_end - start;
+		if (length <= 0)
+			return string;
+		buf = g_strndup (start, length);
+		break;
+	case TYPE_SMILEY:
+		if (smileys) {
+			start = (chunk->sel_start == NULL) ? chunk->bit->text : chunk->sel_start;
+			length = (chunk->sel_end == NULL) ? strlen (start) : chunk->sel_end - start;
+			if (length <= 0)
+				return string;
+			buf = g_strndup (start, length);
+		} else {
+			start = (chunk->sel_start == NULL) ? chunk->text : chunk->sel_start;
+			length = (chunk->sel_end == NULL) ? strlen (start) : chunk->sel_end - start;
+			if (length <= 0)
+				return string;
+			buf = g_strndup (start, length);
+		}
+		break;
+	case TYPE_BR:
+		buf = g_strdup ("\n");
+		break;
+	default:
+		return string;
+		break;
+	}
+
+	new_string = g_string_append (string, buf);
+	g_free (buf);
+
+	return new_string;
+}
+
+#define COORDS_IN_CHUNK(xx, yy) (((xx) < chunk->x + chunk->width) && \
+				 ((yy) < chunk->y + chunk->height))
+
+static void
+gtk_imhtml_select_bits (GtkIMHtml *imhtml)
+{
+	GList *bits;
+	GList *chunks;
+	GtkIMHtmlBit *bit;
+	struct line_info *chunk;
+	GtkWidget *darea;
+
+	guint startx = imhtml->sel_startx,
+	      starty = imhtml->sel_starty,
+	      endx   = imhtml->sel_endx,
+	      endy   = imhtml->sel_endy;
+	gchar *new_pos;
+	gint selection = 0;
+	gboolean smileys = imhtml->smileys;
+	gboolean redraw = FALSE;
+	gboolean got_start = FALSE;
+	gboolean got_end = FALSE;
+
+	g_return_if_fail (GTK_IS_IMHTML (imhtml));
+
+	if (!imhtml->selection)
+		return;
+
+	if (imhtml->selected_text) {
+		g_string_free (imhtml->selected_text, TRUE);
+		imhtml->selected_text = g_string_new ("");
+	}
+
+	bits = imhtml->bits;
+	while (bits) {
+		bit = bits->data;
+		chunks = bit->chunks;
+
+		while (chunks) {
+			darea = chunks->data;
+			chunk = gtk_object_get_user_data (GTK_OBJECT (darea));
+
+			switch (selection) {
+			case 0:
+				if (COORDS_IN_CHUNK (startx, starty)) {
+					new_pos = get_position (chunk, startx, smileys);
+					if ( !chunk->selected ||
+					    (chunk->sel_start != new_pos) ||
+					    (chunk->sel_end != NULL))
+						redraw = TRUE;
+					chunk->selected = TRUE;
+					chunk->sel_start = new_pos;
+					chunk->sel_end = NULL;
+					selection++;
+					got_start = TRUE;
+				}
+
+				if (COORDS_IN_CHUNK (endx, endy)) {
+					if (got_start) {
+						new_pos = get_position (chunk, endx, smileys);
+						if (chunk->sel_end != new_pos)
+							redraw = TRUE;
+						if (chunk->sel_start > new_pos) {
+							chunk->sel_end = chunk->sel_start;
+							chunk->sel_start = new_pos;
+						} else
+							chunk->sel_end = new_pos;
+						selection = 2;
+						got_end = TRUE;
+					} else {
+						new_pos = get_position (chunk, endx, smileys);
+						if ( !chunk->selected ||
+						    (chunk->sel_start != new_pos) ||
+						    (chunk->sel_end != NULL))
+							redraw = TRUE;
+						chunk->selected = TRUE;
+						chunk->sel_start = new_pos;
+						chunk->sel_end = NULL;
+						selection++;
+						got_end = TRUE;
+					}
+				} else if (!COORDS_IN_CHUNK (startx, starty) && !got_start) {
+					if (chunk->selected)
+						redraw = TRUE;
+					chunk->selected = FALSE;
+					chunk->sel_start = chunk->text;
+					chunk->sel_end = NULL;
+				}
+
+				break;
+			case 1:
+				if (!got_start && COORDS_IN_CHUNK (startx, starty)) {
+					new_pos = get_position (chunk, startx, smileys);
+					if ( !chunk->selected ||
+					    (chunk->sel_end != new_pos) ||
+					    (chunk->sel_start != chunk->text))
+						redraw = TRUE;
+					chunk->selected = TRUE;
+					chunk->sel_start = chunk->text;
+					chunk->sel_end = new_pos;
+					selection++;
+					got_start = TRUE;
+				} else if (!got_end && COORDS_IN_CHUNK (endx, endy)) {
+					new_pos = get_position (chunk, endx, smileys);
+					if ( !chunk->selected ||
+					    (chunk->sel_end != new_pos) ||
+					    (chunk->sel_start != chunk->text))
+						redraw = TRUE;
+					chunk->selected = TRUE;
+					chunk->sel_start = chunk->text;
+					chunk->sel_end = new_pos;
+					selection++;
+					got_end = TRUE;
+				} else {
+					if ( !chunk->selected ||
+					    (chunk->sel_end != new_pos) ||
+					    (chunk->sel_start != NULL))
+						redraw = TRUE;
+					chunk->selected = TRUE;
+					chunk->sel_start = chunk->text;
+					chunk->sel_end = NULL;
+				}
+
+				break;
+			case 2:
+				if ( chunk->selected ||
+				    (chunk->sel_start != chunk->text) ||
+				    (chunk->sel_end != NULL))
+					redraw = TRUE;
+				chunk->selected = FALSE;
+				chunk->sel_start = chunk->text;
+				chunk->sel_end = NULL;
+				break;
+			}
+
+			if (chunk->selected == TRUE)
+				imhtml->selected_text = append_to_sel (imhtml->selected_text,
+								       chunk, smileys);
+
+			if (redraw) {
+				gtk_widget_queue_draw (darea);
+				redraw = FALSE;
+			}
+
+			chunks = g_list_next (chunks);
+		}
+
+		bits = g_list_next (bits);
+	}
+}
+
+static gint
+scroll_timeout (GtkIMHtml *imhtml)
+{
+	GdkEventMotion event;
+	gint x, y;
+	GdkModifierType mask;
+
+	imhtml->scroll_timer = 0;
+
+	gdk_window_get_pointer (imhtml->layout.bin_window, &x, &y, &mask);
+
+	if (mask & GDK_BUTTON1_MASK) {
+		event.is_hint = 0;
+		event.x = x;
+		event.y = y;
+		event.state = mask;
+
+		gtk_imhtml_motion_notify_event (GTK_WIDGET (imhtml), &event);
+	}
+
+	return FALSE;
+}
+
+static gint
+gtk_imhtml_motion_notify_event (GtkWidget      *widget,
+				GdkEventMotion *event)
+{
+	gint x, y;
+	GdkModifierType state;
+	GtkIMHtml *imhtml = GTK_IMHTML (widget);
+	GtkAdjustment *vadj = GTK_LAYOUT (widget)->vadjustment;
+	GtkAdjustment *hadj = GTK_LAYOUT (widget)->hadjustment;
+
+	if (event->is_hint)
+		gdk_window_get_pointer (event->window, &x, &y, &state);
+	else {
+		x = event->x + hadj->value;
+		y = event->y + vadj->value;
+		state = event->state;
+	}
+
+	if (state & GDK_BUTTON1_MASK) {
+		gint diff;
+		gint height = vadj->page_size;
+		gint yy = y - vadj->value;
+
+		if (((yy < 0) || (yy > height)) &&
+		    (imhtml->scroll_timer == 0) &&
+		    (vadj->upper > vadj->page_size)) {
+			imhtml->scroll_timer = gtk_timeout_add (100,
+								(GtkFunction) scroll_timeout,
+								imhtml);
+			diff = (yy < 0) ? (yy >> 1) : ((yy - height) >> 1);
+			gtk_adjustment_set_value (vadj,
+						  MIN (vadj->value + diff, vadj->upper - height + 20));
+		}
+
+		if (imhtml->selection) {
+			imhtml->sel_endx = MAX (x, 0);
+			imhtml->sel_endy = MAX (y, 0);
+			gtk_imhtml_select_bits (imhtml);
+		}
+	} else {
+		GList *urls = imhtml->urls;
+		struct url_widget *uw;
+
+		while (urls) {
+			uw = (struct url_widget *) urls->data;
+			if ((x > uw->x) && (x < uw->x + uw->width) &&
+			    (y > uw->y) && (y < uw->y + uw->height)) {
+				gdk_window_set_cursor (imhtml->layout.bin_window, imhtml->hand_cursor);
+				return TRUE;
+			}
+			urls = g_list_next (urls);
+		}
+	}
+
+	gdk_window_set_cursor (imhtml->layout.bin_window, imhtml->arrow_cursor);
+
+	return TRUE;
+}
+
+static gint
+gtk_imhtml_button_press_event (GtkWidget      *widget,
+			       GdkEventButton *event)
+{
+	GtkIMHtml *imhtml = GTK_IMHTML (widget);
+	GtkAdjustment *vadj = GTK_LAYOUT (widget)->vadjustment;
+	GtkAdjustment *hadj = GTK_LAYOUT (widget)->hadjustment;
+	gint x, y;
+
+	if (event->button == 1) {
+		x = event->x + hadj->value;
+		y = event->y + vadj->value;
+
+		imhtml->sel_startx = x;
+		imhtml->sel_starty = y;
+		imhtml->selection = TRUE;
+		gtk_imhtml_select_none (imhtml);
+	}
+
+	return TRUE;
+}
+
+static gint
+gtk_imhtml_button_release_event (GtkWidget      *widget,
+				 GdkEventButton *event)
+{
+	GtkIMHtml *imhtml = GTK_IMHTML (widget);
+	GtkAdjustment *vadj = GTK_LAYOUT (widget)->vadjustment;
+	GtkAdjustment *hadj = GTK_LAYOUT (widget)->hadjustment;
+	gint x, y;
+
+	if ((event->button == 1) && imhtml->selection) {
+		x = event->x + hadj->value;
+		y = event->y + vadj->value;
+
+		if ((x == imhtml->sel_startx) && (y == imhtml->sel_starty)) {
+			imhtml->sel_startx = imhtml->sel_starty = 0;
+			imhtml->selection = FALSE;
+			gtk_imhtml_select_none (imhtml);
+		} else {
+			imhtml->sel_endx = MAX (x, 0);
+			imhtml->sel_endy = MAX (y, 0);
+			gtk_imhtml_select_bits (imhtml);
+		}
+
+		gtk_selection_owner_set (widget, GDK_SELECTION_PRIMARY, event->time);
+	}
+
+	return TRUE;
+}
+
+static void
+gtk_imhtml_selection_get (GtkWidget        *widget,
+			  GtkSelectionData *sel_data,
+			  guint             sel_info,
+			  guint32           time)
+{
+	GtkIMHtml *imhtml;
+	gchar *string;
+	gint length;
+
+	g_return_if_fail (widget != NULL);
+	g_return_if_fail (GTK_IS_IMHTML (widget));
+	g_return_if_fail (sel_data->selection == GDK_SELECTION_PRIMARY);
+
+	imhtml = GTK_IMHTML (widget);
+
+	g_return_if_fail (imhtml->selected_text != NULL);
+	g_return_if_fail (imhtml->selected_text->str != NULL);
+
+	if (imhtml->selected_text->len <= 0) {
+		string = NULL;
+		length = 0;
+	} else {
+		string = g_strdup (imhtml->selected_text->str);
+		length = strlen (string);
+	}
+
+	if (sel_info == TARGET_STRING) {
+		gtk_selection_data_set (sel_data,
+					GDK_SELECTION_TYPE_STRING,
+					8 * sizeof (gchar),
+					(guchar *) string,
+					length);
+	} else if ((sel_info == TARGET_TEXT) || (sel_info == TARGET_COMPOUND_TEXT)) {
+		guchar *text;
+		GdkAtom encoding;
+		gint format;
+		gint new_length;
+
+		gdk_string_to_compound_text (string, &encoding, &format, &text, &new_length);
+		gtk_selection_data_set (sel_data, encoding, format, text, new_length);
+		gdk_free_compound_text (text);
+	}
+
+	if (string)
+		g_free (string);
+}
+
+static gint
+gtk_imhtml_selection_clear_event (GtkWidget         *widget,
+				  GdkEventSelection *event)
+{
+	GtkIMHtml *imhtml;
+
+	g_return_val_if_fail (widget != NULL, FALSE);
+	g_return_val_if_fail (GTK_IS_IMHTML (widget), FALSE);
+	g_return_val_if_fail (event != NULL, FALSE);
+	g_return_val_if_fail (event->selection == GDK_SELECTION_PRIMARY, TRUE);
+
+	if (!gtk_selection_clear (widget, event))
+		return FALSE;
+
+	imhtml = GTK_IMHTML (widget);
+
+	gtk_imhtml_select_none (imhtml);
+
+	return TRUE;
+}
+
+static void
+gtk_imhtml_set_scroll_adjustments (GtkLayout     *layout,
+				   GtkAdjustment *hadj,
+				   GtkAdjustment *vadj)
+{
+	if (parent_class->set_scroll_adjustments)
+		(* parent_class->set_scroll_adjustments) (layout, hadj, vadj);
+}
+
+static void
+gtk_imhtml_class_init (GtkIMHtmlClass *class)
+{
+	GtkObjectClass *object_class;
+	GtkWidgetClass *widget_class;
+	GtkLayoutClass *layout_class;
+
+	object_class = (GtkObjectClass*) class;
+	widget_class = (GtkWidgetClass*) class;
+	layout_class = (GtkLayoutClass*) class;
+
+	parent_class = gtk_type_class (GTK_TYPE_LAYOUT);
+
+	signals [URL_CLICKED] =
+		gtk_signal_new ("url_clicked",
+				GTK_RUN_FIRST,
+				object_class->type,
+				GTK_SIGNAL_OFFSET (GtkIMHtmlClass, url_clicked),
+				gtk_marshal_NONE__POINTER,
+				GTK_TYPE_NONE, 1,
+				GTK_TYPE_POINTER);
+
+	gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
+
+	object_class->destroy = gtk_imhtml_destroy;
+
+	widget_class->realize = gtk_imhtml_realize;
+	widget_class->unrealize = gtk_imhtml_unrealize;
+	widget_class->draw = gtk_imhtml_draw;
+	widget_class->style_set = gtk_imhtml_style_set;
+	widget_class->expose_event  = gtk_imhtml_expose;
+	widget_class->size_allocate = gtk_imhtml_size_allocate;
+	widget_class->motion_notify_event = gtk_imhtml_motion_notify_event;
+	widget_class->button_press_event = gtk_imhtml_button_press_event;
+	widget_class->button_release_event = gtk_imhtml_button_release_event;
+	widget_class->selection_get = gtk_imhtml_selection_get;
+	widget_class->selection_clear_event = gtk_imhtml_selection_clear_event;
+
+	layout_class->set_scroll_adjustments = gtk_imhtml_set_scroll_adjustments;
+}
+
+static GdkFont*
+gtk_imhtml_font_load (GtkIMHtml *imhtml,
+		      gchar     *name,
+		      gboolean   bold,
+		      gboolean   italics,
+		      gint       fontsize)
+{
+	gchar buf [16 * 1024];
+	GdkFont *font;
+	gint size = fontsize ? font_sizes [MIN (fontsize, MAX_SIZE) - 1] : 120;
+
+	g_snprintf (buf, sizeof (buf), "-*-%s-%s-%c-*-*-*-%d-*-*-*-*-*-*",
+		    name ? name : DEFAULT_FONT_NAME,
+		    bold ? "bold" : "medium",
+		    italics ? 'i' : 'r',
+		    size);
+	font = gdk_font_load (buf);
+	if (font)
+		return font;
+
+	if (italics) {
+		g_snprintf (buf, sizeof (buf), "-*-%s-%s-%c-*-*-*-%d-*-*-*-*-*-*",
+			    name ? name : DEFAULT_FONT_NAME,
+			    bold ? "bold" : "medium",
+			    'o',
+			    size);
+		font = gdk_font_load (buf);
+		if (font)
+			return font;
+
+		if (bold) {
+			g_snprintf (buf, sizeof (buf), "-*-%s-%s-%c-*-*-*-%d-*-*-*-*-*-*",
+				    name ? name : DEFAULT_FONT_NAME,
+				    "bold",
+				    'r',
+				    size);
+			font = gdk_font_load (buf);
+			if (font)
+				return font;
+		}
+	}
+
+	if (bold) {
+		g_snprintf (buf, sizeof (buf), "-*-%s-%s-%c-*-*-*-%d-*-*-*-*-*-*",
+			    name ? name : DEFAULT_FONT_NAME,
+			    "medium",
+			    italics ? 'i' : 'r',
+			    size);
+		font = gdk_font_load (buf);
+		if (font)
+			return font;
+
+		if (italics) {
+			g_snprintf (buf, sizeof (buf), "-*-%s-%s-%c-*-*-*-%d-*-*-*-*-*-*",
+				    name ? name : DEFAULT_FONT_NAME,
+				    "medium",
+				    'o',
+				    size);
+			font = gdk_font_load (buf);
+			if (font)
+				return font;
+		}
+	}
+
+	if (!bold && !italics) {
+		g_snprintf (buf, sizeof (buf), "-*-%s-medium-r-*-*-*-%d-*-*-*-*-*-*",
+			    name ? name : DEFAULT_FONT_NAME,
+			    size);
+		font = gdk_font_load (buf);
+		if (font)
+			return font;
+	}
+
+	g_snprintf (buf, sizeof (buf), "-*-%s-medium-r-*-*-*-%d-*-*-*-*-*-*",
+		    DEFAULT_FONT_NAME,
+		    size);
+	font = gdk_font_load (buf);
+	if (font)
+		return font;
+
+	if (imhtml->default_font)
+		return gdk_font_ref (imhtml->default_font);
+
+	return NULL;
+}
+
+static void
+gtk_imhtml_init (GtkIMHtml *imhtml)
+{
+	static const GtkTargetEntry targets [] = {
+		{ "STRING", 0, TARGET_STRING },
+		{ "TEXT", 0, TARGET_TEXT },
+		{ "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }
+	};
+
+	imhtml->default_font = gtk_imhtml_font_load (imhtml, NULL, FALSE, FALSE, 0);
+	if (imhtml->default_font == NULL)
+		g_warning ("GtkIMHtml: Could not load default font!");
+	imhtml->default_fg_color = gdk_color_copy (&GTK_WIDGET (imhtml)->style->black);
+	imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2);
+	imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR);
+
+	GTK_WIDGET_SET_FLAGS (GTK_WIDGET (imhtml), GTK_CAN_FOCUS);
+	gtk_selection_add_targets (GTK_WIDGET (imhtml), GDK_SELECTION_PRIMARY, targets, 3);
+}
+
+GtkType
+gtk_imhtml_get_type (void)
+{
+	static GtkType imhtml_type = 0;
+
+	if (!imhtml_type) {
+		static const GtkTypeInfo imhtml_info = {
+			"GtkIMHtml",
+			sizeof (GtkIMHtml),
+			sizeof (GtkIMHtmlClass),
+			(GtkClassInitFunc) gtk_imhtml_class_init,
+			(GtkObjectInitFunc) gtk_imhtml_init,
+			NULL,
+			NULL,
+			NULL
+		};
+
+		imhtml_type = gtk_type_unique (GTK_TYPE_LAYOUT, &imhtml_info);
+	}
+
+	return imhtml_type;
+}
+
+static void
+gtk_imhtml_init_smiley_hash (GtkIMHtml *imhtml)
+{
+	g_return_if_fail (imhtml != NULL);
+	g_return_if_fail (GTK_IS_IMHTML (imhtml));
+
+	imhtml->smiley_hash = g_hash_table_new (g_str_hash, g_str_equal);
+
+	gtk_imhtml_associate_smiley (imhtml, ":)", smile_xpm);
+	gtk_imhtml_associate_smiley (imhtml, ":-)", smile_xpm);
+
+	gtk_imhtml_associate_smiley (imhtml, ":(", sad_xpm);
+	gtk_imhtml_associate_smiley (imhtml, ":-(", sad_xpm);
+
+	gtk_imhtml_associate_smiley (imhtml, ";)", wink_xpm);
+	gtk_imhtml_associate_smiley (imhtml, ";-)", wink_xpm);
+
+	gtk_imhtml_associate_smiley (imhtml, ":-p", tongue_xpm);
+	gtk_imhtml_associate_smiley (imhtml, ":-P", tongue_xpm);
+
+	gtk_imhtml_associate_smiley (imhtml, "=-O", scream_xpm);
+	gtk_imhtml_associate_smiley (imhtml, ":-*", kiss_xpm);
+	gtk_imhtml_associate_smiley (imhtml, ">:o", yell_xpm);
+	gtk_imhtml_associate_smiley (imhtml, "8-)", smile8_xpm);
+	gtk_imhtml_associate_smiley (imhtml, ":-$", moneymouth_xpm);
+	gtk_imhtml_associate_smiley (imhtml, ":-!", burp_xpm);
+	gtk_imhtml_associate_smiley (imhtml, ":-[", embarrassed_xpm);
+	gtk_imhtml_associate_smiley (imhtml, ":'(", cry_xpm);
+
+	gtk_imhtml_associate_smiley (imhtml, ":-/", think_xpm);
+	gtk_imhtml_associate_smiley (imhtml, ":-\\", think_xpm);
+
+	gtk_imhtml_associate_smiley (imhtml, ":-X", crossedlips_xpm);
+	gtk_imhtml_associate_smiley (imhtml, ":-D", bigsmile_xpm);
+	gtk_imhtml_associate_smiley (imhtml, "O:-)", angel_xpm);
+}
+
+GtkWidget*
+gtk_imhtml_new (GtkAdjustment *hadj,
+		GtkAdjustment *vadj)
+{
+	GtkIMHtml *imhtml = gtk_type_new (GTK_TYPE_IMHTML);
+
+	gtk_imhtml_set_adjustments (imhtml, hadj, vadj);
+
+	imhtml->bits = NULL;
+	imhtml->urls = NULL;
+
+	imhtml->x = BORDER_SIZE;
+	imhtml->y = BORDER_SIZE + 10;
+	imhtml->llheight = 0;
+	imhtml->llascent = 0;
+	imhtml->line = NULL;
+
+	imhtml->selected_text = g_string_new ("");
+	imhtml->scroll_timer = 0;
+
+	imhtml->img = NULL;
+
+	imhtml->smileys = TRUE;
+	imhtml->comments = FALSE;
+
+	imhtml->smin = G_MAXINT;
+	imhtml->smax = 0;
+	gtk_imhtml_init_smiley_hash (imhtml);
+
+	return GTK_WIDGET (imhtml);
+}
+
+void
+gtk_imhtml_set_adjustments (GtkIMHtml     *imhtml,
+			    GtkAdjustment *hadj,
+			    GtkAdjustment *vadj)
+{
+	gtk_layout_set_hadjustment (GTK_LAYOUT (imhtml), hadj);
+	gtk_layout_set_vadjustment (GTK_LAYOUT (imhtml), vadj);
+}
+
+void
+gtk_imhtml_set_defaults (GtkIMHtml *imhtml,
+			 GdkFont   *font,
+			 GdkColor  *fg_color)
+{
+	g_return_if_fail (imhtml != NULL);
+	g_return_if_fail (GTK_IS_IMHTML (imhtml));
+
+	if (font) {
+		if (imhtml->default_font)
+			gdk_font_unref (imhtml->default_font);
+		imhtml->default_font = gdk_font_ref (font);
+	}
+
+	if (fg_color) {
+		if (imhtml->default_fg_color)
+			gdk_color_free (imhtml->default_fg_color);
+		imhtml->default_fg_color = gdk_color_copy (fg_color);
+	}
+}
+
+void
+gtk_imhtml_set_img_handler (GtkIMHtml      *imhtml,
+			    GtkIMHtmlImage  handler)
+{
+	g_return_if_fail (imhtml != NULL);
+	g_return_if_fail (GTK_IS_IMHTML (imhtml));
+
+	imhtml->img = handler;
+}
+
+void
+gtk_imhtml_associate_smiley (GtkIMHtml  *imhtml,
+			     gchar      *text,
+			     gchar     **xpm)
+{
+	g_return_if_fail (imhtml != NULL);
+	g_return_if_fail (GTK_IS_IMHTML (imhtml));
+	g_return_if_fail (text != NULL);
+
+	if (strlen (text) < imhtml->smin)
+		imhtml->smin = strlen (text);
+
+	if (strlen (text) > imhtml->smax)
+		imhtml->smax = strlen (text);
+
+	if (xpm == NULL)
+		g_hash_table_remove (imhtml->smiley_hash, text);
+	else
+		g_hash_table_insert (imhtml->smiley_hash, text, xpm);
+}
+
+static gint
+draw_text (GtkWidget *widget,
+	   GdkEvent  *event,
+	   gpointer   data)
+{
+	GtkIMHtmlBit *bit;
+	struct line_info *line;
+	GdkGC *gc;
+	GdkColormap *cmap;
+
+	line = gtk_object_get_user_data (GTK_OBJECT (widget));
+	bit = line->bit;
+	gc = gdk_gc_new (widget->window);
+	cmap = gdk_colormap_new (gdk_visual_get_best (), FALSE);
+
+	if (bit->bg != NULL) {
+		gdk_color_alloc (cmap, bit->bg);
+		gdk_gc_set_foreground (gc, bit->bg);
+	} else
+		gdk_gc_copy (gc, widget->style->white_gc);
+
+	gdk_draw_rectangle (widget->window, gc, TRUE, 0, 0,
+			    widget->allocation.width,
+			    widget->allocation.height);
+
+	if (!line->text) {
+		gdk_colormap_unref (cmap);
+		gdk_gc_unref (gc);
+		return TRUE;
+	}
+
+	if (bit->back != NULL) {
+		gdk_color_alloc (cmap, bit->back);
+		gdk_gc_set_foreground (gc, bit->back);
+		gdk_draw_rectangle (widget->window, gc, TRUE, 0, 0,
+				    gdk_string_width (bit->font, line->text),
+				    widget->allocation.height);
+	}
+
+	if (line->selected) {
+		gint width, x;
+		gchar *start, *end;
+		GdkColor col;
+
+		if ((line->sel_start > line->sel_end) && (line->sel_end != NULL)) {
+			start = line->sel_end;
+			end = line->sel_start;
+		} else {
+			start = line->sel_start;
+			end = line->sel_end;
+		}
+
+		if (start == NULL)
+			x = 0;
+		else
+			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);
+
+		gdk_draw_rectangle (widget->window, gc, TRUE, x, 0,
+				    width, widget->allocation.height);
+	}
+
+	if (bit->url) {
+		GdkColor *tc = gtk_imhtml_get_color ("#0000a0");
+		gdk_color_alloc (cmap, tc);
+		gdk_gc_set_foreground (gc, tc);
+		gdk_color_free (tc);
+	} else if (bit->fore) {
+		gdk_color_alloc (cmap, bit->fore);
+		gdk_gc_set_foreground (gc, bit->fore);
+	} else
+		gdk_gc_copy (gc, widget->style->black_gc);
+
+	gdk_draw_string (widget->window, bit->font, gc,
+			 0, line->ascent, line->text);
+
+	if (bit->underline || bit->url)
+		gdk_draw_rectangle (widget->window, gc, TRUE,
+				    0, line->ascent + 1,
+				    gdk_string_width (bit->font, line->text), 1);
+	if (bit->strike)
+		gdk_draw_rectangle (widget->window, gc, TRUE,
+				    0, line->ascent - (bit->font->ascent >> 1),
+				    gdk_string_width (bit->font, line->text), 1);
+
+	gdk_colormap_unref (cmap);
+	gdk_gc_unref (gc);
+
+	return TRUE;
+}
+
+static gint
+draw_img (GtkWidget *widget,
+	  GdkEvent  *event,
+	  gpointer   data)
+{
+	GtkIMHtmlBit *bit;
+	struct line_info *line;
+	GdkGC *gc;
+	GdkColormap *cmap;
+	gint width, height, hoff;
+
+	line = gtk_object_get_user_data (GTK_OBJECT (widget));
+	bit = line->bit;
+	gdk_window_get_size (bit->pm, &width, &height);
+	hoff = (widget->allocation.height - height) / 2;
+	gc = gdk_gc_new (widget->window);
+	cmap = gdk_colormap_new (gdk_visual_get_best (), FALSE);
+
+	if (bit->bg != NULL) {
+		gdk_color_alloc (cmap, bit->bg);
+		gdk_gc_set_foreground (gc, bit->bg);
+	} else
+		gdk_gc_copy (gc, widget->style->white_gc);
+
+	gdk_draw_rectangle (widget->window, gc, TRUE, 0, 0,
+			    widget->allocation.width,
+			    widget->allocation.height);
+
+	if (bit->back != NULL) {
+		gdk_color_alloc (cmap, bit->back);
+		gdk_gc_set_foreground (gc, bit->back);
+		gdk_draw_rectangle (widget->window, gc, TRUE, 0, 0,
+				    width, widget->allocation.height);
+	}
+
+	gdk_draw_pixmap (widget->window, gc, bit->pm, 0, 0, 0, hoff, -1, -1);
+
+	gdk_colormap_unref (cmap);
+	gdk_gc_unref (gc);
+
+	return TRUE;
+}
+
+static gint
+draw_line (GtkWidget *widget,
+	   GdkEvent  *event,
+	   gpointer   data)
+{
+	GtkIMHtmlBit *bit;
+	GdkDrawable *drawable;
+	GdkColormap *cmap;
+	GdkGC *gc;
+	guint max_width;
+	guint max_height;
+
+	bit = data;
+	drawable = widget->window;
+	cmap = gdk_colormap_new (gdk_visual_get_best (), FALSE);
+	gc = gdk_gc_new (drawable);
+
+	if (bit->bg != NULL) {
+		gdk_color_alloc (cmap, bit->bg);
+		gdk_gc_set_foreground (gc, bit->bg);
+
+		gdk_draw_rectangle (widget->window, gc, TRUE, 0, 0,
+				    widget->allocation.width,
+				    widget->allocation.height);
+	}
+
+	gdk_gc_copy (gc, widget->style->black_gc);
+
+	max_width = widget->allocation.width;
+	max_height = widget->allocation.height / 2;
+
+	gdk_draw_rectangle (drawable, gc,
+			    TRUE,
+			    0, max_height / 2,
+			    max_width, max_height);
+
+	gdk_colormap_unref (cmap);
+	gdk_gc_unref (gc);
+
+	return TRUE;
+}
+
+static gint
+click_event_box (GtkBin         *bin,
+		 GdkEventButton *event,
+		 GtkIMHtml      *imhtml)
+{
+	struct line_info *li = gtk_object_get_user_data (GTK_OBJECT (bin->child));
+
+	if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
+		gtk_signal_emit (GTK_OBJECT (imhtml), signals [URL_CLICKED], li->bit->url);
+
+	return TRUE;
+}
+
+static void
+new_line (GtkIMHtml *imhtml)
+{
+	GList *last = g_list_last (imhtml->line);
+	GtkWidget *widget;
+	struct line_info *li;
+
+	if (last) {
+		widget = last->data;
+		li = gtk_object_get_user_data (GTK_OBJECT (widget));
+		if (li->x + li->width != imhtml->xsize - BORDER_SIZE) {
+			li->width = imhtml->xsize - BORDER_SIZE - li->x;
+			gtk_widget_set_usize (widget, li->width, li->height);
+		}
+	}
+
+	last = imhtml->line;
+	if (last) {
+		widget = last->data;
+		li = gtk_object_get_user_data (GTK_OBJECT (widget));
+		if (li->height < MIN_HEIGHT) {
+			while (last) {
+				gint diff;
+				widget = last->data;
+				li = gtk_object_get_user_data (GTK_OBJECT (widget));
+				diff = MIN_HEIGHT - li->height;
+				li->height = MIN_HEIGHT;
+				gtk_widget_set_usize (widget, li->width, li->height);
+				li->ascent += diff >> 1;
+				last = g_list_next (last);
+			}
+			imhtml->llheight = MIN_HEIGHT;
+		}
+	}
+
+	g_list_free (imhtml->line);
+	imhtml->line = NULL;
+
+	imhtml->x = BORDER_SIZE;
+	imhtml->y += imhtml->llheight;
+}
+
+static void
+backwards_update (GtkIMHtml    *imhtml,
+		  GtkIMHtmlBit *bit,
+		  gint          height,
+		  gint          ascent)
+{
+	gint diff;
+	GList *ls = NULL;
+	struct line_info *li;
+	struct url_widget *uw;
+
+	if (height > imhtml->llheight) {
+		diff = height - imhtml->llheight;
+
+		ls = imhtml->line;
+		while (ls) {
+			GtkWidget *data = ls->data;
+			li = gtk_object_get_user_data (GTK_OBJECT (data));
+			li->height += diff;
+			if (ascent)
+				li->ascent = ascent;
+			else
+				li->ascent += diff >> 1;
+			gtk_widget_set_usize (data, li->width, li->height);
+			ls = g_list_next (ls);
+		}
+
+		ls = imhtml->urls;
+		while (ls) {
+			uw = ls->data;
+			if (uw->y + diff > imhtml->y)
+				uw->y += diff;
+			ls = g_list_next (ls);
+		}
+
+		imhtml->llheight = height;
+		if (ascent)
+			imhtml->llascent = ascent;
+		else
+			imhtml->llascent += diff >> 1;
+	}
+}
+
+static GtkTooltips *tips = NULL;
+
+static void
+add_text_renderer (GtkIMHtml    *imhtml,
+		   GtkIMHtmlBit *bit,
+		   gchar        *text)
+{
+	GtkWidget *darea;
+	GtkWidget *eventbox;
+	struct line_info *li;
+	struct url_widget *uw;
+	gint width;
+
+	if (text)
+		width = gdk_string_width (bit->font, text);
+	else
+		width = 0;
+
+	darea = gtk_drawing_area_new ();
+	gtk_widget_set_usize (darea, width, imhtml->llheight);
+	gtk_signal_connect (GTK_OBJECT (darea), "expose_event", GTK_SIGNAL_FUNC (draw_text), NULL);
+
+	li = g_new0 (struct line_info, 1);
+	li->x = imhtml->x;
+	li->y = imhtml->y;
+	li->width = width;
+	li->height = imhtml->llheight;
+	if (text)
+		li->ascent = MAX (imhtml->llascent, bit->font->ascent);
+	else
+		li->ascent = 0;
+	li->text = text;
+	li->bit = bit;
+
+	gtk_object_set_user_data (GTK_OBJECT (darea), li);
+
+	if (bit->url) {
+		eventbox = gtk_event_box_new ();
+		gtk_layout_put (GTK_LAYOUT (imhtml), eventbox, imhtml->x, imhtml->y);
+		gtk_signal_connect (GTK_OBJECT (eventbox), "button_press_event",
+				    GTK_SIGNAL_FUNC (click_event_box), imhtml);
+		gtk_widget_show (eventbox);
+
+		gtk_container_add (GTK_CONTAINER (eventbox), darea);
+
+		uw = g_new0 (struct url_widget, 1);
+		uw->x = imhtml->x;
+		uw->y = imhtml->y;
+		uw->width = width;
+		uw->height = imhtml->llheight;
+		uw->url = bit->url;
+		imhtml->urls = g_list_append (imhtml->urls, uw);
+
+		if (!tips)
+			tips = gtk_tooltips_new ();
+		gtk_tooltips_set_tip (tips, eventbox, bit->url, "");
+	} else {
+		gtk_layout_put (GTK_LAYOUT (imhtml), darea, imhtml->x, imhtml->y);
+	}
+
+	bit->chunks = g_list_append (bit->chunks, darea);
+	imhtml->line = g_list_append (imhtml->line, darea);
+	gtk_widget_show (darea);
+
+	if (bit->bg) {
+		GdkColormap *cmap;
+
+		cmap = gdk_colormap_new (gdk_visual_get_best (), FALSE);
+		gdk_color_alloc (cmap, bit->bg);
+		gdk_window_set_background (darea->window, bit->bg);
+		gdk_colormap_unref (cmap);
+	} else
+		gdk_window_set_background (darea->window, &darea->style->white);
+}
+
+static void
+add_img_renderer (GtkIMHtml    *imhtml,
+		  GtkIMHtmlBit *bit)
+{
+	GtkWidget *darea;
+	GtkWidget *eventbox;
+	struct line_info *li;
+	struct url_widget *uw;
+	gint width;
+
+	gdk_window_get_size (bit->pm, &width, NULL);
+
+	darea = gtk_drawing_area_new ();
+	gtk_widget_set_usize (darea, width, imhtml->llheight);
+	gtk_signal_connect (GTK_OBJECT (darea), "expose_event", GTK_SIGNAL_FUNC (draw_img), NULL);
+
+	li = g_new0 (struct line_info, 1);
+	li->x = imhtml->x;
+	li->y = imhtml->y;
+	li->width = width;
+	li->height = imhtml->llheight;
+	li->ascent = 0;
+	li->bit = bit;
+
+	gtk_object_set_user_data (GTK_OBJECT (darea), li);
+
+	if (bit->url) {
+		eventbox = gtk_event_box_new ();
+		gtk_layout_put (GTK_LAYOUT (imhtml), eventbox, imhtml->x, imhtml->y);
+		gtk_signal_connect (GTK_OBJECT (eventbox), "button_press_event",
+				    GTK_SIGNAL_FUNC (click_event_box), imhtml);
+		gtk_widget_show (eventbox);
+
+		gtk_container_add (GTK_CONTAINER (eventbox), darea);
+
+		uw = g_new0 (struct url_widget, 1);
+		uw->x = imhtml->x;
+		uw->y = imhtml->y;
+		uw->width = width;
+		uw->height = imhtml->llheight;
+		uw->url = bit->url;
+		imhtml->urls = g_list_append (imhtml->urls, uw);
+
+		if (!tips)
+			tips = gtk_tooltips_new ();
+		gtk_tooltips_set_tip (tips, eventbox, bit->url, "");
+	} else {
+		gtk_layout_put (GTK_LAYOUT (imhtml), darea, imhtml->x, imhtml->y);
+	}
+
+	bit->chunks = g_list_append (bit->chunks, darea);
+	imhtml->line = g_list_append (imhtml->line, darea);
+	gtk_widget_show (darea);
+
+	if (bit->bg) {
+		GdkColormap *cmap;
+
+		cmap = gdk_colormap_new (gdk_visual_get_best (), FALSE);
+		gdk_color_alloc (cmap, bit->bg);
+		gdk_window_set_background (darea->window, bit->bg);
+		gdk_colormap_unref (cmap);
+	} else
+		gdk_window_set_background (darea->window, &darea->style->white);
+
+	imhtml->x += width;
+}
+
+static void
+gtk_imhtml_draw_bit (GtkIMHtml    *imhtml,
+		     GtkIMHtmlBit *bit)
+{
+	gint width, height;
+	GdkWindow *window;
+	GdkGC *gc;
+
+	g_return_if_fail (imhtml != NULL);
+	g_return_if_fail (GTK_IS_IMHTML (imhtml));
+	g_return_if_fail (bit != NULL);
+
+	window = GTK_LAYOUT (imhtml)->bin_window;
+	gc = gdk_gc_new (window);
+
+	if ( (bit->type == TYPE_TEXT) ||
+	    ((bit->type == TYPE_SMILEY) && !imhtml->smileys) ||
+	    ((bit->type == TYPE_COMMENT) && imhtml->comments)) {
+		gchar *copy = g_strdup (bit->text);
+		gint pos = 0;
+		gboolean seenspace = FALSE;
+		gchar *tmp;
+
+		height = bit->font->ascent + bit->font->descent;
+		width = gdk_string_width (bit->font, bit->text);
+
+		if ((imhtml->x != BORDER_SIZE) &&
+				((imhtml->x + width + BORDER_SIZE + BORDER_SIZE + 5) > imhtml->xsize)) {
+			gint remain = imhtml->xsize - imhtml->x - BORDER_SIZE - BORDER_SIZE - 5;
+			while (gdk_text_width (bit->font, copy, pos) < remain) {
+				if (copy [pos] == ' ')
+					seenspace = TRUE;
+				pos++;
+			}
+			if (seenspace) {
+				while (copy [pos - 1] != ' ') pos--;
+
+				tmp = g_strndup (copy, pos);
+
+				backwards_update (imhtml, bit, height, bit->font->ascent);
+				add_text_renderer (imhtml, bit, tmp);
+			} else
+				pos = 0;
+			seenspace = FALSE;
+			new_line (imhtml);
+			imhtml->llheight = 0;
+			imhtml->llascent = 0;
+		}
+
+		backwards_update (imhtml, bit, height, bit->font->ascent);
+
+		while (pos < strlen (bit->text)) {
+			width = gdk_string_width (bit->font, copy + pos);
+			if (imhtml->x + width + BORDER_SIZE + BORDER_SIZE + 5 > imhtml->xsize) {
+				gint newpos = 0;
+				gint remain = imhtml->xsize - imhtml->x - BORDER_SIZE - BORDER_SIZE - 5;
+				while (gdk_text_width (bit->font, copy + pos, newpos) < remain) {
+					if (copy [pos + newpos] == ' ')
+						seenspace = TRUE;
+					newpos++;
+				}
+
+				if (seenspace)
+					while (copy [pos + newpos - 1] != ' ') newpos--;
+
+				if (newpos == 0)
+					break;
+
+				tmp = g_strndup (copy + pos, newpos);
+				pos += newpos;
+
+				add_text_renderer (imhtml, bit, tmp);
+
+				seenspace = FALSE;
+				new_line (imhtml);
+			} else {
+				tmp = g_strdup (copy + pos);
+
+				add_text_renderer (imhtml, bit, tmp);
+
+				pos = strlen (bit->text);
+
+				imhtml->x += width;
+			}
+		}
+
+		g_free (copy);
+	} else if ((bit->type == TYPE_SMILEY) || (bit->type == TYPE_IMG)) {
+		gdk_window_get_size (bit->pm, &width, &height);
+
+		if ((imhtml->x != BORDER_SIZE) &&
+				((imhtml->x + width + BORDER_SIZE + BORDER_SIZE + 5) > imhtml->xsize)) {
+			new_line (imhtml);
+			imhtml->llheight = 0;
+			imhtml->llascent = 0;
+		} else
+			backwards_update (imhtml, bit, height, height * 3 / 4);
+
+		add_img_renderer (imhtml, bit);
+	} else if (bit->type == TYPE_BR) {
+		new_line (imhtml);
+		imhtml->llheight = 0;
+		imhtml->llascent = 0;
+		add_text_renderer (imhtml, bit, NULL);
+	} else if (bit->type == TYPE_SEP) {
+		GtkWidget *darea;
+		if (imhtml->llheight) {
+			new_line (imhtml);
+			imhtml->llheight = 0;
+			imhtml->llascent = 0;
+		}
+		darea = gtk_drawing_area_new ();
+		gtk_widget_set_usize (darea, imhtml->xsize - (BORDER_SIZE * 2), HR_HEIGHT * 2);
+		gtk_layout_put (GTK_LAYOUT (imhtml), darea, imhtml->x, imhtml->y);
+		gtk_signal_connect (GTK_OBJECT (darea), "expose_event",
+				    GTK_SIGNAL_FUNC (draw_line), bit);
+		gtk_widget_show (darea);
+		imhtml->llheight = HR_HEIGHT * 2;
+		new_line (imhtml);
+		imhtml->llheight = 0;
+		imhtml->llascent = 0;
+		add_text_renderer (imhtml, bit, NULL);
+	}
+
+	gtk_layout_set_size (GTK_LAYOUT (imhtml), imhtml->xsize, imhtml->y + 5);
+
+	gdk_gc_destroy (gc);
+}
+
+void
+gtk_imhtml_show_smileys (GtkIMHtml *imhtml,
+			 gboolean   show)
+{
+	g_return_if_fail (imhtml != NULL);
+	g_return_if_fail (GTK_IS_IMHTML (imhtml));
+
+	imhtml->smileys = show;
+
+	if (GTK_WIDGET_VISIBLE (GTK_WIDGET (imhtml)))
+		gtk_imhtml_redraw_all (imhtml);
+}
+
+void
+gtk_imhtml_show_comments (GtkIMHtml *imhtml,
+			  gboolean   show)
+{
+	g_return_if_fail (imhtml != NULL);
+	g_return_if_fail (GTK_IS_IMHTML (imhtml));
+
+	imhtml->comments = show;
+
+	if (GTK_WIDGET_VISIBLE (GTK_WIDGET (imhtml)))
+		gtk_imhtml_redraw_all (imhtml);
+}
+
+static GdkColor *
+gtk_imhtml_get_color (const gchar *color)
+{
+	GdkColor c;
+	gboolean valid = TRUE;
+
+	g_return_val_if_fail (color != NULL, NULL);
+
+	c.red = 0; c.green = 0; c.blue = 0;
+
+	if (!g_strcasecmp (color, "aliceblue")) {
+		c.red = 0xf000; c.green = 0xf800; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "antiquewhite")) {
+		c.red = 0xfa00; c.green = 0xeb00; c.blue = 0xd700;
+	} else if (!g_strcasecmp (color, "aqua")) {
+		c.red = 0; c.green = 0xff00; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "aquamarine")) {
+		c.red = 0; c.green = 0xff00; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "azure")) {
+		c.red = 0xf000; c.green = 0xff00; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "beige")) {
+		c.red = 0xf500; c.green = 0xf500; c.blue = 0xdc00;
+	} else if (!g_strcasecmp (color, "bisque")) {
+		c.red = 0xff00; c.green = 0xe400; c.blue = 0xc400;
+	} else if (!g_strcasecmp (color, "black")) {
+		c.red = 0; c.green = 0; c.blue = 0;
+	} else if (!g_strcasecmp (color, "blanchedalmond")) {
+		c.red = 0xff00; c.green = 0xeb00; c.blue = 0xcd00;
+	} else if (!g_strcasecmp (color, "blue")) {
+		c.red = 0; c.green = 0; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "blueviolet")) {
+		c.red = 0; c.green = 0; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "brown")) {
+		c.red = 0xa500; c.green = 0x2a00; c.blue = 0x2a00;
+	} else if (!g_strcasecmp (color, "burlywood")) {
+		c.red = 0xde00; c.green = 0xb800; c.blue = 0x8700;
+	} else if (!g_strcasecmp (color, "cadetblue")) {
+		c.red = 0x5f00; c.green = 0x9e00; c.blue = 0xa000;
+	} else if (!g_strcasecmp (color, "chartreuse")) {
+		c.red = 0x7f00; c.green = 0xff00; c.blue = 0;
+	} else if (!g_strcasecmp (color, "chocolate")) {
+		c.red = 0xd200; c.green = 0x6900; c.blue = 0x1e00;
+	} else if (!g_strcasecmp (color, "coral")) {
+		c.red = 0xff00; c.green = 0x7f00; c.blue = 0x5000;
+	} else if (!g_strcasecmp (color, "cornflowerblue")) {
+		c.red = 0x6400; c.green = 0x9500; c.blue = 0xed00;
+	} else if (!g_strcasecmp (color, "cornsilk")) {
+		c.red = 0xff00; c.green = 0xf800; c.blue = 0xdc00;
+	} else if (!g_strcasecmp (color, "crimson")) {
+		c.red = 0xdc00; c.green = 0x1400; c.blue = 0x3c00;
+	} else if (!g_strcasecmp (color, "cyan")) {
+		c.red = 0; c.green = 0xff00; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "darkblue")) {
+		c.red = 0; c.green = 0; c.blue = 0x8b00;
+	} else if (!g_strcasecmp (color, "darkcyan")) {
+		c.red = 0; c.green = 0x8b00; c.blue = 0x8b00;
+	} else if (!g_strcasecmp (color, "darkgoldenrod")) {
+		c.red = 0xb800; c.green = 0x8600; c.blue = 0x0b00;
+	} else if (!g_strcasecmp (color, "darkgray")) {
+		c.red = 0xa900; c.green = 0xa900; c.blue = 0xa900;
+	} else if (!g_strcasecmp (color, "darkgreen")) {
+		c.red = 0; c.green = 0x6400; c.blue = 0;
+	} else if (!g_strcasecmp (color, "darkkhaki")) {
+		c.red = 0xbd00; c.green = 0xb700; c.blue = 0x6b00;
+	} else if (!g_strcasecmp (color, "darkmagenta")) {
+		c.red = 0x8b00; c.green = 0; c.blue = 0x8b00;
+	} else if (!g_strcasecmp (color, "darkolivegreen")) {
+		c.red = 0x5500; c.green = 0x6b00; c.blue = 0x2f00;
+	} else if (!g_strcasecmp (color, "darkorange")) {
+		c.red = 0xff00; c.green = 0x8c00; c.blue = 0;
+	} else if (!g_strcasecmp (color, "darkorchid")) {
+		c.red = 0x9900; c.green = 0x3200; c.blue = 0xcc00;
+	} else if (!g_strcasecmp (color, "darkred")) {
+		c.red = 0x8b00; c.green = 0; c.blue = 0;
+	} else if (!g_strcasecmp (color, "darksalmon")) {
+		c.red = 0xe900; c.green = 0x9600; c.blue = 0x7a00;
+	} else if (!g_strcasecmp (color, "darkseagreen")) {
+		c.red = 0x8f00; c.green = 0xbc00; c.blue = 0x8f00;
+	} else if (!g_strcasecmp (color, "darkslateblue")) {
+		c.red = 0x4800; c.green = 0x3d00; c.blue = 0x8b00;
+	} else if (!g_strcasecmp (color, "darkslategray")) {
+		c.red = 0x2f00; c.green = 0x4f00; c.blue = 0x4f00;
+	} else if (!g_strcasecmp (color, "darkturquoise")) {
+		c.red = 0; c.green = 0xce00; c.blue = 0xd100;
+	} else if (!g_strcasecmp (color, "darkviolet")) {
+		c.red = 0x9400; c.green = 0; c.blue = 0xd300;
+	} else if (!g_strcasecmp (color, "deeppink")) {
+		c.red = 0xff00; c.green = 0x1400; c.blue = 0x9300;
+	} else if (!g_strcasecmp (color, "deepskyblue")) {
+		c.red = 0; c.green = 0xbf00; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "dimgray")) {
+		c.red = 0x6900; c.green = 0x6900; c.blue = 0x6900;
+	} else if (!g_strcasecmp (color, "dodgerblue")) {
+		c.red = 0x1e00; c.green = 0x9000; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "firebrick")) {
+		c.red = 0xb200; c.green = 0x2200; c.blue = 0x2200;
+	} else if (!g_strcasecmp (color, "floralwhite")) {
+		c.red = 0xff00; c.green = 0xfa00; c.blue = 0xf000;
+	} else if (!g_strcasecmp (color, "forestgreen")) {
+		c.red = 0x2200; c.green = 0x8b00; c.blue = 0x2200;
+	} else if (!g_strcasecmp (color, "fuchsia")) {
+		c.red = 0xff00; c.green = 0; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "gainsboro")) {
+		c.red = 0xdc00; c.green = 0xdc00; c.blue = 0xdc00;
+	} else if (!g_strcasecmp (color, "ghostwhite")) {
+		c.red = 0xf800; c.green = 0xf800; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "gold")) {
+		c.red = 0xff00; c.green = 0xd700; c.blue = 0;
+	} else if (!g_strcasecmp (color, "goldenrod")) {
+		c.red = 0xff00; c.green = 0xd700; c.blue = 0;
+	} else if (!g_strcasecmp (color, "gray")) {
+		c.red = 0x8000; c.green = 0x8000; c.blue = 0x8000;
+	} else if (!g_strcasecmp (color, "green")) {
+		c.red = 0; c.green = 0x8000; c.blue = 0;
+	} else if (!g_strcasecmp (color, "greenyellow")) {
+		c.red = 0; c.green = 0x8000; c.blue = 0;
+	} else if (!g_strcasecmp (color, "honeydew")) {
+		c.red = 0xf000; c.green = 0xff00; c.blue = 0xf000;
+	} else if (!g_strcasecmp (color, "hotpink")) {
+		c.red = 0xff00; c.green = 0x6900; c.blue = 0xb400;
+	} else if (!g_strcasecmp (color, "indianred")) {
+		c.red = 0xcd00; c.green = 0x5c00; c.blue = 0x5c00;
+	} else if (!g_strcasecmp (color, "indigo")) {
+		c.red = 0x4b00; c.green = 0; c.blue = 0x8200;
+	} else if (!g_strcasecmp (color, "ivory")) {
+		c.red = 0xff00; c.green = 0xff00; c.blue = 0xf000;
+	} else if (!g_strcasecmp (color, "khaki")) {
+		c.red = 0xf000; c.green = 0xe600; c.blue = 0x8c00;
+	} else if (!g_strcasecmp (color, "lavender")) {
+		c.red = 0xe600; c.green = 0xe600; c.blue = 0xfa00;
+	} else if (!g_strcasecmp (color, "lavenderblush")) {
+		c.red = 0xe600; c.green = 0xe600; c.blue = 0xfa00;
+	} else if (!g_strcasecmp (color, "lawngreen")) {
+		c.red = 0x7c00; c.green = 0xfc00; c.blue = 0;
+	} else if (!g_strcasecmp (color, "lemonchiffon")) {
+		c.red = 0xff00; c.green = 0xfa00; c.blue = 0xcd00;
+	} else if (!g_strcasecmp (color, "lightblue")) {
+		c.red = 0xad00; c.green = 0xd800; c.blue = 0xe600;
+	} else if (!g_strcasecmp (color, "lightcoral")) {
+		c.red = 0xf000; c.green = 0x8000; c.blue = 0x8000;
+	} else if (!g_strcasecmp (color, "lightcyan")) {
+		c.red = 0xe000; c.green = 0xff00; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "lightgoldenrodyellow")) {
+		c.red = 0xfa00; c.green = 0xfa00; c.blue = 0xd200;
+	} else if (!g_strcasecmp (color, "lightgreen")) {
+		c.red = 0x9000; c.green = 0xee00; c.blue = 0x9000;
+	} else if (!g_strcasecmp (color, "lightgray")) {
+		c.red = 0xd300; c.green = 0xd300; c.blue = 0xd300;
+	} else if (!g_strcasecmp (color, "lightpink")) {
+		c.red = 0xff00; c.green = 0xb600; c.blue = 0xc100;
+	} else if (!g_strcasecmp (color, "lightsalmon")) {
+		c.red = 0xff00; c.green = 0xa000; c.blue = 0x7a00;
+	} else if (!g_strcasecmp (color, "lightseagreen")) {
+		c.red = 0x2000; c.green = 0xb200; c.blue = 0xaa00;
+	} else if (!g_strcasecmp (color, "lightskyblue")) {
+		c.red = 0x8700; c.green = 0xce00; c.blue = 0xfa00;
+	} else if (!g_strcasecmp (color, "lightslategray")) {
+		c.red = 0x7700; c.green = 0x8800; c.blue = 0x9900;
+	} else if (!g_strcasecmp (color, "lightsteelblue")) {
+		c.red = 0xb000; c.green = 0xc400; c.blue = 0xde00;
+	} else if (!g_strcasecmp (color, "lightyellow")) {
+		c.red = 0xff00; c.green = 0xff00; c.blue = 0xe000;
+	} else if (!g_strcasecmp (color, "lime")) {
+		c.red = 0; c.green = 0xff00; c.blue = 0;
+	} else if (!g_strcasecmp (color, "limegreen")) {
+		c.red = 0; c.green = 0xff00; c.blue = 0;
+	} else if (!g_strcasecmp (color, "linen")) {
+		c.red = 0xfa00; c.green = 0xf000; c.blue = 0xe600;
+	} else if (!g_strcasecmp (color, "magenta")) {
+		c.red = 0xff00; c.green = 0; c.blue = 0xff00;
+	} else if (!g_strcasecmp (color, "maroon")) {
+		c.red = 0x8000; c.green = 0; c.blue = 0;
+	} else if (!g_strcasecmp (color, "mediumaquamarine")) {
+		c.red = 0x6600; c.green = 0xcd00; c.blue = 0xaa00;
+	} else if (!g_strcasecmp (color, "mediumblue")) {
+		c.red = 0; c.green = 0; c.blue = 0xcd00;
+	} else if (!g_strcasecmp (color, "mediumorchid")) {
+		c.red = 0xba00; c.green = 0x5500; c.blue = 0xd300;
+	} else if (!g_strcasecmp (color, "mediumpurple")) {
+		c.red = 0x93; c.green = 0x7000; c.blue = 0xdb00;
+	} else if (!g_strcasecmp (color, "mediumseagreen")) {
+		c.red = 0x3c00; c.green = 0xb300; c.blue = 0x7100;
+	} else if (!g_strcasecmp (color, "mediumslateblue")) {
+		c.red = 0x7b00; c.green = 0x6800; c.blue = 0xee00;
+	} else if (!g_strcasecmp (color, "mediumspringgreen")) {
+		c.red = 0; c.green = 0xfa00; c.blue = 0x9a00;
+	} else if (!g_strcasecmp (color, "mediumturquoise")) {
+		c.red = 0x4800; c.green = 0xd100; c.blue = 0xcc00;
+	} else if (!g_strcasecmp (color, "mediumvioletred")) {
+		c.red = 0xc700; c.green = 0x1500; c.blue = 0x8500;
+	} else if (!g_strcasecmp (color, "midnightblue")) {
+		c.red = 0x1900; c.green = 0x1900; c.blue = 0x7000;
+	} else if (!g_strcasecmp (color, "mintcream")) {
+		c.red = 0xf500; c.green = 0xff00; c.blue = 0xfa00;
+	} else if (!g_strcasecmp (color, "mistyrose")) {
+		c.red = 0xff00; c.green = 0xe400; c.blue = 0xe100;
+	} else if (!g_strcasecmp (color, "moccasin")) {
+		c.red = 0xff00; c.green = 0xe400; c.blue = 0xb500;
+	} else if (!g_strcasecmp (color, "navajowhite")) {
+		c.red = 0xff00; c.green = 0xde00; c.blue = 0xad00;
+	} else if (!g_strcasecmp (color, "navy")) {
+		c.red = 0; c.green = 0x8000; c.blue = 0;
+	} else if (!g_strcasecmp (color, "oldlace")) {
+		c.red = 0xfd00; c.green = 0xf500; c.blue = 0xe600;
+	} else if (!g_strcasecmp (color, "olive")) {
+		c.red = 0x8000; c.green = 0x8000; c.blue = 0;
+	} else if (!g_strcasecmp (color, "olivedrab")) {
+		c.red = 0x8000; c.green = 0x8000; c.blue = 0;
+	} else if (!g_strcasecmp (color, "orange")) {
+		c.red = 0xff00; c.green = 0xa500; c.blue = 0;
+	} else if (!g_strcasecmp (color, "orangered")) {
+		c.red = 0xff00; c.green = 0xa500; c.blue = 0;
+	} else if (!g_strcasecmp (color, "orchid")) {
+		c.red = 0xda00; c.green = 0x7000; c.blue = 0xd600;
+	} else if (!g_strcasecmp (color, "palegoldenrod")) {
+		c.red = 0xee00; c.green = 0xe800; c.blue = 0xaa00;
+	} else if (!g_strcasecmp (color, "palegreen")) {
+		c.red = 0x9800; c.green = 0xfb00; c.blue = 0x9800;
+	} else if (!g_strcasecmp (color, "paleturquoise")) {
+		c.red = 0xaf00; c.green = 0xee00; c.blue = 0xee00;
+	} else if (!g_strcasecmp (color, "palevioletred")) {
+		c.red = 0xdb00; c.green = 0x7000; c.blue = 0x9300;
+	} else if (!g_strcasecmp (color, "papayawhip")) {
+		c.red = 0xff00; c.green = 0xef00; c.blue = 0xd500;
+	} else if (!g_strcasecmp (color, "peachpuff")) {
+		c.red = 0xff00; c.green = 0xda00; c.blue = 0xb900;
+	} else if (!g_strcasecmp (color, "peru")) {
+		c.red = 0xcd00; c.green = 0x8500; c.blue = 0x3f00;
+	} else if (!g_strcasecmp (color, "pink")) {
+		c.red = 0xff00; c.green = 0xc000; c.blue = 0xcb00;
+	} else if (!g_strcasecmp (color, "plum")) {
+		c.red = 0xdd00; c.green = 0xa000; c.blue = 0xdd00;
+	} else if (!g_strcasecmp (color, "powderblue")) {
+		c.red = 0xb000; c.green = 0xe000; c.blue = 0xe600;
+	} else if (!g_strcasecmp (color, "purple")) {
+		c.red = 0x8000; c.green = 0; c.blue = 0x8000;
+	} else if (!g_strcasecmp (color, "red")) {
+		c.red = 0xff00; c.green = 0; c.blue = 0;
+	} else if (!g_strcasecmp (color, "rosybrown")) {
+		c.red = 0xbc00; c.green = 0x8f00; c.blue = 0x8f00;
+	} else if (!g_strcasecmp (color, "royalblue")) {
+		c.red = 0x4100; c.green = 0x6900; c.blue = 0xe100;
+	} else if (!g_strcasecmp (color, "saddlebrown")) {
+		c.red = 0x8b00; c.green = 0x4500; c.blue = 0x1300;
+	} else if (!g_strcasecmp (color, "salmon")) {
+		c.red = 0xfa00; c.green = 0x8000; c.blue = 0x7200;
+	} else if (!g_strcasecmp (color, "sandybrown")) {
+		c.red = 0xf400; c.green = 0xa400; c.blue = 0x6000;
+	} else if (!g_strcasecmp (color, "seagreen")) {
+		c.red = 0x2e00; c.green = 0x8b00; c.blue = 0x5700;
+	} else if (!g_strcasecmp (color, "seashell")) {
+		c.red = 0xff00; c.green = 0xf500; c.blue = 0xee00;
+	} else if (!g_strcasecmp (color, "sienna")) {
+		c.red = 0xa000; c.green = 0x5200; c.blue = 0x2d00;
+	} else if (!g_strcasecmp (color, "silver")) {
+		c.red = 0xc000; c.green = 0xc000; c.blue = 0xc000;
+	} else if (!g_strcasecmp (color, "skyblue")) {
+		c.red = 0x8700; c.green = 0xce00; c.blue = 0xeb00;
+	} else if (!g_strcasecmp (color, "slateblue")) {
+		c.red = 0x6a00; c.green = 0x5a00; c.blue = 0xcd00;
+	} else if (!g_strcasecmp (color, "slategray")) {
+		c.red = 0x7000; c.green = 0x8000; c.blue = 0x9000;
+	} else if (!g_strcasecmp (color, "springgreen")) {
+		c.red = 0; c.green = 0xff00; c.blue = 0x7f00;
+	} else if (!g_strcasecmp (color, "steelblue")) {
+		c.red = 0x4600; c.green = 0x8200; c.blue = 0xb400;
+	} else if (!g_strcasecmp (color, "teal")) {
+		c.red = 0; c.green = 0x8000; c.blue = 0x8000;
+	} else if (!g_strcasecmp (color, "thistle")) {
+		c.red = 0xd800; c.green = 0xbf00; c.blue = 0xd800;
+	} else if (!g_strcasecmp (color, "tomato")) {
+		c.red = 0xff00; c.green = 0x6300; c.blue = 0x4700;
+	} else if (!g_strcasecmp (color, "turquoise")) {
+		c.red = 0x4000; c.green = 0xe000; c.blue = 0xd000;
+	} else if (!g_strcasecmp (color, "violet")) {
+		c.red = 0xee00; c.green = 0x8200; c.blue = 0xee00;
+	} else if (!g_strcasecmp (color, "wheat")) {
+		c.red = 0xf500; c.green = 0xde00; c.blue = 0xb300;
+	} else if (!g_strcasecmp (color, "white")) {
+		c.red = 0xfe00; c.green = 0xfe00; c.blue = 0xfe00;
+	} else if (!g_strcasecmp (color, "whitesmoke")) {
+		c.red = 0xfe00; c.green = 0xfe00; c.blue = 0xfe00;
+	} else if (!g_strcasecmp (color, "yellow")) {
+		c.red = 0xff00; c.green = 0xff00; c.blue = 0;
+	} else if (!g_strcasecmp (color, "yellowgreen")) {
+		c.red = 0xff00; c.green = 0xff00; c.blue = 0;
+	} else {
+		const gchar *hex;
+		guint32 value;
+
+		if (color [0] == '#')
+			hex = color + 1;
+		else
+			hex = color;
+
+		if (strlen (hex) == 6) {
+			gint i = 0;
+			for ( ; i < 6; i++)
+				if (!isxdigit ((gint) hex [i]))
+					break;
+			if (i == 6) {
+				sscanf (hex, "%x", &value);
+				c.red = (value & 0xff0000) >> 8;
+				c.green = value & 0xff00;
+				c.blue = (value & 0xff) << 8;
+			} else {
+				valid = FALSE;
+			}
+		} else {
+			valid = FALSE;
+		}
+	}
+
+	if (valid)
+		return gdk_color_copy (&c);
+
+	return NULL;
+}
+
+static gint
+gtk_imhtml_is_smiley (GtkIMHtml   *imhtml,
+		      const gchar *text)
+{
+	gchar *tmp;
+	gint i;
+
+	g_return_val_if_fail (imhtml != NULL, 0);
+	g_return_val_if_fail (GTK_IS_IMHTML (imhtml), 0);
+	g_return_val_if_fail (text != NULL, 0);
+
+	tmp = g_malloc (imhtml->smax + 1);
+
+	for (i = imhtml->smin; i <= imhtml->smax; i++) {
+		if (strlen (text) < i) {
+			g_free (tmp);
+			return 0;
+		}
+		g_snprintf (tmp, i + 1, "%s", text);
+		if (g_hash_table_lookup (imhtml->smiley_hash, tmp)) {
+			g_free (tmp);
+			return i;
+		}
+	}
+
+	g_free (tmp);
+	return 0;
+}
+
+static GtkIMHtmlBit *
+gtk_imhtml_new_bit (GtkIMHtml  *imhtml,
+		    gint        type,
+		    gchar      *text,
+		    gint        bold,
+		    gint        italics,
+		    gint        underline,
+		    gint        strike,
+		    FontDetail *font,
+		    GdkColor   *bg,
+		    gchar      *url)
+{
+	GtkIMHtmlBit *bit = NULL;
+
+	g_return_val_if_fail (imhtml != NULL, NULL);
+	g_return_val_if_fail (GTK_IS_IMHTML (imhtml), NULL);
+
+	if ((type == TYPE_TEXT) && ((text == NULL) || (strlen (text) == 0)))
+		return NULL;
+
+	bit = g_new0 (GtkIMHtmlBit, 1);
+	bit->type = type;
+
+	if ((text != NULL) && (strlen (text) != 0))
+		bit->text = g_strdup (text);
+
+	if ((font != NULL) || bold || italics) {
+		if (font && (bold || italics || font->size || font->face)) {
+			bit->font = gtk_imhtml_font_load (imhtml, font->face, bold, italics, font->size);
+		} else if (bold || italics) {
+			bit->font = gtk_imhtml_font_load (imhtml, NULL, bold, italics, 0);
+		}
+
+		if (font && (type != TYPE_BR)) {
+			if (font->fore != NULL)
+				bit->fore = gdk_color_copy (font->fore);
+
+			if (font->back != NULL)
+				bit->back = gdk_color_copy (font->back);
+		}
+	}
+
+	if (((bit->type == TYPE_TEXT) || (bit->type == TYPE_SMILEY) || (bit->type == TYPE_COMMENT)) &&
+	    (bit->font == NULL))
+		bit->font = gdk_font_ref (imhtml->default_font);
+
+	if (bg != NULL)
+		bit->bg = gdk_color_copy (bg);
+
+	bit->underline = underline;
+	bit->strike = strike;
+
+	if (url != NULL)
+		bit->url = g_strdup (url);
+
+	if (type == TYPE_SMILEY) {
+		GdkColor *clr;
+
+		if ((font != NULL) && (font->back != NULL))
+			clr = font->back;
+		else
+			clr = (bg != NULL) ? bg : &GTK_WIDGET (imhtml)->style->white;
+
+		bit->pm = gdk_pixmap_create_from_xpm_d (GTK_WIDGET (imhtml)->window,
+							&bit->bm,
+							clr,
+							g_hash_table_lookup (imhtml->smiley_hash, text));
+	}
+
+	return bit;
+}
+
+#define NEW_TEXT_BIT    gtk_imhtml_new_bit (imhtml, TYPE_TEXT, ws, bold, italics, underline, strike, \
+				fonts ? fonts->data : NULL, bg, url)
+#define NEW_SMILEY_BIT  gtk_imhtml_new_bit (imhtml, TYPE_SMILEY, ws, bold, italics, underline, strike, \
+				fonts ? fonts->data : NULL, bg, url)
+#define NEW_SEP_BIT     gtk_imhtml_new_bit (imhtml, TYPE_SEP, NULL, 0, 0, 0, 0, NULL, bg, NULL)
+#define NEW_BR_BIT      gtk_imhtml_new_bit (imhtml, TYPE_BR, NULL, 0, 0, 0, 0, \
+				fonts ? fonts->data : NULL, bg, NULL)
+#define NEW_COMMENT_BIT gtk_imhtml_new_bit (imhtml, TYPE_COMMENT, ws, bold, italics, underline, strike, \
+				fonts ? fonts->data : NULL, bg, url)
+
+#define NEW_BIT(bit) { GtkIMHtmlBit *tmp = bit; if (tmp != NULL) \
+				newbits = g_list_append (newbits, tmp); }
+
+#define UPDATE_BG_COLORS \
+	{ \
+		GdkColormap *cmap; \
+		GList *rev; \
+		cmap = gdk_colormap_new (gdk_visual_get_best (), FALSE); \
+		rev = g_list_last (newbits); \
+		while (rev) { \
+			GtkIMHtmlBit *bit = rev->data; \
+			if (bit->type == TYPE_BR) \
+				break; \
+			if (bit->bg) \
+				gdk_color_free (bit->bg); \
+			bit->bg = gdk_color_copy (bg); \
+			rev = g_list_previous (rev); \
+		} \
+		if (!rev) { \
+			rev = g_list_last (imhtml->bits); \
+			while (rev) { \
+				GList *ln; \
+				GtkIMHtmlBit *bit = rev->data; \
+				if (bit->type == TYPE_BR) \
+					break; \
+				if (bit->bg) \
+					gdk_color_free (bit->bg); \
+				bit->bg = gdk_color_copy (bg); \
+				gdk_color_alloc (cmap, bit->bg); \
+				ln = bit->chunks; \
+				while (ln) { \
+					GtkWidget *widget = ln->data; \
+					gdk_window_set_background (widget->window, bit->bg); \
+					ln = g_list_next (ln); \
+				} \
+				rev = g_list_previous (rev); \
+			} \
+			gdk_colormap_unref (cmap); \
+		} \
+	}
+
+GString*
+gtk_imhtml_append_text (GtkIMHtml        *imhtml,
+			const gchar      *text,
+			GtkIMHtmlOptions  options)
+{
+	const gchar *c;
+	gboolean intag = FALSE;
+	gboolean tagquote = FALSE;
+	gboolean incomment = FALSE;
+	gchar *ws;
+	gchar *tag;
+	gint wpos = 0;
+	gint tpos = 0;
+	int smilelen;
+	GList *newbits = NULL;
+
+	guint	bold = 0,
+		italics = 0,
+		underline = 0,
+		strike = 0,
+		sub = 0,
+		sup = 0,
+		title = 0;
+	GSList *fonts = NULL;
+	GdkColor *bg = NULL;
+	gchar *url = NULL;
+
+	GtkAdjustment *vadj;
+	gboolean scrolldown = TRUE;
+
+	GString *retval = NULL;
+
+	g_return_val_if_fail (imhtml != NULL, NULL);
+	g_return_val_if_fail (GTK_IS_IMHTML (imhtml), NULL);
+	g_return_val_if_fail (text != NULL, NULL);
+
+	if (options & GTK_IMHTML_RETURN_LOG)
+		retval = g_string_new ("");
+
+	vadj = GTK_LAYOUT (imhtml)->vadjustment;
+	if ((vadj->value < imhtml->y + 5 - GTK_WIDGET (imhtml)->allocation.height) &&
+	    (vadj->upper >= GTK_WIDGET (imhtml)->allocation.height))
+		scrolldown = FALSE;
+
+	c = text;
+	ws = g_malloc (strlen (text) + 1);
+	tag = g_malloc (strlen (text) + 1);
+
+	ws [0] = '\0';
+
+	while (*c) {
+		if (*c == '<') {
+			if (intag) {
+				ws [wpos] = 0;
+				tag [tpos] = 0;
+				tpos = 0;
+				strcat (ws, tag);
+				wpos = strlen (ws);
+			}
+
+			if (incomment) {
+				ws [wpos++] = *c++;
+				continue;
+			}
+
+			if (!g_strncasecmp (c, "<!--", strlen ("<!--"))) {
+				if (!(options & GTK_IMHTML_NO_COMMENTS)) {
+					ws [wpos] = 0;
+					wpos = 0;
+					tag [tpos] = 0;
+					strcat (tag, ws);
+					incomment = TRUE;
+					intag = FALSE;
+				}
+				ws [wpos++] = *c++;
+				ws [wpos++] = *c++;
+				ws [wpos++] = *c++;
+				ws [wpos++] = *c++;
+				continue;
+			}
+
+			tag [tpos++] = *c++;
+			intag = TRUE;
+		} else if (incomment && (*c == '-') && !g_strncasecmp (c, "-->", strlen ("-->"))) {
+			gchar *tmp;
+			ws [wpos] = 0;
+			wpos = 0;
+			tmp = g_strdup (ws);
+			ws [wpos] = 0;
+			strcat (ws, tag);
+			NEW_BIT (NEW_TEXT_BIT);
+			ws [wpos] = 0;
+			strcat (ws, tmp + strlen ("<!--"));
+			g_free (tmp);
+			NEW_BIT (NEW_COMMENT_BIT);
+			incomment = FALSE;
+			c += strlen ("-->");
+		} else if (*c == '>' && intag && !tagquote) {
+			gboolean got_tag = FALSE;
+			tag [tpos++] = *c++;
+			tag [tpos] = 0;
+			ws [wpos] = 0;
+
+			if (!g_strcasecmp (tag, "<B>") || !g_strcasecmp (tag, "<BOLD>")) {
+				got_tag = TRUE;
+				NEW_BIT (NEW_TEXT_BIT);
+				bold++;
+			} else if (!g_strcasecmp (tag, "</B>") || !g_strcasecmp (tag, "</BOLD>")) {
+				got_tag = TRUE;
+				if (bold) {
+					NEW_BIT (NEW_TEXT_BIT);
+					bold--;
+				}
+			} else if (!g_strcasecmp (tag, "<I>") || !g_strcasecmp (tag, "<ITALIC>")) {
+				got_tag = TRUE;
+				NEW_BIT (NEW_TEXT_BIT);
+				italics++;
+			} else if (!g_strcasecmp (tag, "</I>") || !g_strcasecmp (tag, "</ITALIC>")) {
+				got_tag = TRUE;
+				if (italics) {
+					NEW_BIT (NEW_TEXT_BIT);
+					italics--;
+				}
+			} else if (!g_strcasecmp (tag, "<U>") || !g_strcasecmp (tag, "<UNDERLINE>")) {
+				got_tag = TRUE;
+				NEW_BIT (NEW_TEXT_BIT);
+				underline++;
+			} else if (!g_strcasecmp (tag, "</U>") || !g_strcasecmp (tag, "</UNDERLINE>")) {
+				got_tag = TRUE;
+				if (underline) {
+					NEW_BIT (NEW_TEXT_BIT);
+					underline--;
+				}
+			} else if (!g_strcasecmp (tag, "<S>") || !g_strcasecmp (tag, "<STRIKE>")) {
+				got_tag = TRUE;
+				NEW_BIT (NEW_TEXT_BIT);
+				strike++;
+			} else if (!g_strcasecmp (tag, "</S>") || !g_strcasecmp (tag, "</STRIKE>")) {
+				got_tag = TRUE;
+				if (strike) {
+					NEW_BIT (NEW_TEXT_BIT);
+					strike--;
+				}
+			} else if (!g_strcasecmp (tag, "<SUB>")) {
+				got_tag = TRUE;
+				sub++;
+			} else if (!g_strcasecmp (tag, "</SUB>")) {
+				got_tag = TRUE;
+				if (sub) {
+					sub--;
+				}
+			} else if (!g_strcasecmp (tag, "<SUP>")) {
+				got_tag = TRUE;
+				sup++;
+			} else if (!g_strcasecmp (tag, "</SUP>")) {
+				got_tag = TRUE;
+				if (sup) {
+					sup--;
+				}
+			} else if (!g_strcasecmp (tag, "<TITLE>")) {
+				if (options & GTK_IMHTML_NO_TITLE) {
+					got_tag = TRUE;
+					title++;
+				} else {
+					intag = FALSE;
+					tpos = 0;
+					continue;
+				}
+			} else if (!g_strcasecmp (tag, "</TITLE>")) {
+				if (title) {
+					got_tag = TRUE;
+					wpos = 0;
+					ws [wpos] = '\0';
+					title--;
+				} else {
+					intag = FALSE;
+					tpos = 0;
+					continue;
+				}
+			} else if (!g_strcasecmp (tag, "<BR>")) {
+				got_tag = TRUE;
+				NEW_BIT (NEW_TEXT_BIT);
+				NEW_BIT (NEW_BR_BIT);
+			} else if (!g_strcasecmp (tag, "<HR>") ||
+				   !g_strncasecmp (tag, "<HR ", strlen ("<HR "))) {
+				got_tag = TRUE;
+				NEW_BIT (NEW_TEXT_BIT);
+				NEW_BIT (NEW_SEP_BIT);
+			} else if (!g_strncasecmp (tag, "<FONT ", strlen ("<FONT "))) {
+				gchar *t, *e, *a, *value;
+				FontDetail *font = NULL;
+				GdkColor *clr;
+				gint saw;
+				gint i;
+
+				t = tag + strlen ("<FONT ");
+
+				while (*t != '\0') {
+					value = NULL;
+					saw = 0;
+
+					while (g_strncasecmp (t, "COLOR=", strlen ("COLOR="))
+					    && g_strncasecmp (t, "BACK=", strlen ("BACK="))
+					    && g_strncasecmp (t, "FACE=", strlen ("FACE="))
+					    && g_strncasecmp (t, "SIZE=", strlen ("SIZE="))) {
+						gboolean quote = FALSE;
+						if (*t == '\0') break;
+						while (*t && !((*t == ' ') && !quote)) {
+							if (*t == '\"')
+								quote = ! quote;
+							t++;
+						}
+						while (*t && (*t == ' ')) t++;
+					}
+
+					if (!g_strncasecmp (t, "COLOR=", strlen ("COLOR="))) {
+						t += strlen ("COLOR=");
+						saw = 1;
+					} else if (!g_strncasecmp (t, "BACK=", strlen ("BACK="))) {
+						t += strlen ("BACK=");
+						saw = 2;
+					} else if (!g_strncasecmp (t, "FACE=", strlen ("FACE="))) {
+						t += strlen ("FACE=");
+						saw = 3;
+					} else if (!g_strncasecmp (t, "SIZE=", strlen ("SIZE="))) {
+						t += strlen ("SIZE=");
+						saw = 4;
+					}
+
+					if (!saw)
+						continue;
+
+					if ((*t == '\"') || (*t == '\'')) {
+						e = a = ++t;
+						while (*e && (*e != *(t - 1))) e++;
+						if (*e != '\0') {
+							*e = '\0';
+							t = e + 1;
+							value = g_strdup (a);
+						} else {
+							*t = '\0';
+						}
+					} else {
+						e = a = t;
+						while (*e && !isspace ((gint) *e)) e++;
+						if (*e == '\0') e--;
+						*e = '\0';
+						t = e + 1;
+						value = g_strdup (a);
+					}
+
+					if (value == NULL)
+						continue;
+
+					if (font == NULL)
+						font = g_new0 (FontDetail, 1);
+
+					switch (saw) {
+					case 1:
+						clr = gtk_imhtml_get_color (value);
+						if (clr != NULL) {
+							if ( (font->fore == NULL) &&
+							    !(options & GTK_IMHTML_NO_COLOURS))
+								font->fore = clr;
+						}
+						break;
+					case 2:
+						clr = gtk_imhtml_get_color (value);
+						if (clr != NULL) {
+							if ( (font->back == NULL) &&
+							    !(options & GTK_IMHTML_NO_COLOURS))
+								font->back = clr;
+						}
+						break;
+					case 3:
+						if ( (font->face == NULL) &&
+						    !(options & GTK_IMHTML_NO_FONTS))
+							font->face = g_strdup (value);
+						break;
+					case 4:
+						if ((font->size != 0) ||
+						    (options & GTK_IMHTML_NO_SIZES))
+							break;
+
+						if (isdigit ((gint) value [0])) {
+							for (i = 0; i < strlen (value); i++)
+								if (!isdigit ((gint) value [i]))
+									break;
+							if (i != strlen (value))
+								break;
+
+							sscanf (value, "%hd", &font->size);
+							break;
+						}
+
+						if ((value [0] == '+') && (value [1] != '\0')) {
+							for (i = 1; i < strlen (value); i++)
+								if (!isdigit ((gint) value [i]))
+									break;
+							if (i != strlen (value))
+								break;
+
+							sscanf (value + 1, "%hd", &font->size);
+							font->size += 3;
+							break;
+						}
+
+						if ((value [0] == '-') && (value [1] != '\0')) {
+							for (i = 1; i < strlen (value); i++)
+								if (!isdigit ((gint) value [i]))
+									break;
+							if (i != strlen (value))
+								break;
+
+							sscanf (value + 1, "%hd", &font->size);
+							font->size = MIN (font->size, 2);
+							font->size = 3 - font->size;
+							break;
+						}
+
+						break;
+					}
+
+					g_free (value);
+				}
+
+				if (!font) {
+					intag = FALSE;
+					tpos = 0;
+					continue;
+				}
+
+				if (!(font->size || font->face || font->fore || font->back)) {
+					g_free (font);
+					intag = FALSE;
+					tpos = 0;
+					continue;
+				}
+
+				NEW_BIT (NEW_TEXT_BIT);
+
+				if (fonts) {
+					FontDetail *oldfont = fonts->data;
+					if (!font->size)
+						font->size = oldfont->size;
+					if (!font->face)
+						font->face = g_strdup (oldfont->face);
+					if (!font->fore && oldfont->fore)
+						font->fore = gdk_color_copy (oldfont->fore);
+					if (!font->back && oldfont->back)
+						font->back = gdk_color_copy (oldfont->back);
+				} else {
+					if (!font->size)
+						font->size = 3;
+					if (!font->face)
+						font->face = g_strdup ("helvetica");
+				}
+
+				fonts = g_slist_prepend (fonts, font);
+				got_tag = TRUE;
+			} else if (!g_strcasecmp (tag, "</FONT>")) {
+				FontDetail *font;
+
+				if (fonts) {
+					got_tag = TRUE;
+					NEW_BIT (NEW_TEXT_BIT);
+					font = fonts->data;
+					fonts = g_slist_remove (fonts, font);
+					g_free (font->face);
+					if (font->fore)
+						gdk_color_free (font->fore);
+					if (font->back)
+						gdk_color_free (font->back);
+					g_free (font);
+				} else {
+					intag = FALSE;
+					tpos = 0;
+					continue;
+				}
+			} else if (!g_strncasecmp (tag, "<BODY ", strlen ("<BODY "))) {
+				gchar *t, *e, *color = NULL;
+				GdkColor *tmp;
+
+				got_tag = TRUE;
+
+				if (!(options & GTK_IMHTML_NO_COLOURS)) {
+					t = tag + strlen ("<BODY");
+					do {
+						gboolean quote = FALSE;
+						if (*t == '\0') break;
+						while (*t && !((*t == ' ') && !quote)) {
+							if (*t == '\"')
+								quote = ! quote;
+							t++;
+						}
+						while (*t && (*t == ' ')) t++;
+					} while (g_strncasecmp (t, "BGCOLOR=", strlen ("BGCOLOR=")));
+
+					if (!g_strncasecmp (t, "BGCOLOR=", strlen ("BGCOLOR="))) {
+						t += strlen ("BGCOLOR=");
+						if ((*t == '\"') || (*t == '\'')) {
+							e = ++t;
+							while (*e && (*e != *(t - 1))) e++;
+							if (*e != '\0') {
+								*e = '\0';
+								color = g_strdup (t);
+							}
+						} else {
+							e = t;
+							while (*e && !isspace ((gint) *e)) e++;
+							if (*e == '\0') e--;
+							*e = '\0';
+							color = g_strdup (t);
+						}
+
+						if (color != NULL) {
+							tmp = gtk_imhtml_get_color (color);
+							g_free (color);
+							if (tmp != NULL) {
+								NEW_BIT (NEW_TEXT_BIT);
+								bg = tmp;
+								UPDATE_BG_COLORS;
+							}
+						}
+					}
+				}
+			} else if (!g_strncasecmp (tag, "<A ", strlen ("<A "))) {
+				gchar *t, *e;
+
+				got_tag = TRUE;
+				NEW_BIT (NEW_TEXT_BIT);
+
+				if (url != NULL)
+					g_free (url);
+				url = NULL;
+
+				t = tag + strlen ("<A");
+				do {
+					gboolean quote = FALSE;
+					if (*t == '\0') break;
+					while (*t && !((*t == ' ') && !quote)) {
+						if (*t == '\"')
+							quote = ! quote;
+						t++;
+					}
+					while (*t && (*t == ' ')) t++;
+				} while (g_strncasecmp (t, "HREF=", strlen ("HREF=")));
+
+				if (!g_strncasecmp (t, "HREF=", strlen ("HREF="))) {
+					t += strlen ("HREF=");
+					if ((*t == '\"') || (*t == '\'')) {
+						e = ++t;
+						while (*e && (*e != *(t - 1))) e++;
+						if (*e != '\0') {
+							*e = '\0';
+							url = g_strdup (t);
+						}
+					} else {
+						e = t;
+						while (*e && !isspace ((gint) *e)) e++;
+						if (*e == '\0') e--;
+						*e = '\0';
+						url = g_strdup (t);
+					}
+				}
+			} else if (!g_strcasecmp (tag, "</A>")) {
+				got_tag = TRUE;
+				if (url != NULL) {
+					NEW_BIT (NEW_TEXT_BIT);
+					g_free (url);
+				}
+				url = NULL;
+			} else if (!g_strncasecmp (tag, "<IMG ", strlen ("<IMG "))) {
+				gchar *t, *e, *src = NULL;
+				gchar *copy = g_strdup (tag);
+				gchar **xpm;
+				GdkColor *clr = NULL;
+				GtkIMHtmlBit *bit;
+
+				intag = FALSE;
+				tpos = 0;
+
+				if (imhtml->img == NULL)
+					continue;
+
+				t = tag + strlen ("<IMG");
+				do {
+					gboolean quote = FALSE;
+					if (*t == '\0') break;
+					while (*t && !((*t == ' ') && !quote)) {
+						if (*t == '\"')
+							quote = ! quote;
+						t++;
+					}
+					while (*t && (*t == ' ')) t++;
+				} while (g_strncasecmp (t, "SRC=", strlen ("SRC=")));
+
+				if (!g_strncasecmp (t, "SRC=", strlen ("SRC="))) {
+					t += strlen ("SRC=");
+					if ((*t == '\"') || (*t == '\'')) {
+						e = ++t;
+						while (*e && (*e != *(t - 1))) e++;
+						if (*e != '\0') {
+							*e = '\0';
+							src = g_strdup (t);
+						}
+					} else {
+						e = t;
+						while (*e && !isspace ((gint) *e)) e++;
+						if (*e == '\0') e--;
+						*e = '\0';
+						src = g_strdup (t);
+					}
+				}
+
+				if (src == NULL) {
+					ws [wpos] = 0;
+					strcat (ws, copy);
+					wpos = strlen (ws);
+					g_free (copy);
+					continue;
+				}
+
+				xpm = (* imhtml->img) (src);
+				if (xpm == NULL) {
+					g_free (src);
+					ws [wpos] = 0;
+					strcat (ws, copy);
+					wpos = strlen (ws);
+					g_free (copy);
+					continue;
+				}
+
+				g_free (copy);
+
+				if (!fonts || ((clr = ((FontDetail *)fonts->data)->back) == NULL))
+					clr = (bg != NULL) ? bg : &GTK_WIDGET (imhtml)->style->white;
+
+				if (!GTK_WIDGET_REALIZED (imhtml))
+					gtk_widget_realize (GTK_WIDGET (imhtml));
+
+				bit = g_new0 (GtkIMHtmlBit, 1);
+				bit->type = TYPE_IMG;
+				bit->pm = gdk_pixmap_create_from_xpm_d (GTK_WIDGET (imhtml)->window,
+									&bit->bm,
+									clr,
+									xpm);
+				if (url)
+					bit->url = g_strdup (url);
+
+				NEW_BIT (bit);
+
+				g_free (src);
+
+				continue;
+			} else if (!g_strcasecmp (tag, "<P>") ||
+				   !g_strcasecmp (tag, "</P>") ||
+				   !g_strncasecmp (tag, "<P ", strlen ("<P ")) ||
+				   !g_strcasecmp (tag, "<PRE>") ||
+				   !g_strcasecmp (tag, "</PRE>") ||
+				   !g_strcasecmp (tag, "<HTML>") ||
+				   !g_strcasecmp (tag, "</HTML>") ||
+				   !g_strcasecmp (tag, "<BODY>") ||
+				   !g_strcasecmp (tag, "</BODY>") ||
+				   !g_strcasecmp (tag, "<FONT>") ||
+				   !g_strcasecmp (tag, "<HEAD>") ||
+				   !g_strcasecmp (tag, "</HEAD>")) {
+				intag = FALSE;
+				tpos = 0;
+				continue;
+			}
+
+			if (!got_tag) {
+				ws [wpos] = 0;
+				strcat (ws, tag);
+				wpos = strlen (ws);
+			} else {
+				wpos = 0;
+			}
+			intag = FALSE;
+			tpos = 0;
+		} else if (*c == '&' && !intag) {
+			if (!g_strncasecmp (c, "&amp;", 5)) {
+				ws [wpos++] = '&';
+				c += 5;
+			} else if (!g_strncasecmp (c, "&lt;", 4)) {
+				ws [wpos++] = '<';
+				c += 4;
+			} else if (!g_strncasecmp (c, "&gt;", 4)) {
+				ws [wpos++] = '>';
+				c += 4;
+			} else if (!g_strncasecmp (c, "&nbsp;", 6)) {
+				ws [wpos++] = ' ';
+				c += 6;
+			} else if (!g_strncasecmp (c, "&copy;", 6)) {
+				ws [wpos++] = '©';
+				c += 6;
+			} else if (!g_strncasecmp (c, "&quot;", 6)) {
+				ws [wpos++] = '\"';
+				c += 6;
+			} else if (!g_strncasecmp (c, "&reg;", 5)) {
+				ws [wpos++] = '®';
+				c += 5;
+			} else if (*(c + 1) == '#') {
+				gint pound = 0;
+				if (sscanf (c, "&#%d;", &pound) == 1) {
+					if (*(c + 3 + (gint)log10 (pound)) != ';') {
+						ws [wpos++] = *c++;
+						continue;
+					}
+					ws [wpos++] = (gchar)pound;
+					c += 2;
+					while (isdigit ((gint) *c)) c++;
+					if (*c == ';') c++;
+				} else {
+					ws [wpos++] = *c++;
+				}
+			} else {
+				ws [wpos++] = *c++;
+			}
+		} else if (intag) {
+			if (*c == '\"')
+				tagquote = !tagquote;
+			tag [tpos++] = *c++;
+		} else if (incomment) {
+			ws [wpos++] = *c++;
+		} else if (((smilelen = gtk_imhtml_is_smiley (imhtml, c)) != 0)) {
+			ws [wpos] = 0;
+			wpos = 0;
+			NEW_BIT (NEW_TEXT_BIT);
+			g_snprintf (ws, smilelen + 1, "%s", c);
+			NEW_BIT (NEW_SMILEY_BIT);
+			c += smilelen;
+		} else if (*c == '\n') {
+			if (!(options & GTK_IMHTML_NO_NEWLINE)) {
+				ws [wpos] = 0;
+				wpos = 0;
+				NEW_BIT (NEW_TEXT_BIT);
+				NEW_BIT (NEW_BR_BIT);
+			}
+			c++;
+		} else {
+			ws [wpos++] = *c++;
+		}
+	}
+
+	if (intag) {
+		tag [tpos] = 0;
+		c = tag;
+		while (*c) {
+			if ((smilelen = gtk_imhtml_is_smiley (imhtml, c)) != 0) {
+				ws [wpos] = 0;
+				wpos = 0;
+				NEW_BIT (NEW_TEXT_BIT);
+				g_snprintf (ws, smilelen + 1, "%s", c);
+				NEW_BIT (NEW_SMILEY_BIT);
+				c += smilelen;
+			} else {
+				ws [wpos++] = *c++;
+			}
+		}
+	} else if (incomment) {
+		ws [wpos] = 0;
+		wpos = 0;
+		strcat (tag, ws);
+		ws [wpos] = 0;
+		c = tag;
+		while (*c) {
+			if ((smilelen = gtk_imhtml_is_smiley (imhtml, c)) != 0) {
+				ws [wpos] = 0;
+				wpos = 0;
+				NEW_BIT (NEW_TEXT_BIT);
+				g_snprintf (ws, smilelen + 1, "%s", c);
+				NEW_BIT (NEW_SMILEY_BIT);
+				c += smilelen;
+			} else {
+				ws [wpos++] = *c++;
+			}
+		}
+	}
+
+	ws [wpos] = 0;
+	NEW_BIT (NEW_TEXT_BIT);
+
+	while (newbits) {
+		GtkIMHtmlBit *bit = newbits->data;
+		imhtml->bits = g_list_append (imhtml->bits, bit);
+		newbits = g_list_remove (newbits, bit);
+		gtk_imhtml_draw_bit (imhtml, bit);
+	}
+
+	gtk_widget_set_usize (GTK_WIDGET (imhtml), -1, imhtml->y + 5);
+
+	if (!(options & GTK_IMHTML_NO_SCROLL) &&
+	    scrolldown &&
+	    (imhtml->y + 5 >= GTK_WIDGET (imhtml)->allocation.height))
+		gtk_adjustment_set_value (vadj, imhtml->y + 5 - GTK_WIDGET (imhtml)->allocation.height);
+
+	if (url) {
+		g_free (url);
+		if (retval)
+			retval = g_string_append (retval, "</A>");
+	}
+	if (bg)
+		gdk_color_free (bg);
+	while (fonts) {
+		FontDetail *font = fonts->data;
+		fonts = g_slist_remove (fonts, font);
+		g_free (font->face);
+		if (font->fore)
+			gdk_color_free (font->fore);
+		if (font->back)
+			gdk_color_free (font->back);
+		g_free (font);
+		if (retval)
+			retval = g_string_append (retval, "</FONT>");
+	}
+	if (retval) {
+		while (bold) {
+			retval = g_string_append (retval, "</B>");
+			bold--;
+		}
+		while (italics) {
+			retval = g_string_append (retval, "</I>");
+			italics--;
+		}
+		while (underline) {
+			retval = g_string_append (retval, "</U>");
+			underline--;
+		}
+		while (strike) {
+			retval = g_string_append (retval, "</S>");
+			strike--;
+		}
+		while (sub) {
+			retval = g_string_append (retval, "</SUB>");
+			sub--;
+		}
+		while (sup) {
+			retval = g_string_append (retval, "</SUP>");
+			sup--;
+		}
+		while (title) {
+			retval = g_string_append (retval, "</TITLE>");
+			title--;
+		}
+	}
+	g_free (ws);
+	g_free (tag);
+
+	return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gtkimhtml.h	Fri Jan 26 02:02:36 2001 +0000
@@ -0,0 +1,127 @@
+/*
+ * GtkIMHtml
+ *
+ * Copyright (C) 2000, Eric Warmenhoven <warmenhoven@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * 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
+ *
+ */
+
+#ifndef __GTK_IMHTML_H
+#define __GTK_IMHTML_H
+
+#include <gdk/gdk.h>
+#include <gtk/gtklayout.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GTK_TYPE_IMHTML            (gtk_imhtml_get_type ())
+#define GTK_IMHTML(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_IMHTML, GtkIMHtml))
+#define GTK_IMHTML_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_IMHTML, GtkIMHtmlClass))
+#define GTK_IS_IMHTML(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_IMHTML))
+#define GTK_IS_IMHTML_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_IMHTML))
+
+typedef gchar** (*GtkIMHtmlImage) (gchar *url);
+
+typedef struct _GtkIMHtml      GtkIMHtml;
+typedef struct _GtkIMHtmlClass GtkIMHtmlClass;
+
+struct _GtkIMHtml {
+	GtkLayout layout;
+
+	GdkFont *default_font;
+	GdkColor *default_fg_color;
+
+	GdkCursor *hand_cursor;
+	GdkCursor *arrow_cursor;
+
+	GList *bits;
+	GList *urls;
+
+	guint sel_startx, sel_starty;
+	guint sel_endx, sel_endy;
+	gboolean selection;
+	GString *selected_text;
+	guint scroll_timer;
+
+	guint x, y;
+	guint xsize;
+	guint llheight;
+	guint llascent;
+	GList *line;
+
+	GtkIMHtmlImage img;
+
+	gboolean smileys;
+	gboolean comments;
+
+	GHashTable *smiley_hash;
+	gint smin, smax;
+};
+
+struct _GtkIMHtmlClass {
+	GtkLayoutClass parent_class;
+
+	void (*url_clicked) (GtkIMHtml *, const gchar *);
+};
+
+typedef enum
+{
+	GTK_IMHTML_NO_COLOURS   = 1 << 0,
+	GTK_IMHTML_NO_FONTS     = 1 << 1,
+	GTK_IMHTML_NO_COMMENTS  = 1 << 2,
+	GTK_IMHTML_NO_TITLE     = 1 << 3,
+	GTK_IMHTML_NO_NEWLINE   = 1 << 4,
+	GTK_IMHTML_NO_SIZES	= 1 << 5,
+	GTK_IMHTML_NO_SCROLL	= 1 << 6,
+	GTK_IMHTML_RETURN_LOG	= 1 << 7
+} GtkIMHtmlOptions;
+
+GtkType    gtk_imhtml_get_type         (void);
+GtkWidget* gtk_imhtml_new              (GtkAdjustment    *hadj,
+					GtkAdjustment    *vadj);
+
+void       gtk_imhtml_set_adjustments  (GtkIMHtml        *imhtml,
+					GtkAdjustment    *hadj,
+					GtkAdjustment    *vadj);
+
+void       gtk_imhtml_set_defaults     (GtkIMHtml        *imhtml,
+					GdkFont          *font,
+					GdkColor         *fg_color);
+
+void       gtk_imhtml_set_img_handler  (GtkIMHtml        *imhtml,
+					GtkIMHtmlImage    handler);
+
+void       gtk_imhtml_associate_smiley (GtkIMHtml        *imhtml,
+					gchar            *text,
+					gchar           **xpm);
+
+void       gtk_imhtml_show_smileys     (GtkIMHtml        *imhtml,
+					gboolean          show);
+
+void       gtk_imhtml_show_comments    (GtkIMHtml        *imhtml,
+					gboolean          show);
+
+GString*   gtk_imhtml_append_text      (GtkIMHtml        *imhtml,
+					const gchar      *text,
+					GtkIMHtmlOptions  options);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- a/src/prefs.c	Thu Jan 25 20:31:12 2001 +0000
+++ b/src/prefs.c	Fri Jan 26 02:02:36 2001 +0000
@@ -251,9 +251,9 @@
 
 	gaim_button(_("Show graphical smileys"), &display_options, OPT_DISP_SHOW_SMILEY, box);
 	gaim_button(_("Show timestamp on messages"), &display_options, OPT_DISP_SHOW_TIME, box);
-	gaim_button(_("Ignore incoming colors"), &display_options, OPT_DISP_IGNORE_COLOUR, box);
-	gaim_button(_("Ignore incoming fonts"), &display_options, OPT_DISP_IGNORE_FONTS, box);
-	gaim_button(_("Ignore white backgrounds"), &display_options, OPT_DISP_IGN_WHITE, box);
+	gaim_button(_("Ignore colors"), &display_options, OPT_DISP_IGNORE_COLOUR, box);
+	gaim_button(_("Ignore font faces"), &display_options, OPT_DISP_IGNORE_FONTS, box);
+	gaim_button(_("Ignore font sizes"), &display_options, OPT_DISP_IGNORE_SIZES, box);
 
 	sep = gtk_hseparator_new();
 	gtk_box_pack_start(GTK_BOX(box), sep, FALSE, FALSE, 5);
@@ -2066,6 +2066,12 @@
 	if (blist && ((int)option == OPT_DISP_SHOW_BUTTON_XPM))
 		update_button_pix();
 
+	if ((int)option == OPT_DISP_SHOW_SMILEY)
+		toggle_smileys();
+
+	if ((int)option == OPT_DISP_SHOW_TIME)
+		toggle_timestamps();
+
 #ifdef USE_APPLET
 	update_pixmaps();
 #endif