* src/modest-marshal.list:
authorJose Dapena Paz <jdapena@igalia.com>
Wed, 10 Oct 2007 12:44:19 +0000 (12:44 +0000)
committerJose Dapena Paz <jdapena@igalia.com>
Wed, 10 Oct 2007 12:44:19 +0000 (12:44 +0000)
        * Added two marshallers.
* src/modest-tny-platform-factory.c:
        * Added a proper implementation of get_msg_view.
* src/modest-msg-view.[ch]:
        * Removed all references to gtkhtml library, as now we
          use the new ModestGtkhtmlMimePartView. This hides all
          gtkhtml inners in modest/tny api.
        * Implemented ModestZoomable interface, and removed old api so
          now you have to use ModestZoomable api always.
        * Adapted the signal handlers to use the ModestMimePartView
          signals instead of gtkhtml signals.
        * Now ModestMsgView implement TnyMsg and TnyMimePart interfaces.
          Removed old methods to get/set messages, as now we use
          Tny api.
        * Reestructured a bit the code, to separate the interfaces
          implementations from the implementation itself.
        * Now we properly find the embedded attachments, if they're
          stored in a multipart/related.
* Added src/modest-isearch-view.[ch]:
        * Incremental search view interface. This new interface exposes
          a view where incremental search is available (writing a string
          and beginning to search this string the times required to find
          it).
* Added src/modest-mime-part-view.[ch]:
        * New interface, child of TnyMimePartView. This interface adds
          method is_empty and signals "activate_uri", "link_hover" and
          "fetch_url" to TnyMimePartView. This is for implementing the
          specific backend for gtkhtml (included in this commit) and a
          future one using GtkMozembed.
* Added src/modest-zoomable.[ch]:
        * This new interface should be implemented by all widgets
          supporting any kind of zoom. In particular, this is
          implemented in the new ModestGtkhtmlMimePartView and in
          ModestMsgView. In the future ModestWindow children should
          implement this.
* Added src/modest-gtkhtml-mime-part-view.[ch]:
        * This is an implementation of ModestMimePartView interface,
          ModestISearchView interface, and ModestZoomable interface. It
          uses gtkhtml as backend, and is, in fact, the place where all
          the gtkhtml code that was present in ModestMsgView has gone.
* src/maemo/modest-msg-view-window.c:
        * Use TnyMsg and ModestZoomable api to access ModestMsgView.

pmo-trunk-r3481

14 files changed:
src/maemo/modest-msg-view-window.c
src/modest-marshal.list
src/modest-tny-platform-factory.c
src/widgets/Makefile.am
src/widgets/modest-gtkhtml-mime-part-view.c [new file with mode: 0644]
src/widgets/modest-gtkhtml-mime-part-view.h [new file with mode: 0644]
src/widgets/modest-isearch-view.c [new file with mode: 0644]
src/widgets/modest-isearch-view.h [new file with mode: 0644]
src/widgets/modest-mime-part-view.c [new file with mode: 0644]
src/widgets/modest-mime-part-view.h [new file with mode: 0644]
src/widgets/modest-msg-view.c
src/widgets/modest-msg-view.h
src/widgets/modest-zoomable.c [new file with mode: 0644]
src/widgets/modest-zoomable.h [new file with mode: 0644]

index 904a218..5d14535 100644 (file)
@@ -1196,7 +1196,7 @@ modest_msg_view_window_get_message (ModestMsgViewWindow *self)
 
        msg_view = MODEST_MSG_VIEW (priv->msg_view);
 
 
        msg_view = MODEST_MSG_VIEW (priv->msg_view);
 
-       return modest_msg_view_get_message (msg_view);
+       return tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
 }
 
 const gchar*
 }
 
 const gchar*
@@ -1310,7 +1310,7 @@ modest_msg_view_window_set_zoom (ModestWindow *window,
 
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
        parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
 
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
        parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
-       modest_msg_view_set_zoom (MODEST_MSG_VIEW (priv->msg_view), zoom);
+       modest_zoomable_set_zoom (MODEST_ZOOMABLE (priv->msg_view), zoom);
 
        action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
                                            "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu");
 
        action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
                                            "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu");
@@ -1326,7 +1326,7 @@ modest_msg_view_window_get_zoom (ModestWindow *window)
        g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), 1.0);
 
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
        g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), 1.0);
 
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
-       return modest_msg_view_get_zoom (MODEST_MSG_VIEW (priv->msg_view));
+       return modest_zoomable_get_zoom (MODEST_ZOOMABLE (priv->msg_view));
 }
 
 static gboolean
 }
 
 static gboolean
@@ -1788,7 +1788,7 @@ view_msg_cb (ModestMailOperation *mail_op,
                tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
 
        /* Set new message */
                tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
 
        /* Set new message */
-       modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg);
+       tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
        modest_msg_view_window_update_priority (self);
        update_window_title (MODEST_MSG_VIEW_WINDOW (self));
        modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
        modest_msg_view_window_update_priority (self);
        update_window_title (MODEST_MSG_VIEW_WINDOW (self));
        modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
@@ -1818,7 +1818,7 @@ modest_msg_view_window_get_folder_type (ModestMsgViewWindow *window)
 
        folder_type = TNY_FOLDER_TYPE_UNKNOWN;
 
 
        folder_type = TNY_FOLDER_TYPE_UNKNOWN;
 
-       msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
+       msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
        if (msg) {
                TnyFolder *folder;
 
        if (msg) {
                TnyFolder *folder;
 
@@ -2569,10 +2569,10 @@ modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean
 /*             modest_msg_view_remove_attachment (MODEST_MSG_VIEW (priv->msg_view), node->data); */
        }
 
 /*             modest_msg_view_remove_attachment (MODEST_MSG_VIEW (priv->msg_view), node->data); */
        }
 
-       msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
-       modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), NULL);
+       msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
+       tny_msg_view_clear (TNY_MSG_VIEW (priv->msg_view));
        tny_msg_rewrite_cache (msg);
        tny_msg_rewrite_cache (msg);
-       modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg);
+       tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg);
 
        g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL);
        g_list_free (mime_parts);
 
        g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL);
        g_list_free (mime_parts);
@@ -2600,7 +2600,7 @@ update_window_title (ModestMsgViewWindow *window)
        TnyHeader *header = NULL;
        const gchar *subject = NULL;
 
        TnyHeader *header = NULL;
        const gchar *subject = NULL;
 
