]> git.deb.at Git - pkg/abook.git/blobdiff - filter.c
Fetch real Portuguese debconf translation
[pkg/abook.git] / filter.c
index 9f62171f0f93e4ad122e63494fea928fcb4b7af1..f13d0995943dbbba872a5c70b5f924c302c28bb1 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -1,6 +1,6 @@
 
 /*
- * $Id: filter.c,v 1.31 2004/06/30 19:48:28 jheinonen Exp $
+ * $Id: filter.c,v 1.55 2006/09/06 02:46:44 cduval Exp $
  *
  * by JH <jheinonen@users.sourceforge.net>
  *
 #include "abook.h"
 #include "database.h"
 #include "edit.h"
+#include "gettext.h"
 #include "list.h"
 #include "misc.h"
 #include "options.h"
+#include "ui.h"
+#include "xmalloc.h"
 #include <assert.h>
 
-extern int items;
-extern list_item *database;
-extern struct abook_field abook_fields[];
+extern abook_field_list *fields_list;
+extern int fields_count;
 
 /*
  * function declarations
@@ -41,6 +43,7 @@ static int    mutt_parse_file(FILE *in);
 static int     pine_parse_file(FILE *in);
 static int     csv_parse_file(FILE *in);
 static int     allcsv_parse_file(FILE *in);
+static int     palmcsv_parse_file(FILE *in);
 
 /*
  * export filter prototypes
@@ -57,34 +60,39 @@ static int  mutt_alias_export(FILE *out, struct db_enumerator e);
 static int     elm_alias_export(FILE *out, struct db_enumerator e);
 static int     text_export_database(FILE *out, struct db_enumerator e);
 static int     spruce_export_database(FILE *out, struct db_enumerator e);
+static int     wl_export_database(FILE *out, struct db_enumerator e);
+static int     bsdcal_export_database(FILE *out, struct db_enumerator e);
 
 /*
  * end of function declarations
  */
 
 struct abook_input_filter i_filters[] = {
-       { "abook", "abook native format", parse_database },
-       { "ldif", "ldif / Netscape addressbook", ldif_parse_file },
-       { "mutt", "mutt alias", mutt_parse_file },
-       { "pine", "pine addressbook", pine_parse_file },
-       { "csv", "comma separated values", csv_parse_file },
-       { "allcsv", "comma separated all values", allcsv_parse_file },
+       { "abook", N_("abook native format"), parse_database },
+       { "ldif", N_("ldif / Netscape addressbook"), ldif_parse_file },
+       { "mutt", N_("mutt alias"), mutt_parse_file },
+       { "pine", N_("pine addressbook"), pine_parse_file },
+       { "csv", N_("comma separated values"), csv_parse_file },
+       { "allcsv", N_("comma separated values (all fields)"), allcsv_parse_file },
+       { "palmcsv", N_("Palm comma separated values"), palmcsv_parse_file },
        { "\0", NULL, NULL }
 };
 
 struct abook_output_filter e_filters[] = {
-       { "abook", "abook native format", write_database },
-       { "ldif", "ldif / Netscape addressbook (.4ld)", ldif_export_database },
-       { "mutt", "mutt alias", mutt_alias_export },
-       { "html", "html document", html_export_database },
-       { "pine", "pine addressbook", pine_export_database },
-       { "gcrd", "GnomeCard (VCard) addressbook", gcrd_export_database },
-       { "csv", "comma separated values", csv_export_database },
-       { "allcsv", "comma separated all values", allcsv_export_database },
-       { "palmcsv", "Palm comma separated values", palm_export_database},
-       { "elm", "elm alias", elm_alias_export },
-       { "text", "plain text", text_export_database },
-       { "spruce", "Spruce address book", spruce_export_database },
+       { "abook", N_("abook native format"), write_database },
+       { "ldif", N_("ldif / Netscape addressbook (.4ld)"), ldif_export_database },
+       { "mutt", N_("mutt alias"), mutt_alias_export },
+       { "html", N_("html document"), html_export_database },
+       { "pine", N_("pine addressbook"), pine_export_database },
+       { "gcrd", N_("GnomeCard (VCard) addressbook"), gcrd_export_database },
+       { "csv", N_("comma separated values"), csv_export_database },
+       { "allcsv", N_("comma separated values (all fields)"), allcsv_export_database },
+       { "palmcsv", N_("Palm comma separated values"), palm_export_database},
+       { "elm", N_("elm alias"), elm_alias_export },
+       { "text", N_("plain text"), text_export_database },
+       { "wl", N_("Wanderlust address book"), wl_export_database },
+       { "spruce", N_("Spruce address book"), spruce_export_database },
+       { "bsdcal", N_("BSD calendar"), bsdcal_export_database },
        { "\0", NULL, NULL }
 };
 
@@ -96,18 +104,18 @@ void
 print_filters()
 {
        int i;
-       
-       puts("input:");
+
+       puts(_("input:"));
        for(i=0; *i_filters[i].filtname ; i++)
                printf("\t%s\t%s\n", i_filters[i].filtname,
-                       i_filters[i].desc);
+                       gettext(i_filters[i].desc));
 
        putchar('\n');
-       
-       puts("output:");
+
+       puts(_("output:"));
        for(i=0; *e_filters[i].filtname ; i++)
                printf("\t%s\t%s\n", e_filters[i].filtname,
-                       e_filters[i].desc);
+                       gettext(e_filters[i].desc));
 
        putchar('\n');
 }
@@ -144,13 +152,13 @@ get_real_name()
 
        pwent = getpwnam(username);
 
-       if((tmp = strdup(pwent->pw_gecos)) == NULL)
-               return strdup(username);
+       if((tmp = xstrdup(pwent->pw_gecos)) == NULL)
+               return xstrdup(username);
 
        rtn = sscanf(pwent->pw_gecos, "%[^,]", tmp);
        if (rtn == EOF || rtn == 0) {
                free(tmp);
-               return strdup(username);
+               return xstrdup(username);
        } else
                return tmp;
 }
@@ -158,28 +166,28 @@ get_real_name()
 /*
  * import
  */
-       
+
 static int             i_read_file(char *filename, int (*func) (FILE *in));
 
 static void
 import_screen()
 {
        int i;
-       
+
        clear();
 
        refresh_statusline();
-       headerline("import database");
+       headerline(_("import database"));
+
+       mvaddstr(3, 1, _("please select a filter"));
 
-       mvaddstr(3, 1, "please select a filter");
-       
 
        for(i=0; *i_filters[i].filtname ; i++)
                mvprintw(5 + i, 6, "%c -\t%s\t%s\n", 'a' + i,
                        i_filters[i].filtname,
-                       i_filters[i].desc);
+                       gettext(i_filters[i].desc));
 
-       mvprintw(6 + i, 6, "x -\tcancel");
+       mvprintw(6 + i, 6, _("x -\tcancel"));
 }
 
 int
