New address book.
[claws.git] / src / jpilot.c
index 27d08967d4e6187dbb0c1b75a97de9a8507b3a93..9b4d4b1303e51781126d50329ae52b0a8c387e20 100644 (file)
@@ -39,6 +39,8 @@
 #include <pi-address.h>
 
 #include "mgutils.h"
+#include "addritem.h"
+#include "addrcache.h"
 #include "jpilot.h"
 
 #define JPILOT_DBHOME_DIR   ".jpilot"
 #define IND_CUSTOM_LABEL    14 // Offset to custom label names
 #define NUM_CUSTOM_LABEL    4  // Number of custom labels
 
-typedef struct _JPilotCategory JPilotCategory;
-struct _JPilotCategory {
-       AddressItem *category;
-       GList *addressList;
-       gint count;
-};
-
-/*
-* Specify name to be used.
-*/
-void jpilot_set_name( JPilotFile* pilotFile, const gchar *name ) {
-       if( pilotFile->name ) g_free( pilotFile->name );
-       if( name ) pilotFile->name = g_strdup( name );
-}
-
-/*
-* Specify file to be used.
-*/
-void jpilot_set_file( JPilotFile* pilotFile, const gchar *path ) {
-       g_return_if_fail( pilotFile != NULL );
-       mgu_refresh_cache( pilotFile->addressCache );
-       pilotFile->readMetadata = FALSE;
+// Shamelessly copied from JPilot (libplugin.h)
+typedef struct {
+       unsigned char db_name[32];
+       unsigned char flags[2];
+       unsigned char version[2];
+       unsigned char creation_time[4];
+       unsigned char modification_time[4];
+       unsigned char backup_time[4];
+       unsigned char modification_number[4];
+       unsigned char app_info_offset[4];
+       unsigned char sort_info_offset[4];
+       unsigned char type[4];/*Database ID */
+       unsigned char creator_id[4];/*Application ID */
+       unsigned char unique_id_seed[4];
+       unsigned char next_record_list_id[4];
+       unsigned char number_of_records[2];
+} RawDBHeader;
+
+// Shamelessly copied from JPilot (libplugin.h)
+typedef struct {
+       char db_name[32];
+       unsigned int flags;
+       unsigned int version;
+       time_t creation_time;
+       time_t modification_time;
+       time_t backup_time;
+       unsigned int modification_number;
+       unsigned int app_info_offset;
+       unsigned int sort_info_offset;
+       char type[5];/*Database ID */
+       char creator_id[5];/*Application ID */
+       char unique_id_seed[5];
+       unsigned int next_record_list_id;
+       unsigned int number_of_records;
+} DBHeader;
+
+// Shamelessly copied from JPilot (libplugin.h)
+typedef struct {
+       unsigned char Offset[4];  /*4 bytes offset from BOF to record */
+       unsigned char attrib;
+       unsigned char unique_ID[3];
+} record_header;
 
-       /* Copy file path */
-       if( pilotFile->path ) g_free( pilotFile->path );
-       if( path ) pilotFile->path = g_strdup( path );
-}
+// Shamelessly copied from JPilot (libplugin.h)
+typedef struct mem_rec_header_s {
+       unsigned int rec_num;
+       unsigned int offset;
+       unsigned int unique_id;
+       unsigned char attrib;
+       struct mem_rec_header_s *next;
+} mem_rec_header;
+
+// Shamelessly copied from JPilot (libplugin.h)
+#define SPENT_PC_RECORD_BIT    256
+
+typedef enum {
+       PALM_REC = 100L,
+       MODIFIED_PALM_REC = 101L,
+       DELETED_PALM_REC = 102L,
+       NEW_PC_REC = 103L,
+       DELETED_PC_REC = SPENT_PC_RECORD_BIT + 104L,
+       DELETED_DELETED_PALM_REC = SPENT_PC_RECORD_BIT + 105L
+} PCRecType;
+
+// Shamelessly copied from JPilot (libplugin.h)
+typedef struct {
+       PCRecType rt;
+       unsigned int unique_id;
+       unsigned char attrib;
+       void *buf;
+       int size;
+} buf_rec;
 
 /*
 * Create new pilot file object.
 */
 JPilotFile *jpilot_create() {
        JPilotFile *pilotFile;
-       pilotFile = g_new( JPilotFile, 1 );
+       pilotFile = g_new0( JPilotFile, 1 );
        pilotFile->name = NULL;
-       pilotFile->path = NULL;
        pilotFile->file = NULL;
-       pilotFile->addressCache = mgu_create_cache();
+       pilotFile->path = NULL;
+       pilotFile->addressCache = addrcache_create();
        pilotFile->readMetadata = FALSE;
        pilotFile->customLabels = NULL;
        pilotFile->labelInd = NULL;
        pilotFile->retVal = MGU_SUCCESS;
-       pilotFile->categoryList = NULL;
-       pilotFile->catAddrList = NULL;
+       pilotFile->accessFlag = FALSE;
        return pilotFile;
 }
 
@@ -109,37 +155,81 @@ JPilotFile *jpilot_create_path( const gchar *path ) {
        return pilotFile;
 }
 
