* make the memory card Archive folder a localized one,
[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_or_mmc_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 static TnyStream* create_stream_for_uri (const gchar* uri)
1461 {
1462         if (!uri)
1463                 return NULL;
1464                 
1465         TnyStream *result = NULL;
1466
1467         GnomeVFSHandle *handle = NULL;
1468         GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1469         if (test == GNOME_VFS_OK) {
1470                 /* Create the tinymail stream: */
1471                 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1472                 result = TNY_STREAM (tny_vfs_stream_new (handle));
1473         }
1474         
1475         return result;
1476 }
1477
1478 void
1479 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1480 {
1481         
1482         ModestMsgEditWindowPrivate *priv;
1483         GtkWidget *dialog = NULL;
1484         gint response = 0;
1485         GSList *uris = NULL;
1486         GSList *uri_node = NULL;
1487         
1488         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1489         
1490         dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1491         gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1492         gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1493
1494         modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1495
1496         response = gtk_dialog_run (GTK_DIALOG (dialog));
1497         switch (response) {
1498         case GTK_RESPONSE_OK:
1499                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1500                 break;
1501         default:
1502                 break;
1503         }
1504         gtk_widget_destroy (dialog);
1505
1506         for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1507                 const gchar *uri;
1508                 GnomeVFSHandle *handle = NULL;
1509                 GnomeVFSResult result;
1510                 GtkTextIter position;
1511                 GtkTextMark *insert_mark;
1512
1513                 uri = (const gchar *) uri_node->data;
1514                 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1515                 if (result == GNOME_VFS_OK) {
1516                         GdkPixbufLoader *loader;
1517                         GdkPixbuf *pixbuf;
1518                         GnomeVFSFileInfo info;
1519                         gchar *filename, *basename, *escaped_filename;
1520                         TnyMimePart *mime_part;
1521                         gchar *content_id;
1522                         const gchar *mime_type = NULL;
1523                         GnomeVFSURI *vfs_uri;
1524
1525                         vfs_uri = gnome_vfs_uri_new (uri);
1526
1527                         escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1528                         filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1529                         g_free (escaped_filename);
1530                         gnome_vfs_uri_unref (vfs_uri);
1531
1532                         if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1533                                                      | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE) 
1534                             == GNOME_VFS_OK)
1535                                 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1536
1537                         mime_part = tny_platform_factory_new_mime_part
1538                                 (modest_runtime_get_platform_factory ());
1539                                 
1540                         TnyStream *stream = create_stream_for_uri (uri);
1541                         tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1542                         
1543                         content_id = g_strdup_printf ("%d", priv->last_cid);
1544                         tny_mime_part_set_content_id (mime_part, content_id);
1545                         g_free (content_id);
1546                         priv->last_cid++;
1547                         
1548                         basename = g_path_get_basename (filename);
1549                         tny_mime_part_set_filename (mime_part, basename);
1550                         g_free (basename);
1551                         
1552                         tny_stream_reset (TNY_STREAM (stream));
1553                         loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1554                         while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1555                                 unsigned char read_buffer[128];
1556                                 gint readed;
1557                                 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1558                                 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
1559                                         break;
1560                         }
1561                         pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1562                         g_object_ref (pixbuf);
1563                         gdk_pixbuf_loader_close (loader, NULL);
1564                         g_object_unref (loader);
1565
1566                         if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1567                                 GdkPixbuf *new_pixbuf;
1568                                 gint new_height;
1569                                 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1570                                         gdk_pixbuf_get_width (pixbuf);
1571                                 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1572                                 g_object_unref (pixbuf);
1573                                 pixbuf = new_pixbuf;
1574                         }
1575
1576                         if (pixbuf != NULL) {
1577                                 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1578                                 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1579                                 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1580                         } 
1581
1582                         priv->attachments = g_list_prepend (priv->attachments, mime_part);
1583                         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1584                                                                 mime_part);
1585                         gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1586                         gtk_widget_show_all (priv->attachments_caption);
1587                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1588                         g_free (filename);
1589
1590                 }
1591         }
1592
1593
1594 }
1595
1596 void
1597 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1598 {
1599         
1600         ModestMsgEditWindowPrivate *priv;
1601         GtkWidget *dialog = NULL;
1602         gint response = 0;
1603         GSList *uris = NULL;
1604         GSList *uri_node;
1605         
1606         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1607         
1608         dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1609         gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1610         gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1611
1612         response = gtk_dialog_run (GTK_DIALOG (dialog));
1613         switch (response) {
1614         case GTK_RESPONSE_OK:
1615                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1616                 break;
1617         default:
1618                 break;
1619         }
1620         gtk_widget_destroy (dialog);
1621
1622         for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1623                 const gchar *uri = (const gchar *) uri_node->data;
1624                 modest_msg_edit_window_attach_file_one (window, uri);
1625         }
1626         g_slist_foreach (uris, (GFunc) g_free, NULL);
1627         g_slist_free (uris);
1628 }
1629
1630 void
1631 modest_msg_edit_window_attach_file_one (
1632                 ModestMsgEditWindow *window,
1633                 const gchar *uri)
1634 {
1635         g_return_if_fail (window);
1636         g_return_if_fail (uri);
1637                 
1638         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1639         
1640         
1641         GnomeVFSHandle *handle = NULL;
1642         GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1643         if (result == GNOME_VFS_OK) {
1644                 TnyMimePart *mime_part;
1645                 TnyStream *stream;
1646                 const gchar *mime_type = NULL;
1647                 gchar *basename;
1648                 gchar *escaped_filename;
1649                 gchar *filename;
1650                 gchar *content_id;
1651                 GnomeVFSFileInfo info;
1652                 GnomeVFSURI *vfs_uri;
1653
1654                 vfs_uri = gnome_vfs_uri_new (uri);
1655                 
1656
1657                 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1658                 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1659                 g_free (escaped_filename);
1660                 gnome_vfs_uri_unref (vfs_uri);
1661                 
1662                 if (gnome_vfs_get_file_info (uri, 
1663                                              &info, 
1664                                              GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1665                                              GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1666                     == GNOME_VFS_OK)
1667                         mime_type = gnome_vfs_file_info_get_mime_type (&info);
1668                 mime_part = tny_platform_factory_new_mime_part
1669                         (modest_runtime_get_platform_factory ());
1670                 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1671                 
1672                 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1673                 
1674                 content_id = g_strdup_printf ("%d", priv->last_cid);
1675                 tny_mime_part_set_content_id (mime_part, content_id);
1676                 g_free (content_id);
1677                 priv->last_cid++;
1678                 
1679                 basename = g_path_get_basename (filename);
1680                 tny_mime_part_set_filename (mime_part, basename);
1681                 g_free (basename);
1682                 
1683                 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1684                 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1685                                                         mime_part);
1686                 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1687                 gtk_widget_show_all (priv->attachments_caption);
1688                 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1689                 g_free (filename);
1690         }
1691 }
1692
1693 void
1694 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1695                                           GList *att_list)
1696 {
1697         ModestMsgEditWindowPrivate *priv;
1698         gboolean clean_list = FALSE;
1699
1700         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1701         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1702
1703         if (att_list == NULL) {
1704                 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1705                 clean_list = TRUE;
1706         }
1707
1708         if (att_list == NULL) {
1709                 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1710         } else {
1711                 GtkWidget *confirmation_dialog = NULL;
1712                 gboolean dialog_response;
1713                 GList *node;
1714                 gchar *message = NULL;
1715                 const gchar *filename = NULL;
1716
1717                 if (att_list->next == NULL) {
1718                         filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1719                 } else {
1720                         filename = "";
1721                 }
1722                 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1723                                                     att_list->next == NULL), filename);
1724                 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1725                 g_free (message);
1726                 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1727                 gtk_widget_destroy (confirmation_dialog);
1728                 if (!dialog_response) {
1729                         if (clean_list)
1730                                 g_list_free (att_list);
1731                         return;
1732                 }
1733                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1734
1735                 for (node = att_list; node != NULL; node = g_list_next (node)) {
1736                         TnyMimePart *mime_part = (TnyMimePart *) node->data;
1737                         const gchar *att_id;
1738                         priv->attachments = g_list_remove (priv->attachments, mime_part);
1739
1740                         modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1741                                                                    mime_part);
1742                         if (priv->attachments == NULL)
1743                                 gtk_widget_hide (priv->attachments_caption);
1744                         att_id = tny_mime_part_get_content_id (mime_part);
1745                         if (att_id != NULL)
1746                                 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1747                                                                  att_id);
1748                         g_object_unref (mime_part);
1749                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1750                 }
1751         }
1752
1753         if (clean_list)
1754                 g_list_free (att_list);
1755 }
1756
1757 static void
1758 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1759                                             gpointer userdata)
1760 {
1761         ModestMsgEditWindowPrivate *priv;
1762         GdkColor *new_color;
1763         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1764         
1765 #ifdef MODEST_HAVE_HILDON0_WIDGETS      
1766         new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1767 #else 
1768         GdkColor col;
1769         hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1770         new_color = &col;
1771 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1772
1773         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1774         
1775         gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1776
1777 }
1778
1779 static void
1780 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1781                                     gpointer userdata)
1782 {
1783         ModestMsgEditWindowPrivate *priv;
1784         gint new_size_index;
1785         ModestMsgEditWindow *window;
1786         GtkWidget *label;
1787         
1788         window = MODEST_MSG_EDIT_WINDOW (userdata);
1789         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1790         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1791
1792         if (gtk_check_menu_item_get_active (menu_item)) {
1793                 gchar *markup;
1794                 WPTextBufferFormat format;
1795
1796                 memset (&format, 0, sizeof (format));
1797                 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1798
1799                 label = gtk_bin_get_child (GTK_BIN (menu_item));
1800                 
1801                 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1802                 format.cs.font_size = TRUE;
1803                 format.cs.text_position = TRUE;
1804                 format.cs.font = TRUE;
1805                 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1806 /*              wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1807
1808                 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1809                                                    (gpointer) wp_get_font_size_index (new_size_index, 12)))
1810                         wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1811                 
1812                 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1813                 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1814                 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1815                 g_free (markup);
1816         }
1817 }
1818
1819 static void
1820 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1821                                     gpointer userdata)
1822 {
1823         ModestMsgEditWindowPrivate *priv;
1824         gint new_font_index;
1825         ModestMsgEditWindow *window;
1826         GtkWidget *label;
1827         
1828         window = MODEST_MSG_EDIT_WINDOW (userdata);
1829         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1830         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1831
1832         if (gtk_check_menu_item_get_active (menu_item)) {
1833                 gchar *markup;
1834
1835                 label = gtk_bin_get_child (GTK_BIN (menu_item));
1836                 
1837                 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1838
1839                 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, 
1840                                                    (gpointer) new_font_index))
1841                         wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1842                 
1843                 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1844                     markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1845                 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1846                 g_free (markup);
1847         }
1848 }
1849
1850 static void
1851 modest_msg_edit_window_set_zoom (ModestWindow *window,
1852                                  gdouble zoom)
1853 {
1854         ModestMsgEditWindowPrivate *priv;
1855         ModestWindowPrivate *parent_priv;
1856         GtkRadioAction *zoom_radio_action;
1857      
1858         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1859
1860         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1861         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1862         priv->zoom_level = zoom;
1863         wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
1864
1865         /* Zoom level menu options should be updated with the current zoom level */
1866         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1867         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1868                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1869 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1870         /* FIXME: Not availible before Gtk 2.10 */
1871 #else
1872         gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1873 #endif
1874 }
1875
1876 static gdouble
1877 modest_msg_edit_window_get_zoom (ModestWindow *window)
1878 {
1879         ModestMsgEditWindowPrivate *priv;
1880      
1881         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1882
1883         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1884         return priv->zoom_level;
1885 }
1886
1887 static gboolean
1888 zoom_allowed (ModestMsgEditWindow *window)
1889 {
1890         GtkWidget *focus;
1891
1892         focus = gtk_window_get_focus (GTK_WINDOW (window));
1893         return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1894 }
1895
1896 static gboolean
1897 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1898 {
1899         ModestWindowPrivate *parent_priv;
1900         GtkRadioAction *zoom_radio_action;
1901         GSList *group, *node;
1902
1903         /* First we check if the text view is focused. If not, zooming is not allowed */
1904         if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1905                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1906                 return FALSE;
1907         }
1908
1909         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1910         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1911                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1912
1913         group = gtk_radio_action_get_group (zoom_radio_action);
1914
1915         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1916                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
1917                 return FALSE;
1918         }
1919
1920         for (node = group; node != NULL; node = g_slist_next (node)) {
1921                 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1922                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1923                         return TRUE;
1924                 }
1925         }
1926         return FALSE;
1927 }
1928
1929 static gboolean
1930 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1931 {
1932         ModestWindowPrivate *parent_priv;
1933         GtkRadioAction *zoom_radio_action;
1934         GSList *group, *node;
1935
1936         /* First we check if the text view is focused. If not, zooming is not allowed */
1937         if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1938                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1939                 return FALSE;
1940         }
1941
1942         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1943         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1944                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1945
1946         group = gtk_radio_action_get_group (zoom_radio_action);
1947
1948         for (node = group; node != NULL; node = g_slist_next (node)) {
1949                 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1950                         if (node->next != NULL) {
1951                                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1952                                 return TRUE;
1953                         } else
1954                                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
1955                         break;
1956                 }
1957         }
1958         return FALSE;
1959 }
1960
1961 static gboolean
1962 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1963 {
1964         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1965                 ModestWindowPrivate *parent_priv;
1966                 ModestWindowMgr *mgr;
1967                 gboolean is_fullscreen;
1968                 GtkAction *fs_toggle_action;
1969                 gboolean active;
1970
1971                 mgr = modest_runtime_get_window_mgr ();
1972                 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1973
1974                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1975                 
1976                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1977                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1978                 if (is_fullscreen != active)
1979                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1980         }
1981
1982         return FALSE;
1983
1984 }
1985
1986 void
1987 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1988 {
1989         ModestWindowPrivate *parent_priv;
1990         GtkAction *fs_toggle_action;
1991         gboolean active;
1992
1993         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1994
1995         fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1996         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1997         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1998 }
1999
2000 void
2001 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window, 
2002                                 gboolean show)
2003 {
2004         ModestMsgEditWindowPrivate *priv = NULL;
2005         const gchar *recipients;
2006         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2007
2008         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2009         gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2010         recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field));
2011         if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2012                 gtk_widget_show (priv->cc_caption);
2013         else
2014                 gtk_widget_hide (priv->cc_caption);
2015         modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2016 }
2017
2018 void
2019 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window, 
2020                                  gboolean show)
2021 {
2022         ModestMsgEditWindowPrivate *priv = NULL;
2023         const gchar *recipients;
2024         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2025
2026         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2027         gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2028         recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field));
2029         if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2030                 gtk_widget_show (priv->bcc_caption);
2031         else
2032                 gtk_widget_hide (priv->bcc_caption);
2033         modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2034 }
2035
2036 static void
2037 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2038                                          ModestRecptEditor *editor)
2039 {
2040         ModestMsgEditWindowPrivate *priv;
2041
2042         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2043         g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2044         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2045
2046         if (editor == NULL) {
2047                 GtkWidget *view_focus;
2048                 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2049
2050                 /* This code should be kept in sync with ModestRecptEditor. The
2051                    textview inside the recpt editor is the one that really gets the
2052                    focus. As it's inside a scrolled window, and this one inside the
2053                    hbox recpt editor inherits from, we'll need to go up in the 
2054                    hierarchy to know if the text view is part of the recpt editor
2055                    or if it's a different text entry */
2056
2057                 if (gtk_widget_get_parent (view_focus)) {
2058                         GtkWidget *first_parent;
2059
2060                         first_parent = gtk_widget_get_parent (view_focus);
2061                         if (gtk_widget_get_parent (first_parent) && 
2062                             MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2063                                 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2064                         }
2065                 }
2066
2067                 if (editor == NULL)
2068                         editor = MODEST_RECPT_EDITOR (priv->to_field);
2069
2070         }
2071
2072         modest_address_book_select_addresses (editor);
2073
2074 }
2075
2076 void
2077 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2078 {
2079         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2080
2081         modest_msg_edit_window_open_addressbook (window, NULL);
2082 }
2083
2084 static void
2085 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2086                                      gboolean show_toolbar)
2087 {
2088         ModestWindowPrivate *parent_priv;
2089         
2090         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2091         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2092
2093         /* FIXME: we can not just use the code of
2094            modest_msg_edit_window_setup_toolbar because it has a
2095            mixture of both initialization and creation code. */
2096
2097         if (show_toolbar)
2098                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2099         else
2100                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2101 }
2102
2103 void
2104 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2105                                            TnyHeaderFlags priority_flags)
2106 {
2107         ModestMsgEditWindowPrivate *priv;
2108         ModestWindowPrivate *parent_priv;
2109
2110         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2111
2112         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2113         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2114         priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2115
2116         if (priv->priority_flags != priority_flags) {
2117                 GtkAction *priority_action = NULL;
2118
2119                 priv->priority_flags = priority_flags;
2120
2121                 switch (priority_flags) {
2122                 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2123                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2124                         gtk_widget_show (priv->priority_icon);
2125                         priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
2126                                                                      "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2127                         break;
2128                 case TNY_HEADER_FLAG_LOW_PRIORITY:
2129                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2130                         gtk_widget_show (priv->priority_icon);
2131                         priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
2132                                                                      "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2133                         break;
2134                 default:
2135                         gtk_widget_hide (priv->priority_icon);
2136                         priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
2137                                                                      "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2138                         break;
2139                 }
2140                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2141                 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2142         }
2143 }
2144
2145 void
2146 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2147                                         gint file_format)
2148 {
2149         ModestMsgEditWindowPrivate *priv;
2150         ModestWindowPrivate *parent_priv;
2151         gint current_format;
2152
2153         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2154
2155         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2156         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2157
2158         current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2159                 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2160
2161         if (current_format != file_format) {
2162                 switch (file_format) {
2163                 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2164                         wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2165                         break;
2166                 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2167                 {
2168                         GtkWidget *dialog;
2169                         gint response;
2170                         dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2171                         response = gtk_dialog_run (GTK_DIALOG (dialog));
2172                         gtk_widget_destroy (dialog);
2173                         if (response == GTK_RESPONSE_OK) {
2174                                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2175                         } else {
2176                                 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2177                                 toggle_action_set_active_block_notify (action, TRUE);
2178                         }
2179                 }
2180                         break;
2181                 }
2182                 update_dimmed (window);
2183         }
2184 }
2185
2186 void
2187 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2188 {
2189         GtkWidget *dialog;
2190         ModestMsgEditWindowPrivate *priv;
2191         WPTextBufferFormat oldfmt, fmt;
2192         gint old_position = 0;
2193         gint response = 0;
2194         gint position = 0;
2195         gint font_size;
2196         GdkColor *color = NULL;
2197         gboolean bold, bold_set, italic, italic_set;
2198         gboolean underline, underline_set;
2199         gboolean strikethrough, strikethrough_set;
2200         gboolean position_set;
2201         gboolean font_size_set, font_set, color_set;
2202         gchar *font_name;
2203
2204         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2205         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2206         
2207         dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2208
2209         /* First we get the currently selected font information */
2210         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2211         g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2212
2213         switch (oldfmt.text_position) {
2214         case TEXT_POSITION_NORMAL:
2215                 old_position = 0;
2216                 break;
2217         case TEXT_POSITION_SUPERSCRIPT:
2218                 old_position = 1;
2219                 break;
2220         default:
2221                 old_position = -1;
2222                 break;
2223         }
2224
2225         g_object_set (G_OBJECT (dialog),
2226                       "bold", oldfmt.bold != FALSE,
2227                       "bold-set", !oldfmt.cs.bold,
2228                       "underline", oldfmt.underline != FALSE,
2229                       "underline-set", !oldfmt.cs.underline,
2230                       "italic", oldfmt.italic != FALSE,
2231                       "italic-set", !oldfmt.cs.italic,
2232                       "strikethrough", oldfmt.strikethrough != FALSE,
2233                       "strikethrough-set", !oldfmt.cs.strikethrough,
2234                       "color", &oldfmt.color,
2235                       "color-set", !oldfmt.cs.color,
2236                       "size", wp_font_size[oldfmt.font_size],
2237                       "size-set", !oldfmt.cs.font_size,
2238                       "position", old_position,
2239                       "position-set", !oldfmt.cs.text_position,
2240                       "family", wp_get_font_name (oldfmt.font),
2241                       "family-set", !oldfmt.cs.font,
2242                       NULL);
2243
2244         gtk_widget_show_all (dialog);
2245         response = gtk_dialog_run (GTK_DIALOG (dialog));
2246         if (response == GTK_RESPONSE_OK) {
2247
2248                 g_object_get( dialog,
2249                               "bold", &bold,
2250                               "bold-set", &bold_set,
2251                               "underline", &underline,
2252                               "underline-set", &underline_set,
2253                               "italic", &italic,
2254                               "italic-set", &italic_set,
2255                               "strikethrough", &strikethrough,
2256                               "strikethrough-set", &strikethrough_set,
2257                               "color", &color,
2258                               "color-set", &color_set,
2259                               "size", &font_size,
2260                               "size-set", &font_size_set,
2261                               "family", &font_name,
2262                               "family-set", &font_set,
2263                               "position", &position,
2264                               "position-set", &position_set,
2265                               NULL );
2266                 
2267         }       
2268
2269         if (response == GTK_RESPONSE_OK) {
2270                 memset(&fmt, 0, sizeof(fmt));
2271                 if (bold_set) {
2272                         fmt.bold = bold;
2273                         fmt.cs.bold = TRUE;
2274                 }
2275                 if (italic_set) {
2276                         fmt.italic = italic;
2277                         fmt.cs.italic = TRUE;
2278                 }
2279                 if (underline_set) {
2280                         fmt.underline = underline;
2281                         fmt.cs.underline = TRUE;
2282                 }
2283                 if (strikethrough_set) {
2284                         fmt.strikethrough = strikethrough;
2285                         fmt.cs.strikethrough = TRUE;
2286                 }
2287                 if (position_set) {
2288                         fmt.text_position =
2289                                 ( position == 0 )
2290                                 ? TEXT_POSITION_NORMAL
2291                                 : ( ( position == 1 )
2292                                     ? TEXT_POSITION_SUPERSCRIPT
2293                                     : TEXT_POSITION_SUBSCRIPT );
2294                         fmt.cs.text_position = TRUE;
2295                 }
2296                 if (color_set) {
2297                         fmt.color = *color;
2298                         fmt.cs.color = TRUE;
2299                 }
2300                 if (font_set) {
2301                         fmt.font = wp_get_font_index(font_name,
2302                                                      DEFAULT_FONT);
2303                         fmt.cs.font = TRUE;
2304                 }
2305                 g_free(font_name);
2306                 if (font_size_set) {
2307                         fmt.font_size = wp_get_font_size_index(
2308                                 font_size, DEFAULT_FONT_SIZE);
2309                         fmt.cs.font_size = TRUE;
2310                 }
2311                 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2312         }
2313         gtk_widget_destroy (dialog);
2314         
2315         gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2316 }
2317
2318 void
2319 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2320 {
2321         ModestMsgEditWindowPrivate *priv;
2322
2323         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2324         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2325         
2326         wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2327
2328         update_dimmed (window);
2329
2330 }
2331
2332 void
2333 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2334 {
2335         ModestMsgEditWindowPrivate *priv;
2336
2337         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2338         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2339         
2340         wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2341
2342         update_dimmed (window);
2343
2344 }
2345
2346 static void
2347 update_dimmed (ModestMsgEditWindow *window)
2348 {
2349         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2350         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2351         GtkAction *action;
2352         GtkWidget *widget;
2353         gboolean rich_text;
2354         gboolean editor_focused;
2355
2356         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2357         editor_focused = gtk_widget_is_focus (priv->msg_body);
2358
2359         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2360         gtk_action_set_sensitive (action, rich_text && editor_focused);
2361         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2362         gtk_action_set_sensitive (action, rich_text && editor_focused);
2363         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2364         gtk_action_set_sensitive (action, rich_text && editor_focused);
2365         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2366         gtk_action_set_sensitive (action, rich_text && editor_focused);
2367         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2368         gtk_action_set_sensitive (action, rich_text && editor_focused);
2369         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2370         gtk_action_set_sensitive (action, rich_text && editor_focused);
2371         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2372         gtk_action_set_sensitive (action, rich_text && editor_focused);
2373         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2374         gtk_action_set_sensitive (action, rich_text && editor_focused);
2375         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2376         gtk_action_set_sensitive (action, rich_text && editor_focused);
2377         widget = priv->font_color_button;
2378         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2379         widget = priv->font_size_toolitem;
2380         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2381         widget = priv->font_face_toolitem;
2382         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2383 }
2384
2385 static void
2386 setup_insensitive_handlers (ModestMsgEditWindow *window)
2387 {
2388         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2389         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2390         GtkWidget *widget;
2391
2392         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2393         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2394         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2395         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2396         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2397         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2398         widget = priv->font_color_button;
2399         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2400         widget = priv->font_size_toolitem;
2401         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2402         widget = priv->font_face_toolitem;
2403         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2404
2405 }
2406
2407 static void  
2408 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2409 {
2410         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2411         GtkAction *action;
2412
2413         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2414         gtk_action_set_sensitive (action, can_undo);
2415 }
2416
2417 static void  
2418 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2419 {
2420         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2421         GtkAction *action;
2422
2423         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2424         gtk_action_set_sensitive (action, can_redo);
2425 }
2426
2427 static void
2428 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2429 {
2430         GtkTextIter iter;
2431         GtkTextIter match_start, match_end;
2432
2433         if (image_id == NULL)
2434                 return;
2435
2436         gtk_text_buffer_get_start_iter (buffer, &iter);
2437
2438         while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2439                 GSList *tags = gtk_text_iter_get_tags (&match_start);
2440                 GSList *node;
2441                 for (node = tags; node != NULL; node = g_slist_next (node)) {
2442                         GtkTextTag *tag = (GtkTextTag *) node->data;
2443                         if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2444                                 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2445                                 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2446                                         gint offset;
2447                                         offset = gtk_text_iter_get_offset (&match_start);
2448                                         gtk_text_buffer_delete (buffer, &match_start, &match_end);
2449                                         gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2450                                 }
2451                         }
2452                 }
2453                 gtk_text_iter_forward_char (&iter);
2454         }
2455 }
2456
2457 static void
2458 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2459 {
2460         ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2461         GtkTextIter real_start, real_end;
2462         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2463
2464         if (gtk_text_iter_compare (start, end) > 0) {
2465                 real_start = *end;
2466                 real_end = *start;
2467         } else {
2468                 real_start = *start;
2469                 real_end = *end;
2470         }
2471         do {
2472                 GSList *tags = gtk_text_iter_get_tags (&real_start);
2473                 GSList *node;
2474                 for (node = tags; node != NULL; node = g_slist_next (node)) {
2475                         GtkTextTag *tag = (GtkTextTag *) node->data;
2476                         if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2477                                 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2478
2479                                 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2480                                                                                  image_id);
2481                                 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2482                         }
2483                 }
2484         } while (gtk_text_iter_forward_char (&real_start)&&
2485                  (gtk_text_iter_compare (&real_start, &real_end)<=0));
2486 }
2487
2488 static gboolean
2489 msg_body_focus (GtkWidget *focus,
2490                 GdkEventFocus *event,
2491                 gpointer userdata)
2492 {
2493         
2494         update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2495         return FALSE;
2496 }
2497
2498 static void
2499 recpt_field_changed (GtkTextBuffer *buffer,
2500                   ModestMsgEditWindow *editor)
2501 {
2502         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2503         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2504         GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2505         gboolean dim = FALSE;
2506         GtkAction *action;
2507
2508         to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2509         cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2510         bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2511         
2512         dim = ((gtk_text_buffer_get_char_count (to_buffer) + 
2513                 gtk_text_buffer_get_char_count (cc_buffer) +
2514                 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2515                         
2516         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2517         gtk_action_set_sensitive (action, !dim);
2518         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2519         gtk_action_set_sensitive (action, !dim);
2520 }
2521
2522 static void  
2523 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2524 {
2525         hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2526 }
2527
2528 static void
2529 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2530 {
2531         gboolean rich_text, editor_focused;
2532
2533         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2534         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2535         editor_focused = gtk_widget_is_focus (priv->msg_body);
2536
2537         if (!rich_text)
2538                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2539         else if (!editor_focused)
2540                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2541 }
2542
2543 static void
2544 reset_modified (ModestMsgEditWindow *editor)
2545 {
2546         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2547         GtkTextBuffer *buffer;
2548
2549         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2550         gtk_text_buffer_set_modified (buffer, FALSE);
2551         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2552         gtk_text_buffer_set_modified (buffer, FALSE);
2553         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2554         gtk_text_buffer_set_modified (buffer, FALSE);
2555         gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2556 }
2557
2558 gboolean
2559 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2560 {
2561         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2562         GtkTextBuffer *buffer;
2563
2564         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2565         if (gtk_text_buffer_get_modified (buffer))
2566                 return TRUE;
2567         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2568         if (gtk_text_buffer_get_modified (buffer))
2569                 return TRUE;
2570         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2571         if (gtk_text_buffer_get_modified (buffer))
2572                 return TRUE;
2573         if (gtk_text_buffer_get_modified (priv->text_buffer))
2574                 return TRUE;
2575
2576         return FALSE;
2577 }
2578
2579 gboolean
2580 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2581 {
2582         ModestMsgEditWindowPrivate *priv = NULL;
2583         
2584         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2585         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2586
2587         /* check if there's no recipient added */
2588         if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2589             (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2590             (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2591                 /* no recipient contents, then select contacts */
2592                 modest_msg_edit_window_open_addressbook (window, NULL);
2593                 return FALSE;
2594         }
2595
2596         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),  add_to_addressbook))
2597                 return FALSE;
2598         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),  add_to_addressbook))
2599                 return FALSE;
2600         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook))
2601                 return FALSE;
2602
2603         modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2604
2605         return TRUE;
2606
2607 }
2608
2609 static void
2610 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2611                                                ModestMsgEditWindow *window)
2612 {
2613         modest_msg_edit_window_offer_attach_file (window);
2614 }
2615
2616 static void
2617 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2618                                                GdkEvent *event,
2619                                                ModestMsgEditWindow *window)
2620 {
2621         ModestWindowPrivate *parent_priv;
2622         ModestMsgEditWindowPrivate *priv;
2623         GtkAction *action;
2624         gboolean has_selection;
2625         GtkWidget *focused;
2626         GList *selected_attachments = NULL;
2627         gint n_att_selected = 0;
2628
2629         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2630         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2631
2632         if (!GTK_WIDGET_VISIBLE (window))
2633                 return;
2634         has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2635         focused = gtk_window_get_focus (GTK_WINDOW (window));
2636
2637         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2638         gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2639         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2640         gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2641
2642         selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2643         n_att_selected = g_list_length (selected_attachments);
2644         g_list_free (selected_attachments);
2645
2646         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2647         gtk_action_set_sensitive (action, n_att_selected == 1);
2648         
2649         update_paste_dimming (window);
2650 }
2651
2652 static void 
2653 update_window_title (ModestMsgEditWindow *window)
2654 {
2655         ModestMsgEditWindowPrivate *priv = NULL;
2656         const gchar *subject;
2657
2658         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2659         subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2660         if (subject == NULL || subject[0] == '\0')
2661                 subject = _("mail_va_new_email");
2662
2663         gtk_window_set_title (GTK_WINDOW (window), subject);
2664
2665 }
2666
2667 static void  
2668 subject_field_changed (GtkEditable *editable, 
2669                        ModestMsgEditWindow *window)
2670 {
2671         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2672         update_window_title (window);
2673         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2674 }
2675
2676 gboolean
2677 message_is_empty (ModestMsgEditWindow *window)
2678 {
2679         ModestMsgEditWindowPrivate *priv = NULL;
2680
2681         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2682         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2683         
2684         /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2685          * so we can ignore markup.
2686          */
2687         GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2688         gint count = 0;
2689         if (buf)
2690                 count = gtk_text_buffer_get_char_count (buf);
2691                 
2692         return count == 0;
2693 }
2694         
2695 void
2696 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2697                                             gboolean show)
2698 {
2699         ModestMsgEditWindowPrivate *priv = NULL;
2700
2701         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2702         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2703
2704         gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2705
2706         /* Show a warning if there is nothing to search: */
2707         if (show && message_is_empty (window)) {
2708                 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2709                 return;
2710         }
2711
2712         if (show) {
2713                 gtk_widget_show_all (priv->find_toolbar);
2714                 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2715         } else {
2716                 gtk_widget_hide_all (priv->find_toolbar);
2717                 gtk_widget_grab_focus (priv->msg_body);
2718         }
2719     
2720 }
2721
2722 static gboolean 
2723 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2724                                           const gchar *str,
2725                                           GtkTextIter *match_start,
2726                                           GtkTextIter *match_end)
2727 {
2728         GtkTextIter end_iter;
2729         gchar *str_casefold;
2730         gint str_chars_n;
2731         gchar *range_text;
2732         gchar *range_casefold;
2733         gint offset;
2734         gint range_chars_n;
2735         gboolean result = FALSE;
2736
2737         if (str == NULL)
2738                 return TRUE;
2739         
2740         /* get end iter */
2741         end_iter = *iter;
2742         gtk_text_iter_forward_to_end (&end_iter);
2743
2744         str_casefold = g_utf8_casefold (str, -1);
2745         str_chars_n = strlen (str);
2746
2747         range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2748         range_casefold = g_utf8_casefold (range_text, -1);
2749         range_chars_n = strlen (range_casefold);
2750
2751         if (range_chars_n < str_chars_n) {
2752                 g_free (str_casefold);
2753                 g_free (range_text);
2754                 g_free (range_casefold);
2755                 return FALSE;
2756         }
2757
2758         for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2759                 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2760                 if (!g_utf8_collate (range_subtext, str_casefold)) {
2761                         gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2762                         result = TRUE;
2763                         gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2764                                                       match_start, match_end, NULL);
2765                         g_free (found_text);
2766                 }
2767                 g_free (range_subtext);
2768                 if (result)
2769                         break;
2770         }
2771         g_free (str_casefold);
2772         g_free (range_text);
2773         g_free (range_casefold);
2774
2775         return result;
2776 }
2777
2778
2779 static void 
2780 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2781                                             ModestMsgEditWindow *window)
2782 {
2783         gchar *current_search = NULL;
2784         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2785         gboolean result;
2786         GtkTextIter selection_start, selection_end;
2787         GtkTextIter match_start, match_end;
2788         gboolean continue_search = FALSE;
2789
2790         g_object_get (G_OBJECT (widget), "prefix", &current_search, NULL);
2791         if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2792                 g_free (current_search);
2793                 g_free (priv->last_search);
2794                 priv->last_search = NULL;
2795                 /* Information banner about empty search */
2796                 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2797                 return;
2798         }
2799
2800         if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2801                 continue_search = TRUE;
2802         } else {
2803                 g_free (priv->last_search);
2804                 priv->last_search = g_strdup (current_search);
2805         }
2806
2807         if (continue_search) {
2808                 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2809                 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search, 
2810                                                                    &match_start, &match_end);
2811                 if (!result)
2812                         hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2813         } else {
2814                 GtkTextIter buffer_start;
2815                 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2816                 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search, 
2817                                                                    &match_start, &match_end);
2818                 if (!result)
2819                         hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2820         }
2821
2822         /* Mark as selected the string found in search */
2823         if (result) {
2824                 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2825                 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2826         } else {
2827                 g_free (priv->last_search);
2828                 priv->last_search = NULL;
2829         }
2830         g_free (current_search);
2831 }
2832
2833 static void
2834 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2835                                            ModestMsgEditWindow *window)
2836 {
2837         GtkToggleAction *toggle;
2838         ModestWindowPrivate *parent_priv;
2839         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2840
2841         toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2842         gtk_toggle_action_set_active (toggle, FALSE);
2843 }
2844
2845
2846 static void 
2847 update_paste_dimming (ModestMsgEditWindow *window)
2848 {
2849         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2850         GtkAction *action = NULL;
2851         GtkClipboard *clipboard = NULL;
2852         GtkWidget *focused;
2853         gboolean active;
2854
2855         focused = gtk_window_get_focus (GTK_WINDOW (window));
2856
2857         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2858         active = gtk_clipboard_wait_is_text_available (clipboard);
2859
2860         if (active) {
2861                 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2862                         active = FALSE;
2863         }
2864
2865         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2866         gtk_action_set_sensitive (action, active);
2867
2868 }
2869
2870 static void 
2871 update_select_all_dimming (ModestMsgEditWindow *window)
2872 {
2873         GtkWidget *focused;
2874         gboolean dimmed = FALSE;
2875         GtkAction *action;
2876         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2877
2878         focused = gtk_window_get_focus (GTK_WINDOW (window));
2879         if (GTK_IS_ENTRY (focused)) {
2880                 const gchar *current_text;
2881                 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2882                 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2883         } else if (GTK_IS_TEXT_VIEW (focused)) {
2884                 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2885                 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2886         } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2887                 dimmed = FALSE;
2888         }
2889         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2890         gtk_action_set_sensitive (action, !dimmed);
2891 }
2892
2893 static void 
2894 update_zoom_dimming (ModestMsgEditWindow *window)
2895 {
2896         GtkWidget *focused;
2897         gboolean dimmed = FALSE;
2898         GtkAction *action;
2899         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2900
2901         focused = gtk_window_get_focus (GTK_WINDOW (window));
2902         dimmed = ! WP_IS_TEXT_VIEW (focused);
2903         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2904         gtk_action_set_sensitive (action, !dimmed);
2905 }
2906
2907 static void
2908 edit_menu_activated (GtkAction *action,
2909                      gpointer userdata)
2910 {
2911         ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2912
2913         update_select_all_dimming (window);
2914         update_paste_dimming (window);
2915 }
2916 static void
2917 view_menu_activated (GtkAction *action,
2918                      gpointer userdata)
2919 {
2920         ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2921
2922         update_zoom_dimming (window);
2923 }
2924
2925 gboolean 
2926 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
2927 {
2928         ModestMsgEditWindowPrivate *priv;
2929
2930         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2931         return priv->sent;
2932 }
2933
2934 void 
2935 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window, 
2936                                  gboolean sent)
2937 {
2938         ModestMsgEditWindowPrivate *priv;
2939
2940         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2941         priv->sent = sent;
2942 }
2943
2944
2945 void            
2946 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
2947                                   TnyMsg *draft)
2948 {
2949         ModestMsgEditWindowPrivate *priv;
2950         TnyHeader *header = NULL;
2951
2952         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2953         g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
2954
2955         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2956         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
2957
2958         if (priv->draft_msg != NULL) {
2959                 header = tny_msg_get_header (priv->draft_msg);
2960                 if (TNY_IS_HEADER (header)) {
2961                         modest_window_mgr_unregister_header (mgr, header);
2962                 }
2963                 g_object_unref (priv->draft_msg);
2964         }
2965
2966         if (draft != NULL) {
2967                 g_object_ref (draft);
2968                 header = tny_msg_get_header (draft);
2969                 if (TNY_IS_HEADER (header))
2970                         modest_window_mgr_register_header (mgr, header);
2971         }
2972
2973         priv->draft_msg = draft;
2974 }