Split the interactive parts of the message display out of EMFormatHTMLDisplay
to a new GtkHTML subclass named EMailDisplay, and have EMFormatHTML create an instance of that. EMailDisplay will handle link clicking, mousing over URIs, popup menus, and interactive search. This makes EMFormatHTMLDisplay and EMailReader more lightweight. Clean up more of the EMFormat stack. svn path=/branches/kill-bonobo/; revision=37346
This commit is contained in:
@ -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 \
|
||||
|
||||
@ -217,6 +217,23 @@ mail_browser_message_selected_cb (EMailBrowser *browser,
|
||||
camel_folder_free_message_info (message_list->folder, info);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
627
mail/e-mail-display.c
Normal file
627
mail/e-mail-display.c
Normal file
@ -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");
|
||||
}
|
||||
83
mail/e-mail-display.h
Normal file
83
mail/e-mail-display.h
Normal file
@ -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 */
|
||||
@ -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,14 +2116,10 @@ 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);
|
||||
|
||||
@ -88,6 +88,19 @@ mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view)
|
||||
e_mail_shell_view_update_sidebar (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)
|
||||
{
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||
|
||||
@ -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)
|
||||
{
|
||||
@ -370,6 +589,143 @@ efh_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (parent_class)->finalize (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)
|
||||
{
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user