diff options
author | Matthew Barnes <mbarnes@src.gnome.org> | 2009-03-01 21:16:31 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@src.gnome.org> | 2009-03-01 21:16:31 +0800 |
commit | 08b1d0ae8e36ef20da800bf6358ca0cd9fb4e026 (patch) | |
tree | 2731ee3191355d6bdc90b16d249f711cb1e78afd /mail/em-format-html.c | |
parent | 24abc4f17353ed818a09f324f5ed8822ad9b5a7e (diff) | |
download | gsoc2013-evolution-08b1d0ae8e36ef20da800bf6358ca0cd9fb4e026.tar.gz gsoc2013-evolution-08b1d0ae8e36ef20da800bf6358ca0cd9fb4e026.tar.zst gsoc2013-evolution-08b1d0ae8e36ef20da800bf6358ca0cd9fb4e026.zip |
Split the interactive parts of the message display out of EMFormatHTMLDisplay
to a new GtkHTML subclass named EMailDisplay, and have EMFormatHTML create an
instance of that. EMailDisplay will handle link clicking, mousing over URIs,
popup menus, and interactive search. This makes EMFormatHTMLDisplay and
EMailReader more lightweight.
Clean up more of the EMFormat stack.
svn path=/branches/kill-bonobo/; revision=37346
Diffstat (limited to 'mail/em-format-html.c')
-rw-r--r-- | mail/em-format-html.c | 749 |
1 files changed, 388 insertions, 361 deletions
diff --git a/mail/em-format-html.c b/mail/em-format-html.c index bafb82ae36..6308947a26 100644 --- a/mail/em-format-html.c +++ b/mail/em-format-html.c @@ -135,12 +135,7 @@ static void efh_gtkhtml_destroy(GtkHTML *html, EMFormatHTML *efh); static void efh_format_message(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info); -static void efh_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMimeMessage *msg, EMFormat *emfsource); -static void efh_format_error(EMFormat *emf, CamelStream *stream, const char *txt); -static void efh_format_source(EMFormat *, CamelStream *, CamelMimePart *); -static void efh_format_attachment(EMFormat *, CamelStream *, CamelMimePart *, const char *, const EMFormatHandler *); static void efh_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid); -static gboolean efh_busy(EMFormat *); static void efh_builtin_init(EMFormatHTMLClass *efhc); @@ -151,6 +146,230 @@ static CamelDataCache *emfh_http_cache; #define EMFH_HTTP_CACHE_PATH "http" +/* Sigh, this is so we have a cancellable, async rendering thread */ +struct _format_msg { + MailMsg base; + + EMFormatHTML *format; + EMFormat *format_source; + EMHTMLStream *estream; + CamelFolder *folder; + char *uid; + CamelMimeMessage *message; +}; + +static gchar * +efh_format_desc (struct _format_msg *m) +{ + return g_strdup(_("Formatting message")); +} + +static void +efh_format_exec (struct _format_msg *m) +{ + struct _EMFormatHTMLJob *job; + struct _EMFormatPURITree *puri_level; + int cancelled = FALSE; + CamelURL *base; + + if (m->format->html == NULL) + return; + + camel_stream_printf ( + (CamelStream *)m->estream, + "<!doctype html public \"-//W3C//DTD HTML 4.0 TRANSITIONAL//EN\">\n<html>\n" + "<head>\n<meta name=\"generator\" content=\"Evolution Mail Component\">\n</head>\n" + "<body bgcolor =\"#%06x\" text=\"#%06x\" marginwidth=6 marginheight=6>\n", + e_color_to_value ( + &m->format->priv->colors[ + EM_FORMAT_HTML_COLOR_BODY]), + e_color_to_value ( + &m->format->priv->colors[ + EM_FORMAT_HTML_COLOR_HEADER])); + + /* <insert top-header stuff here> */ + + if (((EMFormat *)m->format)->mode == EM_FORMAT_SOURCE) { + em_format_format_source((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message); + } else { + const EMFormatHandler *handle; + + handle = em_format_find_handler((EMFormat *)m->format, "x-evolution/message/prefix"); + if (handle) + handle->handler((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message, handle); + handle = em_format_find_handler((EMFormat *)m->format, "x-evolution/message/rfc822"); + if (handle) + handle->handler((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message, handle); + handle = em_format_find_handler((EMFormat *)m->format, "x-evolution/message/post-header-closure"); + if (handle && !((EMFormat *)m->format)->print) + handle->handler((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message, handle); + + } + + camel_stream_flush((CamelStream *)m->estream); + + puri_level = ((EMFormat *)m->format)->pending_uri_level; + base = ((EMFormat *)m->format)->base; + + do { + /* now dispatch any added tasks ... */ + g_mutex_lock(m->format->priv->lock); + while ((job = (struct _EMFormatHTMLJob *)e_dlist_remhead(&m->format->priv->pending_jobs))) { + g_mutex_unlock(m->format->priv->lock); + + /* This is an implicit check to see if the gtkhtml has been destroyed */ + if (!cancelled) + cancelled = m->format->html == NULL; + + /* Now do an explicit check for user cancellation */ + if (!cancelled) + cancelled = camel_operation_cancel_check(NULL); + + /* call jobs even if cancelled, so they can clean up resources */ + ((EMFormat *)m->format)->pending_uri_level = job->puri_level; + if (job->base) + ((EMFormat *)m->format)->base = job->base; + job->callback(job, cancelled); + ((EMFormat *)m->format)->base = base; + + /* clean up the job */ + camel_object_unref(job->stream); + if (job->base) + camel_url_free(job->base); + g_free(job); + + g_mutex_lock(m->format->priv->lock); + } + g_mutex_unlock(m->format->priv->lock); + + if (m->estream) { + /* Closing this base stream can queue more jobs, so we need + to check the list again after we've finished */ + d(printf("out of jobs, closing root stream\n")); + camel_stream_write_string((CamelStream *)m->estream, "</body>\n</html>\n"); + camel_stream_close((CamelStream *)m->estream); + camel_object_unref(m->estream); + m->estream = NULL; + } + + /* e_dlist_empty is atomic and doesn't need locking */ + } while (!e_dlist_empty(&m->format->priv->pending_jobs)); + + d(printf("out of jobs, done\n")); + + ((EMFormat *)m->format)->pending_uri_level = puri_level; +} + +static void +efh_format_done (struct _format_msg *m) +{ + d(printf("formatting finished\n")); + + m->format->priv->format_id = -1; + m->format->priv->load_images_now = FALSE; + m->format->state = EM_FORMAT_HTML_STATE_NONE; + g_signal_emit_by_name(m->format, "complete"); +} + +static void +efh_format_free (struct _format_msg *m) +{ + d(printf("formatter freed\n")); + g_object_unref(m->format); + if (m->estream) { + camel_stream_close((CamelStream *)m->estream); + camel_object_unref(m->estream); + } + if (m->folder) + camel_object_unref(m->folder); + g_free(m->uid); + if (m->message) + camel_object_unref(m->message); + if (m->format_source) + g_object_unref(m->format_source); +} + +static MailMsgInfo efh_format_info = { + sizeof (struct _format_msg), + (MailMsgDescFunc) efh_format_desc, + (MailMsgExecFunc) efh_format_exec, + (MailMsgDoneFunc) efh_format_done, + (MailMsgFreeFunc) efh_format_free +}; + +static gboolean +efh_format_timeout(struct _format_msg *m) +{ + GtkHTMLStream *hstream; + EMFormatHTML *efh = m->format; + struct _EMFormatHTMLPrivate *p = efh->priv; + + if (m->format->html == NULL) { + mail_msg_unref(m); + return FALSE; + } + + d(printf("timeout called ...\n")); + if (p->format_id != -1) { + d(printf(" still waiting for cancellation to take effect, waiting ...\n")); + return TRUE; + } + + g_return_val_if_fail (e_dlist_empty(&p->pending_jobs), FALSE); + + d(printf(" ready to go, firing off format thread\n")); + + /* call super-class to kick it off */ + EM_FORMAT_CLASS (parent_class)->format_clone ( + EM_FORMAT (efh), m->folder, m->uid, + m->message, m->format_source); + em_format_html_clear_pobject(m->format); + + /* FIXME: method off EMFormat? */ + if (((EMFormat *)efh)->valid) { + camel_cipher_validity_free(((EMFormat *)efh)->valid); + ((EMFormat *)efh)->valid = NULL; + ((EMFormat *)efh)->valid_parent = NULL; + } + + if (m->message == NULL) { + hstream = gtk_html_begin(efh->html); + gtk_html_stream_close(hstream, GTK_HTML_STREAM_OK); + mail_msg_unref(m); + p->last_part = NULL; + } else { + efh->state = EM_FORMAT_HTML_STATE_RENDERING; + + if (p->last_part != m->message) { + hstream = gtk_html_begin (efh->html); + gtk_html_stream_printf (hstream, "<h5>%s</h5>", _("Formatting Message...")); + gtk_html_stream_close (hstream, GTK_HTML_STREAM_OK); + } + + hstream = NULL; + m->estream = (EMHTMLStream *)em_html_stream_new(efh->html, hstream); + + if (p->last_part == m->message) { + em_html_stream_set_flags (m->estream, + GTK_HTML_BEGIN_KEEP_SCROLL | GTK_HTML_BEGIN_KEEP_IMAGES + | GTK_HTML_BEGIN_BLOCK_UPDATES | GTK_HTML_BEGIN_BLOCK_IMAGES); + } else { + /* clear cache of inline-scanned text parts */ + g_hash_table_remove_all(p->text_inline_parts); + + p->last_part = m->message; + } + + efh->priv->format_id = m->base.seq; + mail_msg_unordered_push (m); + } + + efh->priv->format_timeout_id = 0; + efh->priv->format_timeout_msg = NULL; + + return FALSE; +} + static void efh_free_cache(struct _EMFormatHTMLCache *efhc) { @@ -371,6 +590,143 @@ efh_finalize (GObject *object) } static void +efh_format_clone (EMFormat *emf, + CamelFolder *folder, + const gchar *uid, + CamelMimeMessage *msg, + EMFormat *emfsource) +{ + EMFormatHTML *efh = EM_FORMAT_HTML (emf); + struct _format_msg *m; + + /* How to sub-class ? Might need to adjust api ... */ + + if (efh->html == NULL) + return; + + d(printf("efh_format called\n")); + if (efh->priv->format_timeout_id != 0) { + d(printf(" timeout for last still active, removing ...\n")); + g_source_remove(efh->priv->format_timeout_id); + efh->priv->format_timeout_id = 0; + mail_msg_unref(efh->priv->format_timeout_msg); + efh->priv->format_timeout_msg = NULL; + } + + if (emfsource != NULL) + g_object_ref (emfsource); + + if (folder != NULL) + camel_object_ref (folder); + + if (msg != NULL) + camel_object_ref (msg); + + m = mail_msg_new (&efh_format_info); + m->format = g_object_ref (emf); + m->format_source = emfsource; + m->folder = folder; + m->uid = g_strdup (uid); + m->message = msg; + + if (efh->priv->format_id == -1) { + d(printf(" idle, forcing format\n")); + efh_format_timeout (m); + } else { + d(printf(" still busy, cancelling and queuing wait\n")); + /* cancel and poll for completion */ + mail_msg_cancel (efh->priv->format_id); + efh->priv->format_timeout_msg = m; + efh->priv->format_timeout_id = g_timeout_add ( + 100, (GSourceFunc) efh_format_timeout, m); + } +} + +static void +efh_format_error (EMFormat *emf, + CamelStream *stream, + const gchar *txt) +{ + gchar *html; + + html = camel_text_to_html ( + txt, CAMEL_MIME_FILTER_TOHTML_CONVERT_NL | + CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); + camel_stream_printf ( + stream, "<em><font color=\"red\">%s</font></em><br>", html); + g_free (html); +} + +static void +efh_format_source (EMFormat *emf, + CamelStream *stream, + CamelMimePart *part) +{ + CamelStreamFilter *filtered_stream; + CamelMimeFilter *filter; + CamelDataWrapper *dw = (CamelDataWrapper *) part; + + filtered_stream = camel_stream_filter_new_with_stream (stream); + + filter = camel_mime_filter_tohtml_new ( + CAMEL_MIME_FILTER_TOHTML_CONVERT_NL | + CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES | + CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT, 0); + camel_stream_filter_add (filtered_stream, filter); + camel_object_unref (filter); + + camel_stream_write_string (stream, "<table><tr><td><tt>"); + em_format_format_text (emf, (CamelStream *) filtered_stream, dw); + camel_object_unref (filtered_stream); + + camel_stream_write_string(stream, "</tt></td></tr></table>"); +} + +static void +efh_format_attachment (EMFormat *emf, + CamelStream *stream, + CamelMimePart *part, + const gchar *mime_type, + const EMFormatHandler *handle) +{ + char *text, *html; + + /* we display all inlined attachments only */ + + /* this could probably be cleaned up ... */ + camel_stream_write_string ( + stream, + "<table border=1 cellspacing=0 cellpadding=0><tr><td>" + "<table width=10 cellspacing=0 cellpadding=0>" + "<tr><td></td></tr></table></td>" + "<td><table width=3 cellspacing=0 cellpadding=0>" + "<tr><td></td></tr></table></td><td><font size=-1>\n"); + + /* output some info about it */ + text = em_format_describe_part(part, mime_type); + html = camel_text_to_html ( + text, ((EMFormatHTML *)emf)->text_html_flags & + CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); + camel_stream_write_string (stream, html); + g_free (html); + g_free (text); + + camel_stream_write_string (stream, "</font></td></tr><tr></table>"); + + if (handle && em_format_is_inline (emf, emf->part_id->str, part, handle)) + handle->handler (emf, stream, part, handle); +} + +static gboolean +efh_busy (EMFormat *emf) +{ + EMFormatHTMLPrivate *priv; + + priv = EM_FORMAT_HTML_GET_PRIVATE (emf); + + return (priv->format_id != -1); +} +static void efh_base_init (EMFormatHTMLClass *class) { efh_builtin_init (class); @@ -399,6 +755,8 @@ efh_class_init (EMFormatHTMLClass *class) format_class->format_secure = efh_format_secure; format_class->busy = efh_busy; + class->html_widget_type = GTK_TYPE_HTML; + g_object_class_install_property ( object_class, PROP_BODY_COLOR, @@ -516,8 +874,10 @@ efh_class_init (EMFormatHTMLClass *class) } static void -efh_init (EMFormatHTML *efh) +efh_init (EMFormatHTML *efh, + EMFormatHTMLClass *class) { + GtkHTML *html; GdkColor *color; efh->priv = EM_FORMAT_HTML_GET_PRIVATE (efh); @@ -531,32 +891,35 @@ efh_init (EMFormatHTML *efh) (GDestroyNotify) NULL, (GDestroyNotify) efh_free_cache); - efh->html = (GtkHTML *) gtk_html_new (); - g_object_ref_sink(efh->html); + html = g_object_new (class->html_widget_type, NULL); + efh->html = g_object_ref_sink (html); - gtk_html_set_blocking (efh->html, FALSE); - gtk_html_set_caret_first_focus_anchor (efh->html, EFM_MESSAGE_START_ANAME); + gtk_html_set_blocking (html, FALSE); + gtk_html_set_caret_first_focus_anchor (html, EFM_MESSAGE_START_ANAME); + gtk_html_set_default_content_type (html, "text/html; charset=utf-8"); + gtk_html_set_editable (html, FALSE); - gtk_html_set_default_content_type(efh->html, "text/html; charset=utf-8"); - gtk_html_set_editable(efh->html, FALSE); - - g_signal_connect(efh->html, "url_requested", G_CALLBACK(efh_url_requested), efh); - g_signal_connect(efh->html, "object_requested", G_CALLBACK(efh_object_requested), efh); + g_signal_connect ( + html, "url-requested", + G_CALLBACK (efh_url_requested), efh); + g_signal_connect ( + html, "object-requested", + G_CALLBACK (efh_object_requested), efh); color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_BODY]; - gdk_color_parse ("0xeeeeee", color); + gdk_color_parse ("#eeeeee", color); color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_CONTENT]; - gdk_color_parse ("0xffffff", color); + gdk_color_parse ("#ffffff", color); color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_FRAME]; - gdk_color_parse ("0x3f3f3f", color); + gdk_color_parse ("#3f3f3f", color); color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_HEADER]; - gdk_color_parse ("0xeeeeee", color); + gdk_color_parse ("#eeeeee", color); color = &efh->priv->colors[EM_FORMAT_HTML_COLOR_TEXT]; - gdk_color_parse ("0x000000", color); + gdk_color_parse ("#000000", color); efh->text_html_flags = CAMEL_MIME_FILTER_TOHTML_CONVERT_NL | @@ -590,18 +953,13 @@ em_format_html_get_type (void) }; type = g_type_register_static ( - em_format_get_type(), "EMFormatHTML", &type_info, 0); + em_format_get_type(), "EMFormatHTML", + &type_info, G_TYPE_FLAG_ABSTRACT); } return type; } -EMFormatHTML * -em_format_html_new(void) -{ - return g_object_new (EM_TYPE_FORMAT_HTML, NULL); -} - void em_format_html_load_images (EMFormatHTML *efh) { @@ -688,7 +1046,7 @@ em_format_html_get_image_loading_policy (EMFormatHTML *efh) { g_return_val_if_fail (EM_IS_FORMAT_HTML (efh), 0); - return efh->priv->image_loading_policy;; + return efh->priv->image_loading_policy; } void @@ -1711,284 +2069,6 @@ efh_builtin_init(EMFormatHTMLClass *efhc) /* ********************************************************************** */ -/* Sigh, this is so we have a cancellable, async rendering thread */ -struct _format_msg { - MailMsg base; - - EMFormatHTML *format; - EMFormat *format_source; - EMHTMLStream *estream; - CamelFolder *folder; - char *uid; - CamelMimeMessage *message; -}; - -static gchar * -efh_format_desc (struct _format_msg *m) -{ - return g_strdup(_("Formatting message")); -} - -static void -efh_format_exec (struct _format_msg *m) -{ - struct _EMFormatHTMLJob *job; - struct _EMFormatPURITree *puri_level; - int cancelled = FALSE; - CamelURL *base; - - if (m->format->html == NULL) - return; - - camel_stream_printf ( - (CamelStream *)m->estream, - "<!doctype html public \"-//W3C//DTD HTML 4.0 TRANSITIONAL//EN\">\n<html>\n" - "<head>\n<meta name=\"generator\" content=\"Evolution Mail Component\">\n</head>\n" - "<body bgcolor =\"#%06x\" text=\"#%06x\" marginwidth=6 marginheight=6>\n", - e_color_to_value ( - &m->format->priv->colors[ - EM_FORMAT_HTML_COLOR_BODY]), - e_color_to_value ( - &m->format->priv->colors[ - EM_FORMAT_HTML_COLOR_HEADER])); - - /* <insert top-header stuff here> */ - - if (((EMFormat *)m->format)->mode == EM_FORMAT_SOURCE) { - em_format_format_source((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message); - } else { - const EMFormatHandler *handle; - - handle = em_format_find_handler((EMFormat *)m->format, "x-evolution/message/prefix"); - if (handle) - handle->handler((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message, handle); - handle = em_format_find_handler((EMFormat *)m->format, "x-evolution/message/rfc822"); - if (handle) - handle->handler((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message, handle); - handle = em_format_find_handler((EMFormat *)m->format, "x-evolution/message/post-header-closure"); - if (handle && !((EMFormat *)m->format)->print) - handle->handler((EMFormat *)m->format, (CamelStream *)m->estream, (CamelMimePart *)m->message, handle); - - } - - camel_stream_flush((CamelStream *)m->estream); - - puri_level = ((EMFormat *)m->format)->pending_uri_level; - base = ((EMFormat *)m->format)->base; - - do { - /* now dispatch any added tasks ... */ - g_mutex_lock(m->format->priv->lock); - while ((job = (struct _EMFormatHTMLJob *)e_dlist_remhead(&m->format->priv->pending_jobs))) { - g_mutex_unlock(m->format->priv->lock); - - /* This is an implicit check to see if the gtkhtml has been destroyed */ - if (!cancelled) - cancelled = m->format->html == NULL; - - /* Now do an explicit check for user cancellation */ - if (!cancelled) - cancelled = camel_operation_cancel_check(NULL); - - /* call jobs even if cancelled, so they can clean up resources */ - ((EMFormat *)m->format)->pending_uri_level = job->puri_level; - if (job->base) - ((EMFormat *)m->format)->base = job->base; - job->callback(job, cancelled); - ((EMFormat *)m->format)->base = base; - - /* clean up the job */ - camel_object_unref(job->stream); - if (job->base) - camel_url_free(job->base); - g_free(job); - - g_mutex_lock(m->format->priv->lock); - } - g_mutex_unlock(m->format->priv->lock); - - if (m->estream) { - /* Closing this base stream can queue more jobs, so we need - to check the list again after we've finished */ - d(printf("out of jobs, closing root stream\n")); - camel_stream_write_string((CamelStream *)m->estream, "</body>\n</html>\n"); - camel_stream_close((CamelStream *)m->estream); - camel_object_unref(m->estream); - m->estream = NULL; - } - - /* e_dlist_empty is atomic and doesn't need locking */ - } while (!e_dlist_empty(&m->format->priv->pending_jobs)); - - d(printf("out of jobs, done\n")); - - ((EMFormat *)m->format)->pending_uri_level = puri_level; -} - -static void -efh_format_done (struct _format_msg *m) -{ - d(printf("formatting finished\n")); - - m->format->priv->format_id = -1; - m->format->priv->load_images_now = FALSE; - m->format->state = EM_FORMAT_HTML_STATE_NONE; - g_signal_emit_by_name(m->format, "complete"); -} - -static void -efh_format_free (struct _format_msg *m) -{ - d(printf("formatter freed\n")); - g_object_unref(m->format); - if (m->estream) { - camel_stream_close((CamelStream *)m->estream); - camel_object_unref(m->estream); - } - if (m->folder) - camel_object_unref(m->folder); - g_free(m->uid); - if (m->message) - camel_object_unref(m->message); - if (m->format_source) - g_object_unref(m->format_source); -} - -static MailMsgInfo efh_format_info = { - sizeof (struct _format_msg), - (MailMsgDescFunc) efh_format_desc, - (MailMsgExecFunc) efh_format_exec, - (MailMsgDoneFunc) efh_format_done, - (MailMsgFreeFunc) efh_format_free -}; - -static gboolean -efh_format_timeout(struct _format_msg *m) -{ - GtkHTMLStream *hstream; - EMFormatHTML *efh = m->format; - struct _EMFormatHTMLPrivate *p = efh->priv; - - if (m->format->html == NULL) { - mail_msg_unref(m); - return FALSE; - } - - d(printf("timeout called ...\n")); - if (p->format_id != -1) { - d(printf(" still waiting for cancellation to take effect, waiting ...\n")); - return TRUE; - } - - g_return_val_if_fail (e_dlist_empty(&p->pending_jobs), FALSE); - - d(printf(" ready to go, firing off format thread\n")); - - /* call super-class to kick it off */ - EM_FORMAT_CLASS (parent_class)->format_clone ( - EM_FORMAT (efh), m->folder, m->uid, - m->message, m->format_source); - em_format_html_clear_pobject(m->format); - - /* FIXME: method off EMFormat? */ - if (((EMFormat *)efh)->valid) { - camel_cipher_validity_free(((EMFormat *)efh)->valid); - ((EMFormat *)efh)->valid = NULL; - ((EMFormat *)efh)->valid_parent = NULL; - } - - if (m->message == NULL) { - hstream = gtk_html_begin(efh->html); - gtk_html_stream_close(hstream, GTK_HTML_STREAM_OK); - mail_msg_unref(m); - p->last_part = NULL; - } else { - efh->state = EM_FORMAT_HTML_STATE_RENDERING; - - if (p->last_part != m->message) { - hstream = gtk_html_begin (efh->html); - gtk_html_stream_printf (hstream, "<h5>%s</h5>", _("Formatting Message...")); - gtk_html_stream_close (hstream, GTK_HTML_STREAM_OK); - } - - hstream = NULL; - m->estream = (EMHTMLStream *)em_html_stream_new(efh->html, hstream); - - if (p->last_part == m->message) { - em_html_stream_set_flags (m->estream, - GTK_HTML_BEGIN_KEEP_SCROLL | GTK_HTML_BEGIN_KEEP_IMAGES - | GTK_HTML_BEGIN_BLOCK_UPDATES | GTK_HTML_BEGIN_BLOCK_IMAGES); - } else { - /* clear cache of inline-scanned text parts */ - g_hash_table_remove_all(p->text_inline_parts); - - p->last_part = m->message; - } - - efh->priv->format_id = m->base.seq; - mail_msg_unordered_push (m); - } - - efh->priv->format_timeout_id = 0; - efh->priv->format_timeout_msg = NULL; - - return FALSE; -} - -static void efh_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMimeMessage *msg, EMFormat *emfsource) -{ - EMFormatHTML *efh = (EMFormatHTML *)emf; - struct _format_msg *m; - - /* How to sub-class ? Might need to adjust api ... */ - - if (efh->html == NULL) - return; - - d(printf("efh_format called\n")); - if (efh->priv->format_timeout_id != 0) { - d(printf(" timeout for last still active, removing ...\n")); - g_source_remove(efh->priv->format_timeout_id); - efh->priv->format_timeout_id = 0; - mail_msg_unref(efh->priv->format_timeout_msg); - efh->priv->format_timeout_msg = NULL; - } - - m = mail_msg_new(&efh_format_info); - m->format = (EMFormatHTML *)emf; - g_object_ref(emf); - m->format_source = emfsource; - if (emfsource) - g_object_ref(emfsource); - m->folder = folder; - if (folder) - camel_object_ref(folder); - m->uid = g_strdup(uid); - m->message = msg; - if (msg) - camel_object_ref(msg); - - if (efh->priv->format_id == -1) { - d(printf(" idle, forcing format\n")); - efh_format_timeout(m); - } else { - d(printf(" still busy, cancelling and queuing wait\n")); - /* cancel and poll for completion */ - mail_msg_cancel(efh->priv->format_id); - efh->priv->format_timeout_msg = m; - efh->priv->format_timeout_id = g_timeout_add(100, (GSourceFunc)efh_format_timeout, m); - } -} - -static void efh_format_error(EMFormat *emf, CamelStream *stream, const char *txt) -{ - char *html; - - html = camel_text_to_html (txt, CAMEL_MIME_FILTER_TOHTML_CONVERT_NL|CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); - camel_stream_printf(stream, "<em><font color=\"red\">%s</font></em><br>", html); - g_free(html); -} - static void efh_format_text_header (EMFormatHTML *emfh, CamelStream *stream, const char *label, const char *value, guint32 flags) { @@ -2563,7 +2643,8 @@ efh_format_headers(EMFormatHTML *efh, CamelStream *stream, CamelMedium *part) } } -static void efh_format_message(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) +static void +efh_format_message(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info) { const EMFormatHandler *handle; @@ -2595,57 +2676,3 @@ static void efh_format_message(EMFormat *emf, CamelStream *stream, CamelMimePart emf->valid = save; emf->valid_parent = save_parent; } - -static void efh_format_source(EMFormat *emf, CamelStream *stream, CamelMimePart *part) -{ - CamelStreamFilter *filtered_stream; - CamelMimeFilter *html_filter; - CamelDataWrapper *dw = (CamelDataWrapper *)part; - - filtered_stream = camel_stream_filter_new_with_stream ((CamelStream *) stream); - html_filter = camel_mime_filter_tohtml_new (CAMEL_MIME_FILTER_TOHTML_CONVERT_NL - | CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES - | CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT, 0); - camel_stream_filter_add(filtered_stream, html_filter); - camel_object_unref(html_filter); - - camel_stream_write_string((CamelStream *)stream, "<table><tr><td><tt>"); - em_format_format_text(emf, (CamelStream *)filtered_stream, dw); - camel_object_unref(filtered_stream); - - camel_stream_write_string(stream, "</tt></td></tr></table>"); -} - -static void -efh_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const char *mime_type, const EMFormatHandler *handle) -{ - char *text, *html; - - /* we display all inlined attachments only */ - - /* this could probably be cleaned up ... */ - camel_stream_write_string(stream, - "<table border=1 cellspacing=0 cellpadding=0><tr><td>" - "<table width=10 cellspacing=0 cellpadding=0>" - "<tr><td></td></tr></table></td>" - "<td><table width=3 cellspacing=0 cellpadding=0>" - "<tr><td></td></tr></table></td><td><font size=-1>\n"); - - /* output some info about it */ - text = em_format_describe_part(part, mime_type); - html = camel_text_to_html(text, ((EMFormatHTML *)emf)->text_html_flags & CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0); - camel_stream_write_string(stream, html); - g_free(html); - g_free(text); - - camel_stream_write_string(stream, "</font></td></tr><tr></table>"); - - if (handle && em_format_is_inline(emf, emf->part_id->str, part, handle)) - handle->handler(emf, stream, part, handle); -} - -static gboolean -efh_busy(EMFormat *emf) -{ - return (((EMFormatHTML *)emf)->priv->format_id != -1); -} |