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