2007-05-16 Murray Cumming <murrayc@murrayc.com>
authorMurray Cumming <murrayc@murrayc.com>
Wed, 16 May 2007 12:30:07 +0000 (12:30 +0000)
committerMurray Cumming <murrayc@murrayc.com>
Wed, 16 May 2007 12:30:07 +0000 (12:30 +0000)
* src/modest-pair.h: Improve the documentation for modest_combo_box_new()
        to explain the memory management issue with the ID in the ModestPair.

        * src/gnome/modest-account-assistant.c: (add_receiving_page),
        (add_sending_page), (modest_account_assistant_finalize):
        * src/gnome/modest-gnome-global-settings-dialog.c:
        (create_updating_page), (create_composing_page):
        * src/gnome/modest-msg-edit-window.c: (get_transports),
        (init_window), (modest_msg_edit_window_finalize),
        (modest_msg_edit_window_get_msg_data):
        * src/gnome/modest-store-widget.c: (imap_pop_configuration):
        * src/gnome/modest-transport-widget.c:
        (modest_transport_widget_finalize), (smtp_configuration):
        * src/maemo/modest-maemo-global-settings-dialog.c:
        (create_updating_page), (create_composing_page):
        * src/maemo/modest-msg-edit-window.c: (get_transports),
        (init_window), (modest_msg_edit_window_finalize),
        (modest_msg_edit_window_get_msg_data),
        (modest_msg_edit_window_free_msg_data):
        * src/maemo/modest-store-widget.c: (imap_pop_configuration),
        (modest_store_widget_finalize):
        * src/maemo/modest-transport-widget.c:
        (modest_transport_widget_finalize), (smtp_configuration):
        * src/modest-main.c: (send_mail):
        * src/widgets/modest-combo-box.h:
        * src/widgets/modest-global-settings-dialog-priv.h:
        * src/widgets/modest-global-settings-dialog.c:
        (modest_global_settings_dialog_finalize):
        * src/widgets/modest-msg-edit-window.h:
        Whenever using modest_combo_box_new(), keep the ModestPairList alive
        as long as the combo box, to prevent use of freed memory for the ID.

pmo-trunk-r1887

16 files changed:
ChangeLog2
src/gnome/modest-account-assistant.c
src/gnome/modest-gnome-global-settings-dialog.c
src/gnome/modest-msg-edit-window.c
src/gnome/modest-store-widget.c
src/gnome/modest-transport-widget.c
src/maemo/modest-maemo-global-settings-dialog.c
src/maemo/modest-msg-edit-window.c
src/maemo/modest-store-widget.c
src/maemo/modest-transport-widget.c
src/modest-main.c
src/modest-pair.h
src/widgets/modest-combo-box.h
src/widgets/modest-global-settings-dialog-priv.h
src/widgets/modest-global-settings-dialog.c
src/widgets/modest-msg-edit-window.h

index 8ffb297..48d6fa3 100644 (file)
@@ -1,3 +1,37 @@
+2007-05-16  Murray Cumming  <murrayc@murrayc.com>
+
+       * src/modest-pair.h: Improve the documentation for modest_combo_box_new() 
+       to explain the memory management issue with the ID in the ModestPair.
+       
+       * src/gnome/modest-account-assistant.c: (add_receiving_page),
+       (add_sending_page), (modest_account_assistant_finalize):
+       * src/gnome/modest-gnome-global-settings-dialog.c:
+       (create_updating_page), (create_composing_page):
+       * src/gnome/modest-msg-edit-window.c: (get_transports),
+       (init_window), (modest_msg_edit_window_finalize),
+       (modest_msg_edit_window_get_msg_data):
+       * src/gnome/modest-store-widget.c: (imap_pop_configuration):
+       * src/gnome/modest-transport-widget.c:
+       (modest_transport_widget_finalize), (smtp_configuration):
+       * src/maemo/modest-maemo-global-settings-dialog.c:
+       (create_updating_page), (create_composing_page):
+       * src/maemo/modest-msg-edit-window.c: (get_transports),
+       (init_window), (modest_msg_edit_window_finalize),
+       (modest_msg_edit_window_get_msg_data),
+       (modest_msg_edit_window_free_msg_data):
+       * src/maemo/modest-store-widget.c: (imap_pop_configuration),
+       (modest_store_widget_finalize):
+       * src/maemo/modest-transport-widget.c:
+       (modest_transport_widget_finalize), (smtp_configuration):
+       * src/modest-main.c: (send_mail):
+       * src/widgets/modest-combo-box.h:
+       * src/widgets/modest-global-settings-dialog-priv.h:
+       * src/widgets/modest-global-settings-dialog.c:
+       (modest_global_settings_dialog_finalize):
+       * src/widgets/modest-msg-edit-window.h:
+       Whenever using modest_combo_box_new(), keep the ModestPairList alive
+       as long as the combo box, to prevent use of freed memory for the ID.
+
 2007-05-15  Murray Cumming  <murrayc@murrayc.com>
 
        * src/modest-tny-account-store.c: (get_server_accounts): Renamed from 
