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