2006-07-31 [wwp] 2.4.0cvs3
authorTristan Chabredier <wwp@claws-mail.org>
Mon, 31 Jul 2006 12:03:02 +0000 (12:03 +0000)
committerTristan Chabredier <wwp@claws-mail.org>
Mon, 31 Jul 2006 12:03:02 +0000 (12:03 +0000)
* src/Makefile.am
* src/addr_compl.c
* src/addr_compl.h
* src/addressbook.c
* src/addressbook.h
* src/addressbook_foldersel.c
* src/addressbook_foldersel.h
* src/addrindex.c
* src/addrindex.h
* src/matcher.c
* src/matcher.h
* src/matcher_parser_lex.l
* src/matcher_parser_parse.y
* src/prefs_common.c
* src/prefs_common.h
* src/prefs_filtering.c
* src/prefs_matcher.c
* src/prefs_matcher.h
* src/summaryview.c
introduce filtering against the address book. It's now possible to add
matched conditions to determine if any email address in a message matches
or doesn't match any or all books or folders in the address book.

22 files changed:
ChangeLog
PATCHSETS
configure.ac
src/Makefile.am
src/addr_compl.c
src/addr_compl.h
src/addressbook.c
src/addressbook.h
src/addressbook_foldersel.c [new file with mode: 0644]
src/addressbook_foldersel.h [new file with mode: 0644]
src/addrindex.c
src/addrindex.h
src/matcher.c
src/matcher.h
src/matcher_parser_lex.l
src/matcher_parser_parse.y
src/prefs_common.c
src/prefs_common.h
src/prefs_filtering.c
src/prefs_matcher.c
src/prefs_matcher.h
src/summaryview.c

index c0b587285300df68badead28b61ad062707db9f0..64717e1bf46c58952387e29b855c687ca42d5e36 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2006-07-31 [wwp]       2.4.0cvs3
+
+       * src/Makefile.am
+       * src/addr_compl.c
+       * src/addr_compl.h
+       * src/addressbook.c
+       * src/addressbook.h
+       * src/addressbook_foldersel.c
+       * src/addressbook_foldersel.h
+       * src/addrindex.c
+       * src/addrindex.h
+       * src/matcher.c
+       * src/matcher.h
+       * src/matcher_parser_lex.l
+       * src/matcher_parser_parse.y
+       * src/prefs_common.c
+       * src/prefs_common.h
+       * src/prefs_filtering.c
+       * src/prefs_matcher.c
+       * src/prefs_matcher.h
+       * src/summaryview.c
+               introduce filtering against the address book. It's now possible to add
+               matched conditions to determine if any email address in a message matches
+               or doesn't match any or all books or folders in the address book.
+
 2006-07-31 [wwp]       2.4.0cvs2
 
        * src/account.c
 2006-07-31 [wwp]       2.4.0cvs2
 
        * src/account.c
index c0d857a4aa81f9cc9bdb3c81480af38a0b23f18c..2f680078a38f6821f622a06d7f345df20f46ce38 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.1.2.9 -r 1.1.2.10 po/ca.po;  ) > 2.3.1cvs91.patchset
 ( cvs diff -u -r 1.8.2.8 -r 1.8.2.9 src/quote_fmt.c;  ) > 2.4.0cvs1.patchset
 ( cvs diff -u -r 1.61.2.48 -r 1.61.2.49 src/account.c;  cvs diff -u -r 1.60.2.19 -r 1.60.2.20 src/filtering.c;  cvs diff -u -r 1.21.2.7 -r 1.21.2.8 src/filtering.h;  cvs diff -u -r 1.213.2.105 -r 1.213.2.106 src/folder.c;  cvs diff -u -r 1.207.2.110 -r 1.207.2.111 src/folderview.c;  cvs diff -u -r 1.149.2.54 -r 1.149.2.55 src/inc.c;  cvs diff -u -r 1.274.2.127 -r 1.274.2.128 src/mainwindow.c;  cvs diff -u -r 1.75.2.26 -r 1.75.2.27 src/matcher.c;  cvs diff -u -r 1.16.2.6 -r 1.16.2.7 src/matcher_parser_lex.l;  cvs diff -u -r 1.25.2.14 -r 1.25.2.15 src/matcher_parser_parse.y;  cvs diff -u -r 1.28.2.22 -r 1.28.2.23 src/mbox.c;  cvs diff -u -r 1.59.2.36 -r 1.59.2.37 src/prefs_filtering.c;  cvs diff -u -r 1.6.2.4 -r 1.6.2.5 src/prefs_filtering.h;  cvs diff -u -r 1.150.2.69 -r 1.150.2.70 src/procmsg.c;  cvs diff -u -r 1.60.2.29 -r 1.60.2.30 src/procmsg.h;  cvs diff -u -r 1.395.2.223 -r 1.395.2.224 src/summaryview.c;  ) > 2.4.0cvs2.patchset
 ( cvs diff -u -r 1.1.2.9 -r 1.1.2.10 po/ca.po;  ) > 2.3.1cvs91.patchset
 ( cvs diff -u -r 1.8.2.8 -r 1.8.2.9 src/quote_fmt.c;  ) > 2.4.0cvs1.patchset
 ( cvs diff -u -r 1.61.2.48 -r 1.61.2.49 src/account.c;  cvs diff -u -r 1.60.2.19 -r 1.60.2.20 src/filtering.c;  cvs diff -u -r 1.21.2.7 -r 1.21.2.8 src/filtering.h;  cvs diff -u -r 1.213.2.105 -r 1.213.2.106 src/folder.c;  cvs diff -u -r 1.207.2.110 -r 1.207.2.111 src/folderview.c;  cvs diff -u -r 1.149.2.54 -r 1.149.2.55 src/inc.c;  cvs diff -u -r 1.274.2.127 -r 1.274.2.128 src/mainwindow.c;  cvs diff -u -r 1.75.2.26 -r 1.75.2.27 src/matcher.c;  cvs diff -u -r 1.16.2.6 -r 1.16.2.7 src/matcher_parser_lex.l;  cvs diff -u -r 1.25.2.14 -r 1.25.2.15 src/matcher_parser_parse.y;  cvs diff -u -r 1.28.2.22 -r 1.28.2.23 src/mbox.c;  cvs diff -u -r 1.59.2.36 -r 1.59.2.37 src/prefs_filtering.c;  cvs diff -u -r 1.6.2.4 -r 1.6.2.5 src/prefs_filtering.h;  cvs diff -u -r 1.150.2.69 -r 1.150.2.70 src/procmsg.c;  cvs diff -u -r 1.60.2.29 -r 1.60.2.30 src/procmsg.h;  cvs diff -u -r 1.395.2.223 -r 1.395.2.224 src/summaryview.c;  ) > 2.4.0cvs2.patchset
+( cvs diff -u -r 1.155.2.39 -r 1.155.2.40 src/Makefile.am;  cvs diff -u -r 1.27.2.18 -r 1.27.2.19 src/addr_compl.c;  cvs diff -u -r 1.8.2.4 -r 1.8.2.5 src/addr_compl.h;  cvs diff -u -r 1.60.2.59 -r 1.60.2.60 src/addressbook.c;  cvs diff -u -r 1.18.2.2 -r 1.18.2.3 src/addressbook.h;  diff -u /dev/null src/addressbook_foldersel.c;  diff -u /dev/null src/addressbook_foldersel.h;  cvs diff -u -r 1.28.2.17 -r 1.28.2.18 src/addrindex.c;  cvs diff -u -r 1.9.2.6 -r 1.9.2.7 src/addrindex.h;  cvs diff -u -r 1.75.2.27 -r 1.75.2.28 src/matcher.c;  cvs diff -u -r 1.39.2.7 -r 1.39.2.8 src/matcher.h;  cvs diff -u -r 1.16.2.7 -r 1.16.2.8 src/matcher_parser_lex.l;  cvs diff -u -r 1.25.2.15 -r 1.25.2.16 src/matcher_parser_parse.y;  cvs diff -u -r 1.204.2.92 -r 1.204.2.93 src/prefs_common.c;  cvs diff -u -r 1.103.2.54 -r 1.103.2.55 src/prefs_common.h;  cvs diff -u -r 1.59.2.37 -r 1.59.2.38 src/prefs_filtering.c;  cvs diff -u -r 1.43.2.40 -r 1.43.2.41 src/prefs_matcher.c;  cvs diff -u -r 1.4.2.3 -r 1.4.2.4 src/prefs_matcher.h;  cvs diff -u -r 1.395.2.224 -r 1.395.2.225 src/summaryview.c;  ) > 2.4.0cvs3.patchset
index 611fa8e9285de6991bd74686e9ae979240d04dac..e95bee47ba2c9b0ff106a243175451f0c60b5bd1 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=4
 MICRO_VERSION=0
 INTERFACE_AGE=0
 BINARY_AGE=0
 MICRO_VERSION=0
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=2
+EXTRA_VERSION=3
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index bac640abfbc6ba57de5fac50dec91e77d0d09cec..867632a0041bd1dd8fc4503fae06c5cd5901c1b4 100644 (file)
@@ -20,6 +20,7 @@ sylpheed_claws_SOURCES = \
        addr_compl.c \
        addressadd.c \
        addressbook.c \
        addr_compl.c \
        addressadd.c \
        addressbook.c \
+       addressbook_foldersel.c \
        addrgather.c \
        addrharvest.c \
        addrindex.c \
        addrgather.c \
        addrharvest.c \
        addrindex.c \
@@ -157,6 +158,7 @@ sylpheed_clawsinclude_HEADERS = \
        addrdefs.h \
        addressadd.h \
        addressbook.h \
        addrdefs.h \
        addressadd.h \
        addressbook.h \
+       addressbook_foldersel.h \
        addressitem.h \
        addrgather.h \
        addrharvest.h \
        addressitem.h \
        addrgather.h \
        addrharvest.h \
index 75bffcb2d9d21af0a53af59c593f0097d2d62d21..f2d3986843574c85a116c063bab60febb4b5ec5b 100644 (file)
@@ -113,6 +113,8 @@ static gchar           *g_completion_prefix;        /* last prefix. (this is cached here
                                                 * because the prefix passed to g_completion
                                                 * is g_strdown()'ed */
 
                                                 * because the prefix passed to g_completion
                                                 * is g_strdown()'ed */
 
+static gchar *completion_folder_path = NULL;
+
 /*******************************************************************************/
 
 /*
 /*******************************************************************************/
 
 /*
@@ -259,8 +261,8 @@ static gint add_address(const gchar *name, const gchar *address,
 /**
  * Read address book, creating all entries in the completion index.
  */ 
 /**
  * Read address book, creating all entries in the completion index.
  */ 
-static void read_address_book(void) {  
-       addrindex_load_completion( add_address );
+static void read_address_book(gchar *folderpath) {     
+       addrindex_load_completion( add_address, folderpath );
        g_address_list = g_list_reverse(g_address_list);
        g_completion_list = g_list_reverse(g_completion_list);
 }
        g_address_list = g_list_reverse(g_address_list);
        g_completion_list = g_list_reverse(g_completion_list);
 }
@@ -298,19 +300,42 @@ static void clear_completion_cache(void)
  * address completion.
  * \return The number of addresses in the completion list.
  */
  * address completion.
  * \return The number of addresses in the completion list.
  */
-gint start_address_completion(void)
+gint start_address_completion(gchar *folderpath)
 {
        clear_completion_cache();
 {
        clear_completion_cache();
+
+       if ((completion_folder_path == NULL && folderpath != NULL) ||
+               (completion_folder_path != NULL && folderpath == NULL) ||
+               (completion_folder_path != NULL && folderpath != NULL &&
+                strcmp(completion_folder_path, folderpath) != 0)) {
+
+               debug_print("start_address_completion: resetting\n");
+
+               /* TODO: wwp: optimize: only reset when the new folderpath is MORE restrictive than the old one
+                 (the most easy case is when folderpath is NULL and completion_folder_path is != NULL */
+               if (g_ref_count) {
+                       free_all();
+                       g_ref_count = 0;
+               }
+       }
+
+       g_free(completion_folder_path);
+       if (folderpath != NULL)
+               completion_folder_path = g_strdup(folderpath);
+       else
+               completion_folder_path = NULL;
+
        if (!g_ref_count) {
                init_all();
                /* open the address book */
        if (!g_ref_count) {
                init_all();
                /* open the address book */
-               read_address_book();
+               read_address_book(folderpath);
                /* merge the completion entry list into g_completion */
                if (g_completion_list)
                        g_completion_add_items(g_completion, g_completion_list);
        }
        g_ref_count++;
                /* merge the completion entry list into g_completion */
                if (g_completion_list)
                        g_completion_add_items(g_completion, g_completion_list);
        }
        g_ref_count++;
-       debug_print("start_address_completion ref count %d\n", g_ref_count);
+       debug_print("start_address_completion(%s) ref count %d\n",
+                               folderpath, g_ref_count);
 
        return g_list_length(g_completion_list);
 }
 
        return g_list_length(g_completion_list);
 }
