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