* src/gnome/modest-account-view-window.c:
[modest] / src / gnome / 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 #include <glib/gi18n.h>
30 #include <string.h>
31 #include <tny-account-store.h>
32 #include <tny-simple-list.h>
33 #include <modest-conf.h>
34 #include <modest-runtime.h>
35 #include <modest-tny-msg.h>
36
37 #include <widgets/modest-window-priv.h>
38 #include <widgets/modest-msg-edit-window.h>
39 #include <widgets/modest-msg-edit-window-ui.h>
40 #include <widgets/modest-combo-box.h>
41 #include <widgets/modest-attachments-view.h>
42
43 #include <modest-widget-memory.h>
44 #include <modest-account-mgr-helpers.h>
45 #include <modest-tny-folder.h>
46 #include <gtkhtml/gtkhtml.h>
47 #include "modest-msg-edit-window-ui-dimming.h"
48 #include <modest-platform.h>
49 #include <libgnomevfs/gnome-vfs-mime-utils.h>
50 #include <libgnomevfs/gnome-vfs.h>
51 #include <tny-vfs-stream.h>
52
53 static void  modest_msg_edit_window_class_init   (ModestMsgEditWindowClass *klass);
54 static void  modest_msg_edit_window_init         (ModestMsgEditWindow *obj);
55 static void  modest_msg_edit_window_finalize     (GObject *obj);
56
57 static void  modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
58                                                             ModestMsgEditWindow *window);
59 static void update_next_cid (ModestMsgEditWindow *self, TnyList *attachments);
60
61 /* list my signals */
62 enum {
63         /* MY_SIGNAL_1, */
64         /* MY_SIGNAL_2, */
65         LAST_SIGNAL
66 };
67
68 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
69 struct _ModestMsgEditWindowPrivate {
70
71         GtkWidget   *toolbar;
72         GtkWidget   *menubar;
73
74         GtkWidget   *msg_body;
75         
76         ModestPairList *from_field_protos;
77         GtkWidget   *from_field;
78         
79         GtkWidget   *to_field;
80         GtkWidget   *cc_field;
81         GtkWidget   *bcc_field;
82         GtkWidget   *subject_field;
83
84         GtkWidget   *attachments_view;
85         TnyList     *attachments;
86         guint       next_cid;
87
88         TnyMsg      *draft_msg;
89         TnyMsg      *outbox_msg;
90         gchar       *msg_uid;
91
92         gboolean    sent;
93 };
94
95 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
96                                                     MODEST_TYPE_MSG_EDIT_WINDOW, \
97                                                     ModestMsgEditWindowPrivate))
98 /* globals */
99 static GtkWindowClass *parent_class = NULL;
100
101 /* uncomment the following if you have defined any signals */
102 /* static guint signals[LAST_SIGNAL] = {0}; */
103
104 GType
105 modest_msg_edit_window_get_type (void)
106 {
107         static GType my_type = 0;
108         if (!my_type) {
109                 static const GTypeInfo my_info = {
110                         sizeof(ModestMsgEditWindowClass),
111                         NULL,           /* base init */
112                         NULL,           /* base finalize */
113                         (GClassInitFunc) modest_msg_edit_window_class_init,
114                         NULL,           /* class finalize */
115                         NULL,           /* class data */
116                         sizeof(ModestMsgEditWindow),
117                         1,              /* n_preallocs */
118                         (GInstanceInitFunc) modest_msg_edit_window_init,
119                         NULL
120                 };
121                 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
122                                                   "ModestMsgEditWindow",
123                                                   &my_info, 0);
124         }
125         return my_type;
126 }
127
128
129 static void
130 save_state (ModestWindow *self)
131 {
132         modest_widget_memory_save (modest_runtime_get_conf (),
133                                     G_OBJECT(self), "modest-edit-msg-window");
134 }
135
136
137 static void
138 restore_settings (ModestMsgEditWindow *self)
139 {
140         modest_widget_memory_restore (modest_runtime_get_conf (),
141                                       G_OBJECT(self), "modest-edit-msg-window");
142 }
143
144 static void
145 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
146 {
147         GObjectClass *gobject_class;
148         ModestWindowClass *modest_window_class;
149         
150         gobject_class = (GObjectClass*) klass;
151         modest_window_class = (ModestWindowClass*) klass;
152
153         parent_class            = g_type_class_peek_parent (klass);
154         gobject_class->finalize = modest_msg_edit_window_finalize;
155
156         g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
157
158         modest_window_class->save_state_func = save_state;
159 }
160
161 static void
162 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
163 {
164         ModestMsgEditWindowPrivate *priv;
165         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
166
167         priv->toolbar       = NULL;
168         priv->menubar       = NULL;
169         priv->msg_body      = NULL;
170         priv->from_field    = NULL;
171         priv->to_field      = NULL;
172         priv->cc_field      = NULL;
173         priv->bcc_field     = NULL;
174         priv->subject_field = NULL;
175         priv->attachments_view = NULL;
176         priv->attachments = TNY_LIST (tny_simple_list_new ());
177         priv->sent          = FALSE;
178         priv->next_cid      = 0;
179         priv->draft_msg = NULL;
180         priv->outbox_msg = NULL;
181         priv->msg_uid = NULL;
182 }
183
184 /** 
185  * @result: A ModestPairList, which must be freed with modest_pair_list_free().
186  */
187 static ModestPairList*
188 get_transports (void)
189 {
190         ModestAccountMgr *account_mgr;
191         GSList *transports = NULL;
192         GSList *cursor, *accounts;
193         
194         account_mgr = modest_runtime_get_account_mgr();
195         cursor = accounts = modest_account_mgr_account_names (account_mgr, TRUE);
196         while (cursor) {
197                 gchar *account_name = cursor->data ? g_strdup((gchar*)cursor->data) : NULL;
198                 gchar *from_string  = modest_account_mgr_get_from_string (account_mgr,
199                                                                           account_name);
200                 if (!from_string)  {
201                         /* something went wrong: ignore this one */
202                         g_free (account_name);
203                         cursor->data = NULL;
204                 } else {
205                         ModestPair *pair;
206                         pair = modest_pair_new ((gpointer) account_name,
207                                                 (gpointer) from_string , TRUE);
208                         transports = g_slist_prepend (transports, pair);
209                 } /* don't free account name; it's freed when the transports list is freed */
210                 cursor = cursor->next;
211         }
212         g_slist_free (accounts);
213         return transports;
214 }
215
216
217 static void
218 on_from_combo_changed (ModestComboBox *combo, ModestWindow *win)
219 {
220         modest_window_set_active_account (
221                 win, modest_combo_box_get_active_id(combo));
222 }
223
224
225
226 static void
227 init_window (ModestMsgEditWindow *obj, const gchar* account)
228 {
229         GtkWidget *to_button, *cc_button, *bcc_button, *add_attachment_button; 
230         GtkWidget *header_table;
231         GtkWidget *main_vbox;
232         GtkWidget *msg_vbox;
233         GtkWidget *scrolled_window;
234         ModestMsgEditWindowPrivate *priv;
235         ModestWindowPrivate *parent_priv;
236         
237         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
238         parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
239
240         to_button     = gtk_button_new_with_label (_("To..."));
241         cc_button     = gtk_button_new_with_label (_("Cc..."));
242         bcc_button    = gtk_button_new_with_label (_("Bcc..."));
243         add_attachment_button = gtk_button_new_with_label (_("Attach..."));
244         
245         /* Note: This ModestPairList* must exist for as long as the combo
246          * that uses it, because the ModestComboBox uses the ID opaquely, 
247          * so it can't know how to manage its memory. */ 
248         priv->from_field_protos = get_transports ();
249         priv->from_field    = modest_combo_box_new (priv->from_field_protos, g_str_equal);
250         
251         if (account) {
252                 modest_combo_box_set_active_id (MODEST_COMBO_BOX(priv->from_field),
253                                                 (gpointer)account);
254                 modest_window_set_active_account (MODEST_WINDOW(obj), account);
255         }
256         /* auto-update the active account */
257         g_signal_connect (G_OBJECT(priv->from_field), "changed", G_CALLBACK(on_from_combo_changed), obj);
258         
259         priv->to_field      = gtk_entry_new_with_max_length (80);
260         priv->cc_field      = gtk_entry_new_with_max_length (80);
261         priv->bcc_field     = gtk_entry_new_with_max_length (80);
262         priv->subject_field = gtk_entry_new_with_max_length (80);
263         priv->attachments_view = modest_attachments_view_new (NULL);
264         
265         header_table = gtk_table_new (6,2, FALSE);
266         
267         gtk_table_attach (GTK_TABLE(header_table), gtk_label_new (_("From:")),
268                           0,1,0,1, GTK_FILL, 0, 0, 0);
269         gtk_table_attach (GTK_TABLE(header_table), to_button,     0,1,1,2, GTK_FILL, 0, 0, 0);
270         gtk_table_attach (GTK_TABLE(header_table), cc_button,     0,1,2,3, GTK_FILL, 0, 0, 0);
271         gtk_table_attach (GTK_TABLE(header_table), bcc_button,    0,1,3,4, GTK_FILL, 0, 0, 0);
272         gtk_table_attach (GTK_TABLE(header_table), gtk_label_new (_("Subject:")),
273                           0,1,4,5, GTK_FILL, 0, 0, 0);
274         gtk_table_attach (GTK_TABLE(header_table), add_attachment_button, 0, 1, 5, 6, GTK_FILL, 0, 0, 0);
275
276         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->from_field,   1,2,0,1);
277         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->to_field,     1,2,1,2);
278         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->cc_field,     1,2,2,3);
279         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->bcc_field,    1,2,3,4);
280         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->subject_field,1,2,4,5);
281         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->attachments_view,1,2,5,6);
282
283         priv->msg_body = gtk_html_new ();
284         gtk_html_load_empty (GTK_HTML (priv->msg_body));
285         gtk_html_set_editable (GTK_HTML (priv->msg_body), TRUE);
286         
287         main_vbox = gtk_vbox_new  (FALSE, 0);
288
289         scrolled_window = gtk_scrolled_window_new (NULL, NULL);
290         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), 
291                                         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
292         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
293
294         gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
295         gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
296         
297         msg_vbox = gtk_vbox_new (FALSE, 0);
298         gtk_box_pack_start (GTK_BOX (main_vbox), msg_vbox, TRUE, TRUE, 0);
299
300         gtk_box_pack_start (GTK_BOX(msg_vbox), header_table, FALSE, FALSE, 0);
301         gtk_container_add (GTK_CONTAINER (scrolled_window), priv->msg_body); 
302
303         gtk_box_pack_start (GTK_BOX(msg_vbox), scrolled_window, TRUE, TRUE, 0);
304
305         gtk_widget_show_all (GTK_WIDGET(main_vbox));
306         gtk_container_add (GTK_CONTAINER(obj), main_vbox);
307
308         g_signal_connect_object (add_attachment_button, "clicked", 
309                                  G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), G_OBJECT (obj), 0);
310 }
311
312
313 static void
314 modest_msg_edit_window_finalize (GObject *obj)
315 {
316         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
317         
318         /* These had to stay alive for as long as the comboboxes that used them: */
319         modest_pair_list_free (priv->from_field_protos);
320         g_object_unref (priv->attachments);
321         priv->attachments = NULL;
322
323         if (priv->draft_msg != NULL) {
324                 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
325                 if (TNY_IS_HEADER (header)) {
326                         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
327                         modest_window_mgr_unregister_header (mgr, header);
328                 }
329                 g_object_unref (priv->draft_msg);
330                 priv->draft_msg = NULL;
331         }
332         if (priv->outbox_msg != NULL) {
333                 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
334                 if (TNY_IS_HEADER (header)) {
335                         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
336                         modest_window_mgr_unregister_header (mgr, header);
337                 }
338                 g_object_unref (priv->outbox_msg);
339                 priv->outbox_msg = NULL;
340         }
341         g_free (priv->msg_uid);
342         
343         G_OBJECT_CLASS(parent_class)->finalize (obj);
344 }
345
346 static void
347 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
348 {
349         TnyIterator *iter;
350         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
351
352         for (iter = tny_list_create_iterator (attachments) ; 
353              !tny_iterator_is_done (iter);
354              tny_iterator_next (iter)) {
355                 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
356                 const gchar *cid = tny_mime_part_get_content_id (part);
357                 if (cid != NULL) {
358                         char *invalid = NULL;
359                         gint int_cid = strtol (cid, &invalid, 10);
360                         if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
361                                 priv->next_cid = int_cid + 1;
362                         }
363                 }
364                 g_object_unref (part);
365         }
366         g_object_unref (iter);
367 }
368
369
370
371 static gboolean
372 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgEditWindow *self)
373 {
374         modest_window_save_state (MODEST_WINDOW(self));
375         return FALSE;
376 }
377
378
379 static void
380 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
381 {
382         TnyHeader *header;
383         TnyFolder *msg_folder;
384         const gchar *to, *cc, *bcc, *subject;
385         ModestMsgEditWindowPrivate *priv;
386         gchar *body;
387         
388         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
389         g_return_if_fail (TNY_IS_MSG (msg));
390
391         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
392
393         header  = tny_msg_get_header (msg);
394         to      = tny_header_get_to (header);
395         cc      = tny_header_get_cc (header);
396         bcc     = tny_header_get_bcc (header);
397         subject = tny_header_get_subject (header);
398
399         if (to)
400                 gtk_entry_set_text (GTK_ENTRY(priv->to_field), to);
401         if (cc)
402                 gtk_entry_set_text (GTK_ENTRY(priv->cc_field), cc);
403         if (bcc)
404                 gtk_entry_set_text (GTK_ENTRY(priv->bcc_field),  bcc);
405         if (subject)
406                 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
407
408         modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
409         priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
410         update_next_cid (self, priv->attachments);
411
412         body = modest_tny_msg_get_body (msg, FALSE, NULL);
413         gtk_html_set_editable (GTK_HTML (priv->msg_body), FALSE);
414         if (body) {
415                 gtk_html_load_from_string (GTK_HTML (priv->msg_body), body, -1);
416         }
417         gtk_html_set_editable (GTK_HTML (priv->msg_body), TRUE);
418         g_free (body);
419
420         modest_msg_edit_window_set_modified (self, FALSE);
421
422         if (priv->msg_uid) {
423                 g_free (priv->msg_uid);
424                 priv->msg_uid = NULL;
425         }
426
427         /* we should set a reference to the incoming message if it is a draft */
428         msg_folder = tny_msg_get_folder (msg);
429         if (msg_folder) {               
430                 if (modest_tny_folder_is_local_folder (msg_folder)) {
431                         TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
432                         if (type == TNY_FOLDER_TYPE_INVALID)
433                                 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
434                         
435                         if (type == TNY_FOLDER_TYPE_DRAFTS) 
436                                 priv->draft_msg = g_object_ref(msg);
437                         if (type == TNY_FOLDER_TYPE_OUTBOX)
438                                 priv->outbox_msg = g_object_ref(msg);
439                         priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
440                 }
441                 g_object_unref (msg_folder);
442         }
443 }
444
445
446 ModestWindow *
447 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account,
448                             gboolean preserve_is_rich)
449 {
450         ModestMsgEditWindow *self;
451         ModestMsgEditWindowPrivate *priv;
452         ModestWindowPrivate *parent_priv;
453         GtkActionGroup *action_group;
454         ModestDimmingRulesGroup *menu_rules_group = NULL;
455         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
456         ModestDimmingRulesGroup *clipboard_rules_group = NULL;
457         GError *error = NULL;
458
459         g_return_val_if_fail (msg, NULL);
460         
461         self = MODEST_MSG_EDIT_WINDOW(g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL));
462         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(self);
463         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
464         
465         parent_priv->ui_manager = gtk_ui_manager_new();
466         action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
467         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
468
469         /* Add common actions */
470         gtk_action_group_add_actions (action_group,
471                                       modest_msg_edit_action_entries,
472                                       G_N_ELEMENTS (modest_msg_edit_action_entries),
473                                       self);
474         gtk_action_group_add_toggle_actions (action_group,
475                                              modest_msg_edit_toggle_action_entries,
476                                              G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
477                                              self);
478         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
479         g_object_unref (action_group);
480
481         /* Load the UI definition */
482         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
483                                          MODEST_UIDIR "modest-msg-edit-window-ui.xml",
484                                          &error);
485         if (error) {
486                 g_printerr ("modest: could not merge modest-msg-edit-window-ui.xml: %s\n", error->message);
487                 g_error_free (error);
488                 error = NULL;
489         }
490         /* ****** */
491
492         /* Add accelerators */
493         gtk_window_add_accel_group (GTK_WINDOW (self), 
494                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
495
496         /* Toolbar / Menubar */
497         priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
498         priv->menubar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar");
499
500         gtk_toolbar_set_tooltips (GTK_TOOLBAR (priv->toolbar), TRUE);
501
502         /* Init window */
503         init_window (MODEST_MSG_EDIT_WINDOW(self), account);
504
505         restore_settings (MODEST_MSG_EDIT_WINDOW(self));
506         
507         gtk_window_set_title (GTK_WINDOW(self), "Modest");
508         gtk_window_set_icon_from_file (GTK_WINDOW(self), MODEST_APP_ICON, NULL);
509
510         g_signal_connect (G_OBJECT(self), "delete-event",
511                           G_CALLBACK(on_delete_event), self);
512         
513         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
514         menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
515         toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
516         clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
517
518         /* Add common dimming rules */
519         modest_dimming_rules_group_add_rules (menu_rules_group, 
520                                               modest_msg_edit_window_menu_dimming_entries,
521                                               G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
522                                               MODEST_WINDOW (self));
523         modest_dimming_rules_group_add_rules (toolbar_rules_group, 
524                                               modest_msg_edit_window_toolbar_dimming_entries,
525                                               G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
526                                               MODEST_WINDOW (self));
527 /*      modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button, */
528 /*                                                  G_CALLBACK (modest_ui_dimming_rules_on_set_style), */
529 /*                                                  MODEST_WINDOW (self)); */
530 /*      modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem, */
531 /*                                                  G_CALLBACK (modest_ui_dimming_rules_on_set_style), */
532 /*                                                  MODEST_WINDOW (self)); */
533 /*      modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem, */
534 /*                                                  G_CALLBACK (modest_ui_dimming_rules_on_set_style), */
535 /*                                                  MODEST_WINDOW (self)); */
536         modest_dimming_rules_group_add_rules (clipboard_rules_group, 
537                                               modest_msg_edit_window_clipboard_dimming_entries,
538                                               G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
539                                               MODEST_WINDOW (self));
540         /* Insert dimming rules group for this window */
541         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
542         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
543         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
544         /* Checks the dimming rules */
545         g_object_unref (menu_rules_group);
546         g_object_unref (toolbar_rules_group);
547         g_object_unref (clipboard_rules_group);
548
549         set_msg (self, msg);
550         
551         return MODEST_WINDOW(self);
552 }
553
554 static gboolean
555 html_export_save_buffer (gpointer engine,
556                          const gchar *data,
557                          size_t len,
558                          GString **buffer)
559 {
560         *buffer = g_string_append (*buffer, data);
561         return TRUE;
562 }
563
564
565 MsgData * 
566 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
567 {
568         MsgData *data;
569         
570         const gchar *account_name;
571         gchar *from_string = NULL;
572         ModestMsgEditWindowPrivate *priv;
573         GString *buffer;
574         TnyIterator *att_iter;
575         
576         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
577
578         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
579         
580         account_name = (gchar*)modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
581         if (account_name) 
582                 from_string = modest_account_mgr_get_from_string (
583                         modest_runtime_get_account_mgr(), account_name);
584         if (!from_string) {
585                 g_printerr ("modest: cannot get from string\n");
586                 return NULL;
587         }
588         
589         
590         
591         data = g_slice_new0 (MsgData);
592         data->from    =  from_string; /* will be freed when data is freed */
593         data->to      =  g_strdup ( gtk_entry_get_text (GTK_ENTRY(priv->to_field)));
594         data->cc      =  g_strdup ( gtk_entry_get_text (GTK_ENTRY(priv->cc_field)));
595         data->bcc     =  g_strdup ( gtk_entry_get_text (GTK_ENTRY(priv->bcc_field)));
596         data->subject =  g_strdup ( gtk_entry_get_text (GTK_ENTRY(priv->subject_field)));
597
598 /*      GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)); */
599 /*      GtkTextIter b, e; */
600 /*      gtk_text_buffer_get_bounds (buf, &b, &e); */
601 /*      data->plain_body =  gtk_text_buffer_get_text (buf, &b, &e, FALSE); /\* Returns a copy. *\/ */
602
603         buffer = g_string_new ("");
604         gtk_html_export (GTK_HTML (priv->msg_body), "text/html", (GtkHTMLSaveReceiverFn) html_export_save_buffer, &buffer);
605         data->html_body = g_string_free (buffer, FALSE);
606         buffer = g_string_new ("");
607         gtk_html_export (GTK_HTML (priv->msg_body), "text/plain", (GtkHTMLSaveReceiverFn) html_export_save_buffer, &buffer);
608         data->plain_body = g_string_free (buffer, FALSE);
609
610         /* deep-copy the attachment data */
611         att_iter = tny_list_create_iterator (priv->attachments);
612         data->attachments = NULL;
613         while (!tny_iterator_is_done (att_iter)) {
614                 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
615                 if (!(TNY_IS_MIME_PART(part))) {
616                         g_warning ("strange data in attachment list");
617                         g_object_unref (part);
618                         tny_iterator_next (att_iter);
619                         continue;
620                 }
621                 data->attachments = g_list_append (data->attachments,
622                                                    part);
623                 tny_iterator_next (att_iter);
624         }
625         g_object_unref (att_iter);
626
627
628         if (priv->draft_msg) {
629                 data->draft_msg = g_object_ref (priv->draft_msg);
630         } else if (priv->outbox_msg) {
631                 data->draft_msg = g_object_ref (priv->outbox_msg);
632         } else {
633                 data->draft_msg = NULL;
634         }
635         return data;
636 }
637
638 static void
639 unref_gobject (GObject *obj, gpointer data)
640 {
641         if (!G_IS_OBJECT(obj))
642                 return;
643         g_object_unref (obj);
644 }
645
646 void 
647 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
648                                       MsgData *data)
649 {
650         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
651
652         if (!data)
653                 return;
654
655         g_free (data->to);
656         g_free (data->cc);
657         g_free (data->bcc);
658         g_free (data->subject);
659         g_free (data->plain_body);
660         g_free (data->html_body);
661
662         if (data->draft_msg != NULL) {
663                 g_object_unref (data->draft_msg);
664                 data->draft_msg = NULL;
665         }       
666         
667         g_list_foreach (data->attachments, (GFunc)unref_gobject,  NULL);
668         g_list_free (data->attachments);
669
670         g_slice_free (MsgData, data);
671 }
672
673 /* Rich formatting API functions */
674 ModestMsgEditFormat
675 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
676 {
677         return MODEST_MSG_EDIT_FORMAT_TEXT;
678 }
679
680 void
681 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
682                                    ModestMsgEditFormat format)
683 {
684         switch (format) {
685         case MODEST_MSG_EDIT_FORMAT_TEXT:
686                 break;
687         case MODEST_MSG_EDIT_FORMAT_HTML:
688                 g_message ("HTML format not supported in Gnome ModestMsgEditWindow");
689                 break;
690         default:
691                 break;
692         }
693 }
694
695 ModestMsgEditFormatState *
696 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
697 {
698         ModestMsgEditFormatState *format_state;
699
700         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
701
702         format_state = g_new0 (ModestMsgEditFormatState, 1);
703
704         return format_state;
705 }
706
707 void
708 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self, 
709                                          const ModestMsgEditFormatState *format_state)
710 {
711         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (self));
712
713         /* Ends silently as set_format_state should do nothing when edit window format
714            is not HTML */
715         return;
716 }
717
718 void
719 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
720 {
721         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
722
723         g_message ("Select color operation is not supported");
724 }
725
726 void
727 modest_msg_edit_window_select_file_format (ModestMsgEditWindow *window,
728                                            gint file_format)
729 {
730         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
731
732         g_message ("Select file format operation is not supported");
733 }
734
735 void
736 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
737 {
738         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
739
740         g_message ("Select font operation is not supported");
741 }
742
743 void
744 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
745 {
746         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
747
748         g_message ("Select background color operation is not supported");
749 }
750
751 void
752 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
753 {
754         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
755
756         g_message ("Insert image operation is not supported");
757 }
758
759 void
760 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
761 {
762         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
763
764         g_message ("Attach file operation is not supported");
765 }
766
767 void
768 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
769                                            TnyList *att_list)
770 {
771         ModestMsgEditWindowPrivate *priv;
772         TnyIterator *iter;
773
774         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
775         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
776
777         if (att_list == NULL) {
778                 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
779         } else {
780                 g_object_ref (att_list);
781         }
782
783         if (tny_list_get_length (att_list) == 0) {
784                 modest_platform_information_banner (NULL, NULL, _("TODO: no attachments selected to remove"));
785         } else {
786                 GtkWidget *confirmation_dialog = NULL;
787                 gboolean dialog_response;
788                 gchar *message = NULL;
789                 gchar *filename = NULL;
790
791                 if (tny_list_get_length (att_list) == 1) {
792                         TnyMimePart *part;
793                         iter = tny_list_create_iterator (att_list);
794                         part = (TnyMimePart *) tny_iterator_get_current (iter);
795                         g_object_unref (iter);
796                         if (TNY_IS_MSG (part)) {
797                                 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
798                                 if (header) {
799                                         filename = g_strdup (tny_header_get_subject (header));
800                                         g_object_unref (header);
801                                 }
802                                 if (filename == NULL) {
803                                         filename = g_strdup (_("mail_va_no_subject"));
804                                 }
805                         } else {
806                                 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
807                         }
808                         g_object_unref (part);
809                 } else {
810                         filename = g_strdup ("");
811                 }
812                 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
813                                                     (tny_list_get_length (att_list) == 1)), filename);
814                 g_free (filename);
815                 confirmation_dialog = gtk_message_dialog_new (GTK_WINDOW (window), 
816                                                               GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, 
817                                                               GTK_MESSAGE_QUESTION,
818                                                               GTK_BUTTONS_OK_CANCEL,
819                                                               message);
820                 g_free (message);
821                 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
822                 gtk_widget_destroy (confirmation_dialog);
823                 if (!dialog_response) {
824                         g_object_unref (att_list);
825                         return;
826                 }
827                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
828                 
829                 for (iter = tny_list_create_iterator (att_list);
830                      !tny_iterator_is_done (iter);
831                      tny_iterator_next (iter)) {
832                         TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
833                         tny_list_remove (priv->attachments, (GObject *) mime_part);
834
835                         modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
836                                                                    mime_part);
837                         g_object_unref (mime_part);
838                 }
839                 g_object_unref (iter);
840         }
841
842         g_object_unref (att_list);
843
844 }
845
846 static void
847 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
848                                                ModestMsgEditWindow *window)
849 {
850         modest_msg_edit_window_offer_attach_file (window);
851 }
852
853 void 
854 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
855                                        gint *parts_count,
856                                        guint64 *parts_size)
857 {
858         ModestMsgEditWindowPrivate *priv;
859
860         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
861
862         modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
863
864 }
865
866 void
867 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window, 
868                                 gboolean show)
869 {
870         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
871
872         g_message ("not implemented yet %s", __FUNCTION__);
873 }
874 void
875 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window, 
876                                 gboolean show)
877 {
878         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
879
880         g_message ("not implemented yet %s", __FUNCTION__);
881 }
882 void
883 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
884 {
885         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
886       
887         g_message ("not implemented yet %s", __FUNCTION__);
888 }
889 void
890 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
891 {
892         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
893       
894         g_message ("not implemented yet %s", __FUNCTION__);
895 }
896 void
897 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
898                                            TnyHeaderFlags priority_flags)
899 {
900         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
901       
902         g_message ("not implemented yet %s", __FUNCTION__);
903 }
904
905
906 void
907 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
908 {
909         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
910
911         g_message ("not implemented yet %s", __FUNCTION__);
912 }
913
914 gboolean
915 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
916 {
917         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
918
919         g_message ("not implemented yet %s", __FUNCTION__);
920         return TRUE;
921 }
922
923 void
924 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
925                                         gint file_format)
926 {
927         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
928
929         g_message ("not implemented yet %s", __FUNCTION__);
930 }
931
932 gboolean 
933 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
934 {
935         ModestMsgEditWindowPrivate *priv;
936
937         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
938         return priv->sent;
939 }
940
941 void 
942 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window, 
943                                  gboolean sent)
944 {
945         ModestMsgEditWindowPrivate *priv;
946
947         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
948         priv->sent = sent;
949 }
950
951 GtkWidget *
952 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
953                                          ModestMsgEditWindowWidgetType widget_type)
954 {
955         ModestMsgEditWindowPrivate *priv;
956
957         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
958         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
959
960         switch (widget_type) {
961         case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
962                 return priv->msg_body;
963                 break;
964         case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
965                 return priv->to_field;
966                 break;
967         case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
968                 return priv->cc_field;
969                 break;
970         case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
971                 return priv->bcc_field;
972                 break;
973         case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
974                 return priv->subject_field;
975                 break;
976         case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
977                 return priv->attachments_view;
978                 break;
979         default:
980                 return NULL;
981         }
982         return NULL;
983 }
984
985 /* FUNCTIONS NOT IMPLEMENTED YET */
986
987 void            
988 modest_msg_edit_window_set_modified      (ModestMsgEditWindow *window,
989                                           gboolean modified)
990 {
991         g_message (__FUNCTION__);
992 }
993
994 void            
995 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
996                                             gboolean show)
997 {
998         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
999 }
1000
1001 void                    
1002 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
1003                                  TnyMimePart *part)
1004 {
1005         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1006
1007         g_return_if_fail (TNY_IS_MIME_PART (part));
1008         tny_list_prepend (priv->attachments, (GObject *) part);
1009         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
1010 }
1011
1012 void            
1013 modest_msg_edit_window_redo               (ModestMsgEditWindow *window)
1014 {
1015         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
1016 }
1017
1018 void                    
1019 modest_msg_edit_window_offer_attach_file           (ModestMsgEditWindow *window)
1020 {
1021         GtkWidget *dialog = NULL;
1022         gint response = 0;
1023         GSList *uris = NULL;
1024         GSList *uri_node;
1025         
1026         dialog = gtk_file_chooser_dialog_new (_("mcen_ti_select_attachment_title"), 
1027                                               GTK_WINDOW (window), 
1028                                               GTK_FILE_CHOOSER_ACTION_OPEN,
1029                                               GTK_STOCK_OPEN,
1030                                               GTK_RESPONSE_OK,
1031                                               GTK_STOCK_CANCEL,
1032                                               GTK_RESPONSE_CANCEL,
1033                                               NULL);
1034
1035         response = gtk_dialog_run (GTK_DIALOG (dialog));
1036         switch (response) {
1037         case GTK_RESPONSE_OK:
1038                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1039                 break;
1040         default:
1041                 break;
1042         }
1043         gtk_widget_destroy (dialog);
1044
1045         for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1046                 const gchar *uri = (const gchar *) uri_node->data;
1047                 modest_msg_edit_window_attach_file_one (window, uri);
1048         }
1049         g_slist_foreach (uris, (GFunc) g_free, NULL);
1050         g_slist_free (uris);
1051 }
1052
1053 void                    
1054 modest_msg_edit_window_attach_file_one           (ModestMsgEditWindow *window, const gchar *uri)
1055 {
1056         GnomeVFSHandle *handle = NULL;
1057         ModestMsgEditWindowPrivate *priv;
1058         GnomeVFSResult result;
1059
1060         g_return_if_fail (window);
1061         g_return_if_fail (uri);
1062                 
1063         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1064         
1065         result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1066         if (result == GNOME_VFS_OK) {
1067                 TnyMimePart *mime_part;
1068                 TnyStream *stream;
1069                 const gchar *mime_type = NULL;
1070                 gchar *basename;
1071                 gchar *escaped_filename;
1072                 gchar *filename;
1073                 gchar *content_id;
1074                 GnomeVFSFileInfo *info;
1075                 GnomeVFSURI *vfs_uri;
1076
1077                 vfs_uri = gnome_vfs_uri_new (uri);
1078
1079                 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1080                 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1081                 g_free (escaped_filename);
1082                 gnome_vfs_uri_unref (vfs_uri);
1083
1084                 info = gnome_vfs_file_info_new ();
1085                 
1086                 if (gnome_vfs_get_file_info (uri, 
1087                                              info, 
1088                                              GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
1089                     == GNOME_VFS_OK)
1090                         mime_type = gnome_vfs_file_info_get_mime_type (info);
1091                 mime_part = tny_platform_factory_new_mime_part
1092                         (modest_runtime_get_platform_factory ());
1093                 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1094                 
1095                 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
1096
1097                 g_object_unref (stream);
1098                 
1099                 content_id = g_strdup_printf ("%d", priv->next_cid);
1100                 tny_mime_part_set_content_id (mime_part, content_id);
1101                 g_free (content_id);
1102                 priv->next_cid++;
1103                 
1104                 basename = g_path_get_basename (filename);
1105                 tny_mime_part_set_filename (mime_part, basename);
1106                 g_free (basename);
1107                 
1108                 tny_list_prepend (priv->attachments, (GObject *) mime_part);
1109                 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1110                                                         mime_part,
1111                                                         info->size == 0, info->size);
1112                 g_free (filename);
1113                 g_object_unref (mime_part);
1114                 gnome_vfs_file_info_unref (info);
1115         }
1116 }
1117
1118 void            
1119 modest_msg_edit_window_set_draft           (ModestMsgEditWindow *window,
1120                                             TnyMsg *draft)
1121 {
1122         ModestMsgEditWindowPrivate *priv;
1123         TnyHeader *header = NULL;
1124
1125         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1126         g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
1127
1128         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1129         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1130
1131         if (priv->draft_msg != NULL) {
1132                 g_object_unref (priv->draft_msg);
1133         }
1134
1135         if (draft != NULL) {
1136                 g_object_ref (draft);
1137                 header = tny_msg_get_header (draft);
1138                 if (priv->msg_uid) {
1139                         g_free (priv->msg_uid);
1140                         priv->msg_uid = NULL;
1141                 }
1142                 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1143                 if (GTK_WIDGET_REALIZED (window))
1144                         modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
1145         }
1146
1147         priv->draft_msg = draft;
1148 }
1149
1150 gboolean        
1151 modest_msg_edit_window_is_modified         (ModestMsgEditWindow *window)
1152 {
1153         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
1154         return TRUE;
1155 }
1156
1157 const gchar *
1158 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
1159 {
1160         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
1161         return NULL;
1162 }
1163
1164 gboolean            
1165 modest_msg_edit_window_can_redo               (ModestMsgEditWindow *window)
1166 {
1167         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
1168         return FALSE;
1169 }
1170 gboolean            
1171 modest_msg_edit_window_can_undo               (ModestMsgEditWindow *window)
1172 {
1173         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
1174         return FALSE;
1175 }
1176
1177 const gchar*    
1178 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
1179 {
1180         ModestMsgEditWindowPrivate *priv;
1181
1182         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);        
1183         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1184
1185         return priv->msg_uid;
1186 }