2007-07-30 [paul] 2.10.0cvs80
[claws.git] / src / prefs_matcher.c
index d0b5ac64963f32e05d60851c48ee8ec8e5b1b816..f7bc3d5814c19c932e324a4c27d903ed053882dd 100644 (file)
@@ -1,10 +1,10 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2001 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail 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
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -13,8 +13,8 @@
  * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * 
  */
 
 #ifdef HAVE_CONFIG_H
@@ -24,6 +24,7 @@
 #include "defs.h"
 
 #include <glib.h>
+#include <glib/gi18n.h>
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
 #include <stdio.h>
@@ -31,7 +32,6 @@
 #include <string.h>
 #include <errno.h>
 
-#include "intl.h"
 #include "main.h"
 #include "prefs_gtk.h"
 #include "prefs_matcher.h"
@@ -67,6 +67,7 @@ static struct Matcher {
        GtkWidget *predicate_combo;
        GtkWidget *predicate_flag_combo;
        GtkWidget *header_combo;
+       GtkWidget *header_addr_combo;
 
        GtkWidget *criteria_list;
 
@@ -78,13 +79,18 @@ static struct Matcher {
 
        GtkWidget *header_entry;
        GtkWidget *header_label;
+       GtkWidget *header_addr_entry;
+       GtkWidget *header_addr_label;
        GtkWidget *value_entry;
        GtkWidget *value_label;
-       GtkWidget *case_chkbtn;
-       GtkWidget *regexp_chkbtn;
+       GtkWidget *addressbook_folder_label;
+       GtkWidget *addressbook_folder_combo;
+       GtkWidget *case_checkbtn;
+       GtkWidget *regexp_checkbtn;
        GtkWidget *color_optmenu;
 
        GtkWidget *test_btn;
+       GtkWidget *addressbook_select_btn;
 
        GtkWidget *cond_list_view;
 
@@ -127,45 +133,80 @@ enum {
        CRITERIA_REPLIED = 19,
        CRITERIA_FORWARDED = 20,
        CRITERIA_LOCKED = 21,
-       CRITERIA_COLORLABEL = 22,
-       CRITERIA_IGNORE_THREAD = 23,
+       CRITERIA_SPAM = 22,
+       CRITERIA_COLORLABEL = 23,
+       CRITERIA_IGNORE_THREAD = 24,
+       CRITERIA_WATCH_THREAD = 25,
+
+       CRITERIA_SCORE_GREATER = 26,
+       CRITERIA_SCORE_LOWER = 27,
+       CRITERIA_SCORE_EQUAL = 28,
 
-       CRITERIA_SCORE_GREATER = 24,
-       CRITERIA_SCORE_LOWER = 25,
-       CRITERIA_SCORE_EQUAL = 26,
+       CRITERIA_TEST = 29,
 
-       CRITERIA_TEST = 27,
+       CRITERIA_SIZE_GREATER = 30,
+       CRITERIA_SIZE_SMALLER = 31,
+       CRITERIA_SIZE_EQUAL   = 32,
+       
+       CRITERIA_PARTIAL = 33,
 
-       CRITERIA_SIZE_GREATER = 28,
-       CRITERIA_SIZE_SMALLER = 29,
-       CRITERIA_SIZE_EQUAL   = 30,
+       CRITERIA_FOUND_IN_ADDRESSBOOK = 34,
        
-       CRITERIA_PARTIAL = 31
+       CRITERIA_TAG = 35,
+       CRITERIA_TAGGED = 36
 };
 
 /*!
  *\brief       Descriptive text for conditions
  */
-static const gchar *criteria_text [] = {
-       N_("All messages"), N_("Subject"),
-       N_("From"), N_("To"), N_("Cc"), N_("To or Cc"),
-       N_("Newsgroups"), N_("In reply to"), N_("References"),
-       N_("Age greater than"), N_("Age lower than"),
-       N_("Header"), N_("Headers part"),
-       N_("Body part"), N_("Whole message"),
-       N_("Unread flag"), N_("New flag"),
-       N_("Marked flag"), N_("Deleted flag"),
-       N_("Replied flag"), N_("Forwarded flag"),
-       N_("Locked flag"),
-       N_("Color label"),
-       N_("Ignore thread"),
-       N_("Score greater than"), N_("Score lower than"),
-       N_("Score equal to"),
-       N_("Test"),
-       N_("Size greater than"), 
-       N_("Size smaller than"),
-       N_("Size exactly"),
-       N_("Partially downloaded")
+typedef struct _struct_criteria_text struct_criteria_text;
+struct _struct_criteria_text {
+       const gchar     *text;
+       gboolean         contains_header_name;
+       /* if contains_header_name is TRUE, prefs_common_translated_headername(text)
+          will be used
+       */
+};
+
+static struct_criteria_text criteria_text [] = {
+       { N_("All messages"), FALSE },
+       { N_("Subject"), TRUE },
+       { N_("From"), TRUE },
+       { N_("To"), TRUE },
+       { N_("Cc"), TRUE },
+       { N_("To or Cc"), TRUE },
+       { N_("Newsgroups"), TRUE },
+       { N_("In reply to"), TRUE },
+       { N_("References"), TRUE },
+       { N_("Age greater than (days)"), FALSE },
+       { N_("Age less than (days)"), FALSE },
+       { N_("Header"), FALSE },
+       { N_("Headers part"), FALSE },
+       { N_("Body part"), FALSE },
+       { N_("Whole message"), FALSE },
+       { N_("Unread flag"), FALSE },
+       { N_("New flag"), FALSE },
+       { N_("Marked flag"), FALSE },
+       { N_("Deleted flag"), FALSE },
+       { N_("Replied flag"), FALSE },
+       { N_("Forwarded flag"), FALSE },
+       { N_("Locked flag"), FALSE },
+       { N_("Spam flag"), FALSE },
+       { N_("Color label"), FALSE },
+       { N_("Ignored thread"), FALSE },
+       { N_("Watched thread"), FALSE },
+       { N_("Score greater than"), FALSE },
+       { N_("Score lower than"), FALSE },
+       { N_("Score equal to"), FALSE },
+       { N_("Test"), FALSE },
+       { N_("Size greater than (bytes)"), FALSE }, 
+       { N_("Size smaller than (bytes)"), FALSE },
+       { N_("Size exactly (bytes)"), FALSE },
+       { N_("Partially downloaded"), FALSE },
+       { N_("Found in addressbook"), FALSE },
+       { N_("Tags"), FALSE },
+       { N_("Tagged"), FALSE },
+       { NULL, FALSE }
 };
 
 /*!
@@ -202,6 +243,13 @@ static const gchar *predicate_text [] = {
        N_("contains"), N_("does not contain")
 };
 
+/*!
+ *\brief       Preset addressbook book/folder items
+ */
+static const gchar *addressbook_folder_text [] = {
+       N_("Any")
+};
+
 /*!
  *\brief       Enabled predicate
  *
@@ -303,6 +351,10 @@ void prefs_matcher_open(MatcherList *matchers, PrefsMatcherSignal *cb)
 
        if (!matcher.window) {
                prefs_matcher_create();
+       } else {
+               /* update color label menu */
+               gtk_option_menu_set_menu(GTK_OPTION_MENU(matcher.color_optmenu),
+                               colorlabel_create_color_menu());
        }
 
        manage_window_set_transient(GTK_WINDOW(matcher.window));
@@ -315,6 +367,18 @@ void prefs_matcher_open(MatcherList *matchers, PrefsMatcherSignal *cb)
        gtk_widget_show(matcher.window);
 }
 
+/*!
+ *\brief       Save Gtk object size to prefs dataset
+ */
+static void prefs_matcher_size_allocate_cb(GtkWidget *widget,
+                                        GtkAllocation *allocation)
+{
+       g_return_if_fail(allocation != NULL);
+
+       prefs_common.matcherwin_width = allocation->width;
+       prefs_common.matcherwin_height = allocation->height;
+}
+
 /*!
  *\brief       Create the matcher dialog
  */
@@ -336,11 +400,16 @@ static void prefs_matcher_create(void)
        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 *addressbook_folder_label;
+       GtkWidget *addressbook_folder_combo;
        GtkWidget *predicate_combo;
        GtkWidget *predicate_list;
        GtkWidget *predicate_flag_combo;
@@ -350,8 +419,8 @@ static void prefs_matcher_create(void)
        GtkWidget *bool_op_list;
        GtkWidget *bool_op_label;
 
-       GtkWidget *regexp_chkbtn;
-       GtkWidget *case_chkbtn;
+       GtkWidget *regexp_checkbtn;
+       GtkWidget *case_checkbtn;
 
        GtkWidget *reg_hbox;
        GtkWidget *btn_hbox;
@@ -369,15 +438,17 @@ static void prefs_matcher_create(void)
        GtkWidget *down_btn;
 
        GtkWidget *test_btn;
+       GtkWidget *addressbook_select_btn;
 
        GtkWidget *color_optmenu;
 
        GList *combo_items;
        gint i;
+       static GdkGeometry geometry;
 
        debug_print("Creating matcher configuration window...\n");
 
-       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+       window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "prefs_matcher");
        gtk_container_set_border_width(GTK_CONTAINER(window), 8);
        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);
