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