# HG changeset patch
# Node ID 2b3e7fb20e0e
# Parent  17237faf35cb
diff --git a/pidgin/gtkconv.c b/pidgin/gtkconv.c
--- a/pidgin/gtkconv.c
+++ b/pidgin/gtkconv.c
@@ -118,6 +118,9 @@
 static GdkColor *nick_colors = NULL;
 static guint nbr_nick_colors;
 
+/* GTK_IMHTML_MAX_CONSEC_RESIZES is also defined in gtkimhtml.c */
+#define GTK_IMHTML_MAX_CONSEC_RESIZES 4
+
 typedef struct {
 	GtkWidget *window;
 
@@ -2361,6 +2364,9 @@
 
 	g_return_if_fail(gtkconv != NULL);
 
+	g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count",
+			  GINT_TO_POINTER(0));
+
 	if (!purple_prefs_get_bool("/purple/conversations/im/send_typing"))
 		return;
 
@@ -2378,6 +2384,9 @@
 
 	g_return_if_fail(gtkconv != NULL);
 
+	g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count",
+			  GINT_TO_POINTER(0));
+
 	conv = gtkconv->active_conv;
 
 	if (!purple_prefs_get_bool("/purple/conversations/im/send_typing"))
@@ -2806,6 +2815,9 @@
 		PurpleContact *contact = purple_buddy_get_contact(buddy);
 		purple_blist_node_set_int((PurpleBlistNode*)contact, "pidgin-infopane-iconsize", size);
 	}
+
+	g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count",
+			  GINT_TO_POINTER(0));
 }
 
 static void
@@ -4331,6 +4343,11 @@
 			new_topic);
 
 	g_free(new_topic);
+
+	g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count",
+			  GINT_TO_POINTER(0));
+	g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count",
+			  GINT_TO_POINTER(0));
 }
 
 static gint
@@ -4596,6 +4613,17 @@
 	gboolean interior_focus;
 	int focus_width;
 
+	if(GPOINTER_TO_INT(
+		   g_object_get_data(
+			   G_OBJECT(gtkconv->entry), "resize-count")) ==
+	   GTK_IMHTML_MAX_CONSEC_RESIZES + 1) {
+		g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count",
+				  GINT_TO_POINTER(0));
+		g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count",
+				  GINT_TO_POINTER(0));
+		return;
+	}
+
 	pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry));
 	pad_bottom = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(gtkconv->entry));
 	pad_inside = gtk_text_view_get_pixels_inside_wrap(GTK_TEXT_VIEW(gtkconv->entry));
@@ -4630,7 +4658,7 @@
 
 	diff = height - gtkconv->entry->allocation.height;
 	if (ABS(diff) < oneline.height / 2)
-		return FALSE;
+		diff = 0;
 
 	gtk_widget_set_size_request(gtkconv->lower_hbox, -1,
 		diff + gtkconv->lower_hbox->allocation.height);
@@ -5056,6 +5084,7 @@
 	gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry");
 	gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry),
 			purple_account_get_protocol_name(conv->account));
+	g_object_set_data(G_OBJECT(gtkconv->entry), "gtkconv", gtkconv);
 
 	g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup",
 	                 G_CALLBACK(entry_popup_menu_cb), gtkconv);
@@ -7380,6 +7409,11 @@
 			gtk_widget_hide(gtkconv->toolbar);
 
 		g_idle_add((GSourceFunc)resize_imhtml_cb,gtkconv);
+
+		g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count",
+				  GINT_TO_POINTER(0));
+		g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count",
+				  GINT_TO_POINTER(0));
 	}
 }
 
@@ -9077,6 +9111,12 @@
 	PurpleConversation *conv = gtkconv->active_conv;
 	const char *text = NULL;
 
