changeset 15358:7c41ecf41614

[gaim-migrate @ 18151] Revert GtkIMHtml hacks that tried to fix gtkimhtml bugs, replace it with heuristic workaround. If you receive a message with more than 100 HTML tags strip all formatting before displaying it. Hopefully nobody has any legitimate uses for 100 HTML tags in a message. I guess we'll see in beta6... which I think we're good for now. I think that post-2.0.0 we'll wind up replacing GtkIMHtml with a legitimate HTML widget and do the Adium/Kopete "chat theme" thing. An HTML widget should be able to handle formatting more efficiently than GtkTextView. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Thu, 18 Jan 2007 02:35:14 +0000
parents b49e2327088a
children 541032720845
files gtk/gtkconv.c gtk/gtkimhtml.c gtk/gtkimhtml.h
diffstat 3 files changed, 22 insertions(+), 126 deletions(-) [+]
line wrap: on
line diff
--- a/gtk/gtkconv.c	Wed Jan 17 22:44:30 2007 +0000
+++ b/gtk/gtkconv.c	Thu Jan 18 02:35:14 2007 +0000
@@ -4810,7 +4810,9 @@
 	GaimConversationType type;
 	char *displaying;
 	gboolean plugin_return;
-
+	char *bracket;
+	int tag_count = 0;
+	
 	g_return_if_fail(conv != NULL);
 	gtkconv = GAIM_GTK_CONVERSATION(conv);
 	g_return_if_fail(gtkconv != NULL);
@@ -4853,6 +4855,19 @@
 	message = displaying;
 	length = strlen(message) + 1;
 
+	/* Awful hack to work around GtkIMHtml's inefficient rendering of messages with lots of formatting changes.
+	 * If a message has over 100 '<' characters, strip formatting before appending it. Hopefully nobody actually
+	 * needs that much formatting, anyway.
+	 */
+	for (bracket = strchr(message, '<'); bracket && *(bracket + 1); bracket = strchr(bracket + 1, '<'))
+		tag_count++;
+	
+	if (tag_count > 100) {
+		char *tmp = message;
+		message = displaying = gaim_markup_strip_html(message);
+		g_free(tmp);
+	}	
+	
 	win = gtkconv->win;
 	prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(gc->prpl);
 
--- a/gtk/gtkimhtml.c	Wed Jan 17 22:44:30 2007 +0000
+++ b/gtk/gtkimhtml.c	Thu Jan 18 02:35:14 2007 +0000
@@ -1215,19 +1215,11 @@
 		g_free(imhtml->clipboard_text_string);
 		g_free(imhtml->clipboard_html_string);
 	}
-	
-	for (l = imhtml->anchors; l; l = l->next) {
-		GtkIMHtmlAnchor *anchor = l->data;
-		gtk_imhtml_anchor_free(anchor);
-	}
-
-	g_slist_free(imhtml->anchors);
+
 	g_list_free(imhtml->scalables);
 	g_slist_free(imhtml->im_images);
 	g_free(imhtml->protocol_name);
 	g_free(imhtml->search_string);
-	g_object_unref(imhtml->empty_buffer);
-	g_object_unref(imhtml->text_buffer);
 	G_OBJECT_CLASS(parent_class)->finalize (object);
 }
 
@@ -1325,7 +1317,6 @@
 {
 	GtkTextIter iter;
 	imhtml->text_buffer = gtk_text_buffer_new(NULL);
-	imhtml->empty_buffer = gtk_text_buffer_new(NULL);
 	gtk_text_buffer_get_end_iter (imhtml->text_buffer, &iter);
 	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_CHAR);
@@ -2364,23 +2355,12 @@
 	}
 }
 
