several actions for each filtering rules can now be defined
authorHoà Viêt Dinh <dinh.viet.hoa@free.fr>
Thu, 7 Aug 2003 13:30:23 +0000 (13:30 +0000)
committerHoà Viêt Dinh <dinh.viet.hoa@free.fr>
Thu, 7 Aug 2003 13:30:23 +0000 (13:30 +0000)
ChangeLog.claws
Makefile.am
configure.ac
src/Makefile.am
src/filtering.c
src/filtering.h
src/matcher_parser.h
src/matcher_parser_parse.y
src/prefs_filtering.c
src/prefs_filtering_action.c [new file with mode: 0644]
src/prefs_filtering_action.h [new file with mode: 0644]

index 721c11bf7df929322a9ff0b20abf0dca4f5ff61d..60bd2e8f0bda35d085160b54e4830f6df5e31c40 100644 (file)
@@ -1,3 +1,17 @@
+2003-08-07 [hoa] 0.9.4claws7
+
+       * src/filtering.[ch]
+       * src/matcher_parser.h
+       * src/matcher_parser_parse.y
+               can define several actions for each filtering rule
+               can import old versions of filtering rules
+
+       * src/prefs_filtering.c
+               call to a new dialog box to define actions
+
+       * src/prefs_filtering_action.[ch]
+               dialog box to define actions for filtering rules
+
 2003-08-06 [christoph] 0.9.4claws6
 
        * src/imap.c
index 59d283ff5c2a71122caa0d0c1f8e7aff62f478c5..945e0e1912218fdea5f3561567f76847c459074c 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = ac po intl src man manual faq tools config
+SUBDIRS = ac po src man manual faq tools config intl
 
 EXTRA_DIST = \
        ChangeLog.claws \
index d23fac3ed342199b0b43b4663c03aa84bcef300e..7b250f8ba34e287517728b9d317590cc1c2ffd5b 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=9
 MICRO_VERSION=4
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=6
+EXTRA_VERSION=7
 if test $EXTRA_VERSION -eq 0; then
     VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}claws
 else
index 025b878d61f1a38566c3f39f9bfa2efa7d3d2a68..25c6e6bdf79b163149457a60243b4cdfba30851d 100644 (file)
@@ -82,6 +82,7 @@ sylpheed_SOURCES = \
        prefs_customheader.c \
        prefs_display_header.c \
        prefs_filtering.c \
+       prefs_filtering_action.c \
        prefs_folder_item.c \
        prefs_gtk.c \
        prefs_matcher.c \
@@ -200,6 +201,7 @@ sylpheedinclude_HEADERS = \
        prefs_customheader.h \
        prefs_display_header.h \
        prefs_filtering.h \
+       prefs_filtering_action.h \
        prefs_folder_item.h \
        prefs_gtk.h \
        prefs_matcher.h \
index 934eb08d437e165bde2e91f8ac382f19f25014be..2bba0912d777ebef9d692c05517c881e867b2cc0 100644 (file)
@@ -36,6 +36,8 @@
 
 GSList * global_processing = NULL;
 
+static gboolean filtering_is_final_action(FilteringAction *filtering_action);
+
 #define STRLEN_WITH_CHECK(expr) \
         strlen_with_check(#expr, __LINE__, expr)
                
@@ -86,17 +88,38 @@ void filteringaction_free(FilteringAction * action)
 }
 
 FilteringProp * filteringprop_new(MatcherList * matchers,
-                                 FilteringAction * action)
+                                 GSList * action_list)
 {
        FilteringProp * filtering;
 
        filtering = g_new0(FilteringProp, 1);
        filtering->matchers = matchers;
-       filtering->action = action;
+       filtering->action_list = action_list;
 
        return filtering;
 }
 
+static FilteringAction * filteringaction_copy(FilteringAction * src)
+{
+        FilteringAction * new;
+        
+        new = g_new0(FilteringAction, 1);
+        
+       new->type = src->type;
+       new->account_id = src->account_id;
+       if (src->destination)
+               new->destination = g_strdup(src->destination);
+       else 
+               new->destination = NULL;
+       if (src->unesc_destination)
+               new->unesc_destination = g_strdup(src->unesc_destination);
+       else
+               new->unesc_destination = NULL;
+       new->labelcolor = src->labelcolor;
+
+        return new;
+}
+
 FilteringProp * filteringprop_copy(FilteringProp *src)
 {
        FilteringProp * new;
@@ -104,7 +127,11 @@ FilteringProp * filteringprop_copy(FilteringProp *src)
        
        new = g_new0(FilteringProp, 1);
        new->matchers = g_new0(MatcherList, 1);
+
+#if 0
        new->action = g_new0(FilteringAction, 1);
+#endif
+
        for (tmp = src->matchers->matchers; tmp != NULL && tmp->data != NULL;) {
                MatcherProp *matcher = (MatcherProp *)tmp->data;
                
@@ -112,7 +139,10 @@ FilteringProp * filteringprop_copy(FilteringProp *src)
                                                   matcherprop_copy(matcher));
                tmp = tmp->next;
        }
+
        new->matchers->bool_and = src->matchers->bool_and;
+
+#if 0
        new->action->type = src->action->type;
        new->action->account_id = src->action->account_id;
        if (src->action->destination)
@@ -124,14 +154,31 @@ FilteringProp * filteringprop_copy(FilteringProp *src)
        else
                new->action->unesc_destination = NULL;
        new->action->labelcolor = src->action->labelcolor;
+#endif
+        new->action_list = NULL;
+
+        for (tmp = src->action_list ; tmp != NULL ; tmp = tmp->next) {
+                FilteringAction *filtering_action;
+                
+                filtering_action = tmp->data;
+                
+                new->action_list = g_slist_append(new->action_list,
+                    filteringaction_copy(filtering_action));
+        }
+
        return new;
 }
 
 void filteringprop_free(FilteringProp * prop)
 {
+        GSList * tmp;
+
        g_return_if_fail(prop);
        matcherlist_free(prop->matchers);
-       filteringaction_free(prop->action);
+        
+        for (tmp = prop->action_list ; tmp != NULL ; tmp = tmp->next) {
+                filteringaction_free(tmp->data);
+        }
        g_free(prop);
 }
 
@@ -297,21 +344,35 @@ static gboolean filtering_match_condition(FilteringProp *filtering, MsgInfo *inf
        return matcherlist_match(filtering->matchers, info);
 }
 
-static gboolean filtering_apply_rule(FilteringProp *filtering, MsgInfo *info)
+static gboolean filtering_apply_rule(FilteringProp *filtering, MsgInfo *info,
+    gboolean * final)
 {
        gboolean result;
        gchar    buf[50];
-
-       if (FALSE == (result = filteringaction_apply(filtering->action, info))) {
-               g_warning("action %s could not be applied", 
-               filteringaction_to_string(buf, sizeof buf, filtering->action));
-       }
+        GSList * tmp;
+        
+        * final = FALSE;
+        for (tmp = filtering->action_list ; tmp != NULL ; tmp = tmp->next) {
+                FilteringAction * action;
+                
+                action = tmp->data;
+                
+                if (FALSE == (result = filteringaction_apply(action, info))) {
+                        g_warning("action %s could not be applied", 
+                            filteringaction_to_string(buf, sizeof buf, action));
+                }
+                
+                if (filtering_is_final_action(action)) {
+                        * final = TRUE;
+                        break;
+                }
+        }
        return result;
 }
 
-static gboolean filtering_is_final_action(FilteringProp *filtering)
+static gboolean filtering_is_final_action(FilteringAction *filtering_action)
 {
-       switch(filtering->action->type) {
+       switch(filtering_action->type) {
        case MATCHACTION_MOVE:
        case MATCHACTION_DELETE:
                return TRUE; /* MsgInfo invalid for message */
@@ -344,9 +405,13 @@ static gboolean filter_msginfo(GSList * filtering_list, MsgInfo * info)
                FilteringProp * filtering = (FilteringProp *) l->data;
 
                if (filtering_match_condition(filtering, info)) {
-                       applied = filtering_apply_rule(filtering, info);
+                       applied = filtering_apply_rule(filtering, info, &final);
+#if 0
                        if (TRUE == (final = filtering_is_final_action(filtering)))
                                break;
+#endif
+                        if (final)
+                                break;
                }               
        }
 
@@ -404,24 +469,57 @@ gchar *filteringaction_to_string(gchar *dest, gint destlen, FilteringAction *act
        }
 }
 
+gchar * filteringaction_list_to_string(GSList * action_list)
+{
+       gchar *action_list_str;
+       gchar  buf[256];
+        GSList * tmp;
+       gchar *list_str;
+
+        action_list_str = NULL;
+        for (tmp = action_list ; tmp != NULL ; tmp = tmp->next) {
+                gchar *action_str;
+                FilteringAction * action;
+                
+                action = tmp->data;
+                
+                action_str = filteringaction_to_string(buf,
+                    sizeof buf, action);
+                
+                if (action_list_str != NULL) {
+                        list_str = g_strconcat(action_list_str, " ", action_str, NULL);
+                        g_free(action_list_str);
+                }
+                else {
+                        list_str = g_strdup(action_str);
+                }
+                action_list_str = list_str;
+        }
+
+        return action_list_str;
+}
+
 gchar * filteringprop_to_string(FilteringProp * prop)
 {
        gchar *list_str;
-       gchar *action_str;
+       gchar *action_list_str;
        gchar *filtering_str;
-       gchar  buf[256];
+        GSList * tmp;
 
-       action_str = filteringaction_to_string(buf, sizeof buf, prop->action);
+        action_list_str = filteringaction_list_to_string(prop->action_list);
 
-       if (action_str == NULL)
+       if (action_list_str == NULL)
                return NULL;
 
        list_str = matcherlist_to_string(prop->matchers);
 
-       if (list_str == NULL)
+       if (list_str == NULL) {
+                g_free(action_list_str);
                return NULL;
+        }
 
-       filtering_str = g_strconcat(list_str, " ", action_str, NULL);
+       filtering_str = g_strconcat(list_str, " ", action_list_str, NULL);
+       g_free(action_list_str);
        g_free(list_str);
 
        return filtering_str;
index 0b8f5e6bde9f820d0ac024a8d8c6b0a8e0a1d2ee..bda6ca59dfedcf5ec3bf72b88b4873c889425c66 100644 (file)
@@ -37,7 +37,7 @@ typedef struct _FilteringAction FilteringAction;
 
 struct _FilteringProp {
        MatcherList * matchers;
-       FilteringAction * action;
+       GSList * action_list;
 };
 
 typedef struct _FilteringProp FilteringProp;
@@ -52,7 +52,7 @@ void filteringaction_free(FilteringAction *action);
 FilteringAction * filteringaction_parse(gchar **str);
 
 FilteringProp * filteringprop_new(MatcherList *matchers,
-                                 FilteringAction *action);
+                                 GSList *action_list);
 void filteringprop_free(FilteringProp *prop);
 
 FilteringProp * filteringprop_parse(gchar **str);
@@ -63,6 +63,7 @@ gboolean filter_message_by_msginfo(GSList *flist, MsgInfo *info);
 gchar * filteringaction_to_string(gchar *dest, gint destlen, FilteringAction *action);
 void prefs_filtering_write_config(void);
 void prefs_filtering_read_config(void);
+gchar * filteringaction_list_to_string(GSList * action_list);
 gchar * filteringprop_to_string(FilteringProp *prop);
 
 void prefs_filtering_clear(void);
index ff2fbd86426f020a1eaaf71e752a79d6c110300c..f9bd43a432d04d3afdb7b725b6cb3bf48d0193e1 100644 (file)
@@ -35,5 +35,6 @@ MatcherList *matcher_parser_get_cond  (gchar *str);
 MatcherProp *matcher_parser_get_prop   (gchar *str);
 FilteringProp *matcher_parser_get_filtering    (gchar *str);
 ScoringProp *matcher_parser_get_scoring                (gchar *str);
+GSList *matcher_parser_get_action_list(gchar *str);
 
 #endif
index 559f680d6eba63ef1ae2a24d97c1e7cc8024a1b9..bbe8a6d8c72dd0430add1cf779554ade4751317e 100644 (file)
@@ -46,6 +46,7 @@ static GSList *matchers_list = NULL;
 
 static MatcherList *cond;
 static gint score = 0;
+static GSList *action_list = NULL;
 static FilteringAction *action = NULL;
 
 static FilteringProp *filtering;
@@ -54,7 +55,19 @@ static ScoringProp *scoring = NULL;
 static GSList **prefs_scoring = NULL;
 static GSList **prefs_filtering = NULL;
 
+#if 0
 static int matcher_parser_dialog = 0;
+#endif
+
+enum {
+        MATCHER_PARSE_NONE,
+        MATCHER_PARSE_NO_EOL,
+        MATCHER_PARSE_CONDITION,
+        MATCHER_PARSE_FILTERING_OR_SCORING,
+};
+
+static int matcher_parse_op = MATCHER_PARSE_NONE;
+
 
 /* ******************************************************************** */
 
@@ -71,14 +84,14 @@ FilteringProp *matcher_parser_get_filtering(gchar *str)
        /* bad coding to enable the sub-grammar matching
           in yacc */
        matcher_parserlineno = 1;
-       matcher_parser_dialog = 1;
+       matcher_parse_op = MATCHER_PARSE_NO_EOL;
        matcher_parserrestart(NULL);
         matcher_parser_init();
        bufstate = matcher_parser_scan_string(str);
         matcher_parser_switch_to_buffer(bufstate);
        if (matcher_parserparse() != 0)
                filtering = NULL;
-       matcher_parser_dialog = 0;
+       matcher_parse_op = MATCHER_PARSE_NONE;
        matcher_parser_delete_buffer(bufstate);
        return filtering;
 }
