fix bug 643638
[claws.git] / src / addrbook.c
index 8e9098e35a7297f7523e9f6a86eabe9e1053b193..138b9b62e4110bb1ab7c9f430f5a86eb362613f8 100644 (file)
  */
 
 /*
- * General functions for accessing external address book files.
+ * General functions for accessing address book files.
  */
 
-#include <stdio.h>
 #include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <dirent.h>
 #include <sys/stat.h>
 #include <math.h>
 #include "addritem.h"
 #include "addrcache.h"
 #include "addrbook.h"
+#include "adbookbase.h"
 
 #ifndef DEV_STANDALONE
 #include "prefs.h"
+#include "codeconv.h"
 #endif
 
 #define ADDRBOOK_MAX_SEARCH_COUNT 1000
 */
 AddressBookFile *addrbook_create_book() {
        AddressBookFile *book;
-       gint t;
+
        book = g_new0( AddressBookFile, 1 );
-       book->name = NULL;
+       book->type = ADBOOKTYPE_BOOK;
+       book->addressCache = addrcache_create();
+       book->retVal = MGU_SUCCESS;
        book->path = NULL;
        book->fileName = NULL;
-       book->retVal = MGU_SUCCESS;
-       book->addressCache = addrcache_create();
-
+       book->maxValue = 0;
        book->tempList = NULL;
-       book->readFlag = FALSE;
-       book->dirtyFlag = FALSE;
-       book->modifyFlag = TRUE;
-       book->accessFlag = FALSE;
        book->tempHash = NULL;
+       book->addressCache->modified = TRUE;
        return book;
 }
 
@@ -71,80 +71,69 @@ AddressBookFile *addrbook_create_book() {
 */
 void addrbook_set_name( AddressBookFile *book, const gchar *value ) {
        g_return_if_fail( book != NULL );
-       book->name = mgu_replace_string( book->name, value );
+       addrcache_set_name( book->addressCache, value );
+}
+gchar *addrbook_get_name( AddressBookFile *book ) {
+       g_return_val_if_fail( book != NULL, NULL );
+       return addrcache_get_name( book->addressCache );
 }
 void addrbook_set_path( AddressBookFile *book, const gchar *value ) {
        g_return_if_fail( book != NULL );
        book->path = mgu_replace_string( book->path, value );
-       book->dirtyFlag = TRUE;
+       addrcache_set_dirty( book->addressCache, TRUE );
 }
 void addrbook_set_file( AddressBookFile *book, const gchar *value ) {
        g_return_if_fail( book != NULL );
        book->fileName = mgu_replace_string( book->fileName, value );
-       book->dirtyFlag = TRUE;
-}
-void addrbook_set_accessed( AddressBookFile *book, const gboolean value ) {
-       g_return_if_fail( book != NULL );
-       book->accessFlag = value;
+       addrcache_set_dirty( book->addressCache, TRUE );
 }
 gboolean addrbook_get_modified( AddressBookFile *book ) {
+       g_return_val_if_fail( book != NULL, FALSE );
+       return book->addressCache->modified;
+}
+void addrbook_set_modified( AddressBookFile *book, const gboolean value ) {
        g_return_if_fail( book != NULL );
-       return book->modifyFlag;
+       book->addressCache->modified = value;
 }
 gboolean addrbook_get_accessed( AddressBookFile *book ) {
+       g_return_val_if_fail( book != NULL, FALSE );
+       return book->addressCache->accessFlag;
+}
+void addrbook_set_accessed( AddressBookFile *book, const gboolean value ) {
        g_return_if_fail( book != NULL );
-       return book->accessFlag;
+       book->addressCache->accessFlag = value;
 }
 gboolean addrbook_get_read_flag( AddressBookFile *book ) {
+       g_return_val_if_fail( book != NULL, FALSE );
+       return book->addressCache->dataRead;
+}
+void addrbook_set_read_flag( AddressBookFile *book, const gboolean value ) {
        g_return_if_fail( book != NULL );
-       return book->readFlag;
+       book->addressCache->dataRead = value;
 }
 gint addrbook_get_status( AddressBookFile *book ) {
-       g_return_if_fail( book != NULL );
+       g_return_val_if_fail( book != NULL, -1 );
        return book->retVal;
 }
 ItemFolder *addrbook_get_root_folder( AddressBookFile *book ) {
-       g_return_if_fail( book != NULL );
+       g_return_val_if_fail( book != NULL, NULL );
        return addrcache_get_root_folder( book->addressCache );
 }
 GList *addrbook_get_list_folder( AddressBookFile *book ) {
-       g_return_if_fail( book != NULL );
+       g_return_val_if_fail( book != NULL, NULL );
        return addrcache_get_list_folder( book->addressCache );
 }
 GList *addrbook_get_list_person( AddressBookFile *book ) {
-       g_return_if_fail( book != NULL );
+       g_return_val_if_fail( book != NULL, NULL );
        return addrcache_get_list_person( book->addressCache );
 }
-gchar *addrbook_get_name( AddressBookFile *book ) {
-       g_return_if_fail( book != NULL );
-       return book->name;
-}
-
-static gint addrcache_free_item_vis( gpointer key, gpointer value, gpointer data ) {
-       AddrItemObject *obj = ( AddrItemObject * ) value;
-       if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
-               addritem_free_item_person( ( ItemPerson * ) obj );
-       }
-       else if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
-               addritem_free_item_group( ( ItemGroup * ) obj );
-       }
-       else if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
-               addritem_free_item_folder( ( ItemFolder * ) obj );
-       }
-       key = NULL;
-       value = NULL;
-       return 0;
+gboolean addrbook_get_dirty( AddressBookFile *book ) {
+       g_return_val_if_fail( book != NULL, FALSE );
+       return addrcache_get_dirty( book->addressCache );
 }
-
-/*
-* Free hash table of address book items.
-*/
-static void addrcache_free_item_hash( GHashTable *table ) {
-       g_return_if_fail( table != NULL );
-       g_hash_table_freeze( table );
-       g_hash_table_foreach_remove( table, addrcache_free_item_vis, NULL );
-       g_hash_table_thaw( table );
-       g_hash_table_destroy( table );
+void addrbook_set_dirty( AddressBookFile *book, const gboolean value ) {
+       g_return_if_fail( book != NULL );
+       addrcache_set_dirty( book->addressCache, value );
 }
 
 /*
@@ -153,19 +142,18 @@ static void addrcache_free_item_hash( GHashTable *table ) {
 void addrbook_empty_book( AddressBookFile *book ) {
        g_return_if_fail( book != NULL );
 
-       // Free up folders and hash table
+       /* Free up internal objects */
        addrcache_clear( book->addressCache );
-
+       addrcache_set_dirty( book->addressCache, FALSE );
        g_list_free( book->tempList );
-       book->tempList = NULL;
 
-       // Reset to initial state
-       book->retVal = MGU_SUCCESS;
+       /* Reset to initial state */
+       book->tempList = NULL;
        book->tempHash = NULL;
-       book->readFlag = FALSE;
-       book->dirtyFlag = FALSE;
-       book->modifyFlag = FALSE;
-       book->accessFlag = FALSE;
+       book->addressCache->dataRead = FALSE;
+       book->addressCache->modified = FALSE;
+       book->addressCache->accessFlag = FALSE;
+       book->retVal = MGU_SUCCESS;
 }
 
 /*
@@ -174,26 +162,24 @@ void addrbook_empty_book( AddressBookFile *book ) {
 void addrbook_free_book( AddressBookFile *book ) {
        g_return_if_fail( book != NULL );
 
-       g_free( book->name );
+       /* Clear cache */
+       addrcache_clear( book->addressCache );
+       addrcache_free( book->addressCache );
+
+       /* Free up internal objects */
        g_free( book->path );
        g_free( book->fileName );
-       book->name = NULL;
+       g_list_free( book->tempList );
+
        book->path = NULL;
        book->fileName = NULL;
