changeset 3922:30f52e7afd1d

[gaim-migrate @ 4094] This is gtkimhtml2--it's a subclass of gtktextview. It's not done yet. It doesn't do smileys or images, and what it does do so far, it doesn't do perfectly. But it's perfectly 100% usable, and like 80,000 times faster than gtkimhtml + Pango. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Fri, 08 Nov 2002 06:10:35 +0000
parents 67209a7ee924
children b8398b505b03
files src/away.c src/buddy_chat.c src/conversation.c src/dialogs.c src/gtkimhtml.c src/gtkimhtml.h src/prefs.c src/server.c
diffstat 8 files changed, 445 insertions(+), 3396 deletions(-) [+]
line wrap: on
line diff
--- a/src/away.c	Fri Nov 08 06:05:03 2002 +0000
+++ b/src/away.c	Fri Nov 08 06:10:35 2002 +0000
@@ -203,8 +203,6 @@
 
 		awaytext = gtk_imhtml_new(NULL, NULL);
 		gtk_container_add(GTK_CONTAINER(sw), awaytext);
-		GTK_LAYOUT(awaytext)->hadjustment->step_increment = 10.0;
-		GTK_LAYOUT(awaytext)->vadjustment->step_increment = 10.0;
 		gaim_setup_imhtml(awaytext);
 		gtk_widget_show(awaytext);
 		buf = stylize(a->message, BUF_LONG);
--- a/src/buddy_chat.c	Fri Nov 08 06:05:03 2002 +0000
+++ b/src/buddy_chat.c	Fri Nov 08 06:10:35 2002 +0000
@@ -1316,8 +1316,6 @@
 	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 (convo_options & OPT_CONVO_SHOW_TIME)
 		gtk_imhtml_show_comments(GTK_IMHTML(text), TRUE);
 	gaim_setup_imhtml(text);
--- a/src/conversation.c	Fri Nov 08 06:05:03 2002 +0000
+++ b/src/conversation.c	Fri Nov 08 06:10:35 2002 +0000
@@ -191,7 +191,7 @@
 	update_checkbox(c);
 	update_smilies(c);
 	plugin_event(event_new_conversation, name);
-	gtk_imhtml_to_bottom(GTK_IMHTML(c->text));
+	/*gtk_imhtml_to_bottom(c->text);*/
 	return c;
 }
 
@@ -2620,7 +2620,7 @@
 
 	update_convo_status(c);
 
-	gtk_imhtml_to_bottom(GTK_IMHTML(c->text));
+	/*gtk_imhtml_to_bottom(c->text);*/
 }
 
 void update_convo_status(struct conversation *c) {
@@ -2848,8 +2848,6 @@
 	text = gtk_imhtml_new(NULL, NULL);
 	c->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 (convo_options & OPT_CONVO_SHOW_TIME)
 		gtk_imhtml_show_comments(GTK_IMHTML(text), TRUE);
 	gaim_setup_imhtml(text);
--- a/src/dialogs.c	Fri Nov 08 06:05:03 2002 +0000
+++ b/src/dialogs.c	Fri Nov 08 06:10:35 2002 +0000
@@ -2365,8 +2365,6 @@
 		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;
 		gtk_widget_set_usize(sw, 300, 250);
 		gtk_imhtml_set_img_handler(GTK_IMHTML(text), info_img_handler);
 		gaim_setup_imhtml(text);
@@ -4227,8 +4225,6 @@
 
 	gtk_signal_connect(GTK_OBJECT(layout), "url_clicked", GTK_SIGNAL_FUNC(open_url), NULL);
 	gtk_container_add(GTK_CONTAINER(sw), layout);
-	GTK_LAYOUT(layout)->hadjustment->step_increment = 10.0;
-	GTK_LAYOUT(layout)->vadjustment->step_increment = 10.0;
 	gaim_setup_imhtml(layout);
 
 	gtk_box_pack_start(GTK_BOX(box), bbox, FALSE, FALSE, 0);
--- a/src/gtkimhtml.c	Fri Nov 08 06:05:03 2002 +0000
+++ b/src/gtkimhtml.c	Fri Nov 08 06:10:35 2002 +0000
@@ -23,15 +23,6 @@
 #include <config.h>
 #endif
 #include "gtkimhtml.h"
-
-#ifndef _WIN32
-#include <X11/Xlib.h>
-#include <gdk/gdkx.h>
-#else
-#include <gdk/gdkwin32.h>
-#endif
-
-#include <stdlib.h>
 #include <gtk/gtk.h>
 #include <string.h>
 #include <ctype.h>
@@ -42,2770 +33,143 @@
 #include <locale.h>
 #endif
 
-#ifdef _WIN32
-/* GDK_SELECTION_PRIMARY is ignored win32 GTK */
-#undef GDK_SELECTION_PRIMARY
-#define GDK_SELECTION_PRIMARY GDK_SELECTION_CLIPBOARD
-#endif
-
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <gdk-pixbuf/gdk-pixbuf-loader.h>
-
-#include <pango/pango.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 MAX_FONT_SIZE 7
-
-#define POINT_SIZE(x) (_point_sizes [MIN ((x), MAX_FONT_SIZE) - 1])
-static gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 };
-
-#define DEFAULT_PRE_FACE "sans"
-
-#define BORDER_SIZE 2
-#define TOP_BORDER 10
-#define MIN_HEIGHT 20
-#define HR_HEIGHT 2
-#define TOOLTIP_TIMEOUT 500
-
-#define DIFF(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
-#define COLOR_MOD  0x8000
-#define COLOR_DIFF 0x800
-
-#define TYPE_TEXT     0
-#define TYPE_SMILEY   1
-#define TYPE_IMG      2
-#define TYPE_SEP      3
-#define TYPE_BR       4
-#define TYPE_COMMENT  5
-
-#define  GTK_IMHTML_GET_STYLE_FONT(style) gtk_style_get_font (style)
-
-#define DRAW_IMG(x) (((x)->type == TYPE_IMG) || (imhtml->smileys && ((x)->type == TYPE_SMILEY)))
-
-typedef struct _GtkIMHtmlBit GtkIMHtmlBit;
-typedef struct _FontDetail   FontDetail;
-
-struct _GtkSmileyTree {
-	GString *values;
-	GtkSmileyTree **children;
-	gchar **image;
-};
-
-/*
- *  PROTOS
- */
-extern void debug_printf(char * fmt, ...);
-
-static GtkSmileyTree*
-gtk_smiley_tree_new ()
-{
-	return g_new0 (GtkSmileyTree, 1);
-}
-
-static void
-gtk_smiley_tree_insert (GtkSmileyTree *tree,
-			const gchar   *text,
-			gchar        **image)
-{
-	GtkSmileyTree *t = tree;
-	const gchar *x = text;
-
-	if (!strlen (x))
-		return;
-
-	while (*x) {
-		gchar *pos;
-		gint index;
-
-		if (!t->values)
-			t->values = g_string_new ("");
-
-		pos = strchr (t->values->str, *x);
-		if (!pos) {
-			t->values = g_string_append_c (t->values, *x);
-			index = t->values->len - 1;
-			t->children = g_realloc (t->children, t->values->len * sizeof (GtkSmileyTree *));
-			t->children [index] = g_new0 (GtkSmileyTree, 1);
-		} else
-			index = (int) pos - (int) t->values->str;
-
-		t = t->children [index];
-
-		x++;
-	}
-
-	t->image = image;
-}
-
-static void
-gtk_smiley_tree_remove (GtkSmileyTree *tree,
-			const gchar   *text)
-{
-	GtkSmileyTree *t = tree;
-	const gchar *x = text;
-	gint len = 0;
-
-	while (*x) {
-		gchar *pos;
-
-		if (!t->values)
-			return;
-
-		pos = strchr (t->values->str, *x);
-		if (pos)
-			t = t->children [(int) pos - (int) t->values->str];
-		else
-			return;
 
-		x++; len++;
-	}
-
-	if (t->image)
-		t->image = NULL;
-}
-
-static gint
-gtk_smiley_tree_lookup (GtkSmileyTree *tree,
-			const gchar   *text)
-{
-	GtkSmileyTree *t = tree;
-	const gchar *x = text;
-	gint len = 0;
-
-	while (*x) {
-		gchar *pos;
-
-		if (!t->values)
-			break;
-
-		pos = strchr (t->values->str, *x);
-		if (pos)
-			t = t->children [(int) pos - (int) t->values->str];
-		else
-			break;
-
-		x++; len++;
-	}
-
-	if (t->image)
-		return len;
-
-	return 0;
-}
-
-static gchar**
-gtk_smiley_tree_image (GtkSmileyTree *tree,
-		       const gchar   *text)
-{
-	GtkSmileyTree *t = tree;
-	const gchar *x = text;
-
-	while (*x) {
-		gchar *pos;
-
-		if (!t->values)
-			return NULL;
-
-		pos = strchr (t->values->str, *x);
-		if (pos) {
-			t = t->children [(int) pos - (int) t->values->str];
-		} else
-			return NULL;
-
-		x++;
-	}
-
-	return t->image;
-}
+/* POINT_SIZE converts from AIM font sizes to point sizes.  It probably should be redone in such a
+ * way that it base the sizes off the default font size rather than using arbitrary font sizes. */
+#define MAX_FONT_SIZE 7
+#define POINT_SIZE(x) (_point_sizes [MIN ((x), MAX_FONT_SIZE) - 1])
+static gint _point_sizes [] = { 4, 6, 8, 10, 20, 30, 40 };
 