-static gboolean
-set_adj_idle_cb(gpointer data)
-{
-	GtkIMHtml *imhtml = data;
-
-	gtk_adjustment_set_value(GTK_TEXT_VIEW(imhtml)->vadjustment, imhtml->adj);
-	return FALSE;
-}
-
 void gtk_imhtml_insert_html_at_iter(GtkIMHtml        *imhtml,
                                     const gchar      *text,
                                     GtkIMHtmlOptions  options,
                                     GtkTextIter      *iter)
 {
 	GdkRectangle rect;
-	GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment;
-	GSList *anchors;
 	gint pos = 0;
 	gchar *ws;
 	gchar *tag;
@@ -2391,8 +2371,6 @@
 	const gchar *c;
 	gchar *amp;
 	gint len_protocol;
-	gboolean refocus = GTK_WIDGET_HAS_FOCUS(imhtml);
-
 
 	guint	bold = 0,
 		italics = 0,
@@ -2404,6 +2382,7 @@
 		pre = 0;
 
 	gboolean br = FALSE;
+
 	GSList *fonts = NULL;
 	GObject *object;
 	GtkIMHtmlScalable *scalable = NULL;
@@ -2416,22 +2395,6 @@
 	ws = g_malloc(len + 1);
 	ws[0] = 0;
 
-	imhtml->adj = gtk_adjustment_get_value(adj);
-
-	for (anchors = imhtml->anchors; anchors; anchors = anchors->next) {
-		GtkIMHtmlAnchor *anchor = anchors->data;
-		if (gtk_text_child_anchor_get_deleted(anchor->anchor)) {
-			imhtml->anchors = g_slist_remove(imhtml->anchors, anchor);
-			gtk_imhtml_anchor_free(anchor);
-			continue;
-		}
-		gtk_container_remove(GTK_CONTAINER(imhtml), anchor->widget);
-
-	}
-	gtk_widget_hide(GTK_WIDGET(imhtml));
-	gtk_widget_unrealize(GTK_WIDGET(imhtml));
-	gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->empty_buffer);
-
 	while (pos < len) {
 		if (*c == '<' && gtk_imhtml_is_tag (c + 1, &tag, &tlen, &type)) {
 			c++;
@@ -3088,19 +3051,10 @@
 	if (!imhtml->wbfo)
 		gtk_imhtml_close_tags(imhtml, iter);
 
-	gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer);
-	for (anchors = imhtml->anchors; anchors; anchors = anchors->next) {
-		GtkIMHtmlAnchor *anchor = anchors->data;
-		gtk_imhtml_add_anchor(imhtml, anchor);
-	}
 	object = g_object_ref(G_OBJECT(imhtml));
-	gtk_widget_realize(GTK_WIDGET(imhtml));
-	gtk_widget_show_all(GTK_WIDGET(imhtml));
-	g_idle_add_full(G_PRIORITY_HIGH_IDLE, set_adj_idle_cb, imhtml, NULL);
-	if (refocus)
-		gtk_widget_grab_focus(GTK_WIDGET(imhtml));
 	g_signal_emit(object, signals[UPDATE_FORMAT], 0);
 	g_object_unref(object);
+
 }
 
 void gtk_imhtml_remove_smileys(GtkIMHtml *imhtml)
@@ -3491,7 +3445,6 @@
 
 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
 {
-	GtkIMHtmlAnchor *ianchor;
 	GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
 	GtkWidget *box = gtk_event_box_new();
 	char *tag;
@@ -3509,9 +3462,7 @@
 	g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", tag, g_free);
 	g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "[Image]");
 
-	ianchor = gtk_imhtml_anchor_new(anchor, box);
-	imhtml->anchors = g_slist_append(imhtml->anchors, ianchor);
-
+	gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor);
 	g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image);
 }
 
@@ -3537,13 +3488,11 @@
 
 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
 {
-	GtkIMHtmlAnchor *ianchor;
 	GtkIMHtmlHr *hr = (GtkIMHtmlHr *)scale;
 	GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
 	g_object_set_data(G_OBJECT(anchor), "gtkimhtml_htmltext", "<hr>");
 	g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "\n---\n");
-	ianchor = gtk_imhtml_anchor_new(anchor, hr->sep);
-	imhtml->anchors = g_slist_append(imhtml->anchors, ianchor);
+	gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), hr->sep, anchor);
 }
 
 void gtk_imhtml_hr_free(GtkIMHtmlScalable *scale)
@@ -3551,36 +3500,6 @@
 	g_free(scale);
 }
 