-       msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
+       msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view));
        if (msg != NULL) {
                header = tny_msg_get_header (msg);
                subject = tny_header_get_subject (header);
        if (msg != NULL) {
                header = tny_msg_get_header (msg);
                subject = tny_header_get_subject (header);
index 38e7b11..1d5587e 100644 (file)
@@ -8,3 +8,5 @@ VOID:STRING,INT,INT
 VOID:STRING,BOOL
 VOID:STRING,POINTER,BOOL
 VOID:POINTER,INT
 VOID:STRING,BOOL
 VOID:STRING,POINTER,BOOL
 VOID:POINTER,INT
+BOOL:STRING
+BOOL:STRING,OBJECT
index dad5e4b..e6a3870 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "modest-tny-platform-factory.h"
 #include "modest-tny-account-store.h"
 
 #include "modest-tny-platform-factory.h"
 #include "modest-tny-account-store.h"
+#include <widgets/modest-msg-view.h>
 
 /* 'private'/'protected' functions */
 static void modest_tny_platform_factory_class_init (ModestTnyPlatformFactoryClass *klass);
 
 /* 'private'/'protected' functions */
 static void modest_tny_platform_factory_class_init (ModestTnyPlatformFactoryClass *klass);
@@ -188,8 +189,8 @@ modest_tny_platform_factory_new_device (TnyPlatformFactory *self)
 static TnyMsgView*
 modest_tny_platform_factory_new_msg_view (TnyPlatformFactory *self)
 {
 static TnyMsgView*
 modest_tny_platform_factory_new_msg_view (TnyPlatformFactory *self)
 {
-       /* TODO */
-       return NULL;
+       /* Here we'll select one of the implementations available */
+       return g_object_new (MODEST_TYPE_MSG_VIEW, NULL);
 }
 
 static TnyMsg*
 }
 
 static TnyMsg*
index 84ea7cd..351295f 100644 (file)
@@ -31,6 +31,8 @@ libmodest_widgets_la_SOURCES=          \
        modest-folder-view.h           \
        modest-global-settings-dialog.c \
        modest-global-settings-dialog.h \
        modest-folder-view.h           \
        modest-global-settings-dialog.c \
        modest-global-settings-dialog.h \
+       modest-gtkhtml-mime-part-view.c \
+       modest-gtkhtml-mime-part-view.h \
        modest-hbox-cell-renderer.c    \
        modest-hbox-cell-renderer.h    \
        modest-vbox-cell-renderer.c    \
        modest-hbox-cell-renderer.c    \
        modest-hbox-cell-renderer.h    \
        modest-vbox-cell-renderer.c    \
@@ -40,11 +42,15 @@ libmodest_widgets_la_SOURCES=          \
        modest-header-view-render.c    \
        modest-header-view.c           \
        modest-header-view.h           \
        modest-header-view-render.c    \
        modest-header-view.c           \
        modest-header-view.h           \
+       modest-isearch-view.c          \
+       modest-isearch-view.h          \
        modest-limit-retrieve-combo-box.h \
        modest-limit-retrieve-combo-box.c \
        modest-mail-header-view.c      \
        modest-mail-header-view.h      \
        modest-main-window.h           \
        modest-limit-retrieve-combo-box.h \
        modest-limit-retrieve-combo-box.c \
        modest-mail-header-view.c      \
        modest-mail-header-view.h      \
        modest-main-window.h           \
+       modest-mime-part-view.c        \
+       modest-mime-part-view.h        \
        modest-msg-edit-window-ui.h    \
        modest-msg-edit-window.h       \
        modest-msg-view-window.h       \
        modest-msg-edit-window-ui.h    \
        modest-msg-edit-window.h       \
        modest-msg-view-window.h       \
@@ -69,7 +75,9 @@ libmodest_widgets_la_SOURCES=          \
        modest-window.c                \
        modest-window.h                \
        modest-window-mgr.h            \
        modest-window.c                \
        modest-window.h                \
        modest-window-mgr.h            \
-       modest-window-mgr.c
+       modest-window-mgr.c            \
+       modest-zoomable.h              \
+       modest-zoomable.c
 
 LDADD = \
        $(MODEST_GSTUFF_LIBS)                           \
 
 LDADD = \
        $(MODEST_GSTUFF_LIBS)                           \
diff --git a/src/widgets/modest-gtkhtml-mime-part-view.c b/src/widgets/modest-gtkhtml-mime-part-view.c
new file mode 100644 (file)
index 0000000..f167c9a
--- /dev/null
@@ -0,0 +1,662 @@
+/* Copyright (c) 2006, 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.
+ */
+
+#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-text-utils.h>
+#include <widgets/modest-mime-part-view.h>
+#include <widgets/modest-zoomable.h>
+#include <widgets/modest-tny-stream-gtkhtml.h>
+
+/* gobject structure methods */
+static void    modest_gtkhtml_mime_part_view_class_init (ModestGtkhtmlMimePartViewClass *klass);
+static void    tny_mime_part_view_init                  (gpointer g, gpointer iface_data);
+static void    modest_mime_part_view_init               (gpointer g, gpointer iface_data);
+static void    modest_zoomable_init                     (gpointer g, gpointer iface_data);
+static void    modest_isearch_view_init                 (gpointer g, gpointer iface_data);
+static void    modest_gtkhtml_mime_part_view_init       (ModestGtkhtmlMimePartView *self);
+static void    modest_gtkhtml_mime_part_view_finalize   (GObject *self);
+
+/* GtkHTML signal handlers */
+static gboolean  on_link_clicked  (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self);
+static gboolean  on_url           (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self);
+static gboolean  on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream,
+                                  ModestGtkhtmlMimePartView *self);
+/* TnyMimePartView implementation */
+static void modest_gtkhtml_mime_part_view_clear (TnyMimePartView *self);
+static void modest_gtkhtml_mime_part_view_clear_default (TnyMimePartView *self);
+static void modest_gtkhtml_mime_part_view_set_part (TnyMimePartView *self, TnyMimePart *part);
+static void modest_gtkhtml_mime_part_view_set_part_default (TnyMimePartView *self, TnyMimePart *part);
+static TnyMimePart* modest_gtkhtml_mime_part_view_get_part (TnyMimePartView *self);
+static TnyMimePart* modest_gtkhtml_mime_part_view_get_part_default (TnyMimePartView *self);
+/* ModestMimePartView implementation */
+static gboolean modest_gtkhtml_mime_part_view_is_empty (ModestMimePartView *self);
+static gboolean modest_gtkhtml_mime_part_view_is_empty_default (ModestMimePartView *self);
+/* ModestZoomable implementation */
+static gdouble modest_gtkhtml_mime_part_view_get_zoom (ModestZoomable *self);
+static void modest_gtkhtml_mime_part_view_set_zoom (ModestZoomable *self, gdouble value);
+static gboolean modest_gtkhtml_mime_part_view_zoom_minus (ModestZoomable *self);
+static gboolean modest_gtkhtml_mime_part_view_zoom_plus (ModestZoomable *self);
+static gdouble modest_gtkhtml_mime_part_view_get_zoom_default (ModestZoomable *self);
+static void modest_gtkhtml_mime_part_view_set_zoom_default (ModestZoomable *self, gdouble value);
+static gboolean modest_gtkhtml_mime_part_view_zoom_minus_default (ModestZoomable *self);
+static gboolean modest_gtkhtml_mime_part_view_zoom_plus_default (ModestZoomable *self);
+/* ModestISearchView implementation */
+static gboolean modest_gtkhtml_mime_part_view_search                    (ModestISearchView *self, const gchar *string);
+static gboolean modest_gtkhtml_mime_part_view_search_next               (ModestISearchView *self);
+static gboolean modest_gtkhtml_mime_part_view_get_selection_area        (ModestISearchView *self, gint *x, gint *y, 
+                                                                        gint *width, gint *height);
+static gboolean modest_gtkhtml_mime_part_view_search_default            (ModestISearchView *self, const gchar *string);
+static gboolean modest_gtkhtml_mime_part_view_search_next_default       (ModestISearchView *self);
+static gboolean modest_gtkhtml_mime_part_view_get_selection_area_default (ModestISearchView *self, gint *x, gint *y, 
+                                                                         gint *width, gint *height);
+
+
+/* internal api */
+static TnyMimePart  *get_part   (ModestGtkhtmlMimePartView *self);
+static void          set_html_part   (ModestGtkhtmlMimePartView *self, TnyMimePart *part);
+static void          set_text_part   (ModestGtkhtmlMimePartView *self, TnyMimePart *part);
+static void          set_empty_part  (ModestGtkhtmlMimePartView *self);
+static void          set_part   (ModestGtkhtmlMimePartView *self, TnyMimePart *part);
+static gboolean      is_empty   (ModestGtkhtmlMimePartView *self);
+static void          set_zoom   (ModestGtkhtmlMimePartView *self, gdouble zoom);
+static gdouble       get_zoom   (ModestGtkhtmlMimePartView *self);
+static gboolean      has_contents_receiver (gpointer engine, const gchar *data,
+                                           size_t len, gboolean *has_contents);
+static gboolean      search             (ModestGtkhtmlMimePartView *self, const gchar *string);
+static gboolean      search_next        (ModestGtkhtmlMimePartView *self);
+static gboolean      get_selection_area (ModestGtkhtmlMimePartView *self, gint *x, gint *y,
+                                        gint *width, gint *height);
+
+typedef struct _ModestGtkhtmlMimePartViewPrivate ModestGtkhtmlMimePartViewPrivate;
+struct _ModestGtkhtmlMimePartViewPrivate {
+       TnyMimePart *part;
+       gdouble current_zoom;
+};
+
+#define MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
+                                                                                      MODEST_TYPE_GTKHTML_MIME_PART_VIEW, \
+                                                                                      ModestGtkhtmlMimePartViewPrivate))
+
+static GtkHTMLClass *parent_class = NULL;
+
+GtkWidget *
+modest_gtkhtml_mime_part_view_new ()
+{
+       return g_object_new (MODEST_TYPE_GTKHTML_MIME_PART_VIEW, NULL);
+}
+
+/* GOBJECT IMPLEMENTATION */
+GType
+modest_gtkhtml_mime_part_view_get_type (void)
+{
+       static GType my_type = 0;
+       if (!my_type) {
+               static const GTypeInfo my_info = {
+                       sizeof(ModestGtkhtmlMimePartViewClass),
+                       NULL,           /* base init */
+                       NULL,           /* base finalize */
+                       (GClassInitFunc) modest_gtkhtml_mime_part_view_class_init,
+                       NULL,           /* class finalize */
+                       NULL,           /* class data */
+                       sizeof(ModestGtkhtmlMimePartView),
+                       1,              /* n_preallocs */
+                       (GInstanceInitFunc) modest_gtkhtml_mime_part_view_init,
+                       NULL
+               };
+
+               static const GInterfaceInfo tny_mime_part_view_info = 
+               {
+                 (GInterfaceInitFunc) tny_mime_part_view_init, /* interface_init */
+                 NULL,         /* interface_finalize */
+                 NULL          /* interface_data */
+               };
+
+               static const GInterfaceInfo modest_mime_part_view_info = 
+               {
+                 (GInterfaceInitFunc) modest_mime_part_view_init, /* interface_init */
+                 NULL,         /* interface_finalize */
+                 NULL          /* interface_data */
+               };
+
+               static const GInterfaceInfo modest_zoomable_info = 
+               {
+                 (GInterfaceInitFunc) modest_zoomable_init, /* interface_init */
+                 NULL,         /* interface_finalize */
+                 NULL          /* interface_data */
+               };
+
+               static const GInterfaceInfo modest_isearch_view_info = 
+               {
+                 (GInterfaceInitFunc) modest_isearch_view_init, /* interface_init */
+                 NULL,         /* interface_finalize */
+                 NULL          /* interface_data */
+               };
+
+               my_type = g_type_register_static (GTK_TYPE_HTML,
+                                                 "ModestGtkhtmlMimePartView",
+                                                 &my_info, 0);
+
+               g_type_add_interface_static (my_type, TNY_TYPE_MIME_PART_VIEW, 
+                       &tny_mime_part_view_info);
+
+               g_type_add_interface_static (my_type, MODEST_TYPE_MIME_PART_VIEW, 
+                       &modest_mime_part_view_info);
+
+               g_type_add_interface_static (my_type, MODEST_TYPE_ZOOMABLE, 
+                       &modest_zoomable_info);
+               g_type_add_interface_static (my_type, MODEST_TYPE_ISEARCH_VIEW, 
+                       &modest_isearch_view_info);
+       }
+       return my_type;
+}
+
+static void
+modest_gtkhtml_mime_part_view_class_init (ModestGtkhtmlMimePartViewClass *klass)
+{
+       GObjectClass *gobject_class;
+       gobject_class = (GObjectClass*) klass;
+
+       parent_class            = g_type_class_peek_parent (klass);
+       gobject_class->finalize = modest_gtkhtml_mime_part_view_finalize;
+
+       klass->get_part_func = modest_gtkhtml_mime_part_view_get_part_default;
+       klass->set_part_func = modest_gtkhtml_mime_part_view_set_part_default;
+       klass->clear_func = modest_gtkhtml_mime_part_view_clear_default;
+       klass->is_empty_func = modest_gtkhtml_mime_part_view_is_empty_default;
+       klass->get_zoom_func = modest_gtkhtml_mime_part_view_get_zoom_default;
+       klass->set_zoom_func = modest_gtkhtml_mime_part_view_set_zoom_default;
+       klass->zoom_minus_func = modest_gtkhtml_mime_part_view_zoom_minus_default;
+       klass->zoom_plus_func = modest_gtkhtml_mime_part_view_zoom_plus_default;
+       klass->search_func = modest_gtkhtml_mime_part_view_search_default;
+       klass->search_next_func = modest_gtkhtml_mime_part_view_search_next_default;
+       klass->get_selection_area_func = modest_gtkhtml_mime_part_view_get_selection_area_default;
+       
+       g_type_class_add_private (gobject_class, sizeof(ModestGtkhtmlMimePartViewPrivate));
+
+}
+
+static void    
+modest_gtkhtml_mime_part_view_init (ModestGtkhtmlMimePartView *self)
+{
+       ModestGtkhtmlMimePartViewPrivate *priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
+
+       gtk_html_set_editable        (GTK_HTML(self), FALSE);
+       gtk_html_allow_selection     (GTK_HTML(self), TRUE);
+       gtk_html_set_caret_mode      (GTK_HTML(self), FALSE);
+       gtk_html_set_blocking        (GTK_HTML(self), FALSE);
+       gtk_html_set_images_blocking (GTK_HTML(self), FALSE);
+
+       g_signal_connect (G_OBJECT(self), "link_clicked",
+                         G_CALLBACK(on_link_clicked), self);
+       g_signal_connect (G_OBJECT(self), "url_requested",
+                         G_CALLBACK(on_url_requested), self);
+       g_signal_connect (G_OBJECT(self), "on_url",
+                         G_CALLBACK(on_url), self);
+
+       priv->part = NULL;
+       priv->current_zoom = 1.0;
+}
+
+static void
+modest_gtkhtml_mime_part_view_finalize (GObject *obj)
+{
+       G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+/* GTKHTML SIGNALS HANDLERS */
+
+static gboolean
+on_link_clicked (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self)
+{
+       gboolean result;
+       g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE);
+
+       g_signal_emit_by_name (G_OBJECT (self), "activate-link", uri, &result);
+       return result;
+}
+
+static gboolean
+on_url (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self)
+{
+       gboolean result;
+       g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE);
+
+       g_signal_emit_by_name (G_OBJECT (self), "link-hover", uri, &result);
+       return result;
+}
+
+static gboolean
+on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream, 
+                 ModestGtkhtmlMimePartView *self)
+{
+       gboolean result;
+       TnyStream *tny_stream;
+       g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), 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);
+       g_object_unref (tny_stream);
+       return result;
+}
+
+/* INTERNAL API */
+
+static void
+set_html_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
+{
+       GtkHTMLStream *gtkhtml_stream;
+       TnyStream *tny_stream;  
+       
+       g_return_if_fail (self);
+       g_return_if_fail (part);
+       
+       gtkhtml_stream = gtk_html_begin(GTK_HTML(self));
+
+       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);
+       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;
+       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));
+       
+       // 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);
+       }
+       
+       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);
+}
+
+static void
+set_empty_part (ModestGtkhtmlMimePartView *self)
+{
+       g_return_if_fail (self);
+
+       gtk_html_load_from_string (GTK_HTML(self),
+                                  "", 1);
+}
+
+static void
+set_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
+{
+       ModestGtkhtmlMimePartViewPrivate *priv;
+
+       g_return_if_fail (self);
+       
+       priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE(self);
+
+       if (part != priv->part) {
+               if (priv->part)
+                       g_object_unref (G_OBJECT(priv->part));
+               if (part)
+                       g_object_ref   (G_OBJECT(part));
+               priv->part = part;
+       }
+       
+       if (!part) {
+               set_empty_part (self);
+               return;
+       }
+
+       if (tny_mime_part_content_type_is (part, "text/html"))
+               set_html_part (self, part);
+       else
+               set_text_part (self, part);
+
+}
+
+static TnyMimePart*
+get_part (ModestGtkhtmlMimePartView *self)
+{
+       TnyMimePart *part;
+
+       g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), NULL);
+
+       part = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE(self)->part;
+
+       if (part)
+               g_object_ref (part);
+       
+       return part;
+}
+
+static gboolean
+has_contents_receiver (gpointer engine, const gchar *data,
+                      size_t len, gboolean *has_contents)
+{
+       if (len > 1 || ((len == 1)&&(data[0]!='\n'))) {
+               *has_contents = TRUE;
+               return FALSE;
+       }
+       return TRUE;
+}
+
+static gboolean      
+is_empty   (ModestGtkhtmlMimePartView *self)
+{
+       /* TODO: Find some gtkhtml API to check whether there is any (visible, non markup)
+        * text in the message:
+        */
+       gboolean has_contents = FALSE;
+
+       gtk_html_export (GTK_HTML (self), "text/plain", 
+                        (GtkHTMLSaveReceiverFn) has_contents_receiver, &has_contents);
+       
+       return !has_contents;
+}
+
+static void
+set_zoom (ModestGtkhtmlMimePartView *self, gdouble zoom)
+{
+       ModestGtkhtmlMimePartViewPrivate *priv;
+
+       g_return_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self));
+
+       priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
+       priv->current_zoom = zoom;
+       gtk_html_set_magnification (GTK_HTML(self), zoom);
+
+       gtk_widget_queue_resize (GTK_WIDGET (self));
+}
+
+static gdouble
+get_zoom (ModestGtkhtmlMimePartView *self)
+{
+       ModestGtkhtmlMimePartViewPrivate *priv;
+
+       g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), 1.0);
+
+       priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
+
+       return priv->current_zoom;
+}
+
+static gboolean
+search (ModestGtkhtmlMimePartView *self, 
+       const gchar *string)
+{
+       return gtk_html_engine_search (GTK_HTML (self),
+                                      string,
+                                      FALSE,   /* case sensitive */
+                                      TRUE,    /* forward */
+                                      FALSE);  /* regexp */
+}
+
+static gboolean
+search_next (ModestGtkhtmlMimePartView *self)
+{
+       return gtk_html_engine_search_next (GTK_HTML (self));
+}
+
+static gboolean
+get_selection_area (ModestGtkhtmlMimePartView *self, 
+                   gint *x, gint *y,
+                   gint *width, gint *height)
+{
+       gtk_html_get_selection_area (GTK_HTML (self), x, y, width, height);
+       return TRUE;
+}
+
+
+/* TNY MIME PART IMPLEMENTATION */
+
+static void
+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;
+
+       return;
+}
+
+static TnyMimePart* 
+modest_gtkhtml_mime_part_view_get_part (TnyMimePartView *self)
+{
+       return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->get_part_func (self);
+}
+
+
+static TnyMimePart* 
+modest_gtkhtml_mime_part_view_get_part_default (TnyMimePartView *self)
+{
+       return TNY_MIME_PART (get_part (MODEST_GTKHTML_MIME_PART_VIEW (self)));
+}
+
+static void
+modest_gtkhtml_mime_part_view_set_part (TnyMimePartView *self,
+                                       TnyMimePart *part)
+{
+       MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->set_part_func (self, part);
+}
+
+static void
+modest_gtkhtml_mime_part_view_set_part_default (TnyMimePartView *self,
+                                               TnyMimePart *part)
+{
+       g_return_if_fail ((part == NULL) || TNY_IS_MIME_PART (part));
+
+       set_part (MODEST_GTKHTML_MIME_PART_VIEW (self), part);
+}
+
+static void
+modest_gtkhtml_mime_part_view_clear (TnyMimePartView *self)
+{
+       MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->clear_func (self);
+}
+
+static void
+modest_gtkhtml_mime_part_view_clear_default (TnyMimePartView *self)
+{
+       set_part (MODEST_GTKHTML_MIME_PART_VIEW (self), NULL);
+}
+
+/* MODEST MIME PART VIEW IMPLEMENTATION */
+
+static void
+modest_mime_part_view_init (gpointer g, gpointer iface_data)
+{
+       ModestMimePartViewIface *klass = (ModestMimePartViewIface *)g;
+
+       klass->is_empty_func = modest_gtkhtml_mime_part_view_is_empty;
+
+       return;
+}
+
+static gboolean
+modest_gtkhtml_mime_part_view_is_empty (ModestMimePartView *self)
+{
+       return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->is_empty_func (self);
+}
+
+static gboolean
+modest_gtkhtml_mime_part_view_is_empty_default (ModestMimePartView *self)
+{
+       return is_empty (MODEST_GTKHTML_MIME_PART_VIEW (self));
+}
+
+
+/* MODEST ZOOMABLE IMPLEMENTATION */
+static void
+modest_zoomable_init (gpointer g, gpointer iface_data)
+{
+       ModestZoomableIface *klass = (ModestZoomableIface *)g;
+       
+       klass->get_zoom_func = modest_gtkhtml_mime_part_view_get_zoom;
+       klass->set_zoom_func = modest_gtkhtml_mime_part_view_set_zoom;
+       klass->zoom_minus_func = modest_gtkhtml_mime_part_view_zoom_minus;
+       klass->zoom_plus_func = modest_gtkhtml_mime_part_view_zoom_plus;
+
+       return;
+}
+
+static gdouble
+modest_gtkhtml_mime_part_view_get_zoom (ModestZoomable *self)
+{
+       return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->get_zoom_func (self);
+}
+
+static gdouble
+modest_gtkhtml_mime_part_view_get_zoom_default (ModestZoomable *self)
+{
+       return get_zoom (MODEST_GTKHTML_MIME_PART_VIEW (self));
+}
+
+static void
+modest_gtkhtml_mime_part_view_set_zoom (ModestZoomable *self, gdouble value)
+{
+       MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->set_zoom_func (self, value);
+}
+
+static void
+modest_gtkhtml_mime_part_view_set_zoom_default (ModestZoomable *self, gdouble value)
+{
+       set_zoom (MODEST_GTKHTML_MIME_PART_VIEW (self), value);
+}
+
+static gboolean
+modest_gtkhtml_mime_part_view_zoom_minus (ModestZoomable *self)
+{
+       return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->zoom_minus_func (self);
+}
+
+static gboolean
+modest_gtkhtml_mime_part_view_zoom_minus_default (ModestZoomable *self)
+{
+       /* operation not supported in ModestGtkhtmlMimePartView */
+       return FALSE;
+}
+
+static gboolean
+modest_gtkhtml_mime_part_view_zoom_plus (ModestZoomable *self)
+{
+       return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->zoom_plus_func (self);
+}
+
+static gboolean
+modest_gtkhtml_mime_part_view_zoom_plus_default (ModestZoomable *self)
+{
+       /* operation not supported in ModestGtkhtmlMimePartView */
+       return FALSE;
+}
+
+/* ISEARCH VIEW IMPLEMENTATION */
+static void
+modest_isearch_view_init (gpointer g, gpointer iface_data)
+{
+       ModestISearchViewIface *klass = (ModestISearchViewIface *)g;
+       
+       klass->search_func = modest_gtkhtml_mime_part_view_search;
+       klass->search_next_func = modest_gtkhtml_mime_part_view_search_next;
+       klass->get_selection_area_func = modest_gtkhtml_mime_part_view_get_selection_area;
+
+       return;
+}
+
+static gboolean 
+modest_gtkhtml_mime_part_view_search (ModestISearchView *self, const gchar *string)
+{
+       return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->search_func (self, string);
+}
+
+static gboolean 
+modest_gtkhtml_mime_part_view_search_default (ModestISearchView *self, const gchar *string)
+{
+       return search (MODEST_GTKHTML_MIME_PART_VIEW (self), string);
+}
+
+static gboolean 
+modest_gtkhtml_mime_part_view_search_next(ModestISearchView *self)
+{
+       return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->search_next_func (self);
+}
+
+static gboolean 
+modest_gtkhtml_mime_part_view_search_next_default (ModestISearchView *self)
+{
+       return search_next (MODEST_GTKHTML_MIME_PART_VIEW (self));
+}
+
+static gboolean 
+modest_gtkhtml_mime_part_view_get_selection_area (ModestISearchView *self, gint *x, gint *y, 
+                                                 gint *width, gint *height)
+{
+       return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->get_selection_area_func (self, x, y, width, height);
+}
+
+static gboolean 
+modest_gtkhtml_mime_part_view_get_selection_area_default (ModestISearchView *self, gint *x, gint *y, 
+                                                         gint *width, gint *height)
+{
+       return get_selection_area (MODEST_GTKHTML_MIME_PART_VIEW (self), x, y, width, height);
+}
diff --git a/src/widgets/modest-gtkhtml-mime-part-view.h b/src/widgets/modest-gtkhtml-mime-part-view.h
new file mode 100644 (file)
index 0000000..510f071
--- /dev/null
@@ -0,0 +1,103 @@
+/* Copyright (c) 2006, 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.
+ */
+
+#ifndef __MODEST_GTKHTML_MIME_PART_VIEW_H__
+#define __MODEST_GTKHTML_MIME_PART_VIEW_H__
+
+#include <config.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <gtkhtml/gtkhtml.h>
+#include <tny-mime-part-view.h>
+#include <widgets/modest-mime-part-view.h>
+#include <widgets/modest-zoomable.h>
+#include <widgets/modest-isearch-view.h>
+
+G_BEGIN_DECLS
+
+/* convenience macros */
+#define MODEST_TYPE_GTKHTML_MIME_PART_VIEW             (modest_gtkhtml_mime_part_view_get_type())
+#define MODEST_GTKHTML_MIME_PART_VIEW(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj),MODEST_TYPE_GTKHTML_MIME_PART_VIEW,ModestGtkhtmlMimePartView))
+#define MODEST_GTKHTML_MIME_PART_VIEW_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass),MODEST_TYPE_GTKHTML_MIME_PART_VIEW,ModestGtkhtmlMimePartViewClass))
+#define MODEST_IS_GTKHTML_MIME_PART_VIEW(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj),MODEST_TYPE_GTKHTML_MIME_PART_VIEW))
+#define MODEST_IS_GTKHTML_MIME_PART_VIEW_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass),MODEST_TYPE_GTKHTML_MIME_PART_VIEW))
+#define MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS((obj),MODEST_TYPE_GTKHTML_MIME_PART_VIEW,ModestGtkhtmlMimePartViewClass))
+
+typedef struct _ModestGtkhtmlMimePartView      ModestGtkhtmlMimePartView;
+typedef struct _ModestGtkhtmlMimePartViewClass ModestGtkhtmlMimePartViewClass;
+
+struct _ModestGtkhtmlMimePartView {
+       GtkHTML parent;
+};
+
+struct _ModestGtkhtmlMimePartViewClass {
+       GtkHTMLClass parent_class;
+
+       /* TnyMimePartView interface methods */
+       TnyMimePart* (*get_part_func) (TnyMimePartView *self);
+       void (*set_part_func) (TnyMimePartView *self, TnyMimePart *part);
+       void (*clear_func) (TnyMimePartView *self);
+       /* ModestMimePartView interface methods */
+       gboolean (*is_empty_func) (ModestMimePartView *self);
+       /* ModestZoomable interface methods */
+       gdouble (*get_zoom_func) (ModestZoomable *self);
+       void (*set_zoom_func) (ModestZoomable *self, gdouble value);
+       gboolean (*zoom_minus_func) (ModestZoomable *self);
+       gboolean (*zoom_plus_func) (ModestZoomable *self);
+       /* ModestISearchView interface methods */
+       gboolean (*search_func)             (ModestISearchView *self, const gchar *string);
+       gboolean (*search_next_func)        (ModestISearchView *self);
+       gboolean (*get_selection_area_func) (ModestISearchView *self, gint *x, gint *y, gint *width, gint *height);
+};
+
+
+/**
+ *
+ * modest_gtkhtml_mime_part_view_get_type
+ *
+ * get the GType for the this class
+ *
+ * Returns: the GType for this class
+ */
+GType        modest_gtkhtml_mime_part_view_get_type    (void) G_GNUC_CONST;
+
+/**
+ * modest_gtkhtml_mime_part_view_new:
+ *
+ * create a new #ModestGtkhtmlMimePartView instance, implementing
+ * interfaces #TnyMimePartView, #ModestMimePartView, #ModestZoomable
+ * and #ModestISearchView.
+ *
+ * Returns: a #ModestGtkhtmlMimePartView
+ */
+GtkWidget   *modest_gtkhtml_mime_part_view_new (void);
+
+G_END_DECLS
+
+#endif /* __MODEST_GTK_HTML_MIME_PART_VIEW_H__ */
diff --git a/src/widgets/modest-isearch-view.c b/src/widgets/modest-isearch-view.c
new file mode 100644 (file)
index 0000000..9e65c4b
--- /dev/null
@@ -0,0 +1,121 @@
+/* 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.
+ */
+
+#include <config.h>
+
+#include <modest-isearch-view.h>
+
+/**
+ * modest_isearch_view_search:
+ * @self: a #ModestISearchView
+ * @string: a string
+ *
+ * Begins a new search in @self trying to match @string.
+ * 
+ * Returns: %TRUE if @string was matches, %FALSE otherwise
+ */
+gboolean
+modest_isearch_view_search (ModestISearchView *self, const gchar *string)
+{
+       return MODEST_ISEARCH_VIEW_GET_IFACE (self)->search_func (self, string);
+}
+
+/**
+ * modest_isearch_view_search_next:
+ * @self: a #ModestISearchView
+ *
+ * Continues the last search.
+ * 
+ * Returns: %TRUE if last search matches again, %FALSE otherwise
+ */
+gboolean
+modest_isearch_view_search_next (ModestISearchView *self)
+{
+       return MODEST_ISEARCH_VIEW_GET_IFACE (self)->search_next_func (self);
+}
+
+/**
+ * modest_isearch_view_get_selection_area:
+ * @self: a #ModestISearchView
+ * @x: a #gint pointer (out)
+ * @y: a #gint pointer (out)
+ * @width: a #gint pointer (out)
+ * @height: a #gint pointer (out)
+ *
+ * Obtains the area of the last search match.
+ * 
+ * Returns: %TRUE if there's any search matched, %FALSE otherwise
+ */
+gboolean
+modest_isearch_view_get_selection_area (ModestISearchView *self, 
+                                       gint *x, gint *y, 
+                                       gint *width, gint *height)
+{
+       return MODEST_ISEARCH_VIEW_GET_IFACE (self)->get_selection_area_func (self, x, y, width, height);
+}
+
+static void
+modest_isearch_view_base_init (gpointer g_class)
+{
+       static gboolean initialized = FALSE;
+
+       if (!initialized) {
+               /* init signals here */
+               initialized = TRUE;
+       }
+}
+
+GType
+modest_isearch_view_get_type (void)
+{
+       static GType type = 0;
+
+       if (G_UNLIKELY(type == 0)) 
+       {
+               static const GTypeInfo info = 
+               {
+                 sizeof (ModestISearchViewIface),
+                 modest_isearch_view_base_init,   /* base_init */
+                 NULL,   /* base_finalize */
+                 NULL,   /* class_init */
+                 NULL,   /* class_finalize */
+                 NULL,   /* class_data */
+                 0,
+                 0,      /* n_preallocs */
+                 NULL,   /* instance_init */
+                 NULL
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                       "ModestISearchView", &info, 0);
+
+       }
+
+       return type;
+}
diff --git a/src/widgets/modest-isearch-view.h b/src/widgets/modest-isearch-view.h
new file mode 100644 (file)
index 0000000..e359627
--- /dev/null
@@ -0,0 +1,64 @@
+/* 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.
+ */
+
+#ifndef MODEST_ISEARCH_VIEW_H
+#define MODEST_ISEARCH_VIEW_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MODEST_TYPE_ISEARCH_VIEW            (modest_isearch_view_get_type ())
+#define MODEST_ISEARCH_VIEW(obj)       (G_TYPE_CHECK_INSTANCE_CAST ((obj), MODEST_TYPE_ISEARCH_VIEW, ModestISearchView))
+#define MODEST_IS_ISEARCH_VIEW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MODEST_TYPE_ISEARCH_VIEW))
+#define MODEST_ISEARCH_VIEW_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), MODEST_TYPE_ISEARCH_VIEW, ModestISearchViewIface))
+
+typedef struct _ModestISearchView ModestISearchView;
+typedef struct _ModestISearchViewIface ModestISearchViewIface;
+
+struct _ModestISearchViewIface
+{
+       GTypeInterface parent;
+
+       /* virtuals */
+       gboolean (*search_func)             (ModestISearchView *self, const gchar *string);
+       gboolean (*search_next_func)        (ModestISearchView *self);
+       gboolean (*get_selection_area_func) (ModestISearchView *self, gint *x, gint *y, gint *width, gint *height);
+};
+
+GType modest_isearch_view_get_type (void);
+
+gboolean modest_isearch_view_search              (ModestISearchView *self, const gchar *string);
+gboolean modest_isearch_view_search_next         (ModestISearchView *self);
+gboolean modest_isearch_view_get_selection_area  (ModestISearchView *self, gint *x, gint *y, gint *width, gint *height);
+
+G_END_DECLS
+
+#endif
diff --git a/src/widgets/modest-mime-part-view.c b/src/widgets/modest-mime-part-view.c
new file mode 100644 (file)
index 0000000..a276c6a
--- /dev/null
@@ -0,0 +1,155 @@
+/* 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.
+ */
+
+#include <config.h>
+
+#include <modest-mime-part-view.h>
+#include <modest-marshal.h>
+
+enum {
+       ACTIVATE_LINK,
+       LINK_HOVER,
+       FETCH_URL,
+       LAST_SIGNAL
+};
+
+static guint mime_part_view_signals[LAST_SIGNAL] = { 0 };
+
+/**
+ * modest_mime_part_view_is_empty:
+ * @self: a #ModestMimePartView
+ *
+ * checks if the mail shown can be considered as empty or not.
+ *
+ * Returns: %TRUE if mail shown is empty, %FALSE otherwise.
+ */
+gboolean
+modest_mime_part_view_is_empty (ModestMimePartView *self)
+{
+       return MODEST_MIME_PART_VIEW_GET_IFACE (self)->is_empty_func (self);
+}
+
+static void
+modest_mime_part_view_base_init (gpointer g_class)
+{
+       static gboolean initialized = FALSE;
+
+       if (!initialized) {
+
+               /**
+                * ModestMimePartView::activate-link:
+                * @self: a #ModestMimePartView instance the signal is emitted
+                * @string: a string containing the URI
+                *
+                * This signal is emitted when a URI is activated
+                *
+                * Returns:
+                */
+               mime_part_view_signals[ACTIVATE_LINK] =
+                       g_signal_new ("activate_link",
+                                     MODEST_TYPE_MIME_PART_VIEW,
+                                     G_SIGNAL_RUN_LAST,
+                                     G_STRUCT_OFFSET (ModestMimePartViewIface, activate_link),
+                                     NULL, NULL,
+                                     modest_marshal_BOOLEAN__STRING,
+                                     G_TYPE_BOOLEAN, 1,
+                                     G_TYPE_STRING);
+               /**
+                * ModestMimePartView::link-hover:
+                * @self: a #ModestMimePartView instance the signal is emitted
+                * @string: a string containing the URI
+                *
+                * This signal is emitted when user passes the mouse over a link
+                *
+                * Returns:
+                */
+               mime_part_view_signals[LINK_HOVER] =
+                       g_signal_new ("link_hover",
+                                     MODEST_TYPE_MIME_PART_VIEW,
+                                     G_SIGNAL_RUN_LAST,
+                                     G_STRUCT_OFFSET (ModestMimePartViewIface, link_hover),
+                                     NULL, NULL,
+                                     modest_marshal_BOOLEAN__STRING,
+                                     G_TYPE_BOOLEAN, 1,
+                                     G_TYPE_STRING);
+
+               /**
+                * ModestMimePartView::fetch-url:
+                * @self: a #ModestMimePartView instance the signal is emitted
+                * @string: a string containing the URI
+                * @stream: a #TnyStream
+                *
+                * This signal is emitted when the page is rendered, and some
+                * url has to be resolved externally. You have to put the
+                * required information in the stream (images, etc).
+                *
+                * Returns:
+                */
+               mime_part_view_signals[FETCH_URL] =
+                       g_signal_new ("fetch_url",
+                                     MODEST_TYPE_MIME_PART_VIEW,
+                                     G_SIGNAL_RUN_LAST,
+                                     G_STRUCT_OFFSET (ModestMimePartViewIface, fetch_url),
+                                     NULL, NULL,
+                                     modest_marshal_BOOLEAN__STRING_OBJECT,
+                                     G_TYPE_BOOLEAN, 2,
+                                     G_TYPE_STRING,
+                                     G_TYPE_OBJECT);
+               initialized = TRUE;
+       }
+}
+
+GType
+modest_mime_part_view_get_type (void)
+{
+       static GType type = 0;
+
+       if (G_UNLIKELY(type == 0)) 
+       {
+               static const GTypeInfo info = 
+               {
+                 sizeof (ModestMimePartViewIface),
+                 modest_mime_part_view_base_init,   /* base_init */
+                 NULL,   /* base_finalize */
+                 NULL,   /* class_init */
+                 NULL,   /* class_finalize */
+                 NULL,   /* class_data */
+                 0,
+                 0,      /* n_preallocs */
+                 NULL,   /* instance_init */
+                 NULL
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                       "ModestMimePartView", &info, 0);
+
+       }
+
+       return type;
+}
diff --git a/src/widgets/modest-mime-part-view.h b/src/widgets/modest-mime-part-view.h
new file mode 100644 (file)
index 0000000..b559861
--- /dev/null
@@ -0,0 +1,66 @@
+/* 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.
+ */
+
+#ifndef MODEST_MIME_PART_VIEW_H
+#define MODEST_MIME_PART_VIEW_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <tny-stream.h>
+
+G_BEGIN_DECLS
+
+#define MODEST_TYPE_MIME_PART_VIEW            (modest_mime_part_view_get_type ())
+#define MODEST_MIME_PART_VIEW(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), MODEST_TYPE_MIME_PART_VIEW, ModestMimePartView))
+#define MODEST_IS_MIME_PART_VIEW(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MODEST_TYPE_MIME_PART_VIEW))
+#define MODEST_MIME_PART_VIEW_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), MODEST_TYPE_MIME_PART_VIEW, ModestMimePartViewIface))
+
+typedef struct _ModestMimePartView ModestMimePartView;
+typedef struct _ModestMimePartViewIface ModestMimePartViewIface;
+
+struct _ModestMimePartViewIface
+{
+       GTypeInterface parent;
+
+       /* signals */
+       gboolean (*activate_link) (ModestMimePartView *self, const gchar *uri);
+       gboolean (*link_hover)    (ModestMimePartView *self, const gchar *uri);
+       gboolean (*fetch_url)     (ModestMimePartView *self, const gchar *uri, TnyStream *stream);
+       
+       /* virtuals */
+       gboolean (*is_empty_func) (ModestMimePartView *self);
+};
+
+GType modest_mime_part_view_get_type (void);
+
+gboolean modest_mime_part_view_is_empty (ModestMimePartView *self);
+
+G_END_DECLS
+
+#endif
index ee39e2e..aff2ca8 100644 (file)
 #include <ctype.h>
 #include <stdlib.h>
 #include <glib/gi18n.h>
 #include <ctype.h>
 #include <stdlib.h>
 #include <glib/gi18n.h>
