fc1a520a5ab971d5818f02ee25f14c67db129671
[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         gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
978
979         /* Dim at start clipboard actions */
980         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
981         gtk_action_set_sensitive (action, FALSE);
982         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
983         gtk_action_set_sensitive (action, FALSE);
984         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
985         gtk_action_set_sensitive (action, FALSE);
986
987         /* Update select all */
988         update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
989         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
990         g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
991         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
992         g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
993
994         /* set initial state of cc and bcc */
995         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
996         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
997                                       modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
998         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
999         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
1000                                       modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1001
1002         /* Setup the file format */
1003         conf = modest_runtime_get_conf ();
1004         prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1005         if (error) {
1006                 g_clear_error (&error);
1007                 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1008         } else
1009                 file_format = (prefer_formatted) ? 
1010                         MODEST_FILE_FORMAT_FORMATTED_TEXT : 
1011                         MODEST_FILE_FORMAT_PLAIN_TEXT;
1012         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1013
1014         update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1015         
1016         return (ModestWindow*) obj;
1017 }
1018
1019 static gint
1020 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1021 {
1022         GString **string_buffer = (GString **) user_data;
1023
1024         *string_buffer = g_string_append (*string_buffer, buffer);
1025    
1026         return 0;
1027 }
1028
1029 /**
1030  * @result: A new string which should be freed with g_free().
1031  */
1032 static gchar *
1033 get_formatted_data (ModestMsgEditWindow *edit_window)
1034 {
1035         ModestMsgEditWindowPrivate *priv;
1036         GString *string_buffer = g_string_new ("");
1037         
1038         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1039
1040         wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1041
1042         return g_string_free (string_buffer, FALSE);
1043                                                                         
1044 }
1045
1046 MsgData * 
1047 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1048 {
1049         MsgData *data;
1050         const gchar *account_name;
1051         ModestMsgEditWindowPrivate *priv;
1052         
1053         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1054
1055         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1056                                                                         
1057         account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1058         g_return_val_if_fail (account_name, NULL);
1059         
1060         
1061         /* don't free these (except from) */
1062         data = g_slice_new0 (MsgData);
1063         data->from    =  modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1064                                                              account_name);
1065         data->account_name = g_strdup (account_name);
1066         data->to      =  g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1067         data->cc      =  g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1068         data->bcc     =  g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1069         data->subject =  g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1070         if (priv->draft_msg) {
1071                 data->draft_msg = g_object_ref (priv->draft_msg);
1072         } else {
1073                 data->draft_msg = NULL;
1074         }
1075
1076         GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1077         GtkTextIter b, e;
1078         gtk_text_buffer_get_bounds (buf, &b, &e);
1079         data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
1080
1081         if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1082                 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1083         else
1084                 data->html_body = NULL;
1085
1086         /* deep-copy the data */
1087         GList *cursor = priv->attachments;
1088         data->attachments = NULL;
1089         while (cursor) {
1090                 if (!(TNY_IS_MIME_PART(cursor->data))) {
1091                         g_warning ("strange data in attachment list");
1092                         continue;
1093                 }
1094                 data->attachments = g_list_append (data->attachments,
1095                                                    g_object_ref (cursor->data));
1096                 cursor = g_list_next (cursor);
1097         }
1098         
1099         data->priority_flags = priv->priority_flags;
1100
1101         return data;
1102 }
1103
1104
1105 static void
1106 unref_gobject (GObject *obj, gpointer data)
1107 {
1108         if (!G_IS_OBJECT(obj))
1109                 return;
1110         g_object_unref (obj);
1111 }
1112
1113 void 
1114 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1115                                                       MsgData *data)
1116 {
1117         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1118
1119         if (!data)
1120                 return;
1121
1122         g_free (data->to);
1123         g_free (data->cc);
1124         g_free (data->bcc);
1125         g_free (data->subject);
1126         g_free (data->plain_body);
1127         g_free (data->html_body);
1128         g_free (data->account_name);
1129         
1130         if (data->draft_msg != NULL) {
1131                 g_object_unref (data->draft_msg);
1132                 data->draft_msg = NULL;
1133         }
1134         
1135         g_list_foreach (data->attachments, (GFunc)unref_gobject,  NULL);
1136         g_list_free (data->attachments);
1137         
1138         g_slice_free (MsgData, data);
1139 }
1140
1141 ModestMsgEditFormat
1142 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1143 {
1144         gboolean rich_text;
1145         ModestMsgEditWindowPrivate *priv = NULL;
1146         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1147
1148         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1149
1150         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1151         if (rich_text)
1152                 return MODEST_MSG_EDIT_FORMAT_HTML;
1153         else
1154                 return MODEST_MSG_EDIT_FORMAT_TEXT;
1155 }
1156
1157 void
1158 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1159                                    ModestMsgEditFormat format)
1160 {
1161         ModestMsgEditWindowPrivate *priv;
1162
1163         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1164         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1165
1166         switch (format) {
1167         case MODEST_MSG_EDIT_FORMAT_HTML:
1168                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1169                 break;
1170         case MODEST_MSG_EDIT_FORMAT_TEXT:
1171                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1172                 break;
1173         default:
1174                 g_return_if_reached ();
1175         }
1176 }
1177
1178 ModestMsgEditFormatState *
1179 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1180 {
1181         ModestMsgEditFormatState *format_state = NULL;
1182         ModestMsgEditWindowPrivate *priv;
1183         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1184
1185         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1186         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1187
1188         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1189
1190         format_state = g_new0 (ModestMsgEditFormatState, 1);
1191         format_state->bold = buffer_format->bold&0x1;
1192         format_state->italics = buffer_format->italic&0x1;
1193         format_state->bullet = buffer_format->bullet&0x1;
1194         format_state->color = buffer_format->color;
1195         format_state->font_size = buffer_format->font_size;
1196         format_state->font_family = wp_get_font_name (buffer_format->font);
1197         format_state->justification = buffer_format->justification;
1198         g_free (buffer_format);
1199
1200         return format_state;
1201  
1202 }
1203
1204 void
1205 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1206                                          const ModestMsgEditFormatState *format_state)
1207 {
1208         ModestMsgEditWindowPrivate *priv;
1209         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1210         WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1211         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1212         g_return_if_fail (format_state != NULL);
1213
1214         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1215         gtk_widget_grab_focus (priv->msg_body);
1216         buffer_format->bold = (format_state->bold != FALSE);
1217         buffer_format->italic = (format_state->italics != FALSE);
1218         buffer_format->color = format_state->color;
1219         buffer_format->font_size = format_state->font_size;
1220         buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1221         buffer_format->justification = format_state->justification;
1222         buffer_format->bullet = format_state->bullet;
1223
1224         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1225
1226         buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1227         buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1228         buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1229         buffer_format->cs.font_size =  (buffer_format->font_size != current_format->font_size);
1230         buffer_format->cs.font = (buffer_format->font != current_format->font);
1231         buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1232         buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1233
1234         wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1235         if (buffer_format->cs.bold) {
1236                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1237         }
1238         if (buffer_format->cs.italic) {
1239                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1240         }
1241         if (buffer_format->cs.color) {
1242                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1243         }
1244         if (buffer_format->cs.font_size) {
1245                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1246         }
1247         if (buffer_format->cs.justification) {
1248                 switch (buffer_format->justification) {
1249                 case GTK_JUSTIFY_LEFT:
1250                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1251                         break;
1252                 case GTK_JUSTIFY_CENTER:
1253                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1254                         break;
1255                 case GTK_JUSTIFY_RIGHT:
1256                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1257                         break;
1258                 default:
1259                         break;
1260                 }
1261                         
1262         }
1263         if (buffer_format->cs.font) {
1264                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1265         }
1266         if (buffer_format->cs.bullet) {
1267                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((int)buffer_format->bullet));
1268         }
1269 /*      wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1270         wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1271
1272         g_free (current_format);
1273
1274 }
1275
1276 static void
1277 toggle_action_set_active_block_notify (GtkToggleAction *action,
1278                                        gboolean value)
1279 {
1280         GSList *proxies = NULL;
1281
1282         for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1283              proxies != NULL; proxies = g_slist_next (proxies)) {
1284                 GtkWidget *widget = (GtkWidget *) proxies->data;
1285                 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1286         }
1287
1288         gtk_toggle_action_set_active (action, value);
1289
1290         for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1291              proxies != NULL; proxies = g_slist_next (proxies)) {
1292                 GtkWidget *widget = (GtkWidget *) proxies->data;
1293                 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1294         }
1295 }
1296
1297 static void
1298 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1299 {
1300         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1301         GtkAction *action;
1302         ModestWindowPrivate *parent_priv;
1303         ModestMsgEditWindowPrivate *priv;
1304         GtkWidget *new_size_menuitem;
1305         GtkWidget *new_font_menuitem;
1306         
1307         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1308         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1309
1310         if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1311                 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1312                 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1313                         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1314         } else {
1315                 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1316                 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1317                         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1318         }
1319
1320         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1321         
1322         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1323         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1324
1325         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1326         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1327
1328         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1329         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1330
1331         g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button), 
1332                                          G_CALLBACK (modest_msg_edit_window_color_button_change),
1333                                          window);
1334         hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1335         g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button), 
1336                                            G_CALLBACK (modest_msg_edit_window_color_button_change),
1337                                            window);
1338
1339         new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group, 
1340                                                       buffer_format->font_size))->data);
1341         if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1342                 GtkWidget *label;
1343                 gchar *markup;
1344
1345                 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1346                 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1347                 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1348                 g_free (markup);
1349                 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1350                                                  G_CALLBACK (modest_msg_edit_window_size_change),
1351                                                  window);
1352                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1353                 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1354                                                    G_CALLBACK (modest_msg_edit_window_size_change),
1355                                                    window);
1356         }
1357
1358         new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group, 
1359                                                       buffer_format->font))->data);
1360         if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1361                 GtkWidget *label;
1362                 gchar *markup;
1363
1364                 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1365                 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1366                 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1367                 g_free (markup);
1368                 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1369                                                  G_CALLBACK (modest_msg_edit_window_font_change),
1370                                                  window);
1371                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1372                 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1373                                                    G_CALLBACK (modest_msg_edit_window_font_change),
1374                                                    window);
1375         }
1376
1377         g_free (buffer_format);
1378
1379 }
1380
1381
1382 void
1383 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1384 {
1385         
1386         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1387         ModestMsgEditWindowPrivate *priv;
1388         GtkWidget *dialog = NULL;
1389         gint response;
1390         const GdkColor *new_color = NULL;
1391         
1392         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1393         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1394         
1395 #ifdef MODEST_HILDON_VERSION_0  
1396         dialog = hildon_color_selector_new (GTK_WINDOW (window));
1397         hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1398 #else
1399         dialog = hildon_color_chooser_new ();
1400         hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1401 #endif /*MODEST_HILDON_VERSION_0*/              
1402         g_free (buffer_format);
1403
1404         response = gtk_dialog_run (GTK_DIALOG (dialog));
1405         switch (response) {
1406         case GTK_RESPONSE_OK: {
1407 #ifdef MODEST_HILDON_VERSION_0
1408                 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1409 #else
1410                 GdkColor col;
1411                 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1412                 new_color = &col;
1413 #endif /*MODEST_HILDON_VERSION_0*/
1414         }
1415
1416         break;
1417         default:
1418                 break;
1419         }
1420         gtk_widget_destroy (dialog);
1421
1422         if (new_color != NULL)
1423                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1424
1425 }
1426
1427 void
1428 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1429 {
1430         
1431         ModestMsgEditWindowPrivate *priv;
1432         GtkWidget *dialog = NULL;
1433         gint response;
1434         GdkColor *old_color = NULL;
1435         const GdkColor *new_color = NULL;
1436         
1437         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1438         old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1439         
1440 #ifdef MODEST_HILDON_VERSION_0  
1441         dialog = hildon_color_selector_new (GTK_WINDOW (window));
1442         hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1443 #else
1444         dialog = hildon_color_chooser_new ();
1445         hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1446 #endif /*MODEST_HILDON_VERSION_9*/              
1447
1448         response = gtk_dialog_run (GTK_DIALOG (dialog));
1449         switch (response) {
1450         case GTK_RESPONSE_OK: {
1451 #ifdef MODEST_HILDON_VERSION_0
1452                 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1453 #else
1454                 GdkColor col;
1455                 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1456                 new_color = &col;
1457 #endif /*MODEST_HILDON_VERSION_0*/
1458           }
1459                 break;
1460         default:
1461                 break;
1462         }
1463         gtk_widget_destroy (dialog);
1464
1465         if (new_color != NULL)
1466                 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1467
1468 }
1469
1470
1471 void
1472 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1473 {
1474         
1475         ModestMsgEditWindowPrivate *priv;
1476         GtkWidget *dialog = NULL;
1477         gint response = 0;
1478         GSList *uris = NULL;
1479         GSList *uri_node = NULL;
1480         
1481         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1482         
1483         dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1484         gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1485         gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1486
1487         modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1488
1489         response = gtk_dialog_run (GTK_DIALOG (dialog));
1490         switch (response) {
1491         case GTK_RESPONSE_OK:
1492                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1493                 break;
1494         default:
1495                 break;
1496         }
1497         gtk_widget_destroy (dialog);
1498
1499         for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1500                 const gchar *uri;
1501                 GnomeVFSHandle *handle = NULL;
1502                 GnomeVFSResult result;
1503                 GtkTextIter position;
1504                 GtkTextMark *insert_mark;
1505
1506                 uri = (const gchar *) uri_node->data;
1507                 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1508                 if (result == GNOME_VFS_OK) {
1509                         GdkPixbufLoader *loader;
1510                         GdkPixbuf *pixbuf;
1511                         GnomeVFSFileInfo info;
1512                         gchar *filename, *basename;
1513                         TnyMimePart *mime_part;
1514                         TnyStream *stream;
1515                         gchar *content_id;
1516                         const gchar *mime_type = NULL;
1517
1518                         filename = g_filename_from_uri (uri, NULL, NULL);
1519                         if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) 
1520                             == GNOME_VFS_OK)
1521                                 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1522
1523                         mime_part = tny_platform_factory_new_mime_part
1524                                 (modest_runtime_get_platform_factory ());
1525                         stream = TNY_STREAM (tny_vfs_stream_new (handle));
1526                         
1527                         tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1528                         
1529                         content_id = g_strdup_printf ("%d", priv->last_cid);
1530                         tny_mime_part_set_content_id (mime_part, content_id);
1531                         g_free (content_id);
1532                         priv->last_cid++;
1533                         
1534                         basename = g_path_get_basename (filename);
1535                         tny_mime_part_set_filename (mime_part, basename);
1536                         g_free (basename);
1537                         
1538                         priv->attachments = g_list_prepend (priv->attachments, mime_part);
1539                         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1540                                                                 mime_part);
1541                         gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1542                         gtk_widget_show_all (priv->attachments_caption);
1543                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1544                         g_free (filename);
1545
1546                         loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1547                         while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1548                                 unsigned char read_buffer[128];
1549                                 gint readed;
1550                                 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1551                                 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
1552                                         break;
1553                         }
1554                         pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1555                         g_object_ref (pixbuf);
1556                         gdk_pixbuf_loader_close (loader, NULL);
1557                         g_object_unref (loader);
1558
1559                         if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1560                                 GdkPixbuf *new_pixbuf;
1561                                 gint new_height;
1562                                 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1563                                         gdk_pixbuf_get_width (pixbuf);
1564                                 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1565                                 g_object_unref (pixbuf);
1566                                 pixbuf = new_pixbuf;
1567                         }
1568
1569                         if (pixbuf != NULL) {
1570                                 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1571                                 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1572                                 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1573                         } 
1574                 }
1575         }
1576
1577
1578 }
1579
1580 void
1581 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
1582 {
1583         
1584         ModestMsgEditWindowPrivate *priv;
1585         GtkWidget *dialog = NULL;
1586         gint response = 0;
1587         GSList *uris = NULL;
1588         GSList *uri_node;
1589         
1590         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1591         
1592         dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1593         gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1594         gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1595
1596         response = gtk_dialog_run (GTK_DIALOG (dialog));
1597         switch (response) {
1598         case GTK_RESPONSE_OK:
1599                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1600                 break;
1601         default:
1602                 break;
1603         }
1604         gtk_widget_destroy (dialog);
1605
1606         for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1607                 const gchar *uri;
1608                 GnomeVFSHandle *handle = NULL;
1609                 GnomeVFSResult result;
1610
1611                 uri = (const gchar *) uri_node->data;
1612                 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1613                 if (result == GNOME_VFS_OK) {
1614                         TnyMimePart *mime_part;
1615                         TnyStream *stream;
1616                         const gchar *mime_type = NULL;
1617                         gchar *basename;
1618                         gchar *filename;
1619                         gchar *content_id;
1620                         GnomeVFSFileInfo info;
1621
1622                         filename = g_filename_from_uri (uri, NULL, NULL);
1623                         
1624                         if (gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE) == GNOME_VFS_OK)
1625                                 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1626                         mime_part = tny_platform_factory_new_mime_part
1627                                 (modest_runtime_get_platform_factory ());
1628                         stream = TNY_STREAM (tny_vfs_stream_new (handle));
1629                         
1630                         tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1631                         
1632                         content_id = g_strdup_printf ("%d", priv->last_cid);
1633                         tny_mime_part_set_content_id (mime_part, content_id);
1634                         g_free (content_id);
1635                         priv->last_cid++;
1636                         
1637                         basename = g_path_get_basename (filename);
1638                         tny_mime_part_set_filename (mime_part, basename);
1639                         g_free (basename);
1640                         
1641                         priv->attachments = g_list_prepend (priv->attachments, mime_part);
1642                         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1643                                                                 mime_part);
1644                         gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1645                         gtk_widget_show_all (priv->attachments_caption);
1646                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1647                         g_free (filename);
1648
1649                 } 
1650         }
1651         g_slist_foreach (uris, (GFunc) g_free, NULL);
1652         g_slist_free (uris);
1653 }
1654
1655 void
1656 modest_msg_edit_window_attach_file_noninteractive (
1657                 ModestMsgEditWindow *window,
1658                 const gchar *file_uri)
1659 {
1660         
1661         ModestMsgEditWindowPrivate *priv;
1662         
1663         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1664
1665         if (file_uri && strlen(file_uri)) {
1666                 gint file_id = 0;
1667                 
1668                 /* TODO: We should probably try to use only the URI,
1669                  * instead of using a filename.
1670                  */
1671                 gchar* filename = g_filename_from_uri (file_uri, NULL, NULL);
1672                 if (!filename) {
1673                         g_warning("%s: g_filename_from_uri('%s') failed.\n", __FUNCTION__, file_uri);
1674                 }
1675
1676                 file_id = g_open (filename, O_RDONLY, 0);
1677                 if (file_id != -1) {
1678                         TnyMimePart *mime_part;
1679                         TnyStream *stream;
1680                         const gchar *mime_type;
1681                         gchar *basename;
1682                         gchar *content_id;
1683 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1684                         mime_type = gnome_vfs_get_mime_type(filename);
1685 #else
1686                         mime_type = gnome_vfs_get_file_mime_type_fast (filename, NULL);
1687 #endif
1688                         mime_part = tny_platform_factory_new_mime_part
1689                                 (modest_runtime_get_platform_factory ());
1690                         stream = TNY_STREAM (tny_fs_stream_new (file_id));
1691                         
1692                         tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1693                         
1694                         content_id = g_strdup_printf ("%d", priv->last_cid);
1695                         tny_mime_part_set_content_id (mime_part, content_id);
1696                         g_free (content_id);
1697                         priv->last_cid++;
1698                         
1699                         basename = g_path_get_basename (filename);
1700                         tny_mime_part_set_filename (mime_part, basename);
1701                         g_free (basename);
1702                         
1703                         priv->attachments = g_list_prepend (priv->attachments, mime_part);
1704                         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1705                                                                 mime_part);
1706                         gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1707                         gtk_widget_show_all (priv->attachments_caption);
1708                 } else if (file_id == -1) {
1709                         close (file_id);
1710                         g_warning("file to be attached does not exist: %s", filename);
1711                 }
1712
1713                 g_free (filename);
1714         }
1715 }
1716
1717 void
1718 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1719                                           GList *att_list)
1720 {
1721         ModestMsgEditWindowPrivate *priv;
1722         gboolean clean_list = FALSE;
1723
1724         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1725         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1726
1727         if (att_list == NULL) {
1728                 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1729                 clean_list = TRUE;
1730         }
1731
1732         if (att_list == NULL) {
1733                 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1734         } else {
1735                 GtkWidget *confirmation_dialog = NULL;
1736                 gboolean dialog_response;
1737                 GList *node;
1738                 gchar *message = NULL;
1739                 const gchar *filename = NULL;
1740
1741                 if (att_list->next == NULL) {
1742                         filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1743                 } else {
1744                         filename = "";
1745                 }
1746                 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1747                                                     att_list->next == NULL), filename);
1748                 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1749                 g_free (message);
1750                 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1751                 gtk_widget_destroy (confirmation_dialog);
1752                 if (!dialog_response) {
1753                         if (clean_list)
1754                                 g_list_free (att_list);
1755                         return;
1756                 }
1757                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1758
1759                 for (node = att_list; node != NULL; node = g_list_next (node)) {
1760                         TnyMimePart *mime_part = (TnyMimePart *) node->data;
1761                         const gchar *att_id;
1762                         priv->attachments = g_list_remove (priv->attachments, mime_part);
1763
1764                         modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1765                                                                    mime_part);
1766                         if (priv->attachments == NULL)
1767                                 gtk_widget_hide (priv->attachments_caption);
1768                         att_id = tny_mime_part_get_content_id (mime_part);
1769                         if (att_id != NULL)
1770                                 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1771                                                                  att_id);
1772                         g_object_unref (mime_part);
1773                         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1774                 }
1775         }
1776
1777         if (clean_list)
1778                 g_list_free (att_list);
1779 }
1780
1781 static void
1782 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1783                                             gpointer userdata)
1784 {
1785         ModestMsgEditWindowPrivate *priv;
1786         GdkColor *new_color;
1787         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1788         
1789 #ifdef MODEST_HAVE_HILDON0_WIDGETS      
1790         new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1791 #else 
1792         GdkColor col;
1793         hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1794         new_color = &col;
1795 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1796
1797         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1798         
1799         gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1800
1801 }
1802
1803 static void
1804 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1805                                     gpointer userdata)
1806 {
1807         ModestMsgEditWindowPrivate *priv;
1808         gint new_size_index;
1809         ModestMsgEditWindow *window;
1810         GtkWidget *label;
1811         
1812         window = MODEST_MSG_EDIT_WINDOW (userdata);
1813         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1814         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1815
1816         if (gtk_check_menu_item_get_active (menu_item)) {
1817                 gchar *markup;
1818                 WPTextBufferFormat format;
1819
1820                 memset (&format, 0, sizeof (format));
1821                 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1822
1823                 label = gtk_bin_get_child (GTK_BIN (menu_item));
1824                 
1825                 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1826                 format.cs.font_size = TRUE;
1827                 format.cs.text_position = TRUE;
1828                 format.cs.font = TRUE;
1829                 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1830 /*              wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1831
1832                 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1833                                                    (gpointer) wp_get_font_size_index (new_size_index, 12)))
1834                         wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1835                 
1836                 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1837                 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1838                 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1839                 g_free (markup);
1840         }
1841 }
1842
1843 static void
1844 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1845                                     gpointer userdata)
1846 {
1847         ModestMsgEditWindowPrivate *priv;
1848         gint new_font_index;
1849         ModestMsgEditWindow *window;
1850         GtkWidget *label;
1851         
1852         window = MODEST_MSG_EDIT_WINDOW (userdata);
1853         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1854         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1855
1856         if (gtk_check_menu_item_get_active (menu_item)) {
1857                 gchar *markup;
1858
1859                 label = gtk_bin_get_child (GTK_BIN (menu_item));
1860                 
1861                 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1862
1863                 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, 
1864                                                    (gpointer) new_font_index))
1865                         wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1866                 
1867                 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1868                     markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1869                 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1870                 g_free (markup);
1871         }
1872 }
1873
1874 static void
1875 modest_msg_edit_window_set_zoom (ModestWindow *window,
1876                                  gdouble zoom)
1877 {
1878         ModestMsgEditWindowPrivate *priv;
1879         ModestWindowPrivate *parent_priv;
1880         GtkRadioAction *zoom_radio_action;
1881      
1882         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1883
1884         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1885         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1886         priv->zoom_level = zoom;
1887         wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
1888
1889         /* Zoom level menu options should be updated with the current zoom level */
1890         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1891         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1892                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1893 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1894         /* FIXME: Not availible before Gtk 2.10 */
1895 #else
1896         gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
1897 #endif
1898 }
1899
1900 static gdouble
1901 modest_msg_edit_window_get_zoom (ModestWindow *window)
1902 {
1903         ModestMsgEditWindowPrivate *priv;
1904      
1905         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1906
1907         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1908         return priv->zoom_level;
1909 }
1910
1911 static gboolean
1912 zoom_allowed (ModestMsgEditWindow *window)
1913 {
1914         GtkWidget *focus;
1915
1916         focus = gtk_window_get_focus (GTK_WINDOW (window));
1917         return (focus != NULL && WP_IS_TEXT_VIEW (focus));
1918 }
1919
1920 static gboolean
1921 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1922 {
1923         ModestWindowPrivate *parent_priv;
1924         GtkRadioAction *zoom_radio_action;
1925         GSList *group, *node;
1926
1927         /* First we check if the text view is focused. If not, zooming is not allowed */
1928         if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1929                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1930                 return FALSE;
1931         }
1932
1933         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1934         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1935                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1936
1937         group = gtk_radio_action_get_group (zoom_radio_action);
1938
1939         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1940                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
1941                 return FALSE;
1942         }
1943
1944         for (node = group; node != NULL; node = g_slist_next (node)) {
1945                 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1946                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1947                         return TRUE;
1948                 }
1949         }
1950         return FALSE;
1951 }
1952
1953 static gboolean
1954 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1955 {
1956         ModestWindowPrivate *parent_priv;
1957         GtkRadioAction *zoom_radio_action;
1958         GSList *group, *node;
1959
1960         /* First we check if the text view is focused. If not, zooming is not allowed */
1961         if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
1962                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
1963                 return FALSE;
1964         }
1965
1966         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1967         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1968                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1969
1970         group = gtk_radio_action_get_group (zoom_radio_action);
1971
1972         for (node = group; node != NULL; node = g_slist_next (node)) {
1973                 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1974                         if (node->next != NULL) {
1975                                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1976                                 return TRUE;
1977                         } else
1978                                 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
1979                         break;
1980                 }
1981         }
1982         return FALSE;
1983 }
1984
1985 static gboolean
1986 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1987 {
1988         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1989                 ModestWindowPrivate *parent_priv;
1990                 ModestWindowMgr *mgr;
1991                 gboolean is_fullscreen;
1992                 GtkAction *fs_toggle_action;
1993                 gboolean active;
1994
1995                 mgr = modest_runtime_get_window_mgr ();
1996                 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1997
1998                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1999                 
2000                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2001                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2002                 if (is_fullscreen != active)
2003                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2004         }
2005
2006         return FALSE;
2007
2008 }
2009
2010 void
2011 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2012 {
2013         ModestWindowPrivate *parent_priv;
2014         GtkAction *fs_toggle_action;
2015         gboolean active;
2016
2017         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2018
2019         fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2020         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2021         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2022 }
2023
2024 void
2025 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window, 
2026                                 gboolean show)
2027 {
2028         ModestMsgEditWindowPrivate *priv = NULL;
2029         const gchar *recipients;
2030         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2031
2032         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2033         gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2034         recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field));
2035         if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2036                 gtk_widget_show (priv->cc_caption);
2037         else
2038                 gtk_widget_hide (priv->cc_caption);
2039         modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2040 }
2041
2042 void
2043 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window, 
2044                                  gboolean show)
2045 {
2046         ModestMsgEditWindowPrivate *priv = NULL;
2047         const gchar *recipients;
2048         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2049
2050         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2051         gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2052         recipients = modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field));
2053         if ((show) || ((recipients != NULL) && (recipients[0] != '\0')))
2054                 gtk_widget_show (priv->bcc_caption);
2055         else
2056                 gtk_widget_hide (priv->bcc_caption);
2057         modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2058 }
2059
2060 static void
2061 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2062                                          ModestRecptEditor *editor)
2063 {
2064         ModestMsgEditWindowPrivate *priv;
2065
2066         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2067         g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2068         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2069
2070         if (editor == NULL) {
2071                 GtkWidget *view_focus;
2072                 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2073
2074                 /* This code should be kept in sync with ModestRecptEditor. The
2075                    textview inside the recpt editor is the one that really gets the
2076                    focus. As it's inside a scrolled window, and this one inside the
2077                    hbox recpt editor inherits from, we'll need to go up in the 
2078                    hierarchy to know if the text view is part of the recpt editor
2079                    or if it's a different text entry */
2080
2081                 if (gtk_widget_get_parent (view_focus)) {
2082                         GtkWidget *first_parent;
2083
2084                         first_parent = gtk_widget_get_parent (view_focus);
2085                         if (gtk_widget_get_parent (first_parent) && 
2086                             MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2087                                 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2088                         }
2089                 }
2090
2091                 if (editor == NULL)
2092                         editor = MODEST_RECPT_EDITOR (priv->to_field);
2093
2094         }
2095
2096         modest_address_book_select_addresses (editor);
2097
2098 }
2099
2100 void
2101 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2102 {
2103         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2104
2105         modest_msg_edit_window_open_addressbook (window, NULL);
2106 }
2107
2108 static void
2109 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2110                                      gboolean show_toolbar)
2111 {
2112         ModestWindowPrivate *parent_priv;
2113         
2114         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2115         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2116
2117         /* FIXME: we can not just use the code of
2118            modest_msg_edit_window_setup_toolbar because it has a
2119            mixture of both initialization and creation code. */
2120
2121         if (show_toolbar)
2122                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2123         else
2124                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2125 }
2126
2127 void
2128 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2129                                            TnyHeaderFlags priority_flags)
2130 {
2131         ModestMsgEditWindowPrivate *priv;
2132         ModestWindowPrivate *parent_priv;
2133
2134         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2135
2136         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2137         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2138         priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2139
2140         if (priv->priority_flags != priority_flags) {
2141                 GtkAction *priority_action = NULL;
2142
2143                 priv->priority_flags = priority_flags;
2144
2145                 switch (priority_flags) {
2146                 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2147                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2148                         gtk_widget_show (priv->priority_icon);
2149                         priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
2150                                                                      "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2151                         break;
2152                 case TNY_HEADER_FLAG_LOW_PRIORITY:
2153                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2154                         gtk_widget_show (priv->priority_icon);
2155                         priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
2156                                                                      "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2157                         break;
2158                 default:
2159                         gtk_widget_hide (priv->priority_icon);
2160                         priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager, 
2161                                                                      "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2162                         break;
2163                 }
2164                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2165                 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2166         }
2167 }
2168
2169 void
2170 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2171                                         gint file_format)
2172 {
2173         ModestMsgEditWindowPrivate *priv;
2174         ModestWindowPrivate *parent_priv;
2175         gint current_format;
2176
2177         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2178
2179         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2180         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2181
2182         current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2183                 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2184
2185         if (current_format != file_format) {
2186                 switch (file_format) {
2187                 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2188                         wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2189                         break;
2190                 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2191                 {
2192                         GtkWidget *dialog;
2193                         gint response;
2194                         dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2195                         response = gtk_dialog_run (GTK_DIALOG (dialog));
2196                         gtk_widget_destroy (dialog);
2197                         if (response == GTK_RESPONSE_OK) {
2198                                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2199                         } else {
2200                                 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2201                                 toggle_action_set_active_block_notify (action, TRUE);
2202                         }
2203                 }
2204                         break;
2205                 }
2206                 update_dimmed (window);
2207         }
2208 }
2209
2210 void
2211 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2212 {
2213         GtkWidget *dialog;
2214         ModestMsgEditWindowPrivate *priv;
2215         WPTextBufferFormat oldfmt, fmt;
2216         gint old_position = 0;
2217         gint response = 0;
2218         gint position = 0;
2219         gint font_size;
2220         GdkColor *color = NULL;
2221         gboolean bold, bold_set, italic, italic_set;
2222         gboolean underline, underline_set;
2223         gboolean strikethrough, strikethrough_set;
2224         gboolean position_set;
2225         gboolean font_size_set, font_set, color_set;
2226         gchar *font_name;
2227
2228         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2229         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2230         
2231         dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2232
2233         /* First we get the currently selected font information */
2234         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2235         g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2236
2237         switch (oldfmt.text_position) {
2238         case TEXT_POSITION_NORMAL:
2239                 old_position = 0;
2240                 break;
2241         case TEXT_POSITION_SUPERSCRIPT:
2242                 old_position = 1;
2243                 break;
2244         default:
2245                 old_position = -1;
2246                 break;
2247         }
2248
2249         g_object_set (G_OBJECT (dialog),
2250                       "bold", oldfmt.bold != FALSE,
2251                       "bold-set", !oldfmt.cs.bold,
2252                       "underline", oldfmt.underline != FALSE,
2253                       "underline-set", !oldfmt.cs.underline,
2254                       "italic", oldfmt.italic != FALSE,
2255                       "italic-set", !oldfmt.cs.italic,
2256                       "strikethrough", oldfmt.strikethrough != FALSE,
2257                       "strikethrough-set", !oldfmt.cs.strikethrough,
2258                       "color", &oldfmt.color,
2259                       "color-set", !oldfmt.cs.color,
2260                       "size", wp_font_size[oldfmt.font_size],
2261                       "size-set", !oldfmt.cs.font_size,
2262                       "position", old_position,
2263                       "position-set", !oldfmt.cs.text_position,
2264                       "family", wp_get_font_name (oldfmt.font),
2265                       "family-set", !oldfmt.cs.font,
2266                       NULL);
2267
2268         gtk_widget_show_all (dialog);
2269         response = gtk_dialog_run (GTK_DIALOG (dialog));
2270         if (response == GTK_RESPONSE_OK) {
2271
2272                 g_object_get( dialog,
2273                               "bold", &bold,
2274                               "bold-set", &bold_set,
2275                               "underline", &underline,
2276                               "underline-set", &underline_set,
2277                               "italic", &italic,
2278                               "italic-set", &italic_set,
2279                               "strikethrough", &strikethrough,
2280                               "strikethrough-set", &strikethrough_set,
2281                               "color", &color,
2282                               "color-set", &color_set,
2283                               "size", &font_size,
2284                               "size-set", &font_size_set,
2285                               "family", &font_name,
2286                               "family-set", &font_set,
2287                               "position", &position,
2288                               "position-set", &position_set,
2289                               NULL );
2290                 
2291         }       
2292
2293         if (response == GTK_RESPONSE_OK) {
2294                 memset(&fmt, 0, sizeof(fmt));
2295                 if (bold_set) {
2296                         fmt.bold = bold;
2297                         fmt.cs.bold = TRUE;
2298                 }
2299                 if (italic_set) {
2300                         fmt.italic = italic;
2301                         fmt.cs.italic = TRUE;
2302                 }
2303                 if (underline_set) {
2304                         fmt.underline = underline;
2305                         fmt.cs.underline = TRUE;
2306                 }
2307                 if (strikethrough_set) {
2308                         fmt.strikethrough = strikethrough;
2309                         fmt.cs.strikethrough = TRUE;
2310                 }
2311                 if (position_set) {
2312                         fmt.text_position =
2313                                 ( position == 0 )
2314                                 ? TEXT_POSITION_NORMAL
2315                                 : ( ( position == 1 )
2316                                     ? TEXT_POSITION_SUPERSCRIPT
2317                                     : TEXT_POSITION_SUBSCRIPT );
2318                         fmt.cs.text_position = TRUE;
2319                 }
2320                 if (color_set) {
2321                         fmt.color = *color;
2322                         fmt.cs.color = TRUE;
2323                 }
2324                 if (font_set) {
2325                         fmt.font = wp_get_font_index(font_name,
2326                                                      DEFAULT_FONT);
2327                         fmt.cs.font = TRUE;
2328                 }
2329                 g_free(font_name);
2330                 if (font_size_set) {
2331                         fmt.font_size = wp_get_font_size_index(
2332                                 font_size, DEFAULT_FONT_SIZE);
2333                         fmt.cs.font_size = TRUE;
2334                 }
2335                 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2336         }
2337         gtk_widget_destroy (dialog);
2338         
2339         gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2340 }
2341
2342 void
2343 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2344 {
2345         ModestMsgEditWindowPrivate *priv;
2346
2347         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2348         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2349         
2350         wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2351
2352         update_dimmed (window);
2353
2354 }
2355
2356 void
2357 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2358 {
2359         ModestMsgEditWindowPrivate *priv;
2360
2361         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2362         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2363         
2364         wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2365
2366         update_dimmed (window);
2367
2368 }
2369
2370 static void
2371 update_dimmed (ModestMsgEditWindow *window)
2372 {
2373         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2374         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2375         GtkAction *action;
2376         GtkWidget *widget;
2377         gboolean rich_text;
2378         gboolean editor_focused;
2379
2380         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2381         editor_focused = gtk_widget_is_focus (priv->msg_body);
2382
2383         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2384         gtk_action_set_sensitive (action, rich_text && editor_focused);
2385         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2386         gtk_action_set_sensitive (action, rich_text && editor_focused);
2387         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2388         gtk_action_set_sensitive (action, rich_text && editor_focused);
2389         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2390         gtk_action_set_sensitive (action, rich_text && editor_focused);
2391         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2392         gtk_action_set_sensitive (action, rich_text && editor_focused);
2393         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2394         gtk_action_set_sensitive (action, rich_text && editor_focused);
2395         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2396         gtk_action_set_sensitive (action, rich_text && editor_focused);
2397         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2398         gtk_action_set_sensitive (action, rich_text && editor_focused);
2399         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2400         gtk_action_set_sensitive (action, rich_text && editor_focused);
2401         widget = priv->font_color_button;
2402         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2403         widget = priv->font_size_toolitem;
2404         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2405         widget = priv->font_face_toolitem;
2406         gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2407 }
2408
2409 static void
2410 setup_insensitive_handlers (ModestMsgEditWindow *window)
2411 {
2412         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2413         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2414         GtkWidget *widget;
2415
2416         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2417         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2418         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2419         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2420         widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2421         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2422         widget = priv->font_color_button;
2423         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2424         widget = priv->font_size_toolitem;
2425         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2426         widget = priv->font_face_toolitem;
2427         g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2428
2429 }
2430
2431 static void  
2432 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2433 {
2434         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2435         GtkAction *action;
2436
2437         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2438         gtk_action_set_sensitive (action, can_undo);
2439 }
2440
2441 static void  
2442 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2443 {
2444         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2445         GtkAction *action;
2446
2447         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2448         gtk_action_set_sensitive (action, can_redo);
2449 }
2450
2451 static void
2452 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2453 {
2454         GtkTextIter iter;
2455         GtkTextIter match_start, match_end;
2456
2457         if (image_id == NULL)
2458                 return;
2459
2460         gtk_text_buffer_get_start_iter (buffer, &iter);
2461
2462         while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2463                 GSList *tags = gtk_text_iter_get_tags (&match_start);
2464                 GSList *node;
2465                 for (node = tags; node != NULL; node = g_slist_next (node)) {
2466                         GtkTextTag *tag = (GtkTextTag *) node->data;
2467                         if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2468                                 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2469                                 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2470                                         gint offset;
2471                                         offset = gtk_text_iter_get_offset (&match_start);
2472                                         gtk_text_buffer_delete (buffer, &match_start, &match_end);
2473                                         gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2474                                 }
2475                         }
2476                 }
2477                 gtk_text_iter_forward_char (&iter);
2478         }
2479 }
2480
2481 static void
2482 text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, gpointer userdata)
2483 {
2484         ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
2485         GtkTextIter real_start, real_end;
2486         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2487
2488         if (gtk_text_iter_compare (start, end) > 0) {
2489                 real_start = *end;
2490                 real_end = *start;
2491         } else {
2492                 real_start = *start;
2493                 real_end = *end;
2494         }
2495         do {
2496                 GSList *tags = gtk_text_iter_get_tags (&real_start);
2497                 GSList *node;
2498                 for (node = tags; node != NULL; node = g_slist_next (node)) {
2499                         GtkTextTag *tag = (GtkTextTag *) node->data;
2500                         if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2501                                 gchar *image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2502
2503                                 modest_attachments_view_remove_attachment_by_id (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2504                                                                                  image_id);
2505                                 gtk_text_buffer_remove_tag (buffer, tag, start, end);
2506                         }
2507                 }
2508         } while (gtk_text_iter_forward_char (&real_start)&&
2509                  (gtk_text_iter_compare (&real_start, &real_end)<=0));
2510 }
2511
2512 static gboolean
2513 msg_body_focus (GtkWidget *focus,
2514                 GdkEventFocus *event,
2515                 gpointer userdata)
2516 {
2517         
2518         update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2519         return FALSE;
2520 }
2521
2522 static void
2523 recpt_field_changed (GtkTextBuffer *buffer,
2524                   ModestMsgEditWindow *editor)
2525 {
2526         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2527         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2528         GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2529         gboolean dim = FALSE;
2530         GtkAction *action;
2531
2532         to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2533         cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2534         bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2535         
2536         dim = ((gtk_text_buffer_get_char_count (to_buffer) + 
2537                 gtk_text_buffer_get_char_count (cc_buffer) +
2538                 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2539                         
2540         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2541         gtk_action_set_sensitive (action, !dim);
2542         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2543         gtk_action_set_sensitive (action, !dim);
2544 }
2545
2546 static void  
2547 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2548 {
2549         hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2550 }
2551
2552 static void
2553 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2554 {
2555         gboolean rich_text, editor_focused;
2556
2557         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2558         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2559         editor_focused = gtk_widget_is_focus (priv->msg_body);
2560
2561         if (!rich_text)
2562                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2563         else if (!editor_focused)
2564                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2565 }
2566
2567 static void
2568 reset_modified (ModestMsgEditWindow *editor)
2569 {
2570         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2571         GtkTextBuffer *buffer;
2572
2573         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2574         gtk_text_buffer_set_modified (buffer, FALSE);
2575         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2576         gtk_text_buffer_set_modified (buffer, FALSE);
2577         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2578         gtk_text_buffer_set_modified (buffer, FALSE);
2579         gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2580 }
2581
2582 gboolean
2583 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2584 {
2585         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2586         GtkTextBuffer *buffer;
2587
2588         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2589         if (gtk_text_buffer_get_modified (buffer))
2590                 return TRUE;
2591         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2592         if (gtk_text_buffer_get_modified (buffer))
2593                 return TRUE;
2594         buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2595         if (gtk_text_buffer_get_modified (buffer))
2596                 return TRUE;
2597         if (gtk_text_buffer_get_modified (priv->text_buffer))
2598                 return TRUE;
2599
2600         return FALSE;
2601 }
2602
2603 gboolean
2604 modest_msg_edit_window_check_names (ModestMsgEditWindow *window)
2605 {
2606         ModestMsgEditWindowPrivate *priv = NULL;
2607
2608         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2609         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2610
2611         /* check if there's no recipient added */
2612         if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2613             (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2614             (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2615                 /* no recipient contents, then select contacts */
2616                 modest_msg_edit_window_open_addressbook (window, NULL);
2617                 return FALSE;
2618         }
2619
2620         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field)))
2621                 return FALSE;
2622         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field)))
2623                 return FALSE;
2624         if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field)))
2625                 return FALSE;
2626
2627         modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2628
2629         return TRUE;
2630
2631 }
2632
2633 static void
2634 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2635                                                ModestMsgEditWindow *window)
2636 {
2637         modest_msg_edit_window_attach_file (window);
2638 }
2639
2640 static void
2641 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2642                                                GdkEvent *event,
2643                                                ModestMsgEditWindow *window)
2644 {
2645         ModestWindowPrivate *parent_priv;
2646         ModestMsgEditWindowPrivate *priv;
2647         GtkAction *action;
2648         gboolean has_selection;
2649         GtkWidget *focused;
2650         GList *selected_attachments = NULL;
2651         gint n_att_selected = 0;
2652
2653         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2654         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2655         has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
2656         focused = gtk_window_get_focus (GTK_WINDOW (window));
2657
2658         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
2659         gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2660         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
2661         gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
2662
2663         selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2664         n_att_selected = g_list_length (selected_attachments);
2665         g_list_free (selected_attachments);
2666
2667         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2668         gtk_action_set_sensitive (action, n_att_selected == 1);
2669         
2670         update_paste_dimming (window);
2671 }
2672
2673 static void 
2674 update_window_title (ModestMsgEditWindow *window)
2675 {
2676         ModestMsgEditWindowPrivate *priv = NULL;
2677         const gchar *subject;
2678
2679         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2680         subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2681         if (subject == NULL || subject[0] == '\0')
2682                 subject = _("mail_va_new_email");
2683
2684         gtk_window_set_title (GTK_WINDOW (window), subject);
2685
2686 }
2687
2688 static void  
2689 subject_field_changed (GtkEditable *editable, 
2690                        ModestMsgEditWindow *window)
2691 {
2692         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2693         update_window_title (window);
2694         gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2695 }
2696
2697 void
2698 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2699                                             gboolean show)
2700 {
2701         ModestMsgEditWindowPrivate *priv = NULL;
2702
2703         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2704         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2705
2706         gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2707         if (show) {
2708                 gtk_widget_show_all (priv->find_toolbar);
2709                 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2710         } else {
2711                 gtk_widget_hide_all (priv->find_toolbar);
2712                 gtk_widget_grab_focus (priv->msg_body);
2713         }
2714     
2715 }
2716
2717 static gboolean 
2718 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2719                                           const gchar *str,
2720                                           GtkTextIter *match_start,
2721                                           GtkTextIter *match_end)
2722 {
2723         GtkTextIter end_iter;
2724         gchar *str_casefold;
2725         gint str_chars_n;
2726         gchar *range_text;
2727         gchar *range_casefold;
2728         gint offset;
2729         gint range_chars_n;
2730         gboolean result = FALSE;
2731
2732         if (str == NULL)
2733                 return TRUE;
2734         
2735         /* get end iter */
2736         end_iter = *iter;
2737         gtk_text_iter_forward_to_end (&end_iter);
2738
2739         str_casefold = g_utf8_casefold (str, -1);
2740         str_chars_n = strlen (str);
2741
2742         range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2743         range_casefold = g_utf8_casefold (range_text, -1);
2744         range_chars_n = strlen (range_casefold);
2745
2746         if (range_chars_n < str_chars_n) {
2747                 g_free (str_casefold);
2748                 g_free (range_text);
2749                 g_free (range_casefold);
2750                 return FALSE;
2751         }
2752
2753         for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2754                 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2755                 if (!g_utf8_collate (range_subtext, str_casefold)) {
2756                         gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2757                         result = TRUE;
2758                         gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2759                                                       match_start, match_end, NULL);
2760                         g_free (found_text);
2761                 }
2762                 g_free (range_subtext);
2763                 if (result)
2764                         break;
2765         }
2766         g_free (str_casefold);
2767         g_free (range_text);
2768         g_free (range_casefold);
2769
2770         return result;
2771 }
2772
2773
2774 static void 
2775 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2776                                             ModestMsgEditWindow *window)
2777 {
2778         gchar *current_search = NULL;
2779         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2780         gboolean result;
2781         GtkTextIter selection_start, selection_end;
2782         GtkTextIter match_start, match_end;
2783         gboolean continue_search = FALSE;
2784
2785         g_object_get (G_OBJECT (widget), "prefix", &current_search, NULL);
2786         if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2787                 g_free (current_search);
2788                 g_free (priv->last_search);
2789                 priv->last_search = NULL;
2790                 /* Information banner about empty search */
2791                 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2792                 return;
2793         }
2794
2795         if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2796                 continue_search = TRUE;
2797         } else {
2798                 g_free (priv->last_search);
2799                 priv->last_search = g_strdup (current_search);
2800         }
2801
2802         if (continue_search) {
2803                 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2804                 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search, 
2805                                                                    &match_start, &match_end);
2806                 if (!result)
2807                         hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2808         } else {
2809                 GtkTextIter buffer_start;
2810                 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2811                 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search, 
2812                                                                    &match_start, &match_end);
2813                 if (!result)
2814                         hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
2815         }
2816
2817         /* Mark as selected the string found in search */
2818         if (result) {
2819                 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
2820                 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
2821         } else {
2822                 g_free (priv->last_search);
2823                 priv->last_search = NULL;
2824         }
2825         g_free (current_search);
2826 }
2827
2828 static void
2829 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
2830                                            ModestMsgEditWindow *window)
2831 {
2832         GtkToggleAction *toggle;
2833         ModestWindowPrivate *parent_priv;
2834         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2835
2836         toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
2837         gtk_toggle_action_set_active (toggle, FALSE);
2838 }
2839
2840
2841 static void 
2842 update_paste_dimming (ModestMsgEditWindow *window)
2843 {
2844         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2845         GtkAction *action = NULL;
2846         GtkClipboard *clipboard = NULL;
2847         GtkWidget *focused;
2848         gboolean active;
2849
2850         focused = gtk_window_get_focus (GTK_WINDOW (window));
2851
2852         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2853         active = gtk_clipboard_wait_is_text_available (clipboard);
2854
2855         if (active) {
2856                 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
2857                         active = FALSE;
2858         }
2859
2860         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
2861         gtk_action_set_sensitive (action, active);
2862
2863 }
2864
2865
2866 static void
2867 modest_msg_edit_window_system_clipboard_owner_change (GtkClipboard *clipboard,
2868                                                       GdkEvent *event,
2869                                                       ModestMsgEditWindow *window)
2870 {
2871         update_paste_dimming (window);
2872 }
2873
2874 static void 
2875 update_select_all_dimming (ModestMsgEditWindow *window)
2876 {
2877         GtkWidget *focused;
2878         gboolean dimmed = FALSE;
2879         GtkAction *action;
2880         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2881
2882         focused = gtk_window_get_focus (GTK_WINDOW (window));
2883         if (GTK_IS_ENTRY (focused)) {
2884                 const gchar *current_text;
2885                 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
2886                 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
2887         } else if (GTK_IS_TEXT_VIEW (focused)) {
2888                 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
2889                 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
2890         } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
2891                 dimmed = FALSE;
2892         }
2893         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
2894         gtk_action_set_sensitive (action, !dimmed);
2895 }
2896
2897 static void 
2898 update_zoom_dimming (ModestMsgEditWindow *window)
2899 {
2900         GtkWidget *focused;
2901         gboolean dimmed = FALSE;
2902         GtkAction *action;
2903         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2904
2905         focused = gtk_window_get_focus (GTK_WINDOW (window));
2906         dimmed = ! WP_IS_TEXT_VIEW (focused);
2907         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
2908         gtk_action_set_sensitive (action, !dimmed);
2909 }
2910
2911 static void
2912 edit_menu_activated (GtkAction *action,
2913                      gpointer userdata)
2914 {
2915         ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2916
2917         update_select_all_dimming (window);
2918 }
2919 static void
2920 view_menu_activated (GtkAction *action,
2921                      gpointer userdata)
2922 {
2923         ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
2924
2925         update_zoom_dimming (window);
2926 }
2927
2928 gboolean 
2929 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
2930 {
2931         ModestMsgEditWindowPrivate *priv;
2932
2933         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2934         return priv->sent;
2935 }
2936
2937 void 
2938 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window, 
2939                                  gboolean sent)
2940 {
2941         ModestMsgEditWindowPrivate *priv;
2942
2943         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
2944         priv->sent = sent;
2945 }
2946
2947
2948 void            
2949 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
2950                                   TnyMsg *draft)
2951 {
2952         ModestMsgEditWindowPrivate *priv;
2953         TnyHeader *header = NULL;
2954
2955         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2956         g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
2957
2958         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2959         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
2960
2961         if (priv->draft_msg != NULL) {
2962                 header = tny_msg_get_header (priv->draft_msg);
2963                 if (TNY_IS_HEADER (header)) {
2964                         modest_window_mgr_unregister_header (mgr, header);
2965                 }
2966                 g_object_unref (priv->draft_msg);
2967         }
2968
2969         if (draft != NULL) {
2970                 g_object_ref (draft);
2971                 header = tny_msg_get_header (draft);
2972                 if (TNY_IS_HEADER (header))
2973                         modest_window_mgr_register_header (mgr, header);
2974         }
2975
2976         priv->draft_msg = draft;
2977 }