-static void
-gtk_smiley_tree_destroy (GtkSmileyTree *tree)
-{
-	GSList *list = g_slist_append (NULL, tree);
-
-	while (list) {
-		GtkSmileyTree *t = list->data;
-		gint i;
-		list = g_slist_remove(list, t);
-		if (t->values) {
-			for (i = 0; i < t->values->len; i++)
-				list = g_slist_append (list, t->children [i]);
-			g_string_free (t->values, TRUE);
-			g_free (t->children);
-		}
-		g_free (t);
-	}
-}
-
-void
-gtk_imhtml_remove_smileys (GtkIMHtml *imhtml)
-{
-	g_return_if_fail (imhtml != NULL);
-	g_return_if_fail (GTK_IS_IMHTML (imhtml));
-
-	gtk_smiley_tree_destroy (imhtml->smiley_data);
-	imhtml->smiley_data = gtk_smiley_tree_new ();
-}
-
-void
-gtk_imhtml_reset_smileys (GtkIMHtml *imhtml) 
-{
-	gtk_imhtml_remove_smileys(imhtml);
-	gtk_imhtml_init_smileys (imhtml);
-}
-	
-
-struct im_image {
-	gchar *filename;
-	
-	gint len;
-	gpointer data;
-	
-	gint x,y;
-	gint width,height;
-	GtkIMHtml *imhtml;
-	GtkIMHtmlBit *bit;
-	GdkPixbuf *pb;
-};
-
-struct _GtkIMHtmlBit {
-	gint type;
-
-	gchar *text;
-	struct im_image *img;
-	GdkPixmap *pm;
-	GdkBitmap *bm;
-
-	PangoFontDescription *font;
-	GdkColor *fore;
-	GdkColor *back;
-	GdkColor *bg;
-	gboolean underline;
-	gboolean strike;
-	gchar *url;
-
-	GList *chunks;
-};
-
+/* The four elements present in a <FONT> tag contained in a struct */
+typedef struct _FontDetail   FontDetail;
 struct _FontDetail {
 	gushort size;
 	gchar *face;
-	GdkColor *fore;
-	GdkColor *back;
+	gchar *fore;
+	gchar *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 clickable {
-	gint x;
-	gint y;
-	gint width;
-	gint height;
-	GtkIMHtml *imhtml;
-	GtkIMHtmlBit *bit;
-};
-
-static GtkLayoutClass *parent_class = NULL;
-
-enum {
-	TARGET_STRING,
-	TARGET_TEXT,
-	TARGET_COMPOUND_TEXT
-};
-
+/* GtkIMHtml has one signal--URL_CLICKED */
 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_finalize (GObject *object)
-{
-	GtkIMHtml *imhtml;
-
-	imhtml = GTK_IMHTML (object);
-
-	gtk_imhtml_clear (imhtml);
-
-	if (imhtml->selected_text)
-		g_string_free (imhtml->selected_text, TRUE);
-
-	if (imhtml->default_font)
-		pango_font_description_free (imhtml->default_font);
-	if (imhtml->default_fg_color)
-		gdk_color_free (imhtml->default_fg_color);
-	if (imhtml->default_bg_color)
-		gdk_color_free (imhtml->default_bg_color);
-	if (imhtml->default_hl_color)
-		gdk_color_free (imhtml->default_hl_color);
-	if (imhtml->default_hlfg_color)
-		gdk_color_free (imhtml->default_hlfg_color);
-
-	gdk_cursor_destroy (imhtml->hand_cursor);
-	gdk_cursor_destroy (imhtml->arrow_cursor);
-
-	gtk_smiley_tree_destroy (imhtml->smiley_data);
-
-	G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gtk_imhtml_realize (GtkWidget *widget)
-{
-	GtkIMHtml *imhtml;
-	GdkWindowAttr attributes;
-	gint attributes_mask;
-
-	g_return_if_fail (widget != NULL);
-	g_return_if_fail (GTK_IS_IMHTML (widget));
-
-	imhtml = GTK_IMHTML (widget);
-	GTK_WIDGET_SET_FLAGS (imhtml, 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 = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_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, widget);
-
-	attributes.x = widget->style->xthickness + BORDER_SIZE;
-	attributes.y = widget->style->xthickness + BORDER_SIZE;
-	attributes.width = MAX (1, (gint) widget->allocation.width - (gint) attributes.x * 2);
-	attributes.height = MAX (1, (gint) widget->allocation.height - (gint) attributes.y * 2);
-	attributes.event_mask = gtk_widget_get_events (widget)
-				| GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
-				| GDK_POINTER_MOTION_MASK | GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK;
-
-	GTK_LAYOUT (imhtml)->bin_window = gdk_window_new (widget->window,
-							  &attributes, attributes_mask);
-	gdk_window_set_user_data (GTK_LAYOUT (imhtml)->bin_window, widget);
-
-	widget->style = gtk_style_attach (widget->style, widget->window);
-
-	gdk_window_set_cursor (widget->window, imhtml->arrow_cursor);
-
-	imhtml->context = gtk_widget_get_pango_context(widget);
-	imhtml->default_font = pango_font_description_copy(pango_context_get_font_description(imhtml->context));
-
-	gdk_window_set_background (widget->window, &widget->style->base [GTK_STATE_NORMAL]);
-	gdk_window_set_background (GTK_LAYOUT (imhtml)->bin_window,
-				   &widget->style->base [GTK_STATE_NORMAL]);
-
-	imhtml->default_fg_color = gdk_color_copy (&GTK_WIDGET (imhtml)->style->fg [GTK_STATE_NORMAL]);
-	imhtml->default_bg_color = gdk_color_copy (&GTK_WIDGET (imhtml)->style->base [GTK_STATE_NORMAL]);
-	imhtml->default_hl_color = gdk_color_copy (&GTK_WIDGET (imhtml)->style->bg [GTK_STATE_SELECTED]);
-	imhtml->default_hlfg_color=gdk_color_copy (&GTK_WIDGET (imhtml)->style->fg [GTK_STATE_SELECTED]);
-
-	gdk_window_show (GTK_LAYOUT (imhtml)->bin_window);
-}
-
-static gboolean
-similar_colors (GdkColor *bg,
-		GdkColor *fg)
-{
-	if ((DIFF (bg->red, fg->red) < COLOR_DIFF) &&
-	    (DIFF (bg->green, fg->green) < COLOR_DIFF) &&
-	    (DIFF (bg->blue, fg->blue) < COLOR_DIFF)) {
-		fg->red = (0xff00 - COLOR_MOD > bg->red) ?
-			bg->red + COLOR_MOD : bg->red - COLOR_MOD;
-		fg->green = (0xff00 - COLOR_MOD > bg->green) ?
-			bg->green + COLOR_MOD : bg->green - COLOR_MOD;
-		fg->blue = (0xff00 - COLOR_MOD > bg->blue) ?
-			bg->blue + COLOR_MOD : bg->blue - COLOR_MOD;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-/* This is an expensive function! Don't blame me. I only stole it from eel */
-static gint
-text_width(PangoContext *context, PangoFontDescription *desc,
-		   const char *text, gint len)
-{
-	static PangoLayout *layout = NULL;
-	int width;
-
-	if (layout == NULL)
-		layout = pango_layout_new(context);
-
-	pango_layout_set_font_description(layout, desc);
-	pango_layout_set_text(layout, text, len);
-	pango_layout_get_pixel_size(layout, &width, NULL);
-
- 	/* g_object_unref(G_OBJECT(layout)); */
-
-	return width;
-}
-
-static gint
-string_width(PangoContext *context, PangoFontDescription *desc,
-			 const char *text)
-{
-	return text_width(context, desc, text, -1);
-}
-
-static void
-set_layout_font(PangoLayout *layout, const char *text, guint len,
-				PangoFontDescription *desc)
-{
-	PangoAttribute *attr;
-	PangoAttrList  *list;
-
-	if (len == -1)
-		len = strlen(text);
-
-	attr = pango_attr_font_desc_new(desc);
-
-	attr->start_index = 0;
-	attr->end_index = len;
-
-	list = pango_attr_list_new();
-	pango_attr_list_insert(list, attr);
-
-	pango_layout_set_attributes(layout, list);
-	pango_attr_list_unref(list);
-
-	pango_layout_set_indent(layout, 0);
-	pango_layout_set_justify(layout, FALSE);
-	pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
-}
-
-static gint
-get_layout_first_baseline(PangoLayout* layout)
-{
-	PangoLayoutIter* iter = pango_layout_get_iter(layout);
-	gint result = pango_layout_iter_get_baseline(iter) / PANGO_SCALE;
-	pango_layout_iter_free(iter);
-	return result;
-}
-
-static void
-draw_text (GtkIMHtml        *imhtml,
-	   struct line_info *line)
+/* Boring GTK stuff */
+static void gtk_imhtml_class_init (GtkIMHtmlClass *class)
 {
-	GtkIMHtmlBit *bit;
-	GdkGC *gc;
-	GdkColormap *cmap;
-	GdkWindow *window = GTK_LAYOUT (imhtml)->bin_window;
-	gfloat xoff, yoff;
-	GdkColor *bg, *fg;
-	PangoLayout *layout;
-	PangoFontMetrics *metrics;
-	gchar *start = NULL, *end = NULL;
-
-	if (GTK_LAYOUT (imhtml)->freeze_count)
-		return;
-
-	bit = line->bit;
-	gc = gdk_gc_new (window);
-	cmap = gtk_widget_get_colormap (GTK_WIDGET (imhtml));
-	xoff = GTK_LAYOUT (imhtml)->hadjustment->value;
-	yoff = GTK_LAYOUT (imhtml)->vadjustment->value;
-
-	if (bit->bg != NULL) {
-		gdk_color_alloc (cmap, bit->bg);
-		gdk_gc_set_foreground (gc, bit->bg);
-		bg = bit->bg;
-	} else {
-		gdk_color_alloc (cmap, imhtml->default_bg_color);
-		gdk_gc_set_foreground (gc, imhtml->default_bg_color);
-		bg = imhtml->default_bg_color;
-	}
-
-	gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff,
-			    line->width ? line->width : imhtml->xsize, line->height);
-
-	if (!line->text) {
-		gdk_gc_unref (gc);
-		return;
-	}
-
-	if (bit->back != NULL) {
-		gdk_color_alloc (cmap, bit->back);
-		gdk_gc_set_foreground (gc, bit->back);
-		gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff,
-				    string_width (imhtml->context, bit->font, line->text), line->height);
-		bg = bit->back;
-	}
-
-	bg = gdk_color_copy (bg);
-
-	if (line->selected) {
-		gint width, x;
-		
-		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 = text_width (imhtml->context, bit->font, line->text, start - line->text);
-
-		if (end == NULL)
-			end = strchr(line->text, '\0');
-		
-		width = text_width (imhtml->context, bit->font, line->text, end - line->text) - x;
-
-		gdk_gc_set_foreground (gc, imhtml->default_hl_color);
-		
-		gdk_draw_rectangle (window, gc, TRUE, x + line->x - xoff, line->y - yoff,
-				    width, line->height);
-		gdk_gc_set_foreground (gc, imhtml->default_hlfg_color);
-		fg = gdk_color_copy(imhtml->default_hlfg_color);
-	}
-	if (bit->url) {
-		GdkColor *tc = gtk_imhtml_get_color ("#0000a0");
-		gdk_color_alloc (cmap, tc);
-		gdk_gc_set_foreground (gc, tc);
-		fg = gdk_color_copy (tc);
-		gdk_color_free (tc);
-	} else if (bit->fore) {
-		gdk_color_alloc (cmap, bit->fore);
-		gdk_gc_set_foreground (gc, bit->fore);
-		fg = gdk_color_copy (bit->fore);
-	} else {
-		gdk_color_alloc (cmap, imhtml->default_fg_color);
-		gdk_gc_set_foreground (gc, imhtml->default_fg_color);
-		fg = gdk_color_copy (imhtml->default_fg_color);
-	}
-
-	if (similar_colors (bg, fg)) {
-		gdk_color_alloc (cmap, fg);
-		gdk_gc_set_foreground (gc, fg);
-	}
-	
-	metrics = pango_context_get_metrics(imhtml->context, bit->font, NULL);
-
-	if (start) {
-		int offset = 0;
-
-		layout = gtk_widget_create_pango_layout(GTK_WIDGET(imhtml), NULL);
-		pango_layout_set_text(layout, line->text, start - line->text);
-		set_layout_font(layout, line->text, start - line->text, bit->font);
-		gdk_draw_layout(window, gc, line->x - xoff,
-						line->y - yoff + line->ascent -
-						get_layout_first_baseline(layout), layout);
-		g_object_unref(G_OBJECT(layout));
-
-		offset = text_width (imhtml->context, bit->font, line->text, start - line->text);
-		if (bit->underline || bit->url)
-			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, 
-					    line->y - yoff + line->ascent + 1,
-					    offset, 1);
-		if (bit->strike)
-			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff,
-					    line->y - yoff + line->ascent -
-						((pango_font_metrics_get_ascent(metrics) / PANGO_SCALE) / 2),
-					    offset, 1);
-		gdk_gc_set_foreground (gc, imhtml->default_hlfg_color);
-
-		layout = gtk_widget_create_pango_layout(GTK_WIDGET(imhtml), NULL);
-		pango_layout_set_text(layout, start, end - start);
-		set_layout_font(layout, start, end - start, bit->font);
-		gdk_draw_layout(window, gc, line->x - xoff + offset,
-						line->y - yoff + line->ascent -
-						get_layout_first_baseline(layout), layout);
-		g_object_unref(G_OBJECT(layout));
-
-		if (bit->underline || bit->url)
-			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset, 
-					    line->y - yoff + line->ascent + 1,
-					    text_width (imhtml->context, bit->font, line->text, end - start), 1);
-		if (bit->strike)
-			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset,
-					    line->y - yoff + line->ascent -
-						((pango_font_metrics_get_ascent(metrics) / PANGO_SCALE) / 2),
-					    text_width (imhtml->context, bit->font, line->text, end - start), 1);
-		offset = text_width (imhtml->context, bit->font, line->text, end - line->text);
-		gdk_gc_set_foreground (gc, fg);
-
-		layout = gtk_widget_create_pango_layout(GTK_WIDGET(imhtml), end);
-		set_layout_font(layout, end, -1, bit->font);
-		gdk_draw_layout(window, gc, line->x - xoff + offset,
-						line->y - yoff + line->ascent -
-						get_layout_first_baseline(layout), layout);
-
-		g_object_unref(G_OBJECT(layout));
-
-		if (bit->underline || bit->url)
-			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset, 
-					    line->y - yoff + line->ascent + 1,
-					    string_width (imhtml->context, bit->font, end), 1);
-		if (bit->strike)
-			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff + offset,
-					    line->y - yoff + line->ascent -
-						((pango_font_metrics_get_ascent(metrics) / PANGO_SCALE) / 2),
-					    string_width (imhtml->context, bit->font, end), 1);
-	} else {
-		layout = gtk_widget_create_pango_layout(GTK_WIDGET(imhtml), line->text);
-		set_layout_font(layout, line->text, -1, bit->font);
-		gdk_draw_layout(window, gc, line->x - xoff,
-						line->y - yoff + line->ascent -
-						get_layout_first_baseline(layout), layout);
-		g_object_unref(G_OBJECT(layout));
-
-		if (bit->underline || bit->url)
-			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff + line->ascent + 1,
-					    string_width (imhtml->context, bit->font, line->text), 1);
-		if (bit->strike)
-			gdk_draw_rectangle (window, gc, TRUE, line->x - xoff,
-					    line->y - yoff + line->ascent -
-						((pango_font_metrics_get_ascent(metrics) / PANGO_SCALE) / 2),
-					    string_width (imhtml->context, bit->font, line->text), 1);
-	}
-		
-	pango_font_metrics_unref(metrics);
-
-	gdk_color_free (bg);
-	gdk_color_free (fg);
-
-	gdk_gc_unref (gc);
-}
-
-static void
-draw_img (GtkIMHtml        *imhtml,
-	  struct line_info *line)
-{
-	GtkIMHtmlBit *bit;
-	GdkGC *gc;
-	GdkColormap *cmap;
-	gint width, height, hoff;
-	GdkWindow *window = GTK_LAYOUT (imhtml)->bin_window;
-	gfloat xoff, yoff;
-
-	if (GTK_LAYOUT (imhtml)->freeze_count)
-		return;
-
-	bit = line->bit;
-	gdk_window_get_size (bit->pm, &width, &height);
-	hoff = (line->height - height) / 2;
-	xoff = GTK_LAYOUT (imhtml)->hadjustment->value;
-	yoff = GTK_LAYOUT (imhtml)->vadjustment->value;
-	gc = gdk_gc_new (window);
-	cmap = gtk_widget_get_colormap (GTK_WIDGET (imhtml));
-	
-	if (bit->bg != NULL) {
-		gdk_color_alloc (cmap, bit->bg);
-		gdk_gc_set_foreground (gc, bit->bg);
-	} else {
-		gdk_color_alloc (cmap, imhtml->default_bg_color);
-		gdk_gc_set_foreground (gc, imhtml->default_bg_color);
-	}
-
-	gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff, line->width, line->height);
-
-	if (line->selected) {
-		gdk_color_alloc (cmap, imhtml->default_hl_color);
-		gdk_gc_set_foreground(gc, imhtml->default_hl_color);
-		gdk_draw_rectangle (window, gc, TRUE, line->x - xoff, line->y - yoff,
-				    width, line->height);
-	} else if (bit->back != NULL) {
-		gdk_color_alloc (cmap, bit->back);
-		gdk_gc_set_foreground (gc, bit->back);
-	}
-
-	if (bit->bm) {
-		gdk_gc_set_clip_mask(gc, bit->bm);
-		gdk_gc_set_clip_origin(gc, line->x - xoff, line->y - yoff + hoff);
-	}
-	gdk_draw_pixmap (window, gc, bit->pm, 0, 0, line->x - xoff, line->y - yoff + hoff, -1, -1);
-
-	gdk_gc_unref (gc);
-}
-
-static void
-draw_line (GtkIMHtml        *imhtml,
-	   struct line_info *line)
-{
-	GtkIMHtmlBit *bit;
-	GdkDrawable *drawable;
-	GdkColormap *cmap;
-	GdkGC *gc;
-	guint line_height;
-	gfloat xoff, yoff;
-
-	if (GTK_LAYOUT (imhtml)->freeze_count)
-		return;
-
-	xoff = GTK_LAYOUT (imhtml)->hadjustment->value;
-	yoff = GTK_LAYOUT (imhtml)->vadjustment->value;
-	bit = line->bit;
-	drawable = GTK_LAYOUT (imhtml)->bin_window;
-	cmap = gtk_widget_get_colormap (GTK_WIDGET (imhtml));
-	gc = gdk_gc_new (drawable);
-
-	if (line->selected) {
-		gdk_color_alloc (cmap, imhtml->default_hl_color);
-		gdk_gc_set_foreground (gc, imhtml->default_hl_color);
-	} else if (bit->bg != NULL) {
-		gdk_color_alloc (cmap, bit->bg);
-		gdk_gc_set_foreground (gc, bit->bg);
-	} else {
-		gdk_color_alloc (cmap, imhtml->default_bg_color);
-		gdk_gc_set_foreground (gc, imhtml->default_bg_color);
-	}
-
-	gdk_draw_rectangle (drawable, gc, TRUE, line->x - xoff, line->y - yoff,
-			    line->width, line->height);
-	
-	
-	if (line->selected) {
-		gdk_color_alloc (cmap, imhtml->default_hlfg_color);
-		gdk_gc_set_foreground (gc, imhtml->default_hlfg_color);
-	} else {
-		gdk_color_alloc (cmap, imhtml->default_fg_color);
-		gdk_gc_set_foreground (gc, imhtml->default_fg_color);
-	}
-
-	line_height = line->height / 2;
-
-	gdk_draw_rectangle (drawable, gc, TRUE, line->x - xoff, line->y - yoff + line_height / 2,
-			    line->width, line_height);
-
-	gdk_gc_unref (gc);
-}
-
-static void
-gtk_imhtml_draw_focus (GtkWidget *widget)
-{
-	GtkIMHtml *imhtml;
-	gint x = 0,
-	     y = 0,
-	     w = 0,
-	     h = 0;
-	
-	imhtml = GTK_IMHTML (widget);
-
-	if (!GTK_WIDGET_DRAWABLE (widget))
-		return;
-
-	if (GTK_WIDGET_HAS_FOCUS (widget)) {
-		gtk_paint_focus (widget->style, widget->window, GTK_STATE_NORMAL, NULL, widget, "text", 
-				 0, 0, widget->allocation.width - 1, widget->allocation.height - 1);
-		x = 1; y = 1; w = 2; h = 2;
-	}
-
-	gtk_paint_shadow (widget->style, widget->window, GTK_STATE_NORMAL,
-			  GTK_SHADOW_IN, NULL, widget, "text", x, y,
-			  widget->allocation.width - w, widget->allocation.height - h);
-}
-
-static void
-gtk_imhtml_draw_exposed (GtkIMHtml *imhtml)
-{
-	GList *bits;
-	GtkIMHtmlBit *bit;
-	GList *chunks;
-	struct line_info *line;
-	gfloat x, y;
-	guint32 width, height;
-
-	x = GTK_LAYOUT (imhtml)->hadjustment->value;
-	y = GTK_LAYOUT (imhtml)->vadjustment->value;
-	gdk_window_get_size (GTK_LAYOUT (imhtml)->bin_window, &width, &height);
-
-	bits = imhtml->bits;
-
-	while (bits) {
-		bit = bits->data;
-		chunks = bit->chunks;
-		if (DRAW_IMG (bit)) {
-			if (chunks) {
-				line = chunks->data;
-				if ((line->x <= x + width) &&
-				    (line->y <= y + height) &&
-				    (x <= line->x + line->width) &&
-				    (y <= line->y + line->height))
-					draw_img (imhtml, line);
-			}
-		} else if (bit->type == TYPE_SEP) {
-			if (chunks) {
-				line = chunks->data;
-				if ((line->x <= x + width) &&
-				    (line->y <= y + height) &&
-				    (x <= line->x + line->width) &&
-				    (y <= line->y + line->height))
-					draw_line (imhtml, line);
-
-				line = chunks->next->data;
-				if ((line->x <= x + width) &&
-				    (line->y <= y + height) &&
-				    (x <= line->x + line->width) &&
-				    (y <= line->y + line->height))
-					draw_text (imhtml, line);
-			}
-		} else {
-			while (chunks) {
-				line = chunks->data;
-				if ((line->x <= x + width) &&
-				    (line->y <= y + height) &&
-				    (x <= line->x + line->width) &&
-				    (y <= line->y + line->height))
-					draw_text (imhtml, line);
-				chunks = g_list_next (chunks);
-			}
-		}
-		bits = g_list_next (bits);
-	}
-
-	gtk_imhtml_draw_focus (GTK_WIDGET (imhtml));
-}
-
-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_CLASS (parent_class)->style_set)
-		(* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, style);
-
-	if (!GTK_WIDGET_REALIZED (widget))
-		return;
-
-	imhtml = GTK_IMHTML (widget);
-	if (imhtml->default_fg_color)
-		gdk_color_free(imhtml->default_fg_color);
-	if (imhtml->default_bg_color)
-		gdk_color_free(imhtml->default_bg_color);
-	if (imhtml->default_hl_color)
-		gdk_color_free(imhtml->default_hl_color);
-	if (imhtml->default_hlfg_color)
-		gdk_color_free(imhtml->default_hlfg_color);
-	imhtml->default_fg_color = gdk_color_copy (&GTK_WIDGET (imhtml)->style->fg [GTK_STATE_NORMAL]);
-	imhtml->default_bg_color = gdk_color_copy (&GTK_WIDGET (imhtml)->style->base [GTK_STATE_NORMAL]);
-	imhtml->default_hl_color = gdk_color_copy (&GTK_WIDGET (imhtml)->style->bg [GTK_STATE_SELECTED]);
-	imhtml->default_hlfg_color=gdk_color_copy (&GTK_WIDGET (imhtml)->style->fg [GTK_STATE_SELECTED]);
-	gdk_window_set_background (widget->window, &widget->style->base [GTK_STATE_NORMAL]);
-	gdk_window_set_background (GTK_LAYOUT (imhtml)->bin_window,
-				   &widget->style->base [GTK_STATE_NORMAL]);
-	gtk_imhtml_draw_exposed (imhtml);
-}
-
-static gint
-gtk_imhtml_expose_event (GtkWidget      *widget,
-			 GdkEventExpose *event)
-{
-	GtkIMHtml *imhtml;
-
-	g_return_val_if_fail (widget != NULL, FALSE);
-	g_return_val_if_fail (GTK_IS_IMHTML (widget), FALSE);
-
-	imhtml = GTK_IMHTML (widget);
-	gtk_imhtml_draw_exposed (imhtml);
-
-	return FALSE;
-}
-
-static void
-gtk_imhtml_redraw_all (GtkIMHtml *imhtml)
-{
-	GList *b;
-	GtkIMHtmlBit *bit;
-	GtkAdjustment *vadj;
-	gfloat oldvalue;
-	gint oldy;
-
-	vadj = GTK_LAYOUT (imhtml)->vadjustment;
-	oldvalue = vadj->value / vadj->upper;
-	oldy = imhtml->y;
-
-	gtk_layout_freeze (GTK_LAYOUT (imhtml));
-
-	g_list_free (imhtml->line);
-	imhtml->line = NULL;
-
-	while (imhtml->click) {
-		g_free (imhtml->click->data);
-		imhtml->click = g_list_remove (imhtml->click, imhtml->click->data);
-	}
-
-	imhtml->x = 0;
-	imhtml->y = TOP_BORDER;
-	imhtml->llheight = 0;
-	imhtml->llascent = 0;
-
-	if (GTK_LAYOUT (imhtml)->vadjustment->value < TOP_BORDER)
-		gdk_window_clear_area (GTK_LAYOUT (imhtml)->bin_window, 0, 0,
-				       imhtml->xsize,
-				       TOP_BORDER - GTK_LAYOUT (imhtml)->vadjustment->value);
-
-	b = imhtml->bits;
-	while (b) {
-		bit = b->data;
-		b = g_list_next (b);
-		while (bit->chunks) {
-			struct line_info *li = bit->chunks->data;
-			if (li->text)
-				g_free (li->text);
-			bit->chunks = g_list_remove (bit->chunks, li);
-			g_free (li);
-		}
-		gtk_imhtml_draw_bit (imhtml, bit);
-	}
-
-	GTK_LAYOUT (imhtml)->height = imhtml->y;
-	GTK_LAYOUT (imhtml)->vadjustment->upper = imhtml->y;
-	gtk_signal_emit_by_name (GTK_OBJECT (GTK_LAYOUT (imhtml)->vadjustment), "changed");
-
-	gtk_widget_set_usize (GTK_WIDGET (imhtml), -1, imhtml->y);
-	gtk_adjustment_set_value (vadj, vadj->upper * oldvalue);
-
-	if (GTK_LAYOUT (imhtml)->bin_window && (imhtml->y < oldy)) {
-		GdkGC *gc;
-		GdkColormap *cmap;
-
-		gc = gdk_gc_new (GTK_LAYOUT (imhtml)->bin_window);
-		cmap = gtk_widget_get_colormap (GTK_WIDGET (imhtml));
-
-		gdk_color_alloc (cmap, imhtml->default_bg_color);
-		gdk_gc_set_foreground (gc, imhtml->default_bg_color);
-
-		gdk_draw_rectangle (GTK_LAYOUT (imhtml)->bin_window, gc, TRUE,
-				    0, imhtml->y - GTK_LAYOUT (imhtml)->vadjustment->value,
-				    GTK_WIDGET (imhtml)->allocation.width,
-				    oldy - imhtml->y);
-
-		gdk_gc_unref (gc);
-	}
-
-	gtk_layout_thaw (GTK_LAYOUT (imhtml));
-	gtk_imhtml_draw_focus (GTK_WIDGET (imhtml));
+	GtkObjectClass *object_class;
+	object_class = (GtkObjectClass*) class;
+	signals[URL_CLICKED] = gtk_signal_new("url_clicked",
+					      GTK_RUN_FIRST,
+					      GTK_CLASS_TYPE(object_class),
+					      GTK_SIGNAL_OFFSET(GtkIMHtmlClass, url_clicked),
+					      gtk_marshal_NONE__POINTER,
+					      GTK_TYPE_NONE, 1,
+					      GTK_TYPE_POINTER);
 }
 