-#include <gtkhtml/gtkhtml.h>
-#include <gtkhtml/gtkhtml-stream.h>
-#include <gtkhtml/gtkhtml-search.h>
-#include <gtkhtml/gtkhtml-embedded.h>
 #include <tny-list.h>
 #include <tny-simple-list.h>
 
 #include <modest-tny-msg.h>
 #include <modest-text-utils.h>
 #include <tny-list.h>
 #include <tny-simple-list.h>
 
 #include <modest-tny-msg.h>
 #include <modest-text-utils.h>
-#include "modest-msg-view.h"
-#include "modest-tny-stream-gtkhtml.h"
-#include <modest-mail-header-view.h>
-#include <modest-attachments-view.h>
+#include <widgets/modest-msg-view.h>
+#include <widgets/modest-mail-header-view.h>
+#include <widgets/modest-attachments-view.h>
 #include <modest-marshal.h>
 #include <modest-marshal.h>
+#include <widgets/modest-gtkhtml-mime-part-view.h>
+#include <widgets/modest-isearch-view.h>
 
 
 /* 'private'/'protected' functions */
 static void     modest_msg_view_class_init   (ModestMsgViewClass *klass);
 
 
 /* 'private'/'protected' functions */
 static void     modest_msg_view_class_init   (ModestMsgViewClass *klass);