@@ -187,30 +195,30 @@ import_database()
 {
        int filter;
        char *filename;
-       int tmp = items;
+       int tmp = db_n_items();
 
        import_screen();
-       
+
        filter = getch() - 'a';
        if(filter == 'x' - 'a' ||
                filter >= number_of_input_filters() || filter < 0) {
                refresh_screen();
                return 1;
        }
-       
+
        mvaddstr(5+filter, 2, "->");
-       
-       filename = ask_filename("Filename: ");
-       if( !filename ) {
+
+       filename = ask_filename(_("Filename: "));
+       if(!filename) {
                refresh_screen();
                return 2;
        }
-               
-       if(  i_read_file(filename, i_filters[filter].func ) )
-               statusline_msg("Error occured while opening the file");
-       else if( tmp == items )
-               statusline_msg("Hmm.., file seems not to be a valid file");
-       
+
+       if(i_read_file(filename, i_filters[filter].func ))
+               statusline_msg(_("Error occured while opening the file"));
+       else if(tmp == db_n_items())
+               statusline_msg(_("File does not seem to be a valid addressbook"));
+
        refresh_screen();
        free(filename);
 
@@ -225,48 +233,48 @@ i_read_file(char *filename, int (*func) (FILE *in))
        FILE *in;
        int ret = 0;
 
-       if( ( in = abook_fopen( filename, "r" ) ) == NULL )
+       if( (in = abook_fopen( filename, "r" )) == NULL )
                return 1;
 
        ret = (*func) (in);
 
        fclose(in);
 
-       return ret;     
+       return ret;
 }
 
 int
 import_file(char filtname[FILTNAME_LEN], char *filename)
 {
        int i;
-       int tmp = items;
+       int tmp = db_n_items();
        int ret = 0;
 
        for(i=0;; i++) {
-               if( ! strncasecmp(i_filters[i].filtname, filtname,
+               if(! strncasecmp(i_filters[i].filtname, filtname,
                                        FILTNAME_LEN) )
                        break;
-               if( ! *i_filters[i].filtname ) {
+               if(! *i_filters[i].filtname) {
                        i = -1;
                        break;
                }
        }
 
-       if( i<0 )
+       if(i < 0)
                return -1;
 
-       if( !strcmp(filename, "-") ) {
+       if(!strcmp(filename, "-")) {
                struct stat s;
-               if( (fstat(fileno(stdin), &s)) == -1 || S_ISDIR(s.st_mode))
+               if((fstat(fileno(stdin), &s)) == -1 || S_ISDIR(s.st_mode))
                        ret = 1;
                else
                        ret = (*i_filters[i].func) (stdin);
        } else
                ret =  i_read_file(filename, i_filters[i].func);
-       
-       if( tmp == items )
+
+       if(tmp == db_n_items())
                ret = 1;
-       
+
        return ret;
 }
 
@@ -274,29 +282,29 @@ import_file(char filtname[FILTNAME_LEN], char *filename)
  * export
  */
 
-static int             e_write_file(char *filename,
+static int e_write_file(char *filename,
                int (*func) (FILE *in, struct db_enumerator e), int mode);
 
 static void
 export_screen()
 {
        int i;
-       
+
        clear();
 
 
        refresh_statusline();
-       headerline("export database");
+       headerline(_("export database"));
 
-       mvaddstr(3, 1, "please select a filter");
-       
+       mvaddstr(3, 1, _("please select a filter"));
 
-       for(i=0; *e_filters[i].filtname ; i++)
+
+       for(i = 0; *e_filters[i].filtname ; i++)
                mvprintw(5 + i, 6, "%c -\t%s\t%s\n", 'a' + i,
                        e_filters[i].filtname,
-                       e_filters[i].desc);
+                       gettext(e_filters[i].desc));
 
-       mvprintw(6 + i, 6, "x -\tcancel");
+       mvprintw(6 + i, 6, _("x -\tcancel"));
 }
 
 int
@@ -307,38 +315,42 @@ export_database()
        char *filename;
 
        export_screen();
-       
+
        filter = getch() - 'a';
        if(filter == 'x' - 'a' ||
                filter >= number_of_output_filters() || filter < 0) {
                refresh_screen();
                return 1;
        }
-       
-       mvaddstr(5+filter, 2, "->");
 
-       if( selected_items() ) {
-               statusline_addstr("Export All/Selected/Cancel (A/s/c)");
-               switch( tolower(getch()) ) {
-                       case 's':
+       mvaddstr(5 + filter, 2, "->");
+
+       if(selected_items()) {
+               switch(statusline_askchoice(
+                       _("Export <a>ll, export <s>elected, or <c>ancel?"),
+                       S_("keybindings:all/selected/cancel|asc"), 3)) {
+                       case 1:
+                               break;
+                       case 2:
                                enum_mode = ENUM_SELECTED;
                                break;
-                       case 'c':
-                               clear_statusline();
+                       case 0:
+                       case 3:
+                               refresh_screen();
                                return 1;
                }
                clear_statusline();
        }
-       
-       filename = ask_filename("Filename: ");
-       if( !filename ) {
+
+       filename = ask_filename(_("Filename: "));
+       if(!filename) {
                refresh_screen();
                return 2;
        }
-       
-       if(  e_write_file(filename, e_filters[filter].func, enum_mode ) )
-               statusline_msg("Error occured while exporting");
-       
+
+       if( e_write_file(filename, e_filters[filter].func, enum_mode))
+               statusline_msg(_("Error occured while exporting"));
+
        refresh_screen();
        free(filename);
 
@@ -353,16 +365,16 @@ e_write_file(char *filename, int (*func) (FILE *in, struct db_enumerator e),
        int ret = 0;
        struct db_enumerator enumerator = init_db_enumerator(mode);
 
-       if( (out = fopen(filename, "a")) == NULL )
+       if((out = fopen(filename, "a")) == NULL)
                return 1;
 
-       if( ftell(out) )
+       if(ftell(out))
                return 1;
 
        ret = (*func) (out, enumerator);
-       
+
        fclose(out);
-       
+
        return ret;
 }
 
@@ -373,10 +385,10 @@ fexport(char filtname[FILTNAME_LEN], FILE *handle, int enum_mode)
        struct db_enumerator e = init_db_enumerator(enum_mode);
 
        for(i=0;; i++) {
-               if( ! strncasecmp(e_filters[i].filtname, filtname,
-                                       FILTNAME_LEN) )
+               if(!strncasecmp(e_filters[i].filtname, filtname,
+                                       FILTNAME_LEN))
                        break;
-               if( ! *e_filters[i].filtname ) {
+               if(!*e_filters[i].filtname) {
                        i = -1;
                        break;
                }
@@ -394,21 +406,21 @@ export_file(char filtname[FILTNAME_LEN], char *filename)
        int i;
        int ret = 0;
        struct db_enumerator e = init_db_enumerator(mode);
-       
+
        for(i=0;; i++) {
-               if( ! strncasecmp(e_filters[i].filtname, filtname,
-                                       FILTNAME_LEN) )
+               if(!strncasecmp(e_filters[i].filtname, filtname,
+                                       FILTNAME_LEN))
                        break;
-               if( ! *e_filters[i].filtname ) {
+               if(!*e_filters[i].filtname) {
                        i = -1;
                        break;
                }
        }
 
-       if( i<0 )
+       if(i < 0)
                return -1;
 
-       if( !strcmp(filename, "-") )
+       if(!strcmp(filename, "-"))
                ret = (e_filters[i].func) (stdout, e);
        else
                ret =  e_write_file(filename, e_filters[i].func, mode);
@@ -430,10 +442,10 @@ static void       ldif_fix_string(char *str);
 
 #define        LDIF_ITEM_FIELDS        16
 
-typedef char*  ldif_item[LDIF_ITEM_FIELDS];
+typedef char *ldif_item[LDIF_ITEM_FIELDS];
 
 static ldif_item ldif_field_names = {
-       "cn",   
+       "cn",
        "mail",
        "streetaddress",
        "streetaddress2",
@@ -455,7 +467,7 @@ static int ldif_conv_table[LDIF_ITEM_FIELDS] = {
        NAME,           /* "cn" */
        EMAIL,          /* "mail" */
        ADDRESS,        /* "streetaddress" */
-       ADDRESS2,       /* "streetaddress2" */     
+       ADDRESS2,       /* "streetaddress2" */
         CITY,          /* "locality" */
        STATE,          /* "st" */
        ZIP,            /* "postalcode" */
@@ -471,7 +483,7 @@ static int ldif_conv_table[LDIF_ITEM_FIELDS] = {
 };
 
 
-static char * 
+static char *
 ldif_read_line(FILE *in)
 {
        char *buf = NULL;
@@ -484,10 +496,10 @@ ldif_read_line(FILE *in)
 
                pos = ftell(in);
                line = getaline(in);
-               
-               if( feof(in) || !line )
+
+               if(feof(in) || !line)
                        break;
-               
+
                if(i == 1) {
                        buf = line;
                        continue;
@@ -518,27 +530,28 @@ ldif_read_line(FILE *in)
 }
 
 static void
-ldif_add_item(ldif_item ldif_item)
+ldif_add_item(ldif_item li)
 {
-       list_item abook_item;
+       list_item item;
        int i;
 
-       memset(abook_item, 0, sizeof(abook_item));
+       item = item_create();
 
-       if( !ldif_item[LDIF_ITEM_FIELDS -1] )
+       if(!li[LDIF_ITEM_FIELDS -1])
                goto bail_out;
 
 
        for(i=0; i < LDIF_ITEM_FIELDS; i++) {
-               if(ldif_conv_table[i] >= 0 && ldif_item[i] && *ldif_item[i] )
-                       abook_item[ldif_conv_table[i]] = strdup(ldif_item[i]);
+               if(ldif_conv_table[i] >= 0 && li[i] && *li[i])
+                       item_fput(item,ldif_conv_table[i],xstrdup(li[i]));
        }
 
-       add_item2database(abook_item);
+       add_item2database(item);
 
 bail_out:
        for(i=0; i < LDIF_ITEM_FIELDS; i++)
-               my_free(ldif_item[i]);
+               xfree(li[i]);
+       item_free(&item);
 
 }
 
@@ -547,19 +560,21 @@ ldif_convert(ldif_item item, char *type, char *value)
 {
        int i;
 
-       if( !strcmp(type, "dn") ) {
+       if(!strcmp(type, "dn")) {
                ldif_add_item(item);
                return;
        }
 
        for(i=0; i < LDIF_ITEM_FIELDS; i++) {
-               if( !safe_strcmp(ldif_field_names[i], type) && *value ) {
-                       if( i == LDIF_ITEM_FIELDS -1) /* this is a dirty hack */
-                               if( safe_strcmp("person", value))
+               if(!safe_strcmp(ldif_field_names[i], type) && *value) {
+                       if(i == LDIF_ITEM_FIELDS - 1) /* this is a dirty hack */
+                               if(safe_strcmp("person", value))
                                        break;
-                       if(item[i])
-                               my_free(item[i]);
-                       item[i] = strdup(value);
+
+                       if(item_fget(item, i))
+                               free(item_fget(item, i));
+
+                       item_fput(item, i, xstrdup(value));
                }
        }
 }
@@ -575,11 +590,11 @@ ldif_parse_file(FILE *handle)
        memset(item, 0, sizeof(item));
 
        do {
-               if( ! (line = ldif_read_line(handle)) )
+               if( !(line = ldif_read_line(handle)) )
                        continue;
 
-               if( -1 == ( str_parse_line(line, &type, &value, &vlen)) ) {
-                       my_free(line);
+               if(-1 == (str_parse_line(line, &type, &value, &vlen))) {
+                       xfree(line);
                        continue; /* just skip the errors */
                }
 
@@ -587,7 +602,7 @@ ldif_parse_file(FILE *handle)
 
                ldif_convert(item, type, value);
 
-               my_free(line);
+               xfree(line);
        } while ( !feof(handle) );
 
        ldif_convert(item, "dn", "");
@@ -600,7 +615,7 @@ ldif_fix_string(char *str)
 {
        int i, j;
 
-       for( i = 0, j = 0; j < (int)strlen(str); i++, j++)
+       for(i = 0, j = 0; j < (int)strlen(str); i++, j++)
                str[i] = ( str[j] == (char)0xc3 ?
                                (char) str[++j] + (char) 0x40 :
                                str[j] );
@@ -627,39 +642,33 @@ mutt_read_line(FILE *in, char **alias, char **rest)
        if( !(line = ptr = getaline(in)) )
                return 1; /* error / EOF */
 
-       while( ISSPACE(*ptr) )
-               ptr++;
+       SKIPWS(ptr);
 
-       if( strncmp("alias", ptr, 5) ) {
+       if(strncmp("alias", ptr, 5)) {
                free(line);
                return 1;
        }
 
        ptr += 5;
 
-       while( ISSPACE(*ptr) )
-               ptr++;
+       SKIPWS(ptr);
 
        tmp = ptr;
 
        while( ! ISSPACE(*ptr) )
                ptr++;
 
-       /* includes also the trailing zero */
-       alias_len = (size_t)(ptr - tmp + 1);
+       alias_len = (size_t)(ptr - tmp);
 
-       if( (*alias = (char *)malloc(alias_len)) == NULL) {
-               free(line);
-               return 1;
-       }
+       if(alias)
+               *alias = xmalloc_inc(alias_len, 1);
 
-       strncpy(*alias, tmp, alias_len - 1);
-       *(*alias + alias_len - 1) = 0;
+       strncpy(*alias, tmp, alias_len);
+       *(*alias + alias_len) = 0;
 
-       while(ISSPACE(*ptr))
-               ptr++;
+       SKIPWS(ptr);
 
-       *rest = strdup(ptr);    
+       *rest = xstrdup(ptr);
 
        free(line);
        return 0;
@@ -688,7 +697,7 @@ mutt_fix_quoting(char *p)
 static void
 mutt_parse_email(list_item item)
 {
-       char *line = item[NAME];
+       char *line = item_fget(item, NAME);
        char *tmp;
        char *name, *email;
 #if 0
@@ -702,11 +711,12 @@ mutt_parse_email(list_item item)
        free(tmp);
 
        if(name)
-               item[NAME] = name;
+               item_fput(item, NAME, name);
        else
                return;
+
        if(email)
-               item[EMAIL] = email;
+               item_fput(item, EMAIL, email);
        else
                return;
 
@@ -725,7 +735,7 @@ mutt_parse_email(list_item item)
                                free(item[EMAIL]);
                                item[EMAIL] = tmp;
                        } else {
-                               my_free(email);
+                               xfree(email);
                        }
                }
        }
@@ -735,22 +745,25 @@ mutt_parse_email(list_item item)
 static int
 mutt_parse_file(FILE *in)
 {
-       list_item item;
+       list_item item = item_create();
 
        for(;;) {
-               memset(item, 0, sizeof(item));
+               memset(item, 0, fields_count * sizeof(char *));
 
-               if( !mutt_read_line(in, &item[NICK],
-                               &item[NAME]) )
+               if(!mutt_read_line(in,
+                                       (field_id(NICK) != -1) ?
+                                       &item[field_id(NICK)] : NULL,
+                                       &item[field_id(NAME)]))
                        mutt_parse_email(item);
 
-               if( feof(in) ) {
-                       free_list_item(item);
+               if(feof(in)) {
+                       item_empty(item);
                        break;
                }
 
                add_item2database(item);
        }
+       item_free(&item);
 
        return 0;
 }
@@ -788,19 +801,21 @@ ldif_export_database(FILE *out, struct db_enumerator e)
                int j;
                get_first_email(email, e.item);
 
-               tmp = mkstr("cn=%s,mail=%s", database[e.item][NAME], email);
+               tmp = strdup_printf("cn=%s,mail=%s",db_name_get(e.item),email);
+
                ldif_fput_type_and_value(out, "dn", tmp);
                free(tmp);
 
-               for(j=0; j < LDIF_ITEM_FIELDS; j++) {
+               for(j = 0; j < LDIF_ITEM_FIELDS; j++) {
                        if(ldif_conv_table[j] >= 0) {
                                if(ldif_conv_table[j] == EMAIL)
                                        ldif_fput_type_and_value(out,
                                                ldif_field_names[j], email);
-                               else if(database[e.item][ldif_conv_table[j]])
+                               else if(db_fget(e.item,ldif_conv_table[j]))
                                        ldif_fput_type_and_value(out,
                                                ldif_field_names[j],
-                                               database[e.item][ldif_conv_table[j]]);
+                                               db_fget(e.item,
+                                                       ldif_conv_table[j]));
                        }
                }
 
@@ -819,38 +834,56 @@ ldif_export_database(FILE *out, struct db_enumerator e)
  * html export filter
  */
 
-static void            html_export_write_head(FILE *out, int extra_column);
+static void            html_export_write_head(FILE *out);
 static void            html_export_write_tail(FILE *out);
 
-extern int extra_column;
+extern struct index_elem *index_elements;
+
+static void
+html_print_emails(FILE *out, struct list_field *f)
+{
+       abook_list *l = csv_to_abook_list(f->data);
+
+       for(; l; l = l->next) {
+               fprintf(out, "<a href=\"mailto:%s\">%s</a>", l->data, l->data);
+               if(l->next)
+                       fprintf(out, ", ");
+       }
+
+       abook_list_free(&l);
+}
 
 static int
 html_export_database(FILE *out, struct db_enumerator e)
 {
-       char tmp[MAX_EMAILSTR_LEN];
+       struct list_field f;
+       struct index_elem *cur;
 
-       if( items < 1 )
+       if(list_is_empty())
                return 2;
 
-       extra_column = (extra_column > 2 && extra_column < ITEM_FIELDS) ?
-               extra_column : PHONE;
+       init_index();
 
-       html_export_write_head(out, extra_column);
+       html_export_write_head(out);
 
        db_enumerate_items(e) {
-               get_first_email(tmp, e.item);
-               if (*tmp)
-                   fprintf(out, "<tr>\n<td><a href=\"mailto:%s\">%s</a>\n",
-                           tmp,
-                           database[e.item][NAME] );
-               else
-                   fprintf(out, "<tr>\n<td>%s\n",
-                           database[e.item][NAME] );
-
-               fprintf(out, "<td>%s\n<td>%s\n",
-                               database[e.item][EMAIL],
-                               safe_str(database[e.item][extra_column]) );
-               fprintf(out, "</tr>\n\n");
+               fprintf(out, "<tr>");
+               for(cur = index_elements; cur; cur = cur->next) {
+                       if(cur->type != INDEX_FIELD)
+                               continue;
+
+                       get_list_field(e.item, cur, &f);
+
+                       if(f.type == FIELD_EMAILS) {
+                               fprintf(out, "<td>");
+                               html_print_emails(out, &f);
+                               fprintf(out, "</td>");
+                               continue;
+                       } else {
+                               fprintf(out, "<td>%s</td>", safe_str(f.data));
+                       }
+               }
+               fprintf(out, "</tr>\n");
        }
 
        html_export_write_tail(out);
@@ -858,21 +891,28 @@ html_export_database(FILE *out, struct db_enumerator e)
        return 0;
 }
 
-
 static void
-html_export_write_head(FILE *out, int extra_column)
+html_export_write_head(FILE *out)
 {
-       char *realname = get_real_name();
+       char *realname = get_real_name(), *str;
+       struct index_elem *cur;
 
        fprintf(out, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
-       fprintf(out, "<html>\n<head>\n <title>%s's addressbook</title>", realname );
+       fprintf(out, "<html>\n<head>\n <title>%s's addressbook</title>",
+                       realname );
        fprintf(out, "\n</head>\n<body>\n");
        fprintf(out, "\n<h2>%s's addressbook</h2>\n", realname );
        fprintf(out, "<br><br>\n\n");
 
-       fprintf(out, "<table border=\"1\" align=\"center\">\n");
-       fprintf(out, "\n<tr><th>Name<th>E-mail address(es)<th>%s</tr>\n\n",
-                       abook_fields[extra_column].name);
+       fprintf(out, "<table border=\"1\" align=\"center\">\n<tr>");
+       for(cur = index_elements; cur; cur = cur->next) {
+               if(cur->type != INDEX_FIELD)
+                       continue;
+
+               get_field_info(cur->d.field.id, NULL, &str, NULL);
+               fprintf(out, "<th>%s</th>", str);
+       }
+       fprintf(out, "</tr>\n\n");
 
        free(realname);
 }
@@ -883,7 +923,7 @@ html_export_write_tail(FILE *out)
        fprintf(out, "\n</table>\n");
        fprintf(out, "\n</body>\n</html>\n");
 }
-       
+
 /*
  * end of html export filter
  */
@@ -900,7 +940,7 @@ pine_fixbuf(char *buf)
 {
        int i,j;
 
-       for(i=0,j=0; j < (int)strlen(buf); i++, j++)
+       for(i = 0,j = 0; j < (int)strlen(buf); i++, j++)
                buf[i] = buf[j] == '\n' ? buf[++j] : buf[j];
 }
 
@@ -910,19 +950,19 @@ pine_convert_emails(char *s)
        int i;
        char *tmp;
 
-       if( s == NULL || *s != '(' )
+       if(s == NULL || *s != '(')
                return;
 
-       for(i=0; s[i]; i++ )
-               s[i] = s[i+1];
+       for(i = 0; s[i]; i++)
+               s[i] = s[i + 1];
 
        if( ( tmp = strchr(s,')')) )
-               *tmp=0;
+               *tmp = '\0';
 
-       for(i=1; ( tmp = strchr(s, ',') ) != NULL ; i++, s=tmp+1 )
-               if( i > MAX_EMAILS - 1 ) {
-                       *tmp = 0;
-                       break;  
+       for(i = 1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1)
+               if(i > MAX_LIST_ITEMS - 1) {
+                       *tmp = '\0';
+                       break;
                }
 
 }
@@ -937,10 +977,10 @@ pine_parse_buf(char *buf)
        int i, len, last;
        int pine_conv_table[]= {NICK, NAME, EMAIL, -1, NOTES};
 
-       memset(&item, 0, sizeof(item) );
-       
+       item = item_create();
+
        for(i=0, last=0; !last ; i++) {
-               if( ! (end = strchr(start, '\t')) )
+               if( !(end = strchr(start, '\t')) )
                        last=1;
 
                len = last ? strlen(start) : (int) (end-start);
@@ -951,13 +991,15 @@ pine_parse_buf(char *buf)
                        strncpy(tmp, start, len);
                        tmp[len] = 0;
                        if(*tmp)
-                               item[pine_conv_table[i]] = strdup(tmp);
+                               item_fput(item, pine_conv_table[i],
+                                               xstrdup(tmp));
                }
                start = end + 1;
        }
 
-       pine_convert_emails(item[EMAIL]);
+       pine_convert_emails(item_fget(item, EMAIL));
        add_item2database(item);
+       item_free(&item);
 }
 
 
@@ -971,32 +1013,32 @@ pine_parse_file(FILE *in)
        char *ptr;
        int i;
 
-       fgets(line, LINESIZE, in);      
+       fgets(line, LINESIZE, in);
 
        while(!feof(in)) {
                for(i = 2;;i++) {
-                       buf = (char *) realloc(buf, i*LINESIZE);
+                       buf = xrealloc(buf, i*LINESIZE);
                        if(i == 2)
                                strcpy(buf, line);
                        fgets(line, LINESIZE, in);
                        ptr=(char *)&line;
-                       if(*ptr != ' ' || feof(in) )
+                       if(*ptr != ' ' || feof(in))
                                break;
                        else
-                               while( *ptr == ' ')
+                               while(*ptr == ' ')
                                        ptr++;
 
                        strcat(buf, ptr);
                }
-               if( *buf == '#' ) {
-                       my_free(buf);
+               if(*buf == '#') {
+                       xfree(buf);
                        continue;
                }
                pine_fixbuf(buf);
 
                pine_parse_buf(buf);
 
-               my_free(buf);
+               xfree(buf);
        }
 
        return 0;
@@ -1017,14 +1059,18 @@ pine_parse_file(FILE *in)
 static int
 pine_export_database(FILE *out, struct db_enumerator e)
 {
+       char *emails;
+
        db_enumerate_items(e) {
-               fprintf(out, have_multiple_emails(e.item) ?
+               emails = db_email_get(e.item);
+               fprintf(out, strchr(emails, ',') /* multiple addresses? */ ?
                                "%s\t%s\t(%s)\t\t%s\n" : "%s\t%s\t%s\t\t%s\n",
-                               safe_str(database[e.item][NICK]),
-                               safe_str(database[e.item][NAME]),
-                               safe_str(database[e.item][EMAIL]),
-                               safe_str(database[e.item][NOTES])
+                               safe_str(db_fget(e.item, NICK)),
+                               safe_str(db_name_get(e.item)),
+                               emails,
+                               safe_str(db_fget(e.item, NOTES))
                                );
+               free(emails);
        }
 
        return 0;
@@ -1041,11 +1087,13 @@ pine_export_database(FILE *out, struct db_enumerator e)
 
 /* FIXME
  * these files should be parsed according to a certain
- * lay out, or the default if layout is not given, at 
+ * lay out, or the default if layout is not given, at
  * the moment only default is done...
- */ 
+ */
 
 #define CSV_COMMENT_CHAR       '#'
+#define CSV_DUPLICATE_SEPARATOR        " "
+#define CSV_TABLE_SIZE(t)      (sizeof (t) / sizeof *(t))
 
 static int csv_conv_table[] = {
        NAME,
@@ -1071,11 +1119,25 @@ static int allcsv_conv_table[] = {
        NICK,
        URL,
        NOTES,
-       CUSTOM1,
-       CUSTOM2,
-       CUSTOM3,
-       CUSTOM4,
-       CUSTOM5,
+       ANNIVERSARY
+};
+
+static int palmcsv_conv_table[] = {
+       NAME,           /* Last name */
+       NAME,           /* First name */
+       NOTES,          /* Title */
+       NICK,           /* Company */
+       WORKPHONE,
+       PHONE,
+       FAX,
+       MOBILEPHONE,
+       EMAIL,
+       ADDRESS,
+       CITY,
+       STATE,
+       ZIP,
+       COUNTRY,
+       ANNIVERSARY,
 };
 
 static void
@@ -1084,13 +1146,13 @@ csv_convert_emails(char *s)
        int i;
        char *tmp;
 
-       if( s == NULL )
+       if(s == NULL)
                return;
 
-       for(i=1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1 )
-               if( i > MAX_EMAILS - 1 ) {
+       for(i = 1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1)
+               if(i > MAX_LIST_ITEMS - 1) {
                        *tmp = 0;
-                       break;  
+                       break;
                }
 
 }
@@ -1101,47 +1163,37 @@ csv_remove_quotes(char *s)
        char *copy, *trimmed;
        int len;
 
-       copy = trimmed = strdup(s);
+       copy = trimmed = xstrdup(s);
        strtrim(trimmed);
 
        len = strlen(trimmed);
        if(trimmed[len - 1] == '\"' && *trimmed == '\"') {
                if(len < 3) {
-                       my_free(copy);
+                       xfree(copy);
                        return NULL;
                }
                trimmed[len - 1] = 0;
                trimmed++;
-               trimmed = strdup(trimmed);
+               trimmed = xstrdup(trimmed);
                free(copy);
                return trimmed;
        }
 
-       my_free(copy);
-       return strdup(s);
+       xfree(copy);
+       return xstrdup(s);
 }
 
-static void
-csv_store_field(list_item item, char *s, int field)
+static int
+csv_field_to_item(int *table_base, size_t table_size, int field)
 {
-       char *newstr = NULL;
-
-       if(!s || !*s)
-               return;
-
-       if( !(newstr = csv_remove_quotes(s)) )
-               return;
+       if(field < table_size)
+               return field_id(table_base[field]);
 
-       if(field < (int)(sizeof(csv_conv_table) / sizeof(*csv_conv_table))
-                       && csv_conv_table[field] >= 0) {
-               item[csv_conv_table[field]] = newstr;
-       } else {
-               my_free(newstr);
-       }
+       return -1;
 }
 
 static void
-allcsv_store_field(list_item item, char *s, int field)
+csv_store_item(list_item item, int i, char *s)
 {
        char *newstr = NULL;
 
@@ -1151,11 +1203,19 @@ allcsv_store_field(list_item item, char *s, int field)
        if( !(newstr = csv_remove_quotes(s)) )
                return;
 
-       if(field < (int)(sizeof(allcsv_conv_table) / sizeof(*allcsv_conv_table))
-                       && allcsv_conv_table[field] >= 0) {
-               item[allcsv_conv_table[field]] = newstr;
+       if(i >= 0) {
+               if (item[i] != NULL) {
+                       char *oldstr = item[i];
+
+                       item[i] = strconcat(newstr, CSV_DUPLICATE_SEPARATOR,
+                               oldstr, NULL);
+                       xfree(newstr);
+                       xfree(oldstr);
+               } else {
+                       item[i] = newstr;
+               }
        } else {
-               my_free(newstr);
+               xfree(newstr);
        }
 }
 
@@ -1189,14 +1249,14 @@ csv_is_valid_quote_start(char *p)
 }
 
 static void
-csv_parse_line(char *line)
+csv_parse_line(char *line, int *table_base, size_t table_size)
 {
        char *p, *start;
        int field;
        bool in_quote = FALSE;
        list_item item;
 
-       memset(item, 0, sizeof(item));
+       item = item_create();
 
        for(p = start = line, field = 0; *p; p++) {
                if(in_quote) {
@@ -1208,9 +1268,11 @@ csv_parse_line(char *line)
                                in_quote = TRUE;
                }
 
-               if( *p == ',' && !in_quote) {
+               if(*p == ',' && !in_quote) {
                        *p = 0;
-                       csv_store_field(item, start, field);
+                       csv_store_item(item,
+                               csv_field_to_item(table_base,table_size,field),
+                               start);
                        field++;
                        start = p + 1;
                }
@@ -1218,51 +1280,16 @@ csv_parse_line(char *line)
        /*
         * store last field
         */
-       csv_store_field(item, start, field);
+       csv_store_item(item, csv_field_to_item(table_base, table_size, field),
+               start);
 
-       csv_convert_emails(item[EMAIL]);
+       csv_convert_emails(item_fget(item, EMAIL));
        add_item2database(item);
+       item_free(&item);
 }
 
-static void
-allcsv_parse_line(char *line)
-{
-       char *p, *start;
-       int field;
-       bool in_quote = FALSE;
-       list_item item;
-
-       memset(item, 0, sizeof(item));
-
-       for(p = start = line, field = 0; *p; p++) {
-               if(in_quote) {
-                       if(csv_is_valid_quote_end(p))
-                               in_quote = FALSE;
-               } else {
-                       if ( (((p - start) / sizeof (char)) < 2 ) &&
-                               csv_is_valid_quote_start(p) )
-                               in_quote = TRUE;
-               }
-
-               if( *p == ',' && !in_quote) {
-                       *p = 0;
-                       allcsv_store_field(item, start, field);
-                       field++;
-                       start = p + 1;
-               }
-       }
-       /*
-        * store last field
-        */
-       allcsv_store_field(item, start, field);
-
-       csv_convert_emails(item[EMAIL]);
-       add_item2database(item);
-}
-
-
 static int
-csv_parse_file(FILE *in)
+csv_parse_file_common(FILE *in, int *conv_table, size_t table_size)
 {
        char *line = NULL;
 
@@ -1270,29 +1297,33 @@ csv_parse_file(FILE *in)
                line = getaline(in);
 
                if(line && *line && *line != CSV_COMMENT_CHAR)
-                       csv_parse_line(line);
+                       csv_parse_line(line, conv_table, table_size);
 
-               my_free(line);
+               xfree(line);
        }
 
        return 0;
 }
 
 static int
-allcsv_parse_file(FILE *in)
+csv_parse_file(FILE *in)
 {
-       char *line = NULL;
-
-       while(!feof(in)) {
-               line = getaline(in);
-
-               if(line && *line && *line != CSV_COMMENT_CHAR)
-                       allcsv_parse_line(line);
+       return csv_parse_file_common(in, csv_conv_table,
+               CSV_TABLE_SIZE(csv_conv_table));
+}
 
-               my_free(line);
-       }
+static int
+allcsv_parse_file(FILE *in)
+{
+       return csv_parse_file_common(in, allcsv_conv_table,
+               CSV_TABLE_SIZE(allcsv_conv_table));
+}
 
-       return 0;
+static int
+palmcsv_parse_file(FILE *in)
+{
+       return csv_parse_file_common(in, palmcsv_conv_table,
+               CSV_TABLE_SIZE(palmcsv_conv_table));
 }
 
 /*
@@ -1323,13 +1354,13 @@ csv_export_common(FILE *out, struct db_enumerator e,
                                        (*special_func)(out, e.item, fields[i]);
                        } else
                                /*fprintf(out,(
-                       strchr(safe_str(database[e.item][fields[i]]), ',') ||
-                       strchr(safe_str(database[e.item][fields[i]]), '\"')) ?
+                       strchr(safe_str(database[e.item][field_idx(fields[i])]), ',') ||
+                       strchr(safe_str(database[e.item][field_idx(fields[i])]), '\"')) ?
                                "\"%s\"" : "%s",
-                               safe_str(database[e.item][fields[i]])
+                               safe_str(database[e.item][field_idx(fields[i])])
                                );*/
                                fprintf(out, "\"%s\"",
-                                       safe_str(database[e.item][fields[i]]));
+                                       safe_str(db_fget(e.item,fields[i])));
 
                        if(fields[i + 1] != CSV_LAST)
                                fputc(',', out);
@@ -1353,7 +1384,7 @@ csv_export_database(FILE *out, struct db_enumerator e)
        };
 
        csv_export_common(out, e, csv_export_fields, NULL);
-       
+
        return 0;
 }
 
@@ -1380,11 +1411,7 @@ allcsv_export_database(FILE *out, struct db_enumerator e)
                NICK,
                URL,
                NOTES,
-               CUSTOM1,
-               CUSTOM2,
-               CUSTOM3,
-               CUSTOM4,
-               CUSTOM5,
+               ANNIVERSARY,
                CSV_LAST
        };
 
@@ -1404,14 +1431,10 @@ allcsv_export_database(FILE *out, struct db_enumerator e)
        fprintf(out, "\"NICK\",");
        fprintf(out, "\"URL\",");
        fprintf(out, "\"NOTES\",");
-       fprintf(out, "\"CUSTOM1\",");
-       fprintf(out, "\"CUSTOM2\",");
-       fprintf(out, "\"CUSTOM3\",");
-       fprintf(out, "\"CUSTOM4\",");
-       fprintf(out, "\"CUSTOM5\"\n");
+       fprintf(out, "\"ANNIVERSARY\"\n");
 
        csv_export_common(out, e, allcsv_export_fields, NULL);
-       
+
        return 0;
 }
 
@@ -1423,7 +1446,7 @@ allcsv_export_database(FILE *out, struct db_enumerator e)
 #define PALM_CSV_END   CSV_SPECIAL(1)
 #define PALM_CSV_CAT   CSV_SPECIAL(2)
 
-static void 
+static void
 palm_split_and_write_name(FILE *out, char *name)
 {
        char *p;
@@ -1442,12 +1465,12 @@ palm_split_and_write_name(FILE *out, char *name)
        }
 }
 
-static void 
+static void
 palm_csv_handle_specials(FILE *out, int item, int field)
 {
        switch(field) {
                case PALM_CSV_NAME:
-                       palm_split_and_write_name(out, database[item][NAME]);
+                       palm_split_and_write_name(out, db_name_get(item));
                        break;
                case PALM_CSV_CAT:
                        fprintf(out, "\"abook\"");
@@ -1472,7 +1495,7 @@ palm_export_database(FILE *out, struct db_enumerator e)
                FAX,                    /* FAX                  */
                MOBILEPHONE,            /* OTHER                */
                EMAIL,                  /* EMAIL                */
-               ADDRESS,                /* ADDRESS              */ 
+               ADDRESS,                /* ADDRESS              */
                CITY,                   /* CITY                 */
                STATE,                  /* STATE                */
                ZIP,                    /* ZIP                  */
@@ -1503,62 +1526,70 @@ palm_export_database(FILE *out, struct db_enumerator e)
 static int
 gcrd_export_database(FILE *out, struct db_enumerator e)
 {
-       char emails[MAX_EMAILS][MAX_EMAIL_LEN];
        int j;
-       char *name;
+       char *name, *tmp;
+       abook_list *emails, *em;
 
        db_enumerate_items(e) {
-               fprintf(out, "BEGIN:VCARD\nFN:%s\n",
-                               safe_str(database[e.item][NAME]));
+               fprintf(out, "BEGIN:VCARD\r\nFN:%s\r\n",
+                               safe_str(db_name_get(e.item)));
 
-               name = get_surname(database[e.item][NAME]);
-               for( j = strlen(database[e.item][NAME]) - 1; j >= 0; j-- ) {
-                       if(database[e.item][NAME][j] == ' ')
+               name = get_surname(db_name_get(e.item));
+               for( j = strlen(db_name_get(e.item)) - 1; j >= 0; j-- ) {
+                       if((db_name_get(e.item))[j] == ' ')
                                break;
-               } 
-               fprintf(out, "N:%s;%.*s\n",
+               }
+               fprintf(out, "N:%s;%.*s\r\n",
                        safe_str(name),
                        j,
-                       safe_str(database[e.item][NAME])
-                       ); 
+                       safe_str(db_name_get(e.item))
+                       );
 
                free(name);
 
-               if ( database[e.item][ADDRESS] )
-                       fprintf(out, "ADR:;;%s;%s;%s;%s;%s;%s\n",
-                               safe_str(database[e.item][ADDRESS]),
-                               safe_str(database[e.item][ADDRESS2]),                           
-                               safe_str(database[e.item][CITY]),
-                               safe_str(database[e.item][STATE]),
-                               safe_str(database[e.item][ZIP]),
-                               safe_str(database[e.item][COUNTRY])
+               if(db_fget(e.item, ADDRESS))
+                       fprintf(out, "ADR:;;%s;%s;%s;%s;%s;%s\r\n",
+                               safe_str(db_fget(e.item, ADDRESS)),
+                               safe_str(db_fget(e.item, ADDRESS2)),
+                               safe_str(db_fget(e.item, CITY)),
+                               safe_str(db_fget(e.item, STATE)),
+                               safe_str(db_fget(e.item, ZIP)),
+                               safe_str(db_fget(e.item, COUNTRY))
                                );
-               
-               if (database[e.item][PHONE])
-                       fprintf(out, "TEL;HOME:%s\n", database[e.item][PHONE]);
-               if (database[e.item][WORKPHONE])
-                       fprintf(out, "TEL;WORK:%s\n", database[e.item][WORKPHONE]);
-               if (database[e.item][FAX])
-                       fprintf(out, "TEL;FAX:%s\n", database[e.item][FAX]);
-               if (database[e.item][MOBILEPHONE])
-                       fprintf(out, "TEL;CELL:%s\n", database[e.item][MOBILEPHONE]);
-
-               if ( database[e.item][EMAIL] ) {
-                       split_emailstr(e.item, emails);
-                       for(j=0; j < MAX_EMAILS ; j++) {
-                               if ( *emails[j] ) 
-                                       fprintf(out, "EMAIL;INTERNET:%s\n",
-                                               emails[j]);
-                       }
+
+               if(db_fget(e.item, PHONE))
+                       fprintf(out, "TEL;HOME:%s\r\n",
+                                       db_fget(e.item, PHONE));
+               if(db_fget(e.item, WORKPHONE))
+                       fprintf(out, "TEL;WORK:%s\r\n",
+                                       db_fget(e.item, WORKPHONE));
+               if(db_fget(e.item, FAX))
+                       fprintf(out, "TEL;FAX:%s\r\n",
+                                       db_fget(e.item, FAX));
+               if(db_fget(e.item, MOBILEPHONE))
+                       fprintf(out, "TEL;CELL:%s\r\n",
+                                       db_fget(e.item, MOBILEPHONE));
+
+               tmp = db_email_get(e.item);
+               if(*tmp) {
+                       emails = csv_to_abook_list(tmp);
+
+                       for(em = emails; em; em = em->next)
+                               fprintf(out, "EMAIL;INTERNET:%s\r\n", em->data);
+
+                       abook_list_free(&emails);
                }
-               
-               if ( database[e.item][NOTES] ) 
-                       fprintf(out, "NOTE:%s\n", database[e.item][NOTES]);
-               if (database[e.item][URL])
-                       fprintf(out, "URL:%s\n",  database[e.item][URL]);
-
-               fprintf(out, "END:VCARD\n\n");
-               
+               free(tmp);
+
+               if(db_fget(e.item, NOTES))
+                       fprintf(out, "NOTE:%s\r\n",
+                                       db_fget(e.item, NOTES));
+               if(db_fget(e.item, URL))
+                       fprintf(out, "URL:%s\r\n",
+                                       db_fget(e.item, URL));
+
+               fprintf(out, "END:VCARD\r\n\r\n");
+
        }
 
        return 0;
@@ -1577,18 +1608,18 @@ static char *
 mutt_alias_genalias(int i)
 {
        char *tmp, *pos;
-       
-       if(database[i][NICK])
-               return strdup(database[i][NICK]);
 
-       tmp = strdup(database[i][NAME]);
+       if(db_fget(i, NICK))
+               return xstrdup(db_fget(i, NICK));
+
+       tmp = xstrdup(db_name_get(i));
 
        if( ( pos = strchr(tmp, ' ') ) )
                *pos = 0;
 
        strlower(tmp);
 
-       return tmp;     
+       return tmp;
 }
 
 static int
@@ -1599,13 +1630,12 @@ mutt_alias_export(FILE *out, struct db_enumerator e)
 
        db_enumerate_items(e) {
                alias = mutt_alias_genalias(e.item);
-
                get_first_email(email, e.item);
                fprintf(out, *email ? "alias %s %s <%s>\n": "alias %s %s%s\n",
                                alias,
-                               database[e.item][NAME],
+                               db_name_get(e.item),
                                email);
-               my_free(alias);
+               xfree(alias);
        }
 
        return 0;
@@ -1623,29 +1653,29 @@ mutt_alias_export(FILE *out, struct db_enumerator e)
 
 static void
 text_write_address_us(FILE *out, int i) {
-       fprintf(out, "\n%s", database[i][ADDRESS]);
+       fprintf(out, "\n%s", db_fget(i, ADDRESS));
+
+       if(db_fget(i, ADDRESS2))
+               fprintf(out, "\n%s", db_fget(i, ADDRESS2));
 
-       if (database[i][ADDRESS2])
-               fprintf(out, "\n%s", database[i][ADDRESS2]);
+       if(db_fget(i, CITY))
+               fprintf(out, "\n%s", db_fget(i, CITY));
 
-       if (database[i][CITY])
-               fprintf(out, "\n%s", database[i][CITY]);
-               
-       if (database[i][STATE] || database[i][ZIP]) {
+       if(db_fget(i, STATE) || db_fget(i, ZIP)) {
                fputc('\n', out);
-               
-               if(database[i][STATE]) {
-                       fprintf(out, "%s", database[i][STATE]);
-                       if(database[i][ZIP])
+
+               if(db_fget(i, STATE)) {
+                       fprintf(out, "%s", db_fget(i, STATE));
+                       if(db_fget(i, ZIP))
                                fputc(' ', out);
                }
 
-               if(database[i][ZIP])
-                       fprintf(out, "%s", database[i][ZIP]);
+               if(db_fget(i, ZIP))
+                       fprintf(out, "%s", db_fget(i, ZIP));
        }
 
-       if (database[i][COUNTRY])
-               fprintf(out, "\n%s", database[i][COUNTRY]);
+       if(db_fget(i, COUNTRY))
+               fprintf(out, "\n%s", db_fget(i, COUNTRY));
 }
 
 
@@ -1653,44 +1683,43 @@ static void
 text_write_address_uk(FILE *out, int i) {
        int j;
 
-       for (j = ADDRESS; j <= COUNTRY; j++)
-               if (database[i][j])
-                       fprintf(out, "\n%s", database[i][j]);
+       for(j = ADDRESS; j <= COUNTRY; j++)
+               if(db_fget(i, j))
+                       fprintf(out, "\n%s", db_fget(i, j));
 }
 
 static void
 text_write_address_eu(FILE *out, int i) {
-       fprintf(out, "\n%s", database[i][ADDRESS]);
+       fprintf(out, "\n%s", db_fget(i, ADDRESS));
 
-       if (database[i][ADDRESS2])
-               fprintf(out, "\n%s", database[i][ADDRESS2]);
+       if(db_fget(i, ADDRESS2))
+               fprintf(out, "\n%s", db_fget(i, ADDRESS2));
 
-       if (database[i][ZIP] || database[i][CITY]) {
+       if(db_fget(i, ZIP) || db_fget(i, CITY)) {
                fputc('\n', out);
 
-               if(database[i][ZIP]) {
-                       fprintf(out, "%s", database[i][ZIP]);
-                       if(database[i][CITY])
+               if(db_fget(i, ZIP)) {
+                       fprintf(out, "%s", db_fget(i, ZIP));
+                       if(db_fget(i, CITY))
                                fputc(' ', out);
                }
 
-               if(database[i][CITY])
-                       fprintf(out, "%s", database[i][CITY]);
+               fprintf(out, "%s", safe_str(db_fget(i, CITY)));
        }
-       
-       if (database[i][STATE])
-               fprintf(out, "\n%s", database[i][STATE]);
 
-       if (database[i][COUNTRY])
-               fprintf(out, "\n%s", database[i][COUNTRY]);
+       if(db_fget(i, STATE))
+               fprintf(out, "\n%s", db_fget(i, STATE));
+
+       if(db_fget(i, COUNTRY))
+               fprintf(out, "\n%s", db_fget(i, COUNTRY));
 }
 
 static int
 text_export_database(FILE * out, struct db_enumerator e)
 {
-       char emails[MAX_EMAILS][MAX_EMAIL_LEN];
+       abook_list *emails, *em;
        int j;
-       char *realname = get_real_name();
+       char *realname = get_real_name(), *str = NULL, *tmp;
        char *style = opt_get_str(STR_ADDRESS_STYLE);
 
        fprintf(out,
@@ -1702,23 +1731,27 @@ text_export_database(FILE * out, struct db_enumerator e)
        db_enumerate_items(e) {
                fprintf(out,
                        "-----------------------------------------\n\n");
-               fprintf(out, "%s", database[e.item][NAME]);
-               if (database[e.item][NICK] && *database[e.item][NICK])
-                       fprintf(out, "\n(%s)", database[e.item][NICK]);
+               fprintf(out, "%s", db_name_get(e.item));
+               if(db_fget(e.item, NICK) && *db_fget(e.item, NICK))
+                       fprintf(out, "\n(%s)", db_fget(e.item, NICK));
                fprintf(out, "\n");
 
-               if (*database[e.item][EMAIL]) {
+               tmp = db_email_get(e.item);
+               if(*tmp) {
+                       emails = csv_to_abook_list(tmp);
+
                        fprintf(out, "\n");
-                       split_emailstr(e.item, emails);
-                       for (j = 0; j < MAX_EMAILS; j++)
-                               if (*emails[j])
-                                       fprintf(out, "%s\n", emails[j]);
+                       for(em = emails; em; em = em->next)
+                               fprintf(out, "%s\n", em->data);
+
+                       abook_list_free(&emails);
                }
+               free(tmp);
                /* Print address */
-               if (database[e.item][ADDRESS]) {
-                       if (!safe_strcmp(style, "us"))  /* US like */
+               if(db_fget(e.item, ADDRESS)) {
+                       if(!safe_strcmp(style, "us"))   /* US like */
                                text_write_address_us(out, e.item);
-                       else if (!safe_strcmp(style, "uk"))     /* UK like */
+                       else if(!safe_strcmp(style, "uk"))      /* UK like */
                                text_write_address_uk(out, e.item);
                        else    /* EU like */
                                text_write_address_eu(out, e.item);
@@ -1726,22 +1759,24 @@ text_export_database(FILE * out, struct db_enumerator e)
                        fprintf(out, "\n");
                }
 
-               if ((database[e.item][PHONE]) ||
-                       (database[e.item][WORKPHONE]) ||
-                       (database[e.item][FAX]) ||
-                       (database[e.item][MOBILEPHONE])) {
+               if((db_fget(e.item, PHONE)) ||
+                       (db_fget(e.item, WORKPHONE)) ||
+                       (db_fget(e.item, FAX)) ||
+                       (db_fget(e.item, MOBILEPHONE))) {
                        fprintf(out, "\n");
-                       for (j = PHONE; j <= MOBILEPHONE; j++)
-                               if (database[e.item][j])
-                                       fprintf(out, "%s: %s\n",
-                                               abook_fields[j].name,
-                                               database[e.item][j]);
+                       for(j = PHONE; j <= MOBILEPHONE; j++)
+                               if(db_fget(e.item, j)) {
+                                       get_field_info(field_id(j),
+                                                       NULL, &str, NULL);
+                                       fprintf(out, "%s: %s\n", str,
+                                               db_fget(e.item, j));
+                               }
                }
 
-               if (database[e.item][URL])
-                       fprintf(out, "\n%s\n", database[e.item][URL]);
-               if (database[e.item][NOTES])
-                       fprintf(out, "\n%s\n", database[e.item][NOTES]);
+               if(db_fget(e.item, URL))
+                       fprintf(out, "\n%s\n", db_fget(e.item, URL));
+               if(db_fget(e.item, NOTES))
+                       fprintf(out, "\n%s\n", db_fget(e.item, NOTES));
 
                fprintf(out, "\n");
        }
@@ -1768,11 +1803,8 @@ elm_alias_export(FILE *out, struct db_enumerator e)
        db_enumerate_items(e) {
                alias = mutt_alias_genalias(e.item);
                get_first_email(email, e.item);
-               fprintf(out, "%s = %s = %s\n",
-                               alias,
-                               database[e.item][NAME],
-                               email);
-               my_free(alias);
+               fprintf(out, "%s = %s = %s\n",alias,db_name_get(e.item),email);
+               xfree(alias);
        }
 
        return 0;
@@ -1792,16 +1824,16 @@ spruce_export_database (FILE *out, struct db_enumerator e)
 {
        char email[MAX_EMAIL_LEN];
 
-       fprintf (out, "# This is a generated file made by abook for the Spruce e-mail client.\n\n");
+       fprintf(out, "# This is a generated file made by abook for the Spruce e-mail client.\n\n");
 
        db_enumerate_items(e) {
-               if(strcmp (safe_str(database[e.item][EMAIL]), "")) {
-                       get_first_email(email, e.item);
+               get_first_email(email, e.item);
+               if(strcmp(email, "")) {
                        fprintf(out, "# Address %d\nName: %s\nEmail: %s\nMemo: %s\n\n",
                                        e.item,
-                                       database[e.item][NAME],
+                                       db_name_get(e.item),
                                        email,
-                                       safe_str(database[e.item][NOTES])
+                                       safe_str(db_fget(e.item, NOTES))
                                        );
                }
        }
@@ -1815,3 +1847,64 @@ spruce_export_database (FILE *out, struct db_enumerator e)
  * end of Spruce export filter
  */
 
+/*
+ * wanderlust addressbook export filter
+ */
+
+static int
+wl_export_database(FILE *out, struct db_enumerator e)
+{
+       char email[MAX_EMAIL_LEN];
+
+       fprintf(out, "# Wanderlust address book written by %s\n\n", PACKAGE);
+       db_enumerate_items(e) {
+               get_first_email(email, e.item);
+               if(*email) {
+                       fprintf(out,
+                               "%s\t\"%s\"\t\"%s\"\n",
+                               email,
+                               safe_str(db_fget(e.item, NICK)),
+                               safe_str(db_name_get(e.item))
+                       );
+               }
+       }
+
+       fprintf (out, "\n# End of address book file.\n");
+
+       return 0;
+}
+
+/*
+ * end of wanderlust addressbook export filter
+ */
+
+/*
+ * BSD calendar export filter
+ */
+
+static int
+bsdcal_export_database(FILE *out, struct db_enumerator e)
+{
+       db_enumerate_items(e) {
+               int year, month = 0, day = 0;
+               char *anniversary = db_fget(e.item, ANNIVERSARY);
+
+               if(anniversary) {
+                       parse_date_string(anniversary, &day, &month, &year);
+
+                       fprintf(out,
+                               _("%02d/%02d\tAnniversary of %s\n"),
+                               month,
+                               day,
+                               safe_str(db_name_get(e.item))
+                       );
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * end of BSD calendar export filter
+ */
+