2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2002 Hiroyuki Yamamoto
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.
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.
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.
28 #include <gdk/gdkkeysyms.h>
37 #include "prefs_filter.h"
38 #include "prefs_common.h"
39 #include "mainwindow.h"
40 #include "foldersel.h"
41 #include "manage_window.h"
46 #include "alertpanel.h"
49 static struct Filter {
54 GtkWidget *hdr_combo1;
55 GtkWidget *hdr_combo2;
56 GtkWidget *hdr_entry1;
57 GtkWidget *hdr_entry2;
58 GtkWidget *key_entry1;
59 GtkWidget *key_entry2;
60 GtkWidget *pred_combo1;
61 GtkWidget *pred_combo2;
62 GtkWidget *pred_entry1;
63 GtkWidget *pred_entry2;
64 GtkWidget *cond_combo;
65 GtkWidget *cond_entry;
67 GtkWidget *dest_entry;
68 GtkWidget *regex_chkbtn;
70 GtkWidget *destsel_btn;
71 GtkWidget *dest_radiobtn;
72 GtkWidget *notrecv_radiobtn;
74 GtkWidget *cond_clist;
78 parameter name, default value, pointer to the prefs variable, data type,
79 pointer to the widget pointer,
80 pointer to the function for data setting,
81 pointer to the function for widget setting
84 /* widget creating functions */
85 static void prefs_filter_create (void);
87 static void prefs_filter_set_dialog (const gchar *header,
89 static void prefs_filter_set_list (void);
90 static gint prefs_filter_clist_set_row (gint row);
92 /* callback functions */
93 static void prefs_filter_select_dest_cb (void);
94 static void prefs_filter_register_cb (void);
95 static void prefs_filter_substitute_cb (void);
96 static void prefs_filter_delete_cb (void);
97 static void prefs_filter_up (void);
98 static void prefs_filter_down (void);
99 static void prefs_filter_select (GtkCList *clist,
103 static void prefs_filter_row_move (GtkCList *clist,
107 static void prefs_filter_dest_radio_button_toggled (void);
108 static void prefs_filter_notrecv_radio_button_toggled (void);
109 static void prefs_filter_regex_check_button_toggled (void);
111 static gint prefs_filter_deleted (GtkWidget *widget,
114 static void prefs_filter_key_pressed (GtkWidget *widget,
117 static void prefs_filter_cancel (void);
118 static void prefs_filter_ok (void);
120 void prefs_filter_open(const gchar *header, const gchar *key)
122 if (prefs_rc_is_readonly(FILTER_RC))
127 if (!filter.window) {
128 prefs_filter_create();
131 manage_window_set_transient(GTK_WINDOW(filter.window));
132 gtk_widget_grab_focus(filter.ok_btn);
134 prefs_filter_set_dialog(header, key);
136 gtk_widget_show(filter.window);
139 static void prefs_filter_create(void)
144 GtkWidget *cancel_btn;
145 GtkWidget *confirm_area;
149 GtkWidget *cond_label;
150 GtkWidget *cond_combo;
151 GtkWidget *cond_entry;
152 GtkWidget *hdr_label;
153 GtkWidget *hdr_combo1;
154 GtkWidget *hdr_combo2;
155 GtkWidget *key_label;
156 GtkWidget *key_entry1;
157 GtkWidget *key_entry2;
158 GtkWidget *pred_label;
159 GtkWidget *pred_combo1;
160 GtkWidget *pred_entry1;
161 GtkWidget *pred_combo2;
162 GtkWidget *pred_entry2;
165 GtkWidget *dest_hbox;
166 GtkWidget *dest_entry;
167 GtkWidget *destsel_btn;
168 GtkWidget *dest_radiobtn;
169 GtkWidget *notrecv_radiobtn;
170 GSList *recv_group = NULL;
172 GtkWidget *regex_chkbtn;
178 GtkWidget *subst_btn;
181 GtkWidget *cond_hbox;
182 GtkWidget *cond_scrolledwin;
183 GtkWidget *cond_clist;
191 debug_print(_("Creating filter setting window...\n"));
193 window = gtk_window_new (GTK_WINDOW_DIALOG);
194 gtk_container_set_border_width (GTK_CONTAINER (window), 8);
195 gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
196 gtk_window_set_modal (GTK_WINDOW (window), TRUE);
197 gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
199 vbox = gtk_vbox_new (FALSE, 6);
200 gtk_widget_show (vbox);
201 gtk_container_add (GTK_CONTAINER (window), vbox);
203 gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
204 &cancel_btn, _("Cancel"), NULL, NULL);
205 gtk_widget_show (confirm_area);
206 gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
207 gtk_widget_grab_default (ok_btn);
210 gtkut_button_set_create (&confirm_area, &close_btn, _("Close"),
211 NULL, NULL, NULL, NULL);
212 gtk_widget_show (confirm_area);
213 gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
214 gtk_widget_grab_default (close_btn);
217 gtk_window_set_title (GTK_WINDOW(window),
218 _("Filter setting"));
219 gtk_signal_connect (GTK_OBJECT(window), "delete_event",
220 GTK_SIGNAL_FUNC(prefs_filter_deleted), NULL);
221 gtk_signal_connect (GTK_OBJECT(window), "key_press_event",
222 GTK_SIGNAL_FUNC(prefs_filter_key_pressed), NULL);
223 gtk_signal_connect (GTK_OBJECT(window), "focus_in_event",
224 GTK_SIGNAL_FUNC(manage_window_focus_in), NULL);
225 gtk_signal_connect (GTK_OBJECT(window), "focus_out_event",
226 GTK_SIGNAL_FUNC(manage_window_focus_out), NULL);
227 gtk_signal_connect (GTK_OBJECT(ok_btn), "clicked",
228 GTK_SIGNAL_FUNC(prefs_filter_ok), NULL);
229 gtk_signal_connect (GTK_OBJECT(cancel_btn), "clicked",
230 GTK_SIGNAL_FUNC(prefs_filter_cancel), NULL);
232 vbox1 = gtk_vbox_new (FALSE, VSPACING);
233 gtk_widget_show (vbox1);
234 gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
235 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
237 table1 = gtk_table_new (3, 4, FALSE);
238 gtk_widget_show (table1);
239 gtk_box_pack_start (GTK_BOX (vbox1), table1, FALSE, FALSE, 0);
240 gtk_table_set_row_spacings (GTK_TABLE (table1), 8);
241 gtk_table_set_col_spacings (GTK_TABLE (table1), 8);
243 cond_label = gtk_label_new (_("Condition"));
244 gtk_widget_show (cond_label);
245 gtk_table_attach (GTK_TABLE (table1), cond_label, 0, 1, 0, 1,
247 gtk_misc_set_alignment (GTK_MISC (cond_label), 0, 0.5);
249 cond_combo = gtk_combo_new ();
250 gtk_widget_show (cond_combo);
251 gtk_table_attach (GTK_TABLE (table1), cond_combo, 0, 1, 2, 3,
253 gtk_widget_set_usize (cond_combo, 52, -1);
254 gtkut_combo_set_items (GTK_COMBO (cond_combo), "and", "or", NULL);
256 cond_entry = GTK_COMBO (cond_combo)->entry;
257 gtk_entry_set_editable (GTK_ENTRY (cond_entry), FALSE);
259 hdr_label = gtk_label_new (_("Header"));
260 gtk_widget_show (hdr_label);
261 gtk_table_attach (GTK_TABLE (table1), hdr_label, 1, 2, 0, 1,
263 gtk_misc_set_alignment (GTK_MISC (hdr_label), 0, 0.5);
265 hdr_combo1 = gtk_combo_new ();
266 gtk_widget_show (hdr_combo1);
267 gtk_table_attach (GTK_TABLE (table1), hdr_combo1, 1, 2, 1, 2,
269 gtk_widget_set_usize (hdr_combo1, 96, -1);
270 gtkut_combo_set_items (GTK_COMBO (hdr_combo1),
271 "Subject", "From", "To", "Cc", "Reply-To",
273 "X-ML-Name", "X-List", "X-Sequence", "X-Mailer",
276 hdr_combo2 = gtk_combo_new ();
277 gtk_widget_show (hdr_combo2);
278 gtk_table_attach (GTK_TABLE (table1), hdr_combo2, 1, 2, 2, 3,
280 gtk_widget_set_usize (hdr_combo2, 96, -1);
281 gtkut_combo_set_items (GTK_COMBO (hdr_combo2), _("(none)"),
282 "Subject", "From", "To", "Cc", "Reply-To",
284 "X-ML-Name", "X-List", "X-Sequence", "X-Mailer",
287 key_label = gtk_label_new (_("Keyword"));
288 gtk_widget_show (key_label);
289 gtk_table_attach (GTK_TABLE (table1), key_label, 2, 3, 0, 1,
290 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
292 gtk_misc_set_alignment (GTK_MISC (key_label), 0, 0.5);
294 key_entry1 = gtk_entry_new ();
295 gtk_widget_show (key_entry1);
296 gtk_widget_set_usize (key_entry1, 128, -1);
297 gtk_table_attach (GTK_TABLE (table1), key_entry1, 2, 3, 1, 2,
298 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
301 key_entry2 = gtk_entry_new ();
302 gtk_widget_show (key_entry2);
303 gtk_widget_set_usize (key_entry2, 128, -1);
304 gtk_table_attach (GTK_TABLE (table1), key_entry2, 2, 3, 2, 3,
305 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
308 pred_label = gtk_label_new (_("Predicate"));
309 gtk_widget_show (pred_label);
310 gtk_table_attach (GTK_TABLE (table1), pred_label, 3, 4, 0, 1,
312 gtk_misc_set_alignment (GTK_MISC (pred_label), 0, 0.5);
314 pred_combo1 = gtk_combo_new ();
315 gtk_widget_show (pred_combo1);
316 gtk_table_attach (GTK_TABLE (table1), pred_combo1, 3, 4, 1, 2,
318 gtk_widget_set_usize (pred_combo1, 92, -1);
319 gtkut_combo_set_items (GTK_COMBO (pred_combo1),
320 _("contains"), _("not contain"), NULL);
322 pred_entry1 = GTK_COMBO (pred_combo1)->entry;
323 gtk_entry_set_editable (GTK_ENTRY (pred_entry1), FALSE);
325 pred_combo2 = gtk_combo_new ();
326 gtk_widget_show (pred_combo2);
327 gtk_table_attach (GTK_TABLE (table1), pred_combo2, 3, 4, 2, 3,
329 gtk_widget_set_usize (pred_combo2, 92, -1);
330 gtkut_combo_set_items (GTK_COMBO (pred_combo2),
331 _("contains"), _("not contain"), NULL);
333 pred_entry2 = GTK_COMBO (pred_combo2)->entry;
334 gtk_entry_set_editable (GTK_ENTRY (pred_entry2), FALSE);
338 vbox2 = gtk_vbox_new (FALSE, VSPACING_NARROW);
339 gtk_widget_show (vbox2);
340 gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, TRUE, 0);
342 dest_hbox = gtk_hbox_new (FALSE, 8);
343 gtk_widget_show (dest_hbox);
344 gtk_box_pack_start (GTK_BOX (vbox2), dest_hbox, FALSE, TRUE, 0);
347 gtk_radio_button_new_with_label (recv_group, _("Destination"));
348 recv_group = gtk_radio_button_group (GTK_RADIO_BUTTON (dest_radiobtn));
349 gtk_widget_show (dest_radiobtn);
350 gtk_box_pack_start (GTK_BOX (dest_hbox), dest_radiobtn,
352 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dest_radiobtn), TRUE);
354 (GTK_OBJECT (dest_radiobtn), "toggled",
355 GTK_SIGNAL_FUNC (prefs_filter_dest_radio_button_toggled),
358 dest_entry = gtk_entry_new ();
359 gtk_widget_show (dest_entry);
360 gtk_widget_set_usize (dest_entry, DEFAULT_ENTRY_WIDTH, -1);
361 gtk_box_pack_start (GTK_BOX (dest_hbox), dest_entry, TRUE, TRUE, 0);
362 gtk_entry_set_editable (GTK_ENTRY (dest_entry), FALSE);
364 destsel_btn = gtk_button_new_with_label (_(" Select... "));
365 gtk_widget_show (destsel_btn);
366 gtk_box_pack_start (GTK_BOX (dest_hbox), destsel_btn, FALSE, FALSE, 0);
367 gtk_signal_connect (GTK_OBJECT (destsel_btn), "clicked",
368 GTK_SIGNAL_FUNC (prefs_filter_select_dest_cb),
371 PACK_CHECK_BUTTON (dest_hbox, regex_chkbtn, _("Use regex"));
373 (GTK_OBJECT (regex_chkbtn), "toggled",
374 GTK_SIGNAL_FUNC (prefs_filter_regex_check_button_toggled),
377 notrecv_radiobtn = gtk_radio_button_new_with_label
378 (recv_group, _("Don't receive"));
379 recv_group = gtk_radio_button_group
380 (GTK_RADIO_BUTTON (notrecv_radiobtn));
381 gtk_widget_show (notrecv_radiobtn);
382 gtk_box_pack_start (GTK_BOX (vbox2), notrecv_radiobtn, FALSE, FALSE, 0);
384 (GTK_OBJECT (notrecv_radiobtn), "toggled",
385 GTK_SIGNAL_FUNC (prefs_filter_notrecv_radio_button_toggled),
388 /* register / substitute / delete */
390 reg_hbox = gtk_hbox_new (FALSE, 4);
391 gtk_widget_show (reg_hbox);
392 gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
394 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
395 gtk_widget_show (arrow);
396 gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
397 gtk_widget_set_usize (arrow, -1, 16);
399 btn_hbox = gtk_hbox_new (TRUE, 4);
400 gtk_widget_show (btn_hbox);
401 gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
403 reg_btn = gtk_button_new_with_label (_("Register"));
404 gtk_widget_show (reg_btn);
405 gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
406 gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
407 GTK_SIGNAL_FUNC (prefs_filter_register_cb), NULL);
409 subst_btn = gtk_button_new_with_label (_(" Substitute "));
410 gtk_widget_show (subst_btn);
411 gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
412 gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
413 GTK_SIGNAL_FUNC (prefs_filter_substitute_cb),
416 del_btn = gtk_button_new_with_label (_("Delete"));
417 gtk_widget_show (del_btn);
418 gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
419 gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
420 GTK_SIGNAL_FUNC (prefs_filter_delete_cb), NULL);
422 cond_hbox = gtk_hbox_new (FALSE, 8);
423 gtk_widget_show (cond_hbox);
424 gtk_box_pack_start (GTK_BOX (vbox1), cond_hbox, TRUE, TRUE, 0);
426 cond_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
427 gtk_widget_show (cond_scrolledwin);
428 gtk_widget_set_usize (cond_scrolledwin, -1, 150);
429 gtk_box_pack_start (GTK_BOX (cond_hbox), cond_scrolledwin,
431 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cond_scrolledwin),
432 GTK_POLICY_AUTOMATIC,
433 GTK_POLICY_AUTOMATIC);
435 title[0] = _("Registered rules");
436 cond_clist = gtk_clist_new_with_titles(1, title);
437 gtk_widget_show (cond_clist);
438 gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
439 gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
440 gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
441 GTK_SELECTION_BROWSE);
442 GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
444 gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
445 GTK_SIGNAL_FUNC (prefs_filter_select), NULL);
446 gtk_signal_connect_after (GTK_OBJECT (cond_clist), "row_move",
447 GTK_SIGNAL_FUNC (prefs_filter_row_move),
450 btn_vbox = gtk_vbox_new (FALSE, 8);
451 gtk_widget_show (btn_vbox);
452 gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
454 up_btn = gtk_button_new_with_label (_("Up"));
455 gtk_widget_show (up_btn);
456 gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
457 gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
458 GTK_SIGNAL_FUNC (prefs_filter_up), NULL);
460 down_btn = gtk_button_new_with_label (_("Down"));
461 gtk_widget_show (down_btn);
462 gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
463 gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
464 GTK_SIGNAL_FUNC (prefs_filter_down), NULL);
466 gtk_widget_show_all(window);
468 filter.window = window;
469 filter.ok_btn = ok_btn;
471 filter.hdr_combo1 = hdr_combo1;
472 filter.hdr_combo2 = hdr_combo2;
473 filter.hdr_entry1 = GTK_COMBO (hdr_combo1)->entry;
474 filter.hdr_entry2 = GTK_COMBO (hdr_combo2)->entry;
475 filter.key_entry1 = key_entry1;
476 filter.key_entry2 = key_entry2;
477 filter.pred_combo1 = pred_combo1;
478 filter.pred_combo2 = pred_combo2;
479 filter.pred_entry1 = pred_entry1;
480 filter.pred_entry2 = pred_entry2;
481 filter.cond_combo = cond_combo;
482 filter.cond_entry = cond_entry;
484 filter.dest_entry = dest_entry;
485 filter.destsel_btn = destsel_btn;
486 filter.dest_radiobtn = dest_radiobtn;
487 filter.notrecv_radiobtn = notrecv_radiobtn;
488 filter.regex_chkbtn = regex_chkbtn;
490 filter.cond_clist = cond_clist;
493 void prefs_filter_read_config(void)
497 gchar buf[PREFSBUFSIZE];
500 debug_print(_("Reading filter configuration...\n"));
502 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, FILTER_RC, NULL);
503 if ((fp = fopen(rcpath, "r")) == NULL) {
504 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
510 /* remove all previous filter list */
511 while (prefs_common.fltlist != NULL) {
512 flt = (Filter *)prefs_common.fltlist->data;
514 prefs_common.fltlist = g_slist_remove(prefs_common.fltlist,
518 while (fgets(buf, sizeof(buf), fp) != NULL) {
520 flt = filter_read_str(buf);
522 prefs_common.fltlist =
523 g_slist_append(prefs_common.fltlist, flt);
530 void prefs_filter_write_config(void)
536 debug_print(_("Writing filter configuration...\n"));
538 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, FILTER_RC, NULL);
539 if ((pfile = prefs_write_open(rcpath)) == NULL) {
540 g_warning(_("failed to write configuration to file\n"));
545 for (cur = prefs_common.fltlist; cur != NULL; cur = cur->next) {
546 Filter *flt = (Filter *)cur->data;
549 fstr = filter_get_str(flt);
550 if (fputs(fstr, pfile->fp) == EOF ||
551 fputc('\n', pfile->fp) == EOF) {
552 FILE_OP_ERROR(rcpath, "fputs || fputc");
553 prefs_write_close_revert(pfile);
563 if (prefs_write_close(pfile) < 0) {
564 g_warning(_("failed to write configuration to file\n"));
569 void prefs_filter_rename_path(const gchar *old_path, const gchar *new_path)
576 for (cur = prefs_common.fltlist; cur != NULL; cur = cur->next) {
577 Filter *flt = (Filter *)cur->data;
579 oldpathlen = strlen(old_path);
580 if (!strncmp(old_path, (gchar *)flt->dest, oldpathlen)) {
581 base = (gchar *)flt->dest + oldpathlen;
582 while (*base == G_DIR_SEPARATOR) base++;
584 dest_path = g_strdup(new_path);
586 dest_path = g_strconcat(new_path,
590 flt->dest = dest_path;
594 prefs_filter_write_config();
597 void prefs_filter_delete_path(const gchar *path)
603 for (cur = prefs_common.fltlist; cur != NULL; cur = next) {
604 Filter *flt = (Filter *)cur->data;
608 if (!strncmp(path, flt->dest, len)) {
610 prefs_common.fltlist =
611 g_slist_remove(prefs_common.fltlist, flt);
615 prefs_filter_write_config();
618 static void prefs_filter_set_dialog(const gchar *header, const gchar *key)
620 GtkCList *clist = GTK_CLIST(filter.cond_clist);
625 gtk_clist_freeze(clist);
626 gtk_clist_clear(clist);
628 cond_str[0] = _("(New)");
629 row = gtk_clist_append(clist, cond_str);
630 gtk_clist_set_row_data(clist, row, NULL);
632 for (cur = prefs_common.fltlist; cur != NULL; cur = cur->next) {
633 Filter *flt = (Filter *)cur->data;
635 cond_str[0] = filter_get_str(flt);
636 subst_char(cond_str[0], '\t', ':');
637 row = gtk_clist_append(clist, cond_str);
638 gtk_clist_set_row_data(clist, row, flt);
643 gtk_clist_thaw(clist);
646 gtk_entry_set_text(GTK_ENTRY(filter.hdr_entry1), header);
647 gtk_entry_set_text(GTK_ENTRY(filter.key_entry1), key);
651 static void prefs_filter_set_list(void)
656 g_slist_free(prefs_common.fltlist);
657 prefs_common.fltlist = NULL;
659 while ((flt = gtk_clist_get_row_data(GTK_CLIST(filter.cond_clist),
661 prefs_common.fltlist = g_slist_append(prefs_common.fltlist,
667 #define GET_ENTRY(entry) \
668 entry_text = gtk_entry_get_text(GTK_ENTRY(entry))
670 static gint prefs_filter_clist_set_row(gint row)
672 GtkCList *clist = GTK_CLIST(filter.cond_clist);
677 g_return_val_if_fail(row != 0, -1);
679 if (GTK_WIDGET_IS_SENSITIVE(filter.dest_entry))
680 GET_ENTRY(filter.dest_entry);
682 entry_text = FILTER_NOT_RECEIVE;
683 if (entry_text[0] == '\0') {
684 alertpanel_error(_("Destination is not set."));
687 GET_ENTRY(filter.hdr_entry1);
688 if (entry_text[0] == '\0') {
689 alertpanel_error(_("Header name is not set."));
693 flt = g_new0(Filter, 1);
695 flt->name1 = g_strdup(entry_text);
697 GET_ENTRY(filter.key_entry1);
698 if (entry_text[0] != '\0')
699 flt->body1 = g_strdup(entry_text);
701 GET_ENTRY(filter.hdr_entry2);
702 if (entry_text[0] != '\0' && strcmp(entry_text, _("(none)")) != 0) {
703 flt->name2 = g_strdup(entry_text);
705 GET_ENTRY(filter.key_entry2);
706 if (entry_text[0] != '\0')
707 flt->body2 = g_strdup(entry_text);
710 if (gtk_toggle_button_get_active
711 (GTK_TOGGLE_BUTTON(filter.regex_chkbtn)))
712 flt->flag1 = flt->flag2 = FLT_REGEX;
714 GET_ENTRY(filter.pred_entry1);
715 if (!strcmp(entry_text, _("contains")))
716 flt->flag1 |= FLT_CONTAIN;
717 GET_ENTRY(filter.pred_entry2);
718 if (!strcmp(entry_text, _("contains")))
719 flt->flag2 |= FLT_CONTAIN;
721 GET_ENTRY(filter.cond_entry);
722 if (!strcmp(entry_text, "and"))
727 if (GTK_WIDGET_IS_SENSITIVE(filter.dest_entry)) {
728 entry_text = gtk_entry_get_text(GTK_ENTRY(filter.dest_entry));
729 flt->dest = g_strdup(entry_text);
730 flt->action = FLT_MOVE;
732 flt->action = FLT_NOTRECV;
734 cond_str[0] = filter_get_str(flt);
735 subst_char(cond_str[0], '\t', ':');
738 row = gtk_clist_append(clist, cond_str);
742 gtk_clist_set_text(clist, row, 0, cond_str[0]);
743 tmpflt = gtk_clist_get_row_data(clist, row);
748 gtk_clist_set_row_data(clist, row, flt);
752 prefs_filter_set_list();
757 static void prefs_filter_select_dest_cb(void)
761 dest = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL);
764 gtk_entry_set_text(GTK_ENTRY(filter.dest_entry), dest->path);
767 static void prefs_filter_register_cb(void)
769 prefs_filter_clist_set_row(-1);
772 static void prefs_filter_substitute_cb(void)
774 GtkCList *clist = GTK_CLIST(filter.cond_clist);
778 if (!clist->selection) return;
780 row = GPOINTER_TO_INT(clist->selection->data);
781 if (row == 0) return;
783 flt = gtk_clist_get_row_data(clist, row);
786 prefs_filter_clist_set_row(row);
789 static void prefs_filter_delete_cb(void)
791 GtkCList *clist = GTK_CLIST(filter.cond_clist);
795 if (!clist->selection) return;
796 row = GPOINTER_TO_INT(clist->selection->data);
797 if (row == 0) return;
799 if (alertpanel(_("Delete rule"),
800 _("Do you really want to delete this rule?"),
801 _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
804 flt = gtk_clist_get_row_data(clist, row);
806 gtk_clist_remove(clist, row);
807 prefs_common.fltlist = g_slist_remove(prefs_common.fltlist, flt);
810 static void prefs_filter_up(void)
812 GtkCList *clist = GTK_CLIST(filter.cond_clist);
815 if (!clist->selection) return;
817 row = GPOINTER_TO_INT(clist->selection->data);
819 gtk_clist_row_move(clist, row, row - 1);
822 static void prefs_filter_down(void)
824 GtkCList *clist = GTK_CLIST(filter.cond_clist);
827 if (!clist->selection) return;
829 row = GPOINTER_TO_INT(clist->selection->data);
830 if (row > 0 && row < clist->rows - 1)
831 gtk_clist_row_move(clist, row, row + 1);
834 #define ENTRY_SET_TEXT(entry, str) \
835 gtk_entry_set_text(GTK_ENTRY(entry), str ? str : "")
837 static void prefs_filter_select(GtkCList *clist, gint row, gint column,
841 Filter default_flt = {"Subject", NULL, NULL, NULL,
842 FLT_CONTAIN, FLT_CONTAIN, FLT_AND,
846 default_flt.name2 = _("(none)");
848 flt = gtk_clist_get_row_data(clist, row);
852 ENTRY_SET_TEXT(filter.dest_entry, flt->dest);
853 ENTRY_SET_TEXT(filter.hdr_entry1, flt->name1);
854 ENTRY_SET_TEXT(filter.key_entry1, flt->body1);
855 ENTRY_SET_TEXT(filter.hdr_entry2,
856 flt->name2 ? flt->name2 : _("(none)"));
857 ENTRY_SET_TEXT(filter.key_entry2, flt->body2);
859 ENTRY_SET_TEXT(filter.pred_entry1,
860 FLT_IS_CONTAIN(flt->flag1)
861 ? _("contains") : _("not contain"));
862 ENTRY_SET_TEXT(filter.pred_entry2,
863 FLT_IS_CONTAIN(flt->flag2)
864 ? _("contains") : _("not contain"));
866 is_regex = FLT_IS_REGEX(flt->flag1);
867 gtk_widget_set_sensitive(filter.pred_combo1, !is_regex);
868 gtk_widget_set_sensitive(filter.pred_combo2, !is_regex);
869 gtk_toggle_button_set_active
870 (GTK_TOGGLE_BUTTON(filter.regex_chkbtn), is_regex);
872 gtk_entry_set_text(GTK_ENTRY(filter.cond_entry),
873 flt->cond == FLT_OR ? "or" : "and");
874 if (flt->action == FLT_NOTRECV)
875 gtk_toggle_button_set_active
876 (GTK_TOGGLE_BUTTON(filter.notrecv_radiobtn), TRUE);
878 gtk_toggle_button_set_active
879 (GTK_TOGGLE_BUTTON(filter.dest_radiobtn), TRUE);
882 static void prefs_filter_row_move(GtkCList *clist, gint source_row,
885 prefs_filter_set_list();
886 if (gtk_clist_row_is_visible(clist, dest_row) != GTK_VISIBILITY_FULL) {
887 gtk_clist_moveto(clist, dest_row, -1,
888 source_row < dest_row ? 1.0 : 0.0, 0.0);
892 static void prefs_filter_dest_radio_button_toggled(void)
894 gtk_widget_set_sensitive(filter.dest_entry, TRUE);
895 gtk_widget_set_sensitive(filter.destsel_btn, TRUE);
898 static void prefs_filter_notrecv_radio_button_toggled(void)
900 gtk_widget_set_sensitive(filter.dest_entry, FALSE);
901 gtk_widget_set_sensitive(filter.destsel_btn, FALSE);
904 static void prefs_filter_regex_check_button_toggled(void)
908 is_regex = gtk_toggle_button_get_active
909 (GTK_TOGGLE_BUTTON(filter.regex_chkbtn));
910 gtk_widget_set_sensitive(filter.pred_combo1, !is_regex);
911 gtk_widget_set_sensitive(filter.pred_combo2, !is_regex);
914 static gint prefs_filter_deleted(GtkWidget *widget, GdkEventAny *event,
917 prefs_filter_cancel();
921 static void prefs_filter_key_pressed(GtkWidget *widget, GdkEventKey *event,
924 if (event && event->keyval == GDK_Escape)
925 prefs_filter_cancel();
928 static void prefs_filter_ok(void)
930 prefs_filter_write_config();
931 gtk_widget_hide(filter.window);
935 static void prefs_filter_cancel(void)
937 prefs_filter_read_config();
938 gtk_widget_hide(filter.window);