index 3ee5f5f..a45f376 100644 (file)
@@ -64,7 +64,10 @@ struct _ModestAccountAssistantPrivate {
        GtkWidget *transport_widget;
 
        GtkWidget *transport_holder;
-       GtkWidget *store_holder;        
+       GtkWidget *store_holder;
+
+       ModestPairList *receiving_transport_store_protos;
+       ModestPairList *sending_transport_store_protos;
 };
 
 #define MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
@@ -293,7 +296,6 @@ static void
 add_receiving_page (ModestAccountAssistant *self)
 {
        GtkWidget *page, *box, *combo;
-       ModestPairList *protos;
        ModestAccountAssistantPrivate *priv;
 
        priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);      
@@ -308,9 +310,11 @@ add_receiving_page (ModestAccountAssistant *self)
                            gtk_label_new(_("Server type")),
                            FALSE,FALSE,6);
 
-       protos = modest_protocol_info_get_transport_store_protocol_pair_list (MODEST_PROTOCOL_TYPE_STORE);
-       combo = modest_combo_box_new (protos, g_str_equal);
-       modest_pair_list_free (protos);
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */
+       priv->receiving_transport_store_protos = modest_protocol_info_get_transport_store_protocol_pair_list (MODEST_PROTOCOL_TYPE_STORE);
+       combo = modest_combo_box_new (priv->receiving_transport_store_protos, g_str_equal);
        
        g_signal_connect (G_OBJECT(combo), "changed",
                          G_CALLBACK(on_receiving_combo_box_changed), self);
@@ -369,7 +373,6 @@ static void
 add_sending_page (ModestAccountAssistant *self)
 {
        GtkWidget *page, *box, *combo;
-       ModestPairList *protos;
        ModestAccountAssistantPrivate *priv;
 
        priv = MODEST_ACCOUNT_ASSISTANT_GET_PRIVATE(self);
@@ -384,9 +387,11 @@ add_sending_page (ModestAccountAssistant *self)
                            gtk_label_new(_("Server type")),
                            FALSE,FALSE,0);
        
-       protos = modest_protocol_info_get_transport_store_protocol_pair_list (MODEST_PROTOCOL_TYPE_TRANSPORT);
-       combo = modest_combo_box_new (protos, g_str_equal);
-       modest_pair_list_free (protos);
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */
+       priv->sending_transport_store_protos = modest_protocol_info_get_transport_store_protocol_pair_list (MODEST_PROTOCOL_TYPE_TRANSPORT);
+       combo = modest_combo_box_new (priv->sending_transport_store_protos, g_str_equal);
 
        g_signal_connect (G_OBJECT(combo), "changed",
                          G_CALLBACK(on_sending_combo_box_changed), self);
@@ -476,6 +481,10 @@ modest_account_assistant_finalize (GObject *obj)
                g_object_unref (G_OBJECT(priv->account_mgr));
                priv->account_mgr = NULL;
        }
+       
+       /* These had to stay alive for as long as the comboboxes that used them: */
+       modest_pair_list_free (priv->receiving_transport_store_protos);
+       modest_pair_list_free (priv->sending_transport_store_protos);
 
        G_OBJECT_CLASS(parent_class)->finalize (obj);
 }
index 7549b08..a5cbca4 100644 (file)
@@ -201,7 +201,6 @@ create_updating_page (ModestGnomeGlobalSettingsDialog *self)
 {
        GtkWidget *vbox, *table_update, *table_limit;
        GtkWidget *label, *check, *combo, *spin;
-       ModestPairList *list;
 
        vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_DEFAULT);
        table_update = gtk_table_new (3, 2, FALSE);
@@ -219,16 +218,27 @@ create_updating_page (ModestGnomeGlobalSettingsDialog *self)
 
        /* Connected via */
        label = create_label (_("mcen_fi_options_connectiontype"));
-       list = _modest_global_settings_dialog_get_connected_via ();
-       combo = modest_combo_box_new (list, g_int_equal);
-       modest_pair_list_free (list);
+
+       ModestGlobalSettingsDialogPrivate *ppriv = 
+               MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (self);
+
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */
+       ppriv->connected_via_list = _modest_global_settings_dialog_get_connected_via ();
+       combo = modest_combo_box_new (ppriv->connected_via_list, g_int_equal);
+
        add_to_table (GTK_TABLE (table_update), label, combo);
 
        /* Update interval */
        label = create_label (_("mcen_fi_options_updateinterval"));
-       list = _modest_global_settings_dialog_get_update_interval ();
-       combo = modest_combo_box_new (list, g_int_equal);
-       modest_pair_list_free (list);
+
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */
+       ppriv->update_interval_list = _modest_global_settings_dialog_get_update_interval ();
+       combo = modest_combo_box_new (ppriv->update_interval_list, g_int_equal);
+
        add_to_table (GTK_TABLE (table_update), label, combo);
 
        /* Add to vbox */
@@ -261,7 +271,6 @@ create_composing_page (ModestGnomeGlobalSettingsDialog *self)
 {
        GtkWidget *vbox, *table;
        GtkWidget *label, *check, *combo;
-       ModestPairList *list;
 
        vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_DEFAULT);
        table = gtk_table_new (2, 2, FALSE);
@@ -271,9 +280,16 @@ create_composing_page (ModestGnomeGlobalSettingsDialog *self)
 
        /* Update interval */
        label = create_label (_("mcen_fi_options_messageformat"));
