[evolution-patches] fix for 60900




Ok this contains the previous patch plus something which should actually fix the bug.

Its a pretty big patch unfortunately, but also adds caching of decrypted parts and verification status, which speeds up when we need to redraw.

--
Michael Zucchi <notzed ximian com>

Novell's Evolution and Free Software Developer
Index: mail/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/mail/ChangeLog,v
retrieving revision 1.3411
diff -u -3 -r1.3411 ChangeLog
--- mail/ChangeLog	5 Jul 2004 15:08:21 -0000	1.3411
+++ mail/ChangeLog	9 Jul 2004 05:10:31 -0000
@@ -1,3 +1,48 @@
+2004-07-09  Not Zed  <NotZed Ximian com>
+
+	** See bug #60900.
+
+	* em-format-html.c: convert the text_inline_parts hash to be keyed
+	off the partid.
+	(efh_free_inline_parts): -> efh_free_cache and fix to do it.
+
+	* em-format.c (emf_free_cache): make the inline table cache other
+	info too based on partid, this frees the structure.
+	(emf_clone_inlines): copy all of the cache data.
+	(em_format_is_inline): use the new data structure to determine
+	state.
+	(em_format_set_inline): same for setting.
+	(emf_multipart_signed): cache/lookup the cached part.
+	(emf_insert_cache): helper to add a cache entry.
+	(emf_multipart_encrypted): cache decrypted part.
+	(emf_application_xpkcs7mime): same.
+
+2004-07-08  Not Zed  <NotZed Ximian com>
+
+	** See bug #60900 (related only).
+
+	* em-format-html-display.c (efhd_attachment_show): let set_inline
+	do the redraw itself if required.  kill some dead code.
+
+	* em-format.c (em_format_set_inline): trigger a redraw here like
+	the other em_format_set methods, if the state changed.
+
+	* em-format.c (emf_format_clone): free inline table keys & setup
+	string hash table.
+
+	* em-format-quote.c (emfq_format_attachment): 
+	* em-format-html-display.c (efhd_format_attachment): 
+	* em-format-html.c (efh_format_attachment): is_inline api changes.
+
+	* em-format-html-display.c (efhd_attachment_show): set_inline api
+	changes.
+
+	* em-format.c (em_format_is_inline): make this use the partid
+	rather than the part address as a key, which may change.
+	(emf_init): make the inline talbe a string hashtable.
+	(emf_finalise): free inline keys.
+	(emf_clone_inlines): copy the key string.
+
 2004-07-02  JP Rosevaer  <jpr novell com>
 
 	* Makefile.am (SUBDIRS): Revert previous error change
Index: mail/em-format-html-display.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-html-display.c,v
retrieving revision 1.47
diff -u -3 -r1.47 em-format-html-display.c
--- mail/em-format-html-display.c	23 Jun 2004 08:08:40 -0000	1.47
+++ mail/em-format-html-display.c	9 Jul 2004 05:10:32 -0000
@@ -1046,38 +1046,7 @@
 	d(printf("show attachment button called\n"));
 
 	info->shown = ~info->shown;
-	em_format_set_inline(info->puri.format, info->puri.part, info->shown);
-	/* FIXME: do this in an idle handler */
-	em_format_redraw(info->puri.format);
-#if 0
-	/* FIXME: track shown state in parent */
-
-	if (info->shown) {
-		d(printf("hiding\n"));
-		info->shown = FALSE;
-		if (info->frame)
-			gtk_widget_hide((GtkWidget *)info->frame);
-		gtk_widget_show(info->forward);
-		gtk_widget_hide(info->down);
-	} else {
-		d(printf("showing\n"));
-		info->shown = TRUE;
-		if (info->frame)
-			gtk_widget_show((GtkWidget *)info->frame);
-		gtk_widget_hide(info->forward);
-		gtk_widget_show(info->down);
-
-		/* have we decoded it yet? */
-		if (info->output) {
-			info->handle->handler(info->puri.format, info->output, info->puri.part, info->handle);
-			camel_stream_close(info->output);
-			camel_object_unref(info->output);
-			info->output = NULL;
-		}
-	}
-
-	em_format_set_inline(info->puri.format, info->puri.part, info->shown);
-#endif
+	em_format_set_inline(info->puri.format, info->puri.part_id, info->shown);
 }
 
 static EMPopupItem efhd_menu_items[] = {
@@ -1498,7 +1467,7 @@
 	info = (struct _attach_puri *)em_format_add_puri(emf, sizeof(*info), classid, part, efhd_attachment_frame);
 	em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(EMFormatHTMLPObject), classid, part, efhd_attachment_button);
 	info->handle = handle;