-static void
-gtk_imhtml_size_allocate (GtkWidget     *widget,
-			  GtkAllocation *allocation)
-{
-	GtkIMHtml *imhtml;
-	GtkLayout *layout;
-	gint new_xsize, new_ysize;
-
-	g_return_if_fail (widget != NULL);
-	g_return_if_fail (GTK_IS_IMHTML (widget));
-	g_return_if_fail (allocation != NULL);
-
-	imhtml = GTK_IMHTML (widget);
-	layout = GTK_LAYOUT (widget);
-
-	widget->allocation = *allocation;
-
-	new_xsize = MAX (1, (gint) allocation->width -
-			    (gint) (widget->style->xthickness + BORDER_SIZE) * 2);
-	new_ysize = MAX (1, (gint) allocation->height -
-			    (gint) (widget->style->ythickness + BORDER_SIZE) * 2);
-
-	if (GTK_WIDGET_REALIZED (widget)) {
-		gint x = widget->style->xthickness + BORDER_SIZE;
-		gint y = widget->style->ythickness + BORDER_SIZE;
-		gdk_window_move_resize (widget->window,
-					allocation->x, allocation->y,
-					allocation->width, allocation->height);
-		gdk_window_move_resize (layout->bin_window,
-					x, y, new_xsize, new_ysize);
-	}
-
-	layout->hadjustment->page_size = new_xsize;
-	layout->hadjustment->page_increment = new_xsize / 2;
-	layout->hadjustment->lower = 0;
-	layout->hadjustment->upper = imhtml->x;
-
-	layout->vadjustment->page_size = new_ysize;
-	layout->vadjustment->page_increment = new_ysize / 2;
-	layout->vadjustment->lower = 0;
-	layout->vadjustment->upper = imhtml->y;
-
-	gtk_signal_emit_by_name (GTK_OBJECT (layout->hadjustment), "changed");
-	gtk_signal_emit_by_name (GTK_OBJECT (layout->vadjustment), "changed");
-
-	if (new_xsize == imhtml->xsize) {
-		if ((GTK_LAYOUT (imhtml)->vadjustment->value > imhtml->y - new_ysize)) {
-			if (imhtml->y > new_ysize)
-				gtk_adjustment_set_value (GTK_LAYOUT (imhtml)->vadjustment,
-							  imhtml->y - new_ysize);
-			else
-				gtk_adjustment_set_value (GTK_LAYOUT (imhtml)->vadjustment, 0);
-		}
-		return;
-	}
-
-	imhtml->xsize = new_xsize;
-
-	if (GTK_WIDGET_REALIZED (widget))
-		gtk_imhtml_redraw_all (imhtml);
-}
-
-static void
-gtk_imhtml_select_none (GtkIMHtml *imhtml)
-{
-	GList *bits;
-	GList *chunks;
-	GtkIMHtmlBit *bit;
-	struct line_info *chunk;
-
-	g_return_if_fail (GTK_IS_IMHTML (imhtml));
-
-	bits = imhtml->bits;
-	while (bits) {
-		bit = bits->data;
-		chunks = bit->chunks;
-
-		while (chunks) {
-			chunk = chunks->data;
-
-			if (chunk->selected) {
-				chunk->selected = FALSE;
-				chunk->sel_start = chunk->text;
-				chunk->sel_end = NULL;
-				if (DRAW_IMG (bit))
-					draw_img (imhtml, chunk);
-				else if ((bit->type == TYPE_SEP) && (bit->chunks->data == chunk))
-					draw_line (imhtml, chunk);
-				else if (chunk->width)
-					draw_text (imhtml, chunk);
-			}
-
-			chunks = g_list_next (chunks);
-		}
-
-		bits = g_list_next (bits);
-	}
-	imhtml->sel_endchunk = NULL;
-}
-
-static gchar*
-get_position (GtkIMHtml *imhtml,
-		  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 = text_width (imhtml->context, chunk->bit->font, pos, 1);
-		if ((width > total) && (width <= total + char_width)) {
-			if (width < total + (char_width / 2))
-				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;
-}
-
-static void
-chunk_select_words (struct line_info *chunk)
-{
-	char *start, *end;
-
-	start = chunk->sel_start;
-	end = chunk->sel_end;
-
-	if (start != chunk->text) {
-		if (isalnum(*start) || *start == '\'')
-			while (start > chunk->text && 
-			       (isalnum(*(start-1)) || *(start-1) == '\''))
-				start--;
-		else if (isspace(*start))
-			while (start > chunk->text && isspace(*(start-1)))
-				start--;
-		else if (ispunct(*start))
-			while (start > chunk->text && ispunct(*(start-1)))
-				start--;
-	}
-	chunk->sel_start = start;
-
-	if (end != NULL) {
-		if (isalnum(*end) || *end == '\'')
-			while (*end != '\0' && 
-			       (isalnum(*end) || *end == '\''))
-				end++;
-		else if (isspace(*end))
-			while (*end != '\0' && isspace(*end))
-				end++;
-		else if (ispunct(*end))
-			while (*end != '\0' && ispunct(*end))
-				end++;
-	}
-	chunk->sel_end = end;
-}
-
-#define COORDS_IN_CHUNK(xx, yy) (((xx) < chunk->x + chunk->width) && \
-				 ((yy) < chunk->y + chunk->height))
-
-static void
-gtk_imhtml_select_bits (GtkIMHtml *imhtml)
+static void gtk_imhtml_init (GtkIMHtml *imhtml)
 {
-	GList *bits;
-	GList *chunks;
-	GtkIMHtmlBit *bit;
-	struct line_info *chunk;
-
-	guint startx = imhtml->sel_startx,
-	      starty = imhtml->sel_starty,
-	      endx   = imhtml->sel_endx,
-	      endy   = imhtml->sel_endy;
-	gchar *new_pos;
-	gint selection = 0;
-	guint mode = imhtml->sel_mode;
-	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 ("");
-	}
-
-	if (mode == 2)
-		startx = endx = 0;
-
-	bits = imhtml->bits;
-	while (bits) {
-		bit = bits->data;
-		chunks = bit->chunks;
-
-		while (chunks) {
-			chunk = chunks->data;
-
-			switch (selection) {
-			case 0:
-				if (COORDS_IN_CHUNK (startx, starty)) {
-					new_pos = get_position (imhtml, 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 (mode == 2)
-						endy += chunk->height;
-					if (mode == 1)
-						chunk_select_words (chunk);
-				}
-
-				if (COORDS_IN_CHUNK (endx, endy)) {
-					if (got_start) {
-						new_pos = get_position (imhtml, 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;
-						imhtml->sel_endchunk = chunk;
-						got_end = TRUE;
-						if (mode == 1)
-							chunk_select_words (chunk);
-					} else {
-						new_pos = get_position (imhtml, 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++;
-						imhtml->sel_endchunk = chunk;
-						got_end = TRUE;
-						if (mode == 2)
-							starty += chunk->height;
-						if (mode == 1)
-							chunk_select_words (chunk);
-					}
-				} 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 (imhtml, 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;
-					if (mode == 1)
-						chunk_select_words (chunk);
-				} else if (!got_end && COORDS_IN_CHUNK (endx, endy)) {
-					new_pos = get_position (imhtml, 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++;
-					imhtml->sel_endchunk = chunk;
-					got_end = TRUE;
-					if (mode == 1)
-						chunk_select_words (chunk);
-				} else {
-					if ( !chunk->selected ||
-					    (chunk->sel_end != NULL) ||
-					    (chunk->sel_start != chunk->text))
-						redraw = TRUE;
-					chunk->selected = TRUE;
-					chunk->sel_start = chunk->text;
-					chunk->sel_end = NULL;
-				}
-
-				break;
-			case 2:
-				if (chunk->selected)
-					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) {
-				if (DRAW_IMG (bit))
-					draw_img (imhtml, chunk);
-				else if ((bit->type == TYPE_SEP) && (bit->chunks->data == chunk))
-					draw_line (imhtml, chunk);
-				else if (chunk->width)
-					draw_text (imhtml, chunk);
-				redraw = FALSE;
-			}
-
-			chunks = g_list_next (chunks);
-		}
-
-		bits = g_list_next (bits);
-	}
-}
-
-static void
-gtk_imhtml_select_in_chunk (GtkIMHtml *imhtml,
-			    struct line_info *chunk)
-{
-	GtkIMHtmlBit *bit = chunk->bit;
-	gchar *new_pos;
-	guint endx = imhtml->sel_endx;
-	guint startx = imhtml->sel_startx;
-	guint starty = imhtml->sel_starty;
-	gboolean smileys = imhtml->smileys;
-	gboolean redraw = FALSE;
-
-	new_pos = get_position (imhtml, chunk, endx, smileys);
-	if ((starty < chunk->y) ||
-	    ((starty < chunk->y + chunk->height) && (startx < endx))) {
-		if (chunk->sel_end != new_pos)
-			redraw = TRUE;
-		chunk->sel_end = new_pos;
-	} else {
-		if (chunk->sel_start != new_pos)
-			redraw = TRUE;
-		chunk->sel_start = new_pos;
-	}
-
-	if (redraw) {
-		if (DRAW_IMG (bit))
-			draw_img (imhtml, chunk);
-		else if ((bit->type == TYPE_SEP) && 
-			 (bit->chunks->data == chunk))
-			draw_line (imhtml, chunk);
-		else if (chunk->width)
-			draw_text (imhtml, chunk);
-	}
-}
-
-static gint
-scroll_timeout (GtkIMHtml *imhtml)
-{
-	GdkEventMotion event;
-	gint x, y;
-	GdkModifierType mask;
-
-	imhtml->scroll_timer = 0;
-
-	gdk_window_get_pointer (GTK_LAYOUT (imhtml)->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_tip_paint (GtkIMHtml *imhtml)
-{
-	int x,y;
-	GtkStyle *style;
-	PangoLayout *layout;
-		if (imhtml->tip_bit->url)
-		layout = gtk_widget_create_pango_layout (imhtml->tip_window, imhtml->tip_bit->url);
-	else if (imhtml->tip_bit->img)
-		layout = gtk_widget_create_pango_layout (imhtml->tip_window, imhtml->tip_bit->img->filename);
-	else
-		return FALSE;
-		
-	style = imhtml->tip_window->style;
-	pango_layout_get_size (layout, &x, &y);
-
-	if (!imhtml->tip_bit)
-		return FALSE;
+	GtkTextIter iter;
+	imhtml->text_buffer = gtk_text_buffer_new(NULL);
+	gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter);
+	imhtml->end = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, FALSE);
+	gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer);
+	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD);
+	gtk_text_view_set_editable(GTK_TEXT_VIEW(imhtml), FALSE);
+	gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(imhtml), 5);
+	gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(imhtml), FALSE);
+	/*gtk_text_view_set_justification(GTK_TEXT_VIEW(imhtml), GTK_JUSTIFY_FILL);*/
 	
