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