changeset 11224:409d6a11da51

[gaim-migrate @ 13360] Restrict the conversation scrollback. Current default is 4000 lines. This also fixes the IM images not actually being cleared by gtk_imhtml_clear(). committer: Tailor Script <tailor@pidgin.im>
author Daniel Atallah <daniel.atallah@gmail.com>
date Wed, 10 Aug 2005 21:13:44 +0000
parents d424c3bbac8d
children 46facec74fc1
files ChangeLog plugins/ChangeLog.API src/gtkconv.c src/gtkimhtml.c src/gtkimhtml.h
diffstat 5 files changed, 113 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Aug 10 05:45:17 2005 +0000
+++ b/ChangeLog	Wed Aug 10 21:13:44 2005 +0000
@@ -46,6 +46,8 @@
 	  directly
 	* Yahoo! buddy requests to add you to their buddy list now prompt for
 	  authorization.
+	* Conversation buffer scrollback limited to avoid large memory
+	  usage in active conversations.
 
 	Bug fixes:
 	* People using input methods can now use Enter again.
--- a/plugins/ChangeLog.API	Wed Aug 10 05:45:17 2005 +0000
+++ b/plugins/ChangeLog.API	Wed Aug 10 21:13:44 2005 +0000
@@ -82,6 +82,7 @@
 	* Changed: "chat-invited" handlers can now return a value to control
 	           what happens to the invite (accept, reject, prompt the user).
 	           See the Doxygen documentation for the details.
+	* Added:   gtk_imhtml_delete to clear out part of a imhtml buffer
 
 version 1.0.0 (09/17/2004):
 	* Added: get_chat_name to the GaimPluginProtocolInfo struct
--- a/src/gtkconv.c	Wed Aug 10 05:45:17 2005 +0000
+++ b/src/gtkconv.c	Wed Aug 10 21:13:44 2005 +0000
@@ -4964,6 +4964,9 @@
 	GaimConvWindow *win;
 	GaimConnection *gc;
 	int gtk_font_options = 0;
+	int max_scrollback_lines = gaim_prefs_get_int(
+		"/gaim/gtk/conversations/scrollback_lines");
+	int line_count;
 	char buf2[BUF_LONG];
 	char mdate[64];
 	char color[10];
@@ -4978,6 +4981,24 @@
 
 	win = gaim_conversation_get_window(conv);
 
+	line_count = gtk_text_buffer_get_line_count(
+			gtk_text_view_get_buffer(GTK_TEXT_VIEW(
+				gtkconv->imhtml)));
+printf("writing to conv - max_scrollback_lines = %d our lines = %d\n", max_scrollback_lines, line_count);
+	/* If we're sitting at more than 100 lines more than the
+	   max scrollback, trim down to max scrollback */
+	if (max_scrollback_lines > 0
+			&& line_count > (max_scrollback_lines + 100)) {
+		GtkTextBuffer *text_buffer = gtk_text_view_get_buffer(
+			GTK_TEXT_VIEW(gtkconv->imhtml));
+		GtkTextIter start, end;
+
+		gtk_text_buffer_get_start_iter(text_buffer, &start);
+		gtk_text_buffer_get_iter_at_line(text_buffer, &end,
+			(line_count - max_scrollback_lines));
+		gtk_imhtml_delete(GTK_IMHTML(gtkconv->imhtml), &start, &end);
+	}
+
 	if (gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->imhtml))))
 		gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<BR>", 0);
 
@@ -6222,6 +6243,7 @@
 	gaim_prefs_add_bool("/gaim/gtk/conversations/tabs", TRUE);
 	gaim_prefs_add_int("/gaim/gtk/conversations/tab_side", GTK_POS_TOP);
 	gaim_prefs_add_bool("/gaim/gtk/conversations/warn_on_unread_close", TRUE);
+	gaim_prefs_add_int("/gaim/gtk/conversations/scrollback_lines", 4000);
 
 	/* Conversations -> Chat */
 	gaim_prefs_add_none("/gaim/gtk/conversations/chat");