@@ -387,8 +458,8 @@ static void prefs_matcher_create(void)
        gtk_widget_show(vbox);
        gtk_container_add(GTK_CONTAINER(window), vbox);
 
-       gtkut_stock_button_set_create(&confirm_area, &ok_btn, GTK_STOCK_OK,
-                                     &cancel_btn, GTK_STOCK_CANCEL, NULL, NULL);
+       gtkut_stock_button_set_create(&confirm_area, &cancel_btn, GTK_STOCK_CANCEL,
+                                     &ok_btn, GTK_STOCK_OK, NULL, NULL);
        gtk_widget_show(confirm_area);
        gtk_box_pack_end(GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
        gtk_widget_grab_default(ok_btn);
@@ -397,6 +468,8 @@ static void prefs_matcher_create(void)
                             _("Condition configuration"));
        g_signal_connect(G_OBJECT(window), "delete_event",
                         G_CALLBACK(prefs_matcher_deleted), NULL);
+       g_signal_connect(G_OBJECT(window), "size_allocate",
+                        G_CALLBACK(prefs_matcher_size_allocate_cb), NULL);
        g_signal_connect(G_OBJECT(window), "key_press_event",
                         G_CALLBACK(prefs_matcher_key_pressed), NULL);
        MANAGE_WINDOW_SIGNALS_CONNECT(window);
@@ -430,15 +503,19 @@ static void prefs_matcher_create(void)
 
        combo_items = NULL;
 