-	info->shown = em_format_is_inline(emf, info->puri.part, handle);
+	info->shown = em_format_is_inline(emf, info->puri.part_id, info->puri.part, handle);
 	info->snoop_mime_type = emf->snoop_mime_type;
 
 	camel_stream_write_string(stream,
Index: mail/em-format-html.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-html.c,v
retrieving revision 1.60
diff -u -3 -r1.60 em-format-html.c
--- mail/em-format-html.c	24 May 2004 08:02:25 -0000	1.60
+++ mail/em-format-html.c	9 Jul 2004 05:10:32 -0000
@@ -75,13 +75,19 @@
 
 #define EFH_TABLE_OPEN "<table>"
 
+struct _EMFormatHTMLCache {
+	CamelMultipart *textmp;
+
+	char partid[1];
+};
+
 struct _EMFormatHTMLPrivate {
 	struct _CamelMimeMessage *last_part;	/* not reffed, DO NOT dereference */
 	volatile int format_id;		/* format thread id */
 	guint format_timeout_id;
 	struct _format_msg *format_timeout_msg;
 
-	/* Table that re-maps text parts into a mutlipart/mixed */
+	/* Table that re-maps text parts into a mutlipart/mixed, EMFormatHTMLCache * */
 	GHashTable *text_inline_parts;
 
 	EDList pending_jobs;
@@ -120,7 +126,7 @@
 	e_dlist_init(&efh->priv->pending_jobs);
 	efh->priv->lock = g_mutex_new();
 	efh->priv->format_id = -1;
-	efh->priv->text_inline_parts = g_hash_table_new(NULL, NULL);
+	efh->priv->text_inline_parts = g_hash_table_new(g_str_hash, g_str_equal);
 
 	efh->html = (GtkHTML *)gtk_html_new();
 	gtk_html_set_blocking(efh->html, FALSE);
@@ -163,10 +169,27 @@
 	}
 }
 
+static struct _EMFormatHTMLCache *
+efh_insert_cache(EMFormatHTML *efh, const char *partid)
+{
+	struct _EMFormatHTMLCache *efhc;
+
+	efhc = g_malloc0(sizeof(*efh) + strlen(partid));
+	strcpy(efhc->partid, partid);
+	g_hash_table_insert(efh->priv->text_inline_parts, efhc->partid, efhc);
+
+	return efhc;
+}
+
+
 static void
-efh_free_inline_parts(void *key, void *data, void *user)
+efh_free_cache(void *key, void *val, void *dat)
 {
-	camel_object_unref(data);
+	struct _EMFormatHTMLCache *efhc = val;
+
+	if (efhc->textmp)
+		camel_object_unref(efhc->textmp);
+	g_free(efhc);
 }
 
 static void
@@ -180,7 +203,7 @@
 
 	efh_gtkhtml_destroy(efh->html, efh);
 
-	g_hash_table_foreach(efh->priv->text_inline_parts, efh_free_inline_parts, NULL);
+	g_hash_table_foreach(efh->priv->text_inline_parts, efh_free_cache, NULL);
 	g_hash_table_destroy(efh->priv->text_inline_parts);
 
 	g_free(efh->priv);
@@ -635,7 +658,8 @@
 	const char *format;
 	guint32 flags;
 	int i, count, len;
