* make maemo work even with the new libhildon (1.1)
[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
38 #include <config.h>
39
40 #include <modest-account-mgr.h>
41 #include <modest-account-mgr-helpers.h>
42
43 #include <widgets/modest-msg-edit-window.h>
44 #include <widgets/modest-combo-box.h>
45 #include <widgets/modest-recpt-editor.h>
46 #include <widgets/modest-attachments-view.h>
47
48 #include <modest-runtime.h>
49
50 #include "modest-platform.h"
51 #include "modest-icon-names.h"
52 #include "modest-widget-memory.h"
53 #include "modest-window-priv.h"
54 #include "modest-mail-operation.h"
55 #include "modest-tny-platform-factory.h"
56 #include "modest-tny-msg.h"
57 #include "modest-address-book.h"
58 #include <tny-simple-list.h>
59 #include <wptextview.h>
60 #include <wptextbuffer.h>
61 #include "modest-scroll-area.h"
62
63 #ifdef MODEST_HILDON_VERSION_0
64 #include <hildon-widgets/hildon-color-selector.h>
65 #include <hildon-widgets/hildon-color-button.h>
66 #include <hildon-widgets/hildon-banner.h>
67 #include <hildon-widgets/hildon-caption.h>
68 #include <hildon-widgets/hildon-note.h>
69 #include <hildon-widgets/hildon-file-chooser-dialog.h>
70 #include <hildon-widgets/hildon-font-selection-dialog.h>
71 #else
72 #include <hildon/hildon-file-chooser-dialog.h>
73 #include <hildon/hildon-color-chooser.h>
74 #include <hildon/hildon-banner.h>
75 #include <hildon/hildon-color-button.h>
76 #include <hildon/hildon-note.h>
77 #include <hildon/hildon-color-button.h>
78 #include <hildon/hildon-font-selection-dialog.h>
79 #include <hildon/hildon-caption.h>
80 #endif /* MODEST_HILDON_VERSION_0*/
81
82
83 #include "widgets/modest-msg-edit-window-ui.h"
84
85 #ifdef MODEST_HILDON_VERSION_0
86 #else
87
88 #endif /*MODEST_HILDON_VERSION_0 */
89
90
91
92 #define DEFAULT_FONT_SIZE 3
93 #define DEFAULT_FONT 2
94 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
95 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
96 #define DEFAULT_MAIN_VBOX_SPACING 6
97 #define SUBJECT_MAX_LENGTH 1000
98
99 static void  modest_msg_edit_window_class_init   (ModestMsgEditWindowClass *klass);
100 static void  modest_msg_edit_window_init         (ModestMsgEditWindow *obj);
101 static void  modest_msg_edit_window_finalize     (GObject *obj);
102
103 static void  text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
104 static void  text_buffer_mark_set (GtkTextBuffer *buffer, GtkTextIter *location, GtkTextMark *mark, gpointer userdata);
105 static void  text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
106 static void  modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
107                                                          gpointer userdata);
108 static void  modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
109                                                  gpointer userdata);
110 static void  modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
111                                                  gpointer userdata);
112 static void  modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
113 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget, 
114                                                            GdkEventWindowState *event, 
115                                                            gpointer userdata);
116 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
117                                                      ModestRecptEditor *editor);
118
119 /* ModestWindow methods implementation */
120 static void  modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
121 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
122 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
123 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
124 static void modest_msg_edit_window_show_toolbar   (ModestWindow *window,
125                                                    gboolean show_toolbar);
126 static void update_dimmed (ModestMsgEditWindow *window);
127
128
129 /* list my signals */
130 enum {
131         /* MY_SIGNAL_1, */
132         /* MY_SIGNAL_2, */
133         LAST_SIGNAL
134 };
135
136 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
137 struct _ModestMsgEditWindowPrivate {
138         GtkWidget   *msg_body;
139         GtkWidget   *header_box;
140         GtkWidget   *from_field;
141         GtkWidget   *to_field;
142         GtkWidget   *cc_field;
143         GtkWidget   *bcc_field;
144         GtkWidget   *subject_field;
145         GtkWidget   *attachments_view;
146         GtkWidget   *priority_icon;
147         GtkWidget   *add_attachment_button;
148
149         GtkWidget   *cc_caption;
150         GtkWidget   *bcc_caption;
151         GtkWidget   *attachments_caption;
152
153         GtkTextBuffer *text_buffer;
154
155         GtkWidget   *font_size_toolitem;
156         GtkWidget   *font_face_toolitem;
157         GtkWidget   *font_color_button;
158         GSList      *font_items_group;
159         GtkWidget   *font_tool_button_label;
160         GSList      *size_items_group;
161         GtkWidget   *size_tool_button_label;
162
163         GtkWidget   *scroll;
164
165         gint last_cid;
166         GList *attachments;
167
168         TnyHeaderFlags priority_flags;
169
170         gdouble zoom_level;
171 };
172
173 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
174                                                     MODEST_TYPE_MSG_EDIT_WINDOW, \
175                                                     ModestMsgEditWindowPrivate))
176 /* globals */
177 static GtkWindowClass *parent_class = NULL;
178
179 /* uncomment the following if you have defined any signals */
180 /* static guint signals[LAST_SIGNAL] = {0}; */
181
182 GType
183 modest_msg_edit_window_get_type (void)
184 {
185         static GType my_type = 0;
186         if (!my_type) {
187                 static const GTypeInfo my_info = {
188                         sizeof(ModestMsgEditWindowClass),
189                         NULL,           /* base init */
190                         NULL,           /* base finalize */
191                         (GClassInitFunc) modest_msg_edit_window_class_init,
192                         NULL,           /* class finalize */
193                         NULL,           /* class data */
194                         sizeof(ModestMsgEditWindow),
195                         1,              /* n_preallocs */
196                         (GInstanceInitFunc) modest_msg_edit_window_init,
197                         NULL
198                 };
199                 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
200                                                   "ModestMsgEditWindow",
201                                                   &my_info, 0);
202
203                 wp_text_buffer_library_init ();
204         }
205         return my_type;
206 }
207
208 static void
209 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
210 {
211         GObjectClass *gobject_class;
212         ModestWindowClass *modest_window_class;
213         gobject_class = (GObjectClass*) klass;
214         modest_window_class = (ModestWindowClass*) klass;
215
216         parent_class            = g_type_class_peek_parent (klass);
217         gobject_class->finalize = modest_msg_edit_window_finalize;
218
219         modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
220         modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
221         modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
222         modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
223         modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
224
225         g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
226 }
227
228 static void
229 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
230 {
231         ModestMsgEditWindowPrivate *priv;
232         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
233
234         priv->msg_body      = NULL;
235         priv->from_field    = NULL;
236         priv->to_field      = NULL;
237         priv->cc_field      = NULL;
238         priv->bcc_field     = NULL;
239         priv->subject_field = NULL;
240         priv->attachments   = NULL;
241         priv->last_cid      = 0;
242         priv->zoom_level    = 1.0;
243
244         priv->cc_caption    = NULL;
245         priv->bcc_caption    = NULL;
246
247         priv->priority_flags = 0;
248 }
249
250
251
252 static void
253 save_settings (ModestMsgEditWindow *self)
254 {
255         modest_widget_memory_save (modest_runtime_get_conf(),
256                                    G_OBJECT(self), "modest-edit-msg-window");
257 }
258
259
260 static void
261 restore_settings (ModestMsgEditWindow *self)
262 {
263         modest_widget_memory_restore (modest_runtime_get_conf(),
264                                       G_OBJECT(self), "modest-edit-msg-window");
265 }
266
267
268 /* FIXME: this is a dup from the one in gtk/ */
269 static ModestPairList*
270 get_transports (void)
271 {
272         ModestAccountMgr *account_mgr;
273         GSList *transports = NULL;
274         GSList *cursor, *accounts;
275         
276         account_mgr = modest_runtime_get_account_mgr();
277         cursor = accounts = modest_account_mgr_account_names (account_mgr); 
278         while (cursor) {
279                 gchar *account_name = (gchar*)cursor->data;
280                 gchar *from_string  = modest_account_mgr_get_from_string (account_mgr,
281                                                                           account_name);
282                 if (!from_string)  {
283                         /* something went wrong: ignore this one */
284                         g_free (account_name);
285                         cursor->data = NULL;
286                 } else {
287                         ModestPair *pair;
288                         pair = modest_pair_new ((gpointer) account_name,
289                                                 (gpointer) from_string , TRUE);
290                         transports = g_slist_prepend (transports, pair);
291                 } /* don't free account name; it's freed when the transports list is freed */
292                 cursor = cursor->next;
293         }
294         g_slist_free (accounts);
295         return transports;
296 }
297
298
299 static void
300 text_buffer_mark_set (GtkTextBuffer *buffer, GtkTextIter *iter, GtkTextMark *mark, gpointer userdata)
301 {
302         ModestMsgEditWindow *window;
303         ModestMsgEditWindowPrivate *priv;
304         GdkRectangle location;
305         gint v_scroll_min_value = 0;
306         gint v_scroll_max_value = 0;
307         gint v_scroll_visible;
308         GtkAdjustment *vadj;
309         GtkTextMark *insert_mark;
310         GtkTextIter insert_iter;
311         
312         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (userdata));
313         g_return_if_fail (GTK_IS_TEXT_MARK (mark));
314         window = MODEST_MSG_EDIT_WINDOW (userdata);
315         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
316                 
317         insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
318         gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &insert_iter, insert_mark);
319         gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &insert_iter, &location);
320         
321         if (priv->header_box)
322                 v_scroll_min_value += priv->header_box->allocation.height + DEFAULT_MAIN_VBOX_SPACING;
323         v_scroll_min_value += location.y;
324         v_scroll_max_value = v_scroll_min_value + location.height;
325         
326         v_scroll_visible = GTK_WIDGET (window)->allocation.height;
327         
328         vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
329         
330         if (((gdouble) v_scroll_min_value) < vadj->value)
331                 gtk_adjustment_set_value (vadj, v_scroll_min_value);
332         else if (((gdouble) v_scroll_max_value) > (vadj->value + vadj->page_size))
333                 gtk_adjustment_set_value (vadj, ((gdouble)v_scroll_max_value) - vadj->page_size);
334 }
335
336 static void
337 init_window (ModestMsgEditWindow *obj)
338 {
339         GtkWidget *from_caption, *to_caption, *subject_caption;
340         GtkWidget *main_vbox;
341         ModestMsgEditWindowPrivate *priv;
342         ModestPairList *protos;
343         GtkSizeGroup *size_group;
344         GtkWidget *frame;
345         GtkWidget *scroll_area;
346         GtkWidget *subject_box;
347         GtkWidget *attachment_icon;
348
349         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
350
351         size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
352
353         protos = get_transports ();
354         priv->from_field    = modest_combo_box_new (protos, g_str_equal);
355         modest_pair_list_free (protos);
356
357         priv->to_field      = modest_recpt_editor_new ();
358         priv->cc_field      = modest_recpt_editor_new ();
359         priv->bcc_field     = modest_recpt_editor_new ();
360         subject_box = gtk_hbox_new (FALSE, 0);
361         priv->priority_icon = gtk_image_new ();
362         gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
363         priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
364         g_object_set (G_OBJECT (priv->subject_field), "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL);
365         gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
366         priv->add_attachment_button = gtk_button_new ();
367         GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
368         gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
369         gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
370         gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
371         attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
372         gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
373         gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
374         priv->attachments_view = modest_attachments_view_new (NULL);
375         
376         priv->header_box = gtk_vbox_new (FALSE, 0);
377         
378         from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
379         to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
380         priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
381         priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
382         subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
383         priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
384         g_object_unref (size_group);
385
386         size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
387         modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
388         modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
389         modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
390         gtk_size_group_add_widget (size_group, priv->subject_field);
391         gtk_size_group_add_widget (size_group, priv->attachments_view);
392         g_object_unref (size_group);
393
394         gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
395         gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
396         gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
397         gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
398         gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
399         gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
400         gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
401
402
403         priv->msg_body = wp_text_view_new ();
404         gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
405         priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
406         g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
407         wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
408 /*      gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
409         wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
410
411         g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
412                           G_CALLBACK (text_buffer_refresh_attributes), obj);
413         g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
414                           G_CALLBACK (text_buffer_mark_set), obj);
415         g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
416                           G_CALLBACK (text_buffer_can_undo), obj);
417         g_signal_connect (G_OBJECT (obj), "window-state-event",
418                           G_CALLBACK (modest_msg_edit_window_window_state_event),
419                           NULL);
420         g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook", 
421                                   G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
422         g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook", 
423                                   G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
424         g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook", 
425                                   G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
426
427         priv->scroll = gtk_scrolled_window_new (NULL, NULL);
428         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
429         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
430         
431         main_vbox = gtk_vbox_new  (FALSE, DEFAULT_MAIN_VBOX_SPACING);
432
433         gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
434         frame = gtk_frame_new (NULL);
435         gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
436
437         gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
438         gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
439         gtk_widget_show_all (GTK_WIDGET(priv->scroll));
440         
441         if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL))
442                 gtk_widget_hide (priv->cc_field);
443         if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL))
444                 gtk_widget_hide (priv->bcc_field);
445
446         gtk_container_add (GTK_CONTAINER(obj), priv->scroll);
447         scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
448         gtk_container_add (GTK_CONTAINER (frame), scroll_area);
449         gtk_container_set_focus_vadjustment (GTK_CONTAINER (scroll_area), 
450                                              gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
451 }
452         
453
454
455 static void
456 modest_msg_edit_window_finalize (GObject *obj)
457 {
458         G_OBJECT_CLASS(parent_class)->finalize (obj);
459 }
460
461
462
463 static gboolean
464 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgEditWindow *self)
465 {
466         save_settings (self);
467         return FALSE;
468 }
469
470 static GtkWidget *
471 menubar_to_menu (GtkUIManager *ui_manager)
472 {
473         GtkWidget *main_menu;
474         GtkWidget *menubar;
475         GList *iter;
476
477         /* Create new main menu */
478         main_menu = gtk_menu_new();
479
480         /* Get the menubar from the UI manager */
481         menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
482
483         iter = gtk_container_get_children (GTK_CONTAINER (menubar));
484         while (iter) {
485                 GtkWidget *menu;
486
487                 menu = GTK_WIDGET (iter->data);
488                 gtk_widget_reparent(menu, main_menu);
489
490                 iter = g_list_next (iter);
491         }
492         return main_menu;
493 }
494
495
496 static void
497 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
498 {
499         TnyHeader *header;
500         const gchar *to, *cc, *bcc, *subject, *body;
501         ModestMsgEditWindowPrivate *priv;
502         
503         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
504         g_return_if_fail (TNY_IS_MSG (msg));
505
506         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
507
508         header = tny_msg_get_header (msg);
509         to      = tny_header_get_to (header);
510         cc      = tny_header_get_cc (header);
511         bcc     = tny_header_get_bcc (header);
512         subject = tny_header_get_subject (header);
513
514         if (to)
515                 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field),  to);
516         if (cc)
517                 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field),  cc);
518         if (bcc)
519                 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
520         if (subject)
521                 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);   
522
523 /*      gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
524         wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
525         body = modest_tny_msg_get_body (msg, FALSE);
526         if ((body!=NULL) && (body[0] != '\0')) {
527                 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
528                 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
529                                                     (gchar *) body,
530                                                     -1);
531                 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
532         } else {
533                 WPTextBufferFormat fmt = {0};
534
535                 fmt.font_size = DEFAULT_FONT_SIZE;
536                 fmt.font = DEFAULT_FONT;
537                 fmt.rich_text = 1;
538                 fmt.text_position = TEXT_POSITION_NORMAL;
539                 fmt.justification = 0;
540                 fmt.cs.font_size = 1;
541                 fmt.cs.font = 1;
542                 fmt.cs.text_position = 1;
543                 fmt.cs.justification = 1;
544                 wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &fmt);
545         }
546
547         /* Set the default focus depending on having already a To: field or not */
548         if ((!to)||(*to == '\0')) {
549                 gtk_widget_grab_focus (priv->to_field);
550         } else {
551                 gtk_widget_grab_focus (priv->msg_body);
552         }
553
554         /* TODO: lower priority, select in the From: combo to the
555            value that comes from msg <- not sure, should it be
556            allowed? */
557         
558         /* Add attachments to the view */
559         modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
560         if (priv->attachments == NULL)
561                 gtk_widget_hide_all (priv->attachments_caption);
562
563         update_dimmed (self);
564         text_buffer_can_undo (priv->text_buffer, FALSE, self);
565 }
566
567 static void
568 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
569                                 gpointer data)
570 {
571         GList *item_children, *node;
572         GtkWidget *bin_child;
573
574         bin_child = gtk_bin_get_child (GTK_BIN(item));
575
576         item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
577         
578         for (node = item_children; node != NULL; node = g_list_next (node)) {
579                 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
580                         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
581                 }
582         }
583         g_list_free (item_children);
584 }
585
586 static void
587 menu_tool_button_dont_expand (GtkMenuToolButton *item)
588 {
589         GtkWidget *box;
590         GList *item_children, *node;
591
592         box = gtk_bin_get_child (GTK_BIN (item));
593         gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
594         item_children = gtk_container_get_children (GTK_CONTAINER (box));
595         
596         for (node = item_children; node != NULL; node = g_list_next (node)) {
597                 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
598                 if (GTK_IS_TOGGLE_BUTTON (node->data))
599                         gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
600                 else if (GTK_IS_BUTTON (node->data))
601                         gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
602         }
603         g_list_free (item_children);
604 }
605
606
607 static void
608 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
609 {
610         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
611         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
612         GtkWidget *placeholder;
613         GtkWidget *tool_item;
614         gint insert_index;
615         gchar size_text[5];
616         gint size_index;
617         gint font_index;
618         GtkWidget *sizes_menu;
619         GtkWidget *fonts_menu;
620         GSList *radio_group = NULL;
621         gchar *markup;
622
623         /* Toolbar */
624         parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
625         hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
626
627         /* should we hide the toolbar? */
628         if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
629                 gtk_widget_hide (parent_priv->toolbar);
630
631         /* Font color placeholder */
632         placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
633         insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
634
635         /* font color */
636         tool_item = GTK_WIDGET (gtk_tool_item_new ());
637         priv->font_color_button = hildon_color_button_new ();
638         gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
639         gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
640         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
641         gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
642         g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
643
644         /* Font size and face placeholder */
645         placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
646         insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
647         /* font_size */
648         tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
649         priv->size_tool_button_label = gtk_label_new (NULL);
650         snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
651         markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
652                               size_text,"</span>", NULL);
653         gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
654         g_free (markup);
655         gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
656         sizes_menu = gtk_menu_new ();
657         priv->size_items_group = NULL;
658         radio_group = NULL;
659         for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
660                 GtkWidget *size_menu_item;
661
662                 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
663                 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
664                 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
665                 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
666                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
667                 gtk_widget_show (size_menu_item);
668
669                 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
670                         
671                 g_signal_connect (G_OBJECT (size_menu_item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
672                                   window);
673         }
674         priv->size_items_group = g_slist_reverse (priv->size_items_group);
675         gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
676         g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
677         gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
678         gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
679         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
680         menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
681         priv->font_size_toolitem = tool_item;
682
683         /* font face */
684         tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
685         priv->font_tool_button_label = gtk_label_new (NULL);
686         markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
687         gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
688         g_free(markup);
689         gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
690         fonts_menu = gtk_menu_new ();
691         priv->font_items_group = NULL;
692         radio_group = NULL;
693         for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
694                 GtkWidget *font_menu_item;
695                 GtkWidget *child_label;
696
697                 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
698                 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
699                 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>", 
700                                       wp_get_font_name (font_index), "</span>", NULL);
701                 gtk_label_set_markup (GTK_LABEL (child_label), markup);
702                 g_free (markup);
703                 
704                 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
705                 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
706                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
707                 gtk_widget_show (font_menu_item);
708
709                 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
710                         
711                 g_signal_connect (G_OBJECT (font_menu_item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
712                                   window);
713         }
714         priv->font_items_group = g_slist_reverse (priv->font_items_group);
715         gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
716         g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
717         gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
718         gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
719         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
720         menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
721         priv->font_face_toolitem = tool_item;
722
723         /* Set expand and homogeneous for remaining items */
724         tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
725         gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
726         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
727         tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
728         gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
729         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
730         tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
731         gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
732         gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
733
734
735 }
736
737
738
739 ModestWindow*
740 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
741 {
742         GObject *obj;
743         ModestWindowPrivate *parent_priv;
744         ModestMsgEditWindowPrivate *priv;
745         GtkActionGroup *action_group;
746         GError *error = NULL;
747         GdkPixbuf *window_icon = NULL;
748
749         g_return_val_if_fail (msg, NULL);
750         
751         obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
752
753         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
754         parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
755
756         parent_priv->ui_manager = gtk_ui_manager_new();
757         action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
758         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
759
760         /* Add common actions */
761         gtk_action_group_add_actions (action_group,
762                                       modest_msg_edit_action_entries,
763                                       G_N_ELEMENTS (modest_msg_edit_action_entries),
764                                       obj);
765         gtk_action_group_add_toggle_actions (action_group,
766                                              modest_msg_edit_toggle_action_entries,
767                                              G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
768                                              obj);
769         gtk_action_group_add_radio_actions (action_group,
770                                             modest_msg_edit_alignment_radio_action_entries,
771                                             G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
772                                             GTK_JUSTIFY_LEFT,
773                                             G_CALLBACK (modest_ui_actions_on_change_justify),
774                                             obj);
775         gtk_action_group_add_radio_actions (action_group,
776                                             modest_msg_edit_zoom_action_entries,
777                                             G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
778                                             100,
779                                             G_CALLBACK (modest_ui_actions_on_change_zoom),
780                                             obj);
781         gtk_action_group_add_radio_actions (action_group,
782                                             modest_msg_edit_priority_action_entries,
783                                             G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
784                                             0,
785                                             G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
786                                             obj);
787         gtk_action_group_add_radio_actions (action_group,
788                                             modest_msg_edit_file_format_action_entries,
789                                             G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
790                                             MODEST_FILE_FORMAT_FORMATTED_TEXT,
791                                             G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
792                                             obj);
793         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
794         g_object_unref (action_group);
795
796         /* Load the UI definition */
797         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml", &error);
798         if (error != NULL) {
799                 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
800                 g_error_free (error);
801                 error = NULL;
802         }
803
804         /* Add accelerators */
805         gtk_window_add_accel_group (GTK_WINDOW (obj), 
806                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
807
808         /* Menubar */
809         parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
810         hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
811
812         /* Init window */
813         init_window (MODEST_MSG_EDIT_WINDOW(obj));
814
815         restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
816                 
817         gtk_window_set_title (GTK_WINDOW(obj), "Modest");
818         gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
819
820         g_signal_connect (G_OBJECT(obj), "delete-event",
821                           G_CALLBACK(on_delete_event), obj);
822
823         modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
824
825         modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
826
827         set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
828
829         text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
830
831         /* Set window icon */
832         window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
833         gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
834         
835         return (ModestWindow*)obj;
836 }
837
838 static gint
839 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
840 {
841         GString **string_buffer = (GString **) user_data;
842
843         *string_buffer = g_string_append (*string_buffer, buffer);
844    
845         return 0;
846 }
847
848 static gchar *
849 get_formatted_data (ModestMsgEditWindow *edit_window)
850 {
851         ModestMsgEditWindowPrivate *priv;
852         GString *string_buffer = g_string_new ("");
853         
854         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
855
856         wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
857
858         return g_string_free (string_buffer, FALSE);
859                                                                         
860 }
861
862 MsgData * 
863 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
864 {
865         MsgData *data;
866         const gchar *account_name;
867         GtkTextBuffer *buf;
868         GtkTextIter b, e;
869         ModestMsgEditWindowPrivate *priv;
870         
871         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
872
873         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
874                                                                         
875         account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
876         g_return_val_if_fail (account_name, NULL);
877         
878         buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));        
879         gtk_text_buffer_get_bounds (buf, &b, &e);
880         
881         /* don't free these (except from) */
882         data = g_slice_new0 (MsgData);
883         data->from    =  modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
884                                                              account_name);
885         data->to      =  (gchar*) modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR(priv->to_field));
886         data->cc      =  (gchar*) modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR(priv->cc_field));
887         data->bcc     =  (gchar*) modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR(priv->bcc_field));
888         data->subject =  (gchar*) gtk_entry_get_text (GTK_ENTRY(priv->subject_field));  
889         data->plain_body =  (gchar *) gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE);
890         if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
891                 data->html_body = get_formatted_data (edit_window);
892         else
893                 data->html_body = NULL;
894         data->attachments = priv->attachments;
895         data->priority_flags = priv->priority_flags;
896
897         return data;
898 }
899
900 void 
901 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
902                                                       MsgData *data)
903 {
904         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
905
906         g_free (data->from);
907         g_free (data->html_body);
908         g_free (data->plain_body);
909         g_slice_free (MsgData, data);
910 }
911
912 ModestMsgEditFormat
913 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
914 {
915         gboolean rich_text;
916         ModestMsgEditWindowPrivate *priv = NULL;
917         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
918
919         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
920
921         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
922         if (rich_text)
923                 return MODEST_MSG_EDIT_FORMAT_HTML;
924         else
925                 return MODEST_MSG_EDIT_FORMAT_TEXT;
926 }
927
928 void
929 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
930                                    ModestMsgEditFormat format)
931 {
932         ModestMsgEditWindowPrivate *priv;
933
934         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
935         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
936
937         switch (format) {
938         case MODEST_MSG_EDIT_FORMAT_HTML:
939                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
940                 break;
941         case MODEST_MSG_EDIT_FORMAT_TEXT:
942                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
943                 break;
944         default:
945                 g_return_if_reached ();
946         }
947 }
948
949 ModestMsgEditFormatState *
950 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
951 {
952         ModestMsgEditFormatState *format_state = NULL;
953         ModestMsgEditWindowPrivate *priv;
954         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
955
956         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
957         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
958
959         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
960
961         format_state = g_new0 (ModestMsgEditFormatState, 1);
962         format_state->bold = buffer_format->bold&0x1;
963         format_state->italics = buffer_format->italic&0x1;
964         format_state->bullet = buffer_format->bullet&0x1;
965         format_state->color = buffer_format->color;
966         format_state->font_size = buffer_format->font_size;
967         format_state->font_family = wp_get_font_name (buffer_format->font);
968         format_state->justification = buffer_format->justification;
969         g_free (buffer_format);
970
971         return format_state;
972  
973 }
974
975 void
976 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
977                                          const ModestMsgEditFormatState *format_state)
978 {
979         ModestMsgEditWindowPrivate *priv;
980         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
981         WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
982         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
983         g_return_if_fail (format_state != NULL);
984
985         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
986         gtk_widget_grab_focus (priv->msg_body);
987         buffer_format->bold = (format_state->bold != FALSE);
988         buffer_format->italic = (format_state->italics != FALSE);
989         buffer_format->color = format_state->color;
990         buffer_format->font_size = format_state->font_size;
991         buffer_format->font = wp_get_font_index (format_state->font_family, 0);
992         buffer_format->justification = format_state->justification;
993         buffer_format->bullet = format_state->bullet;
994
995         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
996
997         buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
998         buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
999         buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
1000         buffer_format->cs.font_size =  (buffer_format->font_size != current_format->font_size);
1001         buffer_format->cs.font = (buffer_format->font != current_format->font);
1002         buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1003         buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1004
1005         wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1006         if (buffer_format->cs.bold) {
1007                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1008         }
1009         if (buffer_format->cs.italic) {
1010                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1011         }
1012         if (buffer_format->cs.color) {
1013                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1014         }
1015         if (buffer_format->cs.font_size) {
1016                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font_size));
1017         }
1018         if (buffer_format->cs.justification) {
1019                 switch (buffer_format->justification) {
1020                 case GTK_JUSTIFY_LEFT:
1021                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1022                         break;
1023                 case GTK_JUSTIFY_CENTER:
1024                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1025                         break;
1026                 case GTK_JUSTIFY_RIGHT:
1027                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1028                         break;
1029                 default:
1030                         break;
1031                 }
1032                         
1033         }
1034         if (buffer_format->cs.font) {
1035                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font));
1036         }
1037         if (buffer_format->cs.bullet) {
1038                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) (buffer_format->bullet));
1039         }
1040 /*      wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1041         wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1042
1043         g_free (current_format);
1044
1045 }
1046
1047 static void
1048 toggle_action_set_active_block_notify (GtkToggleAction *action,
1049                                        gboolean value)
1050 {
1051         GSList *proxies = NULL;
1052
1053         for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1054              proxies != NULL; proxies = g_slist_next (proxies)) {
1055                 GtkWidget *widget = (GtkWidget *) proxies->data;
1056                 gtk_action_block_activate_from (GTK_ACTION (action), widget);
1057         }
1058
1059         gtk_toggle_action_set_active (action, value);
1060
1061         for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
1062              proxies != NULL; proxies = g_slist_next (proxies)) {
1063                 GtkWidget *widget = (GtkWidget *) proxies->data;
1064                 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
1065         }
1066 }
1067
1068 static void
1069 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1070 {
1071         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1072         GtkAction *action;
1073         ModestWindowPrivate *parent_priv;
1074         ModestMsgEditWindowPrivate *priv;
1075         GtkWidget *new_size_menuitem;
1076         GtkWidget *new_font_menuitem;
1077         
1078         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1079         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1080
1081         if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1082                 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1083                 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1084                         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1085         } else {
1086                 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1087                 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1088                         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1089         }
1090
1091         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1092         
1093         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1094         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1095
1096         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1097         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1098
1099         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1100         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1101
1102         g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button), 
1103                                          G_CALLBACK (modest_msg_edit_window_color_button_change),
1104                                          window);
1105         hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1106         g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button), 
1107                                            G_CALLBACK (modest_msg_edit_window_color_button_change),
1108                                            window);
1109
1110         new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group, 
1111                                                       buffer_format->font_size))->data);
1112         if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1113                 GtkWidget *label;
1114                 gchar *markup;
1115
1116                 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1117                 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1118                 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1119                 g_free (markup);
1120                 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1121                                                  G_CALLBACK (modest_msg_edit_window_size_change),
1122                                                  window);
1123                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1124                 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1125                                                    G_CALLBACK (modest_msg_edit_window_size_change),
1126                                                    window);
1127         }
1128
1129         new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group, 
1130                                                       buffer_format->font))->data);
1131         if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1132                 GtkWidget *label;
1133                 gchar *markup;
1134
1135                 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1136                 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1137                 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1138                 g_free (markup);
1139                 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1140                                                  G_CALLBACK (modest_msg_edit_window_font_change),
1141                                                  window);
1142                 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1143                 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1144                                                    G_CALLBACK (modest_msg_edit_window_font_change),
1145                                                    window);
1146         }
1147
1148         g_free (buffer_format);
1149
1150 }
1151
1152
1153 void
1154 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1155 {
1156         
1157         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1158         ModestMsgEditWindowPrivate *priv;
1159         GtkWidget *dialog = NULL;
1160         gint response;
1161         GdkColor *new_color = NULL;
1162         
1163         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1164         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1165         
1166 #ifdef MODEST_HILDON_VERSION_0  
1167         dialog = hildon_color_selector_new (GTK_WINDOW (window));
1168         hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1169 #else
1170         dialog = hildon_color_chooser_new ();
1171         hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1172 #endif /*MODEST_HILDON_VERSION_9*/              
1173         g_free (buffer_format);
1174
1175         response = gtk_dialog_run (GTK_DIALOG (dialog));
1176         switch (response) {
1177         case GTK_RESPONSE_OK: {
1178 #ifdef MODEST_HILDON_VERSION_0
1179                 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1180 #else
1181                 GdkColor col;
1182                 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1183                 new_color = &col;
1184         }
1185 #endif /*MODEST_HILDON_VERSION_0*/
1186         break;
1187         default:
1188                 break;
1189         }
1190         gtk_widget_destroy (dialog);
1191
1192         if (new_color != NULL)
1193                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1194
1195 }
1196
1197 void
1198 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1199 {
1200         
1201         ModestMsgEditWindowPrivate *priv;
1202         GtkWidget *dialog = NULL;
1203         gint response;
1204         GdkColor *old_color = NULL;
1205         GdkColor *new_color = NULL;
1206         
1207         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1208         old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1209         
1210 #ifdef MODEST_HILDON_VERSION_0  
1211         dialog = hildon_color_selector_new (GTK_WINDOW (window));
1212         hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1213 #else
1214         dialog = hildon_color_chooser_new ();
1215         hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1216 #endif /*MODEST_HILDON_VERSION_9*/              
1217
1218         response = gtk_dialog_run (GTK_DIALOG (dialog));
1219         switch (response) {
1220         case GTK_RESPONSE_OK: {
1221 #ifdef MODEST_HILDON_VERSION_0
1222                 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1223 #else
1224                 GdkColor col;
1225                 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1226                 new_color = &col;
1227           }
1228 #endif /*MODEST_HILDON_VERSION_0*/
1229                 break;
1230         default:
1231                 break;
1232         }
1233         gtk_widget_destroy (dialog);
1234
1235         if (new_color != NULL)
1236                 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1237
1238 }
1239
1240 void
1241 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1242 {
1243         
1244         ModestMsgEditWindowPrivate *priv;
1245         GtkWidget *dialog = NULL;
1246         gint response = 0;
1247         gchar *filename = NULL;
1248         
1249         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1250         
1251         dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1252
1253         response = gtk_dialog_run (GTK_DIALOG (dialog));
1254         switch (response) {
1255         case GTK_RESPONSE_OK:
1256                 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1257                 break;
1258         default:
1259                 break;
1260         }
1261         gtk_widget_destroy (dialog);
1262
1263         if (filename) {
1264                 GdkPixbuf *pixbuf = NULL;
1265                 GtkTextIter position;
1266                 GtkTextMark *insert_mark;
1267
1268                 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1269                 if (pixbuf) {
1270                         gint image_file_id;
1271                         GdkPixbufFormat *pixbuf_format;
1272
1273                         image_file_id = g_open (filename, O_RDONLY, 0);
1274                         pixbuf_format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
1275                         if ((image_file_id != -1)&&(pixbuf_format != NULL)) {
1276                                 TnyMimePart *image_part;
1277                                 TnyStream *image_stream;
1278                                 gchar **mime_types;
1279                                 gchar *mime_type;
1280                                 gchar *basename;
1281                                 gchar *content_id;
1282
1283                                 mime_types = gdk_pixbuf_format_get_mime_types (pixbuf_format);
1284                                 if ((mime_types != NULL) && (mime_types[0] != NULL)) {
1285                                         mime_type = mime_types[0];
1286                                 } else {
1287                                         mime_type = "image/unknown";
1288                                 }
1289                                 image_part = tny_platform_factory_new_mime_part
1290                                         (modest_runtime_get_platform_factory ());
1291                                 image_stream = TNY_STREAM (tny_fs_stream_new (image_file_id));
1292
1293                                 tny_mime_part_construct_from_stream (image_part, image_stream, mime_type);
1294                                 g_strfreev (mime_types);
1295
1296                                 content_id = g_strdup_printf ("%d", priv->last_cid);
1297                                 tny_mime_part_set_content_id (image_part, content_id);
1298                                 g_free (content_id);
1299                                 priv->last_cid++;
1300
1301                                 basename = g_path_get_basename (filename);
1302                                 tny_mime_part_set_filename (image_part, basename);
1303                                 g_free (basename);
1304                                 
1305                                 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1306                                 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1307                                 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (image_part)), pixbuf);
1308                                 priv->attachments = g_list_prepend (priv->attachments, image_part);
1309                                 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1310                                                                         image_part);
1311                                 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1312                                 gtk_widget_show_all (priv->attachments_caption);
1313                         } else if (image_file_id == -1) {
1314                                 close (image_file_id);
1315                         }
1316                 }
1317         }
1318
1319
1320 }
1321
1322 static void
1323 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1324                                             gpointer userdata)
1325 {
1326         ModestMsgEditWindowPrivate *priv;
1327         GdkColor *new_color;
1328         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1329         
1330 #ifdef MODEST_HILDON_VERSION_0  
1331         new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1332 #else 
1333         GdkColor col;
1334         hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1335         new_color = &col;
1336 #endif /*MODEST_HILDON_VERSION_0*/
1337
1338         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1339         
1340         gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1341
1342 }
1343
1344 static void
1345 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1346                                     gpointer userdata)
1347 {
1348         ModestMsgEditWindowPrivate *priv;
1349         gint new_size_index;
1350         ModestMsgEditWindow *window;
1351         GtkWidget *label;
1352         
1353         window = MODEST_MSG_EDIT_WINDOW (userdata);
1354         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1355         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1356
1357         if (gtk_check_menu_item_get_active (menu_item)) {
1358                 gchar *markup;
1359
1360                 label = gtk_bin_get_child (GTK_BIN (menu_item));
1361                 
1362                 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1363
1364                 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, 
1365                                                    (gpointer) wp_get_font_size_index (new_size_index, 12)))
1366                         wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1367                 
1368                 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1369                 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1370                 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1371                 g_free (markup);
1372         }
1373 }
1374
1375 static void
1376 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1377                                     gpointer userdata)
1378 {
1379         ModestMsgEditWindowPrivate *priv;
1380         gint new_font_index;
1381         ModestMsgEditWindow *window;
1382         GtkWidget *label;
1383         
1384         window = MODEST_MSG_EDIT_WINDOW (userdata);
1385         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1386         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1387
1388         if (gtk_check_menu_item_get_active (menu_item)) {
1389                 gchar *markup;
1390
1391                 label = gtk_bin_get_child (GTK_BIN (menu_item));
1392                 
1393                 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
1394
1395                 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, 
1396                                                    (gpointer) new_font_index))
1397                         wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1398                 
1399                 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1400                     markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1401                 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1402                 g_free (markup);
1403         }
1404 }
1405
1406 static void
1407 modest_msg_edit_window_set_zoom (ModestWindow *window,
1408                                  gdouble zoom)
1409 {
1410         ModestMsgEditWindowPrivate *priv;
1411      
1412         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1413
1414         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1415         priv->zoom_level = zoom;
1416         wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1417 }
1418
1419 static gdouble
1420 modest_msg_edit_window_get_zoom (ModestWindow *window)
1421 {
1422         ModestMsgEditWindowPrivate *priv;
1423      
1424         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1425
1426         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1427         return priv->zoom_level;
1428 }
1429
1430 static gboolean
1431 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1432 {
1433         ModestWindowPrivate *parent_priv;
1434         GtkRadioAction *zoom_radio_action;
1435         GSList *group, *node;
1436
1437         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1438         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1439                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1440
1441         group = gtk_radio_action_get_group (zoom_radio_action);
1442
1443         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1444                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_max_zoom_level"));
1445                 return FALSE;
1446         }
1447
1448         for (node = group; node != NULL; node = g_slist_next (node)) {
1449                 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1450                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1451                         return TRUE;
1452                 }
1453         }
1454         return FALSE;
1455 }
1456
1457 static gboolean
1458 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1459 {
1460         ModestWindowPrivate *parent_priv;
1461         GtkRadioAction *zoom_radio_action;
1462         GSList *group, *node;
1463
1464         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1465         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1466                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1467
1468         group = gtk_radio_action_get_group (zoom_radio_action);
1469
1470         for (node = group; node != NULL; node = g_slist_next (node)) {
1471                 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1472                         if (node->next != NULL) {
1473                                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1474                                 return TRUE;
1475                         } else
1476                                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_min_zoom_level"));
1477                         break;
1478                 }
1479         }
1480         return FALSE;
1481 }
1482
1483 static gboolean
1484 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1485 {
1486         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1487                 ModestWindowPrivate *parent_priv;
1488                 ModestWindowMgr *mgr;
1489                 gboolean is_fullscreen;
1490                 GtkAction *fs_toggle_action;
1491                 gboolean active;
1492
1493                 mgr = modest_runtime_get_window_mgr ();
1494                 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1495
1496                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1497                 
1498                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1499                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1500                 if (is_fullscreen != active)
1501                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1502         }
1503
1504         return FALSE;
1505
1506 }
1507
1508 void
1509 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1510 {
1511         ModestWindowPrivate *parent_priv;
1512         GtkAction *fs_toggle_action;
1513         gboolean active;
1514
1515         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1516
1517         fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1518         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1519         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1520 }
1521
1522 void
1523 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window, 
1524                                 gboolean show)
1525 {
1526         ModestMsgEditWindowPrivate *priv = NULL;
1527         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1528
1529         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1530         if (show)
1531                 gtk_widget_show (priv->cc_caption);
1532         else
1533                 gtk_widget_hide (priv->cc_caption);
1534 }
1535
1536 void
1537 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window, 
1538                                  gboolean show)
1539 {
1540         ModestMsgEditWindowPrivate *priv = NULL;
1541         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1542
1543         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1544         if (show)
1545                 gtk_widget_show (priv->bcc_caption);
1546         else
1547                 gtk_widget_hide (priv->bcc_caption);
1548 }
1549
1550 static void
1551 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
1552                                          ModestRecptEditor *editor)
1553 {
1554         ModestMsgEditWindowPrivate *priv;
1555
1556         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1557         g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
1558         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1559
1560         if (editor == NULL) {
1561                 GtkWidget *view_focus;
1562                 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
1563
1564                 if (gtk_widget_get_parent (view_focus) && 
1565                     MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (view_focus))) {
1566                         editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (view_focus));
1567                 } else {
1568                         editor = MODEST_RECPT_EDITOR (priv->to_field);
1569                 }
1570         }
1571
1572         modest_address_book_select_addresses (editor);
1573
1574 }
1575
1576 void
1577 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
1578 {
1579         GtkWidget *focused;
1580         ModestMsgEditWindowPrivate *priv;
1581
1582         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1583         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1584         focused = gtk_window_get_focus (GTK_WINDOW (window));
1585
1586         if (MODEST_IS_RECPT_EDITOR (focused)) {
1587                 modest_msg_edit_window_open_addressbook (window, MODEST_RECPT_EDITOR (focused));
1588         } else {
1589                 modest_msg_edit_window_open_addressbook (window, MODEST_RECPT_EDITOR (priv->to_field));
1590         }
1591         
1592 }
1593 static void
1594 modest_msg_edit_window_show_toolbar (ModestWindow *self,
1595                                      gboolean show_toolbar)
1596 {
1597         ModestWindowPrivate *parent_priv;
1598         
1599         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1600
1601         /* FIXME: we can not just use the code of
1602            modest_msg_edit_window_setup_toolbar because it has a
1603            mixture of both initialization and creation code. */
1604
1605         if (show_toolbar)
1606                 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1607         else
1608                 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1609 }
1610
1611 void
1612 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
1613                                            TnyHeaderFlags priority_flags)
1614 {
1615         ModestMsgEditWindowPrivate *priv;
1616
1617         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1618
1619         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1620         priority_flags = priority_flags & (TNY_HEADER_FLAG_HIGH_PRIORITY);
1621
1622         if (priv->priority_flags != priority_flags) {
1623
1624                 priv->priority_flags = priority_flags;
1625
1626                 switch (priority_flags) {
1627                 case TNY_HEADER_FLAG_HIGH_PRIORITY:
1628                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
1629                         gtk_widget_show (priv->priority_icon);
1630                         break;
1631                 case TNY_HEADER_FLAG_LOW_PRIORITY:
1632                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
1633                         gtk_widget_show (priv->priority_icon);
1634                         break;
1635                 default:
1636                         gtk_widget_hide (priv->priority_icon);
1637                         break;
1638                 }
1639         }
1640 }
1641
1642 void
1643 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
1644                                         gint file_format)
1645 {
1646         ModestMsgEditWindowPrivate *priv;
1647         gint current_format;
1648
1649         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1650
1651         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1652
1653         current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
1654                 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
1655
1656         if (current_format != file_format) {
1657                 switch (file_format) {
1658                 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
1659                         wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1660                         break;
1661                 case MODEST_FILE_FORMAT_PLAIN_TEXT:
1662                 {
1663                         GtkWidget *dialog;
1664                         gint response;
1665                         dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
1666                         response = gtk_dialog_run (GTK_DIALOG (dialog));
1667                         gtk_widget_destroy (dialog);
1668                         if (response == GTK_RESPONSE_OK)
1669                                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1670                 }
1671                         break;
1672                 }
1673                 update_dimmed (window);
1674         }
1675 }
1676
1677 void
1678 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
1679 {
1680         GtkWidget *dialog;
1681         ModestMsgEditWindowPrivate *priv;
1682         WPTextBufferFormat oldfmt, fmt;
1683         gint old_position = 0;
1684         gint response = 0;
1685         gint position = 0;
1686         gint font_size;
1687         GdkColor *color = NULL;
1688         gboolean bold, bold_set, italic, italic_set;
1689         gboolean underline, underline_set;
1690         gboolean strikethrough, strikethrough_set;
1691         gboolean position_set;
1692         gboolean font_size_set, font_set, color_set;
1693         gchar *font_name;
1694
1695         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1696         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1697         
1698         dialog = hildon_font_selection_dialog_new (NULL, NULL);
1699
1700         /* First we get the currently selected font information */
1701         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
1702         g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
1703
1704         switch (oldfmt.text_position) {
1705         case TEXT_POSITION_NORMAL:
1706                 old_position = 0;
1707                 break;
1708         case TEXT_POSITION_SUPERSCRIPT:
1709                 old_position = 1;
1710                 break;
1711         default:
1712                 old_position = -1;
1713                 break;
1714         }
1715
1716         g_object_set (G_OBJECT (dialog),
1717                       "bold", oldfmt.bold != FALSE,
1718                       "bold-set", !oldfmt.cs.bold,
1719                       "underline", oldfmt.underline != FALSE,
1720                       "underline-set", !oldfmt.cs.underline,
1721                       "italic", oldfmt.italic != FALSE,
1722                       "italic-set", !oldfmt.cs.italic,
1723                       "strikethrough", oldfmt.strikethrough != FALSE,
1724                       "strikethrough-set", !oldfmt.cs.strikethrough,
1725                       "color", &oldfmt.color,
1726                       "color-set", !oldfmt.cs.color,
1727                       "size", wp_font_size[oldfmt.font_size],
1728                       "size-set", !oldfmt.cs.font_size,
1729                       "position", old_position,
1730                       "position-set", !oldfmt.cs.text_position,
1731                       "family", wp_get_font_name (oldfmt.font),
1732                       "family-set", !oldfmt.cs.font,
1733                       NULL);
1734
1735         gtk_widget_show_all (dialog);
1736         response = gtk_dialog_run (GTK_DIALOG (dialog));
1737         if (response == GTK_RESPONSE_OK) {
1738
1739                 g_object_get( dialog,
1740                               "bold", &bold,
1741                               "bold-set", &bold_set,
1742                               "underline", &underline,
1743                               "underline-set", &underline_set,
1744                               "italic", &italic,
1745                               "italic-set", &italic_set,
1746                               "strikethrough", &strikethrough,
1747                               "strikethrough-set", &strikethrough_set,
1748                               "color", &color,
1749                               "color-set", &color_set,
1750                               "size", &font_size,
1751                               "size-set", &font_size_set,
1752                               "family", &font_name,
1753                               "family-set", &font_set,
1754                               "position", &position,
1755                               "position-set", &position_set,
1756                               NULL );
1757                 
1758         }       
1759
1760         gtk_widget_destroy (dialog);
1761         
1762         if (response == GTK_RESPONSE_OK) {
1763                 memset(&fmt, 0, sizeof(fmt));
1764                 if (bold_set) {
1765                         fmt.bold = bold;
1766                         fmt.cs.bold = TRUE;
1767                 }
1768                 if (italic_set) {
1769                         fmt.italic = italic;
1770                         fmt.cs.italic = TRUE;
1771                 }
1772                 if (underline_set) {
1773                         fmt.underline = underline;
1774                         fmt.cs.underline = TRUE;
1775                 }
1776                 if (strikethrough_set) {
1777                         fmt.strikethrough = strikethrough;
1778                         fmt.cs.strikethrough = TRUE;
1779                 }
1780                 if (position_set) {
1781                         fmt.text_position =
1782                                 ( position == 0 )
1783                                 ? TEXT_POSITION_NORMAL
1784                                 : ( ( position == 1 )
1785                                     ? TEXT_POSITION_SUPERSCRIPT
1786                                     : TEXT_POSITION_SUBSCRIPT );
1787                         fmt.cs.text_position = TRUE;
1788                 }
1789                 if (color_set) {
1790                         fmt.color = *color;
1791                         fmt.cs.color = TRUE;
1792                 }
1793                 gdk_color_free(color);
1794                 if (font_set) {
1795                         fmt.font = wp_get_font_index(font_name,
1796                                                      DEFAULT_FONT);
1797                         fmt.cs.font = TRUE;
1798                 }
1799                 g_free(font_name);
1800                 if (font_size_set) {
1801                         fmt.font_size = wp_get_font_size_index(
1802                                 font_size, DEFAULT_FONT_SIZE);
1803                         fmt.cs.font_size = TRUE;
1804                 }
1805                 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
1806                 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
1807         }
1808
1809 }
1810
1811 void
1812 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
1813 {
1814         ModestMsgEditWindowPrivate *priv;
1815
1816         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1817         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1818         
1819         wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
1820
1821         update_dimmed (window);
1822
1823 }
1824
1825 static void
1826 update_dimmed (ModestMsgEditWindow *window)
1827 {
1828         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1829         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1830         GtkAction *action;
1831         GtkWidget *widget;
1832         gboolean rich_text;
1833
1834         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1835
1836         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
1837         gtk_action_set_sensitive (action, rich_text);
1838         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1839         gtk_action_set_sensitive (action, rich_text);
1840         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
1841         gtk_action_set_sensitive (action, rich_text);
1842         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1843         gtk_action_set_sensitive (action, rich_text);
1844         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1845         gtk_action_set_sensitive (action, rich_text);
1846         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1847         gtk_action_set_sensitive (action, rich_text);
1848         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
1849         gtk_action_set_sensitive (action, rich_text);
1850         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1851         gtk_action_set_sensitive (action, rich_text);
1852         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1853         gtk_action_set_sensitive (action, rich_text);
1854         widget = priv->font_color_button;
1855         gtk_widget_set_sensitive (widget, rich_text);
1856         widget = priv->font_size_toolitem;
1857         gtk_widget_set_sensitive (widget, rich_text);
1858         widget = priv->font_face_toolitem;
1859         gtk_widget_set_sensitive (widget, rich_text);
1860 }
1861
1862 static void  
1863 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
1864 {
1865         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1866         GtkAction *action;
1867
1868         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
1869         gtk_action_set_sensitive (action, can_undo);
1870 }