[balsa] Declare LibBalsaAddress final



commit c2a5b2597388ab70f02c53793d05bc5273174045
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Mon Jun 3 21:45:05 2019 -0400

    Declare LibBalsaAddress final
    
    Use G_DECLARE_FINAL_TYPE to declare LibBalsaAddress
    
    Make the structure private, and provide and use the necessary
    getters and setters.
    
    * libbalsa/abook-completion.c (address_compare):
    * libbalsa/address-book-extern.c (lbe_load_cb),
    (libbalsa_address_book_externq_add_address):
    * libbalsa/address-book-gpe.c (gpe_read_attr), (create_name),
    (gpe_read_address):
    * libbalsa/address-book-ldap.c
    (libbalsa_address_book_ldap_get_address),
    (libbalsa_address_book_ldap_add_address),
    (libbalsa_address_book_ldap_remove_address),
    (libbalsa_address_book_ldap_modify_address):
    * libbalsa/address-book-ldif.c (build_name), (address_new_prefill),
    (lbab_ldif_write_dn), (lbab_ldif_write_addresses),
    (lbab_ldif_write_surname), (lbab_ldif_write_givenname),
    (lbab_ldif_write_nickname), (lbab_ldif_write_organization):
    * libbalsa/address-book-osmo.c (utf8_lba_strstr),
    (libbalsa_address_book_osmo_alias_complete), (osmo_read_addresses):
    * libbalsa/address-book-rubrica.c
    (libbalsa_address_book_rubrica_load),
    (libbalsa_address_book_rubrica_add_address),
    (libbalsa_address_book_rubrica_modify_address),
    (lbab_rubrica_load_xml), (lbab_insert_address_node),
    (extract_cards):
    * libbalsa/address-book-text.c (lbab_text_item_compare),
    (lbab_text_load_file), (libbalsa_address_book_text_load):
    * libbalsa/address-book-vcard.c (lbab_vcard_write_fn),
    (lbab_vcard_write_n), (lbab_vcard_write_nickname),
    (lbab_vcard_write_org), (lbab_vcard_write_addresses),
    (libbalsa_address_book_vcard_parse_address):
    * libbalsa/address-book.c:
    * libbalsa/address-book.h:
    * libbalsa/address.c (libbalsa_address_class_init),
    (libbalsa_address_init), (libbalsa_address_finalize),
    (libbalsa_address_new_from_vcard), (libbalsa_address_set_copy),
    (libbalsa_address_to_gchar), (lba_get_name_or_mailbox),
    (libbalsa_address_get_name_from_list),
    (libbalsa_address_get_mailbox_from_list),
    (libbalsa_address_n_mailboxes_in_list),
    (libbalsa_address_set_edit_entries), (lba_addr_list_widget),
    (addrlist_drag_received_cb), (libbalsa_address_get_edit_widget),
    (libbalsa_address_new_from_edit_entries),
    (libbalsa_address_compare), (libbalsa_address_get_full_name),
    (libbalsa_address_get_first_name),
    (libbalsa_address_get_last_name), (libbalsa_address_get_nick_name),
    (libbalsa_address_get_organization), (libbalsa_address_get_addr),
    (libbalsa_address_get_addr_list), (libbalsa_address_set_full_name),

 ChangeLog                         |  69 +++++++++
 libbalsa/abook-completion.c       |   3 +-
 libbalsa/address-book-extern.c    |  36 +++--
 libbalsa/address-book-gpe.c       | 172 +++++++++++++++--------
 libbalsa/address-book-ldap.c      | 200 +++++++++++++++-----------
 libbalsa/address-book-ldif.c      | 120 +++++++++++-----
 libbalsa/address-book-osmo.c      |  31 +++--
 libbalsa/address-book-rubrica.c   |  88 +++++++-----
 libbalsa/address-book-text.c      |  58 ++++----
 libbalsa/address-book-vcard.c     |  95 +++++++------
 libbalsa/address-book.c           |  14 --
 libbalsa/address-book.h           |   2 -
 libbalsa/address.c                | 286 ++++++++++++++++++++++++++------------
 libbalsa/address.h                |  94 ++++++-------
 libbalsa/rfc2445.c                |  14 +-
 libbalsa/rfc6350.c                |  36 ++---
 src/ab-main.c                     |  11 +-
 src/ab-window.c                   |  32 +++--
 src/balsa-mime-widget-text.c      |  27 ++--
 src/balsa-mime-widget-vcalendar.c |   5 +-
 src/balsa-print-object-text.c     |  24 ++--
 src/store-address.c               |  31 ++---
 22 files changed, 898 insertions(+), 550 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 6e27b50f9..86c2cf536 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,72 @@
+2019-06-03  Peter Bloomfield  <pbloomfield bellsouth net>
+
+       Use G_DECLARE_FINAL_TYPE to declare LibBalsaAddress
+
+       Make the structure private, and provide and use the necessary
+       getters and setters.
+
+       * libbalsa/abook-completion.c (address_compare):
+       * libbalsa/address-book-extern.c (lbe_load_cb),
+       (libbalsa_address_book_externq_add_address):
+       * libbalsa/address-book-gpe.c (gpe_read_attr), (create_name),
+       (gpe_read_address):
+       * libbalsa/address-book-ldap.c
+       (libbalsa_address_book_ldap_get_address),
+       (libbalsa_address_book_ldap_add_address),
+       (libbalsa_address_book_ldap_remove_address),
+       (libbalsa_address_book_ldap_modify_address):
+       * libbalsa/address-book-ldif.c (build_name), (address_new_prefill),
+       (lbab_ldif_write_dn), (lbab_ldif_write_addresses),
+       (lbab_ldif_write_surname), (lbab_ldif_write_givenname),
+       (lbab_ldif_write_nickname), (lbab_ldif_write_organization):
+       * libbalsa/address-book-osmo.c (utf8_lba_strstr),
+       (libbalsa_address_book_osmo_alias_complete), (osmo_read_addresses):
+       * libbalsa/address-book-rubrica.c
+       (libbalsa_address_book_rubrica_load),
+       (libbalsa_address_book_rubrica_add_address),
+       (libbalsa_address_book_rubrica_modify_address),
+       (lbab_rubrica_load_xml), (lbab_insert_address_node),
+       (extract_cards):
+       * libbalsa/address-book-text.c (lbab_text_item_compare),
+       (lbab_text_load_file), (libbalsa_address_book_text_load):
+       * libbalsa/address-book-vcard.c (lbab_vcard_write_fn),
+       (lbab_vcard_write_n), (lbab_vcard_write_nickname),
+       (lbab_vcard_write_org), (lbab_vcard_write_addresses),
+       (libbalsa_address_book_vcard_parse_address):
+       * libbalsa/address-book.c:
+       * libbalsa/address-book.h:
+       * libbalsa/address.c (libbalsa_address_class_init),
+       (libbalsa_address_init), (libbalsa_address_finalize),
+       (libbalsa_address_new_from_vcard), (libbalsa_address_set_copy),
+       (libbalsa_address_to_gchar), (lba_get_name_or_mailbox),
+       (libbalsa_address_get_name_from_list),
+       (libbalsa_address_get_mailbox_from_list),
+       (libbalsa_address_n_mailboxes_in_list),
+       (libbalsa_address_set_edit_entries), (lba_addr_list_widget),
+       (addrlist_drag_received_cb), (libbalsa_address_get_edit_widget),
+       (libbalsa_address_new_from_edit_entries),
+       (libbalsa_address_compare), (libbalsa_address_get_full_name),
+       (libbalsa_address_get_first_name),
+       (libbalsa_address_get_last_name), (libbalsa_address_get_nick_name),
+       (libbalsa_address_get_organization), (libbalsa_address_get_addr),
+       (libbalsa_address_get_addr_list), (libbalsa_address_set_full_name),
+       (libbalsa_address_set_first_name),
+       (libbalsa_address_set_last_name), (libbalsa_address_set_nick_name),
+       (libbalsa_address_set_organization),
+       (libbalsa_address_set_addr_list), (libbalsa_address_add_addr):
+       * libbalsa/address.h:
+       * libbalsa/rfc2445.c (libbalsa_vevent_reply),
+       (cal_address_2445_to_lbaddress):
+       * libbalsa/rfc6350.c (rfc6350_parse_from_stream),
+       (rfc6350_eval_line):
+       * src/ab-main.c (bab_load_cb):
+       * src/ab-window.c (balsa_ab_window_load_cb):
+       * src/balsa-mime-widget-text.c (bm_widget_new_vcard):
+       * src/balsa-mime-widget-vcalendar.c (balsa_vevent_widget):
+       * src/balsa-print-object-text.c (balsa_print_object_text_vcard):
+       * src/store-address.c (store_address_add_address),
+       (store_address_add_lbaddress):
+
 2019-06-02  Albrecht Dreß  <albrecht dress arcor de>
 
        GMimeGpgmeSigstat: use G_DECLARE_FINAL_TYPE(), G_DEFINE_TYPE()
diff --git a/libbalsa/abook-completion.c b/libbalsa/abook-completion.c
index 3b975cf8e..b6475fe32 100644
--- a/libbalsa/abook-completion.c
+++ b/libbalsa/abook-completion.c
@@ -98,7 +98,8 @@ address_compare(LibBalsaAddress *a, LibBalsaAddress *b)
     g_return_val_if_fail(a != NULL, -1);
     g_return_val_if_fail(b != NULL, 1);
 
-    return g_ascii_strcasecmp(a->full_name, b->full_name);
+    return g_ascii_strcasecmp(libbalsa_address_get_full_name(a),
+                              libbalsa_address_get_full_name(b));
 }
 
 /*
diff --git a/libbalsa/address-book-extern.c b/libbalsa/address-book-extern.c
index 7d4ab5b4c..2e8583ec7 100644
--- a/libbalsa/address-book-extern.c
+++ b/libbalsa/address-book-extern.c
@@ -183,6 +183,7 @@ struct lbe_load_data {
     LibBalsaAddressBookLoadFunc callback;
     gpointer closure;
 };
+
 static void
 lbe_load_cb(const gchar *email, const gchar *name, void *data)
 {
@@ -190,14 +191,13 @@ lbe_load_cb(const gchar *email, const gchar *name, void *data)
     LibBalsaAddress *address = libbalsa_address_new();
 
     /* The extern database doesn't support Id's, sorry! */
-    address->nick_name = g_strdup(_("No-Id"));
-    address->address_list = g_list_append(address->address_list,
-                                          g_strdup(email));
-    
-    if (name) address->full_name = g_strdup(name);
-    else address->full_name = g_strdup(_("No-Name"));
+    libbalsa_address_set_nick_name(address, _("No-Id"));
+    libbalsa_address_add_addr(address, email);
+    libbalsa_address_set_full_name(address, name != NULL ? name : _("No-Name"));
+
     d->callback(d->ab, address, d->closure);
-    g_object_unref(G_OBJECT(address));
+
+    g_object_unref(address);
 }
 
 static LibBalsaABErr
@@ -271,7 +271,7 @@ parse_externq_file(LibBalsaAddressBookExternq *ab_externq,
 
 static LibBalsaABErr
 libbalsa_address_book_externq_add_address(LibBalsaAddressBook * ab,
-                                         LibBalsaAddress * new_address)
+                                          LibBalsaAddress * new_address)
 {
     gchar command[LINE_LEN];
     LibBalsaAddressBookExternq *ab_externq;
@@ -280,15 +280,21 @@ libbalsa_address_book_externq_add_address(LibBalsaAddressBook * ab,
 
     ab_externq = LIBBALSA_ADDRESS_BOOK_EXTERNQ(ab);
     if (ab_externq->save != NULL) {
-        g_snprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\"", 
-                   ab_externq->save, 
-                   (gchar *)g_list_first(new_address->address_list)->data, 
-                   new_address->full_name, "TODO");
-        
-        if( (gc = popen(command, "r")) == NULL)
+        GList *addr_list;
+        const gchar *full_name;
+
+        addr_list = libbalsa_address_get_addr_list(new_address);
+        full_name = libbalsa_address_get_full_name(new_address);
+
+        g_snprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\"",
+                   ab_externq->save,
+                   (gchar *) addr_list->data,
+                   full_name, "TODO");
+        if ((gc = popen(command, "r")) == NULL)
             return LBABERR_CANNOT_WRITE;
-        if(fclose(gc) != 0) 
+        if (fclose(gc) != 0)
             return LBABERR_CANNOT_WRITE;
+
         return LBABERR_OK;
     } else return LBABERR_CANNOT_WRITE;
 }
diff --git a/libbalsa/address-book-gpe.c b/libbalsa/address-book-gpe.c
index 7be6bfc34..637770ffd 100644
--- a/libbalsa/address-book-gpe.c
+++ b/libbalsa/address-book-gpe.c
@@ -230,23 +230,30 @@ libbalsa_address_book_gpe_open_db(LibBalsaAddressBookGpe * ab_gpe)
 static int
 gpe_read_attr(void *arg, int argc, char **argv, char **names)
 {
-    LibBalsaAddress * a= arg;
+    LibBalsaAddress *address = arg;
 
     /* follow read_entry_data/db_set_multi_data */
-    if(g_ascii_strcasecmp(argv[0], "NAME") == 0 &&
-       !a->full_name) a->full_name = g_strdup(argv[1]);
-    else if(g_ascii_strcasecmp(argv[0], "GIVEN_NAME") == 0 &&
-            !a->first_name) a->first_name = g_strdup(argv[1]);
-    else if(g_ascii_strcasecmp(argv[0], "FAMILY_NAME") == 0 &&
-            !a->last_name) a->last_name = g_strdup(argv[1]);
-    else if(g_ascii_strcasecmp(argv[0], "NICKNAME") == 0 &&
-            !a->nick_name) a->nick_name = g_strdup(argv[1]);
-    else if(g_ascii_strcasecmp(argv[0], "WORK.ORGANIZATION") == 0 &&
-            !a->organization) a->organization = g_strdup(argv[1]);
-    else if(g_ascii_strcasecmp(argv[0], "HOME.EMAIL") == 0)
-        a->address_list = g_list_prepend(a->address_list, g_strdup(argv[1]));
-    else if(g_ascii_strcasecmp(argv[0], "WORK.EMAIL") == 0)
-        a->address_list = g_list_prepend(a->address_list, g_strdup(argv[1]));
+    if (g_ascii_strcasecmp(argv[0], "NAME") == 0 &&
+        libbalsa_address_get_full_name(address) == NULL) {
+        libbalsa_address_set_full_name(address, argv[1]);
+    } else if (g_ascii_strcasecmp(argv[0], "GIVEN_NAME") == 0 &&
+               libbalsa_address_get_first_name(address) == NULL) {
+        libbalsa_address_set_first_name(address, argv[1]);
+    } else if (g_ascii_strcasecmp(argv[0], "FAMILY_NAME") == 0 &&
+               libbalsa_address_get_last_name(address) == NULL) {
+        libbalsa_address_set_last_name(address, argv[1]);
+    } else if (g_ascii_strcasecmp(argv[0], "NICKNAME") == 0 &&
+               libbalsa_address_get_nick_name(address) == NULL) {
+        libbalsa_address_set_nick_name(address, argv[1]);
+    } else if (g_ascii_strcasecmp(argv[0], "WORK.ORGANIZATION") == 0 &&
+               libbalsa_address_get_organization(address) == NULL) {
+        libbalsa_address_set_organization(address, argv[1]);
+    } else if (g_ascii_strcasecmp(argv[0], "HOME.EMAIL") == 0) {
+        libbalsa_address_add_addr(address, argv[1]);
+    } else if (g_ascii_strcasecmp(argv[0], "WORK.EMAIL") == 0) {
+        libbalsa_address_add_addr(address, argv[1]);
+    }
+
     return 0;
 }
 