@@ -90,14 +103,14 @@ ScoringProp *matcher_parser_get_scoring(gchar *str)
        /* bad coding to enable the sub-grammar matching
           in yacc */
        matcher_parserlineno = 1;
-       matcher_parser_dialog = 1;
+       matcher_parse_op = MATCHER_PARSE_NO_EOL;
        matcher_parserrestart(NULL);
         matcher_parser_init();
        bufstate = matcher_parser_scan_string(str);
         matcher_parser_switch_to_buffer(bufstate);
        if (matcher_parserparse() != 0)
                scoring = NULL;
-       matcher_parser_dialog = 0;
+       matcher_parse_op = MATCHER_PARSE_NONE;
        matcher_parser_delete_buffer(bufstate);
        return scoring;
 }
@@ -133,16 +146,38 @@ MatcherList *matcher_parser_get_cond(gchar *str)
        /* bad coding to enable the sub-grammar matching
           in yacc */
        matcher_parserlineno = 1;
-       matcher_parser_dialog = 1;
+       matcher_parse_op = MATCHER_PARSE_CONDITION;
        matcher_parserrestart(NULL);
         matcher_parser_init();
        bufstate = matcher_parser_scan_string(str);
        matcher_parserparse();
-       matcher_parser_dialog = 0;
+       matcher_parse_op = MATCHER_PARSE_NONE;
        matcher_parser_delete_buffer(bufstate);
        return cond;
 }
 
