Fix for bug NB#74675. Now we limit the retrieval size for texts shown,
authorJose Dapena Paz <jdapena@igalia.com>
Wed, 31 Oct 2007 13:11:38 +0000 (13:11 +0000)
committerJose Dapena Paz <jdapena@igalia.com>
Wed, 31 Oct 2007 13:11:38 +0000 (13:11 +0000)
and make the load much more efficient.
* src/modest-text-utils.[ch]:
        * Now convert_to_html_body method accepts two new parameters,
          one to enable disable linkify and other for processing char
          buffers with a size limit.
        * Now we provide the methods modest_text_utils_linkify_begin
          and modest_text_utils_linkify_end, to cache the regex patterns
          in processing of a big set of strings.
* src/widgets/modest-gtkhtml-mime-part-view.c:
        * Now we use the new ModestStreamTextToHtml decorator for
          gtkhtml stream instead of a big hack we did before to
          convert the text to html and send it to the gtkhtml widget.
        * Now we set the maximum size of text with hyperlinkify (64KB)
          and a maximum size of the text document to show (640KB).
* src/modest-stream-text-to-html.[ch], src/Makefile.am:
        * New stream implementation that proxies a write stream. With
          this all text written to this stream is converted to html and
          sent to the decorated stream.

pmo-trunk-r3607

src/Makefile.am
src/modest-stream-text-to-html.c [new file with mode: 0644]
src/modest-stream-text-to-html.h [new file with mode: 0644]
src/modest-text-utils.c
src/modest-text-utils.h
src/widgets/modest-gtkhtml-mime-part-view.c

index eae8f1e..e2b6483 100644 (file)
@@ -104,6 +104,8 @@ modest_SOURCES=\
        modest-tny-platform-factory.h \
        modest-tny-send-queue.c \
        modest-tny-send-queue.h \
+       modest-stream-text-to-html.c \
+       modest-stream-text-to-html.h \
        modest-ui-actions.c \
        modest-ui-actions.h \
        modest-ui-dimming-manager.c \