+static void     tny_msg_view_init (gpointer g, gpointer iface_data);
+static void     tny_mime_part_view_init (gpointer g, gpointer iface_data);
+static void     modest_zoomable_init (gpointer g, gpointer iface_data);
 static void     modest_msg_view_init         (ModestMsgView *obj);
 static void     modest_msg_view_finalize     (GObject *obj);
 static void     modest_msg_view_destroy     (GtkObject *obj);
 static void     modest_msg_view_init         (ModestMsgView *obj);
 static void     modest_msg_view_finalize     (GObject *obj);
 static void     modest_msg_view_destroy     (GtkObject *obj);
@@ -61,10 +61,10 @@ static void     get_property (GObject *object, guint prop_id, GValue *value, GPa
 static void on_recpt_activated (ModestMailHeaderView *header_view, const gchar *address, ModestMsgView *msg_view);
 static void on_attachment_activated (ModestAttachmentsView * att_view, TnyMimePart *mime_part, gpointer userdata);
 
 static void on_recpt_activated (ModestMailHeaderView *header_view, const gchar *address, ModestMsgView *msg_view);
 static void on_attachment_activated (ModestAttachmentsView * att_view, TnyMimePart *mime_part, gpointer userdata);
 
-/* GtkHtml signals */
-static gboolean on_link_clicked (GtkWidget *widget, const gchar *uri, ModestMsgView *msg_view);
-static gboolean on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream,
-                                 ModestMsgView *msg_view);
+/* body view signals */
+static gboolean on_activate_link (GtkWidget *widget, const gchar *uri, ModestMsgView *msg_view);
+static gboolean on_fetch_url (GtkWidget *widget, const gchar *uri, TnyStream *stream,
+                             ModestMsgView *msg_view);
 static gboolean on_link_hover (GtkWidget *widget, const gchar *uri, ModestMsgView *msg_view);
 
 #ifdef MAEMO_CHANGES
 static gboolean on_link_hover (GtkWidget *widget, const gchar *uri, ModestMsgView *msg_view);
 
 #ifdef MAEMO_CHANGES
@@ -93,6 +93,42 @@ static void forall (GtkContainer *container, gboolean include_internals,
                    GtkCallback callback, gpointer userdata);
 static void container_remove (GtkContainer *container, GtkWidget *widget);
 
                    GtkCallback callback, gpointer userdata);
 static void container_remove (GtkContainer *container, GtkWidget *widget);
 
