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