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