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