Webkit based mime part and msg view implementation.
[modest] / src / widgets / modest-webkit-msg-view.c
1 /* Copyright (c) 2006, 2007, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <config.h>
31 #include <tny-gtk-text-buffer-stream.h>
32 #include <string.h>
33 #include <regex.h>
34 #include <ctype.h>
35 #include <stdlib.h>
36 #include <glib/gi18n.h>
37 #include <tny-list.h>
38 #include <tny-simple-list.h>
39 #include <tny-vfs-stream.h>
40
41 #include <modest-tny-msg.h>
42 #include <modest-text-utils.h>
43 #include <widgets/modest-msg-view.h>
44 #include <widgets/modest-compact-mail-header-view.h>
45 #ifdef MODEST_TOOLKIT_HILDON2
46 #include <hildon/hildon-gtk.h>
47 #endif
48 #include <widgets/modest-attachments-view.h>
49 #include <modest-marshal.h>
50 #include <widgets/modest-webkit-mime-part-view.h>
51 #include <widgets/modest-webkit-msg-view.h>
52 #include <widgets/modest-isearch-view.h>
53 #include <widgets/modest-ui-constants.h>
54 #include <modest-icon-names.h>
55 #include <gtk/gtk.h>
56
57 /* 'private'/'protected' functions */
58 static void     modest_webkit_msg_view_class_init   (ModestWebkitMsgViewClass *klass);
59 static void     tny_header_view_init (gpointer g, gpointer iface_data);
60 static void     tny_msg_view_init (gpointer g, gpointer iface_data);
61 static void     tny_mime_part_view_init (gpointer g, gpointer iface_data);
62 static void     modest_mime_part_view_init (gpointer g, gpointer iface_data);
63 static void     modest_zoomable_init (gpointer g, gpointer iface_data);
64 static void     modest_isearch_view_init (gpointer g, gpointer iface_data);
65 static void     modest_msg_view_init (gpointer g, gpointer iface_data);
66 static void     modest_webkit_msg_view_init         (ModestWebkitMsgView *obj);
67 static void     modest_webkit_msg_view_finalize     (GObject *obj);
68 static void     modest_webkit_msg_view_destroy     (GtkObject *obj);
69
70 /* headers signals */
71 static void on_recpt_activated (ModestMailHeaderView *header_view, const gchar *address, ModestWebkitMsgView *msg_view);
72 static void on_show_details (ModestMailHeaderView *header_view, ModestWebkitMsgView *msg_view);
73 static void on_attachment_activated (ModestAttachmentsView * att_view, TnyMimePart *mime_part, gpointer userdata);
74
75 /* body view signals */
76 static gboolean on_activate_link (GtkWidget *widget, const gchar *uri, ModestWebkitMsgView *msg_view);
77 static gboolean on_fetch_url (GtkWidget *widget, const gchar *uri, TnyStream *stream,
78                               ModestWebkitMsgView *msg_view);
79 static gboolean on_link_hover (GtkWidget *widget, const gchar *uri, ModestWebkitMsgView *msg_view);
80 static void on_limit_error (GtkWidget *widget, ModestWebkitMsgView *msg_view);
81
82 /* TnyMimePartView implementation */
83 static void modest_msg_view_mp_clear (TnyMimePartView *self);
84 static void modest_msg_view_mp_set_part (TnyMimePartView *self, TnyMimePart *part);
85 static void modest_msg_view_mp_set_part_default (TnyMimePartView *self, TnyMimePart *part);
86 static TnyMimePart* modest_msg_view_mp_get_part (TnyMimePartView *self);
87 static TnyMimePart* modest_msg_view_mp_get_part_default (TnyMimePartView *self);
88 /* ModestMimePartView implementation */
89 static gboolean modest_msg_view_mp_is_empty (ModestMimePartView *self);
90 static gboolean modest_msg_view_mp_is_empty_default (ModestMimePartView *self);
91 /* TnyHeaderView implementation */
92 static void modest_msg_view_set_header (TnyHeaderView *self, TnyHeader *header);
93 static void modest_msg_view_set_header_default (TnyHeaderView *self, TnyHeader *header);
94 static void modest_msg_view_clear_header (TnyHeaderView *self);
95 static void modest_msg_view_clear_header_default (TnyHeaderView *self);
96 /* TnyMsgView implementation */
97 static TnyMsg *modest_msg_view_get_msg (TnyMsgView *self);
98 static TnyMsg *modest_msg_view_get_msg_default (TnyMsgView *self);
99 static void modest_msg_view_set_msg (TnyMsgView *self, TnyMsg *msg);
100 static void modest_msg_view_set_msg_default (TnyMsgView *self, TnyMsg *msg);
101 static void modest_msg_view_clear (TnyMsgView *self);
102 static void modest_msg_view_clear_default (TnyMsgView *self);
103 static void modest_msg_view_set_unavailable (TnyMsgView *self);
104 static void modest_msg_view_set_unavailable_default (TnyMsgView *self);
105 static TnyMimePartView *modest_msg_view_create_mime_part_view_for (TnyMsgView *self, TnyMimePart *part);
106 static TnyMimePartView *modest_msg_view_create_mime_part_view_for_default (TnyMsgView *self, TnyMimePart *part);
107 static TnyMsgView *modest_msg_view_create_new_inline_viewer (TnyMsgView *self);
108 static TnyMsgView *modest_msg_view_create_new_inline_viewer_default (TnyMsgView *self);
109 /* ModestZoomable implementation */
110 static gdouble modest_msg_view_get_zoom (ModestZoomable *self);
111 static void modest_msg_view_set_zoom (ModestZoomable *self, gdouble value);
112 static gboolean modest_msg_view_zoom_minus (ModestZoomable *self);
113 static gboolean modest_msg_view_zoom_plus (ModestZoomable *self);
114 static gdouble modest_msg_view_get_zoom_default (ModestZoomable *self);
115 static void modest_msg_view_set_zoom_default (ModestZoomable *self, gdouble value);
116 static gboolean modest_msg_view_zoom_minus_default (ModestZoomable *self);
117 static gboolean modest_msg_view_zoom_plus_default (ModestZoomable *self);
118 /* ModestISearchView implementation */
119 static gboolean modest_msg_view_search (ModestISearchView *self, const gchar *string);
120 static gboolean modest_msg_view_search_default (ModestISearchView *self, const gchar *string);
121 static gboolean modest_msg_view_search_next (ModestISearchView *self);
122 static gboolean modest_msg_view_search_next_default (ModestISearchView *self);
123 /* ModestMsgView implementation */
124 static void modest_webkit_msg_view_set_msg_with_other_body (ModestMsgView *self, TnyMsg *msg, TnyMimePart *other_body);
125 static GtkAdjustment *modest_webkit_msg_view_get_vadjustment (ModestMsgView *self);
126 static GtkAdjustment *modest_webkit_msg_view_get_hadjustment (ModestMsgView *self);
127 static void modest_webkit_msg_view_set_vadjustment (ModestMsgView *self, GtkAdjustment *vadj);
128 static void modest_webkit_msg_view_set_hadjustment (ModestMsgView *self, GtkAdjustment *hadj);
129 static void modest_webkit_msg_view_set_shadow_type (ModestMsgView *self, GtkShadowType type);
130 static GtkShadowType modest_webkit_msg_view_get_shadow_type (ModestMsgView *self);
131 static TnyHeaderFlags modest_webkit_msg_view_get_priority (ModestMsgView *self);
132 static void modest_webkit_msg_view_set_priority (ModestMsgView *self, TnyHeaderFlags flags);
133 static TnyList *modest_webkit_msg_view_get_selected_attachments (ModestMsgView *self);
134 static TnyList *modest_webkit_msg_view_get_attachments (ModestMsgView *self);
135 static void modest_webkit_msg_view_grab_focus (ModestMsgView *self);
136 static void modest_webkit_msg_view_remove_attachment (ModestMsgView *view, TnyMimePart *attachment);
137 static void modest_webkit_msg_view_request_fetch_images (ModestMsgView *view);
138 static void modest_webkit_msg_view_set_branding (ModestMsgView *view, const gchar *brand_name, const GdkPixbuf *brand_icon);
139 static gboolean modest_webkit_msg_view_has_blocked_external_images (ModestMsgView *view);
140 static void modest_webkit_msg_view_set_msg_with_other_body_default (ModestMsgView *view, TnyMsg *msg, TnyMimePart *part);
141 static GtkAdjustment *modest_webkit_msg_view_get_vadjustment_default (ModestMsgView *self);
142 static GtkAdjustment *modest_webkit_msg_view_get_hadjustment_default (ModestMsgView *self);
143 static void modest_webkit_msg_view_set_vadjustment_default (ModestMsgView *self, GtkAdjustment *vadj);
144 static void modest_webkit_msg_view_set_hadjustment_default (ModestMsgView *self, GtkAdjustment *hadj);
145 static void modest_webkit_msg_view_set_shadow_type_default (ModestMsgView *self, GtkShadowType type);
146 static GtkShadowType modest_webkit_msg_view_get_shadow_type_default (ModestMsgView *self);
147 static TnyHeaderFlags modest_webkit_msg_view_get_priority_default (ModestMsgView *self);
148 static void modest_webkit_msg_view_set_priority_default (ModestMsgView *self, TnyHeaderFlags flags);
149 static TnyList *modest_webkit_msg_view_get_selected_attachments_default (ModestMsgView *self);
150 static TnyList *modest_webkit_msg_view_get_attachments_default (ModestMsgView *self);
151 static void modest_webkit_msg_view_grab_focus_default (ModestMsgView *self);
152 static void modest_webkit_msg_view_remove_attachment_default (ModestMsgView *view, TnyMimePart *attachment);
153 static gboolean modest_webkit_msg_view_has_blocked_external_images_default (ModestMsgView *view);
154 static void modest_webkit_msg_view_request_fetch_images_default (ModestMsgView *view);
155 static void modest_webkit_msg_view_set_branding_default (ModestMsgView *view, const gchar *brand_name, const GdkPixbuf *brand_icon);
156
157 /* internal api */
158 static void     set_header     (ModestWebkitMsgView *self, TnyHeader *header);
159 static TnyMsg   *get_message   (ModestWebkitMsgView *self);
160 static void     set_message    (ModestWebkitMsgView *self, TnyMsg *tny_msg, TnyMimePart *other_body);
161 static gboolean is_empty       (ModestWebkitMsgView *self); 
162 static void     set_zoom       (ModestWebkitMsgView *self, gdouble zoom);
163 static gdouble  get_zoom       (ModestWebkitMsgView *self);
164 static gboolean search         (ModestWebkitMsgView *self, const gchar *search);
165 static gboolean search_next    (ModestWebkitMsgView *self);
166 static GtkAdjustment *get_vadjustment (ModestWebkitMsgView *self);
167 static GtkAdjustment *get_hadjustment (ModestWebkitMsgView *self);
168 static void set_vadjustment (ModestWebkitMsgView *self, GtkAdjustment *vadj);
169 static void set_hadjustment (ModestWebkitMsgView *self, GtkAdjustment *hadj);
170 static void set_shadow_type (ModestWebkitMsgView *self, GtkShadowType type);
171 static GtkShadowType get_shadow_type (ModestWebkitMsgView *self);
172 static TnyHeaderFlags get_priority (ModestWebkitMsgView *self);
173 static void set_priority (ModestWebkitMsgView *self, TnyHeaderFlags flags);
174 static TnyList *get_selected_attachments (ModestWebkitMsgView *self);
175 static TnyList *get_attachments (ModestWebkitMsgView *self);
176 static void grab_focus (ModestWebkitMsgView *self);
177 static void remove_attachment (ModestWebkitMsgView *view, TnyMimePart *attachment);
178 static void request_fetch_images (ModestWebkitMsgView *view);
179 static void set_branding (ModestWebkitMsgView *view, const gchar *brand_name, const GdkPixbuf *brand_icon);
180 static gboolean has_blocked_external_images (ModestWebkitMsgView *view);
181
182 typedef struct _ModestWebkitMsgViewPrivate ModestWebkitMsgViewPrivate;
183 struct _ModestWebkitMsgViewPrivate {
184         GtkWidget   *body_view;
185         GtkWidget   *mail_header_view;
186         GtkWidget   *attachments_view;
187
188         TnyMsg      *msg;
189
190         /* embedded elements */
191         GtkWidget   *headers_box;
192         GtkWidget   *attachments_box;
193
194         GtkWidget   *priority_box;
195         GtkWidget   *priority_icon;
196
197         /* zoom */
198         gdouble current_zoom;
199
200         /* link click management */
201         gchar *last_url;
202 };
203
204 #define MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
205                                                                                  MODEST_TYPE_WEBKIT_MSG_VIEW, \
206                                                                                  ModestWebkitMsgViewPrivate))
207
208 /* globals */
209 static GtkContainerClass *parent_class = NULL;
210
211 GType
212 modest_webkit_msg_view_get_type (void)
213 {
214         static GType my_type = 0;
215         if (!my_type) {
216                 static const GTypeInfo my_info = {
217                         sizeof(ModestWebkitMsgViewClass),
218                         NULL,           /* base init */
219                         NULL,           /* base finalize */
220                         (GClassInitFunc) modest_webkit_msg_view_class_init,
221                         NULL,           /* class finalize */
222                         NULL,           /* class data */
223                         sizeof(ModestWebkitMsgView),
224                         1,              /* n_preallocs */
225                         (GInstanceInitFunc) modest_webkit_msg_view_init,
226                         NULL
227                 };
228                 static const GInterfaceInfo tny_msg_view_info = 
229                 {
230                   (GInterfaceInitFunc) tny_msg_view_init, /* interface_init */
231                   NULL,         /* interface_finalize */
232                   NULL          /* interface_data */
233                 };
234
235                 static const GInterfaceInfo tny_mime_part_view_info = 
236                 {
237                   (GInterfaceInitFunc) tny_mime_part_view_init, /* interface_init */
238                   NULL,         /* interface_finalize */
239                   NULL          /* interface_data */
240                 };
241
242                 static const GInterfaceInfo tny_header_view_info = 
243                 {
244                   (GInterfaceInitFunc) tny_header_view_init, /* interface_init */
245                   NULL,         /* interface_finalize */
246                   NULL          /* interface_data */
247                 };
248
249                 static const GInterfaceInfo modest_mime_part_view_info = 
250                 {
251                   (GInterfaceInitFunc) modest_mime_part_view_init, /* interface_init */
252                   NULL,         /* interface_finalize */
253                   NULL          /* interface_data */
254                 };
255
256                 static const GInterfaceInfo modest_zoomable_info = 
257                 {
258                   (GInterfaceInitFunc) modest_zoomable_init, /* interface_init */
259                   NULL,         /* interface_finalize */
260                   NULL          /* interface_data */
261                 };
262
263                 static const GInterfaceInfo modest_isearch_view_info = 
264                 {
265                   (GInterfaceInitFunc) modest_isearch_view_init, /* interface_init */
266                   NULL,         /* interface_finalize */
267                   NULL          /* interface_data */
268                 };
269
270                 static const GInterfaceInfo modest_msg_view_info = 
271                 {
272                   (GInterfaceInitFunc) modest_msg_view_init, /* interface_init */
273                   NULL,         /* interface_finalize */
274                   NULL          /* interface_data */
275                 };
276
277                 my_type = g_type_register_static (GTK_TYPE_VIEWPORT,
278                                                   "ModestWebkitMsgView",
279                                                   &my_info, 0);
280
281                 g_type_add_interface_static (my_type, TNY_TYPE_HEADER_VIEW, 
282                         &tny_header_view_info);
283
284                 g_type_add_interface_static (my_type, TNY_TYPE_MIME_PART_VIEW, 
285                         &tny_mime_part_view_info);
286
287                 g_type_add_interface_static (my_type, MODEST_TYPE_MIME_PART_VIEW, 
288                         &modest_mime_part_view_info);
289
290                 g_type_add_interface_static (my_type, TNY_TYPE_MSG_VIEW, 
291                         &tny_msg_view_info);
292
293                 g_type_add_interface_static (my_type, MODEST_TYPE_ZOOMABLE, 
294                         &modest_zoomable_info);
295
296                 g_type_add_interface_static (my_type, MODEST_TYPE_ISEARCH_VIEW, 
297                         &modest_isearch_view_info);
298
299                 g_type_add_interface_static (my_type, MODEST_TYPE_MSG_VIEW, 
300                         &modest_msg_view_info);
301         }
302         return my_type;
303 }
304
305 static void
306 modest_webkit_msg_view_class_init (ModestWebkitMsgViewClass *klass)
307 {
308         GObjectClass *gobject_class;
309         GtkWidgetClass *widget_class;
310         GtkObjectClass *gtkobject_class;
311         GtkContainerClass *container_class;
312         gobject_class = (GObjectClass*) klass;
313         widget_class = (GtkWidgetClass *) klass;
314         gtkobject_class = (GtkObjectClass *) klass;
315         container_class = (GtkContainerClass *) klass;
316
317         parent_class            = g_type_class_peek_parent (klass);
318         gobject_class->finalize = modest_webkit_msg_view_finalize;
319         gtkobject_class->destroy = modest_webkit_msg_view_destroy;
320
321         klass->set_header_func = modest_msg_view_set_header_default;
322         klass->clear_header_func = modest_msg_view_clear_header_default;
323         klass->get_part_func = modest_msg_view_mp_get_part_default;
324         klass->set_part_func = modest_msg_view_mp_set_part_default;
325         klass->is_empty_func = modest_msg_view_mp_is_empty_default;
326         klass->get_msg_func = modest_msg_view_get_msg_default;
327         klass->set_msg_func = modest_msg_view_set_msg_default;
328         klass->set_unavailable_func = modest_msg_view_set_unavailable_default;
329         klass->clear_func = modest_msg_view_clear_default;
330         klass->create_mime_part_view_for_func = modest_msg_view_create_mime_part_view_for_default;
331         klass->create_new_inline_viewer_func = modest_msg_view_create_new_inline_viewer_default;
332         klass->get_zoom_func = modest_msg_view_get_zoom_default;
333         klass->set_zoom_func = modest_msg_view_set_zoom_default;
334         klass->zoom_minus_func = modest_msg_view_zoom_minus_default;
335         klass->zoom_plus_func = modest_msg_view_zoom_plus_default;
336         klass->search_func = modest_msg_view_search_default;
337         klass->search_next_func = modest_msg_view_search_next_default;
338         klass->set_msg_with_other_body_func = modest_webkit_msg_view_set_msg_with_other_body_default;
339         klass->get_vadjustment_func = modest_webkit_msg_view_get_vadjustment_default;
340         klass->get_hadjustment_func = modest_webkit_msg_view_get_hadjustment_default;
341         klass->set_vadjustment_func = modest_webkit_msg_view_set_vadjustment_default;
342         klass->set_hadjustment_func = modest_webkit_msg_view_set_hadjustment_default;
343         klass->get_shadow_type_func = modest_webkit_msg_view_get_shadow_type_default;
344         klass->set_shadow_type_func = modest_webkit_msg_view_set_shadow_type_default;
345         klass->get_priority_func = modest_webkit_msg_view_get_priority_default;
346         klass->set_priority_func = modest_webkit_msg_view_set_priority_default;
347         klass->get_selected_attachments_func = modest_webkit_msg_view_get_selected_attachments_default;
348         klass->get_attachments_func = modest_webkit_msg_view_get_attachments_default;
349         klass->grab_focus_func = modest_webkit_msg_view_grab_focus_default;
350         klass->remove_attachment_func = modest_webkit_msg_view_remove_attachment_default;
351         klass->request_fetch_images_func = modest_webkit_msg_view_request_fetch_images_default;
352         klass->set_branding_func = modest_webkit_msg_view_set_branding_default;
353         klass->has_blocked_external_images_func = modest_webkit_msg_view_has_blocked_external_images_default;
354
355         g_type_class_add_private (gobject_class, sizeof(ModestWebkitMsgViewPrivate));
356
357 }
358
359 static void
360 modest_webkit_msg_view_init (ModestWebkitMsgView *obj)
361 {
362         ModestWebkitMsgViewPrivate *priv;
363         GtkWidget *vbox;
364
365         GTK_WIDGET_UNSET_FLAGS (obj, GTK_NO_WINDOW);
366         gtk_widget_set_redraw_on_allocate (GTK_WIDGET (obj), TRUE);
367         gtk_container_set_reallocate_redraws (GTK_CONTAINER (obj), TRUE);
368         gtk_container_set_resize_mode (GTK_CONTAINER (obj), GTK_RESIZE_QUEUE);
369         
370         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE(obj);
371
372         vbox = gtk_vbox_new (FALSE, 0);
373
374         priv->current_zoom = 1.0;
375
376         priv->msg                     = NULL;
377
378         priv->body_view                 = GTK_WIDGET (g_object_new (MODEST_TYPE_WEBKIT_MIME_PART_VIEW, NULL));
379         priv->mail_header_view        = GTK_WIDGET (modest_compact_mail_header_view_new ());
380         gtk_widget_set_no_show_all (priv->mail_header_view, TRUE);
381         priv->attachments_view        = GTK_WIDGET(modest_attachments_view_new (NULL));
382
383 #ifdef MODEST_TOOLKIT_HILDON2
384         modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
385                                            MODEST_ATTACHMENTS_VIEW_STYLE_LINKS);
386 #else
387         modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
388                                            MODEST_ATTACHMENTS_VIEW_STYLE_SELECTABLE);
389 #endif
390
391         g_signal_connect (G_OBJECT(priv->body_view), "activate_link",
392                                        G_CALLBACK(on_activate_link), obj);
393         g_signal_connect (G_OBJECT(priv->body_view), "fetch_url",
394                                        G_CALLBACK(on_fetch_url), obj);
395         g_signal_connect (G_OBJECT(priv->body_view), "link_hover",
396                                        G_CALLBACK(on_link_hover), obj);
397         g_signal_connect (G_OBJECT(priv->body_view), "limit_error",
398                           G_CALLBACK(on_limit_error), obj);
399
400         g_signal_connect (G_OBJECT (priv->mail_header_view), "recpt-activated", 
401                           G_CALLBACK (on_recpt_activated), obj);
402         g_signal_connect (G_OBJECT (priv->mail_header_view), "show-details", 
403                           G_CALLBACK (on_show_details), obj);
404
405         g_signal_connect (G_OBJECT (priv->attachments_view), "activate",
406                           G_CALLBACK (on_attachment_activated), obj);
407
408         priv->headers_box = gtk_vbox_new (FALSE, MODEST_MARGIN_DEFAULT);
409         gtk_box_pack_start (GTK_BOX (vbox), priv->headers_box, FALSE, FALSE, 0);
410
411         if (priv->mail_header_view)
412                 gtk_box_pack_start (GTK_BOX(priv->headers_box), priv->mail_header_view, FALSE, FALSE, 0);
413
414         priv->priority_icon = gtk_image_new ();
415         gtk_misc_set_alignment (GTK_MISC (priv->priority_icon), 0.0, 0.5);
416         if (priv->priority_icon) {
417                 priv->priority_box = (GtkWidget *)
418                         modest_mail_header_view_add_custom_header (MODEST_MAIL_HEADER_VIEW (priv->mail_header_view),
419                                                                    _("mcen_me_editor_message_priority"),
420                                                                    priv->priority_icon,
421                                                                    FALSE, FALSE);
422                                                                    
423                 gtk_widget_hide_all (priv->priority_box);
424         }
425         if (priv->attachments_view) {
426                 gchar *att_label = g_strconcat (_("mail_va_attachment"), ":", NULL);
427
428                 priv->attachments_box = (GtkWidget *)
429                         modest_mail_header_view_add_custom_header (MODEST_MAIL_HEADER_VIEW (priv->mail_header_view),
430                                                                    att_label,
431                                                                    priv->attachments_view,
432                                                                    FALSE, FALSE);
433                 gtk_widget_hide_all (priv->attachments_box);
434                 g_free (att_label);
435         }
436
437
438         if (priv->body_view) {
439                 gtk_box_pack_start (GTK_BOX (vbox), priv->body_view, TRUE, TRUE, 0);
440         }
441
442         gtk_container_add (GTK_CONTAINER (obj), vbox);
443         
444 }
445         
446
447 static void
448 modest_webkit_msg_view_finalize (GObject *obj)
449 {       
450         ModestWebkitMsgViewPrivate *priv;
451         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (obj);
452
453         if (priv->msg) {
454                 g_object_unref (G_OBJECT(priv->msg));
455                 priv->msg = NULL;
456         }
457
458         priv->body_view = NULL;
459         priv->attachments_view = NULL;
460
461         G_OBJECT_CLASS(parent_class)->finalize (obj);           
462 }
463
464 static void
465 modest_webkit_msg_view_destroy (GtkObject *obj)
466 {       
467
468         GTK_OBJECT_CLASS(parent_class)->destroy (obj);          
469 }
470
471 static GtkAdjustment *
472 get_vadjustment (ModestWebkitMsgView *self)
473 {
474         return gtk_viewport_get_vadjustment (GTK_VIEWPORT (self));
475 }
476
477 static GtkAdjustment *
478 get_hadjustment (ModestWebkitMsgView *self)
479 {
480         return gtk_viewport_get_hadjustment (GTK_VIEWPORT (self));
481 }
482
483 static void
484 set_hadjustment (ModestWebkitMsgView *self, GtkAdjustment *hadj)
485 {
486         gtk_viewport_set_hadjustment (GTK_VIEWPORT (self), hadj);
487 }
488
489 static void
490 set_vadjustment (ModestWebkitMsgView *self, GtkAdjustment *vadj)
491 {
492         gtk_viewport_set_vadjustment (GTK_VIEWPORT (self), vadj);
493 }
494
495 static void
496 set_shadow_type (ModestWebkitMsgView *self,
497                  GtkShadowType shadow_type)
498 {
499         gtk_viewport_set_shadow_type (GTK_VIEWPORT (self), shadow_type);
500 }
501
502 static GtkShadowType
503 get_shadow_type (ModestWebkitMsgView *self)
504 {
505         return gtk_viewport_get_shadow_type (GTK_VIEWPORT (self));
506 }
507
508 /* INTERNAL METHODS */
509 GtkWidget*
510 modest_msg_view_new (TnyMsg *msg)
511 {
512         GObject *obj;
513         ModestWebkitMsgView* self;
514         
515         obj  = G_OBJECT(g_object_new(MODEST_TYPE_WEBKIT_MSG_VIEW, NULL));
516         self = MODEST_WEBKIT_MSG_VIEW(obj);
517         tny_msg_view_set_msg (TNY_MSG_VIEW (self), msg);
518
519         return GTK_WIDGET(self);
520 }
521
522
523 static void
524 on_recpt_activated (ModestMailHeaderView *header_view, 
525                     const gchar *address,
526                     ModestWebkitMsgView *self)
527 {
528         g_signal_emit_by_name (G_OBJECT (self), "recpt-activated", address);
529 }
530
531 static void
532 on_show_details (ModestMailHeaderView *header_view, 
533                  ModestWebkitMsgView *self)
534 {
535         g_signal_emit_by_name (G_OBJECT (self), "show-details");
536 }
537
538 static void
539 on_attachment_activated (ModestAttachmentsView * att_view, TnyMimePart *mime_part, gpointer self)
540 {
541
542         g_signal_emit_by_name (G_OBJECT(self), "attachment_clicked", mime_part);
543 }
544
545 static void
546 request_fetch_images (ModestWebkitMsgView *self)
547 {
548         ModestWebkitMsgViewPrivate *priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
549         TnyMimePart *part;
550
551         /* The message could have not been downloaded yet */
552         if (priv->msg) {
553                 modest_mime_part_view_set_view_images (MODEST_MIME_PART_VIEW (priv->body_view), TRUE);
554                 part = tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (priv->body_view));
555                 if (part) {
556                         tny_mime_part_view_set_part (TNY_MIME_PART_VIEW (priv->body_view), part);
557                         g_object_unref (part);
558                 }
559                 tny_msg_set_allow_external_images (TNY_MSG (priv->msg), TRUE);
560         }
561 }
562
563 static void
564 set_branding (ModestWebkitMsgView *self, const gchar *brand_name, const GdkPixbuf *brand_icon)
565 {
566         ModestWebkitMsgViewPrivate *priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
567
568         modest_mail_header_view_set_branding (MODEST_MAIL_HEADER_VIEW (priv->mail_header_view), brand_name, brand_icon);
569 }
570
571 static gboolean
572 has_blocked_external_images (ModestWebkitMsgView *self)
573 {
574         ModestWebkitMsgViewPrivate *priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
575
576         return (modest_mime_part_view_has_external_images (MODEST_MIME_PART_VIEW (priv->body_view)) &&
577                 !modest_mime_part_view_get_view_images (MODEST_MIME_PART_VIEW (priv->body_view)));
578 }
579
580 static gboolean
581 on_activate_link (GtkWidget *widget, const gchar *uri, ModestWebkitMsgView *self)
582 {
583         gboolean result;
584         g_return_val_if_fail (self, FALSE);
585
586         g_signal_emit_by_name (G_OBJECT(self), "activate-link", uri, &result);
587
588         return result;
589 }
590
591
592 static gboolean
593 on_link_hover (GtkWidget *widget, const gchar *uri, ModestWebkitMsgView *self)
594 {
595         ModestWebkitMsgViewPrivate *priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
596         gboolean result;
597
598         g_free (priv->last_url);
599         priv->last_url = g_strdup (uri);
600
601         g_signal_emit_by_name (G_OBJECT(self), "link-hover", uri, &result);
602
603         return result;
604 }
605
606 static void 
607 on_limit_error (GtkWidget *widget, ModestWebkitMsgView *msg_view)
608 {
609         g_signal_emit_by_name (G_OBJECT (msg_view), "limit-error");
610 }
611
612
613 static TnyMimePart *
614 find_cid_image (TnyMsg *msg, const gchar *cid)
615 {
616         TnyMimePart *part = NULL;
617         TnyList *parts;
618         TnyIterator *iter;
619         
620         g_return_val_if_fail (msg, NULL);
621         g_return_val_if_fail (cid, NULL);
622         
623         parts  = TNY_LIST (tny_simple_list_new());
624
625         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts); 
626         iter   = tny_list_create_iterator (parts);
627         
628         while (!tny_iterator_is_done(iter)) {
629                 const gchar *part_cid;
630
631                 part = TNY_MIME_PART(tny_iterator_get_current(iter));
632                 part_cid = tny_mime_part_get_content_id (part);
633
634                 /* if there is no content id, try the content location;
635                  * this is what Outlook seems to use when it converts
636                  * it's internal richtext to html
637                  */
638                 if (!part_cid)
639                         part_cid = tny_mime_part_get_content_location (part);
640                 
641                 if (part_cid && strcmp (cid, part_cid) == 0)
642                         break;
643
644                 if (tny_mime_part_content_type_is (part, "multipart/related")) {
645                         TnyList *related_parts = TNY_LIST (tny_simple_list_new ());
646                         TnyIterator *related_iter = NULL;
647                         TnyMimePart *related_part = NULL;
648
649                         tny_mime_part_get_parts (part, related_parts);
650                         related_iter = tny_list_create_iterator (related_parts);
651
652                         while (!tny_iterator_is_done (related_iter)) {
653                                 related_part = TNY_MIME_PART (tny_iterator_get_current (related_iter));
654                                 part_cid = tny_mime_part_get_content_id (related_part);
655                                 if (part_cid && strcmp (cid, part_cid) == 0) {
656                                         break;
657                                 }
658                                 g_object_unref (related_part);
659                                 related_part = NULL;
660                                 tny_iterator_next (related_iter);
661                         }
662
663                         g_object_unref (related_iter);
664                         g_object_unref (related_parts);
665                         if (related_part != NULL) {
666                                 g_object_unref (part);
667                                 part = related_part;
668                                 break;
669                         }
670                 }
671
672                 g_object_unref (G_OBJECT(part));
673         
674                 part = NULL;
675                 tny_iterator_next (iter);
676         }
677         
678         g_object_unref (G_OBJECT(iter));        
679         g_object_unref (G_OBJECT(parts));
680         
681         return part;
682 }
683
684
685 static gboolean
686 on_fetch_url (GtkWidget *widget, const gchar *uri,
687               TnyStream *stream, ModestWebkitMsgView *self)
688 {
689         ModestWebkitMsgViewPrivate *priv;
690         const gchar* my_uri;
691         TnyMimePart *part = NULL;
692         
693
694
695         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
696
697         /*
698          * we search for either something starting with cid:, or something
699          * with no prefix at all; this latter case occurs when sending mails
700          * with MS Outlook in rich-text mode, and 'attach-as-object
701          */
702         if (g_str_has_prefix (uri, "cid:"))  
703                 my_uri = uri + 4;  /* +4 ==> skip "cid:" */
704         else
705                 my_uri = uri;
706         
707         /* now try to find the embedded image */
708         part = find_cid_image (priv->msg, my_uri);
709
710         if (!part) {
711                 if (g_str_has_prefix (uri, "http:")) {
712                         if (modest_mime_part_view_get_view_images (MODEST_MIME_PART_VIEW (priv->body_view))) {
713                                 gboolean result = FALSE;
714                                 g_signal_emit_by_name (self, "fetch-image", uri, stream, &result);
715                                 return result;
716                         } else {
717                                 /* we return immediately to get a "image not found" icon */
718                                 tny_stream_close (stream);
719                                 return TRUE;
720                         }
721                 } else {
722                         return FALSE;
723                 }
724         }
725
726         tny_mime_part_decode_to_stream ((TnyMimePart*)part, stream, NULL);
727         tny_stream_close (stream);
728         g_object_unref (G_OBJECT(part));
729         return TRUE;
730 }
731
732 static void
733 set_message (ModestWebkitMsgView *self, TnyMsg *msg, TnyMimePart *other_body)
734 {
735         TnyMimePart *body;
736         ModestWebkitMsgViewPrivate *priv;
737         TnyHeader *header;
738
739         g_return_if_fail (self);
740
741         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE(self);
742         modest_mail_header_view_set_loading (MODEST_MAIL_HEADER_VIEW (priv->mail_header_view), FALSE);
743         gtk_widget_set_no_show_all (priv->mail_header_view, FALSE);
744         modest_mime_part_view_set_view_images (MODEST_MIME_PART_VIEW (priv->body_view), FALSE);
745
746         if (msg != priv->msg) {
747                 if (priv->msg)
748                         g_object_unref (G_OBJECT(priv->msg));
749                 if (msg)
750                         g_object_ref   (G_OBJECT(msg));
751                 priv->msg = msg;
752         }
753
754         if (!msg) {
755                 tny_header_view_clear (TNY_HEADER_VIEW (priv->mail_header_view));
756                 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), NULL);
757                 gtk_widget_hide_all (priv->mail_header_view);
758                 gtk_widget_hide_all (priv->attachments_box);
759 #ifdef MODEST_TOOKIT_HILDON2
760                 gtk_widget_hide_all (priv->priority_box);
761 #endif
762                 gtk_widget_set_no_show_all (priv->mail_header_view, TRUE);
763                 tny_mime_part_view_clear (TNY_MIME_PART_VIEW (priv->body_view));
764
765                 gtk_widget_set_size_request (GTK_WIDGET (priv->body_view), 1, 1);
766                 gtk_widget_set_size_request (GTK_WIDGET (priv->body_view), -1, -1);
767
768                 gtk_widget_queue_resize (GTK_WIDGET (priv->body_view));
769
770                 gtk_widget_queue_resize (GTK_WIDGET(self));
771                 gtk_widget_queue_draw (GTK_WIDGET(self));
772                 return;
773         }
774
775         header = tny_msg_get_header (msg);
776         tny_header_view_set_header (TNY_HEADER_VIEW (priv->mail_header_view), header);
777         g_object_unref (header);
778
779         modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
780                                              other_body?NULL:msg);
781
782         modest_mime_part_view_set_view_images (MODEST_MIME_PART_VIEW (priv->body_view), tny_msg_get_allow_external_images (msg));
783
784         if (other_body) {
785                 body = other_body;
786                 g_object_ref (body);
787         } else {
788                 body = modest_tny_msg_find_body_part (msg, TRUE);
789         }
790         if (body) {
791                 ModestAttachmentsView *widget;
792
793                 tny_mime_part_view_set_part (TNY_MIME_PART_VIEW (priv->body_view), body);
794                 g_object_unref (body);
795                 widget = MODEST_ATTACHMENTS_VIEW (priv->attachments_view);
796
797                 if (modest_attachments_view_has_attachments (widget)) {
798                         GtkLabel *label;
799                         GList *children = NULL;
800                         gchar *text = NULL;
801                         /* Ugly but... */
802                         children = gtk_container_get_children (GTK_CONTAINER (priv->attachments_box));
803                         label = GTK_LABEL (children->data);
804                         gtk_widget_show_all (priv->attachments_box);
805                         if (modest_attachments_view_get_num_attachments (widget) > 1) {
806                                 text = _("mail_va_attachments");
807                         } else {
808                                 text = _("mail_va_attachment");
809                         }
810                         gtk_label_set_text (label, text);
811                 } else {
812                         gtk_widget_hide_all (priv->attachments_box);
813                 }
814
815         } else {
816                 tny_mime_part_view_clear (TNY_MIME_PART_VIEW (priv->body_view));
817         }
818
819         /* Refresh priority */
820         set_priority (self, tny_header_get_flags (header));
821
822         gtk_widget_show (priv->body_view);
823         gtk_widget_set_no_show_all (priv->priority_box, TRUE);
824         gtk_widget_set_no_show_all (priv->attachments_box, TRUE);
825         gtk_widget_show_all (priv->mail_header_view);
826         gtk_widget_set_no_show_all (priv->attachments_box, FALSE);
827         gtk_widget_set_no_show_all (priv->priority_box, FALSE);
828         gtk_widget_set_no_show_all (priv->mail_header_view, TRUE);
829
830         gtk_widget_set_size_request (GTK_WIDGET (priv->body_view), 1, 1);
831         gtk_widget_set_size_request (GTK_WIDGET (priv->body_view), -1, -1);
832
833         gtk_widget_queue_resize (GTK_WIDGET (priv->body_view));
834
835         gtk_widget_queue_resize (GTK_WIDGET(self));
836         gtk_widget_queue_draw (GTK_WIDGET(self));
837
838 }
839
840 static void
841 set_header (ModestWebkitMsgView *self, TnyHeader *header)
842 {
843         ModestWebkitMsgViewPrivate *priv;
844         
845         g_return_if_fail (self);
846
847         if (header == NULL) {
848                 set_message (self, NULL, NULL);
849                 return;
850         }
851         
852         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE(self);
853         modest_mail_header_view_set_loading (MODEST_MAIL_HEADER_VIEW (priv->mail_header_view), TRUE);
854         gtk_widget_set_no_show_all (priv->mail_header_view, FALSE);
855         modest_mime_part_view_set_view_images (MODEST_MIME_PART_VIEW (priv->body_view), FALSE);
856
857         gtk_widget_set_size_request (GTK_WIDGET (priv->body_view), 1, 1);
858         gtk_widget_set_size_request (GTK_WIDGET (priv->body_view), -1, -1);
859         gtk_widget_queue_resize (GTK_WIDGET (priv->body_view));
860
861         if (priv->msg) {
862                 g_object_unref (G_OBJECT(priv->msg));
863         }
864         priv->msg = NULL;
865         
866         tny_header_view_set_header (TNY_HEADER_VIEW (priv->mail_header_view), header);
867         modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), NULL);
868         gtk_widget_show_all (priv->mail_header_view);
869         gtk_widget_hide_all (priv->attachments_box);
870         gtk_widget_hide_all (priv->priority_box);
871         gtk_widget_set_no_show_all (priv->mail_header_view, TRUE);
872         tny_mime_part_view_clear (TNY_MIME_PART_VIEW (priv->body_view));
873         gtk_widget_queue_resize (GTK_WIDGET(self));
874         gtk_widget_queue_draw (GTK_WIDGET(self));
875 }
876
877
878 static TnyMsg*
879 get_message (ModestWebkitMsgView *self)
880 {
881         TnyMsg *msg;
882
883         g_return_val_if_fail (MODEST_IS_WEBKIT_MSG_VIEW (self), NULL);
884
885         msg = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE(self)->msg;
886
887         if (msg)
888                 g_object_ref (msg);
889         
890         return msg;
891 }
892
893 static gboolean 
894 is_empty (ModestWebkitMsgView *self)
895 {
896         ModestWebkitMsgViewPrivate *priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
897
898         return modest_mime_part_view_is_empty (MODEST_MIME_PART_VIEW (priv->body_view));
899 }
900
901 static void
902 set_zoom (ModestWebkitMsgView *self, gdouble zoom)
903 {
904         ModestWebkitMsgViewPrivate *priv;
905
906         g_return_if_fail (MODEST_IS_WEBKIT_MSG_VIEW (self));
907         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
908
909         modest_zoomable_set_zoom (MODEST_ZOOMABLE(priv->body_view), zoom);
910
911         gtk_widget_set_size_request (GTK_WIDGET (priv->body_view), 1, 1);
912         gtk_widget_set_size_request (GTK_WIDGET (priv->body_view), -1, -1);
913
914         gtk_widget_queue_resize (priv->body_view);
915 }
916
917 static gdouble
918 get_zoom (ModestWebkitMsgView *self)
919 {
920         ModestWebkitMsgViewPrivate *priv;
921
922         g_return_val_if_fail (MODEST_IS_WEBKIT_MSG_VIEW (self), 1.0);
923         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
924
925         return modest_zoomable_get_zoom (MODEST_ZOOMABLE (priv->body_view));
926 }
927
928 static TnyHeaderFlags
929 get_priority (ModestWebkitMsgView *self)
930 {
931         ModestWebkitMsgViewPrivate *priv;
932
933         g_return_val_if_fail (MODEST_IS_WEBKIT_MSG_VIEW (self), 0);
934
935         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
936
937         return modest_mail_header_view_get_priority (MODEST_MAIL_HEADER_VIEW (priv->mail_header_view));
938 }
939
940 static void
941 set_priority (ModestWebkitMsgView *self, TnyHeaderFlags flags)
942 {
943         ModestWebkitMsgViewPrivate *priv;
944
945         g_return_if_fail (MODEST_IS_WEBKIT_MSG_VIEW (self));
946         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
947
948         modest_mail_header_view_set_priority (MODEST_MAIL_HEADER_VIEW (priv->mail_header_view), flags);
949
950         gboolean show_priority = FALSE;
951         TnyHeaderFlags priority_flags;
952
953         priority_flags = flags & TNY_HEADER_FLAG_PRIORITY_MASK;
954         if (priority_flags == TNY_HEADER_FLAG_HIGH_PRIORITY) {
955                 show_priority = TRUE;
956                 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), MODEST_HEADER_ICON_HIGH, GTK_ICON_SIZE_MENU);
957         } else if (priority_flags == TNY_HEADER_FLAG_LOW_PRIORITY) {
958                 show_priority = TRUE;
959                 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), MODEST_HEADER_ICON_LOW, GTK_ICON_SIZE_MENU);
960         }
961
962         if (show_priority && MODEST_IS_COMPACT_MAIL_HEADER_VIEW (priv->mail_header_view)) {
963                 gtk_widget_show_all  (priv->priority_box);
964         } else {
965                 gtk_widget_hide_all (priv->priority_box);
966         }
967
968 }
969
970 /* INCREMENTAL SEARCH IMPLEMENTATION */
971
972 static gboolean 
973 search (ModestWebkitMsgView *self, const gchar *search)
974 {
975         ModestWebkitMsgViewPrivate *priv;
976         gboolean result;
977
978         g_return_val_if_fail (MODEST_IS_WEBKIT_MSG_VIEW (self), FALSE);
979
980         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
981         result = modest_isearch_view_search (MODEST_ISEARCH_VIEW (priv->body_view),
982                                              search);
983
984         return result;
985 }
986
987 static gboolean
988 search_next (ModestWebkitMsgView *self)
989 {
990         ModestWebkitMsgViewPrivate *priv;
991         gboolean result;
992
993         g_return_val_if_fail (MODEST_IS_WEBKIT_MSG_VIEW (self), FALSE);
994
995         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
996         result = modest_isearch_view_search_next (MODEST_ISEARCH_VIEW (priv->body_view));
997
998         return result;
999 }
1000
1001 static TnyList *
1002 get_selected_attachments (ModestWebkitMsgView *self)
1003 {
1004         ModestWebkitMsgViewPrivate *priv;
1005
1006         g_return_val_if_fail (MODEST_IS_WEBKIT_MSG_VIEW (self), NULL);
1007         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
1008
1009         return modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1010         
1011 }
1012
1013 static TnyList *
1014 get_attachments (ModestWebkitMsgView *self)
1015 {
1016         ModestWebkitMsgViewPrivate *priv;
1017
1018         g_return_val_if_fail (MODEST_IS_WEBKIT_MSG_VIEW (self), NULL);
1019         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
1020
1021         return modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1022         
1023 }
1024
1025 static void
1026 grab_focus (ModestWebkitMsgView *self)
1027 {
1028         ModestWebkitMsgViewPrivate *priv = NULL;
1029
1030         g_return_if_fail (MODEST_IS_WEBKIT_MSG_VIEW (self));
1031         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
1032
1033         gtk_widget_grab_focus (priv->body_view);
1034 }
1035
1036 static void
1037 remove_attachment (ModestWebkitMsgView *self, TnyMimePart *attachment)
1038 {
1039         ModestWebkitMsgViewPrivate *priv;
1040
1041         g_return_if_fail (MODEST_IS_WEBKIT_MSG_VIEW (self));
1042         g_return_if_fail (TNY_IS_MIME_PART (attachment));
1043         priv = MODEST_WEBKIT_MSG_VIEW_GET_PRIVATE (self);
1044
1045         modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1046                                                    attachment);
1047         
1048 }
1049
1050 /* TNY HEADER VIEW IMPLEMENTATION */
1051
1052 static void
1053 tny_header_view_init (gpointer g, gpointer iface_data)
1054 {
1055         TnyHeaderViewIface *klass = (TnyHeaderViewIface *)g;
1056
1057         klass->set_header = modest_msg_view_set_header;
1058         klass->clear = modest_msg_view_clear_header;
1059
1060         return;
1061 }
1062
1063 static void
1064 modest_msg_view_set_header (TnyHeaderView *self, TnyHeader *header)
1065 {
1066         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->set_header_func (self, header);
1067 }
1068
1069
1070 static void
1071 modest_msg_view_set_header_default (TnyHeaderView *self, TnyHeader *header)
1072 {
1073         set_header (MODEST_WEBKIT_MSG_VIEW (self), header);
1074 }
1075
1076 static void
1077 modest_msg_view_clear_header (TnyHeaderView *self)
1078 {
1079         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->clear_header_func (self);
1080 }
1081
1082
1083 static void
1084 modest_msg_view_clear_header_default (TnyHeaderView *self)
1085 {
1086         set_message (MODEST_WEBKIT_MSG_VIEW (self), NULL, NULL);
1087 }
1088
1089 /* TNY MSG IMPLEMENTATION */
1090
1091 static void
1092 tny_msg_view_init (gpointer g, gpointer iface_data)
1093 {
1094         TnyMsgViewIface *klass = (TnyMsgViewIface *)g;
1095
1096         klass->get_msg = modest_msg_view_get_msg;
1097         klass->set_msg = modest_msg_view_set_msg;
1098         klass->set_unavailable = modest_msg_view_set_unavailable;
1099         klass->clear = modest_msg_view_clear;
1100         klass->create_mime_part_view_for = modest_msg_view_create_mime_part_view_for;
1101         klass->create_new_inline_viewer = modest_msg_view_create_new_inline_viewer;
1102
1103         return;
1104 }
1105
1106 static TnyMsg *
1107 modest_msg_view_get_msg (TnyMsgView *self)
1108 {
1109         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->get_msg_func (self);
1110 }
1111
1112 static TnyMsg *
1113 modest_msg_view_get_msg_default (TnyMsgView *self)
1114 {
1115         return TNY_MSG (tny_mime_part_view_get_part (TNY_MIME_PART_VIEW (self)));
1116 }
1117
1118 static void
1119 modest_msg_view_set_msg (TnyMsgView *self, TnyMsg *msg)
1120 {
1121         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->set_msg_func (self, msg);
1122 }
1123
1124 static void 
1125 modest_msg_view_set_msg_default (TnyMsgView *self, TnyMsg *msg)
1126 {
1127
1128         tny_mime_part_view_set_part (TNY_MIME_PART_VIEW (self), TNY_MIME_PART (msg));
1129
1130         return;
1131 }
1132
1133 static void
1134 modest_msg_view_set_unavailable (TnyMsgView *self)
1135 {
1136         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->set_unavailable_func (self);
1137 }
1138
1139 static void
1140 modest_msg_view_set_unavailable_default (TnyMsgView *self)
1141 {
1142         tny_msg_view_clear (self);
1143
1144         return;
1145 }
1146
1147 static void
1148 modest_msg_view_clear (TnyMsgView *self)
1149 {
1150         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->clear_func (self);
1151 }
1152
1153 static void
1154 modest_msg_view_clear_default (TnyMsgView *self)
1155 {
1156         set_message (MODEST_WEBKIT_MSG_VIEW (self), NULL, NULL);
1157 }
1158
1159 static TnyMimePartView*
1160 modest_msg_view_create_mime_part_view_for (TnyMsgView *self, TnyMimePart *part)
1161 {
1162         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->create_mime_part_view_for_func (self, part);
1163 }
1164
1165 static TnyMimePartView*
1166 modest_msg_view_create_mime_part_view_for_default (TnyMsgView *self, TnyMimePart *part)
1167 {
1168         g_warning ("modest_msg_view_create_mime_part_view_for_default is not implemented");
1169         return NULL;
1170 }
1171
1172 static TnyMsgView*
1173 modest_msg_view_create_new_inline_viewer (TnyMsgView *self)
1174 {
1175         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->create_new_inline_viewer_func (self);
1176 }
1177
1178 static TnyMsgView*
1179 modest_msg_view_create_new_inline_viewer_default (TnyMsgView *self)
1180 {
1181         g_warning ("modest_msg_view_create_new_inline_viewer_default is not implemented");
1182
1183         return NULL;
1184 }
1185
1186 /* TNY MIME PART IMPLEMENTATION */
1187
1188 static void
1189 tny_mime_part_view_init (gpointer g, gpointer iface_data)
1190 {
1191         TnyMimePartViewIface *klass = (TnyMimePartViewIface *)g;
1192
1193         klass->get_part = modest_msg_view_mp_get_part;
1194         klass->set_part = modest_msg_view_mp_set_part;
1195         klass->clear = modest_msg_view_mp_clear;
1196
1197         return;
1198 }
1199
1200 static TnyMimePart* 
1201 modest_msg_view_mp_get_part (TnyMimePartView *self)
1202 {
1203         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->get_part_func (self);
1204 }
1205
1206
1207 static TnyMimePart* 
1208 modest_msg_view_mp_get_part_default (TnyMimePartView *self)
1209 {
1210         return TNY_MIME_PART (get_message (MODEST_WEBKIT_MSG_VIEW (self)));
1211 }
1212
1213 static void
1214 modest_msg_view_mp_set_part (TnyMimePartView *self,
1215                              TnyMimePart *part)
1216 {
1217         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->set_part_func (self, part);
1218 }
1219
1220 static void
1221 modest_msg_view_mp_set_part_default (TnyMimePartView *self,
1222                                      TnyMimePart *part)
1223 {
1224         g_return_if_fail ((part == NULL) || TNY_IS_MSG (part));
1225
1226         set_message (MODEST_WEBKIT_MSG_VIEW (self), TNY_MSG (part), NULL);
1227 }
1228
1229 static void
1230 modest_msg_view_mp_clear (TnyMimePartView *self)
1231 {
1232         tny_msg_view_clear (TNY_MSG_VIEW (self));
1233 }
1234
1235 /* MODEST MIME PART VIEW IMPLEMENTATION */
1236
1237 static void
1238 modest_mime_part_view_init (gpointer g, gpointer iface_data)
1239 {
1240         ModestMimePartViewIface *klass = (ModestMimePartViewIface *)g;
1241
1242         klass->is_empty_func = modest_msg_view_mp_is_empty;
1243
1244         return;
1245 }
1246
1247 static gboolean
1248 modest_msg_view_mp_is_empty (ModestMimePartView *self)
1249 {
1250         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->is_empty_func (self);
1251 }
1252
1253 static gboolean
1254 modest_msg_view_mp_is_empty_default (ModestMimePartView *self)
1255 {
1256         return is_empty (MODEST_WEBKIT_MSG_VIEW (self));
1257 }
1258
1259 /* MODEST ZOOMABLE IMPLEMENTATION */
1260 static void
1261 modest_zoomable_init (gpointer g, gpointer iface_data)
1262 {
1263         ModestZoomableIface *klass = (ModestZoomableIface *)g;
1264
1265         klass->get_zoom_func = modest_msg_view_get_zoom;
1266         klass->set_zoom_func = modest_msg_view_set_zoom;
1267         klass->zoom_minus_func = modest_msg_view_zoom_minus;
1268         klass->zoom_plus_func = modest_msg_view_zoom_plus;
1269
1270         return;
1271 }
1272
1273 static gdouble
1274 modest_msg_view_get_zoom (ModestZoomable *self)
1275 {
1276         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->get_zoom_func (self);
1277 }
1278
1279 static gdouble
1280 modest_msg_view_get_zoom_default (ModestZoomable *self)
1281 {
1282         return get_zoom (MODEST_WEBKIT_MSG_VIEW (self));
1283 }
1284
1285 static void
1286 modest_msg_view_set_zoom (ModestZoomable *self, gdouble value)
1287 {
1288         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->set_zoom_func (self, value);
1289 }
1290
1291 static void
1292 modest_msg_view_set_zoom_default (ModestZoomable *self, gdouble value)
1293 {
1294         set_zoom (MODEST_WEBKIT_MSG_VIEW (self), value);
1295 }
1296
1297 static gboolean
1298 modest_msg_view_zoom_minus (ModestZoomable *self)
1299 {
1300         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->zoom_minus_func (self);
1301 }
1302
1303 static gboolean
1304 modest_msg_view_zoom_minus_default (ModestZoomable *self)
1305 {
1306         /* operation not supported in ModestMsgView */
1307         return FALSE;
1308 }
1309
1310 static gboolean
1311 modest_msg_view_zoom_plus (ModestZoomable *self)
1312 {
1313         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->zoom_plus_func (self);
1314 }
1315
1316 static gboolean
1317 modest_msg_view_zoom_plus_default (ModestZoomable *self)
1318 {
1319         /* operation not supported in ModestMsgView */
1320         return FALSE;
1321 }
1322
1323 /* MODEST ISEARCH VIEW IMPLEMENTATION */
1324 static void
1325 modest_isearch_view_init (gpointer g, gpointer iface_data)
1326 {
1327         ModestISearchViewIface *klass = (ModestISearchViewIface *)g;
1328
1329         klass->search_func = modest_msg_view_search;
1330         klass->search_next_func = modest_msg_view_search_next;
1331
1332         return;
1333 }
1334
1335 static gboolean
1336 modest_msg_view_search (ModestISearchView *self, const gchar *string)
1337 {
1338         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->search_func (self, string);
1339 }
1340
1341 static gboolean
1342 modest_msg_view_search_default (ModestISearchView *self, const gchar *string)
1343 {
1344         return search (MODEST_WEBKIT_MSG_VIEW (self), string);
1345 }
1346
1347 static gboolean
1348 modest_msg_view_search_next (ModestISearchView *self)
1349 {
1350         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->search_next_func (self);
1351 }
1352
1353 static gboolean
1354 modest_msg_view_search_next_default (ModestISearchView *self)
1355 {
1356         return search_next (MODEST_WEBKIT_MSG_VIEW (self));
1357 }
1358
1359 /* MODEST MSG VIEW IMPLEMENTATION */
1360 static void
1361 modest_msg_view_init (gpointer g, gpointer iface_data)
1362 {
1363         ModestMsgViewIface *klass = (ModestMsgViewIface *)g;
1364
1365         klass->set_msg_with_other_body_func = modest_webkit_msg_view_set_msg_with_other_body;
1366         klass->get_vadjustment_func = modest_webkit_msg_view_get_vadjustment;
1367         klass->get_hadjustment_func = modest_webkit_msg_view_get_hadjustment;
1368         klass->set_vadjustment_func = modest_webkit_msg_view_set_vadjustment;
1369         klass->set_hadjustment_func = modest_webkit_msg_view_set_hadjustment;
1370         klass->set_shadow_type_func = modest_webkit_msg_view_set_shadow_type;
1371         klass->get_shadow_type_func = modest_webkit_msg_view_get_shadow_type;
1372         klass->get_priority_func = modest_webkit_msg_view_get_priority;
1373         klass->set_priority_func = modest_webkit_msg_view_set_priority;
1374         klass->get_selected_attachments_func = modest_webkit_msg_view_get_selected_attachments;
1375         klass->get_attachments_func = modest_webkit_msg_view_get_attachments;
1376         klass->grab_focus_func = modest_webkit_msg_view_grab_focus;
1377         klass->remove_attachment_func = modest_webkit_msg_view_remove_attachment;
1378         klass->request_fetch_images_func = modest_webkit_msg_view_request_fetch_images;
1379         klass->set_branding_func = modest_webkit_msg_view_set_branding;
1380         klass->has_blocked_external_images_func = modest_webkit_msg_view_has_blocked_external_images;
1381
1382         return;
1383 }
1384
1385 static void
1386 modest_webkit_msg_view_set_msg_with_other_body (ModestMsgView *self, TnyMsg *msg, TnyMimePart *other_body)
1387 {
1388         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->set_msg_with_other_body_func (self, msg, other_body);
1389 }
1390
1391 static void
1392 modest_webkit_msg_view_set_msg_with_other_body_default (ModestMsgView *self, TnyMsg *msg, TnyMimePart *other_body)
1393 {
1394         set_message (MODEST_WEBKIT_MSG_VIEW (self), msg, other_body);
1395 }
1396
1397 static GtkAdjustment*
1398 modest_webkit_msg_view_get_vadjustment (ModestMsgView *self)
1399 {
1400         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->get_vadjustment_func (self);
1401 }
1402
1403 static GtkAdjustment*
1404 modest_webkit_msg_view_get_vadjustment_default (ModestMsgView *self)
1405 {
1406         return get_vadjustment (MODEST_WEBKIT_MSG_VIEW (self));
1407 }
1408
1409 static GtkAdjustment*
1410 modest_webkit_msg_view_get_hadjustment (ModestMsgView *self)
1411 {
1412         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->get_hadjustment_func (self);
1413 }
1414
1415 static GtkAdjustment*
1416 modest_webkit_msg_view_get_hadjustment_default (ModestMsgView *self)
1417 {
1418         return get_hadjustment (MODEST_WEBKIT_MSG_VIEW (self));
1419 }
1420
1421 static void
1422 modest_webkit_msg_view_set_vadjustment (ModestMsgView *self, GtkAdjustment *adj)
1423 {
1424         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->set_vadjustment_func (self, adj);
1425 }
1426
1427 static void
1428 modest_webkit_msg_view_set_vadjustment_default (ModestMsgView *self, GtkAdjustment *adj)
1429 {
1430         set_vadjustment (MODEST_WEBKIT_MSG_VIEW (self), adj);
1431 }
1432
1433 static void
1434 modest_webkit_msg_view_set_hadjustment (ModestMsgView *self, GtkAdjustment *adj)
1435 {
1436         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->set_hadjustment_func (self, adj);
1437 }
1438
1439 static void
1440 modest_webkit_msg_view_set_hadjustment_default (ModestMsgView *self, GtkAdjustment *adj)
1441 {
1442         set_hadjustment (MODEST_WEBKIT_MSG_VIEW (self), adj);
1443 }
1444
1445 static void
1446 modest_webkit_msg_view_set_shadow_type (ModestMsgView *self, GtkShadowType type)
1447 {
1448         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->set_shadow_type_func (self, type);
1449 }
1450
1451 static void
1452 modest_webkit_msg_view_set_shadow_type_default (ModestMsgView *self, GtkShadowType type)
1453 {
1454         set_shadow_type (MODEST_WEBKIT_MSG_VIEW (self), type);
1455 }
1456
1457 static GtkShadowType
1458 modest_webkit_msg_view_get_shadow_type (ModestMsgView *self)
1459 {
1460         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->get_shadow_type_func (self);
1461 }
1462
1463 static GtkShadowType
1464 modest_webkit_msg_view_get_shadow_type_default (ModestMsgView *self)
1465 {
1466         return get_shadow_type (MODEST_WEBKIT_MSG_VIEW (self));
1467 }
1468
1469 static void
1470 modest_webkit_msg_view_set_priority (ModestMsgView *self, TnyHeaderFlags flags)
1471 {
1472         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->set_priority_func (self, flags);
1473 }
1474
1475 static void
1476 modest_webkit_msg_view_set_priority_default (ModestMsgView *self, TnyHeaderFlags flags)
1477 {
1478         set_priority (MODEST_WEBKIT_MSG_VIEW (self), flags);
1479 }
1480
1481 static TnyHeaderFlags
1482 modest_webkit_msg_view_get_priority (ModestMsgView *self)
1483 {
1484         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->get_priority_func (self);
1485 }
1486
1487 static TnyHeaderFlags
1488 modest_webkit_msg_view_get_priority_default (ModestMsgView *self)
1489 {
1490         return get_priority (MODEST_WEBKIT_MSG_VIEW (self));
1491 }
1492
1493 static TnyList*
1494 modest_webkit_msg_view_get_selected_attachments (ModestMsgView *self)
1495 {
1496         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->get_selected_attachments_func (self);
1497 }
1498
1499 static TnyList*
1500 modest_webkit_msg_view_get_selected_attachments_default (ModestMsgView *self)
1501 {
1502         return get_selected_attachments (MODEST_WEBKIT_MSG_VIEW (self));
1503 }
1504
1505 static TnyList*
1506 modest_webkit_msg_view_get_attachments (ModestMsgView *self)
1507 {
1508         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->get_attachments_func (self);
1509 }
1510
1511 static TnyList*
1512 modest_webkit_msg_view_get_attachments_default (ModestMsgView *self)
1513 {
1514         return get_attachments (MODEST_WEBKIT_MSG_VIEW (self));
1515 }
1516
1517 static void
1518 modest_webkit_msg_view_grab_focus (ModestMsgView *self)
1519 {
1520         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->grab_focus_func (self);
1521 }
1522
1523 static void
1524 modest_webkit_msg_view_grab_focus_default (ModestMsgView *self)
1525 {
1526         grab_focus (MODEST_WEBKIT_MSG_VIEW (self));
1527 }
1528
1529 static void
1530 modest_webkit_msg_view_remove_attachment (ModestMsgView *self, TnyMimePart *attachment)
1531 {
1532         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->remove_attachment_func (self, attachment);
1533 }
1534
1535 static void
1536 modest_webkit_msg_view_remove_attachment_default (ModestMsgView *self, TnyMimePart *attachment)
1537 {
1538         remove_attachment (MODEST_WEBKIT_MSG_VIEW (self), attachment);
1539 }
1540
1541 static void
1542 modest_webkit_msg_view_request_fetch_images (ModestMsgView *self)
1543 {
1544         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->request_fetch_images_func (self);
1545 }
1546
1547 static void
1548 modest_webkit_msg_view_request_fetch_images_default (ModestMsgView *self)
1549 {
1550         request_fetch_images (MODEST_WEBKIT_MSG_VIEW (self));
1551 }
1552
1553 static void
1554 modest_webkit_msg_view_set_branding (ModestMsgView *self, const gchar *brand_name, const GdkPixbuf *brand_icon)
1555 {
1556         MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->set_branding_func (self, brand_name, brand_icon);
1557 }
1558
1559 static void
1560 modest_webkit_msg_view_set_branding_default (ModestMsgView *self, const gchar *brand_name, const GdkPixbuf *brand_icon)
1561 {
1562         set_branding (MODEST_WEBKIT_MSG_VIEW (self), brand_name, brand_icon);
1563 }
1564
1565 static gboolean
1566 modest_webkit_msg_view_has_blocked_external_images (ModestMsgView *self)
1567 {
1568         return MODEST_WEBKIT_MSG_VIEW_GET_CLASS (self)->has_blocked_external_images_func (self);
1569 }
1570
1571 static gboolean
1572 modest_webkit_msg_view_has_blocked_external_images_default (ModestMsgView *self)
1573 {
1574         return has_blocked_external_images (MODEST_WEBKIT_MSG_VIEW (self));
1575 }