--- a/src/gtkimhtml.c	Wed Aug 10 05:45:17 2005 +0000
+++ b/src/gtkimhtml.c	Wed Aug 10 21:13:44 2005 +0000
@@ -77,6 +77,17 @@
 
 static GtkTextViewClass *parent_class = NULL;
 
+struct scalable_data {
+	GtkIMHtmlScalable *scalable;
+	GtkTextMark *mark;
+};
+
+
+struct im_image_data {
+	int id;
+	GtkTextMark *mark;
+};
+
 static gboolean
 gtk_text_view_drag_motion (GtkWidget        *widget,
                            GdkDragContext   *context,
@@ -371,7 +382,8 @@
 		         gtk_text_view_get_right_margin(GTK_TEXT_VIEW(widget));
 
 		while(iter){
-			GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(iter->data);
+			struct scalable_data *sd = iter->data;
+			GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(sd->scalable);
 			scale->scale(scale, rect.width - xminus, rect.height);
 
 			iter = iter->next;
@@ -1139,15 +1151,17 @@
 		gtk_timeout_remove(imhtml->tip_timer);
 
 	for(scalables = imhtml->scalables; scalables; scalables = scalables->next) {
-		GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(scalables->data);
+		struct scalable_data *sd = scalables->data;
+		GtkIMHtmlScalable *scale = GTK_IMHTML_SCALABLE(sd->scalable);
 		scale->free(scale);
+		g_free(sd);
 	}
 
 	for (l = imhtml->im_images; l; l = l->next) {
-		int id;
-		id = GPOINTER_TO_INT(l->data);
+		struct im_image_data *img_data = l->data;
 		if (imhtml->funcs->image_unref)
-			imhtml->funcs->image_unref(id);
+			imhtml->funcs->image_unref(img_data->id);
+		g_free(img_data);
 	}
 
 	if (imhtml->clipboard_text_string) {
@@ -2463,17 +2477,19 @@
 				case 42:        /* HR (opt) */
 				{
 					int minus;
+					struct scalable_data *sd = g_new(struct scalable_data, 1);
 
 					ws[wpos++] = '\n';
 					gtk_text_buffer_insert(imhtml->text_buffer, iter, ws, wpos);
 
-					scalable = gtk_imhtml_hr_new();
+					sd->scalable = scalable = gtk_imhtml_hr_new();
 					gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect);
 					scalable->add_to(scalable, imhtml, iter);
 					minus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(imhtml)) +
 					        gtk_text_view_get_right_margin(GTK_TEXT_VIEW(imhtml));
 					scalable->scale(scalable, rect.width - minus, rect.height);
-					imhtml->scalables = g_list_append(imhtml->scalables, scalable);
+					sd->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE);
+					imhtml->scalables = g_list_append(imhtml->scalables, sd);
 					ws[0] = '\0'; wpos = 0;
 					ws[wpos++] = '\n';
 
@@ -2969,23 +2985,53 @@
 }
 
 void
-gtk_imhtml_clear (GtkIMHtml *imhtml)
-{
-	GList *del;
-	GtkTextIter start, end;
+gtk_imhtml_delete(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) {
+	GList *l;
+	GSList *sl;
+	GtkTextIter i;
 	GObject *object = g_object_ref(G_OBJECT(imhtml));
-	
-	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);
-
-	for(del = imhtml->scalables; del; del = del->next) {
-		GtkIMHtmlScalable *scale = del->data;
-		scale->free(scale);
+
+	if (start == NULL) {
+		GtkTextIter i_s;
+		gtk_text_buffer_get_start_iter(imhtml->text_buffer, &i_s);
+		start = &i_s;
+	}
+
+	if (end == NULL) {
+		GtkTextIter i_e;
+		gtk_text_buffer_get_end_iter(imhtml->text_buffer, &i_e);
+		end = &i_e;
 	}
-	
-	g_list_free(imhtml->scalables);
-	imhtml->scalables = NULL;
+
+	l = imhtml->scalables;
+	while (l) {
+		GList *next = l->next;
+		struct scalable_data *sd = l->data;
+		gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer,
+			&i, sd->mark);
+		if (gtk_text_iter_in_range(&i, start, end)) {
+			GtkIMHtmlScalable *scale = sd->scalable;
+			scale->free(scale);
+			imhtml->scalables = g_list_remove_link(imhtml->scalables, l);
+		}
+		l = next;
+	}
+
+	sl = imhtml->im_images;
+	while (sl) {
+		GSList *next = sl->next;
+		struct im_image_data *img_data = sl->data;
+		gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer,
+			&i, img_data->mark);
+		if (gtk_text_iter_in_range(&i, start, end)) {
+			if (imhtml->funcs->image_unref)
+				imhtml->funcs->image_unref(img_data->id);
+			imhtml->im_images = g_slist_delete_link(imhtml->im_images, sl);
+			g_free(img_data);
+		}
+		sl = next;
+	}
+	gtk_text_buffer_delete(imhtml->text_buffer, start, end);
 
 	g_object_unref(object);
 }