-	gtk_paint_flat_box (style, imhtml->tip_window->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
-			   NULL, imhtml->tip_window, "tooltip", 0, 0, -1, -1);
-
-	gtk_paint_layout (style, imhtml->tip_window->window, GTK_STATE_NORMAL, TRUE,
-			  NULL, imhtml->tip_window, "tooltip", 4, 4, layout);
-	
-	g_object_unref (layout);
-	return FALSE;
-}
-
-static gint
-gtk_imhtml_tip (gpointer data)
-{
-	GtkIMHtml *imhtml = data;
-	GtkWidget *widget = GTK_WIDGET (imhtml);
-	GtkStyle *style;
-	PangoLayout *layout;
-	gint x, y, w, h, scr_w, scr_h;
-
-	if (!imhtml->tip_bit || !GTK_WIDGET_DRAWABLE (widget)) {
-		imhtml->tip_timer = 0;
-		return FALSE;
-	}
-
-	if (imhtml->tip_window)
-		gtk_widget_destroy (imhtml->tip_window);
-
-	imhtml->tip_window = gtk_window_new (GTK_WINDOW_POPUP);
-	gtk_widget_set_app_paintable (imhtml->tip_window, TRUE);
-	gtk_window_set_policy (GTK_WINDOW (imhtml->tip_window), FALSE, FALSE, TRUE);
-	gtk_widget_set_name (imhtml->tip_window, "gtk-tooltips");
-	gtk_signal_connect_object (GTK_OBJECT (imhtml->tip_window), "expose_event",
-				   GTK_SIGNAL_FUNC (gtk_imhtml_tip_paint), GTK_OBJECT (imhtml));
-
-	gtk_widget_ensure_style (imhtml->tip_window);
-	style = imhtml->tip_window->style;
-	layout = gtk_widget_create_pango_layout(imhtml->tip_window, 
-						imhtml->tip_bit->url ? imhtml->tip_bit->url : imhtml->tip_bit->img->filename);
-
-	scr_w = gdk_screen_width ();
-	scr_h = gdk_screen_height ();
-
-	pango_layout_get_size(layout, &w, &h);
-
-	w = PANGO_PIXELS(w) + 8;
-	h = PANGO_PIXELS(h) + 8;
-
-	gdk_window_get_pointer (NULL, &x, &y, NULL);
-	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 ((y + h + + 4) > scr_h)
-		y = y - h;
-	else 
-		y = y + h - 4;
+	/* These tags will be used often and can be reused--we create them on init and then apply them by name
+	 * other tags (color, size, face, etc.) will have to be created and applied dynamically */ 
+	gtk_text_buffer_create_tag(imhtml->text_buffer, "BOLD", "weight", PANGO_WEIGHT_BOLD, NULL);
+	gtk_text_buffer_create_tag(imhtml->text_buffer, "ITALICS", "style", PANGO_STYLE_ITALIC, NULL);
+	gtk_text_buffer_create_tag(imhtml->text_buffer, "UNDERLINE", "underline", PANGO_UNDERLINE_SINGLE, NULL);
+	gtk_text_buffer_create_tag(imhtml->text_buffer, "STRIKE", "strikethrough", TRUE, NULL);
+	gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL);
+	gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL);
+	gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL);
 	
-	gtk_widget_set_usize (imhtml->tip_window, w, h);
-	gtk_widget_set_uposition (imhtml->tip_window, x, y);
-	gtk_widget_show (imhtml->tip_window);
-
-	imhtml->tip_timer = 0;
-	g_object_unref(layout);
-
-	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 / 2) : ((yy - height) / 2);
-			gtk_adjustment_set_value (vadj,
-						  MIN (vadj->value + diff, vadj->upper - height));
-		}
-
-		if (imhtml->selection) {
-			struct line_info *chunk = imhtml->sel_endchunk;
-			imhtml->sel_endx = MAX (x, 0);
-			imhtml->sel_endy = MAX (y, 0);
-			if ((chunk == NULL) ||
-			    (x < chunk->x) ||
-			    (x > chunk->x + chunk->width) ||
-			    (y < chunk->y) ||
-			    (y > chunk->y + chunk->height) ||
-			    (imhtml->sel_mode > 0))
-				gtk_imhtml_select_bits (imhtml);
-			else
-				gtk_imhtml_select_in_chunk (imhtml, chunk);
-		}
-	} else {
-		GList *click = imhtml->click;
-		struct clickable *uw;
-
-		while (click) {
-			uw = (struct clickable *) click->data;
-			if ((uw->bit->url) && (x > uw->x) && (x < uw->x + uw->width) &&
-			    (y > uw->y) && (y < uw->y + uw->height) &&
-			    (uw->bit->url || uw->bit->img)) {
-				if (imhtml->tip_bit != uw->bit) {
-					imhtml->tip_bit = uw->bit;
-					if (imhtml->tip_timer != 0)
-						gtk_timeout_remove (imhtml->tip_timer);
-					if (imhtml->tip_window) {
-						gtk_widget_destroy (imhtml->tip_window);
-						imhtml->tip_window = NULL;
-					}
-					imhtml->tip_timer = gtk_timeout_add (TOOLTIP_TIMEOUT,
-									     gtk_imhtml_tip,
-									     imhtml);
-				}
-				if (uw->bit->url)
-					gdk_window_set_cursor (GTK_LAYOUT (imhtml)->bin_window,
-							       imhtml->hand_cursor);
-				return TRUE;
-			}
-			click = g_list_next (click);
-		}
-	}
-
-	if (imhtml->tip_timer) {
-		gtk_timeout_remove (imhtml->tip_timer);
-		imhtml->tip_timer = 0;
-	}
-	if (imhtml->tip_window) {
-		gtk_widget_destroy (imhtml->tip_window);
-		imhtml->tip_window = NULL;
-	}
-	imhtml->tip_bit = NULL;
-
-	gdk_window_set_cursor (GTK_LAYOUT (imhtml)->bin_window, imhtml->arrow_cursor);
-
-	return TRUE;
-}
-
-static gint
-gtk_imhtml_leave_notify_event (GtkWidget        *widget,
-			       GdkEventCrossing *event)
-{
-	GtkIMHtml *imhtml = GTK_IMHTML (widget);
-
-	if (imhtml->tip_timer) {
-		gtk_timeout_remove (imhtml->tip_timer);
-		imhtml->tip_timer = 0;
-	}
-	if (imhtml->tip_window) {
-		gtk_widget_destroy (imhtml->tip_window);
-		imhtml->tip_window = NULL;
-	}
-	imhtml->tip_bit = NULL;
-return TRUE;
-}
-struct imgsv {
-	GtkWidget *savedialog;
-	struct im_image *img;
-};
-
-static void
-save_img (GtkObject *object,
-	  gpointer data)
-{
-	struct imgsv *is = data;
-	struct im_image *img = is->img;
-	const gchar *filename;
-	FILE *f;
-	filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(is->savedialog));
-	debug_printf("Saving %s\n", filename);
-	if (! (f=fopen(filename, "w"))) {
-		/* There should be some sort of dialog */
-		debug_printf("Could not open file for writing.\n");
-		gtk_widget_destroy(is->savedialog);
-		g_free(is);
-		return;
-	}
-	
-	fwrite(img->data, 1, img->len, f);
-	fclose(f);
-	gtk_widget_destroy(is->savedialog);
-	g_free(is);
-}
-
-static void
-save_img_dialog (GtkObject *object,
-		 gpointer data)
-{
-	struct imgsv *is = g_malloc(sizeof(struct imgsv)); 
-	struct im_image *img = data;
-	GtkWidget *savedialog = gtk_file_selection_new ("Gaim - Save Image");
-	gtk_file_selection_set_filename (GTK_FILE_SELECTION(savedialog), img->filename);
-	gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION(savedialog)->cancel_button),
-				   "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy),
-				   (gpointer) savedialog);
-	
-	is->img = img;
-	is->savedialog = savedialog;
-	
-	gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(savedialog)->ok_button),
-				   "clicked", GTK_SIGNAL_FUNC (save_img), is);
-	gtk_widget_show (savedialog);
-
+	/* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */
+	imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2);
+	imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR);
 
 }
 
-
-static void
-menu_open_url (GtkObject *object,
-	       gpointer   data)
-{
-	struct clickable *uw = data;
-
-	gtk_signal_emit (GTK_OBJECT (uw->imhtml), signals [URL_CLICKED], uw->bit->url);
-}
-
-static void
-menu_copy_link (GtkObject *object,
-		gpointer   data)
-{
-	struct clickable *uw = data;
-	GtkIMHtml *imhtml = uw->imhtml;
-
-	if (imhtml->selected_text)
-		g_string_free (imhtml->selected_text, TRUE);
-
-	gtk_imhtml_select_none (uw->imhtml);
-
-	imhtml->selection = TRUE;
-	imhtml->selected_text = g_string_new (uw->bit->url);
-
-	gtk_selection_owner_set (GTK_WIDGET (imhtml), GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
-}
-
-static gint
-gtk_imhtml_button_press_event (GtkWidget      *widget,
-			       GdkEventButton *event)
+GtkWidget *gtk_imhtml_new(void *a, void *b)
 {
-	GtkIMHtml *imhtml = GTK_IMHTML (widget);
-	GtkAdjustment *vadj = GTK_LAYOUT (widget)->vadjustment;
-	GtkAdjustment *hadj = GTK_LAYOUT (widget)->hadjustment;
-	gint x, y;
-
-	x = event->x + hadj->value;
-	y = event->y + vadj->value;
-
-	if (event->button == 1) {
-		imhtml->sel_startx = imhtml->sel_endx = x;
-		imhtml->sel_starty = imhtml->sel_endy = y;
-		imhtml->selection = TRUE;
-		if (event->type == GDK_BUTTON_PRESS) {
-			imhtml->sel_mode = 0; /* select by letter */
-			gtk_imhtml_select_none (imhtml);
-		} else if (event->type == GDK_2BUTTON_PRESS) {
-			imhtml->sel_mode = 1; /* select by word */
-			gtk_imhtml_select_none (imhtml);
-		} else if (event->type == GDK_3BUTTON_PRESS) {
-			imhtml->sel_mode = 2; /* select by line */
-			gtk_imhtml_select_bits (imhtml);
-		}
-	}
-
-	if (event->button == 3) {
-		GList *click = imhtml->click;
-		struct clickable *uw;
-
-		while (click) {
-			uw = click->data;
-			if ((x > uw->x) && (x < uw->x + uw->width) &&
-			    (y > uw->y) && (y < uw->y + uw->height)) {
-				static GtkWidget *menu = NULL;
-				GtkWidget *button;
-
-				/*
-				 * If a menu already exists, destroy it before creating a new one,
-				 * thus freeing-up the memory it occupied.
-				 */
-				if(menu)
-					gtk_widget_destroy(menu);
-
-				menu = gtk_menu_new();
-
-				if (uw->bit->url) {
-					button = gtk_menu_item_new_with_label ("Open URL");
-					gtk_signal_connect (GTK_OBJECT (button), "activate",
-							    GTK_SIGNAL_FUNC (menu_open_url), uw);
-					gtk_menu_append (GTK_MENU (menu), button);
-					gtk_widget_show (button);
-
-					button = gtk_menu_item_new_with_label ("Copy Link Location");
-					gtk_signal_connect (GTK_OBJECT (button), "activate",
-							    GTK_SIGNAL_FUNC (menu_copy_link), uw);
-					gtk_menu_append (GTK_MENU (menu), button);
-					gtk_widget_show (button);
-				}
-
-				if (uw->bit->img) {
-					button = gtk_menu_item_new_with_label ("Save Image");
-					gtk_signal_connect (GTK_OBJECT (button), "activate",
-							    GTK_SIGNAL_FUNC (save_img_dialog), uw->bit->img);
-					gtk_menu_append (GTK_MENU (menu), button);
-					gtk_widget_show (button);
-				}
-				
-				gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, event->time);
-
-				if (imhtml->tip_timer) {
-					gtk_timeout_remove (imhtml->tip_timer);
-					imhtml->tip_timer = 0;
-				}
-				if (imhtml->tip_window) {
-					gtk_widget_destroy (imhtml->tip_window);
-					imhtml->tip_window = NULL;
-				}
-				imhtml->tip_bit = NULL;
-
-				return TRUE;
-			}
-			click = g_list_next (click);
-		}
-	}
-
-	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;
-
-	x = event->x + hadj->value;
-	y = event->y + vadj->value;
-
-	if ((event->button == 1) && imhtml->selection) {
-		if ((x == imhtml->sel_startx) && (y == imhtml->sel_starty) &&
-		    (imhtml->sel_mode == 0)) {
-			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);
-	}
-
-	if ((event->button == 1) && (imhtml->sel_startx == 0)) {
-		GList *click = imhtml->click;
-		struct clickable *uw;
-
-		while (click) {
-			uw = (struct clickable *) click->data;
-			if ((x > uw->x) && (x < uw->x + uw->width) &&
-			    (y > uw->y) && (y < uw->y + uw->height)) {
-				gtk_signal_emit (GTK_OBJECT (imhtml), signals [URL_CLICKED],
-						 uw->bit->url);
-				return TRUE;
-			}
-			click = g_list_next (click);
-		}
-	}
-
-	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)
-		return;
-
-	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);
-	}
-
-	g_free (string);
+	return GTK_WIDGET(gtk_type_new(gtk_imhtml_get_type()));
 }
 