-	
+	struct _EMFormatHTMLCache *efhc;
+
 	camel_stream_printf (stream,
 			     "<table bgcolor=\"#%06x\" cellspacing=0 cellpadding=1 width=100%%><tr><td>\n"
 			     "<table bgcolor=\"#%06x\" cellspacing=0 cellpadding=0 width=100%%><tr><td>\n"
@@ -663,8 +687,8 @@
 	   filters a bit.  Perhaps the superclass should just deal with
 	   html anyway and be done with it ... */
 
-	mp = g_hash_table_lookup(efh->priv->text_inline_parts, part);
-	if (mp == NULL) {
+	efhc = g_hash_table_lookup(efh->priv->text_inline_parts, ((EMFormat *)efh)->part_id->str);
+	if (efhc == NULL || (mp = efhc->textmp) == NULL) {
 		EMInlineFilter *inline_filter;
 		CamelStream *null;
 		CamelContentType *ct;
@@ -685,8 +709,12 @@
 		camel_data_wrapper_write_to_stream(dw, (CamelStream *)filtered_stream);
 		camel_stream_close((CamelStream *)filtered_stream);
 		camel_object_unref(filtered_stream);
+
 		mp = em_inline_filter_get_multipart(inline_filter);
-		g_hash_table_insert(efh->priv->text_inline_parts, part, mp);
+		if (efhc == NULL)
+			efhc = efh_insert_cache(efh, ((EMFormat *)efh)->part_id->str);
+		efhc->textmp = mp;
+
 		camel_object_unref(inline_filter);
 		camel_content_type_unref(ct);
 	}
@@ -1292,9 +1320,9 @@
 						  | GTK_HTML_BEGIN_BLOCK_UPDATES | GTK_HTML_BEGIN_BLOCK_IMAGES);
 		} else {
 			/* clear cache of inline-scanned text parts */
-			g_hash_table_foreach(p->text_inline_parts, efh_free_inline_parts, NULL);
+			g_hash_table_foreach(p->text_inline_parts, efh_free_cache, NULL);
 			g_hash_table_destroy(p->text_inline_parts);
-			p->text_inline_parts = g_hash_table_new(NULL, NULL);
+			p->text_inline_parts = g_hash_table_new(g_str_hash, g_str_equal);
 
 			p->last_part = m->message;
 		}
@@ -1744,7 +1772,7 @@
 
 	camel_stream_write_string(stream, "</font></td></tr><tr></table>");
 
-	if (handle && em_format_is_inline(emf, part, handle))
+	if (handle && em_format_is_inline(emf, emf->part_id->str, part, handle))
 		handle->handler(emf, stream, part, handle);
 }
 
