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