@@ -402,10 +427,11 @@ static void replace_address_in_edit(GtkEntry *entry, const gchar *newtext,
  */
 guint complete_address(const gchar *str)
 {
  */
 guint complete_address(const gchar *str)
 {
-       GList *result;
-       gchar *d;
-       guint  count, cpl;
-       completion_entry *ce;
+       GList *result = NULL;
+       gchar *d = NULL;
+       guint  count = 0;
+       guint  cpl = 0;
+       completion_entry *ce = NULL;
 
        g_return_val_if_fail(str != NULL, 0);
 
 
        g_return_val_if_fail(str != NULL, 0);
 
@@ -524,7 +550,8 @@ gint invalidate_address_completion(void)
                debug_print("Invalidation request for address completion\n");
                free_all();
                init_all();
                debug_print("Invalidation request for address completion\n");
                free_all();
                init_all();
-               read_address_book();
+               read_address_book(completion_folder_path);
+               if (g_completion_list)
                g_completion_add_items(g_completion, g_completion_list);
                clear_completion_cache();
        }
                g_completion_add_items(g_completion, g_completion_list);
                clear_completion_cache();
        }
@@ -949,7 +976,7 @@ static void completion_window_apply_selection(GtkTreeView *list_view, GtkEntry *
  */
 void address_completion_start(GtkWidget *mainwindow)
 {
  */
 void address_completion_start(GtkWidget *mainwindow)
 {
-       start_address_completion();
+       start_address_completion(NULL);
 
        /* register focus change hook */
        g_signal_connect(G_OBJECT(mainwindow), "set_focus",
 
        /* register focus change hook */
        g_signal_connect(G_OBJECT(mainwindow), "set_focus",
index cf2896499eb0166e6b8c7c2feb4b23faa2afda7c..10a4ebd17bf5a8e58aa942f79fa5c597d9cb7f7d 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <gtk/gtk.h>
 
 
 #include <gtk/gtk.h>
 
-gint start_address_completion          (void);
+gint start_address_completion          (gchar *folderpath);
 guint complete_address                 (const gchar *str);
 gchar *get_complete_address            (gint index);
 gint invalidate_address_completion     (void);
 guint complete_address                 (const gchar *str);
 gchar *get_complete_address            (gint index);
 gint invalidate_address_completion     (void);
index 8ae1928467446b0e0bb4ddc65a0fc54801132fc0..60074e11a6a48cabc8390c9a16f88af6dc070b9c 100644 (file)
@@ -69,6 +69,7 @@
 #include "addrbook.h"
 #include "addrindex.h"
 #include "addressadd.h"
 #include "addrbook.h"
 #include "addrindex.h"
 #include "addressadd.h"
+#include "addressbook_foldersel.h"
 #include "vcard.h"
 #include "editvcard.h"
 #include "editgroup.h"
 #include "vcard.h"
 #include "editvcard.h"
 #include "editgroup.h"
@@ -115,6 +116,19 @@ typedef enum
        N_LIST_COLS     = 3
 } AddressListColumns;
 
        N_LIST_COLS     = 3
 } AddressListColumns;
 
+typedef struct {
+       AddressBookFile *book;
+       ItemFolder      *folder;
+} FolderInfo;
+
+typedef struct {
+       gchar **folder_path;
+       gboolean matched;
+       gint index;
+       AddressDataSource *book;
+       ItemFolder *folder;
+} FolderPathMatch;
+
 static gchar *list_titles[] = { N_("Name"),
                                 N_("Email Address"),
                                 N_("Remarks") };
 static gchar *list_titles[] = { N_("Name"),
                                 N_("Email Address"),
                                 N_("Remarks") };
@@ -4453,6 +4467,198 @@ gboolean addressbook_add_contact(
        return TRUE;
 }
 
        return TRUE;
 }
 
+/* ***********************************************************************
+ * Book/folder selection.
+ * ***********************************************************************
+ */
+
+/*
+ * This function is used by the matcher dialog to select a book/folder.
+ */
+gboolean addressbook_folder_selection( gchar **folderpath )
+{
+       AddressBookFile *book = NULL;
+       ItemFolder *folder = NULL;
+       gchar *path;
+
+       g_return_val_if_fail( folderpath != NULL, FALSE);
+
+       path = *folderpath;
+       *folderpath = NULL;
+       if ( addressbook_foldersel_selection( _addressIndex_, &book, &folder, path )
+               && book != NULL ) {
+               if ( folder != NULL) {
+                       gchar *tmp = NULL;
+                       gchar *oldtmp = NULL;
+                       AddrItemObject *obj = NULL;
+
+                       /* walk thru folder->parent to build the full folder path */
+                       /* TODO: wwp: optimize this */
+                       obj = &folder->obj;
+                       tmp = g_strdup(obj->uid);
+                       while ( obj->parent ) {
+                               obj = obj->parent;
+                               if ( obj->name != NULL ) {
+                                       oldtmp = g_strdup(tmp);
+                                       g_free(tmp);
+                                       tmp = g_strdup_printf("%s/%s", obj->uid, oldtmp);
+                                       g_free(oldtmp);
+                               }
+                       }
+                       *folderpath = g_strdup_printf("%s/%s", book->fileName, tmp);
+                       g_free(tmp);
+               } else {
+                       *folderpath = g_strdup_printf("%s", book->fileName);
+               }
+               debug_print( "addressbook_foldersel: %s\n", *folderpath);
+               return (*folderpath != NULL);
+       }
+       return FALSE;
+}
+
+/* ***********************************************************************
+ * Book/folder checking.
+ * ***********************************************************************
+ */
+
+static FolderInfo *addressbook_peek_subfolder_exists_create_folderinfo( AddressBookFile *abf, ItemFolder *folder )
+{
+       FolderInfo *fi = g_new0( FolderInfo, 1 );
+       fi->book   = abf;
+       fi->folder = folder;
+       return fi;
+}
+
+static void addressbook_peek_subfolder_exists_load_folder( ItemFolder *parentFolder,
+                                       FolderInfo *fiParent, FolderPathMatch *match )
+{
+       GList *list;
+       ItemFolder *folder;
+       gchar *fName;
+       FolderInfo *fi;
+       FolderPathMatch *nextmatch = NULL;
+
+       list = parentFolder->listFolder;
+       while ( list ) {
+               folder = list->data;
+               fName = g_strdup( ADDRITEM_NAME(folder) );
+
+               /* match folder name, match pointer will be set to NULL if next recursive call
+                  doesn't need to match subfolder name */
+               if ( match != NULL &&
+                        match->matched == FALSE ) {
+                       if ( strcmp(match->folder_path[match->index], folder->obj.uid) == 0 ) {
+                               /* folder name matches, prepare next subfolder match */
+                               debug_print("matched folder name '%s'\n", fName);
+                               match->index++;
+                               if ( match->folder_path[match->index] == NULL ) {
+                                       /* we've matched all elements */
+                                       match->matched = TRUE;
+                                       match->folder = folder;
+                                       debug_print("book/folder path matched!\n");
+                               } else {
+                                       /* keep on matching */
+                                       nextmatch = match;
+                               }
+                       }
+               }
+
+               g_free( fName );
+
+               fi = addressbook_peek_subfolder_exists_create_folderinfo( fiParent->book, folder );
+               addressbook_peek_subfolder_exists_load_folder( folder, fi, nextmatch );
+               list = g_list_next( list );
+       }
+}
+
+/*
+ * This function is used by to check if a matcher book/folder path corresponds to an
+   existing addressbook book/folder ("" or "Any" are considered as valid, NULL invalid).
+ */
+
+gboolean addressbook_peek_folder_exists( gchar *folderpath,
+                                                                                AddressDataSource **book,
+                                                                                ItemFolder **folder )
+{
+       AddressDataSource *ds;
+       GList *list, *nodeDS;
+       ItemFolder *rootFolder;
+       AddressBookFile *abf;
+       FolderInfo *fi;
+       FolderPathMatch folder_path_match = { NULL, FALSE, 0, NULL, NULL };
+       FolderPathMatch *nextmatch;
+
+       if ( book )
+               *book = NULL;
+       if ( folder )
+               *folder = NULL;
+
+       if ( folderpath == NULL )
+               return FALSE;
+
+       if ( strcasecmp(folderpath, _("Any")) == 0 || *folderpath == '\0' )
+               return TRUE;
+
+       /* split the folder path we've received, we'll try to match this path, subpath by
+          subpath against the book/folder structure in order */
+       folder_path_match.folder_path = g_strsplit( folderpath, "/", 256 );
+
+       list = addrindex_get_interface_list( _addressIndex_ );
+       while ( list ) {
+               AddressInterface *interface = list->data;
+               if ( interface->type == ADDR_IF_BOOK ) {
+                       nodeDS = interface->listSource;
+                       while ( nodeDS ) {
+                               ds = nodeDS->data;
+
+                               /* Read address book */
+                               if( ! addrindex_ds_get_read_flag( ds ) ) {
+                                       addrindex_ds_read_data( ds );
+                               }
+
+                               /* Add node for address book */
+                               abf = ds->rawDataSource;
+
+                               /* try to match subfolders if this book is the right book
+                                       (and if there's smth to match, and not yet matched) */
+                               nextmatch = NULL;
+                               if ( folder_path_match.folder_path != NULL &&
+                                        folder_path_match.matched == FALSE &&
+                                        strcmp(folder_path_match.folder_path[0], abf->fileName) == 0 ) {
+                                       debug_print("matched book name '%s'\n", abf->fileName);
+                                       folder_path_match.index = 1;
+                                       if ( folder_path_match.folder_path[folder_path_match.index] == NULL ) {
+                                               /* we've matched all elements */
+                                               folder_path_match.matched = TRUE;
+                                               folder_path_match.book = ds;
+                                               debug_print("book path matched!\n");
+                                       } else {
+                                               /* keep on matching */
+                                               nextmatch = &folder_path_match;
+                                       }
+                               }
+
+                               fi = addressbook_peek_subfolder_exists_create_folderinfo( abf, NULL );
+
+                               rootFolder = addrindex_ds_get_root_folder( ds );
+                               addressbook_peek_subfolder_exists_load_folder( rootFolder, fi, nextmatch );
+
+                               nodeDS = g_list_next( nodeDS );
+                       }
+               }
+               list = g_list_next( list );
+       }
+
+       g_strfreev( folder_path_match.folder_path );
+
+       if ( book )
+               *book = folder_path_match.book;
+       if ( folder )
+               *folder = folder_path_match.folder;
+       return folder_path_match.matched;
+}
+
+
 /* **********************************************************************
  * Address Import.
  * ***********************************************************************
 /* **********************************************************************
  * Address Import.
  * ***********************************************************************
index 23c888df582e0cc42651e87d098ff6a9d2bde15c..c83fcd10c829ded7a6d618723bb2965ec91a3846 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "compose.h"
 #include "addritem.h"
 
 #include "compose.h"
 #include "addritem.h"
+#include "addrindex.h"
 
 void addressbook_open                  ( Compose *target );
 void addressbook_set_target_compose    ( Compose *target );
 
 void addressbook_open                  ( Compose *target );
 void addressbook_set_target_compose    ( Compose *target );
@@ -39,6 +40,11 @@ gboolean addressbook_add_contact     ( const gchar *name,
                                          const gchar *address,
                                          const gchar *remarks );
                                          
                                          const gchar *address,
                                          const gchar *remarks );
                                          
+gboolean addressbook_folder_selection( gchar **folderpath );
+gboolean addressbook_peek_folder_exists( gchar *folderpath,
+                                                                                AddressDataSource **book,
+                                                                                ItemFolder **folder );
+
 gboolean addressbook_load_completion   (gint (*callBackFunc) 
                                               (const gchar *, 
                                                const gchar *, 
 gboolean addressbook_load_completion   (gint (*callBackFunc) 
                                               (const gchar *, 
                                                const gchar *, 
diff --git a/src/addressbook_foldersel.c b/src/addressbook_foldersel.c
new file mode 100644 (file)
index 0000000..f33ae2d
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2001-2006 Match Grun and the Sylpheed-Claws team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Add address to address book dialog.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "defs.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkhbbox.h>
+#include <gtk/gtkbutton.h>
+
+#include "gtkutils.h"
+#include "stock_pixmap.h"
+#include "prefs_common.h"
+#include "addressadd.h"
+#include "addritem.h"
+#include "addrbook.h"
+#include "addrindex.h"
+#include "manage_window.h"
+
+typedef struct {
+       AddressBookFile *book;
+       ItemFolder      *folder;
+} FolderInfo;
+
+typedef struct {
+       gchar **folder_path;
+       gboolean matched;
+       gint index;
+       GtkCTreeNode *node;
+} FolderPathMatch;
+
+static struct _AddressBookFolderSel_dlg {
+       GtkWidget *window;
+       GtkWidget *tree_folder;
+       GtkWidget *ok_btn;
+       GtkWidget *cancel_btn;
+       gint status_cid;
+       FolderInfo *fiSelected;
+} addressbook_foldersel_dlg;
+
+static GdkPixmap *folderXpm;
+static GdkBitmap *folderXpmMask;
+static GdkPixmap *bookXpm;
+static GdkBitmap *bookXpmMask;
+
+static gboolean addressbook_foldersel_cancelled;
+
+static FolderInfo *addressbook_foldersel_create_folderinfo( AddressBookFile *abf, ItemFolder *folder )
+{
+       FolderInfo *fi = g_new0( FolderInfo, 1 );
+       fi->book   = abf;
+       fi->folder = folder;
+       return fi;
+}
+
+static void addressbook_foldersel_free_folderinfo( FolderInfo *fi ) {
+       fi->book   = NULL;
+       fi->folder = NULL;
+       g_free( fi );
+}
+
+static gint addressbook_foldersel_delete_event( GtkWidget *widget, GdkEventAny *event, gboolean *cancelled )
+{
+       addressbook_foldersel_cancelled = TRUE;
+       gtk_main_quit();
+       return TRUE;
+}
+
+static gboolean addressbook_foldersel_key_pressed( GtkWidget *widget, GdkEventKey *event, gboolean *cancelled )
+{
+       if ( event && event->keyval == GDK_Escape ) {
+               addressbook_foldersel_cancelled = TRUE;
+               gtk_main_quit();
+       }
+       return FALSE;
+}
+
+static void addressbook_foldersel_ok( GtkWidget *widget, gboolean *cancelled )
+{
+       addressbook_foldersel_cancelled = FALSE;
+       gtk_main_quit();
+}
+
+static void addressbook_foldersel_cancel( GtkWidget *widget, gboolean *cancelled )
+{
+       addressbook_foldersel_cancelled = TRUE;
+       gtk_main_quit();
+}
+
+static void addressbook_foldersel_folder_select( GtkCTree *ctree, gint row, gint column,
+                                       GdkEvent *event, gpointer data )
+{
+       addressbook_foldersel_dlg.fiSelected = gtk_clist_get_row_data( GTK_CLIST(ctree), row );
+}
+
+static gboolean addressbook_foldersel_tree_button( GtkCTree *ctree, GdkEventButton *event, gpointer data )
+{
+       if ( ! event )
+               return FALSE;
+       if ( event->button == 1 ) {
+               /* Handle double click */
+               if ( event->type == GDK_2BUTTON_PRESS ) {
+                       addressbook_foldersel_cancelled = FALSE;
+                       gtk_main_quit();
+               }
+       }
+
+       return FALSE;
+}
+
+static void addressbook_foldersel_size_allocate_cb(GtkWidget *widget,
+                                        GtkAllocation *allocation)
+{
+       g_return_if_fail(allocation != NULL);
+
+       prefs_common.addressbook_folderselwin_width = allocation->width;
+       prefs_common.addressbook_folderselwin_height = allocation->height;
+}
+
+static void addressbook_foldersel_create( void )
+{
+       GtkWidget *window;
+       GtkWidget *vbox;
+       GtkWidget *tree_folder;
+       GtkWidget *vlbox;
+       GtkWidget *tree_win;
+       GtkWidget *hbbox;
+       GtkWidget *ok_btn;
+       GtkWidget *cancel_btn;
+       static GdkGeometry geometry;
+
+       window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+       gtk_container_set_border_width( GTK_CONTAINER(window), 0 );
+       gtk_window_set_title( GTK_WINDOW(window), _("Select Address Book Folder") );
+       gtk_window_set_position( GTK_WINDOW(window), GTK_WIN_POS_MOUSE );
+       gtk_window_set_modal( GTK_WINDOW(window), TRUE );
+       g_signal_connect( G_OBJECT(window), "delete_event",
+                         G_CALLBACK(addressbook_foldersel_delete_event), NULL );
+       g_signal_connect( G_OBJECT(window), "key_press_event",
+                         G_CALLBACK(addressbook_foldersel_key_pressed), NULL );
+       g_signal_connect(G_OBJECT(window), "size_allocate",
+                        G_CALLBACK(addressbook_foldersel_size_allocate_cb), NULL);
+
+       vbox = gtk_vbox_new(FALSE, 8);
+       gtk_container_add(GTK_CONTAINER(window), vbox);
+       gtk_container_set_border_width( GTK_CONTAINER(vbox), 8 );
+
+       /* Address book/folder tree */
+       vlbox = gtk_vbox_new(FALSE, 8);
+       gtk_box_pack_start(GTK_BOX(vbox), vlbox, TRUE, TRUE, 0);
+       gtk_container_set_border_width( GTK_CONTAINER(vlbox), 8 );
+
+       tree_win = gtk_scrolled_window_new( NULL, NULL );
+       gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(tree_win),
+                                       GTK_POLICY_AUTOMATIC,
+                                       GTK_POLICY_AUTOMATIC );
+       gtk_box_pack_start( GTK_BOX(vlbox), tree_win, TRUE, TRUE, 0 );
+
+       tree_folder = gtk_ctree_new( 1, 0 );
+       gtk_container_add( GTK_CONTAINER(tree_win), tree_folder );
+       gtk_clist_column_titles_show( GTK_CLIST(tree_folder) );
+       gtk_clist_set_column_title( GTK_CLIST(tree_folder), 0, _( "Address Book" ) );
+       gtk_ctree_set_line_style( GTK_CTREE(tree_folder), GTK_CTREE_LINES_DOTTED );
+       gtk_clist_set_selection_mode( GTK_CLIST(tree_folder), GTK_SELECTION_BROWSE );
+       gtk_ctree_set_expander_style( GTK_CTREE(tree_folder), GTK_CTREE_EXPANDER_SQUARE );
+       gtk_ctree_set_indent( GTK_CTREE(tree_folder), CTREE_INDENT );
+       gtk_clist_set_auto_sort( GTK_CLIST(tree_folder), TRUE );
+
+       /* Button panel */
+       gtkut_stock_button_set_create( &hbbox, &cancel_btn, GTK_STOCK_CANCEL,
+                                     &ok_btn, GTK_STOCK_OK,
+                                     NULL, NULL );
+       gtk_box_pack_end( GTK_BOX(vbox), hbbox, FALSE, FALSE, 0 );
+       gtk_container_set_border_width( GTK_CONTAINER(hbbox), 0 );
+       gtk_widget_grab_default( ok_btn );
+
+       g_signal_connect( G_OBJECT(ok_btn), "clicked",
+                        G_CALLBACK(addressbook_foldersel_ok), NULL );
+       g_signal_connect( G_OBJECT(cancel_btn), "clicked",
+                        G_CALLBACK(addressbook_foldersel_cancel), NULL );
+       g_signal_connect( G_OBJECT(tree_folder), "select_row",
+                        G_CALLBACK(addressbook_foldersel_folder_select), NULL );
+       g_signal_connect( G_OBJECT(tree_folder), "button_press_event",
+                        G_CALLBACK(addressbook_foldersel_tree_button), NULL );
+
+       if ( !geometry.min_height ) {
+               geometry.min_width = 300;
+               geometry.min_height = 350;
+       }
+
+       gtk_window_set_geometry_hints( GTK_WINDOW(window), NULL, &geometry,
+                                     GDK_HINT_MIN_SIZE );
+       gtk_widget_set_size_request( window, prefs_common.addressbook_folderselwin_width,
+                                   prefs_common.addressbook_folderselwin_height );
+
+       gtk_widget_show_all( vbox );
+
+       addressbook_foldersel_dlg.window      = window;
+       addressbook_foldersel_dlg.tree_folder = tree_folder;
+       addressbook_foldersel_dlg.ok_btn      = ok_btn;
+       addressbook_foldersel_dlg.cancel_btn  = cancel_btn;
+
+       gtk_widget_show_all( window );
+
+       stock_pixmap_gdk( window, STOCK_PIXMAP_BOOK, &bookXpm, &bookXpmMask );
+       stock_pixmap_gdk( window, STOCK_PIXMAP_DIR_OPEN,
+                         &folderXpm, &folderXpmMask );
+}
+
+static void addressbook_foldersel_load_folder( GtkCTreeNode *parentNode, ItemFolder *parentFolder,
+                                       FolderInfo *fiParent, FolderPathMatch *match )
+{
+       GtkCTree *tree = GTK_CTREE( addressbook_foldersel_dlg.tree_folder );
+       GList *list;
+       ItemFolder *folder;
+       gchar *fName;
+       gchar **name;
+       GtkCTreeNode *node;
+       FolderInfo *fi;
+       FolderPathMatch *nextmatch = NULL;
+
+       list = parentFolder->listFolder;
+       while ( list ) {
+               folder = list->data;
+               fName = g_strdup( ADDRITEM_NAME(folder) );
+
+               name = &fName;
+               node = gtk_sctree_insert_node( tree, parentNode, NULL, name, FOLDER_SPACING,
+                               folderXpm, folderXpmMask, folderXpm, folderXpmMask,
+                               FALSE, TRUE );
+
+               /* match folder name, match pointer will be set to NULL if next recursive call
+                  doesn't need to match subfolder name */
+               if ( match != NULL &&
+                        match->matched == FALSE ) {
+                       if ( strcmp(match->folder_path[match->index], folder->obj.uid) == 0 ) {
+                               /* folder name matches, prepare next subfolder match */
+
+                               debug_print("matched folder name '%s'\n", fName);
+
+                               match->index++;
+
+                               if ( match->folder_path[match->index] == NULL ) {
+                                       /* we've matched all elements */
+                                       match->matched = TRUE;
+                                       match->node = node;
+                                       debug_print("book/folder path matched!\n");
+                               } else {
+                                       /* keep on matching */
+                                       nextmatch = match;
+                               }
+                       }
+               }
+
+               g_free( fName );
+
+               fi = addressbook_foldersel_create_folderinfo( fiParent->book, folder );
+               gtk_ctree_node_set_row_data_full( tree, node, fi,
+                               ( GtkDestroyNotify ) addressbook_foldersel_free_folderinfo );
+               addressbook_foldersel_load_folder( node, folder, fi, nextmatch );
+               list = g_list_next( list );
+       }
+}
+
+static void addressbook_foldersel_load_data( AddressIndex *addrIndex, gchar *path, FolderPathMatch* match )
+{
+       AddressDataSource *ds;
+       GList *list, *nodeDS;
+       gchar **name;
+       gchar *dsName;
+       ItemFolder *rootFolder;
+       AddressBookFile *abf;
+       FolderInfo *fi;
+       GtkCTree *tree = GTK_CTREE( addressbook_foldersel_dlg.tree_folder );
+       GtkCTreeNode *node;
+       FolderPathMatch *nextmatch;
+
+       gtk_clist_clear( GTK_CLIST( tree ) );
+       list = addrindex_get_interface_list( addrIndex );
+       while ( list ) {
+               AddressInterface *interface = list->data;
+               if ( interface->type == ADDR_IF_BOOK ) {
+                       nodeDS = interface->listSource;
+                       while ( nodeDS ) {
+                               ds = nodeDS->data;
+                               dsName = g_strdup( addrindex_ds_get_name( ds ) );
+
+                               /* Read address book */
+                               if( ! addrindex_ds_get_read_flag( ds ) ) {
+                                       addrindex_ds_read_data( ds );
+                               }
+
+                               /* Add node for address book */
+                               abf = ds->rawDataSource;
+                               name = &dsName;
+                               node = gtk_sctree_insert_node( tree, NULL, NULL,
+                                               name, FOLDER_SPACING, bookXpm,
+                                               bookXpmMask, bookXpm, bookXpmMask,
+                                               FALSE, TRUE );
+                               g_free( dsName );
+
+                               /* try to match subfolders if this book is the right book
+                                       (and if there's smth to match, and not yet matched) */
+                               nextmatch = NULL;
+                               if ( match->folder_path != NULL &&
+                                        match->matched == FALSE &&
+                                        match->folder_path[0] != NULL &&
+                                        strcmp(match->folder_path[0], abf->fileName) == 0 ) {
+
+                                       debug_print("matched book name '%s'\n", abf->fileName);
+
+                                       match->index = 1;
+
+                                       if ( match->folder_path[match->index] == NULL ) {
+                                               /* we've matched all elements */
+                                               match->matched = TRUE;
+                                               match->node = node;
+                                               debug_print("book path matched!\n");
+                                       } else {
+                                               /* keep on matching */
+                                               nextmatch = match;
+                                       }
+                               }
+
+                               fi = addressbook_foldersel_create_folderinfo( abf, NULL );
+                               gtk_ctree_node_set_row_data_full( tree, node, fi,
+                                               ( GtkDestroyNotify ) addressbook_foldersel_free_folderinfo );
+
+                               rootFolder = addrindex_ds_get_root_folder( ds );
+                               addressbook_foldersel_load_folder( node, rootFolder, fi, nextmatch );
+
+                               nodeDS = g_list_next( nodeDS );
+                       }
+               }
+               list = g_list_next( list );
+       }
+}
+
+gboolean addressbook_foldersel_selection( AddressIndex *addrIndex,
+                                       AddressBookFile **book, ItemFolder **folder, gchar* path)
+{
+       gboolean retVal = FALSE;
+       addressbook_foldersel_cancelled = FALSE;
+       FolderPathMatch folder_path_match = { NULL, FALSE, 0, NULL };
+
+       if ( ! addressbook_foldersel_dlg.window )
+               addressbook_foldersel_create();
+       gtk_widget_grab_focus(addressbook_foldersel_dlg.ok_btn);
+       gtk_widget_show(addressbook_foldersel_dlg.window);
+       manage_window_set_transient(GTK_WINDOW(addressbook_foldersel_dlg.window));
+
+       addressbook_foldersel_dlg.fiSelected = NULL;
+
+       /* split the folder path we've received, we'll try to match this path, subpath by
+          subpath against the book/folder structure in order to select the folder that
+       corresponds to what we received */
+
+       if ( path != NULL ) {
+               if ( strcasecmp(path, _("Any")) == 0 || *path == '\0' )
+                       /* consider "Any" and "" as valid addressbook root */
+                       folder_path_match.matched = TRUE;
+               else
+                       folder_path_match.folder_path = g_strsplit( path, "/", 256 );
+       }
+
+       addressbook_foldersel_load_data( addrIndex, path, &folder_path_match );
+
+       if ( folder_path_match.folder_path != NULL && folder_path_match.matched == FALSE)
+               g_warning("addressbook_foldersel_load_data: couldn't match book/folder path '%s'\n", path);
+
+       g_strfreev( folder_path_match.folder_path );
+
+       if ( folder_path_match.node != NULL)
+               gtk_ctree_select( GTK_CTREE( addressbook_foldersel_dlg.tree_folder ),
+                                                       GTK_CTREE_NODE( folder_path_match.node ) );
+       else
+               gtk_clist_select_row( GTK_CLIST( addressbook_foldersel_dlg.tree_folder ), 0, 0 );
+       gtk_widget_show(addressbook_foldersel_dlg.window);
+
+       gtk_main();
+       gtk_widget_hide( addressbook_foldersel_dlg.window );
+
+       if ( ! addressbook_foldersel_cancelled ) {
+
+               *book = NULL;
+               *folder = NULL;
+
+               if ( addressbook_foldersel_dlg.fiSelected ) {
+                       *book = addressbook_foldersel_dlg.fiSelected->book;
+                       *folder = addressbook_foldersel_dlg.fiSelected->folder;
+                       retVal = TRUE;
+               }
+       }
+
+       gtk_clist_clear( GTK_CLIST( addressbook_foldersel_dlg.tree_folder ) );
+
+       return retVal;
+}
+
+/*
+* End of Source.
+*/
diff --git a/src/addressbook_foldersel.h b/src/addressbook_foldersel.h
new file mode 100644 (file)
index 0000000..62023e5
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2001-2006 Match Grun and the Sylpheed-Claws team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Add address to address book dialog.
+ */
+
+#ifndef __ADDRESSBOOK_FOLDERSEL_H__
+#define __ADDRESSBOOK_FOLDERSEL_H__
+
+#include "addrindex.h"
+
+gboolean addressbook_foldersel_selection( AddressIndex *addrIndex,
+                               AddressBookFile **book, ItemFolder **folder, gchar *path );
+
+#endif /* __ADDRESSBOOK_FOLDERSEL_H__ */
index 0b7af02c46131ea97f1093dbaa6755bca2ee5f6f..f98ca944c8dcf690988bd27e42a955964d7222d1 100644 (file)
@@ -34,6 +34,7 @@
 #include "addritem.h"
 #include "addrcache.h"
 #include "addrbook.h"
 #include "addritem.h"
 #include "addrcache.h"
 #include "addrbook.h"