+/* TnyMimePartView implementation */
+static void modest_msg_view_mp_clear (TnyMimePartView *self);
+static void modest_msg_view_mp_set_part (TnyMimePartView *self, TnyMimePart *part);
+static void modest_msg_view_mp_set_part_default (TnyMimePartView *self, TnyMimePart *part);
+static TnyMimePart* modest_msg_view_mp_get_part (TnyMimePartView *self);
+static TnyMimePart* modest_msg_view_mp_get_part_default (TnyMimePartView *self);
+/* TnyMsgView implementation */
+static TnyMsg *modest_msg_view_get_msg (TnyMsgView *self);
+static TnyMsg *modest_msg_view_get_msg_default (TnyMsgView *self);
+static void modest_msg_view_set_msg (TnyMsgView *self, TnyMsg *msg);
+static void modest_msg_view_set_msg_default (TnyMsgView *self, TnyMsg *msg);
+static void modest_msg_view_clear (TnyMsgView *self);
+static void modest_msg_view_clear_default (TnyMsgView *self);
+static void modest_msg_view_set_unavailable (TnyMsgView *self);
+static void modest_msg_view_set_unavailable_default (TnyMsgView *self);
+static TnyMimePartView *modest_msg_view_create_mime_part_view_for (TnyMsgView *self, TnyMimePart *part);
+static TnyMimePartView *modest_msg_view_create_mime_part_view_for_default (TnyMsgView *self, TnyMimePart *part);
+static TnyMsgView *modest_msg_view_create_new_inline_viewer (TnyMsgView *self);
+static TnyMsgView *modest_msg_view_create_new_inline_viewer_default (TnyMsgView *self);
+/* ModestZoomable implementation */
+static gdouble modest_msg_view_get_zoom (ModestZoomable *self);
+static void modest_msg_view_set_zoom (ModestZoomable *self, gdouble value);
+static gboolean modest_msg_view_zoom_minus (ModestZoomable *self);
+static gboolean modest_msg_view_zoom_plus (ModestZoomable *self);
+static gdouble modest_msg_view_get_zoom_default (ModestZoomable *self);
+static void modest_msg_view_set_zoom_default (ModestZoomable *self, gdouble value);
+static gboolean modest_msg_view_zoom_minus_default (ModestZoomable *self);
+static gboolean modest_msg_view_zoom_plus_default (ModestZoomable *self);
+
+/* internal api */
+static TnyMsg *get_message    (ModestMsgView *self);
+static void    set_message    (ModestMsgView *self, TnyMsg *tny_msg);
+static void    set_zoom       (ModestMsgView *self, gdouble zoom);
+static gdouble get_zoom       (ModestMsgView *self);
+
+
 /* list my signals */
 enum {
        LINK_CLICKED_SIGNAL,
 /* list my signals */
 enum {
        LINK_CLICKED_SIGNAL,
@@ -113,7 +149,7 @@ enum {
 
 typedef struct _ModestMsgViewPrivate ModestMsgViewPrivate;
 struct _ModestMsgViewPrivate {
 
 typedef struct _ModestMsgViewPrivate ModestMsgViewPrivate;
 struct _ModestMsgViewPrivate {
-       GtkWidget   *gtkhtml;
+       GtkWidget   *body_view;
        GtkWidget   *mail_header_view;
        GtkWidget   *attachments_view;
 
        GtkWidget   *mail_header_view;
        GtkWidget   *attachments_view;
 
@@ -170,9 +206,39 @@ modest_msg_view_get_type (void)
                        (GInstanceInitFunc) modest_msg_view_init,
                        NULL
                };
                        (GInstanceInitFunc) modest_msg_view_init,
                        NULL
                };
+               static const GInterfaceInfo tny_msg_view_info = 
+               {
+                 (GInterfaceInitFunc) tny_msg_view_init, /* interface_init */
+                 NULL,         /* interface_finalize */
+                 NULL          /* interface_data */
+               };
+
+               static const GInterfaceInfo tny_mime_part_view_info = 
+               {
+                 (GInterfaceInitFunc) tny_mime_part_view_init, /* interface_init */
+                 NULL,         /* interface_finalize */
+                 NULL          /* interface_data */
+               };
+
+               static const GInterfaceInfo modest_zoomable_info = 
+               {
+                 (GInterfaceInitFunc) modest_zoomable_init, /* interface_init */
+                 NULL,         /* interface_finalize */
+                 NULL          /* interface_data */
+               };
+
                my_type = g_type_register_static (GTK_TYPE_CONTAINER,
                                                  "ModestMsgView",
                                                  &my_info, 0);
                my_type = g_type_register_static (GTK_TYPE_CONTAINER,
                                                  "ModestMsgView",
                                                  &my_info, 0);
+
+               g_type_add_interface_static (my_type, TNY_TYPE_MIME_PART_VIEW, 
+                       &tny_mime_part_view_info);
+
+               g_type_add_interface_static (my_type, TNY_TYPE_MSG_VIEW, 
+                       &tny_msg_view_info);
+
+               g_type_add_interface_static (my_type, MODEST_TYPE_ZOOMABLE, 
+                       &modest_zoomable_info);
        }
        return my_type;
 }
        }
        return my_type;
 }
@@ -205,6 +271,18 @@ modest_msg_view_class_init (ModestMsgViewClass *klass)
        container_class->remove = container_remove;
 
        klass->set_scroll_adjustments = set_scroll_adjustments;
        container_class->remove = container_remove;
 
        klass->set_scroll_adjustments = set_scroll_adjustments;
+       klass->get_part_func = modest_msg_view_mp_get_part_default;
+       klass->set_part_func = modest_msg_view_mp_set_part_default;
+       klass->get_msg_func = modest_msg_view_get_msg_default;
+       klass->set_msg_func = modest_msg_view_set_msg_default;
+       klass->set_unavailable_func = modest_msg_view_set_unavailable_default;
+       klass->clear_func = modest_msg_view_clear_default;
+       klass->create_mime_part_view_for_func = modest_msg_view_create_mime_part_view_for_default;
+       klass->create_new_inline_viewer_func = modest_msg_view_create_new_inline_viewer_default;
+       klass->get_zoom_func = modest_msg_view_get_zoom_default;
+       klass->set_zoom_func = modest_msg_view_set_zoom_default;
+       klass->zoom_minus_func = modest_msg_view_zoom_minus_default;
+       klass->zoom_plus_func = modest_msg_view_zoom_plus_default;
 
        g_type_class_add_private (gobject_class, sizeof(ModestMsgViewPrivate));
 
 
        g_type_class_add_private (gobject_class, sizeof(ModestMsgViewPrivate));
 
@@ -468,7 +546,7 @@ set_scroll_adjustments (ModestMsgView *msg_view,
        modest_msg_view_set_hadjustment (msg_view, hadj);
        modest_msg_view_set_vadjustment (msg_view, vadj);
 
        modest_msg_view_set_hadjustment (msg_view, hadj);
        modest_msg_view_set_vadjustment (msg_view, vadj);
 
-       gtk_container_set_focus_vadjustment (GTK_CONTAINER (priv->gtkhtml), vadj);
+       gtk_container_set_focus_vadjustment (GTK_CONTAINER (priv->body_view), vadj);
 }
 
 static void
 }
 
 static void
@@ -492,7 +570,7 @@ realize (GtkWidget *widget)
         *      widgets inside.
         *    * headers_window: gdk window for headers_box.
         *    * html_window: gdk window for html_scroll (the scrolled window containing the
         *      widgets inside.
         *    * headers_window: gdk window for headers_box.
         *    * html_window: gdk window for html_scroll (the scrolled window containing the
-        *      gtkhtml showing the contents of the mail).
+        *      body view showing the contents of the mail).
         */
 
        attributes.x = widget->allocation.x;
         */
 
        attributes.x = widget->allocation.x;
@@ -856,6 +934,7 @@ modest_msg_view_init (ModestMsgView *obj)
 {
        ModestMsgViewPrivate *priv;
        GtkAdjustment *html_vadj;
 {
        ModestMsgViewPrivate *priv;
        GtkAdjustment *html_vadj;
+       GtkWidget *separator;
 
        GTK_WIDGET_UNSET_FLAGS (obj, GTK_NO_WINDOW);
        gtk_widget_set_redraw_on_allocate (GTK_WIDGET (obj), TRUE);
 
        GTK_WIDGET_UNSET_FLAGS (obj, GTK_NO_WINDOW);
        gtk_widget_set_redraw_on_allocate (GTK_WIDGET (obj), TRUE);
@@ -882,23 +961,17 @@ modest_msg_view_init (ModestMsgView *obj)
 
        priv->msg                     = NULL;
 
 
        priv->msg                     = NULL;
 
-       priv->gtkhtml                 = gtk_html_new();
-       gtk_html_set_editable        (GTK_HTML(priv->gtkhtml), FALSE);
-       gtk_html_allow_selection     (GTK_HTML(priv->gtkhtml), TRUE);
-       gtk_html_set_caret_mode      (GTK_HTML(priv->gtkhtml), FALSE);
-       gtk_html_set_blocking        (GTK_HTML(priv->gtkhtml), FALSE);
-       gtk_html_set_images_blocking (GTK_HTML(priv->gtkhtml), FALSE);
-
+       priv->body_view                 = GTK_WIDGET (g_object_new (MODEST_TYPE_GTKHTML_MIME_PART_VIEW, NULL));
        priv->mail_header_view        = GTK_WIDGET(modest_mail_header_view_new (TRUE));
        gtk_widget_set_no_show_all (priv->mail_header_view, TRUE);
 
        priv->attachments_view        = GTK_WIDGET(modest_attachments_view_new (NULL));
 
        priv->mail_header_view        = GTK_WIDGET(modest_mail_header_view_new (TRUE));
        gtk_widget_set_no_show_all (priv->mail_header_view, TRUE);
 
        priv->attachments_view        = GTK_WIDGET(modest_attachments_view_new (NULL));
 
-       priv->sig1 = g_signal_connect (G_OBJECT(priv->gtkhtml), "link_clicked",
-                                      G_CALLBACK(on_link_clicked), obj);
-       priv->sig2 = g_signal_connect (G_OBJECT(priv->gtkhtml), "url_requested",
-                                      G_CALLBACK(on_url_requested), obj);
-       priv->sig3 = g_signal_connect (G_OBJECT(priv->gtkhtml), "on_url",
+       priv->sig1 = g_signal_connect (G_OBJECT(priv->body_view), "activate_link",
+                                      G_CALLBACK(on_activate_link), obj);
+       priv->sig2 = g_signal_connect (G_OBJECT(priv->body_view), "fetch_url",
+                                      G_CALLBACK(on_fetch_url), obj);
+       priv->sig3 = g_signal_connect (G_OBJECT(priv->body_view), "link_hover",
                                       G_CALLBACK(on_link_hover), obj);
 
        g_signal_connect (G_OBJECT (priv->mail_header_view), "recpt-activated", 
                                       G_CALLBACK(on_link_hover), obj);
 
        g_signal_connect (G_OBJECT (priv->mail_header_view), "recpt-activated", 
@@ -912,6 +985,40 @@ modest_msg_view_init (ModestMsgView *obj)
        g_signal_connect (G_OBJECT (html_vadj), "changed",
                          G_CALLBACK (html_adjustment_changed), obj);
 
        g_signal_connect (G_OBJECT (html_vadj), "changed",
                          G_CALLBACK (html_adjustment_changed), obj);
 
+       gtk_widget_push_composite_child ();
+       priv->headers_box = gtk_vbox_new (0, FALSE);
+       gtk_widget_set_composite_name (priv->headers_box, "headers");
+       gtk_widget_pop_composite_child ();
+
+       if (priv->mail_header_view)
+               gtk_box_pack_start (GTK_BOX(priv->headers_box), priv->mail_header_view, FALSE, FALSE, 0);
+       
+       if (priv->attachments_view) {
+               gchar *att_label = g_strconcat (_("mcen_me_viewer_attachments"), ":", NULL);
+
+               priv->attachments_box = (GtkWidget *)
+                       modest_mail_header_view_add_custom_header (MODEST_MAIL_HEADER_VIEW (priv->mail_header_view),
+                                                                  att_label,
+                                                                  priv->attachments_view,
+                                                                  FALSE, FALSE);
+               gtk_widget_hide_all (priv->attachments_box);
+               g_free (att_label);
+       }
+
+       separator = gtk_hseparator_new ();
+       gtk_box_pack_start (GTK_BOX(priv->headers_box), separator, FALSE, FALSE, 0);
+
+       gtk_widget_set_parent (priv->headers_box, GTK_WIDGET (obj));
+
+       if (priv->body_view) {
+               gtk_container_add (GTK_CONTAINER (priv->html_scroll), priv->body_view);
+               gtk_widget_set_parent (priv->html_scroll, GTK_WIDGET(obj));
+#ifdef MAEMO_CHANGES
+               gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->body_view), NULL, NULL, 0);
+               g_signal_connect (G_OBJECT (priv->body_view), "tap-and-hold", G_CALLBACK (on_tap_and_hold), obj);
+#endif
+       }
+
 }
        
 
 }
        
 
@@ -926,13 +1033,13 @@ modest_msg_view_finalize (GObject *obj)
                priv->msg = NULL;
        }
        
                priv->msg = NULL;
        }
        
-       /* we cannot disconnect sigs, because priv->gtkhtml is
+       /* we cannot disconnect sigs, because priv->body_view is
         * already dead */
        
        disconnect_vadjustment (MODEST_MSG_VIEW(obj));
        disconnect_hadjustment (MODEST_MSG_VIEW(obj));
 
         * already dead */
        
        disconnect_vadjustment (MODEST_MSG_VIEW(obj));
        disconnect_hadjustment (MODEST_MSG_VIEW(obj));
 
-       priv->gtkhtml = NULL;
+       priv->body_view = NULL;
        priv->attachments_view = NULL;
 
        G_OBJECT_CLASS(parent_class)->finalize (obj);           
        priv->attachments_view = NULL;
 
        G_OBJECT_CLASS(parent_class)->finalize (obj);           