-       for (i = 0; i < (gint) (sizeof(criteria_text) / sizeof(gchar *)); i++) {
-               combo_items = g_list_append(combo_items,
-                                           (gpointer) _(criteria_text[i]));
+       for (i = 0; criteria_text[i].text != NULL; i++) {
+               if (criteria_text[i].contains_header_name)
+                       combo_items = g_list_append(combo_items,
+                                           (gpointer) prefs_common_translated_header_name(criteria_text[i].text));
+               else
+                       combo_items = g_list_append(combo_items,
+                                           (gpointer) gettext(criteria_text[i].text));
        }
        gtk_combo_set_popdown_strings(GTK_COMBO(criteria_combo), combo_items);
 
        g_list_free(combo_items);
 
-       gtk_widget_set_usize(criteria_combo, 120, -1);
+       gtk_widget_set_size_request(criteria_combo, 190, -1);
        gtk_table_attach(GTK_TABLE(criteria_table), criteria_combo, 0, 1, 1, 2,
                          0, 0, 0, 0);
        criteria_list = GTK_COMBO(criteria_combo)->list;
@@ -459,7 +536,7 @@ static void prefs_matcher_create(void)
 
        header_combo = gtk_combo_new();
        gtk_widget_show(header_combo);
-       gtk_widget_set_usize(header_combo, 96, -1);
+       gtk_widget_set_size_request(header_combo, 120, -1);
        gtkut_combo_set_items(GTK_COMBO (header_combo),
                              "Subject", "From", "To", "Cc", "Reply-To",
                              "Sender", "X-ML-Name", "X-List", "X-Sequence",
@@ -470,6 +547,24 @@ static void prefs_matcher_create(void)
        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),
+                             Q_("Filtering Matcher Menu|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"));
@@ -480,18 +575,53 @@ static void prefs_matcher_create(void)
 
        value_entry = gtk_entry_new();
        gtk_widget_show(value_entry);
-       gtk_widget_set_usize(value_entry, 200, -1);
+       gtk_widget_set_size_request(value_entry, 200, -1);
        gtk_table_attach(GTK_TABLE(criteria_table), value_entry, 2, 3, 1, 2,
                         GTK_FILL | GTK_SHRINK | GTK_EXPAND, 0, 0, 0);
 
-       test_btn = gtk_button_new_with_label(_("Info ..."));
+       /* 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
+       test_btn = gtk_button_new_with_label(_("Info..."));
+#endif
        gtk_widget_show(test_btn);
        gtk_table_attach(GTK_TABLE (criteria_table), test_btn, 3, 4, 1, 2,
-                        GTK_FILL | GTK_SHRINK | GTK_EXPAND, 0, 0, 0);
+                        0, 0, 0, 0);
        g_signal_connect(G_OBJECT (test_btn), "clicked",
                         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());
@@ -513,7 +643,7 @@ static void prefs_matcher_create(void)
 
        predicate_combo = gtk_combo_new();
        gtk_widget_show(predicate_combo);
-       gtk_widget_set_usize(predicate_combo, 120, -1);
+       gtk_widget_set_size_request(predicate_combo, 120, -1);
        predicate_list = GTK_COMBO(predicate_combo)->list;
        gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(predicate_combo)->entry),
                               FALSE);
@@ -535,7 +665,7 @@ static void prefs_matcher_create(void)
 
        predicate_flag_combo = gtk_combo_new();
        gtk_widget_hide(predicate_flag_combo);
-       gtk_widget_set_usize(predicate_flag_combo, 120, -1);
+       gtk_widget_set_size_request(predicate_flag_combo, 120, -1);
        predicate_flag_list = GTK_COMBO(predicate_flag_combo)->list;
        gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(predicate_flag_combo)->entry), FALSE);
 
@@ -556,8 +686,8 @@ static void prefs_matcher_create(void)
        gtk_widget_show (vbox3);
        gtk_box_pack_start(GTK_BOX(hbox1), vbox3, FALSE, FALSE, 0);
 
-       PACK_CHECK_BUTTON(vbox3, case_chkbtn, _("Case sensitive"));
-       PACK_CHECK_BUTTON(vbox3, regexp_chkbtn, _("Use regexp"));
+       PACK_CHECK_BUTTON(vbox3, case_checkbtn, _("Case sensitive"));
+       PACK_CHECK_BUTTON(vbox3, regexp_checkbtn, _("Use regexp"));
 
        /* register / substitute / delete */
 
@@ -568,9 +698,9 @@ static void prefs_matcher_create(void)
        arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
        gtk_widget_show(arrow);
        gtk_box_pack_start(GTK_BOX(reg_hbox), arrow, FALSE, FALSE, 0);
-       gtk_widget_set_usize(arrow, -1, 16);
+       gtk_widget_set_size_request(arrow, -1, 16);
 
-       btn_hbox = gtk_hbox_new(TRUE, 4);
+       btn_hbox = gtk_hbox_new(FALSE, 4);
        gtk_widget_show(btn_hbox);
        gtk_box_pack_start(GTK_BOX(reg_hbox), btn_hbox, FALSE, FALSE, 0);
 
@@ -580,14 +710,14 @@ static void prefs_matcher_create(void)
        g_signal_connect(G_OBJECT(reg_btn), "clicked",
                         G_CALLBACK(prefs_matcher_register_cb), NULL);
 
