add 'fast filter' for claws' filtering
[claws.git] / src / prefs_filtering.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2001 Hiroyuki Yamamoto
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "defs.h"
25
26 #include <glib.h>
27 #include <gtk/gtk.h>
28 #include <gtk/gtkoptionmenu.h>
29 #include <gdk/gdkkeysyms.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34
35 #include "intl.h"
36 #include "main.h"
37 #include "prefs.h"
38 #include "prefs_matcher.h"
39 #include "prefs_filtering.h"
40 #include "prefs_common.h"
41 #include "mainwindow.h"
42 #include "foldersel.h"
43 #include "manage_window.h"
44 #include "inc.h"
45 #include "utils.h"
46 #include "gtkutils.h"
47 #include "alertpanel.h"
48 #include "folder.h"
49 #include "filtering.h"
50 #include "addr_compl.h"
51 #include "colorlabel.h"
52
53 #include "matcher_parser.h"
54
55 static struct Filtering {
56         GtkWidget *window;
57
58         GtkWidget *ok_btn;
59         GtkWidget *cond_entry;
60         GtkWidget *action_list;
61         GtkWidget *action_combo;
62         GtkWidget *account_list;
63         GtkWidget *account_combo;
64         GtkWidget *dest_entry;
65         GtkWidget *dest_btn;
66         GtkWidget *dest_label;
67         GtkWidget *exec_label;
68         GtkWidget *exec_btn;
69
70         GtkWidget *color_label;
71         GtkWidget *color_optmenu;
72
73         GtkWidget *cond_clist;
74
75         /* need this to make address completion entry work */
76         gint current_action;
77 } filtering;
78
79 /* widget creating functions */
80 static void prefs_filtering_create              (void);
81
82 static void prefs_filtering_set_dialog  (const gchar *header,
83                                          const gchar *key);
84 static void prefs_filtering_set_list    (void);
85
86 /* callback functions */
87 /* static void prefs_filtering_select_dest_cb   (void); */
88 static void prefs_filtering_register_cb (void);
89 static void prefs_filtering_substitute_cb       (void);
90 static void prefs_filtering_delete_cb   (void);
91 static void prefs_filtering_up          (void);
92 static void prefs_filtering_down                (void);
93 static void prefs_filtering_select              (GtkCList       *clist,
94                                          gint            row,
95                                          gint            column,
96                                          GdkEvent       *event);
97
98 static gint prefs_filtering_deleted     (GtkWidget      *widget,
99                                          GdkEventAny    *event,
100                                          gpointer        data);
101 static void prefs_filtering_key_pressed (GtkWidget      *widget,
102                                          GdkEventKey    *event,
103                                          gpointer        data);
104 static void prefs_filtering_cancel              (void);
105 static void prefs_filtering_ok          (void);
106
107 static void prefs_filtering_condition_define    (void);
108 static gint prefs_filtering_clist_set_row(gint row, FilteringProp * prop);
109 static void prefs_filtering_select_dest(void);
110 static void prefs_filtering_action_select(GtkList *list,
111                                           GtkWidget *widget, 
112                                           gpointer user_data);
113 static void prefs_filtering_action_selection_changed(GtkList *list,
114                                                      gpointer user_data);
115                                           
116 static void prefs_filtering_reset_dialog(void);
117
118 static FolderItem * cur_item = NULL;
119
120 enum {
121         ACTION_MOVE = 0,
122         ACTION_COPY = 1,
123         ACTION_DELETE = 2,
124         ACTION_MARK = 3,
125         ACTION_UNMARK = 4,
126         ACTION_MARK_AS_READ = 5,
127         ACTION_MARK_AS_UNREAD = 6,
128         ACTION_FORWARD = 7,
129         ACTION_FORWARD_AS_ATTACHMENT = 8,
130         ACTION_BOUNCE = 9,
131         ACTION_EXECUTE = 10,
132         ACTION_COLOR = 11,
133         ACTION_DELETE_ON_SERVER = 12,
134 };
135
136 static gint get_sel_from_list(GtkList * list)
137 {
138         gint row = 0;
139         void * sel;
140         GList * child;
141
142         if (list->selection == NULL)
143                 return -1;
144
145         sel = list->selection->data;
146         for(child = list->children ; child != NULL ;
147             child = g_list_next(child)) {
148                 if (child->data == sel)
149                         return row;
150                 row ++;
151         }
152         
153         return row;
154 }
155
156 static gint get_account_id_from_list_id(gint list_id)
157 {
158         GList * accounts;
159
160         for (accounts = account_get_list() ; accounts != NULL;
161              accounts = accounts->next) {
162                 PrefsAccount *ac = (PrefsAccount *)accounts->data;
163
164                 if (list_id == 0)
165                         return ac->account_id;
166                 list_id--;
167         }
168         return 0;
169 }
170
171 static gint get_list_id_from_account_id(gint account_id)
172 {
173         GList * accounts;
174         gint list_id = 0;
175
176         for (accounts = account_get_list() ; accounts != NULL;
177              accounts = accounts->next) {
178                 PrefsAccount *ac = (PrefsAccount *)accounts->data;
179
180                 if (account_id == ac->account_id)
181                         return list_id;
182                 list_id++;
183         }
184         return 0;
185 }
186
187 static gint prefs_filtering_get_matching_from_action(gint action_id)
188 {
189         switch(action_id) {
190         case ACTION_MOVE:
191                 return MATCHACTION_MOVE;
192         case ACTION_COPY:
193                 return MATCHACTION_COPY;
194         case ACTION_DELETE:
195                 return MATCHACTION_DELETE;
196         case ACTION_MARK:
197                 return MATCHACTION_MARK;
198         case ACTION_UNMARK:
199                 return MATCHACTION_UNMARK;
200         case ACTION_MARK_AS_READ:
201                 return MATCHACTION_MARK_AS_READ;
202         case ACTION_MARK_AS_UNREAD:
203                 return MATCHACTION_MARK_AS_UNREAD;
204         case ACTION_FORWARD:
205                 return MATCHACTION_FORWARD;
206         case ACTION_FORWARD_AS_ATTACHMENT:
207                 return MATCHACTION_FORWARD_AS_ATTACHMENT;
208         case ACTION_BOUNCE:
209                 return MATCHACTION_BOUNCE;
210         case ACTION_EXECUTE:
211                 return MATCHACTION_EXECUTE;
212         case ACTION_COLOR:
213                 return MATCHACTION_COLOR;
214         case ACTION_DELETE_ON_SERVER:
215                 return MATCHACTION_DELETE_ON_SERVER;
216         default:
217                 return -1;
218         }
219 }
220
221 static gchar * action_text [] = {
222         N_("Move"),     
223         N_("Copy"), 
224         N_("Delete"),
225         N_("Mark"), 
226         N_("Unmark"), 
227         N_("Mark as read"), 
228         N_("Mark as unread"),
229         N_("Forward"), 
230         N_("Forward as attachment"), 
231         N_("Bounce"), 
232         N_("Execute"),
233         N_("Color"),
234         N_("Delete on Server")
235 };
236
237 void prefs_filtering_open(FolderItem * item,
238                           const gchar *header,
239                           const gchar *key)
240 {
241         if (prefs_rc_is_readonly(FILTERING_RC))
242                 return;
243
244         inc_lock();
245
246         if (!filtering.window) {
247                 prefs_filtering_create();
248         }
249
250         manage_window_set_transient(GTK_WINDOW(filtering.window));
251         gtk_widget_grab_focus(filtering.ok_btn);
252
253         cur_item = item;
254
255         prefs_filtering_set_dialog(header, key);
256
257         gtk_widget_show(filtering.window);
258
259         start_address_completion();
260 }
261
262 /* prefs_filtering_close() - just to have one common exit point */
263 static void prefs_filtering_close(void)
264 {
265         end_address_completion();
266         
267         gtk_widget_hide(filtering.window);
268         inc_unlock();
269 }
270
271 static void prefs_filtering_create(void)
272 {
273         GtkWidget *window;
274         GtkWidget *vbox;
275         GtkWidget *ok_btn;
276         GtkWidget *cancel_btn;
277         GtkWidget *confirm_area;
278
279         GtkWidget *vbox1;
280         GtkWidget *hbox1;
281         GtkWidget *reg_hbox;
282         GtkWidget *arrow;
283         GtkWidget *btn_hbox;
284
285         GtkWidget *cond_label;
286         GtkWidget *cond_entry;
287         GtkWidget *cond_btn;
288         GtkWidget *action_label;
289         GtkWidget *action_list;
290         GtkWidget *action_combo;
291         GtkWidget *account_label;
292         GtkWidget *account_list;
293         GtkWidget *account_combo;
294         GtkWidget *dest_label;
295         GtkWidget *exec_label;
296         GtkWidget *dest_entry;
297         GtkWidget *dest_btn;
298         GtkWidget *exec_btn;
299         GtkWidget *color_label;
300         GtkWidget *color_optmenu;
301
302         GtkWidget *reg_btn;
303         GtkWidget *subst_btn;
304         GtkWidget *del_btn;
305
306         GtkWidget *cond_hbox;
307         GtkWidget *cond_scrolledwin;
308         GtkWidget *cond_clist;
309
310         GtkWidget *btn_vbox;
311         GtkWidget *up_btn;
312         GtkWidget *down_btn;
313
314         GtkWidget *dummy;
315
316         GList *combo_items;
317         gint i;
318
319         GList *accounts;
320         GList * cur;
321
322         gchar *title[1];
323
324         debug_print(_("Creating filtering setting window...\n"));
325
326         window = gtk_window_new (GTK_WINDOW_DIALOG);
327         gtk_container_set_border_width (GTK_CONTAINER (window), 8);
328         gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
329         gtk_window_set_modal (GTK_WINDOW (window), TRUE);
330         gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
331
332         vbox = gtk_vbox_new (FALSE, 6);
333         gtk_widget_show (vbox);
334         gtk_container_add (GTK_CONTAINER (window), vbox);
335
336         gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
337                                 &cancel_btn, _("Cancel"), NULL, NULL);
338         gtk_widget_show (confirm_area);
339         gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
340         gtk_widget_grab_default (ok_btn);
341
342         gtk_window_set_title (GTK_WINDOW(window),
343                               _("Filtering setting"));
344         gtk_signal_connect (GTK_OBJECT(window), "delete_event",
345                             GTK_SIGNAL_FUNC(prefs_filtering_deleted), NULL);
346         gtk_signal_connect (GTK_OBJECT(window), "key_press_event",
347                             GTK_SIGNAL_FUNC(prefs_filtering_key_pressed), NULL);
348         MANAGE_WINDOW_SIGNALS_CONNECT (window);
349         gtk_signal_connect (GTK_OBJECT(ok_btn), "clicked",
350                             GTK_SIGNAL_FUNC(prefs_filtering_ok), NULL);
351         gtk_signal_connect (GTK_OBJECT(cancel_btn), "clicked",
352                             GTK_SIGNAL_FUNC(prefs_filtering_cancel), NULL);
353
354         vbox1 = gtk_vbox_new (FALSE, VSPACING);
355         gtk_widget_show (vbox1);
356         gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
357         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
358
359         cond_label = gtk_label_new (_("Condition"));
360         gtk_widget_show (cond_label);
361         gtk_misc_set_alignment (GTK_MISC (cond_label), 0, 0.5);
362         gtk_box_pack_start (GTK_BOX (vbox1), cond_label, FALSE, FALSE, 0);
363
364         hbox1 = gtk_hbox_new (FALSE, VSPACING);
365         gtk_widget_show (vbox1);
366         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
367         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
368
369         cond_entry = gtk_entry_new ();
370         gtk_widget_show (cond_entry);
371         gtk_box_pack_start (GTK_BOX (hbox1), cond_entry, TRUE, TRUE, 0);
372
373         cond_btn = gtk_button_new_with_label (_("Define ..."));
374         gtk_widget_show (cond_btn);
375         gtk_box_pack_start (GTK_BOX (hbox1), cond_btn, FALSE, FALSE, 0);
376         gtk_signal_connect (GTK_OBJECT (cond_btn), "clicked",
377                             GTK_SIGNAL_FUNC (prefs_filtering_condition_define),
378                             NULL);
379
380         hbox1 = gtk_hbox_new (FALSE, VSPACING);
381         gtk_widget_show (vbox1);
382         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
383         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
384
385         action_label = gtk_label_new (_("Action"));
386         gtk_widget_show (action_label);
387         gtk_misc_set_alignment (GTK_MISC (action_label), 0, 0.5);
388         gtk_box_pack_start (GTK_BOX (hbox1), action_label, FALSE, FALSE, 0);
389
390         action_combo = gtk_combo_new ();
391         gtk_widget_show (action_combo);
392         gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(action_combo)->entry),
393                                FALSE);
394
395         combo_items = NULL;
396
397         for(i = 0 ; i < (gint) (sizeof(action_text) / sizeof(gchar *)) ;
398             i++) {
399                 combo_items = g_list_append(combo_items,
400                                             (gpointer) _(action_text[i]));
401         }
402         gtk_combo_set_popdown_strings(GTK_COMBO(action_combo), combo_items);
403
404         g_list_free(combo_items);
405
406         gtk_box_pack_start (GTK_BOX (hbox1), action_combo,
407                             TRUE, TRUE, 0);
408         action_list = GTK_COMBO(action_combo)->list;
409         gtk_signal_connect (GTK_OBJECT (action_list), "select-child",
410                             GTK_SIGNAL_FUNC (prefs_filtering_action_select),
411                             NULL);
412
413         gtk_signal_connect(GTK_OBJECT(action_list), "selection-changed",
414                            GTK_SIGNAL_FUNC(prefs_filtering_action_selection_changed),
415                            NULL);
416
417         /* accounts */
418
419         hbox1 = gtk_hbox_new (FALSE, VSPACING);
420         gtk_widget_show (vbox1);
421         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
422         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
423
424         account_label = gtk_label_new (_("Account"));
425         gtk_widget_show (account_label);
426         gtk_misc_set_alignment (GTK_MISC (account_label), 0, 0.5);
427         gtk_box_pack_start (GTK_BOX (hbox1), account_label, FALSE, FALSE, 0);
428
429         account_combo = gtk_combo_new ();
430         gtk_widget_show (account_combo);
431
432         combo_items = NULL;
433         for (accounts = account_get_list() ; accounts != NULL;
434              accounts = accounts->next) {
435                 PrefsAccount *ac = (PrefsAccount *)accounts->data;
436                 gchar *name;
437
438                 name = g_strdup_printf("%s <%s> (%s)",
439                                        ac->name, ac->address,
440                                        ac->account_name);
441                 combo_items = g_list_append(combo_items, (gpointer) name);
442         }
443
444         gtk_combo_set_popdown_strings(GTK_COMBO(account_combo), combo_items);
445
446         for(cur = g_list_first(combo_items) ; cur != NULL ;
447             cur = g_list_next(cur))
448                 g_free(cur->data);
449         g_list_free(combo_items);
450
451         gtk_box_pack_start (GTK_BOX (hbox1), account_combo,
452                             TRUE, TRUE, 0);
453         account_list = GTK_COMBO(account_combo)->list;
454         gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(account_combo)->entry),
455                                FALSE);
456
457         /* destination */
458
459         hbox1 = gtk_hbox_new (FALSE, VSPACING);
460         gtk_widget_show (vbox1);
461         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
462         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
463
464         dest_label = gtk_label_new (_("Destination"));
465         gtk_widget_show (dest_label);
466         gtk_misc_set_alignment (GTK_MISC (dest_label), 0, 0.5);
467         gtk_box_pack_start (GTK_BOX (hbox1), dest_label, FALSE, FALSE, 0);
468
469         exec_label = gtk_label_new (_("Execute"));
470         gtk_widget_show (exec_label);
471         gtk_misc_set_alignment (GTK_MISC (exec_label), 0, 0.5);
472         gtk_box_pack_start (GTK_BOX (hbox1), exec_label, FALSE, FALSE, 0);
473         
474         color_label = gtk_label_new (_("Color"));
475         gtk_widget_show(color_label);
476         gtk_misc_set_alignment(GTK_MISC(color_label), 0, 0.5);
477         gtk_box_pack_start(GTK_BOX(hbox1), color_label, FALSE, FALSE, 0);
478
479         dest_entry = gtk_entry_new ();
480         gtk_widget_show (dest_entry);
481         gtk_box_pack_start (GTK_BOX (hbox1), dest_entry, TRUE, TRUE, 0);
482         
483         color_optmenu = gtk_option_menu_new();
484         gtk_option_menu_set_menu(GTK_OPTION_MENU(color_optmenu),
485                                  colorlabel_create_color_menu());
486         gtk_box_pack_start(GTK_BOX(hbox1), color_optmenu, TRUE, TRUE, 0);
487
488         dest_btn = gtk_button_new_with_label (_("Select ..."));
489         gtk_widget_show (dest_btn);
490         gtk_box_pack_start (GTK_BOX (hbox1), dest_btn, FALSE, FALSE, 0);
491         gtk_signal_connect (GTK_OBJECT (dest_btn), "clicked",
492                             GTK_SIGNAL_FUNC (prefs_filtering_select_dest),
493                             NULL);
494
495         exec_btn = gtk_button_new_with_label (_("Info ..."));
496         gtk_widget_show (exec_btn);
497         gtk_box_pack_start (GTK_BOX (hbox1), exec_btn, FALSE, FALSE, 0);
498         gtk_signal_connect (GTK_OBJECT (exec_btn), "clicked",
499                             GTK_SIGNAL_FUNC (prefs_matcher_exec_info),
500                             NULL);
501
502         /* register / substitute / delete */
503
504         reg_hbox = gtk_hbox_new (FALSE, 4);
505         gtk_widget_show (reg_hbox);
506         gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
507
508         arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
509         gtk_widget_show (arrow);
510         gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
511         gtk_widget_set_usize (arrow, -1, 16);
512
513         btn_hbox = gtk_hbox_new (TRUE, 4);
514         gtk_widget_show (btn_hbox);
515         gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
516
517         reg_btn = gtk_button_new_with_label (_("Register"));
518         gtk_widget_show (reg_btn);
519         gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
520         gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
521                             GTK_SIGNAL_FUNC (prefs_filtering_register_cb), NULL);
522
523         subst_btn = gtk_button_new_with_label (_(" Substitute "));
524         gtk_widget_show (subst_btn);
525         gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
526         gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
527                             GTK_SIGNAL_FUNC (prefs_filtering_substitute_cb),
528                             NULL);
529
530         del_btn = gtk_button_new_with_label (_("Delete"));
531         gtk_widget_show (del_btn);
532         gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
533         gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
534                             GTK_SIGNAL_FUNC (prefs_filtering_delete_cb), NULL);
535
536         cond_hbox = gtk_hbox_new (FALSE, 8);
537         gtk_widget_show (cond_hbox);
538         gtk_box_pack_start (GTK_BOX (vbox1), cond_hbox, TRUE, TRUE, 0);
539
540         cond_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
541         gtk_widget_show (cond_scrolledwin);
542         gtk_widget_set_usize (cond_scrolledwin, -1, 150);
543         gtk_box_pack_start (GTK_BOX (cond_hbox), cond_scrolledwin,
544                             TRUE, TRUE, 0);
545         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cond_scrolledwin),
546                                         GTK_POLICY_AUTOMATIC,
547                                         GTK_POLICY_AUTOMATIC);
548
549         title[0] = _("Registered rules");
550         cond_clist = gtk_clist_new_with_titles(1, title);
551         gtk_widget_show (cond_clist);
552         gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
553         gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
554         gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
555                                       GTK_SELECTION_BROWSE);
556         GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
557                                 GTK_CAN_FOCUS);
558         gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
559                             GTK_SIGNAL_FUNC (prefs_filtering_select), NULL);
560
561         btn_vbox = gtk_vbox_new (FALSE, 8);
562         gtk_widget_show (btn_vbox);
563         gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
564
565         up_btn = gtk_button_new_with_label (_("Up"));
566         gtk_widget_show (up_btn);
567         gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
568         gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
569                             GTK_SIGNAL_FUNC (prefs_filtering_up), NULL);
570
571         down_btn = gtk_button_new_with_label (_("Down"));
572         gtk_widget_show (down_btn);
573         gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
574         gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
575                             GTK_SIGNAL_FUNC (prefs_filtering_down), NULL);
576
577         gtk_widget_set_usize(window, 500, -1);
578
579         gtk_widget_show_all(window);
580
581         filtering.window    = window;
582         filtering.ok_btn = ok_btn;
583
584         filtering.cond_entry = cond_entry;
585         filtering.action_list = action_list;
586         filtering.action_combo = action_combo;
587         filtering.account_list = account_list;
588         filtering.account_combo = account_combo;
589         filtering.dest_entry = dest_entry;
590         filtering.dest_btn = dest_btn;
591         filtering.dest_label = dest_label;
592         filtering.exec_label = exec_label;
593         filtering.exec_btn = exec_btn;
594
595         filtering.cond_clist   = cond_clist;
596
597         filtering.color_label   = color_label;
598         filtering.color_optmenu = color_optmenu;
599 }
600
601 static void prefs_filtering_update_hscrollbar(void)
602 {
603         gint optwidth = gtk_clist_optimal_column_width(GTK_CLIST(filtering.cond_clist), 0);
604         gtk_clist_set_column_width(GTK_CLIST(filtering.cond_clist), 0, optwidth);
605 }
606
607 void prefs_filtering_rename_path(const gchar *old_path, const gchar *new_path)
608 {
609         GSList *cur;
610         gchar *base;
611         gchar *prefix;
612         gchar *suffix;
613         gchar *dest_path;
614         gint destlen;
615         gint prefixlen;
616         gint oldpathlen;
617
618         g_return_if_fail(old_path != NULL);
619         g_return_if_fail(new_path != NULL);
620
621         oldpathlen = strlen(old_path);
622
623         for (cur = global_processing; cur != NULL; cur = cur->next) {
624                 FilteringProp   *filtering = (FilteringProp *)cur->data;
625                 FilteringAction *action = filtering->action;
626
627                 if (!action->destination) continue;
628
629                 destlen = strlen(action->destination);
630
631                 if (destlen > oldpathlen) {
632                         prefixlen = destlen - oldpathlen;
633                         suffix = action->destination + prefixlen;
634
635                         if (!strncmp(old_path, suffix, oldpathlen)) {
636                                 prefix = g_malloc0(prefixlen + 1);
637                                 strncpy2(prefix, action->destination, prefixlen);
638
639                                 base = suffix + oldpathlen;
640                                 while (*base == G_DIR_SEPARATOR) base++;
641                                 if (*base == '\0')
642                                         dest_path = g_strconcat(prefix,
643                                                                 G_DIR_SEPARATOR_S,
644                                                                 new_path, NULL);
645                                 else
646                                         dest_path = g_strconcat(prefix,
647                                                                 G_DIR_SEPARATOR_S,
648                                                                 new_path,
649                                                                 G_DIR_SEPARATOR_S,
650                                                                 base, NULL);
651
652                                 g_free(prefix);
653                                 g_free(action->destination);
654                                 action->destination = dest_path;
655                         }
656                 }
657         }
658
659         prefs_matcher_write_config();
660 }
661
662 void prefs_filtering_delete_path(const gchar *path)
663 {
664         GSList *cur;
665         GSList *next;
666         gchar *suffix;
667         gint destlen;
668         gint prefixlen;
669         gint pathlen;
670
671         g_return_if_fail(path != NULL);
672
673         pathlen = strlen(path);
674         for (cur = global_processing; cur != NULL; cur = next) {
675                 FilteringProp *filtering = (FilteringProp *)cur->data;
676                 FilteringAction *action = filtering->action;
677                 next = cur->next;
678
679                 if (!action->destination) continue;
680
681                 destlen = strlen(action->destination);
682
683                 if (destlen > pathlen) {
684                         prefixlen = destlen - pathlen;
685                         suffix = action->destination + prefixlen;
686
687                         if (suffix && !strncmp(path, suffix, pathlen)) {
688                                 filteringprop_free(filtering);
689                                 global_processing = 
690                                         g_slist_remove(global_processing, filtering);
691                         }
692                 }
693         }
694
695         prefs_matcher_write_config();
696 }
697
698 static void prefs_filtering_set_dialog(const gchar *header, const gchar *key)
699 {
700         GtkCList *clist = GTK_CLIST(filtering.cond_clist);
701         GSList *cur;
702         GSList * prefs_filtering;
703         gchar *cond_str[1];
704         gint row;
705         
706         gtk_clist_freeze(clist);
707         gtk_clist_clear(clist);
708
709         cond_str[0] = _("(New)");
710         row = gtk_clist_append(clist, cond_str);
711         gtk_clist_set_row_data(clist, row, NULL);
712
713         if (cur_item == NULL)
714                 prefs_filtering = global_processing;
715         else
716                 prefs_filtering = cur_item->prefs->processing;
717
718         for(cur = prefs_filtering ; cur != NULL ; cur = g_slist_next(cur)) {
719                 FilteringProp * prop = (FilteringProp *) cur->data;
720
721                 cond_str[0] = filteringprop_to_string(prop);
722                 subst_char(cond_str[0], '\t', ':');
723                 row = gtk_clist_append(clist, cond_str);
724                 gtk_clist_set_row_data(clist, row, prop);
725
726                 g_free(cond_str[0]);
727         }
728
729         prefs_filtering_update_hscrollbar();
730         gtk_clist_thaw(clist);
731
732         prefs_filtering_reset_dialog();
733
734         if (header && key) {
735                 gchar *match_str = g_strconcat(header, " ",
736                         get_matchparser_tab_str(MATCHTYPE_MATCHCASE),
737                         " \"", key, "\"", NULL);
738                 gtk_entry_set_text(GTK_ENTRY(filtering.cond_entry), match_str);
739                 g_free(match_str);
740         }
741 }
742
743 static void prefs_filtering_reset_dialog(void)
744 {
745         gtk_list_select_item(GTK_LIST(filtering.action_list), 0);
746         gtk_list_select_item(GTK_LIST(filtering.account_list), 0);
747         gtk_entry_set_text(GTK_ENTRY(filtering.dest_entry), "");
748         gtk_entry_set_text(GTK_ENTRY(filtering.cond_entry), "");
749 }
750
751 static void prefs_filtering_set_list(void)
752 {
753         gint row = 1;
754         FilteringProp *prop;
755         GSList * cur;
756         gchar * filtering_str;
757         gchar * tmp;
758         GSList * prefs_filtering;
759
760         if (cur_item == NULL)
761                 prefs_filtering = global_processing;
762         else
763                 prefs_filtering = cur_item->prefs->processing;
764
765         for(cur = prefs_filtering ; cur != NULL ; cur = g_slist_next(cur))
766                 filteringprop_free((FilteringProp *) cur->data);
767         g_slist_free(prefs_filtering);
768         prefs_filtering = NULL;
769
770         while (gtk_clist_get_text(GTK_CLIST(filtering.cond_clist),
771                                   row, 0, &filtering_str)) {
772                 if (strcmp(filtering_str, _("(New)")) != 0) {
773                         /* tmp = filtering_str; */
774                         prop = matcher_parser_get_filtering(filtering_str);
775                         if (prop != NULL)
776                                 prefs_filtering =
777                                         g_slist_append(prefs_filtering, prop);
778                 }
779                 row++;
780         }
781
782         if (cur_item == NULL)
783                 global_processing = prefs_filtering;
784         else
785                 cur_item->prefs->processing = prefs_filtering;
786 }
787
788 static gint prefs_filtering_clist_set_row(gint row, FilteringProp * prop)
789 {
790         GtkCList *clist = GTK_CLIST(filtering.cond_clist);
791         gchar * str;
792         gchar *cond_str[1];
793
794         if (prop == NULL) {
795                 cond_str[0] = _("(New)");
796                 return gtk_clist_append(clist, cond_str);
797         }
798
799         str = filteringprop_to_string(prop);
800         if (str == NULL) {
801                 return -1;
802         }
803         cond_str[0] = str;
804
805         if (row < 0)
806                 row = gtk_clist_append(clist, cond_str);
807         else
808                 gtk_clist_set_text(clist, row, 0, cond_str[0]);
809         g_free(str);
810
811         return row;
812 }
813
814 static void prefs_filtering_condition_define_done(MatcherList * matchers)
815 {
816         gchar * str;
817
818         if (matchers == NULL)
819                 return;
820
821         str = matcherlist_to_string(matchers);
822
823         if (str != NULL) {
824                 gtk_entry_set_text(GTK_ENTRY(filtering.cond_entry), str);
825                 g_free(str);
826         }
827 }
828
829 static void prefs_filtering_condition_define(void)
830 {
831         gchar * cond_str;
832         MatcherList * matchers = NULL;
833
834         cond_str = gtk_entry_get_text(GTK_ENTRY(filtering.cond_entry));
835
836         if (*cond_str != '\0') {
837                 gchar * tmp;
838                 
839                 /* tmp = cond_str; */
840                 matchers = matcher_parser_get_cond(cond_str);
841                 if (matchers == NULL)
842                         alertpanel_error(_("Match string is not valid."));
843         }
844
845         prefs_matcher_open(matchers, prefs_filtering_condition_define_done);
846
847         if (matchers != NULL)
848                 matcherlist_free(matchers);
849 }
850
851
852 /* register / substitute delete buttons */
853
854
855 static FilteringProp * prefs_filtering_dialog_to_filtering(void)
856 {
857         MatcherList * cond;
858         gchar * cond_str;
859         FilteringProp * prop;
860         FilteringAction * action;
861         gchar * tmp;
862         gint list_id;
863         gint action_id;
864         gint action_type;
865         gint account_id;
866         gchar * destination;
867         gint labelcolor;
868         
869         cond_str = gtk_entry_get_text(GTK_ENTRY(filtering.cond_entry));
870         if (*cond_str == '\0') {
871                 alertpanel_error(_("Score is not set."));
872                 return NULL;
873         }
874
875         action_id = get_sel_from_list(GTK_LIST(filtering.action_list));
876         action_type = prefs_filtering_get_matching_from_action(action_id);
877         list_id = get_sel_from_list(GTK_LIST(filtering.account_list));
878         account_id = get_account_id_from_list_id(list_id);
879
880         switch (action_id) {
881         case ACTION_MOVE:
882         case ACTION_COPY:
883         case ACTION_FORWARD:
884         case ACTION_FORWARD_AS_ATTACHMENT:
885         case ACTION_BOUNCE:
886         case ACTION_EXECUTE:
887                 destination = gtk_entry_get_text(GTK_ENTRY(filtering.dest_entry));
888                 if (*destination == '\0') {
889                         alertpanel_error(_("Destination is not set."));
890                         return NULL;
891                 }
892                 break;
893         case ACTION_COLOR:
894                 labelcolor = colorlabel_get_color_menu_active_item(
895                         gtk_option_menu_get_menu(GTK_OPTION_MENU(filtering.color_optmenu)));
896                 destination = NULL;     
897                 break;
898         case ACTION_DELETE_ON_SERVER:
899                 destination = NULL;
900                 break;
901         default:
902                 destination = NULL;
903                 break;
904         }
905         
906         action = filteringaction_new(action_type, account_id, destination, labelcolor);
907
908         cond = matcher_parser_get_cond(cond_str);
909
910         if (cond == NULL) {
911                 alertpanel_error(_("Match string is not valid."));
912                 filteringaction_free(action);
913                 return NULL;
914         }
915
916         prop = filteringprop_new(cond, action);
917
918         return prop;
919 }
920
921 static void prefs_filtering_register_cb(void)
922 {
923         FilteringProp * prop;
924         
925         prop = prefs_filtering_dialog_to_filtering();
926         if (prop == NULL)
927                 return;
928         prefs_filtering_clist_set_row(-1, prop);
929
930         filteringprop_free(prop);
931         
932         prefs_filtering_update_hscrollbar();
933 }
934
935 static void prefs_filtering_substitute_cb(void)
936 {
937         GtkCList *clist = GTK_CLIST(filtering.cond_clist);
938         gint row;
939         FilteringProp * prop;
940         
941         if (!clist->selection) return;
942
943         row = GPOINTER_TO_INT(clist->selection->data);
944         if (row == 0) return;
945
946         prop = prefs_filtering_dialog_to_filtering();
947         if (prop == NULL)
948                 return;
949         prefs_filtering_clist_set_row(row, prop);
950
951         filteringprop_free(prop);
952         
953         prefs_filtering_update_hscrollbar();
954 }
955
956 static void prefs_filtering_delete_cb(void)
957 {
958         GtkCList *clist = GTK_CLIST(filtering.cond_clist);
959         gint row;
960
961         if (!clist->selection) return;
962         row = GPOINTER_TO_INT(clist->selection->data);
963         if (row == 0) return;
964
965         if (alertpanel(_("Delete rule"),
966                        _("Do you really want to delete this rule?"),
967                        _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
968                 return;
969
970         gtk_clist_remove(clist, row);
971
972         prefs_filtering_update_hscrollbar();
973 }
974
975 static void prefs_filtering_up(void)
976 {
977         GtkCList *clist = GTK_CLIST(filtering.cond_clist);
978         gint row;
979
980         if (!clist->selection) return;
981
982         row = GPOINTER_TO_INT(clist->selection->data);
983         if (row > 1) {
984                 gtk_clist_row_move(clist, row, row - 1);
985                 if(gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL) {
986                         gtk_clist_moveto(clist, row - 1, 0, 0, 0);
987                 } 
988         }
989 }
990
991 static void prefs_filtering_down(void)
992 {
993         GtkCList *clist = GTK_CLIST(filtering.cond_clist);
994         gint row;
995
996         if (!clist->selection) return;
997
998         row = GPOINTER_TO_INT(clist->selection->data);
999         if (row > 0 && row < clist->rows - 1) {
1000                 gtk_clist_row_move(clist, row, row + 1);
1001                 if(gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL) {
1002                         gtk_clist_moveto(clist, row + 1, 0, 1, 0);
1003                 } 
1004         }
1005 }
1006
1007 static void prefs_filtering_select_set(FilteringProp * prop)
1008 {
1009         FilteringAction * action;
1010         gchar * matcher_str;
1011         gint list_id;
1012
1013         prefs_filtering_reset_dialog();
1014
1015         action = prop->action;
1016
1017         matcher_str = matcherlist_to_string(prop->matchers);
1018         if (matcher_str == NULL) {
1019                 filteringprop_free(prop);
1020                 return;
1021         }
1022
1023         gtk_entry_set_text(GTK_ENTRY(filtering.cond_entry), matcher_str);
1024         
1025         if (action->destination)
1026                 gtk_entry_set_text(GTK_ENTRY(filtering.dest_entry), action->destination);
1027         else
1028                 gtk_entry_set_text(GTK_ENTRY(filtering.dest_entry), "");
1029
1030         switch(action->type) {
1031         case MATCHACTION_MOVE:
1032                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1033                                      ACTION_MOVE);
1034                 break;
1035         case MATCHACTION_COPY:
1036                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1037                                      ACTION_COPY);
1038                 break;
1039         case MATCHACTION_DELETE:
1040                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1041                                      ACTION_DELETE);
1042                 break;
1043         case MATCHACTION_MARK:
1044                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1045                                      ACTION_MARK);
1046                 break;
1047         case MATCHACTION_UNMARK:
1048                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1049                                      ACTION_UNMARK);
1050                 break;
1051         case MATCHACTION_MARK_AS_READ:
1052                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1053                                      ACTION_MARK_AS_READ);
1054                 break;
1055         case MATCHACTION_MARK_AS_UNREAD:
1056                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1057                                      ACTION_MARK_AS_UNREAD);
1058                 break;
1059         case MATCHACTION_FORWARD:
1060                 list_id = get_list_id_from_account_id(action->account_id);
1061                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1062                                      ACTION_FORWARD);
1063                 gtk_list_select_item(GTK_LIST(filtering.account_list),
1064                                      list_id);
1065                 break;
1066         case MATCHACTION_FORWARD_AS_ATTACHMENT:
1067                 list_id = get_list_id_from_account_id(action->account_id);
1068                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1069                                      ACTION_FORWARD_AS_ATTACHMENT);
1070                 gtk_list_select_item(GTK_LIST(filtering.account_list),
1071                                      list_id);
1072                 break;
1073         case MATCHACTION_BOUNCE:
1074                 list_id = get_list_id_from_account_id(action->account_id);
1075                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1076                                      ACTION_BOUNCE);
1077                 gtk_list_select_item(GTK_LIST(filtering.account_list),
1078                                      list_id);
1079                 break;
1080         case MATCHACTION_EXECUTE:
1081                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1082                                      ACTION_EXECUTE);
1083                 break;
1084         case MATCHACTION_COLOR:
1085                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1086                                      ACTION_COLOR);
1087                 gtk_option_menu_set_history(GTK_OPTION_MENU(filtering.color_optmenu), action->labelcolor);     
1088                 break;
1089         case MATCHACTION_DELETE_ON_SERVER:
1090                 gtk_list_select_item(GTK_LIST(filtering.action_list),
1091                                      ACTION_DELETE_ON_SERVER);
1092                 break;
1093         }
1094
1095         g_free(matcher_str);
1096 }
1097
1098 static void prefs_filtering_select(GtkCList *clist, gint row, gint column,
1099                                 GdkEvent *event)
1100 {
1101         FilteringProp * prop;
1102         gchar * tmp;
1103         gchar * filtering_str;
1104
1105         if (row == 0) {
1106                 prefs_filtering_reset_dialog();
1107                 return;
1108         }
1109
1110         if (!gtk_clist_get_text(GTK_CLIST(filtering.cond_clist),
1111                                 row, 0, &filtering_str))
1112                 return;
1113         
1114         prop = matcher_parser_get_filtering(filtering_str);
1115         if (prop == NULL)
1116                 return;
1117
1118         prefs_filtering_select_set(prop);
1119
1120         filteringprop_free(prop);
1121 }
1122
1123 static void prefs_filtering_select_dest(void)
1124 {
1125         FolderItem *dest;
1126         gchar * path;
1127
1128         dest = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL);
1129         if (!dest) return;
1130
1131         path = folder_item_get_identifier(dest);
1132
1133         gtk_entry_set_text(GTK_ENTRY(filtering.dest_entry), path);
1134         g_free(path);
1135 }
1136
1137 static void prefs_filtering_action_selection_changed(GtkList *list,
1138                                                      gpointer user_data)
1139 {
1140         gint value;
1141
1142         value = get_sel_from_list(GTK_LIST(filtering.action_list));
1143
1144         if (filtering.current_action != value) {
1145                 if (filtering.current_action == ACTION_FORWARD 
1146                 ||  filtering.current_action == ACTION_FORWARD_AS_ATTACHMENT) {
1147                         debug_print("unregistering address completion entry\n");
1148                         address_completion_unregister_entry(GTK_ENTRY(filtering.dest_entry));
1149                 }
1150                 if (value == ACTION_FORWARD || value == ACTION_FORWARD_AS_ATTACHMENT) {
1151                         debug_print("registering address completion entry\n");
1152                         address_completion_register_entry(GTK_ENTRY(filtering.dest_entry));
1153                 }
1154                 filtering.current_action = value;
1155         }
1156 }
1157
1158 static void prefs_filtering_action_select(GtkList *list,
1159                                           GtkWidget *widget,
1160                                           gpointer user_data)
1161 {
1162         gint value;
1163
1164         value = get_sel_from_list(GTK_LIST(filtering.action_list));
1165
1166         switch (value) {
1167         case ACTION_MOVE:
1168                 gtk_widget_set_sensitive(filtering.account_combo, FALSE);
1169                 gtk_widget_show(filtering.dest_entry);
1170                 gtk_widget_set_sensitive(filtering.dest_entry, TRUE);
1171                 gtk_widget_show(filtering.dest_btn);
1172                 gtk_widget_show(filtering.dest_label);
1173                 gtk_widget_hide(filtering.exec_label);
1174                 gtk_widget_hide(filtering.exec_btn);
1175                 gtk_widget_hide(filtering.color_optmenu);
1176                 gtk_widget_hide(filtering.color_label);
1177                 break;
1178         case ACTION_COPY:
1179                 gtk_widget_set_sensitive(filtering.account_combo, FALSE);
1180                 gtk_widget_show(filtering.dest_entry);
1181                 gtk_widget_set_sensitive(filtering.dest_entry, TRUE);
1182                 gtk_widget_show(filtering.dest_btn);
1183                 gtk_widget_show(filtering.dest_label);
1184                 gtk_widget_hide(filtering.exec_label);
1185                 gtk_widget_hide(filtering.exec_btn);
1186                 gtk_widget_hide(filtering.color_optmenu);
1187                 gtk_widget_hide(filtering.color_label);
1188                 break;
1189         case ACTION_DELETE:
1190                 gtk_widget_set_sensitive(filtering.account_combo, FALSE);
1191                 gtk_widget_show(filtering.dest_entry);
1192                 gtk_widget_set_sensitive(filtering.dest_entry, FALSE);
1193                 gtk_widget_hide(filtering.dest_btn);
1194                 gtk_widget_show(filtering.dest_label);
1195                 gtk_widget_hide(filtering.exec_label);
1196                 gtk_widget_hide(filtering.exec_btn);
1197                 gtk_widget_hide(filtering.color_optmenu);
1198                 gtk_widget_hide(filtering.color_label);
1199                 break;
1200         case ACTION_MARK:
1201                 gtk_widget_set_sensitive(filtering.account_combo, FALSE);
1202                 gtk_widget_show(filtering.dest_entry);
1203                 gtk_widget_set_sensitive(filtering.dest_entry, FALSE);
1204                 gtk_widget_hide(filtering.dest_btn);
1205                 gtk_widget_show(filtering.dest_label);
1206                 gtk_widget_hide(filtering.exec_label);
1207                 gtk_widget_hide(filtering.exec_btn);
1208                 gtk_widget_hide(filtering.color_optmenu);
1209                 gtk_widget_hide(filtering.color_label);
1210                 break;
1211         case ACTION_UNMARK:
1212                 gtk_widget_set_sensitive(filtering.account_combo, FALSE);
1213                 gtk_widget_show(filtering.dest_entry);
1214                 gtk_widget_set_sensitive(filtering.dest_entry, FALSE);
1215                 gtk_widget_hide(filtering.dest_btn);
1216                 gtk_widget_show(filtering.dest_label);
1217                 gtk_widget_hide(filtering.exec_label);
1218                 gtk_widget_hide(filtering.exec_btn);
1219                 gtk_widget_hide(filtering.color_optmenu);
1220                 gtk_widget_hide(filtering.color_label);
1221                 break;
1222         case ACTION_MARK_AS_READ:
1223                 gtk_widget_set_sensitive(filtering.account_combo, FALSE);
1224                 gtk_widget_show(filtering.dest_entry);
1225                 gtk_widget_set_sensitive(filtering.dest_entry, FALSE);
1226                 gtk_widget_hide(filtering.dest_btn);
1227                 gtk_widget_show(filtering.dest_label);
1228                 gtk_widget_hide(filtering.exec_label);
1229                 gtk_widget_hide(filtering.exec_btn);
1230                 gtk_widget_hide(filtering.color_optmenu);
1231                 gtk_widget_hide(filtering.color_label);
1232                 break;
1233         case ACTION_MARK_AS_UNREAD:
1234                 gtk_widget_set_sensitive(filtering.account_combo, FALSE);
1235                 gtk_widget_show(filtering.dest_entry);
1236                 gtk_widget_set_sensitive(filtering.dest_entry, FALSE);
1237                 gtk_widget_hide(filtering.dest_btn);
1238                 gtk_widget_show(filtering.dest_label);
1239                 gtk_widget_hide(filtering.exec_label);
1240                 gtk_widget_hide(filtering.exec_btn);
1241                 gtk_widget_hide(filtering.color_optmenu);
1242                 gtk_widget_hide(filtering.color_label);
1243                 break;
1244         case ACTION_FORWARD:
1245                 gtk_widget_set_sensitive(filtering.account_combo, TRUE);
1246                 gtk_widget_show(filtering.dest_entry);
1247                 gtk_widget_set_sensitive(filtering.dest_entry, TRUE);
1248                 gtk_widget_hide(filtering.dest_btn);
1249                 gtk_widget_show(filtering.dest_label);
1250                 gtk_widget_hide(filtering.exec_label);
1251                 gtk_widget_hide(filtering.exec_btn);
1252                 gtk_widget_hide(filtering.color_optmenu);
1253                 gtk_widget_hide(filtering.color_label);
1254                 break;
1255         case ACTION_FORWARD_AS_ATTACHMENT:
1256                 gtk_widget_set_sensitive(filtering.account_combo, TRUE);
1257                 gtk_widget_show(filtering.dest_entry);
1258                 gtk_widget_set_sensitive(filtering.dest_entry, TRUE);
1259                 gtk_widget_hide(filtering.dest_btn);
1260                 gtk_widget_show(filtering.dest_label);
1261                 gtk_widget_hide(filtering.exec_label);
1262                 gtk_widget_hide(filtering.exec_btn);
1263                 gtk_widget_hide(filtering.color_optmenu);
1264                 gtk_widget_hide(filtering.color_label);
1265                 break;
1266         case ACTION_BOUNCE:
1267                 gtk_widget_set_sensitive(filtering.account_combo, TRUE);
1268                 gtk_widget_show(filtering.dest_entry);
1269                 gtk_widget_set_sensitive(filtering.dest_entry, TRUE);
1270                 gtk_widget_hide(filtering.dest_btn);
1271                 gtk_widget_show(filtering.dest_label);
1272                 gtk_widget_hide(filtering.exec_label);
1273                 gtk_widget_hide(filtering.exec_btn);
1274                 gtk_widget_hide(filtering.color_optmenu);
1275                 gtk_widget_hide(filtering.color_label);
1276                 break;
1277         case ACTION_EXECUTE:
1278                 gtk_widget_set_sensitive(filtering.account_combo, FALSE);
1279                 gtk_widget_show(filtering.dest_entry);
1280                 gtk_widget_set_sensitive(filtering.dest_entry, TRUE);
1281                 gtk_widget_hide(filtering.dest_btn);
1282                 gtk_widget_hide(filtering.dest_label);
1283                 gtk_widget_show(filtering.exec_label);
1284                 gtk_widget_set_sensitive(filtering.exec_btn, TRUE);
1285                 gtk_widget_show(filtering.exec_btn);
1286                 gtk_widget_hide(filtering.color_optmenu);
1287                 gtk_widget_hide(filtering.color_label);
1288                 break;
1289         case ACTION_COLOR:
1290                 gtk_widget_set_sensitive(filtering.account_combo, FALSE);
1291                 gtk_widget_hide(filtering.dest_entry);
1292                 gtk_widget_hide(filtering.dest_btn);
1293                 gtk_widget_hide(filtering.dest_label);
1294                 gtk_widget_hide(filtering.exec_label);
1295                 gtk_widget_show(filtering.exec_btn);
1296                 gtk_widget_set_sensitive(filtering.exec_btn, FALSE);
1297                 gtk_widget_show(filtering.color_optmenu);
1298                 gtk_widget_show(filtering.color_label);
1299                 break;
1300         case ACTION_DELETE_ON_SERVER:
1301                 gtk_widget_set_sensitive(filtering.account_combo, FALSE);
1302                 gtk_widget_hide(filtering.dest_entry);
1303                 gtk_widget_hide(filtering.dest_btn);
1304                 gtk_widget_hide(filtering.dest_label);
1305                 gtk_widget_hide(filtering.exec_label);
1306                 gtk_widget_show(filtering.exec_btn);
1307                 gtk_widget_hide(filtering.exec_btn);
1308                 gtk_widget_hide(filtering.color_optmenu);
1309                 gtk_widget_hide(filtering.color_label);
1310                 break;
1311         }
1312 }
1313
1314 static gint prefs_filtering_deleted(GtkWidget *widget, GdkEventAny *event,
1315                                  gpointer data)
1316 {
1317         prefs_filtering_cancel();
1318         return TRUE;
1319 }
1320
1321 static void prefs_filtering_key_pressed(GtkWidget *widget, GdkEventKey *event,
1322                                      gpointer data)
1323 {
1324         if (event && event->keyval == GDK_Escape)
1325                 prefs_filtering_cancel();
1326 }
1327
1328 static void prefs_filtering_ok(void)
1329 {
1330         prefs_filtering_set_list();
1331         prefs_matcher_write_config();
1332         prefs_filtering_close();
1333 }
1334
1335 static void prefs_filtering_cancel(void)
1336 {
1337         prefs_matcher_read_config();
1338         prefs_filtering_close();
1339 }