aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@src.gnome.org>2009-03-01 21:16:31 +0800
committerMatthew Barnes <mbarnes@src.gnome.org>2009-03-01 21:16:31 +0800
commit08b1d0ae8e36ef20da800bf6358ca0cd9fb4e026 (patch)
tree2731ee3191355d6bdc90b16d249f711cb1e78afd /mail
parent24abc4f17353ed818a09f324f5ed8822ad9b5a7e (diff)
downloadgsoc2013-evolution-08b1d0ae8e36ef20da800bf6358ca0cd9fb4e026.tar
gsoc2013-evolution-08b1d0ae8e36ef20da800bf6358ca0cd9fb4e026.tar.gz
gsoc2013-evolution-08b1d0ae8e36ef20da800bf6358ca0cd9fb4e026.tar.bz2
gsoc2013-evolution-08b1d0ae8e36ef20da800bf6358ca0cd9fb4e026.tar.lz
gsoc2013-evolution-08b1d0ae8e36ef20da800bf6358ca0cd9fb4e026.tar.xz
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')
-rw-r--r--mail/Makefile.am2
-rw-r--r--mail/e-mail-browser.c29
-rw-r--r--mail/e-mail-display.c627
-rw-r--r--mail/e-mail-display.h83
-rw-r--r--mail/e-mail-reader.c45
-rw-r--r--mail/e-mail-shell-view-private.c23
-rw-r--r--mail/em-folder-view.c59
-rw-r--r--mail/em-format-html-display.c1313
-rw-r--r--mail/em-format-html-display.h30
-rw-r--r--mail/em-format-html.c749
-rw-r--r--mail/em-format-html.h5
-rw-r--r--mail/em-html-stream.c147
-rw-r--r--mail/em-html-stream.h55
13 files changed, 1755 insertions, 1412 deletions
diff --git a/mail/Makefile.am b/mail/Makefile.am
index b7b2a1d48a..cf7f71acea 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -37,6 +37,8 @@ module_LTLIBRARIES = \
libevolution_module_mail_la_SOURCES = \
e-mail-browser.c \
e-mail-browser.h \
+ e-mail-display.c \
+ e-mail-display.h \
e-mail-label-dialog.c \
e-mail-label-dialog.h \
e-mail-label-list-store.c \
diff --git a/mail/e-mail-browser.c b/mail/e-mail-browser.c
index 0e4239d4a7..8d685537bf 100644
--- a/mail/e-mail-browser.c
+++ b/mail/e-mail-browser.c
@@ -218,6 +218,23 @@ mail_browser_message_selected_cb (EMailBrowser *browser,
}
static void
+mail_browser_status_message_cb (EMailBrowser *browser,
+ const gchar *status_message)
+{
+ GtkStatusbar *statusbar;
+ guint context_id;
+
+ statusbar = GTK_STATUSBAR (browser->priv->statusbar);
+ context_id = gtk_statusbar_get_context_id (statusbar, G_STRFUNC);
+
+ /* Always pop first. This prevents messages from piling up. */
+ gtk_statusbar_pop (statusbar, context_id);
+
+ if (status_message != NULL && *status_message != '\0')
+ gtk_statusbar_push (statusbar, context_id, status_message);
+}
+
+static void
mail_browser_set_shell_module (EMailBrowser *browser,
EShellModule *shell_module)
{
@@ -320,6 +337,7 @@ mail_browser_dispose (GObject *object)
static void
mail_browser_constructed (GObject *object)
{
+ EMFormatHTMLDisplay *html_display;
EMailBrowserPrivate *priv;
EMailReader *reader;
EShellModule *shell_module;
@@ -329,6 +347,7 @@ mail_browser_constructed (GObject *object)
GtkUIManager *ui_manager;
GtkWidget *container;
GtkWidget *widget;
+ GtkHTML *html;
const gchar *domain;
guint merge_id;
@@ -338,10 +357,14 @@ mail_browser_constructed (GObject *object)
ui_manager = priv->ui_manager;
domain = GETTEXT_PACKAGE;
+ html_display = e_mail_reader_get_html_display (reader);
shell_module = e_mail_reader_get_shell_module (reader);
+
shell = e_shell_module_get_shell (shell_module);
e_shell_watch_window (shell, GTK_WINDOW (object));
+ html = EM_FORMAT_HTML (html_display)->html;
+
/* The message list is a widget, but it is not shown in the browser.
* Unfortunately, the widget is inseparable from its model, and the
* model is all we need. */
@@ -352,6 +375,10 @@ mail_browser_constructed (GObject *object)
priv->message_list, "message-selected",
G_CALLBACK (mail_browser_message_selected_cb), object);
+ g_signal_connect_swapped (
+ html, "status-message",
+ G_CALLBACK (mail_browser_status_message_cb), object);
+
e_mail_reader_init (reader);
action_group = priv->action_group;
@@ -409,7 +436,7 @@ mail_browser_constructed (GObject *object)
container = widget;
- widget = GTK_WIDGET (((EMFormatHTML *) priv->html_display)->html);
+ widget = GTK_WIDGET (EM_FORMAT_HTML (html_display)->html);
gtk_container_add (GTK_CONTAINER (container), widget);
gtk_widget_show (widget);
}
diff --git a/mail/e-mail-display.c b/mail/e-mail-display.c
new file mode 100644
index 0000000000..8ad72ebf86
--- /dev/null
+++ b/mail/e-mail-display.c
@@ -0,0 +1,627 @@
+/*
+ * e-mail-display.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-mail-display.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+
+#include "e-util/e-util.h"
+
+#define E_MAIL_DISPLAY_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_DISPLAY, EMailDisplayPrivate))
+
+struct _EMailDisplayPrivate {
+ EMFormatHTML *formatter;
+};
+
+enum {
+ PROP_0,
+ PROP_ANIMATE,
+ PROP_CARET_MODE,
+ PROP_FORMATTER
+};
+
+enum {
+ POPUP_EVENT,
+ STATUS_MESSAGE,
+ LAST_SIGNAL
+};
+
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
+
+static gboolean
+mail_display_emit_popup_event (EMailDisplay *display,
+ GdkEventButton *event,
+ const gchar *uri,
+ EMFormatPURI *puri)
+{
+ CamelMimePart *mime_part;
+ gboolean stop_handlers = FALSE;
+
+ mime_part = (puri != NULL) ? puri->part : NULL;
+
+ g_signal_emit (
+ display, signals[POPUP_EVENT], 0,
+ event, uri, mime_part, &stop_handlers);
+
+ return stop_handlers;
+}
+
+static void
+mail_display_emit_status_message (EMailDisplay *display,
+ const gchar *status_message)
+{
+ g_signal_emit (display, signals[STATUS_MESSAGE], 0, status_message);
+}
+
+static void
+mail_display_get_uri_puri (EMailDisplay *display,
+ GdkEventButton *event,
+ gchar **uri,
+ EMFormatPURI **puri)
+{
+ EMFormat *formatter;
+ GtkHTML *html;
+ gchar *text_uri;
+ gchar *image_uri;
+ gboolean is_cid;
+
+ html = GTK_HTML (display);
+ formatter = EM_FORMAT (display->priv->formatter);
+
+ if (event != NULL) {
+ text_uri = gtk_html_get_url_at (html, event->x, event->y);
+ image_uri = gtk_html_get_image_src_at (html, event->x, event->y);
+ } else {
+ text_uri = gtk_html_get_cursor_url (html);
+ image_uri = gtk_html_get_cursor_image_src (html);
+ }
+
+ is_cid = (image_uri != NULL) &&
+ (g_ascii_strncasecmp (image_uri, "cid:", 4) == 0);
+
+ if (image_uri != NULL) {
+ if (strstr (image_uri, "://") == NULL && !is_cid) {
+ gchar *temp;
+
+ temp = g_strconcat ("file://", image_uri, NULL);
+ g_free (image_uri);
+ temp = image_uri;
+ }
+ }
+
+ if (puri != NULL) {
+ if (text_uri != NULL)
+ *puri = em_format_find_puri (formatter, text_uri);
+
+ if (*puri == NULL && image_uri != NULL)
+ *puri = em_format_find_puri (formatter, image_uri);
+ }
+
+ if (uri != NULL) {
+ *uri = NULL;
+ if (is_cid) {
+ if (text_uri != NULL)
+ *uri = g_strdup_printf (
+ "%s\n%s", text_uri, image_uri);
+ else {
+ *uri = image_uri;
+ image_uri = NULL;
+ }
+ } else {
+ *uri = text_uri;
+ text_uri = NULL;
+ }
+ }
+
+ g_free (text_uri);
+ g_free (image_uri);
+}
+
+static void
+mail_display_update_formatter_colors (EMailDisplay *display)
+{
+ EMFormatHTMLColorType type;
+ EMFormatHTML *formatter;
+ GdkColor *color;
+ GtkStyle *style;
+ gint state;
+
+ state = GTK_WIDGET_STATE (display);
+ formatter = display->priv->formatter;
+
+ style = gtk_widget_get_style (GTK_WIDGET (display));
+ if (style == NULL)
+ return;
+
+ g_object_freeze_notify (G_OBJECT (formatter));
+
+ color = &style->bg[state];
+ type = EM_FORMAT_HTML_COLOR_BODY;
+ em_format_html_set_color (formatter, type, color);
+
+ color = &style->base[GTK_STATE_NORMAL];
+ type = EM_FORMAT_HTML_COLOR_CONTENT;
+ em_format_html_set_color (formatter, type, color);
+
+ color = &style->dark[state];
+ type = EM_FORMAT_HTML_COLOR_FRAME;
+ em_format_html_set_color (formatter, type, color);
+
+ color = &style->fg[state];
+ type = EM_FORMAT_HTML_COLOR_HEADER;
+ em_format_html_set_color (formatter, type, color);
+
+ color = &style->text[state];
+ type = EM_FORMAT_HTML_COLOR_TEXT;
+ em_format_html_set_color (formatter, type, color);
+
+ g_object_thaw_notify (G_OBJECT (formatter));
+}
+
+static void
+mail_display_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ANIMATE:
+ e_mail_display_set_animate (
+ E_MAIL_DISPLAY (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_CARET_MODE:
+ e_mail_display_set_caret_mode (
+ E_MAIL_DISPLAY (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_FORMATTER:
+ e_mail_display_set_formatter (
+ E_MAIL_DISPLAY (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_display_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ANIMATE:
+ g_value_set_boolean (
+ value, e_mail_display_get_animate (
+ E_MAIL_DISPLAY (object)));
+ return;
+
+ case PROP_CARET_MODE:
+ g_value_set_boolean (
+ value, e_mail_display_get_caret_mode (
+ E_MAIL_DISPLAY (object)));
+ return;
+
+ case PROP_FORMATTER:
+ g_value_set_object (
+ value, e_mail_display_get_formatter (
+ E_MAIL_DISPLAY (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_display_dispose (GObject *object)
+{
+ EMailDisplayPrivate *priv;
+
+ priv = E_MAIL_DISPLAY_GET_PRIVATE (object);
+
+ if (priv->formatter) {
+ g_object_unref (priv->formatter);
+ priv->formatter = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+mail_display_realize (GtkWidget *widget)
+{
+ /* Chain up to parent's realize() method. */
+ GTK_WIDGET_CLASS (parent_class)->realize (widget);
+
+ mail_display_update_formatter_colors (E_MAIL_DISPLAY (widget));
+}
+
+static void
+mail_display_style_set (GtkWidget *widget,
+ GtkStyle *previous_style)
+{
+ EMailDisplayPrivate *priv;
+
+ priv = E_MAIL_DISPLAY_GET_PRIVATE (widget);
+
+ /* Chain up to parent's style_set() method. */
+ GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);
+
+ mail_display_update_formatter_colors (E_MAIL_DISPLAY (widget));
+ em_format_redraw (EM_FORMAT (priv->formatter));
+}
+
+static gboolean
+mail_display_button_press_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ if (event->button == 3) {
+ EMailDisplay *display;
+ EMFormatPURI *puri = NULL;
+ gboolean stop_handlers = TRUE;
+ gchar *uri = NULL;
+
+ display = E_MAIL_DISPLAY (widget);
+ mail_display_get_uri_puri (display, event, &uri, &puri);
+
+ if (uri == NULL || !g_str_has_prefix (uri, "##"))
+ stop_handlers = mail_display_emit_popup_event (
+ display, event, uri, puri);
+
+ g_free (uri);
+
+ if (stop_handlers)
+ return TRUE;
+ }
+
+ /* Chain up to parent's button_press_event() method. */
+ return GTK_WIDGET_CLASS (parent_class)->
+ button_press_event (widget, event);
+}
+
+static gboolean
+mail_display_scroll_event (GtkWidget *widget,
+ GdkEventScroll *event)
+{
+ if (event->state & GDK_CONTROL_MASK) {
+ switch (event->direction) {
+ case GDK_SCROLL_UP:
+ gtk_html_zoom_in (GTK_HTML (widget));
+ return TRUE;
+ case GDK_SCROLL_DOWN:
+ gtk_html_zoom_out (GTK_HTML (widget));
+ return TRUE;
+ default:
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+mail_display_link_clicked (GtkHTML *html,
+ const gchar *uri)
+{
+ EMailDisplayPrivate *priv;
+
+ priv = E_MAIL_DISPLAY_GET_PRIVATE (html);
+ g_return_if_fail (priv->formatter != NULL);
+
+ if (g_str_has_prefix (uri, "##")) {
+ guint32 flags;
+
+ flags = priv->formatter->header_wrap_flags;
+
+ if (strcmp (uri, "##TO##") == 0) {
+ if (!(flags & EM_FORMAT_HTML_HEADER_TO))
+ flags |= EM_FORMAT_HTML_HEADER_TO;
+ else
+ flags &= ~EM_FORMAT_HTML_HEADER_TO;
+ } else if (strcmp (uri, "##CC##") == 0) {
+ if (!(flags & EM_FORMAT_HTML_HEADER_CC))
+ flags |= EM_FORMAT_HTML_HEADER_CC;
+ else
+ flags |= EM_FORMAT_HTML_HEADER_CC;
+ } else if (strcmp (uri, "##BCC##") == 0) {
+ if (!(flags & EM_FORMAT_HTML_HEADER_BCC))
+ flags |= EM_FORMAT_HTML_HEADER_BCC;
+ else
+ flags |= EM_FORMAT_HTML_HEADER_BCC;
+ }
+
+ priv->formatter->header_wrap_flags = flags;
+ em_format_redraw (EM_FORMAT (priv->formatter));
+
+ } else if (*uri == '#')
+ gtk_html_jump_to_anchor (html, uri + 1);
+
+ else if (g_ascii_strncasecmp (uri, "thismessage:", 12) == 0)
+ /* ignore */ ;
+
+ else if (g_ascii_strncasecmp (uri, "cid:", 4) == 0)
+ /* ignore */ ;
+
+ else {
+ gpointer parent;
+
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (html));
+ parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
+
+ e_show_uri (parent, uri);
+ }
+}
+
+static void
+mail_display_on_url (GtkHTML *html,
+ const gchar *uri)
+{
+ EMailDisplay *display;
+ CamelInternetAddress *address;
+ CamelURL *curl;
+ const gchar *format = NULL;
+ gchar *message = NULL;
+ gchar *who;
+
+ display = E_MAIL_DISPLAY (html);
+
+ if (uri == NULL || *uri == '\0')
+ goto exit;
+
+ if (g_str_has_prefix (uri, "mailto:"))
+ format = _("Click to mail %s");
+ else if (g_str_has_prefix (uri, "callto:"))
+ format = _("Click to call %s");
+ else if (g_str_has_prefix (uri, "h323:"))
+ format = _("Click to call %s");
+ else if (g_str_has_prefix (uri, "sip:"))
+ format = _("Click to call %s");
+ else if (g_str_has_prefix (uri, "##"))
+ message = g_strdup (_("Click to hide/unhide addresses"));
+ else
+ message = g_strdup_printf (_("Click to open %s"), uri);
+
+ if (format == NULL)
+ goto exit;
+
+ curl = camel_url_new (uri, NULL);
+ address = camel_internet_address_new ();
+ camel_address_decode (CAMEL_ADDRESS (address), curl->path);
+ who = camel_address_format (CAMEL_ADDRESS (address));
+ camel_object_unref (address);
+ camel_url_free (curl);
+
+ if (who == NULL)
+ who = g_strdup (strchr (uri, ':') + 1);
+
+ message = g_strdup_printf (format, who);
+
+ g_free (who);
+
+exit:
+ mail_display_emit_status_message (display, message);
+
+ g_free (message);
+}
+
+static void
+mail_display_iframe_created (GtkHTML *html,
+ GtkHTML *iframe)
+{
+ g_signal_connect_swapped (
+ iframe, "button-press-event",
+ G_CALLBACK (mail_display_button_press_event), html);
+}
+
+static void
+mail_display_class_init (EMailDisplayClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkHTMLClass *html_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EMailDisplayPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mail_display_set_property;
+ object_class->get_property = mail_display_get_property;
+ object_class->dispose = mail_display_dispose;
+
+ widget_class = GTK_WIDGET_CLASS (class);
+ widget_class->realize = mail_display_realize;
+ widget_class->style_set = mail_display_style_set;
+ widget_class->button_press_event = mail_display_button_press_event;
+ widget_class->scroll_event = mail_display_scroll_event;
+
+ html_class = GTK_HTML_CLASS (class);
+ html_class->link_clicked = mail_display_link_clicked;
+ html_class->on_url = mail_display_on_url;
+ html_class->iframe_created = mail_display_iframe_created;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_ANIMATE,
+ g_param_spec_boolean (
+ "animate",
+ "Animate Images",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CARET_MODE,
+ g_param_spec_boolean (
+ "caret-mode",
+ "Caret Mode",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_FORMATTER,
+ g_param_spec_object (
+ "formatter",
+ "HTML Formatter",
+ NULL,
+ EM_TYPE_FORMAT_HTML,
+ G_PARAM_READWRITE));
+
+ signals[POPUP_EVENT] = g_signal_new (
+ "popup-event",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EMailDisplayClass, popup_event),
+ g_signal_accumulator_true_handled, NULL,
+ e_marshal_BOOLEAN__BOXED_POINTER_POINTER,
+ G_TYPE_BOOLEAN, 3,
+ GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
+ G_TYPE_POINTER,
+ G_TYPE_POINTER);
+
+ signals[STATUS_MESSAGE] = g_signal_new (
+ "status-message",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EMailDisplayClass, status_message),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+}
+
+static void
+mail_display_init (EMailDisplay *display)
+{
+ display->priv = E_MAIL_DISPLAY_GET_PRIVATE (display);
+}
+
+GType
+e_mail_display_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EMailDisplayClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) mail_display_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EMailDisplay),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mail_display_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_HTML, "EMailDisplay", &type_info, 0);
+ }
+
+ return type;
+}
+
+gboolean
+e_mail_display_get_animate (EMailDisplay *display)
+{
+ /* XXX This is just here to maintain symmetry
+ * with e_mail_display_set_animate(). */
+
+ g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), FALSE);
+
+ return gtk_html_get_animate (GTK_HTML (display));
+}
+
+void
+e_mail_display_set_animate (EMailDisplay *display,
+ gboolean animate)
+{
+ /* XXX GtkHTML does not utilize GObject properties as well
+ * as it could. This just wraps gtk_html_set_animate()
+ * so we can get a "notify::animate" signal. */
+
+ g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+ gtk_html_set_animate (GTK_HTML (display), animate);
+
+ g_object_notify (G_OBJECT (display), "animate");
+}
+
+gboolean
+e_mail_display_get_caret_mode (EMailDisplay *display)
+{
+ /* XXX This is just here to maintain symmetry
+ * with e_mail_display_get_caret_mode(). */
+
+ g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), FALSE);
+
+ return gtk_html_get_caret_mode (GTK_HTML (display));
+}
+
+void
+e_mail_display_set_caret_mode (EMailDisplay *display,
+ gboolean caret_mode)
+{
+ /* XXX GtkHTML does not utilize GObject properties as well
+ * as it could. This just wraps gtk_html_set_caret_mode()
+ * so we can get a "notify::caret-mode" signal. */
+
+ g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+
+ gtk_html_set_caret_mode (GTK_HTML (display), caret_mode);
+
+ g_object_notify (G_OBJECT (display), "caret-mode");
+}
+
+EMFormatHTML *
+e_mail_display_get_formatter (EMailDisplay *display)
+{
+ g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL);
+
+ return display->priv->formatter;
+}
+
+void
+e_mail_display_set_formatter (EMailDisplay *display,
+ EMFormatHTML *formatter)
+{
+ g_return_if_fail (E_IS_MAIL_DISPLAY (display));
+ g_return_if_fail (EM_IS_FORMAT_HTML (formatter));
+
+ if (display->priv->formatter != NULL)
+ g_object_unref (display->priv->formatter);
+
+ display->priv->formatter = g_object_ref (formatter);
+
+ g_object_notify (G_OBJECT (display), "formatter");
+}
diff --git a/mail/e-mail-display.h b/mail/e-mail-display.h
new file mode 100644
index 0000000000..f1d5fc583f
--- /dev/null
+++ b/mail/e-mail-display.h
@@ -0,0 +1,83 @@
+/*
+ * e-mail-display.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_MAIL_DISPLAY_H
+#define E_MAIL_DISPLAY_H
+
+#include <gtkhtml/gtkhtml.h>
+#include <mail/em-format-html.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_DISPLAY \
+ (e_mail_display_get_type ())
+#define E_MAIL_DISPLAY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_DISPLAY, EMailDisplay))
+#define E_MAIL_DISPLAY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_DISPLAY, EMailDisplayClass))
+#define E_IS_MAIL_DISPLAY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_DISPLAY))
+#define E_IS_MAIL_DISPLAY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_DISPLAY))
+#define E_MAIL_DISPLAY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_DISPLAY, EMailDisplayClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailDisplay EMailDisplay;
+typedef struct _EMailDisplayClass EMailDisplayClass;
+typedef struct _EMailDisplayPrivate EMailDisplayPrivate;
+
+struct _EMailDisplay {
+ GtkHTML parent;
+ EMailDisplayPrivate *priv;
+};
+
+struct _EMailDisplayClass {
+ GtkHTMLClass parent_class;
+
+ /* Signals */
+ gboolean (*popup_event) (EMailDisplay *display,
+ GdkEventButton *event,
+ const gchar *uri,
+ EMFormatPURI *puri);
+ void (*status_message) (EMailDisplay *display,
+ const gchar *status_message);
+};
+
+GType e_mail_display_get_type (void);
+gboolean e_mail_display_get_animate (EMailDisplay *display);
+void e_mail_display_set_animate (EMailDisplay *display,
+ gboolean animate);
+gboolean e_mail_display_get_caret_mode (EMailDisplay *display);
+void e_mail_display_set_caret_mode (EMailDisplay *display,
+ gboolean caret_mode);
+EMFormatHTML * e_mail_display_get_formatter (EMailDisplay *display);
+void e_mail_display_set_formatter (EMailDisplay *display,
+ EMFormatHTML *formatter);
+
+G_END_DECLS
+
+#endif /* E_MAIL_DISPLAY_H */
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index ab7c86c160..b058fda07e 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -1620,40 +1620,6 @@ static GtkToggleActionEntry mail_reader_toggle_entries[] = {
FALSE }
};
-static void
-mail_reader_link_clicked_cb (EMailReader *reader,
- const gchar *uri,
- EMFormatHTMLDisplay *html_display)
-{
- GtkHTML *html;
- GtkWindow *window;
- MessageList *message_list;
- const gchar *folder_uri;
-
- html = EM_FORMAT_HTML (html_display)->html;
- message_list = e_mail_reader_get_message_list (reader);
- window = e_mail_reader_get_window (reader);
- folder_uri = message_list->folder_uri;
-
- if (g_str_has_prefix (uri, "##"))
- return;
-
- if (g_ascii_strncasecmp (uri, "mailto:", 7) == 0)
- em_utils_compose_new_message_with_mailto (uri, folder_uri);
-
- else if (*uri == '#')
- gtk_html_jump_to_anchor (html, uri + 1);
-
- else if (g_ascii_strncasecmp (uri, "thismessage:", 12) == 0)
- /* ignore */ ;
-
- else if (g_ascii_strncasecmp (uri, "cid:", 4) == 0)
- /* ignore */ ;
-
- else
- e_show_uri (window, uri);
-}
-
static gboolean
mail_reader_html_button_release_event_cb (EMailReader *reader,
GdkEventButton *button,
@@ -2057,6 +2023,7 @@ e_mail_reader_init (EMailReader *reader)
MessageList *message_list;
GConfBridge *bridge;
GtkAction *action;
+ GtkHTML *html;
const gchar *action_name;
const gchar *key;
@@ -2070,6 +2037,8 @@ e_mail_reader_init (EMailReader *reader)
shell = e_shell_module_get_shell (shell_module);
shell_settings = e_shell_get_shell_settings (shell);
+ html = EM_FORMAT_HTML (html_display)->html;
+
gtk_action_group_add_actions (
action_group, mail_reader_entries,
G_N_ELEMENTS (mail_reader_entries), reader);
@@ -2136,7 +2105,7 @@ e_mail_reader_init (EMailReader *reader)
e_binding_new (
G_OBJECT (shell_settings), "mail-show-animated-images",
- G_OBJECT (html_display), "animate");
+ G_OBJECT (html), "animate");
e_binding_new (
G_OBJECT (shell_settings), "mail-show-sender-photo",
@@ -2147,15 +2116,11 @@ e_mail_reader_init (EMailReader *reader)
e_mutual_binding_new (
G_OBJECT (action), "active",
- G_OBJECT (html_display), "caret-mode");
+ G_OBJECT (html), "caret-mode");
/* Connect signals. */
g_signal_connect_swapped (
- html_display, "link-clicked",
- G_CALLBACK (mail_reader_link_clicked_cb), reader);
-
- g_signal_connect_swapped (
EM_FORMAT_HTML (html_display)->html, "button-release-event",
G_CALLBACK (mail_reader_html_button_release_event_cb), reader);
diff --git a/mail/e-mail-shell-view-private.c b/mail/e-mail-shell-view-private.c
index 994f250565..460856ba5e 100644
--- a/mail/e-mail-shell-view-private.c
+++ b/mail/e-mail-shell-view-private.c
@@ -89,6 +89,19 @@ mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view)
}
static void
+mail_shell_view_reader_status_message_cb (EMailShellView *mail_shell_view,
+ const gchar *status_message)
+{
+ EShellView *shell_view;
+ EShellTaskbar *shell_taskbar;
+
+ shell_view = E_SHELL_VIEW (mail_shell_view);
+ shell_taskbar = e_shell_view_get_shell_taskbar (shell_view);
+
+ e_shell_taskbar_set_message (shell_taskbar, status_message);
+}
+
+static void
mail_shell_view_load_view_collection (EShellViewClass *shell_view_class)
{
GalViewCollection *collection;
@@ -160,6 +173,7 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
EShellSettings *shell_settings;
EShellSidebar *shell_sidebar;
EShellWindow *shell_window;
+ EMFormatHTMLDisplay *html_display;
EMFolderTreeModel *folder_tree_model;
EMFolderTree *folder_tree;
RuleContext *context;
@@ -168,6 +182,7 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
GtkUIManager *ui_manager;
MessageList *message_list;
EMailReader *reader;
+ GtkHTML *html;
const gchar *source;
guint merge_id;
gchar *uri;
@@ -197,11 +212,14 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
priv->mail_shell_sidebar = g_object_ref (shell_sidebar);
reader = E_MAIL_READER (shell_content);
+ html_display = e_mail_reader_get_html_display (reader);
message_list = e_mail_reader_get_message_list (reader);
mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar);
folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
+ html = EM_FORMAT_HTML (html_display)->html;
+
g_signal_connect_swapped (
folder_tree, "folder-selected",
G_CALLBACK (mail_shell_view_folder_tree_selected_cb),
@@ -243,6 +261,11 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
G_CALLBACK (e_mail_shell_view_update_search_filter),
mail_shell_view);
+ g_signal_connect_swapped (
+ html, "status-message",
+ G_CALLBACK (mail_shell_view_reader_status_message_cb),
+ mail_shell_view);
+
e_mail_shell_view_actions_init (mail_shell_view);
e_mail_shell_view_update_search_filter (mail_shell_view);
e_mail_reader_init (reader);
diff --git a/mail/em-folder-view.c b/mail/em-folder-view.c
index 9783a7157c..fb449e558c 100644
--- a/mail/em-folder-view.c
+++ b/mail/em-folder-view.c
@@ -238,7 +238,7 @@ emfv_init(GObject *o)
// em_format_set_session ((EMFormat *) emfv->preview, session);
// g_signal_connect(emfv->preview, "link_clicked", G_CALLBACK(emfv_format_link_clicked), emfv);
g_signal_connect(emfv->preview, "popup_event", G_CALLBACK(emfv_format_popup_event), emfv);
- g_signal_connect (emfv->preview, "on_url", G_CALLBACK (emfv_on_url_cb), emfv);
+// g_signal_connect (emfv->preview, "on_url", G_CALLBACK (emfv_on_url_cb), emfv);
// g_signal_connect (((EMFormatHTML *)emfv->preview)->html, "button-release-event", G_CALLBACK (emfv_on_html_button_released_cb), emfv);
//#ifdef ENABLE_PROFILING
// g_signal_connect(emfv->preview, "complete", G_CALLBACK (emfv_format_complete), emfv);
@@ -268,7 +268,7 @@ emfv_class_init(GObjectClass *klass)
((EMFolderViewClass *)klass)->set_message = emfv_set_message;
((EMFolderViewClass *)klass)->activate = emfv_activate;
- ((EMFolderViewClass *)klass)->on_url = emfv_on_url;
+// ((EMFolderViewClass *)klass)->on_url = emfv_on_url;
signals[EMFV_ON_URL] = g_signal_new ("on-url",
G_OBJECT_CLASS_TYPE (klass),
@@ -1077,58 +1077,3 @@ emfv_setting_notify(GConfClient *gconf, guint cnxn_id, GConfEntry *entry, EMFold
break; }
}
}
-
-static void
-emfv_on_url (EMFolderView *emfv, const char *uri, const char *nice_uri)
-{
- if (emfv->statusbar_active) {
- if (emfv->uic) {
- bonobo_ui_component_set_status (emfv->uic, nice_uri, NULL);
- /* Make sure the node keeps existing if nice_url == NULL */
- if (!nice_uri)
- bonobo_ui_component_set_translate (
- emfv->uic, "/", "<status><item name=\"main\"/></status>", NULL);
- }
- }
-}
-
-static void
-emfv_on_url_cb (GObject *emitter, const char *url, EMFolderView *emfv)
-{
- char *nice_url = NULL;
-
- if (url) {
- if (strncmp (url, "mailto:", 7) == 0) {
- CamelInternetAddress *cia = camel_internet_address_new();
- CamelURL *curl;
- char *addr;
-
- curl = camel_url_new(url, NULL);
- camel_address_decode((CamelAddress *)cia, curl->path);
- addr = camel_address_format((CamelAddress *)cia);
- nice_url = g_strdup_printf (_("Click to mail %s"), addr&&addr[0]?addr:(url + 7));
- g_free(addr);
- camel_url_free(curl);
- camel_object_unref(cia);
- } else if (strncmp (url, "callto:", 7) == 0 || strncmp (url, "h323:", 5) == 0 || strncmp (url, "sip:", 4) == 0) {
- CamelInternetAddress *cia = camel_internet_address_new();
- CamelURL *curl;
- char *addr;
-
- curl = camel_url_new(url, NULL);
- camel_address_decode((CamelAddress *)cia, curl->path);
- addr = camel_address_format((CamelAddress *)cia);
- nice_url = g_strdup_printf (_("Click to call %s"), addr&&addr[0]?addr:(url + 7));
- g_free(addr);
- camel_url_free(curl);
- camel_object_unref(cia);
- } else if (!strncmp (url, "##", 2)) {
- nice_url = g_strdup (_("Click to hide/unhide addresses"));
- } else
- nice_url = g_strdup_printf (_("Click to open %s"), url);
- }
-
- g_signal_emit (emfv, signals[EMFV_ON_URL], 0, url, nice_url);
-
- g_free (nice_url);
-}
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index 70b92c39ff..72cec78559 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -75,6 +75,7 @@
#include "mail-config.h"
+#include "e-mail-display.h"
#include "em-format-html-display.h"
#include "e-searching-tokenizer.h"
#include "em-icon-stream.h"
@@ -126,20 +127,47 @@ struct _EMFormatHTMLDisplayPrivate {
gboolean updated;
};
-enum {
- PROP_0,
- PROP_ANIMATE,
- PROP_CARET_MODE
+struct _smime_pobject {
+ EMFormatHTMLPObject object;
+
+ int signature;
+ CamelCipherValidity *valid;
+ GtkWidget *widget;
};
-static int efhd_html_button_press_event (GtkWidget *widget, GdkEventButton *event, EMFormatHTMLDisplay *efh);
-static void efhd_html_link_clicked (GtkHTML *html, const char *url, EMFormatHTMLDisplay *efhd);
-static void efhd_html_on_url (GtkHTML *html, const char *url, EMFormatHTMLDisplay *efhd);
+/* TODO: move the dialogue elsehwere */
+/* FIXME: also in em-format-html.c */
+static const struct {
+ const char *icon, *shortdesc, *description;
+} smime_sign_table[5] = {
+ { "stock_signature-bad", N_("Unsigned"), N_("This message is not signed. There is no guarantee that this message is authentic.") },
+ { "stock_signature-ok", N_("Valid signature"), N_("This message is signed and is valid meaning that it is very likely that this message is authentic.") },
+ { "stock_signature-bad", N_("Invalid signature"), N_("The signature of this message cannot be verified, it may have been altered in transit.") },
+ { "stock_signature", N_("Valid signature, but cannot verify sender"), N_("This message is signed with a valid signature, but the sender of the message cannot be verified.") },
+ { "stock_signature-bad", N_("Signature exists, but need public key"), N_("This message is signed with a signature, but there is no corresponding public key.") },
+
+};
+
+static const struct {
+ const char *icon, *shortdesc, *description;
+} smime_encrypt_table[4] = {
+ { "stock_lock-broken", N_("Unencrypted"), N_("This message is not encrypted. Its content may be viewed in transit across the Internet.") },
+ { "stock_lock-ok", N_("Encrypted, weak"), N_("This message is encrypted, but with a weak encryption algorithm. It would be difficult, but not impossible for an outsider to view the content of this message in a practical amount of time.") },
+ { "stock_lock-ok", N_("Encrypted"), N_("This message is encrypted. It would be difficult for an outsider to view the content of this message.") },
+ { "stock_lock-ok", N_("Encrypted, strong"), N_("This message is encrypted, with a strong encryption algorithm. It would be very difficult for an outsider to view the content of this message in a practical amount of time.") },
+};
+
+static const char *smime_sign_colour[5] = {
+ "", " bgcolor=\"#88bb88\"", " bgcolor=\"#bb8888\"", " bgcolor=\"#e8d122\"",""
+};
static void efhd_attachment_frame(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri);
static gboolean efhd_attachment_image(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject);
static void efhd_message_add_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info);
static void efhd_message_update_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info);
+static void efhd_attachment_button_show (GtkWidget *w, void *data);
+static gboolean efhd_attachment_button (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject);
+static gboolean efhd_attachment_optional (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *object);
static void efhd_attachment_bar_refresh (EMFormatHTMLDisplay *efhd);
struct _attach_puri {
@@ -177,151 +205,250 @@ struct _attach_puri {
};
-static void efhd_iframe_created(GtkHTML *html, GtkHTML *iframe, EMFormatHTMLDisplay *efh);
-/*static void efhd_url_requested(GtkHTML *html, const char *url, GtkHTMLStream *handle, EMFormatHTMLDisplay *efh);
- static gboolean efhd_object_requested(GtkHTML *html, GtkHTMLEmbedded *eb, EMFormatHTMLDisplay *efh);*/
-
static void efhd_message_prefix(EMFormat *emf, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info);
-static const EMFormatHandler *efhd_find_handler(EMFormat *emf, const char *mime_type);
-static void efhd_format_clone(EMFormat *, CamelFolder *folder, const char *, CamelMimeMessage *msg, EMFormat *);
-static void efhd_format_error(EMFormat *emf, CamelStream *stream, const char *txt);
-static void efhd_format_source(EMFormat *, CamelStream *, CamelMimePart *);
-static void efhd_format_attachment(EMFormat *, CamelStream *, CamelMimePart *, const char *, const EMFormatHandler *);
-static void efhd_format_optional(EMFormat *, CamelStream *, CamelMimePart *, CamelStream *);
-static void efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid);
static void efhd_complete(EMFormat *);
gboolean efhd_mnemonic_show_bar (GtkWidget *widget, gboolean focus, GtkWidget *efhd);
static void efhd_builtin_init(EMFormatHTMLDisplayClass *efhc);
-enum {
- EFHD_LINK_CLICKED,
- EFHD_POPUP_EVENT,
- EFHD_ON_URL,
- EFHD_LAST_SIGNAL,
-};
-
-static guint efhd_signals[EFHD_LAST_SIGNAL] = { 0 };
-
-static EMFormatHTMLClass *efhd_parent;
-static EMFormatClass *efhd_format_class;
+static EMFormatHTMLClass *parent_class;
static void
-efhd_gtkhtml_realize(GtkHTML *html, EMFormatHTMLDisplay *efhd)
+efhd_xpkcs7mime_free (EMFormatHTMLPObject *o)
{
- EMFormatHTMLColorType type;
- EMFormatHTML *efh;
- GdkColor *color;
- GtkStyle *style;
- gint state;
+ struct _smime_pobject *po = (struct _smime_pobject *)o;
- efh = EM_FORMAT_HTML (efhd);
- state = GTK_WIDGET_STATE (html);
+ if (po->widget)
+ gtk_widget_destroy(po->widget);
+ camel_cipher_validity_free(po->valid);
+}
- style = gtk_widget_get_style (GTK_WIDGET (html));
- if (style == NULL)
- return;
+static void
+efhd_xpkcs7mime_info_response (GtkWidget *widget,
+ guint button,
+ struct _smime_pobject *po)
+{
+ gtk_widget_destroy (widget);
+ po->widget = NULL;
+}
- g_object_freeze_notify (G_OBJECT (efh));
+#ifdef HAVE_NSS
+static void
+efhd_xpkcs7mime_viewcert_clicked (GtkWidget *button,
+ struct _smime_pobject *po)
+{
+ CamelCipherCertInfo *info = g_object_get_data((GObject *)button, "e-cert-info");
+ ECertDB *db = e_cert_db_peek();
+ ECert *ec = NULL;
- color = &style->bg[state];
- type = EM_FORMAT_HTML_COLOR_BODY;
- em_format_html_set_color (efh, type, color);
+ if (info->email)
+ ec = e_cert_db_find_cert_by_email_address(db, info->email, NULL);
- color = &style->base[GTK_STATE_NORMAL];
- type = EM_FORMAT_HTML_COLOR_CONTENT;
- em_format_html_set_color (efh, type, color);
+ if (ec == NULL && info->name)
+ ec = e_cert_db_find_cert_by_nickname(db, info->name, NULL);
- color = &style->dark[state];
- type = EM_FORMAT_HTML_COLOR_FRAME;
- em_format_html_set_color (efh, type, color);
+ if (ec != NULL) {
+ GtkWidget *w = certificate_viewer_show(ec);
- color = &style->fg[state];
- type = EM_FORMAT_HTML_COLOR_HEADER;
- em_format_html_set_color (efh, type, color);
+ /* oddly enough certificate_viewer_show doesn't ... */
+ gtk_widget_show(w);
+ g_signal_connect(w, "response", G_CALLBACK(gtk_widget_destroy), NULL);
- color = &style->text[state];
- type = EM_FORMAT_HTML_COLOR_TEXT;
- em_format_html_set_color (efh, type, color);
+ if (w && po->widget)
+ gtk_window_set_transient_for((GtkWindow *)w, (GtkWindow *)po->widget);
- g_object_thaw_notify (G_OBJECT (efh));
+ g_object_unref(ec);
+ } else {
+ g_warning("can't find certificate for %s <%s>", info->name?info->name:"", info->email?info->email:"");
+ }
}
+#endif
static void
-efhd_gtkhtml_style_set(GtkHTML *html, GtkStyle *old, EMFormatHTMLDisplay *efhd)
+efhd_xpkcs7mime_add_cert_table (GtkWidget *vbox,
+ CamelDList *certlist,
+ struct _smime_pobject *po)
{
- efhd_gtkhtml_realize(html, efhd);
- em_format_redraw((EMFormat *)efhd);
+ CamelCipherCertInfo *info = (CamelCipherCertInfo *)certlist->head;
+ GtkTable *table = (GtkTable *)gtk_table_new(camel_dlist_length(certlist), 2, FALSE);
+ int n = 0;
+
+ while (info->next) {
+ char *la = NULL;
+ const char *l = NULL;
+
+ if (info->name) {
+ if (info->email && strcmp(info->name, info->email) != 0)
+ l = la = g_strdup_printf("%s <%s>", info->name, info->email);
+ else
+ l = info->name;
+ } else {
+ if (info->email)
+ l = info->email;
+ }
+
+ if (l) {
+ GtkWidget *w;
+#if defined(HAVE_NSS)
+ ECertDB *db = e_cert_db_peek();
+ ECert *ec = NULL;
+#endif
+ w = gtk_label_new(l);
+ gtk_misc_set_alignment((GtkMisc *)w, 0.0, 0.5);
+ g_free(la);
+ gtk_table_attach(table, w, 0, 1, n, n+1, GTK_FILL, GTK_FILL, 3, 3);
+#if defined(HAVE_NSS)
+ w = gtk_button_new_with_mnemonic(_("_View Certificate"));
+ gtk_table_attach(table, w, 1, 2, n, n+1, 0, 0, 3, 3);
+ g_object_set_data((GObject *)w, "e-cert-info", info);
+ g_signal_connect(w, "clicked", G_CALLBACK(efhd_xpkcs7mime_viewcert_clicked), po);
+
+ if (info->email)
+ ec = e_cert_db_find_cert_by_email_address(db, info->email, NULL);
+ if (ec == NULL && info->name)
+ ec = e_cert_db_find_cert_by_nickname(db, info->name, NULL);
+
+ if (ec == NULL)
+ gtk_widget_set_sensitive(w, FALSE);
+ else
+ g_object_unref(ec);
+#else
+ w = gtk_label_new (_("This certificate is not viewable"));
+ gtk_table_attach(table, w, 1, 2, n, n+1, 0, 0, 3, 3);
+#endif
+ n++;
+ }
+
+ info = info->next;
+ }
+
+ gtk_box_pack_start((GtkBox *)vbox, (GtkWidget *)table, TRUE, TRUE, 6);
}
static void
-efhd_init(GObject *o)
+efhd_xpkcs7mime_validity_clicked (GtkWidget *button,
+ EMFormatHTMLPObject *pobject)
{
- EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)o;
-#define efh ((EMFormatHTML *)efhd)
+ struct _smime_pobject *po = (struct _smime_pobject *)pobject;
+ GladeXML *xml;
+ GtkWidget *vbox, *w;
+ char *gladefile;
- efhd->priv = EM_FORMAT_HTML_DISPLAY_GET_PRIVATE(efhd);
+ if (po->widget)
+ /* FIXME: window raise? */
+ return;
- efhd->search_tok = (ESearchingTokenizer *)e_searching_tokenizer_new();
- gtk_html_set_tokenizer (efh->html, (HTMLTokenizer *)efhd->search_tok);
+ gladefile = g_build_filename (
+ EVOLUTION_GLADEDIR, "mail-dialogs.glade", NULL);
+ xml = glade_xml_new (gladefile, "message_security_dialog", NULL);
+ g_free (gladefile);
- g_signal_connect(efh->html, "realize", G_CALLBACK(efhd_gtkhtml_realize), o);
- g_signal_connect(efh->html, "style-set", G_CALLBACK(efhd_gtkhtml_style_set), o);
- /* we want to convert url's etc */
- efh->text_html_flags |= CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES;
-#undef efh
+ po->widget = glade_xml_get_widget(xml, "message_security_dialog");
- efhd->nobar = getenv("EVOLUTION_NO_BAR") != NULL;
+ vbox = glade_xml_get_widget(xml, "signature_vbox");
+ w = gtk_label_new (_(smime_sign_table[po->valid->sign.status].description));
+ gtk_misc_set_alignment((GtkMisc *)w, 0.0, 0.5);
+ gtk_label_set_line_wrap((GtkLabel *)w, TRUE);
+ gtk_box_pack_start((GtkBox *)vbox, w, TRUE, TRUE, 6);
+ if (po->valid->sign.description) {
+ GtkTextBuffer *buffer;
- efhd->priv->show_bar = FALSE;
- efhd->priv->files = NULL;
-}
+ buffer = gtk_text_buffer_new(NULL);
+ gtk_text_buffer_set_text(buffer, po->valid->sign.description, strlen(po->valid->sign.description));
+ w = g_object_new(gtk_scrolled_window_get_type(),
+ "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
+ "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
+ "shadow_type", GTK_SHADOW_IN,
+ "child", g_object_new(gtk_text_view_get_type(),
+ "buffer", buffer,
+ "cursor_visible", FALSE,
+ "editable", FALSE,
+ "width_request", 500,
+ "height_request", 160,
+ NULL),
+ NULL);
+ g_object_unref(buffer);
-static void
-efhd_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_ANIMATE:
- em_format_html_display_set_animate (
- EM_FORMAT_HTML_DISPLAY (object),
- g_value_get_boolean (value));
- return;
+ gtk_box_pack_start((GtkBox *)vbox, w, TRUE, TRUE, 6);
+ }
- case PROP_CARET_MODE:
- em_format_html_display_set_caret_mode (
- EM_FORMAT_HTML_DISPLAY (object),
- g_value_get_boolean (value));
- return;
+ if (!camel_dlist_empty(&po->valid->sign.signers))
+ efhd_xpkcs7mime_add_cert_table(vbox, &po->valid->sign.signers, po);
+
+ gtk_widget_show_all(vbox);
+
+ vbox = glade_xml_get_widget(xml, "encryption_vbox");
+ w = gtk_label_new(_(smime_encrypt_table[po->valid->encrypt.status].description));
+ gtk_misc_set_alignment((GtkMisc *)w, 0.0, 0.5);
+ gtk_label_set_line_wrap((GtkLabel *)w, TRUE);
+ gtk_box_pack_start((GtkBox *)vbox, w, TRUE, TRUE, 6);
+ if (po->valid->encrypt.description) {
+ GtkTextBuffer *buffer;
+
+ buffer = gtk_text_buffer_new(NULL);
+ gtk_text_buffer_set_text(buffer, po->valid->encrypt.description, strlen(po->valid->encrypt.description));
+ w = g_object_new(gtk_scrolled_window_get_type(),
+ "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
+ "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
+ "shadow_type", GTK_SHADOW_IN,
+ "child", g_object_new(gtk_text_view_get_type(),
+ "buffer", buffer,
+ "cursor_visible", FALSE,
+ "editable", FALSE,
+ "width_request", 500,
+ "height_request", 160,
+ NULL),
+ NULL);
+ g_object_unref(buffer);
+
+ gtk_box_pack_start((GtkBox *)vbox, w, TRUE, TRUE, 6);
}
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ if (!camel_dlist_empty(&po->valid->encrypt.encrypters))
+ efhd_xpkcs7mime_add_cert_table(vbox, &po->valid->encrypt.encrypters, po);
+
+ gtk_widget_show_all(vbox);
+
+ g_object_unref(xml);
+
+ g_signal_connect(po->widget, "response", G_CALLBACK(efhd_xpkcs7mime_info_response), po);
+ gtk_widget_show(po->widget);
}
-static void
-efhd_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_ANIMATE:
- g_value_set_boolean (
- value, em_format_html_display_get_animate (
- EM_FORMAT_HTML_DISPLAY (object)));
- return;
+static gboolean
+efhd_xpkcs7mime_button (EMFormatHTML *efh,
+ GtkHTMLEmbedded *eb,
+ EMFormatHTMLPObject *pobject)
+{
+ GtkWidget *container;
+ GtkWidget *widget;
+ struct _smime_pobject *po = (struct _smime_pobject *)pobject;
+ const char *icon_name;
- case PROP_CARET_MODE:
- g_value_set_boolean (
- value, em_format_html_display_get_caret_mode (
- EM_FORMAT_HTML_DISPLAY (object)));
- return;
- }
+ /* FIXME: need to have it based on encryption and signing too */
+ if (po->valid->sign.status != 0)
+ icon_name = smime_sign_table[po->valid->sign.status].icon;
+ else
+ icon_name = smime_encrypt_table[po->valid->encrypt.status].icon;
+
+ container = GTK_WIDGET (eb);
+
+ widget = gtk_button_new ();
+ g_signal_connect (
+ widget, "clicked",
+ G_CALLBACK (efhd_xpkcs7mime_validity_clicked), pobject);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ gtk_widget_show (widget);
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ container = widget;
+
+ widget = gtk_image_new_from_icon_name (
+ icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ gtk_widget_show (widget);
+
+ return TRUE;
}
static void
@@ -337,206 +464,294 @@ efhd_finalize (GObject *object)
g_free (priv->search_text);
/* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (efhd_parent)->finalize (object);
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
-static gboolean
-efhd_bool_accumulator(GSignalInvocationHint *ihint, GValue *out, const GValue *in, void *data)
+static void
+efhd_format_clone (EMFormat *emf,
+ CamelFolder *folder,
+ const gchar *uid,
+ CamelMimeMessage *msg,
+ EMFormat *src)
{
- gboolean val = g_value_get_boolean(in);
+ EMFormatHTMLDisplayPrivate *priv;
+
+ priv = EM_FORMAT_HTML_DISPLAY_GET_PRIVATE (emf);
+
+ if (emf != src) {
+ priv->show_bar = (src != NULL) ?
+ EM_FORMAT_HTML_DISPLAY (src)->priv->show_bar : FALSE;
- g_value_set_boolean(out, val);
+ EM_FORMAT_HTML (emf)->header_wrap_flags = 0;
+ }
- return !val;
+ /* Chain up to parent's format_clone() method. */
+ EM_FORMAT_CLASS (parent_class)->
+ format_clone (emf, folder, uid, msg, src);
}
static void
-efhd_class_init (GObjectClass *class)
+efhd_format_attachment (EMFormat *emf,
+ CamelStream *stream,
+ CamelMimePart *part,
+ const gchar *mime_type,
+ const EMFormatHandler *handle)
{
- GObjectClass *object_class;
- EMFormatClass *format_class;
+ char *classid, *text, *html;
+ struct _attach_puri *info;
- g_type_class_add_private (class, sizeof (EMFormatHTMLDisplayPrivate));
+ classid = g_strdup_printf ("attachment%s", emf->part_id->str);
+ info = (struct _attach_puri *) em_format_add_puri (
+ emf, sizeof (*info), classid, part, efhd_attachment_frame);
+ em_format_html_add_pobject (
+ EM_FORMAT_HTML (emf), sizeof (EMFormatHTMLPObject),
+ classid, part, efhd_attachment_button);
+ info->handle = handle;
+ info->shown = em_format_is_inline (
+ emf, info->puri.part_id, info->puri.part, handle);
+ info->snoop_mime_type = emf->snoop_mime_type;
+ info->attachment = e_attachment_new_from_mime_part (info->puri.part);
+ e_attachment_bar_create_attachment_cache (info->attachment);
- object_class = G_OBJECT_CLASS (class);
- object_class->set_property = efhd_set_property;
- object_class->get_property = efhd_get_property;
- object_class->finalize = efhd_finalize;
+ if (emf->valid) {
+ info->sign = emf->valid->sign.status;
+ info->encrypt = emf->valid->encrypt.status;
+ }
- format_class = EM_FORMAT_CLASS (class);
- format_class->find_handler = efhd_find_handler;
- format_class->format_clone = efhd_format_clone;
- format_class->format_error = efhd_format_error;
- format_class->format_source = efhd_format_source;
- format_class->format_attachment = efhd_format_attachment;
- format_class->format_optional = efhd_format_optional;
- format_class->format_secure = efhd_format_secure;
- format_class->complete = efhd_complete;
+ camel_stream_write_string(
+ stream, EM_FORMAT_HTML_VPAD
+ "<table cellspacing=0 cellpadding=0><tr><td>"
+ "<table width=10 cellspacing=0 cellpadding=0>"
+ "<tr><td></td></tr></table></td>");
- g_object_class_install_property (
- object_class,
- PROP_ANIMATE,
- g_param_spec_boolean (
- "animate",
- "Animate Images",
- NULL,
- FALSE,
- G_PARAM_READWRITE));
-
- g_object_class_install_property (
- object_class,
- PROP_CARET_MODE,
- g_param_spec_boolean (
- "caret-mode",
- "Caret Mode",
- NULL,
- FALSE,
- G_PARAM_READWRITE));
-
- efhd_signals[EFHD_LINK_CLICKED] =
- g_signal_new("link_clicked",
- G_TYPE_FROM_CLASS(class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(EMFormatHTMLDisplayClass, link_clicked),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
-
- efhd_signals[EFHD_POPUP_EVENT] =
- g_signal_new("popup_event",
- G_TYPE_FROM_CLASS(class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(EMFormatHTMLDisplayClass, popup_event),
- efhd_bool_accumulator, NULL,
- e_marshal_BOOLEAN__BOXED_POINTER_POINTER,
- G_TYPE_BOOLEAN, 3,
- GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
- G_TYPE_POINTER, G_TYPE_POINTER);
-
- efhd_signals[EFHD_ON_URL] =
- g_signal_new("on_url",
- G_TYPE_FROM_CLASS(class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(EMFormatHTMLDisplayClass, on_url),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1,
- G_TYPE_STRING);
-
- efhd_builtin_init((EMFormatHTMLDisplayClass *)class);
-}
+ camel_stream_printf (
+ stream, "<td><object classid=\"%s\"></object></td>", classid);
-GType
-em_format_html_display_get_type (void)
-{
- static GType type = 0;
+ camel_stream_write_string (
+ stream, "<td><table width=3 cellspacing=0 cellpadding=0>"
+ "<tr><td></td></tr></table></td><td><font size=-1>");
- if (type == 0) {
- static const GTypeInfo info = {
- sizeof(EMFormatHTMLDisplayClass),
- NULL, NULL,
- (GClassInitFunc)efhd_class_init,
- NULL, NULL,
- sizeof(EMFormatHTMLDisplay), 0,
- (GInstanceInitFunc)efhd_init
- };
- efhd_parent = g_type_class_ref(em_format_html_get_type());
- efhd_format_class = g_type_class_ref(em_format_get_type());
- type = g_type_register_static(em_format_html_get_type(), "EMFormatHTMLDisplay", &info, 0);
- }
+ /* output some info about it */
+ /* FIXME: should we look up mime_type from object again? */
+ text = em_format_describe_part (part, mime_type);
+ html = camel_text_to_html (
+ text, EM_FORMAT_HTML (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>\n"
+ EM_FORMAT_HTML_VPAD);
- return type;
+ if (handle && info->shown)
+ handle->handler (emf, stream, part, handle);
+
+ g_free (classid);
}
-static gboolean
-efhd_scroll_event(GtkWidget *w, GdkEventScroll *event, EMFormatHTMLDisplay *efhd)
+static void
+efhd_format_optional (EMFormat *emf,
+ CamelStream *fstream,
+ CamelMimePart *part,
+ CamelStream *mstream)
{
- if(event->state & GDK_CONTROL_MASK)
- {
- if(event->direction == GDK_SCROLL_UP)
- {
- gtk_html_zoom_in (efhd->parent.html);
- }
- else if(event->direction == GDK_SCROLL_DOWN)
- {
- gtk_html_zoom_out (efhd->parent.html);
- }
- return TRUE;
+ char *classid, *html;
+ struct _attach_puri *info;
+ CamelStream *stream;
+
+ if (CAMEL_IS_STREAM_FILTER (fstream) && ((CamelStreamFilter *) fstream)->source)
+ stream = ((CamelStreamFilter *) fstream)->source;
+ else
+ stream = fstream;
+
+ classid = g_strdup_printf ("optional%s", emf->part_id->str);
+ info = (struct _attach_puri *) em_format_add_puri (
+ emf, sizeof (*info), classid, part, efhd_attachment_frame);
+ em_format_html_add_pobject (
+ EM_FORMAT_HTML (emf), sizeof (EMFormatHTMLPObject),
+ classid, part, efhd_attachment_optional);
+ info->handle = em_format_find_handler (emf, "text/plain");
+ info->shown = FALSE;
+ info->snoop_mime_type = "text/plain";
+ info->attachment = e_attachment_new_from_mime_part (info->puri.part);
+ info->mstream = (CamelStreamMem *) mstream;
+ if (emf->valid) {
+ info->sign = emf->valid->sign.status;
+ info->encrypt = emf->valid->encrypt.status;
}
- return FALSE;
-}
-EMFormatHTMLDisplay *em_format_html_display_new(void)
-{
- EMFormatHTMLDisplay *efhd;
+ camel_stream_write_string (
+ stream, EM_FORMAT_HTML_VPAD
+ "<table cellspacing=0 cellpadding=0><tr><td>"
+ "<h3><font size=-1 color=red>");
+
+ html = camel_text_to_html (
+ _("Evolution cannot render this email as it is too "
+ "large to process. You can view it unformatted or "
+ "with an external text editor."),
+ EM_FORMAT_HTML (emf)->text_html_flags &
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
+ camel_stream_write_string (stream, html);
+ camel_stream_write_string (
+ stream, "</font></h3></td></tr></table>\n");
+ camel_stream_write_string (
+ stream, "<table cellspacing=0 cellpadding=0><tr>");
+ camel_stream_printf (
+ stream, "<td><object classid=\"%s\"></object>"
+ "</td></tr></table>", classid);
- efhd = g_object_new(em_format_html_display_get_type(), 0);
+ g_free(html);
- g_signal_connect(efhd->parent.html, "iframe_created", G_CALLBACK(efhd_iframe_created), efhd);
- g_signal_connect(efhd->parent.html, "link_clicked", G_CALLBACK(efhd_html_link_clicked), efhd);
- g_signal_connect(efhd->parent.html, "on_url", G_CALLBACK(efhd_html_on_url), efhd);
- g_signal_connect(efhd->parent.html, "button_press_event", G_CALLBACK(efhd_html_button_press_event), efhd);
- g_signal_connect(efhd->parent.html,"scroll_event", G_CALLBACK(efhd_scroll_event), efhd);
+ camel_stream_write_string (
+ stream, EM_FORMAT_HTML_VPAD);
- return efhd;
+ g_free (classid);
}
-gboolean
-em_format_html_display_get_animate (EMFormatHTMLDisplay *efhd)
+static void
+efhd_format_secure (EMFormat *emf,
+ CamelStream *stream,
+ CamelMimePart *part,
+ CamelCipherValidity *valid)
{
- GtkHTML *html;
+ EM_FORMAT_CLASS (parent_class)->
+ format_secure (emf, stream, part, valid);
+
+ if (emf->valid == valid
+ && (valid->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE
+ || valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE)) {
+ char *classid;
+ struct _smime_pobject *pobj;
+
+ camel_stream_printf (
+ stream, "<table border=0 width=\"100%%\" "
+ "cellpadding=3 cellspacing=0%s><tr>",
+ smime_sign_colour[valid->sign.status]);
+
+ classid = g_strdup_printf (
+ "smime:///em-format-html/%s/icon/signed",
+ emf->part_id->str);
+ pobj = (struct _smime_pobject *) em_format_html_add_pobject (
+ EM_FORMAT_HTML (emf), sizeof (*pobj),
+ classid, part, efhd_xpkcs7mime_button);
+ pobj->valid = camel_cipher_validity_clone(valid);
+ pobj->object.free = efhd_xpkcs7mime_free;
+ camel_stream_printf (
+ stream, "<td valign=center><object classid=\"%s\">"
+ "</object></td><td width=100%% valign=center>",
+ classid);
+ g_free (classid);
+
+ if (valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) {
+ const gchar *desc;
+ gint status;
- g_return_val_if_fail (EM_IS_FORMAT_HTML_DISPLAY (efhd), FALSE);
+ status = valid->sign.status;
+ desc = smime_sign_table[status].shortdesc;
+ camel_stream_printf (stream, "%s", gettext (desc));
+ }
- html = ((EMFormatHTML *) efhd)->html;
+ if (valid->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) {
+ const gchar *desc;
+ gint status;
- return gtk_html_get_animate (html);
+ if (valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) {
+ camel_stream_printf (stream, "<br>");
+ }
+
+ status = valid->encrypt.status;
+ desc = smime_encrypt_table[status].shortdesc;
+ camel_stream_printf (stream, "%s", gettext (desc));
+ }
+
+ camel_stream_printf(stream, "</td></tr></table>");
+ }
}
-void
-em_format_html_display_set_animate (EMFormatHTMLDisplay *efhd,
- gboolean animate)
+static void
+efhd_class_init (EMFormatHTMLDisplayClass *class)
{
- GtkHTML *html;
+ GObjectClass *object_class;
+ EMFormatClass *format_class;
+ EMFormatHTMLClass *format_html_class;
- /* XXX Note this is imperfect. If animate is set by
- * some other means we won't emit a notification. */
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EMFormatHTMLDisplayPrivate));
- g_return_if_fail (EM_IS_FORMAT_HTML_DISPLAY (efhd));
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = efhd_finalize;
- html = ((EMFormatHTML *) efhd)->html;
- gtk_html_set_animate (html, animate);
+ format_class = EM_FORMAT_CLASS (class);
+ format_class->format_clone = efhd_format_clone;
+ format_class->format_attachment = efhd_format_attachment;
+ format_class->format_optional = efhd_format_optional;
+ format_class->format_secure = efhd_format_secure;
+ format_class->complete = efhd_complete;
+
+ format_html_class = EM_FORMAT_HTML_CLASS (class);
+ format_html_class->html_widget_type = E_TYPE_MAIL_DISPLAY;
- g_object_notify (G_OBJECT (efhd), "animate");
+ efhd_builtin_init (class);
}
-gboolean
-em_format_html_display_get_caret_mode (EMFormatHTMLDisplay *efhd)
+static void
+efhd_init (EMFormatHTMLDisplay *efhd)
{
GtkHTML *html;
- g_return_val_if_fail (EM_IS_FORMAT_HTML_DISPLAY (efhd), FALSE);
+ html = EM_FORMAT_HTML (efhd)->html;
+
+ efhd->priv = EM_FORMAT_HTML_DISPLAY_GET_PRIVATE (efhd);
- html = ((EMFormatHTML *) efhd)->html;
+ e_mail_display_set_formatter (
+ E_MAIL_DISPLAY (html), EM_FORMAT_HTML (efhd));
- return gtk_html_get_caret_mode (html);
+ efhd->search_tok =
+ (ESearchingTokenizer *) e_searching_tokenizer_new ();
+ gtk_html_set_tokenizer (html, (HTMLTokenizer *) efhd->search_tok);
+
+ /* we want to convert url's etc */
+ EM_FORMAT_HTML (efhd)->text_html_flags |=
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
+ CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES;
+
+ efhd->priv->show_bar = FALSE;
+ efhd->priv->files = NULL;
}
-void
-em_format_html_display_set_caret_mode (EMFormatHTMLDisplay *efhd,
- gboolean caret_mode)
+GType
+em_format_html_display_get_type (void)
{
- GtkHTML *html;
+ static GType type = 0;
- /* XXX Note this is imperfect. If caret mode is set by
- * some other means we won't emit a notification. */
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EMFormatHTMLDisplayClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) efhd_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EMFormatHTMLDisplay),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) efhd_init,
+ NULL /* value_table */
+ };
- g_return_if_fail (EM_IS_FORMAT_HTML_DISPLAY (efhd));
+ type = g_type_register_static (
+ EM_TYPE_FORMAT_HTML, "EMFormatHTMLDisplay",
+ &type_info, 0);
+ }
- html = ((EMFormatHTML *) efhd)->html;
- gtk_html_set_caret_mode (html, caret_mode);
+ return type;
+}
- g_object_notify (G_OBJECT (efhd), "caret-mode");
+EMFormatHTMLDisplay *
+em_format_html_display_new (void)
+{
+ return g_object_new (EM_TYPE_FORMAT_HTML_DISPLAY, NULL);
}
EAttachmentBar *
@@ -896,147 +1111,6 @@ em_format_html_display_zoom_reset (EMFormatHTMLDisplay *efhd)
/* ********************************************************************** */
static void
-efhd_iframe_created(GtkHTML *html, GtkHTML *iframe, EMFormatHTMLDisplay *efh)
-{
- d(printf("Iframe created %p ... \n", iframe));
-
- g_signal_connect(iframe, "button_press_event", G_CALLBACK (efhd_html_button_press_event), efh);
-
- return;
-}
-
-static void
-efhd_get_uri_puri (GtkWidget *html, GdkEventButton *event, EMFormatHTMLDisplay *efhd, char **uri, EMFormatPURI **puri)
-{
- char *url, *img_url;
-
- g_return_if_fail (html != NULL);
- g_return_if_fail (GTK_IS_HTML (html));
- g_return_if_fail (efhd != NULL);
-
- if (event) {
- url = gtk_html_get_url_at (GTK_HTML (html), event->x, event->y);
- img_url = gtk_html_get_image_src_at (GTK_HTML (html), event->x, event->y);
- } else {
- url = gtk_html_get_cursor_url (GTK_HTML (html));
- img_url = gtk_html_get_cursor_image_src (GTK_HTML (html));
- }
-
- if (img_url) {
- if (!(strstr (img_url, "://") || g_ascii_strncasecmp (img_url, "cid:", 4) == 0)) {
- char *u = g_strconcat ("file://", img_url, NULL);
- g_free (img_url);
- img_url = u;
- }
- }
-
- if (puri) {
- if (url)
- *puri = em_format_find_puri ((EMFormat *)efhd, url);
-
- if (!*puri && img_url)
- *puri = em_format_find_puri ((EMFormat *)efhd, img_url);
- }
-
- if (uri) {
- *uri = NULL;
- if (img_url && g_ascii_strncasecmp (img_url, "cid:", 4) != 0) {
- if (url)
- *uri = g_strdup_printf ("%s\n%s", url, img_url);
- else {
- *uri = img_url;
- img_url = NULL;
- }
- } else {
- *uri = url;
- url = NULL;
- }
- }
-
- g_free (url);
- g_free (img_url);
-}
-
-static int
-efhd_html_button_press_event (GtkWidget *widget, GdkEventButton *event, EMFormatHTMLDisplay *efhd)
-{
- char *uri = NULL;
- EMFormatPURI *puri = NULL;
- gboolean res = FALSE;
-
- if (event->button != 3)
- return FALSE;
-
- d(printf("popup button pressed\n"));
-
- efhd_get_uri_puri (widget, event, efhd, &uri, &puri);
-
- if (uri && !strncmp (uri, "##", 2)) {
- g_free (uri);
- return TRUE;
- }
-
- g_signal_emit((GtkObject *)efhd, efhd_signals[EFHD_POPUP_EVENT], 0, event, uri, puri?puri->part:NULL, &res);
-
- g_free (uri);
-
- return res;
-}
-
-gboolean
-em_format_html_display_popup_menu (EMFormatHTMLDisplay *efhd)
-{
- GtkHTML *html;
- char *uri = NULL;
- EMFormatPURI *puri = NULL;
- gboolean res = FALSE;
-
- html = efhd->parent.html;
-
- efhd_get_uri_puri (GTK_WIDGET (html), NULL, efhd, &uri, &puri);
-
- g_signal_emit ((GtkObject *)efhd, efhd_signals[EFHD_POPUP_EVENT], 0, NULL, uri, puri?puri->part:NULL, &res);
-
- g_free (uri);
-
- return res;
-}
-
-static void
-efhd_html_link_clicked (GtkHTML *html, const char *url, EMFormatHTMLDisplay *efhd)
-{
- d(printf("link clicked event '%s'\n", url));
- if (url && !strncmp(url, "##", 2)) {
- if (!strcmp (url, "##TO##"))
- if (!(((EMFormatHTML *) efhd)->header_wrap_flags & EM_FORMAT_HTML_HEADER_TO))
- ((EMFormatHTML *) efhd)->header_wrap_flags |= EM_FORMAT_HTML_HEADER_TO;
- else
- ((EMFormatHTML *) efhd)->header_wrap_flags &= ~EM_FORMAT_HTML_HEADER_TO;
- else if (!strcmp (url, "##CC##"))
- if (!(((EMFormatHTML *) efhd)->header_wrap_flags & EM_FORMAT_HTML_HEADER_CC))
- ((EMFormatHTML *) efhd)->header_wrap_flags |= EM_FORMAT_HTML_HEADER_CC;
- else
- ((EMFormatHTML *) efhd)->header_wrap_flags &= ~EM_FORMAT_HTML_HEADER_CC;
- else if (!strcmp (url, "##BCC##")) {
- if (!(((EMFormatHTML *) efhd)->header_wrap_flags & EM_FORMAT_HTML_HEADER_BCC))
- ((EMFormatHTML *) efhd)->header_wrap_flags |= EM_FORMAT_HTML_HEADER_BCC;
- else
- ((EMFormatHTML *) efhd)->header_wrap_flags &= ~EM_FORMAT_HTML_HEADER_BCC;
- }
- em_format_redraw((EMFormat *)efhd);
- } else
- g_signal_emit((GObject *)efhd, efhd_signals[EFHD_LINK_CLICKED], 0, url);
-}
-
-static void
-efhd_html_on_url (GtkHTML *html, const char *url, EMFormatHTMLDisplay *efhd)
-{
- d(printf("on_url event '%s'\n", url));
-
- g_signal_emit((GObject *)efhd, efhd_signals[EFHD_ON_URL], 0, url);
-}
-
-static void
efhd_complete(EMFormat *emf)
{
EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)emf;
@@ -1052,306 +1126,6 @@ efhd_complete(EMFormat *emf)
/* ********************************************************************** */
-/* TODO: move the dialogue elsehwere */
-/* FIXME: also in em-format-html.c */
-static const struct {
- const char *icon, *shortdesc, *description;
-} smime_sign_table[5] = {
- { "stock_signature-bad", N_("Unsigned"), N_("This message is not signed. There is no guarantee that this message is authentic.") },
- { "stock_signature-ok", N_("Valid signature"), N_("This message is signed and is valid meaning that it is very likely that this message is authentic.") },
- { "stock_signature-bad", N_("Invalid signature"), N_("The signature of this message cannot be verified, it may have been altered in transit.") },
- { "stock_signature", N_("Valid signature, but cannot verify sender"), N_("This message is signed with a valid signature, but the sender of the message cannot be verified.") },
- { "stock_signature-bad", N_("Signature exists, but need public key"), N_("This message is signed with a signature, but there is no corresponding public key.") },
-
-};
-
-static const struct {
- const char *icon, *shortdesc, *description;
-} smime_encrypt_table[4] = {
- { "stock_lock-broken", N_("Unencrypted"), N_("This message is not encrypted. Its content may be viewed in transit across the Internet.") },
- { "stock_lock-ok", N_("Encrypted, weak"), N_("This message is encrypted, but with a weak encryption algorithm. It would be difficult, but not impossible for an outsider to view the content of this message in a practical amount of time.") },
- { "stock_lock-ok", N_("Encrypted"), N_("This message is encrypted. It would be difficult for an outsider to view the content of this message.") },
- { "stock_lock-ok", N_("Encrypted, strong"), N_("This message is encrypted, with a strong encryption algorithm. It would be very difficult for an outsider to view the content of this message in a practical amount of time.") },
-};
-
-static const char *smime_sign_colour[5] = {
- "", " bgcolor=\"#88bb88\"", " bgcolor=\"#bb8888\"", " bgcolor=\"#e8d122\"",""
-};
-
-struct _smime_pobject {
- EMFormatHTMLPObject object;
-
- int signature;
- CamelCipherValidity *valid;
- GtkWidget *widget;
-};
-
-static void
-efhd_xpkcs7mime_free(EMFormatHTMLPObject *o)
-{
- struct _smime_pobject *po = (struct _smime_pobject *)o;
-
- if (po->widget)
- gtk_widget_destroy(po->widget);
- camel_cipher_validity_free(po->valid);
-}
-
-static void
-efhd_xpkcs7mime_info_response(GtkWidget *w, guint button, struct _smime_pobject *po)
-{
- gtk_widget_destroy(w);
- po->widget = NULL;
-}
-
-#ifdef HAVE_NSS
-static void
-efhd_xpkcs7mime_viewcert_foad(GtkWidget *w, guint button, struct _smime_pobject *po)
-{
- gtk_widget_destroy(w);
-}
-
-static void
-efhd_xpkcs7mime_viewcert_clicked(GtkWidget *button, struct _smime_pobject *po)
-{
- CamelCipherCertInfo *info = g_object_get_data((GObject *)button, "e-cert-info");
- ECertDB *db = e_cert_db_peek();
- ECert *ec = NULL;
-
- if (info->email)
- ec = e_cert_db_find_cert_by_email_address(db, info->email, NULL);
-
- if (ec == NULL && info->name)
- ec = e_cert_db_find_cert_by_nickname(db, info->name, NULL);
-
- if (ec != NULL) {
- GtkWidget *w = certificate_viewer_show(ec);
-
- /* oddly enough certificate_viewer_show doesn't ... */
- gtk_widget_show(w);
- g_signal_connect(w, "response", G_CALLBACK(efhd_xpkcs7mime_viewcert_foad), po);
-
- if (w && po->widget)
- gtk_window_set_transient_for((GtkWindow *)w, (GtkWindow *)po->widget);
-
- g_object_unref(ec);
- } else {
- g_warning("can't find certificate for %s <%s>", info->name?info->name:"", info->email?info->email:"");
- }
-}
-#endif
-
-static void
-efhd_xpkcs7mime_add_cert_table(GtkWidget *vbox, CamelDList *certlist, struct _smime_pobject *po)
-{
- CamelCipherCertInfo *info = (CamelCipherCertInfo *)certlist->head;
- GtkTable *table = (GtkTable *)gtk_table_new(camel_dlist_length(certlist), 2, FALSE);
- int n = 0;
-
- while (info->next) {
- char *la = NULL;
- const char *l = NULL;
-
- if (info->name) {
- if (info->email && strcmp(info->name, info->email) != 0)
- l = la = g_strdup_printf("%s <%s>", info->name, info->email);
- else
- l = info->name;
- } else {
- if (info->email)
- l = info->email;
- }
-
- if (l) {
- GtkWidget *w;
-#if defined(HAVE_NSS)
- ECertDB *db = e_cert_db_peek();
- ECert *ec = NULL;
-#endif
- w = gtk_label_new(l);
- gtk_misc_set_alignment((GtkMisc *)w, 0.0, 0.5);
- g_free(la);
- gtk_table_attach(table, w, 0, 1, n, n+1, GTK_FILL, GTK_FILL, 3, 3);
-#if defined(HAVE_NSS)
- w = gtk_button_new_with_mnemonic(_("_View Certificate"));
- gtk_table_attach(table, w, 1, 2, n, n+1, 0, 0, 3, 3);
- g_object_set_data((GObject *)w, "e-cert-info", info);
- g_signal_connect(w, "clicked", G_CALLBACK(efhd_xpkcs7mime_viewcert_clicked), po);
-
- if (info->email)
- ec = e_cert_db_find_cert_by_email_address(db, info->email, NULL);
- if (ec == NULL && info->name)
- ec = e_cert_db_find_cert_by_nickname(db, info->name, NULL);
-
- if (ec == NULL)
- gtk_widget_set_sensitive(w, FALSE);
- else
- g_object_unref(ec);
-#else
- w = gtk_label_new (_("This certificate is not viewable"));
- gtk_table_attach(table, w, 1, 2, n, n+1, 0, 0, 3, 3);
-#endif
- n++;
- }
-
- info = info->next;
- }
-
- gtk_box_pack_start((GtkBox *)vbox, (GtkWidget *)table, TRUE, TRUE, 6);
-}
-
-static void
-efhd_xpkcs7mime_validity_clicked(GtkWidget *button, EMFormatHTMLPObject *pobject)
-{
- struct _smime_pobject *po = (struct _smime_pobject *)pobject;
- GladeXML *xml;
- GtkWidget *vbox, *w;
- char *gladefile;
-
- if (po->widget)
- /* FIXME: window raise? */
- return;
-
- gladefile = g_build_filename (EVOLUTION_GLADEDIR,
- "mail-dialogs.glade",
- NULL);
- xml = glade_xml_new(gladefile, "message_security_dialog", NULL);
- g_free (gladefile);
-
- po->widget = glade_xml_get_widget(xml, "message_security_dialog");
-
- vbox = glade_xml_get_widget(xml, "signature_vbox");
- w = gtk_label_new (_(smime_sign_table[po->valid->sign.status].description));
- gtk_misc_set_alignment((GtkMisc *)w, 0.0, 0.5);
- gtk_label_set_line_wrap((GtkLabel *)w, TRUE);
- gtk_box_pack_start((GtkBox *)vbox, w, TRUE, TRUE, 6);
- if (po->valid->sign.description) {
- GtkTextBuffer *buffer;
-
- buffer = gtk_text_buffer_new(NULL);
- gtk_text_buffer_set_text(buffer, po->valid->sign.description, strlen(po->valid->sign.description));
- w = g_object_new(gtk_scrolled_window_get_type(),
- "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
- "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
- "shadow_type", GTK_SHADOW_IN,
- "child", g_object_new(gtk_text_view_get_type(),
- "buffer", buffer,
- "cursor_visible", FALSE,
- "editable", FALSE,
- "width_request", 500,
- "height_request", 160,
- NULL),
- NULL);
- g_object_unref(buffer);
-
- gtk_box_pack_start((GtkBox *)vbox, w, TRUE, TRUE, 6);
- }
-
- if (!camel_dlist_empty(&po->valid->sign.signers))
- efhd_xpkcs7mime_add_cert_table(vbox, &po->valid->sign.signers, po);
-
- gtk_widget_show_all(vbox);
-
- vbox = glade_xml_get_widget(xml, "encryption_vbox");
- w = gtk_label_new(_(smime_encrypt_table[po->valid->encrypt.status].description));
- gtk_misc_set_alignment((GtkMisc *)w, 0.0, 0.5);
- gtk_label_set_line_wrap((GtkLabel *)w, TRUE);
- gtk_box_pack_start((GtkBox *)vbox, w, TRUE, TRUE, 6);
- if (po->valid->encrypt.description) {
- GtkTextBuffer *buffer;
-
- buffer = gtk_text_buffer_new(NULL);
- gtk_text_buffer_set_text(buffer, po->valid->encrypt.description, strlen(po->valid->encrypt.description));
- w = g_object_new(gtk_scrolled_window_get_type(),
- "hscrollbar_policy", GTK_POLICY_AUTOMATIC,
- "vscrollbar_policy", GTK_POLICY_AUTOMATIC,
- "shadow_type", GTK_SHADOW_IN,
- "child", g_object_new(gtk_text_view_get_type(),
- "buffer", buffer,
- "cursor_visible", FALSE,
- "editable", FALSE,
- "width_request", 500,
- "height_request", 160,
- NULL),
- NULL);
- g_object_unref(buffer);
-
- gtk_box_pack_start((GtkBox *)vbox, w, TRUE, TRUE, 6);
- }
-
- if (!camel_dlist_empty(&po->valid->encrypt.encrypters))
- efhd_xpkcs7mime_add_cert_table(vbox, &po->valid->encrypt.encrypters, po);
-
- gtk_widget_show_all(vbox);
-
- g_object_unref(xml);
-
- g_signal_connect(po->widget, "response", G_CALLBACK(efhd_xpkcs7mime_info_response), po);
- gtk_widget_show(po->widget);
-}
-
-static gboolean
-efhd_xpkcs7mime_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
-{
- GtkWidget *icon, *button;
- struct _smime_pobject *po = (struct _smime_pobject *)pobject;
- const char *icon_name;
-
- /* FIXME: need to have it based on encryption and signing too */
- if (po->valid->sign.status != 0)
- icon_name = smime_sign_table[po->valid->sign.status].icon;
- else
- icon_name = smime_encrypt_table[po->valid->encrypt.status].icon;
-
- icon = gtk_image_new_from_icon_name (
- icon_name, GTK_ICON_SIZE_LARGE_TOOLBAR);
- gtk_widget_show(icon);
-
- button = gtk_button_new();
- g_signal_connect(button, "clicked", G_CALLBACK(efhd_xpkcs7mime_validity_clicked), pobject);
-
- gtk_container_add((GtkContainer *)button, icon);
- gtk_widget_show(button);
- gtk_container_add((GtkContainer *)eb, button);
-
- return TRUE;
-}
-
-static void
-efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid)
-{
- /* Note: We call EMFormatClass directly, not EMFormatHTML, our parent */
- efhd_format_class->format_secure(emf, stream, part, valid);
-
- if (emf->valid == valid
- && (valid->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE
- || valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE)) {
- char *classid;
- struct _smime_pobject *pobj;
-
- camel_stream_printf (stream, "<table border=0 width=\"100%%\" cellpadding=3 cellspacing=0%s><tr>",
- smime_sign_colour[valid->sign.status]);
-
- classid = g_strdup_printf("smime:///em-format-html/%s/icon/signed", emf->part_id->str);
- pobj = (struct _smime_pobject *)em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(*pobj), classid, part, efhd_xpkcs7mime_button);
- pobj->valid = camel_cipher_validity_clone(valid);
- pobj->object.free = efhd_xpkcs7mime_free;
- camel_stream_printf(stream, "<td valign=center><object classid=\"%s\"></object></td><td width=100%% valign=center>", classid);
- g_free(classid);
- if (valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) {
- camel_stream_printf (stream, "%s", _(smime_sign_table[valid->sign.status].shortdesc));
- }
-
- if (valid->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) {
- if (valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE) {
- camel_stream_printf (stream, "<br>");
- }
- camel_stream_printf (stream, "%s", _(smime_encrypt_table[valid->encrypt.status].shortdesc));
- }
-
- camel_stream_printf(stream, "</td></tr></table>");
- }
-}
-
static void
efhd_image(EMFormatHTML *efh, CamelStream *stream, CamelMimePart *part, EMFormatHandler *handle)
{
@@ -1417,27 +1191,6 @@ efhd_builtin_init(EMFormatHTMLDisplayClass *efhc)
em_format_class_add_handler((EMFormatClass *)efhc, &type_builtin_table[i]);
}
-static const EMFormatHandler *
-efhd_find_handler(EMFormat *emf, const char *mime_type)
-{
- return ((EMFormatClass *) efhd_parent)->find_handler (emf, mime_type);
-}
-
-static void efhd_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMimeMessage *msg, EMFormat *src)
-{
- EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) emf;
-
- if (emf != src) {
- if (src)
- efhd->priv->show_bar = ((EMFormatHTMLDisplay *)src)->priv->show_bar;
- else
- efhd->priv->show_bar = FALSE;
- ((EMFormatHTML *) emf)->header_wrap_flags = 0;
- }
-
- ((EMFormatClass *)efhd_parent)->format_clone(emf, folder, uid, msg, src);
-}
-
static void
efhd_write_image(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri)
{
@@ -1449,7 +1202,8 @@ efhd_write_image(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri)
camel_stream_close(stream);
}
-static void efhd_message_prefix(EMFormat *emf, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info)
+static void
+efhd_message_prefix(EMFormat *emf, CamelStream *stream, CamelMimePart *part, EMFormatHandler *info)
{
const char *flag, *comp, *due;
time_t date;
@@ -1508,17 +1262,6 @@ static void efhd_message_prefix(EMFormat *emf, CamelStream *stream, CamelMimePar
camel_stream_printf(stream, "</td></tr></table>");
}
-/* TODO: if these aren't going to do anything should remove */
-static void efhd_format_error(EMFormat *emf, CamelStream *stream, const char *txt)
-{
- ((EMFormatClass *)efhd_parent)->format_error(emf, stream, txt);
-}
-
-static void efhd_format_source(EMFormat *emf, CamelStream *stream, CamelMimePart *part)
-{
- ((EMFormatClass *)efhd_parent)->format_source(emf, stream, part);
-}
-
/* ********************************************************************** */
/* Checks on the widget whether it can be processed, based on the state of EMFormatHTML.
@@ -2381,7 +2124,7 @@ efhd_message_update_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part,
EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) emf;
const char *classid = "attachment-bar-refresh";
- if (efhd->nobar || efhd->priv->updated)
+ if (efhd->priv->updated)
return;
efhd->priv->files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@@ -2397,7 +2140,7 @@ efhd_message_add_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part, co
EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) emf;
const char *classid = "attachment-bar";
- if (efhd->nobar || efhd->priv->files)
+ if (efhd->priv->files)
return;
efhd->priv->files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@@ -2408,56 +2151,6 @@ efhd_message_add_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part, co
}
static void
-efhd_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const char *mime_type, const EMFormatHandler *handle)
-{
- char *classid, *text, *html;
- struct _attach_puri *info;
-
- classid = g_strdup_printf("attachment%s", emf->part_id->str);
- 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_id, info->puri.part, handle);
- info->snoop_mime_type = emf->snoop_mime_type;
- info->attachment = e_attachment_new_from_mime_part (info->puri.part);
- e_attachment_bar_create_attachment_cache (info->attachment);
-
- if (emf->valid) {
- info->sign = emf->valid->sign.status;
- info->encrypt = emf->valid->encrypt.status;
- }
-
- camel_stream_write_string(stream,
- EM_FORMAT_HTML_VPAD
- "<table cellspacing=0 cellpadding=0><tr><td>"
- "<table width=10 cellspacing=0 cellpadding=0>"
- "<tr><td></td></tr></table></td>");
-
- camel_stream_printf(stream, "<td><object classid=\"%s\"></object></td>", classid);
-
- camel_stream_write_string(stream,
- "<td><table width=3 cellspacing=0 cellpadding=0>"
- "<tr><td></td></tr></table></td><td><font size=-1>");
-
- /* output some info about it */
- /* FIXME: should we look up mime_type from object again? */
- 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>\n"
- EM_FORMAT_HTML_VPAD);
-
- if (handle && info->shown)
- handle->handler(emf, stream, part, handle);
-
- g_free(classid);
-}
-
-static void
efhd_optional_button_show (GtkWidget *widget, GtkWidget *w)
{
GtkWidget *label = g_object_get_data (G_OBJECT (widget), "text-label");
@@ -2570,49 +2263,3 @@ efhd_attachment_optional(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPOb
return TRUE;
}
-static void
-efhd_format_optional(EMFormat *emf, CamelStream *fstream, CamelMimePart *part, CamelStream *mstream)
-{
- char *classid, *html;
- struct _attach_puri *info;
- CamelStream *stream;
-
- if (CAMEL_IS_STREAM_FILTER (fstream) && ((CamelStreamFilter *) fstream)->source)
- stream = ((CamelStreamFilter *) fstream)->source;
- else
- stream = fstream;
-
- classid = g_strdup_printf("optional%s", emf->part_id->str);
- 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_optional);
- info->handle = em_format_find_handler(emf, "text/plain");
- info->shown = FALSE;
- info->snoop_mime_type = "text/plain";
- info->attachment = e_attachment_new_from_mime_part (info->puri.part);
- info->mstream = (CamelStreamMem *)mstream;
- if (emf->valid) {
- info->sign = emf->valid->sign.status;
- info->encrypt = emf->valid->encrypt.status;
- }
-
- camel_stream_write_string(stream,
- EM_FORMAT_HTML_VPAD
- "<table cellspacing=0 cellpadding=0><tr><td><h3><font size=-1 color=red>");
-
- html = camel_text_to_html(_("Evolution cannot render this email as it is too large to process. You can view it unformatted or with an external text editor."), ((EMFormatHTML *)emf)->text_html_flags & CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS, 0);
- camel_stream_write_string(stream, html);
- camel_stream_write_string(stream,
- "</font></h3></td></tr></table>\n");
- camel_stream_write_string(stream,
- "<table cellspacing=0 cellpadding=0>"
- "<tr>");
- camel_stream_printf(stream, "<td><object classid=\"%s\"></object></td></tr></table>", classid);
-
- g_free(html);
-
- camel_stream_write_string(stream,
-/* "</font></h2></td></tr></table>\n" */
- EM_FORMAT_HTML_VPAD);
-
- g_free(classid);
-}
diff --git a/mail/em-format-html-display.h b/mail/em-format-html-display.h
index b659994114..a74d87207b 100644
--- a/mail/em-format-html-display.h
+++ b/mail/em-format-html-display.h
@@ -25,8 +25,9 @@
#ifndef EM_FORMAT_HTML_DISPLAY_H
#define EM_FORMAT_HTML_DISPLAY_H
-#include "mail/em-format-html.h"
-#include "widgets/misc/e-attachment-bar.h"
+#include <camel/camel-mime-part.h>
+#include <mail/em-format-html.h>
+#include <widgets/misc/e-attachment-bar.h>
/* Standard GObject macros */
#define EM_TYPE_FORMAT_HTML_DISPLAY \
@@ -58,41 +59,32 @@ typedef struct _EMFormatHTMLDisplay EMFormatHTMLDisplay;
typedef struct _EMFormatHTMLDisplayClass EMFormatHTMLDisplayClass;
typedef struct _EMFormatHTMLDisplayPrivate EMFormatHTMLDisplayPrivate;
-struct _CamelMimePart;
-
struct _EMFormatHTMLDisplay {
EMFormatHTML parent;
EMFormatHTMLDisplayPrivate *priv;
struct _ESearchingTokenizer *search_tok;
-
- unsigned int nobar:1;
};
struct _EMFormatHTMLDisplayClass {
EMFormatHTMLClass parent_class;
/* a link clicked normally */
- void (*link_clicked)(EMFormatHTMLDisplay *efhd, const char *uri);
+ void (*link_clicked) (EMFormatHTMLDisplay *efhd,
+ const gchar *uri);
/* a part or a link button pressed event */
- int (*popup_event)(EMFormatHTMLDisplay *efhd, GdkEventButton *event, const char *uri, struct _CamelMimePart *part);
+ gint (*popup_event) (EMFormatHTMLDisplay *efhd,
+ GdkEventButton *event,
+ const gchar *uri,
+ CamelMimePart *part);
/* the mouse is over a link */
- void (*on_url)(EMFormatHTMLDisplay *efhd, const char *uri);
+ void (*on_url) (EMFormatHTMLDisplay *efhd,
+ const gchar *uri);
};
GType em_format_html_display_get_type (void);
EMFormatHTMLDisplay *
em_format_html_display_new (void);
-gboolean em_format_html_display_get_animate
- (EMFormatHTMLDisplay *efhd);
-void em_format_html_display_set_animate
- (EMFormatHTMLDisplay *efhd,
- gboolean animate);
-gboolean em_format_html_display_get_caret_mode
- (EMFormatHTMLDisplay *efhd);
-void em_format_html_display_set_caret_mode
- (EMFormatHTMLDisplay *efhd,
- gboolean caret_mode);
void em_format_html_display_set_search
(EMFormatHTMLDisplay *efhd,
int type,
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);
-}
diff --git a/mail/em-format-html.h b/mail/em-format-html.h
index 33d60ae19a..d35556316a 100644
--- a/mail/em-format-html.h
+++ b/mail/em-format-html.h
@@ -22,7 +22,7 @@
*/
/*
- Concrete class for formatting mails to html
+ Abstract class for formatting mails to html
*/
#ifndef EM_FORMAT_HTML_H
@@ -226,10 +226,11 @@ struct _EMFormatHTML {
struct _EMFormatHTMLClass {
EMFormatClass parent_class;
+
+ GType html_widget_type;
};
GType em_format_html_get_type (void);
-EMFormatHTML * em_format_html_new (void);
void em_format_html_load_images (EMFormatHTML *efh);
void em_format_html_get_color (EMFormatHTML *efh,
EMFormatHTMLColorType type,
diff --git a/mail/em-html-stream.c b/mail/em-html-stream.c
index daa81d356d..096e1c9aa5 100644
--- a/mail/em-html-stream.c
+++ b/mail/em-html-stream.c
@@ -27,84 +27,39 @@
#endif
#include <stdio.h>
-#include <gtkhtml/gtkhtml.h>
-#include <gtkhtml/gtkhtml-stream.h>
#include <gtk/gtk.h>
#include "em-html-stream.h"
#define d(x)
-static void em_html_stream_class_init (EMHTMLStreamClass *klass);
-static void em_html_stream_init (CamelObject *object);
-static void em_html_stream_finalize (CamelObject *object);
-
-static ssize_t emhs_sync_write(CamelStream *stream, const char *buffer, size_t n);
-static int emhs_sync_close(CamelStream *stream);
-static int emhs_sync_flush(CamelStream *stream);
-
static EMSyncStreamClass *parent_class = NULL;
-CamelType
-em_html_stream_get_type (void)
-{
- static CamelType type = CAMEL_INVALID_TYPE;
-
- if (type == CAMEL_INVALID_TYPE) {
- parent_class = (EMSyncStreamClass *)em_sync_stream_get_type();
- type = camel_type_register (em_sync_stream_get_type(),
- "EMHTMLStream",
- sizeof (EMHTMLStream),
- sizeof (EMHTMLStreamClass),
- (CamelObjectClassInitFunc) em_html_stream_class_init,
- NULL,
- (CamelObjectInitFunc) em_html_stream_init,
- (CamelObjectFinalizeFunc) em_html_stream_finalize);
- }
-
- return type;
-}
-
-static void
-em_html_stream_class_init (EMHTMLStreamClass *klass)
-{
- ((EMSyncStreamClass *)klass)->sync_write = emhs_sync_write;
- ((EMSyncStreamClass *)klass)->sync_flush = emhs_sync_flush;
- ((EMSyncStreamClass *)klass)->sync_close = emhs_sync_close;
-}
-
-static void
-em_html_stream_init (CamelObject *object)
-{
- /*EMHTMLStream *emhs = (EMHTMLStream *)object;*/
-}
-
static void
-emhs_cleanup(EMHTMLStream *emhs)
+emhs_cleanup (EMHTMLStream *emhs)
{
if (emhs->sync.cancel && emhs->html_stream)
- gtk_html_stream_close (emhs->html_stream, GTK_HTML_STREAM_ERROR);
+ gtk_html_stream_close (
+ emhs->html_stream, GTK_HTML_STREAM_ERROR);
+
emhs->html_stream = NULL;
emhs->sync.cancel = TRUE;
- g_signal_handler_disconnect(emhs->html, emhs->destroy_id);
- g_object_unref(emhs->html);
+ g_signal_handler_disconnect (emhs->html, emhs->destroy_id);
+ g_object_unref (emhs->html);
emhs->html = NULL;
}
static void
-em_html_stream_finalize (CamelObject *object)
+emhs_gtkhtml_destroy (GtkHTML *html,
+ EMHTMLStream *emhs)
{
- EMHTMLStream *emhs = (EMHTMLStream *)object;
-
- d(printf("%p: finalising stream\n", object));
- if (emhs->html_stream) {
- d(printf("%p: html stream still open - error\n", object));
- /* set 'in finalise' flag */
- camel_stream_close((CamelStream *)emhs);
- }
+ emhs->sync.cancel = TRUE;
+ emhs_cleanup (emhs);
}
static ssize_t
-emhs_sync_write(CamelStream *stream, const char *buffer, size_t n)
+emhs_sync_write (CamelStream *stream,
+ const char *buffer,
+ size_t n)
{
EMHTMLStream *emhs = EM_HTML_STREAM (stream);
@@ -112,9 +67,10 @@ emhs_sync_write(CamelStream *stream, const char *buffer, size_t n)
return -1;
if (emhs->html_stream == NULL)
- emhs->html_stream = gtk_html_begin_full (emhs->html, NULL, NULL, emhs->flags);
+ emhs->html_stream = gtk_html_begin_full (
+ emhs->html, NULL, NULL, emhs->flags);
- gtk_html_stream_write(emhs->html_stream, buffer, n);
+ gtk_html_stream_write (emhs->html_stream, buffer, n);
return (ssize_t) n;
}
@@ -133,48 +89,93 @@ emhs_sync_flush(CamelStream *stream)
}
static int
-emhs_sync_close(CamelStream *stream)
+emhs_sync_close (CamelStream *stream)
{
EMHTMLStream *emhs = (EMHTMLStream *)stream;
if (emhs->html_stream == NULL)
return -1;
- gtk_html_stream_close(emhs->html_stream, GTK_HTML_STREAM_OK);
- emhs_cleanup(emhs);
+ gtk_html_stream_close (emhs->html_stream, GTK_HTML_STREAM_OK);
+ emhs_cleanup (emhs);
return 0;
}
static void
-emhs_gtkhtml_destroy(struct _GtkHTML *html, EMHTMLStream *emhs)
+em_html_stream_class_init (EMHTMLStreamClass *class)
{
- d(printf("%p: emhs gtkhtml destroy\n", emhs));
- emhs->sync.cancel = TRUE;
- emhs_cleanup(emhs);
+ EMSyncStreamClass *sync_stream_class;
+
+ parent_class = (EMSyncStreamClass *)em_sync_stream_get_type();
+
+ sync_stream_class = EM_SYNC_STREAM_CLASS (class);
+ sync_stream_class->sync_write = emhs_sync_write;
+ sync_stream_class->sync_flush = emhs_sync_flush;
+ sync_stream_class->sync_close = emhs_sync_close;
+}
+
+static void
+em_html_stream_init (EMHTMLStream *emhs)
+{
+}
+
+static void
+em_html_stream_finalize (EMHTMLStream *emhs)
+{
+ if (emhs->html_stream) {
+ /* set 'in finalise' flag */
+ camel_stream_close (CAMEL_STREAM (emhs));
+ }
+}
+
+CamelType
+em_html_stream_get_type (void)
+{
+ static CamelType type = CAMEL_INVALID_TYPE;
+
+ if (G_UNLIKELY (type == CAMEL_INVALID_TYPE)) {
+ type = camel_type_register (
+ em_sync_stream_get_type(),
+ "EMHTMLStream",
+ sizeof (EMHTMLStream),
+ sizeof (EMHTMLStreamClass),
+ (CamelObjectClassInitFunc) em_html_stream_class_init,
+ NULL,
+ (CamelObjectInitFunc) em_html_stream_init,
+ (CamelObjectFinalizeFunc) em_html_stream_finalize);
+ }
+
+ return type;
}
/* TODO: Could pass NULL for html_stream, and do a gtk_html_begin
on first data -> less flashing */
CamelStream *
-em_html_stream_new(struct _GtkHTML *html, struct _GtkHTMLStream *html_stream)
+em_html_stream_new (GtkHTML *html,
+ GtkHTMLStream *html_stream)
{
EMHTMLStream *new;
+ g_return_val_if_fail (GTK_IS_HTML (html), NULL);
+
new = EM_HTML_STREAM (camel_object_new (EM_HTML_STREAM_TYPE));
new->html_stream = html_stream;
- new->html = html;
+ new->html = g_object_ref (html);
new->flags = 0;
- g_object_ref(html);
- new->destroy_id = g_signal_connect(html, "destroy", G_CALLBACK(emhs_gtkhtml_destroy), new);
+ new->destroy_id = g_signal_connect (
+ html, "destroy",
+ G_CALLBACK (emhs_gtkhtml_destroy), new);
- em_sync_stream_set_buffer_size(&new->sync, 8192);
+ em_sync_stream_set_buffer_size (&new->sync, 8192);
- return (CamelStream *)new;
+ return CAMEL_STREAM (new);
}
void
em_html_stream_set_flags (EMHTMLStream *emhs, GtkHTMLBeginFlags flags)
{
+ g_return_if_fail (EM_IS_HTML_STREAM (emhs));
+
emhs->flags = flags;
}
diff --git a/mail/em-html-stream.h b/mail/em-html-stream.h
index a8eabdda55..674cc590af 100644
--- a/mail/em-html-stream.h
+++ b/mail/em-html-stream.h
@@ -24,44 +24,47 @@
#ifndef EM_HTML_STREAM_H
#define EM_HTML_STREAM_H
-#ifdef __cplusplus
-extern "C" {
-#pragma }
-#endif /* __cplusplus */
+#include <gtkhtml/gtkhtml.h>
+#include <gtkhtml/gtkhtml-stream.h>
+#include <mail/em-sync-stream.h>
-#define EM_HTML_STREAM_TYPE (em_html_stream_get_type ())
-#define EM_HTML_STREAM(obj) (CAMEL_CHECK_CAST((obj), EM_HTML_STREAM_TYPE, EMHTMLStream))
-#define EM_HTML_STREAM_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), EM_HTML_STREAM_TYPE, EMHTMLStreamClass))
-#define EM_IS_HTML_STREAM(o) (CAMEL_CHECK_TYPE((o), EM_HTML_STREAM_TYPE))
+#define EM_HTML_STREAM_TYPE \
+ (em_html_stream_get_type ())
+#define EM_HTML_STREAM(obj) \
+ (CAMEL_CHECK_CAST \
+ ((obj), EM_HTML_STREAM_TYPE, EMHTMLStream))
+#define EM_HTML_STREAM_CLASS(cls) \
+ (CAMEL_CHECK_CLASS_CAST \
+ ((cls), EM_HTML_STREAM_TYPE, EMHTMLStreamClass))
+#define EM_IS_HTML_STREAM(obj) \
+ (CAMEL_CHECK_TYPE \
+ ((obj), EM_HTML_STREAM_TYPE))
-struct _GtkHTML;
-struct _GtkHTMLStream;
+G_BEGIN_DECLS
-#include "mail/em-sync-stream.h"
+typedef struct _EMHTMLStream EMHTMLStream;
+typedef struct _EMHTMLStreamClass EMHTMLStreamClass;
-typedef struct _EMHTMLStream {
+struct _EMHTMLStream {
EMSyncStream sync;
guint destroy_id;
- struct _GtkHTML *html;
- struct _GtkHTMLStream *html_stream;
+ GtkHTML *html;
+ GtkHTMLStream *html_stream;
GtkHTMLBeginFlags flags;
-} EMHTMLStream;
+};
-typedef struct {
+struct _EMHTMLStreamClass {
EMSyncStreamClass parent_class;
-} EMHTMLStreamClass;
+};
+CamelType em_html_stream_get_type (void);
+CamelStream * em_html_stream_new (GtkHTML *html,
+ GtkHTMLStream *html_stream);
+void em_html_stream_set_flags (EMHTMLStream *emhs,
+ GtkHTMLBeginFlags flags);
-CamelType em_html_stream_get_type (void);
-
-/* the html_stream is closed when we are finalised (with an error), or closed (ok) */
-CamelStream *em_html_stream_new(struct _GtkHTML *html, struct _GtkHTMLStream *html_stream);
-void em_html_stream_set_flags (EMHTMLStream *emhs, GtkHTMLBeginFlags flags);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_END_DECLS
#endif /* EM_HTML_STREAM_H */