@@ -4194,6 +4240,7 @@
 	gpointer image;
 	GdkRectangle rect;
 	GtkIMHtmlScalable *scalable = NULL;
+	struct scalable_data *sd;
 	int minus;
 
 	if (!imhtml->funcs || !imhtml->funcs->image_get ||
@@ -4226,19 +4273,24 @@
 	if (pixbuf) {
 		filename = imhtml->funcs->image_get_filename(image);
 		imhtml->funcs->image_ref(id);
-		imhtml->im_images = g_slist_prepend(imhtml->im_images, GINT_TO_POINTER(id));
+		struct im_image_data *t = g_new(struct im_image_data, 1);
+		t->id = id;
+		t->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE);
+		imhtml->im_images = g_slist_prepend(imhtml->im_images, t);
 	} else {
 		pixbuf = gtk_widget_render_icon(GTK_WIDGET(imhtml), GTK_STOCK_MISSING_IMAGE,
 						GTK_ICON_SIZE_BUTTON, "gtkimhtml-missing-image");
 	}
 
-	scalable = gtk_imhtml_image_new(pixbuf, filename, id);
+	sd = g_new(struct scalable_data, 1);
+	sd->scalable = scalable = gtk_imhtml_image_new(pixbuf, filename, id);
 	gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(imhtml), &rect);
 	scalable->add_to(scalable, imhtml, iter);
 	minus = gtk_text_view_get_left_margin(GTK_TEXT_VIEW(imhtml)) +
 		gtk_text_view_get_right_margin(GTK_TEXT_VIEW(imhtml));
 	scalable->scale(scalable, rect.width - minus, rect.height);
-	imhtml->scalables = g_list_append(imhtml->scalables, scalable);
+	sd->mark = gtk_text_buffer_create_mark(imhtml->text_buffer, NULL, iter, TRUE);
+	imhtml->scalables = g_list_append(imhtml->scalables, sd);
 
 	g_object_unref(G_OBJECT(pixbuf));
 }
--- a/src/gtkimhtml.h	Wed Aug 10 05:45:17 2005 +0000
+++ b/src/gtkimhtml.h	Wed Aug 10 21:13:44 2005 +0000
@@ -347,11 +347,21 @@
 void gtk_imhtml_scroll_to_end(GtkIMHtml *imhtml);
 
 /**
+ * Delete the contents of a GTK+ IM/HTML between start and end.
+ *
+ * @param imhtml  The GTK+ IM/HTML.
+ * @param start   a postition in the imhtml's buffer
+ * @param end     another postition in the imhtml's buffer
+ */
+void gtk_imhtml_delete(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end);
+
+/**
  * Purges the contents from a GTK+ IM/HTML and resets formatting.
  *
  * @param imhtml  The GTK+ IM/HTML.
  */
-void gtk_imhtml_clear(GtkIMHtml *imhtml);
+#define gtk_imhtml_clear(imhtml) \
+ gtk_imhtml_delete(imhtml, NULL, NULL)
 
 /**
  * Scrolls a GTK+ IM/HTML up by one page.