Index: mail/em-format-quote.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-quote.c,v
retrieving revision 1.10
diff -u -3 -r1.10 em-format-quote.c
--- mail/em-format-quote.c	25 May 2004 16:16:25 -0000	1.10
+++ mail/em-format-quote.c	9 Jul 2004 05:10:32 -0000
@@ -394,7 +394,7 @@
 static void
 emfq_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const char *mime_type, const EMFormatHandler *handle)
 {
-	if (handle && em_format_is_inline(emf, part, handle)) {
+	if (handle && em_format_is_inline(emf, emf->part_id->str, part, handle)) {
 		char *text, *html;
 
 		camel_stream_write_string(stream,
Index: mail/em-format.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format.c,v
retrieving revision 1.37
diff -u -3 -r1.37 em-format.c
--- mail/em-format.c	19 May 2004 07:02:12 -0000	1.37
+++ mail/em-format.c	9 Jul 2004 05:10:33 -0000
@@ -54,6 +54,24 @@
 
 #define d(x) 
 
+/* Used to cache various data/info for redraws
+   The validity stuff could be cached at a higher level but this is easier
+   This absolutely relies on the partid being _globally unique_
+   This is still kind of yucky, we should maintian a full tree of all this data,
+   along with/as part of the puri tree */
+struct _EMFormatCache {
+	struct _CamelCipherValidity *valid; /* validity copy */
+	struct _CamelMimePart *secured;	/* encrypted subpart */
+
+	unsigned int state:2;		/* inline state */
+
+	char partid[1];
+};
+
+#define INLINE_UNSET (0)
+#define INLINE_ON (1)
+#define INLINE_OFF (2)
+
 static void emf_builtin_init(EMFormatClass *);
 
 static const EMFormatHandler *emf_find_handler(EMFormat *emf, const char *mime_type);
@@ -71,11 +89,35 @@
 static GObjectClass *emf_parent;
 
 static void
+emf_free_cache(void *key, void *val, void *dat)
+{
+	struct _EMFormatCache *efc = val;
+
+	if (efc->valid)
+		camel_cipher_validity_free(efc->valid);
+	if (efc->secured)
+		camel_object_unref(efc->secured);
+	g_free(efc);
+}
+
+static struct _EMFormatCache *
+emf_insert_cache(EMFormat *emf, const char *partid)
+{
+	struct _EMFormatCache *new;
+
+	new = g_malloc0(sizeof(*new)+strlen(partid));
+	strcpy(new->partid, partid);
+	g_hash_table_insert(emf->inline_table, new->partid, new);
+
+	return new;
+}
+
+static void
 emf_init(GObject *o)
 {
 	EMFormat *emf = (EMFormat *)o;
 	
-	emf->inline_table = g_hash_table_new(NULL, NULL);
+	emf->inline_table = g_hash_table_new(g_str_hash, g_str_equal);
 	e_dlist_init(&emf->header_list);
 	em_format_default_headers(emf);
 	emf->part_id = g_string_new("");
@@ -89,8 +131,8 @@
 	if (emf->session)
 		camel_object_unref(emf->session);
 
-	if (emf->inline_table)
-		g_hash_table_destroy(emf->inline_table);
+	g_hash_table_foreach(emf->inline_table, emf_free_cache, NULL);
+	g_hash_table_destroy(emf->inline_table);
 
 	em_format_clear_headers(emf);
 	camel_cipher_validity_free(emf->valid);
@@ -526,7 +568,14 @@
 static void
 emf_clone_inlines(void *key, void *val, void *data)
 {
-	g_hash_table_insert(((EMFormat *)data)->inline_table, key, val);
+	struct _EMFormatCache *emfc = val, *new;
+
+	new = emf_insert_cache((EMFormat *)data, emfc->partid);
+	new->state = emfc->state;
+	if (emfc->valid)
+		new->valid = camel_cipher_validity_clone(emfc->valid);
+	if (emfc->secured)
+		camel_object_ref((new->secured = emfc->secured));
 }
 
 static void
@@ -535,8 +584,9 @@
 	em_format_clear_puri_tree(emf);
 
 	if (emf != emfsource) {
+		g_hash_table_foreach(emf->inline_table, emf_free_cache, NULL);
 		g_hash_table_destroy(emf->inline_table);
-		emf->inline_table = g_hash_table_new(NULL, NULL);
+		emf->inline_table = g_hash_table_new(g_str_hash, g_str_equal);
 		if (emfsource) {
 			struct _EMFormatHeader *h;
 
@@ -829,6 +879,7 @@
  * em_format_is_inline:
  * @emf: 
  * @part: 
+ * @partid: format->part_id part id of this part.
  * @handle: handler for this part
  * 
  * Returns true if the part should be displayed inline.  Any part with
@@ -840,16 +891,17 @@
  * 
  * Return value: 
  **/
-int em_format_is_inline(EMFormat *emf, CamelMimePart *part, const EMFormatHandler *handle)
+int em_format_is_inline(EMFormat *emf, const char *partid, CamelMimePart *part, const EMFormatHandler *handle)
 {
-	void *dummy, *override;
+	struct _EMFormatCache *emfc;
 	const char *tmp;
 
 	if (handle == NULL)
 		return FALSE;
 
-	if (g_hash_table_lookup_extended(emf->inline_table, part, &dummy, &override))
-		return GPOINTER_TO_INT(override);
+	emfc = g_hash_table_lookup(emf->inline_table, partid);
+	if (emfc && emfc->state != INLINE_UNSET)
+		return emfc->state & 1;
 
 	/* some types need to override the disposition, e.g. application/x-pkcs7-mime */
 	if (handle->flags & EM_FORMAT_HANDLER_INLINE_DISPOSITION)
@@ -866,16 +918,27 @@
 /**
  * em_format_set_inline:
  * @emf: 
- * @part: 
+ * @partid: id of part
  * @state: 
  * 
  * Force the attachment @part to be expanded or hidden explictly to match
  * @state.  This is used only to record the change for a redraw or
  * cloned layout render and does not force a redraw.
  **/
-void em_format_set_inline(EMFormat *emf, CamelMimePart *part, int state)
+void em_format_set_inline(EMFormat *emf, const char *partid, int state)
 {
-	g_hash_table_insert(emf->inline_table, part, GINT_TO_POINTER(state));
+	struct _EMFormatCache *emfc;
+
+	emfc = g_hash_table_lookup(emf->inline_table, partid);
+	if (emfc == NULL) {
+		emfc = emf_insert_cache(emf, partid);
+	} else if (emfc->state != INLINE_UNSET && (emfc->state & 1) == state)
+		return;
+
+	emfc->state = state?INLINE_ON:INLINE_OFF;
+
+	if (emf->message)
+		em_format_redraw(emf);
 }
 
 void em_format_format_error(EMFormat *emf, CamelStream *stream, const char *fmt, ...)
@@ -1013,6 +1076,14 @@
 	extern CamelSession *session;
 	CamelMimePart *opart;
 	CamelCipherValidity *valid;
+	struct _EMFormatCache *emfc;
+
+	/* should this perhaps run off a key of ".secured" ? */
+	emfc = g_hash_table_lookup(emf->inline_table, emf->part_id->str);
+	if (emfc && emfc->valid) {
+		em_format_format_secure(emf, stream, emfc->secured, camel_cipher_validity_clone(emfc->valid));
+		return;
+	}
 
 	ex = camel_exception_new();
 
@@ -1024,6 +1095,12 @@
 		em_format_format_error(emf, stream, ex->desc?ex->desc:_("Could not parse S/MIME message: Unknown error"));
 		em_format_part_as(emf, stream, part, NULL);
 	} else {
+		if (emfc == NULL)
+			emfc = emf_insert_cache(emf, emf->part_id->str);
+
+		emfc->valid = camel_cipher_validity_clone(valid);
+		camel_object_ref((emfc->secured = opart));
+
 		em_format_format_secure(emf, stream, opart, valid);
 	}
 
@@ -1126,6 +1203,14 @@
 	const char *protocol;
 	CamelMimePart *opart;
 	CamelCipherValidity *valid;
+	struct _EMFormatCache *emfc;
+
+	/* should this perhaps run off a key of ".secured" ? */
+	emfc = g_hash_table_lookup(emf->inline_table, emf->part_id->str);
+	if (emfc && emfc->valid) {
+		em_format_format_secure(emf, stream, emfc->secured, camel_cipher_validity_clone(emfc->valid));
+		return;
+	}
 
 	/* Currently we only handle RFC2015-style PGP encryption. */
 	protocol = camel_content_type_param (((CamelDataWrapper *) part)->mime_type, "protocol");
@@ -1145,9 +1230,16 @@
 			em_format_format_error(emf, stream, ex->desc);
 		em_format_part_as(emf, stream, part, "multipart/mixed");
 	} else {
+		if (emfc == NULL)
+			emfc = emf_insert_cache(emf, emf->part_id->str);
+
+		emfc->valid = camel_cipher_validity_clone(valid);
+		camel_object_ref((emfc->secured = opart));
+
 		em_format_format_secure(emf, stream, opart, valid);
 	}
 
+	/* TODO: Make sure when we finalise this part, it is zero'd out */
 	camel_object_unref(opart);
 	camel_object_unref(context);
 	camel_exception_free(ex);
@@ -1272,6 +1364,14 @@
 	CamelMimePart *cpart;
 	CamelMultipartSigned *mps;
 	CamelCipherContext *cipher = NULL;
+	struct _EMFormatCache *emfc;
+
+	/* should this perhaps run off a key of ".secured" ? */
+	emfc = g_hash_table_lookup(emf->inline_table, emf->part_id->str);
+	if (emfc && emfc->valid) {
+		em_format_format_secure(emf, stream, emfc->secured, camel_cipher_validity_clone(emfc->valid));
+		return;
+	}
 
 	mps = (CamelMultipartSigned *)camel_medium_get_content_object((CamelMedium *)part);
 	if (!CAMEL_IS_MULTIPART_SIGNED(mps)
@@ -1308,6 +1408,12 @@
 				em_format_format_error(emf, stream, ex->desc);
 			em_format_part_as(emf, stream, part, "multipart/mixed");
 		} else {
+			if (emfc == NULL)
+				emfc = emf_insert_cache(emf, emf->part_id->str);
+
+			emfc->valid = camel_cipher_validity_clone(valid);
+			camel_object_ref((emfc->secured = cpart));
+
 			em_format_format_secure(emf, stream, cpart, valid);
 		}
 
Index: mail/em-format.h
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format.h,v
retrieving revision 1.11
diff -u -3 -r1.11 em-format.h
--- mail/em-format.h	15 Mar 2004 15:19:00 -0000	1.11
+++ mail/em-format.h	9 Jul 2004 05:10:33 -0000
@@ -190,9 +190,10 @@
    Or maybe it should live with sub-classes? */
 
 int em_format_is_attachment(EMFormat *emf, struct _CamelMimePart *part);
-int em_format_is_inline(EMFormat *emf, struct _CamelMimePart *part, const EMFormatHandler *handle);
-/* FIXME: not sure about this api */
-void em_format_set_inline(EMFormat *emf, struct _CamelMimePart *part, int state);
+
+int em_format_is_inline(EMFormat *emf, const char *partid, struct _CamelMimePart *part, const EMFormatHandler *handle);
+void em_format_set_inline(EMFormat *emf, const char *partid, int state);
+
 char *em_format_describe_part(struct _CamelMimePart *part, const char *mimetype);
 
 /* for implementers */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]