* added the 6 bug fixes for week 27 release for diablo pe2
[modest] / src / widgets / modest-gtkhtml-mime-part-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 <widgets/modest-gtkhtml-mime-part-view.h>
32 #include <string.h>
33 #include <gtkhtml/gtkhtml-stream.h>
34 #include <gtkhtml/gtkhtml-search.h>
35 #include <tny-stream.h>
36 #include <tny-mime-part-view.h>
37 #include <modest-stream-text-to-html.h>
38 #include <modest-text-utils.h>
39 #include <modest-conf.h>
40 #include <modest-runtime.h>
41 #include <widgets/modest-mime-part-view.h>
42 #include <widgets/modest-zoomable.h>
43 #include <widgets/modest-tny-stream-gtkhtml.h>
44 #include <libgnomevfs/gnome-vfs.h>
45
46 /* gobject structure methods */
47 static void    modest_gtkhtml_mime_part_view_class_init (ModestGtkhtmlMimePartViewClass *klass);
48 static void    tny_mime_part_view_init                  (gpointer g, gpointer iface_data);
49 static void    modest_mime_part_view_init               (gpointer g, gpointer iface_data);
50 static void    modest_zoomable_init                     (gpointer g, gpointer iface_data);
51 static void    modest_isearch_view_init                 (gpointer g, gpointer iface_data);
52 static void    modest_gtkhtml_mime_part_view_init       (ModestGtkhtmlMimePartView *self);
53 static void    modest_gtkhtml_mime_part_view_finalize   (GObject *self);
54
55 /* GtkHTML signal handlers */
56 static gboolean  on_link_clicked  (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self);
57 static gboolean  on_url           (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self);
58 static gboolean  on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream,
59                                    ModestGtkhtmlMimePartView *self);
60 /* TnyMimePartView implementation */
61 static void modest_gtkhtml_mime_part_view_clear (TnyMimePartView *self);
62 static void modest_gtkhtml_mime_part_view_clear_default (TnyMimePartView *self);
63 static void modest_gtkhtml_mime_part_view_set_part (TnyMimePartView *self, TnyMimePart *part);
64 static void modest_gtkhtml_mime_part_view_set_part_default (TnyMimePartView *self, TnyMimePart *part);
65 static TnyMimePart* modest_gtkhtml_mime_part_view_get_part (TnyMimePartView *self);
66 static TnyMimePart* modest_gtkhtml_mime_part_view_get_part_default (TnyMimePartView *self);
67 /* ModestMimePartView implementation */
68 static gboolean modest_gtkhtml_mime_part_view_is_empty (ModestMimePartView *self);
69 static gboolean modest_gtkhtml_mime_part_view_is_empty_default (ModestMimePartView *self);
70 static gboolean modest_gtkhtml_mime_part_view_get_view_images (ModestMimePartView *self);
71 static gboolean modest_gtkhtml_mime_part_view_get_view_images_default (ModestMimePartView *self);
72 static void     modest_gtkhtml_mime_part_view_set_view_images (ModestMimePartView *self, gboolean view_images);
73 static void     modest_gtkhtml_mime_part_view_set_view_images_default (ModestMimePartView *self, gboolean view_images);
74 static gboolean modest_gtkhtml_mime_part_view_has_external_images (ModestMimePartView *self);
75 static gboolean modest_gtkhtml_mime_part_view_has_external_images_default (ModestMimePartView *self);
76 /* ModestZoomable implementation */
77 static gdouble modest_gtkhtml_mime_part_view_get_zoom (ModestZoomable *self);
78 static void modest_gtkhtml_mime_part_view_set_zoom (ModestZoomable *self, gdouble value);
79 static gboolean modest_gtkhtml_mime_part_view_zoom_minus (ModestZoomable *self);
80 static gboolean modest_gtkhtml_mime_part_view_zoom_plus (ModestZoomable *self);
81 static gdouble modest_gtkhtml_mime_part_view_get_zoom_default (ModestZoomable *self);
82 static void modest_gtkhtml_mime_part_view_set_zoom_default (ModestZoomable *self, gdouble value);
83 static gboolean modest_gtkhtml_mime_part_view_zoom_minus_default (ModestZoomable *self);
84 static gboolean modest_gtkhtml_mime_part_view_zoom_plus_default (ModestZoomable *self);
85 /* ModestISearchView implementation */
86 static gboolean modest_gtkhtml_mime_part_view_search                    (ModestISearchView *self, const gchar *string);
87 static gboolean modest_gtkhtml_mime_part_view_search_next               (ModestISearchView *self);
88 static gboolean modest_gtkhtml_mime_part_view_get_selection_area        (ModestISearchView *self, gint *x, gint *y, 
89                                                                          gint *width, gint *height);
90 static gboolean modest_gtkhtml_mime_part_view_search_default            (ModestISearchView *self, const gchar *string);
91 static gboolean modest_gtkhtml_mime_part_view_search_next_default       (ModestISearchView *self);
92 static gboolean modest_gtkhtml_mime_part_view_get_selection_area_default (ModestISearchView *self, gint *x, gint *y, 
93                                                                           gint *width, gint *height);
94
95
96 /* internal api */
97 static TnyMimePart  *get_part   (ModestGtkhtmlMimePartView *self);
98 static void          set_html_part   (ModestGtkhtmlMimePartView *self, TnyMimePart *part);
99 static void          set_text_part   (ModestGtkhtmlMimePartView *self, TnyMimePart *part);
100 static void          set_empty_part  (ModestGtkhtmlMimePartView *self);
101 static void          set_part   (ModestGtkhtmlMimePartView *self, TnyMimePart *part);
102 static gboolean      is_empty   (ModestGtkhtmlMimePartView *self);
103 static gboolean      get_view_images   (ModestGtkhtmlMimePartView *self);
104 static void          set_view_images   (ModestGtkhtmlMimePartView *self, gboolean view_images);
105 static gboolean      has_external_images   (ModestGtkhtmlMimePartView *self);
106 static void          set_zoom   (ModestGtkhtmlMimePartView *self, gdouble zoom);
107 static gdouble       get_zoom   (ModestGtkhtmlMimePartView *self);
108 static gboolean      has_contents_receiver (gpointer engine, const gchar *data,
109                                             size_t len, gboolean *has_contents);
110 static gboolean      search             (ModestGtkhtmlMimePartView *self, const gchar *string);
111 static gboolean      search_next        (ModestGtkhtmlMimePartView *self);
112 static gboolean      get_selection_area (ModestGtkhtmlMimePartView *self, gint *x, gint *y,
113                                          gint *width, gint *height);
114
115 typedef struct _ModestGtkhtmlMimePartViewPrivate ModestGtkhtmlMimePartViewPrivate;
116 struct _ModestGtkhtmlMimePartViewPrivate {
117         TnyMimePart *part;
118         gdouble current_zoom;
119         gboolean view_images;
120         gboolean has_external_images;
121 };
122
123 #define MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
124                                                                                        MODEST_TYPE_GTKHTML_MIME_PART_VIEW, \
125                                                                                        ModestGtkhtmlMimePartViewPrivate))
126
127 static GtkHTMLClass *parent_class = NULL;
128
129 GtkWidget *
130 modest_gtkhtml_mime_part_view_new ()
131 {
132         return g_object_new (MODEST_TYPE_GTKHTML_MIME_PART_VIEW, NULL);
133 }
134
135 /* GOBJECT IMPLEMENTATION */
136 GType
137 modest_gtkhtml_mime_part_view_get_type (void)
138 {
139         static GType my_type = 0;
140         if (!my_type) {
141                 static const GTypeInfo my_info = {
142                         sizeof(ModestGtkhtmlMimePartViewClass),
143                         NULL,           /* base init */
144                         NULL,           /* base finalize */
145                         (GClassInitFunc) modest_gtkhtml_mime_part_view_class_init,
146                         NULL,           /* class finalize */
147                         NULL,           /* class data */
148                         sizeof(ModestGtkhtmlMimePartView),
149                         1,              /* n_preallocs */
150                         (GInstanceInitFunc) modest_gtkhtml_mime_part_view_init,
151                         NULL
152                 };
153
154                 static const GInterfaceInfo tny_mime_part_view_info = 
155                 {
156                   (GInterfaceInitFunc) tny_mime_part_view_init, /* interface_init */
157                   NULL,         /* interface_finalize */
158                   NULL          /* interface_data */
159                 };
160
161                 static const GInterfaceInfo modest_mime_part_view_info = 
162                 {
163                   (GInterfaceInitFunc) modest_mime_part_view_init, /* interface_init */
164                   NULL,         /* interface_finalize */
165                   NULL          /* interface_data */
166                 };
167
168                 static const GInterfaceInfo modest_zoomable_info = 
169                 {
170                   (GInterfaceInitFunc) modest_zoomable_init, /* interface_init */
171                   NULL,         /* interface_finalize */
172                   NULL          /* interface_data */
173                 };
174
175                 static const GInterfaceInfo modest_isearch_view_info = 
176                 {
177                   (GInterfaceInitFunc) modest_isearch_view_init, /* interface_init */
178                   NULL,         /* interface_finalize */
179                   NULL          /* interface_data */
180                 };
181
182                 my_type = g_type_register_static (GTK_TYPE_HTML,
183                                                   "ModestGtkhtmlMimePartView",
184                                                   &my_info, 0);
185
186                 g_type_add_interface_static (my_type, TNY_TYPE_MIME_PART_VIEW, 
187                         &tny_mime_part_view_info);
188
189                 g_type_add_interface_static (my_type, MODEST_TYPE_MIME_PART_VIEW, 
190                         &modest_mime_part_view_info);
191
192                 g_type_add_interface_static (my_type, MODEST_TYPE_ZOOMABLE, 
193                         &modest_zoomable_info);
194                 g_type_add_interface_static (my_type, MODEST_TYPE_ISEARCH_VIEW, 
195                         &modest_isearch_view_info);
196         }
197         return my_type;
198 }
199
200 static void
201 modest_gtkhtml_mime_part_view_class_init (ModestGtkhtmlMimePartViewClass *klass)
202 {
203         GObjectClass *gobject_class;
204         gobject_class = (GObjectClass*) klass;
205
206         parent_class            = g_type_class_peek_parent (klass);
207         gobject_class->finalize = modest_gtkhtml_mime_part_view_finalize;
208
209         klass->get_part_func = modest_gtkhtml_mime_part_view_get_part_default;
210         klass->set_part_func = modest_gtkhtml_mime_part_view_set_part_default;
211         klass->clear_func = modest_gtkhtml_mime_part_view_clear_default;
212         klass->is_empty_func = modest_gtkhtml_mime_part_view_is_empty_default;
213         klass->get_view_images_func = modest_gtkhtml_mime_part_view_get_view_images_default;
214         klass->set_view_images_func = modest_gtkhtml_mime_part_view_set_view_images_default;
215         klass->has_external_images_func = modest_gtkhtml_mime_part_view_has_external_images_default;
216         klass->get_zoom_func = modest_gtkhtml_mime_part_view_get_zoom_default;
217         klass->set_zoom_func = modest_gtkhtml_mime_part_view_set_zoom_default;
218         klass->zoom_minus_func = modest_gtkhtml_mime_part_view_zoom_minus_default;
219         klass->zoom_plus_func = modest_gtkhtml_mime_part_view_zoom_plus_default;
220         klass->search_func = modest_gtkhtml_mime_part_view_search_default;
221         klass->search_next_func = modest_gtkhtml_mime_part_view_search_next_default;
222         klass->get_selection_area_func = modest_gtkhtml_mime_part_view_get_selection_area_default;
223         
224         g_type_class_add_private (gobject_class, sizeof(ModestGtkhtmlMimePartViewPrivate));
225
226 }
227
228 static void    
229 modest_gtkhtml_mime_part_view_init (ModestGtkhtmlMimePartView *self)
230 {
231         ModestGtkhtmlMimePartViewPrivate *priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
232
233         gtk_html_set_editable        (GTK_HTML(self), FALSE);
234         gtk_html_allow_selection     (GTK_HTML(self), TRUE);
235         gtk_html_set_caret_mode      (GTK_HTML(self), FALSE);
236         gtk_html_set_blocking        (GTK_HTML(self), TRUE);
237         gtk_html_set_images_blocking (GTK_HTML(self), TRUE);
238
239         g_signal_connect (G_OBJECT(self), "link_clicked",
240                           G_CALLBACK(on_link_clicked), self);
241         g_signal_connect (G_OBJECT(self), "url_requested",
242                           G_CALLBACK(on_url_requested), self);
243         g_signal_connect (G_OBJECT(self), "on_url",
244                           G_CALLBACK(on_url), self);
245
246         priv->part = NULL;
247         priv->current_zoom = 1.0;
248         priv->view_images = FALSE;
249         priv->has_external_images = FALSE;
250 }
251
252 static void
253 modest_gtkhtml_mime_part_view_finalize (GObject *obj)
254 {
255         G_OBJECT_CLASS (parent_class)->finalize (obj);
256 }
257
258 /* GTKHTML SIGNALS HANDLERS */
259
260 static gboolean
261 on_link_clicked (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self)
262 {
263         gboolean result;
264         g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE);
265
266         g_signal_emit_by_name (G_OBJECT (self), "activate-link", uri, &result);
267         return result;
268 }
269
270 static gboolean
271 on_url (GtkWidget *widget, const gchar *uri, ModestGtkhtmlMimePartView *self)
272 {
273         gboolean result;
274         g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE);
275
276         g_signal_emit_by_name (G_OBJECT (self), "link-hover", uri, &result);
277         return result;
278 }
279
280 typedef struct {
281         gpointer buffer;
282         GtkHTML *html;
283         GtkHTMLStream *stream;
284 } ImageFetcherInfo;
285
286 static gboolean
287 on_url_requested (GtkWidget *widget, const gchar *uri, GtkHTMLStream *stream, 
288                   ModestGtkhtmlMimePartView *self)
289 {
290         gboolean result;
291         TnyStream *tny_stream;
292         g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE);
293
294         if (g_str_has_prefix (uri, "http:")) {
295                 ModestGtkhtmlMimePartViewPrivate *priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
296
297                 if (!priv->view_images)
298                         priv->has_external_images = TRUE;
299         }
300                         
301         tny_stream = TNY_STREAM (modest_tny_stream_gtkhtml_new (stream, GTK_HTML (widget)));
302         g_signal_emit_by_name (MODEST_MIME_PART_VIEW (self), "fetch-url", uri, tny_stream, &result);
303         g_object_unref (tny_stream);
304         return result;
305 }
306
307 /* INTERNAL API */
308
309 static void
310 set_html_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
311 {
312         GtkHTMLStream *gtkhtml_stream;
313         TnyStream *tny_stream;  
314         
315         g_return_if_fail (self);
316         g_return_if_fail (part);
317         
318         gtkhtml_stream = gtk_html_begin(GTK_HTML(self));
319
320         tny_stream     = TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream, GTK_HTML (self)));
321         tny_stream_reset (tny_stream);
322
323         tny_mime_part_decode_to_stream ((TnyMimePart*)part, tny_stream, NULL);
324         tny_stream_close (tny_stream);
325         g_object_unref (G_OBJECT(tny_stream));
326 }
327
328 static void
329 set_text_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
330 {
331         TnyStream* text_to_html_stream, *tny_stream;
332         GtkHTMLStream *gtkhtml_stream;
333         
334         g_return_if_fail (self);
335         g_return_if_fail (part);
336
337         gtkhtml_stream = gtk_html_begin(GTK_HTML(self)); 
338         tny_stream =  TNY_STREAM(modest_tny_stream_gtkhtml_new (gtkhtml_stream, GTK_HTML (self)));
339         text_to_html_stream = TNY_STREAM (modest_stream_text_to_html_new (tny_stream));
340         modest_stream_text_to_html_set_linkify_limit (MODEST_STREAM_TEXT_TO_HTML (text_to_html_stream), 64*1024);
341         modest_stream_text_to_html_set_full_limit (MODEST_STREAM_TEXT_TO_HTML (text_to_html_stream), 640*1024);
342         
343         // FIXME: tinymail
344         tny_mime_part_decode_to_stream ((TnyMimePart*)part, text_to_html_stream, NULL);
345         tny_stream_write (text_to_html_stream, "\n", 1);
346         tny_stream_reset (text_to_html_stream);         
347         tny_stream_close (text_to_html_stream);
348         
349         g_object_unref (G_OBJECT(text_to_html_stream));
350         g_object_unref (G_OBJECT(tny_stream));
351         /* gtk_html_stream_destroy (gtkhtml_stream); */
352 }
353
354 static void
355 set_empty_part (ModestGtkhtmlMimePartView *self)
356 {
357         g_return_if_fail (self);
358
359         gtk_html_load_from_string (GTK_HTML(self),
360                                    "", 1);
361 }
362
363 static void
364 set_part (ModestGtkhtmlMimePartView *self, TnyMimePart *part)
365 {
366         ModestGtkhtmlMimePartViewPrivate *priv;
367
368         g_return_if_fail (self);
369         
370         priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE(self);
371         priv->has_external_images = FALSE;
372
373         if (part != priv->part) {
374                 if (priv->part)
375                         g_object_unref (G_OBJECT(priv->part));
376                 if (part)
377                         g_object_ref   (G_OBJECT(part));
378                 priv->part = part;
379         }
380         
381         if (!part) {
382                 set_empty_part (self);
383                 return;
384         }
385
386         if (tny_mime_part_content_type_is (part, "text/html"))
387                 set_html_part (self, part);
388         else
389                 set_text_part (self, part);
390
391 }
392
393 static TnyMimePart*
394 get_part (ModestGtkhtmlMimePartView *self)
395 {
396         TnyMimePart *part;
397
398         g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), NULL);
399
400         part = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE(self)->part;
401
402         if (part)
403                 g_object_ref (part);
404         
405         return part;
406 }
407
408 static gboolean
409 has_contents_receiver (gpointer engine, const gchar *data,
410                        size_t len, gboolean *has_contents)
411 {
412         if (len > 1 || ((len == 1)&&(data[0]!='\n'))) {
413                 *has_contents = TRUE;
414                 return FALSE;
415         }
416         return TRUE;
417 }
418
419 static gboolean      
420 is_empty   (ModestGtkhtmlMimePartView *self)
421 {
422         /* TODO: Find some gtkhtml API to check whether there is any (visible, non markup)
423          * text in the message:
424          */
425         gboolean has_contents = FALSE;
426
427         gtk_html_export (GTK_HTML (self), "text/plain", 
428                          (GtkHTMLSaveReceiverFn) has_contents_receiver, &has_contents);
429         
430         return !has_contents;
431 }
432
433 static gboolean      
434 get_view_images   (ModestGtkhtmlMimePartView *self)
435 {
436         ModestGtkhtmlMimePartViewPrivate *priv;
437
438         g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE);
439
440         priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
441         return priv->view_images;
442 }
443
444 static void
445 set_view_images   (ModestGtkhtmlMimePartView *self, gboolean view_images)
446 {
447         ModestGtkhtmlMimePartViewPrivate *priv;
448
449         g_return_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self));
450
451         priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
452         priv->view_images = view_images;
453 }
454
455 static gboolean      
456 has_external_images   (ModestGtkhtmlMimePartView *self)
457 {
458         ModestGtkhtmlMimePartViewPrivate *priv;
459
460         g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), FALSE);
461
462         priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
463         return priv->has_external_images;
464 }
465
466 static void
467 set_zoom (ModestGtkhtmlMimePartView *self, gdouble zoom)
468 {
469         ModestGtkhtmlMimePartViewPrivate *priv;
470
471         g_return_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self));
472
473         priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
474         priv->current_zoom = zoom;
475         gtk_html_set_magnification (GTK_HTML(self), zoom);
476
477         gtk_widget_queue_resize (GTK_WIDGET (self));
478 }
479
480 static gdouble
481 get_zoom (ModestGtkhtmlMimePartView *self)
482 {
483         ModestGtkhtmlMimePartViewPrivate *priv;
484
485         g_return_val_if_fail (MODEST_IS_GTKHTML_MIME_PART_VIEW (self), 1.0);
486
487         priv = MODEST_GTKHTML_MIME_PART_VIEW_GET_PRIVATE (self);
488
489         return priv->current_zoom;
490 }
491
492 static gboolean
493 search (ModestGtkhtmlMimePartView *self, 
494         const gchar *string)
495 {
496         return gtk_html_engine_search (GTK_HTML (self),
497                                        string,
498                                        FALSE,   /* case sensitive */
499                                        TRUE,    /* forward */
500                                        FALSE);  /* regexp */
501 }
502
503 static gboolean
504 search_next (ModestGtkhtmlMimePartView *self)
505 {
506         return gtk_html_engine_search_next (GTK_HTML (self));
507 }
508
509 static gboolean
510 get_selection_area (ModestGtkhtmlMimePartView *self, 
511                     gint *x, gint *y,
512                     gint *width, gint *height)
513 {
514 #ifdef HAVE_GTK_HTML_GET_SELECTION_AREA
515         gtk_html_get_selection_area (GTK_HTML (self), x, y, width, height);
516         return TRUE;
517 #else
518         return FALSE;
519 #endif
520 }
521
522
523 /* TNY MIME PART IMPLEMENTATION */
524
525 static void
526 tny_mime_part_view_init (gpointer g, gpointer iface_data)
527 {
528         TnyMimePartViewIface *klass = (TnyMimePartViewIface *)g;
529
530         klass->get_part = modest_gtkhtml_mime_part_view_get_part;
531         klass->set_part = modest_gtkhtml_mime_part_view_set_part;
532         klass->clear = modest_gtkhtml_mime_part_view_clear;
533
534         return;
535 }
536
537 static TnyMimePart* 
538 modest_gtkhtml_mime_part_view_get_part (TnyMimePartView *self)
539 {
540         return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->get_part_func (self);
541 }
542
543
544 static TnyMimePart* 
545 modest_gtkhtml_mime_part_view_get_part_default (TnyMimePartView *self)
546 {
547         return TNY_MIME_PART (get_part (MODEST_GTKHTML_MIME_PART_VIEW (self)));
548 }
549
550 static void
551 modest_gtkhtml_mime_part_view_set_part (TnyMimePartView *self,
552                                         TnyMimePart *part)
553 {
554         MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->set_part_func (self, part);
555 }
556
557 static void
558 modest_gtkhtml_mime_part_view_set_part_default (TnyMimePartView *self,
559                                                 TnyMimePart *part)
560 {
561         g_return_if_fail ((part == NULL) || TNY_IS_MIME_PART (part));
562
563         set_part (MODEST_GTKHTML_MIME_PART_VIEW (self), part);
564 }
565
566 static void
567 modest_gtkhtml_mime_part_view_clear (TnyMimePartView *self)
568 {
569         MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->clear_func (self);
570 }
571
572 static void
573 modest_gtkhtml_mime_part_view_clear_default (TnyMimePartView *self)
574 {
575         set_part (MODEST_GTKHTML_MIME_PART_VIEW (self), NULL);
576 }
577
578 /* MODEST MIME PART VIEW IMPLEMENTATION */
579
580 static void
581 modest_mime_part_view_init (gpointer g, gpointer iface_data)
582 {
583         ModestMimePartViewIface *klass = (ModestMimePartViewIface *)g;
584
585         klass->is_empty_func = modest_gtkhtml_mime_part_view_is_empty;
586         klass->get_view_images_func = modest_gtkhtml_mime_part_view_get_view_images;
587         klass->set_view_images_func = modest_gtkhtml_mime_part_view_set_view_images;
588         klass->has_external_images_func = modest_gtkhtml_mime_part_view_has_external_images;
589
590         return;
591 }
592
593 static gboolean
594 modest_gtkhtml_mime_part_view_is_empty (ModestMimePartView *self)
595 {
596         return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->is_empty_func (self);
597 }
598
599 static gboolean
600 modest_gtkhtml_mime_part_view_get_view_images (ModestMimePartView *self)
601 {
602         return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->get_view_images_func (self);
603 }
604
605 static void
606 modest_gtkhtml_mime_part_view_set_view_images (ModestMimePartView *self, gboolean view_images)
607 {
608         MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->set_view_images_func (self, view_images);
609 }
610
611 static gboolean
612 modest_gtkhtml_mime_part_view_has_external_images (ModestMimePartView *self)
613 {
614         return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->has_external_images_func (self);
615 }
616
617 static gboolean
618 modest_gtkhtml_mime_part_view_is_empty_default (ModestMimePartView *self)
619 {
620         return is_empty (MODEST_GTKHTML_MIME_PART_VIEW (self));
621 }
622
623 static gboolean
624 modest_gtkhtml_mime_part_view_get_view_images_default (ModestMimePartView *self)
625 {
626         return get_view_images (MODEST_GTKHTML_MIME_PART_VIEW (self));
627 }
628
629 static void
630 modest_gtkhtml_mime_part_view_set_view_images_default (ModestMimePartView *self, gboolean view_images)
631 {
632         set_view_images (MODEST_GTKHTML_MIME_PART_VIEW (self), view_images);
633 }
634
635 static gboolean
636 modest_gtkhtml_mime_part_view_has_external_images_default (ModestMimePartView *self)
637 {
638         return has_external_images (MODEST_GTKHTML_MIME_PART_VIEW (self));
639 }
640
641
642 /* MODEST ZOOMABLE IMPLEMENTATION */
643 static void
644 modest_zoomable_init (gpointer g, gpointer iface_data)
645 {
646         ModestZoomableIface *klass = (ModestZoomableIface *)g;
647         
648         klass->get_zoom_func = modest_gtkhtml_mime_part_view_get_zoom;
649         klass->set_zoom_func = modest_gtkhtml_mime_part_view_set_zoom;
650         klass->zoom_minus_func = modest_gtkhtml_mime_part_view_zoom_minus;
651         klass->zoom_plus_func = modest_gtkhtml_mime_part_view_zoom_plus;
652
653         return;
654 }
655
656 static gdouble
657 modest_gtkhtml_mime_part_view_get_zoom (ModestZoomable *self)
658 {
659         return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->get_zoom_func (self);
660 }
661
662 static gdouble
663 modest_gtkhtml_mime_part_view_get_zoom_default (ModestZoomable *self)
664 {
665         return get_zoom (MODEST_GTKHTML_MIME_PART_VIEW (self));
666 }
667
668 static void
669 modest_gtkhtml_mime_part_view_set_zoom (ModestZoomable *self, gdouble value)
670 {
671         MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->set_zoom_func (self, value);
672 }
673
674 static void
675 modest_gtkhtml_mime_part_view_set_zoom_default (ModestZoomable *self, gdouble value)
676 {
677         set_zoom (MODEST_GTKHTML_MIME_PART_VIEW (self), value);
678 }
679
680 static gboolean
681 modest_gtkhtml_mime_part_view_zoom_minus (ModestZoomable *self)
682 {
683         return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->zoom_minus_func (self);
684 }
685
686 static gboolean
687 modest_gtkhtml_mime_part_view_zoom_minus_default (ModestZoomable *self)
688 {
689         /* operation not supported in ModestGtkhtmlMimePartView */
690         return FALSE;
691 }
692
693 static gboolean
694 modest_gtkhtml_mime_part_view_zoom_plus (ModestZoomable *self)
695 {
696         return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->zoom_plus_func (self);
697 }
698
699 static gboolean
700 modest_gtkhtml_mime_part_view_zoom_plus_default (ModestZoomable *self)
701 {
702         /* operation not supported in ModestGtkhtmlMimePartView */
703         return FALSE;
704 }
705
706 /* ISEARCH VIEW IMPLEMENTATION */
707 static void
708 modest_isearch_view_init (gpointer g, gpointer iface_data)
709 {
710         ModestISearchViewIface *klass = (ModestISearchViewIface *)g;
711         
712         klass->search_func = modest_gtkhtml_mime_part_view_search;
713         klass->search_next_func = modest_gtkhtml_mime_part_view_search_next;
714         klass->get_selection_area_func = modest_gtkhtml_mime_part_view_get_selection_area;
715
716         return;
717 }
718
719 static gboolean 
720 modest_gtkhtml_mime_part_view_search (ModestISearchView *self, const gchar *string)
721 {
722         return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->search_func (self, string);
723 }
724
725 static gboolean 
726 modest_gtkhtml_mime_part_view_search_default (ModestISearchView *self, const gchar *string)
727 {
728         return search (MODEST_GTKHTML_MIME_PART_VIEW (self), string);
729 }
730
731 static gboolean 
732 modest_gtkhtml_mime_part_view_search_next(ModestISearchView *self)
733 {
734         return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->search_next_func (self);
735 }
736
737 static gboolean 
738 modest_gtkhtml_mime_part_view_search_next_default (ModestISearchView *self)
739 {
740         return search_next (MODEST_GTKHTML_MIME_PART_VIEW (self));
741 }
742
743 static gboolean 
744 modest_gtkhtml_mime_part_view_get_selection_area (ModestISearchView *self, gint *x, gint *y, 
745                                                   gint *width, gint *height)
746 {
747         return MODEST_GTKHTML_MIME_PART_VIEW_GET_CLASS (self)->get_selection_area_func (self, x, y, width, height);
748 }
749
750 static gboolean 
751 modest_gtkhtml_mime_part_view_get_selection_area_default (ModestISearchView *self, gint *x, gint *y, 
752                                                           gint *width, gint *height)
753 {
754         return get_selection_area (MODEST_GTKHTML_MIME_PART_VIEW (self), x, y, width, height);
755 }