@@ -1079,49 +1186,10 @@ modest_msg_view_new (TnyMsg *msg)
 {
        GObject *obj;
        ModestMsgView* self;
 {
        GObject *obj;
        ModestMsgView* self;
-       ModestMsgViewPrivate *priv;
-       GtkWidget *separator;
        
        obj  = G_OBJECT(g_object_new(MODEST_TYPE_MSG_VIEW, NULL));
        self = MODEST_MSG_VIEW(obj);
        
        obj  = G_OBJECT(g_object_new(MODEST_TYPE_MSG_VIEW, NULL));
        self = MODEST_MSG_VIEW(obj);
-       priv = MODEST_MSG_VIEW_GET_PRIVATE (self);
-
-       gtk_widget_push_composite_child ();
-       priv->headers_box = gtk_vbox_new (0, FALSE);
-       gtk_widget_set_composite_name (priv->headers_box, "headers");
-       gtk_widget_pop_composite_child ();
-
-       if (priv->mail_header_view)
-               gtk_box_pack_start (GTK_BOX(priv->headers_box), priv->mail_header_view, FALSE, FALSE, 0);
-       
-       if (priv->attachments_view) {
-               gchar *att_label = g_strconcat (_("mcen_me_viewer_attachments"), ":", NULL);
-
-               priv->attachments_box = (GtkWidget *)
-                       modest_mail_header_view_add_custom_header (MODEST_MAIL_HEADER_VIEW (priv->mail_header_view),
-                                                                  att_label,
-                                                                  priv->attachments_view,
-                                                                  FALSE, FALSE);
-               gtk_widget_hide_all (priv->attachments_box);
-               g_free (att_label);
-/*             gtk_widget_set_no_show_all (priv->attachments_box, TRUE); */
-       }
-
-       separator = gtk_hseparator_new ();
-       gtk_box_pack_start (GTK_BOX(priv->headers_box), separator, FALSE, FALSE, 0);
-
-       gtk_widget_set_parent (priv->headers_box, GTK_WIDGET (self));
-
-       if (priv->gtkhtml) {
-               gtk_container_add (GTK_CONTAINER (priv->html_scroll), priv->gtkhtml);
-               gtk_widget_set_parent (priv->html_scroll, GTK_WIDGET(self));
-#ifdef MAEMO_CHANGES
-               gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->gtkhtml), NULL, NULL, 0);
-               g_signal_connect (G_OBJECT (priv->gtkhtml), "tap-and-hold", G_CALLBACK (on_tap_and_hold), obj);
-#endif
-       }
-
-       modest_msg_view_set_message (self, msg);
+       tny_msg_view_set_msg (TNY_MSG_VIEW (self), msg);
 
        return GTK_WIDGET(self);
 }
 
        return GTK_WIDGET(self);
 }
@@ -1156,7 +1224,7 @@ on_attachment_activated (ModestAttachmentsView * att_view, TnyMimePart *mime_par
 }
 
 static gboolean
 }
 
 static gboolean
-on_link_clicked (GtkWidget *widget, const gchar *uri, ModestMsgView *msg_view)
+on_activate_link (GtkWidget *widget, const gchar *uri, ModestMsgView *msg_view)
 {
        g_return_val_if_fail (msg_view, FALSE);
        
 {
        g_return_val_if_fail (msg_view, FALSE);
        
@@ -1200,14 +1268,42 @@ find_cid_image (TnyMsg *msg, const gchar *cid)
        
        while (!tny_iterator_is_done(iter)) {
                const gchar *part_cid;
        
        while (!tny_iterator_is_done(iter)) {
                const gchar *part_cid;
+
                part = TNY_MIME_PART(tny_iterator_get_current(iter));
                part_cid = tny_mime_part_get_content_id (part);
 
                if (part_cid && strcmp (cid, part_cid) == 0)
                        break;
 
                part = TNY_MIME_PART(tny_iterator_get_current(iter));
                part_cid = tny_mime_part_get_content_id (part);
 
                if (part_cid && strcmp (cid, part_cid) == 0)
                        break;
 
-               if (part)
-                       g_object_unref (G_OBJECT(part));
+               if (tny_mime_part_content_type_is (part, "multipart/related")) {
+                       TnyList *related_parts = TNY_LIST (tny_simple_list_new ());
+                       TnyIterator *related_iter = NULL;
+                       TnyMimePart *related_part = NULL;
+
+                       tny_mime_part_get_parts (part, related_parts);
+                       related_iter = tny_list_create_iterator (related_parts);
+
+                       while (!tny_iterator_is_done (related_iter)) {
+                               related_part = TNY_MIME_PART (tny_iterator_get_current (related_iter));
+                               part_cid = tny_mime_part_get_content_id (related_part);
+                               if (part_cid && strcmp (cid, part_cid) == 0) {
+                                       break;
+                               }
+                               g_object_unref (related_part);
+                               related_part = NULL;
+                               tny_iterator_next (related_iter);
+                       }
+
+                       g_object_unref (related_iter);
+                       g_object_unref (related_parts);
+                       if (related_part != NULL) {
+                               g_object_unref (part);
+                               part = related_part;
+                               break;
+                       }
+               }
+
+               g_object_unref (G_OBJECT(part));
        
                part = NULL;
                tny_iterator_next (iter);
        
                part = NULL;
                tny_iterator_next (iter);
@@ -1221,126 +1317,34 @@ find_cid_image (TnyMsg *msg, const gchar *cid)
 
 
 static gboolean
 
 
 static gboolean
-on_url_requested (GtkWidget *widget, const gchar *uri,
-                 GtkHTMLStream *stream, ModestMsgView *msg_view)
+on_fetch_url (GtkWidget *widget, const gchar *uri,
+             TnyStream *stream, ModestMsgView *msg_view)
 {
        ModestMsgViewPrivate *priv;
        priv = MODEST_MSG_VIEW_GET_PRIVATE (msg_view);
 {
        ModestMsgViewPrivate *priv;
        priv = MODEST_MSG_VIEW_GET_PRIVATE (msg_view);
+       gboolean result = FALSE;
        
        if (g_str_has_prefix (uri, "cid:")) {
                /* +4 ==> skip "cid:" */
                TnyMimePart *part = find_cid_image (priv->msg, uri + 4);
                if (!part) {
                        g_printerr ("modest: '%s' not found\n", uri + 4);
        
        if (g_str_has_prefix (uri, "cid:")) {
                /* +4 ==> skip "cid:" */
                TnyMimePart *part = find_cid_image (priv->msg, uri + 4);
                if (!part) {
                        g_printerr ("modest: '%s' not found\n", uri + 4);
-                       gtk_html_stream_close (stream, GTK_HTML_STREAM_ERROR);
+                       result = FALSE;
                } else {
                } else {
-                       TnyStream *tny_stream =
-                               TNY_STREAM(modest_tny_stream_gtkhtml_new(stream));
                        tny_mime_part_decode_to_stream ((TnyMimePart*)part,
                        tny_mime_part_decode_to_stream ((TnyMimePart*)part,
-                                                                 tny_stream);
-                       gtk_html_stream_close (stream, GTK_HTML_STREAM_OK);
-       
-                       g_object_unref (G_OBJECT(tny_stream));
+                                                       stream);
                        g_object_unref (G_OBJECT(part));
                        g_object_unref (G_OBJECT(part));
+                       result = TRUE;
                }
                }
+       } else {
+               return TRUE;
        }
 
        }
 
-       return TRUE;
-}
-
-static gboolean
-set_html_message (ModestMsgView *self, TnyMimePart *tny_body, TnyMsg *msg)
-{
-       GtkHTMLStream *gtkhtml_stream;
-       TnyStream *tny_stream;  
-       ModestMsgViewPrivate *priv;
-       
-       g_return_val_if_fail (self, FALSE);
-       g_return_val_if_fail (tny_body, FALSE);
-       
-       priv = MODEST_MSG_VIEW_GET_PRIVATE(self);
-
-       gtkhtml_stream = gtk_html_begin(GTK_HTML(priv->gtkhtml));
-
-       tny_stream     = TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream));
-       tny_stream_reset (tny_stream);
-
-       tny_mime_part_decode_to_stream ((TnyMimePart*)tny_body, tny_stream);
-       g_object_unref (G_OBJECT(tny_stream));
-       
-       gtk_html_stream_destroy (gtkhtml_stream);
-       
-       return TRUE;
-}
-
-
-/* FIXME: this is a hack --> we use the tny_text_buffer_stream to
- * get the message text, then write to gtkhtml 'by hand' */
-static gboolean
-set_text_message (ModestMsgView *self, TnyMimePart *tny_body, TnyMsg *msg)
-{
-       GtkTextBuffer *buf;
-       GtkTextIter begin, end;
-       TnyStream* txt_stream, *tny_stream;
-       GtkHTMLStream *gtkhtml_stream;
-       gchar *txt;
-       ModestMsgViewPrivate *priv;
-               
-       g_return_val_if_fail (self, FALSE);
-       g_return_val_if_fail (tny_body, FALSE);
-
-       priv           = MODEST_MSG_VIEW_GET_PRIVATE(self);
-       
-       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(priv->gtkhtml)); 
-       tny_stream =  TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream));
-       
-       // FIXME: tinymail
-       tny_mime_part_decode_to_stream ((TnyMimePart*)tny_body, 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);
-       }
-       
-       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);
-       
-       return TRUE;
-}
-
-
-static gboolean
-set_empty_message (ModestMsgView *self)
-{
-       ModestMsgViewPrivate *priv;
-       
-       g_return_val_if_fail (self, FALSE);
-       priv           = MODEST_MSG_VIEW_GET_PRIVATE(self);
-
-       gtk_html_load_from_string (GTK_HTML(priv->gtkhtml),
-                                  "", 1);
-
-       
-       return TRUE;
+       return result;
 }
 
 }
 
-
-void
-modest_msg_view_set_message (ModestMsgView *self, TnyMsg *msg)
+static void
+set_message (ModestMsgView *self, TnyMsg *msg)
 {
        TnyMimePart *body;
        ModestMsgViewPrivate *priv;
 {
        TnyMimePart *body;
        ModestMsgViewPrivate *priv;
@@ -1366,7 +1370,7 @@ modest_msg_view_set_message (ModestMsgView *self, TnyMsg *msg)
                gtk_widget_hide_all (priv->mail_header_view);
                gtk_widget_hide_all (priv->attachments_box);
                gtk_widget_set_no_show_all (priv->mail_header_view, TRUE);
                gtk_widget_hide_all (priv->mail_header_view);
                gtk_widget_hide_all (priv->attachments_box);
                gtk_widget_set_no_show_all (priv->mail_header_view, TRUE);
-               set_empty_message (self);
+               tny_mime_part_view_clear (TNY_MIME_PART_VIEW (priv->body_view));
                gtk_widget_queue_resize (GTK_WIDGET(self));
                gtk_widget_queue_draw (GTK_WIDGET(self));
                return;
                gtk_widget_queue_resize (GTK_WIDGET(self));
                gtk_widget_queue_draw (GTK_WIDGET(self));
                return;
@@ -1381,10 +1385,7 @@ modest_msg_view_set_message (ModestMsgView *self, TnyMsg *msg)
        
        body = modest_tny_msg_find_body_part (msg, TRUE);
        if (body) {
        
        body = modest_tny_msg_find_body_part (msg, TRUE);
        if (body) {
-               if (tny_mime_part_content_type_is (body, "text/html"))
-                       set_html_message (self, body, msg);
-               else
-                       set_text_message (self, body, msg);
+               tny_mime_part_view_set_part (TNY_MIME_PART_VIEW (priv->body_view), body);
 
                if(modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view))) {
                        gtk_widget_show_all (priv->attachments_box);
 
                if(modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view))) {
                        gtk_widget_show_all (priv->attachments_box);
@@ -1392,21 +1393,13 @@ modest_msg_view_set_message (ModestMsgView *self, TnyMsg *msg)
                        gtk_widget_hide_all (priv->attachments_box);
                }
 
                        gtk_widget_hide_all (priv->attachments_box);
                }
 
-/*             g_print ("---\nfilename %s\ncontent_location %s\ncontent_id%s\ncontent_type%s\n", */
-/*                      tny_mime_part_get_filename (body), */
-/*                      tny_mime_part_get_content_location (body), */
-/*                      tny_mime_part_get_content_id (body), */
-/*                      tny_mime_part_get_content_type (body)); */
-                       
        } else 
        } else 
-               set_empty_message (self);
+               tny_mime_part_view_clear (TNY_MIME_PART_VIEW (priv->body_view));
 
 
-       gtk_widget_show (priv->gtkhtml);
+       gtk_widget_show (priv->body_view);
        gtk_widget_set_no_show_all (priv->attachments_box, TRUE);
        gtk_widget_show_all (priv->mail_header_view);
        gtk_widget_set_no_show_all (priv->attachments_box, FALSE);
        gtk_widget_set_no_show_all (priv->attachments_box, TRUE);
        gtk_widget_show_all (priv->mail_header_view);
        gtk_widget_set_no_show_all (priv->attachments_box, FALSE);
-/*     gtk_widget_show_all (priv->attachments_box); */
-/*     gtk_widget_show_all (priv->attachments_box); */
        gtk_widget_set_no_show_all (priv->mail_header_view, TRUE);
        gtk_widget_queue_resize (GTK_WIDGET(self));
        gtk_widget_queue_draw (GTK_WIDGET(self));
        gtk_widget_set_no_show_all (priv->mail_header_view, TRUE);
        gtk_widget_queue_resize (GTK_WIDGET(self));
        gtk_widget_queue_draw (GTK_WIDGET(self));