+/*
+* Properties...
+*/
+void jpilot_set_name( JPilotFile* pilotFile, const gchar *value ) {
+       g_return_if_fail( pilotFile != NULL );
+       pilotFile->name = mgu_replace_string( pilotFile->name, value );
+}
+void jpilot_set_file( JPilotFile* pilotFile, const gchar *value ) {
+       g_return_if_fail( pilotFile != NULL );
+       addrcache_refresh( pilotFile->addressCache );
+       pilotFile->readMetadata = FALSE;
+       pilotFile->path = mgu_replace_string( pilotFile->path, value );
+}
+void jpilot_set_accessed( JPilotFile *pilotFile, const gboolean value ) {
+       g_return_if_fail( pilotFile != NULL );
+       pilotFile->accessFlag = value;
+}
+
+gint jpilot_get_status( JPilotFile *pilotFile ) {
+       g_return_if_fail( pilotFile != NULL );
+       return pilotFile->retVal;
+}
+ItemFolder *jpilot_get_root_folder( JPilotFile *pilotFile ) {
+       g_return_if_fail( pilotFile != NULL );
+       return addrcache_get_root_folder( pilotFile->addressCache );
+}
+gchar *jpilot_get_name( JPilotFile *pilotFile ) {
+       g_return_if_fail( pilotFile != NULL );
+       return pilotFile->name;
+}
+
 /*
 * Test whether file was modified since last access.
 * Return: TRUE if file was modified.
 */
 gboolean jpilot_get_modified( JPilotFile *pilotFile ) {
        g_return_if_fail( pilotFile != NULL );
-       return mgu_check_file( pilotFile->addressCache, pilotFile->path );
+       return addrcache_check_file( pilotFile->addressCache, pilotFile->path );
+}
+gboolean jpilot_get_accessed( JPilotFile *pilotFile ) {
+       g_return_if_fail( pilotFile != NULL );
+       return pilotFile->accessFlag;
+}
+
+/*
+* Test whether file was read.
+* Return: TRUE if file was read.
+*/
+gboolean jpilot_get_read_flag( JPilotFile *pilotFile ) {
+       g_return_if_fail( pilotFile != NULL );
+       return pilotFile->addressCache->dataRead;
 }
 
 /*
 * Free up custom label list.
 */
 void jpilot_clear_custom_labels( JPilotFile *pilotFile ) {
-       GSList *node;
+       GList *node;
        g_return_if_fail( pilotFile != NULL );
 
        // Release custom labels
-       mgu_free_list( pilotFile->customLabels );
+       mgu_free_dlist( pilotFile->customLabels );
        pilotFile->customLabels = NULL;
 
        // Release indexes
        node = pilotFile->labelInd;
        while( node ) {
                node->data = NULL;
-               node = g_slist_next( node );
+               node = g_list_next( node );
        }
-       g_slist_free( pilotFile->labelInd );
+       g_list_free( pilotFile->labelInd );
        pilotFile->labelInd = NULL;
 
        // Force a fresh read
-       mgu_refresh_cache( pilotFile->addressCache );
+       addrcache_refresh( pilotFile->addressCache );
 }
 
 /*
@@ -156,9 +246,9 @@ void jpilot_add_custom_label( JPilotFile *pilotFile, const gchar *labelName ) {
                        g_free( labelCopy );
                }
                else {
-                       pilotFile->customLabels = g_slist_append( pilotFile->customLabels, labelCopy );
+                       pilotFile->customLabels = g_list_append( pilotFile->customLabels, labelCopy );
                        // Force a fresh read
-                       mgu_refresh_cache( pilotFile->addressCache );
+                       addrcache_refresh( pilotFile->addressCache );
                }
        }
 }
@@ -169,12 +259,12 @@ void jpilot_add_custom_label( JPilotFile *pilotFile, const gchar *labelName ) {
 */
 GList *jpilot_get_custom_labels( JPilotFile *pilotFile ) {
        GList *retVal = NULL;
-       GSList *node;
+       GList *node;
        g_return_if_fail( pilotFile != NULL );
        node = pilotFile->customLabels;
        while( node ) {
                retVal = g_list_append( retVal, g_strdup( node->data ) );
-               node = g_slist_next( node );
+               node = g_list_next( node );
        }
        return retVal;
 }
