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