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