-GtkIMHtmlAnchor *gtk_imhtml_anchor_new(GtkTextChildAnchor *anchor, GtkWidget *widget)
-{
-	GtkIMHtmlAnchor *a = g_new0(GtkIMHtmlAnchor, 1);
-	a->anchor = anchor;
-	a->widget = widget;
-	
-	g_object_ref(anchor);
-	g_object_ref(widget);
-	
-	return a;
-}
-
-void gtk_imhtml_anchor_free(GtkIMHtmlAnchor *anchor)
-{
-	g_object_unref(anchor->anchor);
-	g_object_unref(anchor->widget);
-	g_free(anchor);
-}
-
-void gtk_imhtml_add_anchor(GtkIMHtml *imhtml, GtkIMHtmlAnchor *anchor)
-{
-	if (gtk_text_child_anchor_get_deleted(anchor->anchor)) {
-		imhtml->anchors = g_slist_remove(imhtml->anchors, anchor);
-		gtk_imhtml_anchor_free(anchor);
-		return;
-	}
-
-	gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), anchor->widget, anchor->anchor);
-}
-
 gboolean gtk_imhtml_search_find(GtkIMHtml *imhtml, const gchar *text)
 {
 	GtkTextIter iter, start, end;
@@ -4530,7 +4449,6 @@
 	}
 
 	if (icon) {
-		GtkIMHtmlAnchor *ianchor;
 		anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
 		g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(unescaped), g_free);
 		g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free);
@@ -4542,10 +4460,7 @@
 		g_signal_connect(G_OBJECT(icon), "expose-event", G_CALLBACK(image_expose), NULL);
 
 		gtk_widget_show(icon);
-		ianchor = gtk_imhtml_anchor_new(anchor, icon);
-		imhtml->anchors = g_slist_append(imhtml->anchors, ianchor);
-		if (imhtml->text_buffer == GTK_TEXT_VIEW(imhtml)->buffer)
-			gtk_imhtml_add_anchor(imhtml, ianchor);
+		gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor);
 	} else if (imhtml_smiley != NULL && (imhtml->format_functions & GTK_IMHTML_SMILEY)) {
 		anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
 		imhtml_smiley->anchors = g_slist_append(imhtml_smiley->anchors, anchor);
--- a/gtk/gtkimhtml.h	Wed Jan 17 22:44:30 2007 +0000
+++ b/gtk/gtkimhtml.h	Thu Jan 18 02:35:14 2007 +0000
@@ -53,7 +53,6 @@
 typedef struct _GtkIMHtmlImage		GtkIMHtmlImage;
 typedef struct _GtkIMHtmlHr			GtkIMHtmlHr;
 typedef struct _GtkIMHtmlFuncs		GtkIMHtmlFuncs;
-typedef struct _GtkIMHtmlAnchor         GtkIMHtmlAnchor;
 
 typedef enum {
 	GTK_IMHTML_BOLD =       1 << 0,
@@ -80,7 +79,6 @@
 struct _GtkIMHtml {
 	GtkTextView text_view;
 	GtkTextBuffer *text_buffer;
-	GtkTextBuffer *empty_buffer;
 	GdkCursor *hand_cursor;
 	GdkCursor *arrow_cursor;
 	GdkCursor *text_cursor;
@@ -89,7 +87,6 @@
 	char *protocol_name;
 	guint scroll_src;
 	GTimer *scroll_time;
-	gdouble adj;
 
 	gboolean show_comments;
 
@@ -126,7 +123,6 @@
 	char *clipboard_html_string;
 
 	GSList *im_images;
-	GSList *anchors;
 	GtkIMHtmlFuncs *funcs;
 };
 
@@ -192,11 +188,6 @@
 	GtkWidget *sep;
 };
 
-struct _GtkIMHtmlAnchor {
-	GtkTextChildAnchor *anchor;
-	GtkWidget *widget;
-};
-
 typedef enum {
 	GTK_IMHTML_NO_COLOURS          = 1 << 0,
 	GTK_IMHTML_NO_FONTS            = 1 << 1,
@@ -481,31 +472,6 @@
 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter);
 
 /**
- * Creates a new anchor for GTK+ widgets, taking care of reference counting
- *
- * @param anchor The GtkTextChildAnchor
- * @param widget The GtkWidget
- *
- * @return The GtkIMHtmlAnchor
- */
-GtkIMHtmlAnchor *gtk_imhtml_anchor_new(GtkTextChildAnchor *anchor, GtkWidget *widget);
-
-/**
- * Frees an anchor, taking care of refcounting
- *
- * @param anchor The anchor
- */
-void gtk_imhtml_anchor_free(GtkIMHtmlAnchor *anchor);
-
-/**
- * Associates an anchor with an imhtml
- *
- * @param imhtml  The IMHTML to associate with.
- * @param anchor  The anchor to associate
- */
-void gtk_imhtml_add_anchor(GtkIMHtml *imhtml, GtkIMHtmlAnchor *anchor);
-
-/**
  * Finds and highlights a given string in a GTK+ IM/HTML.
  *
  * @param imhtml The GTK+ IM/HTML.