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