* src/modest-text-utils.[ch]:
[modest] / src / maemo / modest-msg-edit-window.c
index 3b15b43..96eb886 100644 (file)
@@ -35,6 +35,7 @@
 #include <tny-account-store.h>
 #include <tny-fs-stream.h>
 #include <tny-vfs-stream.h>
+#include <tny-camel-mem-stream.h>
 
 #include <config.h>
 
@@ -180,12 +181,6 @@ static void text_buffer_mark_set (GtkTextBuffer *buffer,
 void vadj_changed (GtkAdjustment *adj, 
                   ModestMsgEditWindow *window);
 
-static ModestPair *find_transport_from_message_sender (ModestPairList *transports,
-                                                      TnyMsg *msg);
-
-
-
-
 static void DEBUG_BUFFER (WPTextBuffer *buffer)
 {
 #ifdef DEBUG
@@ -246,7 +241,7 @@ struct _ModestMsgEditWindowPrivate {
        
        ModestPairList *from_field_protos;
        GtkWidget   *from_field;
-       const gchar *original_account_name;
+       gchar       *original_account_name;
        
        GtkWidget   *to_field;
        GtkWidget   *cc_field;
@@ -274,6 +269,8 @@ struct _ModestMsgEditWindowPrivate {
        GtkWidget   *find_toolbar;
        gchar       *last_search;
 
+       GtkWidget   *font_dialog;
+
        GtkWidget   *scroll;
        guint        scroll_drag_timeout_id;
        gdouble      last_upper;
@@ -446,6 +443,8 @@ modest_msg_edit_window_init (ModestMsgEditWindow *obj)
        priv->scroll_drag_timeout_id = 0;
        priv->last_upper = 0.0;
 
+       priv->font_dialog = NULL;
+
        modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
                                            GTK_WINDOW(obj),"applications_email_editor");
 
@@ -498,41 +497,6 @@ get_transports (void)
        return transports;
 }
 
-/**
- * Search an (account, address) ModestPairList for a pair whose
- * address matches the one in the From: header of a TnyMsg
- *
- * @result: A ModestPair * with a matching address, or NULL if none found
- */
-static ModestPair *
-find_transport_from_message_sender (ModestPairList *transports, TnyMsg *msg)
-{
-       g_return_val_if_fail (transports, NULL);
-       g_return_val_if_fail (msg, NULL);
-
-       ModestPair *account_pair = NULL;
-       TnyHeader *header = tny_msg_get_header (msg);
-
-       if (header != NULL && tny_header_get_from (header)) {
-               char *from_addr = modest_text_utils_get_email_address (tny_header_get_from (header));
-               GSList *iter;
-               for (iter = transports; iter && !account_pair; iter = iter->next) {
-                       ModestPair *pair = (ModestPair *) iter->data;
-                       char *account_addr = modest_text_utils_get_email_address ((char *) pair->second);
-                       if (account_addr && !strcasecmp(from_addr, account_addr)) {
-                               account_pair = pair;
-                       }
-                       g_free (account_addr);
-               }
-               g_free (from_addr);
-       }
-
-       if (header)
-               g_object_unref (header);
-
-       return account_pair;
-}
-
 static void window_focus (GtkWindow *window,
                          GtkWidget *widget,
                          gpointer userdata)
@@ -959,6 +923,10 @@ modest_msg_edit_window_finalize (GObject *obj)
           call this function before */
        modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
 
+       if (priv->font_dialog != NULL) {
+               gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
+       }
+
        if (priv->clipboard_text != NULL) {
                g_free (priv->clipboard_text);
                priv->clipboard_text = NULL;
@@ -990,6 +958,8 @@ modest_msg_edit_window_finalize (GObject *obj)
                g_source_remove (priv->clipboard_owner_idle);
                priv->clipboard_owner_idle = 0;
        }
+       if (priv->original_account_name)
+               g_free (priv->original_account_name);
        g_free (priv->msg_uid);
        g_free (priv->last_search);
        g_slist_free (priv->font_items_group);
@@ -1173,7 +1143,7 @@ static void
 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
 {
        TnyHeader *header;
-       const gchar *to, *cc, *bcc, *subject;
+       gchar *to, *cc, *bcc, *subject;
        gchar *body;
        ModestMsgEditWindowPrivate *priv;
        GtkTextIter iter;
@@ -1187,10 +1157,10 @@ set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
        priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
 
        header = tny_msg_get_header (msg);
-       to      = tny_header_get_to (header);
-       cc      = tny_header_get_cc (header);
-       bcc     = tny_header_get_bcc (header);
-       subject = tny_header_get_subject (header);
+       to      = tny_header_dup_to (header);
+       cc      = tny_header_dup_cc (header);
+       bcc     = tny_header_dup_bcc (header);
+       subject = tny_header_dup_subject (header);
        priority_flags = tny_header_get_priority (header);
 
        if (to)
@@ -1298,6 +1268,11 @@ set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
                }
                g_object_unref (msg_folder);
        }
+
+       g_free (to);
+       g_free (subject);
+       g_free (cc);
+       g_free (bcc);
 }
 
 static void