@@ -260,7 +267,7 @@ gpe_read_attr(void *arg, int argc, char **argv, char **names)
  *   NULL on failure (both first and last names invalid.
  */
 static gchar *
-create_name(gchar * first, gchar * last)
+create_name(const gchar * first, const gchar * last)
 {
     if ((first == NULL) && (last == NULL))
        return NULL;
@@ -282,7 +289,7 @@ static int
 gpe_read_address(void *arg, int argc, char **argv, char **names)
 {
     struct gpe_closure *gc = arg;
-    LibBalsaAddress * a= libbalsa_address_new();
+    LibBalsaAddress *address = libbalsa_address_new();
     guint uid = atoi(argv[0]);
 
     /* follow read_entry_data. FIXME: error reporting */
@@ -290,21 +297,35 @@ gpe_read_address(void *arg, int argc, char **argv, char **names)
     gchar *sql =
         sqlite3_mprintf("select tag,value from contacts where urn=%d",
                         uid);
-    sqlite3_exec(gc->ab_gpe->db, sql, gpe_read_attr, a, NULL);
+    sqlite3_exec(gc->ab_gpe->db, sql, gpe_read_attr, address, NULL);
     sqlite3_free(sql);
 #else                           /* HAVE_SQLITE3 */
-    sqlite_exec_printf (gc->ab_gpe->db,
-                        "select tag,value from contacts where urn=%d",
-                        gpe_read_attr, a, NULL, uid);
+    sqlite_exec_printf(gc->ab_gpe->db,
+                       "select tag,value from contacts where urn=%d",
+                       gpe_read_attr, address, NULL, uid);
 #endif                          /* HAVE_SQLITE3 */
-    if(!a->address_list) { /* entry without address: ignore! */
-        g_object_unref(a);
+
+    if (libbalsa_address_get_addr_list(address) == NULL) {
+        /* entry without address: ignore! */
+        g_object_unref(address);
         return 0;
     }
-    if(!a->full_name)
-        a->full_name = create_name(a->first_name, a->last_name);
-    g_object_set_data(G_OBJECT(a), "urn", GUINT_TO_POINTER(uid));
-    gc->callback(LIBBALSA_ADDRESS_BOOK(gc->ab_gpe), a, gc->closure);
+
+    if (libbalsa_address_get_full_name(address) == NULL) {
+        const gchar *first_name;
+        const gchar *last_name;
+        gchar *full_name;
+
+        first_name = libbalsa_address_get_first_name(address);
+        last_name  = libbalsa_address_get_last_name(address);
+        full_name  = create_name(first_name, last_name);
+        libbalsa_address_set_full_name(address, full_name);
+        g_free(full_name);
+    }
+
+    g_object_set_data(G_OBJECT(address), "urn", GUINT_TO_POINTER(uid));
+    gc->callback(LIBBALSA_ADDRESS_BOOK(gc->ab_gpe), address, gc->closure);
+
     return 0;
 }
 
@@ -411,6 +432,7 @@ libbalsa_address_book_gpe_add_address(LibBalsaAddressBook *ab,
                                        LibBalsaAddress *address)
 {
     LibBalsaAddressBookGpe *ab_gpe = LIBBALSA_ADDRESS_BOOK_GPE(ab);
+    const gchar *addr;
     int r;
     guint id;
     char *err = NULL;
@@ -418,8 +440,9 @@ libbalsa_address_book_gpe_add_address(LibBalsaAddressBook *ab,
     gchar *sql;
 #endif                          /* HAVE_SQLITE3 */
 
-    g_return_val_if_fail(address, LBABERR_CANNOT_WRITE);
-    g_return_val_if_fail(address->address_list, LBABERR_CANNOT_WRITE);
+    g_return_val_if_fail(address != NULL, LBABERR_CANNOT_WRITE);
+    addr = libbalsa_address_get_addr(address);
+    g_return_val_if_fail(addr != NULL, LBABERR_CANNOT_WRITE);
 
     if (ab_gpe->db == NULL) {
         if(!libbalsa_address_book_gpe_open_db(ab_gpe))
@@ -447,13 +470,19 @@ libbalsa_address_book_gpe_add_address(LibBalsaAddressBook *ab,
 #else                           /* HAVE_SQLITE3 */
     id = sqlite_last_insert_rowid(ab_gpe->db);
 #endif                          /* HAVE_SQLITE3 */
-    INSERT_ATTR(ab_gpe->db,id, "NAME",        address->full_name);
-    INSERT_ATTR(ab_gpe->db,id, "GIVEN_NAME",  address->first_name);
-    INSERT_ATTR(ab_gpe->db,id, "FAMILY_NAME", address->last_name);
-    INSERT_ATTR(ab_gpe->db,id, "NICKNAME",    address->nick_name);
-    INSERT_ATTR(ab_gpe->db,id, "WORK.ORGANIZATION", address->organization);
-    INSERT_ATTR(ab_gpe->db,id, "WORK.EMAIL",
-                (char*)address->address_list->data);
+
+    INSERT_ATTR(ab_gpe->db,id, "NAME",
+                libbalsa_address_get_full_name(address));
+    INSERT_ATTR(ab_gpe->db,id, "GIVEN_NAME",
+                libbalsa_address_get_first_name(address));
+    INSERT_ATTR(ab_gpe->db,id, "FAMILY_NAME",
+                libbalsa_address_get_last_name(address));
+    INSERT_ATTR(ab_gpe->db,id, "NICKNAME",
+                libbalsa_address_get_nick_name(address));
+    INSERT_ATTR(ab_gpe->db,id, "WORK.ORGANIZATION",
+                libbalsa_address_get_organization(address));
+    INSERT_ATTR(ab_gpe->db,id, "WORK.EMAIL", addr);
+
 #ifdef HAVE_SQLITE3
     sql = sqlite3_mprintf("insert into contacts values "
                           "('%d', 'MODIFIED', %d)",
@@ -533,8 +562,8 @@ libbalsa_address_book_gpe_remove_address(LibBalsaAddressBook *ab,
     LibBalsaAddressBookGpe *ab_gpe = LIBBALSA_ADDRESS_BOOK_GPE(ab);
     guint uid;
     char *err;
-    g_return_val_if_fail(address, LBABERR_CANNOT_WRITE);
-    g_return_val_if_fail(address->address_list, LBABERR_CANNOT_WRITE);
+
+    g_return_val_if_fail(address != NULL, LBABERR_CANNOT_WRITE);
 
     if (ab_gpe->db == NULL) {
         if( !libbalsa_address_book_gpe_open_db(ab_gpe))
@@ -583,6 +612,7 @@ libbalsa_address_book_gpe_modify_address(LibBalsaAddressBook *ab,
                                          LibBalsaAddress *newval)
 {
     LibBalsaAddressBookGpe *ab_gpe = LIBBALSA_ADDRESS_BOOK_GPE(ab);
+    const gchar *addr;
     guint uid;
     int r;
     char *err;
@@ -590,9 +620,11 @@ libbalsa_address_book_gpe_modify_address(LibBalsaAddressBook *ab,
     gchar *sql;
 #endif                          /* HAVE_SQLITE3 */
 
-    g_return_val_if_fail(address, LBABERR_CANNOT_WRITE);
-    g_return_val_if_fail(address->address_list, LBABERR_CANNOT_WRITE);
-    g_return_val_if_fail(newval->address_list, LBABERR_CANNOT_WRITE);
+    g_return_val_if_fail(address != NULL, LBABERR_CANNOT_WRITE);
+    g_return_val_if_fail(newval  != NULL, LBABERR_CANNOT_WRITE);
+
+    addr = libbalsa_address_get_addr(newval);
+    g_return_val_if_fail(addr != NULL, LBABERR_CANNOT_WRITE);
 
     if (ab_gpe->db == NULL) {
         if( !libbalsa_address_book_gpe_open_db(ab_gpe))
@@ -639,13 +671,19 @@ libbalsa_address_book_gpe_modify_address(LibBalsaAddressBook *ab,
           NULL, NULL, &err, uid)) != SQLITE_OK)
         goto rollback;
 #endif                          /* HAVE_SQLITE3 */
-    INSERT_ATTR_R(ab_gpe->db,uid, "NAME",        newval->full_name);
-    INSERT_ATTR_R(ab_gpe->db,uid, "GIVEN_NAME",  newval->first_name);
-    INSERT_ATTR_R(ab_gpe->db,uid, "FAMILY_NAME", newval->last_name);
-    INSERT_ATTR_R(ab_gpe->db,uid, "NICKNAME",    newval->nick_name);
-    INSERT_ATTR_R(ab_gpe->db,uid, "WORK.ORGANIZATION", newval->organization);
-    INSERT_ATTR_R(ab_gpe->db,uid, "WORK.EMAIL",
-                (char*)newval->address_list->data);
+
+    INSERT_ATTR_R(ab_gpe->db,uid, "NAME",
+                  libbalsa_address_get_full_name(newval));
+    INSERT_ATTR_R(ab_gpe->db,uid, "GIVEN_NAME",
+                  libbalsa_address_get_first_name(newval));
+    INSERT_ATTR_R(ab_gpe->db,uid, "FAMILY_NAME",
+                  libbalsa_address_get_last_name(newval));
+    INSERT_ATTR_R(ab_gpe->db,uid, "NICKNAME",
+                  libbalsa_address_get_nick_name(newval));
+    INSERT_ATTR_R(ab_gpe->db,uid, "WORK.ORGANIZATION",
+                  libbalsa_address_get_organization(newval));
+    INSERT_ATTR_R(ab_gpe->db,uid, "WORK.EMAIL", addr);
+
 #ifdef HAVE_SQLITE3
     sql = sqlite3_mprintf("insert into contacts values "
                           "('%d', 'MODIFIED', %d)", uid, time(NULL));
@@ -694,8 +732,9 @@ static int
 gpe_read_completion(void *arg, int argc, char **argv, char **names)
 {
     struct gpe_completion_closure *gc = arg;
-    LibBalsaAddress * a= libbalsa_address_new();
+    LibBalsaAddress *address = libbalsa_address_new();
     InternetAddress *ia;
+    GList *addr_list;
     GList *l;
     guint uid = atoi(argv[0]);
 #ifdef HAVE_SQLITE3
@@ -704,26 +743,43 @@ gpe_read_completion(void *arg, int argc, char **argv, char **names)
     /* follow read_entry_data. FIXME: error reporting */
     sql = sqlite3_mprintf("select tag,value from contacts where urn=%d",
                           uid);
-    sqlite3_exec(gc->db, sql, gpe_read_attr, a, NULL);
+    sqlite3_exec(gc->db, sql, gpe_read_attr, address, NULL);
     sqlite3_free(sql);
 #else                           /* HAVE_SQLITE3 */
 
     /* follow read_entry_data. FIXME: error reporting */
     sqlite_exec_printf(gc->db,
                        "select tag,value from contacts where urn=%d",
-                       gpe_read_attr, a, NULL, uid);
+                       gpe_read_attr, address, NULL, uid);
 #endif                          /* HAVE_SQLITE3 */
-    if(!a->address_list) { /* entry without address: ignore! */
-        g_object_unref(a);
+
+    addr_list = libbalsa_address_get_addr_list(address);
+    if (addr_list == NULL) {
+        /* entry without address: ignore! */
+        g_object_unref(address);
         return 0;
     }
-    if(!a->full_name)
-        a->full_name = create_name(a->first_name, a->last_name);
-    for(l=a->address_list; l; l = l->next) {
-        ia = internet_address_mailbox_new(a->full_name, l->data);
+
+    if (libbalsa_address_get_full_name(address) == NULL) {
+        const gchar *first_name;
+        const gchar *last_name;
+        gchar *full_name;
+
+        first_name = libbalsa_address_get_first_name(address);
+        last_name  = libbalsa_address_get_last_name(address);
+        full_name  = create_name(first_name, last_name);
+        libbalsa_address_set_full_name(address, full_name);
+        g_free(full_name);
+    }
+
+    for (l = addr_list; l != NULL; l = l->next) {
+        const gchar *full_name = libbalsa_address_get_full_name(address);
+        ia = internet_address_mailbox_new(full_name, (gchar *) l->data);
         gc->res = g_list_prepend(gc->res, ia);
     }
-    g_object_unref(G_OBJECT(a));
+
+    g_object_unref(address);
+
     return 0;
 }
 
diff --git a/libbalsa/address-book-ldap.c b/libbalsa/address-book-ldap.c
index 303aeafa3..219d88d1b 100644
--- a/libbalsa/address-book-ldap.c
+++ b/libbalsa/address-book-ldap.c
@@ -432,7 +432,7 @@ libbalsa_address_book_ldap_get_address(LibBalsaAddressBook * ab,
                                       LDAPMessage * e)
 {
     LibBalsaAddressBookLdap *ab_ldap;
-    GList *email = NULL;
+    gchar *email = NULL;
     gchar *cn = NULL, *org = NULL, *uid = NULL;
     gchar *first = NULL, *last = NULL;
     LibBalsaAddress *address = NULL;
@@ -448,20 +448,27 @@ libbalsa_address_book_ldap_get_address(LibBalsaAddressBook * ab,
        /*
         * For each attribute, get the attribute name and values.
         */
-       if ((vals=ldap_get_values_len(ab_ldap->directory, e, attr)) != NULL) {
+       if ((vals = ldap_get_values_len(ab_ldap->directory, e, attr)) != NULL) {
            for (i = 0; vals[i] != NULL; i++) {
-               if ((g_ascii_strcasecmp(attr, "sn") == 0) && (!last))
-                   last = g_strndup(vals[i]->bv_val, vals[i]->bv_len);
-               if ((g_ascii_strcasecmp(attr, "cn") == 0) && (!cn))
-                   cn = g_strndup(vals[i]->bv_val, vals[i]->bv_len);
-               if ((g_ascii_strcasecmp(attr, "givenName") == 0) && (!first))
-                   first = g_strndup(vals[i]->bv_val, vals[i]->bv_len);
-               if ((g_ascii_strcasecmp(attr, "o") == 0) && (!org))
-                   org = g_strndup(vals[i]->bv_val, vals[i]->bv_len);
-               if ((g_ascii_strcasecmp(attr, "uid") == 0) && (!uid))
-                   uid = g_strndup(vals[i]->bv_val, vals[i]->bv_len);
-               if (g_ascii_strcasecmp(attr, "mail") == 0)
-                   email = g_list_prepend(email, g_strndup(vals[i]->bv_val, vals[i]->bv_len));
+               if (g_ascii_strcasecmp(attr, "sn") == 0) {
+                    if (last == NULL)
+                        last = g_strndup(vals[i]->bv_val, vals[i]->bv_len);
+                } else if (g_ascii_strcasecmp(attr, "cn") == 0) {
+                    if (cn == NULL)
+                        cn = g_strndup(vals[i]->bv_val, vals[i]->bv_len);
+                } else if (g_ascii_strcasecmp(attr, "givenName") == 0) {
+                    if (first == NULL)
+                        first = g_strndup(vals[i]->bv_val, vals[i]->bv_len);
+                } else if (g_ascii_strcasecmp(attr, "o") == 0) {
+                    if (org == NULL)
+                        org = g_strndup(vals[i]->bv_val, vals[i]->bv_len);
+                } else if (g_ascii_strcasecmp(attr, "uid") == 0) {
+                    if (uid == NULL)
+                        uid = g_strndup(vals[i]->bv_val, vals[i]->bv_len);
+                } else if (g_ascii_strcasecmp(attr, "mail") == 0) {
+                    if (email == NULL)
+                        email = g_strndup(vals[i]->bv_val, vals[i]->bv_len);
+                }
            }
            ldap_value_free_len(vals);
        }
@@ -470,22 +477,34 @@ libbalsa_address_book_ldap_get_address(LibBalsaAddressBook * ab,
     /*
      * Record will have e-mail (searched)
      */
-    if(email == NULL) email = g_list_prepend(email, g_strdup("none"));
-    g_return_val_if_fail(email != NULL, NULL);
+    if (email == NULL)
+        email = g_strdup("none");
 
     address = libbalsa_address_new();
-    if (cn)
-       address->full_name = cn;
-    else {
-       address->full_name = create_name(first, last);
-        if(!address->full_name)
-            address->full_name = g_strdup(_("No-Name"));
+    if (cn != NULL) {
+        libbalsa_address_set_full_name(address, cn);
+        g_free(cn);
+    } else {
+        gchar *full_name = create_name(first, last);
+
+        if (full_name != NULL) {
+            libbalsa_address_set_full_name(address, full_name);
+            g_free(full_name);
+        } else {
+            libbalsa_address_set_full_name(address, _("No-Name"));
+        }
     }
-    address->first_name = first;
-    address->last_name = last;
-    address->nick_name = uid;
-    address->organization = org;
-    address->address_list = email;
+
+    libbalsa_address_set_first_name(address, first);
+    g_free(first);
+    libbalsa_address_set_last_name(address, last);
+    g_free(last);
+    libbalsa_address_set_nick_name(address, uid);
+    g_free(uid);
+    libbalsa_address_set_organization(address, org);
+    g_free(org);
+    libbalsa_address_add_addr(address, email);
+    g_free(email);
 
     return address;
 }
@@ -557,7 +576,7 @@ create_name(gchar * first, gchar * last)
 
 #define SETMOD(mods,modarr,op,attr,strv,val) \
    do { (mods) = &(modarr); (modarr).mod_type=attr; (modarr).mod_op=op;\
-        (strv)[0]=(val); (modarr).mod_values=strv; \
+        (strv)[0]=(char*)(val); (modarr).mod_values=strv; \
       } while(0)
 
 static LibBalsaABErr
@@ -576,9 +595,12 @@ libbalsa_address_book_ldap_add_address(LibBalsaAddressBook *ab,
     char *sn[]   = {NULL, NULL};
     char *mail[] = {NULL, NULL};
     LibBalsaAddressBookLdap *ab_ldap = LIBBALSA_ADDRESS_BOOK_LDAP(ab);
+    const gchar *addr;
+    const gchar *item;
 
-    g_return_val_if_fail(address, LBABERR_CANNOT_WRITE);
-    g_return_val_if_fail(address->address_list, LBABERR_CANNOT_WRITE);
+    g_return_val_if_fail(address != NULL, LBABERR_CANNOT_WRITE);
+    addr = libbalsa_address_get_addr(address);
+    g_return_val_if_fail(addr != NULL, LBABERR_CANNOT_WRITE);
 
     if (ab_ldap->directory == NULL) {
         if(libbalsa_address_book_ldap_open_connection(ab_ldap) != LDAP_SUCCESS)
@@ -592,7 +614,7 @@ libbalsa_address_book_ldap_add_address(LibBalsaAddressBook *ab,
     }
 
     dn = g_strdup_printf("mail=%s,%s",
-                         (char*)address->address_list->data,
+                         addr,
                          ab_ldap->priv_book_dn);
     mods[0] = &modarr[0];
     modarr[0].mod_op = LDAP_MOD_ADD;
@@ -600,26 +622,31 @@ libbalsa_address_book_ldap_add_address(LibBalsaAddressBook *ab,
     modarr[0].mod_values = object_class_values;
     cnt = 1;
 
-    if(address->full_name) {
-        SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_ADD,"cn",cn,address->full_name);
+    item = libbalsa_address_get_full_name(address);
+    if (item != NULL) {
+        SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "cn", cn, item);
         cnt++;
     }
-    if(address->first_name) {
-        SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_ADD,"givenName",gn,
-               address->first_name);
+
+    item = libbalsa_address_get_first_name(address);
+    if (item != NULL) {
+        SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "givenName", gn, item);
         cnt++;
     }
-    if(address->last_name) {
-        SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_ADD,"sn",sn,address->last_name);
+
+    item = libbalsa_address_get_last_name(address);
+    if (item != NULL) {
+        SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "sn", sn, item);
         cnt++;
     }
-    if(address->organization) {
-        SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_ADD,"o",org,
-               address->organization);
+
+    item = libbalsa_address_get_organization(address);
+    if (item != NULL) {
+        SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "o", org, item);
         cnt++;
     }
-    SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_ADD,"mail",mail,
-               (char*)address->address_list->data);
+
+    SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "mail", mail, addr);
     cnt++;
     mods[cnt] = NULL;
 
@@ -655,11 +682,13 @@ libbalsa_address_book_ldap_remove_address(LibBalsaAddressBook *ab,
                                           LibBalsaAddress *address)
 {
     LibBalsaAddressBookLdap *ab_ldap = LIBBALSA_ADDRESS_BOOK_LDAP(ab);
+    const gchar *addr;
     gchar *dn;
     int cnt, rc;
 
-    g_return_val_if_fail(address, LBABERR_CANNOT_WRITE);
-    g_return_val_if_fail(address->address_list, LBABERR_CANNOT_WRITE);
+    g_return_val_if_fail(address != NULL, LBABERR_CANNOT_WRITE);
+    addr = libbalsa_address_get_addr(address);
+    g_return_val_if_fail(addr != NULL, LBABERR_CANNOT_WRITE);
 
     if (ab_ldap->directory == NULL) {
         if( (rc=libbalsa_address_book_ldap_open_connection(ab_ldap))
@@ -668,7 +697,7 @@ libbalsa_address_book_ldap_remove_address(LibBalsaAddressBook *ab,
     }
 
     dn = g_strdup_printf("mail=%s,%s",
-                         (char*)address->address_list->data,
+                         addr,
                          ab_ldap->priv_book_dn);
     cnt = 0;
     do {
@@ -712,75 +741,88 @@ libbalsa_address_book_ldap_modify_address(LibBalsaAddressBook *ab,
     char *org[]  = {NULL, NULL};
     char *sn[]   = {NULL, NULL};
     LibBalsaAddressBookLdap *ab_ldap = LIBBALSA_ADDRESS_BOOK_LDAP(ab);
+    const gchar *addr;
+    const gchar *new_addr;
+    const gchar *item;
+    const gchar *new_item;
 
-    g_return_val_if_fail(address, LBABERR_CANNOT_WRITE);
-    g_return_val_if_fail(address->address_list, LBABERR_CANNOT_WRITE);
-    g_return_val_if_fail(newval->address_list, LBABERR_CANNOT_WRITE);
+    g_return_val_if_fail(address != NULL, LBABERR_CANNOT_WRITE);
+    addr = libbalsa_address_get_addr(address);
+    g_return_val_if_fail(addr != NULL, LBABERR_CANNOT_WRITE);
 
-    if(!STREQ(address->address_list->data,newval->address_list->data)) {
+    g_return_val_if_fail(newval != NULL, LBABERR_CANNOT_WRITE);
+    new_addr = libbalsa_address_get_addr(newval);
+    g_return_val_if_fail(new_addr != NULL, LBABERR_CANNOT_WRITE);
+
+    if(!STREQ(addr, new_addr)) {
         /* email address has changed, we have to remove old entry and
          * add a new one. */
-        if( (rc=libbalsa_address_book_ldap_add_address(ab, newval)) 
+        if ((rc = libbalsa_address_book_ldap_add_address(ab, newval))
             != LBABERR_OK)
             return rc;
         return libbalsa_address_book_ldap_remove_address(ab, address);
     }
-    /* the email address has not changed, continue with changing other 
+
+    /* the email address has not changed, continue with changing other
      * attributes. */
     if (ab_ldap->directory == NULL) {
-        if( (rc=libbalsa_address_book_ldap_open_connection(ab_ldap))
+        if ((rc = libbalsa_address_book_ldap_open_connection(ab_ldap))
            != LDAP_SUCCESS)
            return LBABERR_CANNOT_CONNECT;
     }
 
     dn = g_strdup_printf("mail=%s,%s",
-                         (char*)address->address_list->data,
+                         addr,
                          ab_ldap->priv_book_dn);
     cnt = 0;
 
-    if(!STREQ(address->full_name,newval->full_name)) {
-        if(newval->full_name)
-            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_REPLACE,"cn",cn,
-                   newval->full_name);
+    item = libbalsa_address_get_full_name(address);
+    new_item = libbalsa_address_get_full_name(newval);
+    if (!STREQ(item, new_item)) {
+        if (new_item != NULL)
+            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_REPLACE,"cn",cn, new_item);
         else
-            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_DELETE,"cn",cn,
-                   address->full_name);
+            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_DELETE,"cn",cn, item);
         cnt++;
     }
-    if(!STREQ(address->first_name,newval->first_name)) {
-        if(newval->first_name)
-            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_REPLACE,"givenName",gn,
-                   newval->first_name);
+
+    item = libbalsa_address_get_first_name(address);
+    new_item = libbalsa_address_get_first_name(newval);
+    if (!STREQ(item, new_item)) {
+        if (new_item != NULL)
+            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_REPLACE,"givenName",gn, new_item);
         else
-            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_DELETE,"givenName",gn,
-                   address->first_name);
+            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_DELETE,"givenName",gn, item);
         cnt++;
     }
-    if(!STREQ(address->last_name,newval->last_name)) {
-        if(newval->last_name)
-            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_REPLACE,"sn",sn,
-                   newval->last_name);
+
+    item = libbalsa_address_get_last_name(address);
+    new_item = libbalsa_address_get_last_name(newval);
+    if (!STREQ(item, new_item)) {
+        if (new_item != NULL)
+            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_REPLACE,"sn",sn, new_item);
         else
-            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_DELETE,"sn",sn,
-                   address->last_name);
+            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_DELETE,"sn",sn, item);
         cnt++;
     }
-    if(!STREQ(address->organization,newval->organization)) {
-        if(newval->organization)
-            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_REPLACE,"o",
-                   org, newval->organization);
+
+    item = libbalsa_address_get_organization(address);
+    new_item = libbalsa_address_get_organization(newval);
+    if (!STREQ(item, new_item)) {
+        if (new_item != NULL)
+            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_REPLACE,"o", org, new_item);
         else
-            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_DELETE,"o",
-                   org, address->organization);
+            SETMOD(mods[cnt],modarr[cnt],LDAP_MOD_DELETE,"o", org, item);
         cnt++;
     }
     mods[cnt] = NULL;
 
-    if(cnt == 0) {
+    if (cnt == 0) {
         /* nothing to modify */
         g_free(dn);
         return LBABERR_OK;
     }
+
     cnt = 0;
     do {
         rc = ldap_modify_ext_s(ab_ldap->directory, dn, mods, NULL, NULL);
diff --git a/libbalsa/address-book-ldif.c b/libbalsa/address-book-ldif.c
index 78ead0c14..6231db42a 100644
--- a/libbalsa/address-book-ldif.c
+++ b/libbalsa/address-book-ldif.c
@@ -179,19 +179,22 @@ read_line(FILE* f)
    Returns a NULL pointer if it couldn't figure out a name. 
 */
 static gchar *
-build_name(gchar *cn, gchar *givenname, gchar *surname)
+build_name(const gchar *cn, const gchar *givenname, const gchar *surname)
 {
     gchar *name = NULL;
 
-    if(cn && *cn) {
+    if (cn != NULL && cn[0] != '\0') {
        name = g_strdup(cn);
-    } else if(givenname && *givenname && surname && *surname) {
-       name = g_strconcat (givenname," ",surname,NULL);
-    } else if(givenname && *givenname) {
+    } else if(givenname != NULL && givenname[0] != '\0' &&
+              surname != NULL && surname[0] != '\0') {
+       name = g_strconcat(givenname, " ", surname, NULL);
+    } else if (givenname != NULL && givenname[0] != '\0') {
        name = g_strdup(givenname);
-    } else if(surname && *surname) {
+    } else if(surname != NULL && surname[0] != '\0') {
        name = g_strdup(surname);
-    } else name = g_strdup(_("No-Name")); 
+    } else
+        name = g_strdup(_("No-Name"));
+
     return name;
 }
 
@@ -203,19 +206,47 @@ address_new_prefill(LibBalsaAddress * address, GList * address_list,
                     gchar * nickn, gchar * givenn, gchar * surn,
                     gchar * fulln, gchar * org)
 {
-    address->address_list = address_list;
-    
-    address->first_name = givenn ? givenn : g_strdup(nickn ? nickn : "");
-    address->last_name = surn ? surn : g_strdup("");
-    address->full_name = build_name(fulln, address->first_name, surn);
+    gchar *full_name;
+
+    libbalsa_address_set_addr_list(address, address_list);
+
+    if (givenn != NULL) {
+        libbalsa_address_set_first_name(address, givenn);
+        g_free(givenn);
+    } else {
+        libbalsa_address_set_first_name(address, nickn != NULL ? nickn : "");
+    }
+
+    if (surn != NULL) {
+        libbalsa_address_set_last_name(address, surn);
+        g_free(surn);
+    } else {
+        libbalsa_address_set_last_name(address, "");
+    }
+
+    full_name = build_name(fulln, libbalsa_address_get_first_name(address), surn);
+    if (full_name != NULL) {
+        libbalsa_address_set_full_name(address, full_name);
+        g_free(full_name);
+    } else {
+        libbalsa_address_set_full_name(address, _("No-Name"));
+    }
     g_free(fulln);
-    address->organization = org ? org : g_strdup("");
-    
-    address->nick_name = nickn ? nickn : 
-       g_strdup(address->full_name ? address->full_name : _("No-Id"));
-    
-    if (address->full_name == NULL)
-       address->full_name = g_strdup(_("No-Name"));
+
+    if (org != NULL) {
+        libbalsa_address_set_organization(address, org);
+        g_free(org);
+    } else {
+        libbalsa_address_set_organization(address, "");
+    }
+
+    if (nickn != NULL) {
+        libbalsa_address_set_nick_name(address, nickn);
+        g_free(nickn);
+    } else {
+        libbalsa_address_set_nick_name(address,
+                                       full_name != NULL ? full_name : _("No-Id"));
+    }
 }
 
 /* Class methods */
@@ -226,13 +257,18 @@ address_new_prefill(LibBalsaAddress * address, GList * address_list,
 static void
 lbab_ldif_write_dn(FILE * stream, LibBalsaAddress * address)
 {
+    const gchar *full_name = libbalsa_address_get_full_name(address);
     gchar *cn = NULL;
+    const gchar *addr;
     gchar *value, *value_spec;
 
-    if (address->full_name != NULL && address->full_name[0] != '\0') {
-        cn = g_strdup(address->full_name);
+    if (full_name != NULL && full_name[0] != '\0') {
+        cn = g_strdup(full_name);
     } else {
-        cn = build_name(NULL, address->first_name, address->last_name);
+        const gchar *first_name = libbalsa_address_get_first_name(address);
+        const gchar *last_name  = libbalsa_address_get_last_name(address);
+
+        cn = build_name(NULL, first_name, last_name);
         if (cn == NULL) {
             cn = g_strdup(_("No-Name"));
         } else {
@@ -243,12 +279,12 @@ lbab_ldif_write_dn(FILE * stream, LibBalsaAddress * address)
         }
     }
 
-    if (address->address_list && address->address_list->data) {
-        value =
-            g_strdup_printf("cn=%s,mail=%s",
-                            cn, (gchar *) address->address_list->data);
-    } else
+    addr = libbalsa_address_get_addr(address);
+    if (addr != NULL && addr[0] != '\0') {
+        value = g_strdup_printf("cn=%s,mail=%s", cn, addr);
+    } else {
         value = g_strdup_printf("cn=%s", cn);
+    }
     value_spec = string_to_value_spec(value);
     fprintf(stream, "dn:%s\n", value_spec);
     g_free(value_spec);
@@ -265,9 +301,11 @@ lbab_ldif_write_addresses(FILE * stream, LibBalsaAddress * address)
 {
     GList *list;
 
-    for (list = address->address_list; list; list = list->next) {
+    for (list = libbalsa_address_get_addr_list(address);
+         list != NULL; list = list->next) {
         const gchar *mail = list->data;
-        if (mail && *mail) {
+
+        if (mail != NULL && mail[0] != '\0') {
             gchar *value_spec = string_to_value_spec(mail);
             fprintf(stream, "mail:%s\n", value_spec);
             g_free(value_spec);
@@ -278,8 +316,10 @@ lbab_ldif_write_addresses(FILE * stream, LibBalsaAddress * address)
 static void
 lbab_ldif_write_surname(FILE * stream, LibBalsaAddress * address)
 {
-    if (address->last_name && *(address->last_name)) {
-        gchar *value_spec = string_to_value_spec(address->last_name);
+    const gchar *last_name = libbalsa_address_get_last_name(address);
+
+    if (last_name != NULL && last_name[0] != '\0') {
+        gchar *value_spec = string_to_value_spec(last_name);
         fprintf(stream, "sn:%s\n", value_spec);
         g_free(value_spec);
     }
@@ -288,8 +328,10 @@ lbab_ldif_write_surname(FILE * stream, LibBalsaAddress * address)
 static void
 lbab_ldif_write_givenname(FILE * stream, LibBalsaAddress * address)
 {
-    if (address->first_name && *(address->first_name)) {
-        gchar *value_spec = string_to_value_spec(address->first_name);
+    const gchar *first_name = libbalsa_address_get_first_name(address);
+
+    if (first_name != NULL && first_name[0] != '\0') {
+        gchar *value_spec = string_to_value_spec(first_name);
         fprintf(stream, "givenname:%s\n", value_spec);
         g_free(value_spec);
     }
@@ -298,8 +340,10 @@ lbab_ldif_write_givenname(FILE * stream, LibBalsaAddress * address)
 static void
 lbab_ldif_write_nickname(FILE * stream, LibBalsaAddress * address)
 {
-    if (address->nick_name) {
-        gchar *value_spec = string_to_value_spec(address->nick_name);
+    const gchar *nick_name = libbalsa_address_get_nick_name(address);
+
+    if (nick_name != NULL) {
+        gchar *value_spec = string_to_value_spec(nick_name);
         fprintf(stream, "xmozillanickname:%s\n", value_spec);
         g_free(value_spec);
     }
@@ -308,8 +352,10 @@ lbab_ldif_write_nickname(FILE * stream, LibBalsaAddress * address)
 static void
 lbab_ldif_write_organization(FILE * stream, LibBalsaAddress * address)
 {
-    if (address->organization) {
-        gchar *value_spec = string_to_value_spec(address->organization);
+    const gchar *organization = libbalsa_address_get_nick_name(address);
+
+    if (organization != NULL) {
+        gchar *value_spec = string_to_value_spec(organization);
         fprintf(stream, "o:%s\n", value_spec);
         g_free(value_spec);
     }
diff --git a/libbalsa/address-book-osmo.c b/libbalsa/address-book-osmo.c
index d7ea4efa4..084174367 100644
--- a/libbalsa/address-book-osmo.c
+++ b/libbalsa/address-book-osmo.c
@@ -212,13 +212,13 @@ utf8_strstr(const gchar *haystack, const gchar *utf8_needle)
  * LibBalsaAddress::nick_name and LibBalsaAddress::organization.
  */
 static inline gboolean
-utf8_lba_strstr(const LibBalsaAddress *address, const gchar *utf8_needle)
+utf8_lba_strstr(LibBalsaAddress *address, const gchar *utf8_needle)
 {
-       return utf8_strstr(address->full_name, utf8_needle) ||
-               utf8_strstr(address->first_name, utf8_needle) ||
-               utf8_strstr(address->last_name, utf8_needle) ||
-               utf8_strstr(address->nick_name, utf8_needle) ||
-               utf8_strstr(address->organization, utf8_needle);
+    return utf8_strstr(libbalsa_address_get_full_name(address), utf8_needle)  ||
+           utf8_strstr(libbalsa_address_get_first_name(address), utf8_needle) ||
+           utf8_strstr(libbalsa_address_get_last_name(address), utf8_needle)  ||
+           utf8_strstr(libbalsa_address_get_nick_name(address), utf8_needle)  ||
+           utf8_strstr(libbalsa_address_get_organization(address), utf8_needle);
 }
 
 
@@ -254,24 +254,29 @@ libbalsa_address_book_osmo_alias_complete(LibBalsaAddressBook *ab,
                        gboolean names_match;
 
                        names_match = utf8_lba_strstr(this_addr, utf8_filter);
-                       for (this_mail = this_addr->address_list; this_mail != NULL; this_mail = 
this_mail->next) {
+                       for (this_mail = libbalsa_address_get_addr_list(this_addr);
+                             this_mail != NULL; this_mail = this_mail->next) {
                                const gchar *mail_addr = (gchar *) this_mail->data;
 
                                if (names_match || (strstr(mail_addr, prefix) != NULL)) {
+                                        const gchar *full_name;
                                        InternetAddress *addr;
 
-                                       g_debug("%s: found %s <%s>", __func__, this_addr->full_name, 
mail_addr);
-                                       addr = internet_address_mailbox_new(this_addr->full_name, 
g_strdup(mail_addr));
+                                        full_name =
+                                            libbalsa_address_get_full_name(this_addr),
+                                       g_debug("%s: found %s <%s>", __func__,
+                                                full_name, mail_addr);
+                                       addr = internet_address_mailbox_new(full_name,
+                                                mail_addr);
                                        result = g_list_prepend(result, g_object_ref(addr));
                                }
                        }
                }
+
                g_free(utf8_filter);
                g_list_free_full(addresses, g_object_unref);
 
-               if (result != NULL) {
-                       result = g_list_reverse(result);
-               }
+               result = g_list_reverse(result);
        }
 
        return result;
@@ -337,7 +342,7 @@ osmo_read_addresses(LibBalsaAddressBookOsmo *ab_osmo,
 
                                this_addr = rfc6350_parse_from_stream(data, &eos, error);
                                if (this_addr != NULL) {
-                                       if (this_addr->address_list != NULL) {
+                                       if (libbalsa_address_get_addr(this_addr) != NULL) {
                                                addresses = g_list_prepend(addresses, this_addr);
                                        } else {
                                                g_object_unref(this_addr);
diff --git a/libbalsa/address-book-rubrica.c b/libbalsa/address-book-rubrica.c
index c58d1e1ba..123f7194d 100644
--- a/libbalsa/address-book-rubrica.c
+++ b/libbalsa/address-book-rubrica.c
@@ -196,8 +196,8 @@ libbalsa_address_book_rubrica_load(LibBalsaAddressBook * ab,
 
        if (callback &&
            (!filter_hi ||
-            lbab_rubrica_starts_from(address->last_name, filter_hi) ||
-            lbab_rubrica_starts_from(address->full_name, filter_hi)))
+            lbab_rubrica_starts_from(libbalsa_address_get_last_name(address), filter_hi) ||
+            lbab_rubrica_starts_from(libbalsa_address_get_full_name(address), filter_hi)))
            callback(ab, address, data);
     }
     if (callback)
@@ -257,7 +257,7 @@ libbalsa_address_book_rubrica_add_address(LibBalsaAddressBook * ab,
 
     /* eject if we already have this address */
     if (g_slist_find_custom(libbalsa_address_book_text_get_item_list(ab_text), new_address,
-                           (GCompareFunc) address_compare)) {
+                           (GCompareFunc) libbalsa_address_compare)) {
        xmlFreeDoc(doc);
        return LBABERR_DUPLICATE;
     }
@@ -346,7 +346,7 @@ libbalsa_address_book_rubrica_modify_address(LibBalsaAddressBook * ab,
            gchar *full_name = xml_node_get_attr(card, CXMLCHARP("name"));
 
            if (full_name) {
-               found = !g_ascii_strcasecmp(address->full_name, full_name);
+               found = !g_ascii_strcasecmp(libbalsa_address_get_full_name(address), full_name);
                g_free(full_name);
            }
        }
@@ -395,8 +395,8 @@ static LibBalsaABErr
 lbab_rubrica_load_xml(LibBalsaAddressBookRubrica * ab_rubrica,
                      xmlDocPtr * docptr)
 {
-    LibBalsaAddressBookText *ab_text =
-        LIBBALSA_ADDRESS_BOOK_TEXT(ab_rubrica);
+    LibBalsaAddressBook *ab = LIBBALSA_ADDRESS_BOOK(ab_rubrica);
+    LibBalsaAddressBookText *ab_text = LIBBALSA_ADDRESS_BOOK_TEXT(ab_rubrica);
     const gchar *path = libbalsa_address_book_text_get_path(ab_text);
     struct stat stat_buf;
     int fd;
@@ -456,35 +456,37 @@ lbab_rubrica_load_xml(LibBalsaAddressBookRubrica * ab_rubrica,
     completion_list = NULL;
     for (list = libbalsa_address_book_text_get_item_list(ab_text); list != NULL; list = list->next) {
        LibBalsaAddress *address = LIBBALSA_ADDRESS(list->data);
+        GList *addr_list;
 
-       if (!address)
+       if (address == NULL)
            continue;
 
-       if (address->address_list->next
-           && libbalsa_address_book_get_dist_list_mode(LIBBALSA_ADDRESS_BOOK(ab_rubrica))) {
+        addr_list = libbalsa_address_get_addr_list(address);
+       if (libbalsa_address_book_get_dist_list_mode(ab)
+            && addr_list != NULL && addr_list->next != NULL) {
            /* Create a group address. */
             GList *l;
            InternetAddress *ia =
-               internet_address_group_new(address->full_name);
+               internet_address_group_new(libbalsa_address_get_full_name(address));
             InternetAddressGroup *group = (InternetAddressGroup *) ia;
 
-           for (l = address->address_list; l; l = l->next) {
+           for (l = addr_list; l != NULL; l = l->next) {
                InternetAddress *member =
                    internet_address_mailbox_new(NULL, l->data);
                internet_address_group_add_member(group, member);
                g_object_unref(member);
            }
-           cmp_data = completion_data_new(ia, address->nick_name);
+           cmp_data = completion_data_new(ia, libbalsa_address_get_nick_name(address));
            completion_list = g_list_prepend(completion_list, cmp_data);
            g_object_unref(ia);
        } else {
            /* Create name addresses. */
            GList *l;
 
-           for (l = address->address_list; l; l = l->next) {
+           for (l = addr_list; l != NULL; l = l->next) {
                InternetAddress *ia =
-                   internet_address_mailbox_new(address->full_name, l->data);
-               cmp_data = completion_data_new(ia, address->nick_name);
+                   internet_address_mailbox_new(libbalsa_address_get_full_name(address), l->data);
+               cmp_data = completion_data_new(ia, libbalsa_address_get_nick_name(address));
                completion_list =
                    g_list_prepend(completion_list, cmp_data);
                g_object_unref(ia);
@@ -510,25 +512,25 @@ lbab_insert_address_node(const LibBalsaAddress * address,
 
     /* create a new card */
     new_addr = xmlNewChild(parent, NULL, CXMLCHARP("Card"), NULL);
-    xmlNewProp(new_addr, CXMLCHARP("name"), CXMLCHARP(address->full_name));
+    xmlNewProp(new_addr, CXMLCHARP("name"), CXMLCHARP(libbalsa_address_get_full_name(address)));
 
     /* create the Data section of the card */
     new_data = xmlNewChild(new_addr, NULL, CXMLCHARP("Data"), NULL);
     xmlNewChild(new_data, NULL, CXMLCHARP("FirstName"),
-               CXMLCHARP(address->first_name));
+               CXMLCHARP(libbalsa_address_get_first_name(address)));
     xmlNewChild(new_data, NULL, CXMLCHARP("LastName"),
-               CXMLCHARP(address->last_name));
+               CXMLCHARP(libbalsa_address_get_last_name(address)));
     xmlNewChild(new_data, NULL, CXMLCHARP("NickName"),
-               CXMLCHARP(address->nick_name));
+               CXMLCHARP(libbalsa_address_get_nick_name(address)));
 
     /* create the Work section of the card */
     new_data = xmlNewChild(new_addr, NULL, CXMLCHARP("Work"), NULL);
     xmlNewChild(new_data, NULL, CXMLCHARP("Organization"),
-               CXMLCHARP(address->organization));
+               CXMLCHARP(libbalsa_address_get_organization(address)));
 
     /* create the Net section of the card */
     new_data = xmlNewChild(new_addr, NULL, CXMLCHARP("Net"), NULL);
-    for (l = address->address_list; l; l = g_list_next(l)) {
+    for (l = libbalsa_address_get_addr_list(address); l != NULL; l = l->next) {
        xmlNodePtr new_mail =
            xmlNewChild(new_data, NULL, CXMLCHARP("Uri"),
                        CXMLCHARP(l->data));
@@ -564,25 +566,45 @@ extract_cards(xmlNodePtr card)
        if (!xmlStrcmp(card->name, CXMLCHARP("Card"))) {
            LibBalsaAddress *address = libbalsa_address_new();
            xmlNodePtr children;
+            gchar *full_name;
+            GList *address_list = NULL;
+
+            full_name = xml_node_get_attr(card, CXMLCHARP("name"));
+           libbalsa_address_set_full_name(address, full_name);
+            g_free(full_name);
 
-           address->full_name =
-               xml_node_get_attr(card, CXMLCHARP("name"));
            children = card->children;
            while (children) {
-               if (!xmlStrcmp(children->name, CXMLCHARP("Data")))
-                   extract_data(children->children, &address->first_name,
-                                &address->last_name, &address->nick_name);
-               else if (!xmlStrcmp(children->name, CXMLCHARP("Work")))
-                   extract_work(children->children,
-                                &address->organization);
-               else if (!xmlStrcmp(children->name, CXMLCHARP("Net")))
-                   extract_net(children->children,
-                               &address->address_list);
+               if (!xmlStrcmp(children->name, CXMLCHARP("Data"))) {
+                    gchar *first_name;
+                    gchar *last_name = NULL;
+                    gchar *nick_name = NULL;
+
+                   extract_data(children->children,
+                                 &first_name, &last_name, &nick_name);
+
+                    libbalsa_address_set_first_name(address, first_name);
+                    libbalsa_address_set_last_name(address, last_name);
+                    libbalsa_address_set_nick_name(address, nick_name);
+
+                    g_free(first_name);
+                    g_free(last_name);
+                    g_free(nick_name);
+                } else if (!xmlStrcmp(children->name, CXMLCHARP("Work"))) {
+                    gchar *organization = NULL;
+
+                   extract_work(children->children, &organization);
+                    libbalsa_address_set_organization(address, organization);
+                    g_free(organization);
+                } else if (!xmlStrcmp(children->name, CXMLCHARP("Net"))) {
+                   extract_net(children->children, &address_list);
+                    libbalsa_address_set_addr_list(address, address_list);
+                }
 
                children = children->next;
            }
 
-           if (address->address_list)
+           if (address_list != NULL)
                addrlist = g_slist_prepend(addrlist, address);
            else
                g_object_unref(address);
diff --git a/libbalsa/address-book-text.c b/libbalsa/address-book-text.c
index 52c0dba99..fab865bd5 100644
--- a/libbalsa/address-book-text.c
+++ b/libbalsa/address-book-text.c
@@ -261,19 +261,20 @@ lbab_text_item_compare(LibBalsaAddressBookTextItem * a,
     g_return_val_if_fail(a != NULL, -1);
     g_return_val_if_fail(b != NULL, 1);
 
-    if (!a->address)
+    if (a->address == NULL)
         return -1;
-    if (!b->address)
+    if (b->address == NULL)
         return 1;
 
-    return g_ascii_strcasecmp(a->address->full_name,
-                              b->address->full_name);
+    return g_ascii_strcasecmp(libbalsa_address_get_full_name(a->address),
+                              libbalsa_address_get_full_name(b->address));
 }
 
 /* Load the book from the stream */
 static gboolean
 lbab_text_load_file(LibBalsaAddressBookText * ab_text, FILE * stream)
 {
+    LibBalsaAddressBook *ab = ( LibBalsaAddressBook *) ab_text;
     LibBalsaAddressBookTextPrivate *priv =
         libbalsa_address_book_text_get_instance_private(ab_text);
     LibBalsaAddressBookTextClass *ab_text_class =
@@ -331,33 +332,38 @@ lbab_text_load_file(LibBalsaAddressBookText * ab_text, FILE * stream)
 #if MAKE_GROUP_BY_ORGANIZATION
         gchar **groups, **group;
 #endif                          /* MAKE_GROUP_BY_ORGANIZATION */
-        if (!address)
+        GList *addr_list;
+
+        if (address == NULL)
             continue;
 
-        if (address->address_list->next
-            && libbalsa_address_book_get_dist_list_mode(LIBBALSA_ADDRESS_BOOK(ab_text))) {
+        addr_list = libbalsa_address_get_addr_list(address);
+       if (libbalsa_address_book_get_dist_list_mode(ab)
+            && addr_list != NULL && addr_list->next != NULL) {
             /* Create a group address. */
             InternetAddress *ia =
-                internet_address_group_new(address->full_name);
+                internet_address_group_new(libbalsa_address_get_full_name(address));
             GList *l;
 
-            for (l = address->address_list; l; l = l->next) {
+            for (l = addr_list; l != NULL; l = l->next) {
                 InternetAddress *member =
                     internet_address_mailbox_new(NULL, l->data);
                 internet_address_group_add_member((InternetAddressGroup *)ia, member);
                 g_object_unref(member);
             }
-            cmp_data = completion_data_new(ia, address->nick_name);
+            cmp_data = completion_data_new(ia, libbalsa_address_get_nick_name(address));
             completion_list = g_list_prepend(completion_list, cmp_data);
             g_object_unref(ia);
         } else {
             /* Create name addresses. */
             GList *l;
 
-            for (l = address->address_list; l; l = l->next) {
+            for (l = addr_list; l != NULL; l = l->next) {
                 InternetAddress *ia =
-                    internet_address_mailbox_new(address->full_name, l->data);
-                cmp_data = completion_data_new(ia, address->nick_name);
+                    internet_address_mailbox_new(libbalsa_address_get_full_name(address),
+                                                 l->data);
+                cmp_data =
+                    completion_data_new(ia, libbalsa_address_get_nick_name(address));
                 completion_list =
                     g_list_prepend(completion_list, cmp_data);
                 g_object_unref(ia);
@@ -532,22 +538,22 @@ libbalsa_address_book_text_load(LibBalsaAddressBook * ab,
     if (filter)
         filter_hi = g_utf8_strup(filter, -1);
 
-    for (list = priv->item_list; list != NULL; list = list->next) {
-        LibBalsaAddressBookTextItem *item = list->data;
-        LibBalsaAddress *address = item->address;
+    if (callback != NULL) {
+        for (list = priv->item_list; list != NULL; list = list->next) {
+            LibBalsaAddressBookTextItem *item = list->data;
+            LibBalsaAddress *address = item->address;
 
-        if (!address)
-            continue;
+            if (address == NULL)
+                continue;
+
+            if ((!filter_hi ||
+                 lbab_text_starts_from(libbalsa_address_get_last_name(address), filter_hi) ||
+                 lbab_text_starts_from(libbalsa_address_get_full_name(address), filter_hi)))
+                callback(ab, address, data);
+        }
 
-        if (callback && (!filter_hi
-                         || lbab_text_starts_from(address->last_name,
-                                                  filter_hi)
-                         || lbab_text_starts_from(address->full_name,
-                                                  filter_hi)))
-            callback(ab, address, data);
-    }
-    if (callback)
         callback(ab, NULL, data);
+    }
 
     g_free(filter_hi);
 
diff --git a/libbalsa/address-book-vcard.c b/libbalsa/address-book-vcard.c
index e6776fce9..567df9609 100644
--- a/libbalsa/address-book-vcard.c
+++ b/libbalsa/address-book-vcard.c
@@ -124,21 +124,25 @@ lbab_vcard_write_begin(FILE * stream)
 static void
 lbab_vcard_write_fn(FILE * stream, LibBalsaAddress * address)
 {
-    if (address->full_name && *address->full_name != '\0')
-        fprintf(stream, "FN:%s\n", address->full_name);
+    const gchar *full_name = libbalsa_address_get_full_name(address);
+
+    if (full_name != NULL && full_name[0] != '\0')
+        fprintf(stream, "FN:%s\n", full_name);
 }
 
 static void
 lbab_vcard_write_n(FILE * stream, LibBalsaAddress * address)
 {
-    if (address->first_name && *address->first_name != '\0') {
-        if (address->last_name && *address->last_name != '\0') {
-            fprintf(stream, "N:%s;%s\n", address->last_name,
-                    address->first_name);
+    const gchar *first_name = libbalsa_address_get_first_name(address);
+    const gchar *last_name = libbalsa_address_get_last_name(address);
+
+    if (first_name != NULL && first_name[0] != '\0') {
+        if (last_name != NULL && last_name[0] != '\0') {
+            fprintf(stream, "N:%s;%s\n", last_name, first_name);
         } else
-            fprintf(stream, "N:;%s\n", address->first_name);
-    } else if (address->last_name && *address->last_name != '\0') {
-        fprintf(stream, "N:%s\n", address->last_name);
+            fprintf(stream, "N:;%s\n", first_name);
+    } else if (last_name != NULL && last_name[0] != '\0') {
+        fprintf(stream, "N:%s\n", last_name);
     } else
         fprintf(stream, "N:%s\n", _("No-Name"));
 }
@@ -146,15 +150,19 @@ lbab_vcard_write_n(FILE * stream, LibBalsaAddress * address)
 static void
 lbab_vcard_write_nickname(FILE * stream, LibBalsaAddress * address)
 {
-    if (address->nick_name && *address->nick_name != '\0')
-        fprintf(stream, "NICKNAME:%s\n", address->nick_name);
+    const gchar *nick_name = libbalsa_address_get_nick_name(address);
+
+    if (nick_name != NULL && nick_name[0] != '\0')
+        fprintf(stream, "NICKNAME:%s\n", nick_name);
 }
 
 static void
 lbab_vcard_write_org(FILE * stream, LibBalsaAddress * address)
 {
-    if (address->organization && *address->organization != '\0')
-        fprintf(stream, "ORG:%s\n", address->organization);
+    const gchar *organization = libbalsa_address_get_organization(address);
+
+    if (organization != NULL && organization[0] != '\0')
+        fprintf(stream, "ORG:%s\n", organization);
 }
 
 static void
@@ -162,7 +170,8 @@ lbab_vcard_write_addresses(FILE * stream, LibBalsaAddress * address)
 {
     GList *list;
 
-    for (list = address->address_list; list; list = list->next)
+    for (list = libbalsa_address_get_addr_list(address);
+         list != NULL; list = list->next)
         fprintf(stream, "EMAIL;INTERNET:%s\n", (gchar *) list->data);
 }
 
@@ -197,7 +206,7 @@ libbalsa_address_book_vcard_parse_address(FILE * stream,
     gchar *name = NULL, *nick_name = NULL, *org = NULL;
     gchar *full_name = NULL, *last_name = NULL, *first_name = NULL;
     gint in_vcard = FALSE;
-    GList *address_list = NULL;
+    GList *addr_list = NULL;
     guint wrote = 0;
 
     while (fgets(string, sizeof(string), stream)) {
@@ -216,8 +225,8 @@ libbalsa_address_book_vcard_parse_address(FILE * stream,
             /*
              * We are done loading a card.
              */
-           if (address_list) {
-                if (stream_out) {
+           if (addr_list != NULL) {
+                if (stream_out != NULL) {
                     if (!(wrote & (1 << FULL_NAME)))
                         lbab_vcard_write_fn(stream_out, address_out);
                     if (!(wrote & (1 << FIRST_NAME)))
@@ -229,27 +238,35 @@ libbalsa_address_book_vcard_parse_address(FILE * stream,
                     lbab_vcard_write_addresses(stream_out, address_out);
                     res = lbab_vcard_write_end(stream_out);
                 }
-                if (address) {
-                    if (full_name) {
-                        address->full_name = full_name;
-                        g_free(name);
-                    } else if (name)
-                        address->full_name = name;
-                    else if (nick_name)
-                        address->full_name = g_strdup(nick_name);
+                if (address != NULL) {
+                    if (full_name != NULL)
+                        libbalsa_address_set_full_name(address, full_name);
+                    else if (name != NULL)
+                        libbalsa_address_set_full_name(address, name);
+                    else if (nick_name != NULL)
+                        libbalsa_address_set_full_name(address, nick_name);
                     else
-                        address->full_name = g_strdup(_("No-Name"));
-
-                    address->last_name = last_name;
-                    address->first_name = first_name;
-                    address->nick_name = nick_name;
-                    address->organization = org;
-                    address->address_list = g_list_reverse(address_list);
-
-                    return LBABERR_OK;
+                        libbalsa_address_set_full_name(address, _("No-Name"));
+
+                    libbalsa_address_set_last_name(address, last_name);
+                    libbalsa_address_set_first_name(address, first_name);
+                    libbalsa_address_set_nick_name(address, nick_name);
+                    libbalsa_address_set_organization(address, org);
+                    libbalsa_address_set_addr_list(address,
+                                                   g_list_reverse(addr_list));
+
+                    res = LBABERR_OK;
+                    g_free(full_name);
+                    g_free(name);
+                    g_free(last_name);
+                    g_free(first_name);
+                    g_free(nick_name);
+                    g_free(org);
+
+                    return res;
                 }
-                g_list_foreach(address_list, (GFunc) g_free, NULL);
-                g_list_free(address_list);
+
+                g_list_free_full(addr_list, g_free);
            }
             /* Record without e-mail address, or we're not creating
              * addresses: free memory. */
@@ -316,10 +333,8 @@ libbalsa_address_book_vcard_parse_address(FILE * stream,
         */
        if (g_ascii_strncasecmp(string, "EMAIL", 5) == 0) {
            gchar *ptr = strchr(string + 5, ':');
-           if (ptr) {
-               address_list =
-                   g_list_prepend(address_list, g_strdup(ptr + 1));
-           }
+           if (ptr != NULL)
+               addr_list = g_list_prepend(addr_list, g_strdup(ptr + 1));
            continue;
        }
 
diff --git a/libbalsa/address-book.c b/libbalsa/address-book.c
index 5c884965a..e12429b8e 100644
--- a/libbalsa/address-book.c
+++ b/libbalsa/address-book.c
@@ -241,20 +241,6 @@ libbalsa_address_book_alias_complete(LibBalsaAddressBook * ab,
 }
 
 
-gboolean
-libbalsa_address_is_dist_list(LibBalsaAddressBook *ab,
-                              LibBalsaAddress *address)
-{
-    LibBalsaAddressBookPrivate *priv = libbalsa_address_book_get_instance_private(ab);
-
-    g_return_val_if_fail(LIBBALSA_IS_ADDRESS_BOOK(ab), FALSE);
-    g_return_val_if_fail(LIBBALSA_IS_ADDRESS(address), FALSE);
-
-    return (priv->dist_list_mode && address->address_list->next != NULL);
-}
-
-
-
 static void
 libbalsa_address_book_real_save_config(LibBalsaAddressBook * ab,
                                       const gchar * group)
diff --git a/libbalsa/address-book.h b/libbalsa/address-book.h
index 70efa1b3e..17d5cb0cc 100644
--- a/libbalsa/address-book.h
+++ b/libbalsa/address-book.h
@@ -113,8 +113,6 @@ const gchar* libbalsa_address_book_strerror(LibBalsaAddressBook * ab,
 */
 GList *libbalsa_address_book_alias_complete(LibBalsaAddressBook * ab,
                                            const gchar *prefix);
-gboolean libbalsa_address_is_dist_list(LibBalsaAddressBook *ab,
-                                      LibBalsaAddress *address);
 
 /*
  * Getters
diff --git a/libbalsa/address.c b/libbalsa/address.c
index 20e35b639..e5eb99e22 100644
--- a/libbalsa/address.c
+++ b/libbalsa/address.c
@@ -29,47 +29,53 @@
 #include "misc.h"
 #include <glib/gi18n.h>
 
-static GObjectClass *parent_class;
-
-static void libbalsa_address_class_init(LibBalsaAddressClass * klass);
-static void libbalsa_address_init(LibBalsaAddress * ab);
 static void libbalsa_address_finalize(GObject * object);
 
 static gchar ** vcard_strsplit(const gchar * string);
 
-GType libbalsa_address_get_type(void)
-{
-    static GType address_type = 0;
-
-    if (!address_type) {
-       static const GTypeInfo address_info = {
-           sizeof(LibBalsaAddressClass),
-            NULL,               /* base_init */
-            NULL,               /* base_finalize */
-           (GClassInitFunc) libbalsa_address_class_init,
-            NULL,               /* class_finalize */
-            NULL,               /* class_data */
-           sizeof(LibBalsaAddress),
-            0,                  /* n_preallocs */
-           (GInstanceInitFunc) libbalsa_address_init
-       };
-
-       address_type =
-           g_type_register_static(G_TYPE_OBJECT,
-                                  "LibBalsaAddress",
-                                   &address_info, 0);
-    }
+/* General address structure to be used with address books.
+*/
+struct _LibBalsaAddress {
+    GObject parent;
+
+    /*
+     * ID
+     * VCard FN: Field
+     * LDAP/LDIF: xmozillanickname
+     */
+    gchar *nick_name;
+
+    /* First and last names
+     * VCard: parsed from N: field
+     * LDAP/LDIF: cn, givenName, surName.
+     */
+    gchar *full_name;
+    gchar *first_name;
+    gchar *last_name;
+
+    /* Organisation
+     * VCard: ORG: field
+     * ldif: o: attribute.
+     */
+    gchar *organization;
+
+    /* Email addresses
+     * A list of mailboxes, ie. user@domain.
+     */
+    GList *addr_list;
+};
 
-    return address_type;
-}
+struct _LibBalsaAddressClass {
+    GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE(LibBalsaAddress, libbalsa_address, G_TYPE_OBJECT)
 
 static void
 libbalsa_address_class_init(LibBalsaAddressClass * klass)
 {
     GObjectClass *object_class;
 
-    parent_class = g_type_class_peek_parent(klass);
-
     object_class = G_OBJECT_CLASS(klass);
     object_class->finalize = libbalsa_address_finalize;
 }
@@ -82,29 +88,23 @@ libbalsa_address_init(LibBalsaAddress * addr)
     addr->first_name = NULL;
     addr->last_name = NULL;
     addr->organization = NULL;
-    addr->address_list = NULL;
+    addr->addr_list = NULL;
 }
 
 static void
 libbalsa_address_finalize(GObject * object)
 {
-    LibBalsaAddress *addr;
-
-    g_return_if_fail(object != NULL);
+    LibBalsaAddress *addr = LIBBALSA_ADDRESS(object);
 
-    addr = LIBBALSA_ADDRESS(object);
+    g_free(addr->nick_name);
+    g_free(addr->full_name);
+    g_free(addr->first_name);
+    g_free(addr->last_name);
+    g_free(addr->organization);
 
-    g_free(addr->nick_name);    addr->nick_name = NULL;
-    g_free(addr->full_name);    addr->full_name = NULL;
-    g_free(addr->first_name);   addr->first_name = NULL;
-    g_free(addr->last_name);    addr->last_name = NULL;
-    g_free(addr->organization); addr->organization = NULL;
+    g_list_free_full(addr->addr_list, g_free);
 
-    g_list_foreach(addr->address_list, (GFunc) g_free, NULL);
-    g_list_free(addr->address_list);
-    addr->address_list = NULL;
-
-    G_OBJECT_CLASS(parent_class)->finalize(object);
+    G_OBJECT_CLASS(libbalsa_address_parent_class)->finalize(object);
 }
 
 LibBalsaAddress *
@@ -330,7 +330,7 @@ libbalsa_address_new_from_vcard(const gchar *str, const gchar *charset)
     gchar *name = NULL, *nick_name = NULL, *org = NULL;
     gchar *full_name = NULL, *last_name = NULL, *first_name = NULL;
     gint in_vcard = FALSE;
-    GList *address_list = NULL;
+    GList *addr_list = NULL;
     const gchar *string, *next_line;
     gchar * vcard;
 
@@ -389,7 +389,7 @@ libbalsa_address_new_from_vcard(const gchar *str, const gchar *charset)
                 */
                LibBalsaAddress *address;
 
-               if (!address_list)
+               if (!addr_list)
                     break;
 
                address = g_object_new(LIBBALSA_TYPE_ADDRESS, NULL);
@@ -408,7 +408,7 @@ libbalsa_address_new_from_vcard(const gchar *str, const gchar *charset)
                 address->first_name = first_name;
                 address->nick_name = nick_name;
                 address->organization = org;
-                address->address_list = g_list_reverse(address_list);
+                address->addr_list = g_list_reverse(addr_list);
 
                 g_free(vcard);
 
@@ -503,8 +503,8 @@ libbalsa_address_new_from_vcard(const gchar *str, const gchar *charset)
 
             } else if (g_ascii_strncasecmp(line, "EMAIL:", 6) == 0) {
 
-               address_list =
-                   g_list_prepend(address_list, g_strdup(line + 6));
+                addr_list = g_list_prepend(addr_list, g_strdup(line + 6));
+
             }
             g_free(line);
         }
@@ -516,11 +516,10 @@ libbalsa_address_new_from_vcard(const gchar *str, const gchar *charset)
     g_free(first_name);
     g_free(nick_name);
     g_free(org);
-    g_list_foreach(address_list, (GFunc) g_free, NULL);
-    g_list_free(address_list);
-
     g_free(vcard);
 
+    g_list_free_full(addr_list, g_free);
+
     return NULL;
 }
 
@@ -542,13 +541,12 @@ libbalsa_address_set_copy(LibBalsaAddress * dest, LibBalsaAddress * src)
     dest->last_name = g_strdup(src->last_name);
     g_free(dest->organization);
     dest->organization = g_strdup(src->organization);
-    g_list_foreach(dest->address_list, (GFunc) g_free, NULL);
-    g_list_free(dest->address_list);
+    g_list_free_full(dest->addr_list, g_free);
 
     dst_al = NULL;
-    for (src_al = src->address_list; src_al; src_al = src_al->next)
+    for (src_al = src->addr_list; src_al != NULL; src_al = src_al->next)
         dst_al = g_list_prepend(dst_al, g_strdup(src_al->data));
-    dest->address_list = g_list_reverse(dst_al);
+    dest->addr_list = g_list_reverse(dst_al);
 }
 
 static gchar *
@@ -597,16 +595,16 @@ libbalsa_address_to_gchar(LibBalsaAddress * address, gint n)
 
     g_return_val_if_fail(LIBBALSA_IS_ADDRESS(address), NULL);
 
-    if(!address->address_list)
+    if (address->addr_list == NULL)
         return NULL;
-    if(n==-1) {
-        if(address->address_list->next)
-            retc = rfc2822_group(address->full_name, address->address_list);
+    if (n == -1) {
+        if (address->addr_list->next != NULL)
+            retc = rfc2822_group(address->full_name, address->addr_list);
         else
             retc = rfc2822_mailbox(address->full_name,
-                                   address->address_list->data);
+                                   address->addr_list->data);
     } else {
-       const gchar *mailbox = g_list_nth_data(address->address_list, n);
+       const gchar *mailbox = g_list_nth_data(address->addr_list, n);
        g_return_val_if_fail(mailbox != NULL, NULL);
 
        retc = rfc2822_mailbox(address->full_name, mailbox);
@@ -617,19 +615,19 @@ libbalsa_address_to_gchar(LibBalsaAddress * address, gint n)
 
 /* Helper */
 static const gchar *
-lba_get_name_or_mailbox(InternetAddressList * address_list,
+lba_get_name_or_mailbox(InternetAddressList * addr_list,
                         gboolean get_name, gboolean in_group)
 {
     const gchar *retval = NULL;
     InternetAddress *ia;
     gint i, len;
 
-    if (address_list == NULL)
+    if (addr_list == NULL)
        return NULL;
 
-    len = internet_address_list_length(address_list);
+    len = internet_address_list_length(addr_list);
     for (i = 0; i < len; i++) {
-        ia = internet_address_list_get_address (address_list, i);
+        ia = internet_address_list_get_address (addr_list, i);
 
         if (get_name && ia->name && *ia->name)
             return ia->name;
@@ -652,30 +650,30 @@ lba_get_name_or_mailbox(InternetAddressList * address_list,
 
 /* Get either a name or a mailbox from an InternetAddressList. */
 const gchar *
-libbalsa_address_get_name_from_list(InternetAddressList *address_list)
+libbalsa_address_get_name_from_list(InternetAddressList *addr_list)
 {
-    return lba_get_name_or_mailbox(address_list, TRUE, FALSE);
+    return lba_get_name_or_mailbox(addr_list, TRUE, FALSE);
 }
 
 /* Get a mailbox from an InternetAddressList. */
 const gchar *
-libbalsa_address_get_mailbox_from_list(InternetAddressList *address_list)
+libbalsa_address_get_mailbox_from_list(InternetAddressList *addr_list)
 {
-    return lba_get_name_or_mailbox(address_list, FALSE, FALSE);
+    return lba_get_name_or_mailbox(addr_list, FALSE, FALSE);
 }
 
 /* Number of individual mailboxes in an InternetAddressList. */
 gint
-libbalsa_address_n_mailboxes_in_list(InternetAddressList * address_list)
+libbalsa_address_n_mailboxes_in_list(InternetAddressList * addr_list)
 {
     gint i, len, n_mailboxes = 0;
 
-    g_return_val_if_fail(IS_INTERNET_ADDRESS_LIST(address_list), -1);
+    g_return_val_if_fail(IS_INTERNET_ADDRESS_LIST(addr_list), -1);
 
-    len = internet_address_list_length(address_list);
+    len = internet_address_list_length(addr_list);
     for (i = 0; i < len; i++) {
         const InternetAddress *ia =
-            internet_address_list_get_address(address_list, i);
+            internet_address_list_get_address(addr_list, i);
 
         if (INTERNET_ADDRESS_IS_MAILBOX(ia))
             ++n_mailboxes;
@@ -710,9 +708,9 @@ libbalsa_address_set_edit_entries(const LibBalsaAddress * address,
     GtkTreeIter iter;
 
     new_email = g_strdup(address
-                         && address->address_list
-                         && address->address_list->data ?
-                         address->address_list->data : "");
+                         && address->addr_list
+                         && address->addr_list->data ?
+                         address->addr_list->data : "");
     /* initialize the organization... */
     if (!address || address->organization == NULL)
        new_organization = g_strdup("");
@@ -774,7 +772,7 @@ libbalsa_address_set_edit_entries(const LibBalsaAddress * address,
     if (address) {
         GList *list;
 
-        for (list = address->address_list; list; list = list->next) {
+        for (list = address->addr_list; list; list = list->next) {
             gtk_list_store_append(store, &iter);
             gtk_list_store_set(store, &iter, 0, list->data, -1);
         }
@@ -825,7 +823,7 @@ lba_cell_edited(GtkCellRendererText * cell, const gchar * path_string,
 }
 
 static GtkWidget *
-lba_address_list_widget(GCallback changed_cb, gpointer changed_data)
+lba_addr_list_widget(GCallback changed_cb, gpointer changed_data)
 {
     GtkListStore *store;
     GtkWidget *tree_view;
@@ -890,12 +888,12 @@ addrlist_drag_received_cb(GtkWidget * widget, GdkDragContext * context,
         case LIBBALSA_ADDRESS_TRG_ADDRESS:
             addr = *(LibBalsaAddress **)
                 gtk_selection_data_get_data(selection_data);
-            if(addr && addr->address_list) {
-                g_print ("string: %s\n", (gchar*)addr->address_list->data);
+            if (addr != NULL && addr->addr_list != NULL) {
+                g_print ("string: %s\n", (gchar*)addr->addr_list->data);
                 gtk_list_store_insert_with_values(GTK_LIST_STORE(model),
                                                   &iter, 99999,
                                                   0,
-                                                  addr->address_list->data,
+                                                  addr->addr_list->data,
                                                   -1);
                 dnd_success = TRUE;
             }
@@ -979,8 +977,7 @@ libbalsa_address_get_edit_widget(const LibBalsaAddress *address,
         if (cnt == EMAIL_ADDRESS) {
             GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
             GtkWidget *but = gtk_button_new_with_mnemonic(_("A_dd"));
-            entries[cnt] = lba_address_list_widget(changed_cb,
-                                                   changed_data);
+            entries[cnt] = lba_addr_list_widget(changed_cb, changed_data);
             gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 1);
             gtk_box_pack_start(GTK_BOX(box), but,   FALSE, FALSE, 1);
             lhs = box;
@@ -1076,7 +1073,124 @@ libbalsa_address_new_from_edit_entries(GtkWidget ** entries)
         if (email && *email)
             list = g_list_prepend(list, email);
     }
-    address->address_list = g_list_reverse(list);
+    address->addr_list = g_list_reverse(list);
 
     return address;
 }
+
+/*
+ * Comparison func
+ */
+
+gint
+libbalsa_address_compare(LibBalsaAddress *a, LibBalsaAddress *b)
+{
+    g_return_val_if_fail(a != NULL, -1);
+    g_return_val_if_fail(b != NULL, 1);
+
+    return g_ascii_strcasecmp(a->full_name, b->full_name);
+}
+
+/*
+ * Getters
+ */
+
+const gchar *
+libbalsa_address_get_full_name(const LibBalsaAddress * address)
+{
+    return address->full_name;
+}
+
+const gchar *
+libbalsa_address_get_first_name(const LibBalsaAddress * address)
+{
+    return address->first_name;
+}
+
+const gchar *
+libbalsa_address_get_last_name(const LibBalsaAddress * address)
+{
+    return address->last_name;
+}
+
+const gchar *
+libbalsa_address_get_nick_name(const LibBalsaAddress * address)
+{
+    return address->nick_name;
+}
+
+const gchar *
+libbalsa_address_get_organization(const LibBalsaAddress * address)
+{
+    return address->organization;
+}
+
+const gchar *
+libbalsa_address_get_addr(const LibBalsaAddress * address)
+{
+    return address->addr_list != NULL ? address->addr_list->data : NULL;
+}
+
+GList *
+libbalsa_address_get_addr_list(const LibBalsaAddress * address)
+{
+    return address->addr_list;
+}
+
+/*
+ * Setters
+ */
+
+void
+libbalsa_address_set_full_name(LibBalsaAddress * address,
+                               const gchar     * full_name)
+{
+    g_free(address->full_name);
+    address->full_name = g_strdup(full_name);
+}
+
+void
+libbalsa_address_set_first_name(LibBalsaAddress * address,
+                                const gchar     * first_name)
+{
+    g_free(address->first_name);
+    address->first_name = g_strdup(first_name);
+}
+
+void
+libbalsa_address_set_last_name(LibBalsaAddress * address,
+                               const gchar     * last_name)
+{
+    g_free(address->last_name);
+    address->last_name = g_strdup(last_name);
+}
+
+void
+libbalsa_address_set_nick_name(LibBalsaAddress * address,
+                               const gchar     * nick_name)
+{
+    g_free(address->nick_name);
+    address->nick_name = g_strdup(nick_name);
+}
+
+void
+libbalsa_address_set_organization(LibBalsaAddress * address,
+                                  const gchar     * organization)
+{
+    g_free(address->organization);
+    address->organization = g_strdup(organization);
+}
+
+void
+libbalsa_address_set_addr_list(LibBalsaAddress * address,
+                               GList           * addr_list)
+{
+    g_list_free_full(address->addr_list, g_free);
+    address->addr_list = addr_list;
+}
+
+void libbalsa_address_add_addr(LibBalsaAddress * address,
+                               const gchar     * addr)
+{
+    address->addr_list = g_list_prepend(address->addr_list, g_strdup(addr));
+}
diff --git a/libbalsa/address.h b/libbalsa/address.h
index 9118f32b9..6ababa845 100644
--- a/libbalsa/address.h
+++ b/libbalsa/address.h
@@ -21,17 +21,11 @@
 #ifndef __LIBBALSA_ADDRESS_H__
 #define __LIBBALSA_ADDRESS_H__
 
-#include <gtk/gtk.h>
 #include <gmime/gmime.h>
+#include <gtk/gtk.h>
 
-#define LIBBALSA_TYPE_ADDRESS                          (libbalsa_address_get_type())
-#define LIBBALSA_ADDRESS(obj)                          (G_TYPE_CHECK_INSTANCE_CAST (obj, 
LIBBALSA_TYPE_ADDRESS, LibBalsaAddress))
-#define LIBBALSA_ADDRESS_CLASS(klass)                  (G_TYPE_CHECK_CLASS_CAST (klass, 
LIBBALSA_TYPE_ADDRESS, LibBalsaAddressClass))
-#define LIBBALSA_IS_ADDRESS(obj)                       (G_TYPE_CHECK_INSTANCE_TYPE (obj, 
LIBBALSA_TYPE_ADDRESS))
-#define LIBBALSA_IS_ADDRESS_CLASS(klass)               (G_TYPE_CHECK_CLASS_TYPE (klass, 
LIBBALSA_TYPE_ADDRESS))
-
-typedef struct _LibBalsaAddress LibBalsaAddress;
-typedef struct _LibBalsaAddressClass LibBalsaAddressClass;
+#define LIBBALSA_TYPE_ADDRESS (libbalsa_address_get_type())
+G_DECLARE_FINAL_TYPE(LibBalsaAddress, libbalsa_address, LIBBALSA, ADDRESS, GObject)
 
 typedef enum _LibBalsaAddressField LibBalsaAddressField;
 
@@ -45,44 +39,6 @@ enum _LibBalsaAddressField {
     NUM_FIELDS
 };
 
-/* General address structure to be used with address books.
-*/
-struct _LibBalsaAddress {
-    GObject parent;
-
-    /*
-     * ID
-     * VCard FN: Field
-     * LDAP/LDIF: xmozillanickname
-     */
-    gchar *nick_name;
-
-    /* First and last names
-     * VCard: parsed from N: field
-     * LDAP/LDIF: cn, givenName, surName.
-     */
-    gchar *full_name;
-    gchar *first_name;
-    gchar *last_name;
-
-    /* Organisation
-     * VCard: ORG: field
-     * ldif: o: attribute.
-     */
-    gchar *organization;
-
-    /* Email addresses
-     * A list of mailboxes, ie. user@domain.
-     */
-    GList *address_list;
-};
-
-struct _LibBalsaAddressClass {
-    GObjectClass parent_class;
-};
-
-GType libbalsa_address_get_type(void);
- 
 LibBalsaAddress *libbalsa_address_new(void);
 LibBalsaAddress *libbalsa_address_new_from_vcard(const gchar *str,
                                                 const gchar *charset);
@@ -94,11 +50,11 @@ void libbalsa_address_set_copy(LibBalsaAddress *dest, LibBalsaAddress *src);
 gchar *libbalsa_address_to_gchar(LibBalsaAddress * address, gint n);
 
 const gchar *libbalsa_address_get_name_from_list(InternetAddressList
-                                                 * address_list);
+                                                 * addr_list);
 const gchar *libbalsa_address_get_mailbox_from_list(InternetAddressList *
-                                                    address_list);
+                                                    addr_list);
 gint libbalsa_address_n_mailboxes_in_list(InternetAddressList *
-                                          address_list);
+                                          addr_list);
 
 /* =================================================================== */
 /*                                UI PART                              */
@@ -128,4 +84,42 @@ GtkWidget *libbalsa_address_get_edit_widget(const LibBalsaAddress *addr,
                                             GCallback changed_cb,
                                             gpointer changed_data);
 LibBalsaAddress *libbalsa_address_new_from_edit_entries(GtkWidget **widget);
+
+/*
+ * Comparison func
+ */
+gint libbalsa_address_compare(LibBalsaAddress *a,
+                              LibBalsaAddress *b);
+
+/*
+ * Getters
+ */
+
+const gchar * libbalsa_address_get_full_name   (const LibBalsaAddress * address);
+const gchar * libbalsa_address_get_first_name  (const LibBalsaAddress * address);
+const gchar * libbalsa_address_get_last_name   (const LibBalsaAddress * address);
+const gchar * libbalsa_address_get_nick_name   (const LibBalsaAddress * address);
+const gchar * libbalsa_address_get_organization(const LibBalsaAddress * address);
+const gchar * libbalsa_address_get_addr        (const LibBalsaAddress * address);
+GList       * libbalsa_address_get_addr_list   (const LibBalsaAddress * address);
+
+/*
+ * Setters
+ */
+
+void libbalsa_address_set_full_name   (LibBalsaAddress * address,
+                                       const gchar     * full_name);
+void libbalsa_address_set_first_name  (LibBalsaAddress * address,
+                                       const gchar     * first_name);
+void libbalsa_address_set_last_name   (LibBalsaAddress * address,
+                                       const gchar     * last_name);
+void libbalsa_address_set_nick_name   (LibBalsaAddress * address,
+                                       const gchar     * nick_name);
+void libbalsa_address_set_organization(LibBalsaAddress * address,
+                                       const gchar     * organization);
+void libbalsa_address_set_addr_list   (LibBalsaAddress * address,
+                                       GList           * addr_list);
+void libbalsa_address_add_addr        (LibBalsaAddress * address,
+                                       const gchar     * addr);
+
 #endif                         /* __LIBBALSA_ADDRESS_H__ */
diff --git a/libbalsa/rfc2445.c b/libbalsa/rfc2445.c
index 0a15688c5..d59c48662 100644
--- a/libbalsa/rfc2445.c
+++ b/libbalsa/rfc2445.c
@@ -489,10 +489,12 @@ libbalsa_vevent_reply(const LibBalsaVEvent * event, const gchar * sender,
                           pstats[(int) new_stat].str_2445, sender);
     if (event->uid)
        g_string_append_printf(retval, "UID:%s\n", event->uid);
-    if (event->organizer && event->organizer->address_list)
-       g_string_append_printf(retval, "ORGANIZER:mailto:%s\n";,
-                              (gchar *) event->organizer->address_list->
-                              data);
+    if (event->organizer != NULL) {
+        const gchar *addr = libbalsa_address_get_addr(event->organizer);
+
+        if (addr != NULL)
+            g_string_append_printf(retval, "ORGANIZER:mailto:%s\n";, addr);
+    }
     if (event->summary) {
        buf = text_2445_escape(event->summary);
        g_string_append_printf(retval, "SUMMARY:%s\n", buf);
@@ -648,7 +650,7 @@ cal_address_2445_to_lbaddress(const gchar * uri, gchar ** attributes,
        return NULL;
 
     retval = libbalsa_address_new();
-    retval->address_list = g_list_prepend(NULL, g_strdup(uri + 7));
+    libbalsa_address_add_addr(retval, uri + 7);
     if (!is_organizer)
        g_object_set_data(G_OBJECT(retval), RFC2445_ROLE,
                          LB_ROLE2PTR(VCAL_ROLE_REQ_PART));
@@ -660,7 +662,7 @@ cal_address_2445_to_lbaddress(const gchar * uri, gchar ** attributes,
        /* scan attributes for extra information */
        for (n = 0; (the_attr = attributes[n]); n++) {
            if (!g_ascii_strncasecmp(the_attr, "CN=", 3))
-               retval->full_name = g_strdup(the_attr + 3);
+               libbalsa_address_set_full_name(retval, the_attr + 3);
            else if (!g_ascii_strncasecmp(the_attr, "ROLE=", 5))
                g_object_set_data(G_OBJECT(retval), RFC2445_ROLE,
                                  LB_ROLE2PTR(vcal_str_to_role(the_attr + 5)));
diff --git a/libbalsa/rfc6350.c b/libbalsa/rfc6350.c
index ae26ac4af..c2d07546a 100644
--- a/libbalsa/rfc6350.c
+++ b/libbalsa/rfc6350.c
@@ -105,11 +105,11 @@ rfc6350_parse_from_stream(GDataInputStream *stream,
 
        /* ignore items without an Email address, fill empty full name if necessary */
        if (result != NULL) {
-               if (result->address_list == NULL) {
+               if (libbalsa_address_get_addr_list(result) == NULL) {
                        g_object_unref(result);
                        result = NULL;
-               } else if (result->full_name == NULL) {
-                       result->full_name = g_strdup(_("No-Name"));
+               } else if (libbalsa_address_get_full_name(result) == NULL) {
+                        libbalsa_address_set_full_name(result, _("No-Name"));
                }
        }
 
@@ -272,42 +272,30 @@ rfc6350_eval_line(gchar                     *line,
                        g_debug("%s: line='%s' name='%s', value='%s'", __func__, line, name, value);
                        if (g_ascii_strcasecmp(name, "FN") == 0) {
                                rfc6350_unescape(value);
-                               g_free(address->full_name);
-                               address->full_name = g_strdup(value);
+                                libbalsa_address_set_full_name(address, value);
                        } else if (g_ascii_strcasecmp(name, "N") == 0) {
                                gchar **n_items;
 
                                n_items = rfc6350_strsplit(value, 5U);
-                               g_free(address->first_name);
-                               g_free(address->last_name);
-                               if (n_items[1] != NULL) {
-                                       address->first_name = g_strdup(n_items[1]);
-                               } else {
-                                       address->first_name = NULL;
-                               }
-                               if (n_items[0] != NULL) {
-                                       address->last_name = g_strdup(n_items[0]);
-                               } else {
-                                       address->last_name = NULL;
-                               }
-                               if (address->full_name == NULL) {
-                                       address->full_name = rfc6350_fn_from_n(n_items);
+                                libbalsa_address_set_first_name(address, n_items[1]);
+                                libbalsa_address_set_last_name(address, n_items[0]);
+                               if (libbalsa_address_get_full_name(address) == NULL) {
+                                        libbalsa_address_set_full_name
+                                            (address, rfc6350_fn_from_n(n_items));
                                }
                                g_strfreev(n_items);
                        } else if (g_ascii_strcasecmp(name, "NICKNAME") == 0) {
                                rfc6350_unescape(value);
-                               g_free(address->nick_name);
-                               address->nick_name = g_strdup(value);
+                                libbalsa_address_set_nick_name(address, value);
                        } else if (g_ascii_strcasecmp(name, "ORG") == 0) {
                                gchar **n_items;
 
                                n_items = rfc6350_strsplit(value, 2U);
-                               g_free(address->organization);
-                               address->organization = g_strdup(n_items[0]);
+                                libbalsa_address_set_organization(address, n_items[0]);
                                g_strfreev(n_items);
                        } else if (g_ascii_strcasecmp(name, "EMAIL") == 0) {
                                rfc6350_unescape(value);
-                               address->address_list = g_list_prepend(address->address_list, 
g_strdup(value));
+                                libbalsa_address_add_addr(address, value);
                        } else {
                                /* ignore any other items */
                        }
diff --git a/src/ab-main.c b/src/ab-main.c
index 1ef8604a7..9fd8053f5 100644
--- a/src/ab-main.c
+++ b/src/ab-main.c
@@ -122,19 +122,22 @@ bab_load_cb(LibBalsaAddressBook *libbalsa_ab,
             LibBalsaAddress *address, GtkTreeModel *model)
 {
     GtkTreeIter iter;
+    GList *addr_list;
 
     g_return_if_fail(LIBBALSA_IS_ADDRESS_BOOK(libbalsa_ab));
 
     if (address == NULL)
        return;
 
-    if (libbalsa_address_is_dist_list(libbalsa_ab, address)) {
+    addr_list = libbalsa_address_get_addr_list(address);
+    if (libbalsa_address_book_get_dist_list_mode(libbalsa_ab)
+        && addr_list != NULL && addr_list->next != NULL) {
         gchar *address_string = libbalsa_address_to_gchar(address, -1);
 
         gtk_list_store_prepend(GTK_LIST_STORE(model), &iter);
         /* GtkListStore refs address, and unrefs it when cleared  */
         gtk_list_store_set(GTK_LIST_STORE(model), &iter,
-                           LIST_COLUMN_NAME, address->full_name,
+                           LIST_COLUMN_NAME, libbalsa_address_get_full_name(address),
                            LIST_COLUMN_ADDRSPEC, address_string,
                            LIST_COLUMN_ADDRESS, address,
                            -1);
@@ -143,13 +146,13 @@ bab_load_cb(LibBalsaAddressBook *libbalsa_ab,
     } else {
         GList *l;
 
-       for (l = address->address_list; l; l = l->next) {
+       for (l = addr_list; l != NULL; l = l->next) {
             gtk_list_store_prepend(GTK_LIST_STORE(model), &iter);
             /* GtkListStore refs address once for each address in
              * the list, and unrefs it the same number of times when
              * cleared */
             gtk_list_store_set(GTK_LIST_STORE(model), &iter,
-                               LIST_COLUMN_NAME, address->full_name,
+                               LIST_COLUMN_NAME, libbalsa_address_get_full_name(address),
                                LIST_COLUMN_ADDRSPEC, l->data,
                                LIST_COLUMN_ADDRESS, address,
                                -1);
diff --git a/src/ab-window.c b/src/ab-window.c
index ac292a382..36fb3531f 100644
--- a/src/ab-window.c
+++ b/src/ab-window.c
@@ -117,7 +117,7 @@ balsa_ab_window_new(gboolean composing, GtkWindow* parent)
     GtkWidget *ret;
     BalsaAbWindow *ab;
     gint use_headerbar = 1;
-       const gchar *dialog_env;
+    const gchar *dialog_env;
 
     /* header bar configuration */
        dialog_env = g_getenv("BALSA_DIALOG_HEADERBAR");
@@ -751,23 +751,28 @@ balsa_ab_window_load_cb(LibBalsaAddressBook *libbalsa_ab,
 {
     GtkTreeModel *model;
     GtkTreeIter iter;
-    GList *address_list;
+    GList *addr_list;
     gint count;
+    const gchar *full_name;
 
-    g_return_if_fail ( BALSA_IS_AB_WINDOW(ab));
-    g_return_if_fail ( LIBBALSA_IS_ADDRESS_BOOK(libbalsa_ab) );
+    g_return_if_fail(BALSA_IS_AB_WINDOW(ab));
+    g_return_if_fail(LIBBALSA_IS_ADDRESS_BOOK(libbalsa_ab));
 
-    if ( address == NULL )
+    if (address == NULL)
        return;
 
+    full_name = libbalsa_address_get_full_name(address);
     model = gtk_tree_view_get_model(GTK_TREE_VIEW(ab->address_list));
-    if ( libbalsa_address_is_dist_list(libbalsa_ab, address) ) {
+
+    addr_list = libbalsa_address_get_addr_list(address);
+    if (libbalsa_address_book_get_dist_list_mode(libbalsa_ab)
+        && addr_list != NULL && addr_list->next != NULL) {
         gchar *address_string = libbalsa_address_to_gchar(address, -1);
 
         gtk_list_store_prepend(GTK_LIST_STORE(model), &iter);
         /* GtkListStore refs address, and unrefs it when cleared  */
         gtk_list_store_set(GTK_LIST_STORE(model), &iter,
-                           LIST_COLUMN_NAME, address->full_name,
+                           LIST_COLUMN_NAME, full_name,
                            LIST_COLUMN_ADDRESS_STRING, address_string,
                            LIST_COLUMN_ADDRESS, address,
                            LIST_COLUMN_WHICH, -1,
@@ -775,23 +780,20 @@ balsa_ab_window_load_cb(LibBalsaAddressBook *libbalsa_ab,
 
        g_free(address_string);
     } else {
-       address_list = address->address_list;
-       count = 0;
-       while ( address_list ) {
+       for (count = 0, addr_list = libbalsa_address_get_addr_list(address);
+             addr_list != NULL;
+             ++count, addr_list = addr_list->next) {
             gtk_list_store_prepend(GTK_LIST_STORE(model), &iter);
             /* GtkListStore refs address once for each address in
              * the list, and unrefs it the same number of times when
              * cleared */
             gtk_list_store_set(GTK_LIST_STORE(model), &iter,
-                               LIST_COLUMN_NAME, address->full_name,
+                               LIST_COLUMN_NAME, full_name,
                                LIST_COLUMN_ADDRESS_STRING,
-                               address_list->data,
+                               addr_list->data,
                                LIST_COLUMN_ADDRESS, address,
                                LIST_COLUMN_WHICH, count,
                                -1);
-
-           address_list = g_list_next(address_list);
-           count++;
        }
     }
 }
diff --git a/src/balsa-mime-widget-text.c b/src/balsa-mime-widget-text.c
index deba4763a..528d37b3e 100644
--- a/src/balsa-mime-widget-text.c
+++ b/src/balsa-mime-widget-text.c
@@ -1221,15 +1221,15 @@ bm_widget_new_vcard(BalsaMessage *bm, LibBalsaMessageBody *mime_body,
                     gchar *ptr, size_t len)
 {
     BalsaMimeWidget *mw = g_object_new(BALSA_TYPE_MIME_WIDGET, NULL);
-    LibBalsaAddress *addr;
+    LibBalsaAddress *address;
     GtkGrid *grid;
     GtkWidget *w;
     int row = 1;
 
-    addr =
+    address =
         libbalsa_address_new_from_vcard(ptr, mime_body->charset ?
                                         mime_body-> charset : "us-ascii");
-    if (!addr)
+    if (address == NULL)
         return NULL;
 
     mw->widget = gtk_grid_new();
@@ -1240,18 +1240,15 @@ bm_widget_new_vcard(BalsaMessage *bm, LibBalsaMessageBody *mime_body,
     w = gtk_button_new_with_mnemonic(_("S_tore Address"));
     gtk_grid_attach(grid, w, 0, 0, 2, 1);
     g_signal_connect_swapped(w, "clicked",
-                             G_CALLBACK(balsa_store_address), addr);
-    g_object_weak_ref(G_OBJECT(mw), (GWeakNotify)g_object_unref, addr);
-
-
-    GRID_ATTACH(grid, addr->full_name,    _("Full Name:"));
-    GRID_ATTACH(grid, addr->nick_name,    _("Nick Name:"));
-    GRID_ATTACH(grid, addr->first_name,   _("First Name:"));
-    GRID_ATTACH(grid, addr->last_name,    _("Last Name:"));
-    GRID_ATTACH(grid, addr->organization, _("Organization:"));
-    if(addr->address_list) {
-        GRID_ATTACH(grid, addr->address_list->data, _("Email Address:"));
-    }
+                             G_CALLBACK(balsa_store_address), address);
+    g_object_weak_ref(G_OBJECT(mw), (GWeakNotify)g_object_unref, address);
+
+    GRID_ATTACH(grid, libbalsa_address_get_full_name(address),    _("Full Name:"));
+    GRID_ATTACH(grid, libbalsa_address_get_nick_name(address),    _("Nick Name:"));
+    GRID_ATTACH(grid, libbalsa_address_get_first_name(address),   _("First Name:"));
+    GRID_ATTACH(grid, libbalsa_address_get_last_name(address),    _("Last Name:"));
+    GRID_ATTACH(grid, libbalsa_address_get_organization(address), _("Organization:"));
+    GRID_ATTACH(grid, libbalsa_address_get_addr(address),         _("Email Address:"));
 
     g_object_set_data(G_OBJECT(mw->widget), "mime-body", mime_body);
     return mw;
diff --git a/src/balsa-mime-widget-vcalendar.c b/src/balsa-mime-widget-vcalendar.c
index 6f14747f1..aee834a5d 100644
--- a/src/balsa-mime-widget-vcalendar.c
+++ b/src/balsa-mime-widget-vcalendar.c
@@ -189,9 +189,8 @@ balsa_vevent_widget(LibBalsaVEvent * event, gboolean may_reply,
            g_free(this_att);
 
            if (may_reply && libbalsa_vcal_attendee_rsvp(lba)) {
-               InternetAddress *ia =
-                    internet_address_mailbox_new(NULL,
-                                                 lba->address_list->data);
+                const gchar *addr = libbalsa_address_get_addr(lba);
+                InternetAddress *ia = internet_address_mailbox_new(NULL, addr);
                 GList *list;
 
                 for (list = balsa_app.identities; list; list = list->next) {
diff --git a/src/balsa-print-object-text.c b/src/balsa-print-object-text.c
index 47e98a8b9..0815f1b92 100644
--- a/src/balsa-print-object-text.c
+++ b/src/balsa-print-object-text.c
@@ -436,7 +436,7 @@ balsa_print_object_text_vcard(GList * list,
     PangoTabArray *tabs;
     GString *desc_buf;
     gdouble c_max_height;
-    LibBalsaAddress * addr = NULL;
+    LibBalsaAddress * address = NULL;
     gchar *textbuf;
 
     /* check if we can create an address from the body and fall back to default if 
@@ -446,8 +446,8 @@ balsa_print_object_text_vcard(GList * list,
     else
        libbalsa_message_body_get_content(body, &textbuf, NULL);
     if (textbuf)
-        addr = libbalsa_address_new_from_vcard(textbuf, body->charset);
-    if (!addr) {
+        address = libbalsa_address_new_from_vcard(textbuf, body->charset);
+    if (address == NULL) {
        g_free(textbuf);
        return balsa_print_object_text(list, context, body, psetup);
     }
@@ -488,19 +488,19 @@ balsa_print_object_text_vcard(GList * list,
     desc_buf = g_string_new("");
     pod->p_label_width = 0;
     ADD_VCARD_FIELD(desc_buf, pod->p_label_width, test_layout,
-                   addr->full_name,    _("Full Name"));
+                   libbalsa_address_get_full_name(address),    _("Full Name"));
     ADD_VCARD_FIELD(desc_buf, pod->p_label_width, test_layout,
-                   addr->nick_name,    _("Nick Name"));
+                   libbalsa_address_get_nick_name(address),    _("Nick Name"));
     ADD_VCARD_FIELD(desc_buf, pod->p_label_width, test_layout,
-                   addr->first_name,   _("First Name"));
+                   libbalsa_address_get_first_name(address),   _("First Name"));
     ADD_VCARD_FIELD(desc_buf, pod->p_label_width, test_layout,
-                   addr->last_name,    _("Last Name"));
+                   libbalsa_address_get_last_name(address),    _("Last Name"));
     ADD_VCARD_FIELD(desc_buf, pod->p_label_width, test_layout,
-                   addr->organization, _("Organization"));
-    if (addr->address_list)
-        ADD_VCARD_FIELD(desc_buf, pod->p_label_width, test_layout,
-                       (const gchar *) addr->address_list->data, _("Email Address"));
-    g_object_unref(addr);
+                   libbalsa_address_get_organization(address), _("Organization"));
+    ADD_VCARD_FIELD(desc_buf, pod->p_label_width, test_layout,
+                    libbalsa_address_get_addr(address),         _("Email Address"));
+
+    g_object_unref(address);
 
     /* add a small space between label and value */
     pod->p_label_width += C_TO_P(C_LABEL_SEP);
diff --git a/src/store-address.c b/src/store-address.c
index 199c3f1f0..fb444bec1 100644
--- a/src/store-address.c
+++ b/src/store-address.c
@@ -376,32 +376,25 @@ store_address_add_address(StoreAddressInfo * info,
 
     text = internet_address_to_string(ia, FALSE);
     address = libbalsa_address_new();
-    if (ia->name != NULL) {
-       address->full_name = g_strdup(ia->name);
-    } else {
-       address->full_name = g_strdup((group != NULL) ? group->name : NULL);
-    }
+    libbalsa_address_set_full_name(address,
+                                   ia->name != NULL ? ia->name :
+                                   group != NULL ? group->name : NULL);
     if (INTERNET_ADDRESS_IS_GROUP(ia)) {
         InternetAddressList *members;
         int j;
 
-        address->address_list = NULL;
         members = INTERNET_ADDRESS_GROUP(ia)->members;
 
         for (j = 0; j < internet_address_list_length(members); j++) {
             InternetAddress *member_address =
                 internet_address_list_get_address(members, j);
             if (INTERNET_ADDRESS_IS_MAILBOX(member_address))
-                address->address_list =
-                    g_list_prepend(address->address_list,
-                                   g_strdup(INTERNET_ADDRESS_MAILBOX
-                                            (member_address)->addr));
+                libbalsa_address_add_addr
+                    (address, INTERNET_ADDRESS_MAILBOX(member_address)->addr);
         }
-        address->address_list = g_list_reverse(address->address_list);
+        libbalsa_address_add_addr(address, INTERNET_ADDRESS_MAILBOX(ia)->addr);
     } else {
-        address->address_list =
-            g_list_prepend(NULL,
-                           g_strdup(INTERNET_ADDRESS_MAILBOX(ia)->addr));
+        libbalsa_address_add_addr(address, INTERNET_ADDRESS_MAILBOX(ia)->addr);
     }
     ew = libbalsa_address_get_edit_widget(address, entries, NULL, NULL);
     g_object_unref(address);
@@ -422,15 +415,19 @@ store_address_add_lbaddress(StoreAddressInfo * info,
 {
     gchar *label_text;
     GtkWidget **entries, *ew;
+    const gchar *addr;
+    const gchar *full_name;
+
+    addr = libbalsa_address_get_addr(address);
+    g_return_if_fail(addr != NULL);
 
-    g_return_if_fail(address->address_list);
     entries = g_new(GtkWidget *, NUM_FIELDS);
     info->entries_list = g_list_append(info->entries_list, entries);
 
     ew = libbalsa_address_get_edit_widget(address, entries, NULL, NULL);
 
-    label_text = g_strdup(address->full_name ? address->full_name :
-                          address->address_list->data);
+    full_name = libbalsa_address_get_full_name(address);
+    label_text = g_strdup(full_name != NULL ? full_name : addr);
     if (g_utf8_strlen(label_text, -1) > 15)
         /* truncate to an arbitrary length: */
         *g_utf8_offset_to_pointer(label_text, 15) = '\0';


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]