* Merged patch for bug 84605 from PE2 branch
[modest] / src / widgets / modest-gtkhtml-mime-part-view.c
index f167c9a..28031b9 100644 (file)
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <config.h>
 #include <widgets/modest-gtkhtml-mime-part-view.h>
 #include <string.h>
 #include <gtkhtml/gtkhtml-stream.h>
 #include <gtkhtml/gtkhtml-search.h>
 #include <tny-stream.h>
 #include <tny-mime-part-view.h>
-#include <tny-gtk-text-buffer-stream.h>
+#include <modest-stream-text-to-html.h>
 #include <modest-text-utils.h>
+#include <modest-conf.h>
+#include <modest-runtime.h>
 #include <widgets/modest-mime-part-view.h>
 #include <widgets/modest-zoomable.h>
 #include <widgets/modest-tny-stream-gtkhtml.h>
+#include <libgnomevfs/gnome-vfs.h>
 
 /* gobject structure methods */
 static void    modest_gtkhtml_mime_part_view_class_init (ModestGtkhtmlMimePartViewClass *klass);
@@ -257,6 +261,70 @@ on_url (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self)
        return result;
 }
 
+typedef struct {
+       gpointer buffer;
+       GtkHTML *html;
+       GtkHTMLStream *stream;
+       gboolean html_finalized;
+} ImageFetcherInfo;
+
+static void
+html_finalized_notify (ImageFetcherInfo *ifinfo,
+                      GObject *destroyed)
+{
+       ifinfo->html_finalized = TRUE;
+}
+
+static void
+image_fetcher_close (GnomeVFSAsyncHandle *handle,
+                    GnomeVFSResult result,
+                    gpointer data)
+{
+}
+
+static void
+image_fetcher_read (GnomeVFSAsyncHandle *handle,
+                   GnomeVFSResult result,
+                   gpointer buffer,
+                   GnomeVFSFileSize bytes_requested,
+                   GnomeVFSFileSize bytes_read,
+                   ImageFetcherInfo *ifinfo)
+{
+
+       if (ifinfo->html_finalized || result != GNOME_VFS_OK) {
+               gnome_vfs_async_close (handle, (GnomeVFSAsyncCloseCallback) image_fetcher_close, (gpointer) NULL);
+               if (!ifinfo->html_finalized) {
+                       gtk_html_stream_close (ifinfo->stream, GTK_HTML_STREAM_OK);
+                       g_object_weak_unref ((GObject *) ifinfo->html, (GWeakNotify) html_finalized_notify, (gpointer) ifinfo);
+               }
+               g_slice_free1 (128, ifinfo->buffer);
+               g_slice_free (ImageFetcherInfo, ifinfo);
+               return;
+       }
+       gtk_html_stream_write (ifinfo->stream, buffer, bytes_read);
+       gnome_vfs_async_read (handle, ifinfo->buffer, 128, 
+                             (GnomeVFSAsyncReadCallback)image_fetcher_read, ifinfo);
+       return;
+}
+
+static void
+image_fetcher_open (GnomeVFSAsyncHandle *handle,
+                   GnomeVFSResult result,
+                   ImageFetcherInfo *ifinfo)
+{
+       if (!ifinfo->html_finalized && result == GNOME_VFS_OK) {
+               ifinfo->buffer = g_slice_alloc (128);
+               gnome_vfs_async_read (handle, ifinfo->buffer, 128, 
+                                     (GnomeVFSAsyncReadCallback) image_fetcher_read, ifinfo);
+       } else {
+               if (!ifinfo->html_finalized) {
+                       gtk_html_stream_close (ifinfo->stream, GTK_HTML_STREAM_OK);
+                       g_object_weak_unref ((GObject *) ifinfo->html, (GWeakNotify) html_finalized_notify, (gpointer) ifinfo);
+               }
+               g_slice_free (ImageFetcherInfo, ifinfo);
+       }
+}
+
 static gboolean
 on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream, 
                  ModestGtkhtmlMimePartView *self)
@@ -265,9 +333,26 @@ on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream,
        TnyStream *tny_stream;
        g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE);
 
