1 /*
2 * e-mail-formatter.c
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 #include "e-mail-formatter.h"
19
20 #include <string.h>
21
22 #include <gdk/gdk.h>
23 #include <libebackend/libebackend.h>
24
25 #include <e-util/e-util.h>
26 #include <shell/e-shell.h>
27
28 #include "e-mail-formatter-enumtypes.h"
29 #include "e-mail-formatter-extension.h"
30 #include "e-mail-formatter-utils.h"
31 #include "e-mail-part.h"
32
33 #define d(x)
34
35 #define E_MAIL_FORMATTER_GET_PRIVATE(obj) \
36 (G_TYPE_INSTANCE_GET_PRIVATE \
37 ((obj), E_TYPE_MAIL_FORMATTER, EMailFormatterPrivate))
38
39 #define STYLESHEET_URI "evo-file://$EVOLUTION_WEBKITDATADIR/webview.css"
40
41 typedef struct _AsyncContext AsyncContext;
42
43 struct _EMailFormatterPrivate {
44 EImageLoadingPolicy image_loading_policy;
45
46 gboolean show_sender_photo;
47 gboolean show_real_date;
48 gboolean animate_images;
49
50 GMutex property_lock;
51
52 gchar *charset;
53 gchar *default_charset;
54 };
55
56 struct _AsyncContext {
57 GOutputStream *stream;
58 EMailPartList *part_list;
59 EMailFormatterHeaderFlags flags;
60 EMailFormatterMode mode;
61 };
62
63 /* internal formatter extensions */
64 GType e_mail_formatter_attachment_get_type (void);
65 GType e_mail_formatter_audio_get_type (void);
66 GType e_mail_formatter_error_get_type (void);
67 GType e_mail_formatter_headers_get_type (void);
68 GType e_mail_formatter_image_get_type (void);
69 GType e_mail_formatter_message_rfc822_get_type (void);
70 GType e_mail_formatter_secure_button_get_type (void);
71 GType e_mail_formatter_source_get_type (void);
72 GType e_mail_formatter_text_enriched_get_type (void);
73 GType e_mail_formatter_text_html_get_type (void);
74 GType e_mail_formatter_text_plain_get_type (void);
75
76 static gpointer e_mail_formatter_parent_class = 0;
77
78 enum {
79 PROP_0,
80 PROP_ANIMATE_IMAGES,
81 PROP_BODY_COLOR,
82 PROP_CHARSET,
83 PROP_CITATION_COLOR,
84 PROP_CONTENT_COLOR,
85 PROP_DEFAULT_CHARSET,
86 PROP_FRAME_COLOR,
87 PROP_HEADER_COLOR,
88 PROP_IMAGE_LOADING_POLICY,
89 PROP_MARK_CITATIONS,
90 PROP_SHOW_REAL_DATE,
91 PROP_SHOW_SENDER_PHOTO,
92 PROP_TEXT_COLOR
93 };
94
95 enum {
96 NEED_REDRAW,
97 CLAIM_ATTACHMENT,
98 LAST_SIGNAL
99 };
100
101 static gint signals[LAST_SIGNAL];
102
103 static void
async_context_free(AsyncContext * async_context)104 async_context_free (AsyncContext *async_context)
105 {
106 g_clear_object (&async_context->part_list);
107 g_clear_object (&async_context->stream);
108
109 g_slice_free (AsyncContext, async_context);
110 }
111
112 static EMailFormatterContext *
mail_formatter_create_context(EMailFormatter * formatter,EMailPartList * part_list,EMailFormatterMode mode,EMailFormatterHeaderFlags flags)113 mail_formatter_create_context (EMailFormatter *formatter,
114 EMailPartList *part_list,
115 EMailFormatterMode mode,
116 EMailFormatterHeaderFlags flags)
117 {
118 EMailFormatterClass *class;
119 EMailFormatterContext *context;
120
121 class = E_MAIL_FORMATTER_GET_CLASS (formatter);
122 g_return_val_if_fail (class != NULL, NULL);
123
124 g_warn_if_fail (class->context_size >= sizeof (EMailFormatterContext));
125
126 context = g_malloc0 (class->context_size);
127 context->part_list = g_object_ref (part_list);
128 context->mode = mode;
129 context->flags = flags;
130
131 return context;
132 }
133
134 static void
mail_formatter_free_context(EMailFormatterContext * context)135 mail_formatter_free_context (EMailFormatterContext *context)
136 {
137 if (context->part_list != NULL)
138 g_object_unref (context->part_list);
139
140 g_free (context);
141 }
142
143 static void
shell_gone_cb(gpointer user_data,GObject * gone_extension_registry)144 shell_gone_cb (gpointer user_data,
145 GObject *gone_extension_registry)
146 {
147 EMailFormatterClass *class = user_data;
148
149 g_return_if_fail (class != NULL);
150
151 g_clear_object (&class->extension_registry);
152 }
153
154 static void
e_mail_formatter_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)155 e_mail_formatter_set_property (GObject *object,
156 guint property_id,
157 const GValue *value,
158 GParamSpec *pspec)
159 {
160 switch (property_id) {
161 case PROP_ANIMATE_IMAGES:
162 e_mail_formatter_set_animate_images (
163 E_MAIL_FORMATTER (object),
164 g_value_get_boolean (value));
165 return;
166
167 case PROP_BODY_COLOR:
168 e_mail_formatter_set_color (
169 E_MAIL_FORMATTER (object),
170 E_MAIL_FORMATTER_COLOR_BODY,
171 g_value_get_boxed (value));
172 return;
173
174 case PROP_CHARSET:
175 e_mail_formatter_set_charset (
176 E_MAIL_FORMATTER (object),
177 g_value_get_string (value));
178 return;
179
180 case PROP_CITATION_COLOR:
181 e_mail_formatter_set_color (
182 E_MAIL_FORMATTER (object),
183 E_MAIL_FORMATTER_COLOR_CITATION,
184 g_value_get_boxed (value));
185 return;
186
187 case PROP_CONTENT_COLOR:
188 e_mail_formatter_set_color (
189 E_MAIL_FORMATTER (object),
190 E_MAIL_FORMATTER_COLOR_CONTENT,
191 g_value_get_boxed (value));
192 return;
193
194 case PROP_DEFAULT_CHARSET:
195 e_mail_formatter_set_default_charset (
196 E_MAIL_FORMATTER (object),
197 g_value_get_string (value));
198 return;
199
200 case PROP_FRAME_COLOR:
201 e_mail_formatter_set_color (
202 E_MAIL_FORMATTER (object),
203 E_MAIL_FORMATTER_COLOR_FRAME,
204 g_value_get_boxed (value));
205 return;
206
207 case PROP_HEADER_COLOR:
208 e_mail_formatter_set_color (
209 E_MAIL_FORMATTER (object),
210 E_MAIL_FORMATTER_COLOR_HEADER,
211 g_value_get_boxed (value));
212 return;
213
214 case PROP_IMAGE_LOADING_POLICY:
215 e_mail_formatter_set_image_loading_policy (
216 E_MAIL_FORMATTER (object),
217 g_value_get_enum (value));
218 return;
219
220 case PROP_MARK_CITATIONS:
221 e_mail_formatter_set_mark_citations (
222 E_MAIL_FORMATTER (object),
223 g_value_get_boolean (value));
224 return;
225
226 case PROP_SHOW_REAL_DATE:
227 e_mail_formatter_set_show_real_date (
228 E_MAIL_FORMATTER (object),
229 g_value_get_boolean (value));
230 return;
231
232 case PROP_SHOW_SENDER_PHOTO:
233 e_mail_formatter_set_show_sender_photo (
234 E_MAIL_FORMATTER (object),
235 g_value_get_boolean (value));
236 return;
237
238 case PROP_TEXT_COLOR:
239 e_mail_formatter_set_color (
240 E_MAIL_FORMATTER (object),
241 E_MAIL_FORMATTER_COLOR_TEXT,
242 g_value_get_boxed (value));
243 return;
244 }
245
246 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
247 }
248
249 static void
e_mail_formatter_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)250 e_mail_formatter_get_property (GObject *object,
251 guint property_id,
252 GValue *value,
253 GParamSpec *pspec)
254 {
255 switch (property_id) {
256 case PROP_ANIMATE_IMAGES:
257 g_value_set_boolean (
258 value,
259 e_mail_formatter_get_animate_images (
260 E_MAIL_FORMATTER (object)));
261 return;
262
263 case PROP_BODY_COLOR:
264 g_value_set_boxed (
265 value,
266 e_mail_formatter_get_color (
267 E_MAIL_FORMATTER (object),
268 E_MAIL_FORMATTER_COLOR_BODY));
269 return;
270
271 case PROP_CHARSET:
272 g_value_take_string (
273 value,
274 e_mail_formatter_dup_charset (
275 E_MAIL_FORMATTER (object)));
276 return;
277
278 case PROP_CITATION_COLOR:
279 g_value_set_boxed (
280 value,
281 e_mail_formatter_get_color (
282 E_MAIL_FORMATTER (object),
283 E_MAIL_FORMATTER_COLOR_CITATION));
284 return;
285
286 case PROP_CONTENT_COLOR:
287 g_value_set_boxed (
288 value,
289 e_mail_formatter_get_color (
290 E_MAIL_FORMATTER (object),
291 E_MAIL_FORMATTER_COLOR_CONTENT));
292 return;
293
294 case PROP_DEFAULT_CHARSET:
295 g_value_take_string (
296 value,
297 e_mail_formatter_dup_default_charset (
298 E_MAIL_FORMATTER (object)));
299 return;
300
301 case PROP_FRAME_COLOR:
302 g_value_set_boxed (
303 value,
304 e_mail_formatter_get_color (
305 E_MAIL_FORMATTER (object),
306 E_MAIL_FORMATTER_COLOR_FRAME));
307 return;
308
309 case PROP_HEADER_COLOR:
310 g_value_set_boxed (
311 value,
312 e_mail_formatter_get_color (
313 E_MAIL_FORMATTER (object),
314 E_MAIL_FORMATTER_COLOR_HEADER));
315 return;
316
317 case PROP_IMAGE_LOADING_POLICY:
318 g_value_set_enum (
319 value,
320 e_mail_formatter_get_image_loading_policy (
321 E_MAIL_FORMATTER (object)));
322 return;
323
324 case PROP_MARK_CITATIONS:
325 g_value_set_boolean (
326 value,
327 e_mail_formatter_get_mark_citations (
328 E_MAIL_FORMATTER (object)));
329 return;
330
331 case PROP_SHOW_REAL_DATE:
332 g_value_set_boolean (
333 value,
334 e_mail_formatter_get_show_real_date (
335 E_MAIL_FORMATTER (object)));
336 return;
337
338 case PROP_SHOW_SENDER_PHOTO:
339 g_value_set_boolean (
340 value,
341 e_mail_formatter_get_show_sender_photo (
342 E_MAIL_FORMATTER (object)));
343 return;
344
345 case PROP_TEXT_COLOR:
346 g_value_set_boxed (
347 value,
348 e_mail_formatter_get_color (
349 E_MAIL_FORMATTER (object),
350 E_MAIL_FORMATTER_COLOR_TEXT));
351 return;
352 }
353
354 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
355 }
356
357 static void
e_mail_formatter_finalize(GObject * object)358 e_mail_formatter_finalize (GObject *object)
359 {
360 EMailFormatterPrivate *priv;
361
362 priv = E_MAIL_FORMATTER_GET_PRIVATE (object);
363
364 g_free (priv->charset);
365 g_free (priv->default_charset);
366
367 g_mutex_clear (&priv->property_lock);
368
369 /* Chain up to parent's finalize() method. */
370 G_OBJECT_CLASS (e_mail_formatter_parent_class)->finalize (object);
371 }
372
373 static void
e_mail_formatter_constructed(GObject * object)374 e_mail_formatter_constructed (GObject *object)
375 {
376 /* Chain up to parent's constructed() method. */
377 G_OBJECT_CLASS (e_mail_formatter_parent_class)->constructed (object);
378
379 e_extensible_load_extensions (E_EXTENSIBLE (object));
380 }
381
382 static void
mail_formatter_run(EMailFormatter * formatter,EMailFormatterContext * context,GOutputStream * stream,GCancellable * cancellable)383 mail_formatter_run (EMailFormatter *formatter,
384 EMailFormatterContext *context,
385 GOutputStream *stream,
386 GCancellable *cancellable)
387 {
388 GQueue queue = G_QUEUE_INIT;
389 GList *head, *link;
390 gchar *hdr;
391 const gchar *string;
392
393 hdr = e_mail_formatter_get_html_header (formatter);
394 g_output_stream_write_all (
395 stream, hdr, strlen (hdr), NULL, cancellable, NULL);
396 g_free (hdr);
397
398 e_mail_part_list_queue_parts (context->part_list, NULL, &queue);
399
400 head = g_queue_peek_head_link (&queue);
401
402 for (link = head; link != NULL; link = g_list_next (link)) {
403 EMailPart *part = link->data;
404 const gchar *part_id;
405 gboolean ok;
406
407 part_id = e_mail_part_get_id (part);
408
409 if (g_cancellable_is_cancelled (cancellable))
410 break;
411
412 if (part->is_hidden && !part->is_error) {
413 if (e_mail_part_id_has_suffix (part, ".rfc822")) {
414 link = e_mail_formatter_find_rfc822_end_iter (link);
415 }
416
417 if (link == NULL)
418 break;
419
420 continue;
421 }
422
423 if (context->mode == E_MAIL_FORMATTER_MODE_PRINTING &&
424 !e_mail_part_get_is_printable (part))
425 continue;
426
427 /* Force formatting as source if needed */
428 if (context->mode != E_MAIL_FORMATTER_MODE_SOURCE) {
429 const gchar *mime_type;
430
431 mime_type = e_mail_part_get_mime_type (part);
432 if (mime_type == NULL)
433 continue;
434
435 ok = e_mail_formatter_format_as (
436 formatter, context, part, stream,
437 mime_type, cancellable);
438
439 /* If the written part was message/rfc822 then
440 * jump to the end of the message, because content
441 * of the whole message has been formatted by
442 * message_rfc822 formatter */
443 if (ok && e_mail_part_id_has_suffix (part, ".rfc822")) {
444 link = e_mail_formatter_find_rfc822_end_iter (link);
445
446 if (link == NULL)
447 break;
448
449 continue;
450 }
451
452 } else {
453 ok = FALSE;
454 }
455
456 if (!ok) {
457 /* We don't want to source these */
458 if (e_mail_part_id_has_suffix (part, ".headers"))
459 continue;
460
461 e_mail_formatter_format_as (
462 formatter, context, part, stream,
463 "application/vnd.evolution.source", cancellable);
464
465 /* .message is the entire message. There's nothing more
466 * to be written. */
467 if (g_strcmp0 (part_id, ".message") == 0)
468 break;
469
470 /* If we just wrote source of a rfc822 message, then jump
471 * behind the message (otherwise source of all parts
472 * would be rendered twice) */
473 if (e_mail_part_id_has_suffix (part, ".rfc822")) {
474
475 do {
476 part = link->data;
477 if (e_mail_part_id_has_suffix (part, ".rfc822.end"))
478 break;
479
480 link = g_list_next (link);
481 } while (link != NULL);
482
483 if (link == NULL)
484 break;
485 }
486 }
487 }
488
489 while (!g_queue_is_empty (&queue))
490 g_object_unref (g_queue_pop_head (&queue));
491
492 string = "</body></html>";
493 g_output_stream_write_all (
494 stream, string, strlen (string),
495 NULL, cancellable, NULL);
496 }
497
498 static void
mail_formatter_update_style(EMailFormatter * formatter,GtkStateFlags state)499 mail_formatter_update_style (EMailFormatter *formatter,
500 GtkStateFlags state)
501 {
502 GtkStyleContext *style_context;
503 GtkWidgetPath *widget_path;
504 GdkRGBA rgba;
505
506 g_object_freeze_notify (G_OBJECT (formatter));
507
508 style_context = gtk_style_context_new ();
509 widget_path = gtk_widget_path_new ();
510 gtk_widget_path_append_type (widget_path, GTK_TYPE_WINDOW);
511 gtk_style_context_set_path (style_context, widget_path);
512
513 if (!gtk_style_context_lookup_color (style_context, "theme_bg_color", &rgba))
514 gdk_rgba_parse (&rgba, E_UTILS_DEFAULT_THEME_BG_COLOR);
515
516 e_mail_formatter_set_color (formatter, E_MAIL_FORMATTER_COLOR_BODY, &rgba);
517
518 rgba.red *= 0.8;
519 rgba.green *= 0.8;
520 rgba.blue *= 0.8;
521 e_mail_formatter_set_color (
522 formatter, E_MAIL_FORMATTER_COLOR_FRAME, &rgba);
523
524 if (!gtk_style_context_lookup_color (style_context, "theme_fg_color", &rgba))
525 gdk_rgba_parse (&rgba, E_UTILS_DEFAULT_THEME_FG_COLOR);
526
527 e_mail_formatter_set_color (formatter, E_MAIL_FORMATTER_COLOR_HEADER, &rgba);
528
529 if (!gtk_style_context_lookup_color (style_context, "theme_base_color", &rgba))
530 gdk_rgba_parse (&rgba, E_UTILS_DEFAULT_THEME_BASE_COLOR);
531
532 e_mail_formatter_set_color (formatter, E_MAIL_FORMATTER_COLOR_CONTENT, &rgba);
533
534 if (!gtk_style_context_lookup_color (style_context, "theme_fg_color", &rgba))
535 gdk_rgba_parse (&rgba, E_UTILS_DEFAULT_THEME_FG_COLOR);
536
537 e_mail_formatter_set_color (formatter, E_MAIL_FORMATTER_COLOR_TEXT, &rgba);
538
539 gtk_widget_path_free (widget_path);
540 g_object_unref (style_context);
541
542 g_object_thaw_notify (G_OBJECT (formatter));
543 }
544
545 static void
e_mail_formatter_base_init(EMailFormatterClass * class)546 e_mail_formatter_base_init (EMailFormatterClass *class)
547 {
548 EShell *shell;
549
550 /* Register internal extensions. */
551 g_type_ensure (e_mail_formatter_attachment_get_type ());
552 /* This is currently disabled, because the WebKit player requires javascript,
553 which is disabled in Evolution. */
554 /* g_type_ensure (e_mail_formatter_audio_get_type ()); */
555 g_type_ensure (e_mail_formatter_error_get_type ());
556 g_type_ensure (e_mail_formatter_headers_get_type ());
557 g_type_ensure (e_mail_formatter_image_get_type ());
558 g_type_ensure (e_mail_formatter_message_rfc822_get_type ());
559 g_type_ensure (e_mail_formatter_secure_button_get_type ());
560 g_type_ensure (e_mail_formatter_source_get_type ());
561 g_type_ensure (e_mail_formatter_text_enriched_get_type ());
562 g_type_ensure (e_mail_formatter_text_html_get_type ());
563 g_type_ensure (e_mail_formatter_text_plain_get_type ());
564
565 class->extension_registry = g_object_new (
566 E_TYPE_MAIL_FORMATTER_EXTENSION_REGISTRY, NULL);
567
568 e_mail_formatter_extension_registry_load (
569 class->extension_registry,
570 E_TYPE_MAIL_FORMATTER_EXTENSION);
571
572 e_extensible_load_extensions (
573 E_EXTENSIBLE (class->extension_registry));
574
575 class->text_html_flags =
576 CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
577 CAMEL_MIME_FILTER_TOHTML_CONVERT_NL |
578 CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES |
579 CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES |
580 CAMEL_MIME_FILTER_TOHTML_MARK_CITATION;
581
582 shell = e_shell_get_default ();
583 /* It can be NULL when creating developer documentation */
584 if (shell)
585 g_object_weak_ref (G_OBJECT (shell), shell_gone_cb, class);
586 }
587
588 static void
e_mail_formatter_class_init(EMailFormatterClass * class)589 e_mail_formatter_class_init (EMailFormatterClass *class)
590 {
591 GObjectClass *object_class;
592 GdkRGBA *rgba;
593
594 e_mail_formatter_parent_class = g_type_class_peek_parent (class);
595 g_type_class_add_private (class, sizeof (EMailFormatterPrivate));
596
597 object_class = G_OBJECT_CLASS (class);
598 object_class->set_property = e_mail_formatter_set_property;
599 object_class->get_property = e_mail_formatter_get_property;
600 object_class->finalize = e_mail_formatter_finalize;
601 object_class->constructed = e_mail_formatter_constructed;
602
603 class->context_size = sizeof (EMailFormatterContext);
604 class->run = mail_formatter_run;
605 class->update_style = mail_formatter_update_style;
606
607 rgba = &class->colors[E_MAIL_FORMATTER_COLOR_BODY];
608 gdk_rgba_parse (rgba, "#eeeeee");
609
610 rgba = &class->colors[E_MAIL_FORMATTER_COLOR_CONTENT];
611 gdk_rgba_parse (rgba, "#ffffff");
612
613 rgba = &class->colors[E_MAIL_FORMATTER_COLOR_FRAME];
614 gdk_rgba_parse (rgba, "#3f3f3f");
615
616 rgba = &class->colors[E_MAIL_FORMATTER_COLOR_HEADER];
617 gdk_rgba_parse (rgba, "#000000");
618
619 rgba = &class->colors[E_MAIL_FORMATTER_COLOR_TEXT];
620 gdk_rgba_parse (rgba, "#000000");
621
622 g_object_class_install_property (
623 object_class,
624 PROP_ANIMATE_IMAGES,
625 g_param_spec_boolean (
626 "animate-images",
627 "Animate images",
628 NULL,
629 FALSE,
630 G_PARAM_READWRITE |
631 G_PARAM_STATIC_STRINGS));
632
633 g_object_class_install_property (
634 object_class,
635 PROP_BODY_COLOR,
636 g_param_spec_boxed (
637 "body-color",
638 "Body Color",
639 NULL,
640 GDK_TYPE_RGBA,
641 G_PARAM_READWRITE |
642 G_PARAM_STATIC_STRINGS));
643
644 g_object_class_install_property (
645 object_class,
646 PROP_CHARSET,
647 g_param_spec_string (
648 "charset",
649 NULL,
650 NULL,
651 NULL,
652 G_PARAM_READWRITE |
653 G_PARAM_STATIC_STRINGS));
654
655 g_object_class_install_property (
656 object_class,
657 PROP_CITATION_COLOR,
658 g_param_spec_boxed (
659 "citation-color",
660 "Citation Color",
661 NULL,
662 GDK_TYPE_RGBA,
663 G_PARAM_READWRITE |
664 G_PARAM_STATIC_STRINGS));
665
666 g_object_class_install_property (
667 object_class,
668 PROP_CONTENT_COLOR,
669 g_param_spec_boxed (
670 "content-color",
671 "Content Color",
672 NULL,
673 GDK_TYPE_RGBA,
674 G_PARAM_READWRITE |
675 G_PARAM_STATIC_STRINGS));
676
677 g_object_class_install_property (
678 object_class,
679 PROP_DEFAULT_CHARSET,
680 g_param_spec_string (
681 "default-charset",
682 NULL,
683 NULL,
684 NULL,
685 G_PARAM_READWRITE |
686 G_PARAM_STATIC_STRINGS));
687
688 g_object_class_install_property (
689 object_class,
690 PROP_FRAME_COLOR,
691 g_param_spec_boxed (
692 "frame-color",
693 "Frame Color",
694 NULL,
695 GDK_TYPE_RGBA,
696 G_PARAM_READWRITE |
697 G_PARAM_STATIC_STRINGS));
698
699 g_object_class_install_property (
700 object_class,
701 PROP_HEADER_COLOR,
702 g_param_spec_boxed (
703 "header-color",
704 "Header Color",
705 NULL,
706 GDK_TYPE_RGBA,
707 G_PARAM_READWRITE |
708 G_PARAM_STATIC_STRINGS));
709
710 g_object_class_install_property (
711 object_class,
712 PROP_IMAGE_LOADING_POLICY,
713 g_param_spec_enum (
714 "image-loading-policy",
715 "Image Loading Policy",
716 NULL,
717 E_TYPE_IMAGE_LOADING_POLICY,
718 E_IMAGE_LOADING_POLICY_NEVER,
719 G_PARAM_READWRITE |
720 G_PARAM_STATIC_STRINGS));
721
722 g_object_class_install_property (
723 object_class,
724 PROP_MARK_CITATIONS,
725 g_param_spec_boolean (
726 "mark-citations",
727 "Mark Citations",
728 NULL,
729 TRUE,
730 G_PARAM_READWRITE |
731 G_PARAM_STATIC_STRINGS));
732
733 g_object_class_install_property (
734 object_class,
735 PROP_SHOW_REAL_DATE,
736 g_param_spec_boolean (
737 "show-real-date",
738 "Show real Date header value",
739 NULL,
740 TRUE,
741 G_PARAM_READWRITE |
742 G_PARAM_CONSTRUCT |
743 G_PARAM_STATIC_STRINGS));
744
745 g_object_class_install_property (
746 object_class,
747 PROP_SHOW_SENDER_PHOTO,
748 g_param_spec_boolean (
749 "show-sender-photo",
750 "Show Sender Photo",
751 NULL,
752 FALSE,
753 G_PARAM_READWRITE |
754 G_PARAM_CONSTRUCT |
755 G_PARAM_STATIC_STRINGS));
756
757 g_object_class_install_property (
758 object_class,
759 PROP_TEXT_COLOR,
760 g_param_spec_boxed (
761 "text-color",
762 "Text Color",
763 NULL,
764 GDK_TYPE_COLOR,
765 G_PARAM_READWRITE |
766 G_PARAM_STATIC_STRINGS));
767
768 signals[CLAIM_ATTACHMENT] = g_signal_new (
769 "claim-attachment",
770 E_TYPE_MAIL_FORMATTER,
771 G_SIGNAL_RUN_FIRST,
772 G_STRUCT_OFFSET (EMailFormatterClass, claim_attachment),
773 NULL, NULL, NULL,
774 G_TYPE_NONE, 1, E_TYPE_ATTACHMENT);
775
776 signals[NEED_REDRAW] = g_signal_new (
777 "need-redraw",
778 E_TYPE_MAIL_FORMATTER,
779 G_SIGNAL_RUN_FIRST,
780 G_STRUCT_OFFSET (EMailFormatterClass, need_redraw),
781 NULL, NULL, NULL,
782 G_TYPE_NONE, 0);
783 }
784
785 static void
e_mail_formatter_init(EMailFormatter * formatter)786 e_mail_formatter_init (EMailFormatter *formatter)
787 {
788 formatter->priv = E_MAIL_FORMATTER_GET_PRIVATE (formatter);
789
790 g_mutex_init (&formatter->priv->property_lock);
791 }
792
793 static void
e_mail_formatter_extensible_interface_init(EExtensibleInterface * iface)794 e_mail_formatter_extensible_interface_init (EExtensibleInterface *iface)
795 {
796
797 }
798
799 EMailFormatter *
e_mail_formatter_new(void)800 e_mail_formatter_new (void)
801 {
802 return g_object_new (E_TYPE_MAIL_FORMATTER, NULL);
803 }
804
805 GType
e_mail_formatter_get_type(void)806 e_mail_formatter_get_type (void)
807 {
808 static GType type = 0;
809
810 if (G_UNLIKELY (type == 0)) {
811 const GTypeInfo type_info = {
812 sizeof (EMailFormatterClass),
813 (GBaseInitFunc) e_mail_formatter_base_init,
814 (GBaseFinalizeFunc) NULL,
815 (GClassInitFunc) e_mail_formatter_class_init,
816 (GClassFinalizeFunc) NULL,
817 NULL, /* class_data */
818 sizeof (EMailFormatter),
819 0, /* n_preallocs */
820 (GInstanceInitFunc) e_mail_formatter_init,
821 NULL /* value_table */
822 };
823
824 const GInterfaceInfo e_extensible_interface_info = {
825 (GInterfaceInitFunc) e_mail_formatter_extensible_interface_init
826 };
827
828 type = g_type_register_static (
829 G_TYPE_OBJECT,
830 "EMailFormatter", &type_info, 0);
831
832 g_type_add_interface_static (
833 type, E_TYPE_EXTENSIBLE, &e_extensible_interface_info);
834 }
835
836 return type;
837 }
838
839 void
e_mail_formatter_claim_attachment(EMailFormatter * formatter,EAttachment * attachment)840 e_mail_formatter_claim_attachment (EMailFormatter *formatter,
841 EAttachment *attachment)
842 {
843 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
844 g_return_if_fail (E_IS_ATTACHMENT (attachment));
845
846 g_signal_emit (formatter, signals[CLAIM_ATTACHMENT], 0, attachment);
847 }
848
849 void
e_mail_formatter_format_sync(EMailFormatter * formatter,EMailPartList * part_list,GOutputStream * stream,EMailFormatterHeaderFlags flags,EMailFormatterMode mode,GCancellable * cancellable)850 e_mail_formatter_format_sync (EMailFormatter *formatter,
851 EMailPartList *part_list,
852 GOutputStream *stream,
853 EMailFormatterHeaderFlags flags,
854 EMailFormatterMode mode,
855 GCancellable *cancellable)
856 {
857 EMailFormatterContext *context;
858 EMailFormatterClass *class;
859
860 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
861 /* EMailPartList can be NULL. */
862 g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
863
864 class = E_MAIL_FORMATTER_GET_CLASS (formatter);
865 g_return_if_fail (class != NULL);
866 g_return_if_fail (class->run != NULL);
867
868 context = mail_formatter_create_context (
869 formatter, part_list, mode, flags);
870
871 class->run (formatter, context, stream, cancellable);
872
873 mail_formatter_free_context (context);
874 }
875
876 static void
mail_formatter_format_thread(GSimpleAsyncResult * simple,GObject * source_object,GCancellable * cancellable)877 mail_formatter_format_thread (GSimpleAsyncResult *simple,
878 GObject *source_object,
879 GCancellable *cancellable)
880 {
881 AsyncContext *async_context;
882
883 async_context = g_simple_async_result_get_op_res_gpointer (simple);
884
885 e_mail_formatter_format_sync (
886 E_MAIL_FORMATTER (source_object),
887 async_context->part_list,
888 async_context->stream,
889 async_context->flags,
890 async_context->mode,
891 cancellable);
892 }
893
894 void
e_mail_formatter_format(EMailFormatter * formatter,EMailPartList * part_list,GOutputStream * stream,EMailFormatterHeaderFlags flags,EMailFormatterMode mode,GAsyncReadyCallback callback,GCancellable * cancellable,gpointer user_data)895 e_mail_formatter_format (EMailFormatter *formatter,
896 EMailPartList *part_list,
897 GOutputStream *stream,
898 EMailFormatterHeaderFlags flags,
899 EMailFormatterMode mode,
900 GAsyncReadyCallback callback,
901 GCancellable *cancellable,
902 gpointer user_data)
903 {
904 GSimpleAsyncResult *simple;
905 AsyncContext *async_context;
906 EMailFormatterClass *class;
907
908 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
909 /* EMailPartList can be NULL. */
910 g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
911
912 class = E_MAIL_FORMATTER_GET_CLASS (formatter);
913 g_return_if_fail (class != NULL);
914 g_return_if_fail (class->run != NULL);
915
916 async_context = g_slice_new0 (AsyncContext);
917 async_context->stream = g_object_ref (stream);
918 async_context->flags = flags;
919 async_context->mode = mode;
920
921 simple = g_simple_async_result_new (
922 G_OBJECT (formatter), callback,
923 user_data, e_mail_formatter_format);
924
925 g_simple_async_result_set_check_cancellable (simple, cancellable);
926
927 g_simple_async_result_set_op_res_gpointer (
928 simple, async_context, (GDestroyNotify) async_context_free);
929
930 if (part_list != NULL) {
931 async_context->part_list = g_object_ref (part_list);
932
933 g_simple_async_result_run_in_thread (
934 simple, mail_formatter_format_thread,
935 G_PRIORITY_DEFAULT, cancellable);
936 } else {
937 g_simple_async_result_complete_in_idle (simple);
938 }
939
940 g_object_unref (simple);
941 }
942
943 gboolean
e_mail_formatter_format_finish(EMailFormatter * formatter,GAsyncResult * result,GError ** error)944 e_mail_formatter_format_finish (EMailFormatter *formatter,
945 GAsyncResult *result,
946 GError **error)
947 {
948 GSimpleAsyncResult *simple;
949
950 g_return_val_if_fail (
951 g_simple_async_result_is_valid (
952 result, G_OBJECT (formatter),
953 e_mail_formatter_format), FALSE);
954
955 simple = G_SIMPLE_ASYNC_RESULT (result);
956
957 /* Assume success unless a GError is set. */
958 return !g_simple_async_result_propagate_error (simple, error);
959 }
960
961 /**
962 * e_mail_formatter_format_as:
963 * @formatter: an #EMailFormatter
964 * @context: an #EMailFormatterContext
965 * @part: an #EMailPart
966 * @stream: a #GOutputStream
967 * @as_mime_type: (allow-none) mime-type to use for formatting, or %NULL
968 * @cancellable: (allow-none) an optional #GCancellable
969 *
970 * Formats given @part using a @formatter extension for given mime type. When
971 * the mime type is %NULL, the function will try to lookup the best formatter
972 * for given @part by it's default mime type.
973 *
974 * Return Value: %TRUE on success, %FALSE when no suitable formatter is found or
975 * when it fails to format the part.
976 */
977 gboolean
e_mail_formatter_format_as(EMailFormatter * formatter,EMailFormatterContext * context,EMailPart * part,GOutputStream * stream,const gchar * as_mime_type,GCancellable * cancellable)978 e_mail_formatter_format_as (EMailFormatter *formatter,
979 EMailFormatterContext *context,
980 EMailPart *part,
981 GOutputStream *stream,
982 const gchar *as_mime_type,
983 GCancellable *cancellable)
984 {
985 EMailExtensionRegistry *extension_registry;
986 GQueue *formatters;
987 gboolean ok;
988 d (
989 gint _call_i;
990 static gint _call = 0;
991 G_LOCK_DEFINE_STATIC (_call);
992 G_LOCK (_call);
993 _call++;
994 _call_i = _call;
995 G_UNLOCK (_call)
996 );
997
998 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), FALSE);
999 g_return_val_if_fail (part != NULL, FALSE);
1000 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1001
1002 if (as_mime_type == NULL || *as_mime_type == '\0')
1003 as_mime_type = e_mail_part_get_mime_type (part);
1004
1005 if (as_mime_type == NULL || *as_mime_type == '\0')
1006 return FALSE;
1007
1008 extension_registry =
1009 e_mail_formatter_get_extension_registry (formatter);
1010 formatters = e_mail_extension_registry_get_for_mime_type (
1011 extension_registry, as_mime_type);
1012 if (formatters == NULL)
1013 formatters = e_mail_extension_registry_get_fallback (
1014 extension_registry, as_mime_type);
1015
1016 ok = FALSE;
1017
1018 d (
1019 printf ("(%d) Formatting for part %s of type %s (found %d formatters)\n",
1020 _call_i, e_mail_part_get_id (part), as_mime_type,
1021 formatters ? g_queue_get_length (formatters) : 0));
1022
1023 if (formatters != NULL) {
1024 GList *head, *link;
1025
1026 head = g_queue_peek_head_link (formatters);
1027
1028 for (link = head; link != NULL; link = g_list_next (link)) {
1029 EMailFormatterExtension *extension;
1030
1031 extension = link->data;
1032 if (extension == NULL)
1033 continue;
1034
1035 ok = e_mail_formatter_extension_format (
1036 extension, formatter, context,
1037 part, stream, cancellable);
1038
1039 d (
1040 printf (
1041 "\t(%d) trying %s...%s\n", _call_i,
1042 G_OBJECT_TYPE_NAME (extension),
1043 ok ? "OK" : "failed"));
1044
1045 if (ok)
1046 break;
1047 }
1048 }
1049
1050 return ok;
1051 }
1052
1053 /**
1054 * em_format_format_text:
1055 * @part: an #EMailPart to decode
1056 * @formatter: an #EMailFormatter
1057 * @stream: Where to write the converted text
1058 * @cancellable: optional #GCancellable object, or %NULL
1059 *
1060 * Decode/output a part's content to @stream.
1061 **/
1062 void
e_mail_formatter_format_text(EMailFormatter * formatter,EMailPart * part,GOutputStream * stream,GCancellable * cancellable)1063 e_mail_formatter_format_text (EMailFormatter *formatter,
1064 EMailPart *part,
1065 GOutputStream *stream,
1066 GCancellable *cancellable)
1067 {
1068 CamelMimeFilter *filter;
1069 const gchar *charset = NULL;
1070 CamelMimeFilter *windows = NULL;
1071 CamelMimePart *mime_part;
1072 CamelContentType *mime_type;
1073
1074 if (g_cancellable_is_cancelled (cancellable))
1075 return;
1076
1077 mime_part = e_mail_part_ref_mime_part (part);
1078 mime_type = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (mime_part));
1079
1080 if (formatter->priv->charset != NULL) {
1081 charset = formatter->priv->charset;
1082 } else if (mime_type != NULL
1083 && (charset = camel_content_type_param (mime_type, "charset"))
1084 && g_ascii_strncasecmp (charset, "iso-8859-", 9) == 0) {
1085 GOutputStream *null_stream;
1086 GOutputStream *filter_stream;
1087
1088 /* Since a few Windows mailers like to claim they sent
1089 * out iso-8859-# encoded text when they really sent
1090 * out windows-cp125#, do some simple sanity checking
1091 * before we move on... */
1092
1093 null_stream = camel_null_output_stream_new ();
1094 windows = camel_mime_filter_windows_new (charset);
1095 filter_stream = camel_filter_output_stream_new (
1096 null_stream, windows);
1097 g_filter_output_stream_set_close_base_stream (
1098 G_FILTER_OUTPUT_STREAM (filter_stream), FALSE);
1099
1100 camel_data_wrapper_decode_to_output_stream_sync (
1101 CAMEL_DATA_WRAPPER (mime_part),
1102 filter_stream, cancellable, NULL);
1103 g_output_stream_flush (filter_stream, cancellable, NULL);
1104
1105 g_object_unref (filter_stream);
1106 g_object_unref (null_stream);
1107
1108 charset = camel_mime_filter_windows_real_charset (
1109 CAMEL_MIME_FILTER_WINDOWS (windows));
1110 } else if (charset == NULL) {
1111 charset = formatter->priv->default_charset;
1112 }
1113
1114 filter = camel_mime_filter_charset_new (charset, "UTF-8");
1115 if (filter != NULL) {
1116 e_mail_part_set_converted_to_utf8 (part, TRUE);
1117
1118 stream = camel_filter_output_stream_new (stream, filter);
1119 g_filter_output_stream_set_close_base_stream (
1120 G_FILTER_OUTPUT_STREAM (stream), FALSE);
1121 g_object_unref (filter);
1122 } else {
1123 g_object_ref (stream);
1124 }
1125
1126 camel_data_wrapper_decode_to_output_stream_sync (
1127 camel_medium_get_content (CAMEL_MEDIUM (mime_part)),
1128 stream, cancellable, NULL);
1129 g_output_stream_flush (stream, cancellable, NULL);
1130
1131 g_object_unref (stream);
1132 g_clear_object (&windows);
1133 g_clear_object (&mime_part);
1134 }
1135
1136 const gchar *
e_mail_formatter_get_sub_html_header(EMailFormatter * formatter)1137 e_mail_formatter_get_sub_html_header (EMailFormatter *formatter)
1138 {
1139 return "<!DOCTYPE HTML>\n"
1140 "<html>\n"
1141 "<head>\n"
1142 "<meta name=\"generator\" content=\"Evolution Mail\"/>\n"
1143 "<meta name=\"color-scheme\" content=\"light dark\">\n"
1144 "<title>Evolution Mail Display</title>\n"
1145 "<link type=\"text/css\" rel=\"stylesheet\" "
1146 " href=\"" STYLESHEET_URI "\"/>\n"
1147 "<style type=\"text/css\">\n"
1148 " table th { font-weight: bold; }\n"
1149 "</style>\n"
1150 "</head>"
1151 "<body class=\"-e-web-view-background-color -e-web-view-text-color\">";
1152 }
1153
1154 gchar *
e_mail_formatter_get_html_header(EMailFormatter * formatter)1155 e_mail_formatter_get_html_header (EMailFormatter *formatter)
1156 {
1157 return g_strdup (
1158 "<!DOCTYPE HTML>\n"
1159 "<html>\n"
1160 "<head>\n"
1161 "<meta name=\"generator\" content=\"Evolution Mail\"/>\n"
1162 "<meta name=\"color-scheme\" content=\"light dark\">\n"
1163 "<title>Evolution Mail Display</title>\n"
1164 "<link type=\"text/css\" rel=\"stylesheet\" "
1165 " href=\"" STYLESHEET_URI "\"/>\n"
1166 "<style type=\"text/css\">\n"
1167 " table th { font-weight: bold; }\n"
1168 "</style>\n"
1169 "</head>"
1170 "<body class=\"-e-mail-formatter-body-color "
1171 "-e-web-view-background-color -e-web-view-text-color\">");
1172 }
1173
1174 EMailExtensionRegistry *
e_mail_formatter_get_extension_registry(EMailFormatter * formatter)1175 e_mail_formatter_get_extension_registry (EMailFormatter *formatter)
1176 {
1177 EMailFormatterClass *klass;
1178
1179 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
1180
1181 klass = E_MAIL_FORMATTER_GET_CLASS (formatter);
1182 g_return_val_if_fail (klass != NULL, NULL);
1183
1184 return E_MAIL_EXTENSION_REGISTRY (klass->extension_registry);
1185 }
1186
1187 CamelMimeFilterToHTMLFlags
e_mail_formatter_get_text_format_flags(EMailFormatter * formatter)1188 e_mail_formatter_get_text_format_flags (EMailFormatter *formatter)
1189 {
1190 EMailFormatterClass *klass;
1191
1192 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), 0);
1193
1194 klass = E_MAIL_FORMATTER_GET_CLASS (formatter);
1195 g_return_val_if_fail (klass != NULL, 0);
1196
1197 return klass->text_html_flags;
1198 }
1199
1200 const GdkRGBA *
e_mail_formatter_get_color(EMailFormatter * formatter,EMailFormatterColor type)1201 e_mail_formatter_get_color (EMailFormatter *formatter,
1202 EMailFormatterColor type)
1203 {
1204 EMailFormatterClass *klass;
1205
1206 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
1207 g_return_val_if_fail (type < E_MAIL_FORMATTER_NUM_COLOR_TYPES, NULL);
1208
1209 klass = E_MAIL_FORMATTER_GET_CLASS (formatter);
1210 g_return_val_if_fail (klass != NULL, NULL);
1211
1212 return &(klass->colors[type]);
1213 }
1214
1215 void
e_mail_formatter_set_color(EMailFormatter * formatter,EMailFormatterColor type,const GdkRGBA * color)1216 e_mail_formatter_set_color (EMailFormatter *formatter,
1217 EMailFormatterColor type,
1218 const GdkRGBA *color)
1219 {
1220 EMailFormatterClass *klass;
1221 GdkRGBA *format_color;
1222 const gchar *property_name;
1223
1224 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
1225 g_return_if_fail (type < E_MAIL_FORMATTER_NUM_COLOR_TYPES);
1226 g_return_if_fail (color != NULL);
1227
1228 klass = E_MAIL_FORMATTER_GET_CLASS (formatter);
1229 g_return_if_fail (klass != NULL);
1230
1231 format_color = &(klass->colors[type]);
1232
1233 if (gdk_rgba_equal (color, format_color))
1234 return;
1235
1236 format_color->red = color->red;
1237 format_color->green = color->green;
1238 format_color->blue = color->blue;
1239
1240 switch (type) {
1241 case E_MAIL_FORMATTER_COLOR_BODY:
1242 property_name = "body-color";
1243 break;
1244 case E_MAIL_FORMATTER_COLOR_CITATION:
1245 property_name = "citation-color";
1246 break;
1247 case E_MAIL_FORMATTER_COLOR_CONTENT:
1248 property_name = "content-color";
1249 break;
1250 case E_MAIL_FORMATTER_COLOR_FRAME:
1251 property_name = "frame-color";
1252 break;
1253 case E_MAIL_FORMATTER_COLOR_HEADER:
1254 property_name = "header-color";
1255 break;
1256 case E_MAIL_FORMATTER_COLOR_TEXT:
1257 property_name = "text-color";
1258 break;
1259 default:
1260 g_return_if_reached ();
1261 }
1262
1263 g_object_notify (G_OBJECT (formatter), property_name);
1264 }
1265
1266 void
e_mail_formatter_update_style(EMailFormatter * formatter,GtkStateFlags state)1267 e_mail_formatter_update_style (EMailFormatter *formatter,
1268 GtkStateFlags state)
1269 {
1270 EMailFormatterClass *class;
1271
1272 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
1273
1274 class = E_MAIL_FORMATTER_GET_CLASS (formatter);
1275 g_return_if_fail (class != NULL);
1276 g_return_if_fail (class->update_style != NULL);
1277
1278 class->update_style (formatter, state);
1279 }
1280
1281 EImageLoadingPolicy
e_mail_formatter_get_image_loading_policy(EMailFormatter * formatter)1282 e_mail_formatter_get_image_loading_policy (EMailFormatter *formatter)
1283 {
1284 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), 0);
1285
1286 return formatter->priv->image_loading_policy;
1287 }
1288
1289 void
e_mail_formatter_set_image_loading_policy(EMailFormatter * formatter,EImageLoadingPolicy policy)1290 e_mail_formatter_set_image_loading_policy (EMailFormatter *formatter,
1291 EImageLoadingPolicy policy)
1292 {
1293 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
1294
1295 if (policy == formatter->priv->image_loading_policy)
1296 return;
1297
1298 formatter->priv->image_loading_policy = policy;
1299
1300 g_object_notify (G_OBJECT (formatter), "image-loading-policy");
1301 }
1302
1303 gboolean
e_mail_formatter_get_mark_citations(EMailFormatter * formatter)1304 e_mail_formatter_get_mark_citations (EMailFormatter *formatter)
1305 {
1306 EMailFormatterClass *klass;
1307 guint32 flags;
1308
1309 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), FALSE);
1310
1311 klass = E_MAIL_FORMATTER_GET_CLASS (formatter);
1312 g_return_val_if_fail (klass != NULL, FALSE);
1313
1314 flags = klass->text_html_flags;
1315
1316 return ((flags & CAMEL_MIME_FILTER_TOHTML_MARK_CITATION) != 0);
1317 }
1318
1319 void
e_mail_formatter_set_mark_citations(EMailFormatter * formatter,gboolean mark_citations)1320 e_mail_formatter_set_mark_citations (EMailFormatter *formatter,
1321 gboolean mark_citations)
1322 {
1323 EMailFormatterClass *klass;
1324
1325 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
1326
1327 klass = E_MAIL_FORMATTER_GET_CLASS (formatter);
1328 g_return_if_fail (klass != NULL);
1329
1330 if (mark_citations)
1331 klass->text_html_flags |= CAMEL_MIME_FILTER_TOHTML_MARK_CITATION;
1332 else
1333 klass->text_html_flags &= ~CAMEL_MIME_FILTER_TOHTML_MARK_CITATION;
1334
1335 g_object_notify (G_OBJECT (formatter), "mark-citations");
1336 }
1337
1338 gboolean
e_mail_formatter_get_show_sender_photo(EMailFormatter * formatter)1339 e_mail_formatter_get_show_sender_photo (EMailFormatter *formatter)
1340 {
1341 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), FALSE);
1342
1343 return formatter->priv->show_sender_photo;
1344 }
1345
1346 void
e_mail_formatter_set_show_sender_photo(EMailFormatter * formatter,gboolean show_sender_photo)1347 e_mail_formatter_set_show_sender_photo (EMailFormatter *formatter,
1348 gboolean show_sender_photo)
1349 {
1350 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
1351
1352 if (formatter->priv->show_sender_photo == show_sender_photo)
1353 return;
1354
1355 formatter->priv->show_sender_photo = show_sender_photo;
1356
1357 g_object_notify (G_OBJECT (formatter), "show-sender-photo");
1358 }
1359
1360 gboolean
e_mail_formatter_get_show_real_date(EMailFormatter * formatter)1361 e_mail_formatter_get_show_real_date (EMailFormatter *formatter)
1362 {
1363 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), FALSE);
1364
1365 return formatter->priv->show_real_date;
1366 }
1367
1368 void
e_mail_formatter_set_show_real_date(EMailFormatter * formatter,gboolean show_real_date)1369 e_mail_formatter_set_show_real_date (EMailFormatter *formatter,
1370 gboolean show_real_date)
1371 {
1372 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
1373
1374 if (formatter->priv->show_real_date == show_real_date)
1375 return;
1376
1377 formatter->priv->show_real_date = show_real_date;
1378
1379 g_object_notify (G_OBJECT (formatter), "show-real-date");
1380 }
1381
1382 gboolean
e_mail_formatter_get_animate_images(EMailFormatter * formatter)1383 e_mail_formatter_get_animate_images (EMailFormatter *formatter)
1384 {
1385 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), FALSE);
1386
1387 return formatter->priv->animate_images;
1388 }
1389
1390 void
e_mail_formatter_set_animate_images(EMailFormatter * formatter,gboolean animate_images)1391 e_mail_formatter_set_animate_images (EMailFormatter *formatter,
1392 gboolean animate_images)
1393 {
1394 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
1395
1396 if (formatter->priv->animate_images == animate_images)
1397 return;
1398
1399 formatter->priv->animate_images = animate_images;
1400
1401 g_object_notify (G_OBJECT (formatter), "animate-images");
1402 }
1403
1404 const gchar *
e_mail_formatter_get_charset(EMailFormatter * formatter)1405 e_mail_formatter_get_charset (EMailFormatter *formatter)
1406 {
1407 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
1408
1409 return formatter->priv->charset;
1410 }
1411
1412 gchar *
e_mail_formatter_dup_charset(EMailFormatter * formatter)1413 e_mail_formatter_dup_charset (EMailFormatter *formatter)
1414 {
1415 const gchar *protected;
1416 gchar *duplicate;
1417
1418 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
1419
1420 g_mutex_lock (&formatter->priv->property_lock);
1421
1422 protected = e_mail_formatter_get_charset (formatter);
1423 duplicate = g_strdup (protected);
1424
1425 g_mutex_unlock (&formatter->priv->property_lock);
1426
1427 return duplicate;
1428 }
1429
1430 void
e_mail_formatter_set_charset(EMailFormatter * formatter,const gchar * charset)1431 e_mail_formatter_set_charset (EMailFormatter *formatter,
1432 const gchar *charset)
1433 {
1434 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
1435
1436 g_mutex_lock (&formatter->priv->property_lock);
1437
1438 if (g_strcmp0 (formatter->priv->charset, charset) == 0) {
1439 g_mutex_unlock (&formatter->priv->property_lock);
1440 return;
1441 }
1442
1443 g_free (formatter->priv->charset);
1444 formatter->priv->charset = g_strdup (charset);
1445
1446 g_mutex_unlock (&formatter->priv->property_lock);
1447
1448 g_object_notify (G_OBJECT (formatter), "charset");
1449 }
1450
1451 const gchar *
e_mail_formatter_get_default_charset(EMailFormatter * formatter)1452 e_mail_formatter_get_default_charset (EMailFormatter *formatter)
1453 {
1454 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
1455
1456 return formatter->priv->default_charset;
1457 }
1458
1459 gchar *
e_mail_formatter_dup_default_charset(EMailFormatter * formatter)1460 e_mail_formatter_dup_default_charset (EMailFormatter *formatter)
1461 {
1462 const gchar *protected;
1463 gchar *duplicate;
1464
1465 g_return_val_if_fail (E_IS_MAIL_FORMATTER (formatter), NULL);
1466
1467 g_mutex_lock (&formatter->priv->property_lock);
1468
1469 protected = e_mail_formatter_get_default_charset (formatter);
1470 duplicate = g_strdup (protected);
1471
1472 g_mutex_unlock (&formatter->priv->property_lock);
1473
1474 return duplicate;
1475 }
1476
1477 void
e_mail_formatter_set_default_charset(EMailFormatter * formatter,const gchar * default_charset)1478 e_mail_formatter_set_default_charset (EMailFormatter *formatter,
1479 const gchar *default_charset)
1480 {
1481 g_return_if_fail (E_IS_MAIL_FORMATTER (formatter));
1482 g_return_if_fail (default_charset && *default_charset);
1483
1484 g_mutex_lock (&formatter->priv->property_lock);
1485
1486 if (g_strcmp0 (formatter->priv->default_charset, default_charset) == 0) {
1487 g_mutex_unlock (&formatter->priv->property_lock);
1488 return;
1489 }
1490
1491 g_free (formatter->priv->default_charset);
1492 formatter->priv->default_charset = g_strdup (default_charset);
1493
1494 g_mutex_unlock (&formatter->priv->property_lock);
1495
1496 g_object_notify (G_OBJECT (formatter), "default-charset");
1497 }
1498
1499