-       subst_btn = gtk_button_new_with_label(_("  Replace  "));
+       subst_btn = gtkut_get_replace_btn(_("Replace"));
        gtk_widget_show(subst_btn);
        gtk_box_pack_start(GTK_BOX(btn_hbox), subst_btn, FALSE, TRUE, 0);
        g_signal_connect(G_OBJECT(subst_btn), "clicked",
                         G_CALLBACK(prefs_matcher_substitute_cb),
                         NULL);
 
-       del_btn = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
+       del_btn = gtk_button_new_from_stock(GTK_STOCK_DELETE);
        gtk_widget_show(del_btn);
        gtk_box_pack_start(GTK_BOX(btn_hbox), del_btn, FALSE, TRUE, 0);
        g_signal_connect(G_OBJECT(del_btn), "clicked",
@@ -603,7 +733,7 @@ static void prefs_matcher_create(void)
 
        bool_op_combo = gtk_combo_new();
        gtk_widget_show(bool_op_combo);
-       gtk_widget_set_usize(bool_op_combo, 50, -1);
+       gtk_widget_set_size_request(bool_op_combo, 60, -1);
        bool_op_list = GTK_COMBO(bool_op_combo)->list;
        gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(bool_op_combo)->entry),
                               FALSE);
@@ -627,7 +757,7 @@ static void prefs_matcher_create(void)
 
        cond_scrolledwin = gtk_scrolled_window_new(NULL, NULL);
        gtk_widget_show(cond_scrolledwin);
-       gtk_widget_set_usize(cond_scrolledwin, -1, 150);
+       gtk_widget_set_size_request(cond_scrolledwin, -1, 150);
        gtk_box_pack_start(GTK_BOX(cond_hbox), cond_scrolledwin,
                           TRUE, TRUE, 0);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(cond_scrolledwin),
@@ -654,7 +784,21 @@ static void prefs_matcher_create(void)
        g_signal_connect(G_OBJECT(down_btn), "clicked",
                         G_CALLBACK(prefs_matcher_down), NULL);
 
