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