aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
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 */