* fix for GLIB CRITICAL (copy paste bug, modest_msg_edit_window_show_toolbar checked...
[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 save_state (ModestWindow *self)
196 {
197         modest_widget_memory_save (modest_runtime_get_conf(),
198                                    G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
199 }
200
201
202 static void
203 restore_settings (ModestMsgEditWindow *self)
204 {
205         modest_widget_memory_restore (modest_runtime_get_conf(),
206                                       G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
207 }
208
209
210 static void
211 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
212 {
213         GObjectClass *gobject_class;
214         ModestWindowClass *modest_window_class;
215         gobject_class = (GObjectClass*) klass;
216         modest_window_class = (ModestWindowClass*) klass;
217
218         parent_class            = g_type_class_peek_parent (klass);
219         gobject_class->finalize = modest_msg_edit_window_finalize;
220
221         modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
222         modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
223         modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
224         modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
225         modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
226
227         g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
228
229         modest_window_class->save_state_func = save_state;
230 }
231
232 static void
233 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
234 {
235         ModestMsgEditWindowPrivate *priv;
236         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
237
238         priv->msg_body      = NULL;
239         priv->from_field    = NULL;
240         priv->to_field      = NULL;
241         priv->cc_field      = NULL;
242         priv->bcc_field     = NULL;
243         priv->subject_field = NULL;
244         priv->attachments   = NULL;
245         priv->last_cid      = 0;
246         priv->zoom_level    = 1.0;
247
248         priv->cc_caption    = NULL;
249         priv->bcc_caption    = NULL;
250
251         priv->priority_flags = 0;
252
253         priv->draft_msg = NULL;
254 }
255
256
257 /* FIXME: this is a dup from the one in gtk/ */
258 static ModestPairList*
259 get_transports (void)
260 {
261         ModestAccountMgr *account_mgr;
262         GSList *transports = NULL;
263         GSList *cursor, *accounts;
264         
265         account_mgr = modest_runtime_get_account_mgr();
266         cursor = accounts = modest_account_mgr_account_names (account_mgr, 
267                                                 TRUE /* only enabled accounts. */); 
268         while (cursor) {
269                 gchar *account_name = (gchar*)cursor->data;
270                 gchar *from_string  = modest_account_mgr_get_from_string (account_mgr,
271                                                                           account_name);
272                 if (!from_string)  {
273                         /* something went wrong: ignore this one */
274                         g_free (account_name);
275                         cursor->data = NULL;
276                 } else {
277                         ModestPair *pair;
278                         pair = modest_pair_new ((gpointer) account_name,
279                                                 (gpointer) from_string , TRUE);
280                         transports = g_slist_prepend (transports, pair);
281                 } /* don't free account name; it's freed when the transports list is freed */
282                 cursor = cursor->next;
283         }
284         g_slist_free (accounts);
285         return transports;
286 }
287
288
289 static void
290 text_buffer_mark_set (GtkTextBuffer *buffer, GtkTextIter *iter, GtkTextMark *mark, gpointer userdata)
291 {
292         ModestMsgEditWindow *window;
293         ModestMsgEditWindowPrivate *priv;
294         GdkRectangle location;
295         gint v_scroll_min_value = 0;
296         gint v_scroll_max_value = 0;
297         gint v_scroll_visible;
298         GtkAdjustment *vadj;
299         GtkTextMark *insert_mark;
300         GtkTextIter insert_iter;
301         
302         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (userdata));
303         g_return_if_fail (GTK_IS_TEXT_MARK (mark));
304         window = MODEST_MSG_EDIT_WINDOW (userdata);
305         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
306                 
307         insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
308         gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &insert_iter, insert_mark);
309         gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &insert_iter, &location);
310         
311         if (priv->header_box)
312                 v_scroll_min_value += priv->header_box->allocation.height + DEFAULT_MAIN_VBOX_SPACING;
313         v_scroll_min_value += location.y;
314         v_scroll_max_value = v_scroll_min_value + location.height;
315         
316         v_scroll_visible = GTK_WIDGET (window)->allocation.height;
317         
318         vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
319         
320         if (((gdouble) v_scroll_min_value) < vadj->value)
321                 gtk_adjustment_set_value (vadj, v_scroll_min_value);
322         else if (((gdouble) v_scroll_max_value) > (vadj->value + vadj->page_size))
323                 gtk_adjustment_set_value (vadj, ((gdouble)v_scroll_max_value) - vadj->page_size);
324 }
325
326 static void
327 init_window (ModestMsgEditWindow *obj)
328 {
329         GtkWidget *from_caption, *to_caption, *subject_caption;
330         GtkWidget *main_vbox;
331         ModestMsgEditWindowPrivate *priv;
332         ModestPairList *protos;
333         GtkSizeGroup *size_group;
334         GtkWidget *frame;
335         GtkWidget *scroll_area;
336         GtkWidget *subject_box;
337         GtkWidget *attachment_icon;
338
339         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
340
341         size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
342
343         protos = get_transports ();
344         priv->from_field    = modest_combo_box_new (protos, g_str_equal);
345         modest_pair_list_free (protos);
346
347         priv->to_field      = modest_recpt_editor_new ();
348         priv->cc_field      = modest_recpt_editor_new ();
349         priv->bcc_field     = modest_recpt_editor_new ();
350         subject_box = gtk_hbox_new (FALSE, 0);
351         priv->priority_icon = gtk_image_new ();
352         gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
353         priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
354         g_object_set (G_OBJECT (priv->subject_field), "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL);
355         gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
356         priv->add_attachment_button = gtk_button_new ();
357         GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
358         gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
359         gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
360         gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
361         attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
362         gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
363         gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
364         priv->attachments_view = modest_attachments_view_new (NULL);
365         
366         priv->header_box = gtk_vbox_new (FALSE, 0);
367         
368         from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
369         to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
370         priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
371         priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
372         subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
373         priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
374         g_object_unref (size_group);
375
376         size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
377         modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
378         modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
379         modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
380         gtk_size_group_add_widget (size_group, priv->subject_field);
381         gtk_size_group_add_widget (size_group, priv->attachments_view);
382         g_object_unref (size_group);
383
384         gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
385         gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
386         gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
387         gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
388         gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
389         gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
390         gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
391
392
393         priv->msg_body = wp_text_view_new ();
394         gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
395         priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
396         g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
397         wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
398 /*      gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
399         wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
400
401         g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
402                           G_CALLBACK (text_buffer_refresh_attributes), obj);
403         g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
404                           G_CALLBACK (text_buffer_mark_set), obj);
405         g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
406                           G_CALLBACK (text_buffer_can_undo), obj);
407         g_signal_connect (G_OBJECT (obj), "window-state-event",
408                           G_CALLBACK (modest_msg_edit_window_window_state_event),
409                           NULL);
410         g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook", 
411                                   G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
412         g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook", 
413                                   G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
414         g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook", 
415                                   G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
416
417         g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
418                           G_CALLBACK (msg_body_focus), obj);
419         g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
420                           G_CALLBACK (msg_body_focus), obj);
421         g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
422                           "changed", G_CALLBACK (to_field_changed), obj);
423         to_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
424
425         priv->scroll = gtk_scrolled_window_new (NULL, NULL);
426         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
427         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
428         
429         main_vbox = gtk_vbox_new  (FALSE, DEFAULT_MAIN_VBOX_SPACING);
430
431         gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
432         frame = gtk_frame_new (NULL);
433         gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
434
435         gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
436         gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
437         gtk_widget_show_all (GTK_WIDGET(priv->scroll));
438         
439         if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL))
440                 gtk_widget_hide (priv->cc_field);
441         if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL))
442                 gtk_widget_hide (priv->bcc_field);
443
444         gtk_container_add (GTK_CONTAINER(obj), priv->scroll);
445         scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
446         gtk_container_add (GTK_CONTAINER (frame), scroll_area);
447         gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area), 
448                                              gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
449 }
450         
451
452
453 static void
454 modest_msg_edit_window_finalize (GObject *obj)
455 {
456         G_OBJECT_CLASS(parent_class)->finalize (obj);
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         modest_window_save_state (MODEST_WINDOW (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         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1640         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1641
1642         /* FIXME: we can not just use the code of
1643            modest_msg_edit_window_setup_toolbar because it has a
1644            mixture of both initialization and creation code. */
1645
1646         if (show_toolbar)
1647                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1648         else
1649                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1650 }
1651
1652 void
1653 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
1654                                            TnyHeaderFlags priority_flags)
1655 {
1656         ModestMsgEditWindowPrivate *priv;
1657
1658         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1659
1660         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1661         priority_flags = priority_flags & (TNY_HEADER_FLAG_HIGH_PRIORITY);
1662
1663         if (priv->priority_flags != priority_flags) {
1664
1665                 priv->priority_flags = priority_flags;
1666
1667                 switch (priority_flags) {
1668                 case TNY_HEADER_FLAG_HIGH_PRIORITY:
1669                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
1670                         gtk_widget_show (priv->priority_icon);
1671                         break;
1672                 case TNY_HEADER_FLAG_LOW_PRIORITY:
1673                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
1674                         gtk_widget_show (priv->priority_icon);
1675                         break;
1676                 default:
1677                         gtk_widget_hide (priv->priority_icon);
1678                         break;
1679                 }
1680         }
1681 }
1682
1683 void
1684 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
1685                                         gint file_format)
1686 {
1687         ModestMsgEditWindowPrivate *priv;
1688         gint current_format;
1689
1690         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1691
1692         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1693
1694         current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
1695                 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
1696
1697         if (current_format != file_format) {
1698                 switch (file_format) {
1699                 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
1700                         wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1701                         break;
1702                 case MODEST_FILE_FORMAT_PLAIN_TEXT:
1703                 {
1704                         GtkWidget *dialog;
1705                         gint response;
1706                         dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
1707                         response = gtk_dialog_run (GTK_DIALOG (dialog));
1708                         gtk_widget_destroy (dialog);
1709                         if (response == GTK_RESPONSE_OK)
1710                                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1711                 }
1712                         break;
1713                 }
1714                 update_dimmed (window);
1715         }
1716 }
1717
1718 void
1719 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
1720 {
1721         GtkWidget *dialog;
1722         ModestMsgEditWindowPrivate *priv;
1723         WPTextBufferFormat oldfmt, fmt;
1724         gint old_position = 0;
1725         gint response = 0;
1726         gint position = 0;
1727         gint font_size;
1728         GdkColor *color = NULL;
1729         gboolean bold, bold_set, italic, italic_set;
1730         gboolean underline, underline_set;
1731         gboolean strikethrough, strikethrough_set;
1732         gboolean position_set;
1733         gboolean font_size_set, font_set, color_set;
1734         gchar *font_name;
1735
1736         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1737         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1738         
1739         dialog = hildon_font_selection_dialog_new (NULL, NULL);
1740
1741         /* First we get the currently selected font information */
1742         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
1743         g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
1744
1745         switch (oldfmt.text_position) {
1746         case TEXT_POSITION_NORMAL:
1747                 old_position = 0;
1748                 break;
1749         case TEXT_POSITION_SUPERSCRIPT:
1750                 old_position = 1;
1751                 break;
1752         default:
1753                 old_position = -1;
1754                 break;
1755         }
1756
1757         g_object_set (G_OBJECT (dialog),
1758                       "bold", oldfmt.bold != FALSE,
1759                       "bold-set", !oldfmt.cs.bold,
1760                       "underline", oldfmt.underline != FALSE,
1761                       "underline-set", !oldfmt.cs.underline,
1762                       "italic", oldfmt.italic != FALSE,
1763                       "italic-set", !oldfmt.cs.italic,
1764                       "strikethrough", oldfmt.strikethrough != FALSE,
1765                       "strikethrough-set", !oldfmt.cs.strikethrough,
1766                       "color", &oldfmt.color,
1767                       "color-set", !oldfmt.cs.color,
1768                       "size", wp_font_size[oldfmt.font_size],
1769                       "size-set", !oldfmt.cs.font_size,
1770                       "position", old_position,
1771                       "position-set", !oldfmt.cs.text_position,
1772                       "family", wp_get_font_name (oldfmt.font),
1773                       "family-set", !oldfmt.cs.font,
1774                       NULL);
1775
1776         gtk_widget_show_all (dialog);
1777         response = gtk_dialog_run (GTK_DIALOG (dialog));
1778         if (response == GTK_RESPONSE_OK) {
1779
1780                 g_object_get( dialog,
1781                               "bold", &bold,
1782                               "bold-set", &bold_set,
1783                               "underline", &underline,
1784                               "underline-set", &underline_set,
1785                               "italic", &italic,
1786                               "italic-set", &italic_set,
1787                               "strikethrough", &strikethrough,
1788                               "strikethrough-set", &strikethrough_set,
1789                               "color", &color,
1790                               "color-set", &color_set,
1791                               "size", &font_size,
1792                               "size-set", &font_size_set,
1793                               "family", &font_name,
1794                               "family-set", &font_set,
1795                               "position", &position,
1796                               "position-set", &position_set,
1797                               NULL );
1798                 
1799         }       
1800
1801         gtk_widget_destroy (dialog);
1802         
1803         if (response == GTK_RESPONSE_OK) {
1804                 memset(&fmt, 0, sizeof(fmt));
1805                 if (bold_set) {
1806                         fmt.bold = bold;
1807                         fmt.cs.bold = TRUE;
1808                 }
1809                 if (italic_set) {
1810                         fmt.italic = italic;
1811                         fmt.cs.italic = TRUE;
1812                 }
1813                 if (underline_set) {
1814                         fmt.underline = underline;
1815                         fmt.cs.underline = TRUE;
1816                 }
1817                 if (strikethrough_set) {
1818                         fmt.strikethrough = strikethrough;
1819                         fmt.cs.strikethrough = TRUE;
1820                 }
1821                 if (position_set) {
1822                         fmt.text_position =
1823                                 ( position == 0 )
1824                                 ? TEXT_POSITION_NORMAL
1825                                 : ( ( position == 1 )
1826                                     ? TEXT_POSITION_SUPERSCRIPT
1827                                     : TEXT_POSITION_SUBSCRIPT );
1828                         fmt.cs.text_position = TRUE;
1829                 }
1830                 if (color_set) {
1831                         fmt.color = *color;
1832                         fmt.cs.color = TRUE;
1833                 }
1834                 gdk_color_free(color);
1835                 if (font_set) {
1836                         fmt.font = wp_get_font_index(font_name,
1837                                                      DEFAULT_FONT);
1838                         fmt.cs.font = TRUE;
1839                 }
1840                 g_free(font_name);
1841                 if (font_size_set) {
1842                         fmt.font_size = wp_get_font_size_index(
1843                                 font_size, DEFAULT_FONT_SIZE);
1844                         fmt.cs.font_size = TRUE;
1845                 }
1846                 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
1847                 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
1848         }
1849
1850 }
1851
1852 void
1853 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
1854 {
1855         ModestMsgEditWindowPrivate *priv;
1856
1857         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1858         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1859         
1860         wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
1861
1862         update_dimmed (window);
1863
1864 }
1865
1866 static void
1867 update_dimmed (ModestMsgEditWindow *window)
1868 {
1869         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1870         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1871         GtkAction *action;
1872         GtkWidget *widget;
1873         gboolean rich_text;
1874         gboolean editor_focused;
1875
1876         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1877         editor_focused = gtk_widget_is_focus (priv->msg_body);
1878
1879         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
1880         gtk_action_set_sensitive (action, rich_text && editor_focused);
1881         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1882         gtk_action_set_sensitive (action, rich_text && editor_focused);
1883         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
1884         gtk_action_set_sensitive (action, rich_text && editor_focused);
1885         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1886         gtk_action_set_sensitive (action, rich_text && editor_focused);
1887         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1888         gtk_action_set_sensitive (action, rich_text && editor_focused);
1889         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1890         gtk_action_set_sensitive (action, rich_text && editor_focused);
1891         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
1892         gtk_action_set_sensitive (action, rich_text && editor_focused);
1893         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1894         gtk_action_set_sensitive (action, rich_text && editor_focused);
1895         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1896         gtk_action_set_sensitive (action, rich_text && editor_focused);
1897         widget = priv->font_color_button;
1898         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
1899         widget = priv->font_size_toolitem;
1900         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
1901         widget = priv->font_face_toolitem;
1902         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
1903 }
1904
1905 static void
1906 setup_insensitive_handlers (ModestMsgEditWindow *window)
1907 {
1908         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1909         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1910         GtkWidget *widget;
1911
1912         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1913         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
1914         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
1915         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
1916
1917         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
1918         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
1919         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1920         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
1921         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
1922         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
1923         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1924         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
1925         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1926         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
1927         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1928         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
1929         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
1930         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
1931         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1932         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
1933         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1934         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
1935         widget = priv->font_color_button;
1936         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
1937         widget = priv->font_size_toolitem;
1938         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
1939         widget = priv->font_face_toolitem;
1940         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
1941
1942 }
1943
1944 static void  
1945 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
1946 {
1947         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1948         GtkAction *action;
1949
1950         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
1951         gtk_action_set_sensitive (action, can_undo);
1952 }
1953
1954 static gboolean
1955 msg_body_focus (GtkWidget *focus,
1956                 GdkEventFocus *event,
1957                 gpointer userdata)
1958 {
1959         update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
1960         return FALSE;
1961 }
1962
1963 static void
1964 to_field_changed (GtkTextBuffer *buffer,
1965                   ModestMsgEditWindow *editor)
1966 {
1967         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
1968         GtkAction *action;
1969
1970         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1971         gtk_action_set_sensitive (action, gtk_text_buffer_get_char_count (buffer) != 0);
1972         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
1973         gtk_action_set_sensitive (action, gtk_text_buffer_get_char_count (buffer) != 0);
1974 }
1975
1976 static void  
1977 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
1978 {
1979         hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
1980 }
1981
1982 static void
1983 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
1984 {
1985         gboolean rich_text, editor_focused;
1986
1987         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
1988         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1989         editor_focused = gtk_widget_is_focus (priv->msg_body);
1990
1991         if (!rich_text)
1992                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
1993         else if (!editor_focused)
1994                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
1995 }
1996
1997 static void
1998 reset_modified (ModestMsgEditWindow *editor)
1999 {
2000         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2001         GtkTextBuffer *buffer;
2002
2003         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2004         gtk_text_buffer_set_modified (buffer, FALSE);
2005         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2006         gtk_text_buffer_set_modified (buffer, FALSE);
2007         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2008         gtk_text_buffer_set_modified (buffer, FALSE);
2009         gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2010 }
2011
2012 static gboolean
2013 is_modified (ModestMsgEditWindow *editor)
2014 {
2015         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2016         GtkTextBuffer *buffer;
2017
2018         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2019         if (gtk_text_buffer_get_modified (buffer))
2020                 return TRUE;
2021         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2022         if (gtk_text_buffer_get_modified (buffer))
2023                 return TRUE;
2024         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2025         if (gtk_text_buffer_get_modified (buffer))
2026                 return TRUE;
2027         if (gtk_text_buffer_get_modified (priv->text_buffer))
2028                 return TRUE;
2029
2030         return FALSE;
2031 }
2032
2033 gboolean
2034 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2035 {
2036         ModestMsgEditWindowPrivate *priv = NULL;
2037
2038         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2039         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2040
2041         /* check if there's no recipient added */
2042         if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2043             (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2044             (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2045                 /* no recipient contents, then select contacts */
2046                 modest_msg_edit_window_open_addressbook (window, NULL);
2047                 return FALSE;
2048         }
2049
2050         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2051                 return FALSE;
2052         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2053                 return FALSE;
2054         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2055                 return FALSE;
2056
2057         modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2058
2059         return TRUE;
2060
2061 }