@@ -192,13 +282,11 @@ void jpilot_free( JPilotFile *pilotFile ) {
        jpilot_clear_custom_labels( pilotFile );
 
        /* Clear cache */
-       mgu_clear_cache( pilotFile->addressCache );
-       mgu_free_cache( pilotFile->addressCache );
-       mgu_free_dlist( pilotFile->categoryList );
+       addrcache_clear( pilotFile->addressCache );
+       addrcache_free( pilotFile->addressCache );
        pilotFile->addressCache = NULL;
        pilotFile->readMetadata = FALSE;
-       pilotFile->categoryList = NULL;
-       pilotFile->catAddrList = NULL;
+       pilotFile->accessFlag = FALSE;
 
        /* Now release file object */
        g_free( pilotFile );
@@ -208,42 +296,41 @@ void jpilot_free( JPilotFile *pilotFile ) {
 * Refresh internal variables to force a file read.
 */
 void jpilot_force_refresh( JPilotFile *pilotFile ) {
-       mgu_refresh_cache( pilotFile->addressCache );
+       addrcache_refresh( pilotFile->addressCache );
 }
 
 /*
-* Print category address list for specified category.
+* Print object to specified stream.
 */
-void jpilot_print_category( JPilotCategory *jpcat, FILE *stream ) {
-       fprintf( stream, "category: %s : count: %d\n", jpcat->category->name, jpcat->count );
-       if( jpcat->addressList ) {
-               mgu_print_address_list( jpcat->addressList, stream );
+void jpilot_print_file( JPilotFile *pilotFile, FILE *stream ) {
+       GList *node;
+       g_return_if_fail( pilotFile != NULL );
+       fprintf( stream, "JPilotFile:\n" );
+       fprintf( stream, "file spec: '%s'\n", pilotFile->path );
+       fprintf( stream, " metadata: %s\n", pilotFile->readMetadata ? "yes" : "no" );
+       fprintf( stream, "  ret val: %d\n", pilotFile->retVal );
+
+       node = pilotFile->customLabels;
+       while( node ) {
+               fprintf( stream, "  c label: %s\n", node->data );
+               node = g_list_next( node );
        }
-       fprintf( stream, "=========================================\n" );
-}
 
-/*
-* Print address list for all categories.
-*/
-void jpilot_print_category_list( GList *catAddrList, FILE *stream ) {
-       GList *node;
-       JPilotCategory *jpcat;
-       if( catAddrList == NULL ) return;
-       
-       fprintf( stream, "Address list by category\n" );
-       node = catAddrList;
+       node = pilotFile->labelInd;
        while( node ) {
-               jpcat = node->data;
-               jpilot_print_category( jpcat, stream );
+               fprintf( stream, " labelind: %d\n", GPOINTER_TO_INT(node->data) );
                node = g_list_next( node );
        }
+
+       addrcache_print( pilotFile->addressCache, stream );
+       addritem_print_item_folder( pilotFile->addressCache->rootFolder, stream );
 }
 
 /*
-* Print object to specified stream.
+* Print summary of object to specified stream.
 */
-void jpilot_print_file( JPilotFile *pilotFile, FILE *stream ) {
-       GSList *node;
+void jpilot_print_short( JPilotFile *pilotFile, FILE *stream ) {
+       GList *node;
        g_return_if_fail( pilotFile != NULL );
        fprintf( stream, "JPilotFile:\n" );
        fprintf( stream, "file spec: '%s'\n", pilotFile->path );
@@ -253,27 +340,25 @@ void jpilot_print_file( JPilotFile *pilotFile, FILE *stream ) {
        node = pilotFile->customLabels;
        while( node ) {
                fprintf( stream, "  c label: %s\n", node->data );
-               node = g_slist_next( node );
+               node = g_list_next( node );
        }
 
        node = pilotFile->labelInd;
        while( node ) {
                fprintf( stream, " labelind: %d\n", GPOINTER_TO_INT(node->data) );
-               node = g_slist_next( node );
+               node = g_list_next( node );
        }
-
-       mgu_print_cache( pilotFile->addressCache, stream );
-       jpilot_print_category_list( pilotFile->catAddrList, stream );
+       addrcache_print( pilotFile->addressCache, stream );
 }
 
 // Shamelessly copied from JPilot (libplugin.c)
 static unsigned int bytes_to_bin(unsigned char *bytes, unsigned int num_bytes) {
-   unsigned int i, n;
-   n=0;
-   for (i=0;i<num_bytes;i++) {
-      n = n*256+bytes[i];
-   }
-   return n;
+unsigned int i, n;
+       n=0;
+       for (i=0;i<num_bytes;i++) {
+               n = n*256+bytes[i];
+       }
+       return n;
 }
 
 // Shamelessly copied from JPilot (utils.c)
@@ -287,29 +372,29 @@ time_t pilot_time_to_unix_time ( unsigned long raw_time ) {
 
 // Shamelessly copied from JPilot (libplugin.c)
 static int raw_header_to_header(RawDBHeader *rdbh, DBHeader *dbh) {
-   unsigned long temp;
-   strncpy(dbh->db_name, rdbh->db_name, 31);
-   dbh->db_name[31] = '\0';
-   dbh->flags = bytes_to_bin(rdbh->flags, 2);
-   dbh->version = bytes_to_bin(rdbh->version, 2);
-   temp = bytes_to_bin(rdbh->creation_time, 4);
-   dbh->creation_time = pilot_time_to_unix_time(temp);
-   temp = bytes_to_bin(rdbh->modification_time, 4);
-   dbh->modification_time = pilot_time_to_unix_time(temp);
-   temp = bytes_to_bin(rdbh->backup_time, 4);
-   dbh->backup_time = pilot_time_to_unix_time(temp);
-   dbh->modification_number = bytes_to_bin(rdbh->modification_number, 4);
-   dbh->app_info_offset = bytes_to_bin(rdbh->app_info_offset, 4);
-   dbh->sort_info_offset = bytes_to_bin(rdbh->sort_info_offset, 4);
-   strncpy(dbh->type, rdbh->type, 4);
-   dbh->type[4] = '\0';
-   strncpy(dbh->creator_id, rdbh->creator_id, 4);
-   dbh->creator_id[4] = '\0';
-   strncpy(dbh->unique_id_seed, rdbh->unique_id_seed, 4);
-   dbh->unique_id_seed[4] = '\0';
-   dbh->next_record_list_id = bytes_to_bin(rdbh->next_record_list_id, 4);
-   dbh->number_of_records = bytes_to_bin(rdbh->number_of_records, 2);
-   return 0;
+       unsigned long temp;
+       strncpy(dbh->db_name, rdbh->db_name, 31);
+       dbh->db_name[31] = '\0';
+       dbh->flags = bytes_to_bin(rdbh->flags, 2);
+       dbh->version = bytes_to_bin(rdbh->version, 2);
+       temp = bytes_to_bin(rdbh->creation_time, 4);
+       dbh->creation_time = pilot_time_to_unix_time(temp);
+       temp = bytes_to_bin(rdbh->modification_time, 4);
+       dbh->modification_time = pilot_time_to_unix_time(temp);
+       temp = bytes_to_bin(rdbh->backup_time, 4);
+       dbh->backup_time = pilot_time_to_unix_time(temp);
+       dbh->modification_number = bytes_to_bin(rdbh->modification_number, 4);
+       dbh->app_info_offset = bytes_to_bin(rdbh->app_info_offset, 4);
+       dbh->sort_info_offset = bytes_to_bin(rdbh->sort_info_offset, 4);
+       strncpy(dbh->type, rdbh->type, 4);
+       dbh->type[4] = '\0';
+       strncpy(dbh->creator_id, rdbh->creator_id, 4);
+       dbh->creator_id[4] = '\0';
+       strncpy(dbh->unique_id_seed, rdbh->unique_id_seed, 4);
+       dbh->unique_id_seed[4] = '\0';
+       dbh->next_record_list_id = bytes_to_bin(rdbh->next_record_list_id, 4);
+       dbh->number_of_records = bytes_to_bin(rdbh->number_of_records, 2);
+       return 0;
 }
 
 // Shamelessly copied from JPilot (libplugin.c)
@@ -350,7 +435,7 @@ static void free_mem_rec_header(mem_rec_header **mem_rh) {
 }
 
 // Shamelessly copied from JPilot (libplugin.c)
-int jpilot_free_db_list( GList **br_list ) {
+static int jpilot_free_db_list( GList **br_list ) {
        GList *temp_list, *first;
        buf_rec *br;
 
@@ -376,7 +461,7 @@ int jpilot_free_db_list( GList **br_list ) {
 
 // Shamelessly copied from JPilot (libplugin.c)
 // Read file size.
-int jpilot_get_info_size( FILE *in, int *size ) {
+static int jpilot_get_info_size( FILE *in, int *size ) {
        RawDBHeader rdbh;
        DBHeader dbh;
        unsigned int offset;
@@ -413,7 +498,7 @@ int jpilot_get_info_size( FILE *in, int *size ) {
 
 // Read address file into address list. Based on JPilot's
 // libplugin.c (jp_get_app_info)
-gint jpilot_get_file_info( JPilotFile *pilotFile, unsigned char **buf, int *buf_size ) {
+static gint jpilot_get_file_info( JPilotFile *pilotFile, unsigned char **buf, int *buf_size ) {
        FILE *in;
        int num;
        unsigned int rec_size;
@@ -488,7 +573,7 @@ gint jpilot_get_file_info( JPilotFile *pilotFile, unsigned char **buf, int *buf_
 #define        EMAIL_BUFSIZE      256
 // Read address file into address cache. Based on JPilot's
 // jp_read_DB_files (from libplugin.c)
-gint jpilot_read_cache( JPilotFile *pilotFile ) {
+static gint jpilot_read_file( JPilotFile *pilotFile ) {
        FILE *in;
        char *buf;
        int num_records, recs_returned, i, num, r;
@@ -510,10 +595,12 @@ gint jpilot_read_cache( JPilotFile *pilotFile ) {
        gchar fullName[ FULLNAME_BUFSIZE ];
        gchar bufEMail[ EMAIL_BUFSIZE ];
        gchar* extID;
-       AddressItem *addrItem = NULL;
+       ItemPerson *person;
+       ItemEMail *email;
        int *indPhoneLbl;
        char *labelEntry;
-       GSList *node;
+       GList *node;
+       ItemFolder *folderInd[ JPILOT_NUM_CATEG ];
 
        retVal = MGU_SUCCESS;
        mem_rh = last_mem_rh = NULL;
@@ -613,6 +700,17 @@ gint jpilot_read_cache( JPilotFile *pilotFile ) {
                }
                fseek(in, next_offset, SEEK_SET);
 
+               // Build array of pointers to categories;
+               i = 0;
+               node = addrcache_get_list_folder( pilotFile->addressCache );
+               while( node ) {
+                       if( i < JPILOT_NUM_CATEG ) {
+                               folderInd[i] = node->data;
+                       }
+                       node = g_list_next( node );
+                       i++;
+               }
+
                // Now go load all records              
                while(!feof(in)) {
                        struct CategoryAppInfo *cat = & ai->category;
@@ -662,14 +760,27 @@ gint jpilot_read_cache( JPilotFile *pilotFile ) {
                                }
                                g_strchug( fullName );
                                g_strchomp( fullName );
+
+                               person = addritem_create_item_person();
+                               addritem_person_set_common_name( person, fullName );
+                               addritem_person_set_first_name( person, addrEnt[ IND_LABEL_FIRSTNAME ] );
+                               addritem_person_set_last_name( person, addrEnt[ IND_LABEL_LASTNAME ] );
+                               addrcache_id_person( pilotFile->addressCache, person );
+
                                extID = g_strdup_printf( "%d", unique_id );
+                               addritem_person_set_external_id( person, extID );
+                               g_free( extID );
+                               extID = NULL;
 
                                // Add entry for each email address listed under phone labels.
                                indPhoneLbl = addr.phoneLabel;
                                for( k = 0; k < JPILOT_NUM_ADDR_PHONE; k++ ) {
                                        int ind;
                                        ind = indPhoneLbl[k];
-                                       // fprintf( stdout, "%d : %d : %20s : %s\n", k, ind, ai->phoneLabels[ind], addrEnt[3+k] );
+                                       /*
+                                       fprintf( stdout, "%d : %d : %20s : %s\n", k, ind,
+                                               ai->phoneLabels[ind], addrEnt[3+k] );
+                                       */
                                        if( indPhoneLbl[k] == IND_PHONE_EMAIL ) {
                                                labelEntry = addrEnt[ OFFSET_PHONE_LABEL + k ];
                                                if( labelEntry ) {
@@ -677,13 +788,11 @@ gint jpilot_read_cache( JPilotFile *pilotFile ) {
                                                        g_strchug( bufEMail );
                                                        g_strchomp( bufEMail );
 
-                                                       addrItem = mgu_create_address();
-                                                       addrItem->name = g_strdup( fullName );
-                                                       addrItem->address = g_strdup( bufEMail );
-                                                       addrItem->remarks = g_strdup( "" );
-                                                       addrItem->externalID = g_strdup( extID );
-                                                       addrItem->categoryID = cat_id;
-                                                       mgu_add_cache( pilotFile->addressCache, addrItem );
+                                                       email = addritem_create_item_email();
+                                                       addritem_email_set_address( email, bufEMail );
+                                                       addrcache_id_email( pilotFile->addressCache, email );
+                                                       addrcache_person_add_email(
+                                                               pilotFile->addressCache, person, email );
                                                }
                                        }
                                }
@@ -694,29 +803,45 @@ gint jpilot_read_cache( JPilotFile *pilotFile ) {
                                        gint ind;
                                        ind = GPOINTER_TO_INT( node->data );
                                        if( ind > -1 ) {
-                                               // fprintf( stdout, "%d : %20s : %s\n", ind, ai->labels[ind], addrEnt[ind] );
+                                               /*
+                                               fprintf( stdout, "%d : %20s : %s\n", ind, ai->labels[ind],
+                                                       addrEnt[ind] );
+                                               */
                                                labelEntry = addrEnt[ind];
                                                if( labelEntry ) {
                                                        strcpy( bufEMail, labelEntry );
                                                        g_strchug( bufEMail );
                                                        g_strchomp( bufEMail );
 
-                                                       addrItem = mgu_create_address();
-                                                       addrItem->name = g_strdup( fullName );
-                                                       addrItem->address = g_strdup( bufEMail );
-                                                       addrItem->remarks = g_strdup( ai->labels[ind] );
-                                                       addrItem->externalID = g_strdup( extID );
-                                                       addrItem->categoryID = cat_id;
-                                                       mgu_add_cache( pilotFile->addressCache, addrItem );
+                                                       email = addritem_create_item_email();
+                                                       addritem_email_set_address( email, bufEMail );
+                                                       addritem_email_set_remarks( email, ai->labels[ind] );
+                                                       addrcache_id_email( pilotFile->addressCache, email );
+                                                       addrcache_person_add_email(
+                                                               pilotFile->addressCache, person, email );
                                                }
 
                                        }
 
-                                       node = g_slist_next( node );
+                                       node = g_list_next( node );
+                               }
+
+                               if( person->listEMail ) {
+                                       if( cat_id > -1 && cat_id < JPILOT_NUM_CATEG ) {
+                                               // Add to specified category
+                                               addrcache_folder_add_person(
+                                                       pilotFile->addressCache, folderInd[cat_id], person );
+                                       }
+                                       else {
+                                               // Add to root folder
+                                               addrcache_add_person( pilotFile->addressCache, person );
+                                       }
+                               }
+                               else {
+                                       addritem_free_item_person( person );
+                                       person = NULL;
                                }
 
-                               g_free( extID );
-                               extID = NULL;
                        }
                        recs_returned++;
                }
@@ -729,7 +854,7 @@ gint jpilot_read_cache( JPilotFile *pilotFile ) {
 /*
 * Read metadata from file.
 */
-gint jpilot_read_metadata( JPilotFile *pilotFile ) {
+static gint jpilot_read_metadata( JPilotFile *pilotFile ) {
        gint retVal;
        unsigned int rec_size;
        unsigned char *buf;
@@ -738,6 +863,7 @@ gint jpilot_read_metadata( JPilotFile *pilotFile ) {
        g_return_if_fail( pilotFile != NULL );
 
        pilotFile->readMetadata = FALSE;
+       addrcache_clear( pilotFile->addressCache );
 
        // Read file info
        retVal = jpilot_get_file_info( pilotFile, &buf, &rec_size);
@@ -765,10 +891,10 @@ gint jpilot_read_metadata( JPilotFile *pilotFile ) {
 * Setup labels and indexes from metadata.
 * Return: TRUE is setup successfully.
 */
-gboolean jpilot_setup_labels( JPilotFile *pilotFile ) {
+static gboolean jpilot_setup_labels( JPilotFile *pilotFile ) {
        gboolean retVal = FALSE;
        struct AddressAppInfo *ai;
-       GSList *node;
+       GList *node;
 
        g_return_if_fail( pilotFile != NULL );
 
@@ -776,7 +902,7 @@ gboolean jpilot_setup_labels( JPilotFile *pilotFile ) {
        node = pilotFile->labelInd;
        while( node ) {
                node->data = NULL;
-               node = g_slist_next( node );
+               node = g_list_next( node );
        }
        pilotFile->labelInd = NULL;
 
@@ -784,20 +910,18 @@ gboolean jpilot_setup_labels( JPilotFile *pilotFile ) {
                ai = & pilotFile->addrInfo;
                node = pilotFile->customLabels;
                while( node ) {
-                       gchar *lbl, *labelName;
-                       int i;
-                       gint ind;
-                       ind = -1;
-                       lbl = node->data;
+                       gchar *lbl = node->data;
+                       gint ind = -1;
+                       gint i;
                        for( i = 0; i < JPILOT_NUM_LABELS; i++ ) {
-                               labelName = ai->labels[i];
+                               gchar *labelName = ai->labels[i];
                                if( g_strcasecmp( labelName, lbl ) == 0 ) {
                                        ind = i;
                                        break;
                                }
                        }
-                       pilotFile->labelInd = g_slist_append( pilotFile->labelInd, GINT_TO_POINTER(ind) );
-                       node = g_slist_next( node );
+                       pilotFile->labelInd = g_list_append( pilotFile->labelInd, GINT_TO_POINTER(ind) );
+                       node = g_list_next( node );
                }
                retVal = TRUE;
        }
@@ -807,7 +931,7 @@ gboolean jpilot_setup_labels( JPilotFile *pilotFile ) {
 /*
 * Load list with character strings of label names.
 */
-GSList *jpilot_load_label( JPilotFile *pilotFile, GSList *labelList ) {
+GList *jpilot_load_label( JPilotFile *pilotFile, GList *labelList ) {
        int i;
        g_return_if_fail( pilotFile != NULL );
        if( pilotFile->readMetadata ) {
@@ -815,10 +939,10 @@ GSList *jpilot_load_label( JPilotFile *pilotFile, GSList *labelList ) {
                for( i = 0; i < JPILOT_NUM_LABELS; i++ ) {
                        gchar *labelName = ai->labels[i];
                        if( labelName ) {
-                               labelList = g_slist_append( labelList, g_strdup( labelName ) );
+                               labelList = g_list_append( labelList, g_strdup( labelName ) );
                        }
                        else {
-                               labelList = g_slist_append( labelList, g_strdup( "" ) );
+                               labelList = g_list_append( labelList, g_strdup( "" ) );
                        }
                }
        }
@@ -849,7 +973,7 @@ gchar *jpilot_get_category_name( JPilotFile *pilotFile, gint catID ) {
 /*
 * Load list with character strings of phone label names.
 */
-GSList *jpilot_load_phone_label( JPilotFile *pilotFile, GSList *labelList ) {
+GList *jpilot_load_phone_label( JPilotFile *pilotFile, GList *labelList ) {
        int i;
        g_return_if_fail( pilotFile != NULL );
        if( pilotFile->readMetadata ) {
@@ -857,10 +981,10 @@ GSList *jpilot_load_phone_label( JPilotFile *pilotFile, GSList *labelList ) {
                for( i = 0; i < JPILOT_NUM_PHONELABELS; i++ ) {
                        gchar   *labelName = ai->phoneLabels[i];
                        if( labelName ) {
-                               labelList = g_slist_append( labelList, g_strdup( labelName ) );
+                               labelList = g_list_append( labelList, g_strdup( labelName ) );
                        }
                        else {
-                               labelList = g_slist_append( labelList, g_strdup( "" ) );
+                               labelList = g_list_append( labelList, g_strdup( "" ) );
                        }
                }
        }
@@ -894,8 +1018,8 @@ GList *jpilot_load_custom_label( JPilotFile *pilotFile, GList *labelList ) {
 /*
 * Load list with character strings of category names.
 */
-GSList *jpilot_get_category_list( JPilotFile *pilotFile ) {
-       GSList *catList = NULL;
+GList *jpilot_get_category_list( JPilotFile *pilotFile ) {
+       GList *catList = NULL;
        int i;
        g_return_if_fail( pilotFile != NULL );
        if( pilotFile->readMetadata ) {
@@ -904,10 +1028,10 @@ GSList *jpilot_get_category_list( JPilotFile *pilotFile ) {
                for( i = 0; i < JPILOT_NUM_CATEG; i++ ) {
                        gchar *catName = cat->name[i];
                        if( catName ) {
-                               catList = g_slist_append( catList, g_strdup( catName ) );
+                               catList = g_list_append( catList, g_strdup( catName ) );
                        }
                        else {
-                               catList = g_slist_append( catList, g_strdup( "" ) );
+                               catList = g_list_append( catList, g_strdup( "" ) );
                        }
                }
        }
@@ -915,131 +1039,56 @@ GSList *jpilot_get_category_list( JPilotFile *pilotFile ) {
 }
 
 /*
-* Free category address list.
+* Build folder for each category.
 */
-void jpilot_free_address_list( JPilotFile *pilotFile ) {
-       GList *addrList;
-       g_return_if_fail( pilotFile != NULL );
-
-       addrList = pilotFile->catAddrList;
-       while( addrList ) {
-               JPilotCategory *jpcat = addrList->data;
-               mgu_free_address( jpcat->category );
-               mgu_free_address_list( jpcat->addressList );
-               jpcat->category = NULL;
-               jpcat->addressList = NULL;
-               jpcat->count = 0;
-               g_free( jpcat );
-               jpcat = NULL;
-               addrList->data = NULL;
-               addrList = g_list_next( addrList );
-       }
-       pilotFile->catAddrList = NULL;
-}
-
-/*
-* Move data from address list and group into category address list.
-*/
-void jpilot_load_category_items( JPilotFile *pilotFile ) {
-       JPilotCategory *jpcat[ 1 + JPILOT_NUM_CATEG ];
+static void jpilot_build_category_list( JPilotFile *pilotFile ) {
        struct AddressAppInfo *ai = & pilotFile->addrInfo;
        struct CategoryAppInfo *cat = & ai->category;
-       AddressItem *itemCat;
-       GList *addrList;
-       int i;
-
-       // Create array for data by category
-       for( i = 0; i < 1 + JPILOT_NUM_CATEG; i++ ) {
-               itemCat = mgu_create_address_item( ADDR_CATEGORY );
-               itemCat->categoryID = i;
-               jpcat[i] = g_new( JPilotCategory, 1 );
-               jpcat[i]->category = itemCat;
-               jpcat[i]->addressList = NULL;
-               jpcat[i]->count = 0;
-               if( i < JPILOT_NUM_CATEG ) {
-                       gchar *catName = cat->name[i];
-                       if( catName && strlen( catName ) > 0 ) {
-                               itemCat->name = g_strdup( catName );
-                       }
-               }
+       gint i;
+       for( i = 0; i < JPILOT_NUM_CATEG; i++ ) {
+               ItemFolder *folder = addritem_create_item_folder();
+               addritem_folder_set_name( folder, cat->name[i] );
+               addrcache_id_folder( pilotFile->addressCache, folder );
+               addrcache_add_folder( pilotFile->addressCache, folder );
        }
-
-       // Process address list moving data to category
-       addrList = pilotFile->addressCache->addressList;
-       while( addrList ) {
-               GList *addrLink;
-               AddressItem *item;
-               item = addrList->data;
-               i = item->categoryID;
-               if( i < 0 || i > JPILOT_NUM_CATEG ) i = JPILOT_NUM_CATEG; // Position at end of array
-
-               // Add item to category list
-               addrLink = jpcat[i]->addressList;
-               addrLink = g_list_append( addrLink, item );
-               jpcat[i]->addressList = addrLink;
-               jpcat[i]->count++;
-
-               // Clear from cache list
-               addrList->data = NULL;
-               addrList = g_list_next( addrList );
-       }
-
-       // Remove entries from address cache
-       mgu_clear_cache_null( pilotFile->addressCache );
-
-/*
-       printf( "dump jpcArray[]...\n" );
-       for( i = 0; i < 1 + JPILOT_NUM_CATEG; i++ ) {
-               jpilot_print_category( jpcat[i], stdout );
-       }
-*/
-
-       // Free up existing category address list
-       jpilot_free_address_list( pilotFile );
-
-       // Move categories from array to category address list
-       addrList = NULL;
-       for( i = 0; i < 1 + JPILOT_NUM_CATEG; i++ ) {
-               if( jpcat[i]->count > 0 ) {
-                       itemCat = jpcat[i]->category;
-                       if( ! itemCat->name ) {
-                               // Create a category name
-                               itemCat->name = g_strdup_printf( "? %d", itemCat->categoryID );
-                       }
-               }
-               addrList = g_list_append( addrList, jpcat[i] );
-               jpcat[i] = NULL;
-       }
-       pilotFile->catAddrList = addrList;
-
-       // jpilot_print_category_list( pilotFile->catAddrList, stdout );
-
 }
 
 /*
-* Build linked list of address items for each category.
+* Remove empty folders (categories).
 */
-GList *jpilot_build_category_list( JPilotFile *pilotFile ) {
-       GList *catList = NULL;
+static void jpilot_remove_empty( JPilotFile *pilotFile ) {
+       GList *listFolder;
+       GList *remList;
        GList *node;
-       node = pilotFile->catAddrList;
+       gint i = 0;
+
+       listFolder = addrcache_get_list_folder( pilotFile->addressCache );
+       node = listFolder;
+       remList = NULL;
        while( node ) {
-               JPilotCategory *jpcat = node->data;
-               AddressItem *catItem = jpcat->category;
-
-               catItem = jpcat->category;
-               if( jpcat->count > 0 || catItem->name ) {
-                       AddressItem *itemNew = mgu_copy_address_item( catItem );
-                       if( itemNew ) {
-                               catList = g_list_append( catList, itemNew );
+               ItemFolder *folder = node->data;
+               if( ADDRITEM_NAME(folder) == NULL || *ADDRITEM_NAME(folder) == '\0' ) {
+                       if( folder->listPerson ) {
+                               // Give name to folder
+                               gchar name[20];
+                               sprintf( name, "? %d", i );
+                               addritem_folder_set_name( folder, name );
+                       }
+                       else {
+                               // Mark for removal
+                               remList = g_list_append( remList, folder );
                        }
                }
                node = g_list_next( node );
+               i++;
        }
-       mgu_free_address_list( pilotFile->categoryList );
-       pilotFile->categoryList = catList;
-       // mgu_print_address_list( catList, stdout );
-       return catList;
+       node = remList;
+       while( node ) {
+               ItemFolder *folder = node->data;
+               addrcache_remove_folder( pilotFile->addressCache, folder );
+               node = g_list_next( node );
+       }
+       g_list_free( remList );
 }
 
 // ============================================================================================
@@ -1051,58 +1100,52 @@ GList *jpilot_build_category_list( JPilotFile *pilotFile ) {
 gint jpilot_read_data( JPilotFile *pilotFile ) {
        g_return_if_fail( pilotFile != NULL );
        pilotFile->retVal = MGU_SUCCESS;
-       if( mgu_check_file( pilotFile->addressCache, pilotFile->path ) ) {
-               mgu_clear_cache( pilotFile->addressCache );
+       pilotFile->accessFlag = FALSE;
+       if( addrcache_check_file( pilotFile->addressCache, pilotFile->path ) ) {
+               addrcache_clear( pilotFile->addressCache );
                jpilot_read_metadata( pilotFile );
                if( pilotFile->retVal == MGU_SUCCESS ) {
                        jpilot_setup_labels( pilotFile );
-                       pilotFile->retVal = jpilot_read_cache( pilotFile );
+                       jpilot_build_category_list( pilotFile );
+                       pilotFile->retVal = jpilot_read_file( pilotFile );
                        if( pilotFile->retVal == MGU_SUCCESS ) {
-                               mgu_mark_cache( pilotFile->addressCache, pilotFile->path );
+                               jpilot_remove_empty( pilotFile );
+                               addrcache_mark_file( pilotFile->addressCache, pilotFile->path );
                                pilotFile->addressCache->modified = FALSE;
                                pilotFile->addressCache->dataRead = TRUE;
                        }
-                       jpilot_load_category_items( pilotFile );
-                       jpilot_build_category_list( pilotFile );
                }
        }
        return pilotFile->retVal;
 }
 
 /*
-* Return linked list of address items for loaded category names.
+* Return link list of persons.
 */
-GList *jpilot_get_category_items( JPilotFile *pilotFile ) {
+GList *jpilot_get_list_person( JPilotFile *pilotFile ) {
        g_return_if_fail( pilotFile != NULL );
-       return pilotFile->categoryList;
+       return addrcache_get_list_person( pilotFile->addressCache );
 }
 
 /*
-* Return address list for specified category.
+* Return link list of folders. This is always NULL since there are
+* no folders in GnomeCard.
+* Return: NULL.
 */
-GList *jpilot_get_address_list_cat( JPilotFile *pilotFile, const gint catID ) {
-       GList *addrList = NULL, *node;
+GList *jpilot_get_list_folder( JPilotFile *pilotFile ) {
        g_return_if_fail( pilotFile != NULL );
-
-       node = pilotFile->catAddrList;
-       while( node ) {
-               JPilotCategory *jpcat = node->data;
-               AddressItem *catItem = jpcat->category;
-               if( catItem->categoryID == catID ) {
-                       addrList = jpcat->addressList;
-                       break;
-               }
-               node = g_list_next( node );
-       }
-       return addrList;
+       return addrcache_get_list_folder( pilotFile->addressCache );
 }
 
 /*
-* Return linked list of address items.
+* Return link list of all persons. Note that the list contains references
+* to items. Do *NOT* attempt to use the addrbook_free_xxx() functions...
+* this will destroy the addressbook data!
+* Return: List of items, or NULL if none.
 */
-GList *jpilot_get_address_list( JPilotFile *pilotFile ) {
+GList *jpilot_get_all_persons( JPilotFile *pilotFile ) {
        g_return_if_fail( pilotFile != NULL );
-       return pilotFile->addressCache->addressList;
+       return addrcache_get_all_persons( pilotFile->addressCache );
 }
 
 /*
@@ -1176,7 +1219,7 @@ gchar *jpilot_find_pilotdb( void ) {
        strcat( str, G_DIR_SEPARATOR_S );
        strcat( str, JPILOT_DBHOME_FILE );
 
-       // Attempt to open\e
+       // Attempt to open
        if( ( fp = fopen( str, "r" ) ) != NULL ) {
                fclose( fp );
        }
@@ -1212,7 +1255,7 @@ gint jpilot_test_read_file( const gchar *fileSpec ) {
 */
 gboolean jpilot_test_custom_label( JPilotFile *pilotFile, const gchar *labelName ) {
        gboolean retVal;
-       GSList *node;
+       GList *node;
        g_return_if_fail( pilotFile != NULL );
 
        retVal = FALSE;
@@ -1223,7 +1266,7 @@ gboolean jpilot_test_custom_label( JPilotFile *pilotFile, const gchar *labelName
                                retVal = TRUE;
                                break;
                        }
-                       node = g_slist_next( node );
+                       node = g_list_next( node );
                }
        }
        return retVal;
@@ -1262,3 +1305,5 @@ gboolean jpilot_test_pilot_lib() {
 /*
 * End of Source.
 */
+
+