-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_adjustment_changed (GtkAdjustment *adjustment,
-			       GtkIMHtml     *imhtml)
-{
-	GtkLayout *layout = GTK_LAYOUT (imhtml);
-
-	if (!GTK_WIDGET_MAPPED (imhtml) || !GTK_WIDGET_REALIZED (imhtml))
-		return;
-
-	if (layout->freeze_count)
-		return;
-
-	if (layout->vadjustment->value < TOP_BORDER)
-		gdk_window_clear_area (layout->bin_window, 0, 0,
-				       imhtml->xsize, TOP_BORDER - layout->vadjustment->value);
-
-	gtk_imhtml_draw_exposed (imhtml);
-}
-
-static void
-gtk_imhtml_set_scroll_adjustments (GtkLayout     *layout,
-				   GtkAdjustment *hadj,
-				   GtkAdjustment *vadj)
-{
-	gboolean need_adjust = FALSE;
-
-	g_return_if_fail (layout != NULL);
-	g_return_if_fail (GTK_IS_IMHTML (layout));
-
-	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 (layout->hadjustment && (layout->hadjustment != hadj)) {
-		gtk_signal_disconnect_by_data (GTK_OBJECT (layout->hadjustment), layout);
-		gtk_object_unref (GTK_OBJECT (layout->hadjustment));
-	}
-
-	if (layout->vadjustment && (layout->vadjustment != vadj)) {
-		gtk_signal_disconnect_by_data (GTK_OBJECT (layout->vadjustment), layout);
-		gtk_object_unref (GTK_OBJECT (layout->vadjustment));
-	}
-
-	if (layout->hadjustment != hadj) {
-		layout->hadjustment = hadj;
-		gtk_object_ref (GTK_OBJECT (layout->hadjustment));
-		gtk_object_sink (GTK_OBJECT (layout->hadjustment));
-
-		gtk_signal_connect (GTK_OBJECT (layout->hadjustment), "value_changed",
-				    (GtkSignalFunc) gtk_imhtml_adjustment_changed, layout);
-		need_adjust = TRUE;
-	}
-	
-	if (layout->vadjustment != vadj) {
-		layout->vadjustment = vadj;
-		gtk_object_ref (GTK_OBJECT (layout->vadjustment));
-		gtk_object_sink (GTK_OBJECT (layout->vadjustment));
-
-		gtk_signal_connect (GTK_OBJECT (layout->vadjustment), "value_changed",
-				    (GtkSignalFunc) gtk_imhtml_adjustment_changed, layout);
-		need_adjust = TRUE;
-	}
-
-	if (need_adjust)
-		gtk_imhtml_adjustment_changed (NULL, GTK_IMHTML (layout));
-}
-
-static void
-gtk_imhtml_class_init (GtkIMHtmlClass *class)
+GtkType gtk_imhtml_get_type()
 {
-	GObjectClass  *gobject_class;
-	GtkObjectClass *object_class;
-	GtkWidgetClass *widget_class;
-	GtkLayoutClass *layout_class;
-
-	gobject_class = (GObjectClass*) 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,
-				GTK_CLASS_TYPE (object_class),
-				GTK_SIGNAL_OFFSET (GtkIMHtmlClass, url_clicked),
-				gtk_marshal_NONE__POINTER,
-				GTK_TYPE_NONE, 1,
-				GTK_TYPE_POINTER);
-
-	gobject_class->finalize = gtk_imhtml_finalize;
-
-	widget_class->realize = gtk_imhtml_realize;
-	widget_class->style_set = gtk_imhtml_style_set;
-	widget_class->expose_event  = gtk_imhtml_expose_event;
-	widget_class->size_allocate = gtk_imhtml_size_allocate;
-	widget_class->motion_notify_event = gtk_imhtml_motion_notify_event;
-	widget_class->leave_notify_event = gtk_imhtml_leave_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;
-}
-
-/* the font stuff is the most insane stuff. i don't understand it half
- * the time. so we're going to comment it. isn't that wonderful. */
-
-/* when you g_strsplit a valid font name, these are the positions of all the various parts of it. */
-#define FNDRY 1
-#define FMLY 2
-#define WGHT 3
-#define SLANT 4
-#define SWDTH 5
-#define ADSTYL 6
-#define PXLSZ 7
-#define PTSZ 8
-#define RESX 9
-#define RESY 10
-#define SPC 11
-#define AVGWDTH 12
-#define RGSTRY 13
-#define ENCDNG 14
-
-#if 0
-static const gchar*
-gtk_imhtml_get_font_name (PangoFontDescription *font)
-{
-	return pango_font_description_get_family(font);
-}
-#endif
-
-static PangoFontDescription *
-gtk_imhtml_font_load (GtkIMHtml *imhtml,
-		      gchar     *name,
-		      gboolean   bold,
-		      gboolean   italics,
-		      gint       fontsize)
-{
-	PangoFontDescription *default_font = imhtml->default_font;
-	PangoFontDescription *ret_font;
-	
-	if (!name && !bold && !italics && !fontsize)
-		return default_font;
-//		return pango_font_description_copy(default_font);
-
-	ret_font = pango_font_description_copy(default_font);
-
-	if (name)
-		pango_font_description_set_family(ret_font, name);
-	
-	if (italics)
-		pango_font_description_set_style(ret_font, PANGO_STYLE_ITALIC);
-
-	if (bold)
-		pango_font_description_set_weight(ret_font, PANGO_WEIGHT_BOLD);
-
-	if (fontsize)
-	{
-		pango_font_description_set_size(ret_font,
-										POINT_SIZE(fontsize) * PANGO_SCALE);
-	}
-
-	return ret_font;
-}
-	
-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->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;
+	static guint imhtml_type = 0;
 
 	if (!imhtml_type) {
-		static const GtkTypeInfo imhtml_info = {
+		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);
+		
+		imhtml_type = gtk_type_unique (gtk_text_view_get_type (), &imhtml_info);
 	}
 
 	return imhtml_type;
 }
 
