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