+GSList *matcher_parser_get_action_list(gchar *str)
+{
+       void *bufstate;
+
+       if (!check_quote_symetry(str)) {
+               action_list = NULL;
+               return action_list;
+       }
+       
+       /* bad coding to enable the sub-grammar matching
+          in yacc */
+       matcher_parserlineno = 1;
+       matcher_parse_op = MATCHER_PARSE_FILTERING_OR_SCORING;
+       matcher_parserrestart(NULL);
+        matcher_parser_init();
+       bufstate = matcher_parser_scan_string(str);
+       matcher_parserparse();
+       matcher_parse_op = MATCHER_PARSE_NONE;
+       matcher_parser_delete_buffer(bufstate);
+       return action_list;
+}
+
 MatcherProp *matcher_parser_get_prop(gchar *str)
 {
        MatcherList *list;
@@ -233,7 +268,7 @@ int matcher_parserwrap(void)
 
 file:
 {
-       if (!matcher_parser_dialog) {
+       if (matcher_parse_op == MATCHER_PARSE_NONE) {
                prefs_scoring = &global_scoring;
                prefs_filtering = &global_processing;
        }
@@ -248,7 +283,9 @@ file_line_list
 
 file_line:
 section_notification
-| instruction
+| 
+{ action_list = NULL; }
+instruction
 | error MATCHER_EOL
 {
        yyerrok;
@@ -260,7 +297,7 @@ MATCHER_SECTION MATCHER_EOL
        gchar *folder = $1;
        FolderItem *item = NULL;
 
-       if (!matcher_parser_dialog) {
+       if (matcher_parse_op == MATCHER_PARSE_NONE) {
                if (!strcmp(folder, "global")) {
                        prefs_scoring = &global_scoring;
                        prefs_filtering = &global_processing;
@@ -279,43 +316,44 @@ MATCHER_SECTION MATCHER_EOL
 ;
 
 instruction:
-condition end_instr_opt
-| MATCHER_EOL
-;
-
-end_instr_opt:
-filtering_or_scoring end_action
-|
+condition filtering_or_scoring MATCHER_EOL
+| condition filtering_or_scoring
 {
-       if (matcher_parser_dialog)
+       if (matcher_parse_op == MATCHER_PARSE_NO_EOL)
                YYACCEPT;
        else {
                matcher_parsererror("parse error");
                YYERROR;
        }
 }
-;
-
-end_action:
-MATCHER_EOL
-|
+| condition
+{
+       if (matcher_parse_op == MATCHER_PARSE_CONDITION)
+               YYACCEPT;
+       else {
+               matcher_parsererror("parse error");
+               YYERROR;
+       }
+}
+| filtering_action_list
 {
-       if (matcher_parser_dialog)
+       if (matcher_parse_op == MATCHER_PARSE_FILTERING_OR_SCORING)
                YYACCEPT;
        else {
                matcher_parsererror("parse error");
                YYERROR;
        }
 }
+| MATCHER_EOL
 ;
 
 filtering_or_scoring:
-filtering_action
+filtering_action_list
 {
-       filtering = filteringprop_new(cond, action);
+       filtering = filteringprop_new(cond, action_list);
        cond = NULL;
-       action = NULL;
-       if (!matcher_parser_dialog && (prefs_filtering != NULL)) {
+       action_list = NULL;
+       if ((matcher_parse_op == MATCHER_PARSE_NONE) && (prefs_filtering != NULL)) {
                *prefs_filtering = g_slist_append(*prefs_filtering,
                                                  filtering);
                filtering = NULL;
@@ -326,13 +364,27 @@ filtering_action
        scoring = scoringprop_new(cond, score);
        cond = NULL;
        score = 0;
-       if (!matcher_parser_dialog && (prefs_scoring != NULL)) {
+       if ((matcher_parse_op == MATCHER_PARSE_NONE)
+            && (prefs_scoring != NULL)) {
                *prefs_scoring = g_slist_append(*prefs_scoring, scoring);
                scoring = NULL;
        }
 }
 ;
 
+filtering_action_list:
+filtering_action_b filtering_action_list
+| filtering_action_b
+;
+
+filtering_action_b:
+filtering_action
+{
+        action_list = g_slist_append(action_list, action);
+        action = NULL;
+}
+;
+
 match_type:
 MATCHER_MATCHCASE
 {
index 77cf6f0aa95bfb2d853aed3fe8d139faf1e3e7c7..900076f2b6a9eaea462f5fd2e0534f2fc14d0b18 100644 (file)
@@ -58,25 +58,9 @@ static struct Filtering {
 
        GtkWidget *ok_btn;
        GtkWidget *cond_entry;
-       GtkWidget *action_list;
-       GtkWidget *action_combo;
-       GtkWidget *account_label;
-       GtkWidget *account_list;
-       GtkWidget *account_combo;
-       GtkWidget *dest_entry;
-       GtkWidget *dest_btn;
-       GtkWidget *dest_label;
-       GtkWidget *recip_label;
-       GtkWidget *exec_label;
-       GtkWidget *exec_btn;
-
-       GtkWidget *color_label;
-       GtkWidget *color_optmenu;
+       GtkWidget *action_entry;
 
        GtkWidget *cond_clist;
-
-       /* need this to make address completion entry work */
-       gint current_action;
 } filtering;
 
 /* widget creating functions */
@@ -107,6 +91,7 @@ static void prefs_filtering_cancel   (void);
 static void prefs_filtering_ok         (void);
 
 static void prefs_filtering_condition_define   (void);
+static void prefs_filtering_action_define(void);
 static gint prefs_filtering_clist_set_row      (gint row, FilteringProp * prop);
 static void prefs_filtering_select_dest                (void);
 static void prefs_filtering_action_select      (GtkList *list,
@@ -312,19 +297,8 @@ static void prefs_filtering_create(void)
        GtkWidget *cond_entry;
        GtkWidget *cond_btn;
        GtkWidget *action_label;
-       GtkWidget *action_list;
-       GtkWidget *action_combo;
-       GtkWidget *account_label;
-       GtkWidget *account_list;
-       GtkWidget *account_combo;
-       GtkWidget *dest_label;
-       GtkWidget *recip_label;
-       GtkWidget *exec_label;
-       GtkWidget *dest_entry;
-       GtkWidget *dest_btn;
-       GtkWidget *exec_btn;
-       GtkWidget *color_label;
-       GtkWidget *color_optmenu;
+       GtkWidget *action_entry;
+       GtkWidget *action_btn;
 
        GtkWidget *reg_btn;
        GtkWidget *subst_btn;
@@ -404,128 +378,25 @@ static void prefs_filtering_create(void)
                            GTK_SIGNAL_FUNC (prefs_filtering_condition_define),
                            NULL);
 
-       hbox1 = gtk_hbox_new (FALSE, VSPACING);
-       gtk_widget_show (hbox1);
-       gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
-       gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
-
        action_label = gtk_label_new (_("Action"));
        gtk_widget_show (action_label);
        gtk_misc_set_alignment (GTK_MISC (action_label), 0, 0.5);
-       gtk_box_pack_start (GTK_BOX (hbox1), action_label, FALSE, FALSE, 0);
-
-       action_combo = gtk_combo_new ();
-       gtk_widget_show (action_combo);
-       gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(action_combo)->entry),
-                              FALSE);
-
-       combo_items = NULL;
-       for (i = 0; i < sizeof action_text / sizeof action_text[0]; i++)
-               combo_items = g_list_append
-                       (combo_items, (gpointer) _(action_text[i].text));
-       gtk_combo_set_popdown_strings(GTK_COMBO(action_combo), combo_items);
-
-       g_list_free(combo_items);
-
-       gtk_box_pack_start (GTK_BOX (hbox1), action_combo,
-                           TRUE, TRUE, 0);
-       action_list = GTK_COMBO(action_combo)->list;
-       gtk_signal_connect (GTK_OBJECT (action_list), "select-child",
-                           GTK_SIGNAL_FUNC (prefs_filtering_action_select),
-                           NULL);
-
-       gtk_signal_connect(GTK_OBJECT(action_list), "selection-changed",
-                          GTK_SIGNAL_FUNC(prefs_filtering_action_selection_changed),
-                          NULL);
-
-       /* accounts */
+       gtk_box_pack_start (GTK_BOX (vbox1), action_label, FALSE, FALSE, 0);
 
        hbox1 = gtk_hbox_new (FALSE, VSPACING);
        gtk_widget_show (hbox1);
        gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
        gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
 
-       account_label = gtk_label_new (_("Account"));
-       gtk_widget_show (account_label);
-       gtk_misc_set_alignment (GTK_MISC (account_label), 0, 0.5);
-       gtk_box_pack_start (GTK_BOX (hbox1), account_label, FALSE, FALSE, 0);
+       action_entry = gtk_entry_new ();
+       gtk_widget_show (action_entry);
+       gtk_box_pack_start (GTK_BOX (hbox1), action_entry, TRUE, TRUE, 0);
 
-       account_combo = gtk_combo_new ();
-       gtk_widget_show (account_combo);
-
-       combo_items = NULL;
-       for (accounts = account_get_list() ; accounts != NULL;
-            accounts = accounts->next) {
-               PrefsAccount *ac = (PrefsAccount *)accounts->data;
-               gchar *name;
-
-               name = g_strdup_printf("%s <%s> (%s)",
-                                      ac->name, ac->address,
-                                      ac->account_name);
-               combo_items = g_list_append(combo_items, (gpointer) name);
-       }
-
-       gtk_combo_set_popdown_strings(GTK_COMBO(account_combo), combo_items);
-
-       for(cur = g_list_first(combo_items) ; cur != NULL ;
-           cur = g_list_next(cur))
-               g_free(cur->data);
-       g_list_free(combo_items);
-
-       gtk_box_pack_start (GTK_BOX (hbox1), account_combo,
-                           TRUE, TRUE, 0);
-       account_list = GTK_COMBO(account_combo)->list;
-       gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(account_combo)->entry),
-                              FALSE);
-
-       /* destination */
-
-       hbox1 = gtk_hbox_new (FALSE, VSPACING);
-       gtk_widget_show (hbox1);
-       gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
-       gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
-
-       dest_label = gtk_label_new (_("Destination"));
-       gtk_widget_show (dest_label);
-       gtk_misc_set_alignment (GTK_MISC (dest_label), 0, 0.5);
-       gtk_box_pack_start (GTK_BOX (hbox1), dest_label, FALSE, FALSE, 0);
-
-       recip_label = gtk_label_new (_("Recipient"));
-       gtk_widget_show (recip_label);
-       gtk_misc_set_alignment (GTK_MISC (recip_label), 0, 0.5);
-       gtk_box_pack_start (GTK_BOX (hbox1), recip_label, FALSE, FALSE, 0);
-
-       exec_label = gtk_label_new (_("Execute"));
-       gtk_widget_show (exec_label);
-       gtk_misc_set_alignment (GTK_MISC (exec_label), 0, 0.5);
-       gtk_box_pack_start (GTK_BOX (hbox1), exec_label, FALSE, FALSE, 0);
-       
-       color_label = gtk_label_new (_("Color"));
-       gtk_widget_show(color_label);
-       gtk_misc_set_alignment(GTK_MISC(color_label), 0, 0.5);
-       gtk_box_pack_start(GTK_BOX(hbox1), color_label, FALSE, FALSE, 0);
-
-       dest_entry = gtk_entry_new ();
-       gtk_widget_show (dest_entry);
-       gtk_box_pack_start (GTK_BOX (hbox1), dest_entry, TRUE, TRUE, 0);
-       
-       color_optmenu = gtk_option_menu_new();
-       gtk_option_menu_set_menu(GTK_OPTION_MENU(color_optmenu),
-                                colorlabel_create_color_menu());
-       gtk_box_pack_start(GTK_BOX(hbox1), color_optmenu, TRUE, TRUE, 0);
-
-       dest_btn = gtk_button_new_with_label (_("Select ..."));
-       gtk_widget_show (dest_btn);
-       gtk_box_pack_start (GTK_BOX (hbox1), dest_btn, FALSE, FALSE, 0);
-       gtk_signal_connect (GTK_OBJECT (dest_btn), "clicked",
-                           GTK_SIGNAL_FUNC (prefs_filtering_select_dest),
-                           NULL);
-
-       exec_btn = gtk_button_new_with_label (_("Info ..."));
-       gtk_widget_show (exec_btn);
-       gtk_box_pack_start (GTK_BOX (hbox1), exec_btn, FALSE, FALSE, 0);
-       gtk_signal_connect (GTK_OBJECT (exec_btn), "clicked",
-                           GTK_SIGNAL_FUNC (prefs_matcher_exec_info),
+       action_btn = gtk_button_new_with_label (_("Define ..."));
+       gtk_widget_show (action_btn);
+       gtk_box_pack_start (GTK_BOX (hbox1), action_btn, FALSE, FALSE, 0);
+       gtk_signal_connect (GTK_OBJECT (action_btn), "clicked",
+                           GTK_SIGNAL_FUNC (prefs_filtering_action_define),
                            NULL);
 
        /* register / substitute / delete */
@@ -611,22 +482,8 @@ static void prefs_filtering_create(void)
        filtering.ok_btn = ok_btn;
 
        filtering.cond_entry = cond_entry;
-       filtering.action_list = action_list;
-       filtering.action_combo = action_combo;
-       filtering.account_label = account_label;
-       filtering.account_list = account_list;
-       filtering.account_combo = account_combo;
-       filtering.dest_entry = dest_entry;
-       filtering.dest_btn = dest_btn;
-       filtering.dest_label = dest_label;
-       filtering.recip_label = recip_label;
-       filtering.exec_label = exec_label;
-       filtering.exec_btn = exec_btn;
-
+       filtering.action_entry = action_entry;
        filtering.cond_clist   = cond_clist;
-
-       filtering.color_label   = color_label;
-       filtering.color_optmenu = color_optmenu;
 }
 
 static void prefs_filtering_update_hscrollbar(void)
@@ -663,6 +520,7 @@ static gboolean prefs_filtering_rename_path_func(GNode *node, gpointer data)
        gint prefixlen;
        gint oldpathlen;
        FolderItem *item;
+        GSList * action_cur;
 
        old_path = ((gchar **)data)[0];
        new_path = ((gchar **)data)[1];
@@ -681,59 +539,66 @@ static gboolean prefs_filtering_rename_path_func(GNode *node, gpointer data)
                cur = item->prefs->processing;
        }
 
+
        for (; cur != NULL; cur = cur->next) {
                FilteringProp   *filtering = (FilteringProp *)cur->data;
-               FilteringAction *action = filtering->action;
-
-               if (!action->destination) continue;
-
-               destlen = strlen(action->destination);
-
-               if (destlen > oldpathlen) {
-                       prefixlen = destlen - oldpathlen;
-                       suffix = action->destination + prefixlen;
-
-                       if (!strncmp(old_path, suffix, oldpathlen)) {
-                               prefix = g_malloc0(prefixlen + 1);
-                               strncpy2(prefix, action->destination, prefixlen);
-
-                               base = suffix + oldpathlen;
-                               while (*base == G_DIR_SEPARATOR) base++;
-                               if (*base == '\0')
-                                       dest_path = g_strconcat(prefix,
-                                                               G_DIR_SEPARATOR_S,
-                                                               new_path, NULL);
-                               else
-                                       dest_path = g_strconcat(prefix,
-                                                               G_DIR_SEPARATOR_S,
-                                                               new_path,
-                                                               G_DIR_SEPARATOR_S,
-                                                               base, NULL);
-
-                               g_free(prefix);
-                               g_free(action->destination);
-                               action->destination = dest_path;
-                       } else { /* for non-leaf folders */
-                               /* compare with trailing slash */
-                               if (!strncmp(old_path_with_sep, action->destination, oldpathlen+1)) {
-                                       
-                                       suffix = action->destination + oldpathlen + 1;
-                                       dest_path = g_strconcat(new_path,
-                                                               G_DIR_SEPARATOR_S,
-                                                               suffix, NULL);
-                                       g_free(action->destination);
-                                       action->destination = dest_path;
-                               }
-                       }
-               } else {
-                       /* folder-moving a leaf */
-                       if (!strcmp(old_path, action->destination)) {           
-                               dest_path = g_strdup(new_path);
-                               g_free(action->destination);
-                               action->destination = dest_path;
-                       }
-               }
-       }
+                
+                for(action_cur = filtering->action_list ; action_cur != NULL ;
+                    action_cur = action_cur->next) {
+
+                        FilteringAction *action = action_cur->data;
+                        
+                        if (!action->destination) continue;
+                        
+                        destlen = strlen(action->destination);
+                        
+                        if (destlen > oldpathlen) {
+                                prefixlen = destlen - oldpathlen;
+                                suffix = action->destination + prefixlen;
+                                
+                                if (!strncmp(old_path, suffix, oldpathlen)) {
+                                        prefix = g_malloc0(prefixlen + 1);
+                                        strncpy2(prefix, action->destination, prefixlen);
+                                        
+                                        base = suffix + oldpathlen;
+                                        while (*base == G_DIR_SEPARATOR) base++;
+                                        if (*base == '\0')
+                                                dest_path = g_strconcat(prefix,
+                                                    G_DIR_SEPARATOR_S,
+                                                    new_path, NULL);
+                                        else
+                                                dest_path = g_strconcat(prefix,
+                                                    G_DIR_SEPARATOR_S,
+                                                    new_path,
+                                                    G_DIR_SEPARATOR_S,
+                                                    base, NULL);
+                                        
+                                        g_free(prefix);
+                                        g_free(action->destination);
+                                        action->destination = dest_path;
+                                } else { /* for non-leaf folders */
+                                        /* compare with trailing slash */
+                                        if (!strncmp(old_path_with_sep, action->destination, oldpathlen+1)) {
+                                                
+                                                suffix = action->destination + oldpathlen + 1;
+                                                dest_path = g_strconcat(new_path,
+                                                    G_DIR_SEPARATOR_S,
+                                                    suffix, NULL);
+                                                g_free(action->destination);
+                                                action->destination = dest_path;
+                                        }
+                                }
+                        } else {
+                                /* folder-moving a leaf */
+                                if (!strcmp(old_path, action->destination)) {          
+                                        dest_path = g_strdup(new_path);
+                                        g_free(action->destination);
+                                        action->destination = dest_path;
+                                }
+                        }
+                }
+        }
+        
        g_free(old_path_with_sep);
        prefs_matcher_write_config();
 
@@ -755,13 +620,13 @@ void prefs_filtering_delete_path(const gchar *path)
 static gboolean prefs_filtering_delete_path_func(GNode *node, gpointer data)
 {
        GSList *cur, *orig;
-       GSList *next;
        gchar *path = (gchar *)data;
        gchar *suffix;
        gint destlen;
        gint prefixlen;
        gint pathlen;
        FolderItem *item;
+        GSList * action_cur;
        
        g_return_val_if_fail(path != NULL, FALSE);
 
@@ -778,41 +643,43 @@ static gboolean prefs_filtering_delete_path_func(GNode *node, gpointer data)
        
        for (; cur != NULL; cur = cur->next) {
                FilteringProp *filtering = (FilteringProp *)cur->data;
-               FilteringAction *action;
-               if (!cur->data)
-                       break;
-               
-               action = filtering->action;
-               next = cur->next;
-
-               if (!action->destination) continue;
-
-               destlen = strlen(action->destination);
-
-               if (destlen > pathlen) {
-                       prefixlen = destlen - pathlen;
-                       suffix = action->destination + prefixlen;
-
-                       if (suffix && !strncmp(path, suffix, pathlen)) {
-                               filteringprop_free(filtering);
-                               orig = g_slist_remove(orig, filtering);
-                       }
-               } else if (strcmp(action->destination, path) == 0) {
-                       filteringprop_free(filtering);
-                       orig = g_slist_remove(orig, filtering);
-
-               }
-       }
-
-       if (node == NULL)
-               global_processing = orig;
-       else {
-               item = node->data;
-               if (!item || !item->prefs)
+                
+                for(action_cur = filtering->action_list ; action_cur != NULL ;
+                    action_cur = action_cur->next) {
+                
+                        FilteringAction *action;
+                        
+                        action = action_cur->data;
+                        
+                        if (!action->destination) continue;
+                        
+                        destlen = strlen(action->destination);
+                        
+                        if (destlen > pathlen) {
+                                prefixlen = destlen - pathlen;
+                                suffix = action->destination + prefixlen;
+                                
+                                if (suffix && !strncmp(path, suffix, pathlen)) {
+                                        filteringprop_free(filtering);
+                                        orig = g_slist_remove(orig, filtering);
+                                }
+                        } else if (strcmp(action->destination, path) == 0) {
+                                filteringprop_free(filtering);
+                                orig = g_slist_remove(orig, filtering);
+                                
+                        }
+                }
+        }                
+        
+        if (node == NULL)
+                global_processing = orig;
+        else {
+                item = node->data;
+                if (!item || !item->prefs)
                        return FALSE;
-               item->prefs->processing = orig;
-       }
-
+                item->prefs->processing = orig;
+        }
+        
        prefs_matcher_write_config();
 
        return FALSE;
@@ -865,10 +732,8 @@ static void prefs_filtering_set_dialog(const gchar *header, const gchar *key)
 
 static void prefs_filtering_reset_dialog(void)
 {
-       gtk_list_select_item(GTK_LIST(filtering.action_list), 0);
-       gtk_list_select_item(GTK_LIST(filtering.account_list), 0);
-       gtk_entry_set_text(GTK_ENTRY(filtering.dest_entry), "");
        gtk_entry_set_text(GTK_ENTRY(filtering.cond_entry), "");
+       gtk_entry_set_text(GTK_ENTRY(filtering.action_entry), "");
 }
 
 static void prefs_filtering_set_list(void)
@@ -892,7 +757,6 @@ static void prefs_filtering_set_list(void)
        while (gtk_clist_get_text(GTK_CLIST(filtering.cond_clist),
                                  row, 0, &filtering_str)) {
                if (strcmp(filtering_str, _("(New)")) != 0) {
-                       /* tmp = filtering_str; */
                        prop = matcher_parser_get_filtering(filtering_str);
                        if (prop != NULL)
                                prefs_filtering =
@@ -967,6 +831,45 @@ static void prefs_filtering_condition_define(void)
                matcherlist_free(matchers);
 }
 
+static void prefs_filtering_action_define_done(GSList * action_list)
+{
+       gchar * str;
+
+       if (action_list == NULL)
+               return;
+
+       str = filteringaction_list_to_string(action_list);
+
+       if (str != NULL) {
+               gtk_entry_set_text(GTK_ENTRY(filtering.action_entry), str);
+               g_free(str);
+       }
+}
+
+static void prefs_filtering_action_define(void)
+{
+       gchar * action_str;
+       GSList * action_list = NULL;
+
+       action_str = gtk_entry_get_text(GTK_ENTRY(filtering.action_entry));
+
+       if (*action_str != '\0') {
+               action_list = matcher_parser_get_action_list(action_str);
+               if (action_list == NULL)
+                       alertpanel_error(_("Action string is not valid."));
+       }
+
+       prefs_filtering_action_open(action_list,
+            prefs_filtering_action_define_done);
+
+       if (action_list != NULL) {
+                GSList * cur;
+               for(cur = action_list ; cur != NULL ; cur = cur->next) {
+                        filteringaction_free(cur->data);
+                }
+        }
+}
+
 
 /* register / substitute delete buttons */
 
@@ -975,6 +878,7 @@ static FilteringProp * prefs_filtering_dialog_to_filtering(gboolean alert)
 {
        MatcherList * cond;
        gchar * cond_str;
+       gchar * action_str;
        FilteringProp * prop;
        FilteringAction * action;
        gint list_id;
@@ -983,58 +887,35 @@ static FilteringProp * prefs_filtering_dialog_to_filtering(gboolean alert)
        gint account_id;
        gchar * destination;
        gint labelcolor = 0;
-       
+       GSList * action_list;
+
        cond_str = gtk_entry_get_text(GTK_ENTRY(filtering.cond_entry));
        if (*cond_str == '\0') {
                if(alert == TRUE) alertpanel_error(_("Condition string is empty."));
                return NULL;
        }
 
-       action_id = get_sel_from_list(GTK_LIST(filtering.action_list));
-       action_type = prefs_filtering_get_matching_from_action(action_id);
-       list_id = get_sel_from_list(GTK_LIST(filtering.account_list));
-       account_id = get_account_id_from_list_id(list_id);
-
-       switch (action_id) {
-       case ACTION_MOVE:
-       case ACTION_COPY:
-       case ACTION_EXECUTE:
-               destination = gtk_entry_get_text(GTK_ENTRY(filtering.dest_entry));
-               if (*destination == '\0') {
-                       if(alert == TRUE) alertpanel_error(_("Destination is not set."));
-                       return NULL;
-               }
-               break;
-       case ACTION_FORWARD:
-       case ACTION_FORWARD_AS_ATTACHMENT:
-       case ACTION_REDIRECT:
-               destination = gtk_entry_get_text(GTK_ENTRY(filtering.dest_entry));
-               if (*destination == '\0') {
-                       if(alert == TRUE) alertpanel_error(_("Recipient is not set."));
-                       return NULL;
-               }
-               break;
-       case ACTION_COLOR:
-               labelcolor = colorlabel_get_color_menu_active_item(
-                       gtk_option_menu_get_menu(GTK_OPTION_MENU(filtering.color_optmenu)));
-               destination = NULL;     
-               break;
-       default:
-               destination = NULL;
-               break;
+       action_str = gtk_entry_get_text(GTK_ENTRY(filtering.action_entry));
+       if (*action_str == '\0') {
+               if(alert == TRUE) alertpanel_error(_("Action string is empty."));
+               return NULL;
        }
-       
-       action = filteringaction_new(action_type, account_id, destination, labelcolor);
 
        cond = matcher_parser_get_cond(cond_str);
 
        if (cond == NULL) {
                if(alert == TRUE) alertpanel_error(_("Condition string is not valid."));
-               filteringaction_free(action);
                return NULL;
        }
+        
+        action_list = matcher_parser_get_action_list(action_str);
 
-       prop = filteringprop_new(cond, action);
+       if (action_list == NULL) {
+               if(alert == TRUE) alertpanel_error(_("Action string is not valid."));
+               return NULL;
+       }
+
+       prop = filteringprop_new(cond, action_list);
 
        return prop;
 }
@@ -1132,93 +1013,24 @@ static void prefs_filtering_select_set(FilteringProp *prop)
        FilteringAction *action;
        gchar *matcher_str;
        gint list_id;
+        gchar *action_str;
 
        prefs_filtering_reset_dialog();
 
-       action = prop->action;
-
        matcher_str = matcherlist_to_string(prop->matchers);
        if (matcher_str == NULL) {
-               filteringprop_free(prop);
                return;
        }
 
        gtk_entry_set_text(GTK_ENTRY(filtering.cond_entry), matcher_str);
-       
-       if (action->destination)
-               gtk_entry_set_text(GTK_ENTRY(filtering.dest_entry), action->destination);
-       else
-               gtk_entry_set_text(GTK_ENTRY(filtering.dest_entry), "");
-
-       switch(action->type) {
-       case MATCHACTION_MOVE:
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_MOVE);
-               break;
-       case MATCHACTION_COPY:
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_COPY);
-               break;
-       case MATCHACTION_DELETE:
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_DELETE);
-               break;
-       case MATCHACTION_MARK:
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_MARK);
-               break;
-       case MATCHACTION_UNMARK:
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_UNMARK);
-               break;
-       case MATCHACTION_LOCK:
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_LOCK);
-               break;
-       case MATCHACTION_UNLOCK:
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_UNLOCK);
-               break;
-       case MATCHACTION_MARK_AS_READ:
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_MARK_AS_READ);
-               break;
-       case MATCHACTION_MARK_AS_UNREAD:
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_MARK_AS_UNREAD);
-               break;
-       case MATCHACTION_FORWARD:
-               list_id = get_list_id_from_account_id(action->account_id);
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_FORWARD);
-               gtk_list_select_item(GTK_LIST(filtering.account_list),
-                                    list_id);
-               break;
-       case MATCHACTION_FORWARD_AS_ATTACHMENT:
-               list_id = get_list_id_from_account_id(action->account_id);
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_FORWARD_AS_ATTACHMENT);
-               gtk_list_select_item(GTK_LIST(filtering.account_list),
-                                    list_id);
-               break;
-       case MATCHACTION_REDIRECT:
-               list_id = get_list_id_from_account_id(action->account_id);
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_REDIRECT);
-               gtk_list_select_item(GTK_LIST(filtering.account_list),
-                                    list_id);
-               break;
-       case MATCHACTION_EXECUTE:
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_EXECUTE);
-               break;
-       case MATCHACTION_COLOR:
-               gtk_list_select_item(GTK_LIST(filtering.action_list),
-                                    ACTION_COLOR);
-               gtk_option_menu_set_history(GTK_OPTION_MENU(filtering.color_optmenu), action->labelcolor);     
-               break;
+
+        action_str = filteringaction_list_to_string(prop->action_list);
+       if (matcher_str == NULL) {
+               return;
        }
