67f6917fe18b67ef2c1f763aff8d16653ca2533e
[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         data->attachments = priv->attachments; /* TODO: copy and free ? */
1075         data->priority_flags = priv->priority_flags;
1076
1077         return data;
1078 }
1079
1080 /* TODO: We must duplicate this implementation for GNOME and Maemo, but that is unwise. */
1081 void 
1082 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1083                                                       MsgData *data)
1084 {
1085         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1086
1087         if (!data)
1088                 return;
1089
1090         g_free (data->to);
1091         g_free (data->cc);
1092         g_free (data->bcc);
1093         g_free (data->subject);
1094         g_free (data->plain_body);
1095         g_free (data->html_body);
1096         g_free (data->account_name);
1097         
1098         if (data->draft_msg != NULL) {
1099                 g_object_unref (data->draft_msg);
1100                 data->draft_msg = NULL;
1101         }
1102
1103         g_list_foreach (data->attachments, (GFunc)g_free, NULL);
1104         g_list_free (data->attachments);
1105         
1106         /* TODO: Free data->attachments? */
1107
1108         g_slice_free (MsgData, data);
1109 }
1110
1111 ModestMsgEditFormat
1112 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1113 {
1114         gboolean rich_text;
1115         ModestMsgEditWindowPrivate *priv = NULL;
1116         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1117
1118         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1119
1120         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1121         if (rich_text)
1122                 return MODEST_MSG_EDIT_FORMAT_HTML;
1123         else
1124                 return MODEST_MSG_EDIT_FORMAT_TEXT;
1125 }
1126
1127 void
1128 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1129                                    ModestMsgEditFormat format)
1130 {
1131         ModestMsgEditWindowPrivate *priv;
1132
1133         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1134         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1135
1136         switch (format) {
1137         case MODEST_MSG_EDIT_FORMAT_HTML:
1138                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1139                 break;
1140         case MODEST_MSG_EDIT_FORMAT_TEXT:
1141                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1142                 break;
1143         default:
1144                 g_return_if_reached ();
1145         }
1146 }
1147
1148 ModestMsgEditFormatState *
1149 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1150 {
1151         ModestMsgEditFormatState *format_state = NULL;
1152         ModestMsgEditWindowPrivate *priv;
1153         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1154
1155         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1156         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1157
1158         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1159
1160         format_state = g_new0 (ModestMsgEditFormatState, 1);
1161         format_state->bold = buffer_format->bold&0x1;
1162         format_state->italics = buffer_format->italic&0x1;
1163         format_state->bullet = buffer_format->bullet&0x1;
1164         format_state->color = buffer_format->color;
1165         format_state->font_size = buffer_format->font_size;
1166         format_state->font_family = wp_get_font_name (buffer_format->font);
1167         format_state->justification = buffer_format->justification;
1168         g_free (buffer_format);
1169
1170         return format_state;
1171  
1172 }
1173
1174 void
1175 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1176                                          const ModestMsgEditFormatState *format_state)
1177 {
1178         ModestMsgEditWindowPrivate *priv;
1179         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1180         WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1181         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1182         g_return_if_fail (format_state != NULL);
1183
1184         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1185         gtk_widget_grab_focus (priv->msg_body);
1186         buffer_format->bold = (format_state->bold != FALSE);
1187         buffer_format->italic = (format_state->italics != FALSE);
1188         buffer_format->color = format_state->color;
1189         buffer_format->font_size = format_state->font_size;
1190         buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1191         buffer_format->justification = format_state->justification;
1192         buffer_format->bullet = format_state->bullet;
1193
1194         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1195
1196         buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1197         buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1198         buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1199         buffer_format->cs.font_size =  (buffer_format->font_size != current_format->font_size);
1200         buffer_format->cs.font = (buffer_format->font != current_format->font);
1201         buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1202         buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1203
1204         wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1205         if (buffer_format->cs.bold) {
1206                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1207         }
1208         if (buffer_format->cs.italic) {
1209                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1210         }
1211         if (buffer_format->cs.color) {
1212                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1213         }
1214         if (buffer_format->cs.font_size) {
1215                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1216         }
1217         if (buffer_format->cs.justification) {
1218                 switch (buffer_format->justification) {
1219                 case GTK_JUSTIFY_LEFT:
1220                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1221                         break;
1222                 case GTK_JUSTIFY_CENTER:
1223                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1224                         break;
1225                 case GTK_JUSTIFY_RIGHT:
1226                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1227                         break;
1228                 default:
1229                         break;
1230                 }
1231                         
1232         }
1233         if (buffer_format->cs.font) {
1234                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1235         }
1236         if (buffer_format->cs.bullet) {
1237                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1238         }
1239 /*      wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1240         wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1241
1242         g_free (current_format);
1243
1244 }
1245
1246 static void
1247 toggle_action_set_active_block_notify (GtkToggleAction *action,
1248                                        gboolean value)
1249 {
1250         GSList *proxies = NULL;
1251
1252         for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1253              proxies != NULL; proxies = g_slist_next (proxies)) {
1254                 GtkWidget *widget = (GtkWidget *) proxies->data;
1255                 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1256         }
1257
1258         gtk_toggle_action_set_active (action, value);
1259
1260         for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1261              proxies != NULL; proxies = g_slist_next (proxies)) {
1262                 GtkWidget *widget = (GtkWidget *) proxies->data;
1263                 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1264         }
1265 }
1266
1267 static void
1268 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1269 {
1270         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1271         GtkAction *action;
1272         ModestWindowPrivate *parent_priv;
1273         ModestMsgEditWindowPrivate *priv;
1274         GtkWidget *new_size_menuitem;
1275         GtkWidget *new_font_menuitem;
1276         
1277         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1278         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1279
1280         if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1281                 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1282                 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1283                         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1284         } else {
1285                 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1286                 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1287                         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1288         }
1289
1290         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1291         
1292         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1293         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1294
1295         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1296         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1297
1298         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1299         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1300
1301         g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button), 
1302                                          G_CALLBACK (modest_msg_edit_window_color_button_change),
1303                                          window);
1304         hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1305         g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button), 
1306                                            G_CALLBACK (modest_msg_edit_window_color_button_change),
1307                                            window);
1308
1309         new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group, 
1310                                                       buffer_format->font_size))->data);
1311         if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1312                 GtkWidget *label;
1313                 gchar *markup;
1314
1315                 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1316                 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1317                 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1318                 g_free (markup);
1319                 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1320                                                  G_CALLBACK (modest_msg_edit_window_size_change),
1321                                                  window);
1322                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1323                 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1324                                                    G_CALLBACK (modest_msg_edit_window_size_change),
1325                                                    window);
1326         }
1327
1328         new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group, 
1329                                                       buffer_format->font))->data);
1330         if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1331                 GtkWidget *label;
1332                 gchar *markup;
1333
1334                 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1335                 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1336                 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1337                 g_free (markup);
1338                 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1339                                                  G_CALLBACK (modest_msg_edit_window_font_change),
1340                                                  window);
1341                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1342                 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1343                                                    G_CALLBACK (modest_msg_edit_window_font_change),
1344                                                    window);
1345         }
1346
1347         g_free (buffer_format);
1348
1349 }
1350
1351
1352 void
1353 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1354 {
1355         
1356         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1357         ModestMsgEditWindowPrivate *priv;
1358         GtkWidget *dialog = NULL;
1359         gint response;
1360         const GdkColor *new_color = NULL;
1361         
1362         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1363         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1364         
1365 #ifdef MODEST_HILDON_VERSION_0  
1366         dialog = hildon_color_selector_new (GTK_WINDOW (window));
1367         hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1368 #else
1369         dialog = hildon_color_chooser_new ();
1370         hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1371 #endif /*MODEST_HILDON_VERSION_0*/              
1372         g_free (buffer_format);
1373
1374         response = gtk_dialog_run (GTK_DIALOG (dialog));
1375         switch (response) {
1376         case GTK_RESPONSE_OK: {
1377 #ifdef MODEST_HILDON_VERSION_0
1378                 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1379 #else
1380                 GdkColor col;
1381                 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1382                 new_color = &col;
1383 #endif /*MODEST_HILDON_VERSION_0*/
1384         }
1385
1386         break;
1387         default:
1388                 break;
1389         }
1390         gtk_widget_destroy (dialog);
1391
1392         if (new_color != NULL)
1393                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1394
1395 }
1396
1397 void
1398 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1399 {
1400         
1401         ModestMsgEditWindowPrivate *priv;
1402         GtkWidget *dialog = NULL;
1403         gint response;
1404         GdkColor *old_color = NULL;
1405         const GdkColor *new_color = NULL;
1406         
1407         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1408         old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1409         
1410 #ifdef MODEST_HILDON_VERSION_0  
1411         dialog = hildon_color_selector_new (GTK_WINDOW (window));
1412         hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1413 #else
1414         dialog = hildon_color_chooser_new ();
1415         hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1416 #endif /*MODEST_HILDON_VERSION_9*/              
1417
1418         response = gtk_dialog_run (GTK_DIALOG (dialog));
1419         switch (response) {
1420         case GTK_RESPONSE_OK: {
1421 #ifdef MODEST_HILDON_VERSION_0
1422                 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1423 #else
1424                 GdkColor col;
1425                 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1426                 new_color = &col;
1427 #endif /*MODEST_HILDON_VERSION_0*/
1428           }
1429                 break;
1430         default:
1431                 break;
1432         }
1433         gtk_widget_destroy (dialog);
1434
1435         if (new_color != NULL)
1436                 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1437
1438 }
1439
1440
1441 void
1442 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1443 {
1444         
1445         ModestMsgEditWindowPrivate *priv;
1446         GtkWidget *dialog = NULL;
1447         gint response = 0;
1448         GSList *uris = NULL;
1449         GSList *uri_node = NULL;
1450         
1451         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1452         
1453         dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1454         gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1455         gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1456
1457         modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1458
1459         response = gtk_dialog_run (GTK_DIALOG (dialog));
1460         switch (response) {
1461         case GTK_RESPONSE_OK:
1462                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1463                 break;
1464         default:
1465                 break;
1466         }
1467         gtk_widget_destroy (dialog);
1468
1469         for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1470                 const gchar *uri;
1471                 GnomeVFSHandle *handle = NULL;
1472                 GnomeVFSResult result;
1473                 GtkTextIter position;
1474                 GtkTextMark *insert_mark;
1475
1476                 uri = (const gchar *) uri_node->data;
1477                 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1478                 if (result == GNOME_VFS_OK) {
1479                         GdkPixbufLoader *loader;
1480                         GdkPixbuf *pixbuf;
1481                         GnomeVFSFileInfo info;
1482                         gchar *filename, *basename;
1483                         TnyMimePart *mime_part;
1484                         TnyStream *stream;
1485                         gchar *content_id;
1486                         const gchar *mime_type = NULL;
1487
1488                         filename = g_filename_from_uri (uri, NULL, NULL);
1489                         if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) 
1490                             == GNOME_VFS_OK)
1491                                 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1492
1493                         mime_part = tny_platform_factory_new_mime_part
1494                                 (modest_runtime_get_platform_factory ());
1495                         stream = TNY_STREAM (tny_vfs_stream_new (handle));
1496                         
1497                         tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1498                         
1499                         content_id = g_strdup_printf ("%d", priv->last_cid);
1500                         tny_mime_part_set_content_id (mime_part, content_id);
1501                         g_free (content_id);
1502                         priv->last_cid++;
1503                         
1504                         basename = g_path_get_basename (filename);
1505                         tny_mime_part_set_filename (mime_part, basename);
1506                         g_free (basename);
1507                         
1508                         priv->attachments = g_list_prepend (priv->attachments, mime_part);
1509                         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1510                                                                 mime_part);
1511                         gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1512                         gtk_widget_show_all (priv->attachments_caption);
1513                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1514                         g_free (filename);
1515
1516                         loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1517                         while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1518                                 unsigned char read_buffer[128];
1519                                 gint readed;
1520                                 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1521                                 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
1522                                         break;
1523                         }
1524                         pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1525                         g_object_ref (pixbuf);
1526                         gdk_pixbuf_loader_close (loader, NULL);
1527                         g_object_unref (loader);
1528
1529                         if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1530                                 GdkPixbuf *new_pixbuf;
1531                                 gint new_height;
1532                                 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1533                                         gdk_pixbuf_get_width (pixbuf);
1534                                 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1535                                 g_object_unref (pixbuf);
1536                                 pixbuf = new_pixbuf;
1537                         }
1538
1539                         if (pixbuf != NULL) {
1540                                 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1541                                 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1542                                 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1543                         } 
1544                 }
1545         }
1546
1547
1548 }
1549
1550 void
1551 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1552 {
1553         
1554         ModestMsgEditWindowPrivate *priv;
1555         GtkWidget *dialog = NULL;
1556         gint response = 0;
1557         GSList *uris = NULL;
1558         GSList *uri_node;
1559         
1560         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1561         
1562         dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1563         gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1564
1565         response = gtk_dialog_run (GTK_DIALOG (dialog));
1566         switch (response) {
1567         case GTK_RESPONSE_OK:
1568                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1569                 break;
1570         default:
1571                 break;
1572         }
1573         gtk_widget_destroy (dialog);
1574
1575         for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1576                 const gchar *uri;
1577                 GnomeVFSHandle *handle = NULL;
1578                 GnomeVFSResult result;
1579
1580                 uri = (const gchar *) uri_node->data;
1581                 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1582                 if (result == GNOME_VFS_OK) {
1583                         TnyMimePart *mime_part;
1584                         TnyStream *stream;
1585                         const gchar *mime_type = NULL;
1586                         gchar *basename;
1587                         gchar *filename;
1588                         gchar *content_id;
1589                         GnomeVFSFileInfo info;
1590
1591                         filename = g_filename_from_uri (uri, NULL, NULL);
1592                         
1593                         if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1594                                 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1595                         mime_part = tny_platform_factory_new_mime_part
1596                                 (modest_runtime_get_platform_factory ());
1597                         stream = TNY_STREAM (tny_vfs_stream_new (handle));
1598                         
1599                         tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1600                         
1601                         content_id = g_strdup_printf ("%d", priv->last_cid);
1602                         tny_mime_part_set_content_id (mime_part, content_id);
1603                         g_free (content_id);
1604                         priv->last_cid++;
1605                         
1606                         basename = g_path_get_basename (filename);
1607                         tny_mime_part_set_filename (mime_part, basename);
1608                         g_free (basename);
1609                         
1610                         priv->attachments = g_list_prepend (priv->attachments, mime_part);
1611                         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1612                                                                 mime_part);
1613                         gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1614                         gtk_widget_show_all (priv->attachments_caption);
1615                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1616                         g_free (filename);
1617
1618                 } 
1619         }
1620         g_slist_foreach (uris, (GFunc) g_free, NULL);
1621         g_slist_free (uris);
1622 }
1623
1624 void
1625 modest_msg_edit_window_attach_file_noninteractive (
1626                 ModestMsgEditWindow *window,
1627                 const gchar *file_uri)
1628 {
1629         
1630         ModestMsgEditWindowPrivate *priv;
1631         
1632         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1633
1634         if (file_uri && strlen(file_uri)) {
1635                 gint file_id = 0;
1636                 
1637                 /* TODO: We should probably try to use only the URI,
1638                  * instead of using a filename.
1639                  */
1640                 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1641                 if (!filename) {
1642                         g_warning("%s: g_filename_from_uri('%s') failed.\n", __FUNCTION__, file_uri);
1643                 }
1644
1645                 file_id = g_open (filename, O_RDONLY, 0);
1646                 if (file_id != -1) {
1647                         TnyMimePart *mime_part;
1648                         TnyStream *stream;
1649                         const gchar *mime_type;
1650                         gchar *basename;
1651                         gchar *content_id;
1652 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1653                         mime_type = gnome_vfs_get_mime_type(filename);
1654 #else
1655                         mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1656 #endif
1657                         mime_part = tny_platform_factory_new_mime_part
1658                                 (modest_runtime_get_platform_factory ());
1659                         stream = TNY_STREAM (tny_fs_stream_new (file_id));
1660                         
1661                         tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1662                         
1663                         content_id = g_strdup_printf ("%d", priv->last_cid);
1664                         tny_mime_part_set_content_id (mime_part, content_id);
1665                         g_free (content_id);
1666                         priv->last_cid++;
1667                         
1668                         basename = g_path_get_basename (filename);
1669                         tny_mime_part_set_filename (mime_part, basename);
1670                         g_free (basename);
1671                         
1672                         priv->attachments = g_list_prepend (priv->attachments, mime_part);
1673                         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1674                                                                 mime_part);
1675                         gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1676                         gtk_widget_show_all (priv->attachments_caption);
1677                 } else if (file_id == -1) {
1678                         close (file_id);
1679                         g_warning("file to be attached does not exist: %s", filename);
1680                 }
1681
1682                 g_free (filename);
1683         }
1684 }
1685
1686 void
1687 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1688                                           GList *att_list)
1689 {
1690         ModestMsgEditWindowPrivate *priv;
1691         gboolean clean_list = FALSE;
1692
1693         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1694         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1695
1696         if (att_list == NULL) {
1697                 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1698                 clean_list = TRUE;
1699         }
1700
1701         if (att_list == NULL) {
1702                 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1703         } else {
1704                 GtkWidget *confirmation_dialog = NULL;
1705                 gboolean dialog_response;
1706                 GList *node;
1707                 gchar *message = NULL;
1708                 const gchar *filename = NULL;
1709
1710                 if (att_list->next == NULL) {
1711                         filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1712                 } else {
1713                         filename = "";
1714                 }
1715                 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1716                                                     att_list->next == NULL), filename);
1717                 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1718                 g_free (message);
1719                 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1720                 gtk_widget_destroy (confirmation_dialog);
1721                 if (!dialog_response) {
1722                         if (clean_list)
1723                                 g_list_free (att_list);
1724                         return;
1725                 }
1726                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1727
1728                 for (node = att_list; node != NULL; node = g_list_next (node)) {
1729                         TnyMimePart *mime_part = (TnyMimePart *) node->data;
1730                         const gchar *att_id;
1731                         priv->attachments = g_list_remove (priv->attachments, mime_part);
1732
1733                         modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1734                                                                    mime_part);
1735                         if (priv->attachments == NULL)
1736                                 gtk_widget_hide (priv->attachments_caption);
1737                         att_id = tny_mime_part_get_content_id (mime_part);
1738                         if (att_id != NULL)
1739                                 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1740                                                                  att_id);
1741                         g_object_unref (mime_part);
1742                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1743                 }
1744         }
1745
1746         if (clean_list)
1747                 g_list_free (att_list);
1748 }
1749
1750 static void
1751 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1752                                             gpointer userdata)
1753 {
1754         ModestMsgEditWindowPrivate *priv;
1755         GdkColor *new_color;
1756         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1757         
1758 #ifdef MODEST_HAVE_HILDON0_WIDGETS      
1759         new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1760 #else 
1761         GdkColor col;
1762         hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1763         new_color = &col;
1764 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1765
1766         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1767         
1768         gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1769
1770 }
1771
1772 static void
1773 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1774                                     gpointer userdata)
1775 {
1776         ModestMsgEditWindowPrivate *priv;
1777         gint new_size_index;
1778         ModestMsgEditWindow *window;
1779         GtkWidget *label;
1780         
1781         window = MODEST_MSG_EDIT_WINDOW (userdata);
1782         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1783         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1784
1785         if (gtk_check_menu_item_get_active (menu_item)) {
1786                 gchar *markup;
1787                 WPTextBufferFormat format;
1788
1789                 memset (&format, 0, sizeof (format));
1790                 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1791
1792                 label = gtk_bin_get_child (GTK_BIN (menu_item));
1793                 
1794                 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1795                 format.cs.font_size = TRUE;
1796                 format.cs.text_position = TRUE;
1797                 format.cs.font = TRUE;
1798                 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1799 /*              wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1800
1801                 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1802                                                    (gpointer) wp_get_font_size_index (new_size_index, 12)))
1803                         wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1804                 
1805                 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1806                 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1807                 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1808                 g_free (markup);
1809         }
1810 }
1811
1812 static void
1813 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1814                                     gpointer userdata)
1815 {
1816         ModestMsgEditWindowPrivate *priv;
1817         gint new_font_index;
1818         ModestMsgEditWindow *window;
1819         GtkWidget *label;
1820         
1821         window = MODEST_MSG_EDIT_WINDOW (userdata);
1822         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1823         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1824
1825         if (gtk_check_menu_item_get_active (menu_item)) {
1826                 gchar *markup;
1827
1828                 label = gtk_bin_get_child (GTK_BIN (menu_item));
1829                 
1830                 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1831
1832                 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, 
1833                                                    (gpointer) new_font_index))
1834                         wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1835                 
1836                 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1837                     markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1838                 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1839                 g_free (markup);
1840         }
1841 }
1842
1843 static void
1844 modest_msg_edit_window_set_zoom (ModestWindow *window,
1845                                  gdouble zoom)
1846 {
1847         ModestMsgEditWindowPrivate *priv;
1848         ModestWindowPrivate *parent_priv;
1849         GtkRadioAction *zoom_radio_action;
1850      
1851         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1852
1853         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1854         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1855         priv->zoom_level = zoom;
1856         wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1857
1858         /* Zoom level menu options should be updated with the current zoom level */
1859         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1860         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1861                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1862 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1863         /* FIXME: Not availible before Gtk 2.10 */
1864 #else
1865         gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1866 #endif
1867 }
1868
1869 static gdouble
1870 modest_msg_edit_window_get_zoom (ModestWindow *window)
1871 {
1872         ModestMsgEditWindowPrivate *priv;
1873      
1874         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1875
1876         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1877         return priv->zoom_level;
1878 }
1879
1880 static gboolean
1881 zoom_allowed (ModestMsgEditWindow *window)
1882 {
1883         GtkWidget *focus;
1884
1885         focus = gtk_window_get_focus (GTK_WINDOW (window));
1886         return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1887 }
1888
1889 static gboolean
1890 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1891 {
1892         ModestWindowPrivate *parent_priv;
1893         GtkRadioAction *zoom_radio_action;
1894         GSList *group, *node;
1895
1896         /* First we check if the text view is focused. If not, zooming is not allowed */
1897         if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1898                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1899                 return FALSE;
1900         }
1901
1902         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1903         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1904                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1905
1906         group = gtk_radio_action_get_group (zoom_radio_action);
1907
1908         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1909                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
1910                 return FALSE;
1911         }
1912
1913         for (node = group; node != NULL; node = g_slist_next (node)) {
1914                 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1915                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1916                         return TRUE;
1917                 }
1918         }
1919         return FALSE;
1920 }
1921
1922 static gboolean
1923 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1924 {
1925         ModestWindowPrivate *parent_priv;
1926         GtkRadioAction *zoom_radio_action;
1927         GSList *group, *node;
1928
1929         /* First we check if the text view is focused. If not, zooming is not allowed */
1930         if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1931                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1932                 return FALSE;
1933         }
1934
1935         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1936         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1937                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1938
1939         group = gtk_radio_action_get_group (zoom_radio_action);
1940
1941         for (node = group; node != NULL; node = g_slist_next (node)) {
1942                 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1943                         if (node->next != NULL) {
1944                                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1945                                 return TRUE;
1946                         } else
1947                                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
1948                         break;
1949                 }
1950         }
1951         return FALSE;
1952 }
1953
1954 static gboolean
1955 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1956 {
1957         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1958                 ModestWindowPrivate *parent_priv;
1959                 ModestWindowMgr *mgr;
1960                 gboolean is_fullscreen;
1961                 GtkAction *fs_toggle_action;
1962                 gboolean active;
1963
1964                 mgr = modest_runtime_get_window_mgr ();
1965                 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1966
1967                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1968                 
1969                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1970                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1971                 if (is_fullscreen != active)
1972                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1973         }
1974
1975         return FALSE;
1976
1977 }
1978
1979 void
1980 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1981 {
1982         ModestWindowPrivate *parent_priv;
1983         GtkAction *fs_toggle_action;
1984         gboolean active;
1985
1986         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1987
1988         fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1989         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1990         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1991 }
1992
1993 void
1994 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window, 
1995                                 gboolean show)
1996 {
1997         ModestMsgEditWindowPrivate *priv = NULL;
1998         const gchar *recipients;
1999         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2000
2001         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2002         gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2003         recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field));
2004         if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2005                 gtk_widget_show (priv->cc_caption);
2006         else
2007                 gtk_widget_hide (priv->cc_caption);
2008         modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2009 }
2010
2011 void
2012 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window, 
2013                                  gboolean show)
2014 {
2015         ModestMsgEditWindowPrivate *priv = NULL;
2016         const gchar *recipients;
2017         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2018
2019         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2020         gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2021         recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field));
2022         if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2023                 gtk_widget_show (priv->bcc_caption);
2024         else
2025                 gtk_widget_hide (priv->bcc_caption);
2026         modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2027 }
2028
2029 static void
2030 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2031                                          ModestRecptEditor *editor)
2032 {
2033         ModestMsgEditWindowPrivate *priv;
2034
2035         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2036         g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2037         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2038
2039         if (editor == NULL) {
2040                 GtkWidget *view_focus;
2041                 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2042
2043                 /* This code should be kept in sync with ModestRecptEditor. The
2044                    textview inside the recpt editor is the one that really gets the
2045                    focus. As it's inside a scrolled window, and this one inside the
2046                    hbox recpt editor inherits from, we'll need to go up in the 
2047                    hierarchy to know if the text view is part of the recpt editor
2048                    or if it's a different text entry */
2049
2050                 if (gtk_widget_get_parent (view_focus)) {
2051                         GtkWidget *first_parent;
2052
2053                         first_parent = gtk_widget_get_parent (view_focus);
2054                         if (gtk_widget_get_parent (first_parent) && 
2055                             MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2056                                 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2057                         }
2058                 }
2059
2060                 if (editor == NULL)
2061                         editor = MODEST_RECPT_EDITOR (priv->to_field);
2062
2063         }
2064
2065         modest_address_book_select_addresses (editor);
2066
2067 }
2068
2069 void
2070 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2071 {
2072         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2073
2074         modest_msg_edit_window_open_addressbook (window, NULL);
2075 }
2076
2077 static void
2078 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2079                                      gboolean show_toolbar)
2080 {
2081         ModestWindowPrivate *parent_priv;
2082         
2083         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2084         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2085
2086         /* FIXME: we can not just use the code of
2087            modest_msg_edit_window_setup_toolbar because it has a
2088            mixture of both initialization and creation code. */
2089
2090         if (show_toolbar)
2091                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2092         else
2093                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2094 }
2095
2096 void
2097 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2098                                            TnyHeaderFlags priority_flags)
2099 {
2100         ModestMsgEditWindowPrivate *priv;
2101         ModestWindowPrivate *parent_priv;
2102
2103         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2104
2105         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2106         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2107         priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2108
2109         if (priv->priority_flags != priority_flags) {
2110                 GtkAction *priority_action = NULL;
2111
2112                 priv->priority_flags = priority_flags;
2113
2114                 switch (priority_flags) {
2115                 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2116                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2117                         gtk_widget_show (priv->priority_icon);
2118                         priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
2119                                                                      "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2120                         break;
2121                 case TNY_HEADER_FLAG_LOW_PRIORITY:
2122                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2123                         gtk_widget_show (priv->priority_icon);
2124                         priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
2125                                                                      "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2126                         break;
2127                 default:
2128                         gtk_widget_hide (priv->priority_icon);
2129                         priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
2130                                                                      "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2131                         break;
2132                 }
2133                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2134                 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2135         }
2136 }
2137
2138 void
2139 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2140                                         gint file_format)
2141 {
2142         ModestMsgEditWindowPrivate *priv;
2143         ModestWindowPrivate *parent_priv;
2144         gint current_format;
2145
2146         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2147
2148         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2149         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2150
2151         current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2152                 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2153
2154         if (current_format != file_format) {
2155                 switch (file_format) {
2156                 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2157                         wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2158                         break;
2159                 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2160                 {
2161                         GtkWidget *dialog;
2162                         gint response;
2163                         dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2164                         response = gtk_dialog_run (GTK_DIALOG (dialog));
2165                         gtk_widget_destroy (dialog);
2166                         if (response == GTK_RESPONSE_OK) {
2167                                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2168                         } else {
2169                                 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2170                                 toggle_action_set_active_block_notify (action, TRUE);
2171                         }
2172                 }
2173                         break;
2174                 }
2175                 update_dimmed (window);
2176         }
2177 }
2178
2179 void
2180 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2181 {
2182         GtkWidget *dialog;
2183         ModestMsgEditWindowPrivate *priv;
2184         WPTextBufferFormat oldfmt, fmt;
2185         gint old_position = 0;
2186         gint response = 0;
2187         gint position = 0;
2188         gint font_size;
2189         GdkColor *color = NULL;
2190         gboolean bold, bold_set, italic, italic_set;
2191         gboolean underline, underline_set;
2192         gboolean strikethrough, strikethrough_set;
2193         gboolean position_set;
2194         gboolean font_size_set, font_set, color_set;
2195         gchar *font_name;
2196
2197         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2198         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2199         
2200         dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2201
2202         /* First we get the currently selected font information */
2203         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2204         g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2205
2206         switch (oldfmt.text_position) {
2207         case TEXT_POSITION_NORMAL:
2208                 old_position = 0;
2209                 break;
2210         case TEXT_POSITION_SUPERSCRIPT:
2211                 old_position = 1;
2212                 break;
2213         default:
2214                 old_position = -1;
2215                 break;
2216         }
2217
2218         g_object_set (G_OBJECT (dialog),
2219                       "bold", oldfmt.bold != FALSE,
2220                       "bold-set", !oldfmt.cs.bold,
2221                       "underline", oldfmt.underline != FALSE,
2222                       "underline-set", !oldfmt.cs.underline,
2223                       "italic", oldfmt.italic != FALSE,
2224                       "italic-set", !oldfmt.cs.italic,
2225                       "strikethrough", oldfmt.strikethrough != FALSE,
2226                       "strikethrough-set", !oldfmt.cs.strikethrough,
2227                       "color", &oldfmt.color,
2228                       "color-set", !oldfmt.cs.color,
2229                       "size", wp_font_size[oldfmt.font_size],
2230                       "size-set", !oldfmt.cs.font_size,
2231                       "position", old_position,
2232                       "position-set", !oldfmt.cs.text_position,
2233                       "family", wp_get_font_name (oldfmt.font),
2234                       "family-set", !oldfmt.cs.font,
2235                       NULL);
2236
2237         gtk_widget_show_all (dialog);
2238         response = gtk_dialog_run (GTK_DIALOG (dialog));
2239         if (response == GTK_RESPONSE_OK) {
2240
2241                 g_object_get( dialog,
2242                               "bold", &bold,
2243                               "bold-set", &bold_set,
2244                               "underline", &underline,
2245                               "underline-set", &underline_set,
2246                               "italic", &italic,
2247                               "italic-set", &italic_set,
2248                               "strikethrough", &strikethrough,
2249                               "strikethrough-set", &strikethrough_set,
2250                               "color", &color,
2251                               "color-set", &color_set,
2252                               "size", &font_size,
2253                               "size-set", &font_size_set,
2254                               "family", &font_name,
2255                               "family-set", &font_set,
2256                               "position", &position,
2257                               "position-set", &position_set,
2258                               NULL );
2259                 
2260         }       
2261
2262         if (response == GTK_RESPONSE_OK) {
2263                 memset(&fmt, 0, sizeof(fmt));
2264                 if (bold_set) {
2265                         fmt.bold = bold;
2266                         fmt.cs.bold = TRUE;
2267                 }
2268                 if (italic_set) {
2269                         fmt.italic = italic;
2270                         fmt.cs.italic = TRUE;
2271                 }
2272                 if (underline_set) {
2273                         fmt.underline = underline;
2274                         fmt.cs.underline = TRUE;
2275                 }
2276                 if (strikethrough_set) {
2277                         fmt.strikethrough = strikethrough;
2278                         fmt.cs.strikethrough = TRUE;
2279                 }
2280                 if (position_set) {
2281                         fmt.text_position =
2282                                 ( position == 0 )
2283                                 ? TEXT_POSITION_NORMAL
2284                                 : ( ( position == 1 )
2285                                     ? TEXT_POSITION_SUPERSCRIPT
2286                                     : TEXT_POSITION_SUBSCRIPT );
2287                         fmt.cs.text_position = TRUE;
2288                 }
2289                 if (color_set) {
2290                         fmt.color = *color;
2291                         fmt.cs.color = TRUE;
2292                 }
2293                 if (font_set) {
2294                         fmt.font = wp_get_font_index(font_name,
2295                                                      DEFAULT_FONT);
2296                         fmt.cs.font = TRUE;
2297                 }
2298                 g_free(font_name);
2299                 if (font_size_set) {
2300                         fmt.font_size = wp_get_font_size_index(
2301                                 font_size, DEFAULT_FONT_SIZE);
2302                         fmt.cs.font_size = TRUE;
2303                 }
2304                 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2305         }
2306         gtk_widget_destroy (dialog);
2307         
2308         gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2309 }
2310
2311 void
2312 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2313 {
2314         ModestMsgEditWindowPrivate *priv;
2315
2316         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2317         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2318         
2319         wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2320
2321         update_dimmed (window);
2322
2323 }
2324
2325 void
2326 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2327 {
2328         ModestMsgEditWindowPrivate *priv;
2329
2330         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2331         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2332         
2333         wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2334
2335         update_dimmed (window);
2336
2337 }
2338
2339 static void
2340 update_dimmed (ModestMsgEditWindow *window)
2341 {
2342         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2343         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2344         GtkAction *action;
2345         GtkWidget *widget;
2346         gboolean rich_text;
2347         gboolean editor_focused;
2348
2349         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2350         editor_focused = gtk_widget_is_focus (priv->msg_body);
2351
2352         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2353         gtk_action_set_sensitive (action, rich_text && editor_focused);
2354         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2355         gtk_action_set_sensitive (action, rich_text && editor_focused);
2356         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2357         gtk_action_set_sensitive (action, rich_text && editor_focused);
2358         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2359         gtk_action_set_sensitive (action, rich_text && editor_focused);
2360         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2361         gtk_action_set_sensitive (action, rich_text && editor_focused);
2362         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2363         gtk_action_set_sensitive (action, rich_text && editor_focused);
2364         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2365         gtk_action_set_sensitive (action, rich_text && editor_focused);
2366         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2367         gtk_action_set_sensitive (action, rich_text && editor_focused);
2368         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2369         gtk_action_set_sensitive (action, rich_text && editor_focused);
2370         widget = priv->font_color_button;
2371         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2372         widget = priv->font_size_toolitem;
2373         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2374         widget = priv->font_face_toolitem;
2375         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2376 }
2377
2378 static void
2379 setup_insensitive_handlers (ModestMsgEditWindow *window)
2380 {
2381         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2382         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2383         GtkWidget *widget;
2384
2385         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2386         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2387         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2388         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2389
2390         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2391         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2392         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2393         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2394         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2395         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2396         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2397         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2398         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2399         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2400         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2401         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2402         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2403         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2404         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2405         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2406         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2407         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2408         widget = priv->font_color_button;
2409         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2410         widget = priv->font_size_toolitem;
2411         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2412         widget = priv->font_face_toolitem;
2413         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2414
2415         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2416         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (remove_attachment_insensitive_press), window);
2417         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2418         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (zoom_insensitive_press), window);
2419
2420         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2421         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (paste_insensitive_press), window);
2422         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2423         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (copy_insensitive_press), window);
2424 }
2425
2426 static void  
2427 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2428 {
2429         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2430         GtkAction *action;
2431
2432         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2433         gtk_action_set_sensitive (action, can_undo);
2434 }
2435
2436 static void  
2437 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2438 {
2439         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2440         GtkAction *action;
2441
2442         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2443         gtk_action_set_sensitive (action, can_redo);
2444 }
2445
2446 static void
2447 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2448 {
2449         GtkTextIter iter;
2450         GtkTextIter match_start, match_end;
2451
2452         if (image_id == NULL)
2453                 return;
2454
2455         gtk_text_buffer_get_start_iter (buffer, &iter);
2456
2457         while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2458                 GSList *tags = gtk_text_iter_get_tags (&match_start);
2459                 GSList *node;
2460                 for (node = tags; node != NULL; node = g_slist_next (node)) {
2461                         GtkTextTag *tag = (GtkTextTag *) node->data;
2462                         if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2463                                 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2464                                 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2465                                         gint offset;
2466                                         offset = gtk_text_iter_get_offset (&match_start);
2467                                         gtk_text_buffer_delete (buffer, &match_start, &match_end);
2468                                         gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2469                                 }
2470                         }
2471                 }
2472                 gtk_text_iter_forward_char (&iter);
2473         }
2474 }
2475
2476 static void
2477 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2478 {
2479         ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2480         GtkTextIter real_start, real_end;
2481         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2482
2483         if (gtk_text_iter_compare (start, end) > 0) {
2484                 real_start = *end;
2485                 real_end = *start;
2486         } else {
2487                 real_start = *start;
2488                 real_end = *end;
2489         }
2490         do {
2491                 GSList *tags = gtk_text_iter_get_tags (&real_start);
2492                 GSList *node;
2493                 for (node = tags; node != NULL; node = g_slist_next (node)) {
2494                         GtkTextTag *tag = (GtkTextTag *) node->data;
2495                         if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2496                                 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2497
2498                                 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2499                                                                                  image_id);
2500                                 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2501                         }
2502                 }
2503         } while (gtk_text_iter_forward_char (&real_start)&&
2504                  (gtk_text_iter_compare (&real_start, &real_end)<=0));
2505 }
2506
2507 static gboolean
2508 msg_body_focus (GtkWidget *focus,
2509                 GdkEventFocus *event,
2510                 gpointer userdata)
2511 {
2512         
2513         update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2514         return FALSE;
2515 }
2516
2517 static void
2518 recpt_field_changed (GtkTextBuffer *buffer,
2519                   ModestMsgEditWindow *editor)
2520 {
2521         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2522         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2523         GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2524         gboolean dim = FALSE;
2525         GtkAction *action;
2526
2527         to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2528         cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2529         bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2530         
2531         dim = ((gtk_text_buffer_get_char_count (to_buffer) + 
2532                 gtk_text_buffer_get_char_count (cc_buffer) +
2533                 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2534                         
2535         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2536         gtk_action_set_sensitive (action, !dim);
2537         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2538         gtk_action_set_sensitive (action, !dim);
2539 }
2540
2541 static void  
2542 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2543 {
2544         hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2545 }
2546
2547 static void  
2548 zoom_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2549 {
2550         hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2551 }
2552
2553 static void  
2554 remove_attachment_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2555 {
2556         ModestWindowPrivate *parent_priv;
2557         ModestMsgEditWindowPrivate *priv;
2558         GList *selected_attachments = NULL;
2559         gint n_att_selected = 0;
2560
2561         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2562         parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2563
2564         selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2565         n_att_selected = g_list_length (selected_attachments);
2566         g_list_free (selected_attachments);
2567
2568         if (n_att_selected > 1)
2569                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
2570         else if (n_att_selected == 0)
2571                 hildon_banner_show_information (NULL, NULL, _("TODO: select one attachment"));
2572         else
2573                 hildon_banner_show_information (NULL, NULL, _("mail_ib_unable_to_purge_attachments"));
2574 }
2575
2576 static void
2577 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2578 {
2579         gboolean rich_text, editor_focused;
2580
2581         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2582         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2583         editor_focused = gtk_widget_is_focus (priv->msg_body);
2584
2585         if (!rich_text)
2586                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2587         else if (!editor_focused)
2588                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2589 }
2590
2591 static void
2592 reset_modified (ModestMsgEditWindow *editor)
2593 {
2594         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2595         GtkTextBuffer *buffer;
2596
2597         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2598         gtk_text_buffer_set_modified (buffer, FALSE);
2599         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2600         gtk_text_buffer_set_modified (buffer, FALSE);
2601         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2602         gtk_text_buffer_set_modified (buffer, FALSE);
2603         gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2604 }
2605
2606 gboolean
2607 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2608 {
2609         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2610         GtkTextBuffer *buffer;
2611
2612         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2613         if (gtk_text_buffer_get_modified (buffer))
2614                 return TRUE;
2615         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2616         if (gtk_text_buffer_get_modified (buffer))
2617                 return TRUE;
2618         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2619         if (gtk_text_buffer_get_modified (buffer))
2620                 return TRUE;
2621         if (gtk_text_buffer_get_modified (priv->text_buffer))
2622                 return TRUE;
2623
2624         return FALSE;
2625 }
2626
2627 gboolean
2628 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2629 {
2630         ModestMsgEditWindowPrivate *priv = NULL;
2631
2632         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2633         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2634
2635         /* check if there's no recipient added */
2636         if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2637             (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2638             (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2639                 /* no recipient contents, then select contacts */
2640                 modest_msg_edit_window_open_addressbook (window, NULL);
2641                 return FALSE;
2642         }
2643
2644         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2645                 return FALSE;
2646         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2647                 return FALSE;
2648         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2649                 return FALSE;
2650
2651         modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2652
2653         return TRUE;
2654
2655 }
2656
2657 static void
2658 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2659                                                ModestMsgEditWindow *window)
2660 {
2661         modest_msg_edit_window_attach_file (window);
2662 }
2663
2664 static void
2665 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2666                                                GdkEvent *event,
2667                                                ModestMsgEditWindow *window)
2668 {
2669         ModestWindowPrivate *parent_priv;
2670         ModestMsgEditWindowPrivate *priv;
2671         GtkAction *action;
2672         gchar *selection;
2673         GtkWidget *focused;
2674         GList *selected_attachments = NULL;
2675         gint n_att_selected = 0;
2676
2677         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2678         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2679         selection = gtk_clipboard_wait_for_text (clipboard);
2680         focused = gtk_window_get_focus (GTK_WINDOW (window));
2681
2682         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2683         gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2684         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2685         gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2686
2687         selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2688         n_att_selected = g_list_length (selected_attachments);
2689         g_list_free (selected_attachments);
2690
2691         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2692         gtk_action_set_sensitive (action, n_att_selected == 1);
2693         
2694
2695         update_paste_dimming (window);
2696 }
2697
2698 static void 
2699 update_window_title (ModestMsgEditWindow *window)
2700 {
2701         ModestMsgEditWindowPrivate *priv = NULL;
2702         const gchar *subject;
2703
2704         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2705         subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2706         if (subject == NULL || subject[0] == '\0')
2707                 subject = _("mail_va_new_email");
2708
2709         gtk_window_set_title (GTK_WINDOW (window), subject);
2710
2711 }
2712
2713 static void  
2714 subject_field_changed (GtkEditable *editable, 
2715                        ModestMsgEditWindow *window)
2716 {
2717         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2718         update_window_title (window);
2719         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2720 }
2721
2722 void
2723 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2724                                             gboolean show)
2725 {
2726         ModestMsgEditWindowPrivate *priv = NULL;
2727
2728         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2729         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2730
2731         gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2732         if (show) {
2733                 gtk_widget_show_all (priv->find_toolbar);
2734                 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2735         } else {
2736                 gtk_widget_hide_all (priv->find_toolbar);
2737                 gtk_widget_grab_focus (priv->msg_body);
2738         }
2739     
2740 }
2741
2742 static gboolean 
2743 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2744                                           const gchar *str,
2745                                           GtkTextIter *match_start,
2746                                           GtkTextIter *match_end)
2747 {
2748         GtkTextIter end_iter;
2749         gchar *str_casefold;
2750         gint str_chars_n;
2751         gchar *range_text;
2752         gchar *range_casefold;
2753         gint offset;
2754         gint range_chars_n;
2755         gboolean result = FALSE;
2756
2757         if (str == NULL)
2758                 return TRUE;
2759         
2760         /* get end iter */
2761         end_iter = *iter;
2762         gtk_text_iter_forward_to_end (&end_iter);
2763
2764         str_casefold = g_utf8_casefold (str, -1);
2765         str_chars_n = strlen (str);
2766
2767         range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2768         range_casefold = g_utf8_casefold (range_text, -1);
2769         range_chars_n = strlen (range_casefold);
2770
2771         if (range_chars_n < str_chars_n) {
2772                 g_free (str_casefold);
2773                 g_free (range_text);
2774                 g_free (range_casefold);
2775                 return FALSE;
2776         }
2777
2778         for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2779                 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2780                 if (!g_utf8_collate (range_subtext, str_casefold)) {
2781                         gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2782                         result = TRUE;
2783                         gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2784                                                       match_start, match_end, NULL);
2785                         g_free (found_text);
2786                 }
2787                 g_free (range_subtext);
2788                 if (result)
2789                         break;
2790         }
2791         g_free (str_casefold);
2792         g_free (range_text);
2793         g_free (range_casefold);
2794
2795         return result;
2796 }
2797
2798
2799 static void 
2800 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2801                                             ModestMsgEditWindow *window)
2802 {
2803         gchar *current_search = NULL;
2804         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2805         gboolean result;
2806         GtkTextIter selection_start, selection_end;
2807         GtkTextIter match_start, match_end;
2808         gboolean continue_search = FALSE;
2809
2810         g_object_get (G_OBJECT (widget), "prefix", &current_search, NULL);
2811         if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2812                 g_free (current_search);
2813                 g_free (priv->last_search);
2814                 priv->last_search = NULL;
2815                 /* Information banner about empty search */
2816                 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2817                 return;
2818         }
2819
2820         if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2821                 continue_search = TRUE;
2822         } else {
2823                 g_free (priv->last_search);
2824                 priv->last_search = g_strdup (current_search);
2825         }
2826
2827         if (continue_search) {
2828                 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2829                 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search, 
2830                                                                    &match_start, &match_end);
2831                 if (!result)
2832                         hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2833         } else {
2834                 GtkTextIter buffer_start;
2835                 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2836                 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search, 
2837                                                                    &match_start, &match_end);
2838                 if (!result)
2839                         hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2840         }
2841
2842         /* Mark as selected the string found in search */
2843         if (result) {
2844                 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2845                 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2846         } else {
2847                 g_free (priv->last_search);
2848                 priv->last_search = NULL;
2849         }
2850         g_free (current_search);
2851 }
2852
2853 static void
2854 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2855                                            ModestMsgEditWindow *window)
2856 {
2857         GtkToggleAction *toggle;
2858         ModestWindowPrivate *parent_priv;
2859         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2860
2861         toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2862         gtk_toggle_action_set_active (toggle, FALSE);
2863 }
2864
2865
2866 static void 
2867 update_paste_dimming (ModestMsgEditWindow *window)
2868 {
2869         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2870         GtkAction *action = NULL;
2871         GtkClipboard *clipboard = NULL;
2872         GtkWidget *focused;
2873         gboolean active;
2874
2875         focused = gtk_window_get_focus (GTK_WINDOW (window));
2876
2877         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2878         active = gtk_clipboard_wait_is_text_available (clipboard);
2879
2880         if (active) {
2881                 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2882                         active = FALSE;
2883         }
2884
2885         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2886         gtk_action_set_sensitive (action, active);
2887
2888 }
2889
2890 static void  
2891 paste_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2892 {
2893         GtkWidget *focused = gtk_window_get_focus (GTK_WINDOW (editor));
2894
2895         if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2896                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_unable_to_paste_here"));
2897         else
2898                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ecoc_ib_edwin_nothing_to_paste"));
2899                 
2900 }
2901
2902 static void  
2903 copy_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2904 {
2905         hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_unable_to_copy"));
2906                 
2907 }
2908
2909
2910 static void
2911 modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
2912                                                       GdkEvent *event,
2913                                                       ModestMsgEditWindow *window)
2914 {
2915         update_paste_dimming (window);
2916 }
2917
2918 static void 
2919 update_select_all_dimming (ModestMsgEditWindow *window)
2920 {
2921         GtkWidget *focused;
2922         gboolean dimmed = FALSE;
2923         GtkAction *action;
2924         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2925
2926         focused = gtk_window_get_focus (GTK_WINDOW (window));
2927         if (GTK_IS_ENTRY (focused)) {
2928                 const gchar *current_text;
2929                 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2930                 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2931         } else if (GTK_IS_TEXT_VIEW (focused)) {
2932                 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2933                 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2934         } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2935                 dimmed = FALSE;
2936         }
2937         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2938         gtk_action_set_sensitive (action, !dimmed);
2939 }
2940
2941 static void 
2942 update_zoom_dimming (ModestMsgEditWindow *window)
2943 {
2944         GtkWidget *focused;
2945         gboolean dimmed = FALSE;
2946         GtkAction *action;
2947         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2948
2949         focused = gtk_window_get_focus (GTK_WINDOW (window));
2950         dimmed = ! WP_IS_TEXT_VIEW (focused);
2951         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2952         gtk_action_set_sensitive (action, !dimmed);
2953 }
2954
2955 static void
2956 edit_menu_activated (GtkAction *action,
2957                      gpointer userdata)
2958 {
2959         ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2960
2961         update_select_all_dimming (window);
2962 }
2963 static void
2964 view_menu_activated (GtkAction *action,
2965                      gpointer userdata)
2966 {
2967         ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2968
2969         update_zoom_dimming (window);
2970 }
2971
2972 gboolean 
2973 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
2974 {
2975         ModestMsgEditWindowPrivate *priv;
2976
2977         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2978         return priv->sent;
2979 }
2980
2981 void 
2982 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window, 
2983                                  gboolean sent)
2984 {
2985         ModestMsgEditWindowPrivate *priv;
2986
2987         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2988         priv->sent = sent;
2989 }
2990
2991