evolution bnc bug #178631 patch

Jeffrey Stedfast <[email protected]>
Newsgroups gmane.comp.gnome.evolution.patches
Message-ID <[email protected]>
not sure if evo patches need to be reviewed by NLD-Patches reviewers or
what, but sending it anyway...

https://bugzilla.novell.com/show_bug.cgi?id=178631

The problem was that if gnome-vfs failed to "download" the remote file,
e-attachment-bar.c:update() would think that just because the attachment
download had "completed", it was safe to try and get mime info/pixmap
foo/etc to display in the icon list. This was unfortunately not the
case, and so it would crash.

The patch basically removes the attachment object from the
attachment-bar if it fails to download (any content). Had to change the
code to use a GPtrArray instead because it made doing this a lot simpler
than it would have been using the linked list approach (plus the linked
list approach had lots of FIXME's all over the place anyway and using a
GPtrArray fixed all of those).

Jeff

_______________________________________________
Evolution-patches mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/evolution-patches
bnc-178631.patch (text/x-patch, 26.8 KB)
Index: widgets/misc/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/widgets/misc/ChangeLog,v
retrieving revision 1.403.2.1
diff -u -r1.403.2.1 ChangeLog
--- widgets/misc/ChangeLog	10 Apr 2006 09:18:05 -0000	1.403.2.1
+++ widgets/misc/ChangeLog	26 May 2006 20:07:05 -0000
@@ -1,3 +1,46 @@
+2006-05-26  Jeffrey Stedfast  <[email protected]>
+
+	Fix for Novell bug #178631
+
+	* e-attachment-bar.c: Changed the EAttachmentBarPrivate struct, we
+	no longer use a linked list, instead we use a GPtrArray - faster,
+	simpler (plus all the code used indexes anyway, so it was really
+	bizarre).
+	(free_attachment_list): Removed.
+	(attachment_destroy): New GWeakNotify callback for when an
+	EAttachment object gets destroyed. Remove the attachment from the
+	attachments array.
+	(add_common): Updated to add to an array rather than a linked
+	list. Also weak_ref the attachment object.
+	(remove_attachment): Removed.
+	(update): Updated to use the array instead of linked list of
+	attachments.
+	(e_attachment_bar_remove_selected): Same.
+	(e_attachment_bar_set_width): Same.
+	(e_attachment_bar_edit_selected): Same.
+	(e_attachment_bar_get_selected): Same.
+	(e_attachment_bar_get_attachment): Same.
+	(e_attachment_bar_get_all_attachments): Same and also optimised
+	since we can cheat now without having to g_slist_reverse.
+	(e_attachment_bar_get_parts): Same.
+	(destroy): Same.
+	(eab_drag_data_get): Same.
+	(init): Init attachments to a g_ptr_array_new
+	(e_attachment_bar_to_multipart): Updated to use the attachments
+	array.
+	(e_attachment_bar_get_num_attachments): Updated to return the
+	attachments->len.
+	(e_attachment_bar_get_download_count): Updated to use the array.
+
+	* e-attachment.c (finalise): Close the editor dialog if it is
+	open.
+	(async_progress_update_cb): If the phase is COMPLETE but the
+	file_size is 0, then treat it as an error. In the error case,
+	unref the attachment object (this will magically remove it from
+	the EAttachmentBar).
+	(close_cb): Don't unref the attachment object here anymore.
+	(e_attachment_edit): Don't ref the EAttachment anymore.
+
 2006-03-28  Li Yuan  <[email protected]>
 
 	**Fixes bug #335618
Index: widgets/misc/e-attachment-bar.c
===================================================================
RCS file: /cvs/gnome/evolution/widgets/misc/e-attachment-bar.c,v
retrieving revision 1.16
diff -u -r1.16 e-attachment-bar.c
--- widgets/misc/e-attachment-bar.c	6 Mar 2006 10:47:01 -0000	1.16
+++ widgets/misc/e-attachment-bar.c	26 May 2006 20:07:05 -0000
@@ -65,18 +65,16 @@
 #define ICON_BORDER 2
 #define ICON_TEXT_SPACING 2
 
-
 static GnomeIconListClass *parent_class = NULL;
 
 struct _EAttachmentBarPrivate {
 	GtkWidget *attach;	/* attachment file dialogue, if active */
-
-	GList *attachments;
-	guint num_attachments;
-	gchar *path;
+	
+	gboolean batch_unref;
+	GPtrArray *attachments;
+	char *path;
 };
 