+	g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count",
+			  GINT_TO_POINTER(0));
+
+	g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count",
+			  GINT_TO_POINTER(0));
+
 	if (!GTK_WIDGET_VISIBLE(gtkconv->infopane)) {
 		/* There's already an entry for alias. Let's not create another one. */
 		return FALSE;
@@ -9236,6 +9276,21 @@
 
 static gboolean gtk_conv_configure_cb(GtkWidget *w, GdkEventConfigure *event, gpointer data) {
 	int x, y;
+	GList *gtkconvs;
+	PidginWindow *win = data;
+	PidginConversation *gtkconv;
+
+	if(win != NULL) {
+		for (gtkconvs = win->gtkconvs; gtkconvs != NULL; gtkconvs = gtkconvs->next) {
+			gtkconv = gtkconvs->data;
+			if(gtkconv != NULL) {
+				g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count",
+						  GINT_TO_POINTER(0));
+				g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count",
+						  GINT_TO_POINTER(0));
+			}
+		}
+	}
 
 	if (GTK_WIDGET_VISIBLE(w))
 		gtk_window_get_position(GTK_WINDOW(w), &x, &y);
@@ -9269,6 +9324,9 @@
 pidgin_conv_set_position_size(PidginWindow *win, int conv_x, int conv_y,
 		int conv_width, int conv_height)
 {
+	GList *gtkconvs;
+	PidginConversation *gtkconvs_data;
+
 	 /* if the window exists, is hidden, we're saving positions, and the
           * position is sane... */
 	if (win && win->window &&
@@ -9291,6 +9349,18 @@
 #endif
 		gtk_window_resize(GTK_WINDOW(win->window), conv_width, conv_height);
 	}
+
+	if(win != NULL) {
+		for (gtkconvs = win->gtkconvs; gtkconvs != NULL; gtkconvs = gtkconvs->next) {
+			gtkconvs_data = gtkconvs->data;
+			if(gtkconvs_data != NULL) {
+				g_object_set_data(G_OBJECT(gtkconvs_data->imhtml), "resize-count",
+						  GINT_TO_POINTER(0));
+				g_object_set_data(G_OBJECT(gtkconvs_data->entry), "resize-count",
+						  GINT_TO_POINTER(0));
+			}
+		}
+	}
 }
 
 static void
@@ -9498,6 +9568,8 @@
 	GtkWidget *tab_cont = gtkconv->tab_cont;
 	PurpleConversationType conv_type;
 	const gchar *tmp_lab;
+	GList *gtkconvs;
+	PidginConversation *gtkconvs_data;
 
 	conv_type = purple_conversation_get_type(conv);
 
@@ -9566,6 +9638,16 @@
 
 	if (pidgin_conv_window_get_gtkconv_count(win) == 1)
 		update_send_to_selection(win);
+
+	for (gtkconvs = win->gtkconvs; gtkconvs != NULL; gtkconvs = gtkconvs->next) {
+		gtkconvs_data = gtkconvs->data;
+		if(gtkconvs_data != NULL) {
+			g_object_set_data(G_OBJECT(gtkconvs_data->imhtml), "resize-count",
+					  GINT_TO_POINTER(0));
+			g_object_set_data(G_OBJECT(gtkconvs_data->entry), "resize-count",
+					  GINT_TO_POINTER(0));
+		}
+	}
 }
 
 static void
@@ -9670,6 +9752,8 @@
 pidgin_conv_window_remove_gtkconv(PidginWindow *win, PidginConversation *gtkconv)
 {
 	unsigned int index;
+	GList *gtkconvs;
+	PidginConversation *gtkconvs_data;
 
 	index = gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont);
 
@@ -9688,6 +9772,14 @@
 
 	if (!win->gtkconvs && win != hidden_convwin)
 		pidgin_conv_window_destroy(win);
+
+	for (gtkconvs = win->gtkconvs; gtkconvs != NULL; gtkconvs = gtkconvs->next) {
+		gtkconvs_data = gtkconvs->data;
+		if(gtkconvs_data != NULL) {
+			g_object_set_data(G_OBJECT(gtkconvs_data->imhtml), "resize-count",
+					  GINT_TO_POINTER(0));
+		}
+	}
 }
 
 PidginConversation *
