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