+       if (!geometry.min_height) {
+               geometry.min_width = 520;
+               geometry.min_height = 368;
+       }
+
+       gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
+                                     GDK_HINT_MIN_SIZE);
+       gtk_widget_set_size_request(window, prefs_common.matcherwin_width,
+                                   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;
 
@@ -664,21 +808,30 @@ static void prefs_matcher_create(void)
        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.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_flag_list = predicate_flag_list;
        matcher.predicate_flag_combo = predicate_flag_combo;
-       matcher.case_chkbtn = case_chkbtn;
-       matcher.regexp_chkbtn = regexp_chkbtn;
+       matcher.case_checkbtn = case_checkbtn;
+       matcher.regexp_checkbtn = regexp_checkbtn;
        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.cond_list_view = cond_list_view;
+
+       matcher.selected_criteria = -1;
+       prefs_matcher_criteria_select(GTK_LIST(criteria_list), NULL, NULL);
 }
 
 /*!
@@ -695,7 +848,7 @@ static void prefs_matcher_list_view_set_row(GtkTreeIter *row, MatcherProp *prop)
 
        if (prop == NULL) {
                prefs_matcher_list_view_insert_matcher(matcher.cond_list_view,
-                                                      NULL, _("New"), FALSE);
+                                                      NULL, _("(New)"), FALSE);
                return;                                                
        }
 
@@ -719,7 +872,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_entry_set_text(GTK_ENTRY(matcher.header_addr_entry), "");
        gtk_entry_set_text(GTK_ENTRY(matcher.value_entry), "");
+       gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(matcher.addressbook_folder_combo)->entry), "");
 }
 
 /*!
@@ -836,6 +991,9 @@ static gint prefs_matcher_get_criteria_from_matching(gint matching_id)
        case MATCHCRITERIA_LOCKED:
        case MATCHCRITERIA_NOT_LOCKED:
                return CRITERIA_LOCKED;
+       case MATCHCRITERIA_NOT_SPAM:
+       case MATCHCRITERIA_SPAM:
+               return CRITERIA_SPAM;
        case MATCHCRITERIA_PARTIAL:
        case MATCHCRITERIA_NOT_PARTIAL:
                return CRITERIA_PARTIAL;
@@ -845,6 +1003,9 @@ static gint prefs_matcher_get_criteria_from_matching(gint matching_id)
        case MATCHCRITERIA_IGNORE_THREAD:
        case MATCHCRITERIA_NOT_IGNORE_THREAD:
                return CRITERIA_IGNORE_THREAD;
+       case MATCHCRITERIA_WATCH_THREAD:
+       case MATCHCRITERIA_NOT_WATCH_THREAD:
+               return CRITERIA_WATCH_THREAD;
        case MATCHCRITERIA_NOT_SUBJECT:
        case MATCHCRITERIA_SUBJECT:
                return CRITERIA_SUBJECT;
@@ -869,13 +1030,18 @@ static gint prefs_matcher_get_criteria_from_matching(gint matching_id)
        case MATCHCRITERIA_NOT_TO_AND_NOT_CC:
        case MATCHCRITERIA_TO_OR_CC:
                return CRITERIA_TO_OR_CC;
+       case MATCHCRITERIA_NOT_TAG:
+       case MATCHCRITERIA_TAG:
+               return CRITERIA_TAG;
+       case MATCHCRITERIA_NOT_TAGGED:
+       case MATCHCRITERIA_TAGGED:
+               return CRITERIA_TAGGED;
        case MATCHCRITERIA_NOT_BODY_PART:
        case MATCHCRITERIA_BODY_PART:
                return CRITERIA_BODY_PART;
        case MATCHCRITERIA_NOT_MESSAGE:
        case MATCHCRITERIA_MESSAGE:
                return CRITERIA_MESSAGE;
-               break;
        case MATCHCRITERIA_NOT_HEADERS_PART:
        case MATCHCRITERIA_HEADERS_PART:
                return CRITERIA_HEADERS_PART;
@@ -901,6 +1067,9 @@ static gint prefs_matcher_get_criteria_from_matching(gint matching_id)
                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;
        }
@@ -933,12 +1102,16 @@ static gint prefs_matcher_get_matching_from_criteria(gint criteria_id)
                return MATCHCRITERIA_FORWARDED;
        case CRITERIA_LOCKED:
                return MATCHCRITERIA_LOCKED;
+       case CRITERIA_SPAM:
+               return MATCHCRITERIA_SPAM;
        case CRITERIA_PARTIAL:
                return MATCHCRITERIA_PARTIAL;
        case CRITERIA_COLORLABEL:
                return MATCHCRITERIA_COLORLABEL;
        case CRITERIA_IGNORE_THREAD:
                return MATCHCRITERIA_IGNORE_THREAD;
+       case CRITERIA_WATCH_THREAD:
+               return MATCHCRITERIA_WATCH_THREAD;
        case CRITERIA_SUBJECT:
                return MATCHCRITERIA_SUBJECT;
        case CRITERIA_FROM:
@@ -949,6 +1122,10 @@ static gint prefs_matcher_get_matching_from_criteria(gint criteria_id)
                return MATCHCRITERIA_CC;
        case CRITERIA_TO_OR_CC:
                return MATCHCRITERIA_TO_OR_CC;
+       case CRITERIA_TAG:
+               return MATCHCRITERIA_TAG;
+       case CRITERIA_TAGGED:
+               return MATCHCRITERIA_TAGGED;
        case CRITERIA_NEWSGROUPS:
                return MATCHCRITERIA_NEWSGROUPS;
        case CRITERIA_INREPLYTO:
@@ -981,6 +1158,8 @@ static gint prefs_matcher_get_matching_from_criteria(gint criteria_id)
                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;
        }
@@ -1011,12 +1190,16 @@ static gint prefs_matcher_not_criteria(gint matcher_criteria)
                return MATCHCRITERIA_NOT_FORWARDED;
        case MATCHCRITERIA_LOCKED:
                return MATCHCRITERIA_NOT_LOCKED;
+       case MATCHCRITERIA_SPAM:
+               return MATCHCRITERIA_NOT_SPAM;
        case MATCHCRITERIA_PARTIAL:
                return MATCHCRITERIA_NOT_PARTIAL;
        case MATCHCRITERIA_COLORLABEL:
                return MATCHCRITERIA_NOT_COLORLABEL;
        case MATCHCRITERIA_IGNORE_THREAD:
                return MATCHCRITERIA_NOT_IGNORE_THREAD;
+       case MATCHCRITERIA_WATCH_THREAD:
+               return MATCHCRITERIA_NOT_WATCH_THREAD;
        case MATCHCRITERIA_SUBJECT:
                return MATCHCRITERIA_NOT_SUBJECT;
        case MATCHCRITERIA_FROM:
@@ -1027,6 +1210,10 @@ static gint prefs_matcher_not_criteria(gint matcher_criteria)
                return MATCHCRITERIA_NOT_CC;
        case MATCHCRITERIA_TO_OR_CC:
                return MATCHCRITERIA_NOT_TO_AND_NOT_CC;
+       case MATCHCRITERIA_TAG:
+               return MATCHCRITERIA_NOT_TAG;
+       case MATCHCRITERIA_TAGGED:
+               return MATCHCRITERIA_NOT_TAGGED;
        case MATCHCRITERIA_NEWSGROUPS:
                return MATCHCRITERIA_NOT_NEWSGROUPS;
        case MATCHCRITERIA_INREPLYTO:
@@ -1043,6 +1230,8 @@ static gint prefs_matcher_not_criteria(gint matcher_criteria)
                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;
        }
@@ -1076,8 +1265,8 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
        value_pred = get_sel_from_list(GTK_LIST(matcher.predicate_list));
        value_pred_flag = get_sel_from_list(GTK_LIST(matcher.predicate_flag_list));
 
-       use_regexp = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(matcher.regexp_chkbtn));
-       case_sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(matcher.case_chkbtn));
+       use_regexp = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(matcher.regexp_checkbtn));
+       case_sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(matcher.case_checkbtn));
 
        switch (value_criteria) {
        case CRITERIA_UNREAD:
@@ -1087,10 +1276,14 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
        case CRITERIA_REPLIED:
        case CRITERIA_FORWARDED:
        case CRITERIA_LOCKED:
+       case CRITERIA_SPAM:
        case CRITERIA_PARTIAL:
        case CRITERIA_TEST:
        case CRITERIA_COLORLABEL:
        case CRITERIA_IGNORE_THREAD:
+       case CRITERIA_WATCH_THREAD:
+       case CRITERIA_FOUND_IN_ADDRESSBOOK:
+       case CRITERIA_TAGGED:
                if (value_pred_flag == PREDICATE_FLAG_DISABLED)
                        criteria = prefs_matcher_not_criteria(criteria);
                break;
@@ -1099,6 +1292,7 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
        case CRITERIA_TO:
        case CRITERIA_CC:
        case CRITERIA_TO_OR_CC:
+       case CRITERIA_TAG:
        case CRITERIA_NEWSGROUPS:
        case CRITERIA_INREPLYTO:
        case CRITERIA_REFERENCES:
@@ -1139,8 +1333,11 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
        case CRITERIA_REPLIED:
        case CRITERIA_FORWARDED:
        case CRITERIA_LOCKED:
+       case CRITERIA_SPAM:
        case CRITERIA_PARTIAL:
        case CRITERIA_IGNORE_THREAD:
+       case CRITERIA_WATCH_THREAD:
+       case CRITERIA_TAGGED:
                break;
 
        case CRITERIA_SUBJECT:
@@ -1148,6 +1345,7 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
        case CRITERIA_TO:
        case CRITERIA_CC:
        case CRITERIA_TO_OR_CC:
+       case CRITERIA_TAG:
        case CRITERIA_NEWSGROUPS:
        case CRITERIA_INREPLYTO:
        case CRITERIA_REFERENCES:
@@ -1174,7 +1372,6 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
                }
 
                value = atoi(value_str);
-
                break;
                
        case CRITERIA_COLORLABEL:
@@ -1184,7 +1381,6 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
                break;
 
        case CRITERIA_HEADER:
-
                header = gtk_entry_get_text(GTK_ENTRY(matcher.header_entry));
                expr = gtk_entry_get_text(GTK_ENTRY(matcher.value_entry));
 
@@ -1193,6 +1389,44 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
                    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;
+                       gchar *tmp;
+
+                       if (strcasecmp(header, Q_("Filtering Matcher Menu|All")) == 0)
+                               tmp = g_strdup(_("all addresses in all headers"));
+                       else
+                       if (strcasecmp(header, _("Any")) == 0)
+                               tmp = g_strdup(_("any address in any header"));
+                       else
+                               tmp = g_strdup_printf(_("the address(es) in header '%s'"), header);
+                       msg = g_strdup_printf(_("Book/folder path is not set.\n\n"
+                                               "If you want to match %s against the whole address book, "
+                                               "you have to select 'Any' from the book/folder drop-down list."),
+                                               tmp);
+                   alertpanel_error(msg);
+                       g_free(msg);
+                       g_free(tmp);
+                   return NULL;
+               }
+               /* don't store translated "Any"/"All" in matcher expressions */
+               if (strcasecmp(header, Q_("Filtering Matcher Menu|All")) == 0)
+                       header = "All";
+               else
+                       if (strcasecmp(header, _("Any")) == 0)
+                               header = "Any";
+               if (strcasecmp(expr, _("Any")) == 0)
+                       expr = "Any";
+               break;
        }
 
        matcherprop = matcherprop_new(criteria, header, matchtype,
@@ -1288,16 +1522,17 @@ static void prefs_matcher_up(void)
 {
        GtkTreePath *prev, *sel, *try;
        GtkTreeIter isel;
-       GtkListStore *store;
+       GtkListStore *store = NULL;
+       GtkTreeModel *model = NULL;
        GtkTreeIter iprev;
        
        if (!gtk_tree_selection_get_selected
                (gtk_tree_view_get_selection
                        (GTK_TREE_VIEW(matcher.cond_list_view)),
-                (GtkTreeModel **) &store,      
+                &model,        
                 &isel))
                return;
-
+       store = (GtkListStore *)model;
        sel = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &isel);
        if (!sel)
                return;
@@ -1329,17 +1564,18 @@ static void prefs_matcher_up(void)
  */
 static void prefs_matcher_down(void)
 {
-       GtkListStore *store;
+       GtkListStore *store = NULL;
+       GtkTreeModel *model = NULL;
        GtkTreeIter next, sel;
        GtkTreePath *try;
        
        if (!gtk_tree_selection_get_selected
                (gtk_tree_view_get_selection
                        (GTK_TREE_VIEW(matcher.cond_list_view)),
-                (GtkTreeModel **) &store,
+                &model,
                 &sel))
                return;
-
+       store = (GtkListStore *)model;
        try = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &sel);
        if (!try) 
                return;
@@ -1371,13 +1607,29 @@ static void prefs_matcher_set_value_widget(GtkWidget *old_widget,
        gtk_widget_ref(old_widget);
        gtkut_container_remove(GTK_CONTAINER(matcher.criteria_table), old_widget);
        gtk_widget_show(new_widget);
-       gtk_widget_set_usize(new_widget, 200, -1);
+       gtk_widget_set_size_request(new_widget, 200, -1);
        gtk_table_attach(GTK_TABLE(matcher.criteria_table), new_widget, 
                         2, 3, 1, 2, 
                         GTK_FILL | GTK_SHRINK | GTK_EXPAND, 
                         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
  *
@@ -1394,7 +1646,10 @@ static void prefs_matcher_criteria_select(GtkList *list,
        old_value = matcher.selected_criteria;
        matcher.selected_criteria = value = get_sel_from_list
                (GTK_LIST(matcher.criteria_list));
-       
+
+       if (old_value == matcher.selected_criteria)
+               return;
+
        /* CLAWS: the value widget is currently either the color label combo box,
         * or a GtkEntry, so kiss for now */
        if (matcher.selected_criteria == CRITERIA_COLORLABEL) { 
@@ -1407,18 +1662,21 @@ static void prefs_matcher_criteria_select(GtkList *list,
 
        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_checkbtn);
+               prefs_matcher_disable_widget(matcher.regexp_checkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
                break;
 
        case CRITERIA_UNREAD:
@@ -1428,34 +1686,44 @@ static void prefs_matcher_criteria_select(GtkList *list,
        case CRITERIA_REPLIED:
        case CRITERIA_FORWARDED:
        case CRITERIA_LOCKED:
+       case CRITERIA_SPAM:
        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);
+       case CRITERIA_WATCH_THREAD:
+       case CRITERIA_TAGGED:
+               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_checkbtn);
+               prefs_matcher_disable_widget(matcher.regexp_checkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
                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_checkbtn);
+               prefs_matcher_disable_widget(matcher.regexp_checkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
                break;
 
        case CRITERIA_SUBJECT:
@@ -1463,39 +1731,46 @@ static void prefs_matcher_criteria_select(GtkList *list,
        case CRITERIA_TO:
        case CRITERIA_CC:
        case CRITERIA_TO_OR_CC:
+       case CRITERIA_TAG:
        case CRITERIA_NEWSGROUPS:
        case CRITERIA_INREPLYTO:
        case CRITERIA_REFERENCES:
        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_checkbtn);
+               prefs_matcher_enable_widget(matcher.regexp_checkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
                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_checkbtn);
+               prefs_matcher_disable_widget(matcher.regexp_checkbtn);
+               prefs_matcher_enable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
                break;
 
        case CRITERIA_AGE_GREATER:
@@ -1506,33 +1781,57 @@ static void prefs_matcher_criteria_select(GtkList *list,
        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_checkbtn);
+               prefs_matcher_disable_widget(matcher.regexp_checkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_disable_widget(matcher.addressbook_select_btn);
                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_checkbtn);
+               prefs_matcher_enable_widget(matcher.regexp_checkbtn);
+               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_checkbtn);
+               prefs_matcher_disable_widget(matcher.regexp_checkbtn);
+               prefs_matcher_disable_widget(matcher.test_btn);
+               prefs_matcher_enable_widget(matcher.addressbook_select_btn);
                break;
        }
 }
@@ -1601,8 +1900,8 @@ static void prefs_matcher_ok(void)
 
                                if (!matcher_str || strcmp(matcher_str, str) != 0) {
                                        val = alertpanel(_("Entry not saved"),
-                                                        _("The entry was not saved\nHave you really finished?"),
-                                                        _("Yes"), _("No"), NULL);
+                                                        _("The entry was not saved.\nClose anyway?"),
+                                                        GTK_STOCK_CLOSE, _("+_Continue editing"), NULL);
                                        if (G_ALERTDEFAULT != val) {
                                                g_free(matcher_str);                                             
                                                g_free(str);
@@ -1643,11 +1942,7 @@ static gint prefs_matcher_deleted(GtkWidget *widget, GdkEventAny *event,
  * When adding new lines, remember to put 2 strings for each line
  */
 static gchar *test_desc_strings[] = {
-       N_("'Test' allows you to test a message or message element"), NULL,
-       N_("using an external program or script. The program will"), NULL,
-       N_("return either 0 or 1"), NULL,
-       N_("The following symbols can be used:"), NULL,
-       "%%",   "%",
+       "%%",   N_("literal %"),
        "%s",   N_("Subject"),
        "%f",   N_("From"),
        "%t",   N_("To"),
@@ -1656,7 +1951,7 @@ static gchar *test_desc_strings[] = {
        "%i",   N_("Message-ID"),
        "%n",   N_("Newsgroups"),
        "%r",   N_("References"),
-       "%F",   N_("Filename - should not be modified"),
+       "%F",   N_("filename (should not be modified)"),
        "\\n",  N_("new line"),
        "\\",   N_("escape character for quotes"),
        "\\\"", N_("quote character"),
@@ -1664,9 +1959,14 @@ static gchar *test_desc_strings[] = {
 };
 
 static DescriptionWindow test_desc_win = { 
+       NULL,
         NULL, 
         2,
         N_("Match Type: 'Test'"),
+       N_("'Test' allows you to test a message or message element "
+          "using an external program or script. The program will "
+          "return either 0 or 1.\n\n"
+          "The following symbols can be used:"),
         test_desc_strings
 };
 
@@ -1680,6 +1980,18 @@ void prefs_matcher_test_info(void)
        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
  */
@@ -1725,7 +2037,7 @@ static GtkWidget *prefs_matcher_list_view_create(void)
        list_view = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
        g_object_unref(model);  
        
-       gtk_tree_view_set_rules_hint(list_view, TRUE);
+       gtk_tree_view_set_rules_hint(list_view, prefs_common.use_stripes_everywhere);
        
        selector = gtk_tree_view_get_selection(list_view);
        gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE);
@@ -1803,21 +2115,27 @@ static gboolean prefs_matcher_selected(GtkTreeSelection *selector,
        case MATCHCRITERIA_NOT_REPLIED:
        case MATCHCRITERIA_NOT_FORWARDED:
        case MATCHCRITERIA_NOT_LOCKED:
+       case MATCHCRITERIA_NOT_SPAM:
        case MATCHCRITERIA_NOT_PARTIAL:
        case MATCHCRITERIA_NOT_COLORLABEL:
        case MATCHCRITERIA_NOT_IGNORE_THREAD:
+       case MATCHCRITERIA_NOT_WATCH_THREAD:
        case MATCHCRITERIA_NOT_SUBJECT:
        case MATCHCRITERIA_NOT_FROM:
        case MATCHCRITERIA_NOT_TO:
        case MATCHCRITERIA_NOT_CC:
+       case MATCHCRITERIA_NOT_TO_AND_NOT_CC:
+       case MATCHCRITERIA_NOT_TAG:
+       case MATCHCRITERIA_NOT_TAGGED:
        case MATCHCRITERIA_NOT_NEWSGROUPS:
        case MATCHCRITERIA_NOT_INREPLYTO:
        case MATCHCRITERIA_NOT_REFERENCES:
-       case MATCHCRITERIA_NOT_TO_AND_NOT_CC:
-       case MATCHCRITERIA_NOT_BODY_PART:
-       case MATCHCRITERIA_NOT_MESSAGE:
-       case MATCHCRITERIA_NOT_HEADERS_PART:
        case MATCHCRITERIA_NOT_HEADER:
+       case MATCHCRITERIA_NOT_HEADERS_PART:
+       case MATCHCRITERIA_NOT_MESSAGE:
+       case MATCHCRITERIA_NOT_BODY_PART:
+       case MATCHCRITERIA_NOT_TEST:
+       case MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK:
                negative_cond = TRUE;
                break;
        }
@@ -1831,17 +2149,20 @@ static gboolean prefs_matcher_selected(GtkTreeSelection *selector,
        case MATCHCRITERIA_NOT_TO:
        case MATCHCRITERIA_NOT_CC:
        case MATCHCRITERIA_NOT_TO_AND_NOT_CC:
+       case MATCHCRITERIA_NOT_TAG:
        case MATCHCRITERIA_NOT_NEWSGROUPS:
        case MATCHCRITERIA_NOT_INREPLYTO:
        case MATCHCRITERIA_NOT_REFERENCES:
        case MATCHCRITERIA_NOT_HEADERS_PART:
        case MATCHCRITERIA_NOT_BODY_PART:
        case MATCHCRITERIA_NOT_MESSAGE:
+       case MATCHCRITERIA_NOT_TEST:
        case MATCHCRITERIA_SUBJECT:
        case MATCHCRITERIA_FROM:
        case MATCHCRITERIA_TO:
        case MATCHCRITERIA_CC:
        case MATCHCRITERIA_TO_OR_CC:
+       case MATCHCRITERIA_TAG:
        case MATCHCRITERIA_NEWSGROUPS:
        case MATCHCRITERIA_INREPLYTO:
        case MATCHCRITERIA_REFERENCES:
@@ -1852,6 +2173,31 @@ static gboolean prefs_matcher_selected(GtkTreeSelection *selector,
                gtk_entry_set_text(GTK_ENTRY(matcher.value_entry), prop->expr);
                break;
 
+       case MATCHCRITERIA_FOUND_IN_ADDRESSBOOK:
+       case MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK:
+       {
+               gchar *header;
+               gchar *expr;
+
+               /* matcher expressions contain UNtranslated "Any"/"All",
+                 select the relevant translated combo item */
+               if (strcasecmp(prop->header, "All") == 0)
+                       header = (gchar*)Q_("Filtering Matcher Menu|All");
+               else
+                       if (strcasecmp(prop->header, "Any") == 0)
+                               header = _("Any");
+                       else
+                               header = prop->header;
+               if (strcasecmp(prop->expr, "Any") == 0)
+                       expr = _("Any");
+               else
+                       expr = prop->expr;
+
+               gtk_entry_set_text(GTK_ENTRY(matcher.header_addr_entry), header);
+               gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(matcher.addressbook_folder_combo)->entry), expr);
+               break;
+       }
+
        case MATCHCRITERIA_AGE_GREATER:
        case MATCHCRITERIA_AGE_LOWER:
        case MATCHCRITERIA_SCORE_GREATER:
@@ -1876,30 +2222,33 @@ static gboolean prefs_matcher_selected(GtkTreeSelection *selector,
                break;
        }
 
-       if (negative_cond)
+       if (negative_cond) {
                gtk_list_select_item(GTK_LIST(matcher.predicate_list), 1);
-       else
+               gtk_list_select_item(GTK_LIST(matcher.predicate_flag_list), 1);
+       } else {
                gtk_list_select_item(GTK_LIST(matcher.predicate_list), 0);
-
+               gtk_list_select_item(GTK_LIST(matcher.predicate_flag_list), 0);
+       }
+       
        switch(prop->matchtype) {
        case MATCHTYPE_MATCH:
-               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.regexp_chkbtn), FALSE);
-               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.case_chkbtn), TRUE);
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.regexp_checkbtn), FALSE);
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.case_checkbtn), TRUE);
                break;
 
        case MATCHTYPE_MATCHCASE:
-               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.regexp_chkbtn), FALSE);
-               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.case_chkbtn), FALSE);
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.regexp_checkbtn), FALSE);
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.case_checkbtn), FALSE);
                break;
 
        case MATCHTYPE_REGEXP:
-               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.regexp_chkbtn), TRUE);
-               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.case_chkbtn), TRUE);
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.regexp_checkbtn), TRUE);
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.case_checkbtn), TRUE);
                break;
 
        case MATCHTYPE_REGEXPCASE:
-               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.regexp_chkbtn), TRUE);
-               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.case_chkbtn), FALSE);
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.regexp_checkbtn), TRUE);
+               gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.case_checkbtn), FALSE);
                break;
        }