@@ -1428,8 +1421,8 @@ modest_msg_view_set_message (ModestMsgView *self, TnyMsg *msg)
 }
 
 
 }
 
 
-TnyMsg*
-modest_msg_view_get_message (ModestMsgView *self)
+static TnyMsg*
+get_message (ModestMsgView *self)
 {
        TnyMsg *msg;
 
 {
        TnyMsg *msg;
 
@@ -1443,32 +1436,225 @@ modest_msg_view_get_message (ModestMsgView *self)
        return msg;
 }
 
        return msg;
 }
 
+gboolean 
+modest_msg_view_get_message_is_empty (ModestMsgView *self)
+{
+       ModestMsgViewPrivate *priv = MODEST_MSG_VIEW_GET_PRIVATE (self);
+
+       return modest_mime_part_view_is_empty (MODEST_MIME_PART_VIEW (priv->body_view));
+}
+
+/* TNY MSG IMPLEMENTATION */
+
+static void
+tny_msg_view_init (gpointer g, gpointer iface_data)
+{
+       TnyMsgViewIface *klass = (TnyMsgViewIface *)g;
+
+       klass->get_msg_func = modest_msg_view_get_msg;
+       klass->set_msg_func = modest_msg_view_set_msg;
+       klass->set_unavailable_func = modest_msg_view_set_unavailable;
+       klass->clear_func = modest_msg_view_clear;
+       klass->create_mime_part_view_for_func = modest_msg_view_create_mime_part_view_for;
+       klass->create_new_inline_viewer_func = modest_msg_view_create_new_inline_viewer;
+
+       return;
+}
+
+static TnyMsg *
+modest_msg_view_get_msg (TnyMsgView *self)
+{
+       return MODEST_MSG_VIEW_GET_CLASS (self)->get_msg_func (self);
+}
+
+static TnyMsg *
+modest_msg_view_get_msg_default (TnyMsgView *self)
+{
+       return TNY_MSG (tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (self)));
+}
+
+static void
+modest_msg_view_set_msg (TnyMsgView *self, TnyMsg *msg)
+{
+       MODEST_MSG_VIEW_GET_CLASS (self)->set_msg_func (self, msg);
+}
+
+static void 
+modest_msg_view_set_msg_default (TnyMsgView *self, TnyMsg *msg)
+{
+
+       tny_mime_part_view_set_part (TNY_MIME_PART_VIEW (self), TNY_MIME_PART (msg));
+
+       return;
+}
+
+static void
+modest_msg_view_set_unavailable (TnyMsgView *self)
+{
+       MODEST_MSG_VIEW_GET_CLASS (self)->set_unavailable_func (self);
+}
+
+static void
+modest_msg_view_set_unavailable_default (TnyMsgView *self)
+{
+       tny_msg_view_clear (self);
+
+       return;
+}
+
+static void
+modest_msg_view_clear (TnyMsgView *self)
+{
+       MODEST_MSG_VIEW_GET_CLASS (self)->clear_func (self);
+}
+
+static void
+modest_msg_view_clear_default (TnyMsgView *self)
+{
+       set_message (MODEST_MSG_VIEW (self), NULL);
+}
+
+static TnyMimePartView*
+modest_msg_view_create_mime_part_view_for (TnyMsgView *self, TnyMimePart *part)
+{
+       return MODEST_MSG_VIEW_GET_CLASS (self)->create_mime_part_view_for_func (self, part);
+}
+
+static TnyMimePartView*
+modest_msg_view_create_mime_part_view_for_default (TnyMsgView *self, TnyMimePart *part)
+{
+       g_warning ("modest_msg_view_create_mime_part_view_for_default is not implemented");
+       return NULL;
+}
+
+static TnyMsgView*
+modest_msg_view_create_new_inline_viewer (TnyMsgView *self)
+{
+       return MODEST_MSG_VIEW_GET_CLASS (self)->create_new_inline_viewer_func (self);
+}
+
+static TnyMsgView*
+modest_msg_view_create_new_inline_viewer_default (TnyMsgView *self)
+{
+       g_warning ("modest_msg_view_create_new_inline_viewer_default is not implemented");
+
+       return NULL;
+}
+
+/* TNY MIME PART IMPLEMENTATION */
+
+static void
+tny_mime_part_view_init (gpointer g, gpointer iface_data)
+{
+       TnyMimePartViewIface *klass = (TnyMimePartViewIface *)g;
+
+       klass->get_part_func = modest_msg_view_mp_get_part;
+       klass->set_part_func = modest_msg_view_mp_set_part;
+       klass->clear_func = modest_msg_view_mp_clear;
+
+       return;
+}
+
+static TnyMimePart* 
+modest_msg_view_mp_get_part (TnyMimePartView *self)
+{
+       return MODEST_MSG_VIEW_GET_CLASS (self)->get_part_func (self);
+}
+
+
+static TnyMimePart* 
+modest_msg_view_mp_get_part_default (TnyMimePartView *self)
+{
+       return TNY_MIME_PART (get_message (MODEST_MSG_VIEW (self)));
+}
+
+static void
+modest_msg_view_mp_set_part (TnyMimePartView *self,
+                            TnyMimePart *part)
+{
+       MODEST_MSG_VIEW_GET_CLASS (self)->set_part_func (self, part);
+}
+
+static void
+modest_msg_view_mp_set_part_default (TnyMimePartView *self,
+                                    TnyMimePart *part)
+{
+       g_return_if_fail ((part == NULL) || TNY_IS_MSG (part));
+
+       set_message (MODEST_MSG_VIEW (self), TNY_MSG (part));
+}
+
+static void
+modest_msg_view_mp_clear (TnyMimePartView *self)
+{
+       tny_msg_view_clear (TNY_MSG_VIEW (self));
+}
+
+/* MODEST ZOOMABLE IMPLEMENTATION */
+static void
+modest_zoomable_init (gpointer g, gpointer iface_data)
+{
+       ModestZoomableIface *klass = (ModestZoomableIface *)g;
+
+       klass->get_zoom_func = modest_msg_view_get_zoom;
+       klass->set_zoom_func = modest_msg_view_set_zoom;
+       klass->zoom_minus_func = modest_msg_view_zoom_minus;
+       klass->zoom_plus_func = modest_msg_view_zoom_plus;
+
+       return;
+}
+
+static gdouble
+modest_msg_view_get_zoom (ModestZoomable *self)
+{
+       return MODEST_MSG_VIEW_GET_CLASS (self)->get_zoom_func (self);
+}
+
+static gdouble
+modest_msg_view_get_zoom_default (ModestZoomable *self)
+{
+       return get_zoom (MODEST_MSG_VIEW (self));
+}
+
+static void
+modest_msg_view_set_zoom (ModestZoomable *self, gdouble value)
+{
+       MODEST_MSG_VIEW_GET_CLASS (self)->set_zoom_func (self, value);
+}
+
+static void
+modest_msg_view_set_zoom_default (ModestZoomable *self, gdouble value)
+{
+       set_zoom (MODEST_MSG_VIEW (self), value);
+}
+
 static gboolean
 static gboolean
-has_contents_receiver (gpointer engine, const gchar *data,
-                      size_t len, gboolean *has_contents)
+modest_msg_view_zoom_minus (ModestZoomable *self)
 {
 {
-       if (len > 1 || ((len == 1)&&(data[0]!='\n'))) {
-               *has_contents = TRUE;
-               return FALSE;
-       }
-       return TRUE;
+       return MODEST_MSG_VIEW_GET_CLASS (self)->zoom_minus_func (self);
 }
 
 }
 
-gboolean 
-modest_msg_view_get_message_is_empty (ModestMsgView *self)
+static gboolean
+modest_msg_view_zoom_minus_default (ModestZoomable *self)
 {
 {
-       /* TODO: Find some gtkhtml API to check whether there is any (visible, non markup)
-        * text in the message:
-        */
-       ModestMsgViewPrivate *priv = MODEST_MSG_VIEW_GET_PRIVATE (self);
-       gboolean has_contents = FALSE;
+       /* operation not supported in ModestMsgView */
+       return FALSE;
+}
 
 
-       gtk_html_export (GTK_HTML (priv->gtkhtml), "text/plain", 
-                        (GtkHTMLSaveReceiverFn) has_contents_receiver, &has_contents);
-       
-       return !has_contents;
+static gboolean
+modest_msg_view_zoom_plus (ModestZoomable *self)
+{
+       return MODEST_MSG_VIEW_GET_CLASS (self)->zoom_plus_func (self);
+}
+
+static gboolean
+modest_msg_view_zoom_plus_default (ModestZoomable *self)
+{
+       /* operation not supported in ModestMsgView */
+       return FALSE;
 }
 
 }
 
+/* INCREMENTAL SEARCH IMPLEMENTATION */
 
 gboolean 
 modest_msg_view_search (ModestMsgView *self, const gchar *search)
 
 gboolean 
 modest_msg_view_search (ModestMsgView *self, const gchar *search)
@@ -1481,21 +1667,18 @@ modest_msg_view_search (ModestMsgView *self, const gchar *search)
        g_return_val_if_fail (MODEST_IS_MSG_VIEW (self), FALSE);
 
        priv = MODEST_MSG_VIEW_GET_PRIVATE (self);
        g_return_val_if_fail (MODEST_IS_MSG_VIEW (self), FALSE);
 
        priv = MODEST_MSG_VIEW_GET_PRIVATE (self);
-       vadj = gtk_layout_get_vadjustment (GTK_LAYOUT (priv->gtkhtml));
+       vadj = gtk_layout_get_vadjustment (GTK_LAYOUT (priv->body_view));
        g_object_ref (vadj);
        tmp_vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, vadj->lower, vadj->upper, vadj->step_increment, 32.0, 32.0));
        g_object_ref (vadj);
        tmp_vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, vadj->lower, vadj->upper, vadj->step_increment, 32.0, 32.0));
-       gtk_layout_set_vadjustment (GTK_LAYOUT (priv->gtkhtml), tmp_vadj);
-       result = gtk_html_engine_search (GTK_HTML (priv->gtkhtml),
-                                        search,
-                                        FALSE,   /* case sensitive */
-                                        TRUE,    /* forward */
-                                        FALSE);  /* regexp */
+       gtk_layout_set_vadjustment (GTK_LAYOUT (priv->body_view), tmp_vadj);
+       result = modest_isearch_view_search (MODEST_ISEARCH_VIEW (priv->body_view),
+                                            search);
 
        if (result) {
                gint x, y, w, h;
                gdouble offset_top, offset_bottom;
                GtkAdjustment *adj;
 
        if (result) {
                gint x, y, w, h;
                gdouble offset_top, offset_bottom;
                GtkAdjustment *adj;
-               gtk_html_get_selection_area (GTK_HTML (priv->gtkhtml), &x, &y, &w, &h);
+               modest_isearch_view_get_selection_area (MODEST_ISEARCH_VIEW (priv->body_view), &x, &y, &w, &h);
                offset_top = (gdouble) (priv->headers_box->requisition.height + y);
                offset_bottom = (gdouble) (priv->headers_box->requisition.height + y + h);
                adj = GTK_ADJUSTMENT (priv->vadj);
                offset_top = (gdouble) (priv->headers_box->requisition.height + y);
                offset_bottom = (gdouble) (priv->headers_box->requisition.height + y + h);
                adj = GTK_ADJUSTMENT (priv->vadj);
@@ -1506,7 +1689,7 @@ modest_msg_view_search (ModestMsgView *self, const gchar *search)
        }
 
        y_offset = tmp_vadj->value;
        }
 
        y_offset = tmp_vadj->value;
-       gtk_layout_set_vadjustment (GTK_LAYOUT (priv->gtkhtml), vadj);
+       gtk_layout_set_vadjustment (GTK_LAYOUT (priv->body_view), vadj);
        g_object_unref (vadj);
 
        return result;
        g_object_unref (vadj);
 
        return result;
@@ -1521,14 +1704,13 @@ modest_msg_view_search_next (ModestMsgView *self)
        g_return_val_if_fail (MODEST_IS_MSG_VIEW (self), FALSE);
 
        priv = MODEST_MSG_VIEW_GET_PRIVATE (self);
        g_return_val_if_fail (MODEST_IS_MSG_VIEW (self), FALSE);
 
        priv = MODEST_MSG_VIEW_GET_PRIVATE (self);
-       result = gtk_html_engine_search_next (GTK_HTML (priv->gtkhtml));
+       result = modest_isearch_view_search_next (MODEST_ISEARCH_VIEW (priv->body_view));
 
        if (result) {
                gint x, y, w, h;
                gdouble offset_top, offset_bottom;
                GtkAdjustment *adj;
 
        if (result) {
                gint x, y, w, h;
                gdouble offset_top, offset_bottom;
                GtkAdjustment *adj;
-               gtk_html_get_selection_area (GTK_HTML (priv->gtkhtml), &x, &y, &w, &h);
-               g_message ("SELECTION AREA x%d y%d w%d h%d", x, y, w, h);
+               modest_isearch_view_get_selection_area (MODEST_ISEARCH_VIEW (priv->body_view), &x, &y, &w, &h);
                offset_top = (gdouble) (priv->headers_box->requisition.height + y);
                offset_bottom = (gdouble) (priv->headers_box->requisition.height + y + h);
                adj = GTK_ADJUSTMENT (priv->vadj);
                offset_top = (gdouble) (priv->headers_box->requisition.height + y);
                offset_bottom = (gdouble) (priv->headers_box->requisition.height + y + h);
                adj = GTK_ADJUSTMENT (priv->vadj);
@@ -1540,30 +1722,30 @@ modest_msg_view_search_next (ModestMsgView *self)
        return result;
 }
 
        return result;
 }
 