+       gtk_entry_set_text(GTK_ENTRY(filtering.action_entry), action_str);
 
+       g_free(action_str);
        g_free(matcher_str);
 }
 
@@ -1246,200 +1058,6 @@ static void prefs_filtering_select(GtkCList *clist, gint row, gint column,
        filteringprop_free(prop);
 }
 
-static void prefs_filtering_select_dest(void)
-{
-       FolderItem *dest;
-       gchar * path;
-
-       dest = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL);
-       if (!dest) return;
-
-       path = folder_item_get_identifier(dest);
-
-       gtk_entry_set_text(GTK_ENTRY(filtering.dest_entry), path);
-       g_free(path);
-}
-
-static void prefs_filtering_action_selection_changed(GtkList *list,
-                                                    gpointer user_data)
-{
-       gint value;
-
-       value = get_sel_from_list(GTK_LIST(filtering.action_list));
-
-       if (filtering.current_action != value) {
-               if (filtering.current_action == ACTION_FORWARD 
-               ||  filtering.current_action == ACTION_FORWARD_AS_ATTACHMENT
-               ||  filtering.current_action == ACTION_REDIRECT) {
-                       debug_print("unregistering address completion entry\n");
-                       address_completion_unregister_entry(GTK_ENTRY(filtering.dest_entry));
-               }
-               if (value == ACTION_FORWARD || value == ACTION_FORWARD_AS_ATTACHMENT
-               ||  value == ACTION_REDIRECT) {
-                       debug_print("registering address completion entry\n");
-                       address_completion_register_entry(GTK_ENTRY(filtering.dest_entry));
-               }
-               filtering.current_action = value;
-       }
-}
-
-static void prefs_filtering_action_select(GtkList *list,
-                                         GtkWidget *widget,
-                                         gpointer user_data)
-{
-       Action value;
-
-       value = (Action) get_sel_from_list(GTK_LIST(filtering.action_list));
-
-       switch (value) {
-       case ACTION_MOVE:
-               gtk_widget_show(filtering.account_label);
-               gtk_widget_set_sensitive(filtering.account_label, FALSE);
-               gtk_widget_set_sensitive(filtering.account_combo, FALSE);
-               gtk_widget_show(filtering.dest_entry);
-               gtk_widget_set_sensitive(filtering.dest_entry, TRUE);
-               gtk_widget_show(filtering.dest_btn);
-               gtk_widget_set_sensitive(filtering.dest_btn, TRUE);
-               gtk_widget_show(filtering.dest_label);
-               gtk_widget_set_sensitive(filtering.dest_label, TRUE);
-               gtk_widget_hide(filtering.recip_label);
-               gtk_widget_hide(filtering.exec_label);
-               gtk_widget_hide(filtering.exec_btn);
-               gtk_widget_hide(filtering.color_optmenu);
-               gtk_widget_hide(filtering.color_label);
-               break;
-       case ACTION_COPY:
-               gtk_widget_show(filtering.account_label);
-               gtk_widget_set_sensitive(filtering.account_label, FALSE);
-               gtk_widget_set_sensitive(filtering.account_combo, FALSE);
-               gtk_widget_show(filtering.dest_entry);
-               gtk_widget_set_sensitive(filtering.dest_entry, TRUE);
-               gtk_widget_show(filtering.dest_btn);
-               gtk_widget_set_sensitive(filtering.dest_btn, TRUE);
-               gtk_widget_show(filtering.dest_label);
-               gtk_widget_set_sensitive(filtering.dest_label, TRUE);
-               gtk_widget_hide(filtering.recip_label);
-               gtk_widget_hide(filtering.exec_label);
-               gtk_widget_hide(filtering.exec_btn);
-               gtk_widget_hide(filtering.color_optmenu);
-               gtk_widget_hide(filtering.color_label);
-               break;
-       case ACTION_DELETE:
-               gtk_widget_show(filtering.account_label);
-               gtk_widget_set_sensitive(filtering.account_label, FALSE);
-               gtk_widget_set_sensitive(filtering.account_combo, FALSE);
-               gtk_widget_show(filtering.dest_entry);
-               gtk_widget_set_sensitive(filtering.dest_entry, FALSE);
-               gtk_widget_show(filtering.dest_btn);
-               gtk_widget_set_sensitive(filtering.dest_btn, FALSE);
-               gtk_widget_show(filtering.dest_label);
-               gtk_widget_set_sensitive(filtering.dest_label, FALSE);
-               gtk_widget_hide(filtering.recip_label);
-               gtk_widget_hide(filtering.exec_label);
-               gtk_widget_hide(filtering.exec_btn);
-               gtk_widget_hide(filtering.color_optmenu);
-               gtk_widget_hide(filtering.color_label);
-               break;
-       case ACTION_MARK:
-       case ACTION_UNMARK:
-       case ACTION_LOCK:
-       case ACTION_UNLOCK:
-       case ACTION_MARK_AS_READ:
-       case ACTION_MARK_AS_UNREAD:
-               gtk_widget_show(filtering.account_label);
-               gtk_widget_set_sensitive(filtering.account_label, FALSE);
-               gtk_widget_set_sensitive(filtering.account_combo, FALSE);
-               gtk_widget_show(filtering.dest_entry);
-               gtk_widget_set_sensitive(filtering.dest_entry, FALSE);
-               gtk_widget_show(filtering.dest_btn);
-               gtk_widget_set_sensitive(filtering.dest_btn, FALSE);
-               gtk_widget_show(filtering.dest_label);
-               gtk_widget_set_sensitive(filtering.dest_label, FALSE);
-               gtk_widget_hide(filtering.recip_label);
-               gtk_widget_hide(filtering.exec_label);
-               gtk_widget_hide(filtering.exec_btn);
-               gtk_widget_hide(filtering.color_optmenu);
-               gtk_widget_hide(filtering.color_label);
-               break;
-       case ACTION_FORWARD:
-               gtk_widget_show(filtering.account_label);
-               gtk_widget_set_sensitive(filtering.account_label, TRUE);
-               gtk_widget_set_sensitive(filtering.account_combo, TRUE);
-               gtk_widget_show(filtering.dest_entry);
-               gtk_widget_set_sensitive(filtering.dest_entry, TRUE);
-               gtk_widget_show(filtering.dest_btn);
-               gtk_widget_set_sensitive(filtering.dest_btn, FALSE);
-               gtk_widget_hide(filtering.dest_label);
-               gtk_widget_show(filtering.recip_label);
-               gtk_widget_set_sensitive(filtering.recip_label, TRUE);
-               gtk_widget_hide(filtering.exec_label);
-               gtk_widget_hide(filtering.exec_btn);
-               gtk_widget_hide(filtering.color_optmenu);
-               gtk_widget_hide(filtering.color_label);
-               break;
-       case ACTION_FORWARD_AS_ATTACHMENT:
-               gtk_widget_show(filtering.account_label);
-               gtk_widget_set_sensitive(filtering.account_label, TRUE);
-               gtk_widget_set_sensitive(filtering.account_combo, TRUE);
-               gtk_widget_show(filtering.dest_entry);
-               gtk_widget_set_sensitive(filtering.dest_entry, TRUE);
-               gtk_widget_show(filtering.dest_btn);
-               gtk_widget_set_sensitive(filtering.dest_btn, FALSE);
-               gtk_widget_hide(filtering.dest_label);
-               gtk_widget_show(filtering.recip_label);
-               gtk_widget_set_sensitive(filtering.recip_label, TRUE);
-               gtk_widget_hide(filtering.exec_label);
-               gtk_widget_hide(filtering.exec_btn);
-               gtk_widget_hide(filtering.color_optmenu);
-               gtk_widget_hide(filtering.color_label);
-               break;
-       case ACTION_REDIRECT:
-               gtk_widget_show(filtering.account_label);
-               gtk_widget_set_sensitive(filtering.account_label, TRUE);
-               gtk_widget_set_sensitive(filtering.account_combo, TRUE);
-               gtk_widget_show(filtering.dest_entry);
-               gtk_widget_set_sensitive(filtering.dest_entry, TRUE);
-               gtk_widget_show(filtering.dest_btn);
-               gtk_widget_set_sensitive(filtering.dest_btn, FALSE);
-               gtk_widget_hide(filtering.dest_label);
-               gtk_widget_show(filtering.recip_label);
-               gtk_widget_set_sensitive(filtering.recip_label, TRUE);
-               gtk_widget_hide(filtering.exec_label);
-               gtk_widget_hide(filtering.exec_btn);
-               gtk_widget_hide(filtering.color_optmenu);
-               gtk_widget_hide(filtering.color_label);
-               break;
-       case ACTION_EXECUTE:
-               gtk_widget_show(filtering.account_label);
-               gtk_widget_set_sensitive(filtering.account_label, FALSE);
-               gtk_widget_set_sensitive(filtering.account_combo, FALSE);
-               gtk_widget_show(filtering.dest_entry);
-               gtk_widget_set_sensitive(filtering.dest_entry, TRUE);
-               gtk_widget_hide(filtering.dest_btn);
-               gtk_widget_hide(filtering.dest_label);
-               gtk_widget_hide(filtering.recip_label);
-               gtk_widget_show(filtering.exec_label);
-               gtk_widget_set_sensitive(filtering.exec_btn, TRUE);
-               gtk_widget_show(filtering.exec_btn);
-               gtk_widget_hide(filtering.color_optmenu);
-               gtk_widget_hide(filtering.color_label);
-               break;
-       case ACTION_COLOR:
-               gtk_widget_show(filtering.account_label);
-               gtk_widget_set_sensitive(filtering.account_label, FALSE);
-               gtk_widget_set_sensitive(filtering.account_combo, FALSE);
-               gtk_widget_hide(filtering.dest_entry);
-               gtk_widget_hide(filtering.dest_btn);
-               gtk_widget_hide(filtering.dest_label);
-               gtk_widget_hide(filtering.recip_label);
-               gtk_widget_hide(filtering.exec_label);
-               gtk_widget_show(filtering.exec_btn);
-               gtk_widget_set_sensitive(filtering.exec_btn, FALSE);
-               gtk_widget_show(filtering.color_optmenu);
-               gtk_widget_show(filtering.color_label);
-               break;
-       }
-}
 
 static gint prefs_filtering_deleted(GtkWidget *widget, GdkEventAny *event,
                                 gpointer data)
