* Added the proper icon to each window
[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
46 #include <modest-runtime.h>
47
48 #include "modest-platform.h"
49 #include "modest-icon-names.h"
50 #include "modest-widget-memory.h"
51 #include "modest-window-priv.h"
52 #include "modest-mail-operation.h"
53 #include "modest-tny-platform-factory.h"
54 #include "modest-tny-msg.h"
55 #include <tny-simple-list.h>
56 #include <wptextview.h>
57 #include <wptextbuffer.h>
58 #include <hildon-widgets/hildon-color-selector.h>
59 #include <hildon-widgets/hildon-color-button.h>
60 #include <hildon-widgets/hildon-banner.h>
61 #include <hildon-widgets/hildon-caption.h>
62 #include "widgets/modest-msg-edit-window-ui.h"
63
64 #ifdef MODEST_HILDON_VERSION_0
65 #include <hildon-widgets/hildon-file-chooser-dialog.h>
66 #else
67 #include <hildon/hildon-file-chooser-dialog.h>
68
69 #endif /*MODEST_HILDON_VERSION_0 */
70
71
72
73 #define DEFAULT_FONT_SIZE 3
74 #define DEFAULT_FONT 2
75 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
76 #define DEFAULT_MAIN_VBOX_SPACING 6
77 #define SUBJECT_MAX_LENGTH 1000
78
79 static void  modest_msg_edit_window_class_init   (ModestMsgEditWindowClass *klass);
80 static void  modest_msg_edit_window_init         (ModestMsgEditWindow *obj);
81 static void  modest_msg_edit_window_finalize     (GObject *obj);
82
83 static void  text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
84 static void  text_buffer_mark_set (GtkTextBuffer *buffer, GtkTextIter *location, GtkTextMark *mark, gpointer userdata);
85 static void  modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
86                                                          gpointer userdata);
87 static void  modest_msg_edit_window_size_combobox_change (ModestMsgEditWindow *window,
88                                                           gpointer userdata);
89 static void  modest_msg_edit_window_font_combobox_change (ModestMsgEditWindow *window,
90                                                           gpointer userdata);
91 static void  modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
92 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget, 
93                                                            GdkEventWindowState *event, 
94                                                            gpointer userdata);
95
96 /* ModestWindow methods implementation */
97 static void  modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
98 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
99 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
100 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
101
102
103
104 /* list my signals */
105 enum {
106         /* MY_SIGNAL_1, */
107         /* MY_SIGNAL_2, */
108         LAST_SIGNAL
109 };
110
111 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
112 struct _ModestMsgEditWindowPrivate {
113         GtkWidget   *msg_body;
114         GtkWidget   *header_box;
115         GtkWidget   *from_field;
116         GtkWidget   *to_field;
117         GtkWidget   *cc_field;
118         GtkWidget   *bcc_field;
119         GtkWidget   *subject_field;
120
121         GtkWidget   *cc_caption;
122         GtkWidget   *bcc_caption;
123
124         GtkTextBuffer *text_buffer;
125
126         GtkWidget   *font_color_button;
127         GtkWidget   *size_combobox;
128         GtkWidget   *font_combobox;
129
130         GtkWidget   *scroll;
131
132         gint last_cid;
133         GList *attachments;
134
135         gdouble zoom_level;
136 };
137
138 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
139                                                     MODEST_TYPE_MSG_EDIT_WINDOW, \
140                                                     ModestMsgEditWindowPrivate))
141 /* globals */
142 static GtkWindowClass *parent_class = NULL;
143
144 /* uncomment the following if you have defined any signals */
145 /* static guint signals[LAST_SIGNAL] = {0}; */
146
147 GType
148 modest_msg_edit_window_get_type (void)
149 {
150         static GType my_type = 0;
151         if (!my_type) {
152                 static const GTypeInfo my_info = {
153                         sizeof(ModestMsgEditWindowClass),
154                         NULL,           /* base init */
155                         NULL,           /* base finalize */
156                         (GClassInitFunc) modest_msg_edit_window_class_init,
157                         NULL,           /* class finalize */
158                         NULL,           /* class data */
159                         sizeof(ModestMsgEditWindow),
160                         1,              /* n_preallocs */
161                         (GInstanceInitFunc) modest_msg_edit_window_init,
162                         NULL
163                 };
164                 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
165                                                   "ModestMsgEditWindow",
166                                                   &my_info, 0);
167
168                 wp_text_buffer_library_init ();
169         }
170         return my_type;
171 }
172
173 static void
174 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
175 {
176         GObjectClass *gobject_class;
177         ModestWindowClass *modest_window_class;
178         gobject_class = (GObjectClass*) klass;
179         modest_window_class = (ModestWindowClass*) klass;
180
181         parent_class            = g_type_class_peek_parent (klass);
182         gobject_class->finalize = modest_msg_edit_window_finalize;
183
184         modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
185         modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
186         modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
187         modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
188
189         g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
190 }
191
192 static void
193 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
194 {
195         ModestMsgEditWindowPrivate *priv;
196         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
197
198         priv->msg_body      = NULL;
199         priv->from_field    = NULL;
200         priv->to_field      = NULL;
201         priv->cc_field      = NULL;
202         priv->bcc_field     = NULL;
203         priv->subject_field = NULL;
204         priv->attachments   = NULL;
205         priv->last_cid      = 0;
206         priv->zoom_level    = 1.0;
207
208         priv->cc_caption    = NULL;
209         priv->bcc_caption    = NULL;
210 }
211
212
213
214 static void
215 save_settings (ModestMsgEditWindow *self)
216 {
217         modest_widget_memory_save (modest_runtime_get_conf(),
218                                    G_OBJECT(self), "modest-edit-msg-window");
219 }
220
221
222 static void
223 restore_settings (ModestMsgEditWindow *self)
224 {
225         modest_widget_memory_restore (modest_runtime_get_conf(),
226                                       G_OBJECT(self), "modest-edit-msg-window");
227 }
228
229
230 /* FIXME: this is a dup from the one in gtk/ */
231 static ModestPairList*
232 get_transports (void)
233 {
234         ModestAccountMgr *account_mgr;
235         GSList *transports = NULL;
236         GSList *cursor, *accounts;
237         
238         account_mgr = modest_runtime_get_account_mgr();
239         cursor = accounts = modest_account_mgr_account_names (account_mgr); 
240         while (cursor) {
241                 gchar *account_name = (gchar*)cursor->data;
242                 gchar *from_string  = modest_account_mgr_get_from_string (account_mgr,
243                                                                           account_name);
244                 if (!from_string)  {
245                         /* something went wrong: ignore this one */
246                         g_free (account_name);
247                         cursor->data = NULL;
248                 } else {
249                         ModestPair *pair;
250                         pair = modest_pair_new ((gpointer) account_name,
251                                                 (gpointer) from_string , TRUE);
252                         transports = g_slist_prepend (transports, pair);
253                 } /* don't free account name; it's freed when the transports list is freed */
254                 cursor = cursor->next;
255         }
256         g_slist_free (accounts);
257         return transports;
258 }
259
260
261 static void
262 text_buffer_mark_set (GtkTextBuffer *buffer, GtkTextIter *iter, GtkTextMark *mark, gpointer userdata)
263 {
264         ModestMsgEditWindow *window;
265         ModestMsgEditWindowPrivate *priv;
266         GdkRectangle location;
267         gint v_scroll_min_value = 0;
268         gint v_scroll_max_value = 0;
269         gint v_scroll_visible;
270         GtkAdjustment *vadj;
271         GtkTextMark *insert_mark;
272         GtkTextIter insert_iter;
273         
274         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (userdata));
275         g_return_if_fail (GTK_IS_TEXT_MARK (mark));
276         window = MODEST_MSG_EDIT_WINDOW (userdata);
277         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
278                 
279         insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
280         gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &insert_iter, insert_mark);
281         gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &insert_iter, &location);
282         
283         if (priv->header_box)
284                 v_scroll_min_value += priv->header_box->allocation.height + DEFAULT_MAIN_VBOX_SPACING;
285         v_scroll_min_value += location.y;
286         v_scroll_max_value = v_scroll_min_value + location.height;
287         
288         v_scroll_visible = GTK_WIDGET (window)->allocation.height;
289         
290         vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
291         
292         if (((gdouble) v_scroll_min_value) < vadj->value)
293                 gtk_adjustment_set_value (vadj, v_scroll_min_value);
294         else if (((gdouble) v_scroll_max_value) > (vadj->value + vadj->page_size))
295                 gtk_adjustment_set_value (vadj, ((gdouble)v_scroll_max_value) - vadj->page_size);
296 }
297
298 static void
299 init_window (ModestMsgEditWindow *obj)
300 {
301         GtkWidget *from_caption, *to_caption, *subject_caption;
302         GtkWidget *main_vbox;
303         ModestMsgEditWindowPrivate *priv;
304         ModestPairList *protos;
305         GtkSizeGroup *size_group;
306
307         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
308
309         size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
310
311         protos = get_transports ();
312         priv->from_field    = modest_combo_box_new (protos, g_str_equal);
313         modest_pair_list_free (protos);
314
315         priv->to_field      = gtk_entry_new_with_max_length (80);
316         g_object_set (G_OBJECT (priv->to_field), "autocap", FALSE, NULL);
317         priv->cc_field      = gtk_entry_new_with_max_length (80);
318         g_object_set (G_OBJECT (priv->cc_field), "autocap", FALSE, NULL);
319         priv->bcc_field     = gtk_entry_new_with_max_length (80);
320         g_object_set (G_OBJECT (priv->bcc_field), "autocap", FALSE, NULL);
321         priv->subject_field = gtk_entry_new_with_max_length (80);
322         g_object_set (G_OBJECT (priv->subject_field), "autocap", TRUE, NULL);
323         gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field), SUBJECT_MAX_LENGTH);
324         
325         priv->header_box = gtk_vbox_new (FALSE, 0);
326         
327         from_caption = hildon_caption_new (size_group, _("From:"), priv->from_field, NULL, 0);
328         to_caption = hildon_caption_new (size_group, _("To:"), priv->to_field, NULL, 0);
329         priv->cc_caption = hildon_caption_new (size_group, _("Cc:"), priv->cc_field, NULL, 0);
330         priv->bcc_caption = hildon_caption_new (size_group, _("Bcc:"), priv->bcc_field, NULL, 0);
331         subject_caption = hildon_caption_new (size_group, _("Subject:"), priv->subject_field, NULL, 0);
332
333         gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
334         gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
335         gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
336         gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
337         gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
338
339
340         priv->msg_body = wp_text_view_new ();
341         gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
342         priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
343         g_object_set (priv->text_buffer, "font_scale", 1.0, NULL);
344         wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
345 /*      gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
346         wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
347         g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
348                           G_CALLBACK (text_buffer_refresh_attributes), obj);
349         g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
350                           G_CALLBACK (text_buffer_mark_set), obj);
351         g_signal_connect (G_OBJECT (obj), "window-state-event",
352                           G_CALLBACK (modest_msg_edit_window_window_state_event),
353                           NULL);
354
355         priv->scroll = gtk_scrolled_window_new (NULL, NULL);
356         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
357         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SCROLL_NONE);
358         
359         main_vbox = gtk_vbox_new  (FALSE, DEFAULT_MAIN_VBOX_SPACING);
360
361         gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
362         gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
363
364         gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
365         gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
366         gtk_widget_show_all (GTK_WIDGET(priv->scroll));
367         
368         if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL))
369                 gtk_widget_hide (priv->cc_field);
370         if (!modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL))
371                 gtk_widget_hide (priv->bcc_field);
372
373         gtk_container_add (GTK_CONTAINER(obj), priv->scroll);
374 }
375         
376
377
378 static void
379 modest_msg_edit_window_finalize (GObject *obj)
380 {
381         G_OBJECT_CLASS(parent_class)->finalize (obj);
382 }
383
384
385
386 static gboolean
387 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgEditWindow *self)
388 {
389         save_settings (self);
390         return FALSE;
391 }
392
393 static GtkWidget *
394 menubar_to_menu (GtkUIManager *ui_manager)
395 {
396         GtkWidget *main_menu;
397         GtkWidget *menubar;
398         GList *iter;
399
400         /* Create new main menu */
401         main_menu = gtk_menu_new();
402
403         /* Get the menubar from the UI manager */
404         menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
405
406         iter = gtk_container_get_children (GTK_CONTAINER (menubar));
407         while (iter) {
408                 GtkWidget *menu;
409
410                 menu = GTK_WIDGET (iter->data);
411                 gtk_widget_reparent(menu, main_menu);
412
413                 iter = g_list_next (iter);
414         }
415         return main_menu;
416 }
417
418
419 static void
420 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
421 {
422         TnyHeader *header;
423         const gchar *to, *cc, *bcc, *subject, *body;
424         ModestMsgEditWindowPrivate *priv;
425         
426         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
427         g_return_if_fail (TNY_IS_MSG (msg));
428
429         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
430
431         header = tny_msg_get_header (msg);
432         to      = tny_header_get_to (header);
433         cc      = tny_header_get_cc (header);
434         bcc     = tny_header_get_bcc (header);
435         subject = tny_header_get_subject (header);
436
437         if (to)
438                 gtk_entry_set_text (GTK_ENTRY(priv->to_field),  to);
439         if (cc)
440                 gtk_entry_set_text (GTK_ENTRY(priv->cc_field),  cc);
441         if (bcc)
442                 gtk_entry_set_text (GTK_ENTRY(priv->bcc_field), bcc);
443         if (subject)
444                 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);   
445
446 /*      gtk_text_buffer_set_can_paste_rich_text (priv->text_buffer, TRUE); */
447         wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
448         body = modest_tny_msg_get_body (msg, FALSE);
449         if ((body!=NULL) && (body[0] != '\0')) {
450                 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
451                 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
452                                                     (gchar *) body,
453                                                     -1);
454                 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
455         } else {
456                 WPTextBufferFormat fmt = {0};
457
458                 fmt.font_size = DEFAULT_FONT_SIZE;
459                 fmt.font = DEFAULT_FONT;
460                 fmt.rich_text = 1;
461                 fmt.text_position = TEXT_POSITION_NORMAL;
462                 fmt.justification = 0;
463                 fmt.cs.font_size = 1;
464                 fmt.cs.font = 1;
465                 fmt.cs.text_position = 1;
466                 fmt.cs.justification = 1;
467                 wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &fmt);
468         }
469
470         if (!to) {
471                 gtk_widget_grab_focus (priv->to_field);
472         } else {
473                 gtk_widget_grab_focus (priv->msg_body);
474         }
475
476         /* TODO: lower priority, select in the From: combo to the
477            value that comes from msg <- not sure, should it be
478            allowed? */
479         
480         /* TODO: set attachments */
481 }
482
483 static void
484 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
485 {
486         ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
487         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
488         GtkWidget *font_placeholder;
489         GtkWidget *tool_item;
490         gint insert_index;
491         gint size_index;
492         gint font_index;
493
494         /* Toolbar */
495         parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
496         hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
497
498         /* should we hide the toolbar? */
499         if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
500                 gtk_widget_hide (parent_priv->toolbar);
501
502         /* Font management toolbar elements */
503         font_placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
504         insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(font_placeholder));
505
506         /* font color */
507         tool_item = GTK_WIDGET (gtk_tool_item_new ());
508         priv->font_color_button = hildon_color_button_new ();
509         gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
510         gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
511         g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
512
513         /* font_size */
514         priv->size_combobox = gtk_combo_box_new_text ();
515         gtk_widget_set_size_request (priv->size_combobox, DEFAULT_SIZE_COMBOBOX_WIDTH, -1);
516         for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
517                 gchar size_text[5];
518                 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
519                 gtk_combo_box_append_text (GTK_COMBO_BOX (priv->size_combobox), size_text);
520         }
521         gtk_combo_box_set_active (GTK_COMBO_BOX (priv->size_combobox), wp_get_font_size_index(12, 4));
522         tool_item = GTK_WIDGET (gtk_tool_item_new ());
523         gtk_container_add (GTK_CONTAINER (tool_item), priv->size_combobox);
524         gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
525         g_signal_connect_swapped (G_OBJECT (priv->size_combobox), "changed", G_CALLBACK (modest_msg_edit_window_size_combobox_change), window);
526
527         priv->font_combobox = gtk_combo_box_new_text ();
528         for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
529                 gtk_combo_box_append_text (GTK_COMBO_BOX (priv->font_combobox), wp_get_font_name (font_index));
530         }
531         tool_item = GTK_WIDGET (gtk_tool_item_new ());
532         gtk_container_add (GTK_CONTAINER (tool_item), priv->font_combobox);
533         gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
534         g_signal_connect_swapped (G_OBJECT (priv->font_combobox), "changed", G_CALLBACK (modest_msg_edit_window_font_combobox_change), window);
535 }
536
537
538
539 ModestWindow*
540 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name)
541 {
542         GObject *obj;
543         ModestWindowPrivate *parent_priv;
544         ModestMsgEditWindowPrivate *priv;
545         GtkActionGroup *action_group;
546         GError *error = NULL;
547         GdkPixbuf *window_icon = NULL;
548
549         g_return_val_if_fail (msg, NULL);
550         
551         obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
552
553         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
554         parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
555
556         parent_priv->ui_manager = gtk_ui_manager_new();
557         action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
558
559         /* Add common actions */
560         gtk_action_group_add_actions (action_group,
561                                       modest_msg_edit_action_entries,
562                                       G_N_ELEMENTS (modest_msg_edit_action_entries),
563                                       obj);
564         gtk_action_group_add_toggle_actions (action_group,
565                                              modest_msg_edit_toggle_action_entries,
566                                              G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
567                                              obj);
568         gtk_action_group_add_radio_actions (action_group,
569                                             modest_msg_edit_alignment_radio_action_entries,
570                                             G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
571                                             GTK_JUSTIFY_LEFT,
572                                             G_CALLBACK (modest_ui_actions_on_change_justify),
573                                             obj);
574         gtk_action_group_add_radio_actions (action_group,
575                                             modest_msg_edit_zoom_action_entries,
576                                             G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
577                                             100,
578                                             G_CALLBACK (modest_ui_actions_on_change_zoom),
579                                             obj);
580         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
581         g_object_unref (action_group);
582
583         /* Load the UI definition */
584         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml", &error);
585         if (error != NULL) {
586                 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
587                 g_error_free (error);
588                 error = NULL;
589         }
590
591         /* Add accelerators */
592         gtk_window_add_accel_group (GTK_WINDOW (obj), 
593                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
594
595         /* Menubar */
596         parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
597         hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
598
599         /* Init window */
600         init_window (MODEST_MSG_EDIT_WINDOW(obj));
601
602         restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
603                 
604         gtk_window_set_title (GTK_WINDOW(obj), "Modest");
605         gtk_window_set_icon_from_file (GTK_WINDOW(obj), MODEST_APP_ICON, NULL);
606
607         g_signal_connect (G_OBJECT(obj), "delete-event",
608                           G_CALLBACK(on_delete_event), obj);
609
610         modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
611
612         modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
613
614         set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg);
615
616         text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
617
618         /* Set window icon */
619         window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
620         gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
621         
622         return (ModestWindow*)obj;
623 }
624
625 static gint
626 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
627 {
628         GString **string_buffer = (GString **) user_data;
629
630         *string_buffer = g_string_append (*string_buffer, buffer);
631    
632         return 0;
633 }
634
635 static gchar *
636 get_formatted_data (ModestMsgEditWindow *edit_window)
637 {
638         ModestMsgEditWindowPrivate *priv;
639         GString *string_buffer = g_string_new ("");
640         
641         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
642
643         wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
644
645         return g_string_free (string_buffer, FALSE);
646                                                                         
647 }
648
649 MsgData * 
650 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
651 {
652         MsgData *data;
653         const gchar *account_name;
654         GtkTextBuffer *buf;
655         GtkTextIter b, e;
656         ModestMsgEditWindowPrivate *priv;
657         
658         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
659
660         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
661                                                                         
662         account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
663         g_return_val_if_fail (account_name, NULL);
664         
665         buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));        
666         gtk_text_buffer_get_bounds (buf, &b, &e);
667         
668         /* don't free these (except from) */
669         data = g_slice_new0 (MsgData);
670         data->from    =  modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
671                                                              account_name);
672         data->to      =  (gchar*) gtk_entry_get_text (GTK_ENTRY(priv->to_field));
673         data->cc      =  (gchar*) gtk_entry_get_text (GTK_ENTRY(priv->cc_field));
674         data->bcc     =  (gchar*) gtk_entry_get_text (GTK_ENTRY(priv->bcc_field));
675         data->subject =  (gchar*) gtk_entry_get_text (GTK_ENTRY(priv->subject_field));  
676         data->plain_body =  (gchar *) gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE);
677         data->html_body  =  get_formatted_data (edit_window);
678         data->attachments = priv->attachments;
679
680         return data;
681 }
682
683 void 
684 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
685                                                       MsgData *data)
686 {
687         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
688
689         g_free (data->from);
690         g_free (data->html_body);
691         g_free (data->plain_body);
692         g_slice_free (MsgData, data);
693 }
694
695 ModestMsgEditFormat
696 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
697 {
698         gboolean rich_text;
699         ModestMsgEditWindowPrivate *priv = NULL;
700         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
701
702         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
703
704         rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
705         if (rich_text)
706                 return MODEST_MSG_EDIT_FORMAT_HTML;
707         else
708                 return MODEST_MSG_EDIT_FORMAT_TEXT;
709 }
710
711 void
712 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
713                                    ModestMsgEditFormat format)
714 {
715         ModestMsgEditWindowPrivate *priv;
716
717         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
718         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
719
720         switch (format) {
721         case MODEST_MSG_EDIT_FORMAT_HTML:
722                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
723                 break;
724         case MODEST_MSG_EDIT_FORMAT_TEXT:
725                 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
726                 break;
727         default:
728                 g_return_if_reached ();
729         }
730 }
731
732 ModestMsgEditFormatState *
733 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
734 {
735         ModestMsgEditFormatState *format_state = NULL;
736         ModestMsgEditWindowPrivate *priv;
737         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
738
739         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
740         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
741
742         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
743
744         format_state = g_new0 (ModestMsgEditFormatState, 1);
745         format_state->bold = buffer_format->bold&0x1;
746         format_state->italics = buffer_format->italic&0x1;
747         format_state->bullet = buffer_format->bullet&0x1;
748         format_state->color = buffer_format->color;
749         format_state->font_size = buffer_format->font_size;
750         format_state->font_family = wp_get_font_name (buffer_format->font);
751         format_state->justification = buffer_format->justification;
752         g_free (buffer_format);
753
754         return format_state;
755  
756 }
757
758 void
759 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
760                                          const ModestMsgEditFormatState *format_state)
761 {
762         ModestMsgEditWindowPrivate *priv;
763         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
764         WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
765         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
766         g_return_if_fail (format_state != NULL);
767
768         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
769         gtk_widget_grab_focus (priv->msg_body);
770         buffer_format->bold = (format_state->bold != FALSE);
771         buffer_format->italic = (format_state->italics != FALSE);
772         buffer_format->color = format_state->color;
773         buffer_format->font_size = format_state->font_size;
774         buffer_format->font = wp_get_font_index (format_state->font_family, 0);
775         buffer_format->justification = format_state->justification;
776         buffer_format->bullet = format_state->bullet;
777
778         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
779
780         buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
781         buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
782         buffer_format->cs.color = gdk_color_equal(&(buffer_format->color), &(current_format->color));
783         buffer_format->cs.font_size =  (buffer_format->font_size != current_format->font_size);
784         buffer_format->cs.font = (buffer_format->font != current_format->font);
785         buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
786         buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
787
788         wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
789         if (buffer_format->cs.bold) {
790                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
791         }
792         if (buffer_format->cs.italic) {
793                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
794         }
795         if (buffer_format->cs.color) {
796                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
797         }
798         if (buffer_format->cs.font_size) {
799                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font_size));
800         }
801         if (buffer_format->cs.justification) {
802                 switch (buffer_format->justification) {
803                 case GTK_JUSTIFY_LEFT:
804                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
805                         break;
806                 case GTK_JUSTIFY_CENTER:
807                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
808                         break;
809                 case GTK_JUSTIFY_RIGHT:
810                         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
811                         break;
812                 default:
813                         break;
814                 }
815                         
816         }
817         if (buffer_format->cs.font) {
818                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->font));
819         }
820         if (buffer_format->cs.bullet) {
821                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) (buffer_format->bullet));
822         }
823 /*      wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
824         wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
825
826         g_free (current_format);
827
828 }
829
830 static void
831 toggle_action_set_active_block_notify (GtkToggleAction *action,
832                                        gboolean value)
833 {
834         GSList *proxies = NULL;
835
836         for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
837              proxies != NULL; proxies = g_slist_next (proxies)) {
838                 GtkWidget *widget = (GtkWidget *) proxies->data;
839                 gtk_action_block_activate_from (GTK_ACTION (action), widget);
840         }
841
842         gtk_toggle_action_set_active (action, value);
843
844         for (proxies = gtk_action_get_proxies (GTK_ACTION (action));
845              proxies != NULL; proxies = g_slist_next (proxies)) {
846                 GtkWidget *widget = (GtkWidget *) proxies->data;
847                 gtk_action_unblock_activate_from (GTK_ACTION (action), widget);
848         }
849 }
850
851 static void
852 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
853 {
854         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
855         GtkAction *action;
856         ModestWindowPrivate *parent_priv;
857         ModestMsgEditWindowPrivate *priv;
858         
859         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
860         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
861
862         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
863         
864         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
865         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
866
867         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
868         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
869
870         action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBulletedList");
871         toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
872
873         g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button), 
874                                          G_CALLBACK (modest_msg_edit_window_color_button_change),
875                                          window);
876         hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
877         g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button), 
878                                            G_CALLBACK (modest_msg_edit_window_color_button_change),
879                                            window);
880
881         g_signal_handlers_block_by_func (G_OBJECT (priv->size_combobox), 
882                                          G_CALLBACK (modest_msg_edit_window_size_combobox_change),
883                                          window);
884         gtk_combo_box_set_active (GTK_COMBO_BOX (priv->size_combobox), buffer_format->font_size);
885         g_signal_handlers_unblock_by_func (G_OBJECT (priv->size_combobox), 
886                                            G_CALLBACK (modest_msg_edit_window_size_combobox_change),
887                                            window);
888
889         g_signal_handlers_block_by_func (G_OBJECT (priv->font_combobox), 
890                                          G_CALLBACK (modest_msg_edit_window_font_combobox_change),
891                                          window);
892         gtk_combo_box_set_active (GTK_COMBO_BOX (priv->font_combobox), buffer_format->font);
893         g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_combobox), 
894                                            G_CALLBACK (modest_msg_edit_window_font_combobox_change),
895                                            window);
896
897         g_free (buffer_format);
898
899 }
900
901 void
902 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
903 {
904         
905         WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
906         ModestMsgEditWindowPrivate *priv;
907         GtkWidget *dialog = NULL;
908         gint response;
909         const GdkColor *new_color = NULL;
910         
911         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
912         wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
913         
914         dialog = hildon_color_selector_new (GTK_WINDOW (window));
915         hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), & (buffer_format->color));
916         g_free (buffer_format);
917
918         response = gtk_dialog_run (GTK_DIALOG (dialog));
919         switch (response) {
920         case GTK_RESPONSE_OK:
921                 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
922                 break;
923         default:
924                 break;
925         }
926         gtk_widget_destroy (dialog);
927
928         if (new_color != NULL)
929                 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
930
931 }
932
933 void
934 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
935 {
936         
937         ModestMsgEditWindowPrivate *priv;
938         GtkWidget *dialog = NULL;
939         gint response;
940         const GdkColor *old_color = NULL;
941         const GdkColor *new_color = NULL;
942         
943         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
944         old_color = wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
945         
946         dialog = hildon_color_selector_new (GTK_WINDOW (window));
947         hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), (GdkColor *) old_color);
948
949         response = gtk_dialog_run (GTK_DIALOG (dialog));
950         switch (response) {
951         case GTK_RESPONSE_OK:
952                 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
953                 break;
954         default:
955                 break;
956         }
957         gtk_widget_destroy (dialog);
958
959         if (new_color != NULL)
960                 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
961
962 }
963
964 void
965 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
966 {
967         
968         ModestMsgEditWindowPrivate *priv;
969         GtkWidget *dialog = NULL;
970         gint response = 0;
971         gchar *filename = NULL;
972         
973         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
974         
975         dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
976
977         response = gtk_dialog_run (GTK_DIALOG (dialog));
978         switch (response) {
979         case GTK_RESPONSE_OK:
980                 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
981                 break;
982         default:
983                 break;
984         }
985         gtk_widget_destroy (dialog);
986
987         if (filename) {
988                 GdkPixbuf *pixbuf = NULL;
989                 GtkTextIter position;
990                 GtkTextMark *insert_mark;
991
992                 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
993                 if (pixbuf) {
994                         gint image_file_id;
995                         GdkPixbufFormat *pixbuf_format;
996
997                         image_file_id = g_open (filename, O_RDONLY, 0);
998                         pixbuf_format = gdk_pixbuf_get_file_info (filename, NULL, NULL);
999                         if ((image_file_id != -1)&&(pixbuf_format != NULL)) {
1000                                 TnyMimePart *image_part;
1001                                 TnyStream *image_stream;
1002                                 gchar **mime_types;
1003                                 gchar *mime_type;
1004                                 gchar *basename;
1005                                 gchar *content_id;
1006
1007                                 mime_types = gdk_pixbuf_format_get_mime_types (pixbuf_format);
1008                                 if ((mime_types != NULL) && (mime_types[0] != NULL)) {
1009                                         mime_type = mime_types[0];
1010                                 } else {
1011                                         mime_type = "image/unknown";
1012                                 }
1013                                 image_part = tny_platform_factory_new_mime_part
1014                                         (modest_runtime_get_platform_factory ());
1015                                 image_stream = TNY_STREAM (tny_fs_stream_new (image_file_id));
1016
1017                                 tny_mime_part_construct_from_stream (image_part, image_stream, mime_type);
1018                                 g_strfreev (mime_types);
1019
1020                                 content_id = g_strdup_printf ("%d", priv->last_cid);
1021                                 tny_mime_part_set_content_id (image_part, content_id);
1022                                 g_free (content_id);
1023                                 priv->last_cid++;
1024
1025                                 basename = g_path_get_basename (filename);
1026                                 tny_mime_part_set_filename (image_part, basename);
1027                                 g_free (basename);
1028                                 
1029                                 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1030                                 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1031                                 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (image_part)), pixbuf);
1032                                 priv->attachments = g_list_prepend (priv->attachments, image_part);
1033                         } else if (image_file_id == -1) {
1034                                 close (image_file_id);
1035                         }
1036                 }
1037         }
1038
1039
1040 }
1041
1042 static void
1043 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1044                                             gpointer userdata)
1045 {
1046         ModestMsgEditWindowPrivate *priv;
1047         GdkColor *new_color;
1048
1049         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1050         new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1051
1052         wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1053         gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1054
1055 }
1056
1057 static void
1058 modest_msg_edit_window_size_combobox_change (ModestMsgEditWindow *window,
1059                                              gpointer userdata)
1060 {
1061         ModestMsgEditWindowPrivate *priv;
1062         gint new_size_index;
1063
1064         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1065         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1066
1067         new_size_index = gtk_combo_box_get_active (GTK_COMBO_BOX (priv->size_combobox));
1068
1069         if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) new_size_index))
1070                 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1071
1072         text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));;
1073 }
1074
1075 static void
1076 modest_msg_edit_window_font_combobox_change (ModestMsgEditWindow *window,
1077                                              gpointer userdata)
1078 {
1079         ModestMsgEditWindowPrivate *priv;
1080         gint new_font_index;
1081
1082         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1083         gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1084
1085         new_font_index = gtk_combo_box_get_active (GTK_COMBO_BOX (priv->font_combobox));
1086
1087         if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) new_font_index))
1088                 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1089
1090         text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1091 }
1092
1093 static void
1094 modest_msg_edit_window_set_zoom (ModestWindow *window,
1095                                  gdouble zoom)
1096 {
1097         ModestMsgEditWindowPrivate *priv;
1098      
1099         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1100
1101         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1102         priv->zoom_level = zoom;
1103         wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom);
1104 }
1105
1106 static gdouble
1107 modest_msg_edit_window_get_zoom (ModestWindow *window)
1108 {
1109         ModestMsgEditWindowPrivate *priv;
1110      
1111         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
1112
1113         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1114         return priv->zoom_level;
1115 }
1116
1117 static gboolean
1118 modest_msg_edit_window_zoom_plus (ModestWindow *window)
1119 {
1120         ModestWindowPrivate *parent_priv;
1121         GtkRadioAction *zoom_radio_action;
1122         GSList *group, *node;
1123
1124         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1125         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1126                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1127
1128         group = gtk_radio_action_get_group (zoom_radio_action);
1129
1130         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
1131                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_max_zoom_level"));
1132                 return FALSE;
1133         }
1134
1135         for (node = group; node != NULL; node = g_slist_next (node)) {
1136                 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
1137                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
1138                         return TRUE;
1139                 }
1140         }
1141         return FALSE;
1142 }
1143
1144 static gboolean
1145 modest_msg_edit_window_zoom_minus (ModestWindow *window)
1146 {
1147         ModestWindowPrivate *parent_priv;
1148         GtkRadioAction *zoom_radio_action;
1149         GSList *group, *node;
1150
1151         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1152         zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, 
1153                                                                          "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
1154
1155         group = gtk_radio_action_get_group (zoom_radio_action);
1156
1157         for (node = group; node != NULL; node = g_slist_next (node)) {
1158                 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
1159                         if (node->next != NULL) {
1160                                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
1161                                 return TRUE;
1162                         } else
1163                                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_min_zoom_level"));
1164                         break;
1165                 }
1166         }
1167         return FALSE;
1168 }
1169
1170 static gboolean
1171 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1172 {
1173         if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1174                 ModestWindowPrivate *parent_priv;
1175                 ModestWindowMgr *mgr;
1176                 gboolean is_fullscreen;
1177                 GtkAction *fs_toggle_action;
1178                 gboolean active;
1179
1180                 mgr = modest_runtime_get_window_mgr ();
1181                 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1182
1183                 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1184                 
1185                 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1186                 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1187                 if (is_fullscreen != active)
1188                         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1189         }
1190
1191         return FALSE;
1192
1193 }
1194
1195 void
1196 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
1197 {
1198         ModestWindowPrivate *parent_priv;
1199         GtkAction *fs_toggle_action;
1200         gboolean active;
1201
1202         parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1203
1204         fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1205         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
1206         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
1207 }
1208
1209 void
1210 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window, 
1211                                 gboolean show)
1212 {
1213         ModestMsgEditWindowPrivate *priv = NULL;
1214         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1215
1216         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1217         if (show)
1218                 gtk_widget_show (priv->cc_caption);
1219         else
1220                 gtk_widget_hide (priv->cc_caption);
1221 }
1222
1223 void
1224 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window, 
1225                                  gboolean show)
1226 {
1227         ModestMsgEditWindowPrivate *priv = NULL;
1228         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1229
1230         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1231         if (show)
1232                 gtk_widget_show (priv->bcc_caption);
1233         else
1234                 gtk_widget_hide (priv->bcc_caption);
1235 }
1236