-void
-modest_msg_view_set_zoom (ModestMsgView *self, gdouble zoom)
+/* ZOOM IMPLEMENTATION */
+
+static void
+set_zoom (ModestMsgView *self, gdouble zoom)
 {
        ModestMsgViewPrivate *priv;
 
        g_return_if_fail (MODEST_IS_MSG_VIEW (self));
 {
        ModestMsgViewPrivate *priv;
 
        g_return_if_fail (MODEST_IS_MSG_VIEW (self));
-
        priv = MODEST_MSG_VIEW_GET_PRIVATE (self);
        priv = MODEST_MSG_VIEW_GET_PRIVATE (self);
-       priv->current_zoom = zoom;
-       gtk_html_set_magnification (GTK_HTML(priv->gtkhtml), zoom);
 
 
-       gtk_widget_queue_resize (priv->gtkhtml);
+       modest_zoomable_set_zoom (MODEST_ZOOMABLE(priv->body_view), zoom);
+
+       gtk_widget_queue_resize (priv->body_view);
 }
 
 }
 
-gdouble
-modest_msg_view_get_zoom (ModestMsgView *self)
+static gdouble
+get_zoom (ModestMsgView *self)
 {
        ModestMsgViewPrivate *priv;
 
        g_return_val_if_fail (MODEST_IS_MSG_VIEW (self), 1.0);
 {
        ModestMsgViewPrivate *priv;
 
        g_return_val_if_fail (MODEST_IS_MSG_VIEW (self), 1.0);
-
        priv = MODEST_MSG_VIEW_GET_PRIVATE (self);
 
        priv = MODEST_MSG_VIEW_GET_PRIVATE (self);
 
-       return priv->current_zoom;
+       return modest_zoomable_get_zoom (MODEST_ZOOMABLE (priv->body_view));
 }
 
 TnyHeaderFlags
 }
 
 TnyHeaderFlags
@@ -1624,20 +1806,18 @@ modest_msg_view_grab_focus (ModestMsgView *view)
        g_return_if_fail (MODEST_IS_MSG_VIEW (view));
        priv = MODEST_MSG_VIEW_GET_PRIVATE (view);
 
        g_return_if_fail (MODEST_IS_MSG_VIEW (view));
        priv = MODEST_MSG_VIEW_GET_PRIVATE (view);
 
-       gtk_widget_grab_focus (priv->gtkhtml);
+       gtk_widget_grab_focus (priv->body_view);
 }
 
 void
 modest_msg_view_remove_attachment (ModestMsgView *view, TnyMimePart *attachment)
 {
 }
 
 void
 modest_msg_view_remove_attachment (ModestMsgView *view, TnyMimePart *attachment)
 {
-       TnyMsg *msg;
        ModestMsgViewPrivate *priv;
 
        g_return_if_fail (MODEST_IS_MSG_VIEW (view));
        g_return_if_fail (TNY_IS_MIME_PART (attachment));
        priv = MODEST_MSG_VIEW_GET_PRIVATE (view);
 
        ModestMsgViewPrivate *priv;
 
        g_return_if_fail (MODEST_IS_MSG_VIEW (view));
        g_return_if_fail (TNY_IS_MIME_PART (attachment));
        priv = MODEST_MSG_VIEW_GET_PRIVATE (view);
 
-       msg = modest_msg_view_get_message (view);
        modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
                                                   attachment);
        
        modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
                                                   attachment);
        
index 067e236..80c0902 100644 (file)
@@ -35,6 +35,7 @@
 #include <tny-mime-part.h>
 #include <tny-msg-view.h>
 #include <widgets/modest-recpt-view.h>
 #include <tny-mime-part.h>
 #include <tny-msg-view.h>
 #include <widgets/modest-recpt-view.h>
+#include <widgets/modest-zoomable.h>
 
 G_BEGIN_DECLS
 
 
 G_BEGIN_DECLS
 
@@ -56,6 +57,23 @@ struct _ModestMsgView {
 struct _ModestMsgViewClass {
        GtkContainerClass parent_class;
 
 struct _ModestMsgViewClass {
        GtkContainerClass parent_class;
 
+       /* TnyMimePartView interface */
+       TnyMimePart* (*get_part_func) (TnyMimePartView *self);
+       void (*set_part_func) (TnyMimePartView *self, TnyMimePart *part);
+       /* TnyMsgView interface */
+       TnyMsg* (*get_msg_func) (TnyMsgView *self);
+       void (*set_msg_func) (TnyMsgView *self, TnyMsg *msg);
+       void (*set_unavailable_func) (TnyMsgView *self);
+       void (*clear_func) (TnyMsgView *self);
+       TnyMimePartView* (*create_mime_part_view_for_func) (TnyMsgView *self, TnyMimePart *part);
+       TnyMsgView* (*create_new_inline_viewer_func) (TnyMsgView *self);
+       /* ModestZoomable interface */
+       gdouble (*get_zoom_func) (ModestZoomable *self);
+       void (*set_zoom_func) (ModestZoomable *self, gdouble value);
+       gboolean (*zoom_minus_func) (ModestZoomable *self);
+       gboolean (*zoom_plus_func) (ModestZoomable *self);
+
+       /* signals */
        void (*set_scroll_adjustments)      (ModestMsgView *msg_view,
                                             GtkAdjustment *hadj,
                                             GtkAdjustment *vadj);
        void (*set_scroll_adjustments)      (ModestMsgView *msg_view,
                                             GtkAdjustment *hadj,
                                             GtkAdjustment *vadj);
@@ -97,28 +115,6 @@ GType        modest_msg_view_get_type    (void) G_GNUC_CONST;
 GtkWidget*   modest_msg_view_new          (TnyMsg *tny_msg);
 
 
 GtkWidget*   modest_msg_view_new          (TnyMsg *tny_msg);
 
 
-/**
- * modest_msg_view_set_message
- * @self: a ModestMsgView instance
- * @tny_msg: a TnyMsg instance, or NULL
- *
- * display the @tny_msg e-mail message. If @tny_msg is NULL,
- * then a blank page will be displayed
- *  */
-void         modest_msg_view_set_message  (ModestMsgView *self, TnyMsg *tny_msg);
-
-
-
-/**
- * modest_msg_view_set_message
- * @self: a ModestMsgView instance
- *
- * gets a new reference the #TnyMsg of the message view. The caller
- * must free the new reference
- *
- * Returns: the message or NULL
- */
-TnyMsg*      modest_msg_view_get_message  (ModestMsgView *self);
 
 /**
  * modest_msg_view_get_message_is_empty
 
 /**
  * modest_msg_view_get_message_is_empty
@@ -140,8 +136,6 @@ GtkShadowType modest_msg_view_get_shadow_type (ModestMsgView *self);
 
 gboolean modest_msg_view_search (ModestMsgView *self, const gchar *search);
 gboolean modest_msg_view_search_next (ModestMsgView *self);
 
 gboolean modest_msg_view_search (ModestMsgView *self, const gchar *search);
 gboolean modest_msg_view_search_next (ModestMsgView *self);
-void modest_msg_view_set_zoom (ModestMsgView *self, gdouble zoom);
-gdouble modest_msg_view_get_zoom (ModestMsgView *self);
 TnyHeaderFlags modest_msg_view_get_priority (ModestMsgView *self);
 void modest_msg_view_set_priority (ModestMsgView *self, TnyHeaderFlags flags);
 GList *modest_msg_view_get_selected_attachments (ModestMsgView *self);
 TnyHeaderFlags modest_msg_view_get_priority (ModestMsgView *self);
 void modest_msg_view_set_priority (ModestMsgView *self, TnyHeaderFlags flags);
 GList *modest_msg_view_get_selected_attachments (ModestMsgView *self);
diff --git a/src/widgets/modest-zoomable.c b/src/widgets/modest-zoomable.c
new file mode 100644 (file)
index 0000000..72e0eb8
--- /dev/null
@@ -0,0 +1,130 @@
+/* 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.
+ */
+
+#include <config.h>
+
+#include <modest-zoomable.h>
+
+/**
+ * modest_zoomable_set_zoom:
+ * @zoomable: a #ModestZoomable instance
+ * @value: a #gdouble (1.0 is no zoom).
+ *
+ * sets the current zoom leven of @zoomable to @value
+ */
+void            
+modest_zoomable_set_zoom (ModestZoomable *zoomable,
+                         gdouble value)
+{
+       MODEST_ZOOMABLE_GET_IFACE (zoomable)->set_zoom_func (zoomable, value);
+}
+
+/**
+ * modest_zoomable_get_zoom:
+ * @zoomable: a #ModestZoomable instance
+ *
+ * obtains the current zoom level of @zoomable.
+ *
+ * Returns: a #gdouble (1.0 is no zoom).
+ */
+gdouble         
+modest_zoomable_get_zoom (ModestZoomable *zoomable)
+{
+       return MODEST_ZOOMABLE_GET_IFACE (zoomable)->get_zoom_func (zoomable);
+}
+
+/**
+ * modest_zoomable_zoom_plus:
+ * @zoomable: a #ModestZoomable instance
+ *
+ * increases the zoom level, if it can. If not
+ * it returns %FALSE
+ *
+ * Returns: %TRUE if zoom was increased, %FALSE otherwise
+ */
+gboolean
+modest_zoomable_zoom_plus   (ModestZoomable *zoomable)
+{
+       return MODEST_ZOOMABLE_GET_IFACE (zoomable)->zoom_plus_func (zoomable);
+}
+
+/**
+ * modest_zoomable_zoom_minus:
+ * @zoomable: a #ModestZoomable instance
+ *
+ * decreases the zoom level, if it can. If not
+ * it returns %FALSE
+ *
+ * Returns: %TRUE if zoom was decreased, %FALSE otherwise
+ */
+gboolean        
+modest_zoomable_zoom_minus  (ModestZoomable *zoomable)
+{
+       return MODEST_ZOOMABLE_GET_IFACE (zoomable)->zoom_minus_func (zoomable);
+}
+
+static void
+modest_zoomable_base_init (gpointer g_class)
+{
+       static gboolean initialized = FALSE;
+
+       if (!initialized) {
+               /* create interface signals here. */
+               initialized = TRUE;
+       }
+}
+
+GType
+modest_zoomable_get_type (void)
+{
+       static GType type = 0;
+
+       if (G_UNLIKELY(type == 0)) 
+       {
+               static const GTypeInfo info = 
+               {
+                 sizeof (ModestZoomableIface),
+                 modest_zoomable_base_init,   /* base_init */
+                 NULL,   /* base_finalize */
+                 NULL,   /* class_init */
+                 NULL,   /* class_finalize */
+                 NULL,   /* class_data */
+                 0,
+                 0,      /* n_preallocs */
+                 NULL,   /* instance_init */
+                 NULL
+               };
+
+               type = g_type_register_static (G_TYPE_INTERFACE,
+                       "ModestZoomable", &info, 0);
+
+       }
+
+       return type;
+}
diff --git a/src/widgets/modest-zoomable.h b/src/widgets/modest-zoomable.h
new file mode 100644 (file)
index 0000000..7953a08
--- /dev/null
@@ -0,0 +1,67 @@
+/* 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.
+ */
+
+#ifndef MODEST_ZOOMABLE_H
+#define MODEST_ZOOMABLE_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MODEST_TYPE_ZOOMABLE            (modest_zoomable_get_type ())
+#define MODEST_ZOOMABLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), MODEST_TYPE_ZOOMABLE, ModestZoomable))
+#define MODEST_IS_ZOOMABLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MODEST_TYPE_ZOOMABLE))
+#define MODEST_ZOOMABLE_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), MODEST_TYPE_ZOOMABLE, ModestZoomableIface))
+
+typedef struct _ModestZoomable ModestZoomable;
+typedef struct _ModestZoomableIface ModestZoomableIface;
+
+struct _ModestZoomableIface
+{
+       GTypeInterface parent;
+
+       void (*set_zoom_func) (ModestZoomable *self, gdouble zoom);
+       gdouble (*get_zoom_func) (ModestZoomable *self);
+       gboolean (*zoom_plus_func) (ModestZoomable *self);
+       gboolean (*zoom_minus_func) (ModestZoomable *self);
+};
+
+GType modest_zoomable_get_type (void);
+
+void            modest_zoomable_set_zoom    (ModestZoomable *zoomable,
+                                            gdouble value);
+gdouble         modest_zoomable_get_zoom    (ModestZoomable *zoomable);
+gboolean        modest_zoomable_zoom_plus   (ModestZoomable *zoomable);
+gboolean        modest_zoomable_zoom_minus  (ModestZoomable *zoomable);
+
+
+G_END_DECLS
+
+#endif