diff --git a/src/prefs_filtering_action.c b/src/prefs_filtering_action.c
new file mode 100644 (file)
index 0000000..1e10f3d
--- /dev/null
@@ -0,0 +1,1273 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2001 Hiroyuki Yamamoto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include "defs.h"
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "intl.h"
+#include "main.h"
+#include "prefs_gtk.h"
+#include "prefs_filtering_action.h"
+#include "prefs_common.h"
+#include "mainwindow.h"
+#include "foldersel.h"
+#include "manage_window.h"
+#include "inc.h"
+#include "matcher.h"
+#include "utils.h"
+#include "gtkutils.h"
+#include "alertpanel.h"
+#include "folder.h"
+#include "description_window.h"
+
+#include "matcher_parser.h"
+#include "colorlabel.h"
+
+
+static void prefs_filtering_action_create(void);
+static void prefs_filtering_action_delete_cb(void);
+static void prefs_filtering_action_substitute_cb(void);
+static void prefs_filtering_action_register_cb(void);
+static void prefs_filtering_action_reset_dialog(void);
+static void prefs_filtering_action_key_pressed(GtkWidget *widget,
+    GdkEventKey *event, gpointer data);
+static void prefs_filtering_action_cancel(void);
+static void prefs_filtering_action_ok(void);
+static gint prefs_filtering_action_deleted(GtkWidget *widget,
+    GdkEventAny *event, gpointer data);
+static void prefs_filtering_action_type_selection_changed(GtkList *list,
+    gpointer user_data);
+static void prefs_filtering_action_type_select(GtkList *list,
+    GtkWidget *widget, gpointer user_data);
+static void prefs_filtering_action_select_dest(void);
+static void prefs_filtering_action_select(GtkCList *clist,
+    gint row, gint column, GdkEvent *event);
+static void prefs_filtering_action_up(void);
+static void prefs_filtering_action_down(void);
+static void prefs_filtering_action_set_dialog(GSList *action_list);
+static GSList *prefs_filtering_action_get_list(void);
+
+
+/*!
+ *\brief       UI data for matcher dialog
+ */
+static struct FilteringAction {
+       GtkWidget *window;
+
+       GtkWidget *ok_btn;
+
+       GtkWidget *action_clist;
+       GtkWidget *action_type_list;
+       GtkWidget *action_combo;
+       GtkWidget *account_label;
+       GtkWidget *account_list;
+       GtkWidget *account_combo;
+       GtkWidget *dest_entry;
+       GtkWidget *dest_btn;
+       GtkWidget *dest_label;
+       GtkWidget *recip_label;
+       GtkWidget *exec_label;
+       GtkWidget *exec_btn;
+       GtkWidget *color_label;
+       GtkWidget *color_optmenu;
+
+       gint current_action;
+} filtering_action;
+
+
+typedef enum Action_ {
+       ACTION_MOVE,
+       ACTION_COPY,
+       ACTION_DELETE,
+       ACTION_MARK,
+       ACTION_UNMARK,
+       ACTION_LOCK,
+       ACTION_UNLOCK,
+       ACTION_MARK_AS_READ,
+       ACTION_MARK_AS_UNREAD,
+       ACTION_FORWARD,
+       ACTION_FORWARD_AS_ATTACHMENT,
+       ACTION_REDIRECT,
+       ACTION_EXECUTE,
+       ACTION_COLOR,
+       /* add other action constants */
+} Action;
+
+static struct {
+       gchar *text;
+       Action action;
+} action_text [] = {
+       { N_("Move"),                   ACTION_MOVE     },      
+       { N_("Copy"),                   ACTION_COPY     },
+       { N_("Delete"),                 ACTION_DELETE   },
+       { N_("Mark"),                   ACTION_MARK     },
+       { N_("Unmark"),                 ACTION_UNMARK   },
+       { N_("Lock"),                   ACTION_LOCK     },
+       { N_("Unlock"),                 ACTION_UNLOCK   },
+       { N_("Mark as read"),           ACTION_MARK_AS_READ },
+       { N_("Mark as unread"),         ACTION_MARK_AS_UNREAD },
+       { N_("Forward"),                ACTION_FORWARD  },
+       { N_("Forward as attachment"),  ACTION_FORWARD_AS_ATTACHMENT },
+       { N_("Redirect"),               ACTION_REDIRECT },
+       { N_("Execute"),                ACTION_EXECUTE  },
+       { N_("Color"),                  ACTION_COLOR    }
+};
+
+
+/*!
+ *\brief       Hooks
+ */
+static PrefsFilteringActionSignal *filtering_action_callback;
+
+/*!
+ *\brief       Find index of list selection 
+ *
+ *\param       list GTK list widget
+ *
+ *\return      gint Selection index
+ */
+static gint get_sel_from_list(GtkList *list)
+{
+       gint row = 0;
+       void * sel;
+       GList * child;
+
+       if (list->selection == NULL)
+               return -1;
+
+       sel = list->selection->data;
+       for (child = list->children; child != NULL; child = g_list_next(child)) {
+               if (child->data == sel)
+                       return row;
+               row ++;
+       }
+       
+       return row;
+}
+
+/*!
+ *\brief       Opens the filtering action dialog with a list of actions
+ *
+ *\param       matchers List of conditions
+ *\param       cb Callback
+ *
+ */
+void prefs_filtering_action_open(GSList *action_list,
+    PrefsFilteringActionSignal *cb)
+{
+       inc_lock();
+
+       if (!filtering_action.window) {
+               prefs_filtering_action_create();
+       }
+
+       manage_window_set_transient(GTK_WINDOW(filtering_action.window));
+       gtk_widget_grab_focus(filtering_action.ok_btn);
+
+       filtering_action_callback = cb;
+
+       prefs_filtering_action_set_dialog(action_list);
+
+       gtk_widget_show(filtering_action.window);
+}
+
+/*!
+ *\brief       Create the matcher dialog
+ */
+static void prefs_filtering_action_create(void)
+{
+       GtkWidget *window;
+       GtkWidget *vbox;
+       GtkWidget *ok_btn;
+       GtkWidget *cancel_btn;
+       GtkWidget *confirm_area;
+
+       GtkWidget *vbox1;
+
+       GtkWidget *hbox1;
+
+       GtkWidget *action_label;
+       GtkWidget *recip_label;
+       GtkWidget *action_combo;
+       GtkWidget *action_type_list;
+       GtkWidget *account_list;
+       GtkWidget *dest_label;
+       GtkWidget *exec_label;
+       GtkWidget *color_label;
+       GtkWidget *account_label;
+       GtkWidget *account_combo;
+       GtkWidget *dest_entry;
+       GtkWidget *dest_btn;
+        GList * cur;
+
+       GtkWidget *reg_hbox;
+       GtkWidget *btn_hbox;
+       GtkWidget *arrow;
+       GtkWidget *reg_btn;
+       GtkWidget *subst_btn;
+       GtkWidget *del_btn;
+
+       GtkWidget *action_hbox;
+       GtkWidget *action_scrolledwin;
+       GtkWidget *action_clist;
+
+       GtkWidget *btn_vbox;
+       GtkWidget *up_btn;
+       GtkWidget *down_btn;
+
+       GtkWidget *exec_btn;
+
+       GtkWidget *color_optmenu;
+
+       GList *combo_items;
+       gint i;
+
+       gchar *title[1];
+        GList * accounts;
+
+       debug_print("Creating matcher configuration window...\n");
+
+       window = gtk_window_new(GTK_WINDOW_DIALOG);
+       gtk_container_set_border_width(GTK_CONTAINER(window), 8);
+       gtk_window_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
+       gtk_window_set_modal(GTK_WINDOW(window), TRUE);
+       gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE);
+
+       vbox = gtk_vbox_new(FALSE, 6);
+       gtk_widget_show(vbox);
+       gtk_container_add(GTK_CONTAINER(window), vbox);
+
+       gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
+                               &cancel_btn, _("Cancel"), 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);
+
+       gtk_window_set_title(GTK_WINDOW(window),
+                            _("Filtering action configuration"));
+       gtk_signal_connect(GTK_OBJECT(window), "delete_event",
+                          GTK_SIGNAL_FUNC(prefs_filtering_action_deleted), NULL);
+       gtk_signal_connect(GTK_OBJECT(window), "key_press_event",
+                          GTK_SIGNAL_FUNC(prefs_filtering_action_key_pressed), NULL);
+       MANAGE_WINDOW_SIGNALS_CONNECT(window);
+       gtk_signal_connect(GTK_OBJECT(ok_btn), "clicked",
+                          GTK_SIGNAL_FUNC(prefs_filtering_action_ok), NULL);
+       gtk_signal_connect(GTK_OBJECT(cancel_btn), "clicked",
+                          GTK_SIGNAL_FUNC(prefs_filtering_action_cancel), NULL);
+
+       vbox1 = gtk_vbox_new(FALSE, VSPACING);
+       gtk_widget_show(vbox1);
+       gtk_box_pack_start(GTK_BOX(vbox), vbox1, TRUE, TRUE, 0);
+       gtk_container_set_border_width(GTK_CONTAINER (vbox1), 2);
+
+        /* action to be defined */
+
+       hbox1 = gtk_hbox_new (FALSE, VSPACING);
+       gtk_widget_show (hbox1);
+       gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
+       gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
+
+       action_label = gtk_label_new (_("Action"));
+       gtk_widget_show (action_label);
+       gtk_misc_set_alignment (GTK_MISC (action_label), 0, 0.5);
+       gtk_box_pack_start (GTK_BOX (hbox1), action_label, FALSE, FALSE, 0);
+
+       action_combo = gtk_combo_new ();
+       gtk_widget_show (action_combo);
+       gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(action_combo)->entry),
+                              FALSE);
+
+       combo_items = NULL;
+       for (i = 0; i < sizeof action_text / sizeof action_text[0]; i++)
+               combo_items = g_list_append
+                       (combo_items, (gpointer) _(action_text[i].text));
+       gtk_combo_set_popdown_strings(GTK_COMBO(action_combo), combo_items);
+
+       g_list_free(combo_items);
+
+       gtk_box_pack_start (GTK_BOX (hbox1), action_combo,
+                           TRUE, TRUE, 0);
+       action_type_list = GTK_COMBO(action_combo)->list;
+       gtk_signal_connect (GTK_OBJECT (action_type_list), "select-child",
+                           GTK_SIGNAL_FUNC (prefs_filtering_action_type_select),
+                           NULL);
+
+       gtk_signal_connect(GTK_OBJECT(action_type_list), "selection-changed",
+                          GTK_SIGNAL_FUNC(prefs_filtering_action_type_selection_changed),
+                          NULL);
+
+       /* accounts */
+
+       hbox1 = gtk_hbox_new (FALSE, VSPACING);
+       gtk_widget_show (vbox1);
+       gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
+       gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
+
+       account_label = gtk_label_new (_("Account"));
+       gtk_widget_show (account_label);
+       gtk_misc_set_alignment (GTK_MISC (account_label), 0, 0.5);
+       gtk_box_pack_start (GTK_BOX (hbox1), account_label, FALSE, FALSE, 0);
+
+       account_combo = gtk_combo_new ();
+       gtk_widget_set_usize (account_combo, 150, -1);
+       gtk_widget_show (account_combo);
+
+       combo_items = NULL;
+       for (accounts = account_get_list() ; accounts != NULL;
+            accounts = accounts->next) {
+               PrefsAccount *ac = (PrefsAccount *)accounts->data;
+               gchar *name;
+
+               name = g_strdup_printf("%s <%s> (%s)",
+                                      ac->name, ac->address,
+                                      ac->account_name);
+               combo_items = g_list_append(combo_items, (gpointer) name);
+       }
+
+       gtk_combo_set_popdown_strings(GTK_COMBO(account_combo), combo_items);
+
+       for(cur = g_list_first(combo_items) ; cur != NULL ;
+           cur = g_list_next(cur))
+               g_free(cur->data);
+       g_list_free(combo_items);
+
+       gtk_box_pack_start (GTK_BOX (hbox1), account_combo,
+                           TRUE, TRUE, 0);
+       account_list = GTK_COMBO(account_combo)->list;
+       gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(account_combo)->entry),
+                              FALSE);
+
+       /* destination */
+
+       hbox1 = gtk_hbox_new (FALSE, VSPACING);
+       gtk_widget_show (vbox1);
+       gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
+       gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
+
+       dest_label = gtk_label_new (_("Destination"));
+       gtk_widget_show (dest_label);
+       gtk_misc_set_alignment (GTK_MISC (dest_label), 0, 0.5);
+       gtk_box_pack_start (GTK_BOX (hbox1), dest_label, FALSE, FALSE, 0);
+
+       recip_label = gtk_label_new (_("Recipient"));
+       gtk_widget_show (recip_label);
+       gtk_misc_set_alignment (GTK_MISC (recip_label), 0, 0.5);
+       gtk_box_pack_start (GTK_BOX (hbox1), recip_label, FALSE, FALSE, 0);
+
+       exec_label = gtk_label_new (_("Execute"));
+       gtk_widget_show (exec_label);
+       gtk_misc_set_alignment (GTK_MISC (exec_label), 0, 0.5);
+       gtk_box_pack_start (GTK_BOX (hbox1), exec_label, FALSE, FALSE, 0);
+       
+       color_label = gtk_label_new (_("Color"));
+       gtk_widget_show(color_label);
+       gtk_misc_set_alignment(GTK_MISC(color_label), 0, 0.5);
+       gtk_box_pack_start(GTK_BOX(hbox1), color_label, FALSE, FALSE, 0);
+
+       dest_entry = gtk_entry_new ();
+       gtk_widget_set_usize (dest_entry, 150, -1);
+       gtk_widget_show (dest_entry);
+       gtk_box_pack_start (GTK_BOX (hbox1), dest_entry, TRUE, TRUE, 0);
+       
+       color_optmenu = gtk_option_menu_new();
+       gtk_option_menu_set_menu(GTK_OPTION_MENU(color_optmenu),
+                                colorlabel_create_color_menu());
+       gtk_box_pack_start(GTK_BOX(hbox1), color_optmenu, TRUE, TRUE, 0);
+
+       dest_btn = gtk_button_new_with_label (_("Select ..."));
+       gtk_widget_show (dest_btn);
+       gtk_box_pack_start (GTK_BOX (hbox1), dest_btn, FALSE, FALSE, 0);
+       gtk_signal_connect (GTK_OBJECT (dest_btn), "clicked",
+                           GTK_SIGNAL_FUNC (prefs_filtering_action_select_dest),
+                           NULL);
+
+       exec_btn = gtk_button_new_with_label (_("Info ..."));
+       gtk_widget_show (exec_btn);
+       gtk_box_pack_start (GTK_BOX (hbox1), exec_btn, FALSE, FALSE, 0);
+       gtk_signal_connect (GTK_OBJECT (exec_btn), "clicked",
+                           GTK_SIGNAL_FUNC (prefs_filtering_action_exec_info),
+                           NULL);
+
+       /* register / substitute / delete */
+
+       reg_hbox = gtk_hbox_new(FALSE, 4);
+       gtk_widget_show(reg_hbox);
+       gtk_box_pack_start(GTK_BOX(vbox1), reg_hbox, FALSE, FALSE, 0);
+
+       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);
+
+       btn_hbox = gtk_hbox_new(TRUE, 4);
+       gtk_widget_show(btn_hbox);
+       gtk_box_pack_start(GTK_BOX(reg_hbox), btn_hbox, FALSE, FALSE, 0);
+
+       reg_btn = gtk_button_new_with_label(_("Add"));
+       gtk_widget_show(reg_btn);
+       gtk_box_pack_start(GTK_BOX(btn_hbox), reg_btn, FALSE, TRUE, 0);
+       gtk_signal_connect(GTK_OBJECT(reg_btn), "clicked",
+                          GTK_SIGNAL_FUNC(prefs_filtering_action_register_cb), NULL);
+
+       subst_btn = gtk_button_new_with_label(_("  Replace  "));
+       gtk_widget_show(subst_btn);
+       gtk_box_pack_start(GTK_BOX(btn_hbox), subst_btn, FALSE, TRUE, 0);
+       gtk_signal_connect(GTK_OBJECT(subst_btn), "clicked",
+                          GTK_SIGNAL_FUNC(prefs_filtering_action_substitute_cb),
+                          NULL);
+
+       del_btn = gtk_button_new_with_label(_("Delete"));
+       gtk_widget_show(del_btn);
+       gtk_box_pack_start(GTK_BOX(btn_hbox), del_btn, FALSE, TRUE, 0);
+       gtk_signal_connect(GTK_OBJECT(del_btn), "clicked",
+                          GTK_SIGNAL_FUNC(prefs_filtering_action_delete_cb), NULL);
+
+       action_hbox = gtk_hbox_new(FALSE, 8);
+       gtk_widget_show(action_hbox);
+       gtk_box_pack_start(GTK_BOX(vbox1), action_hbox, TRUE, TRUE, 0);
+
+       action_scrolledwin = gtk_scrolled_window_new(NULL, NULL);
+       gtk_widget_show(action_scrolledwin);
+       gtk_widget_set_usize(action_scrolledwin, -1, 150);
+       gtk_box_pack_start(GTK_BOX(action_hbox), action_scrolledwin,
+                          TRUE, TRUE, 0);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(action_scrolledwin),
+                                      GTK_POLICY_AUTOMATIC,
+                                      GTK_POLICY_AUTOMATIC);
+
+       title[0] = _("Current action list");
+       action_clist = gtk_clist_new_with_titles(1, title);
+       gtk_widget_show(action_clist);
+       gtk_container_add(GTK_CONTAINER(action_scrolledwin), action_clist);
+       gtk_clist_set_column_width(GTK_CLIST(action_clist), 0, 80);
+       gtk_clist_set_selection_mode(GTK_CLIST(action_clist),
+                                    GTK_SELECTION_BROWSE);
+       GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(action_clist)->column[0].button,
+                              GTK_CAN_FOCUS);
+       gtk_signal_connect(GTK_OBJECT(action_clist), "select_row",
+                          GTK_SIGNAL_FUNC(prefs_filtering_action_select), NULL);
+
+       btn_vbox = gtk_vbox_new(FALSE, 8);
+       gtk_widget_show(btn_vbox);
+       gtk_box_pack_start(GTK_BOX(action_hbox), btn_vbox, FALSE, FALSE, 0);
+
+       up_btn = gtk_button_new_with_label(_("Up"));
+       gtk_widget_show(up_btn);
+       gtk_box_pack_start(GTK_BOX(btn_vbox), up_btn, FALSE, FALSE, 0);
+       gtk_signal_connect(GTK_OBJECT(up_btn), "clicked",
+                          GTK_SIGNAL_FUNC(prefs_filtering_action_up), NULL);
+
+       down_btn = gtk_button_new_with_label(_("Down"));
+       gtk_widget_show(down_btn);
+       gtk_box_pack_start(GTK_BOX(btn_vbox), down_btn, FALSE, FALSE, 0);
+       gtk_signal_connect(GTK_OBJECT(down_btn), "clicked",
+                          GTK_SIGNAL_FUNC(prefs_filtering_action_down), NULL);
+
+       gtk_widget_show_all(window);
+
+       filtering_action.window    = window;
+       filtering_action.action_type_list = action_type_list;
+       filtering_action.action_combo = action_combo;
+       filtering_action.account_label = account_label;
+       filtering_action.account_list = account_list;
+       filtering_action.account_combo = account_combo;
+       filtering_action.dest_entry = dest_entry;
+       filtering_action.dest_btn = dest_btn;
+       filtering_action.dest_label = dest_label;
+       filtering_action.recip_label = recip_label;
+       filtering_action.exec_label = exec_label;
+       filtering_action.exec_btn = exec_btn;
+       filtering_action.color_label   = color_label;
+       filtering_action.color_optmenu = color_optmenu;
+       filtering_action.ok_btn = ok_btn;
+       filtering_action.action_clist = action_clist;
+}
+
+/*!
+ *\brief       Set the contents of a row
+ *
+ *\param       row Index of row to set
+ *\param       prop Condition to set
+ *
+ *\return      gint Row index \a prop has been added
+ */
+static gint prefs_filtering_action_clist_set_row(gint row, FilteringAction *action)
+{
+       GtkCList *clist = GTK_CLIST(filtering_action.action_clist);
+       gchar *action_tab_str[1];
+       gchar *action_str;
+        gchar buf[256];
+
+       if (action == NULL) {
+               action_tab_str[0] = _("(New)");
+               return gtk_clist_append(clist, action_tab_str);
+       }
+
+        filteringaction_to_string(buf, sizeof buf, action);
+       action_str = g_strdup(buf);
+        
+       action_tab_str[0] = action_str;
+       if (row < 0)
+               row = gtk_clist_append(clist, action_tab_str);
+       else
+               gtk_clist_set_text(clist, row, 0, action_tab_str[0]);
+       g_free(action_str);
+
+       return row;
+}
+
+/*!
+ *\brief       Update scrollbar
+ */
+static void prefs_filtering_action_update_hscrollbar(void)
+{
+       gint optwidth = gtk_clist_optimal_column_width(GTK_CLIST(filtering_action.action_clist), 0);
+       gtk_clist_set_column_width(GTK_CLIST(filtering_action.action_clist), 0, optwidth);
+}
+
+/*!
+ *\brief       Initializes dialog with a set of conditions
+ *
+ *\param       matchers List of conditions
+ */
+static void prefs_filtering_action_set_dialog(GSList *action_list)
+{
+       GtkCList *clist = GTK_CLIST(filtering_action.action_clist);
+       GSList *cur;
+
+       gtk_clist_freeze(clist);
+       gtk_clist_clear(clist);
+
+       prefs_filtering_action_clist_set_row(-1, NULL);
+       if (action_list != NULL) {
+               for (cur = action_list; cur != NULL;
+                    cur = g_slist_next(cur)) {
+                       FilteringAction *action;
+                       action = (FilteringAction *) cur->data;
+                       prefs_filtering_action_clist_set_row(-1, action);
+               }
+       }
+       
+       prefs_filtering_action_update_hscrollbar();
+
+       gtk_clist_thaw(clist);
+
+        prefs_filtering_action_reset_dialog();
+}
+
+/*!
+ *\brief       Converts current actions in list box in
+ *             an action list used by the filtering system.
+ *
+ *\return      GSList * List of actions.
+ */
+static GSList *prefs_filtering_action_get_list(void)
+{
+       gchar *action_str;
+       FilteringAction *action;
+       gint row = 1;
+       GSList *action_list;
+
+       action_list = NULL;
+
+       while (gtk_clist_get_text(GTK_CLIST(filtering_action.action_clist),
+                                 row, 0, &action_str)) {
+
+               if (strcmp(action_str, _("(New)")) != 0) {
+                        GSList * tmp_action_list;
+                       tmp_action_list = matcher_parser_get_action_list(action_str);
+                       
+                       if (tmp_action_list == NULL)
+                               break;
+
+                       action_list = g_slist_concat(action_list,
+                            tmp_action_list);
+               }
+               row ++;
+       }
+
+       return action_list;
+}
+
+/*!
+ *\brief       Returns account ID from the given list index
+ *
+ *\return      gint account ID
+ */
+static gint get_account_id_from_list_id(gint list_id)
+{
+       GList * accounts;
+
+       for (accounts = account_get_list() ; accounts != NULL;
+            accounts = accounts->next) {
+               PrefsAccount *ac = (PrefsAccount *)accounts->data;
+
+               if (list_id == 0)
+                       return ac->account_id;
+               list_id--;
+       }
+       return 0;
+}
+
+/*!
+ *\brief       Returns list index from the given account ID
+ *
+ *\return      gint list index
+ */
+static gint get_list_id_from_account_id(gint account_id)
+{
+       GList * accounts;
+       gint list_id = 0;
+
+       for (accounts = account_get_list() ; accounts != NULL;
+            accounts = accounts->next) {
+               PrefsAccount *ac = (PrefsAccount *)accounts->data;
+
+               if (account_id == ac->account_id)
+                       return list_id;
+               list_id++;
+       }
+       return 0;
+}
+
+
+/*!
+ *\brief       Returns parser action ID from internal action ID
+ *
+ *\return      gint parser action ID
+ */
+static gint prefs_filtering_action_get_matching_from_action(Action action_id)
+{
+       switch (action_id) {
+       case ACTION_MOVE:
+               return MATCHACTION_MOVE;
+       case ACTION_COPY:
+               return MATCHACTION_COPY;
+       case ACTION_DELETE:
+               return MATCHACTION_DELETE;
+       case ACTION_MARK:
+               return MATCHACTION_MARK;
+       case ACTION_UNMARK:
+               return MATCHACTION_UNMARK;
+       case ACTION_LOCK:
+               return MATCHACTION_LOCK;
+       case ACTION_UNLOCK:
+               return MATCHACTION_UNLOCK;
+       case ACTION_MARK_AS_READ:
+               return MATCHACTION_MARK_AS_READ;
+       case ACTION_MARK_AS_UNREAD:
+               return MATCHACTION_MARK_AS_UNREAD;
+       case ACTION_FORWARD:
+               return MATCHACTION_FORWARD;
+       case ACTION_FORWARD_AS_ATTACHMENT:
+               return MATCHACTION_FORWARD_AS_ATTACHMENT;
+       case ACTION_REDIRECT:
+               return MATCHACTION_REDIRECT;
+       case ACTION_EXECUTE:
+               return MATCHACTION_EXECUTE;
+       case ACTION_COLOR:
+               return MATCHACTION_COLOR;
+       default:
+               return -1;
+       }
+}
+
+/*!
+ *\brief       Returns action from the content of the dialog
+ *
+ *\param       alert specifies whether alert dialog boxes should be shown
+ *                or not.
+ *
+ *\return      FilteringAction * action entered in the dialog box.
+ */
+static FilteringAction * prefs_filtering_action_dialog_to_action(gboolean alert)
+{
+       Action action_id;
+       gint action_type;
+       gint list_id;
+       gint account_id;
+       gchar * destination;
+       gint labelcolor = 0;
+        FilteringAction * action;
+
+       action_id = get_sel_from_list(GTK_LIST(filtering_action.action_type_list));
+       action_type = prefs_filtering_action_get_matching_from_action(action_id);
+       list_id = get_sel_from_list(GTK_LIST(filtering_action.account_list));
+       account_id = get_account_id_from_list_id(list_id);
+
+       switch (action_id) {
+       case ACTION_MOVE:
+       case ACTION_COPY:
+       case ACTION_EXECUTE:
+               destination = gtk_entry_get_text(GTK_ENTRY(filtering_action.dest_entry));
+               if (*destination == '\0') {
+                       if (alert)
+                                alertpanel_error(_("Destination is not set."));
+                       return NULL;
+               }
+               break;
+       case ACTION_FORWARD:
+       case ACTION_FORWARD_AS_ATTACHMENT:
+       case ACTION_REDIRECT:
+               destination = gtk_entry_get_text(GTK_ENTRY(filtering_action.dest_entry));
+               if (*destination == '\0') {
+                       if (alert)
+                                alertpanel_error(_("Recipient is not set."));
+                       return NULL;
+               }
+               break;
+       case ACTION_COLOR:
+               labelcolor = colorlabel_get_color_menu_active_item(
+                       gtk_option_menu_get_menu(GTK_OPTION_MENU(filtering_action.color_optmenu)));
+               destination = NULL;     
+               break;
+       default:
+               destination = NULL;
+               break;
+       }
+       
+       action = filteringaction_new(action_type, account_id, destination, labelcolor);
+
+        return action;
+}
+
+/*!
+ *\brief       Signal handler for register button
+ */
+static void prefs_filtering_action_register_cb(void)
+{
+       FilteringAction *action;
+       
+       action = prefs_filtering_action_dialog_to_action(TRUE);
+       if (action == NULL)
+               return;
+
+       prefs_filtering_action_clist_set_row(-1, action);
+
+       filteringaction_free(action);
+
+       prefs_filtering_action_reset_dialog();
+       prefs_filtering_action_update_hscrollbar();
+}
+
+/*!
+ *\brief       Signal handler for substitute button
+ */
+static void prefs_filtering_action_substitute_cb(void)
+{
+       GtkCList *clist = GTK_CLIST(filtering_action.action_clist);
+       gint row;
+       FilteringAction *action;
+
+       if (!clist->selection) return;
+       row = GPOINTER_TO_INT(clist->selection->data);
+       if (row == 0)
+               return;
+       
+       action = prefs_filtering_action_dialog_to_action(TRUE);
+       if (action == NULL)
+               return;
+
+       prefs_filtering_action_clist_set_row(row, action);
+
+       filteringaction_free(action);
+
+       prefs_filtering_action_reset_dialog();
+       
+       prefs_filtering_action_update_hscrollbar();
+}
+
+/*!
+ *\brief       Signal handler for delete button
+ */
+static void prefs_filtering_action_delete_cb(void)
+{
+       GtkCList *clist = GTK_CLIST(filtering_action.action_clist);
+       gint row;
+
+       if (!clist->selection) return;
+       row = GPOINTER_TO_INT(clist->selection->data);
+       if (row == 0)
+               return;
+
+       gtk_clist_remove(clist, row);
+
+       prefs_filtering_action_reset_dialog();
+
+       prefs_filtering_action_update_hscrollbar();
+}
+
+/*!
+ *\brief       Signal handler for 'move up' button
+ */
+static void prefs_filtering_action_up(void)
+{
+       GtkCList *clist = GTK_CLIST(filtering_action.action_clist);
+       gint row;
+
+       if (!clist->selection) return;
+
+       row = GPOINTER_TO_INT(clist->selection->data);
+       if (row > 1) {
+               gtk_clist_row_move(clist, row, row - 1);
+               if (gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL)
+                       gtk_clist_moveto(clist, row - 1, 0, 0, 0);
+       }
+}
+
+/*!
+ *\brief       Signal handler for 'move down' button
+ */
+static void prefs_filtering_action_down(void)
+{
+       GtkCList *clist = GTK_CLIST(filtering_action.action_clist);
+       gint row;
+
+       if (!clist->selection) return;
+
+       row = GPOINTER_TO_INT(clist->selection->data);
+       if (row >= 1 && row < clist->rows - 1) {
+               gtk_clist_row_move(clist, row, row + 1);
+               if (gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL)
+                       gtk_clist_moveto(clist, row + 1, 0, 1, 0);
+       }
+}
+
+/*!
+ *\brief       Signal handler for select row.
+ *
+ *\param       clist List widget
+ *\param       row Selected row
+ *\param       column Selected column
+ *\param       event Event information
+ */
+static void prefs_filtering_action_select(GtkCList *clist,
+    gint row, gint column, GdkEvent *event)
+{
+       gchar *action_str;
+       FilteringAction *action;
+        GSList * action_list;
+       gint list_id;
+
+       if (!gtk_clist_get_text(GTK_CLIST(filtering_action.action_clist),
+                               row, 0, &action_str))
+               return;
+
+       if (row == 0) {
+               prefs_filtering_action_reset_dialog();
+               return;
+       }
+
+       action_list = matcher_parser_get_action_list(action_str);
+       if (action_list == NULL)
+               return;
+
+        action = action_list->data;
+        g_slist_free(action_list);
+
+       if (action->destination)
+               gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), action->destination);
+       else
+               gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), "");
+
+       switch(action->type) {
+       case MATCHACTION_MOVE:
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_MOVE);
+               break;
+       case MATCHACTION_COPY:
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_COPY);
+               break;
+       case MATCHACTION_DELETE:
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_DELETE);
+               break;
+       case MATCHACTION_MARK:
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_MARK);
+               break;
+       case MATCHACTION_UNMARK:
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_UNMARK);
+               break;
+       case MATCHACTION_LOCK:
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_LOCK);
+               break;
+       case MATCHACTION_UNLOCK:
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_UNLOCK);
+               break;
+       case MATCHACTION_MARK_AS_READ:
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_MARK_AS_READ);
+               break;
+       case MATCHACTION_MARK_AS_UNREAD:
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_MARK_AS_UNREAD);
+               break;
+       case MATCHACTION_FORWARD:
+               list_id = get_list_id_from_account_id(action->account_id);
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_FORWARD);
+               gtk_list_select_item(GTK_LIST(filtering_action.account_list),
+                                    list_id);
+               break;
+       case MATCHACTION_FORWARD_AS_ATTACHMENT:
+               list_id = get_list_id_from_account_id(action->account_id);
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_FORWARD_AS_ATTACHMENT);
+               gtk_list_select_item(GTK_LIST(filtering_action.account_list),
+                                    list_id);
+               break;
+       case MATCHACTION_REDIRECT:
+               list_id = get_list_id_from_account_id(action->account_id);
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_REDIRECT);
+               gtk_list_select_item(GTK_LIST(filtering_action.account_list),
+                                    list_id);
+               break;
+       case MATCHACTION_EXECUTE:
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_EXECUTE);
+               break;
+       case MATCHACTION_COLOR:
+               gtk_list_select_item(GTK_LIST(filtering_action.action_type_list),
+                                    ACTION_COLOR);
+               gtk_option_menu_set_history(GTK_OPTION_MENU(filtering_action.color_optmenu), action->labelcolor);     
+               break;
+       }
+}
+
+/*!
+ *\brief       Handle key press
+ *
+ *\param       widget Widget receiving key press
+ *\param       event Key event
+ *\param       data User data
+ */
+static void prefs_filtering_action_key_pressed(GtkWidget *widget,
+    GdkEventKey *event, gpointer data)
+{
+       if (event && event->keyval == GDK_Escape)
+               prefs_filtering_action_cancel();
+}
+
+/*!
+ *\brief       Cancel matcher dialog
+ */
+static void prefs_filtering_action_cancel(void)
+{
+       gtk_widget_hide(filtering_action.window);
+       inc_unlock();
+}
+
+/*!
+ *\brief       Accept current matchers
+ */
+static void prefs_filtering_action_ok(void)
+{
+        GSList * action_list;
+        GSList * cur;
+
+       action_list = prefs_filtering_action_get_list();
+
+        if (action_list == NULL) {
+                alertpanel_error(_("No action was defined."));
+                return;
+        }
+
+        if (filtering_action_callback != NULL)
+                filtering_action_callback(action_list);
+        for(cur = action_list ; cur != NULL ; cur = cur->next) {
+                filteringaction_free(cur->data);
+        }
+        g_slist_free(action_list);
+
+       gtk_widget_hide(filtering_action.window);
+        inc_unlock();
+}
+
+/*!
+ *\brief       Called when closing dialog box
+ *
+ *\param       widget Dialog widget
+ *\param       event Event info
+ *\param       data User data
+ *
+ *\return      gint TRUE
+ */
+static gint prefs_filtering_action_deleted(GtkWidget *widget,
+    GdkEventAny *event, gpointer data)
+{
+       prefs_filtering_action_cancel();
+       return TRUE;
+}
+
+/*
+ * Strings describing exec format strings
+ * 
+ * When adding new lines, remember to put 2 strings for each line
+ */
+static gchar *exec_desc_strings[] = {
+       "%%",   "%",
+       "%s",   N_("Subject"),
+       "%f",   N_("From"),
+       "%t",   N_("To"),
+       "%c",   N_("Cc"),
+       "%d",   N_("Date"),
+       "%i",   N_("Message-ID"),
+       "%n",   N_("Newsgroups"),
+       "%r",   N_("References"),
+       "%F",   N_("Filename - should not be modified"),
+       "\\n",  N_("new line"),
+       "\\",   N_("escape character for quotes"),
+       "\\\"",N_("quote character"),
+       NULL, NULL
+};
+
+static DescriptionWindow exec_desc_win = { 
+        NULL, 
+        2,
+        N_("Description of symbols"),
+        exec_desc_strings
+};
+
+
+
+/*!
+ *\brief       Show Execute action's info
+ */
+void prefs_filtering_action_exec_info(void)
+{
+       description_window_create(&exec_desc_win);
+}
+
+static void prefs_filtering_action_select_dest(void)
+{
+       FolderItem *dest;
+       gchar * path;
+
+       dest = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL);
+       if (!dest) return;
+
+       path = folder_item_get_identifier(dest);
+
+       gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), path);
+       g_free(path);
+}
+
+static void prefs_filtering_action_type_selection_changed(GtkList *list,
+    gpointer user_data)
+{
+       gint value;
+
+       value = get_sel_from_list(GTK_LIST(filtering_action.action_type_list));
+
+       if (filtering_action.current_action != value) {
+               if (filtering_action.current_action == ACTION_FORWARD 
+               ||  filtering_action.current_action == ACTION_FORWARD_AS_ATTACHMENT
+               ||  filtering_action.current_action == ACTION_REDIRECT) {
+                       debug_print("unregistering address completion entry\n");
+                       address_completion_unregister_entry(GTK_ENTRY(filtering_action.dest_entry));
+               }
+               if (value == ACTION_FORWARD || value == ACTION_FORWARD_AS_ATTACHMENT
+               ||  value == ACTION_REDIRECT) {
+                       debug_print("registering address completion entry\n");
+                       address_completion_register_entry(GTK_ENTRY(filtering_action.dest_entry));
+               }
+               filtering_action.current_action = value;
+       }
+}
+
+static void prefs_filtering_action_type_select(GtkList *list,
+    GtkWidget *widget, gpointer user_data)
+{
+       Action value;
+
+       value = (Action) get_sel_from_list(GTK_LIST(filtering_action.action_type_list));
+
+       switch (value) {
+       case ACTION_MOVE:
+               gtk_widget_show(filtering_action.account_label);
+               gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
+               gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
+               gtk_widget_show(filtering_action.dest_entry);
+               gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
+               gtk_widget_show(filtering_action.dest_btn);
+               gtk_widget_set_sensitive(filtering_action.dest_btn, TRUE);
+               gtk_widget_show(filtering_action.dest_label);
+               gtk_widget_set_sensitive(filtering_action.dest_label, TRUE);
+               gtk_widget_hide(filtering_action.recip_label);
+               gtk_widget_hide(filtering_action.exec_label);
+               gtk_widget_hide(filtering_action.exec_btn);
+               gtk_widget_hide(filtering_action.color_optmenu);
+               gtk_widget_hide(filtering_action.color_label);
+               break;
+       case ACTION_COPY:
+               gtk_widget_show(filtering_action.account_label);
+               gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
+               gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
+               gtk_widget_show(filtering_action.dest_entry);
+               gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
+               gtk_widget_show(filtering_action.dest_btn);
+               gtk_widget_set_sensitive(filtering_action.dest_btn, TRUE);
+               gtk_widget_show(filtering_action.dest_label);
+               gtk_widget_set_sensitive(filtering_action.dest_label, TRUE);
+               gtk_widget_hide(filtering_action.recip_label);
+               gtk_widget_hide(filtering_action.exec_label);
+               gtk_widget_hide(filtering_action.exec_btn);
+               gtk_widget_hide(filtering_action.color_optmenu);
+               gtk_widget_hide(filtering_action.color_label);
+               break;
+       case ACTION_DELETE:
+               gtk_widget_show(filtering_action.account_label);
+               gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
+               gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
+               gtk_widget_show(filtering_action.dest_entry);
+               gtk_widget_set_sensitive(filtering_action.dest_entry, FALSE);
+               gtk_widget_show(filtering_action.dest_btn);
+               gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE);
+               gtk_widget_show(filtering_action.dest_label);
+               gtk_widget_set_sensitive(filtering_action.dest_label, FALSE);
+               gtk_widget_hide(filtering_action.recip_label);
+               gtk_widget_hide(filtering_action.exec_label);
+               gtk_widget_hide(filtering_action.exec_btn);
+               gtk_widget_hide(filtering_action.color_optmenu);
+               gtk_widget_hide(filtering_action.color_label);
+               break;
+       case ACTION_MARK:
+       case ACTION_UNMARK:
+       case ACTION_LOCK:
+       case ACTION_UNLOCK:
+       case ACTION_MARK_AS_READ:
+       case ACTION_MARK_AS_UNREAD:
+               gtk_widget_show(filtering_action.account_label);
+               gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
+               gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
+               gtk_widget_show(filtering_action.dest_entry);
+               gtk_widget_set_sensitive(filtering_action.dest_entry, FALSE);
+               gtk_widget_show(filtering_action.dest_btn);
+               gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE);
+               gtk_widget_show(filtering_action.dest_label);
+               gtk_widget_set_sensitive(filtering_action.dest_label, FALSE);
+               gtk_widget_hide(filtering_action.recip_label);
+               gtk_widget_hide(filtering_action.exec_label);
+               gtk_widget_hide(filtering_action.exec_btn);
+               gtk_widget_hide(filtering_action.color_optmenu);
+               gtk_widget_hide(filtering_action.color_label);
+               break;
+       case ACTION_FORWARD:
+               gtk_widget_show(filtering_action.account_label);
+               gtk_widget_set_sensitive(filtering_action.account_label, TRUE);
+               gtk_widget_set_sensitive(filtering_action.account_combo, TRUE);
+               gtk_widget_show(filtering_action.dest_entry);
+               gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
+               gtk_widget_show(filtering_action.dest_btn);
+               gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE);
+               gtk_widget_hide(filtering_action.dest_label);
+               gtk_widget_show(filtering_action.recip_label);
+               gtk_widget_set_sensitive(filtering_action.recip_label, TRUE);
+               gtk_widget_hide(filtering_action.exec_label);
+               gtk_widget_hide(filtering_action.exec_btn);
+               gtk_widget_hide(filtering_action.color_optmenu);
+               gtk_widget_hide(filtering_action.color_label);
+               break;
+       case ACTION_FORWARD_AS_ATTACHMENT:
+               gtk_widget_show(filtering_action.account_label);
+               gtk_widget_set_sensitive(filtering_action.account_label, TRUE);
+               gtk_widget_set_sensitive(filtering_action.account_combo, TRUE);
+               gtk_widget_show(filtering_action.dest_entry);
+               gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
+               gtk_widget_show(filtering_action.dest_btn);
+               gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE);
+               gtk_widget_hide(filtering_action.dest_label);
+               gtk_widget_show(filtering_action.recip_label);
+               gtk_widget_set_sensitive(filtering_action.recip_label, TRUE);
+               gtk_widget_hide(filtering_action.exec_label);
+               gtk_widget_hide(filtering_action.exec_btn);
+               gtk_widget_hide(filtering_action.color_optmenu);
+               gtk_widget_hide(filtering_action.color_label);
+               break;
+       case ACTION_REDIRECT:
+               gtk_widget_show(filtering_action.account_label);
+               gtk_widget_set_sensitive(filtering_action.account_label, TRUE);
+               gtk_widget_set_sensitive(filtering_action.account_combo, TRUE);
+               gtk_widget_show(filtering_action.dest_entry);
+               gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
+               gtk_widget_show(filtering_action.dest_btn);
+               gtk_widget_set_sensitive(filtering_action.dest_btn, FALSE);
+               gtk_widget_hide(filtering_action.dest_label);
+               gtk_widget_show(filtering_action.recip_label);
+               gtk_widget_set_sensitive(filtering_action.recip_label, TRUE);
+               gtk_widget_hide(filtering_action.exec_label);
+               gtk_widget_hide(filtering_action.exec_btn);
+               gtk_widget_hide(filtering_action.color_optmenu);
+               gtk_widget_hide(filtering_action.color_label);
+               break;
+       case ACTION_EXECUTE:
+               gtk_widget_show(filtering_action.account_label);
+               gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
+               gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
+               gtk_widget_show(filtering_action.dest_entry);
+               gtk_widget_set_sensitive(filtering_action.dest_entry, TRUE);
+               gtk_widget_hide(filtering_action.dest_btn);
+               gtk_widget_hide(filtering_action.dest_label);
+               gtk_widget_hide(filtering_action.recip_label);
+               gtk_widget_show(filtering_action.exec_label);
+               gtk_widget_set_sensitive(filtering_action.exec_btn, TRUE);
+               gtk_widget_show(filtering_action.exec_btn);
+               gtk_widget_hide(filtering_action.color_optmenu);
+               gtk_widget_hide(filtering_action.color_label);
+               break;
+       case ACTION_COLOR:
+               gtk_widget_show(filtering_action.account_label);
+               gtk_widget_set_sensitive(filtering_action.account_label, FALSE);
+               gtk_widget_set_sensitive(filtering_action.account_combo, FALSE);
+               gtk_widget_hide(filtering_action.dest_entry);
+               gtk_widget_hide(filtering_action.dest_btn);
+               gtk_widget_hide(filtering_action.dest_label);
+               gtk_widget_hide(filtering_action.recip_label);
+               gtk_widget_hide(filtering_action.exec_label);
+               gtk_widget_show(filtering_action.exec_btn);
+               gtk_widget_set_sensitive(filtering_action.exec_btn, FALSE);
+               gtk_widget_show(filtering_action.color_optmenu);
+               gtk_widget_show(filtering_action.color_label);
+               break;
+       }
+}
+
+static void prefs_filtering_action_reset_dialog(void)
+{
+       gtk_list_select_item(GTK_LIST(filtering_action.action_type_list), 0);
+       gtk_list_select_item(GTK_LIST(filtering_action.account_list), 0);
+       gtk_entry_set_text(GTK_ENTRY(filtering_action.dest_entry), "");
+}
diff --git a/src/prefs_filtering_action.h b/src/prefs_filtering_action.h
new file mode 100644 (file)
index 0000000..01d11fc
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2001 Hiroyuki Yamamoto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PREFS_FILTERING_ACTION_H__
+#define __PREFS_FILTERING_ACTION_H__
+
+#include "matcher.h"
+
+typedef void PrefsFilteringActionSignal        (GSList *action_list);
+
+void prefs_filtering_action_open               (GSList *action_list,
+                                PrefsFilteringActionSignal *cb);
+void prefs_filtering_action_exec_info  (void);
+
+#endif /* __PREFS_FILTER_H__ */