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