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