+#include "addressbook.h"
 #include "addrindex.h"
 #include "xml.h"
 #include "addrquery.h"
 #include "addrindex.h"
 #include "xml.h"
 #include "addrquery.h"
@@ -2788,39 +2789,15 @@ void addrindex_remove_results( AddressDataSource *ds, ItemFolder *folder ) {
 * ***********************************************************************
 */
 
 * ***********************************************************************
 */
 
-/**
- * This function is used by the address completion function to load
- * addresses for all non-external address book interfaces.
- *
- * \param callBackFunc Function to be called when an address is
- *                     to be loaded.
- * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
- */
-gboolean addrindex_load_completion(
+static void addrindex_load_completion_load_persons(
                gint (*callBackFunc) ( const gchar *, const gchar *, 
                gint (*callBackFunc) ( const gchar *, const gchar *, 
-                                      const gchar *, const gchar * ) )
+                                      const gchar *, const gchar * ),
+               AddressDataSource *ds)
 {
 {
-       AddressDataSource *ds;
-       GList *nodeIf, *nodeDS;
        GList *listP, *nodeP;
        GList *nodeM;
        gchar *sName;
 
        GList *listP, *nodeP;
        GList *nodeM;
        gchar *sName;
 
-       nodeIf = addrindex_get_interface_list( _addressIndex_ );
-       while( nodeIf ) {
-               AddressInterface *iface = nodeIf->data;
-
-               nodeIf = g_list_next( nodeIf );
-               if( ! iface->useInterface ) {
-                       continue;
-               }
-               if( iface->externalQuery ) {
-                       continue;
-               }
-               nodeDS = iface->listSource;
-               while( nodeDS ) {
-                       ds = nodeDS->data;
-
                        /* Read address book */
                        if( addrindex_ds_get_modify_flag( ds ) ) {
                                addrindex_ds_read_data( ds );
                        /* Read address book */
                        if( addrindex_ds_get_modify_flag( ds ) ) {
                                addrindex_ds_read_data( ds );
@@ -2856,10 +2833,111 @@ gboolean addrindex_load_completion(
                        }
                        /* Free up the list */
                        g_list_free( listP );
                        }
                        /* Free up the list */
                        g_list_free( listP );
+}              
 
 
+/**
+ * This function is used by the address completion function to load
+ * addresses for all non-external address book interfaces.
+ *
+ * \param callBackFunc Function to be called when an address is
+ *                     to be loaded.
+ * \param folderpath Addressbook's Book/folder path to restrict to (if NULL or ""
+ *                     or "Any", assume the whole addressbook
+ * \return <i>TRUE</i> if data loaded, <i>FALSE</i> if address index not loaded.
+ */
+
+gboolean addrindex_load_completion(
+               gint (*callBackFunc) ( const gchar *, const gchar *, 
+                                      const gchar *, const gchar * ),
+               gchar *folderpath )
+{
+       GList *nodeIf, *nodeDS;
+
+       if( folderpath != NULL ) {
+               AddressDataSource *book;
+               ItemFolder* folder;
+
+               /* split the folder path we've received, we'll try to match this path, subpath by
+                  subpath against the book/folder structure in order and restrict loading of
+                  addresses to that subpart (if matches). book/folder path must exist and
+                  folderpath must not be empty or NULL */
+               
+               if( ! addressbook_peek_folder_exists( folderpath, &book, &folder ) ) {
+                       g_warning("addrindex_load_completion: folder path '%s' doesn't exist\n", folderpath);
+                       return FALSE;
+               }
+
+               if( book != NULL ) {
+                       AddressBookFile *abf = book->rawDataSource;
+
+                       debug_print("addrindex_load_completion: book %p '%s'\n", book, abf->fileName);
+
+                       addrindex_load_completion_load_persons( callBackFunc, book );
+
+                       return TRUE;
+
+               } else {
+
+                       if( folder != NULL ) {
+                               GList *items;
+                               GList *nodeM;
+                               gchar *sName;
+                               ItemPerson *person;
+
+                               debug_print("addrindex_load_completion: folder %p '%s'\n", folder, folder->obj.name);
+
+                               /* Load email addresses */
+                               items = addritem_folder_get_person_list( folder );
+                               for( ; items != NULL; items = g_list_next( items ) ) {
+                                       person = items->data;
+                                       nodeM = person->listEMail;
+
+                                       /* Figure out name to use */
+                                       sName = ADDRITEM_NAME(person);
+                                       if( sName == NULL || *sName == '\0' ) {
+                                               sName = person->nickName;
+                                       }
+
+                                       /* Process each E-Mail address */
+                                       while( nodeM ) {
+                                               ItemEMail *email = nodeM->data;
+
+                                               callBackFunc( sName, email->address, person->nickName, 
+                                                                 ADDRITEM_NAME(email) );
+
+                                               nodeM = g_list_next( nodeM );
+                                       }
+                               }
+                               /* Free up the list */
+                               mgu_clear_list( items );
+                               g_list_free( items );
+
+                               return TRUE;
+
+                       } else {
+                               g_warning("addrindex_load_completion: book/folder path is valid but got no pointer\n");
+                       }
+               }
+               return FALSE;
+
+       } else {
+
+               nodeIf = addrindex_get_interface_list( _addressIndex_ );
+               while( nodeIf ) {
+                       AddressInterface *iface = nodeIf->data;
+
+                       nodeIf = g_list_next( nodeIf );
+
+                       if( ! iface->useInterface || iface->externalQuery )
+                               continue;
+
+                       nodeDS = iface->listSource;
+                       while( nodeDS ) {
+                               addrindex_load_completion_load_persons( callBackFunc, nodeDS->data );
                        nodeDS = g_list_next( nodeDS );
                }
        }
                        nodeDS = g_list_next( nodeDS );
                }
        }
+       }
 
        return TRUE;
 }
 
        return TRUE;
 }
@@ -2887,12 +2965,10 @@ gboolean addrindex_load_person_attribute(
                AddressInterface *iface = nodeIf->data;
 
                nodeIf = g_list_next( nodeIf );
                AddressInterface *iface = nodeIf->data;
 
                nodeIf = g_list_next( nodeIf );
-               if( ! iface->useInterface ) {
-                       continue;
-               }
-               if( iface->externalQuery ) {
+
+               if( ! iface->useInterface || iface->externalQuery )
                        continue;
                        continue;
-               }
+
                nodeDS = iface->listSource;
                while( nodeDS ) {
                        ds = nodeDS->data;
                nodeDS = iface->listSource;
                while( nodeDS ) {
                        ds = nodeDS->data;
index 2eb5ff99b79914f6e499463804adb9a4fd9cd32a..31e089406658685dcc8e7b557ac2ac310f99ed81 100644 (file)
@@ -181,7 +181,8 @@ void addrindex_remove_results               ( AddressDataSource *ds,
 gboolean addrindex_load_completion(
                gint (*callBackFunc)
                        ( const gchar *, const gchar *, 
 gboolean addrindex_load_completion(
                gint (*callBackFunc)
                        ( const gchar *, const gchar *, 
-                         const gchar *, const gchar * ) );
+                         const gchar *, const gchar * ),
+                       gchar *folderpath );
 
 gboolean addrindex_load_person_attribute( const gchar *attr,
                gint (*callBackFunc)
 
 gboolean addrindex_load_person_attribute( const gchar *attr,
                gint (*callBackFunc)
index 3cbc7a8ecced74bc2d1ed79d8283f0a27e615fe5..44b6d9297555f6be4405184c44ed6d3bccba411d 100644 (file)
@@ -103,6 +103,8 @@ static const MatchParser matchparser_tab[] = {
        {MATCHCRITERIA_SCORE_EQUAL, "score_equal"},
        {MATCHCRITERIA_PARTIAL, "partial"},
        {MATCHCRITERIA_NOT_PARTIAL, "~partial"},
        {MATCHCRITERIA_SCORE_EQUAL, "score_equal"},
        {MATCHCRITERIA_PARTIAL, "partial"},
        {MATCHCRITERIA_NOT_PARTIAL, "~partial"},
+       {MATCHCRITERIA_FOUND_IN_ADDRESSBOOK, "found_in_addressbook"},
+       {MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK, "~found_in_addressbook"},
 
        {MATCHCRITERIA_SIZE_GREATER, "size_greater"},
        {MATCHCRITERIA_SIZE_SMALLER, "size_smaller"},
 
        {MATCHCRITERIA_SIZE_GREATER, "size_greater"},
        {MATCHCRITERIA_SIZE_SMALLER, "size_smaller"},
@@ -125,8 +127,6 @@ static const MatchParser matchparser_tab[] = {
        {MATCHTYPE_MATCH, "match"},
        {MATCHTYPE_REGEXPCASE, "regexpcase"},
        {MATCHTYPE_REGEXP, "regexp"},
        {MATCHTYPE_MATCH, "match"},
        {MATCHTYPE_REGEXPCASE, "regexpcase"},
        {MATCHTYPE_REGEXP, "regexp"},
-       {MATCHTYPE_ANY_IN_ADDRESSBOOK, "any_in_addressbook"},
-       {MATCHTYPE_ALL_IN_ADDRESSBOOK, "all_in_addressbook"},
 
        /* actions */
        {MATCHACTION_SCORE, "score"},    /* for backward compatibility */
 
        /* actions */
        {MATCHACTION_SCORE, "score"},    /* for backward compatibility */
@@ -151,6 +151,12 @@ static const MatchParser matchparser_tab[] = {
        {MATCHACTION_IGNORE, "ignore"},
 };
 
        {MATCHACTION_IGNORE, "ignore"},
 };
 
+enum {
+       MATCH_ANY = 0,
+       MATCH_ALL = 1,
+       MATCH_ONE = 2
+};
+
 /*!
  *\brief       Look up table with keywords defined in \sa matchparser_tab
  */
 /*!
  *\brief       Look up table with keywords defined in \sa matchparser_tab
  */
@@ -213,7 +219,8 @@ gint get_matchparser_tab_id(const gchar *str)
  *             "condition" (a matcher structure)
  *
  *\param       criteria Criteria ID (MATCHCRITERIA_XXXX)
  *             "condition" (a matcher structure)
  *
  *\param       criteria Criteria ID (MATCHCRITERIA_XXXX)
- *\param       header Header string (if criteria is MATCHCRITERIA_HEADER)
+ *\param       header Header string (if criteria is MATCHCRITERIA_HEADER
+                       or MATCHCRITERIA_FOUND_IN_ADDRESSBOOK)
  *\param       matchtype Type of action (MATCHTYPE_XXX)
  *\param       expr String value or expression to check
  *\param       value Integer value to check
  *\param       matchtype Type of action (MATCHTYPE_XXX)
  *\param       expr String value or expression to check
  *\param       value Integer value to check
@@ -280,38 +287,59 @@ MatcherProp *matcherprop_copy(const MatcherProp *src)
 /* ************** match ******************************/
 
 static gboolean match_with_addresses_in_addressbook
 /* ************** match ******************************/
 
 static gboolean match_with_addresses_in_addressbook
-       (MatcherProp *prop, const gchar *str, gint type)
+       (MatcherProp *prop, GSList *address_list, gint type,
+        gchar* folderpath, gint match)
 {
 {
-       GSList *address_list = NULL;
-       GSList *walk;
-       gboolean res = FALSE;
+       GSList *walk = NULL;
+       gboolean found = FALSE;
+       gchar *path = NULL;
 
 
-       if (str == NULL || *str == 0) 
-               return FALSE;
+       g_return_val_if_fail(address_list != NULL, FALSE);
+
+       debug_print("match_with_addresses_in_addressbook(%d, %s)\n",
+                               g_slist_length(address_list), folderpath);
+
+       if (folderpath == NULL ||
+               strcasecmp(folderpath, _("Any")) == 0 ||
+               *folderpath == '\0')
+               path = NULL;
+       else
+               path = folderpath;
        
        
-       /* XXX: perhaps complete with comments too */
-       address_list = address_list_append(address_list, str);
-       if (!address_list) 
-               return FALSE;
+       start_address_completion(path);
 
 
-       start_address_completion();             
-       res = FALSE;
        for (walk = address_list; walk != NULL; walk = walk->next) {
        for (walk = address_list; walk != NULL; walk = walk->next) {
-               gboolean found = complete_address(walk->data) ? TRUE : FALSE;
-               
+               /* exact matching of email address */
+               guint num_addr = complete_address(walk->data);
+               found = FALSE;
+               if (num_addr > 1) {
+                       /* skip first item (this is the search string itself) */
+                       int i = 1;
+                       for (; i < num_addr && !found; i++) {
+                               gchar *addr = get_complete_address(i);
+                               extract_address(addr);
+                               if (strcasecmp(addr, walk->data) == 0)
+                                       found = TRUE;
+                               g_free(addr);
+                       }
+               }
                g_free(walk->data);
                g_free(walk->data);
-               if (!found && type == MATCHTYPE_ALL_IN_ADDRESSBOOK) {
-                       res = FALSE;
+
+               if (match == MATCH_ALL) {
+                       /* if matching all addresses, stop if one doesn't match */
+                       if (!found)
                        break;
                        break;
-               } else if (found) 
-                       res = TRUE;
+               } else if (match == MATCH_ANY) {
+                       /* if matching any address, stop if one does match */
+                       if (found)
+                               break;
+       }
+               /* MATCH_ONE: there should be only one loop iteration */
        }
        }
-
-       g_slist_free(address_list);
 
        end_address_completion();
        
 
        end_address_completion();
        
-       return res;
+       return found;
 }
 
 /*!
 }
 
 /*!
@@ -354,11 +382,6 @@ static gboolean matcherprop_string_match(MatcherProp *prop, const gchar *str)
                else
                        return FALSE;
                        
                else
                        return FALSE;
                        
-       case MATCHTYPE_ALL_IN_ADDRESSBOOK:      
-       case MATCHTYPE_ANY_IN_ADDRESSBOOK:
-               return match_with_addresses_in_addressbook
-                       (prop, str, prop->matchtype);
-
        case MATCHTYPE_MATCH:
                return (strstr(str, prop->expr) != NULL);
 
        case MATCHTYPE_MATCH:
                return (strstr(str, prop->expr) != NULL);
 
@@ -624,7 +647,7 @@ gboolean matcherprop_match(MatcherProp *prop,
        case MATCHCRITERIA_NOT_TEST:
                return !matcherprop_match_test(prop, info);
        default:
        case MATCHCRITERIA_NOT_TEST:
                return !matcherprop_match_test(prop, info);
        default:
-               return 0;
+               return FALSE;
        }
 }
 
        }
 }
 
@@ -690,8 +713,8 @@ static void matcherlist_skip_headers(FILE *fp)
 static gboolean matcherprop_match_one_header(MatcherProp *matcher,
                                             gchar *buf)
 {
 static gboolean matcherprop_match_one_header(MatcherProp *matcher,
                                             gchar *buf)
 {
-       gboolean result;
-       Header *header;
+       gboolean result = FALSE;
+       Header *header = NULL;
 
        switch (matcher->criteria) {
        case MATCHCRITERIA_HEADER:
 
        switch (matcher->criteria) {
        case MATCHCRITERIA_HEADER:
@@ -720,7 +743,57 @@ static gboolean matcherprop_match_one_header(MatcherProp *matcher,
                return !matcherprop_string_decode_match(matcher, buf);
        case MATCHCRITERIA_NOT_HEADERS_PART:
                return !matcherprop_string_match(matcher, buf);
                return !matcherprop_string_decode_match(matcher, buf);
        case MATCHCRITERIA_NOT_HEADERS_PART:
                return !matcherprop_string_match(matcher, buf);
+       case MATCHCRITERIA_FOUND_IN_ADDRESSBOOK:
+       case MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK:
+               {
+                       GSList *address_list = NULL;
+                       gint match = MATCH_ONE;
+                       gboolean found = FALSE;
+
+                       /* how many address headers are me trying to mach? */
+                       if (strcasecmp(matcher->header, _("Any")) == 0)
+                               match = MATCH_ANY;
+                       else if (strcasecmp(matcher->header, _("All")) == 0)
+                                       match = MATCH_ALL;
+
+                       if (match == MATCH_ONE) {
+                               /* matching one address header exactly, is that the right one? */
+                               header = procheader_parse_header(buf);
+                               if (!header ||
+                                               !procheader_headername_equal(header->name, matcher->header))
+                                       return FALSE;
+                               address_list = address_list_append(address_list, header->body);
+                               if (address_list == NULL)
+                                       return FALSE;
+
+                       } else {
+                               header = procheader_parse_header(buf);
+                               if (!header)
+                                       return FALSE;
+                               /* address header is one of the headers we have to match when checking
+                                  for any address header or all address headers? */
+                               if (procheader_headername_equal(header->name, "From") ||
+                                        procheader_headername_equal(header->name, "To") ||
+                                        procheader_headername_equal(header->name, "Cc") ||
+                                        procheader_headername_equal(header->name, "Reply-To") ||
+                                        procheader_headername_equal(header->name, "Sender"))
+                                       address_list = address_list_append(address_list, header->body);
+                               if (address_list == NULL)
+                                       return FALSE;
+                       }
+
+                       found = match_with_addresses_in_addressbook
+                                                       (matcher, address_list, matcher->criteria,
+                                                        matcher->expr, match);
+                       g_slist_free(address_list);
+
+                       if (matcher->criteria == MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK)
+                               return !found;
+                       else
+                               return found;
+       }
        }
        }
+
        return FALSE;
 }
 
        return FALSE;
 }
 
@@ -740,6 +813,8 @@ static gboolean matcherprop_criteria_headers(const MatcherProp *matcher)
        case MATCHCRITERIA_NOT_HEADER:
        case MATCHCRITERIA_HEADERS_PART:
        case MATCHCRITERIA_NOT_HEADERS_PART:
        case MATCHCRITERIA_NOT_HEADER:
        case MATCHCRITERIA_HEADERS_PART:
        case MATCHCRITERIA_NOT_HEADERS_PART:
+       case MATCHCRITERIA_FOUND_IN_ADDRESSBOOK:
+       case MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK:
                return TRUE;
        default:
                return FALSE;
                return TRUE;
        default:
                return FALSE;
@@ -785,14 +860,46 @@ static gboolean matcherlist_match_headers(MatcherList *matchers, FILE *fp)
        while (procheader_get_one_field(buf, sizeof(buf), fp, NULL) != -1) {
                for (l = matchers->matchers ; l != NULL ; l = g_slist_next(l)) {
                        MatcherProp *matcher = (MatcherProp *) l->data;
        while (procheader_get_one_field(buf, sizeof(buf), fp, NULL) != -1) {
                for (l = matchers->matchers ; l != NULL ; l = g_slist_next(l)) {
                        MatcherProp *matcher = (MatcherProp *) l->data;
+                       gint match = MATCH_ANY;
 
                        if (matcher->done)
                                continue;
 
 
                        if (matcher->done)
                                continue;
 
-                       /* if the criteria is ~headers_part or ~message, ZERO lines
-                        * must NOT match for the rule to match. */
+                       /* determine the match range (all, any are our concern here) */
                        if (matcher->criteria == MATCHCRITERIA_NOT_HEADERS_PART ||
                            matcher->criteria == MATCHCRITERIA_NOT_MESSAGE) {
                        if (matcher->criteria == MATCHCRITERIA_NOT_HEADERS_PART ||
                            matcher->criteria == MATCHCRITERIA_NOT_MESSAGE) {
+                               match = MATCH_ALL;
+
+                       } else if (matcher->criteria == MATCHCRITERIA_FOUND_IN_ADDRESSBOOK ||
+                                          matcher->criteria == MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK) {
+                               Header *header = NULL;
+
+                               /* address header is one of the headers we have to match when checking
+                                  for any address header or all address headers? */
+                               header = procheader_parse_header(buf);
+                               if (header &&
+                                       (procheader_headername_equal(header->name, "From") ||
+                                        procheader_headername_equal(header->name, "To") ||
+                                        procheader_headername_equal(header->name, "Cc") ||
+                                        procheader_headername_equal(header->name, "Reply-To") ||
+                                        procheader_headername_equal(header->name, "Sender"))) {
+
+                                       if (strcasecmp(matcher->header, _("Any")) == 0)
+                                               match = MATCH_ANY;
+                                       else if (strcasecmp(matcher->header, _("All")) == 0)
+                                               match = MATCH_ALL;
+                                       else
+                                               match = MATCH_ONE;
+                               } else {
+                                       /* further call to matcherprop_match_one_header() can't match
+                                          and it irrelevant, so: don't alter the match result */
+                                       continue;
+                               }
+                       }
+
+                       /* ZERO line must NOT match for the rule to match.
+                        */
+                       if (match == MATCH_ALL) {
                                if (matcherprop_match_one_header(matcher, buf)) {
                                        matcher->result = TRUE;
                                } else {
                                if (matcherprop_match_one_header(matcher, buf)) {
                                        matcher->result = TRUE;
                                } else {
@@ -802,7 +909,7 @@ static gboolean matcherlist_match_headers(MatcherList *matchers, FILE *fp)
                        /* else, just one line matching is enough for the rule to match
                         */
                        } else if (matcherprop_criteria_headers(matcher) ||
                        /* else, just one line matching is enough for the rule to match
                         */
                        } else if (matcherprop_criteria_headers(matcher) ||
-                                  matcherprop_criteria_message(matcher)){
+                                  matcherprop_criteria_message(matcher)) {
                                if (matcherprop_match_one_header(matcher, buf)) {
                                        matcher->result = TRUE;
                                        matcher->done = TRUE;
                                if (matcherprop_match_one_header(matcher, buf)) {
                                        matcher->result = TRUE;
                                        matcher->done = TRUE;
@@ -817,6 +924,7 @@ static gboolean matcherlist_match_headers(MatcherList *matchers, FILE *fp)
                        }
                }
        }
                        }
                }
        }
+
        return FALSE;
 }
 
        return FALSE;
 }
 
@@ -1180,6 +1288,7 @@ gchar *matcherprop_to_string(MatcherProp *matcher)
        const gchar *matchtype_str;
        int i;
        gchar * quoted_expr;
        const gchar *matchtype_str;
        int i;
        gchar * quoted_expr;
+       gchar * quoted_header;
        
        criteria_str = NULL;
        for (i = 0; i < (int) (sizeof(matchparser_tab) / sizeof(MatchParser)); i++) {
        
        criteria_str = NULL;
        for (i = 0; i < (int) (sizeof(matchparser_tab) / sizeof(MatchParser)); i++) {
@@ -1228,6 +1337,15 @@ gchar *matcherprop_to_string(MatcherProp *matcher)
                                              criteria_str, quoted_expr);
                g_free(quoted_expr);
                 return matcher_str;
                                              criteria_str, quoted_expr);
                g_free(quoted_expr);
                 return matcher_str;
+       case MATCHCRITERIA_FOUND_IN_ADDRESSBOOK:
+       case MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK:
+               quoted_header = matcher_quote_str(matcher->header);
+               quoted_expr = matcher_quote_str(matcher->expr);
+               matcher_str = g_strdup_printf("%s \"%s\" in \"%s\"",
+                                             criteria_str, quoted_header, quoted_expr);
+               g_free(quoted_header);
+               g_free(quoted_expr);
+               return matcher_str;
        }
 
        matchtype_str = NULL;
        }
 
        matchtype_str = NULL;
@@ -1244,12 +1362,8 @@ gchar *matcherprop_to_string(MatcherProp *matcher)
        case MATCHTYPE_MATCHCASE:
        case MATCHTYPE_REGEXP:
        case MATCHTYPE_REGEXPCASE:
        case MATCHTYPE_MATCHCASE:
        case MATCHTYPE_REGEXP:
        case MATCHTYPE_REGEXPCASE:
-       case MATCHTYPE_ALL_IN_ADDRESSBOOK:
-       case MATCHTYPE_ANY_IN_ADDRESSBOOK:
                quoted_expr = matcher_quote_str(matcher->expr);
                if (matcher->header) {
                quoted_expr = matcher_quote_str(matcher->expr);
                if (matcher->header) {
-                       gchar * quoted_header;
-                       
                        quoted_header = matcher_quote_str(matcher->header);
                        matcher_str = g_strdup_printf
                                        ("%s \"%s\" %s \"%s\"",
                        quoted_header = matcher_quote_str(matcher->header);
                        matcher_str = g_strdup_printf
                                        ("%s \"%s\" %s \"%s\"",
index 17e93f622b761e42b52c9d22e0c07a16aadda00f..f0f407bf278e2ae4af7434b61648ca839029ba6b 100644 (file)
@@ -101,13 +101,12 @@ enum {
        MC_(SIZE_GREATER), 
        MC_(SIZE_SMALLER),
        MC_(SIZE_EQUAL),
        MC_(SIZE_GREATER), 
        MC_(SIZE_SMALLER),
        MC_(SIZE_EQUAL),
+       MC_(FOUND_IN_ADDRESSBOOK),MC_(NOT_FOUND_IN_ADDRESSBOOK),
        /* match type */
        MT_(MATCHCASE),
        MT_(MATCH),
        MT_(REGEXPCASE),
        MT_(REGEXP),
        /* match type */
        MT_(MATCHCASE),
        MT_(MATCH),
        MT_(REGEXPCASE),
        MT_(REGEXP),
-       MT_(ANY_IN_ADDRESSBOOK),
-       MT_(ALL_IN_ADDRESSBOOK),
        /* actions */
        MA_(SCORE),
        MA_(EXECUTE),
        /* actions */
        MA_(SCORE),
        MA_(EXECUTE),
index 390490ee4afcd2e3626b7ef8648a4eb6f152652e..ef12ca921bba5869db16ff8487eaa16fcdf095b8 100644 (file)
@@ -57,6 +57,8 @@ void matcher_parser_init(void)
 
 %%
                        
 
 %%
                        
+"in"   return MATCHER_IN; 
+
                        /*
                         * a keyword consists of alpha and underscore 
                         * characters, possibly preceded by a tilde (~)
                        /*
                         * a keyword consists of alpha and underscore 
                         * characters, possibly preceded by a tilde (~)
index 5adbdd8a9e1b0c8ed03670d70b1a2ec69607a4b0..b9ca4a89b4ba3b92f3211bd7bfcf23dd18894fe0 100644 (file)
@@ -310,7 +310,7 @@ int matcher_parserwrap(void)
 %token MATCHER_NOT_MESSAGE  MATCHER_BODY_PART  MATCHER_NOT_BODY_PART
 %token MATCHER_TEST  MATCHER_NOT_TEST  MATCHER_MATCHCASE  MATCHER_MATCH
 %token MATCHER_REGEXPCASE  MATCHER_REGEXP  MATCHER_SCORE  MATCHER_MOVE
 %token MATCHER_NOT_MESSAGE  MATCHER_BODY_PART  MATCHER_NOT_BODY_PART
 %token MATCHER_TEST  MATCHER_NOT_TEST  MATCHER_MATCHCASE  MATCHER_MATCH
 %token MATCHER_REGEXPCASE  MATCHER_REGEXP  MATCHER_SCORE  MATCHER_MOVE
-%token MATCHER_ANY_IN_ADDRESSBOOK MATCHER_ALL_IN_ADDRESSBOOK
+%token MATCHER_FOUND_IN_ADDRESSBOOK MATCHER_NOT_FOUND_IN_ADDRESSBOOK MATCHER_IN
 %token MATCHER_COPY  MATCHER_DELETE  MATCHER_MARK  MATCHER_UNMARK
 %token MATCHER_LOCK MATCHER_UNLOCK
 %token MATCHER_EXECUTE
 %token MATCHER_COPY  MATCHER_DELETE  MATCHER_MARK  MATCHER_UNMARK
 %token MATCHER_LOCK MATCHER_UNLOCK
 %token MATCHER_EXECUTE
@@ -546,14 +546,6 @@ MATCHER_MATCHCASE
 {
        match_type = MATCHTYPE_REGEXP;
 }
 {
        match_type = MATCHTYPE_REGEXP;
 }
-| MATCHER_ANY_IN_ADDRESSBOOK
-{
-       match_type = MATCHTYPE_ANY_IN_ADDRESSBOOK;
-}
-| MATCHER_ALL_IN_ADDRESSBOOK
-{
-       match_type = MATCHTYPE_ALL_IN_ADDRESSBOOK;
-}
 ;
 
 condition:
 ;
 
 condition:
@@ -1000,6 +992,32 @@ MATCHER_ALL
        expr = $3;
        prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
 }
        expr = $3;
        prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
 }
+| MATCHER_FOUND_IN_ADDRESSBOOK MATCHER_STRING
+{
+       header = g_strdup($2);
+} MATCHER_IN MATCHER_STRING
+{
+       gint criteria = 0;
+       gchar *expr = NULL;
+
+       criteria = MATCHCRITERIA_FOUND_IN_ADDRESSBOOK;
+       expr = $2;
+       prop = matcherprop_new(criteria, header, match_type, expr, 0);
+       g_free(header);
+}
+| MATCHER_NOT_FOUND_IN_ADDRESSBOOK MATCHER_STRING
+{
+       header = g_strdup($2);
+} MATCHER_IN MATCHER_STRING
+{
+       gint criteria = 0;
+       gchar *expr = NULL;
+
+       criteria = MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK;
+       expr = $2;
+       prop = matcherprop_new(criteria, header, match_type, expr, 0);
+       g_free(header);
+}
 | MATCHER_MESSAGE match_type MATCHER_STRING
 {
        gint criteria = 0;
 | MATCHER_MESSAGE match_type MATCHER_STRING
 {
        gint criteria = 0;
index a519f0a65c68dffc8534629735d7df76b3d2f5b3..0a83b2d1172c4d63b1a4f7196befd6f250d509bd 100644 (file)
@@ -749,6 +749,11 @@ static PrefParam param[] = {
        {"addressaddwin_height", "-1", &prefs_common.addressaddwin_height, P_INT,
         NULL, NULL, NULL},
 
        {"addressaddwin_height", "-1", &prefs_common.addressaddwin_height, P_INT,
         NULL, NULL, NULL},
 
+       {"addressbook_folderselwin_width", "300", &prefs_common.addressbook_folderselwin_width, P_INT,
+        NULL, NULL, NULL},
+       {"addressbook_folderselwin_height", "-1", &prefs_common.addressbook_folderselwin_height, P_INT,
+        NULL, NULL, NULL},
+
        /* Hidden */
        {"warn_dnd", "1", &prefs_common.warn_dnd, P_INT,
         NULL, NULL, NULL},
        /* Hidden */
        {"warn_dnd", "1", &prefs_common.warn_dnd, P_INT,
         NULL, NULL, NULL},
index 95418f7f46c9c947141212b53f06d2db0ca5d580..6283e2fd581006f2dded559a55b60914846a39af 100644 (file)
@@ -378,6 +378,8 @@ struct _PrefsCommon
        gint folderselwin_height;
        gint addressaddwin_width;
        gint addressaddwin_height;
        gint folderselwin_height;
        gint addressaddwin_width;
        gint addressaddwin_height;
+       gint addressbook_folderselwin_width;
+       gint addressbook_folderselwin_height;
 
        gint warn_dnd;
        gint broken_are_utf8;
 
        gint warn_dnd;
        gint broken_are_utf8;
index cc2b5cf3da094d9e6d6b879ba2edf45d97b66cfa..177ce09146d82e1671b496f90a26563bff456862 100644 (file)
@@ -210,7 +210,7 @@ void prefs_filtering_open(GSList ** p_processing,
 
        gtk_widget_show(filtering.window);
 
 
        gtk_widget_show(filtering.window);
 
-       start_address_completion();
+       start_address_completion(NULL);
 }
 
 static void prefs_filtering_size_allocate_cb(GtkWidget *widget,
 }
 
 static void prefs_filtering_size_allocate_cb(GtkWidget *widget,
index 020089301e93bf7f8c4da6c67550ef8fb4f11206..c06da84529a7f373945a7668b668da0573500f1b 100644 (file)
@@ -67,6 +67,7 @@ static struct Matcher {
        GtkWidget *predicate_combo;
        GtkWidget *predicate_flag_combo;
        GtkWidget *header_combo;
        GtkWidget *predicate_combo;
        GtkWidget *predicate_flag_combo;
        GtkWidget *header_combo;
+       GtkWidget *header_addr_combo;
 
        GtkWidget *criteria_list;
 
 
        GtkWidget *criteria_list;
 
@@ -78,13 +79,18 @@ static struct Matcher {
 
        GtkWidget *header_entry;
        GtkWidget *header_label;
 
        GtkWidget *header_entry;
        GtkWidget *header_label;
+       GtkWidget *header_addr_entry;
+       GtkWidget *header_addr_label;
        GtkWidget *value_entry;
        GtkWidget *value_label;
        GtkWidget *value_entry;
        GtkWidget *value_label;
+       GtkWidget *addressbook_folder_label;
+       GtkWidget *addressbook_folder_combo;
        GtkWidget *case_chkbtn;
        GtkWidget *regexp_chkbtn;
        GtkWidget *color_optmenu;
 
        GtkWidget *test_btn;
        GtkWidget *case_chkbtn;
        GtkWidget *regexp_chkbtn;
        GtkWidget *color_optmenu;
 
        GtkWidget *test_btn;
+       GtkWidget *addressbook_select_btn;
 
        GtkWidget *cond_list_view;
 
 
        GtkWidget *cond_list_view;
 
@@ -140,7 +146,9 @@ enum {
        CRITERIA_SIZE_SMALLER = 29,
        CRITERIA_SIZE_EQUAL   = 30,
        
        CRITERIA_SIZE_SMALLER = 29,
        CRITERIA_SIZE_EQUAL   = 30,
        
-       CRITERIA_PARTIAL = 31
+       CRITERIA_PARTIAL = 31,
+
+       CRITERIA_FOUND_IN_ADDRESSBOOK = 32
 };
 
 /*!
 };
 
 /*!
@@ -165,7 +173,8 @@ static const gchar *criteria_text [] = {
        N_("Size greater than"), 
        N_("Size smaller than"),
        N_("Size exactly"),
        N_("Size greater than"), 
        N_("Size smaller than"),
        N_("Size exactly"),
-       N_("Partially downloaded")
+       N_("Partially downloaded"),
+       N_("Found in addressbook")
 };
 
 /*!
 };
 
 /*!
@@ -202,6 +211,13 @@ static const gchar *predicate_text [] = {
        N_("contains"), N_("does not contain")
 };
 
        N_("contains"), N_("does not contain")
 };
 
+/*!
+ *\brief       Preset addressbook book/folder items
+ */
+static const gchar *addressbook_folder_text [] = {
+       N_("Any")
+};
+
 /*!
  *\brief       Enabled predicate
  *
 /*!
  *\brief       Enabled predicate
  *
@@ -348,11 +364,16 @@ static void prefs_matcher_create(void)
        GtkWidget *header_combo;
        GtkWidget *header_entry;
        GtkWidget *header_label;
        GtkWidget *header_combo;
        GtkWidget *header_entry;
        GtkWidget *header_label;
+       GtkWidget *header_addr_combo;
+       GtkWidget *header_addr_entry;
+       GtkWidget *header_addr_label;
        GtkWidget *criteria_combo;
        GtkWidget *criteria_list;
        GtkWidget *criteria_label;
        GtkWidget *value_label;
        GtkWidget *value_entry;
        GtkWidget *criteria_combo;
        GtkWidget *criteria_list;
        GtkWidget *criteria_label;
        GtkWidget *value_label;
        GtkWidget *value_entry;
+       GtkWidget *addressbook_folder_label;
+       GtkWidget *addressbook_folder_combo;
        GtkWidget *predicate_combo;
        GtkWidget *predicate_list;
        GtkWidget *predicate_flag_combo;
        GtkWidget *predicate_combo;
        GtkWidget *predicate_list;
        GtkWidget *predicate_flag_combo;
@@ -381,6 +402,7 @@ static void prefs_matcher_create(void)
        GtkWidget *down_btn;
 
        GtkWidget *test_btn;
        GtkWidget *down_btn;
 
        GtkWidget *test_btn;
+       GtkWidget *addressbook_select_btn;
 
        GtkWidget *color_optmenu;
 
 
        GtkWidget *color_optmenu;
 
@@ -485,6 +507,23 @@ static void prefs_matcher_create(void)
        header_entry = GTK_COMBO(header_combo)->entry;
        gtk_entry_set_editable(GTK_ENTRY(header_entry), TRUE);
 
        header_entry = GTK_COMBO(header_combo)->entry;
        gtk_entry_set_editable(GTK_ENTRY(header_entry), TRUE);
 
+       /* address header name */
+
+       header_addr_label = gtk_label_new(_("Address header"));
+       gtk_misc_set_alignment(GTK_MISC(header_addr_label), 0, 0.5);
+       gtk_table_attach(GTK_TABLE(criteria_table), header_addr_label, 1, 2, 0, 1,
+                        GTK_FILL, 0, 0, 0);
+
+       header_addr_combo = gtk_combo_new();
+       gtk_widget_set_size_request(header_addr_combo, 120, -1);
+       gtkut_combo_set_items(GTK_COMBO (header_addr_combo),
+                             _("All"), _("Any"), "From", "To", "Cc", "Reply-To", "Sender",
+                             NULL);
+       gtk_table_attach(GTK_TABLE(criteria_table), header_addr_combo, 1, 2, 1, 2,
+                        0, 0, 0, 0);
+       header_addr_entry = GTK_COMBO(header_addr_combo)->entry;
+       gtk_entry_set_editable(GTK_ENTRY(header_addr_entry), TRUE);
+
        /* value */
 
        value_label = gtk_label_new(_("Value"));
        /* value */
 
        value_label = gtk_label_new(_("Value"));
@@ -499,6 +538,30 @@ static void prefs_matcher_create(void)
        gtk_table_attach(GTK_TABLE(criteria_table), value_entry, 2, 3, 1, 2,
                         GTK_FILL | GTK_SHRINK | GTK_EXPAND, 0, 0, 0);
 
        gtk_table_attach(GTK_TABLE(criteria_table), value_entry, 2, 3, 1, 2,
                         GTK_FILL | GTK_SHRINK | GTK_EXPAND, 0, 0, 0);
 
+       /* book/folder value */
+
+       addressbook_folder_label = gtk_label_new(_("Book/folder"));
+       gtk_misc_set_alignment(GTK_MISC (addressbook_folder_label), 0, 0.5);
+       gtk_table_attach(GTK_TABLE(criteria_table), addressbook_folder_label, 2, 3, 0, 1,
+                        GTK_FILL | GTK_SHRINK | GTK_EXPAND, 0, 0, 0);
+
+       addressbook_folder_combo = gtk_combo_new();
+       gtk_widget_show(addressbook_folder_combo);
+       gtk_widget_set_size_request(addressbook_folder_combo, 200, -1);
+       gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(addressbook_folder_combo)->entry),
+                              TRUE);
+
+       combo_items = NULL;
+       for (i = 0; i < (gint) (sizeof(addressbook_folder_text) / sizeof(gchar *)); i++) {
+               combo_items = g_list_append(combo_items,
+                                           (gpointer) _(addressbook_folder_text[i]));
+       }
+       gtk_combo_set_popdown_strings(GTK_COMBO(addressbook_folder_combo), combo_items);
+       g_list_free(combo_items);
+
+       gtk_table_attach(GTK_TABLE(criteria_table), addressbook_folder_combo, 2, 3, 1, 2,
+                        GTK_FILL | GTK_SHRINK | GTK_EXPAND, 0, 0, 0);
+
 #if GTK_CHECK_VERSION(2, 8, 0)
        test_btn = gtk_button_new_from_stock(GTK_STOCK_INFO);
 #else
 #if GTK_CHECK_VERSION(2, 8, 0)
        test_btn = gtk_button_new_from_stock(GTK_STOCK_INFO);
 #else
@@ -511,6 +574,13 @@ static void prefs_matcher_create(void)
                         G_CALLBACK(prefs_matcher_test_info),
                         NULL);
 
                         G_CALLBACK(prefs_matcher_test_info),
                         NULL);
 
+       addressbook_select_btn = gtk_button_new_with_label(_(" Select... "));
+       gtk_table_attach(GTK_TABLE (criteria_table), addressbook_select_btn, 3, 4, 1, 2,
+                        0, 0, 0, 0);
+       g_signal_connect(G_OBJECT (addressbook_select_btn), "clicked",
+                        G_CALLBACK(prefs_matcher_addressbook_select),
+                        NULL);
+
        color_optmenu = gtk_option_menu_new();
        gtk_option_menu_set_menu(GTK_OPTION_MENU(color_optmenu),
                                 colorlabel_create_color_menu());
        color_optmenu = gtk_option_menu_new();
        gtk_option_menu_set_menu(GTK_OPTION_MENU(color_optmenu),
                                 colorlabel_create_color_menu());
@@ -684,6 +754,10 @@ static void prefs_matcher_create(void)
                                    prefs_common.matcherwin_height);
 
        gtk_widget_show_all(window);
                                    prefs_common.matcherwin_height);
 
        gtk_widget_show_all(window);
+       gtk_widget_hide(header_addr_label);
+       gtk_widget_hide(header_addr_combo);
+       gtk_widget_hide(addressbook_select_btn);
+       gtk_widget_hide(addressbook_folder_label);
 
        matcher.window    = window;
 
 
        matcher.window    = window;
 
@@ -693,8 +767,13 @@ static void prefs_matcher_create(void)
        matcher.header_combo = header_combo;
        matcher.header_entry = header_entry;
        matcher.header_label = header_label;
        matcher.header_combo = header_combo;
        matcher.header_entry = header_entry;
        matcher.header_label = header_label;
+       matcher.header_addr_combo = header_addr_combo;
+       matcher.header_addr_entry = header_addr_entry;
+       matcher.header_addr_label = header_addr_label;
        matcher.value_entry = value_entry;
        matcher.value_label = value_label;
        matcher.value_entry = value_entry;
        matcher.value_label = value_label;
+       matcher.addressbook_folder_label = addressbook_folder_label;
+       matcher.addressbook_folder_combo = addressbook_folder_combo;
        matcher.predicate_label = predicate_label;
        matcher.predicate_list = predicate_list;
        matcher.predicate_combo = predicate_combo;
        matcher.predicate_label = predicate_label;
        matcher.predicate_list = predicate_list;
        matcher.predicate_combo = predicate_combo;
@@ -704,6 +783,7 @@ static void prefs_matcher_create(void)
        matcher.regexp_chkbtn = regexp_chkbtn;
        matcher.bool_op_list = bool_op_list;
        matcher.test_btn = test_btn;
        matcher.regexp_chkbtn = regexp_chkbtn;
        matcher.bool_op_list = bool_op_list;
        matcher.test_btn = test_btn;
+       matcher.addressbook_select_btn = addressbook_select_btn;
        matcher.color_optmenu = color_optmenu;
        matcher.criteria_table = criteria_table;
 
        matcher.color_optmenu = color_optmenu;
        matcher.criteria_table = criteria_table;
 
@@ -751,7 +831,9 @@ static void prefs_matcher_reset_condition(void)
        gtk_list_select_item(GTK_LIST(matcher.criteria_list), 0);
        gtk_list_select_item(GTK_LIST(matcher.predicate_list), 0);
        gtk_entry_set_text(GTK_ENTRY(matcher.header_entry), "");
        gtk_list_select_item(GTK_LIST(matcher.criteria_list), 0);
        gtk_list_select_item(GTK_LIST(matcher.predicate_list), 0);
        gtk_entry_set_text(GTK_ENTRY(matcher.header_entry), "");
+       gtk_entry_set_text(GTK_ENTRY(matcher.header_addr_entry), "");
        gtk_entry_set_text(GTK_ENTRY(matcher.value_entry), "");
        gtk_entry_set_text(GTK_ENTRY(matcher.value_entry), "");
+       gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(matcher.addressbook_folder_combo)->entry), "");
 }
 
 /*!
 }
 
 /*!
@@ -907,7 +989,6 @@ static gint prefs_matcher_get_criteria_from_matching(gint matching_id)
        case MATCHCRITERIA_NOT_MESSAGE:
        case MATCHCRITERIA_MESSAGE:
                return CRITERIA_MESSAGE;
        case MATCHCRITERIA_NOT_MESSAGE:
        case MATCHCRITERIA_MESSAGE:
                return CRITERIA_MESSAGE;
-               break;
        case MATCHCRITERIA_NOT_HEADERS_PART:
        case MATCHCRITERIA_HEADERS_PART:
                return CRITERIA_HEADERS_PART;
        case MATCHCRITERIA_NOT_HEADERS_PART:
        case MATCHCRITERIA_HEADERS_PART:
                return CRITERIA_HEADERS_PART;
@@ -933,6 +1014,9 @@ static gint prefs_matcher_get_criteria_from_matching(gint matching_id)
                return CRITERIA_SIZE_SMALLER;
        case MATCHCRITERIA_SIZE_EQUAL:
                return CRITERIA_SIZE_EQUAL;
                return CRITERIA_SIZE_SMALLER;
        case MATCHCRITERIA_SIZE_EQUAL:
                return CRITERIA_SIZE_EQUAL;
+       case MATCHCRITERIA_FOUND_IN_ADDRESSBOOK:
+       case MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK:
+               return CRITERIA_FOUND_IN_ADDRESSBOOK;
        default:
                return -1;
        }
        default:
                return -1;
        }
@@ -1013,6 +1097,8 @@ static gint prefs_matcher_get_matching_from_criteria(gint criteria_id)
                return MATCHCRITERIA_SIZE_SMALLER;
        case CRITERIA_SIZE_EQUAL:
                return MATCHCRITERIA_SIZE_EQUAL;
                return MATCHCRITERIA_SIZE_SMALLER;
        case CRITERIA_SIZE_EQUAL:
                return MATCHCRITERIA_SIZE_EQUAL;
+       case CRITERIA_FOUND_IN_ADDRESSBOOK:
+               return MATCHCRITERIA_FOUND_IN_ADDRESSBOOK;
        default:
                return -1;
        }
        default:
                return -1;
        }
@@ -1075,6 +1161,8 @@ static gint prefs_matcher_not_criteria(gint matcher_criteria)
                return MATCHCRITERIA_NOT_TEST;
        case MATCHCRITERIA_BODY_PART:
                return MATCHCRITERIA_NOT_BODY_PART;
                return MATCHCRITERIA_NOT_TEST;
        case MATCHCRITERIA_BODY_PART:
                return MATCHCRITERIA_NOT_BODY_PART;
+       case MATCHCRITERIA_FOUND_IN_ADDRESSBOOK:
+               return MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK;
        default:
                return matcher_criteria;
        }
        default:
                return matcher_criteria;
        }
@@ -1123,6 +1211,7 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
        case CRITERIA_TEST:
        case CRITERIA_COLORLABEL:
        case CRITERIA_IGNORE_THREAD:
        case CRITERIA_TEST:
        case CRITERIA_COLORLABEL:
        case CRITERIA_IGNORE_THREAD:
+       case CRITERIA_FOUND_IN_ADDRESSBOOK:
                if (value_pred_flag == PREDICATE_FLAG_DISABLED)
                        criteria = prefs_matcher_not_criteria(criteria);
                break;
                if (value_pred_flag == PREDICATE_FLAG_DISABLED)
                        criteria = prefs_matcher_not_criteria(criteria);
                break;
@@ -1206,7 +1295,6 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
                }
 
                value = atoi(value_str);
                }
 
                value = atoi(value_str);
-
                break;
                
        case CRITERIA_COLORLABEL:
                break;
                
        case CRITERIA_COLORLABEL:
@@ -1216,7 +1304,6 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
                break;
 
        case CRITERIA_HEADER:
                break;
 
        case CRITERIA_HEADER:
-
                header = gtk_entry_get_text(GTK_ENTRY(matcher.header_entry));
                expr = gtk_entry_get_text(GTK_ENTRY(matcher.value_entry));
 
                header = gtk_entry_get_text(GTK_ENTRY(matcher.header_entry));
                expr = gtk_entry_get_text(GTK_ENTRY(matcher.value_entry));
 
@@ -1225,6 +1312,27 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
                    return NULL;
                }
                break;
                    return NULL;
                }
                break;
+
+       case CRITERIA_FOUND_IN_ADDRESSBOOK:
+               header = gtk_entry_get_text(GTK_ENTRY(matcher.header_addr_entry));
+               expr = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(matcher.addressbook_folder_combo)->entry));
+
+               if (*header == '\0') {
+                   alertpanel_error(_("Header name is not set."));
+                   return NULL;
+               }
+               if (*expr == '\0') {
+                       gchar *msg;
+
+                       msg = g_strdup_printf(_("Book/folder path is not set.\n\n"
+                                                               "If you want to match the '%s' address against the whole address book, "
+                                                               "you have to select 'Any' from the book/folder drop-down list."),
+                                                               header);
+                   alertpanel_error(msg);
+                       g_free(msg);
+                   return NULL;
+               }
+               break;
        }
 
        matcherprop = matcherprop_new(criteria, header, matchtype,
        }
 
        matcherprop = matcherprop_new(criteria, header, matchtype,
@@ -1412,6 +1520,22 @@ static void prefs_matcher_set_value_widget(GtkWidget *old_widget,
                         0, 0, 0);
 }
 
                         0, 0, 0);
 }
 
+static void prefs_matcher_disable_widget(GtkWidget* widget)
+{
+       g_return_if_fail( widget != NULL);
+
+       gtk_widget_set_sensitive(widget, FALSE);
+       gtk_widget_hide(widget);
+}
+
+static void prefs_matcher_enable_widget(GtkWidget* widget)
+{
+       g_return_if_fail( widget != NULL);
+
+       gtk_widget_set_sensitive(widget, TRUE);
+       gtk_widget_show(widget);
+}
+
 /*!
  *\brief       Change widgets depending on the selected condition
  *
 /*!
  *\brief       Change widgets depending on the selected condition
  *
@@ -1444,18 +1568,21 @@ static void prefs_matcher_criteria_select(GtkList *list,
 
        switch (value) {
        case CRITERIA_ALL:
 
        switch (value) {
        case CRITERIA_ALL:
-               gtk_widget_set_sensitive(matcher.header_combo, FALSE);
-               gtk_widget_set_sensitive(matcher.header_label, FALSE);
-               gtk_widget_set_sensitive(matcher.value_label, FALSE);
-               gtk_widget_set_sensitive(matcher.value_entry, FALSE);
-               gtk_widget_set_sensitive(matcher.predicate_label, FALSE);
-               gtk_widget_set_sensitive(matcher.predicate_combo, FALSE);
-               gtk_widget_set_sensitive(matcher.predicate_flag_combo, FALSE);
-               gtk_widget_hide(matcher.predicate_combo);
-               gtk_widget_show(matcher.predicate_flag_combo);
-               gtk_widget_set_sensitive(matcher.case_chkbtn, FALSE);
-               gtk_widget_set_sensitive(matcher.regexp_chkbtn, FALSE);
-               gtk_widget_set_sensitive(matcher.test_btn, FALSE);
+               prefs_matcher_disable_widget(matcher.header_combo);
+               prefs_matcher_disable_widget(matcher.header_label);
+               prefs_matcher_disable_widget(matcher.header_addr_combo);
+               prefs_matcher_disable_widget(matcher.header_addr_label);
+               prefs_matcher_disable_widget(matcher.value_label);
+               prefs_matcher_disable_widget(matcher.value_entry);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_label);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_combo);
+               prefs_matcher_disable_widget(matcher.predicate_label);
+               prefs_matcher_disable_widget(matcher.predicate_combo);
+               prefs_matcher_disable_widget(matcher.predicate_flag_combo);
+               prefs_matcher_disable_widget(matcher.case_chkbtn);
+               prefs_matcher_disable_widget(matcher.regexp_chkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
                break;
 
        case CRITERIA_UNREAD:
                break;
 
        case CRITERIA_UNREAD:
@@ -1467,32 +1594,39 @@ static void prefs_matcher_criteria_select(GtkList *list,
        case CRITERIA_LOCKED:
        case CRITERIA_PARTIAL:
        case CRITERIA_IGNORE_THREAD:
        case CRITERIA_LOCKED:
        case CRITERIA_PARTIAL:
        case CRITERIA_IGNORE_THREAD:
-               gtk_widget_set_sensitive(matcher.header_combo, FALSE);
-               gtk_widget_set_sensitive(matcher.header_label, FALSE);
-               gtk_widget_set_sensitive(matcher.value_label, FALSE);
-               gtk_widget_set_sensitive(matcher.value_entry, FALSE);
-               gtk_widget_set_sensitive(matcher.predicate_label, TRUE);
-               gtk_widget_set_sensitive(matcher.predicate_combo, FALSE);
-               gtk_widget_set_sensitive(matcher.predicate_flag_combo, TRUE);
-               gtk_widget_hide(matcher.predicate_combo);
-               gtk_widget_show(matcher.predicate_flag_combo);
-               gtk_widget_set_sensitive(matcher.case_chkbtn, FALSE);
-               gtk_widget_set_sensitive(matcher.regexp_chkbtn, FALSE);
-               gtk_widget_set_sensitive(matcher.test_btn, FALSE);
+               prefs_matcher_disable_widget(matcher.header_combo);
+               prefs_matcher_disable_widget(matcher.header_label);
+               prefs_matcher_disable_widget(matcher.header_addr_combo);
+               prefs_matcher_disable_widget(matcher.header_addr_label);
+               prefs_matcher_disable_widget(matcher.value_label);
+               prefs_matcher_disable_widget(matcher.value_entry);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_label);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_combo);
+               prefs_matcher_enable_widget(matcher.predicate_label);
+               prefs_matcher_disable_widget(matcher.predicate_combo);
+               prefs_matcher_enable_widget(matcher.predicate_flag_combo);
+               prefs_matcher_disable_widget(matcher.case_chkbtn);
+               prefs_matcher_disable_widget(matcher.regexp_chkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
                break;
                
        case CRITERIA_COLORLABEL:
                break;
                
        case CRITERIA_COLORLABEL:
-               gtk_widget_set_sensitive(matcher.header_combo, FALSE);
-               gtk_widget_set_sensitive(matcher.header_label, FALSE);
-               gtk_widget_set_sensitive(matcher.value_label, TRUE);
-               gtk_widget_set_sensitive(matcher.predicate_label, TRUE);
-               gtk_widget_set_sensitive(matcher.predicate_combo, FALSE);
-               gtk_widget_set_sensitive(matcher.predicate_flag_combo, TRUE);
-               gtk_widget_hide(matcher.predicate_combo);
-               gtk_widget_show(matcher.predicate_flag_combo);
-               gtk_widget_set_sensitive(matcher.case_chkbtn, FALSE);
-               gtk_widget_set_sensitive(matcher.regexp_chkbtn, FALSE);
-               gtk_widget_set_sensitive(matcher.test_btn, FALSE);
+               prefs_matcher_disable_widget(matcher.header_combo);
+               prefs_matcher_disable_widget(matcher.header_label);
+               prefs_matcher_disable_widget(matcher.header_addr_combo);
+               prefs_matcher_disable_widget(matcher.header_addr_label);
+               prefs_matcher_enable_widget(matcher.value_label);
+               prefs_matcher_disable_widget(matcher.value_entry);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_label);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_combo);
+               prefs_matcher_enable_widget(matcher.predicate_label);
+               prefs_matcher_disable_widget(matcher.predicate_combo);
+               prefs_matcher_enable_widget(matcher.predicate_flag_combo);
+               prefs_matcher_disable_widget(matcher.case_chkbtn);
+               prefs_matcher_disable_widget(matcher.regexp_chkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
                break;
 
        case CRITERIA_SUBJECT:
                break;
 
        case CRITERIA_SUBJECT:
@@ -1506,33 +1640,39 @@ static void prefs_matcher_criteria_select(GtkList *list,
        case CRITERIA_HEADERS_PART:
        case CRITERIA_BODY_PART:
        case CRITERIA_MESSAGE:
        case CRITERIA_HEADERS_PART:
        case CRITERIA_BODY_PART:
        case CRITERIA_MESSAGE:
-               gtk_widget_set_sensitive(matcher.header_combo, FALSE);
-               gtk_widget_set_sensitive(matcher.header_label, FALSE);
-               gtk_widget_set_sensitive(matcher.value_label, TRUE);
-               gtk_widget_set_sensitive(matcher.value_entry, TRUE);
-               gtk_widget_set_sensitive(matcher.predicate_label, TRUE);
-               gtk_widget_set_sensitive(matcher.predicate_combo, TRUE);
-               gtk_widget_set_sensitive(matcher.predicate_flag_combo, FALSE);
-               gtk_widget_show(matcher.predicate_combo);
-               gtk_widget_hide(matcher.predicate_flag_combo);
-               gtk_widget_set_sensitive(matcher.case_chkbtn, TRUE);
-               gtk_widget_set_sensitive(matcher.regexp_chkbtn, TRUE);
-               gtk_widget_set_sensitive(matcher.test_btn, FALSE);
+               prefs_matcher_disable_widget(matcher.header_combo);
+               prefs_matcher_disable_widget(matcher.header_label);
+               prefs_matcher_disable_widget(matcher.header_addr_combo);
+               prefs_matcher_disable_widget(matcher.header_addr_label);
+               prefs_matcher_enable_widget(matcher.value_label);
+               prefs_matcher_enable_widget(matcher.value_entry);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_label);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_combo);
+               prefs_matcher_enable_widget(matcher.predicate_label);
+               prefs_matcher_enable_widget(matcher.predicate_combo);
+               prefs_matcher_disable_widget(matcher.predicate_flag_combo);
+               prefs_matcher_enable_widget(matcher.case_chkbtn);
+               prefs_matcher_enable_widget(matcher.regexp_chkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
                break;
 
        case CRITERIA_TEST:
                break;
 
        case CRITERIA_TEST:
-               gtk_widget_set_sensitive(matcher.header_combo, FALSE);
-               gtk_widget_set_sensitive(matcher.header_label, FALSE);
-               gtk_widget_set_sensitive(matcher.value_label, TRUE);
-               gtk_widget_set_sensitive(matcher.value_entry, TRUE);
-               gtk_widget_set_sensitive(matcher.predicate_label, TRUE);
-               gtk_widget_set_sensitive(matcher.predicate_combo, FALSE);
-               gtk_widget_set_sensitive(matcher.predicate_flag_combo, TRUE);
-               gtk_widget_hide(matcher.predicate_combo);
-               gtk_widget_show(matcher.predicate_flag_combo);
-               gtk_widget_set_sensitive(matcher.case_chkbtn, FALSE);
-               gtk_widget_set_sensitive(matcher.regexp_chkbtn, FALSE);
-               gtk_widget_set_sensitive(matcher.test_btn, TRUE);
+               prefs_matcher_disable_widget(matcher.header_combo);
+               prefs_matcher_disable_widget(matcher.header_label);
+               prefs_matcher_disable_widget(matcher.header_addr_combo);
+               prefs_matcher_disable_widget(matcher.header_addr_label);
+               prefs_matcher_enable_widget(matcher.value_label);
+               prefs_matcher_enable_widget(matcher.value_entry);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_label);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_combo);
+               prefs_matcher_enable_widget(matcher.predicate_label);
+               prefs_matcher_disable_widget(matcher.predicate_combo);
+               prefs_matcher_enable_widget(matcher.predicate_flag_combo);
+               prefs_matcher_disable_widget(matcher.case_chkbtn);
+               prefs_matcher_disable_widget(matcher.regexp_chkbtn);
+               prefs_matcher_enable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
                break;
 
        case CRITERIA_AGE_GREATER:
                break;
 
        case CRITERIA_AGE_GREATER:
@@ -1543,33 +1683,57 @@ static void prefs_matcher_criteria_select(GtkList *list,
        case CRITERIA_SIZE_GREATER:
        case CRITERIA_SIZE_SMALLER:
        case CRITERIA_SIZE_EQUAL:
        case CRITERIA_SIZE_GREATER:
        case CRITERIA_SIZE_SMALLER:
        case CRITERIA_SIZE_EQUAL:
-               gtk_widget_set_sensitive(matcher.header_combo, FALSE);
-               gtk_widget_set_sensitive(matcher.header_label, FALSE);
-               gtk_widget_set_sensitive(matcher.value_label, TRUE);
-               gtk_widget_set_sensitive(matcher.value_entry, TRUE);
-               gtk_widget_set_sensitive(matcher.predicate_label, FALSE);
-               gtk_widget_set_sensitive(matcher.predicate_combo, FALSE);
-               gtk_widget_set_sensitive(matcher.predicate_flag_combo, FALSE);
-               gtk_widget_show(matcher.predicate_combo);
-               gtk_widget_hide(matcher.predicate_flag_combo);
-               gtk_widget_set_sensitive(matcher.case_chkbtn, FALSE);
-               gtk_widget_set_sensitive(matcher.regexp_chkbtn, FALSE);
-               gtk_widget_set_sensitive(matcher.test_btn, FALSE);
+               prefs_matcher_disable_widget(matcher.header_combo);
+               prefs_matcher_disable_widget(matcher.header_label);
+               prefs_matcher_disable_widget(matcher.header_addr_combo);
+               prefs_matcher_disable_widget(matcher.header_addr_label);
+               prefs_matcher_enable_widget(matcher.value_label);
+               prefs_matcher_enable_widget(matcher.value_entry);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_label);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_combo);
+               prefs_matcher_disable_widget(matcher.predicate_label);
+               prefs_matcher_disable_widget(matcher.predicate_combo);
+               prefs_matcher_disable_widget(matcher.predicate_flag_combo);
+               prefs_matcher_disable_widget(matcher.case_chkbtn);
+               prefs_matcher_disable_widget(matcher.regexp_chkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
                break;
 
        case CRITERIA_HEADER:
                break;
 
        case CRITERIA_HEADER:
-               gtk_widget_set_sensitive(matcher.header_combo, TRUE);
-               gtk_widget_set_sensitive(matcher.header_label, TRUE);
-               gtk_widget_set_sensitive(matcher.value_label, TRUE);
-               gtk_widget_set_sensitive(matcher.value_entry, TRUE);
-               gtk_widget_set_sensitive(matcher.predicate_label, TRUE);
-               gtk_widget_set_sensitive(matcher.predicate_combo, TRUE);
-               gtk_widget_set_sensitive(matcher.predicate_flag_combo, FALSE);
-               gtk_widget_show(matcher.predicate_combo);
-               gtk_widget_hide(matcher.predicate_flag_combo);
-               gtk_widget_set_sensitive(matcher.case_chkbtn, TRUE);
-               gtk_widget_set_sensitive(matcher.regexp_chkbtn, TRUE);
-               gtk_widget_set_sensitive(matcher.test_btn, FALSE);
+               prefs_matcher_enable_widget(matcher.header_combo);
+               prefs_matcher_enable_widget(matcher.header_label);
+               prefs_matcher_disable_widget(matcher.header_addr_combo);
+               prefs_matcher_disable_widget(matcher.header_addr_label);
+               prefs_matcher_enable_widget(matcher.value_label);
+               prefs_matcher_enable_widget(matcher.value_entry);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_label);
+               prefs_matcher_disable_widget(matcher.addressbook_folder_combo);
+               prefs_matcher_enable_widget(matcher.predicate_label);
+               prefs_matcher_enable_widget(matcher.predicate_combo);
+               prefs_matcher_disable_widget(matcher.predicate_flag_combo);
+               prefs_matcher_enable_widget(matcher.case_chkbtn);
+               prefs_matcher_enable_widget(matcher.regexp_chkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
+               break;
+
+       case CRITERIA_FOUND_IN_ADDRESSBOOK:
+               prefs_matcher_disable_widget(matcher.header_combo);
+               prefs_matcher_disable_widget(matcher.header_label);
+               prefs_matcher_enable_widget(matcher.header_addr_combo);
+               prefs_matcher_enable_widget(matcher.header_addr_label);
+               prefs_matcher_disable_widget(matcher.value_label);
+               prefs_matcher_disable_widget(matcher.value_entry);
+               prefs_matcher_enable_widget(matcher.addressbook_folder_label);
+               prefs_matcher_enable_widget(matcher.addressbook_folder_combo);
+               prefs_matcher_enable_widget(matcher.predicate_label);
+               prefs_matcher_disable_widget(matcher.predicate_combo);
+               prefs_matcher_enable_widget(matcher.predicate_flag_combo);
+               prefs_matcher_disable_widget(matcher.case_chkbtn);
+               prefs_matcher_disable_widget(matcher.regexp_chkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_enable_widget(matcher.addressbook_select_btn);
                break;
        }
 }
                break;
        }
 }
@@ -1718,6 +1882,18 @@ void prefs_matcher_test_info(void)
        description_window_create(&test_desc_win);
 }
 
        description_window_create(&test_desc_win);
 }
 
+void prefs_matcher_addressbook_select(void)
+{
+       gchar *folderpath = NULL;
+       gboolean ret = FALSE;
+
+       folderpath = (gchar *) gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(matcher.addressbook_folder_combo)->entry));
+       ret = addressbook_folder_selection(&folderpath);
+       if ( ret != FALSE && folderpath != NULL)
+               gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(matcher.addressbook_folder_combo)->entry), folderpath);
+}
+
+
 /*
  * list view
  */
 /*
  * list view
  */
@@ -1857,6 +2033,7 @@ static gboolean prefs_matcher_selected(GtkTreeSelection *selector,
        case MATCHCRITERIA_NOT_MESSAGE:
        case MATCHCRITERIA_NOT_BODY_PART:
        case MATCHCRITERIA_NOT_TEST:
        case MATCHCRITERIA_NOT_MESSAGE:
        case MATCHCRITERIA_NOT_BODY_PART:
        case MATCHCRITERIA_NOT_TEST:
+       case MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK:
                negative_cond = TRUE;
                break;
        }
                negative_cond = TRUE;
                break;
        }
@@ -1892,6 +2069,12 @@ static gboolean prefs_matcher_selected(GtkTreeSelection *selector,
                gtk_entry_set_text(GTK_ENTRY(matcher.value_entry), prop->expr);
                break;
 
                gtk_entry_set_text(GTK_ENTRY(matcher.value_entry), prop->expr);
                break;
 
+       case MATCHCRITERIA_FOUND_IN_ADDRESSBOOK:
+       case MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK:
+               gtk_entry_set_text(GTK_ENTRY(matcher.header_addr_entry), prop->header);
+               gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(matcher.addressbook_folder_combo)->entry), prop->expr);
+               break;
+
        case MATCHCRITERIA_AGE_GREATER:
        case MATCHCRITERIA_AGE_LOWER:
        case MATCHCRITERIA_SCORE_GREATER:
        case MATCHCRITERIA_AGE_GREATER:
        case MATCHCRITERIA_AGE_LOWER:
        case MATCHCRITERIA_SCORE_GREATER:
index 31693e628e713253f22f203b4610e0f20c5dffd2..05228d3bdfa946cee131dccbc2737fa48bb73f3f 100644 (file)
@@ -27,5 +27,6 @@ typedef void PrefsMatcherSignal       (MatcherList *matchers);
 void prefs_matcher_open                (MatcherList *matchers,
                                 PrefsMatcherSignal *cb);
 void prefs_matcher_test_info   (void);
 void prefs_matcher_open                (MatcherList *matchers,
                                 PrefsMatcherSignal *cb);
 void prefs_matcher_test_info   (void);
+void prefs_matcher_addressbook_select  (void);
 
 #endif /* __PREFS_FILTER_H__ */
 
 #endif /* __PREFS_FILTER_H__ */
index c107c2dd8bf5c04a73f3cc3f325d42adbb69aaee..7c11a321075653eed317186556a72804656c1033 100644 (file)
@@ -2447,7 +2447,7 @@ static void summary_set_ctree_from_list(SummaryView *summaryview,
        summaryview->subject_table = subject_table;
 
        if (prefs_common.use_addr_book)
        summaryview->subject_table = subject_table;
 
        if (prefs_common.use_addr_book)
-               start_address_completion();
+               start_address_completion(NULL);
        
        if (summaryview->threaded) {
                GNode *root, *gnode;
        
        if (summaryview->threaded) {
                GNode *root, *gnode;