aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog50
-rw-r--r--mail/em-folder-browser.c6
-rw-r--r--mail/em-format-html-display.c35
-rw-r--r--mail/em-format-html.c52
-rw-r--r--mail/em-format-quote.c2
-rw-r--r--mail/em-format.c130
-rw-r--r--mail/em-format.h7
7 files changed, 219 insertions, 63 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 6b0eafccfc..fd86443c71 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,53 @@
+2004-07-09 Not Zed <NotZed@Ximian.com>
+
+ * em-folder-browser.c (emfb_folder_expunge): only call expunge if
+ the folder is set.
+ (emfb_enable_map[]): only enable expunge menu item if we have a
+ valid folder set.
+
+ ** 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-07 Jeffrey Stedfast <fejj@novell.com>
Fix for bug #61199.
diff --git a/mail/em-folder-browser.c b/mail/em-folder-browser.c
index e61453e8ce..e9c14ea600 100644
--- a/mail/em-folder-browser.c
+++ b/mail/em-folder-browser.c
@@ -556,8 +556,9 @@ static void
emfb_folder_expunge(BonoboUIComponent *uid, void *data, const char *path)
{
EMFolderBrowser *emfb = data;
-
- em_utils_expunge_folder(gtk_widget_get_toplevel((GtkWidget *)emfb), emfb->view.folder);
+
+ if (emfb->view.folder)
+ em_utils_expunge_folder(gtk_widget_get_toplevel((GtkWidget *)emfb), emfb->view.folder);
}
static void
@@ -722,6 +723,7 @@ static const EMFolderViewEnable emfb_enable_map[] = {
{ "EditInvertSelection", EM_POPUP_SELECT_FOLDER },
{ "EditSelectAll", EM_POPUP_SELECT_FOLDER },
{ "EditSelectThread", EM_FOLDER_VIEW_SELECT_THREADED },
+ { "FolderExpunge", EM_POPUP_SELECT_FOLDER },
{ "MailPost", EM_POPUP_SELECT_FOLDER },
{ "MessageMarkAllAsRead", EM_POPUP_SELECT_FOLDER },
{ "ViewHideSelected", EM_POPUP_SELECT_MANY },
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index a55189d644..fd5e653625 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -1046,38 +1046,7 @@ efhd_attachment_show(GtkWidget *w, struct _attach_puri *info)
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 @@ efhd_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part,
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,
diff --git a/mail/em-format-html.c b/mail/em-format-html.c
index 0cb3e15cb2..d84238fda0 100644
--- a/mail/em-format-html.c
+++ b/mail/em-format-html.c
@@ -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 @@ efh_init(GObject *o)
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 @@ efh_gtkhtml_destroy(GtkHTML *html, EMFormatHTML *efh)
}
}
+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_finalise(GObject *o)
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 @@ efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFo
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 @@ efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFo
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 @@ efh_text_plain(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFo
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 @@ efh_format_timeout(struct _format_msg *m)
| 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;
}
@@ -1747,7 +1775,7 @@ efh_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part, c
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);
}
diff --git a/mail/em-format-quote.c b/mail/em-format-quote.c
index dc5695cfc2..16d6bbc4e6 100644
--- a/mail/em-format-quote.c
+++ b/mail/em-format-quote.c
@@ -397,7 +397,7 @@ emfq_format_source(EMFormat *emf, CamelStream *stream, CamelMimePart *part)
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,
diff --git a/mail/em-format.c b/mail/em-format.c
index 35fed724ca..b7598f97c8 100644
--- a/mail/em-format.c
+++ b/mail/em-format.c
@@ -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 guint emf_signals[EMF_LAST_SIGNAL];
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 @@ emf_finalise(GObject *o)
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 @@ em_format_part(EMFormat *emf, CamelStream *stream, CamelMimePart *part)
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 @@ emf_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMimeM
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 @@ int em_format_is_attachment(EMFormat *emf, CamelMimePart *part)
* 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 @@ int em_format_is_attachment(EMFormat *emf, CamelMimePart *part)
*
* 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 @@ int em_format_is_inline(EMFormat *emf, CamelMimePart *part, const EMFormatHandle
/**
* 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 @@ emf_application_xpkcs7mime(EMFormat *emf, CamelStream *stream, CamelMimePart *pa
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 @@ emf_application_xpkcs7mime(EMFormat *emf, CamelStream *stream, CamelMimePart *pa
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 @@ emf_multipart_encrypted(EMFormat *emf, CamelStream *stream, CamelMimePart *part,
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 @@ emf_multipart_encrypted(EMFormat *emf, CamelStream *stream, CamelMimePart *part,
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 @@ emf_multipart_signed(EMFormat *emf, CamelStream *stream, CamelMimePart *part, co
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 @@ emf_multipart_signed(EMFormat *emf, CamelStream *stream, CamelMimePart *part, co
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);
}
diff --git a/mail/em-format.h b/mail/em-format.h
index 14db358e58..8cbdc69a1a 100644
--- a/mail/em-format.h
+++ b/mail/em-format.h
@@ -190,9 +190,10 @@ void em_format_add_header(EMFormat *emf, const char *name, guint32 flags);
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 */