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