-
 enum {
 	CHANGED,
 	LAST_SIGNAL
@@ -84,10 +82,8 @@
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
-
 static void update (EAttachmentBar *bar);
 
-
 static char *
 size_to_string (gulong size)
 {
@@ -120,17 +116,13 @@
 /* Attachment handling functions.  */
 
 static void
-free_attachment_list (EAttachmentBar *bar)
+attachment_destroy (EAttachmentBar *bar, EAttachment *attachment)
 {
-	EAttachmentBarPrivate *priv;
-	GList *p;
-	
-	priv = bar->priv;
-	
-	for (p = priv->attachments; p != NULL; p = p->next)
-		g_object_unref (p->data);
+	if (bar->priv->batch_unref)
+		return;
 	
-	priv->attachments = NULL;
+	if (g_ptr_array_remove (bar->priv->attachments, attachment))
+		g_signal_emit (bar, signals[CHANGED], 0);
 }
 
 static void
@@ -146,13 +138,9 @@
 {
 	g_return_if_fail (attachment != NULL);
 	
-	g_signal_connect (attachment, "changed",
-			  G_CALLBACK (attachment_changed_cb),
-			  bar);
-	
-	bar->priv->attachments = g_list_append (bar->priv->attachments,
-						attachment);
-	bar->priv->num_attachments++;
+	g_ptr_array_add (bar->priv->attachments, attachment);
+	g_object_weak_ref ((GObject *) attachment, (GWeakNotify) attachment_destroy, bar);
+	g_signal_connect (attachment, "changed", G_CALLBACK (attachment_changed_cb), bar);
 	
 	update (bar);
 	
@@ -186,27 +174,7 @@
 	}
 }
 
-static void
-remove_attachment (EAttachmentBar *bar,
-		   EAttachment *attachment)
-{
-	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
-	g_return_if_fail (g_list_find (bar->priv->attachments, attachment) != NULL);
 
-	bar->priv->attachments = g_list_remove (bar->priv->attachments,
-						attachment);
-	bar->priv->num_attachments--;
-	if (attachment->editor_gui != NULL) {
-		GtkWidget *dialog = glade_xml_get_widget (attachment->editor_gui, "dialog");
-		g_signal_emit_by_name (dialog, "response", GTK_RESPONSE_CLOSE);
-	}
-	
-	g_object_unref(attachment);
-	
-	g_signal_emit (bar, signals[CHANGED], 0);
-}
-
-
 /* Icon list contents handling.  */
 
 static void
@@ -215,7 +183,7 @@
         int width, height, icon_width;
         PangoFontMetrics *metrics;
         PangoContext *context;
-			
+	
         context = gtk_widget_get_pango_context ((GtkWidget *) bar);
         metrics = pango_context_get_metrics (context, ((GtkWidget *) bar)->style->font_desc, pango_context_get_language (context));
         width = PANGO_PIXELS (pango_font_metrics_get_approximate_char_width (metrics)) * 15;
@@ -236,10 +204,10 @@
 static void
 update (EAttachmentBar *bar)
 {
-	EAttachmentBarPrivate *priv;
+	struct _EAttachmentBarPrivate *priv;
 	GnomeIconList *icon_list;
-	GList *p;
 	int bar_width, bar_height;
+	int i;
 	
 	priv = bar->priv;
 	icon_list = GNOME_ICON_LIST (bar);
@@ -249,15 +217,15 @@
 	gnome_icon_list_clear (icon_list);
 	
 	/* FIXME could be faster, but we don't care.  */
-	for (p = priv->attachments; p != NULL; p = p->next) {
+	for (i = 0; i < priv->attachments->len; i++) {
 		EAttachment *attachment;
 		CamelContentType *content_type;
 		char *size_string, *label;
 		GdkPixbuf *pixbuf=NULL;
 		const char *desc;
 		
-		attachment = p->data;
-
+		attachment = priv->attachments->pdata[i];
+		
 		if (!attachment->is_available_local) {
 			/* stock_attach would be better, but its fugly scaled up */
 			pixbuf = e_icon_factory_get_icon("stock_unknown", E_ICON_SIZE_DIALOG);
@@ -267,6 +235,7 @@
 			}
 			continue;
 		}
+		
 		content_type = camel_mime_part_get_content_type (attachment->body);
 		/* Get the image out of the attachment 
 		   and create a thumbnail for it */
@@ -407,14 +376,14 @@
 	/* Resize */
 	if (bar->expand) {
 		gtk_widget_get_size_request ((GtkWidget *)bar, &bar_width, &bar_height);
-	
-		if (bar->priv->num_attachments) {
+		
+		if (bar->priv->attachments->len) {
 			int per_col, rows, height, width;
-	
+			
 			calculate_height_width(bar, &width, &height);
 			per_col = bar_width / width;
 			per_col = (per_col ? per_col : 1);
-			rows = (bar->priv->num_attachments + per_col -1 )/ per_col;
+			rows = (bar->priv->attachments->len + per_col -1) / per_col;
 			gtk_widget_set_size_request ((GtkWidget *)bar, bar_width, rows * height);
 		}
 	}
@@ -452,47 +421,35 @@
 void
 e_attachment_bar_remove_selected (EAttachmentBar *bar)
 {
-	GnomeIconList *icon_list;
+	struct _EAttachmentBarPrivate *priv;
 	EAttachment *attachment;
-	GList *attachment_list, *p;
-	int num = 0, left, dlen;
-
-	g_return_if_fail (bar != NULL);
+	int id, left, nrem = 0;
+	GList *items;
+	
 	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
 	
-	icon_list = GNOME_ICON_LIST (bar);
+	priv = bar->priv;
 	
-	/* Weee!  I am especially proud of this piece of cheesy code: it is
-           truly awful.  But unless one attaches a huge number of files, it
-           will not be as greedy as intended.  FIXME of course.  */
-	
-	attachment_list = NULL;
-	p = gnome_icon_list_get_selection (icon_list);
-	dlen = g_list_length (p);
-	for ( ; p != NULL; p = p->next) {
-		num = GPOINTER_TO_INT (p->data);
-		attachment = E_ATTACHMENT (g_list_nth_data (bar->priv->attachments, num));
-
-		/* We need to check if there are duplicated index in the return list of 
-		   gnome_icon_list_get_selection() because of gnome bugzilla bug #122356.
-		   FIXME in the future. */
-
-		if (g_list_find (attachment_list, attachment) == NULL) {
-			attachment_list = g_list_prepend (attachment_list, attachment);
+	if (!(items = gnome_icon_list_get_selection ((GnomeIconList *) bar)))
+		return;
+	
+	while (items != NULL) {
+		if ((id = GPOINTER_TO_INT (items->data) - nrem) < priv->attachments->len) {
+			/* Note: this removes the item from the array due to the weak_ref callback */
+			attachment = priv->attachments->pdata[id];
+			g_object_unref (attachment);
+			nrem++;
 		}
+		
+		items = items->next;
 	}
 	
-	for (p = attachment_list; p != NULL; p = p->next)
-		remove_attachment (bar, E_ATTACHMENT (p->data));
-	
-	g_list_free (attachment_list);
-	
 	update (bar);
 	
-	left = gnome_icon_list_get_num_icons (icon_list);
-	num = num - dlen + 1;
-	if (left > 0)
-		gnome_icon_list_focus_icon (icon_list, left > num ? num : left - 1);
+	id++;
+	
+	if ((left = gnome_icon_list_get_num_icons ((GnomeIconList *) bar)) > 0)
+		gnome_icon_list_focus_icon ((GnomeIconList *) bar, left > id ? id : left - 1);
 }
 
 void
@@ -503,120 +460,136 @@
 	calculate_height_width(bar, &width, &height);
 	per_col = bar_width / width;
 	per_col = (per_col ? per_col : 1);
-	rows = (bar->priv->num_attachments + per_col - 1) / per_col;
+	rows = (bar->priv->attachments->len + per_col - 1) / per_col;
 	gtk_widget_set_size_request ((GtkWidget *)bar, bar_width, rows * height);
 }
 
 void
 e_attachment_bar_edit_selected (EAttachmentBar *bar)
 {
-	GnomeIconList *icon_list;
-	GList *selection, *attach;
-	int num;
-
-	g_return_if_fail (bar != NULL);
+	struct _EAttachmentBarPrivate *priv;
+	EAttachment *attachment;
+	GList *items;
+	int id;
+	
 	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
 	
-	icon_list = GNOME_ICON_LIST (bar);
+	priv = bar->priv;
 	
-	selection = gnome_icon_list_get_selection (icon_list);
-	if (selection) {
-		num = GPOINTER_TO_INT (selection->data);
-		attach = g_list_nth (bar->priv->attachments, num);
-		if (attach)
-			e_attachment_edit ((EAttachment *)attach->data, GTK_WIDGET (bar));
+	items = gnome_icon_list_get_selection ((GnomeIconList *) bar);
+	while (items != NULL) {
+		if ((id = GPOINTER_TO_INT (items->data)) < priv->attachments->len) {
+			attachment = priv->attachments->pdata[id];
+			e_attachment_edit (attachment, GTK_WIDGET (bar));
+		}
+		
+		items = items->next;
 	}
 }
 
 GtkWidget **
 e_attachment_bar_get_selector(EAttachmentBar *bar)
 {
-	g_return_val_if_fail (bar != NULL, 0);
-	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), 0);
+	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
 	
 	return &bar->priv->attach;
 }
 
+
+/**
+ * e_attachment_bar_get_selected:
+ * @bar: an #EAttachmentBar object
+ *
+ * Returns a newly allocated #GSList of ref'd #EAttachment objects
+ * representing the selected items in the #EAttachmentBar Icon List.
+ **/
 GSList *
 e_attachment_bar_get_selected (EAttachmentBar *bar)
 {
+	struct _EAttachmentBarPrivate *priv;
 	GSList *attachments = NULL;
-	GList *p;
-
-	g_return_val_if_fail (bar != NULL, 0);
-	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), 0);
-
-	p = gnome_icon_list_get_selection((GnomeIconList *)bar);
-	for ( ; p != NULL; p = p->next) {
-		int num = GPOINTER_TO_INT(p->data);
-		EAttachment *attachment = g_list_nth_data(bar->priv->attachments, num);
-			
-		if (attachment && g_slist_find(attachments, attachment) == NULL) {
-			g_object_ref(attachment);
-			attachments = g_slist_prepend(attachments, attachment);
+	EAttachment *attachment;
+	GList *items;
+	int id;
+	
+	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
+	
+	priv = bar->priv;
+	
+	items = gnome_icon_list_get_selection ((GnomeIconList *) bar);
+	
+	while (items != NULL) {
+		if ((id = GPOINTER_TO_INT (items->data)) < priv->attachments->len) {
+			attachment = priv->attachments->pdata[id];
+			attachments = g_slist_prepend (attachments, attachment);
+			g_object_ref (attachment);
 		}
+		
+		items = items->next;
 	}
-	attachments = g_slist_reverse(attachments);
+	
+	attachments = g_slist_reverse (attachments);
 	
 	return attachments;
 }
 
 /* FIXME: Cleanup this, since there is a api to get selected attachments */
-/* if id != -1, then use it as an index for target of the popup */
+/**
+ * e_attachment_bar_get_attachment:
+ * @bar: an #EAttachmentBar object
+ * @id: Index of the desired attachment or -1 to request all selected attachments
+ *
+ * Returns a newly allocated #GSList of ref'd #EAttachment objects
+ * representing the requested item(s) in the #EAttachmentBar Icon
+ * List.
+ **/
 GSList *
 e_attachment_bar_get_attachment (EAttachmentBar *bar, int id)
 {
-	GSList *attachments = NULL;
-	GList *p;
+	struct _EAttachmentBarPrivate *priv;
 	EAttachment *attachment;
-
-	g_return_val_if_fail (bar != NULL, 0);
-	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), 0);
-
-	/* We need to check if there are duplicated index in the return list of 
-	   gnome_icon_list_get_selection() because of gnome bugzilla bug #122356.
-	   FIXME in the future. */
-
-	if (id == -1
-	    || (attachment = g_list_nth_data(bar->priv->attachments, id)) == NULL) {
-		p = gnome_icon_list_get_selection((GnomeIconList *)bar);
-		for ( ; p != NULL; p = p->next) {
-			int num = GPOINTER_TO_INT(p->data);
-			EAttachment *attachment = g_list_nth_data(bar->priv->attachments, num);
-			
-			if (attachment && g_slist_find(attachments, attachment) == NULL) {
-				g_object_ref(attachment);
-				attachments = g_slist_prepend(attachments, attachment);
-			}
-		}
-		attachments = g_slist_reverse(attachments);
-	} else {
-		g_object_ref(attachment);
-		attachments = g_slist_prepend(attachments, attachment);
-	}
+	GSList *attachments;
+	
+	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
+	
+	priv = bar->priv;
+	
+	if (id == -1 || id > priv->attachments->len)
+		return e_attachment_bar_get_selected (bar);
+	
+	attachment = priv->attachments->pdata[id];
+	attachments = g_slist_prepend (NULL, attachment);
+	g_object_ref (attachment);
 	
 	return attachments;
 }
 
+
+/**
+ * e_attachment_bar_get_all_attachments:
+ * @bar: an #EAttachmentBar object
+ *
+ * Returns a newly allocated #GSList of ref'd #EAttachment objects.
+ **/
 GSList *
 e_attachment_bar_get_all_attachments (EAttachmentBar *bar)
 {
+	struct _EAttachmentBarPrivate *priv;
 	GSList *attachments = NULL;
-	GList *p;
 	EAttachment *attachment;
-
-	g_return_val_if_fail (bar != NULL, 0);
-	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), 0);
-
-        for ( p = bar->priv->attachments; p!= NULL; p = p->next) {
-                attachment = p->data;
-                if (attachment && attachment->is_available_local) {
+	int i;
+	
+	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
+	
+	priv = bar->priv;
+	
+	for (i = priv->attachments->len - 1; i >= 0; i--) {
+		attachment = priv->attachments->pdata[i];
+		if (attachment->is_available_local) {
+			attachments = g_slist_prepend (attachments, attachment);
 			g_object_ref (attachment);
-                        attachments= g_slist_prepend(attachments, attachment);
 		}
-        }
-
-	attachments = g_slist_reverse(attachments);
+	}
 	
 	return attachments;
 }
@@ -625,20 +598,22 @@
 GSList *
 e_attachment_bar_get_parts (EAttachmentBar *bar)
 {
-        EAttachment *attachment;
-        GList *p = NULL;
-	GSList *part_list = NULL;
-
-	g_return_val_if_fail (bar != NULL, 0);
-	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), 0);
-
-        for ( p = bar->priv->attachments; p!= NULL; p = p->next) {
-                attachment = p->data;
-                if (attachment && attachment->is_available_local)
-                        part_list = g_slist_prepend(part_list, attachment->body);
-        }
+	struct _EAttachmentBarPrivate *priv;
+	EAttachment *attachment;
+	GSList *parts = NULL;
+	int i;
+	
+	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), NULL);
 	