-void
-gtk_imhtml_init_smileys (GtkIMHtml *imhtml)
-{
-	g_return_if_fail (imhtml != NULL);
-	g_return_if_fail (GTK_IS_IMHTML (imhtml));
-
-	imhtml->smiley_data = gtk_smiley_tree_new ();
-
-	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, "=-o", scream_xpm);
-	gtk_imhtml_associate_smiley (imhtml, ":-*", kiss_xpm);
-	gtk_imhtml_associate_smiley (imhtml, ">:O", yell_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, ":-x", crossedlips_xpm);
-	gtk_imhtml_associate_smiley (imhtml, ":-D", bigsmile_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->im_images = NULL;
-
-	imhtml->bits = NULL;
-	imhtml->click = NULL;
-
-	imhtml->x = 0;
-	imhtml->y = TOP_BORDER;
-	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;
-
-	gtk_imhtml_init_smileys (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,
-			 PangoFontDescription   *font,
-			 GdkColor  *fg_color,
-			 GdkColor  *bg_color)
-{
-	g_return_if_fail (imhtml != NULL);
-	g_return_if_fail (GTK_IS_IMHTML (imhtml));
-
-	if (font) {
-		if (imhtml->default_font)
-			pango_font_description_free(imhtml->default_font);
-		imhtml->default_font = pango_font_description_copy(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);
-	}
-
-	if (bg_color) {
-		if (imhtml->default_bg_color)
-			gdk_color_free (imhtml->default_bg_color);
-		imhtml->default_bg_color = gdk_color_copy (bg_color);
-		gdk_window_set_background (GTK_LAYOUT (imhtml)->bin_window, imhtml->default_bg_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 (xpm == NULL)
-		gtk_smiley_tree_remove (imhtml->smiley_data, text);
-	else
-		gtk_smiley_tree_insert (imhtml->smiley_data, text, xpm);
-}
-
-static void
-new_line (GtkIMHtml *imhtml)
-{
-	GList *last = g_list_last (imhtml->line);
-	struct line_info *li;
-
-	if (last) {
-		li = last->data;
-		if (li->x + li->width != imhtml->xsize)
-			li->width = imhtml->xsize - li->x;
-	}
-
-	last = imhtml->line;
-	if (last) {
-		li = last->data;
-		if (li->height < MIN_HEIGHT) {
-			while (last) {
-				gint diff;
-				li = last->data;
-				diff = MIN_HEIGHT - li->height;
-				li->height = MIN_HEIGHT;
-				li->ascent += diff / 2;
-				last = g_list_next (last);
-			}
-			imhtml->llheight = MIN_HEIGHT;
-		}
-	}
-
-	g_list_free (imhtml->line);
-	imhtml->line = NULL;
-
-	imhtml->x = 0;
-	imhtml->y += imhtml->llheight;
-	imhtml->llheight = 0;
-	imhtml->llascent = 0;
-}
-
-static void
-backwards_update (GtkIMHtml    *imhtml,
-		  GtkIMHtmlBit *bit,
-		  gint          height,
-		  gint          ascent)
-{
-	gint diff;
-	GList *ls = NULL;
-	struct line_info *li;
-	struct clickable *uw;
-	struct im_image *img;
-
-	if (height > imhtml->llheight) {
-		diff = height - imhtml->llheight;
-
-		ls = imhtml->line;
-		while (ls) {
-			li = ls->data;
-			li->height += diff;
-			if (ascent)
-				li->ascent = ascent;
-			else
-				li->ascent += diff / 2;
-			ls = g_list_next (ls);
-		}
-
-		ls = imhtml->click;
-		while (ls) {
-			uw = ls->data;
-			if (uw->y + diff > imhtml->y)
-				uw->y += diff;
-			ls = g_list_next (ls);
-		}
-
-		ls = imhtml->im_images;
-		while(ls) {
-			img = ls->data;
-			if (img->y + diff > imhtml->y)
-				img->y += diff;
-			ls = g_list_next(ls);
-		}
-
-		imhtml->llheight = height;
-		if (ascent)
-			imhtml->llascent = ascent;
-		else
-			imhtml->llascent += diff / 2;
+/* The call back for an event on a link tag. */
+void tag_event(GtkTextTag *tag, GObject *arg1, GdkEvent *event, GtkTextIter *arg2, char *url) {
+	if (event->type == GDK_BUTTON_RELEASE) {
+		/* A link was clicked--we emit the "url_clicked" signal with the URL as the argument */
+		//	if ((GdkEventButton)(event)->button == 1) 
+			gtk_signal_emit (G_OBJECT(arg1), signals[URL_CLICKED], url);
+	} else if (event->type == GDK_ENTER_NOTIFY) {
+		/* make a hand cursor and a tooltip timeout -- if GTK worked as it should */
+	} else if (event->type == GDK_LEAVE_NOTIFY) {
+		/* clear timeout and make an arrow cursor again --if GTK worked as it should */
 	}
 }
 
-static void
-add_text_renderer (GtkIMHtml    *imhtml,
-		   GtkIMHtmlBit *bit,
-		   gchar        *text)
-{
-	struct line_info *li;
-	struct clickable *uw;
-	PangoFontMetrics *metrics;
-	gint width;
-
-	if (text)
-		width = string_width (imhtml->context, bit->font, text);
-	else
-		width = 0;
-
-	li = g_new0 (struct line_info, 1);
-	li->x = imhtml->x;
-	li->y = imhtml->y;
-	li->width = width;
-	li->height = imhtml->llheight;
-	if (text) {
-		metrics = pango_context_get_metrics(imhtml->context, bit->font, NULL);
-		li->ascent = MAX (imhtml->llascent, pango_font_metrics_get_ascent(metrics) / PANGO_SCALE);
-		pango_font_metrics_unref(metrics);
-	} else
-		li->ascent = 0;
-	li->text = text;
-	li->bit = bit;
-
-	if (bit->url) {
-		uw = g_new0 (struct clickable, 1);
-		uw->x = imhtml->x;
-		uw->y = imhtml->y;
-		uw->width = width;
-		uw->height = imhtml->llheight;
-		uw->imhtml = imhtml;
-		uw->bit = bit;
-		imhtml->click = g_list_append (imhtml->click, uw);
-	}
-
-	bit->chunks = g_list_append (bit->chunks, li);
-	imhtml->line = g_list_append (imhtml->line, li);
-}
-
-static void
-add_img_renderer (GtkIMHtml    *imhtml,
-		  GtkIMHtmlBit *bit)
-{
-	struct line_info *li;
-	struct clickable *uw;
-	gint width;
-
-	gdk_window_get_size (bit->pm, &width, 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;
-
-
-	if (bit->url || bit->img) {
-		uw = g_new0 (struct clickable, 1);
-		uw->x = imhtml->x;
-		uw->y = imhtml->y;
-		uw->width = width;
-		uw->height = imhtml->llheight;
-		uw->imhtml = imhtml;
-		uw->bit = bit;
-		imhtml->click = g_list_append (imhtml->click, uw);
-	}
-
-	bit->chunks = g_list_append (bit->chunks, li);
-	imhtml->line = g_list_append (imhtml->line, li);
-
-	imhtml->x += width;
-}
-
-static void
-gtk_imhtml_draw_bit (GtkIMHtml    *imhtml,
-		     GtkIMHtmlBit *bit)
-{
-	PangoFontMetrics *metrics;
-	gint width, height;
-
-	g_return_if_fail (imhtml != NULL);
-	g_return_if_fail (GTK_IS_IMHTML (imhtml));
-	g_return_if_fail (bit != NULL);
-
-
-	if ( ((bit->type == TYPE_TEXT) ||
-	    ((bit->type == TYPE_SMILEY) && !imhtml->smileys) ||
-	    ((bit->type == TYPE_COMMENT) && imhtml->comments)) &&
-	     bit->text) {
-		gchar *copy = g_strdup (bit->text);
-		gint pos = 0;
-		gboolean seenspace = FALSE;
-		gchar *tmp;
-
-		metrics = pango_context_get_metrics(imhtml->context, bit->font, NULL);
-		height = (pango_font_metrics_get_ascent(metrics) + pango_font_metrics_get_descent(metrics)) / PANGO_SCALE;
-		width = string_width (imhtml->context, bit->font, bit->text);
-
-		if ((imhtml->x != 0) && ((imhtml->x + width) > imhtml->xsize)) {
-			gint remain = imhtml->xsize - imhtml->x;
-			while (text_width (imhtml->context, 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, pango_font_metrics_get_ascent(metrics) / PANGO_SCALE);
-				add_text_renderer (imhtml, bit, tmp);
-			} else
-				pos = 0;
-			seenspace = FALSE;
-			new_line (imhtml);
-		}
-
-		backwards_update (imhtml, bit, height, pango_font_metrics_get_ascent(metrics) / PANGO_SCALE);
-
-		while (pos < strlen (bit->text)) {
-			width = string_width (imhtml->context, bit->font, copy + pos);
-			if (imhtml->x + width > imhtml->xsize) {
-				gint newpos = 0;
-				gint remain = imhtml->xsize - imhtml->x;
-				while (text_width (imhtml->context, 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;
-
-				backwards_update (imhtml, bit, height, pango_font_metrics_get_ascent(metrics) / PANGO_SCALE);
-				add_text_renderer (imhtml, bit, tmp);
-
-				seenspace = FALSE;
-				new_line (imhtml);
-			} else {
-				tmp = g_strdup (copy + pos);
-
-				backwards_update (imhtml, bit, height, pango_font_metrics_get_ascent(metrics) / PANGO_SCALE);
-				add_text_renderer (imhtml, bit, tmp);
-
-				pos = strlen (bit->text);
-
-				imhtml->x += width;
-			}
-		}
-
-		pango_font_metrics_unref(metrics);
-		g_free(copy);
-	} else if ((bit->type == TYPE_SMILEY) || (bit->type == TYPE_IMG)) {
-	  if (bit->img) {
-			GdkPixbuf *imagepb = bit->img->pb;
-			GdkPixbuf *tmp = NULL;
-			if (gdk_pixbuf_get_width(imagepb) > imhtml->xsize - imhtml->x)
-				new_line (imhtml);
-			
-			if (gdk_pixbuf_get_width(imagepb) > imhtml->xsize) {
-				tmp = gdk_pixbuf_scale_simple(imagepb, imhtml->xsize,
-							      gdk_pixbuf_get_height(imagepb) *
-							      imhtml->xsize/
-							      gdk_pixbuf_get_width(imagepb), 
-							      GDK_INTERP_TILES);
-				if (bit->pm)
-					gdk_pixmap_unref (bit->pm);
-				if (bit->bm)
-					gdk_bitmap_unref (bit->bm);
-				gdk_pixbuf_render_pixmap_and_mask(tmp, &(bit->pm), &(bit->bm), 100);
-				gdk_pixbuf_unref(tmp);
-			}
-			else {
-				if (bit->pm)
-					gdk_pixmap_unref (bit->pm);
-				if (bit->bm)
-					gdk_bitmap_unref (bit->bm);
-				gdk_pixbuf_render_pixmap_and_mask(imagepb, &(bit->pm), &(bit->bm), 100);
-			}
-	  }
-		
-		gdk_window_get_size (bit->pm, &width, &height);
+#define VALID_TAG(x)	if (!g_strncasecmp (string, x ">", strlen (x ">"))) {	\
+				*tag = g_strndup (string, strlen (x));		\
+				*len = strlen (x) + 1;				\
+				return TRUE;					\
+			}							\
+			(*type)++
 
-		if ((imhtml->x != 0) && ((imhtml->x + width) > imhtml->xsize))
-			new_line (imhtml);
-		else
-			backwards_update (imhtml, bit, height, 0);
-
-		add_img_renderer (imhtml, bit);
-	} else if (bit->type == TYPE_BR) {
-		new_line (imhtml);
-		add_text_renderer (imhtml, bit, NULL);
-	} else if (bit->type == TYPE_SEP) {
-		struct line_info *li;
-		if (imhtml->llheight)
-			new_line (imhtml);
-
-		li = g_new0 (struct line_info, 1);
-		li->x = imhtml->x;
-		li->y = imhtml->y;
-		li->width = imhtml->xsize;
-		li->height = HR_HEIGHT * 2;
-		li->ascent = 0;
-		li->text = NULL;
-		li->bit = bit;
-
-		bit->chunks = g_list_append (bit->chunks, li);
-
-		imhtml->llheight = HR_HEIGHT * 2;
-		new_line (imhtml);
-		add_text_renderer (imhtml, bit, NULL);
-	}
-
-}
-
-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;
-
-	if (!gdk_color_parse (color, &c))
-		return NULL;
-
-	return gdk_color_copy (&c);
-}
-
-static gboolean
-gtk_imhtml_is_smiley (GtkIMHtml   *imhtml,
-		      const gchar *text,
-		      gint        *len)
-{
-	*len = gtk_smiley_tree_lookup (imhtml->smiley_data, text);
-	return (*len > 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,
-		    gint        pre,
-		    gint        sub,
-		    gint        sup)
-{
-	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;
+#define VALID_OPT_TAG(x)	if (!g_strncasecmp (string, x " ", strlen (x " "))) {	\
+					const gchar *c = string + strlen (x " ");	\
+					gchar e = '"';					\
+					gboolean quote = FALSE;				\
+					while (*c) {					\
+						if (*c == '"' || *c == '\'') {		\
+							if (quote && (*c == e))		\
+								quote = !quote;		\
+							else if (!quote) {		\
+								quote = !quote;		\
+								e = *c;			\
+							}				\
+						} else if (!quote && (*c == '>'))	\
+							break;				\
+						c++;					\
+					}						\
+					if (*c) {					\
+						*tag = g_strndup (string, c - string);	\
+						*len = c - string + 1;			\
+						return TRUE;				\
+					}						\
+				}							\
+				(*type)++
 
-	bit = g_new0 (GtkIMHtmlBit, 1);
-	bit->type = type;
-
-	if ((text != NULL) && (strlen (text) != 0))
-		bit->text = g_strdup (text);
-
-	if ((font != NULL) || bold || italics || pre) {
-		if (font && (bold || italics || font->size || font->face || pre)) {
-			if (pre) {
-				bit->font = gtk_imhtml_font_load (imhtml, DEFAULT_PRE_FACE, bold, italics, font->size);
-			} else {
-				bit->font = gtk_imhtml_font_load (imhtml, font->face, bold, italics, font->size);
-			}
-		} else if (bold || italics || pre) {
-			if (pre) {
-				bit->font = gtk_imhtml_font_load (imhtml, DEFAULT_PRE_FACE, bold, italics, 0);
-			} else {
-				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 = pango_font_description_copy (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 : imhtml->default_bg_color;
-
-		bit->pm = gdk_pixmap_create_from_xpm_d (GTK_WIDGET (imhtml)->window,
-							&bit->bm,
-							clr,
-							gtk_smiley_tree_image (imhtml->smiley_data, 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, pre, sub, sup)
-#define NEW_SMILEY_BIT  gtk_imhtml_new_bit (imhtml, TYPE_SMILEY, ws, bold, italics, underline, strike, \
-				fonts ? fonts->data : NULL, bg, url, pre, sub, sup)
-#define NEW_SEP_BIT     gtk_imhtml_new_bit (imhtml, TYPE_SEP, NULL, 0, 0, 0, 0, NULL, bg, NULL, 0, 0, 0)
-#define NEW_BR_BIT      gtk_imhtml_new_bit (imhtml, TYPE_BR, NULL, 0, 0, 0, 0, \
-				fonts ? fonts->data : NULL, bg, NULL, 0, 0, 0)
-#define NEW_COMMENT_BIT gtk_imhtml_new_bit (imhtml, TYPE_COMMENT, ws, bold, italics, underline, strike, \
-				fonts ? fonts->data : NULL, bg, url, pre, sub, sup)
-
-#define NEW_BIT(bit)	ws [wpos] = '\0';				\
-			{ GtkIMHtmlBit *tmp = bit; if (tmp != NULL)	\
-			  newbits = g_list_append (newbits, tmp); }	\
-			wpos = 0; ws [wpos] = '\0'
-
-#define UPDATE_BG_COLORS \
-	{ \
-		GdkColormap *cmap; \
-		GList *rev; \
-		cmap = gtk_widget_get_colormap (GTK_WIDGET (imhtml)); \
-		rev = g_list_last (newbits); \
-		while (rev) { \
-			GtkIMHtmlBit *bit = rev->data; \
-			if (bit->bg) \
-				gdk_color_free (bit->bg); \
-			bit->bg = gdk_color_copy (bg); \
-			if (bit->type == TYPE_BR) \
-				break; \
-			rev = g_list_previous (rev); \
-		} \
-		if (!rev) { \
-			rev = g_list_last (imhtml->bits); \
-			while (rev) { \
-				GtkIMHtmlBit *bit = rev->data; \
-				if (bit->bg) \
-					gdk_color_free (bit->bg); \
-				bit->bg = gdk_color_copy (bg); \
-				gdk_color_alloc (cmap, bit->bg); \
-				if (bit->type == TYPE_BR) \
-					break; \
-				rev = g_list_previous (rev); \
-			} \
-		} \
-	}
 
 static gboolean
 gtk_imhtml_is_amp_escape (const gchar *string,
@@ -2856,37 +220,6 @@
 	return TRUE;
 }
 
-#define VALID_TAG(x)	if (!g_strncasecmp (string, x ">", strlen (x ">"))) {	\
-				*tag = g_strndup (string, strlen (x));		\
-				*len = strlen (x) + 1;				\
-				return TRUE;					\
-			}							\
-			(*type)++
-
-#define VALID_OPT_TAG(x)	if (!g_strncasecmp (string, x " ", strlen (x " "))) {	\
-					const gchar *c = string + strlen (x " ");	\
-					gchar e = '"';					\
-					gboolean quote = FALSE;				\
-					while (*c) {					\
-						if (*c == '"' || *c == '\'') {		\
-							if (quote && (*c == e))		\
-								quote = !quote;		\
-							else if (!quote) {		\
-								quote = !quote;		\
-								e = *c;			\
-							}				\
-						} else if (!quote && (*c == '>'))	\
-							break;				\
-						c++;					\
-					}						\
-					if (*c) {					\
-						*tag = g_strndup (string, c - string);	\
-						*len = c - string + 1;			\
-						return TRUE;				\
-					}						\
-				}							\
-				(*type)++
-
 static gboolean
 gtk_imhtml_is_tag (const gchar *string,
 		   gchar      **tag,
@@ -2998,28 +331,94 @@
 	}
 }
 
-GString*
-gtk_imhtml_append_text (GtkIMHtml        *imhtml,
-			const gchar      *text,
-			gint              len,
-			GtkIMHtmlOptions  options)
+
+
+#define NEW_TEXT_BIT 0
+#define NEW_HR_BIT 1
+#define NEW_BIT(x)	ws [wpos] = '\0'; \
+                        mark2 = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, &iter, TRUE); \
+                        gtk_text_buffer_insert(imhtml->text_buffer, &iter, ws, -1); \
+                      	gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \
+                        gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &siter, mark2); \
+                        gtk_text_buffer_delete_mark(imhtml->text_buffer, mark2); \
+                        if (bold) \
+                                 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "BOLD", &siter, &iter); \
+		        if (italics) \
+                                 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "ITALICS", &siter, &iter); \
+                        if (underline) \
+                                 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "UNDERLINE", &siter, &iter); \
+                        if (strike) \
+                                 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "STRIKE", &siter, &iter); \
+                        if (sub) \
+                                 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "SUB", &siter, &iter); \
+                        if (sup) \
+                                 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "SUP", &siter, &iter); \
+                        if (pre) \
+                                 gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "PRE", &siter, &iter); \
+                        if (bg) { \
+                                texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", bg, NULL); \
+                                gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \
+                        } \
+                        if (fonts) { \
+                                 FontDetail *fd = fonts->data; \
+                                 if (fd->fore) { \
+	                                    texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", fd->fore, NULL); \
+                                            gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \
+                                 } \
+                                 if (fd->back) { \
+                                            texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "background", fd->back, NULL); \
+                                            gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \
+                                 } \
+                                 if (fd->face) { \
+                                            texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "font", fd->face, NULL); \
+                                            gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \
+                                 } \
+                                 if (fd->size) { \
+                                            texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "size-points", (double)POINT_SIZE(fd->size), NULL); \
+                                            gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \
+                                 } \
+                        } \
+                        if (url) { \
+                                 texttag = gtk_text_buffer_create_tag(imhtml->text_buffer, NULL, "foreground", "blue", "underline", PANGO_UNDERLINE_SINGLE, NULL); \
+                                 g_signal_connect(G_OBJECT(texttag), "event", G_CALLBACK(tag_event), strdup(url)); \
+                                 gtk_text_buffer_apply_tag(imhtml->text_buffer, texttag, &siter, &iter); \
+                        } \
+                        wpos = 0; \
+                        ws[0] = 0; \
+                        gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); \
+
+
+/*                        if (x == NEW_HR_BIT) { \
+	                         sep = gtk_hseparator_new(); \
+                                 gtk_widget_size_request(GTK_WIDGET(imhtml), &req); \
+                                 gtk_widget_set_size_request(sep, 20, -1); \
+	                         anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, &iter); \
+                                 gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), sep, anchor); \
+                                 gtk_widget_show(sep); \
+			  } */
+
+GString* gtk_imhtml_append_text (GtkIMHtml        *imhtml,
+				 const gchar      *text,
+				 gint              len,
+				 GtkIMHtmlOptions  options)
 {
-	const gchar *c;
-	gboolean binary = TRUE;
-	gchar *ws;
 	gint pos = 0;
-	gint wpos = 0;
-
+	GString *str = NULL;
+	GtkTextIter iter, siter;
+	GtkTextMark *mark, *mark2;
+	GtkTextChildAnchor *anchor;
+	GtkTextTag *texttag;
+	GtkWidget *sep;
+	GtkRequisition req;
+	gchar *ws;
 	gchar *tag;
-	gint tlen;
+	gchar *url = NULL;
+	gchar *bg = NULL;
+	gint tlen, wpos=0;
 	gint type;
-
+	const gchar *c;
 	gchar amp;
 
-	gint smilelen;
-
-	GList *newbits = NULL;
-
 	guint	bold = 0,
 		italics = 0,
 		underline = 0,
@@ -3027,386 +426,244 @@
 		sub = 0,
 		sup = 0,
 		title = 0,
-		pre = 0;
-	GSList *fonts = NULL;
-	GdkColor *bg = NULL;
-	gchar *url = NULL;
+		pre = 0;	
 
-	GtkAdjustment *vadj;
-	gboolean scrolldown = TRUE;
-
-	GString *retval = NULL;
+	GSList *fonts = 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);
+	g_return_val_if_fail (len != 0, NULL);
+	
+	c = text;
+	if (len == -1)
+		len = strlen(text);
+	ws = g_malloc(len + 1);
+	ws[0] = 0;
 
 	if (options & GTK_IMHTML_RETURN_LOG)
-		retval = g_string_new ("");
-
-	vadj = GTK_LAYOUT (imhtml)->vadjustment;
-	if ((vadj->value < imhtml->y - GTK_WIDGET (imhtml)->allocation.height) &&
-	    (vadj->upper >= GTK_WIDGET (imhtml)->allocation.height))
-		scrolldown = FALSE;
+		str = g_string_new("");
 
