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