-        return part_list;
+	priv = bar->priv;
+	
+	for (i = 0; i < priv->attachments->len; i++) {
+		attachment = priv->attachments->pdata[i];
+		if (attachment->is_available_local)
+			parts = g_slist_prepend (parts, attachment->body);
+	}
+	
+        return parts;
 }
 
 /* GtkObject methods.  */
@@ -646,20 +621,26 @@
 static void
 destroy (GtkObject *object)
 {
-	EAttachmentBar *bar;
-	
-	bar = E_ATTACHMENT_BAR (object);
+	EAttachmentBar *bar = (EAttachmentBar *) object;
+	struct _EAttachmentBarPrivate *priv = bar->priv;
+	EAttachment *attachment;
+	int i;
 	
-	if (bar->priv) {
-		free_attachment_list (bar);
-
-		if (bar->priv->attach)
-			gtk_widget_destroy(bar->priv->attach);
-
-		if (bar->priv->path)
-			g_free (bar->priv->path);
-
-		g_free (bar->priv);
+	if ((priv = bar->priv)) {
+		priv->batch_unref = TRUE;
+		for (i = 0; i < priv->attachments->len; i++) {
+			attachment = priv->attachments->pdata[i];
+			g_object_unref (attachment);
+		}
+		g_ptr_array_free (priv->attachments, TRUE);
+		
+		if (priv->attach)
+			gtk_widget_destroy (priv->attach);
+		
+		if (priv->path)
+			g_free (priv->path);
+		
+		g_free (priv);
 		bar->priv = NULL;
 	}
 	
@@ -723,51 +704,54 @@
 static void
 eab_drag_data_get(EAttachmentBar *bar, GdkDragContext *drag, GtkSelectionData *data, guint info, guint time)
 {
-	char *path;
-	GList *tmp;
-	gchar **uris;
-	int length, i=0;
-
+	struct _EAttachmentBarPrivate *priv = bar->priv;
+	EAttachment *attachment;
+	char *path, **uris;
+	int len, n, i = 0;
+	CamelURL *url;
+	GList *items;
+	
 	if (info)
 		return;
 	
-	tmp = gnome_icon_list_get_selection (GNOME_ICON_LIST(bar));
-	length = g_list_length (tmp);
-
-	uris = g_malloc0(sizeof(bar) * (length+1));
-
-	for (; tmp; tmp = tmp->next) {
-		int num = GPOINTER_TO_INT(tmp->data);
-		EAttachment *attachment = g_list_nth_data(bar->priv->attachments, num);	
-		CamelURL *curl;
-
+	items = gnome_icon_list_get_selection (GNOME_ICON_LIST (bar));
+	len = g_list_length (items);
+	
+	uris = g_malloc0 (sizeof (char *) * (len + 1));
+	
+	for ( ; items != NULL; items = items->next) {
+		if (!((n = GPOINTER_TO_INT (items->data)) < priv->attachments->len))
+			continue;
+		
+		attachment = priv->attachments->pdata[n];
+		
 		if (!attachment->is_available_local)
 			continue;
-
+		
 		if (attachment->store_uri) {
-			uris[i] = attachment->store_uri;
-			i++;
+			uris[i++] = attachment->store_uri;
 			continue;
 		}
-		path = temp_save_part(attachment->body);
-		/* If we are not able to save, ignore it*/
-		if (path == NULL) 
+		
+		/* If we are not able to save, ignore it */
+		if (!(path = temp_save_part (attachment->body)))
 			continue;
 		
-		curl = camel_url_new("file:", NULL);
-		camel_url_set_path (curl, path);
-		attachment->store_uri = camel_url_to_string (curl, 0);
-		camel_url_free(curl);		
-		g_free(path);
+		url = camel_url_new ("file:", NULL);
+		camel_url_set_path (url, path);
+		attachment->store_uri = camel_url_to_string (url, 0);
+		camel_url_free (url);
+		g_free (path);
 		
-		uris[i] = attachment->store_uri;
-		i++;
+		uris[i++] = attachment->store_uri;
 	}
-	uris[i]=0;
-	gtk_selection_data_set_uris(data, uris);
+	
+	uris[i] = NULL;
+	
+	gtk_selection_data_set_uris (data, uris);
 	
 	g_free (uris);
-
+	
 	return;
 }
 
@@ -922,13 +906,13 @@
 static void
 init (EAttachmentBar *bar)
 {
-	EAttachmentBarPrivate *priv;
+	struct _EAttachmentBarPrivate *priv;
 	
-	priv = g_new (EAttachmentBarPrivate, 1);
+	priv = g_new (struct _EAttachmentBarPrivate, 1);
 	
 	priv->attach = NULL;
-	priv->attachments = NULL;
-	priv->num_attachments = 0;
+	priv->batch_unref = FALSE;
+	priv->attachments = g_ptr_array_new ();
 	priv->path = NULL;
 	
 	bar->priv = priv;
@@ -1093,38 +1077,36 @@
 			       CamelMultipart *multipart,
 			       const char *default_charset)
 {
-	EAttachmentBarPrivate *priv;
-	GList *p;
+	struct _EAttachmentBarPrivate *priv;
+	EAttachment *attachment;
+	int i;
 	
 	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
 	g_return_if_fail (CAMEL_IS_MULTIPART (multipart));
 	
 	priv = bar->priv;
 	
-	for (p = priv->attachments; p != NULL; p = p->next) {
-		EAttachment *attachment;
-		
-		attachment = E_ATTACHMENT (p->data);
+	for (i = 0; i < priv->attachments->len; i++) {
+		attachment = priv->attachments->pdata[i];
 		if (attachment->is_available_local)
 			attach_to_multipart (multipart, attachment, default_charset);
 	}
 }
 
-
+
 guint
 e_attachment_bar_get_num_attachments (EAttachmentBar *bar)
 {
-	g_return_val_if_fail (bar != NULL, 0);
 	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), 0);
 	
-	return bar->priv->num_attachments;
+	return bar->priv->attachments->len;
 }
 
-
+
 void
 e_attachment_bar_attach (EAttachmentBar *bar,
-			 const gchar *file_name,
-			 char *disposition)
+			 const char *file_name,
+			 const char *disposition)
 {
 	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
 	g_return_if_fail ( file_name != NULL && disposition != NULL);
@@ -1136,7 +1118,6 @@
 e_attachment_bar_add_attachment (EAttachmentBar *bar,
 				 EAttachment *attachment)
 {
-	g_return_if_fail (bar != NULL);
 	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
 	
 	add_common (bar, attachment);
@@ -1145,44 +1126,40 @@
 int 
 e_attachment_bar_get_download_count (EAttachmentBar *bar)
 {
-	EAttachmentBarPrivate *priv;
-	GList *p;
-	int count=0;
+	struct _EAttachmentBarPrivate *priv;
+	EAttachment *attachment;
+	int i, n = 0;
 	
-	g_return_val_if_fail (bar != NULL, 0);
 	g_return_val_if_fail (E_IS_ATTACHMENT_BAR (bar), 0);
 	
 	priv = bar->priv;
 	
-	for (p = priv->attachments; p != NULL; p = p->next) {
-		EAttachment *attachment;
-		
-		attachment = p->data;
+	for (i = 0; i < priv->attachments->len; i++) {
+		attachment = priv->attachments->pdata[i];
 		if (!attachment->is_available_local)
-			count++;
+			n++;
 	}
-
-	return count;
+	
+	return n;
 }
 
 void 
 e_attachment_bar_attach_remote_file (EAttachmentBar *bar,
-				     const gchar *url)
+				     const char *url)
 {
 	EAttachment *attachment;
 	CamelException ex;
-
-	g_return_if_fail ( bar!=NULL );
+	
 	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
-
+	
 	if (!bar->priv->path)
 		bar->priv->path = e_mkdtemp("attach-XXXXXX");
-
+	
 	camel_exception_init (&ex);
 	attachment = e_attachment_new_remote_file (url, "attachment", bar->priv->path, &ex);
-	g_signal_connect (attachment, "update", G_CALLBACK(update_remote_file), bar);
 	if (attachment) {
 		add_common (bar, attachment);
+		g_signal_connect (attachment, "update", G_CALLBACK (update_remote_file), bar);
 	} else {
 		e_error_run((GtkWindow *)gtk_widget_get_toplevel((GtkWidget *)bar), "mail-composer:no-attach",
 			    attachment->file_name, camel_exception_get_description(&ex), NULL);
@@ -1194,7 +1171,6 @@
 e_attachment_bar_attach_mime_part (EAttachmentBar *bar,
 				   CamelMimePart *part)
 {
-	g_return_if_fail ( bar!=NULL );
 	g_return_if_fail (E_IS_ATTACHMENT_BAR (bar));
 	
 	add_from_mime_part (bar, part);
Index: widgets/misc/e-attachment-bar.h
===================================================================
RCS file: /cvs/gnome/evolution/widgets/misc/e-attachment-bar.h,v
retrieving revision 1.5
diff -u -r1.5 e-attachment-bar.h
--- widgets/misc/e-attachment-bar.h	15 Nov 2005 17:08:51 -0000	1.5
+++ widgets/misc/e-attachment-bar.h	26 May 2006 20:07:05 -0000
@@ -48,13 +48,12 @@
 
 typedef struct _EAttachmentBar EAttachmentBar;
 typedef struct _EAttachmentBarClass EAttachmentBarClass;
-typedef struct _EAttachmentBarPrivate EAttachmentBarPrivate;
 
 struct _EAttachmentBar {
 	GnomeIconList parent;
 	gboolean expand;
-
-	EAttachmentBarPrivate *priv;
+	
+	struct _EAttachmentBarPrivate *priv;
 };
 
 struct _EAttachmentBarClass {
@@ -68,12 +67,12 @@
 
 GtkWidget *e_attachment_bar_new (GtkAdjustment *adj);
 void e_attachment_bar_to_multipart (EAttachmentBar *bar, CamelMultipart *multipart,
-						 const char *default_charset);
+				    const char *default_charset);
 guint e_attachment_bar_get_num_attachments (EAttachmentBar *bar);
-void e_attachment_bar_attach (EAttachmentBar *bar, const char *file_name, char *disposition);
+void e_attachment_bar_attach (EAttachmentBar *bar, const char *file_name, const char *disposition);
 void e_attachment_bar_attach_mime_part (EAttachmentBar *bar, CamelMimePart *part);
 int e_attachment_bar_get_download_count (EAttachmentBar *bar);
-void e_attachment_bar_attach_remote_file (EAttachmentBar *bar,const gchar *url);
+void e_attachment_bar_attach_remote_file (EAttachmentBar *bar, const char *url);
 GSList *e_attachment_bar_get_attachment (EAttachmentBar *bar, int id);
 void e_attachment_bar_add_attachment (EAttachmentBar *bar, EAttachment *attachment);
 void e_attachment_bar_edit_selected (EAttachmentBar *bar);
Index: widgets/misc/e-attachment.c
===================================================================
RCS file: /cvs/gnome/evolution/widgets/misc/e-attachment.c,v
retrieving revision 1.9
diff -u -r1.9 e-attachment.c
--- widgets/misc/e-attachment.c	30 Jan 2006 12:28:04 -0000	1.9
+++ widgets/misc/e-attachment.c	26 May 2006 20:07:05 -0000
@@ -78,12 +78,16 @@
 /* GtkObject methods.  */
 
 static void
-finalise(GObject *object)
+finalise (GObject *object)
 {
-	EAttachment *attachment;
+	EAttachment *attachment = (EAttachment *) object;
+	GtkWidget *dialog;
+	
+	if (attachment->editor_gui != NULL) {
+		dialog = glade_xml_get_widget (attachment->editor_gui, "dialog");
+		g_signal_emit_by_name (dialog, "response", GTK_RESPONSE_CLOSE);
+	}
 	
-	attachment = E_ATTACHMENT (object);
-
 	if (attachment->is_available_local) {
 		camel_object_unref (attachment->body);
 		if (attachment->pixbuf_cache != NULL)
@@ -93,10 +97,10 @@
 			gnome_vfs_async_cancel(attachment->handle);
 		g_free (attachment->description);
 	}
-
+	
 	g_free (attachment->file_name);
 	g_free (attachment->store_uri);
-
+	
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -208,7 +212,7 @@
 	return type;
 }
 
-
+
 /**
  * e_attachment_new:
  * @file_name: filename to attach
@@ -324,7 +328,6 @@
 {
 	switch (info->status) {
 	case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
-	{
 		if (info->file_size) {
 			download_info->attachment->percentage = info->bytes_copied*100/info->file_size;
 			g_signal_emit (download_info->attachment, signals[UPDATE], 0);
@@ -336,6 +339,9 @@
 		if (info->phase == GNOME_VFS_XFER_PHASE_COMPLETED) {
 			CamelException ex;
 			
+			if (!info->file_size)
+				goto error;
+			
 			download_info->attachment->is_available_local = TRUE;
 			download_info->attachment->handle = NULL;
 			camel_exception_init (&ex);
@@ -346,13 +352,12 @@
 			g_free (download_info);
 		}
 		return TRUE;
-	}
 	case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
-		gnome_vfs_async_cancel (handle);
+	error:
+		g_object_unref (download_info->attachment);
 		g_free (download_info->file_name);
 		g_free (download_info);
 		return FALSE;
-
 	default:
 		break;
 	}
@@ -599,8 +604,6 @@
 	g_object_unref (attachment->editor_gui);
 	attachment->editor_gui = NULL;
 	
-	g_object_unref (attachment);
-	
 	destroy_dialog_data (dialog_data);
 }
 
@@ -673,7 +676,6 @@
 	char *type;
 	char *filename;
 	
-	g_return_if_fail (attachment != NULL);
 	g_return_if_fail (E_IS_ATTACHMENT (attachment));
 	
 	if (attachment->editor_gui != NULL) {
@@ -704,7 +706,6 @@
 		 GTK_WINDOW (gtk_widget_get_toplevel (parent)));
 	
 	dialog_data = g_new (DialogData, 1);
-	g_object_ref (attachment);
 	dialog_data->attachment = attachment;
 	dialog_data->dialog = glade_xml_get_widget (editor_gui, "dialog");
 	dialog_data->file_name_entry = GTK_ENTRY (
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.