-       list = _modest_global_settings_dialog_get_msg_formats ();
-       combo = modest_combo_box_new (list, g_int_equal);
-       modest_pair_list_free (list);
+
+       ModestGlobalSettingsDialogPrivate *ppriv = 
+               MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (self);
+
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */
+       ppriv->combo_msg_formats_list = _modest_global_settings_dialog_get_msg_formats ();
+       combo = modest_combo_box_new (ppriv->cmsg_formats_list, g_int_equal);
+
        add_to_table (GTK_TABLE (table), label, combo);
 
        label = create_label (_("mcen_va_options_include_original_inreply"));
index 052f2c5..3adfc52 100644 (file)
@@ -60,7 +60,10 @@ struct _ModestMsgEditWindowPrivate {
        GtkWidget   *menubar;
 
        GtkWidget   *msg_body;
+       
+       ModestProtoList *from_field_protos;
        GtkWidget   *from_field;
+       
        GtkWidget   *to_field;
        GtkWidget   *cc_field;
        GtkWidget   *bcc_field;
@@ -149,7 +152,9 @@ modest_msg_edit_window_init (ModestMsgEditWindow *obj)
        priv->subject_field = NULL;
 }
 
-
+/** 
+ * @result: A ModestPairList, which must be freed with modest_pair_list_free().
+ */
 static ModestPairList*
 get_transports (void)
 {
@@ -160,7 +165,7 @@ get_transports (void)
        account_mgr = modest_runtime_get_account_mgr();
        cursor = accounts = modest_account_mgr_account_names (account_mgr, TRUE);
        while (cursor) {
-               gchar *account_name = (gchar*)cursor->data;
+               gchar *account_name = cursor->data ? g_strdup((gchar*)cursor->data) : NULL;
                gchar *from_string  = modest_account_mgr_get_from_string (account_mgr,
                                                                          account_name);
                if (!from_string)  {
@@ -197,7 +202,6 @@ init_window (ModestMsgEditWindow *obj, const gchar* account)
        GtkWidget *main_vbox;
        ModestMsgEditWindowPrivate *priv;
        ModestWindowPrivate *parent_priv;
-       ModestPairList *protos;
        
        priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
        parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
@@ -206,9 +210,12 @@ init_window (ModestMsgEditWindow *obj, const gchar* account)
        cc_button     = gtk_button_new_with_label (_("Cc..."));
        bcc_button    = gtk_button_new_with_label (_("Bcc..."));
        
-       protos = get_transports ();
-       priv->from_field    = modest_combo_box_new (protos, g_str_equal);
-       modest_pair_list_free (protos);
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       priv->from_field_protos = get_transports ();
+       priv->from_field    = modest_combo_box_new (priv->from_field_protos, g_str_equal);
+       
        if (account) {
                modest_combo_box_set_active_id (MODEST_COMBO_BOX(priv->from_field),
                                                (gpointer)account);
@@ -255,6 +262,11 @@ init_window (ModestMsgEditWindow *obj, const gchar* account)
 static void
 modest_msg_edit_window_finalize (GObject *obj)
 {
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
+       
+       /* These had to stay alive for as long as the comboboxes that used them: */
+       modest_pair_list_free (priv->from_field_protos);
+       
        G_OBJECT_CLASS(parent_class)->finalize (obj);
 }
 
@@ -378,8 +390,7 @@ MsgData *
 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
 {
        MsgData *data;
-       GtkTextBuffer *buf;
-       GtkTextIter b, e;
+       
        const gchar *account_name;
        gchar *from_string = NULL;
        ModestMsgEditWindowPrivate *priv;
@@ -397,17 +408,20 @@ modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
                return NULL;
        }
        
-       buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
-       gtk_text_buffer_get_bounds (buf, &b, &e);
+       
 
-       /* don't free these (except from) */
        data = g_slice_new0 (MsgData);
        data->from    =  from_string, /* will be freed when data is freed */
-       data->to      =  (gchar*) gtk_entry_get_text (GTK_ENTRY(priv->to_field));
-       data->cc      =  (gchar*) gtk_entry_get_text (GTK_ENTRY(priv->cc_field));
-       data->bcc     =  (gchar*) gtk_entry_get_text (GTK_ENTRY(priv->bcc_field));
-       data->subject =  (gchar*) gtk_entry_get_text (GTK_ENTRY(priv->subject_field));
-       data->plain_body    =  gtk_text_buffer_get_text (buf, &b, &e, FALSE);
+       data->to      =  g_strdup (gtk_entry_get_text (GTK_ENTRY(priv->to_field))));
+       data->cc      =  g_strdup ( gtk_entry_get_text (GTK_ENTRY(priv->cc_field)));
+       data->bcc     =  g_strdup ( gtk_entry_get_text (GTK_ENTRY(priv->bcc_field)));
+       data->subject =  g_strdup ( gtk_entry_get_text (GTK_ENTRY(priv->subject_field)));
+
+       GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
+       GtkTextIter b, e;
+       gtk_text_buffer_get_bounds (buf, &b, &e);
+       data->plain_body =  gtk_text_buffer_get_text (buf, &b, &e, FALSE); /* Returns a copy. */
+
        /* No rich supported yet, then html body is NULL */
        data->html_body = NULL;
 
@@ -420,9 +434,18 @@ modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
 {
        g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
 
-       g_free (data->from);
+       if (!data)
+               return;
+
+       g_free (data->to);
+       g_free (data->cc);
+       g_free (data->bcc);
+       g_free (data->subject);
        g_free (data->plain_body);
        g_free (data->html_body);
+
+       /* TODO: Free data->attachments? */
+
        g_slice_free (MsgData, data);
 }
 
index 27918d2..8583343 100644 (file)
@@ -48,8 +48,13 @@ struct _ModestStoreWidgetPrivate {
        
        GtkWidget *servername;
        GtkWidget *username;
+       
+       ModestProtoList *security_protos;
        GtkWidget *security;
+       
+       ModestProtoList *auth_protos;
        GtkWidget *auth;
+       
        GtkWidget *chooser;
 
        ModestTransportStoreProtocol proto;
@@ -195,7 +200,6 @@ on_entry_changed (GtkEntry *entry, gpointer user_data)
 static GtkWidget*
 imap_pop_configuration (ModestStoreWidget *self)
 {
-       ModestPairList *protos;
        ModestStoreWidgetPrivate *priv;
        GtkWidget *label, *box, *hbox;
        
@@ -226,9 +230,12 @@ imap_pop_configuration (ModestStoreWidget *self)
        gtk_label_set_markup (GTK_LABEL(label),_("<b>Security</b>"));
        gtk_box_pack_start (GTK_BOX(box), label, FALSE, FALSE, 0);
 
-       protos = modest_protocol_info_get_connection_protocol_pair_list ();
-       priv->security = modest_combo_box_new (protos, g_str_equal);
-       modest_pair_list_free (protos);
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       priv->security_protos = modest_protocol_info_get_connection_protocol_pair_list ();
+
+       priv->security = modest_combo_box_new (priv->security_protos, g_str_equal);
        
        hbox = gtk_hbox_new (FALSE, 6);
        label = gtk_label_new(NULL);
@@ -243,9 +250,11 @@ imap_pop_configuration (ModestStoreWidget *self)
        gtk_label_set_text (GTK_LABEL(label),_("Authentication:"));
        gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 6);
        
-       protos = modest_protocol_info_get_auth_protocol_pair_list (;
-       priv->auth =  modest_combo_box_new (protos, g_str_equal);
-       modest_pair_list_free (protos);
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       priv->auth_protos = modest_protocol_info_get_auth_protocol_pair_list (;
+       priv->auth =  modest_combo_box_new (priv->auth_protos, g_str_equal);
 
        gtk_box_pack_start (GTK_BOX(hbox), priv->auth, FALSE, FALSE, 0);
        
@@ -262,6 +271,12 @@ imap_pop_configuration (ModestStoreWidget *self)
 static void
 modest_store_widget_finalize (GObject *obj)
 {
+       ModestStoreWidgetPrivate *priv = MODEST_STORE_WIDGET_GET_PRIVATE(obj);
+       
+       /* These had to stay alive for as long as the comboboxes that used them: */
+       modest_pair_list_free (priv->security_protos);
+       modest_pair_list_free (priv->auth_protos);
+       
        G_OBJECT_CLASS(parent_class)->finalize (obj);
 }
 
index aec1ab5..16271fc 100644 (file)
@@ -29,6 +29,8 @@ struct _ModestTransportWidgetPrivate {
        GtkWidget *username;
        GtkWidget *auth;
        GtkWidget *remember_pwd;
+       
+       ModestPairList *transport_store_protos;
 };
 #define MODEST_TRANSPORT_WIDGET_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
                                                      MODEST_TYPE_TRANSPORT_WIDGET, \
@@ -94,6 +96,11 @@ modest_transport_widget_init (ModestTransportWidget *obj)
 static void
 modest_transport_widget_finalize (GObject *obj)
 {
+       ModestTransportWidgetPrivate *priv = MODEST_TRANSPORT_WIDGET_GET_PRIVATE(obj);
+       
+       /* These had to stay alive for as long as the comboboxes that used them: */
+       modest_pair_list_free (priv->transport_store_protos);
+       
        G_OBJECT_CLASS(parent_class)->finalize (obj);
 }
 
@@ -116,7 +123,6 @@ smtp_configuration (ModestTransportWidget *self)
 {
        ModestTransportWidgetPrivate *priv;
        GtkWidget *label, *box, *hbox, *combo;
-       ModestPairList *protos;
        
        priv = MODEST_TRANSPORT_WIDGET_GET_PRIVATE(self);
        box = gtk_vbox_new (FALSE, 6);
@@ -160,9 +166,11 @@ smtp_configuration (ModestTransportWidget *self)
        gtk_label_set_text (GTK_LABEL(label),_("Connection type:"));
        gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
 
-       protos = modest_protocol_info_get_auth_protocol_pair_list ();
-       combo  = modest_combo_box_new (protos, g_str_equal);
-       modest_pair_list_free (protos);
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       priv->transport_store_protos = modest_protocol_info_get_transport_store_protocol_pair_list ();
+       combo  = modest_combo_box_new (priv->transport_store_protos, g_str_equal);
        
        gtk_box_pack_start (GTK_BOX(hbox), combo, FALSE, FALSE,0);
        gtk_box_pack_start (GTK_BOX(box), hbox, FALSE, FALSE, 0);
@@ -173,9 +181,11 @@ smtp_configuration (ModestTransportWidget *self)
        gtk_label_set_text (GTK_LABEL(label),_("Authentication:"));
        gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 6);
 
-       protos = modest_protocol_info_get_auth_protocol_pair_list ();
-       combo  = modest_combo_box_new (protos, g_str_equal);
-       modest_pair_list_free (protos);
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       priv->auth_protos = modest_protocol_info_get_auth_protocol_pair_list ();
+       combo  = modest_combo_box_new (priv->auth_protos, g_str_equal);
        
        gtk_box_pack_start (GTK_BOX(hbox), combo, FALSE, FALSE, 0);
        priv->remember_pwd =
index e262409..b9b8ff8 100644 (file)
@@ -87,6 +87,7 @@ static void       on_auto_update_toggled (GtkToggleButton *togglebutton,
 
 typedef struct _ModestMaemoGlobalSettingsDialogPrivate ModestMaemoGlobalSettingsDialogPrivate;
 struct _ModestMaemoGlobalSettingsDialogPrivate {
+       ModestPairList *connect_via_list;
 };
 #define MODEST_MAEMO_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
                                                            MODEST_TYPE_MAEMO_GLOBAL_SETTINGS_DIALOG, \
@@ -181,7 +182,6 @@ create_updating_page (ModestMaemoGlobalSettingsDialog *self)
 {
        GtkWidget *vbox, *vbox_update, *vbox_limit, *caption;
        GtkSizeGroup *size_group;
-       ModestPairList *list;
        ModestGlobalSettingsDialogPrivate *ppriv;
 
        ppriv = MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (self);
@@ -202,9 +202,13 @@ create_updating_page (ModestMaemoGlobalSettingsDialog *self)
        g_signal_connect (ppriv->auto_update, "toggled", G_CALLBACK (on_auto_update_toggled), self);
 
        /* Connected via */
-       list = _modest_global_settings_dialog_get_connected_via ();
-       ppriv->connect_via = modest_combo_box_new (list, g_int_equal);
-       modest_pair_list_free (list);
+
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       ppriv->connect_via_list = _modest_global_settings_dialog_get_connected_via ();
+       ppriv->connect_via = modest_combo_box_new (ppriv->connect_via_list, g_int_equal);
+
        caption = hildon_caption_new (size_group, 
                                      _("mcen_fi_options_connectiontype"),
                                      ppriv->connect_via, 
@@ -213,9 +217,13 @@ create_updating_page (ModestMaemoGlobalSettingsDialog *self)
        gtk_box_pack_start (GTK_BOX (vbox_update), caption, FALSE, FALSE, MODEST_MARGIN_HALF);
 
        /* Update interval */
-       list = _modest_global_settings_dialog_get_update_interval ();
-       ppriv->update_interval = modest_combo_box_new (list, g_int_equal);
-       modest_pair_list_free (list);
+
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       ppriv->update_interval_list = _modest_global_settings_dialog_get_update_interval ();
+       ppriv->update_interval = modest_combo_box_new (ppriv->update_interval_list, g_int_equal);
+
        caption = hildon_caption_new (size_group, 
                                      _("mcen_fi_options_updateinterval"),
                                      ppriv->update_interval, 
@@ -268,7 +276,6 @@ create_composing_page (ModestMaemoGlobalSettingsDialog *self)
        GtkWidget *vbox;
        GtkSizeGroup *size_group;
        ModestGlobalSettingsDialogPrivate *ppriv;
-       ModestPairList *list;
        GtkWidget *caption;
 
        ppriv = MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (self);
@@ -276,9 +283,13 @@ create_composing_page (ModestMaemoGlobalSettingsDialog *self)
        vbox = gtk_vbox_new (FALSE, MODEST_MARGIN_DEFAULT);
 
        /* Update interval */
-       list = _modest_global_settings_dialog_get_msg_formats ();
-       ppriv->msg_format = modest_combo_box_new (list, g_int_equal);
-       modest_pair_list_free (list);
+
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       ppriv->msg_format_list = _modest_global_settings_dialog_get_msg_formats ();
+       ppriv->msg_format = modest_combo_box_new (ppriv->msg_format_list, g_int_equal);
+
        caption = hildon_caption_new (size_group, 
                                      _("mcen_fi_options_messageformat"),
                                      ppriv->msg_format, 
index b3492c7..5b9f0e0 100644 (file)
@@ -129,7 +129,10 @@ typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
 struct _ModestMsgEditWindowPrivate {
        GtkWidget   *msg_body;
        GtkWidget   *header_box;
+       
+       ModestPairList *from_field_protos;
        GtkWidget   *from_field;
+       
        GtkWidget   *to_field;
        GtkWidget   *cc_field;
        GtkWidget   *bcc_field;
@@ -266,30 +269,35 @@ modest_msg_edit_window_init (ModestMsgEditWindow *obj)
 
 
 /* FIXME: this is a dup from the one in gtk/ */
+
+/** 
+ * @result: A ModestPairList, which must be freed with modest_pair_list_free().
+ */
 static ModestPairList*
 get_transports (void)
 {
-       ModestAccountMgr *account_mgr;
        GSList *transports = NULL;
-       GSList *cursor, *accounts;
        
-       account_mgr = modest_runtime_get_account_mgr();
-       cursor = accounts = modest_account_mgr_account_names (account_mgr, 
+       ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
+       GSList *accounts = modest_account_mgr_account_names (account_mgr, 
                                                TRUE /* only enabled accounts. */); 
+                                               
+       GSList *cursor = accounts;
        while (cursor) {
-               gchar *account_name = (gchar*)cursor->data;
-               gchar *from_string  = modest_account_mgr_get_from_string (account_mgr,
+               const gchar *account_name = cursor->data;
+               gchar *from_string  = NULL;
+               if (account_name) {
+                       from_string = modest_account_mgr_get_from_string (account_mgr,
                                                                          account_name);
-               if (!from_string)  {
-                       /* something went wrong: ignore this one */
-                       g_free (account_name);
-                       cursor->data = NULL;
-               } else {
-                       ModestPair *pair;
-                       pair = modest_pair_new ((gpointer) account_name,
+               }
+               
+               if (from_string && account_name) {
+                       gchar *name = g_strdup (account_name);
+                       ModestPair *pair = modest_pair_new ((gpointer) name,
                                                (gpointer) from_string , TRUE);
                        transports = g_slist_prepend (transports, pair);
-               } /* don't free account name; it's freed when the transports list is freed */
+               }
+               
                cursor = cursor->next;
        }
        g_slist_free (accounts);
@@ -340,7 +348,7 @@ init_window (ModestMsgEditWindow *obj)
        GtkWidget *from_caption, *to_caption, *subject_caption;
        GtkWidget *main_vbox;
        ModestMsgEditWindowPrivate *priv;
-       ModestPairList *protos;
+
        GtkSizeGroup *size_group;
        GtkWidget *frame;
        GtkWidget *scroll_area;
@@ -351,9 +359,12 @@ init_window (ModestMsgEditWindow *obj)
 
        size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
 
-       protos = get_transports ();
-       priv->from_field    = modest_combo_box_new (protos, g_str_equal);
-       modest_pair_list_free (protos);
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */ 
+       priv->from_field_protos = get_transports ();
+
+       priv->from_field    = modest_combo_box_new (priv->from_field_protos, g_str_equal);
 
        priv->to_field      = modest_recpt_editor_new ();
        priv->cc_field      = modest_recpt_editor_new ();
@@ -474,10 +485,15 @@ modest_msg_edit_window_finalize (GObject *obj)
 {
        ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
 
+       
        if (priv->clipboard_change_handler_id > 0) {
                g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler_id);
                priv->clipboard_change_handler_id = 0;
        }
+       
+       /* This had to stay alive for as long as the combobox that used it: */
+       modest_pair_list_free (priv->from_field_protos);
+       
        G_OBJECT_CLASS(parent_class)->finalize (obj);
 }
 
@@ -935,6 +951,9 @@ get_formatted_data_cb (const gchar *buffer, gpointer user_data)
        return 0;
 }
 
+/**
+ * @result: A new string which should be freed with g_free().
+ */
 static gchar *
 get_formatted_data (ModestMsgEditWindow *edit_window)
 {
@@ -954,8 +973,6 @@ modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
 {
        MsgData *data;
        const gchar *account_name;
-       GtkTextBuffer *buf;
-       GtkTextIter b, e;
        ModestMsgEditWindowPrivate *priv;
        
        g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
@@ -965,37 +982,51 @@ modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
        account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
        g_return_val_if_fail (account_name, NULL);
        
-       buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));        
-       gtk_text_buffer_get_bounds (buf, &b, &e);
        
        /* don't free these (except from) */
        data = g_slice_new0 (MsgData);
        data->from    =  modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
                                                             account_name);
-       data->to      =  (gchar*) modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR(priv->to_field));
-       data->cc      =  (gchar*) modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR(priv->cc_field));
-       data->bcc     =  (gchar*) modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR(priv->bcc_field));
-       data->subject =  (gchar*) gtk_entry_get_text (GTK_ENTRY(priv->subject_field));  
-       data->plain_body =  (gchar *) gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE);
+       data->to      =  g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
+       data->cc      =  g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
+       data->bcc     =  g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
+       data->subject =  g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
+
+       GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
+       GtkTextIter b, e;
+       gtk_text_buffer_get_bounds (buf, &b, &e);
+       data->plain_body = g_strdup (gtk_text_buffer_get_text (priv->text_buffer, &b, &e, FALSE)); /* returns a copy */
+
        if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
-               data->html_body = get_formatted_data (edit_window);
+               data->html_body = get_formatted_data (edit_window); /* returns a copy. */
        else
                data->html_body = NULL;
-       data->attachments = priv->attachments;
+
+       data->attachments = priv->attachments; /* TODO: copy and free ? */
        data->priority_flags = priv->priority_flags;
 
        return data;
 }
 
+/* TODO: We must duplicate this implementation for GNOME and Maemo, but that is unwise. */
 void 
 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
                                                      MsgData *data)
 {
        g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
 
-       g_free (data->from);
-       g_free (data->html_body);
+       if (!data)
+               return;
+
+       g_free (data->to);
+       g_free (data->cc);
+       g_free (data->bcc);
+       g_free (data->subject);
        g_free (data->plain_body);
+       g_free (data->html_body);
+
+       /* TODO: Free data->attachments? */
+
        g_slice_free (MsgData, data);
 }
 
index 6a14a0c..f77a087 100644 (file)
@@ -48,7 +48,12 @@ struct _ModestStoreWidgetPrivate {
        
        GtkWidget *servername;
        GtkWidget *username;
+       
+       ModestPairList *security_protos;
        GtkWidget *security;
+       
+       ModestPairList *transport_store_protos;
+       
        GtkWidget *auth;
        GtkWidget *chooser;
        GtkWidget *remember_pwd;
@@ -196,7 +201,6 @@ on_entry_changed (GtkEntry *entry, gpointer user_data)
 static GtkWidget*
 imap_pop_configuration (ModestStoreWidget *self)
 {
-       ModestPairList *protos;
        ModestStoreWidgetPrivate *priv;
        GtkWidget *label, *box, *hbox;
        GtkWidget *combo;
@@ -228,9 +232,11 @@ imap_pop_configuration (ModestStoreWidget *self)
        gtk_label_set_markup (GTK_LABEL(label),_("<b>Security</b>"));
        gtk_box_pack_start (GTK_BOX(box), label, FALSE, FALSE, 0);
 
-       protos = modest_protocol_info_get_connection_protocol_pair_list ();
-       priv->security = modest_combo_box_new (protos, g_str_equal);
-       modest_pair_list_free (protos);
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */
+       priv->security_protos = modest_protocol_info_get_connection_protocol_pair_list ();
+       priv->security = modest_combo_box_new (priv->security_protos, g_str_equal);
        
        hbox = gtk_hbox_new (FALSE, 6);
        label = gtk_label_new(NULL);
@@ -245,9 +251,11 @@ imap_pop_configuration (ModestStoreWidget *self)
        gtk_label_set_text (GTK_LABEL(label),_("Authentication:"));
        gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 6);
        
-       protos = modest_protocol_info_get_transport_store_protocol_pair_list ();
-       combo =  modest_combo_box_new (protos, g_str_equal);
-       modest_pair_list_free (protos);
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */
+       priv->transport_store_protos = modest_protocol_info_get_transport_store_protocol_pair_list ();
+       combo =  modest_combo_box_new (priv->transport_store_protos, g_str_equal);
 
        gtk_box_pack_start (GTK_BOX(hbox), combo, FALSE, FALSE, 0);
        priv->remember_pwd =
@@ -268,6 +276,12 @@ imap_pop_configuration (ModestStoreWidget *self)
 static void
 modest_store_widget_finalize (GObject *obj)
 {
+       ModestStoreWidgetPrivate *priv = MODEST_STORE_WIDGET_GET_PRIVATE(obj);
+       
+       /* These had to stay alive for as long as the comboboxes that used them: */
+       modest_pair_list_free (priv->security_protos);
+       modest_pair_list_free (priv->transport_store_protos);
+       
        G_OBJECT_CLASS(parent_class)->finalize (obj);
 }
 
index 7465483..3b114e6 100644 (file)
@@ -54,6 +54,9 @@ struct _ModestTransportWidgetPrivate {
        GtkWidget *username;
        GtkWidget *auth;
        GtkWidget *remember_pwd;
+       
+       ModestPairList *transport_store_protos;
+       ModestPairList *auth_protos;
 };
 #define MODEST_TRANSPORT_WIDGET_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
                                                      MODEST_TYPE_TRANSPORT_WIDGET, \
@@ -119,6 +122,12 @@ modest_transport_widget_init (ModestTransportWidget *obj)
 static void
 modest_transport_widget_finalize (GObject *obj)
 {
+       ModestTransportWidgetPrivate *priv = MODEST_TRANSPORT_WIDGET_GET_PRIVATE(obj);
+       
+       /* These had to stay alive for as long as the comboboxes that used them: */
+       modest_pair_list_free (priv->transport_store_protos);
+       modest_pair_list_free (priv->auth_protos);
+       
        G_OBJECT_CLASS(parent_class)->finalize (obj);
 }
 
@@ -141,7 +150,6 @@ smtp_configuration (ModestTransportWidget *self)
 {
        ModestTransportWidgetPrivate *priv;
        GtkWidget *label, *box, *hbox, *combo;
-       ModestPairList *protos;
        
        priv = MODEST_TRANSPORT_WIDGET_GET_PRIVATE(self);
        box = gtk_vbox_new (FALSE, 6);
@@ -185,9 +193,11 @@ smtp_configuration (ModestTransportWidget *self)
        gtk_label_set_text (GTK_LABEL(label),_("Connection type:"));
        gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
 
-       protos = modest_protocol_info_get_transport_store_protocol_pair_list ();
-       combo  = modest_combo_box_new (protos, g_str_equal);
-       modest_pair_list_free (protos);
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */
+       priv->transport_store_protos = modest_protocol_info_get_transport_store_protocol_pair_list ();
+       combo = modest_combo_box_new (priv->transport_store_protos, g_str_equal);
        
        gtk_box_pack_start (GTK_BOX(hbox), combo, FALSE, FALSE,0);
        gtk_box_pack_start (GTK_BOX(box), hbox, FALSE, FALSE, 0);
@@ -198,9 +208,11 @@ smtp_configuration (ModestTransportWidget *self)
        gtk_label_set_text (GTK_LABEL(label),_("Authentication:"));
        gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 6);
 
-       protos = modest_protocol_info_get_auth_protocol_pair_list ();
-       combo  = modest_combo_box_new (protos, g_str_equal);
-       modest_pair_list_free (protos);
+       /* Note: This ModestPairList* must exist for as long as the combo
+        * that uses it, because the ModestComboBox uses the ID opaquely, 
+        * so it can't know how to manage its memory. */
+       priv->auth_protos = modest_protocol_info_get_auth_protocol_pair_list ();
+       combo  = modest_combo_box_new (priv->auth_protos, g_str_equal);
        
        gtk_box_pack_start (GTK_BOX(hbox), combo, FALSE, FALSE, 0);
        priv->remember_pwd =
index 4effe5c..ca96b75 100644 (file)
@@ -284,10 +284,11 @@ send_mail (const gchar* account_name,
                                                          account_name);
 
        mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_SEND, NULL);
+
        modest_mail_operation_send_new_mail (mail_operation, account,
                                             from_string, mailto,
-                                            cc, bcc, subject, body, NULL,
-                                            NULL, 0);
+                                            cc, bcc, subject, body, NULL /* html_body */,
+                                            NULL /* attachments */, 0 /* priority */);
        if (modest_mail_operation_get_status (mail_operation) == 
            MODEST_MAIL_OPERATION_STATUS_FAILED) {
                retval = MODEST_ERR_SEND;
index 45f4e1e..f2deaf3 100644 (file)
@@ -71,7 +71,7 @@ void        modest_pair_free       (ModestPair *self);
  * modest_pair_list_free:
  * @pairs: a valid ModestPairList
  *
- * convenience function to destroy all pairs in a list 
+ * Convenience function to destroy all pairs in a list and the list itself.
  *
  */
 void  modest_pair_list_free (ModestPairList *pairs);
index d27644c..bf464cd 100644 (file)
@@ -63,7 +63,13 @@ GType        modest_combo_box_get_type    (void) G_GNUC_CONST;
 
 /**
  * modest_combo_box_new
- * @pairs: a #ModestPairList; each element should be a ptr to a #ModestPair 
+ * @pairs: a #ModestPairList; each element should be a ptr to a #ModestPair,
+ * with the first item in the pair being an opaque ID, and the second item being 
+ * a gchar* string for display. 
+ * If the ID is a string or other non fundamental type, you must make sure that 
+ * the instance remains allocated for the lifetime of this combo box.
+ * The simplest way to achieve this is to ensure that the ModestPairList exists 
+ * for as long as the combo box.
  * @cmp_id_func: a GEqualFunc to compare the ids (= the first elements of the pairs)
  * For example, if the ids are strings, you can use g_str_equal.
  *
index 1f39e5b..9deadcb 100644 (file)
@@ -52,11 +52,19 @@ struct _ModestGlobalSettingsDialogPrivate {
        GtkWidget *composing_page;
 
        GtkWidget *auto_update;
+       
+       ModestPairList *connect_via_list;
        GtkWidget *connect_via;
+       
+       ModestPairList *update_interval_list;
        GtkWidget *update_interval;
+       
        GtkWidget *size_limit;
        GtkWidget *play_sound;
+       
+       ModestPairList *msg_format_list;
        GtkWidget *msg_format;
+       
        GtkWidget *include_reply;
 
        gboolean   changed;
index c57246d..43d01f1 100644 (file)
@@ -140,7 +140,14 @@ modest_global_settings_dialog_init (ModestGlobalSettingsDialog *self)
 static void
 modest_global_settings_dialog_finalize (GObject *obj)
 {
-/*     free/unref instance resources here */
+       ModestGlobalSettingsDialogPrivate *priv = 
+               MODEST_GLOBAL_SETTINGS_DIALOG_GET_PRIVATE (obj);
+
+       /* These had to stay alive as long as the comboboxes that used them: */
+       modest_pair_list_free (priv->connect_via_list);
+       modest_pair_list_free (priv->update_interval_list);
+       modest_pair_list_free (priv->msg_format_list);
+       
        G_OBJECT_CLASS(parent_class)->finalize (obj);
 }
 
index 047442a..a1e1a90 100644 (file)
@@ -70,6 +70,9 @@ typedef enum {
        MODEST_MSG_EDIT_FORMAT_HTML
 } ModestMsgEditFormat;
 
+/** Get these with modest_msg_edit_window_get_msg_data() 
+ * and free them with modest_msg_edit_window_free_msg_data().
+ */
 typedef struct  {
        gchar *from, *to, *cc, *bcc, *subject, *plain_body, *html_body;
        GList *attachments;