-
-       // Free up folders and hash table
-       addrcache_free( book->addressCache );
-       book->addressCache = NULL;
-
-       g_list_free( book->tempList );
+       book->maxValue = 0;
        book->tempList = NULL;
+       book->tempHash = NULL;
 
+       book->type = ADBOOKTYPE_NONE;
+       book->addressCache = NULL;
        book->retVal = MGU_SUCCESS;
-       book->tempHash = NULL;
-       book->readFlag = FALSE;
-       book->dirtyFlag = FALSE;
-       book->modifyFlag = FALSE;
-       book->accessFlag = FALSE;
 
        g_free( book );
 }
@@ -203,6 +189,7 @@ void addrbook_free_book( AddressBookFile *book ) {
 */
 void addrbook_print_item_list( GList *list, FILE *stream ) {
        GList *node = list;
+
        while( node ) {
                AddrItemObject *obj = node->data;
                if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
@@ -224,8 +211,8 @@ void addrbook_print_item_list( GList *list, FILE *stream ) {
 */
 void addrbook_print_book( AddressBookFile *book, FILE *stream ) {
        g_return_if_fail( book != NULL );
+
        fprintf( stream, "AddressBook:\n" );
-       fprintf( stream, "\tname  : '%s'\n", book->name );
        fprintf( stream, "\tpath  : '%s'\n", book->path );
        fprintf( stream, "\tfile  : '%s'\n", book->fileName );
        fprintf( stream, "\tstatus: %d : '%s'\n", book->retVal, mgu_error2string( book->retVal ) );
@@ -236,9 +223,10 @@ void addrbook_print_book( AddressBookFile *book, FILE *stream ) {
 * Dump entire address book traversing folders.
 */
 void addrbook_dump_book( AddressBookFile *book, FILE *stream ) {
-       GList *node;
        ItemFolder *folder;
+
        g_return_if_fail( book != NULL );
+
        addrbook_print_book( book, stream );
        folder = book->addressCache->rootFolder;
        addritem_print_item_folder( folder, stream );
@@ -250,11 +238,8 @@ void addrbook_dump_book( AddressBookFile *book, FILE *stream ) {
 * return: Group, or NULL if not found. Note that object should still be freed.
 */
 ItemGroup *addrbook_remove_group( AddressBookFile *book, ItemGroup *group ) {
-       ItemGroup *item;
-       g_return_if_fail( book != NULL );
-       item = addrcache_remove_group( book->addressCache, group );
-       if( item ) book->dirtyFlag = TRUE;
-       return item;
+       g_return_val_if_fail( book != NULL, NULL );
+       return addrcache_remove_group( book->addressCache, group );
 }
 
 /*
@@ -263,11 +248,8 @@ ItemGroup *addrbook_remove_group( AddressBookFile *book, ItemGroup *group ) {
 * return: Person, or NULL if not found. Note that object should still be freed.
 */
 ItemPerson *addrbook_remove_person( AddressBookFile *book, ItemPerson *person ) {
-       ItemPerson *item;
-       g_return_if_fail( book != NULL );
-       item = addrcache_remove_person( book->addressCache, person );
-       if( item ) book->dirtyFlag = TRUE;
-       return item;
+       g_return_val_if_fail( book != NULL, NULL );
+       return addrcache_remove_person( book->addressCache, person );
 }
 
 /*
@@ -277,11 +259,8 @@ ItemPerson *addrbook_remove_person( AddressBookFile *book, ItemPerson *person )
 * return: EMail object, or NULL if not found. Note that object should still be freed.
 */
 ItemEMail *addrbook_person_remove_email( AddressBookFile *book, ItemPerson *person, ItemEMail *email ) {
-       ItemEMail *item;
-       g_return_if_fail( book != NULL );
-       item = addrcache_person_remove_email( book->addressCache, person, email );
-       if( item ); book->dirtyFlag = TRUE;
-       return item;
+       g_return_val_if_fail( book != NULL, NULL );
+       return addrcache_person_remove_email( book->addressCache, person, email );
 }
 
 /* **********************************************************************
@@ -316,7 +295,7 @@ ItemEMail *addrbook_person_remove_email( AddressBookFile *book, ItemPerson *pers
 * ***********************************************************************
 */
 
-// Element tag names
+/* Element tag names */
 #define AB_ELTAG_ADDRESS         "address"
 #define AB_ELTAG_ATTRIBUTE       "attribute"
 #define AB_ELTAG_ATTRIBUTE_LIST  "attribute-list"
@@ -330,7 +309,7 @@ ItemEMail *addrbook_person_remove_email( AddressBookFile *book, ItemPerson *pers
 #define AB_ELTAG_GROUP           "group"
 #define AB_ELTAG_FOLDER          "folder"
 
-// Attribute tag names
+/* Attribute tag names */
 #define AB_ATTAG_TYPE            "type"
 #define AB_ATTAG_UID             "uid"
 #define AB_ATTAG_NAME            "name"
@@ -344,7 +323,7 @@ ItemEMail *addrbook_person_remove_email( AddressBookFile *book, ItemPerson *pers
 #define AB_ATTAG_EID             "eid"
 #define AB_ATTAG_PID             "pid"
 
-// Attribute values
+/* Attribute values */
 #define AB_ATTAG_VAL_PERSON      "person"
 #define AB_ATTAG_VAL_GROUP       "group"
 #define AB_ATTAG_VAL_FOLDER      "folder"
@@ -496,7 +475,7 @@ static void addrbook_parse_person( AddressBookFile *book, XMLFile *file ) {
                }
                attr = g_list_next( attr );
        }
-       if( xml_parse_next_tag( file ) ) {      // Consume closing tag
+       if( xml_parse_next_tag( file ) ) {      /* Consume closing tag */
                longjmp( book->jumper, 1 );
        }
        if( xml_compare_tag( file, AB_ELTAG_ADDRESS_LIST ) ) {
@@ -505,7 +484,7 @@ static void addrbook_parse_person( AddressBookFile *book, XMLFile *file ) {
                        addrcache_hash_add_person( book->addressCache, person );
                }
        }
-       if( xml_parse_next_tag( file ) ) {      // Consume closing tag
+       if( xml_parse_next_tag( file ) ) {      /* Consume closing tag */
                longjmp( book->jumper, 1 );
        }
        if( xml_compare_tag( file, AB_ELTAG_ATTRIBUTE_LIST ) ) {
@@ -534,7 +513,8 @@ static void addrbook_parse_member( AddressBookFile *book, XMLFile *file, ItemGro
                }
                attr = g_list_next( attr );
        }
-       email = addrcache_get_email( book->addressCache, pid, eid );
+       /* email = addrcache_get_email( book->addressCache, pid, eid ); */
+       email = addrcache_get_email( book->addressCache, eid );
        if( email ) {
                if( group ) {
                        addrcache_group_add_email( book->addressCache, group, email );
@@ -552,7 +532,6 @@ static void addrbook_parse_member( AddressBookFile *book, XMLFile *file, ItemGro
 static void addrbook_parse_member_list( AddressBookFile *book, XMLFile *file, ItemGroup *group ){
        GList *attr;
        guint prev_level;
-       gchar *element;
 
        for (;;) {
                prev_level = file->level;
@@ -595,7 +574,7 @@ static void addrbook_parse_group( AddressBookFile *book, XMLFile *file ) {
                }
                attr = g_list_next( attr );
        }
-       if( xml_parse_next_tag( file ) ) {      // Consume closing tag
+       if( xml_parse_next_tag( file ) ) {      /* Consume closing tag */
                longjmp( book->jumper, 1 );
        }
        if( xml_compare_tag( file, AB_ELTAG_MEMBER_LIST ) ) {
@@ -636,7 +615,6 @@ static void addrbook_parse_folder_item( AddressBookFile *book, XMLFile *file, It
 static void addrbook_parse_folder_list( AddressBookFile *book, XMLFile *file, ItemFolder *folder ){
        GList *attr;
        guint prev_level;
-       gchar *element;
 
        for (;;) {
                prev_level = file->level;
@@ -681,14 +659,14 @@ static void addrbook_parse_folder( AddressBookFile *book, XMLFile *file ) {
                }
                attr = g_list_next( attr );
        }
-       if( xml_parse_next_tag( file ) ) {      // Consume closing tag
+       if( xml_parse_next_tag( file ) ) {      /* Consume closing tag */
                longjmp( book->jumper, 1 );
        }
        if( xml_compare_tag( file, AB_ELTAG_ITEM_LIST ) ) {
                if( folder ) {
                        if( addrcache_hash_add_folder( book->addressCache, folder ) ) {
                                book->tempList = g_list_append( book->tempList, folder );
-                               ADDRITEM_PARENT(folder) = NULL; // We will resolve folder later
+                               ADDRITEM_PARENT(folder) = NULL; /* We will resolve folder later */
                        }
                }
                addrbook_parse_folder_list( book, file, folder );
@@ -728,7 +706,7 @@ static gboolean addrbook_read_tree( AddressBookFile *book, XMLFile *file ) {
        retVal = TRUE;
        for (;;) {
                if (! file->level ) break;
-               // Get next item tag (person, group or folder)
+               /* Get next item tag (person, group or folder) */
                if( xml_parse_next_tag( file ) ) {
                        longjmp( book->jumper, 1 );
                }
@@ -798,19 +776,19 @@ static void addrbook_resolve_folder_items( AddressBookFile *book ) {
                                        folder->listGroup = g_list_append( folder->listGroup, item );
                                        ADDRITEM_PARENT(item) = ADDRITEM_OBJECT(folder);
                                }
-                               // Replace data with pointer to item
+                               /* Replace data with pointer to item */
                                g_free( uid );
                                node->data = aio;
                        }
                        else {
-                               // Not found, append to remove list.
+                               /* Not found, append to remove list. */
                                listRemove = g_list_append( listRemove, uid );
                        }
                        node = g_list_next( node );
                }
                rootFolder->listFolder = g_list_append( rootFolder->listFolder, folder );
 
-               // Process remove list
+               /* Process remove list */
                node = listRemove;
                while( node ) {
                        gchar *uid = node->data;
@@ -822,23 +800,23 @@ static void addrbook_resolve_folder_items( AddressBookFile *book ) {
                nodeFolder = g_list_next( nodeFolder );
        }
 
-       // Remove folders with parents.
+       /* Remove folders with parents. */
        listRemove = NULL;
        node = rootFolder->listFolder;
        while( node ) {
                ItemFolder *folder = ( ItemFolder * ) node->data;
                if( ADDRITEM_PARENT(folder) ) {
-                       // Remove folders with parents
+                       /* Remove folders with parents */
                        listRemove = g_list_append( listRemove, folder );
                }
                else {
-                       // Add to root folder
+                       /* Add to root folder */
                        ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(book->addressCache->rootFolder);
                }
                node = g_list_next( node );
        }
 
-       // Process remove list
+       /* Process remove list */
        node = listRemove;
        while( node ) {
                rootFolder->listFolder = g_list_remove( rootFolder->listFolder, node->data );
@@ -846,10 +824,10 @@ static void addrbook_resolve_folder_items( AddressBookFile *book ) {
        }
        g_list_free( listRemove );
 
-       // Move all unparented persons and groups into root folder
+       /* Move all unparented persons and groups into root folder */
        g_hash_table_foreach( book->addressCache->itemHash, addrbook_res_items_vis, book );
 
-       // Free up some more
+       /* Free up some more */
        nodeFolder = book->tempList;
        while( nodeFolder ) {
                ItemFolder *folder = nodeFolder->data;
@@ -868,18 +846,25 @@ static void addrbook_resolve_folder_items( AddressBookFile *book ) {
 gint addrbook_read_data( AddressBookFile *book ) {
        XMLFile *file = NULL;
        gchar *fileSpec = NULL;
-       g_return_if_fail( book != NULL );
+
+       g_return_val_if_fail( book != NULL, -1 );
+
+       /*
+       printf( "...addrbook_read_data :%s:\t:%s:\n", book->fileName,
+               addrcache_get_name( book->addressCache ) );
+       */
 
        fileSpec = g_strconcat( book->path, G_DIR_SEPARATOR_S, book->fileName, NULL );
        book->retVal = MGU_OPEN_FILE;
-       book->accessFlag = FALSE;
-       book->modifyFlag = FALSE;
+       addrcache_clear( book->addressCache );
+       book->addressCache->modified = FALSE;
+       book->addressCache->accessFlag = FALSE;
        file = xml_open_file( fileSpec );
        g_free( fileSpec );
        if( file ) {
                book->tempList = NULL;
 
-               // Trap for parsing errors.
+               /* Trap for parsing errors. */
                if( setjmp( book->jumper ) ) {
                        xml_close_file( file );
                        return book->retVal;
@@ -887,11 +872,12 @@ gint addrbook_read_data( AddressBookFile *book ) {
                addrbook_read_tree( book, file );
                xml_close_file( file );
 
-               // Resolve folder items
+               /* Resolve folder items */
                addrbook_resolve_folder_items( book );
                book->tempList = NULL;
-               book->readFlag = TRUE;
-               book->dirtyFlag = FALSE;
+               book->addressCache->modified = FALSE;
+               book->addressCache->dataRead = TRUE;
+               addrcache_set_dirty( book->addressCache, FALSE );
        }
        return book->retVal;
 }
@@ -926,6 +912,7 @@ static void addrbook_write_item_person_vis( gpointer key, gpointer value, gpoint
        AddrItemObject *obj = ( AddrItemObject * ) value;
        FILE *fp = ( FILE * ) data;
        GList *node;
+
        if( ! obj ) return;
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
                ItemPerson *person = ( ItemPerson * ) value;
@@ -938,7 +925,7 @@ static void addrbook_write_item_person_vis( gpointer key, gpointer value, gpoint
                        addrbook_write_attr( fp, AB_ATTAG_COMMON_NAME, ADDRITEM_NAME(person) );
                        fputs( " >\n", fp);
 
-                       // Output email addresses
+                       /* Output email addresses */
                        addrbook_write_elem_s( fp, 2, AB_ELTAG_ADDRESS_LIST );
                        fputs( ">\n", fp );
                        node = person->listEMail;
@@ -954,7 +941,7 @@ static void addrbook_write_item_person_vis( gpointer key, gpointer value, gpoint
                        }
                        addrbook_write_elem_e( fp, 2, AB_ELTAG_ADDRESS_LIST );
 
-                       // Output user attributes
+                       /* Output user attributes */
                        addrbook_write_elem_s( fp, 2, AB_ELTAG_ATTRIBUTE_LIST );
                        fputs( ">\n", fp );
                        node = person->listAttrib;
@@ -974,47 +961,6 @@ static void addrbook_write_item_person_vis( gpointer key, gpointer value, gpoint
        }
 }
 
-/*
-* Output all groups in folder.
-*/
-static void addrbook_write_folder_group( ItemFolder *parent, FILE *fp ) {
-       GList *nodeGrp = parent->listGroup;
-       GList *node;
-       while( nodeGrp ) {
-               ItemGroup *group = nodeGrp->data;
-               if( group ) {
-                       addrbook_write_elem_s( fp, 1, AB_ELTAG_GROUP );
-                       addrbook_write_attr( fp, AB_ATTAG_UID, ADDRITEM_ID(group) );
-                       addrbook_write_attr( fp, AB_ATTAG_NAME, ADDRITEM_NAME(group) );
-                       addrbook_write_attr( fp, AB_ATTAG_REMARKS, group->remarks );
-                       fputs( " >\n", fp );
-
-                       // Output email address links
-                       addrbook_write_elem_s( fp, 2, AB_ELTAG_MEMBER_LIST );
-                       fputs( ">\n", fp );
-                       node = group->listEMail;
-                       while ( node ) {
-                               ItemEMail *email = node->data;
-                               ItemPerson *person = ( ItemPerson * ) ADDRITEM_PARENT(email);
-                               addrbook_write_elem_s( fp, 3, AB_ELTAG_MEMBER );
-                               addrbook_write_attr( fp, AB_ATTAG_PID, ADDRITEM_ID(person) );
-                               addrbook_write_attr( fp, AB_ATTAG_EID, ADDRITEM_ID(email) );
-                               fputs( " />\n", fp );
-                               node = g_list_next( node );
-                       }
-                       addrbook_write_elem_e( fp, 2, AB_ELTAG_MEMBER_LIST );
-                       addrbook_write_elem_e( fp, 1, AB_ELTAG_GROUP );
-               }
-               nodeGrp = g_list_next( nodeGrp );
-       }
-       node = parent->listFolder;
-       while( node ) {
-               ItemFolder *folder = node->data;
-               addrbook_write_folder_group( folder, fp );
-               node = g_list_next( node );
-       }
-}
-
 /*
 * Write file hash table visitor function.
 */
@@ -1022,6 +968,7 @@ static void addrbook_write_item_group_vis( gpointer key, gpointer value, gpointe
        AddrItemObject *obj = ( AddrItemObject * ) value;
        FILE *fp = ( FILE * ) data;
        GList *node;
+
        if( ! obj ) return;
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_GROUP ) {
                ItemGroup *group = ( ItemGroup * ) value;
@@ -1032,7 +979,7 @@ static void addrbook_write_item_group_vis( gpointer key, gpointer value, gpointe
                        addrbook_write_attr( fp, AB_ATTAG_REMARKS, group->remarks );
                        fputs( " >\n", fp );
 
-                       // Output email address links
+                       /* Output email address links */
                        addrbook_write_elem_s( fp, 2, AB_ELTAG_MEMBER_LIST );
                        fputs( ">\n", fp );
                        node = group->listEMail;
@@ -1051,63 +998,6 @@ static void addrbook_write_item_group_vis( gpointer key, gpointer value, gpointe
        }
 }
 
-/*
-* Output all folders in folder.
-*/
-static void addrbook_write_folder_folder( ItemFolder *parent, FILE *fp ) {
-       GList *nodeFold = parent->listFolder;
-       GList *node;
-       while( nodeFold ) {
-               ItemFolder *folder = nodeFold->data;
-               addrbook_write_folder_folder( folder, fp );
-               if( folder ) {
-                       addrbook_write_elem_s( fp, 1, AB_ELTAG_FOLDER );
-                       addrbook_write_attr( fp, AB_ATTAG_UID, ADDRITEM_ID(folder) );
-                       addrbook_write_attr( fp, AB_ATTAG_NAME, ADDRITEM_NAME(folder) );
-                       addrbook_write_attr( fp, AB_ATTAG_REMARKS, folder->remarks );
-                       fputs( " >\n", fp );
-                       addrbook_write_elem_s( fp, 2, AB_ELTAG_ITEM_LIST );
-                       fputs( ">\n", fp );
-
-                       // Output persons
-                       node = folder->listPerson;
-                       while ( node ) {
-                               ItemPerson *item = node->data;
-                               addrbook_write_elem_s( fp, 2, AB_ELTAG_ITEM );
-                               addrbook_write_attr( fp, AB_ATTAG_TYPE,  AB_ATTAG_VAL_PERSON );
-                               addrbook_write_attr( fp, AB_ATTAG_UID, ADDRITEM_ID(item ) );
-                               fputs( " />\n", fp );
-                               node = g_list_next( node );
-                       }
-
-                       // Output groups
-                       node = folder->listGroup;
-                       while ( node ) {
-                               ItemGroup *item = node->data;
-                               addrbook_write_elem_s( fp, 2, AB_ELTAG_ITEM );
-                               addrbook_write_attr( fp, AB_ATTAG_TYPE, AB_ATTAG_VAL_GROUP );
-                               addrbook_write_attr( fp, AB_ATTAG_UID, ADDRITEM_ID(item ) );
-                               fputs( " />\n", fp );
-                               node = g_list_next( node );
-                       }
-
-                       // Output folders
-                       node = folder->listFolder;
-                       while ( node ) {
-                               ItemFolder *item = node->data;
-                               addrbook_write_elem_s( fp, 2, AB_ELTAG_ITEM );
-                               addrbook_write_attr( fp, AB_ATTAG_TYPE, AB_ATTAG_VAL_FOLDER );
-                               addrbook_write_attr( fp, AB_ATTAG_UID, ADDRITEM_ID(item ) );
-                               fputs( " />\n", fp );
-                               node = g_list_next( node );
-                       }
-                       addrbook_write_elem_e( fp, 2, AB_ELTAG_ITEM_LIST );
-                       addrbook_write_elem_e( fp, 1, AB_ELTAG_FOLDER );
-               }
-               nodeFold = g_list_next( nodeFold );
-       }
-}
-
 /*
 * Write file hash table visitor function.
 */
@@ -1115,6 +1005,7 @@ static void addrbook_write_item_folder_vis( gpointer key, gpointer value, gpoint
        AddrItemObject *obj = ( AddrItemObject * ) value;
        FILE *fp = ( FILE * ) data;
        GList *node;
+
        if( ! obj ) return;
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_FOLDER ) {
                ItemFolder *folder = ( ItemFolder * ) value;
@@ -1127,7 +1018,7 @@ static void addrbook_write_item_folder_vis( gpointer key, gpointer value, gpoint
                        addrbook_write_elem_s( fp, 2, AB_ELTAG_ITEM_LIST );
                        fputs( ">\n", fp );
 
-                       // Output persons
+                       /* Output persons */
                        node = folder->listPerson;
                        while ( node ) {
                                ItemPerson *item = node->data;
@@ -1138,7 +1029,7 @@ static void addrbook_write_item_folder_vis( gpointer key, gpointer value, gpoint
                                node = g_list_next( node );
                        }
 
-                       // Output groups
+                       /* Output groups */
                        node = folder->listGroup;
                        while ( node ) {
                                ItemGroup *item = node->data;
@@ -1149,7 +1040,7 @@ static void addrbook_write_item_folder_vis( gpointer key, gpointer value, gpoint
                                node = g_list_next( node );
                        }
 
-                       // Output folders
+                       /* Output folders */
                        node = folder->listFolder;
                        while ( node ) {
                                ItemFolder *item = node->data;
@@ -1176,14 +1067,14 @@ gint addrbook_write_to( AddressBookFile *book, gchar *newFile ) {
        PrefFile *pfile;
 #endif
 
-       g_return_if_fail( book != NULL );
-       g_return_if_fail( newFile != NULL );
+       g_return_val_if_fail( book != NULL, -1 );
+       g_return_val_if_fail( newFile != NULL, -1 );
 
        fileSpec = g_strconcat( book->path, G_DIR_SEPARATOR_S, newFile, NULL );
 
        book->retVal = MGU_OPEN_FILE;
 #ifdef DEV_STANDALONE
-       fp = fopen( fileSpec, "w" );
+       fp = fopen( fileSpec, "wb" );
        g_free( fileSpec );
        if( fp ) {
                fputs( "<?xml version=\"1.0\" ?>\n", fp );
@@ -1196,19 +1087,17 @@ gint addrbook_write_to( AddressBookFile *book, gchar *newFile ) {
                                conv_get_current_charset_str() );
 #endif
                addrbook_write_elem_s( fp, 0, AB_ELTAG_ADDRESS_BOOK );
-               addrbook_write_attr( fp, AB_ATTAG_NAME, book->name );
+               addrbook_write_attr( fp, AB_ATTAG_NAME, addrcache_get_name( book->addressCache ) );
                fputs( " >\n", fp );
 
-               // Output all persons
+               /* Output all persons */
                g_hash_table_foreach( book->addressCache->itemHash, addrbook_write_item_person_vis, fp );
 
-               // Output all groups
+               /* Output all groups */
                g_hash_table_foreach( book->addressCache->itemHash, addrbook_write_item_group_vis, fp );
-               // addrbook_write_folder_group( book->rootFolder, fp );
 
-               // Output all folders
+               /* Output all folders */
                g_hash_table_foreach( book->addressCache->itemHash, addrbook_write_item_folder_vis, fp );
-               // addrbook_write_folder_folder( book->rootFolder, fp );
 
                addrbook_write_elem_e( fp, 0, AB_ELTAG_ADDRESS_BOOK );
                book->retVal = MGU_SUCCESS;
@@ -1230,7 +1119,7 @@ gint addrbook_write_to( AddressBookFile *book, gchar *newFile ) {
 * return: Status code.
 */
 gint addrbook_save_data( AddressBookFile *book ) {
-       g_return_if_fail( book != NULL );
+       g_return_val_if_fail( book != NULL, -1 );
 
        book->retVal = MGU_NO_FILE;
        if( book->fileName == NULL || *book->fileName == '\0' ) return book->retVal;
@@ -1238,7 +1127,7 @@ gint addrbook_save_data( AddressBookFile *book ) {
 
        addrbook_write_to( book, book->fileName );
        if( book->retVal == MGU_SUCCESS ) {
-               book->dirtyFlag = FALSE;
+               addrcache_set_dirty( book->addressCache, FALSE );
        }
        return book->retVal;
 }
@@ -1259,10 +1148,12 @@ ItemEMail *addrbook_move_email_before( AddressBookFile *book, ItemPerson *person
                        ItemEMail *itemMove, ItemEMail *itemTarget )
 {
        ItemEMail *email = NULL;
-       g_return_if_fail( book != NULL );
+
+       g_return_val_if_fail( book != NULL, NULL );
+
        email = addritem_move_email_before( person, itemMove, itemTarget );
        if( email ) {
-               book->dirtyFlag = TRUE;
+               addrcache_set_dirty( book->addressCache, TRUE );
        }
        return email;
 }
@@ -1278,18 +1169,22 @@ ItemEMail *addrbook_move_email_after( AddressBookFile *book, ItemPerson *person,
                        ItemEMail *itemMove, ItemEMail *itemTarget )
 {
        ItemEMail *email = NULL;
-       g_return_if_fail( book != NULL );
+
+       g_return_val_if_fail( book != NULL, NULL );
+
        email = addritem_move_email_after( person, itemMove, itemTarget );
        if( email ) {
-               book->dirtyFlag = TRUE;
+               addrcache_set_dirty( book->addressCache, TRUE );
        }
        return email;
 }
 
 /*
-* Hash table visitor function.
+* Hash table visitor function for deletion of hashtable entries.
 */
-static gboolean addrbook_free_simple_hash_vis( gpointer *key, gpointer *value, gpointer *data ) {
+static gboolean addrbook_free_simple_hash_vis(
+       gpointer *key, gpointer *value, gpointer *data )
+{
        g_free( key );
        key = NULL;
        value = NULL;
@@ -1300,55 +1195,47 @@ static gboolean addrbook_free_simple_hash_vis( gpointer *key, gpointer *value, g
 * Update address book email list for specified person.
 * Enter: book      Address book.
 *        person    Person to update.
-*        listEMail New list of email addresses.
+*        listEMail List of new email addresses.
 * Note: The existing email addresses are replaced with the new addresses. Any references
 * to old addresses in the groups are re-linked to the new addresses. All old addresses
 * linked to the person are removed.
 */
-void addrbook_update_address_list( AddressBookFile *book, ItemPerson *person, GList *listEMail ) {
+void addrbook_update_address_list(
+       AddressBookFile *book, ItemPerson *person, GList *listEMail )
+{
        GList *node;
-       GList *oldData;
+       GList *listDelete;
        GList *listGroup;
 
        g_return_if_fail( book != NULL );
        g_return_if_fail( person != NULL );
 
-       // Remember old list
-       oldData = person->listEMail;
-
-       // Attach new address list to person.
-       node = listEMail;
-       while( node ) {
-               ItemEMail *email = node->data;
-               if( ADDRITEM_ID(email) == NULL ) {
-                       // Allocate an ID
-                       addrcache_id_email( book->addressCache, email );
-               }
-               ADDRITEM_PARENT(email) = ADDRITEM_OBJECT(person);
-               node = g_list_next( node );
-       }
-       person->listEMail = listEMail;
-
-       // Get groups where person's email is listed
+       /* Get groups where person's existing email addresses are listed */
        listGroup = addrcache_get_group_for_person( book->addressCache, person );
        if( listGroup ) {
                GHashTable *hashEMail;
+               GHashTable *hashEMailAlias;
                GList *nodeGrp;
 
-               // Load hash table with new address entries
+               /* Load hash table with new address entries */
                hashEMail = g_hash_table_new( g_str_hash, g_str_equal );
+               hashEMailAlias = g_hash_table_new( g_str_hash, g_str_equal );
                node = listEMail;
                while( node ) {
                        ItemEMail *email = node->data;
                        gchar *addr = g_strdup( email->address );
+                       gchar *alias = email->obj.name ;
                        g_strdown( addr );
                        if( ! g_hash_table_lookup( hashEMail, addr ) ) {
                                g_hash_table_insert( hashEMail, addr, email );
                        }
+                       if ( *alias != '\0' && ! g_hash_table_lookup( hashEMailAlias, alias ) ) {
+                               g_hash_table_insert( hashEMailAlias, alias, email );
+                       }
                        node = g_list_next( node );
                }
 
-               // Re-parent new addresses to existing groups, where email address match.
+               /* Re-parent new addresses to existing groups, where email address match. */
                nodeGrp = listGroup;
                while( nodeGrp ) {
                        ItemGroup *group = ( ItemGroup * ) nodeGrp->data;
@@ -1356,31 +1243,45 @@ void addrbook_update_address_list( AddressBookFile *book, ItemPerson *person, GL
                        GList *nodeGrpEM;
                        GList *listRemove = NULL;
 
-                       // Process each email item linked to group
+                       /* Process each email item linked to group */
                        nodeGrpEM = groupEMail;
                        while( nodeGrpEM ) {
                                ItemEMail *emailGrp = ( ItemEMail * ) nodeGrpEM->data;
+
                                if( ADDRITEM_PARENT(emailGrp) == ADDRITEM_OBJECT(person) ) {
-                                       // Found an email address for this person
+                                       /* Found an email address for this person */
                                        ItemEMail *emailNew = NULL;
-                                       gchar *addr = g_strdup( emailGrp->address );
+                                       gchar *addr = g_strdup( emailGrp->address );
+                                       gchar *alias = emailGrp->obj.name;
                                        g_strdown( addr );
-                                       emailNew = ( ItemEMail * ) g_hash_table_lookup( hashEMail, addr );
+                                       emailNew = ( ItemEMail * )
+                                               g_hash_table_lookup( hashEMail, addr );
                                        g_free( addr );
+                                       /* If no match by e-mail, try to match by e-mail alias */
+                                       if( ! emailNew && *alias != '\0' ) {
+                                               emailNew = ( ItemEMail * )
+                                                       g_hash_table_lookup( hashEMailAlias, alias);
+                                       }
+                                       
                                        if( emailNew ) {
-                                               // Point to this entry
+                                               /* Point to this entry */
                                                nodeGrpEM->data = emailNew;
                                        }
+                                       else if(g_hash_table_size(hashEMail)==1) {
+                                               /* If the person has just one e-mail address, then 
+                                                  change e-mail address in group list */
+                                               nodeGrpEM->data = listEMail->data;
+                                       } 
                                        else {
-                                               // Mark for removal
+                                               /* Mark for removal */
                                                listRemove = g_list_append( listRemove, emailGrp );
                                        }
                                }
-                               // Move on to next email link
+                               /* Move on to next email link */
                                nodeGrpEM = g_list_next( nodeGrpEM );
                        }
 
-                       // Process all removed links in current group
+                       /* Process all removed links in current group */
                        nodeGrpEM = listRemove;
                        while( nodeGrpEM ) {
                                ItemEMail *emailGrp = nodeGrpEM->data;
@@ -1388,23 +1289,65 @@ void addrbook_update_address_list( AddressBookFile *book, ItemPerson *person, GL
                                nodeGrpEM = g_list_next( nodeGrpEM );
                        }
 
-                       // Move on to next group
+                       g_list_free( listRemove );
+
+                       /* Move on to next group */
                        nodeGrp = g_list_next( nodeGrp );
 
                }
 
-               // Clear hash table
-               g_hash_table_foreach_remove( hashEMail, ( GHRFunc ) addrbook_free_simple_hash_vis, NULL );
+               /* Clear hash table */
+               g_hash_table_foreach_remove(
+                       hashEMail, ( GHRFunc ) addrbook_free_simple_hash_vis, NULL );
                g_hash_table_destroy( hashEMail );
                hashEMail = NULL;
+               g_hash_table_destroy( hashEMailAlias );
+               hashEMailAlias = NULL;
                g_list_free( listGroup );
                listGroup = NULL;
        }
 
-       // Free up old data
-       addritem_free_list_email( oldData );
-       oldData = NULL;
-       book->dirtyFlag = TRUE;
+       /* Remove old addresses from person and cache */
+       listDelete = NULL;
+       node = person->listEMail;
+       while( node ) {
+               ItemEMail *email = node->data;
+
+               if( addrcache_person_remove_email( book->addressCache, person, email ) ) {
+                       addrcache_remove_email( book->addressCache, email );
+               }
+               listDelete = g_list_append( listDelete, email );
+               node = person->listEMail;
+       }
+
+       /* Add new address entries */
+       node = listEMail;
+       while( node ) {
+               ItemEMail *email = node->data;
+
+               if( ADDRITEM_ID(email) == NULL ) {
+                       /* Allocate an ID for new address */
+                       addrcache_id_email( book->addressCache, email );
+               }
+               addrcache_person_add_email( book->addressCache, person, email );
+               node = g_list_next( node );
+       }
+
+       addrcache_set_dirty( book->addressCache, TRUE );
+
+       /* Free up memory */
+       g_list_free( listEMail );
+       listEMail = NULL;
+
+       node = listDelete;
+       while( node ) {
+               ItemEMail *email = node->data;
+
+               addritem_free_item_email( email );
+               node = g_list_next( node );
+       }
+       g_list_free( listDelete );
+       listDelete = NULL;
 
 }
 
@@ -1422,7 +1365,7 @@ ItemPerson *addrbook_add_address_list( AddressBookFile *book, ItemFolder *folder
        ItemFolder *f = folder;
        GList *node;
 
-       g_return_if_fail( book != NULL );
+       g_return_val_if_fail( book != NULL, NULL );
 
        if( ! f ) f = book->addressCache->rootFolder;
        person = addritem_create_item_person();
@@ -1438,46 +1381,23 @@ ItemPerson *addrbook_add_address_list( AddressBookFile *book, ItemFolder *folder
                addrcache_person_add_email( book->addressCache, person, email );
                node = g_list_next( node );
        }
-       book->dirtyFlag = TRUE;
        return person;
 }
 
-/*
-* Load hash table visitor function.
-*/
-static void addrbook_load_hash_table_email_vis( gpointer key, gpointer value, gpointer data ) {
-       AddrItemObject *obj = ( AddrItemObject * ) value;
-       if( ADDRITEM_TYPE(obj) == ITEMTYPE_EMAIL ) {
-               GHashTable *table = ( GHashTable * ) data;
-               gchar *newKey = g_strdup( key );
-               ItemEMail *email = ( ItemEMail * ) obj;
-               if( ! g_hash_table_lookup( table, newKey ) ) {
-                       g_hash_table_insert( table, newKey, email );
-               }
-       }
-}
-
-/*
-* Load hash table with links to email addresses.
-*/
-static void addrbook_load_hash_table_email( AddressBookFile *book, GHashTable *table ) {
-       g_return_if_fail( book != NULL );
-       g_return_if_fail( table != NULL );
-       g_hash_table_foreach( book->addressCache->itemHash, addrbook_load_hash_table_email_vis, table );
-}
-
 /*
 * Build available email list visitor function.
 */
 static void addrbook_build_avail_email_vis( gpointer key, gpointer value, gpointer data ) {
        AddrItemObject *obj = ( AddrItemObject * ) value;
+
        if( ADDRITEM_TYPE(obj) == ITEMTYPE_PERSON ) {
                AddressBookFile *book = data;
                ItemPerson *person = ( ItemPerson * ) obj;
                GList *node = person->listEMail;
                while( node ) {
                        ItemEMail *email = node->data;
-                       gchar *newKey = g_strdup( ADDRITEM_ID(email) );
+                       /* gchar *newKey = g_strdup( ADDRITEM_ID(email) ); */
+
                        if( ! g_hash_table_lookup( book->tempHash, ADDRITEM_ID(email) ) ) {
                                book->tempList = g_list_append( book->tempList, email );
                        }
@@ -1497,9 +1417,9 @@ GList *addrbook_get_available_email_list( AddressBookFile *book, ItemGroup *grou
        GList *list = NULL;
        GHashTable *table;
 
-       g_return_if_fail( book != NULL );
+       g_return_val_if_fail( book != NULL, NULL );
 
-       // Load hash table with group email entries
+       /* Load hash table with group email entries */
        table = g_hash_table_new( g_str_hash, g_str_equal );
        if( group ) {
                list = group->listEMail;
@@ -1510,7 +1430,7 @@ GList *addrbook_get_available_email_list( AddressBookFile *book, ItemGroup *grou
                }
        }
 
-       // Build list of available email addresses which exclude those already in groups
+       /* Build list of available email addresses which exclude those already in groups */
        book->tempList = NULL;
        book->tempHash = table;
        g_hash_table_foreach( book->addressCache->itemHash, addrbook_build_avail_email_vis, book );
@@ -1518,7 +1438,7 @@ GList *addrbook_get_available_email_list( AddressBookFile *book, ItemGroup *grou
        book->tempList = NULL;
        book->tempHash = NULL;
 
-       // Clear hash table
+       /* Clear hash table */
        g_hash_table_destroy( table );
        table = NULL;
 
@@ -1540,12 +1460,13 @@ void addrbook_update_group_list( AddressBookFile *book, ItemGroup *group, GList
        g_return_if_fail( book != NULL );
        g_return_if_fail( group != NULL );
 
-       // Remember old list
+       addrcache_set_dirty( book->addressCache, TRUE );
+
+       /* Remember old list */
        oldData = group->listEMail;
        group->listEMail = listEMail;
        mgu_clear_list( oldData );
        oldData = NULL;
-       book->dirtyFlag = TRUE;
 }
 
 /*
@@ -1561,14 +1482,14 @@ void addrbook_update_group_list( AddressBookFile *book, ItemGroup *group, GList
 ItemGroup *addrbook_add_group_list( AddressBookFile *book, ItemFolder *folder, GList *listEMail ) {
        ItemGroup *group = NULL;
        ItemFolder *f = folder;
-       g_return_if_fail( book != NULL );
+
+       g_return_val_if_fail( book != NULL, NULL );
 
        if( ! f ) f = book->addressCache->rootFolder;
        group = addritem_create_item_group();
        addrcache_id_group( book->addressCache, group );
        addrcache_folder_add_group( book->addressCache, f, group );
        group->listEMail = listEMail;
-       book->dirtyFlag = TRUE;
        return group;
 }
 
@@ -1581,7 +1502,8 @@ ItemGroup *addrbook_add_group_list( AddressBookFile *book, ItemFolder *folder, G
 ItemFolder *addrbook_add_new_folder( AddressBookFile *book, ItemFolder *parent ) {
        ItemFolder *folder = NULL;
        ItemFolder *p = parent;
-       g_return_if_fail( book != NULL );
+
+       g_return_val_if_fail( book != NULL, NULL );
 
        if( ! p ) p = book->addressCache->rootFolder;
        folder = addritem_create_item_folder();
@@ -1589,7 +1511,7 @@ ItemFolder *addrbook_add_new_folder( AddressBookFile *book, ItemFolder *parent )
        if( addrcache_hash_add_folder( book->addressCache, folder ) ) {
                p->listFolder = g_list_append( p->listFolder, folder );
                ADDRITEM_PARENT(folder) = ADDRITEM_OBJECT(p);
-               book->dirtyFlag = TRUE;
+               addrcache_set_dirty( book->addressCache, TRUE );
        }
        else {
                addritem_free_item_folder( folder );
@@ -1613,25 +1535,25 @@ void addrbook_update_attrib_list( AddressBookFile *book, ItemPerson *person, GLi
        g_return_if_fail( book != NULL );
        g_return_if_fail( person != NULL );
 
-       // Remember old list
+       /* Remember old list */
        oldData = person->listAttrib;
 
-       // Attach new address list to person.
+       /* Attach new address list to person. */
        node = listAttrib;
        while( node ) {
                UserAttribute *attrib = node->data;
                if( attrib->uid == NULL ) {
-                       // Allocate an ID
+                       /* Allocate an ID */
                        addrcache_id_attribute( book->addressCache, attrib );
                }
                node = g_list_next( node );
        }
        person->listAttrib = listAttrib;
+       addrcache_set_dirty( book->addressCache, TRUE );
 
-       // Free up old data
+       /* Free up old data */
        addritem_free_list_attribute( oldData );
        oldData = NULL;
-       book->dirtyFlag = TRUE;
 
 }
 
@@ -1644,6 +1566,7 @@ void addrbook_update_attrib_list( AddressBookFile *book, ItemPerson *person, GLi
 */
 void addrbook_add_attrib_list( AddressBookFile *book, ItemPerson *person, GList *listAttrib ) {
        GList *node;
+
        g_return_if_fail( book != NULL );
        g_return_if_fail( person != NULL );
 
@@ -1656,7 +1579,7 @@ void addrbook_add_attrib_list( AddressBookFile *book, ItemPerson *person, GList
                addritem_person_add_attribute( person, attrib );
                node = g_list_next( node );
        }
-       book->dirtyFlag = TRUE;
+       addrcache_set_dirty( book->addressCache, TRUE );
 }
 
 /*
@@ -1666,6 +1589,7 @@ void addrbook_add_attrib_list( AddressBookFile *book, ItemPerson *person, GList
 */
 AddressBookFile *addrbook_item_get_bookfile( AddrItemObject *aio ) {
        AddressBookFile *book = NULL;
+
        if( aio ) {
                ItemFolder *parent = NULL;
                ItemFolder *root = NULL;
@@ -1695,9 +1619,10 @@ AddressBookFile *addrbook_item_get_bookfile( AddrItemObject *aio ) {
 */
 ItemFolder *addrbook_remove_folder( AddressBookFile *book, ItemFolder *folder ) {
        ItemFolder *f;
-       g_return_if_fail( book != NULL );
+
+       g_return_val_if_fail( book != NULL, NULL );
+
        f = addrcache_remove_folder( book->addressCache, folder );
-       if( f ) book->dirtyFlag = TRUE;
        return f;
 }
 
@@ -1708,9 +1633,10 @@ ItemFolder *addrbook_remove_folder( AddressBookFile *book, ItemFolder *folder )
 */
 ItemFolder *addrbook_remove_folder_delete( AddressBookFile *book, ItemFolder *folder ) {
        ItemFolder *f;
-       g_return_if_fail( book != NULL );
+
+       g_return_val_if_fail( book != NULL, NULL );
+
        f = addrcache_remove_folder_delete( book->addressCache, folder );
-       if( f ) book->dirtyFlag = TRUE;
        return f;
 }
 
@@ -1733,7 +1659,7 @@ GList *addrbook_get_bookfile_list( AddressBookFile *book ) {
        long int val, maxval;
        GList *fileList = NULL;
 
-       g_return_if_fail( book != NULL );
+       g_return_val_if_fail( book != NULL, NULL );
 
        if( book->path == NULL || *book->path == '\0' ) {
                book->retVal = MGU_NO_PATH;
@@ -1764,7 +1690,7 @@ GList *addrbook_get_bookfile_list( AddressBookFile *book ) {
        maxval = -1;
 
        while( ( entry = readdir( dp ) ) != NULL ) {
-               gchar **endptr = NULL;
+               gchar *endptr = NULL;
                gint i;
                gboolean flg;
 
@@ -1775,6 +1701,7 @@ GList *addrbook_get_bookfile_list( AddressBookFile *book ) {
                        if( strncmp( entry->d_name, ADDRBOOK_PREFIX, lenpre ) == 0 ) {
                                if( strncmp( (entry->d_name) + lennum, ADDRBOOK_SUFFIX, lensuf ) == 0 ) {
                                        strncpy( numbuf, (entry->d_name) + lenpre, FILE_NUMDIGITS );
+                                       numbuf[ FILE_NUMDIGITS ] = '\0';
                                        flg = TRUE;
                                        for( i = 0; i < FILE_NUMDIGITS; i++ ) {
                                                if( ! strchr( ADDRBOOK_DIGITS, numbuf[i] ) ) {
@@ -1783,7 +1710,7 @@ GList *addrbook_get_bookfile_list( AddressBookFile *book ) {
                                                }
                                        }
                                        if( flg ) {
-                                               // Get value
+                                               /* Get value */
                                                val = strtol( numbuf, &endptr, 10 );
                                                if( endptr  && val > -1 ) {
                                                        if( val > maxval ) maxval = val;
@@ -1816,8 +1743,8 @@ gchar *addrbook_gen_new_file_name( gint fileNum ) {
        if( n < 1 ) n = 1;
        nmax = -1 + (long int) pow( 10, FILE_NUMDIGITS );
        if( fileNum > nmax ) return NULL;
-       sprintf( fmt, "%%s%%0%dd%%s", FILE_NUMDIGITS );
-       sprintf( buf, fmt, ADDRBOOK_PREFIX, n, ADDRBOOK_SUFFIX );
+       g_snprintf( fmt, sizeof(fmt), "%%s%%0%dd%%s", FILE_NUMDIGITS );
+       g_snprintf( buf, sizeof(buf), fmt, ADDRBOOK_PREFIX, n, ADDRBOOK_SUFFIX );
        return g_strdup( buf );
 }
 
@@ -1826,16 +1753,6 @@ gchar *addrbook_gen_new_file_name( gint fileNum ) {
 * ***********************************************************************
 */
 
-static void addrbook_show_attribs( GList *attr ) {
-       while( attr ) {
-               gchar *name = ((XMLAttr *)attr->data)->name;
-               gchar *value = ((XMLAttr *)attr->data)->value;
-               printf( "\tn/v = %s : %s\n", name, value );
-               attr = g_list_next( attr );
-       }
-       printf( "\t---\n" );
-}
-
 /*
 * Test email address list.
 */
@@ -1850,7 +1767,7 @@ static void addrbook_chkparse_addr_list( AddressBookFile *book, XMLFile *file ){
                }
                if (file->level < prev_level) return;
                attr = xml_get_current_tag_attr(file);
-               // addrbook_show_attribs( attr );
+               /* addrbook_show_attribs( attr ); */
                if( xml_compare_tag( file, AB_ELTAG_ADDRESS ) ) {
                        addrbook_chkparse_addr_list( book, file );
                }
@@ -1865,9 +1782,9 @@ static void addrbook_chkparse_attribute( AddressBookFile *book, XMLFile *file )
        gchar *element;
 
        attr = xml_get_current_tag_attr(file);
-       // addrbook_show_attribs( attr );
+       /* addrbook_show_attribs( attr ); */
        element = xml_get_element( file );
-       // printf( "\t\tattrib value : %s\n", element );
+       /* printf( "\t\tattrib value : %s\n", element ); */
 }
 
 /*
@@ -1894,17 +1811,16 @@ static void addrbook_chkparse_attr_list( AddressBookFile *book, XMLFile *file ){
 */
 static void addrbook_chkparse_person( AddressBookFile *book, XMLFile *file ) {
        GList *attr;
-       gchar *name, *value;
 
        attr = xml_get_current_tag_attr(file);
-       // addrbook_show_attribs( attr );
-       if( xml_parse_next_tag( file ) ) {      // Consume closing tag
+       /* addrbook_show_attribs( attr ); */
+       if( xml_parse_next_tag( file ) ) {      /* Consume closing tag */
                longjmp( book->jumper, 1 );
        }
        if( xml_compare_tag( file, AB_ELTAG_ADDRESS_LIST ) ) {
                addrbook_chkparse_addr_list( book, file );
        }
-       if( xml_parse_next_tag( file ) ) {      // Consume closing tag
+       if( xml_parse_next_tag( file ) ) {      /* Consume closing tag */
                longjmp( book->jumper, 1 );
        }
        if( xml_compare_tag( file, AB_ELTAG_ATTRIBUTE_LIST ) ) {
@@ -1927,12 +1843,12 @@ static void addrbook_chkparse_member_list( AddressBookFile *book, XMLFile *file
                if (file->level < prev_level) return;
                if( xml_compare_tag( file, AB_ELTAG_MEMBER ) ) {
                        attr = xml_get_current_tag_attr(file);
-                       // addrbook_show_attribs( attr );
+                       /* addrbook_show_attribs( attr ); */
                        addrbook_chkparse_member_list( book, file );
                }
                else {
                        attr = xml_get_current_tag_attr( file );
-                       // addrbook_show_attribs( attr );
+                       /* addrbook_show_attribs( attr ); */
                }
        }
 }
@@ -1942,11 +1858,10 @@ static void addrbook_chkparse_member_list( AddressBookFile *book, XMLFile *file
 */
 static void addrbook_chkparse_group( AddressBookFile *book, XMLFile *file ) {
        GList *attr;
-       gchar *name, *value;
 
        attr = xml_get_current_tag_attr(file);
-       // addrbook_show_attribs( attr );
-       if( xml_parse_next_tag( file ) ) {      // Consume closing tag
+       /* addrbook_show_attribs( attr ); */
+       if( xml_parse_next_tag( file ) ) {      /* Consume closing tag */
                longjmp( book->jumper, 1 );
        }
        if( xml_compare_tag( file, AB_ELTAG_MEMBER_LIST ) ) {
@@ -1969,12 +1884,12 @@ static void addrbook_chkparse_folder_list( AddressBookFile *book, XMLFile *file
                if (file->level < prev_level) return;
                if( xml_compare_tag( file, AB_ELTAG_ITEM ) ) {
                        attr = xml_get_current_tag_attr(file);
-                       // addrbook_show_attribs( attr );
+                       /* addrbook_show_attribs( attr ); */
                        addrbook_chkparse_folder_list( book, file );
                }
                else {
                        attr = xml_get_current_tag_attr( file );
-                       // addrbook_show_attribs( attr );
+                       /* addrbook_show_attribs( attr ); */
                }
        }
 }
@@ -1984,11 +1899,10 @@ static void addrbook_chkparse_folder_list( AddressBookFile *book, XMLFile *file
 */
 static void addrbook_chkparse_folder( AddressBookFile *book, XMLFile *file ) {
        GList *attr;
-       gchar *name, *value;
 
        attr = xml_get_current_tag_attr(file);
-       // addrbook_show_attribs( attr );
-       if( xml_parse_next_tag( file ) ) {      // Consume closing tag
+       /* addrbook_show_attribs( attr ); */
+       if( xml_parse_next_tag( file ) ) {      /* Consume closing tag */
                longjmp( book->jumper, 1 );
        }
        if( xml_compare_tag( file, AB_ELTAG_ITEM_LIST ) ) {
@@ -2001,7 +1915,6 @@ static void addrbook_chkparse_folder( AddressBookFile *book, XMLFile *file ) {
 */
 static gboolean addrbook_chkread_tree( AddressBookFile *book, XMLFile *file ) {
        GList *attr;
-       gchar *name, *value;
        gboolean retVal;
 
        if( xml_get_dtd( file ) ) {
@@ -2016,19 +1929,16 @@ static gboolean addrbook_chkread_tree( AddressBookFile *book, XMLFile *file ) {
        }
 
        attr = xml_get_current_tag_attr(file);
-       // addrbook_show_attribs( attr );
+       /* addrbook_show_attribs( attr ); */
 
        retVal = TRUE;
        for (;;) {
                if (! file->level ) break;
-               // Get item tag
-               if( xml_parse_next_tag( file ) ) {
-                       longjmp( book->jumper, 1 );
-               }
-               // Get next tag (person, group or folder)
+               /* Get item tag */
                if( xml_parse_next_tag( file ) ) {
                        longjmp( book->jumper, 1 );
                }
+               /* Get next tag (person, group or folder) */
                if( xml_compare_tag( file, AB_ELTAG_PERSON ) ) {
                        addrbook_chkparse_person( book, file );
                }
@@ -2038,10 +1948,6 @@ static gboolean addrbook_chkread_tree( AddressBookFile *book, XMLFile *file ) {
                else if( xml_compare_tag( file, AB_ELTAG_FOLDER ) ) {
                        addrbook_chkparse_folder( book, file );
                }
-               else {
-                       // Item not recognized
-                       retVal = FALSE;
-               }
        }
        return retVal;
 }
@@ -2056,7 +1962,7 @@ gint addrbook_test_read_file( AddressBookFile *book, gchar *fileName ) {
        XMLFile *file = NULL;
        gchar *fileSpec = NULL;
 
-       g_return_if_fail( book != NULL );
+       g_return_val_if_fail( book != NULL, -1 );
 
        fileSpec = g_strconcat( book->path, G_DIR_SEPARATOR_S, fileName, NULL );
        book->retVal = MGU_OPEN_FILE;
@@ -2065,7 +1971,7 @@ gint addrbook_test_read_file( AddressBookFile *book, gchar *fileName ) {
        if( file ) {
                book->retVal = MGU_BAD_FORMAT;
                if( setjmp( book->jumper ) ) {
-                       // printf( "Caught Ya!!!\n" );
+                       /* printf( "Caught Ya!!!\n" ); */
                        xml_close_file( file );
                        return book->retVal;
                }
@@ -2084,7 +1990,7 @@ gint addrbook_test_read_file( AddressBookFile *book, gchar *fileName ) {
 * Return: List of items, or NULL if none.
 */
 GList *addrbook_get_all_persons( AddressBookFile *book ) {
-       g_return_if_fail( book != NULL );
+       g_return_val_if_fail( book != NULL, NULL );
        return addrcache_get_all_persons( book->addressCache );
 }
 
@@ -2101,14 +2007,32 @@ GList *addrbook_get_all_persons( AddressBookFile *book ) {
 ItemPerson *addrbook_add_contact( AddressBookFile *book, ItemFolder *folder, const gchar *name,
                const gchar *address, const gchar *remarks )
 {
-       ItemPerson *person = NULL;
-       g_return_if_fail( book != NULL );
-       person = addrcache_add_contact( book->addressCache, folder, name, address, remarks );
-       if( person ) book->dirtyFlag = TRUE;
-       return person;
+       g_return_val_if_fail( book != NULL, NULL );
+       return addrcache_add_contact( book->addressCache, folder, name, address, remarks );
+}
+
+/*
+ * Return file name for next address book file.
+ * Enter:  book Address book.
+ * Return: File name, or NULL if could not create. This should be g_free()
+ *         when done.
+ */
+gchar *addrbook_guess_next_file( AddressBookFile *book ) {
+       gchar *newFile = NULL;
+       GList *fileList = NULL;
+       gint fileNum = 1;
+       fileList = addrbook_get_bookfile_list( book );
+       if( fileList ) {
+               fileNum = 1 + book->maxValue;
+       }
+       newFile = addrbook_gen_new_file_name( fileNum );
+       g_list_free( fileList );
+       fileList = NULL;
+       return newFile;
 }
 
 /*
 * End of Source.
 */
 
+