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