@@ -1496,7 +1471,6 @@ modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean pre
        GObject *obj;
        ModestWindowPrivate *parent_priv;
        ModestMsgEditWindowPrivate *priv;
-       ModestPair *account_pair = NULL;
        ModestDimmingRulesGroup *menu_rules_group = NULL;
        ModestDimmingRulesGroup *toolbar_rules_group = NULL;
        ModestDimmingRulesGroup *clipboard_rules_group = NULL;
@@ -1517,6 +1491,7 @@ modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean pre
        hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
        priv->from_field_protos = get_transports ();
        modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
+       modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), (gpointer) account_name);
        modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
        hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
 
@@ -1527,14 +1502,7 @@ modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean pre
                
        modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
 
-       account_pair = find_transport_from_message_sender (priv->from_field_protos, msg);
-       if (account_pair == NULL) {
-               account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
-       }
-       if (account_pair != NULL)
-               modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
-
-       priv->original_account_name = account_pair ? (const gchar *) account_pair->first : NULL;
+       priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
 
        parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
        menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
@@ -1618,6 +1586,8 @@ get_formatted_data (ModestMsgEditWindow *edit_window)
 
        wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
 
+       modest_text_utils_hyperlinkify (string_buffer);
+
        gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
 
        return g_string_free (string_buffer, FALSE);
@@ -2134,7 +2104,8 @@ modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
 
 
 
-static TnyStream* create_stream_for_uri (const gchar* uri)
+static TnyStream*
+create_stream_for_uri (const gchar* uri)
 {
        if (!uri)
                return NULL;
@@ -2144,9 +2115,22 @@ static TnyStream* create_stream_for_uri (const gchar* uri)
        GnomeVFSHandle *handle = NULL;
        GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
        if (test == GNOME_VFS_OK) {
-               /* Create the tinymail stream: */
-               /* Presumably tinymai will call gnome_vfs_close (handle) later. */
-               result = TNY_STREAM (tny_vfs_stream_new (handle));
+               TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
+               /* Streams over OBEX (Bluetooth) are not seekable but
+                * we expect them to be (we might need to read them
+                * several times). So if this is a Bluetooth URI just
+                * read the whole file into memory (this is not a fast
+                * protocol so we can assume that these files are not
+                * going to be very big) */
+               if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
+                   (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
+                       TnyStream *memstream = tny_camel_mem_stream_new ();
+                       tny_stream_write_to_stream (vfssstream, memstream);
+                       g_object_unref (vfssstream);
+                       result = memstream;
+               } else {
+                       result = vfssstream;
+               }
        }
        
        return result;
@@ -2199,6 +2183,7 @@ modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
                        GnomeVFSURI *vfs_uri;
                        guint64 stream_size;
 
+                       gnome_vfs_close (handle);
                        vfs_uri = gnome_vfs_uri_new (uri);
 
                        escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
@@ -2216,6 +2201,16 @@ modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
                                (modest_runtime_get_platform_factory ());
                                
                        TnyStream *stream = create_stream_for_uri (uri);
+
+                       if (stream == NULL) {
+
+                               modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
+                               
+                               g_object_unref (mime_part);
+                               gnome_vfs_file_info_unref (info);
+                               continue;
+                       }
+
                        tny_mime_part_construct (mime_part, stream, mime_type, "base64");
                        
                        content_id = g_strdup_printf ("%d", priv->next_cid);
@@ -2256,10 +2251,22 @@ modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
        gint response = 0;
        GSList *uris = NULL;
        GSList *uri_node;
+       GnomeVFSFileSize total_size, allowed_size;
+       ModestMsgEditWindowPrivate *priv;
+       gint att_num;
+       guint64 att_size;
+
+       g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
+               
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
+               return;
        
        dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
        gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
        gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
 
        response = gtk_dialog_run (GTK_DIALOG (dialog));
        switch (response) {
@@ -2271,25 +2278,48 @@ modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
        }
        gtk_widget_destroy (dialog);
 
+       /* allowed size is the maximum size - what's already there */
+       modest_attachments_view_get_sizes (
+               MODEST_ATTACHMENTS_VIEW (priv->attachments_view), 
+               &att_num, &att_size);
+       allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
+
+       total_size = 0;
        for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
+
                const gchar *uri = (const gchar *) uri_node->data;
-               modest_msg_edit_window_attach_file_one (window, uri);
+               
+               total_size += modest_msg_edit_window_attach_file_one 
+                       (window, uri, allowed_size);
+               
+               if (total_size > allowed_size) {
+                       g_warning ("%s: total size: %u", 
+                                  __FUNCTION__, (unsigned int)total_size);
+                       break;
+               }
+
+               allowed_size -= total_size;
+               
+
        }
        g_slist_foreach (uris, (GFunc) g_free, NULL);
        g_slist_free (uris);
 }
 
