/* internal api */
static TnyMimePart *get_part (ModestGtkhtmlMimePartView *self);
-static void set_html_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part);
+static void set_html_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part, const gchar *encoding);
static void set_text_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part);
static void set_empty_part (ModestGtkhtmlMimePartView *self);
static void set_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part);
enum {
STOP_STREAMS_SIGNAL,
+ LIMIT_ERROR_SIGNAL,
LAST_SIGNAL
};
gtk_binding_entry_skip (binding_set, GDK_End, 0);
gtk_binding_entry_skip (binding_set, GDK_KP_Home, 0);
gtk_binding_entry_skip (binding_set, GDK_KP_End, 0);
-
+
g_type_class_add_private (gobject_class, sizeof(ModestGtkhtmlMimePartViewPrivate));
signals[STOP_STREAMS_SIGNAL] =
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ signals[LIMIT_ERROR_SIGNAL] =
+ g_signal_new ("limit-error",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (ModestGtkhtmlMimePartViewClass,limit_error),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
}
-static void
+static void
modest_gtkhtml_mime_part_view_init (ModestGtkhtmlMimePartView *self)
{
ModestGtkhtmlMimePartViewPrivate *priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
gtk_html_set_caret_mode (GTK_HTML(self), FALSE);
gtk_html_set_blocking (GTK_HTML(self), TRUE);
gtk_html_set_images_blocking (GTK_HTML(self), TRUE);
- gtk_container_set_border_width (GTK_CONTAINER (self), MODEST_MARGIN_DEFAULT);
+ /* We don't need this for Hildon2 as this widget will be most
+ likely inside pannable area */
+#ifndef MODEST_TOOLKIT_HILDON2
+ gtk_html_set_auto_panning (GTK_HTML (self), TRUE);
+#endif
+
+#ifdef MODEST_TOOLKIT_HILDON2
+#ifdef HAVE_GTK_HTML_SET_MAX_IMAGE_SIZE
+ /* We set a maximum width of a bit less than the width of the screen, and a
+ maximum height of 2 times the full size of the window. Should be enough */
+ gtk_html_set_max_image_size (GTK_HTML (self), 720, 880);
+#endif
+#ifdef HAVE_GTK_HTML_SET_ALLOW_DND
+ gtk_html_set_allow_dnd (GTK_HTML(self), FALSE);
+#endif
+#endif
+
+#ifdef HAVE_GTK_HTML_SET_DEFAULT_ENGINE
+ /* Enable Content type handling */
+ gtk_html_set_default_engine (GTK_HTML (self), TRUE);
+#endif
gdk_color_parse ("#fff", &base);
gdk_color_parse ("#000", &text);
return result;
}
-typedef struct {
- gpointer buffer;
- GtkHTML *html;
- GtkHTMLStream *stream;
-} ImageFetcherInfo;
-
static gboolean
on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream,
ModestGtkhtmlMimePartView *self)
if (!priv->view_images)
priv->has_external_images = TRUE;
}
-
+
tny_stream = TNY_STREAM (modest_tny_stream_gtkhtml_new (stream, GTK_HTML (widget)));
g_signal_emit_by_name (MODEST_MIME_PART_VIEW (self), "fetch-url", uri, tny_stream, &result);
g_object_unref (tny_stream);
}
/* INTERNAL API */
+static void
+decode_to_stream_cb (TnyMimePart *self,
+ gboolean cancelled,
+ TnyStream *stream,
+ GError *err,
+ gpointer user_data)
+{
+ ModestGtkhtmlMimePartView *view = (ModestGtkhtmlMimePartView *) user_data;
+
+ if (MODEST_IS_STREAM_TEXT_TO_HTML (stream)) {
+ if (tny_stream_write (stream, "\n", 1) == -1) {
+ g_warning ("failed to write CR in %s", __FUNCTION__);
+ }
+ if (modest_stream_text_to_html_limit_reached (MODEST_STREAM_TEXT_TO_HTML (stream))) {
+ g_signal_emit (G_OBJECT (view), signals[LIMIT_ERROR_SIGNAL], 0);
+ }
+ tny_stream_reset (stream);
+ } else {
+ if (modest_tny_stream_gtkhtml_limit_reached (MODEST_TNY_STREAM_GTKHTML (stream))) {
+ g_signal_emit (G_OBJECT (view), signals[LIMIT_ERROR_SIGNAL], 0);
+ }
+ }
+ tny_stream_close (stream);
+}
static void
-set_html_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
+set_html_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part, const gchar *encoding)
{
GtkHTMLStream *gtkhtml_stream;
- TnyStream *tny_stream;
-
+ TnyStream *tny_stream;
+ gchar *content_type;
+
g_return_if_fail (self);
g_return_if_fail (part);
g_signal_emit (G_OBJECT (self), signals[STOP_STREAMS_SIGNAL], 0);
-
- gtkhtml_stream = gtk_html_begin(GTK_HTML(self));
+
+ content_type = g_strdup_printf ("text/html; charset=%s", encoding);
+ gtkhtml_stream = gtk_html_begin_full(GTK_HTML(self), NULL, content_type, 0);
+ g_free (content_type);
tny_stream = TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream, GTK_HTML (self)));
+ modest_tny_stream_gtkhtml_set_max_size (MODEST_TNY_STREAM_GTKHTML (tny_stream), 128*1024);
tny_stream_reset (tny_stream);
- tny_mime_part_decode_to_stream ((TnyMimePart*)part, tny_stream, NULL);
- tny_stream_close (tny_stream);
- g_object_unref (G_OBJECT(tny_stream));
+ tny_mime_part_decode_to_stream_async (TNY_MIME_PART (part),
+ tny_stream, decode_to_stream_cb,
+ NULL, self);
+ g_object_unref (tny_stream);
}
static void
{
TnyStream* text_to_html_stream, *tny_stream;
GtkHTMLStream *gtkhtml_stream;
-
+
g_return_if_fail (self);
g_return_if_fail (part);
g_signal_emit (G_OBJECT (self), signals[STOP_STREAMS_SIGNAL], 0);
-
- gtkhtml_stream = gtk_html_begin(GTK_HTML(self));
+
+ gtkhtml_stream = gtk_html_begin(GTK_HTML(self));
tny_stream = TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream, GTK_HTML (self)));
+ modest_tny_stream_gtkhtml_set_max_size (MODEST_TNY_STREAM_GTKHTML (tny_stream), 128*1024);
text_to_html_stream = TNY_STREAM (modest_stream_text_to_html_new (tny_stream));
- modest_stream_text_to_html_set_linkify_limit (MODEST_STREAM_TEXT_TO_HTML (text_to_html_stream), 64*1024);
- modest_stream_text_to_html_set_full_limit (MODEST_STREAM_TEXT_TO_HTML (text_to_html_stream), 640*1024);
-
- // FIXME: tinymail
- tny_mime_part_decode_to_stream ((TnyMimePart*)part, text_to_html_stream, NULL);
- tny_stream_write (text_to_html_stream, "\n", 1);
- tny_stream_reset (text_to_html_stream);
- tny_stream_close (text_to_html_stream);
-
+ modest_stream_text_to_html_set_linkify_limit (MODEST_STREAM_TEXT_TO_HTML (text_to_html_stream),
+ 64*1024);
+ modest_stream_text_to_html_set_full_limit (MODEST_STREAM_TEXT_TO_HTML (text_to_html_stream),
+ 128*1024);
+ modest_stream_text_to_html_set_line_limit (MODEST_STREAM_TEXT_TO_HTML (text_to_html_stream),
+ 1024);
+
+ tny_mime_part_decode_to_stream_async (TNY_MIME_PART (part),
+ text_to_html_stream, decode_to_stream_cb,
+ NULL, self);
+
g_object_unref (G_OBJECT(text_to_html_stream));
g_object_unref (G_OBJECT(tny_stream));
- /* gtk_html_stream_destroy (gtkhtml_stream); */
}
static void
g_return_if_fail (self);
g_signal_emit (G_OBJECT (self), signals[STOP_STREAMS_SIGNAL], 0);
-
- gtk_html_load_from_string (GTK_HTML(self),
- "", 1);
+ gtk_html_load_from_string (GTK_HTML(self), "", 1);
}
static void
set_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
{
ModestGtkhtmlMimePartViewPrivate *priv;
+ gchar *header_content_type, *header_content_type_lower;
+ const gchar *tmp;
+ gchar *charset = NULL;
g_return_if_fail (self);
return;
}
+ header_content_type = modest_tny_mime_part_get_header_value (part, "Content-Type");
+ if (header_content_type) {
+ header_content_type = g_strstrip (header_content_type);
+ header_content_type_lower = g_ascii_strdown (header_content_type, -1);
+ } else {
+ header_content_type_lower = NULL;
+ }
+
+ if (header_content_type_lower) {
+ tmp = strstr (header_content_type_lower, "charset=");
+ if (tmp) {
+ const gchar *tmp2;
+ tmp = tmp + strlen ("charset=");
+
+ tmp2 = strstr (tmp, ";");
+ if (tmp2) {
+ charset = g_strndup (tmp, tmp2-tmp);
+ } else {
+ charset = g_strdup (tmp);
+ }
+ }
+ }
+
if (tny_mime_part_content_type_is (part, "text/html")) {
- set_html_part (self, part);
+ set_html_part (self, part, charset);
} else {
if (tny_mime_part_content_type_is (part, "message/rfc822")) {
- gchar *header_content_type, *header_content_type_lower;
- header_content_type = modest_tny_mime_part_get_header_value (part, "Content-Type");
if (header_content_type) {
- header_content_type = g_strstrip (header_content_type);
- header_content_type_lower = g_ascii_strdown (header_content_type, -1);
-
- if (!g_ascii_strcasecmp (header_content_type_lower, "text/html"))
- set_html_part (self, part);
+ if (g_str_has_prefix (header_content_type_lower, "text/html"))
+ set_html_part (self, part, charset);
else
set_text_part (self, part);
- g_free (header_content_type_lower);
- g_free (header_content_type);
} else {
set_text_part (self, part);
}
set_text_part (self, part);
}
}
+ g_free (header_content_type_lower);
+ g_free (header_content_type);
}