Fixed some problems with synchronization between the attachments in
[modest] / src / maemo / modest-msg-edit-window.c
1 /* Copyright (c) 2006, 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 <gtk/gtk.h>
31 #include <glib/gi18n.h>
32 #include <fcntl.h>
33 #include <glib/gstdio.h>
34 #include <string.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38
39 #include <config.h>
40
41 #include <modest-account-mgr.h>
42 #include <modest-account-mgr-helpers.h>
43
44 #include <widgets/modest-msg-edit-window.h>
45 #include <widgets/modest-combo-box.h>
46 #include <widgets/modest-recpt-editor.h>
47 #include <widgets/modest-attachments-view.h>
48
49 #include <modest-runtime.h>
50
51 #include "modest-platform.h"
52 #include "modest-icon-names.h"
53 #include "modest-widget-memory.h"
54 #include "modest-window-priv.h"
55 #include "modest-mail-operation.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-tny-msg.h"
58 #include "modest-address-book.h"
59 #include "modest-text-utils.h"
60 #include <tny-simple-list.h>
61 #include <wptextview.h>
62 #include <wptextbuffer.h>
63 #include "modest-scroll-area.h"
64
65 #include "modest-hildon-includes.h"
66 #include "widgets/modest-msg-edit-window-ui.h"
67 #include <libgnomevfs/gnome-vfs-mime.h>
68
69
70 #define DEFAULT_FONT_SIZE 3
71 #define DEFAULT_FONT 2
72 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
73 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
74 #define DEFAULT_MAIN_VBOX_SPACING 6
75 #define SUBJECT_MAX_LENGTH 1000
76
77 static void  modest_msg_edit_window_class_init   (ModestMsgEditWindowClass *klass);
78 static void  modest_msg_edit_window_init         (ModestMsgEditWindow *obj);
79 static void  modest_msg_edit_window_finalize     (GObject *obj);
80
81 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
82 static void  recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
83 static void  send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
84 static void  style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
85 static void  setup_insensitive_handlers (ModestMsgEditWindow *editor);
86 static void  reset_modified (ModestMsgEditWindow *editor);
87 static gboolean is_modified (ModestMsgEditWindow *editor);
88
89 static void  text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
90 static void  text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata);
91 static void  text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
92 static void  text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
93 static void  subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
94 static void  modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
95                                                          gpointer userdata);
96 static void  modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
97                                                  gpointer userdata);
98 static void  modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
99                                                  gpointer userdata);
100 static void  modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
101 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget, 
102                                                            GdkEventWindowState *event, 
103                                                            gpointer userdata);
104 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
105                                                      ModestRecptEditor *editor);
106 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
107                                                            ModestMsgEditWindow *window);
108
109 /* ModestWindow methods implementation */
110 static void  modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
111 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
112 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
113 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
114 static void modest_msg_edit_window_show_toolbar   (ModestWindow *window,
115                                                    gboolean show_toolbar);
116 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
117                                                            GdkEvent *event,
118                                                            ModestMsgEditWindow *window);
119 static void update_window_title (ModestMsgEditWindow *window);
120 static void update_dimmed (ModestMsgEditWindow *window);
121
122
123 /* list my signals */
124 enum {
125         /* MY_SIGNAL_1, */
126         /* MY_SIGNAL_2, */
127         LAST_SIGNAL
128 };
129
130 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
131 struct _ModestMsgEditWindowPrivate {
132         GtkWidget   *msg_body;
133         GtkWidget   *header_box;
134         
135         ModestPairList *from_field_protos;
136         GtkWidget   *from_field;
137         
138         GtkWidget   *to_field;
139         GtkWidget   *cc_field;
140         GtkWidget   *bcc_field;
141         GtkWidget   *subject_field;
142         GtkWidget   *attachments_view;
143         GtkWidget   *priority_icon;
144         GtkWidget   *add_attachment_button;
145
146         GtkWidget   *cc_caption;
147         GtkWidget   *bcc_caption;
148         GtkWidget   *attachments_caption;
149
150         GtkTextBuffer *text_buffer;
151
152         GtkWidget   *font_size_toolitem;
153         GtkWidget   *font_face_toolitem;
154         GtkWidget   *font_color_button;
155         GSList      *font_items_group;
156         GtkWidget   *font_tool_button_label;
157         GSList      *size_items_group;
158         GtkWidget   *size_tool_button_label;
159
160         GtkWidget   *scroll;
161
162         gint last_cid;
163         GList *attachments;
164
165         TnyHeaderFlags priority_flags;
166
167         gdouble zoom_level;
168         
169         gulong      clipboard_change_handler_id;
170
171         TnyMsg      *draft_msg;
172 };
173
174 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
175                                                     MODEST_TYPE_MSG_EDIT_WINDOW, \
176                                                     ModestMsgEditWindowPrivate))
177 /* globals */
178 static GtkWindowClass *parent_class = NULL;
179
180 /* uncomment the following if you have defined any signals */
181 /* static guint signals[LAST_SIGNAL] = {0}; */
182
183 GType
184 modest_msg_edit_window_get_type (void)
185 {
186         static GType my_type = 0;
187         if (!my_type) {
188                 static const GTypeInfo my_info = {
189                         sizeof(ModestMsgEditWindowClass),
190                         NULL,           /* base init */
191                         NULL,           /* base finalize */
192                         (GClassInitFunc) modest_msg_edit_window_class_init,
193                         NULL,           /* class finalize */
194                         NULL,           /* class data */
195                         sizeof(ModestMsgEditWindow),
196                         1,              /* n_preallocs */
197                         (GInstanceInitFunc) modest_msg_edit_window_init,
198                         NULL
199                 };
200                 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
201                                                   "ModestMsgEditWindow",
202                                                   &my_info, 0);
203
204                 wp_text_buffer_library_init ();
205         }
206         return my_type;
207 }
208
209 static void
210 save_state (ModestWindow *self)
211 {
212         modest_widget_memory_save (modest_runtime_get_conf(),
213                                    G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
214 }
215
216
217 static void
218 restore_settings (ModestMsgEditWindow *self)
219 {
220         modest_widget_memory_restore (modest_runtime_get_conf(),
221                                       G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
222 }
223
224
225 static void
226 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
227 {
228         GObjectClass *gobject_class;
229         ModestWindowClass *modest_window_class;
230         gobject_class = (GObjectClass*) klass;
231         modest_window_class = (ModestWindowClass*) klass;
232
233         parent_class            = g_type_class_peek_parent (klass);
234         gobject_class->finalize = modest_msg_edit_window_finalize;
235
236         modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
237         modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
238         modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
239         modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
240         modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
241
242         g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
243
244         modest_window_class->save_state_func = save_state;
245 }
246
247 static void
248 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
249 {
250         ModestMsgEditWindowPrivate *priv;
251         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
252
253         priv->msg_body      = NULL;
254         priv->from_field    = NULL;
255         priv->to_field      = NULL;
256         priv->cc_field      = NULL;
257         priv->bcc_field     = NULL;
258         priv->subject_field = NULL;
259         priv->attachments   = NULL;
260         priv->last_cid      = 0;
261         priv->zoom_level    = 1.0;
262
263         priv->cc_caption    = NULL;
264         priv->bcc_caption    = NULL;
265
266         priv->priority_flags = 0;
267
268         priv->draft_msg = NULL;
269         priv->clipboard_change_handler_id = 0;
270 }
271
272
273 /* FIXME: this is a dup from the one in gtk/ */
274
275 /** 
276  * @result: A ModestPairList, which must be freed with modest_pair_list_free().
277  */
278 static ModestPairList*
279 get_transports (void)
280 {
281         GSList *transports = NULL;
282         
283         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
284         GSList *accounts = modest_account_mgr_account_names (account_mgr, 
285                                                 TRUE /* only enabled accounts. */); 
286                                                 
287         GSList *cursor = accounts;
288         while (cursor) {
289                 const gchar *account_name = cursor->data;
290                 gchar *from_string  = NULL;
291                 if (account_name) {
292                         from_string = modest_account_mgr_get_from_string (account_mgr,
293                                                                           account_name);
294                 }
295                 
296                 if (from_string && account_name) {
297                         gchar *name = g_strdup (account_name);
298                         ModestPair *pair = modest_pair_new ((gpointer) name,
299                                                 (gpointer) from_string , TRUE);
300                         transports = g_slist_prepend (transports, pair);
301                 }
302                 
303                 cursor = cursor->next;
304         }
305         g_slist_free (accounts);
306         return transports;
307 }
308
309
310 static void
311 init_window (ModestMsgEditWindow *obj)
312 {
313         GtkWidget *from_caption, *to_caption, *subject_caption;
314         GtkWidget *main_vbox;
315         ModestMsgEditWindowPrivate *priv;
316
317         GtkSizeGroup *size_group;
318         GtkWidget *frame;
319         GtkWidget *scroll_area;
320         GtkWidget *subject_box;
321         GtkWidget *attachment_icon;
322
323         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
324
325         size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
326
327         /* Note: This ModestPairList* must exist for as long as the combo
328          * that uses it, because the ModestComboBox uses the ID opaquely, 
329          * so it can't know how to manage its memory. */ 
330         priv->from_field_protos = get_transports ();
331
332         priv->from_field    = modest_combo_box_new (priv->from_field_protos, g_str_equal);
333
334         priv->to_field      = modest_recpt_editor_new ();
335         priv->cc_field      = modest_recpt_editor_new ();
336         priv->bcc_field     = modest_recpt_editor_new ();
337         subject_box = gtk_hbox_new (FALSE, 0);
338         priv->priority_icon = gtk_image_new ();
339         gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
340         priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
341         g_object_set (G_OBJECT (priv->subject_field), "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL);
342         gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
343         priv->add_attachment_button = gtk_button_new ();
344         GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
345         gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
346         gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
347         gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
348         attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
349         gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
350         gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
351         priv->attachments_view = modest_attachments_view_new (NULL);
352         
353         priv->header_box = gtk_vbox_new (FALSE, 0);
354         
355         from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
356         to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
357         priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
358         priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
359         subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
360         priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
361         g_object_unref (size_group);
362
363         size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
364         modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
365         modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
366         modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
367         gtk_size_group_add_widget (size_group, priv->subject_field);
368         gtk_size_group_add_widget (size_group, priv->attachments_view);
369         g_object_unref (size_group);
370
371         gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
372         gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
373         gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
374         gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
375         gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
376         gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
377         gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
378
379
380         priv->msg_body = wp_text_view_new ();
381         gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
382         priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
383         g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
384         wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
385 /*      gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
386         wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
387
388         g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
389                           G_CALLBACK (text_buffer_refresh_attributes), obj);
390         g_signal_connect (G_OBJECT (priv->text_buffer), "delete-range",
391                           G_CALLBACK (text_buffer_delete_range), obj);
392         g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
393                           G_CALLBACK (text_buffer_can_undo), obj);
394         g_signal_connect (G_OBJECT (obj), "window-state-event",
395                           G_CALLBACK (modest_msg_edit_window_window_state_event),
396                           NULL);
397         g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook", 
398                                   G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
399         g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook", 
400                                   G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
401         g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook", 
402                                   G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
403
404         g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
405                           G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
406
407         g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
408                           G_CALLBACK (msg_body_focus), obj);
409         g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
410                           G_CALLBACK (msg_body_focus), obj);
411         g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
412                           "changed", G_CALLBACK (recpt_field_changed), obj);
413         g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
414                           "changed", G_CALLBACK (recpt_field_changed), obj);
415         g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
416                           "changed", G_CALLBACK (recpt_field_changed), obj);
417         recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
418         g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
419
420         priv->scroll = gtk_scrolled_window_new (NULL, NULL);
421         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
422         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
423         
424         main_vbox = gtk_vbox_new  (FALSE, DEFAULT_MAIN_VBOX_SPACING);
425
426         gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
427         frame = gtk_frame_new (NULL);
428         gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
429
430         gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
431         gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
432         gtk_widget_show_all (GTK_WIDGET(priv->scroll));
433         
434         if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL)) {
435                 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
436                 gtk_widget_hide (priv->cc_caption);
437         }
438         if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL)) {
439                 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
440                 gtk_widget_hide (priv->bcc_caption);
441         }
442
443         gtk_container_add (GTK_CONTAINER(obj), priv->scroll);
444         scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
445         gtk_container_add (GTK_CONTAINER (frame), scroll_area);
446         gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area), 
447                                              gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
448
449         priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
450                                                               G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
451 }
452         
453
454
455 static void
456 modest_msg_edit_window_finalize (GObject *obj)
457 {
458         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
459
460         
461         if (priv->clipboard_change_handler_id > 0) {
462                 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
463                 priv->clipboard_change_handler_id = 0;
464         }
465         
466         /* This had to stay alive for as long as the combobox that used it: */
467         modest_pair_list_free (priv->from_field_protos);
468         
469         G_OBJECT_CLASS(parent_class)->finalize (obj);
470 }
471
472 static gboolean
473 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgEditWindow *self)
474 {
475         GtkWidget *close_dialog;
476         ModestMsgEditWindowPrivate *priv;
477         gint response;
478
479         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
480         modest_window_save_state (MODEST_WINDOW (self));
481         if (is_modified (self)) {
482                 close_dialog = hildon_note_new_confirmation (GTK_WINDOW (self), _("mcen_nc_no_email_message_modified_save_changes"));
483                 response = gtk_dialog_run (GTK_DIALOG (close_dialog));
484                 gtk_widget_destroy (close_dialog);
485
486                 if (response != GTK_RESPONSE_CANCEL) {
487                         modest_ui_actions_on_save_to_drafts (NULL, self);
488                 }
489         } 
490 /*      /\* remove old message from drafts *\/ */
491 /*      if (priv->draft_msg) { */
492 /*              TnyHeader *header = tny_msg_get_header (priv->draft_msg); */
493 /*              TnyAccount *account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(), */
494 /*                                                                                         account_name, */
495 /*                                                                                         TNY_ACCOUNT_TYPE_STORE); */
496 /*              TnyFolder *folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS); */
497 /*              g_return_val_if_fail (TNY_IS_HEADER (header), FALSE); */
498 /*              g_return_val_if_fail (TNY_IS_FOLDER (folder), FALSE); */
499 /*              tny_folder_remove_msg (folder, header, NULL); */
500 /*              g_object_unref (folder); */
501 /*              g_object_unref (header); */
502 /*              g_object_unref (priv->draft_msg); */
503 /*              priv->draft_msg = NULL; */
504 /*      } */
505         gtk_widget_destroy (GTK_WIDGET (self));
506         
507         return TRUE;
508 }
509
510 static GtkWidget *
511 menubar_to_menu (GtkUIManager *ui_manager)
512 {
513         GtkWidget *main_menu;
514         GtkWidget *menubar;
515         GList *iter;
516
517         /* Create new main menu */
518         main_menu = gtk_menu_new();
519
520         /* Get the menubar from the UI manager */
521         menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
522
523         iter = gtk_container_get_children (GTK_CONTAINER (menubar));
524         while (iter) {
525                 GtkWidget *menu;
526
527                 menu = GTK_WIDGET (iter->data);
528                 gtk_widget_reparent(menu, main_menu);
529
530                 iter = g_list_next (iter);
531         }
532         return main_menu;
533 }
534
535
536 static void
537 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
538 {
539         TnyHeader *header;
540         const gchar *to, *cc, *bcc, *subject;
541         gchar *body;
542         ModestMsgEditWindowPrivate *priv;
543         GtkTextIter iter;
544         
545         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
546         g_return_if_fail (TNY_IS_MSG (msg));
547
548         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
549
550         header = tny_msg_get_header (msg);
551         to      = tny_header_get_to (header);
552         cc      = tny_header_get_cc (header);
553         bcc     = tny_header_get_bcc (header);
554         subject = tny_header_get_subject (header);
555
556         if (to)
557                 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field),  to);
558         if (cc)
559                 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field),  cc);
560         if (bcc)
561                 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
562         if (subject)
563                 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
564
565         update_window_title (self);
566
567 /*      gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
568         wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
569         body = modest_tny_msg_get_body (msg, TRUE);
570
571         if ((body == NULL)||(body[0] == '\0')) {
572                 g_free (body);
573                 body = modest_text_utils_convert_to_html ("");
574         }
575         wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
576         wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
577                                             (gchar *) body,
578                                             strlen (body));
579         wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
580         g_free (body);
581
582         /* Get the default format required from configuration */
583         if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
584                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
585         }
586
587         /* Set the default focus depending on having already a To: field or not */
588         if ((!to)||(*to == '\0')) {
589                 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
590         } else {
591                 gtk_widget_grab_focus (priv->msg_body);
592         }
593
594         /* TODO: lower priority, select in the From: combo to the
595            value that comes from msg <- not sure, should it be
596            allowed? */
597         
598         /* Add attachments to the view */
599         modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
600         priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
601         if (priv->attachments == NULL) {
602                 gtk_widget_hide (priv->attachments_caption);
603         } else {
604                 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
605                 gtk_widget_show_all (priv->attachments_caption);
606         }
607
608         gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
609         gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
610
611         reset_modified (self);
612
613         update_dimmed (self);
614         text_buffer_can_undo (priv->text_buffer, FALSE, self);
615
616         priv->draft_msg = msg;
617 }
618
619 static void
620 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
621                                 gpointer data)
622 {
623         GList *item_children, *node;
624         GtkWidget *bin_child;
625
626         bin_child = gtk_bin_get_child (GTK_BIN(item));
627
628         item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
629         
630         for (node = item_children; node != NULL; node = g_list_next (node)) {
631                 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
632                         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
633                 }
634         }
635         g_list_free (item_children);
636 }
637
638 static void
639 menu_tool_button_dont_expand (GtkMenuToolButton *item)
640 {
641         GtkWidget *box;
642         GList *item_children, *node;
643
644         box = gtk_bin_get_child (GTK_BIN (item));
645         gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
646         item_children = gtk_container_get_children (GTK_CONTAINER (box));
647         
648         for (node = item_children; node != NULL; node = g_list_next (node)) {
649                 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
650                 if (GTK_IS_TOGGLE_BUTTON (node->data))
651                         gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
652                 else if (GTK_IS_BUTTON (node->data))
653                         gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
654         }
655         g_list_free (item_children);
656 }
657
658
659 static void
660 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
661 {
662         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
663         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
664         GtkWidget *placeholder;
665         GtkWidget *tool_item;
666         gint insert_index;
667         gchar size_text[5];
668         gint size_index;
669         gint font_index;
670         GtkWidget *sizes_menu;
671         GtkWidget *fonts_menu;
672         GSList *radio_group = NULL;
673         GSList *node = NULL;
674         gchar *markup;
675
676         /* Toolbar */
677         parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
678         hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
679
680         /* should we hide the toolbar? */
681         if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
682                 gtk_widget_hide (parent_priv->toolbar);
683
684         /* Font color placeholder */
685         placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
686         insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
687
688         /* font color */
689         tool_item = GTK_WIDGET (gtk_tool_item_new ());
690         priv->font_color_button = hildon_color_button_new ();
691         GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
692         GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
693         gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
694         gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
695         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
696         gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
697         g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
698
699         /* Font size and face placeholder */
700         placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
701         insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
702         /* font_size */
703         tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
704         priv->size_tool_button_label = gtk_label_new (NULL);
705         snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
706         markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
707                               size_text,"</span>", NULL);
708         gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
709         g_free (markup);
710         gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
711         sizes_menu = gtk_menu_new ();
712         priv->size_items_group = NULL;
713         radio_group = NULL;
714         for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
715                 GtkWidget *size_menu_item;
716
717                 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
718                 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
719                 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
720                 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
721                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
722                 gtk_widget_show (size_menu_item);
723
724                 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
725                         
726         }
727
728         for (node = radio_group; node != NULL; node = g_slist_next (node)) {
729                 GtkWidget *item = (GtkWidget *) node->data;
730                 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
731                                   window);
732         }
733
734         priv->size_items_group = g_slist_reverse (priv->size_items_group);
735         gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
736         g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
737         gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
738         gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
739         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
740         menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
741         priv->font_size_toolitem = tool_item;
742
743         /* font face */
744         tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
745         priv->font_tool_button_label = gtk_label_new (NULL);
746         markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
747         gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
748         g_free(markup);
749         gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
750         fonts_menu = gtk_menu_new ();
751         priv->font_items_group = NULL;
752         radio_group = NULL;
753         for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
754                 GtkWidget *font_menu_item;
755                 GtkWidget *child_label;
756
757                 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
758                 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
759                 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>", 
760                                       wp_get_font_name (font_index), "</span>", NULL);
761                 gtk_label_set_markup (GTK_LABEL (child_label), markup);
762                 g_free (markup);
763                 
764                 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
765                 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
766                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
767                 gtk_widget_show (font_menu_item);
768
769                 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
770                         
771         }
772         for (node = radio_group; node != NULL; node = g_slist_next (node)) {
773                 GtkWidget *item = (GtkWidget *) node->data;
774                 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
775                                   window);
776         }
777         priv->font_items_group = g_slist_reverse (priv->font_items_group);
778         gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
779         g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
780         gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
781         gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
782         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
783         menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
784         priv->font_face_toolitem = tool_item;
785
786         /* Set expand and homogeneous for remaining items */
787         tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
788         gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
789         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
790         tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
791         gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
792         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
793         tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
794         gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
795         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
796
797
798 }
799
800
801
802 ModestWindow*
803 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
804 {
805         GObject *obj;
806         ModestWindowPrivate *parent_priv;
807         ModestMsgEditWindowPrivate *priv;
808         GtkActionGroup *action_group;
809         GError *error = NULL;
810         GdkPixbuf *window_icon = NULL;
811         GtkAction *action;
812         ModestConf *conf;
813         gboolean prefer_formatted;
814         gint file_format;
815
816         g_return_val_if_fail (msg, NULL);
817         
818         obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
819
820         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
821         parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
822
823         parent_priv->ui_manager = gtk_ui_manager_new();
824         action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
825         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
826
827         /* Add common actions */
828         gtk_action_group_add_actions (action_group,
829                                       modest_msg_edit_action_entries,
830                                       G_N_ELEMENTS (modest_msg_edit_action_entries),
831                                       obj);
832         gtk_action_group_add_toggle_actions (action_group,
833                                              modest_msg_edit_toggle_action_entries,
834                                              G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
835                                              obj);
836         gtk_action_group_add_radio_actions (action_group,
837                                             modest_msg_edit_alignment_radio_action_entries,
838                                             G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
839                                             GTK_JUSTIFY_LEFT,
840                                             G_CALLBACK (modest_ui_actions_on_change_justify),
841                                             obj);
842         gtk_action_group_add_radio_actions (action_group,
843                                             modest_msg_edit_zoom_action_entries,
844                                             G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
845                                             100,
846                                             G_CALLBACK (modest_ui_actions_on_change_zoom),
847                                             obj);
848         gtk_action_group_add_radio_actions (action_group,
849                                             modest_msg_edit_priority_action_entries,
850                                             G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
851                                             0,
852                                             G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
853                                             obj);
854         gtk_action_group_add_radio_actions (action_group,
855                                             modest_msg_edit_file_format_action_entries,
856                                             G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
857                                             modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
858                                             G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
859                                             obj);
860         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
861         g_object_unref (action_group);
862
863         /* Load the UI definition */
864         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml", &error);
865         if (error != NULL) {
866                 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
867                 g_clear_error (&error);
868         }
869
870         /* Add accelerators */
871         gtk_window_add_accel_group (GTK_WINDOW (obj), 
872                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
873
874         /* Menubar */
875         parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
876         hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
877
878         /* Init window */
879         init_window (MODEST_MSG_EDIT_WINDOW(obj));
880
881         restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
882                 
883         gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
884
885         g_signal_connect (G_OBJECT(obj), "delete-event",
886                           G_CALLBACK(on_delete_event), obj);
887
888         modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
889
890         modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
891
892         setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
893
894         set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
895
896         text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
897
898         /* Set window icon */
899         window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
900         gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
901
902         /* Dim at start clipboard actions */
903         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
904         gtk_action_set_sensitive (action, FALSE);
905         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
906         gtk_action_set_sensitive (action, FALSE);
907
908         /* set initial state of cc and bcc */
909         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
910         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
911                                       modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
912         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
913         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
914                                       modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
915
916         /* Setup the file format */
917         conf = modest_runtime_get_conf ();
918         prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
919         if (error) {
920                 g_clear_error (&error);
921                 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
922         } else
923                 file_format = (prefer_formatted) ? 
924                         MODEST_FILE_FORMAT_FORMATTED_TEXT : 
925                         MODEST_FILE_FORMAT_PLAIN_TEXT;
926         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
927         
928         return (ModestWindow*) obj;
929 }
930
931 static gint
932 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
933 {
934         GString **string_buffer = (GString **) user_data;
935
936         *string_buffer = g_string_append (*string_buffer, buffer);
937    
938         return 0;
939 }
940
941 /**
942  * @result: A new string which should be freed with g_free().
943  */
944 static gchar *
945 get_formatted_data (ModestMsgEditWindow *edit_window)
946 {
947         ModestMsgEditWindowPrivate *priv;
948         GString *string_buffer = g_string_new ("");
949         
950         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
951
952         wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
953
954         return g_string_free (string_buffer, FALSE);
955                                                                         
956 }
957
958 MsgData * 
959 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
960 {
961         MsgData *data;
962         const gchar *account_name;
963         ModestMsgEditWindowPrivate *priv;
964         
965         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
966
967         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
968                                                                         
969         account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
970         g_return_val_if_fail (account_name, NULL);
971         
972         
973         /* don't free these (except from) */
974         data = g_slice_new0 (MsgData);
975         data->from    =  modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
976                                                              account_name);
977         data->account_name = g_strdup (account_name);
978         data->to      =  g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
979         data->cc      =  g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
980         data->bcc     =  g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
981         data->subject =  g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
982         if (priv->draft_msg) {
983                 data->draft_msg = g_object_ref (priv->draft_msg);
984         } else {
985                 data->draft_msg = NULL;
986         }
987
988         GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
989         GtkTextIter b, e;
990         gtk_text_buffer_get_bounds (buf, &b, &e);
991         data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
992
993         if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
994                 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
995         else
996                 data->html_body = NULL;
997
998         data->attachments = priv->attachments; /* TODO: copy and free ? */
999         data->priority_flags = priv->priority_flags;
1000
1001         return data;
1002 }
1003
1004 /* TODO: We must duplicate this implementation for GNOME and Maemo, but that is unwise. */
1005 void 
1006 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1007                                                       MsgData *data)
1008 {
1009         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1010
1011         if (!data)
1012                 return;
1013
1014         g_free (data->to);
1015         g_free (data->cc);
1016         g_free (data->bcc);
1017         g_free (data->subject);
1018         g_free (data->plain_body);
1019         g_free (data->html_body);
1020         if (data->draft_msg != NULL) {
1021                 g_object_unref (data->draft_msg);
1022                 data->draft_msg = NULL;
1023         }
1024         g_free (data->account_name);
1025
1026         /* TODO: Free data->attachments? */
1027
1028         g_slice_free (MsgData, data);
1029 }
1030
1031 ModestMsgEditFormat
1032 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1033 {
1034         gboolean rich_text;
1035         ModestMsgEditWindowPrivate *priv = NULL;
1036         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1037
1038         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1039
1040         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1041         if (rich_text)
1042                 return MODEST_MSG_EDIT_FORMAT_HTML;
1043         else
1044                 return MODEST_MSG_EDIT_FORMAT_TEXT;
1045 }
1046
1047 void
1048 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1049                                    ModestMsgEditFormat format)
1050 {
1051         ModestMsgEditWindowPrivate *priv;
1052
1053         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1054         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1055
1056         switch (format) {
1057         case MODEST_MSG_EDIT_FORMAT_HTML:
1058                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1059                 break;
1060         case MODEST_MSG_EDIT_FORMAT_TEXT:
1061                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1062                 break;
1063         default:
1064                 g_return_if_reached ();
1065         }
1066 }
1067
1068 ModestMsgEditFormatState *
1069 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1070 {
1071         ModestMsgEditFormatState *format_state = NULL;
1072         ModestMsgEditWindowPrivate *priv;
1073         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1074
1075         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1076         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1077
1078         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1079
1080         format_state = g_new0 (ModestMsgEditFormatState, 1);
1081         format_state->bold = buffer_format->bold&0x1;
1082         format_state->italics = buffer_format->italic&0x1;
1083         format_state->bullet = buffer_format->bullet&0x1;
1084         format_state->color = buffer_format->color;
1085         format_state->font_size = buffer_format->font_size;
1086         format_state->font_family = wp_get_font_name (buffer_format->font);
1087         format_state->justification = buffer_format->justification;
1088         g_free (buffer_format);
1089
1090         return format_state;
1091  
1092 }
1093
1094 void
1095 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1096                                          const ModestMsgEditFormatState *format_state)
1097 {
1098         ModestMsgEditWindowPrivate *priv;
1099         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1100         WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1101         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1102         g_return_if_fail (format_state != NULL);
1103
1104         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1105         gtk_widget_grab_focus (priv->msg_body);
1106         buffer_format->bold = (format_state->bold != FALSE);
1107         buffer_format->italic = (format_state->italics != FALSE);
1108         buffer_format->color = format_state->color;
1109         buffer_format->font_size = format_state->font_size;
1110         buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1111         buffer_format->justification = format_state->justification;
1112         buffer_format->bullet = format_state->bullet;
1113
1114         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1115
1116         buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1117         buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1118         buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1119         buffer_format->cs.font_size =  (buffer_format->font_size != current_format->font_size);
1120         buffer_format->cs.font = (buffer_format->font != current_format->font);
1121         buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1122         buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1123
1124         wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1125         if (buffer_format->cs.bold) {
1126                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1127         }
1128         if (buffer_format->cs.italic) {
1129                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1130         }
1131         if (buffer_format->cs.color) {
1132                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1133         }
1134         if (buffer_format->cs.font_size) {
1135                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font_size));
1136         }
1137         if (buffer_format->cs.justification) {
1138                 switch (buffer_format->justification) {
1139                 case GTK_JUSTIFY_LEFT:
1140                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1141                         break;
1142                 case GTK_JUSTIFY_CENTER:
1143                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1144                         break;
1145                 case GTK_JUSTIFY_RIGHT:
1146                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1147                         break;
1148                 default:
1149                         break;
1150                 }
1151                         
1152         }
1153         if (buffer_format->cs.font) {
1154                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font));
1155         }
1156         if (buffer_format->cs.bullet) {
1157                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) (buffer_format->bullet));
1158         }
1159 /*      wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1160         wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1161
1162         g_free (current_format);
1163
1164 }
1165
1166 static void
1167 toggle_action_set_active_block_notify (GtkToggleAction *action,
1168                                        gboolean value)
1169 {
1170         GSList *proxies = NULL;
1171
1172         for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1173              proxies != NULL; proxies = g_slist_next (proxies)) {
1174                 GtkWidget *widget = (GtkWidget *) proxies->data;
1175                 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1176         }
1177
1178         gtk_toggle_action_set_active (action, value);
1179
1180         for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1181              proxies != NULL; proxies = g_slist_next (proxies)) {
1182                 GtkWidget *widget = (GtkWidget *) proxies->data;
1183                 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1184         }
1185 }
1186
1187 static void
1188 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1189 {
1190         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1191         GtkAction *action;
1192         ModestWindowPrivate *parent_priv;
1193         ModestMsgEditWindowPrivate *priv;
1194         GtkWidget *new_size_menuitem;
1195         GtkWidget *new_font_menuitem;
1196         
1197         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1198         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1199
1200         if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1201                 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1202                 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1203                         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1204         } else {
1205                 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1206                 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1207                         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1208         }
1209
1210         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1211         
1212         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1213         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1214
1215         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1216         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1217
1218         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1219         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1220
1221         g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button), 
1222                                          G_CALLBACK (modest_msg_edit_window_color_button_change),
1223                                          window);
1224         hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1225         g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button), 
1226                                            G_CALLBACK (modest_msg_edit_window_color_button_change),
1227                                            window);
1228
1229         new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group, 
1230                                                       buffer_format->font_size))->data);
1231         if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1232                 GtkWidget *label;
1233                 gchar *markup;
1234
1235                 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1236                 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1237                 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1238                 g_free (markup);
1239                 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1240                                                  G_CALLBACK (modest_msg_edit_window_size_change),
1241                                                  window);
1242                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1243                 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1244                                                    G_CALLBACK (modest_msg_edit_window_size_change),
1245                                                    window);
1246         }
1247
1248         new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group, 
1249                                                       buffer_format->font))->data);
1250         if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1251                 GtkWidget *label;
1252                 gchar *markup;
1253
1254                 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1255                 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1256                 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1257                 g_free (markup);
1258                 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1259                                                  G_CALLBACK (modest_msg_edit_window_font_change),
1260                                                  window);
1261                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1262                 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1263                                                    G_CALLBACK (modest_msg_edit_window_font_change),
1264                                                    window);
1265         }
1266
1267         g_free (buffer_format);
1268
1269 }
1270
1271
1272 void
1273 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1274 {
1275         
1276         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1277         ModestMsgEditWindowPrivate *priv;
1278         GtkWidget *dialog = NULL;
1279         gint response;
1280         const GdkColor *new_color = NULL;
1281         
1282         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1283         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1284         
1285 #ifdef MODEST_HILDON_VERSION_0  
1286         dialog = hildon_color_selector_new (GTK_WINDOW (window));
1287         hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1288 #else
1289         dialog = hildon_color_chooser_new ();
1290         hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1291 #endif /*MODEST_HILDON_VERSION_0*/              
1292         g_free (buffer_format);
1293
1294         response = gtk_dialog_run (GTK_DIALOG (dialog));
1295         switch (response) {
1296         case GTK_RESPONSE_OK: {
1297 #ifdef MODEST_HILDON_VERSION_0
1298                 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1299 #else
1300                 GdkColor col;
1301                 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1302                 new_color = &col;
1303 #endif /*MODEST_HILDON_VERSION_0*/
1304         }
1305
1306         break;
1307         default:
1308                 break;
1309         }
1310         gtk_widget_destroy (dialog);
1311
1312         if (new_color != NULL)
1313                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1314
1315 }
1316
1317 void
1318 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1319 {
1320         
1321         ModestMsgEditWindowPrivate *priv;
1322         GtkWidget *dialog = NULL;
1323         gint response;
1324         GdkColor *old_color = NULL;
1325         const GdkColor *new_color = NULL;
1326         
1327         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1328         old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1329         
1330 #ifdef MODEST_HILDON_VERSION_0  
1331         dialog = hildon_color_selector_new (GTK_WINDOW (window));
1332         hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1333 #else
1334         dialog = hildon_color_chooser_new ();
1335         hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1336 #endif /*MODEST_HILDON_VERSION_9*/              
1337
1338         response = gtk_dialog_run (GTK_DIALOG (dialog));
1339         switch (response) {
1340         case GTK_RESPONSE_OK: {
1341 #ifdef MODEST_HILDON_VERSION_0
1342                 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1343 #else
1344                 GdkColor col;
1345                 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1346                 new_color = &col;
1347 #endif /*MODEST_HILDON_VERSION_0*/
1348           }
1349                 break;
1350         default:
1351                 break;
1352         }
1353         gtk_widget_destroy (dialog);
1354
1355         if (new_color != NULL)
1356                 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1357
1358 }
1359
1360 void
1361 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1362 {
1363         
1364         ModestMsgEditWindowPrivate *priv;
1365         GtkWidget *dialog = NULL;
1366         gint response = 0;
1367         gchar *filename = NULL;
1368         
1369         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1370         
1371         dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1372
1373         response = gtk_dialog_run (GTK_DIALOG (dialog));
1374         switch (response) {
1375         case GTK_RESPONSE_OK:
1376                 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1377                 break;
1378         default:
1379                 break;
1380         }
1381         gtk_widget_destroy (dialog);
1382
1383         if (filename) {
1384                 GdkPixbuf *pixbuf = NULL;
1385                 GtkTextIter position;
1386                 GtkTextMark *insert_mark;
1387
1388                 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1389                 if (pixbuf) {
1390                         gint image_file_id;
1391                         GdkPixbufFormat *pixbuf_format;
1392
1393                         image_file_id = g_open (filename, O_RDONLY, 0);
1394                         pixbuf_format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
1395                         if ((image_file_id != -1)&&(pixbuf_format != NULL)) {
1396                                 TnyMimePart *image_part;
1397                                 TnyStream *image_stream;
1398                                 gchar **mime_types;
1399                                 gchar *mime_type;
1400                                 gchar *basename;
1401                                 gchar *content_id;
1402
1403                                 mime_types = gdk_pixbuf_format_get_mime_types (pixbuf_format);
1404                                 if ((mime_types != NULL) && (mime_types[0] != NULL)) {
1405                                         mime_type = mime_types[0];
1406                                 } else {
1407                                         mime_type = "image/unknown";
1408                                 }
1409                                 image_part = tny_platform_factory_new_mime_part
1410                                         (modest_runtime_get_platform_factory ());
1411                                 image_stream = TNY_STREAM (tny_fs_stream_new (image_file_id));
1412
1413                                 tny_mime_part_construct_from_stream (image_part, image_stream, mime_type);
1414                                 g_strfreev (mime_types);
1415
1416                                 content_id = g_strdup_printf ("%d", priv->last_cid);
1417                                 tny_mime_part_set_content_id (image_part, content_id);
1418                                 g_free (content_id);
1419                                 priv->last_cid++;
1420
1421                                 basename = g_path_get_basename (filename);
1422                                 tny_mime_part_set_filename (image_part, basename);
1423                                 g_free (basename);
1424                                 
1425                                 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1426                                 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1427                                 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (image_part)), pixbuf);
1428                                 priv->attachments = g_list_prepend (priv->attachments, image_part);
1429                                 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1430                                                                         image_part);
1431                                 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1432                                 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1433                                 gtk_widget_show_all (priv->attachments_caption);
1434                         } else if (image_file_id == -1) {
1435                                 close (image_file_id);
1436                         }
1437                 }
1438         }
1439
1440
1441 }
1442
1443 void
1444 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1445 {
1446         
1447         ModestMsgEditWindowPrivate *priv;
1448         GtkWidget *dialog = NULL;
1449         gint response = 0;
1450         gchar *uri = NULL, *filename = NULL;
1451         
1452         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1453         
1454         dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1455
1456         response = gtk_dialog_run (GTK_DIALOG (dialog));
1457         switch (response) {
1458         case GTK_RESPONSE_OK:
1459                 uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
1460                 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1461                 break;
1462         default:
1463                 break;
1464         }
1465         gtk_widget_destroy (dialog);
1466
1467         if (uri) {
1468
1469                 GnomeVFSHandle *handle = NULL;
1470                 GnomeVFSResult result;
1471
1472                 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1473                 if (result == GNOME_VFS_OK) {
1474                         TnyMimePart *mime_part;
1475                         TnyStream *stream;
1476                         const gchar *mime_type = NULL;
1477                         gchar *basename;
1478                         gchar *content_id;
1479                         GnomeVFSFileInfo info;
1480                         
1481                         if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1482                                 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1483                         mime_part = tny_platform_factory_new_mime_part
1484                                 (modest_runtime_get_platform_factory ());
1485                         stream = TNY_STREAM (tny_vfs_stream_new (handle));
1486                         
1487                         tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1488                         
1489                         content_id = g_strdup_printf ("%d", priv->last_cid);
1490                         tny_mime_part_set_content_id (mime_part, content_id);
1491                         g_free (content_id);
1492                         priv->last_cid++;
1493                         
1494                         basename = g_path_get_basename (filename);
1495                         tny_mime_part_set_filename (mime_part, basename);
1496                         g_free (basename);
1497                         
1498                         priv->attachments = g_list_prepend (priv->attachments, mime_part);
1499                         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1500                                                                 mime_part);
1501                         gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1502                         gtk_widget_show_all (priv->attachments_caption);
1503                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1504                 } 
1505                 g_free (filename);
1506         }
1507 }
1508
1509 void
1510 modest_msg_edit_window_attach_file_noninteractive (
1511                 ModestMsgEditWindow *window,
1512                 gchar *filename)
1513 {
1514         
1515         ModestMsgEditWindowPrivate *priv;
1516         
1517         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1518
1519         if (filename) {
1520                 gint file_id;
1521                 
1522                 file_id = g_open (filename, O_RDONLY, 0);
1523                 if (file_id != -1) {
1524                         TnyMimePart *mime_part;
1525                         TnyStream *stream;
1526                         const gchar *mime_type;
1527                         gchar *basename;
1528                         gchar *content_id;
1529                         
1530                         mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1531                         mime_part = tny_platform_factory_new_mime_part
1532                                 (modest_runtime_get_platform_factory ());
1533                         stream = TNY_STREAM (tny_fs_stream_new (file_id));
1534                         
1535                         tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1536                         
1537                         content_id = g_strdup_printf ("%d", priv->last_cid);
1538                         tny_mime_part_set_content_id (mime_part, content_id);
1539                         g_free (content_id);
1540                         priv->last_cid++;
1541                         
1542                         basename = g_path_get_basename (filename);
1543                         tny_mime_part_set_filename (mime_part, basename);
1544                         g_free (basename);
1545                         
1546                         priv->attachments = g_list_prepend (priv->attachments, mime_part);
1547                         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1548                                                                 mime_part);
1549                         gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1550                         gtk_widget_show_all (priv->attachments_caption);
1551                 } else if (file_id == -1) {
1552                         close (file_id);
1553                 }
1554         }
1555 }
1556
1557 void
1558 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1559                                           GList *att_list)
1560 {
1561         ModestMsgEditWindowPrivate *priv;
1562         gboolean clean_list = FALSE;
1563
1564         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1565         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1566
1567         if (att_list == NULL) {
1568                 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1569                 clean_list = TRUE;
1570         }
1571
1572         if (att_list == NULL) {
1573                 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1574         } else {
1575                 GtkWidget *confirmation_dialog = NULL;
1576                 gboolean dialog_response;
1577                 GList *node;
1578                 if (att_list->next == NULL) {
1579                         gchar *message = g_strdup_printf (_("emev_nc_delete_attachment"), 
1580                                                           tny_mime_part_get_filename (TNY_MIME_PART (att_list->data)));
1581                         confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1582                         g_free (message);
1583                 } else {
1584                         confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), _("emev_nc_delete_attachments"));
1585                 }
1586                 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1587                 gtk_widget_destroy (confirmation_dialog);
1588                 if (!dialog_response) {
1589                         if (clean_list)
1590                                 g_list_free (att_list);
1591                         return;
1592                 }
1593                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1594
1595                 for (node = att_list; node != NULL; node = g_list_next (node)) {
1596                         TnyMimePart *mime_part = (TnyMimePart *) node->data;
1597                         const gchar *att_id;
1598                         priv->attachments = g_list_remove (priv->attachments, mime_part);
1599
1600                         modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1601                                                                    mime_part);
1602                         if (priv->attachments == NULL)
1603                                 gtk_widget_hide (priv->attachments_caption);
1604                         att_id = tny_mime_part_get_content_id (mime_part);
1605                         if (att_id != NULL)
1606                                 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1607                                                                  att_id);
1608                         g_object_unref (mime_part);
1609                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1610                 }
1611         }
1612
1613         if (clean_list)
1614                 g_list_free (att_list);
1615 }
1616
1617 static void
1618 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1619                                             gpointer userdata)
1620 {
1621         ModestMsgEditWindowPrivate *priv;
1622         GdkColor *new_color;
1623         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1624         
1625 #ifdef MODEST_HILDON_VERSION_0  
1626         new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1627 #else 
1628         GdkColor col;
1629         hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1630         new_color = &col;
1631 #endif /*MODEST_HILDON_VERSION_0*/
1632
1633         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1634         
1635         gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1636
1637 }
1638
1639 static void
1640 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1641                                     gpointer userdata)
1642 {
1643         ModestMsgEditWindowPrivate *priv;
1644         gint new_size_index;
1645         ModestMsgEditWindow *window;
1646         GtkWidget *label;
1647         
1648         window = MODEST_MSG_EDIT_WINDOW (userdata);
1649         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1650         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1651
1652         if (gtk_check_menu_item_get_active (menu_item)) {
1653                 gchar *markup;
1654                 WPTextBufferFormat format;
1655
1656                 memset (&format, 0, sizeof (format));
1657                 wp_text_buffer_get_current_state (WP_TEXT_BUFFER (priv->text_buffer), &format);
1658
1659                 label = gtk_bin_get_child (GTK_BIN (menu_item));
1660                 
1661                 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1662                 format.cs.font_size = TRUE;
1663                 format.cs.text_position = TRUE;
1664                 format.cs.font = TRUE;
1665                 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1666                 wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format);
1667
1668 /*              if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, */
1669 /*                                                 (gpointer) wp_get_font_size_index (new_size_index, 12))) */
1670 /*                      wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body)); */
1671                 
1672                 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1673                 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1674                 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1675                 g_free (markup);
1676         }
1677 }
1678
1679 static void
1680 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1681                                     gpointer userdata)
1682 {
1683         ModestMsgEditWindowPrivate *priv;
1684         gint new_font_index;
1685         ModestMsgEditWindow *window;
1686         GtkWidget *label;
1687         
1688         window = MODEST_MSG_EDIT_WINDOW (userdata);
1689         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1690         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1691
1692         if (gtk_check_menu_item_get_active (menu_item)) {
1693                 gchar *markup;
1694
1695                 label = gtk_bin_get_child (GTK_BIN (menu_item));
1696                 
1697                 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1698
1699                 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, 
1700                                                    (gpointer) new_font_index))
1701                         wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1702                 
1703                 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1704                     markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1705                 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1706                 g_free (markup);
1707         }
1708 }
1709
1710 static void
1711 modest_msg_edit_window_set_zoom (ModestWindow *window,
1712                                  gdouble zoom)
1713 {
1714         ModestMsgEditWindowPrivate *priv;
1715      
1716         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1717
1718         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1719         priv->zoom_level = zoom;
1720         wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1721 }
1722
1723 static gdouble
1724 modest_msg_edit_window_get_zoom (ModestWindow *window)
1725 {
1726         ModestMsgEditWindowPrivate *priv;
1727      
1728         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1729
1730         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1731         return priv->zoom_level;
1732 }
1733
1734 static gboolean
1735 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1736 {
1737         ModestWindowPrivate *parent_priv;
1738         GtkRadioAction *zoom_radio_action;
1739         GSList *group, *node;
1740
1741         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1742         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1743                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1744
1745         group = gtk_radio_action_get_group (zoom_radio_action);
1746
1747         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1748                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_max_zoom_level"));
1749                 return FALSE;
1750         }
1751
1752         for (node = group; node != NULL; node = g_slist_next (node)) {
1753                 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1754                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1755                         return TRUE;
1756                 }
1757         }
1758         return FALSE;
1759 }
1760
1761 static gboolean
1762 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1763 {
1764         ModestWindowPrivate *parent_priv;
1765         GtkRadioAction *zoom_radio_action;
1766         GSList *group, *node;
1767
1768         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1769         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1770                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1771
1772         group = gtk_radio_action_get_group (zoom_radio_action);
1773
1774         for (node = group; node != NULL; node = g_slist_next (node)) {
1775                 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1776                         if (node->next != NULL) {
1777                                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1778                                 return TRUE;
1779                         } else
1780                                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_min_zoom_level"));
1781                         break;
1782                 }
1783         }
1784         return FALSE;
1785 }
1786
1787 static gboolean
1788 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1789 {
1790         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1791                 ModestWindowPrivate *parent_priv;
1792                 ModestWindowMgr *mgr;
1793                 gboolean is_fullscreen;
1794                 GtkAction *fs_toggle_action;
1795                 gboolean active;
1796
1797                 mgr = modest_runtime_get_window_mgr ();
1798                 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1799
1800                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1801                 
1802                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1803                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1804                 if (is_fullscreen != active)
1805                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1806         }
1807
1808         return FALSE;
1809
1810 }
1811
1812 void
1813 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1814 {
1815         ModestWindowPrivate *parent_priv;
1816         GtkAction *fs_toggle_action;
1817         gboolean active;
1818
1819         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1820
1821         fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1822         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1823         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1824 }
1825
1826 void
1827 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window, 
1828                                 gboolean show)
1829 {
1830         ModestMsgEditWindowPrivate *priv = NULL;
1831         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1832
1833         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1834         gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1835         if (show)
1836                 gtk_widget_show (priv->cc_caption);
1837         else
1838                 gtk_widget_hide (priv->cc_caption);
1839         modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
1840 }
1841
1842 void
1843 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window, 
1844                                  gboolean show)
1845 {
1846         ModestMsgEditWindowPrivate *priv = NULL;
1847         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1848
1849         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1850         gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1851         if (show)
1852                 gtk_widget_show (priv->bcc_caption);
1853         else
1854                 gtk_widget_hide (priv->bcc_caption);
1855         modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
1856 }
1857
1858 static void
1859 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
1860                                          ModestRecptEditor *editor)
1861 {
1862         ModestMsgEditWindowPrivate *priv;
1863
1864         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1865         g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
1866         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1867
1868         if (editor == NULL) {
1869                 GtkWidget *view_focus;
1870                 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
1871
1872                 /* This code should be kept in sync with ModestRecptEditor. The
1873                    textview inside the recpt editor is the one that really gets the
1874                    focus. As it's inside a scrolled window, and this one inside the
1875                    hbox recpt editor inherits from, we'll need to go up in the 
1876                    hierarchy to know if the text view is part of the recpt editor
1877                    or if it's a different text entry */
1878
1879                 if (gtk_widget_get_parent (view_focus)) {
1880                         GtkWidget *first_parent;
1881
1882                         first_parent = gtk_widget_get_parent (view_focus);
1883                         if (gtk_widget_get_parent (first_parent) && 
1884                             MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
1885                                 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
1886                         }
1887                 }
1888
1889                 if (editor == NULL)
1890                         editor = MODEST_RECPT_EDITOR (priv->to_field);
1891
1892         }
1893
1894         modest_address_book_select_addresses (editor);
1895
1896 }
1897
1898 void
1899 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
1900 {
1901         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1902
1903         modest_msg_edit_window_open_addressbook (window, NULL);
1904 }
1905
1906 static void
1907 modest_msg_edit_window_show_toolbar (ModestWindow *self,
1908                                      gboolean show_toolbar)
1909 {
1910         ModestWindowPrivate *parent_priv;
1911         
1912         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1913         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1914
1915         /* FIXME: we can not just use the code of
1916            modest_msg_edit_window_setup_toolbar because it has a
1917            mixture of both initialization and creation code. */
1918
1919         if (show_toolbar)
1920                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1921         else
1922                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1923 }
1924
1925 void
1926 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
1927                                            TnyHeaderFlags priority_flags)
1928 {
1929         ModestMsgEditWindowPrivate *priv;
1930
1931         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1932
1933         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1934         priority_flags = priority_flags & (TNY_HEADER_FLAG_HIGH_PRIORITY);
1935
1936         if (priv->priority_flags != priority_flags) {
1937
1938                 priv->priority_flags = priority_flags;
1939
1940                 switch (priority_flags) {
1941                 case TNY_HEADER_FLAG_HIGH_PRIORITY:
1942                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
1943                         gtk_widget_show (priv->priority_icon);
1944                         break;
1945                 case TNY_HEADER_FLAG_LOW_PRIORITY:
1946                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
1947                         gtk_widget_show (priv->priority_icon);
1948                         break;
1949                 default:
1950                         gtk_widget_hide (priv->priority_icon);
1951                         break;
1952                 }
1953         }
1954 }
1955
1956 void
1957 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
1958                                         gint file_format)
1959 {
1960         ModestMsgEditWindowPrivate *priv;
1961         gint current_format;
1962
1963         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1964
1965         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1966
1967         current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
1968                 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
1969
1970         if (current_format != file_format) {
1971                 switch (file_format) {
1972                 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
1973                         wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1974                         break;
1975                 case MODEST_FILE_FORMAT_PLAIN_TEXT:
1976                 {
1977                         GtkWidget *dialog;
1978                         gint response;
1979                         dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
1980                         response = gtk_dialog_run (GTK_DIALOG (dialog));
1981                         gtk_widget_destroy (dialog);
1982                         if (response == GTK_RESPONSE_OK)
1983                                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1984                 }
1985                         break;
1986                 }
1987                 update_dimmed (window);
1988         }
1989 }
1990
1991 void
1992 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
1993 {
1994         GtkWidget *dialog;
1995         ModestMsgEditWindowPrivate *priv;
1996         WPTextBufferFormat oldfmt, fmt;
1997         gint old_position = 0;
1998         gint response = 0;
1999         gint position = 0;
2000         gint font_size;
2001         GdkColor *color = NULL;
2002         gboolean bold, bold_set, italic, italic_set;
2003         gboolean underline, underline_set;
2004         gboolean strikethrough, strikethrough_set;
2005         gboolean position_set;
2006         gboolean font_size_set, font_set, color_set;
2007         gchar *font_name;
2008
2009         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2010         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2011         
2012         dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2013
2014         /* First we get the currently selected font information */
2015         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2016         g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2017
2018         switch (oldfmt.text_position) {
2019         case TEXT_POSITION_NORMAL:
2020                 old_position = 0;
2021                 break;
2022         case TEXT_POSITION_SUPERSCRIPT:
2023                 old_position = 1;
2024                 break;
2025         default:
2026                 old_position = -1;
2027                 break;
2028         }
2029
2030         g_object_set (G_OBJECT (dialog),
2031                       "bold", oldfmt.bold != FALSE,
2032                       "bold-set", !oldfmt.cs.bold,
2033                       "underline", oldfmt.underline != FALSE,
2034                       "underline-set", !oldfmt.cs.underline,
2035                       "italic", oldfmt.italic != FALSE,
2036                       "italic-set", !oldfmt.cs.italic,
2037                       "strikethrough", oldfmt.strikethrough != FALSE,
2038                       "strikethrough-set", !oldfmt.cs.strikethrough,
2039                       "color", &oldfmt.color,
2040                       "color-set", !oldfmt.cs.color,
2041                       "size", wp_font_size[oldfmt.font_size],
2042                       "size-set", !oldfmt.cs.font_size,
2043                       "position", old_position,
2044                       "position-set", !oldfmt.cs.text_position,
2045                       "family", wp_get_font_name (oldfmt.font),
2046                       "family-set", !oldfmt.cs.font,
2047                       NULL);
2048
2049         gtk_widget_show_all (dialog);
2050         response = gtk_dialog_run (GTK_DIALOG (dialog));
2051         if (response == GTK_RESPONSE_OK) {
2052
2053                 g_object_get( dialog,
2054                               "bold", &bold,
2055                               "bold-set", &bold_set,
2056                               "underline", &underline,
2057                               "underline-set", &underline_set,
2058                               "italic", &italic,
2059                               "italic-set", &italic_set,
2060                               "strikethrough", &strikethrough,
2061                               "strikethrough-set", &strikethrough_set,
2062                               "color", &color,
2063                               "color-set", &color_set,
2064                               "size", &font_size,
2065                               "size-set", &font_size_set,
2066                               "family", &font_name,
2067                               "family-set", &font_set,
2068                               "position", &position,
2069                               "position-set", &position_set,
2070                               NULL );
2071                 
2072         }       
2073
2074         if (response == GTK_RESPONSE_OK) {
2075                 memset(&fmt, 0, sizeof(fmt));
2076                 if (bold_set) {
2077                         fmt.bold = bold;
2078                         fmt.cs.bold = TRUE;
2079                 }
2080                 if (italic_set) {
2081                         fmt.italic = italic;
2082                         fmt.cs.italic = TRUE;
2083                 }
2084                 if (underline_set) {
2085                         fmt.underline = underline;
2086                         fmt.cs.underline = TRUE;
2087                 }
2088                 if (strikethrough_set) {
2089                         fmt.strikethrough = strikethrough;
2090                         fmt.cs.strikethrough = TRUE;
2091                 }
2092                 if (position_set) {
2093                         fmt.text_position =
2094                                 ( position == 0 )
2095                                 ? TEXT_POSITION_NORMAL
2096                                 : ( ( position == 1 )
2097                                     ? TEXT_POSITION_SUPERSCRIPT
2098                                     : TEXT_POSITION_SUBSCRIPT );
2099                         fmt.cs.text_position = TRUE;
2100                 }
2101                 if (color_set) {
2102                         fmt.color = *color;
2103                         fmt.cs.color = TRUE;
2104                 }
2105                 if (font_set) {
2106                         fmt.font = wp_get_font_index(font_name,
2107                                                      DEFAULT_FONT);
2108                         fmt.cs.font = TRUE;
2109                 }
2110                 g_free(font_name);
2111                 if (font_size_set) {
2112                         fmt.font_size = wp_get_font_size_index(
2113                                 font_size, DEFAULT_FONT_SIZE);
2114                         fmt.cs.font_size = TRUE;
2115                 }
2116                 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2117         }
2118         gtk_widget_destroy (dialog);
2119         
2120         gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2121 }
2122
2123 void
2124 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2125 {
2126         ModestMsgEditWindowPrivate *priv;
2127
2128         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2129         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2130         
2131         wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2132
2133         update_dimmed (window);
2134
2135 }
2136
2137 static void
2138 update_dimmed (ModestMsgEditWindow *window)
2139 {
2140         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2141         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2142         GtkAction *action;
2143         GtkWidget *widget;
2144         gboolean rich_text;
2145         gboolean editor_focused;
2146
2147         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2148         editor_focused = gtk_widget_is_focus (priv->msg_body);
2149
2150         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2151         gtk_action_set_sensitive (action, rich_text && editor_focused);
2152         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2153         gtk_action_set_sensitive (action, rich_text && editor_focused);
2154         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2155         gtk_action_set_sensitive (action, rich_text && editor_focused);
2156         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2157         gtk_action_set_sensitive (action, rich_text && editor_focused);
2158         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2159         gtk_action_set_sensitive (action, rich_text && editor_focused);
2160         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2161         gtk_action_set_sensitive (action, rich_text && editor_focused);
2162         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2163         gtk_action_set_sensitive (action, rich_text && editor_focused);
2164         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2165         gtk_action_set_sensitive (action, rich_text && editor_focused);
2166         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2167         gtk_action_set_sensitive (action, rich_text && editor_focused);
2168         widget = priv->font_color_button;
2169         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2170         widget = priv->font_size_toolitem;
2171         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2172         widget = priv->font_face_toolitem;
2173         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2174 }
2175
2176 static void
2177 setup_insensitive_handlers (ModestMsgEditWindow *window)
2178 {
2179         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2180         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2181         GtkWidget *widget;
2182
2183         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2184         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2185         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2186         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2187
2188         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2189         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2190         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2191         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2192         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2193         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2194         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2195         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2196         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2197         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2198         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2199         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2200         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2201         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2202         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2203         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2204         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2205         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2206         widget = priv->font_color_button;
2207         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2208         widget = priv->font_size_toolitem;
2209         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2210         widget = priv->font_face_toolitem;
2211         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2212
2213 }
2214
2215 static void  
2216 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2217 {
2218         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2219         GtkAction *action;
2220
2221         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2222         gtk_action_set_sensitive (action, can_undo);
2223 }
2224
2225 static void
2226 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2227 {
2228         GtkTextIter iter;
2229         GtkTextIter match_start, match_end;
2230
2231         if (image_id == NULL)
2232                 return;
2233
2234         gtk_text_buffer_get_start_iter (buffer, &iter);
2235
2236         while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2237                 GSList *tags = gtk_text_iter_get_tags (&match_start);
2238                 GSList *node;
2239                 for (node = tags; node != NULL; node = g_slist_next (node)) {
2240                         GtkTextTag *tag = (GtkTextTag *) node->data;
2241                         if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2242                                 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2243                                 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2244                                         gint offset;
2245                                         offset = gtk_text_iter_get_offset (&match_start);
2246                                         gtk_text_buffer_delete (buffer, &match_start, &match_end);
2247                                         gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2248                                 }
2249                         }
2250                 }
2251                 gtk_text_iter_forward_char (&iter);
2252         }
2253 }
2254
2255 static void
2256 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2257 {
2258         ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2259         GtkTextIter real_start, real_end;
2260         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2261
2262         if (gtk_text_iter_compare (start, end) > 0) {
2263                 real_start = *end;
2264                 real_end = *start;
2265         } else {
2266                 real_start = *start;
2267                 real_end = *end;
2268         }
2269         do {
2270                 GSList *tags = gtk_text_iter_get_tags (&real_start);
2271                 GSList *node;
2272                 for (node = tags; node != NULL; node = g_slist_next (node)) {
2273                         GtkTextTag *tag = (GtkTextTag *) node->data;
2274                         if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2275                                 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2276
2277                                 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2278                                                                                  image_id);
2279                                 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2280                         }
2281                 }
2282         } while (gtk_text_iter_forward_char (&real_start)&&
2283                  (gtk_text_iter_compare (&real_start, &real_end)<=0));
2284 }
2285
2286 static gboolean
2287 msg_body_focus (GtkWidget *focus,
2288                 GdkEventFocus *event,
2289                 gpointer userdata)
2290 {
2291         
2292         update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2293         return FALSE;
2294 }
2295
2296 static void
2297 recpt_field_changed (GtkTextBuffer *buffer,
2298                   ModestMsgEditWindow *editor)
2299 {
2300         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2301         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2302         GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2303         gboolean dim = FALSE;
2304         GtkAction *action;
2305
2306         to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2307         cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2308         bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2309         
2310         dim = ((gtk_text_buffer_get_char_count (to_buffer) + 
2311                 gtk_text_buffer_get_char_count (cc_buffer) +
2312                 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2313                         
2314         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2315         gtk_action_set_sensitive (action, !dim);
2316         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2317         gtk_action_set_sensitive (action, !dim);
2318 }
2319
2320 static void  
2321 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2322 {
2323         hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2324 }
2325
2326 static void
2327 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2328 {
2329         gboolean rich_text, editor_focused;
2330
2331         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2332         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2333         editor_focused = gtk_widget_is_focus (priv->msg_body);
2334
2335         if (!rich_text)
2336                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2337         else if (!editor_focused)
2338                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2339 }
2340
2341 static void
2342 reset_modified (ModestMsgEditWindow *editor)
2343 {
2344         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2345         GtkTextBuffer *buffer;
2346
2347         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2348         gtk_text_buffer_set_modified (buffer, FALSE);
2349         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2350         gtk_text_buffer_set_modified (buffer, FALSE);
2351         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2352         gtk_text_buffer_set_modified (buffer, FALSE);
2353         gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2354 }
2355
2356 static gboolean
2357 is_modified (ModestMsgEditWindow *editor)
2358 {
2359         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2360         GtkTextBuffer *buffer;
2361
2362         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2363         if (gtk_text_buffer_get_modified (buffer))
2364                 return TRUE;
2365         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2366         if (gtk_text_buffer_get_modified (buffer))
2367                 return TRUE;
2368         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2369         if (gtk_text_buffer_get_modified (buffer))
2370                 return TRUE;
2371         if (gtk_text_buffer_get_modified (priv->text_buffer))
2372                 return TRUE;
2373
2374         return FALSE;
2375 }
2376
2377 gboolean
2378 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2379 {
2380         ModestMsgEditWindowPrivate *priv = NULL;
2381
2382         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2383         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2384
2385         /* check if there's no recipient added */
2386         if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2387             (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2388             (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2389                 /* no recipient contents, then select contacts */
2390                 modest_msg_edit_window_open_addressbook (window, NULL);
2391                 return FALSE;
2392         }
2393
2394         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2395                 return FALSE;
2396         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2397                 return FALSE;
2398         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2399                 return FALSE;
2400
2401         modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2402
2403         return TRUE;
2404
2405 }
2406
2407 static void
2408 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2409                                                ModestMsgEditWindow *window)
2410 {
2411         modest_msg_edit_window_attach_file (window);
2412 }
2413
2414 static void
2415 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2416                                                GdkEvent *event,
2417                                                ModestMsgEditWindow *window)
2418 {
2419         ModestWindowPrivate *parent_priv;
2420         GtkAction *action;
2421         gchar *selection;
2422         GtkWidget *focused;
2423
2424         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2425         selection = gtk_clipboard_wait_for_text (clipboard);
2426         focused = gtk_window_get_focus (GTK_WINDOW (window));
2427
2428         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2429         gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2430         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2431         gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2432 }
2433
2434 static void 
2435 update_window_title (ModestMsgEditWindow *window)
2436 {
2437         ModestMsgEditWindowPrivate *priv = NULL;
2438         const gchar *subject;
2439
2440         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2441         subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2442         if (subject == NULL || subject[0] == '\0')
2443                 subject = _("mail_va_new_email");
2444
2445         gtk_window_set_title (GTK_WINDOW (window), subject);
2446
2447 }
2448
2449 static void  
2450 subject_field_changed (GtkEditable *editable, 
2451                        ModestMsgEditWindow *window)
2452 {
2453         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2454         update_window_title (window);
2455         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2456 }