-void
-modest_msg_edit_window_attach_file_one (
-               ModestMsgEditWindow *window,
-               const gchar *uri)
+
+GnomeVFSFileSize
+modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
+                                       const gchar *uri, 
+                                       GnomeVFSFileSize allowed_size)
+
 {
        GnomeVFSHandle *handle = NULL;
        ModestMsgEditWindowPrivate *priv;
        GnomeVFSResult result;
+       GnomeVFSFileSize size = 0;
 
-       g_return_if_fail (window);
-       g_return_if_fail (uri);
+       g_return_val_if_fail (window, 0);
+       g_return_val_if_fail (uri, 0);
                
        priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
        
@@ -2305,6 +2335,7 @@ modest_msg_edit_window_attach_file_one (
                GnomeVFSFileInfo *info;
                GnomeVFSURI *vfs_uri;
 
+               gnome_vfs_close (handle);
                vfs_uri = gnome_vfs_uri_new (uri);
                
 
@@ -2322,10 +2353,32 @@ modest_msg_edit_window_attach_file_one (
                        mime_type = gnome_vfs_file_info_get_mime_type (info);
                mime_part = tny_platform_factory_new_mime_part
                        (modest_runtime_get_platform_factory ());
-               stream = TNY_STREAM (tny_vfs_stream_new (handle));
                
-               tny_mime_part_construct (mime_part, stream, mime_type, "base64");
+               /* try to get the attachment's size; this may fail for weird
+                * file systems, like obex, upnp... */
+               if (allowed_size != 0 &&
+                   info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
+                       size = info->size;
+                       if (size > allowed_size) {
+                               g_warning ("%s: attachment too big", __FUNCTION__);
+                               modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
+                               return 0;
+                       }
+               } else
+                       g_warning ("%s: could not get attachment size", __FUNCTION__);
+               
+               stream = create_stream_for_uri (uri);
+               
+               if (stream == NULL) {
+
+                       modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
+
+                       g_object_unref (mime_part);
+                       gnome_vfs_file_info_unref (info);
+                       return 0;
+               }
 
+               tny_mime_part_construct (mime_part, stream, mime_type, "base64");
                g_object_unref (stream);
                
                content_id = g_strdup_printf ("%d", priv->next_cid);
@@ -2348,6 +2401,8 @@ modest_msg_edit_window_attach_file_one (
                g_object_unref (mime_part);
                gnome_vfs_file_info_unref (info);
        }
+
+       return size;
 }
 
 void
@@ -2382,7 +2437,7 @@ modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
                        if (TNY_IS_MSG (part)) {
                                TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
                                if (header) {
-                                       filename = g_strdup (tny_header_get_subject (header));
+                                       filename = tny_header_dup_subject (header);
                                        g_object_unref (header);
                                }
                                if (filename == NULL) {
@@ -2396,7 +2451,7 @@ modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
                        filename = g_strdup ("");
                }
                message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
-                                                   (tny_list_get_length (att_list) == 1)), filename);
+                                                   tny_list_get_length (att_list)), filename);
                g_free (filename);
                confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
                g_free (message);
@@ -2602,6 +2657,13 @@ modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
 
        g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
        g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
+       
+       /* we check for low-mem; in that case, show a warning, and don't allow
+        * for the addressbook
+        */
+       if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
+               return;
+
        priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
 
        if (editor == NULL) {
@@ -2783,6 +2845,8 @@ modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
        priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
        
        dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
+                                    GTK_WINDOW(dialog));
 
        /* First we get the currently selected font information */
        wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
@@ -2819,7 +2883,9 @@ modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
                      NULL);
 
        gtk_widget_show_all (dialog);
+       priv->font_dialog = dialog;
        response = gtk_dialog_run (GTK_DIALOG (dialog));
+       priv->font_dialog = NULL;
        if (response == GTK_RESPONSE_OK) {
 
                g_object_get( dialog,