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