@@ -9861,7 +9953,7 @@
 		win = pidgin_conv_window_new();
 
 		g_signal_connect(G_OBJECT(win->window), "configure_event",
-				G_CALLBACK(gtk_conv_configure_cb), NULL);
+				G_CALLBACK(gtk_conv_configure_cb), win);
 
 		pidgin_conv_window_add_gtkconv(win, conv);
 		pidgin_conv_window_show(win);
@@ -9879,6 +9971,11 @@
 	PurpleConversationType type = purple_conversation_get_type(conv->active_conv);
 	GList *all;
 
+	g_object_set_data(G_OBJECT(conv->imhtml), "resize-count",
+			  GINT_TO_POINTER(0));
+	g_object_set_data(G_OBJECT(conv->entry), "resize-count",
+			  GINT_TO_POINTER(0));
+
 	if (GTK_WIDGET_VISIBLE(w))
 		gtk_window_get_position(GTK_WINDOW(w), &x, &y);
 	else
@@ -9961,7 +10058,7 @@
 	win = pidgin_conv_window_new();
 
 	g_signal_connect(G_OBJECT(win->window), "configure_event",
-			G_CALLBACK(gtk_conv_configure_cb), NULL);
+			G_CALLBACK(gtk_conv_configure_cb), win);
 
 	pidgin_conv_window_add_gtkconv(win, conv);
 
diff --git a/pidgin/gtkimhtml.c b/pidgin/gtkimhtml.c
--- a/pidgin/gtkimhtml.c
+++ b/pidgin/gtkimhtml.c
@@ -67,6 +67,9 @@
 
 #define TOOLTIP_TIMEOUT 500
 
+/* GTK_IMHTML_MAX_CONSEC_RESIZES is also defined in gtkconv.c */
+#define GTK_IMHTML_MAX_CONSEC_RESIZES 4
+
 static GtkTextViewClass *parent_class = NULL;
 
 struct scalable_data {
@@ -395,6 +398,59 @@
 	int height = 0, y = 0;
 	GtkTextIter iter;
 	gboolean scroll = TRUE;
+	PidginConversation *gtkconv;
+	GtkIMHtml *entry, *messages;
+	int resize_count;
+	int entry_rc;
+	int messages_rc;
+
+	gtkconv = g_object_get_data(G_OBJECT(imhtml), "gtkconv");
+
+	if(gtkconv != NULL) {
+		entry = GTK_IMHTML(gtkconv->entry);
+		messages = GTK_IMHTML(gtkconv->imhtml);
+
+		entry_rc = GPOINTER_TO_INT(
+			g_object_get_data(
+				G_OBJECT(entry), "resize-count"));
+
+		messages_rc = GPOINTER_TO_INT(
+			g_object_get_data(
+				G_OBJECT(messages), "resize-count"));
+
+		resize_count = GPOINTER_TO_INT(
+			g_object_get_data(
+				G_OBJECT(imhtml), "resize-count"));
+
+		if(imhtml == entry) {
+			if(entry_rc >= GTK_IMHTML_MAX_CONSEC_RESIZES ||
+			   messages_rc >= GTK_IMHTML_MAX_CONSEC_RESIZES) {
+				return;
+			}
+		} else if(imhtml == messages) {
+			if(resize_count >= GTK_IMHTML_MAX_CONSEC_RESIZES) {
+				g_object_set_data(
+					G_OBJECT(entry), "resize-count",
+					GINT_TO_POINTER(
+						GTK_IMHTML_MAX_CONSEC_RESIZES + 1));
+
+				return;
+			}
+
+			if(entry_rc == GTK_IMHTML_MAX_CONSEC_RESIZES + 1) {
+				g_object_set_data(G_OBJECT(messages), "resize-count",
+						  GINT_TO_POINTER(0));
+				return;
+			}
+
+			g_object_set_data(G_OBJECT(entry), "resize-count",
+					  GINT_TO_POINTER(0));
+		}
+
+		resize_count++;
+		g_object_set_data(G_OBJECT(imhtml), "resize-count",
+				  GINT_TO_POINTER(resize_count));
+	}
 
 	gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter);
 