-	c = text;
-	if (len == -1) {
-		binary = FALSE;
-		len = strlen (text);
-	}
-
-	ws = g_malloc (len + 1);
-	ws [0] = '\0';
-
+	gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter);
+	mark = gtk_text_buffer_create_mark (imhtml->text_buffer, NULL, &iter, /* right grav */ FALSE);
 	while (pos < len) {
 		if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) {
 			c++;
 			pos++;
-			switch (type) {
-			case 1:		/* B */
-			case 2:		/* BOLD */
-				NEW_BIT (NEW_TEXT_BIT);
-				bold++;
-				break;
-			case 3:		/* /B */
-			case 4:		/* /BOLD */
-				NEW_BIT (NEW_TEXT_BIT);
-				if (bold)
-					bold--;
-				break;
-			case 5:		/* I */
-			case 6:		/* ITALIC */
-				NEW_BIT (NEW_TEXT_BIT);
-				italics++;
-				break;
-			case 7:		/* /I */
-			case 8:		/* /ITALIC */
-				NEW_BIT (NEW_TEXT_BIT);
-				if (italics)
-					italics--;
-				break;
-			case 9:		/* U */
-			case 10:	/* UNDERLINE */
-				NEW_BIT (NEW_TEXT_BIT);
-				underline++;
-				break;
-			case 11:	/* /U */
-			case 12:	/* /UNDERLINE */
-				NEW_BIT (NEW_TEXT_BIT);
-				if (underline)
-					underline--;
-				break;
-			case 13:	/* S */
-			case 14:	/* STRIKE */
-				NEW_BIT (NEW_TEXT_BIT);
-				strike++;
-				break;
-			case 15:	/* /S */
-			case 16:	/* /STRIKE */
-				NEW_BIT (NEW_TEXT_BIT);
-				if (strike)
-					strike--;
+			switch (type) 
+				{
+				case 1:		/* B */
+				case 2:		/* BOLD */
+					NEW_BIT (NEW_TEXT_BIT);
+					bold++;
+					break;
+				case 3:		/* /B */
+				case 4:		/* /BOLD */
+					NEW_BIT (NEW_TEXT_BIT);
+					if (bold)
+						bold--;
+					break;
+				case 5:		/* I */
+				case 6:		/* ITALIC */
+					NEW_BIT (NEW_TEXT_BIT);
+					italics++;
+					break;
+				case 7:		/* /I */
+				case 8:		/* /ITALIC */
+					NEW_BIT (NEW_TEXT_BIT);
+					if (italics)
+						italics--;
+					break;
+				case 9:		/* U */
+				case 10:	/* UNDERLINE */
+					NEW_BIT (NEW_TEXT_BIT);
+					underline++;
+					break;
+				case 11:	/* /U */
+				case 12:	/* /UNDERLINE */
+					NEW_BIT (NEW_TEXT_BIT);
+					if (underline)
+						underline--;
+					break;
+				case 13:	/* S */
+				case 14:	/* STRIKE */
+					NEW_BIT (NEW_TEXT_BIT);
+					strike++;
+					break;
+				case 15:	/* /S */
+				case 16:	/* /STRIKE */
+					NEW_BIT (NEW_TEXT_BIT);
+					if (strike)
+						strike--;
+					break;
+				case 17:	/* SUB */
+					NEW_BIT (NEW_TEXT_BIT);
+					sub++;
+					break;
+				case 18:	/* /SUB */
+					NEW_BIT (NEW_TEXT_BIT);
+					if (sub)
+						sub--;
+					break;
+				case 19:	/* SUP */
+					NEW_BIT (NEW_TEXT_BIT);
+					sup++;
 				break;
-			case 17:	/* SUB */
-				NEW_BIT (NEW_TEXT_BIT);
-				sub++;
-				break;
-			case 18:	/* /SUB */
-				NEW_BIT (NEW_TEXT_BIT);
-				if (sub)
-					sub--;
-				break;
-			case 19:	/* SUP */
-				NEW_BIT (NEW_TEXT_BIT);
-				sup++;
-				break;
-			case 20:	/* /SUP */
-				NEW_BIT (NEW_TEXT_BIT);
-				if (sup)
-					sup--;
-				break;
-			case 21:	/* PRE */
-				NEW_BIT (NEW_TEXT_BIT);
-				pre++;
-				break;
-			case 22:	/* /PRE */
-				NEW_BIT (NEW_TEXT_BIT);
-				if (pre)
-					pre--;
-				break;
-			case 23:	/* TITLE */
-				NEW_BIT (NEW_TEXT_BIT);
-				title++;
-				break;
-			case 24:	/* /TITLE */
-				if (title) {
-					if (options & GTK_IMHTML_NO_TITLE) {
-						wpos = 0;
-						ws [wpos] = '\0';
+				case 20:	/* /SUP */
+					NEW_BIT (NEW_TEXT_BIT);
+					if (sup)
+						sup--;
+					break;
+				case 21:	/* PRE */
+					NEW_BIT (NEW_TEXT_BIT);
+					pre++;
+					break;
+				case 22:	/* /PRE */
+					NEW_BIT (NEW_TEXT_BIT);
+					if (pre)
+						pre--;
+					break;
+				case 23:	/* TITLE */
+					NEW_BIT (NEW_TEXT_BIT);
+					title++;
+					break;
+				case 24:	/* /TITLE */
+					if (title) {
+						if (options & GTK_IMHTML_NO_TITLE) {
+							wpos = 0;
+							ws [wpos] = '\0';
+						}
+						title--;
 					}
-					title--;
-				}
-				break;
-			case 25:	/* BR */
-				NEW_BIT (NEW_TEXT_BIT);
-				NEW_BIT (NEW_BR_BIT);
-				break;
-			case 26:	/* HR */
-				NEW_BIT (NEW_TEXT_BIT);
-				NEW_BIT (NEW_SEP_BIT);
-				break;
-			case 27:	/* /FONT */
-				if (fonts) {
-					FontDetail *font = fonts->data;
+					break;
+				case 25:	/* BR */
+					ws[wpos] = '\n';
+					wpos++;
 					NEW_BIT (NEW_TEXT_BIT);
-					fonts = g_slist_remove (fonts, font);
-					if (font->face)
-						g_free (font->face);
-					if (font->fore)
-						gdk_color_free (font->fore);
-					if (font->back)
-						gdk_color_free (font->back);
-					g_free (font);
-				}
-				break;
-			case 28:	/* /A */
-				if (url) {
-					NEW_BIT (NEW_TEXT_BIT);
-					g_free (url);
-					url = NULL;
-				}
-				break;
-			case 29:	/* P */
-			case 30:	/* /P */
-			case 31:	/* H3 */
-			case 32:	/* /H3 */
-			case 33:	/* HTML */
-			case 34:	/* /HTML */
-			case 35:	/* BODY */
-			case 36:	/* /BODY */
-			case 37:	/* FONT */
-			case 38:	/* HEAD */
-			case 39:	/* /HEAD */
-				break;
-			case 40:        /* BINARY */
-				
-				NEW_BIT (NEW_TEXT_BIT);
-				while (pos < len) {
-					if (!g_strncasecmp("</BINARY>", c, strlen("</BINARY>"))) 
+					break;	
+				case 26:        /* HR */
+				case 42:        /* HR (opt) */
+					ws[wpos++] = '\n';
+					NEW_BIT(NEW_HR_BIT);
+					break;
+				case 27:	/* /FONT */
+					if (fonts) {
+						FontDetail *font = fonts->data;
+						NEW_BIT (NEW_TEXT_BIT);
+						fonts = g_slist_remove (fonts, font);
+						if (font->face)
+							g_free (font->face);
+						if (font->fore)
+							g_free (font->fore);
+						if (font->back)
+							g_free (font->back);
+						g_free (font);
+					}
+					break;
+				case 28:        /* /A    */
+					if (url) {
+						NEW_BIT(NEW_TEXT_BIT);
+						g_free(url);
+						url = NULL;
 						break;
-					else {
-						c++;
-						pos++;
 					}
-				}
-				c = c - tlen; /* Because it will add this later */
-				break;
-			case 41:        /* /BINARY */
-				break;
-				
-			case 42:	/* HR (opt) */
-				NEW_BIT (NEW_TEXT_BIT);
-				NEW_BIT (NEW_SEP_BIT);
-				break;
-			case 43:	/* FONT (opt) */
-			{
-				gchar *color, *back, *face, *size;
-				FontDetail *font;
+				case 29:	/* P */
+				case 30:	/* /P */
+				case 31:	/* H3 */
+				case 32:	/* /H3 */
+				case 33:	/* HTML */
+				case 34:	/* /HTML */
+				case 35:	/* BODY */
+				case 36:	/* /BODY */
+				case 37:	/* FONT */
+				case 38:	/* HEAD */
+				case 39:	/* /HEAD */
+					break; 
+				case 40:        /* BINARY */
+				case 41:        /* /BINARY */
+					break;
+				case 43:	/* FONT (opt) */
+					{
+						gchar *color, *back, *face, *size;
+						FontDetail *font, *oldfont = NULL;
+						color = gtk_imhtml_get_html_opt (tag, "COLOR=");
+						back = gtk_imhtml_get_html_opt (tag, "BACK=");
+						face = gtk_imhtml_get_html_opt (tag, "FACE=");
+						size = gtk_imhtml_get_html_opt (tag, "SIZE=");
+						
+						if (!(color || back || face || size))
+							break;
+						
+						NEW_BIT (NEW_TEXT_BIT);
+						
+						font = g_new0 (FontDetail, 1);
+						if (fonts)
+							oldfont = fonts->data;
 
-				color = gtk_imhtml_get_html_opt (tag, "COLOR=");
-				back = gtk_imhtml_get_html_opt (tag, "BACK=");
-				face = gtk_imhtml_get_html_opt (tag, "FACE=");
-				size = gtk_imhtml_get_html_opt (tag, "SIZE=");
-
-				if (!(color || back || face || size))
-					break;
-
-				NEW_BIT (NEW_TEXT_BIT);
-
-				font = g_new0 (FontDetail, 1);
-				if (color && !(options & GTK_IMHTML_NO_COLOURS))
-					font->fore = gtk_imhtml_get_color (color);
-				if (back && !(options & GTK_IMHTML_NO_COLOURS))
-					font->back = gtk_imhtml_get_color (back);
-				if (face && !(options & GTK_IMHTML_NO_FONTS))
-					font->face = g_strdup (face);
-				if (size && !(options & GTK_IMHTML_NO_SIZES)) {
-					if (*size == '+') {
-						sscanf (size + 1, "%hd", &font->size);
-						font->size += 3;
-					} else if (*size == '-') {
-						sscanf (size + 1, "%hd", &font->size);
-						font->size = MAX (0, 3 - font->size);
-					} else if (isdigit (*size)) {
-						sscanf (size, "%hd", &font->size);
-					}
-				}
+						if (color && !(options & GTK_IMHTML_NO_COLOURS))
+							font->fore = color;
+						else if (oldfont && oldfont->fore)
+							font->fore = g_strdup(oldfont->fore);
 
-				g_free (color);
-				g_free (back);
-				g_free (face);
-				g_free (size);
-
-				if (fonts) {
-					FontDetail *oldfont = fonts->data;
-					if (!font->size)
-						font->size = oldfont->size;
-					if (!font->face && oldfont->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);
-				}
-
-				fonts = g_slist_prepend (fonts, font);
-			}
-				break;
-			case 44:	/* BODY (opt) */
-				if (!(options & GTK_IMHTML_NO_COLOURS)) {
-					gchar *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR=");
-					if (bgcolor) {
-						GdkColor *tmp = gtk_imhtml_get_color (bgcolor);
-						g_free (bgcolor);
-						if (tmp) {
-							NEW_BIT (NEW_TEXT_BIT);
-							bg = tmp;
-							UPDATE_BG_COLORS;
+						if (back && !(options & GTK_IMHTML_NO_COLOURS))
+							font->back = back;
+						else if (oldfont && oldfont->back)
+							font->back = g_strdup(oldfont->back);
+						
+						if (face && !(options & GTK_IMHTML_NO_FONTS))
+							font->face = face;
+						else if (oldfont && oldfont->face)
+							font->face = g_strdup(oldfont->face);
+						
+						if (size && !(options & GTK_IMHTML_NO_SIZES)) {
+							if (*size == '+') {
+								sscanf (size + 1, "%hd", &font->size);
+								font->size += 3;
+							} else if (*size == '-') {
+								sscanf (size + 1, "%hd", &font->size);
+								font->size = MAX (0, 3 - font->size);
+							} else if (isdigit (*size)) {
+								sscanf (size, "%hd", &font->size);
+							}
+						} else if (oldfont)
+							font->size = oldfont->size;
+						g_free(size);
+						fonts = g_slist_prepend (fonts, font);
+					}
+					break;
+				case 44:	/* BODY (opt) */
+					if (!(options & GTK_IMHTML_NO_COLOURS)) {
+						char *bgcolor = gtk_imhtml_get_html_opt (tag, "BGCOLOR=");
+						if (bgcolor) {
+							NEW_BIT(NEW_TEXT_BIT);
+							if (bg)
+								g_free(bg);
+							bg = bgcolor;
 						}
 					}
-				}
-				break;
-			case 45:	/* A (opt) */
-			{
-				gchar *href = gtk_imhtml_get_html_opt (tag, "HREF=");
-				if (href) {
-					NEW_BIT (NEW_TEXT_BIT);
-					g_free (url);
-					url = href;
-				}
-			}
-				break;
-			case 46:	/* IMG (opt) */
-				{
-				gchar *src = gtk_imhtml_get_html_opt (tag, "SRC=");
-				gchar *id = gtk_imhtml_get_html_opt (tag, "ID=");
-				gchar *datasize = gtk_imhtml_get_html_opt (tag, "DATASIZE=");
-				gchar **xpm;
-				GdkColor *clr;
-				GtkIMHtmlBit *bit;
-
-				if (!src)
 					break;
-				
-				if (!imhtml->img && id && datasize) { /* This is an embedded IM image */
-					char *tmp, *imagedata, *e;
-					const gchar *alltext;
-					struct im_image *img;
-					GdkPixbufLoader *load;
-					GdkPixbuf *imagepb = NULL;
-					GError *err;
-					NEW_BIT (NEW_TEXT_BIT);
-					if (!id || !datasize)
-						break;
-					tmp = g_malloc(strlen("<DATA ID=\"\" SIZE=\"\">") + 
-						       strlen(id) + strlen(datasize));
-					g_snprintf(tmp, strlen("<DATA ID=\"\" SIZE=\"\">") + 
-						   strlen(id) + strlen(datasize) + 1, 
-						   "<DATA ID=\"%s\" SIZE=\"%s\">", id, datasize);
-					alltext = c;
-					while (g_strncasecmp(alltext, tmp, strlen(tmp)) && alltext < (c + len))
-						alltext++;
-					alltext = alltext + strlen("<DATA ID=\"\" SIZE=\"\">") + strlen(id) + strlen(datasize);
-					g_free(tmp);
-					if (atoi(datasize) > len - pos)
-						break;
-					imagedata = g_malloc(atoi(datasize));
-					memcpy(imagedata, alltext, atoi(datasize));
-					
-					if (!GTK_WIDGET_REALIZED (imhtml))
-						gtk_widget_realize (GTK_WIDGET (imhtml));
-					
-					img = g_new0 (struct im_image, 1);
-					tmp = e = src;
-					while (*tmp){
-						if (*tmp == '/' || *tmp == '\\') {
-							tmp++;
-							src = tmp;
-						} else
-							tmp++;
+				case 45:	/* A (opt) */
+					{
+						gchar *href = gtk_imhtml_get_html_opt (tag, "HREF=");
+						if (href) {
+							NEW_BIT (NEW_TEXT_BIT);
+							if (url)
+								g_free (url);
+							url = href;
+						}
 					}
-					
-					*tmp = '\0';
-					
-					img->filename = g_strdup(src);
-					img->len = atoi(datasize);
-					if (img->len) {
-						img->data = g_malloc(img->len);
-						memcpy(img->data, imagedata, img->len);
-						load = gdk_pixbuf_loader_new();
-
-						if (!gdk_pixbuf_loader_write(load, imagedata, 
-									img->len, &err))
-							debug_printf("IM Image corrupt or unreadable.\n");
-						else 
-							imagepb = gdk_pixbuf_loader_get_pixbuf(load);
-						img->pb = imagepb;
-					}
-					if (imagepb) {
-						bit = g_new0 (GtkIMHtmlBit, 1);
-						bit->type = TYPE_IMG;
-						bit->img = img;
-						if (url)
-							bit->url = g_strdup (url);
-						
-						NEW_BIT (bit);
-					} else {
-						g_free(img->filename);
-						g_free(img->data);
-					}
-					g_free(imagedata);
-					g_free(e);
-					g_free(id);
-					g_free(datasize);
-
+					break;
+				case 47:	/* P (opt) */
+				case 48:	/* H3 (opt) */
 					break;
+				case 49:	/* comment */
+					NEW_BIT (NEW_TEXT_BIT);
+					wpos = g_snprintf (ws, len, "%s", tag);
+					NEW_BIT (NEW_COMMENT_BIT);
+					break;
+				default:
+					break;	
 				}
-				
-				if (!imhtml->img || ((xpm = imhtml->img (src)) == NULL)) {
-					g_free (src);
-					break;
-				}
-
-				if (!fonts || ((clr = ((FontDetail *) fonts->data)->back) == NULL))
-					clr = (bg != NULL) ? bg : imhtml->default_bg_color;
-
-				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);
-			}
-				break;
-			case 47:	/* P (opt) */
-			case 48:	/* H3 (opt) */
-				break;
-			case 49:	/* comment */
-				NEW_BIT (NEW_TEXT_BIT);
-				wpos = g_snprintf (ws, len, "%s", tag);
-				NEW_BIT (NEW_COMMENT_BIT);
-				break;
-			default:
-				break;
-			}
-			g_free (tag);
 			c += tlen;
 			pos += tlen;
 		} else if (*c == '&' && gtk_imhtml_is_amp_escape (c, &amp, &tlen)) {
@@ -3415,17 +672,12 @@
 			pos += tlen;
 		} else if (*c == '\n') {
 			if (!(options & GTK_IMHTML_NO_NEWLINE)) {
+				ws[wpos] = '\n';
+				wpos++;
 				NEW_BIT (NEW_TEXT_BIT);
-				NEW_BIT (NEW_BR_BIT);
 			}
 			c++;
 			pos++;
-		} else if (gtk_imhtml_is_smiley (imhtml, c, &smilelen)) {
-			NEW_BIT (NEW_TEXT_BIT);
-			wpos = g_snprintf (ws, smilelen + 1, "%s", c);
-			NEW_BIT (NEW_SMILEY_BIT);
-			c += smilelen;
-			pos += smilelen;
 		} else if (*c) {
 			ws [wpos++] = *c++;
 			pos++;
@@ -3433,242 +685,88 @@
 			break;
 		}
 	}
-
-	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_LAYOUT (imhtml)->height = imhtml->y;
-	GTK_LAYOUT (imhtml)->vadjustment->upper = imhtml->y;
-	gtk_signal_emit_by_name (GTK_OBJECT (GTK_LAYOUT (imhtml)->vadjustment), "changed");
-
-	gtk_widget_set_usize (GTK_WIDGET (imhtml), -1, imhtml->y);
-
-	if (!(options & GTK_IMHTML_NO_SCROLL) &&
-	    scrolldown &&
-	    (imhtml->y >= MAX (1,
-			       (GTK_WIDGET (imhtml)->allocation.height -
-				(GTK_WIDGET (imhtml)->style->ythickness + BORDER_SIZE) * 2))))
-		gtk_adjustment_set_value (vadj, imhtml->y -
-					  MAX (1, (GTK_WIDGET (imhtml)->allocation.height - 
-						   (GTK_WIDGET (imhtml)->style->ythickness +
-						    BORDER_SIZE) * 2)));
-
+	
+	NEW_BIT(NEW_TEXT_BIT);
 	if (url) {
 		g_free (url);
-		if (retval)
-			retval = g_string_append (retval, "</A>");
+		if (str)
+			str = g_string_append (str, "</A>");
 	}
-	if (bg)
-		gdk_color_free (bg);
-	while (fonts) {
-		FontDetail *font = fonts->data;
-		fonts = g_slist_remove (fonts, font);
-		if (font->face)
-			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) {
+	
+	if (str) {
 		while (bold) {
-			retval = g_string_append (retval, "</B>");
+			str = g_string_append (str, "</B>");
 			bold--;
 		}
 		while (italics) {
-			retval = g_string_append (retval, "</I>");
+			str = g_string_append (str, "</I>");
 			italics--;
 		}
 		while (underline) {
-			retval = g_string_append (retval, "</U>");
+			str = g_string_append (str, "</U>");
 			underline--;
 		}
 		while (strike) {
-			retval = g_string_append (retval, "</S>");
+			str = g_string_append (str, "</S>");
 			strike--;
 		}
 		while (sub) {
-			retval = g_string_append (retval, "</SUB>");
+			str = g_string_append (str, "</SUB>");
 			sub--;
 		}
 		while (sup) {
-			retval = g_string_append (retval, "</SUP>");
+			str = g_string_append (str, "</SUP>");
 			sup--;
 		}
 		while (title) {
-			retval = g_string_append (retval, "</TITLE>");
+			str = g_string_append (str, "</TITLE>");
 			title--;
 		}
 		while (pre) {
-			retval = g_string_append (retval, "</PRE>");
+			str = g_string_append (str, "</PRE>");
 			pre--;
 		}
 	}
-	g_free (ws);
+	//g_free (ws);
+	gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (imhtml), mark,
+				      0, TRUE, 0.0, 1.0);
+	gtk_text_buffer_delete_mark (imhtml->text_buffer, mark);
+	return str;
+}
+
+void       gtk_imhtml_set_adjustments  (GtkIMHtml        *imhtml,
+					GtkAdjustment    *hadj,
+	GtkAdjustment    *vadj){}
 
-	return retval;
-}
+void       gtk_imhtml_set_defaults     (GtkIMHtml            *imhtml,
+					PangoFontDescription *font,
+					GdkColor             *fg_color,
+	GdkColor             *bg_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_init_smileys     (GtkIMHtml *imhtml){}
+void       gtk_imhtml_remove_smileys   (GtkIMHtml        *imhtml){}
+void       gtk_imhtml_reset_smileys   (GtkIMHtml        *imhtml){}
+void       gtk_imhtml_show_smileys     (GtkIMHtml        *imhtml,
+	gboolean          show){}
+
+void       gtk_imhtml_show_comments    (GtkIMHtml        *imhtml,
+	gboolean          show){}
 
 void
 gtk_imhtml_clear (GtkIMHtml *imhtml)
 {
-	GtkLayout *layout;
-
-	g_return_if_fail (imhtml != NULL);
-	g_return_if_fail (GTK_IS_IMHTML (imhtml));
-
-	layout = GTK_LAYOUT (imhtml);
-
-	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)
-			pango_font_description_free(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);
-		if (bit->img) {
-			g_free(bit->img->filename);
-			g_free(bit->img->data);
-			gdk_pixbuf_unref(bit->img->pb);
-			g_free(bit->img);
-		}
-		
-		while (bit->chunks) {
-			struct line_info *li = bit->chunks->data;
-			if (li->text)
-				g_free (li->text);
-			bit->chunks = g_list_remove (bit->chunks, li);
-			g_free (li);
-		}
-		g_free (bit);
-	}
-
-	while (imhtml->click) {
-		g_free (imhtml->click->data);
-		imhtml->click = g_list_remove (imhtml->click, imhtml->click->data);
-	}
-	
-	while (imhtml->im_images) {
-		imhtml->im_images = g_list_remove(imhtml->im_images, imhtml->im_images->data);
-	}
+	GtkTextIter start, end;
 	
-	if (imhtml->selected_text) {
-		g_string_free (imhtml->selected_text, TRUE);
-		imhtml->selected_text = g_string_new ("");
-	}
-
-	imhtml->sel_startx = 0;
-	imhtml->sel_starty = 0;
-	imhtml->sel_endx = 0;
-	imhtml->sel_endx = 0;
-	imhtml->sel_endchunk = NULL;
-
-	if (imhtml->tip_timer) {
-		gtk_timeout_remove (imhtml->tip_timer);
-		imhtml->tip_timer = 0;
-	}
-	if (imhtml->tip_window) {
-		gtk_widget_destroy (imhtml->tip_window);
-		imhtml->tip_window = NULL;
-	}
-	imhtml->tip_bit = NULL;
-
-	if (imhtml->scroll_timer) {
-		gtk_timeout_remove (imhtml->scroll_timer);
-		imhtml->scroll_timer = 0;
-	}
-
-	g_list_free(imhtml->im_images);
-	imhtml->im_images = NULL;
-
-	imhtml->x = 0;
-	imhtml->y = TOP_BORDER;
-	imhtml->xsize = 0;
-	imhtml->llheight = 0;
-	imhtml->llascent = 0;
-	if (imhtml->line)
-		g_list_free (imhtml->line);
-	imhtml->line = NULL;
-
-	layout->hadjustment->page_size = 0;
-	layout->hadjustment->page_increment = 0;
-	layout->hadjustment->lower = 0;
-	layout->hadjustment->upper = imhtml->x;
-	gtk_adjustment_set_value (layout->hadjustment, 0);
-
-	layout->vadjustment->page_size = 0;
-	layout->vadjustment->page_increment = 0;
-	layout->vadjustment->lower = 0;
-	layout->vadjustment->upper = imhtml->y;
-	gtk_adjustment_set_value (layout->vadjustment, 0);
-
-	if (GTK_WIDGET_REALIZED (GTK_WIDGET (imhtml))) {
-		gdk_window_set_cursor (GTK_LAYOUT (imhtml)->bin_window, imhtml->arrow_cursor);
-		gdk_window_clear (GTK_LAYOUT (imhtml)->bin_window);
-		gtk_signal_emit_by_name (GTK_OBJECT (layout->hadjustment), "changed");
-		gtk_signal_emit_by_name (GTK_OBJECT (layout->vadjustment), "changed");
-	}
+	gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start);
+	gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end);
+	gtk_text_buffer_delete(imhtml->text_buffer, &start, &end);
 }
 
