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