+       if (g_str_has_prefix (uri, "http:") &&
+           modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_FETCH_HTML_EXTERNAL_IMAGES, NULL)) {
+               GnomeVFSAsyncHandle *handle;
+               ImageFetcherInfo *ifinfo;
+
+               ifinfo = g_slice_new (ImageFetcherInfo);
+               ifinfo->html_finalized = FALSE;
+               ifinfo->html = (GtkHTML *) self;
+               ifinfo->buffer = NULL;
+               ifinfo->stream = stream;
+               g_object_weak_ref ((GObject *) self, (GWeakNotify) html_finalized_notify, (gpointer) ifinfo);
+               gnome_vfs_async_open (&handle, uri, GNOME_VFS_OPEN_READ,
+                                     GNOME_VFS_PRIORITY_DEFAULT, 
+                                     (GnomeVFSAsyncOpenCallback) image_fetcher_open, ifinfo);
+               return FALSE;
+       }
+       
        tny_stream = TNY_STREAM (modest_tny_stream_gtkhtml_new (stream));
        g_signal_emit_by_name (MODEST_MIME_PART_VIEW (self), "fetch-url", uri, tny_stream, &result);
-       gtk_html_stream_close (stream, result?GTK_HTML_STREAM_OK:GTK_HTML_STREAM_ERROR);
+       tny_stream_close (tny_stream);
        g_object_unref (tny_stream);
        return result;
 }
@@ -288,51 +373,35 @@ set_html_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
        tny_stream     = TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream));
        tny_stream_reset (tny_stream);
 
-       tny_mime_part_decode_to_stream ((TnyMimePart*)part, 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));
-       
-       gtk_html_stream_destroy (gtkhtml_stream);
 }
 
 static void
 set_text_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
 {
-       GtkTextBuffer *buf;
-       GtkTextIter begin, end;
-       TnyStream* txt_stream, *tny_stream;
+       TnyStream* text_to_html_stream, *tny_stream;
        GtkHTMLStream *gtkhtml_stream;
-       gchar *txt;
-               
+       
        g_return_if_fail (self);
        g_return_if_fail (part);
 
-       buf            = gtk_text_buffer_new (NULL);
-       txt_stream     = TNY_STREAM(tny_gtk_text_buffer_stream_new (buf));
-               
-       tny_stream_reset (txt_stream);
-
        gtkhtml_stream = gtk_html_begin(GTK_HTML(self)); 
        tny_stream =  TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream));
+       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, txt_stream);
-       tny_stream_reset (txt_stream);          
-       
-       gtk_text_buffer_get_bounds (buf, &begin, &end);
-       txt = gtk_text_buffer_get_text (buf, &begin, &end, FALSE);
-       if (txt) {
-               gchar *html = modest_text_utils_convert_to_html (txt);
-               tny_stream_write (tny_stream, html, strlen(html));
-               tny_stream_reset (tny_stream);
-               g_free (txt);
-               g_free (html);
-       }
+       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);
        
+       g_object_unref (G_OBJECT(text_to_html_stream));
        g_object_unref (G_OBJECT(tny_stream));
-       g_object_unref (G_OBJECT(txt_stream));
-       g_object_unref (G_OBJECT(buf));
-       
-       gtk_html_stream_destroy (gtkhtml_stream);
+       /* gtk_html_stream_destroy (gtkhtml_stream); */
 }
 
 static void
@@ -461,8 +530,12 @@ get_selection_area (ModestGtkhtmlMimePartView *self,
                    gint *x, gint *y,
                    gint *width, gint *height)
 {
+#ifdef HAVE_GTK_HTML_GET_SELECTION_AREA
        gtk_html_get_selection_area (GTK_HTML (self), x, y, width, height);
        return TRUE;
+#else
+       return FALSE;
+#endif
 }
 
 
@@ -473,9 +546,9 @@ tny_mime_part_view_init (gpointer g, gpointer iface_data)
 {
        TnyMimePartViewIface *klass = (TnyMimePartViewIface *)g;
 
-       klass->get_part_func = modest_gtkhtml_mime_part_view_get_part;
-       klass->set_part_func = modest_gtkhtml_mime_part_view_set_part;
-       klass->clear_func = modest_gtkhtml_mime_part_view_clear;
+       klass->get_part = modest_gtkhtml_mime_part_view_get_part;
+       klass->set_part = modest_gtkhtml_mime_part_view_set_part;
+       klass->clear = modest_gtkhtml_mime_part_view_clear;
 
        return;
 }