2006-09-12 [colin] 2.4.0cvs178
[claws.git] / src / prefs_matcher.c
index dd4a7ae69a3c323643450bee95a0096decc79114..0e567bba75552f75b08a2eca72207a31943892f1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2001 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2006 Hiroyuki Yamamoto 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
@@ -14,7 +14,7 @@
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
 #ifdef HAVE_CONFIG_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 *addressbook_folder_label;
+       GtkWidget *addressbook_folder_combo;
        GtkWidget *case_chkbtn;
        GtkWidget *regexp_chkbtn;
        GtkWidget *color_optmenu;
 
        GtkWidget *test_btn;
+       GtkWidget *addressbook_select_btn;
 
        GtkWidget *cond_list_view;
 
@@ -140,7 +146,9 @@ enum {
        CRITERIA_SIZE_SMALLER = 29,
        CRITERIA_SIZE_EQUAL   = 30,
        
-       CRITERIA_PARTIAL = 31
+       CRITERIA_PARTIAL = 31,
+
+       CRITERIA_FOUND_IN_ADDRESSBOOK = 32
 };
 
 /*!
@@ -158,14 +166,15 @@ static const gchar *criteria_text [] = {
        N_("Replied flag"), N_("Forwarded flag"),
        N_("Locked flag"),
        N_("Color label"),
-       N_("Ignore thread"),
+       N_("Ignored 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")
+       N_("Partially downloaded"),
+       N_("Found in addressbook")
 };
 
 /*!
@@ -202,6 +211,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
  *
@@ -315,6 +331,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 +364,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;
@@ -369,11 +402,13 @@ 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");
 
@@ -387,8 +422,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 +432,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);
@@ -438,7 +475,7 @@ static void prefs_matcher_create(void)
 
        g_list_free(combo_items);
 
-       gtk_widget_set_size_request(criteria_combo, 120, -1);
+       gtk_widget_set_size_request(criteria_combo, 170, -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 +496,7 @@ static void prefs_matcher_create(void)
 
        header_combo = gtk_combo_new();
        gtk_widget_show(header_combo);
-       gtk_widget_set_size_request(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 +507,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"));
@@ -484,14 +539,49 @@ 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);
 
-       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());
@@ -580,7 +670,7 @@ 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",
@@ -603,7 +693,7 @@ static void prefs_matcher_create(void)
 
        bool_op_combo = gtk_combo_new();
        gtk_widget_show(bool_op_combo);
-       gtk_widget_set_size_request(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);
@@ -654,7 +744,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,8 +768,13 @@ 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;
@@ -675,10 +784,14 @@ static void prefs_matcher_create(void)
        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.cond_list_view = cond_list_view;
+
+       matcher.selected_criteria = -1;
+       prefs_matcher_criteria_select(GTK_LIST(criteria_list), NULL, NULL);
 }
 
 /*!
@@ -695,7 +808,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 +832,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), "");
 }
 
 /*!
@@ -875,7 +990,6 @@ static gint prefs_matcher_get_criteria_from_matching(gint matching_id)
        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 +1015,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;
        }
@@ -981,6 +1098,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;
        }
@@ -1043,6 +1162,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;
        }
@@ -1091,6 +1212,7 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
        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;
@@ -1174,7 +1296,6 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
                }
 
                value = atoi(value_str);
-
                break;
                
        case CRITERIA_COLORLABEL:
@@ -1184,7 +1305,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 +1313,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,
@@ -1380,6 +1538,22 @@ static void prefs_matcher_set_value_widget(GtkWidget *old_widget,
                         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
  *
@@ -1396,7 +1570,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) { 
@@ -1409,18 +1586,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_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:
@@ -1432,32 +1612,39 @@ static void prefs_matcher_criteria_select(GtkList *list,
        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:
-               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:
@@ -1471,33 +1658,39 @@ static void prefs_matcher_criteria_select(GtkList *list,
        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:
-               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:
@@ -1508,33 +1701,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_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:
-               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;
        }
 }
@@ -1603,8 +1820,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?"),
-                                                        GTK_STOCK_YES, GTK_STOCK_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);
@@ -1645,11 +1862,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"),
@@ -1658,7 +1871,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"),
@@ -1670,6 +1883,10 @@ static DescriptionWindow test_desc_win = {
         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
 };
 
@@ -1683,6 +1900,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
  */
@@ -1728,7 +1957,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, prefs_common.enable_rules_hint);
+       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);
@@ -1813,14 +2042,16 @@ static gboolean prefs_matcher_selected(GtkTreeSelection *selector,
        case MATCHCRITERIA_NOT_FROM:
        case MATCHCRITERIA_NOT_TO:
        case MATCHCRITERIA_NOT_CC:
+       case MATCHCRITERIA_NOT_TO_AND_NOT_CC:
        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;
        }
@@ -1840,6 +2071,7 @@ static gboolean prefs_matcher_selected(GtkTreeSelection *selector,
        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:
@@ -1855,6 +2087,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 = 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:
@@ -1879,11 +2136,14 @@ 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);