2007-11-09 [colin] 3.0.2cvs129
[claws.git] / src / addressbook.c
index cd322c43dc63c974fb51becaa472d6c1dafcd63a..f308bcc386ebd0772e180f148f9c893ee9f8f943 100644 (file)
@@ -44,6 +44,8 @@
 #include <gtk/gtkitemfactory.h>
 #include <string.h>
 #include <setjmp.h>
+#include <sys/types.h>
+#include <dirent.h>
 
 #include "main.h"
 #include "addressbook.h"
@@ -69,6 +71,7 @@
 #include "addrbook.h"
 #include "addrindex.h"
 #include "addressadd.h"
+#include "addrduplicates.h"
 #include "addressbook_foldersel.h"
 #include "vcard.h"
 #include "editvcard.h"
@@ -366,6 +369,7 @@ static void addressbook_list_select_add             ( AddrItemObject    *aio,
 static void addressbook_list_select_remove     ( AddrItemObject    *aio );
 
 static void addressbook_import_ldif_cb         ( void );
+static void addressbook_find_duplicates_cb     ( void );
 static void addressbook_import_mutt_cb         ( void );
 static void addressbook_import_pine_cb         ( void );
 static void addressbook_export_html_cb         ( void );
@@ -424,79 +428,81 @@ static GtkTargetList *addressbook_target_list = NULL;
 
 static GtkItemFactoryEntry addressbook_entries[] =
 {
-       {N_("/_Book"),                  NULL,           NULL, 0, "<Branch>"},
-       {N_("/_Book/New _Book"),        "<control>B",   addressbook_new_book_cb,        0, NULL},
-       {N_("/_Book/New _Folder"),      "<control>R",   addressbook_new_folder_cb,      0, NULL},
-       {N_("/_Book/New _vCard"),       "<control><shift>D",    addressbook_new_vcard_cb,       0, NULL},
+       {N_("/_Book"),                  NULL,           NULL, 0, "<Branch>", NULL},
+       {N_("/_Book/New _Book"),        "<control>B",   addressbook_new_book_cb,        0, NULL, NULL},
+       {N_("/_Book/New _Folder"),      "<control>R",   addressbook_new_folder_cb,      0, NULL, NULL},
+       {N_("/_Book/New _vCard"),       "<control><shift>D",    addressbook_new_vcard_cb,       0, NULL, NULL},
 #ifdef USE_JPILOT
-       {N_("/_Book/New _JPilot"),      "<control>J",   addressbook_new_jpilot_cb,      0, NULL},
+       {N_("/_Book/New _JPilot"),      "<control>J",   addressbook_new_jpilot_cb,      0, NULL, NULL},
 #endif
 #ifdef USE_LDAP
-       {N_("/_Book/New LDAP _Server"), "<control><shift>S",    addressbook_new_ldap_cb,        0, NULL},
+       {N_("/_Book/New LDAP _Server"), "<control><shift>S",    addressbook_new_ldap_cb,        0, NULL, NULL},
 #endif
-       {N_("/_Book/---"),              NULL,           NULL, 0, "<Separator>"},
-       {N_("/_Book/_Edit book"),       NULL,           addressbook_treenode_edit_cb,   0, NULL},
-       {N_("/_Book/_Delete book"),     NULL,           addressbook_treenode_delete_cb, 0, NULL},
-       {N_("/_Book/---"),              NULL,           NULL, 0, "<Separator>"},
-       {N_("/_Book/_Save"),            "<control>S",   addressbook_file_save_cb,       0, NULL},
-       {N_("/_Book/_Close"),           "<control>W",   close_cb,                       0, NULL},
-       {N_("/_Address"),                       NULL,           NULL, 0, "<Branch>"},
-       {N_("/_Address/_Select all"),   "<control>A",   addressbook_select_all_cb,      0, NULL},
-       {N_("/_Address/---"),           NULL,           NULL, 0, "<Separator>"},
-       {N_("/_Address/C_ut"),          "<control>X",   addressbook_clip_cut_cb,        0, NULL},
-       {N_("/_Address/_Copy"),         "<control>C",   addressbook_clip_copy_cb,       0, NULL},
-       {N_("/_Address/_Paste"),        "<control>V",   addressbook_clip_paste_cb,      0, NULL},
-       {N_("/_Address/---"),           NULL,           NULL, 0, "<Separator>"},
-       {N_("/_Address/_Edit"),         "<control>Return",addressbook_edit_address_cb,    0, NULL},
-       {N_("/_Address/_Delete"),       "<control>D",   addressbook_delete_address_cb,  0, NULL},
-       {N_("/_Address/---"),           NULL,           NULL, 0, "<Separator>"},
-       {N_("/_Address/New _Address"),  "<control>N",   addressbook_new_address_cb,     0, NULL},
-       {N_("/_Address/New _Group"),    "<control>G",   addressbook_new_group_cb,       0, NULL},
-       {N_("/_Address/---"),           NULL,           NULL, 0, "<Separator>"},
-       {N_("/_Address/_Mail To"),      NULL,           addressbook_mail_to_cb,         0, NULL},
-       {N_("/_Tools"),                 NULL,           NULL, 0, "<Branch>"},
-       {N_("/_Tools/Import _LDIF file..."), NULL,      addressbook_import_ldif_cb,     0, NULL},
-       {N_("/_Tools/Import M_utt file..."), NULL,      addressbook_import_mutt_cb,     0, NULL},
-       {N_("/_Tools/Import _Pine file..."), NULL,      addressbook_import_pine_cb,     0, NULL},
-       {N_("/_Tools/---"),             NULL,           NULL, 0, "<Separator>"},
-       {N_("/_Tools/Export _HTML..."), NULL,           addressbook_export_html_cb,     0, NULL},
-       {N_("/_Tools/Export LDI_F..."), NULL,           addressbook_export_ldif_cb,     0, NULL},
-       {N_("/_Help"),                  NULL,           NULL, 0, "<Branch>"},
-       {N_("/_Help/_About"),           NULL,           about_show, 0, NULL}
+       {N_("/_Book/---"),              NULL,           NULL, 0, "<Separator>", NULL},
+       {N_("/_Book/_Edit book"),       NULL,           addressbook_treenode_edit_cb,   0, NULL, NULL},
+       {N_("/_Book/_Delete book"),     NULL,           addressbook_treenode_delete_cb, 0, NULL, NULL},
+       {N_("/_Book/---"),              NULL,           NULL, 0, "<Separator>", NULL},
+       {N_("/_Book/_Save"),            "<control>S",   addressbook_file_save_cb,       0, NULL, NULL},
+       {N_("/_Book/_Close"),           "<control>W",   close_cb,                       0, NULL, NULL},
+       {N_("/_Address"),                       NULL,           NULL, 0, "<Branch>", NULL},
+       {N_("/_Address/_Select all"),   "<control>A",   addressbook_select_all_cb,      0, NULL, NULL},
+       {N_("/_Address/---"),           NULL,           NULL, 0, "<Separator>", NULL},
+       {N_("/_Address/C_ut"),          "<control>X",   addressbook_clip_cut_cb,        0, NULL, NULL},
+       {N_("/_Address/_Copy"),         "<control>C",   addressbook_clip_copy_cb,       0, NULL, NULL},
+       {N_("/_Address/_Paste"),        "<control>V",   addressbook_clip_paste_cb,      0, NULL, NULL},
+       {N_("/_Address/---"),           NULL,           NULL, 0, "<Separator>", NULL},
+       {N_("/_Address/_Edit"),         "<control>Return",addressbook_edit_address_cb,    0, NULL, NULL},
+       {N_("/_Address/_Delete"),       "<control>D",   addressbook_delete_address_cb,  0, NULL, NULL},
+       {N_("/_Address/---"),           NULL,           NULL, 0, "<Separator>", NULL},
+       {N_("/_Address/New _Address"),  "<control>N",   addressbook_new_address_cb,     0, NULL, NULL},
+       {N_("/_Address/New _Group"),    "<control>G",   addressbook_new_group_cb,       0, NULL, NULL},
+       {N_("/_Address/---"),           NULL,           NULL, 0, "<Separator>", NULL},
+       {N_("/_Address/_Mail To"),      NULL,           addressbook_mail_to_cb,         0, NULL, NULL},
+       {N_("/_Tools"),                 NULL,           NULL, 0, "<Branch>", NULL},
+       {N_("/_Tools/Import _LDIF file..."), NULL,      addressbook_import_ldif_cb,     0, NULL, NULL},
+       {N_("/_Tools/Import M_utt file..."), NULL,      addressbook_import_mutt_cb,     0, NULL, NULL},
+       {N_("/_Tools/Import _Pine file..."), NULL,      addressbook_import_pine_cb,     0, NULL, NULL},
+       {N_("/_Tools/---"),             NULL,           NULL, 0, "<Separator>", NULL},
+       {N_("/_Tools/Export _HTML..."), NULL,           addressbook_export_html_cb,     0, NULL, NULL},
+       {N_("/_Tools/Export LDI_F..."), NULL,           addressbook_export_ldif_cb,     0, NULL, NULL},
+       {N_("/_Tools/---"),             NULL,           NULL, 0, "<Separator>", NULL},
+       {N_("/_Tools/Find duplicates..."), NULL, addressbook_find_duplicates_cb,        0, NULL, NULL},
+       {N_("/_Help"),                  NULL,           NULL, 0, "<Branch>", NULL},
+       {N_("/_Help/_About"),           NULL,           about_show, 0, NULL, NULL}
 };
 
 static GtkItemFactoryEntry addressbook_tree_popup_entries[] =
 {
-       {N_("/_Edit"),          NULL, addressbook_treenode_edit_cb,   0, NULL},
-       {N_("/_Delete"),        NULL, addressbook_treenode_delete_cb, 0, NULL},
-       {"/---",                NULL, NULL, 0, "<Separator>"},
-       {N_("/New _Book"),      NULL, addressbook_new_book_cb,      0, NULL},
-       {N_("/New _Folder"),    NULL, addressbook_new_folder_cb,      0, NULL},
-       {N_("/New _Group"),     NULL, addressbook_new_group_cb,      0, NULL},
-       {"/---",                NULL, NULL, 0, "<Separator>"},
-       {N_("/C_ut"),           NULL, addressbook_treenode_cut_cb,    0, NULL},
-       {N_("/_Copy"),          NULL, addressbook_treenode_copy_cb,   0, NULL},
-       {N_("/_Paste"),         NULL, addressbook_treenode_paste_cb,  0, NULL}
+       {N_("/_Edit"),          NULL, addressbook_treenode_edit_cb,   0, NULL, NULL},
+       {N_("/_Delete"),        NULL, addressbook_treenode_delete_cb, 0, NULL, NULL},
+       {"/---",                NULL, NULL, 0, "<Separator>", NULL},
+       {N_("/New _Book"),      NULL, addressbook_new_book_cb,      0, NULL, NULL},
+       {N_("/New _Folder"),    NULL, addressbook_new_folder_cb,      0, NULL, NULL},
+       {N_("/New _Group"),     NULL, addressbook_new_group_cb,      0, NULL, NULL},
+       {"/---",                NULL, NULL, 0, "<Separator>", NULL},
+       {N_("/C_ut"),           NULL, addressbook_treenode_cut_cb,    0, NULL, NULL},
+       {N_("/_Copy"),          NULL, addressbook_treenode_copy_cb,   0, NULL, NULL},
+       {N_("/_Paste"),         NULL, addressbook_treenode_paste_cb,  0, NULL, NULL}
 };
 
 static GtkItemFactoryEntry addressbook_list_popup_entries[] =
 {
-       {N_("/_Select all"),    NULL, addressbook_select_all_cb, 0, NULL},
-       {"/---",                NULL, NULL, 0, "<Separator>"},
-       {N_("/_Edit"),          NULL, addressbook_edit_address_cb,   0, NULL},
-       {N_("/_Delete"),        NULL, addressbook_delete_address_cb, 0, NULL},
-       {"/---",                NULL, NULL, 0, "<Separator>"},
-       {N_("/New _Address"),   NULL, addressbook_new_address_cb,    0, NULL},
-       {N_("/New _Group"),     NULL, addressbook_new_group_cb,      0, NULL},
-       {"/---",                NULL, NULL, 0, "<Separator>"},
-       {N_("/C_ut"),           NULL, addressbook_clip_cut_cb,       0, NULL},
-       {N_("/_Copy"),          NULL, addressbook_clip_copy_cb,      0, NULL},
-       {N_("/_Paste"),         NULL, addressbook_clip_paste_cb,     0, NULL},
-       {"/---",                NULL, NULL, 0, "<Separator>"},
-/*     {N_("/Pa_ste Address"), NULL, addressbook_clip_paste_address_cb, 0, NULL},*/
-       {N_("/_Mail To"),       NULL, addressbook_mail_to_cb,            0, NULL},
+       {N_("/_Select all"),    NULL, addressbook_select_all_cb, 0, NULL, NULL},
+       {"/---",                NULL, NULL, 0, "<Separator>", NULL},
+       {N_("/_Edit"),          NULL, addressbook_edit_address_cb,   0, NULL, NULL},
+       {N_("/_Delete"),        NULL, addressbook_delete_address_cb, 0, NULL, NULL},
+       {"/---",                NULL, NULL, 0, "<Separator>", NULL},
+       {N_("/New _Address"),   NULL, addressbook_new_address_cb,    0, NULL, NULL},
+       {N_("/New _Group"),     NULL, addressbook_new_group_cb,      0, NULL, NULL},
+       {"/---",                NULL, NULL, 0, "<Separator>", NULL},
+       {N_("/C_ut"),           NULL, addressbook_clip_cut_cb,       0, NULL, NULL},
+       {N_("/_Copy"),          NULL, addressbook_clip_copy_cb,      0, NULL, NULL},
+       {N_("/_Paste"),         NULL, addressbook_clip_paste_cb,     0, NULL, NULL},
+       {"/---",                NULL, NULL, 0, "<Separator>", NULL},
+/*     {N_("/Pa_ste Address"), NULL, addressbook_clip_paste_address_cb, 0, NULL, NULL},*/
+       {N_("/_Mail To"),       NULL, addressbook_mail_to_cb,            0, NULL, NULL},
 #ifdef USE_LDAP
-       {N_("/_Browse Entry"),  NULL, addressbook_browse_entry_cb,       0, NULL},
+       {N_("/_Browse Entry"),  NULL, addressbook_browse_entry_cb,       0, NULL, NULL},
 #endif 
 };
 
@@ -545,7 +551,7 @@ static ErrMsgTableEntry _lutErrorsLDAP_[] = {
        { LDAPRC_NOENTRIES,                     N_("No LDAP entries found for search criteria") },
        { LDAPRC_STOP_FLAG,                     N_("LDAP search terminated on request") },
        { LDAPRC_TLS,                           N_("Error starting TLS connection") },
-       { LDAPRC_NODN,                          N_("Distinguised Name (dn) is missing") },
+       { LDAPRC_NODN,                          N_("Distinguished Name (dn) is missing") },
        { LDAPRC_NAMING_VIOLATION,              N_("Missing required information") },
        { LDAPRC_ALREADY_EXIST,                 N_("Another contact exists with that key") },
        { LDAPRC_STRONG_AUTH,                   N_("Strong(er) authentication required") },
@@ -686,7 +692,7 @@ Compose *addressbook_get_target_compose(void)
 /**
  * Refresh addressbook and save to file(s).
  */
-static void addressbook_refresh( void )
+void addressbook_refresh( void )
 {
        if (addrbook.window) {
                if (addrbook.treeSelected) {
@@ -745,7 +751,7 @@ static gint list_case_sort(
                        name2 = GTK_CELL_TEXT (row2->cell[sort_column_number])->text;
                if( ! name1 ) return ( name2 != NULL );
                if( ! name2 ) return -1;
-               return strcasecmp( name1, name2 );
+               return g_utf8_collate( name1, name2 );
        } else {
                /* Order groups before person */
                if( aio1->type == ITEMTYPE_GROUP ) {
@@ -1446,6 +1452,8 @@ static void addressbook_del_clicked(GtkButton *button, gpointer data)
                        item = node->data;
                        node = g_list_next( node );
                        aio = ( AddrItemObject * ) item->addressItem;
+                       if (!aio)
+                               continue;
                        if( aio->type == ADDR_ITEM_GROUP ) {
                                ItemGroup *item = ( ItemGroup * ) aio;
                                GtkCTreeNode *nd = NULL;
@@ -1474,6 +1482,10 @@ static void addressbook_del_clicked(GtkButton *button, gpointer data)
                                }
 #endif
                                if( item ) {
+                                       gchar *filename = addritem_person_get_picture(item);
+                                       if (filename && is_file_exist(filename))
+                                               g_unlink(filename);
+                                       g_free(filename);
                                        addritem_free_item_person( item );
                                }
                        }
@@ -2260,7 +2272,7 @@ static void addressbook_list_row_selected( GtkCTree *clist,
 
        aio = gtk_ctree_node_get_row_data( clist, node );
        if( aio ) {
-               /* printf( "list select: %d : '%s'\n", aio->type, aio->name ); */
+               /* g_print( "list select: %d : '%s'\n", aio->type, aio->name ); */
                addressbook_list_select_add( aio, ds );
        }
 
@@ -2279,7 +2291,7 @@ static void addressbook_list_row_unselected( GtkCTree *ctree,
 
        aio = gtk_ctree_node_get_row_data( ctree, node );
        if( aio != NULL ) {
-               /* printf( "list unselect: %d : '%s'\n", aio->type, aio->name ); */
+               /* g_print( "list unselect: %d : '%s'\n", aio->type, aio->name ); */
                addressbook_list_select_remove( aio );
        }
 
@@ -2813,12 +2825,12 @@ static void addressbook_treenode_delete_cb(
 
                adapter->itemFolder = NULL;
                /*
-               printf( "remove folder for ::%s::\n", obj->name );
-               printf( "      folder name ::%s::\n", ADDRITEM_NAME(folder) );
-               printf( "-------------- remove results\n" );
+               g_print( "remove folder for ::%s::\n", obj->name );
+               g_print( "      folder name ::%s::\n", ADDRITEM_NAME(folder) );
+               g_print( "-------------- remove results\n" );
                */
                addrindex_remove_results( ds, folder );
-               /* printf( "-------------- remove node\n" ); */
+               /* g_print( "-------------- remove node\n" ); */
                gtk_ctree_remove_node( ctree, node );
                return;
        }
@@ -3003,7 +3015,7 @@ static void addressbook_new_address_cb( gpointer data, guint action, GtkWidget *
 
        abf = ds->rawDataSource;
        if( abf == NULL ) {
-               printf("no addressbook file\n");
+               g_print("no addressbook file\n");
                return;
        }
 
@@ -3187,7 +3199,10 @@ static void addressbook_move_nodes_up( GtkCTree *ctree, GtkCTreeNode *node ) {
 static void addressbook_edit_address_post_cb( ItemPerson *person )
 {
        if( person ) {
-
+#ifdef USE_LDAP
+               if (strcmp2(person->nickName, ADDRITEM_NAME(person)))
+                       addritem_person_set_nick_name( person, ADDRITEM_NAME(person));
+#endif
                addressbook_folder_refresh_one_person( GTK_CTREE(addrbook.clist), person );
                invalidate_address_completion();
        }
@@ -3404,7 +3419,9 @@ static void addressbook_folder_load_one_person(
        gchar *text[N_LIST_COLS];
        gboolean flgFirst = TRUE, haveAddr = FALSE;
        GList *node;
+#ifdef USE_LDAP
        AddressBookFile *abf = addressbook_get_book_file();
+#endif
 
        if( person == NULL ) return;
 
@@ -3653,10 +3670,10 @@ static AddressDataSource *addressbook_find_datasource( GtkCTreeNode *node ) {
                if( GTK_CTREE_ROW(node)->level < 2 ) return NULL;
                ao = gtk_ctree_node_get_row_data( GTK_CTREE(addrbook.ctree), node );
                if( ao ) {
-                       /* printf( "ao->type = %d\n", ao->type ); */
+                       /* g_print( "ao->type = %d\n", ao->type ); */
                        if( ao->type == ADDR_DATASOURCE ) {
                                AdapterDSource *ads = ADAPTER_DSOURCE(ao);
-                               /* printf( "found it\n" ); */
+                               /* g_print( "found it\n" ); */
                                ds = ads->dataSource;
                                break;
                        }
@@ -3690,7 +3707,7 @@ static void addressbook_set_clist( AddressObject *obj, gboolean refresh ) {
        }
 
        if( obj->type == ADDR_INTERFACE ) {
-               /* printf( "set_clist: loading datasource...\n" ); */
+               /* g_print( "set_clist: loading datasource...\n" ); */
                /* addressbook_node_load_datasource( GTK_CTREE(clist), obj ); */
                return;
        }
@@ -3909,9 +3926,61 @@ static gboolean addressbook_convert( AddressIndex *addrIndex ) {
        return retVal;
 }
 
+static gboolean migrate_addrbook(const gchar *origdir, const gchar *destdir)
+{
+       DIR *dp;
+       struct dirent *d;
+       gboolean failed = FALSE;
+
+       if( ( dp = opendir( origdir ) ) == NULL ) {
+               return FALSE;
+       }
+       
+       while( ( d = readdir( dp ) ) != NULL ) {
+               if (strncmp(d->d_name, "addrbook-", strlen("addrbook-")))
+                       continue;
+               else {
+                       gchar *orig_file = g_strconcat(origdir, G_DIR_SEPARATOR_S, 
+                                       d->d_name, NULL);
+                       gchar *dest_file = g_strconcat(destdir, G_DIR_SEPARATOR_S, 
+                                       d->d_name, NULL);
+                       if (copy_file(orig_file, dest_file, FALSE) < 0) {
+                               failed = TRUE;
+                       }
+                       g_free(orig_file);
+                       g_free(dest_file);
+                       if (failed) {
+                               break;
+                       }
+               }
+       }
+
+       closedir( dp );
+       if (!failed) {
+               /* all copies succeeded, we can remove source files */
+               if( ( dp = opendir( origdir ) ) == NULL ) {
+                       return FALSE;
+               }
+               while( ( d = readdir( dp ) ) != NULL ) {
+                       if (strncmp(d->d_name, "addrbook-", strlen("addrbook-")))
+                               continue;
+                       else {
+                               gchar *orig_file = g_strconcat(origdir, G_DIR_SEPARATOR_S, 
+                                               d->d_name, NULL);
+                               g_unlink(orig_file);
+                               g_free(orig_file);
+                       }
+               }
+               closedir( dp );
+       }
+       
+       return !failed;
+}
+
 void addressbook_read_file( void ) {
        AddressIndex *addrIndex = NULL;
-
+       gchar *indexdir = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, ADDRBOOK_DIR, NULL);
+       
        debug_print( "Reading address index...\n" );
        if( _addressIndex_ ) {
                debug_print( "address book already read!!!\n" );
@@ -3922,7 +3991,24 @@ void addressbook_read_file( void ) {
        addrindex_initialize();
 
        /* Use new address book index. */
-       addrindex_set_file_path( addrIndex, get_rc_dir() );
+       
+       if ( !is_dir_exist(indexdir) ) {
+               if ( make_dir(indexdir) < 0 ) {
+                       addrindex_set_file_path( addrIndex, get_rc_dir() );
+                       g_warning( "couldn't create dir %s\n", indexdir);
+               } else {
+                       if (!migrate_addrbook(get_rc_dir(), indexdir)) {
+                               remove_dir_recursive(indexdir);
+                               addrindex_set_file_path( addrIndex, get_rc_dir() );
+                               g_error("couldn't migrate dir %s", indexdir);
+                       } else {
+                               addrindex_set_file_path( addrIndex, indexdir);
+                       }
+               }
+       } else {
+               addrindex_set_file_path( addrIndex, indexdir);
+       }
+       g_free(indexdir);
        addrindex_set_file_name( addrIndex, ADDRESSBOOK_INDEX_FILE );
        addrindex_read_data( addrIndex );
        if( addrIndex->retVal == MGU_NO_FILE ) {
@@ -4280,7 +4366,7 @@ static void addressbook_search_idle( gpointer data ) {
        gint queryID;
 
        queryID = GPOINTER_TO_INT( data );
-       printf( "addressbook_ldap_idle... queryID=%d\n", queryID );
+       g_print( "addressbook_ldap_idle... queryID=%d\n", queryID );
        */
 }
 
@@ -4577,7 +4663,7 @@ static void addrbookctl_build_map( GtkWidget *window ) {
        atci->showInTree = FALSE;
        atci->treeExpand = FALSE;
        atci->treeLeaf = TRUE;
-       atci->displayName = _( "EMail Address" );
+       atci->displayName = _( "Email Address" );
        atci->iconXpm = addressxpm;
        atci->maskXpm = addressxpmmask;
        atci->iconXpmOpen = addressxpm;
@@ -4828,7 +4914,7 @@ static void addrbookctl_build_ifselect( void ) {
        splitStr = g_strsplit( selectStr, ",", -1 );
        for( i = 0; i < ADDRESSBOOK_MAX_IFACE; i++ ) {
                if( splitStr[i] ) {
-                       /* printf( "%d : %s\n", i, splitStr[i] ); */
+                       /* g_print( "%d : %s\n", i, splitStr[i] ); */
                        ifType = strtol( splitStr[i], &endptr, 10 );
                        enabled = TRUE;
                        if( *endptr ) {
@@ -4836,7 +4922,7 @@ static void addrbookctl_build_ifselect( void ) {
                                        enabled = FALSE;
                                }
                        }
-                       /* printf( "\t%d : %s\n", ifType, enabled ? "yes" : "no" ); */
+                       /* g_print( "\t%d : %s\n", ifType, enabled ? "yes" : "no" ); */
                        adapter = addrbookctl_find_interface( ifType );
                        if( adapter ) {
                                newList = g_list_append( newList, adapter );
@@ -4846,7 +4932,7 @@ static void addrbookctl_build_ifselect( void ) {
                        break;
                }
        }
-       /* printf( "i=%d\n", i ); */
+       /* g_print( "i=%d\n", i ); */
        g_strfreev( splitStr );
        g_free( selectStr );
 
@@ -4866,10 +4952,11 @@ static void addrbookctl_build_ifselect( void ) {
  * This function is used by the Add sender to address book function.
  */
 gboolean addressbook_add_contact(
-               const gchar *name, const gchar *address, const gchar *remarks )
+               const gchar *name, const gchar *address, const gchar *remarks,
+               GdkPixbuf *picture )
 {
        debug_print( "addressbook_add_contact: name/address: %s - %s\n", name, address );
-       if( addressadd_selection( _addressIndex_, name, address, remarks ) ) {
+       if( addressadd_selection( _addressIndex_, name, address, remarks, picture ) ) {
                debug_print( "addressbook_add_contact - added\n" );
                addressbook_refresh();
        }
@@ -5282,6 +5369,11 @@ static void addressbook_export_ldif_cb( void ) {
        addressbook_exp_ldif( cache );
 }
 
+static void addressbook_find_duplicates_cb(void)
+{
+       addrduplicates_find(GTK_WINDOW(addrbook.window));       
+}
+
 static void addressbook_start_drag(GtkWidget *widget, gint button, 
                                   GdkEvent *event,
                                   void *data)
@@ -5339,11 +5431,11 @@ static void addressbook_drag_data_get(GtkWidget        *widget,
                if( ds && ds->interface && ds->interface->readOnly)
                        gtk_selection_data_set(selection_data,
                                       selection_data->target, 8,
-                                      "Dummy_addr_copy", 15);
+                                      (const guchar *)"Dummy_addr_copy", 15);
                else
                        gtk_selection_data_set(selection_data,
                                       selection_data->target, 8,
-                                      "Dummy_addr_move", 15);
+                                      (const guchar *)"Dummy_addr_move", 15);
        } 
 }
 
@@ -5366,12 +5458,14 @@ static gboolean addressbook_drag_motion_cb(GtkWidget      *widget,
        if (gtk_clist_get_selection_info
                (GTK_CLIST(widget), x - 24, y - 24, &row, &column)) {
 
-               if (y > height - 24 && height + vpos < total_height)
+               if (y > height - 24 && height + vpos < total_height) {
                        gtk_adjustment_set_value(pos, (vpos+5 > height ? height : vpos+5));
-
-               if (y < 24 && y > 0)
+                       gtk_adjustment_changed(pos);
+               }
+               if (y < 24 && y > 0) {
                        gtk_adjustment_set_value(pos, (vpos-5 < 0 ? 0 : vpos-5));
-
+                       gtk_adjustment_changed(pos);
+               }
                node = gtk_ctree_node_nth(GTK_CTREE(widget), row);
 
                if (node != NULL) {