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