diff --git a/src/modest-stream-text-to-html.c b/src/modest-stream-text-to-html.c
new file mode 100644 (file)
index 0000000..4eee0f0
--- /dev/null
@@ -0,0 +1,333 @@
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/* modest-stream-text-to-html.c */
+
+#include "modest-stream-text-to-html.h"
+#include <tny-stream.h>
+#include <string.h>
+#include <modest-text-utils.h>
+
+#define HTML_PREFIX "<html><head>" \
+       "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf8\">" \
+       "</head>" \
+       "<body>"
+#define HTML_SUFFIX "</body></html>"
+
+
+/* 'private'/'protected' functions */
+static void  modest_stream_text_to_html_class_init   (ModestStreamTextToHtmlClass *klass);
+static void  modest_stream_text_to_html_init         (ModestStreamTextToHtml *obj);
+static void  modest_stream_text_to_html_finalize     (GObject *obj);
+
+static void  modest_stream_text_to_html_iface_init   (gpointer g_iface, gpointer iface_data);
+static gboolean write_line (TnyStream *self, const gchar *str, gboolean convert_to_html);
+
+
+typedef struct _ModestStreamTextToHtmlPrivate ModestStreamTextToHtmlPrivate;
+struct _ModestStreamTextToHtmlPrivate {
+       TnyStream *out_stream;
+       GString *line_buffer;
+       gboolean written_prefix;
+       gsize linkify_limit;
+       gsize full_limit;
+       gsize total_output;
+};
+#define MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
+                                                       MODEST_TYPE_STREAM_TEXT_TO_HTML, \
+                                                       ModestStreamTextToHtmlPrivate))
+/* globals */
+static GObjectClass *parent_class = NULL;
+
+GType
+modest_stream_text_to_html_get_type (void)
+{
+       static GType my_type = 0;
+       if (!my_type) {
+               static const GTypeInfo my_info = {
+                       sizeof(ModestStreamTextToHtmlClass),
+                       NULL,           /* base init */
+                       NULL,           /* base finalize */
+                       (GClassInitFunc) modest_stream_text_to_html_class_init,
+                       NULL,           /* class finalize */
+                       NULL,           /* class data */
+                       sizeof(ModestStreamTextToHtml),
+                       1,              /* n_preallocs */
+                       (GInstanceInitFunc) modest_stream_text_to_html_init,
+                       NULL
+               };
+
+               static const GInterfaceInfo iface_info = {
+                       (GInterfaceInitFunc) modest_stream_text_to_html_iface_init,
+                       NULL,         /* interface_finalize */
+                       NULL          /* interface_data */
+                };
+
+               my_type = g_type_register_static (G_TYPE_OBJECT,
+                                                 "ModestStreamTextToHtml",
+                                                 &my_info, 0);
+
+               g_type_add_interface_static (my_type, TNY_TYPE_STREAM,
+                                            &iface_info);
+
+       }
+       return my_type;
+}
+
+static void
+modest_stream_text_to_html_class_init (ModestStreamTextToHtmlClass *klass)
+{
+       GObjectClass *gobject_class;
+       gobject_class = (GObjectClass*) klass;
+
+       parent_class            = g_type_class_peek_parent (klass);
+       gobject_class->finalize = modest_stream_text_to_html_finalize;
+
+       g_type_class_add_private (gobject_class, sizeof(ModestStreamTextToHtmlPrivate));
+}
+
+static void
+modest_stream_text_to_html_init (ModestStreamTextToHtml *obj)
+{
+       ModestStreamTextToHtmlPrivate *priv;
+       priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE(obj);
+
+       priv->out_stream  = NULL;
+       priv->written_prefix = FALSE;
+       priv->line_buffer = NULL;
+       priv->linkify_limit = 0;
+       priv->full_limit = 0;
+       priv->total_output = 0;
+}
+
+static void
+modest_stream_text_to_html_finalize (GObject *obj)
+{
+       ModestStreamTextToHtmlPrivate *priv;
+
+       priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE(obj);
+       if (priv->out_stream)
+               g_object_unref (priv->out_stream);
+       priv->out_stream = NULL;
+       if (priv->line_buffer != NULL) {
+               g_string_free (priv->line_buffer, TRUE);
+       }
+}
+
+GObject*
+modest_stream_text_to_html_new (TnyStream *out_stream)
+{
+       GObject *obj;
+       ModestStreamTextToHtmlPrivate *priv;
+       
+       obj  = G_OBJECT(g_object_new(MODEST_TYPE_STREAM_TEXT_TO_HTML, NULL));
+       priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE(obj);
+
+       g_return_val_if_fail (out_stream, NULL);
+       
+       priv->out_stream = g_object_ref (out_stream);
+
+       return obj;
+}
+
+void        
+modest_stream_text_to_html_set_linkify_limit (ModestStreamTextToHtml *self, gssize limit)
+{
+       ModestStreamTextToHtmlPrivate *priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE (self);
+       priv->linkify_limit = limit;
+}
+
+void        
+modest_stream_text_to_html_set_full_limit (ModestStreamTextToHtml *self, gssize limit)
+{
+       ModestStreamTextToHtmlPrivate *priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE (self);
+       priv->full_limit = limit;
+}
+
+/* the rest are interface functions */
+
+
+static ssize_t
+text_to_html_read (TnyStream *self, char *buffer, size_t n)
+{
+       return -1; /* we cannot read */
+}
+
+static gboolean 
+write_line (TnyStream *self, const gchar *str, gboolean convert_to_html)
+{
+       ModestStreamTextToHtmlPrivate *priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE (self);
+       gchar *html_buffer;
+       gchar *offset;
+       gssize pending_bytes;
+       gboolean hyperlinkify = TRUE;
+
+       /* we only leave for full limit if we're converting to html, so that we
+          preserve the prefix and suffix */
+       if (convert_to_html && (priv->full_limit > 0) &&(priv->total_output > priv->full_limit))
+               return TRUE;
+       if ((priv->linkify_limit > 0) && (priv->total_output > priv->linkify_limit))
+               hyperlinkify = FALSE;
+       if (convert_to_html) {
+               html_buffer = modest_text_utils_convert_to_html_body (str, -1, hyperlinkify);
+       } else {
+               html_buffer = (gchar *) str;
+       }
+
+       pending_bytes = strlen (html_buffer);
+       priv->total_output += pending_bytes;
+       offset = html_buffer;
+
+       while (pending_bytes > 0) {
+               gssize written_bytes = 0;
+               written_bytes = tny_stream_write (priv->out_stream, offset, pending_bytes);
+               if (written_bytes < 0) {
+                       if (convert_to_html)
+                               g_free (html_buffer);
+                       return FALSE;
+               }
+               offset += written_bytes;
+               pending_bytes -= written_bytes;
+       }
+       if (convert_to_html)
+               g_free (html_buffer);
+
+       return TRUE;
+}
+
+static ssize_t
+text_to_html_write (TnyStream *self, const char *buffer, size_t n)
+{
+       
+       ModestStreamTextToHtmlPrivate *priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE (self);
+       gssize total = n;
+
+       modest_text_utils_hyperlinkify_begin ();
+       if ((!priv->written_prefix) && (n > 0)) {
+               if (!write_line (self, HTML_PREFIX, FALSE)) {
+                       modest_text_utils_hyperlinkify_end ();
+                       return -1;
+               }
+               priv->written_prefix = TRUE;
+       }
+
+       while (n > 0) {
+               gchar c = *buffer;
+               if (priv->line_buffer == NULL)
+                       priv->line_buffer = g_string_new (NULL);
+
+               priv->line_buffer = g_string_append_c (priv->line_buffer, c);
+               if (c == '\n') {
+                       if (tny_stream_flush (self) == -1) {
+                               modest_text_utils_hyperlinkify_end ();
+                               return -1;
+                       }
+               }
+               buffer ++;
+               n--;
+       }
+       modest_text_utils_hyperlinkify_end ();
+       return total;
+}
+
+       
+static gint
+text_to_html_flush (TnyStream *self)
+{
+       ModestStreamTextToHtmlPrivate *priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE (self);
+
+       if (priv->line_buffer != NULL) {
+               if (!write_line (self, priv->line_buffer->str, TRUE))
+                       return -1;
+               g_string_free (priv->line_buffer, TRUE);
+               priv->line_buffer = NULL;
+       }
+       return 0;
+}
+       
+
+static gint
+text_to_html_close (TnyStream *self)
+{
+       ModestStreamTextToHtmlPrivate *priv;
+       g_return_val_if_fail (self, 0);
+       priv = MODEST_STREAM_TEXT_TO_HTML_GET_PRIVATE(self);
+
+       tny_stream_flush (self);
+       if (!write_line (self, HTML_SUFFIX, FALSE))
+               return -1;
+       
+       tny_stream_close (priv->out_stream);
+       
+       priv->out_stream = NULL;
+
+       return 0;
+}
+
+
+static gboolean
+text_to_html_is_eos (TnyStream *self)
+{
+       return TRUE;
+}
+
+
+       
+static gint
+text_to_html_reset (TnyStream *self)
+{
+       return 0;
+}
+
+       
+static ssize_t
+text_to_html_write_to_stream (TnyStream *self, TnyStream *output)
+{
+       return 0;
+}
+
+
+static void
+modest_stream_text_to_html_iface_init (gpointer g_iface, gpointer iface_data)
+{
+        TnyStreamIface *klass;
+       
+       g_return_if_fail (g_iface);
+
+       klass = (TnyStreamIface*) g_iface;
+       
+        klass->read_func            = text_to_html_read;
+        klass->write_func           = text_to_html_write;
+        klass->flush_func           = text_to_html_flush;
+        klass->close_func           = text_to_html_close;
+       klass->is_eos_func          = text_to_html_is_eos;
+       klass->reset_func           = text_to_html_reset;
+       klass->write_to_stream_func = text_to_html_write_to_stream;
+}
diff --git a/src/modest-stream-text-to-html.h b/src/modest-stream-text-to-html.h
new file mode 100644 (file)
index 0000000..afb8700
--- /dev/null
@@ -0,0 +1,81 @@
+/* Copyright (c) 2007, Nokia Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Nokia Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/* modest-stream-text-to-html.h */
+
+#ifndef __MODEST_STREAM_TEXT_TO_HTML_H__
+#define __MODEST_STREAM_TEXT_TO_HTML_H__
+
+#include <glib-object.h>
+#include <gtkhtml/gtkhtml.h>
+#include <tny-stream.h>
+
+G_BEGIN_DECLS
+
+/* convenience macros */
+#define MODEST_TYPE_STREAM_TEXT_TO_HTML             (modest_stream_text_to_html_get_type())
+#define MODEST_STREAM_TEXT_TO_HTML(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_STREAM_TEXT_TO_HTML,ModestStreamTextToHtml))
+#define MODEST_STREAM_TEXT_TO_HTML_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_STREAM_TEXT_TO_HTML,ModestStreamTextToHtmlClass))
+#define MODEST_IS_STREAM_TEXT_TO_HTML(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_STREAM_TEXT_TO_HTML))
+#define MODEST_IS_STREAM_TEXT_TO_HTML_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_STREAM_TEXT_TO_HTML))
+#define MODEST_STREAM_TEXT_TO_HTML_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_STREAM_TEXT_TO_HTML,ModestStreamTextToHtmlClass))
+
+typedef struct _ModestStreamTextToHtml      ModestStreamTextToHtml;
+typedef struct _ModestStreamTextToHtmlClass ModestStreamTextToHtmlClass;
+
+struct _ModestStreamTextToHtml {
+       GObject parent;
+};
+
+struct _ModestStreamTextToHtmlClass {
+       GObjectClass parent_class;
+};
+
+GType       modest_stream_text_to_html_get_type    (void) G_GNUC_CONST;
+
+
+/**
+ * modest_stream_text_to_html_new:
+ * @stream: a #GtkHTMLStream
+ * 
+ * creates a new #ModestStreamTextToHtml
+ * 
+ * Returns: a new #ModestStreamTextToHtml
+ **/
+GObject*    modest_stream_text_to_html_new         (TnyStream *out_stream);
+
+void        modest_stream_text_to_html_set_linkify_limit (ModestStreamTextToHtml *self, gssize limit);
+void        modest_stream_text_to_html_set_full_limit (ModestStreamTextToHtml *self, gssize limit);
+
+
+G_END_DECLS
+
+#endif /* __MODEST_STREAM_TEXT_TO_HTML_H__ */
+
index 6b3709c..3e61cfc 100644 (file)
@@ -188,7 +188,7 @@ modest_text_utils_cite (const gchar *text,
                retval = g_strdup ("");
        else if (strcmp(content_type, "text/html") == 0) {
                tmp_sig = g_strconcat ("\n", signature, NULL);
-               retval = modest_text_utils_convert_to_html_body(tmp_sig);
+               retval = modest_text_utils_convert_to_html_body(tmp_sig, -1, TRUE);
                g_free (tmp_sig);
        } else {
                retval = g_strconcat (text, "\n", signature, NULL);
@@ -321,17 +321,17 @@ modest_text_utils_remove_address (const gchar *address_list, const gchar *addres
 }
 
 static void
-modest_text_utils_convert_buffer_to_html (GString *html, const gchar *data)
+modest_text_utils_convert_buffer_to_html (GString *html, const gchar *data, gssize n)
 {
        guint            i;
        gboolean        space_seen = FALSE;
-       gsize           len;
        guint           break_dist = 0; /* distance since last break point */
 
-       len = strlen (data);
+       if (n == -1)
+               n = strlen (data);
 
        /* replace with special html chars where needed*/
-       for (i = 0; i != len; ++i)  {
+       for (i = 0; i != n; ++i)  {
                char kar = data[i];
                
                if (space_seen && kar != ' ') {
@@ -391,7 +391,7 @@ modest_text_utils_convert_to_html (const gchar *data)
                                "</head>"
                                "<body>");
 
-       modest_text_utils_convert_buffer_to_html (html, data);
+       modest_text_utils_convert_buffer_to_html (html, data, -1);
        
        g_string_append (html, "</body></html>");
 
@@ -402,20 +402,20 @@ modest_text_utils_convert_to_html (const gchar *data)
 }
 
 gchar *
-modest_text_utils_convert_to_html_body (const gchar *data)
+modest_text_utils_convert_to_html_body (const gchar *data, gssize n, gboolean hyperlinkify)
 {
        GString         *html;      
-       gsize           len;
        
        if (!data)
                return NULL;
 
-       len = strlen (data);
-       html = g_string_sized_new (1.5 * len);  /* just a  guess... */
+       if (n == -1) 
+               n = strlen (data);
+       html = g_string_sized_new (1.5 * n);    /* just a  guess... */
 
-       modest_text_utils_convert_buffer_to_html (html, data);
+       modest_text_utils_convert_buffer_to_html (html, data, n);
 
-       if (len < HYPERLINKIFY_MAX_LENGTH)
+       if (hyperlinkify && (n < HYPERLINKIFY_MAX_LENGTH))
                hyperlinkify_plain_text (html);
 
        return g_string_free (html, FALSE);
@@ -823,12 +823,12 @@ modest_text_utils_quote_html (const gchar *text,
        if (signature == NULL)
                signature_result = g_strdup ("");
        else
-               signature_result = modest_text_utils_convert_to_html_body (signature);
+               signature_result = modest_text_utils_convert_to_html_body (signature, -1, TRUE);
 
        attachments_string = quoted_attachments (attachments);
-       q_attachments_string = modest_text_utils_convert_to_html_body (attachments_string);
-       q_cite = modest_text_utils_convert_to_html_body (cite);
-       html_text = modest_text_utils_convert_to_html_body (text);
+       q_attachments_string = modest_text_utils_convert_to_html_body (attachments_string, -1, TRUE);
+       q_cite = modest_text_utils_convert_to_html_body (cite, -1, TRUE);
+       html_text = modest_text_utils_convert_to_html_body (text, -1, TRUE);
        result = g_strdup_printf (format, signature_result, q_cite, html_text, q_attachments_string);
        g_free (q_cite);
        g_free (html_text);
@@ -845,6 +845,52 @@ cmp_offsets_reverse (const url_match_t *match1, const url_match_t *match2)
        return match2->offset - match1->offset;
 }
 
+static gboolean url_matches_block = 0;
+static url_match_pattern_t patterns[] = MAIL_VIEWER_URL_MATCH_PATTERNS;
+
+
+static gboolean
+compile_patterns ()
+{
+       guint i;
+       const size_t pattern_num = sizeof(patterns)/sizeof(url_match_pattern_t);
+       for (i = 0; i != pattern_num; ++i) {
+               patterns[i].preg = g_slice_new0 (regex_t);
+               
+               /* this should not happen */
+               g_return_val_if_fail (regcomp (patterns[i].preg, patterns[i].regex,
+                                              REG_ICASE|REG_EXTENDED|REG_NEWLINE) == 0, FALSE);
+       }
+       return TRUE;
+}
+
+static void 
+free_patterns ()
+{
+       guint i;
+       const size_t pattern_num = sizeof(patterns)/sizeof(url_match_pattern_t);
+       for (i = 0; i != pattern_num; ++i) {
+               regfree (patterns[i].preg);
+               g_slice_free  (regex_t, patterns[i].preg);
+       } /* don't free patterns itself -- it's static */
+}
+
+void
+modest_text_utils_hyperlinkify_begin (void)
+{
+       if (url_matches_block == 0)
+               compile_patterns ();
+       url_matches_block ++;
+}
+
+void
+modest_text_utils_hyperlinkify_end (void)
+{
+       url_matches_block--;
+       if (url_matches_block <= 0)
+               free_patterns ();
+}
+
 
 static GSList*
 get_url_matches (GString *txt)
@@ -853,17 +899,11 @@ get_url_matches (GString *txt)
         guint rv, i, offset = 0;
         GSList *match_list = NULL;
 
-       static url_match_pattern_t patterns[] = MAIL_VIEWER_URL_MATCH_PATTERNS;
        const size_t pattern_num = sizeof(patterns)/sizeof(url_match_pattern_t);
 
        /* initalize the regexps */
-       for (i = 0; i != pattern_num; ++i) {
-               patterns[i].preg = g_slice_new0 (regex_t);
+       modest_text_utils_hyperlinkify_begin ();
 
-               /* this should not happen */
-               g_return_val_if_fail (regcomp (patterns[i].preg, patterns[i].regex,
-                                              REG_ICASE|REG_EXTENDED|REG_NEWLINE) == 0, NULL);
-       }
         /* find all the matches */
        for (i = 0; i != pattern_num; ++i) {
                offset     = 0; 
@@ -904,10 +944,7 @@ get_url_matches (GString *txt)
                }
        }
 
-       for (i = 0; i != pattern_num; ++i) {
-               regfree (patterns[i].preg);
-               g_slice_free  (regex_t, patterns[i].preg);
-       } /* don't free patterns itself -- it's static */
+       modest_text_utils_hyperlinkify_end ();
        
        /* now sort the list, so the matches are in reverse order of occurence.
         * that way, we can do the replacements starting from the end, so we don't need
index 5945c34..0cba027 100644 (file)
@@ -156,7 +156,20 @@ void     modest_text_utils_address_range_at_position (const gchar *recipients_li
                                                      gint position,
                                                      gint *start,
                                                      gint *end);
-                                                     
+
+/**
+ * modest_text_utils_hyperlinkify_begin:
+ *
+ * begin a linkify block, compiling the caches to be reused.
+ */
+void modest_text_utils_hyperlinkify_begin (void);
+
+/**
+ * modest_text_utils_hyperlinkify_end:
+ *
+ * end a linkify block, freeing the caches to be reused.
+ */
+void modest_text_utils_hyperlinkify_end (void);
 
 /**
  * modest_text_utils_convert_to_html:
@@ -176,7 +189,7 @@ gchar*  modest_text_utils_convert_to_html (const gchar *txt);
  * 
  * Returns: a newly allocated string containing the html
  */
-gchar*  modest_text_utils_convert_to_html_body (const gchar *data);
+gchar*  modest_text_utils_convert_to_html_body (const gchar *data, gssize n, gboolean hyperlinkify);
 
 
 /**
index e048667..b6855c7 100644 (file)
@@ -34,7 +34,7 @@
 #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 <widgets/modest-mime-part-view.h>
 #include <widgets/modest-zoomable.h>
@@ -298,41 +298,24 @@ set_html_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
 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);
+       tny_stream_reset (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);
 }