-void
-gtk_imhtml_page_up (GtkIMHtml *imhtml)
-{
-	GtkAdjustment *vadj;
-
-	g_return_if_fail (imhtml != NULL);
-	g_return_if_fail (GTK_IS_IMHTML (imhtml));
-
-	vadj = GTK_LAYOUT (imhtml)->vadjustment;
-	gtk_adjustment_set_value (vadj, MAX (vadj->value - vadj->page_increment,
-					     vadj->lower));
-	gtk_signal_emit_by_name (GTK_OBJECT (vadj), "changed");
-}
-
-void
-gtk_imhtml_page_down (GtkIMHtml *imhtml)
-{
-	GtkAdjustment *vadj;
-
-	g_return_if_fail (imhtml != NULL);
-	g_return_if_fail (GTK_IS_IMHTML (imhtml));
-
-	vadj = GTK_LAYOUT (imhtml)->vadjustment;
-	gtk_adjustment_set_value (vadj, MIN (vadj->value + vadj->page_increment,
-					     vadj->upper - vadj->page_size));
-	gtk_signal_emit_by_name (GTK_OBJECT (vadj), "changed");
-}
-
-void
-gtk_imhtml_to_bottom (GtkIMHtml *imhtml)
-{
-				GtkAdjustment *vadj;
-				
-				g_return_if_fail (imhtml != NULL);
-				g_return_if_fail (GTK_IS_IMHTML (imhtml));
-
-				vadj = GTK_LAYOUT (imhtml)->vadjustment;
-        gtk_adjustment_set_value (vadj, vadj->upper - vadj->page_size);
-				gtk_signal_emit_by_name (GTK_OBJECT (vadj), "changed");
-}
+void       gtk_imhtml_page_up          (GtkIMHtml        *imhtml){}
+void       gtk_imhtml_page_down        (GtkIMHtml        *imhtml){}
--- a/src/gtkimhtml.h	Fri Nov 08 06:05:03 2002 +0000
+++ b/src/gtkimhtml.h	Fri Nov 08 06:10:35 2002 +0000
@@ -23,7 +23,7 @@
 #define __GTK_IMHTML_H
 
 #include <gdk/gdk.h>
-#include <gtk/gtklayout.h>
+#include <gtk/gtktextview.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -43,50 +43,16 @@
 typedef struct _GtkIMHtmlClass GtkIMHtmlClass;
 
 struct _GtkIMHtml {
-	GtkLayout layout;
-
-	PangoContext *context;
-	PangoFontDescription *default_font;
-	//GdkFont *default_font;
-	GdkColor *default_fg_color;
-	GdkColor *default_bg_color;
-	GdkColor *default_hl_color;
-	GdkColor *default_hlfg_color;
-
+	GtkTextView text_view;
+	GtkTextBuffer *text_buffer;
+	GtkTextMark *end;
+	gboolean comments, smileys;
 	GdkCursor *hand_cursor;
 	GdkCursor *arrow_cursor;
-
-	GList *bits;
-	GList *click;
-	struct _GtkIMHtmlBit *tip_bit;
-	GList *im_images;
-	GtkWidget *tip_window;
-	guint tip_timer;
-
-	guint sel_startx, sel_starty;
-	guint sel_endx, sel_endy;
-	gboolean selection;
-	guint sel_mode;
-	GString *selected_text;
-	struct line_info *sel_endchunk;
-	guint scroll_timer;
-
-	guint x, y;
-	guint xsize;
-	guint llheight;
-	guint llascent;
-	GList *line;
-
-	GtkIMHtmlImage img;
-
-	gboolean smileys;
-	gboolean comments;
-
-	GtkSmileyTree *smiley_data;
 };
 
 struct _GtkIMHtmlClass {
-	GtkLayoutClass parent_class;
+	GtkTextViewClass parent_class;
 
 	void (*url_clicked) (GtkIMHtml *, const gchar *);
 };
@@ -104,8 +70,7 @@
 } GtkIMHtmlOptions;
 
 GtkType    gtk_imhtml_get_type         (void);
-GtkWidget* gtk_imhtml_new              (GtkAdjustment    *hadj,
-					GtkAdjustment    *vadj);
+GtkWidget* gtk_imhtml_new              (void *, void *);
 
 void       gtk_imhtml_set_adjustments  (GtkIMHtml        *imhtml,
 					GtkAdjustment    *hadj,
--- a/src/prefs.c	Fri Nov 08 06:05:03 2002 +0000
+++ b/src/prefs.c	Fri Nov 08 06:10:35 2002 +0000
@@ -1325,8 +1325,6 @@
 	gtk_box_pack_start(GTK_BOX(ret), sw2, TRUE, TRUE, 0);
 
 	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw2), away_text);
-	GTK_LAYOUT(away_text)->hadjustment->step_increment = 10.0;
-	GTK_LAYOUT(away_text)->vadjustment->step_increment = 10.0;
 	gaim_setup_imhtml(away_text);
 	gtk_imhtml_set_defaults(GTK_IMHTML(away_text), NULL, NULL, NULL);
 	sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_view));
--- a/src/server.c	Fri Nov 08 06:05:03 2002 +0000
+++ b/src/server.c	Fri Nov 08 06:10:35 2002 +0000
@@ -1157,8 +1157,6 @@
 
 	text = gtk_imhtml_new(NULL, NULL);
 	gtk_container_add(GTK_CONTAINER(sw), text);
-	GTK_LAYOUT(text)->hadjustment->step_increment = 10.0;
-	GTK_LAYOUT(text)->vadjustment->step_increment = 10.0;
 	gaim_setup_imhtml(text);
 
 	hbox = gtk_hbox_new(FALSE, 5);