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