2007-07-10 Johannes Schmid <johannes.schmid@openismus.com>
[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                         continue;
1086                 }
1087                 data->attachments = g_list_append (data->attachments,
1088                                                    g_object_ref (cursor->data));
1089                 cursor = g_list_next (cursor);
1090         }
1091         
1092         data->priority_flags = priv->priority_flags;
1093
1094         return data;
1095 }
1096
1097
1098 static void
1099 unref_gobject (GObject *obj, gpointer data)
1100 {
1101         if (!G_IS_OBJECT(obj))
1102                 return;
1103         g_object_unref (obj);
1104 }
1105
1106 void 
1107 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1108                                                       MsgData *data)
1109 {
1110         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1111
1112         if (!data)
1113                 return;
1114
1115         g_free (data->to);
1116         g_free (data->cc);
1117         g_free (data->bcc);
1118         g_free (data->subject);
1119         g_free (data->plain_body);
1120         g_free (data->html_body);
1121         g_free (data->account_name);
1122         
1123         if (data->draft_msg != NULL) {
1124                 g_object_unref (data->draft_msg);
1125                 data->draft_msg = NULL;
1126         }
1127         
1128         g_list_foreach (data->attachments, (GFunc)unref_gobject,  NULL);
1129         g_list_free (data->attachments);
1130         
1131         g_slice_free (MsgData, data);
1132 }
1133
1134 ModestMsgEditFormat
1135 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1136 {
1137         gboolean rich_text;
1138         ModestMsgEditWindowPrivate *priv = NULL;
1139         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1140
1141         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1142
1143         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1144         if (rich_text)
1145                 return MODEST_MSG_EDIT_FORMAT_HTML;
1146         else
1147                 return MODEST_MSG_EDIT_FORMAT_TEXT;
1148 }
1149
1150 void
1151 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1152                                    ModestMsgEditFormat format)
1153 {
1154         ModestMsgEditWindowPrivate *priv;
1155
1156         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1157         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1158
1159         switch (format) {
1160         case MODEST_MSG_EDIT_FORMAT_HTML:
1161                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1162                 break;
1163         case MODEST_MSG_EDIT_FORMAT_TEXT:
1164                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1165                 break;
1166         default:
1167                 g_return_if_reached ();
1168         }
1169 }
1170
1171 ModestMsgEditFormatState *
1172 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1173 {
1174         ModestMsgEditFormatState *format_state = NULL;
1175         ModestMsgEditWindowPrivate *priv;
1176         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1177
1178         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1179         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1180
1181         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1182
1183         format_state = g_new0 (ModestMsgEditFormatState, 1);
1184         format_state->bold = buffer_format->bold&0x1;
1185         format_state->italics = buffer_format->italic&0x1;
1186         format_state->bullet = buffer_format->bullet&0x1;
1187         format_state->color = buffer_format->color;
1188         format_state->font_size = buffer_format->font_size;
1189         format_state->font_family = wp_get_font_name (buffer_format->font);
1190         format_state->justification = buffer_format->justification;
1191         g_free (buffer_format);
1192
1193         return format_state;
1194  
1195 }
1196
1197 void
1198 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1199                                          const ModestMsgEditFormatState *format_state)
1200 {
1201         ModestMsgEditWindowPrivate *priv;
1202         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1203         WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1204         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1205         g_return_if_fail (format_state != NULL);
1206
1207         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1208         gtk_widget_grab_focus (priv->msg_body);
1209         buffer_format->bold = (format_state->bold != FALSE);
1210         buffer_format->italic = (format_state->italics != FALSE);
1211         buffer_format->color = format_state->color;
1212         buffer_format->font_size = format_state->font_size;
1213         buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1214         buffer_format->justification = format_state->justification;
1215         buffer_format->bullet = format_state->bullet;
1216
1217         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1218
1219         buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1220         buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1221         buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1222         buffer_format->cs.font_size =  (buffer_format->font_size != current_format->font_size);
1223         buffer_format->cs.font = (buffer_format->font != current_format->font);
1224         buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1225         buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1226
1227         wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1228         if (buffer_format->cs.bold) {
1229                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1230         }
1231         if (buffer_format->cs.italic) {
1232                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1233         }
1234         if (buffer_format->cs.color) {
1235                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1236         }
1237         if (buffer_format->cs.font_size) {
1238                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1239         }
1240         if (buffer_format->cs.justification) {
1241                 switch (buffer_format->justification) {
1242                 case GTK_JUSTIFY_LEFT:
1243                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1244                         break;
1245                 case GTK_JUSTIFY_CENTER:
1246                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1247                         break;
1248                 case GTK_JUSTIFY_RIGHT:
1249                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1250                         break;
1251                 default:
1252                         break;
1253                 }
1254                         
1255         }
1256         if (buffer_format->cs.font) {
1257                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1258         }
1259         if (buffer_format->cs.bullet) {
1260                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1261         }
1262 /*      wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1263         wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1264
1265         g_free (current_format);
1266
1267 }
1268
1269 static void
1270 toggle_action_set_active_block_notify (GtkToggleAction *action,
1271                                        gboolean value)
1272 {
1273         GSList *proxies = NULL;
1274
1275         for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1276              proxies != NULL; proxies = g_slist_next (proxies)) {
1277                 GtkWidget *widget = (GtkWidget *) proxies->data;
1278                 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1279         }
1280
1281         gtk_toggle_action_set_active (action, value);
1282
1283         for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1284              proxies != NULL; proxies = g_slist_next (proxies)) {
1285                 GtkWidget *widget = (GtkWidget *) proxies->data;
1286                 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1287         }
1288 }
1289
1290 static void
1291 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1292 {
1293         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1294         GtkAction *action;
1295         ModestWindowPrivate *parent_priv;
1296         ModestMsgEditWindowPrivate *priv;
1297         GtkWidget *new_size_menuitem;
1298         GtkWidget *new_font_menuitem;
1299         
1300         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1301         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1302
1303         if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1304                 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1305                 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1306                         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1307         } else {
1308                 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1309                 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1310                         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1311         }
1312
1313         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1314         
1315         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1316         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1317
1318         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1319         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1320
1321         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1322         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1323
1324         g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button), 
1325                                          G_CALLBACK (modest_msg_edit_window_color_button_change),
1326                                          window);
1327         hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1328         g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button), 
1329                                            G_CALLBACK (modest_msg_edit_window_color_button_change),
1330                                            window);
1331
1332         new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group, 
1333                                                       buffer_format->font_size))->data);
1334         if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1335                 GtkWidget *label;
1336                 gchar *markup;
1337
1338                 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1339                 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1340                 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1341                 g_free (markup);
1342                 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1343                                                  G_CALLBACK (modest_msg_edit_window_size_change),
1344                                                  window);
1345                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1346                 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1347                                                    G_CALLBACK (modest_msg_edit_window_size_change),
1348                                                    window);
1349         }
1350
1351         new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group, 
1352                                                       buffer_format->font))->data);
1353         if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1354                 GtkWidget *label;
1355                 gchar *markup;
1356
1357                 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1358                 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1359                 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1360                 g_free (markup);
1361                 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1362                                                  G_CALLBACK (modest_msg_edit_window_font_change),
1363                                                  window);
1364                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1365                 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1366                                                    G_CALLBACK (modest_msg_edit_window_font_change),
1367                                                    window);
1368         }
1369
1370         g_free (buffer_format);
1371
1372 }
1373
1374
1375 void
1376 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1377 {
1378         
1379         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1380         ModestMsgEditWindowPrivate *priv;
1381         GtkWidget *dialog = NULL;
1382         gint response;
1383         const GdkColor *new_color = NULL;
1384         
1385         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1386         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1387         
1388 #ifdef MODEST_HILDON_VERSION_0  
1389         dialog = hildon_color_selector_new (GTK_WINDOW (window));
1390         hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1391 #else
1392         dialog = hildon_color_chooser_new ();
1393         hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1394 #endif /*MODEST_HILDON_VERSION_0*/              
1395         g_free (buffer_format);
1396
1397         response = gtk_dialog_run (GTK_DIALOG (dialog));
1398         switch (response) {
1399         case GTK_RESPONSE_OK: {
1400 #ifdef MODEST_HILDON_VERSION_0
1401                 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1402 #else
1403                 GdkColor col;
1404                 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1405                 new_color = &col;
1406 #endif /*MODEST_HILDON_VERSION_0*/
1407         }
1408
1409         break;
1410         default:
1411                 break;
1412         }
1413         gtk_widget_destroy (dialog);
1414
1415         if (new_color != NULL)
1416                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1417
1418 }
1419
1420 void
1421 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1422 {
1423         
1424         ModestMsgEditWindowPrivate *priv;
1425         GtkWidget *dialog = NULL;
1426         gint response;
1427         GdkColor *old_color = NULL;
1428         const GdkColor *new_color = NULL;
1429         
1430         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1431         old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1432         
1433 #ifdef MODEST_HILDON_VERSION_0  
1434         dialog = hildon_color_selector_new (GTK_WINDOW (window));
1435         hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1436 #else
1437         dialog = hildon_color_chooser_new ();
1438         hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1439 #endif /*MODEST_HILDON_VERSION_9*/              
1440
1441         response = gtk_dialog_run (GTK_DIALOG (dialog));
1442         switch (response) {
1443         case GTK_RESPONSE_OK: {
1444 #ifdef MODEST_HILDON_VERSION_0
1445                 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1446 #else
1447                 GdkColor col;
1448                 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1449                 new_color = &col;
1450 #endif /*MODEST_HILDON_VERSION_0*/
1451           }
1452                 break;
1453         default:
1454                 break;
1455         }
1456         gtk_widget_destroy (dialog);
1457
1458         if (new_color != NULL)
1459                 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1460
1461 }
1462
1463
1464 void
1465 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1466 {
1467         
1468         ModestMsgEditWindowPrivate *priv;
1469         GtkWidget *dialog = NULL;
1470         gint response = 0;
1471         GSList *uris = NULL;
1472         GSList *uri_node = NULL;
1473         
1474         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1475         
1476         dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1477         gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1478         gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1479
1480         modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1481
1482         response = gtk_dialog_run (GTK_DIALOG (dialog));
1483         switch (response) {
1484         case GTK_RESPONSE_OK:
1485                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1486                 break;
1487         default:
1488                 break;
1489         }
1490         gtk_widget_destroy (dialog);
1491
1492         for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1493                 const gchar *uri;
1494                 GnomeVFSHandle *handle = NULL;
1495                 GnomeVFSResult result;
1496                 GtkTextIter position;
1497                 GtkTextMark *insert_mark;
1498
1499                 uri = (const gchar *) uri_node->data;
1500                 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1501                 if (result == GNOME_VFS_OK) {
1502                         GdkPixbufLoader *loader;
1503                         GdkPixbuf *pixbuf;
1504                         GnomeVFSFileInfo info;
1505                         gchar *filename, *basename, *escaped_filename;
1506                         TnyMimePart *mime_part;
1507                         TnyStream *stream;
1508                         gchar *content_id;
1509                         const gchar *mime_type = NULL;
1510                         GnomeVFSURI *vfs_uri;
1511
1512                         vfs_uri = gnome_vfs_uri_new (uri);
1513
1514                         escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1515                         filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1516                         g_free (escaped_filename);
1517                         gnome_vfs_uri_unref (vfs_uri);
1518
1519                         if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1520                                                      | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE) 
1521                             == GNOME_VFS_OK)
1522                                 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1523
1524                         mime_part = tny_platform_factory_new_mime_part
1525                                 (modest_runtime_get_platform_factory ());
1526                         stream = TNY_STREAM (tny_vfs_stream_new (handle));
1527                         
1528                         tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1529                         
1530                         content_id = g_strdup_printf ("%d", priv->last_cid);
1531                         tny_mime_part_set_content_id (mime_part, content_id);
1532                         g_free (content_id);
1533                         priv->last_cid++;
1534                         
1535                         basename = g_path_get_basename (filename);
1536                         tny_mime_part_set_filename (mime_part, basename);
1537                         g_free (basename);
1538                         
1539                         priv->attachments = g_list_prepend (priv->attachments, mime_part);
1540                         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1541                                                                 mime_part);
1542                         gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1543                         gtk_widget_show_all (priv->attachments_caption);
1544                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1545                         g_free (filename);
1546
1547                         loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1548                         while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1549                                 unsigned char read_buffer[128];
1550                                 gint readed;
1551                                 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1552                                 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
1553                                         break;
1554                         }
1555                         pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1556                         g_object_ref (pixbuf);
1557                         gdk_pixbuf_loader_close (loader, NULL);
1558                         g_object_unref (loader);
1559
1560                         if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1561                                 GdkPixbuf *new_pixbuf;
1562                                 gint new_height;
1563                                 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1564                                         gdk_pixbuf_get_width (pixbuf);
1565                                 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1566                                 g_object_unref (pixbuf);
1567                                 pixbuf = new_pixbuf;
1568                         }
1569
1570                         if (pixbuf != NULL) {
1571                                 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1572                                 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1573                                 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1574                         } 
1575                 }
1576         }
1577
1578
1579 }
1580
1581 void
1582 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1583 {
1584         
1585         ModestMsgEditWindowPrivate *priv;
1586         GtkWidget *dialog = NULL;
1587         gint response = 0;
1588         GSList *uris = NULL;
1589         GSList *uri_node;
1590         
1591         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1592         
1593         dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1594         gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1595         gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1596
1597         response = gtk_dialog_run (GTK_DIALOG (dialog));
1598         switch (response) {
1599         case GTK_RESPONSE_OK:
1600                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1601                 break;
1602         default:
1603                 break;
1604         }
1605         gtk_widget_destroy (dialog);
1606
1607         for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1608                 const gchar *uri;
1609                 GnomeVFSHandle *handle = NULL;
1610                 GnomeVFSResult result;
1611
1612                 uri = (const gchar *) uri_node->data;
1613                 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1614                 if (result == GNOME_VFS_OK) {
1615                         TnyMimePart *mime_part;
1616                         TnyStream *stream;
1617                         const gchar *mime_type = NULL;
1618                         gchar *basename;
1619                         gchar *escaped_filename;
1620                         gchar *filename;
1621                         gchar *content_id;
1622                         GnomeVFSFileInfo info;
1623                         GnomeVFSURI *vfs_uri;
1624
1625                         vfs_uri = gnome_vfs_uri_new (uri);
1626                         
1627
1628                         escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1629                         filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1630                         g_free (escaped_filename);
1631                         gnome_vfs_uri_unref (vfs_uri);
1632                         
1633                         if (gnome_vfs_get_file_info (uri, 
1634                                                      &info, 
1635                                                      GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1636                                                      GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1637                             == GNOME_VFS_OK)
1638                                 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1639                         mime_part = tny_platform_factory_new_mime_part
1640                                 (modest_runtime_get_platform_factory ());
1641                         stream = TNY_STREAM (tny_vfs_stream_new (handle));
1642                         
1643                         tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1644                         
1645                         content_id = g_strdup_printf ("%d", priv->last_cid);
1646                         tny_mime_part_set_content_id (mime_part, content_id);
1647                         g_free (content_id);
1648                         priv->last_cid++;
1649                         
1650                         basename = g_path_get_basename (filename);
1651                         tny_mime_part_set_filename (mime_part, basename);
1652                         g_free (basename);
1653                         
1654                         priv->attachments = g_list_prepend (priv->attachments, mime_part);
1655                         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1656                                                                 mime_part);
1657                         gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1658                         gtk_widget_show_all (priv->attachments_caption);
1659                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1660                         g_free (filename);
1661
1662                 } 
1663         }
1664         g_slist_foreach (uris, (GFunc) g_free, NULL);
1665         g_slist_free (uris);
1666 }
1667
1668 void
1669 modest_msg_edit_window_attach_file_noninteractive (
1670                 ModestMsgEditWindow *window,
1671                 const gchar *file_uri)
1672 {
1673         
1674         ModestMsgEditWindowPrivate *priv;
1675         
1676         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1677
1678         if (file_uri && strlen(file_uri)) {
1679                 gint file_id = 0;
1680                 
1681                 /* TODO: We should probably try to use only the URI,
1682                  * instead of using a filename.
1683                  */
1684                 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1685                 if (!filename) {
1686                         g_warning("%s: g_filename_from_uri('%s') failed.\n", __FUNCTION__, file_uri);
1687                 }
1688
1689                 file_id = g_open (filename, O_RDONLY, 0);
1690                 if (file_id != -1) {
1691                         TnyMimePart *mime_part;
1692                         TnyStream *stream;
1693                         const gchar *mime_type;
1694                         gchar *basename;
1695                         gchar *content_id;
1696 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1697                         mime_type = gnome_vfs_get_mime_type(filename);
1698 #else
1699                         mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1700 #endif
1701                         mime_part = tny_platform_factory_new_mime_part
1702                                 (modest_runtime_get_platform_factory ());
1703                         stream = TNY_STREAM (tny_fs_stream_new (file_id));
1704                         
1705                         tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1706                         
1707                         content_id = g_strdup_printf ("%d", priv->last_cid);
1708                         tny_mime_part_set_content_id (mime_part, content_id);
1709                         g_free (content_id);
1710                         priv->last_cid++;
1711                         
1712                         basename = g_path_get_basename (filename);
1713                         tny_mime_part_set_filename (mime_part, basename);
1714                         g_free (basename);
1715                         
1716                         priv->attachments = g_list_prepend (priv->attachments, mime_part);
1717                         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1718                                                                 mime_part);
1719                         gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1720                         gtk_widget_show_all (priv->attachments_caption);
1721                 } else if (file_id == -1) {
1722                         close (file_id);
1723                         g_warning("file to be attached does not exist: %s", filename);
1724                 }
1725
1726                 g_free (filename);
1727         }
1728 }
1729
1730 void
1731 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1732                                           GList *att_list)
1733 {
1734         ModestMsgEditWindowPrivate *priv;
1735         gboolean clean_list = FALSE;
1736
1737         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1738         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1739
1740         if (att_list == NULL) {
1741                 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1742                 clean_list = TRUE;
1743         }
1744
1745         if (att_list == NULL) {
1746                 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1747         } else {
1748                 GtkWidget *confirmation_dialog = NULL;
1749                 gboolean dialog_response;
1750                 GList *node;
1751                 gchar *message = NULL;
1752                 const gchar *filename = NULL;
1753
1754                 if (att_list->next == NULL) {
1755                         filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1756                 } else {
1757                         filename = "";
1758                 }
1759                 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1760                                                     att_list->next == NULL), filename);
1761                 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1762                 g_free (message);
1763                 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1764                 gtk_widget_destroy (confirmation_dialog);
1765                 if (!dialog_response) {
1766                         if (clean_list)
1767                                 g_list_free (att_list);
1768                         return;
1769                 }
1770                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1771
1772                 for (node = att_list; node != NULL; node = g_list_next (node)) {
1773                         TnyMimePart *mime_part = (TnyMimePart *) node->data;
1774                         const gchar *att_id;
1775                         priv->attachments = g_list_remove (priv->attachments, mime_part);
1776
1777                         modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1778                                                                    mime_part);
1779                         if (priv->attachments == NULL)
1780                                 gtk_widget_hide (priv->attachments_caption);
1781                         att_id = tny_mime_part_get_content_id (mime_part);
1782                         if (att_id != NULL)
1783                                 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1784                                                                  att_id);
1785                         g_object_unref (mime_part);
1786                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1787                 }
1788         }
1789
1790         if (clean_list)
1791                 g_list_free (att_list);
1792 }
1793
1794 static void
1795 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1796                                             gpointer userdata)
1797 {
1798         ModestMsgEditWindowPrivate *priv;
1799         GdkColor *new_color;
1800         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1801         
1802 #ifdef MODEST_HAVE_HILDON0_WIDGETS      
1803         new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1804 #else 
1805         GdkColor col;
1806         hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1807         new_color = &col;
1808 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1809
1810         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1811         
1812         gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1813
1814 }
1815
1816 static void
1817 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1818                                     gpointer userdata)
1819 {
1820         ModestMsgEditWindowPrivate *priv;
1821         gint new_size_index;
1822         ModestMsgEditWindow *window;
1823         GtkWidget *label;
1824         
1825         window = MODEST_MSG_EDIT_WINDOW (userdata);
1826         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1827         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1828
1829         if (gtk_check_menu_item_get_active (menu_item)) {
1830                 gchar *markup;
1831                 WPTextBufferFormat format;
1832
1833                 memset (&format, 0, sizeof (format));
1834                 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1835
1836                 label = gtk_bin_get_child (GTK_BIN (menu_item));
1837                 
1838                 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1839                 format.cs.font_size = TRUE;
1840                 format.cs.text_position = TRUE;
1841                 format.cs.font = TRUE;
1842                 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1843 /*              wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1844
1845                 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1846                                                    (gpointer) wp_get_font_size_index (new_size_index, 12)))
1847                         wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1848                 
1849                 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1850                 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1851                 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1852                 g_free (markup);
1853         }
1854 }
1855
1856 static void
1857 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1858                                     gpointer userdata)
1859 {
1860         ModestMsgEditWindowPrivate *priv;
1861         gint new_font_index;
1862         ModestMsgEditWindow *window;
1863         GtkWidget *label;
1864         
1865         window = MODEST_MSG_EDIT_WINDOW (userdata);
1866         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1867         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1868
1869         if (gtk_check_menu_item_get_active (menu_item)) {
1870                 gchar *markup;
1871
1872                 label = gtk_bin_get_child (GTK_BIN (menu_item));
1873                 
1874                 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1875
1876                 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, 
1877                                                    (gpointer) new_font_index))
1878                         wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1879                 
1880                 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1881                     markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1882                 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1883                 g_free (markup);
1884         }
1885 }
1886
1887 static void
1888 modest_msg_edit_window_set_zoom (ModestWindow *window,
1889                                  gdouble zoom)
1890 {
1891         ModestMsgEditWindowPrivate *priv;
1892         ModestWindowPrivate *parent_priv;
1893         GtkRadioAction *zoom_radio_action;
1894      
1895         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1896
1897         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1898         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1899         priv->zoom_level = zoom;
1900         wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
1901
1902         /* Zoom level menu options should be updated with the current zoom level */
1903         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1904         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1905                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1906 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1907         /* FIXME: Not availible before Gtk 2.10 */
1908 #else
1909         gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1910 #endif
1911 }
1912
1913 static gdouble
1914 modest_msg_edit_window_get_zoom (ModestWindow *window)
1915 {
1916         ModestMsgEditWindowPrivate *priv;
1917      
1918         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1919
1920         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1921         return priv->zoom_level;
1922 }
1923
1924 static gboolean
1925 zoom_allowed (ModestMsgEditWindow *window)
1926 {
1927         GtkWidget *focus;
1928
1929         focus = gtk_window_get_focus (GTK_WINDOW (window));
1930         return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1931 }
1932
1933 static gboolean
1934 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1935 {
1936         ModestWindowPrivate *parent_priv;
1937         GtkRadioAction *zoom_radio_action;
1938         GSList *group, *node;
1939
1940         /* First we check if the text view is focused. If not, zooming is not allowed */
1941         if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1942                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1943                 return FALSE;
1944         }
1945
1946         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1947         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1948                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1949
1950         group = gtk_radio_action_get_group (zoom_radio_action);
1951
1952         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1953                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
1954                 return FALSE;
1955         }
1956
1957         for (node = group; node != NULL; node = g_slist_next (node)) {
1958                 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1959                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1960                         return TRUE;
1961                 }
1962         }
1963         return FALSE;
1964 }
1965
1966 static gboolean
1967 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1968 {
1969         ModestWindowPrivate *parent_priv;
1970         GtkRadioAction *zoom_radio_action;
1971         GSList *group, *node;
1972
1973         /* First we check if the text view is focused. If not, zooming is not allowed */
1974         if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1975                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1976                 return FALSE;
1977         }
1978
1979         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1980         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1981                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1982
1983         group = gtk_radio_action_get_group (zoom_radio_action);
1984
1985         for (node = group; node != NULL; node = g_slist_next (node)) {
1986                 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1987                         if (node->next != NULL) {
1988                                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1989                                 return TRUE;
1990                         } else
1991                                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
1992                         break;
1993                 }
1994         }
1995         return FALSE;
1996 }
1997
1998 static gboolean
1999 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2000 {
2001         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2002                 ModestWindowPrivate *parent_priv;
2003                 ModestWindowMgr *mgr;
2004                 gboolean is_fullscreen;
2005                 GtkAction *fs_toggle_action;
2006                 gboolean active;
2007
2008                 mgr = modest_runtime_get_window_mgr ();
2009                 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2010
2011                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2012                 
2013                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2014                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2015                 if (is_fullscreen != active)
2016                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2017         }
2018
2019         return FALSE;
2020
2021 }
2022
2023 void
2024 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2025 {
2026         ModestWindowPrivate *parent_priv;
2027         GtkAction *fs_toggle_action;
2028         gboolean active;
2029
2030         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2031
2032         fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2033         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2034         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2035 }
2036
2037 void
2038 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window, 
2039                                 gboolean show)
2040 {
2041         ModestMsgEditWindowPrivate *priv = NULL;
2042         const gchar *recipients;
2043         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2044
2045         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2046         gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2047         recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field));
2048         if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2049                 gtk_widget_show (priv->cc_caption);
2050         else
2051                 gtk_widget_hide (priv->cc_caption);
2052         modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2053 }
2054
2055 void
2056 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window, 
2057                                  gboolean show)
2058 {
2059         ModestMsgEditWindowPrivate *priv = NULL;
2060         const gchar *recipients;
2061         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2062
2063         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2064         gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2065         recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field));
2066         if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2067                 gtk_widget_show (priv->bcc_caption);
2068         else
2069                 gtk_widget_hide (priv->bcc_caption);
2070         modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2071 }
2072
2073 static void
2074 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2075                                          ModestRecptEditor *editor)
2076 {
2077         ModestMsgEditWindowPrivate *priv;
2078
2079         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2080         g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2081         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2082
2083         if (editor == NULL) {
2084                 GtkWidget *view_focus;
2085                 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2086
2087                 /* This code should be kept in sync with ModestRecptEditor. The
2088                    textview inside the recpt editor is the one that really gets the
2089                    focus. As it's inside a scrolled window, and this one inside the
2090                    hbox recpt editor inherits from, we'll need to go up in the 
2091                    hierarchy to know if the text view is part of the recpt editor
2092                    or if it's a different text entry */
2093
2094                 if (gtk_widget_get_parent (view_focus)) {
2095                         GtkWidget *first_parent;
2096
2097                         first_parent = gtk_widget_get_parent (view_focus);
2098                         if (gtk_widget_get_parent (first_parent) && 
2099                             MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2100                                 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2101                         }
2102                 }
2103
2104                 if (editor == NULL)
2105                         editor = MODEST_RECPT_EDITOR (priv->to_field);
2106
2107         }
2108
2109         modest_address_book_select_addresses (editor);
2110
2111 }
2112
2113 void
2114 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2115 {
2116         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2117
2118         modest_msg_edit_window_open_addressbook (window, NULL);
2119 }
2120
2121 static void
2122 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2123                                      gboolean show_toolbar)
2124 {
2125         ModestWindowPrivate *parent_priv;
2126         
2127         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2128         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2129
2130         /* FIXME: we can not just use the code of
2131            modest_msg_edit_window_setup_toolbar because it has a
2132            mixture of both initialization and creation code. */
2133
2134         if (show_toolbar)
2135                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2136         else
2137                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2138 }
2139
2140 void
2141 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2142                                            TnyHeaderFlags priority_flags)
2143 {
2144         ModestMsgEditWindowPrivate *priv;
2145         ModestWindowPrivate *parent_priv;
2146
2147         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2148
2149         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2150         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2151         priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2152
2153         if (priv->priority_flags != priority_flags) {
2154                 GtkAction *priority_action = NULL;
2155
2156                 priv->priority_flags = priority_flags;
2157
2158                 switch (priority_flags) {
2159                 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2160                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2161                         gtk_widget_show (priv->priority_icon);
2162                         priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
2163                                                                      "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2164                         break;
2165                 case TNY_HEADER_FLAG_LOW_PRIORITY:
2166                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2167                         gtk_widget_show (priv->priority_icon);
2168                         priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
2169                                                                      "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2170                         break;
2171                 default:
2172                         gtk_widget_hide (priv->priority_icon);
2173                         priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
2174                                                                      "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2175                         break;
2176                 }
2177                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2178                 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2179         }
2180 }
2181
2182 void
2183 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2184                                         gint file_format)
2185 {
2186         ModestMsgEditWindowPrivate *priv;
2187         ModestWindowPrivate *parent_priv;
2188         gint current_format;
2189
2190         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2191
2192         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2193         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2194
2195         current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2196                 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2197
2198         if (current_format != file_format) {
2199                 switch (file_format) {
2200                 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2201                         wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2202                         break;
2203                 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2204                 {
2205                         GtkWidget *dialog;
2206                         gint response;
2207                         dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2208                         response = gtk_dialog_run (GTK_DIALOG (dialog));
2209                         gtk_widget_destroy (dialog);
2210                         if (response == GTK_RESPONSE_OK) {
2211                                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2212                         } else {
2213                                 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2214                                 toggle_action_set_active_block_notify (action, TRUE);
2215                         }
2216                 }
2217                         break;
2218                 }
2219                 update_dimmed (window);
2220         }
2221 }
2222
2223 void
2224 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2225 {
2226         GtkWidget *dialog;
2227         ModestMsgEditWindowPrivate *priv;
2228         WPTextBufferFormat oldfmt, fmt;
2229         gint old_position = 0;
2230         gint response = 0;
2231         gint position = 0;
2232         gint font_size;
2233         GdkColor *color = NULL;
2234         gboolean bold, bold_set, italic, italic_set;
2235         gboolean underline, underline_set;
2236         gboolean strikethrough, strikethrough_set;
2237         gboolean position_set;
2238         gboolean font_size_set, font_set, color_set;
2239         gchar *font_name;
2240
2241         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2242         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2243         
2244         dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2245
2246         /* First we get the currently selected font information */
2247         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2248         g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2249
2250         switch (oldfmt.text_position) {
2251         case TEXT_POSITION_NORMAL:
2252                 old_position = 0;
2253                 break;
2254         case TEXT_POSITION_SUPERSCRIPT:
2255                 old_position = 1;
2256                 break;
2257         default:
2258                 old_position = -1;
2259                 break;
2260         }
2261
2262         g_object_set (G_OBJECT (dialog),
2263                       "bold", oldfmt.bold != FALSE,
2264                       "bold-set", !oldfmt.cs.bold,
2265                       "underline", oldfmt.underline != FALSE,
2266                       "underline-set", !oldfmt.cs.underline,
2267                       "italic", oldfmt.italic != FALSE,
2268                       "italic-set", !oldfmt.cs.italic,
2269                       "strikethrough", oldfmt.strikethrough != FALSE,
2270                       "strikethrough-set", !oldfmt.cs.strikethrough,
2271                       "color", &oldfmt.color,
2272                       "color-set", !oldfmt.cs.color,
2273                       "size", wp_font_size[oldfmt.font_size],
2274                       "size-set", !oldfmt.cs.font_size,
2275                       "position", old_position,
2276                       "position-set", !oldfmt.cs.text_position,
2277                       "family", wp_get_font_name (oldfmt.font),
2278                       "family-set", !oldfmt.cs.font,
2279                       NULL);
2280
2281         gtk_widget_show_all (dialog);
2282         response = gtk_dialog_run (GTK_DIALOG (dialog));
2283         if (response == GTK_RESPONSE_OK) {
2284
2285                 g_object_get( dialog,
2286                               "bold", &bold,
2287                               "bold-set", &bold_set,
2288                               "underline", &underline,
2289                               "underline-set", &underline_set,
2290                               "italic", &italic,
2291                               "italic-set", &italic_set,
2292                               "strikethrough", &strikethrough,
2293                               "strikethrough-set", &strikethrough_set,
2294                               "color", &color,
2295                               "color-set", &color_set,
2296                               "size", &font_size,
2297                               "size-set", &font_size_set,
2298                               "family", &font_name,
2299                               "family-set", &font_set,
2300                               "position", &position,
2301                               "position-set", &position_set,
2302                               NULL );
2303                 
2304         }       
2305
2306         if (response == GTK_RESPONSE_OK) {
2307                 memset(&fmt, 0, sizeof(fmt));
2308                 if (bold_set) {
2309                         fmt.bold = bold;
2310                         fmt.cs.bold = TRUE;
2311                 }
2312                 if (italic_set) {
2313                         fmt.italic = italic;
2314                         fmt.cs.italic = TRUE;
2315                 }
2316                 if (underline_set) {
2317                         fmt.underline = underline;
2318                         fmt.cs.underline = TRUE;
2319                 }
2320                 if (strikethrough_set) {
2321                         fmt.strikethrough = strikethrough;
2322                         fmt.cs.strikethrough = TRUE;
2323                 }
2324                 if (position_set) {
2325                         fmt.text_position =
2326                                 ( position == 0 )
2327                                 ? TEXT_POSITION_NORMAL
2328                                 : ( ( position == 1 )
2329                                     ? TEXT_POSITION_SUPERSCRIPT
2330                                     : TEXT_POSITION_SUBSCRIPT );
2331                         fmt.cs.text_position = TRUE;
2332                 }
2333                 if (color_set) {
2334                         fmt.color = *color;
2335                         fmt.cs.color = TRUE;
2336                 }
2337                 if (font_set) {
2338                         fmt.font = wp_get_font_index(font_name,
2339                                                      DEFAULT_FONT);
2340                         fmt.cs.font = TRUE;
2341                 }
2342                 g_free(font_name);
2343                 if (font_size_set) {
2344                         fmt.font_size = wp_get_font_size_index(
2345                                 font_size, DEFAULT_FONT_SIZE);
2346                         fmt.cs.font_size = TRUE;
2347                 }
2348                 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2349         }
2350         gtk_widget_destroy (dialog);
2351         
2352         gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2353 }
2354
2355 void
2356 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2357 {
2358         ModestMsgEditWindowPrivate *priv;
2359
2360         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2361         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2362         
2363         wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2364
2365         update_dimmed (window);
2366
2367 }
2368
2369 void
2370 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2371 {
2372         ModestMsgEditWindowPrivate *priv;
2373
2374         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2375         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2376         
2377         wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2378
2379         update_dimmed (window);
2380
2381 }
2382
2383 static void
2384 update_dimmed (ModestMsgEditWindow *window)
2385 {
2386         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2387         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2388         GtkAction *action;
2389         GtkWidget *widget;
2390         gboolean rich_text;
2391         gboolean editor_focused;
2392
2393         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2394         editor_focused = gtk_widget_is_focus (priv->msg_body);
2395
2396         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2397         gtk_action_set_sensitive (action, rich_text && editor_focused);
2398         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2399         gtk_action_set_sensitive (action, rich_text && editor_focused);
2400         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2401         gtk_action_set_sensitive (action, rich_text && editor_focused);
2402         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2403         gtk_action_set_sensitive (action, rich_text && editor_focused);
2404         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2405         gtk_action_set_sensitive (action, rich_text && editor_focused);
2406         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2407         gtk_action_set_sensitive (action, rich_text && editor_focused);
2408         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2409         gtk_action_set_sensitive (action, rich_text && editor_focused);
2410         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2411         gtk_action_set_sensitive (action, rich_text && editor_focused);
2412         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2413         gtk_action_set_sensitive (action, rich_text && editor_focused);
2414         widget = priv->font_color_button;
2415         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2416         widget = priv->font_size_toolitem;
2417         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2418         widget = priv->font_face_toolitem;
2419         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2420 }
2421
2422 static void
2423 setup_insensitive_handlers (ModestMsgEditWindow *window)
2424 {
2425         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2426         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2427         GtkWidget *widget;
2428
2429         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2430         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2431         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2432         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2433         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2434         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2435         widget = priv->font_color_button;
2436         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2437         widget = priv->font_size_toolitem;
2438         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2439         widget = priv->font_face_toolitem;
2440         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2441
2442 }
2443
2444 static void  
2445 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2446 {
2447         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2448         GtkAction *action;
2449
2450         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2451         gtk_action_set_sensitive (action, can_undo);
2452 }
2453
2454 static void  
2455 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2456 {
2457         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2458         GtkAction *action;
2459
2460         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2461         gtk_action_set_sensitive (action, can_redo);
2462 }
2463
2464 static void
2465 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2466 {
2467         GtkTextIter iter;
2468         GtkTextIter match_start, match_end;
2469
2470         if (image_id == NULL)
2471                 return;
2472
2473         gtk_text_buffer_get_start_iter (buffer, &iter);
2474
2475         while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2476                 GSList *tags = gtk_text_iter_get_tags (&match_start);
2477                 GSList *node;
2478                 for (node = tags; node != NULL; node = g_slist_next (node)) {
2479                         GtkTextTag *tag = (GtkTextTag *) node->data;
2480                         if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2481                                 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2482                                 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2483                                         gint offset;
2484                                         offset = gtk_text_iter_get_offset (&match_start);
2485                                         gtk_text_buffer_delete (buffer, &match_start, &match_end);
2486                                         gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2487                                 }
2488                         }
2489                 }
2490                 gtk_text_iter_forward_char (&iter);
2491         }
2492 }
2493
2494 static void
2495 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2496 {
2497         ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2498         GtkTextIter real_start, real_end;
2499         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2500
2501         if (gtk_text_iter_compare (start, end) > 0) {
2502                 real_start = *end;
2503                 real_end = *start;
2504         } else {
2505                 real_start = *start;
2506                 real_end = *end;
2507         }
2508         do {
2509                 GSList *tags = gtk_text_iter_get_tags (&real_start);
2510                 GSList *node;
2511                 for (node = tags; node != NULL; node = g_slist_next (node)) {
2512                         GtkTextTag *tag = (GtkTextTag *) node->data;
2513                         if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2514                                 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2515
2516                                 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2517                                                                                  image_id);
2518                                 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2519                         }
2520                 }
2521         } while (gtk_text_iter_forward_char (&real_start)&&
2522                  (gtk_text_iter_compare (&real_start, &real_end)<=0));
2523 }
2524
2525 static gboolean
2526 msg_body_focus (GtkWidget *focus,
2527                 GdkEventFocus *event,
2528                 gpointer userdata)
2529 {
2530         
2531         update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2532         return FALSE;
2533 }
2534
2535 static void
2536 recpt_field_changed (GtkTextBuffer *buffer,
2537                   ModestMsgEditWindow *editor)
2538 {
2539         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2540         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2541         GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2542         gboolean dim = FALSE;
2543         GtkAction *action;
2544
2545         to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2546         cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2547         bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2548         
2549         dim = ((gtk_text_buffer_get_char_count (to_buffer) + 
2550                 gtk_text_buffer_get_char_count (cc_buffer) +
2551                 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2552                         
2553         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2554         gtk_action_set_sensitive (action, !dim);
2555         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2556         gtk_action_set_sensitive (action, !dim);
2557 }
2558
2559 static void  
2560 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2561 {
2562         hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2563 }
2564
2565 static void
2566 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2567 {
2568         gboolean rich_text, editor_focused;
2569
2570         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2571         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2572         editor_focused = gtk_widget_is_focus (priv->msg_body);
2573
2574         if (!rich_text)
2575                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2576         else if (!editor_focused)
2577                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2578 }
2579
2580 static void
2581 reset_modified (ModestMsgEditWindow *editor)
2582 {
2583         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2584         GtkTextBuffer *buffer;
2585
2586         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2587         gtk_text_buffer_set_modified (buffer, FALSE);
2588         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2589         gtk_text_buffer_set_modified (buffer, FALSE);
2590         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2591         gtk_text_buffer_set_modified (buffer, FALSE);
2592         gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2593 }
2594
2595 gboolean
2596 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2597 {
2598         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2599         GtkTextBuffer *buffer;
2600
2601         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2602         if (gtk_text_buffer_get_modified (buffer))
2603                 return TRUE;
2604         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2605         if (gtk_text_buffer_get_modified (buffer))
2606                 return TRUE;
2607         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2608         if (gtk_text_buffer_get_modified (buffer))
2609                 return TRUE;
2610         if (gtk_text_buffer_get_modified (priv->text_buffer))
2611                 return TRUE;
2612
2613         return FALSE;
2614 }
2615
2616 gboolean
2617 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2618 {
2619         ModestMsgEditWindowPrivate *priv = NULL;
2620
2621         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2622         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2623
2624         /* check if there's no recipient added */
2625         if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2626             (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2627             (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2628                 /* no recipient contents, then select contacts */
2629                 modest_msg_edit_window_open_addressbook (window, NULL);
2630                 return FALSE;
2631         }
2632
2633         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2634                 return FALSE;
2635         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2636                 return FALSE;
2637         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2638                 return FALSE;
2639
2640         modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2641
2642         return TRUE;
2643
2644 }
2645
2646 static void
2647 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2648                                                ModestMsgEditWindow *window)
2649 {
2650         modest_msg_edit_window_attach_file (window);
2651 }
2652
2653 static void
2654 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2655                                                GdkEvent *event,
2656                                                ModestMsgEditWindow *window)
2657 {
2658         ModestWindowPrivate *parent_priv;
2659         ModestMsgEditWindowPrivate *priv;
2660         GtkAction *action;
2661         gboolean has_selection;
2662         GtkWidget *focused;
2663         GList *selected_attachments = NULL;
2664         gint n_att_selected = 0;
2665
2666         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2667         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2668         has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2669         focused = gtk_window_get_focus (GTK_WINDOW (window));
2670
2671         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2672         gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2673         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2674         gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2675
2676         selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2677         n_att_selected = g_list_length (selected_attachments);
2678         g_list_free (selected_attachments);
2679
2680         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2681         gtk_action_set_sensitive (action, n_att_selected == 1);
2682         
2683         update_paste_dimming (window);
2684 }
2685
2686 static void 
2687 update_window_title (ModestMsgEditWindow *window)
2688 {
2689         ModestMsgEditWindowPrivate *priv = NULL;
2690         const gchar *subject;
2691
2692         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2693         subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2694         if (subject == NULL || subject[0] == '\0')
2695                 subject = _("mail_va_new_email");
2696
2697         gtk_window_set_title (GTK_WINDOW (window), subject);
2698
2699 }
2700
2701 static void  
2702 subject_field_changed (GtkEditable *editable, 
2703                        ModestMsgEditWindow *window)
2704 {
2705         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2706         update_window_title (window);
2707         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2708 }
2709
2710 void
2711 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2712                                             gboolean show)
2713 {
2714         ModestMsgEditWindowPrivate *priv = NULL;
2715
2716         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2717         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2718
2719         gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2720         if (show) {
2721                 gtk_widget_show_all (priv->find_toolbar);
2722                 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2723         } else {
2724                 gtk_widget_hide_all (priv->find_toolbar);
2725                 gtk_widget_grab_focus (priv->msg_body);
2726         }
2727     
2728 }
2729
2730 static gboolean 
2731 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2732                                           const gchar *str,
2733                                           GtkTextIter *match_start,
2734                                           GtkTextIter *match_end)
2735 {
2736         GtkTextIter end_iter;
2737         gchar *str_casefold;
2738         gint str_chars_n;
2739         gchar *range_text;
2740         gchar *range_casefold;
2741         gint offset;
2742         gint range_chars_n;
2743         gboolean result = FALSE;
2744
2745         if (str == NULL)
2746                 return TRUE;
2747         
2748         /* get end iter */
2749         end_iter = *iter;
2750         gtk_text_iter_forward_to_end (&end_iter);
2751
2752         str_casefold = g_utf8_casefold (str, -1);
2753         str_chars_n = strlen (str);
2754
2755         range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2756         range_casefold = g_utf8_casefold (range_text, -1);
2757         range_chars_n = strlen (range_casefold);
2758
2759         if (range_chars_n < str_chars_n) {
2760                 g_free (str_casefold);
2761                 g_free (range_text);
2762                 g_free (range_casefold);
2763                 return FALSE;
2764         }
2765
2766         for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2767                 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2768                 if (!g_utf8_collate (range_subtext, str_casefold)) {
2769                         gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2770                         result = TRUE;
2771                         gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2772                                                       match_start, match_end, NULL);
2773                         g_free (found_text);
2774                 }
2775                 g_free (range_subtext);
2776                 if (result)
2777                         break;
2778         }
2779         g_free (str_casefold);
2780         g_free (range_text);
2781         g_free (range_casefold);
2782
2783         return result;
2784 }
2785
2786
2787 static void 
2788 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2789                                             ModestMsgEditWindow *window)
2790 {
2791         gchar *current_search = NULL;
2792         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2793         gboolean result;
2794         GtkTextIter selection_start, selection_end;
2795         GtkTextIter match_start, match_end;
2796         gboolean continue_search = FALSE;
2797
2798         g_object_get (G_OBJECT (widget), "prefix", &current_search, NULL);
2799         if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2800                 g_free (current_search);
2801                 g_free (priv->last_search);
2802                 priv->last_search = NULL;
2803                 /* Information banner about empty search */
2804                 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2805                 return;
2806         }
2807
2808         if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2809                 continue_search = TRUE;
2810         } else {
2811                 g_free (priv->last_search);
2812                 priv->last_search = g_strdup (current_search);
2813         }
2814
2815         if (continue_search) {
2816                 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2817                 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search, 
2818                                                                    &match_start, &match_end);
2819                 if (!result)
2820                         hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2821         } else {
2822                 GtkTextIter buffer_start;
2823                 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2824                 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search, 
2825                                                                    &match_start, &match_end);
2826                 if (!result)
2827                         hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2828         }
2829
2830         /* Mark as selected the string found in search */
2831         if (result) {
2832                 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2833                 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2834         } else {
2835                 g_free (priv->last_search);
2836                 priv->last_search = NULL;
2837         }
2838         g_free (current_search);
2839 }
2840
2841 static void
2842 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2843                                            ModestMsgEditWindow *window)
2844 {
2845         GtkToggleAction *toggle;
2846         ModestWindowPrivate *parent_priv;
2847         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2848
2849         toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2850         gtk_toggle_action_set_active (toggle, FALSE);
2851 }
2852
2853
2854 static void 
2855 update_paste_dimming (ModestMsgEditWindow *window)
2856 {
2857         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2858         GtkAction *action = NULL;
2859         GtkClipboard *clipboard = NULL;
2860         GtkWidget *focused;
2861         gboolean active;
2862
2863         focused = gtk_window_get_focus (GTK_WINDOW (window));
2864
2865         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2866         active = gtk_clipboard_wait_is_text_available (clipboard);
2867
2868         if (active) {
2869                 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2870                         active = FALSE;
2871         }
2872
2873         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2874         gtk_action_set_sensitive (action, active);
2875
2876 }
2877
2878 static void 
2879 update_select_all_dimming (ModestMsgEditWindow *window)
2880 {
2881         GtkWidget *focused;
2882         gboolean dimmed = FALSE;
2883         GtkAction *action;
2884         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2885
2886         focused = gtk_window_get_focus (GTK_WINDOW (window));
2887         if (GTK_IS_ENTRY (focused)) {
2888                 const gchar *current_text;
2889                 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2890                 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2891         } else if (GTK_IS_TEXT_VIEW (focused)) {
2892                 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2893                 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2894         } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2895                 dimmed = FALSE;
2896         }
2897         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2898         gtk_action_set_sensitive (action, !dimmed);
2899 }
2900
2901 static void 
2902 update_zoom_dimming (ModestMsgEditWindow *window)
2903 {
2904         GtkWidget *focused;
2905         gboolean dimmed = FALSE;
2906         GtkAction *action;
2907         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2908
2909         focused = gtk_window_get_focus (GTK_WINDOW (window));
2910         dimmed = ! WP_IS_TEXT_VIEW (focused);
2911         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2912         gtk_action_set_sensitive (action, !dimmed);
2913 }
2914
2915 static void
2916 edit_menu_activated (GtkAction *action,
2917                      gpointer userdata)
2918 {
2919         ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2920
2921         update_select_all_dimming (window);
2922         update_paste_dimming (window);
2923 }
2924 static void
2925 view_menu_activated (GtkAction *action,
2926                      gpointer userdata)
2927 {
2928         ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2929
2930         update_zoom_dimming (window);
2931 }
2932
2933 gboolean 
2934 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
2935 {
2936         ModestMsgEditWindowPrivate *priv;
2937
2938         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2939         return priv->sent;
2940 }
2941
2942 void 
2943 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window, 
2944                                  gboolean sent)
2945 {
2946         ModestMsgEditWindowPrivate *priv;
2947
2948         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2949         priv->sent = sent;
2950 }
2951
2952
2953 void            
2954 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
2955                                   TnyMsg *draft)
2956 {
2957         ModestMsgEditWindowPrivate *priv;
2958         TnyHeader *header = NULL;
2959
2960         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2961         g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
2962
2963         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2964         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
2965
2966         if (priv->draft_msg != NULL) {
2967                 header = tny_msg_get_header (priv->draft_msg);
2968                 if (TNY_IS_HEADER (header)) {
2969                         modest_window_mgr_unregister_header (mgr, header);
2970                 }
2971                 g_object_unref (priv->draft_msg);
2972         }
2973
2974         if (draft != NULL) {
2975                 g_object_ref (draft);
2976                 header = tny_msg_get_header (draft);
2977                 if (TNY_IS_HEADER (header))
2978                         modest_window_mgr_register_header (mgr, header);
2979         }
2980
2981         priv->draft_msg = draft;
2982 }