This commit was manufactured by cvs2svn to create tag 'LAST_STABLE'.
[claws.git] / src / prefs_filter.c
blobeace8b935b47de8bceed5bbf3b5ef867b0881536
1 /*
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.
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
24 #include "defs.h"
26 #include <glib.h>
27 #include <gtk/gtk.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
34 #include "intl.h"
35 #include "main.h"
36 #include "prefs.h"
37 #include "prefs_filter.h"
38 #include "prefs_common.h"
39 #include "mainwindow.h"
40 #include "foldersel.h"
41 #include "manage_window.h"
42 #include "inc.h"
43 #include "filter.h"
44 #include "utils.h"
45 #include "gtkutils.h"
46 #include "alertpanel.h"
47 #include "folder.h"
49 static struct Filter {
50 GtkWidget *window;
52 GtkWidget *ok_btn;
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;
75 } filter;
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,
88 const gchar *key);
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,
100 gint row,
101 gint column,
102 GdkEvent *event);
103 static void prefs_filter_row_move (GtkCList *clist,
104 gint source_row,
105 gint dest_row);
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,
112 GdkEventAny *event,
113 gpointer data);
114 static void prefs_filter_key_pressed (GtkWidget *widget,
115 GdkEventKey *event,
116 gpointer data);
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))
123 return;
125 inc_lock();
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)
141 GtkWidget *window;
142 GtkWidget *vbox;
143 GtkWidget *ok_btn;
144 GtkWidget *cancel_btn;
145 GtkWidget *confirm_area;
147 GtkWidget *vbox1;
148 GtkWidget *table1;
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;
164 GtkWidget *vbox2;
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;
174 GtkWidget *reg_hbox;
175 GtkWidget *btn_hbox;
176 GtkWidget *arrow;
177 GtkWidget *reg_btn;
178 GtkWidget *subst_btn;
179 GtkWidget *del_btn;
181 GtkWidget *cond_hbox;
182 GtkWidget *cond_scrolledwin;
183 GtkWidget *cond_clist;
185 GtkWidget *btn_vbox;
186 GtkWidget *up_btn;
187 GtkWidget *down_btn;
189 gchar *title[1];
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 MANAGE_WINDOW_SIGNALS_CONNECT (window);
224 gtk_signal_connect (GTK_OBJECT(ok_btn), "clicked",
225 GTK_SIGNAL_FUNC(prefs_filter_ok), NULL);
226 gtk_signal_connect (GTK_OBJECT(cancel_btn), "clicked",
227 GTK_SIGNAL_FUNC(prefs_filter_cancel), NULL);
229 vbox1 = gtk_vbox_new (FALSE, VSPACING);
230 gtk_widget_show (vbox1);
231 gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
232 gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
234 table1 = gtk_table_new (3, 4, FALSE);
235 gtk_widget_show (table1);
236 gtk_box_pack_start (GTK_BOX (vbox1), table1, FALSE, FALSE, 0);
237 gtk_table_set_row_spacings (GTK_TABLE (table1), 8);
238 gtk_table_set_col_spacings (GTK_TABLE (table1), 8);
240 cond_label = gtk_label_new (_("Condition"));
241 gtk_widget_show (cond_label);
242 gtk_table_attach (GTK_TABLE (table1), cond_label, 0, 1, 0, 1,
243 GTK_FILL, 0, 0, 0);
244 gtk_misc_set_alignment (GTK_MISC (cond_label), 0, 0.5);
246 cond_combo = gtk_combo_new ();
247 gtk_widget_show (cond_combo);
248 gtk_table_attach (GTK_TABLE (table1), cond_combo, 0, 1, 2, 3,
249 0, 0, 0, 0);
250 gtk_widget_set_usize (cond_combo, 52, -1);
251 gtkut_combo_set_items (GTK_COMBO (cond_combo), "and", "or", NULL);
253 cond_entry = GTK_COMBO (cond_combo)->entry;
254 gtk_entry_set_editable (GTK_ENTRY (cond_entry), FALSE);
256 hdr_label = gtk_label_new (_("Header"));
257 gtk_widget_show (hdr_label);
258 gtk_table_attach (GTK_TABLE (table1), hdr_label, 1, 2, 0, 1,
259 GTK_FILL, 0, 0, 0);
260 gtk_misc_set_alignment (GTK_MISC (hdr_label), 0, 0.5);
262 hdr_combo1 = gtk_combo_new ();
263 gtk_widget_show (hdr_combo1);
264 gtk_table_attach (GTK_TABLE (table1), hdr_combo1, 1, 2, 1, 2,
265 0, 0, 0, 0);
266 gtk_widget_set_usize (hdr_combo1, 96, -1);
267 gtkut_combo_set_items (GTK_COMBO (hdr_combo1),
268 "Subject", "From", "To", "Cc", "Reply-To",
269 "Sender", "List-Id",
270 "X-ML-Name", "X-List", "X-Sequence", "X-Mailer",
271 NULL);
273 hdr_combo2 = gtk_combo_new ();
274 gtk_widget_show (hdr_combo2);
275 gtk_table_attach (GTK_TABLE (table1), hdr_combo2, 1, 2, 2, 3,
276 0, 0, 0, 0);
277 gtk_widget_set_usize (hdr_combo2, 96, -1);
278 gtkut_combo_set_items (GTK_COMBO (hdr_combo2), _("(none)"),
279 "Subject", "From", "To", "Cc", "Reply-To",
280 "Sender", "List-Id",
281 "X-ML-Name", "X-List", "X-Sequence", "X-Mailer",
282 NULL);
284 key_label = gtk_label_new (_("Keyword"));
285 gtk_widget_show (key_label);
286 gtk_table_attach (GTK_TABLE (table1), key_label, 2, 3, 0, 1,
287 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
288 0, 0, 0);
289 gtk_misc_set_alignment (GTK_MISC (key_label), 0, 0.5);
291 key_entry1 = gtk_entry_new ();
292 gtk_widget_show (key_entry1);
293 gtk_widget_set_usize (key_entry1, 128, -1);
294 gtk_table_attach (GTK_TABLE (table1), key_entry1, 2, 3, 1, 2,
295 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
296 0, 0, 0);
298 key_entry2 = gtk_entry_new ();
299 gtk_widget_show (key_entry2);
300 gtk_widget_set_usize (key_entry2, 128, -1);
301 gtk_table_attach (GTK_TABLE (table1), key_entry2, 2, 3, 2, 3,
302 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
303 0, 0, 0);
305 pred_label = gtk_label_new (_("Predicate"));
306 gtk_widget_show (pred_label);
307 gtk_table_attach (GTK_TABLE (table1), pred_label, 3, 4, 0, 1,
308 GTK_FILL, 0, 0, 0);
309 gtk_misc_set_alignment (GTK_MISC (pred_label), 0, 0.5);
311 pred_combo1 = gtk_combo_new ();
312 gtk_widget_show (pred_combo1);
313 gtk_table_attach (GTK_TABLE (table1), pred_combo1, 3, 4, 1, 2,
314 0, 0, 0, 0);
315 gtk_widget_set_usize (pred_combo1, 92, -1);
316 gtkut_combo_set_items (GTK_COMBO (pred_combo1),
317 _("contains"), _("not contain"), NULL);
319 pred_entry1 = GTK_COMBO (pred_combo1)->entry;
320 gtk_entry_set_editable (GTK_ENTRY (pred_entry1), FALSE);
322 pred_combo2 = gtk_combo_new ();
323 gtk_widget_show (pred_combo2);
324 gtk_table_attach (GTK_TABLE (table1), pred_combo2, 3, 4, 2, 3,
325 0, 0, 0, 0);
326 gtk_widget_set_usize (pred_combo2, 92, -1);
327 gtkut_combo_set_items (GTK_COMBO (pred_combo2),
328 _("contains"), _("not contain"), NULL);
330 pred_entry2 = GTK_COMBO (pred_combo2)->entry;
331 gtk_entry_set_editable (GTK_ENTRY (pred_entry2), FALSE);
333 /* destination */
335 vbox2 = gtk_vbox_new (FALSE, VSPACING_NARROW);
336 gtk_widget_show (vbox2);
337 gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, TRUE, 0);
339 dest_hbox = gtk_hbox_new (FALSE, 8);
340 gtk_widget_show (dest_hbox);
341 gtk_box_pack_start (GTK_BOX (vbox2), dest_hbox, FALSE, TRUE, 0);
343 dest_radiobtn =
344 gtk_radio_button_new_with_label (recv_group, _("Destination"));
345 recv_group = gtk_radio_button_group (GTK_RADIO_BUTTON (dest_radiobtn));
346 gtk_widget_show (dest_radiobtn);
347 gtk_box_pack_start (GTK_BOX (dest_hbox), dest_radiobtn,
348 FALSE, FALSE, 0);
349 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dest_radiobtn), TRUE);
350 gtk_signal_connect
351 (GTK_OBJECT (dest_radiobtn), "toggled",
352 GTK_SIGNAL_FUNC (prefs_filter_dest_radio_button_toggled),
353 NULL);
355 dest_entry = gtk_entry_new ();
356 gtk_widget_show (dest_entry);
357 gtk_widget_set_usize (dest_entry, DEFAULT_ENTRY_WIDTH, -1);
358 gtk_box_pack_start (GTK_BOX (dest_hbox), dest_entry, TRUE, TRUE, 0);
359 gtk_entry_set_editable (GTK_ENTRY (dest_entry), FALSE);
361 destsel_btn = gtk_button_new_with_label (_(" Select... "));
362 gtk_widget_show (destsel_btn);
363 gtk_box_pack_start (GTK_BOX (dest_hbox), destsel_btn, FALSE, FALSE, 0);
364 gtk_signal_connect (GTK_OBJECT (destsel_btn), "clicked",
365 GTK_SIGNAL_FUNC (prefs_filter_select_dest_cb),
366 NULL);
368 PACK_CHECK_BUTTON (dest_hbox, regex_chkbtn, _("Use regex"));
369 gtk_signal_connect
370 (GTK_OBJECT (regex_chkbtn), "toggled",
371 GTK_SIGNAL_FUNC (prefs_filter_regex_check_button_toggled),
372 NULL);
374 notrecv_radiobtn = gtk_radio_button_new_with_label
375 (recv_group, _("Don't receive"));
376 recv_group = gtk_radio_button_group
377 (GTK_RADIO_BUTTON (notrecv_radiobtn));
378 gtk_widget_show (notrecv_radiobtn);
379 gtk_box_pack_start (GTK_BOX (vbox2), notrecv_radiobtn, FALSE, FALSE, 0);
380 gtk_signal_connect
381 (GTK_OBJECT (notrecv_radiobtn), "toggled",
382 GTK_SIGNAL_FUNC (prefs_filter_notrecv_radio_button_toggled),
383 NULL);
385 /* register / substitute / delete */
387 reg_hbox = gtk_hbox_new (FALSE, 4);
388 gtk_widget_show (reg_hbox);
389 gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
391 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
392 gtk_widget_show (arrow);
393 gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
394 gtk_widget_set_usize (arrow, -1, 16);
396 btn_hbox = gtk_hbox_new (TRUE, 4);
397 gtk_widget_show (btn_hbox);
398 gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
400 reg_btn = gtk_button_new_with_label (_("Register"));
401 gtk_widget_show (reg_btn);
402 gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
403 gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
404 GTK_SIGNAL_FUNC (prefs_filter_register_cb), NULL);
406 subst_btn = gtk_button_new_with_label (_(" Substitute "));
407 gtk_widget_show (subst_btn);
408 gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
409 gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
410 GTK_SIGNAL_FUNC (prefs_filter_substitute_cb),
411 NULL);
413 del_btn = gtk_button_new_with_label (_("Delete"));
414 gtk_widget_show (del_btn);
415 gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
416 gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
417 GTK_SIGNAL_FUNC (prefs_filter_delete_cb), NULL);
419 cond_hbox = gtk_hbox_new (FALSE, 8);
420 gtk_widget_show (cond_hbox);
421 gtk_box_pack_start (GTK_BOX (vbox1), cond_hbox, TRUE, TRUE, 0);
423 cond_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
424 gtk_widget_show (cond_scrolledwin);
425 gtk_widget_set_usize (cond_scrolledwin, -1, 150);
426 gtk_box_pack_start (GTK_BOX (cond_hbox), cond_scrolledwin,
427 TRUE, TRUE, 0);
428 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cond_scrolledwin),
429 GTK_POLICY_AUTOMATIC,
430 GTK_POLICY_AUTOMATIC);
432 title[0] = _("Registered rules");
433 cond_clist = gtk_clist_new_with_titles(1, title);
434 gtk_widget_show (cond_clist);
435 gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
436 gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
437 gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
438 GTK_SELECTION_BROWSE);
439 GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
440 GTK_CAN_FOCUS);
441 gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
442 GTK_SIGNAL_FUNC (prefs_filter_select), NULL);
443 gtk_signal_connect_after (GTK_OBJECT (cond_clist), "row_move",
444 GTK_SIGNAL_FUNC (prefs_filter_row_move),
445 NULL);
447 btn_vbox = gtk_vbox_new (FALSE, 8);
448 gtk_widget_show (btn_vbox);
449 gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
451 up_btn = gtk_button_new_with_label (_("Up"));
452 gtk_widget_show (up_btn);
453 gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
454 gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
455 GTK_SIGNAL_FUNC (prefs_filter_up), NULL);
457 down_btn = gtk_button_new_with_label (_("Down"));
458 gtk_widget_show (down_btn);
459 gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
460 gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
461 GTK_SIGNAL_FUNC (prefs_filter_down), NULL);
463 gtk_widget_show_all(window);
465 filter.window = window;
466 filter.ok_btn = ok_btn;
468 filter.hdr_combo1 = hdr_combo1;
469 filter.hdr_combo2 = hdr_combo2;
470 filter.hdr_entry1 = GTK_COMBO (hdr_combo1)->entry;
471 filter.hdr_entry2 = GTK_COMBO (hdr_combo2)->entry;
472 filter.key_entry1 = key_entry1;
473 filter.key_entry2 = key_entry2;
474 filter.pred_combo1 = pred_combo1;
475 filter.pred_combo2 = pred_combo2;
476 filter.pred_entry1 = pred_entry1;
477 filter.pred_entry2 = pred_entry2;
478 filter.cond_combo = cond_combo;
479 filter.cond_entry = cond_entry;
481 filter.dest_entry = dest_entry;
482 filter.destsel_btn = destsel_btn;
483 filter.dest_radiobtn = dest_radiobtn;
484 filter.notrecv_radiobtn = notrecv_radiobtn;
485 filter.regex_chkbtn = regex_chkbtn;
487 filter.cond_clist = cond_clist;
490 void prefs_filter_read_config(void)
492 gchar *rcpath;
493 FILE *fp;
494 gchar buf[PREFSBUFSIZE];
495 Filter *flt;
497 debug_print(_("Reading filter configuration...\n"));
499 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, FILTER_RC, NULL);
500 if ((fp = fopen(rcpath, "rb")) == NULL) {
501 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
502 g_free(rcpath);
503 return;
505 g_free(rcpath);
507 /* remove all previous filter list */
508 while (prefs_common.fltlist != NULL) {
509 flt = (Filter *)prefs_common.fltlist->data;
510 filter_free(flt);
511 prefs_common.fltlist = g_slist_remove(prefs_common.fltlist,
512 flt);
515 while (fgets(buf, sizeof(buf), fp) != NULL) {
516 g_strchomp(buf);
517 flt = filter_read_str(buf);
518 if (flt) {
519 prefs_common.fltlist =
520 g_slist_append(prefs_common.fltlist, flt);
524 fclose(fp);
527 void prefs_filter_write_config(void)
529 gchar *rcpath;
530 PrefFile *pfile;
531 GSList *cur;
533 debug_print(_("Writing filter configuration...\n"));
535 rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, FILTER_RC, NULL);
536 if ((pfile = prefs_write_open(rcpath)) == NULL) {
537 g_warning(_("failed to write configuration to file\n"));
538 g_free(rcpath);
539 return;
542 for (cur = prefs_common.fltlist; cur != NULL; cur = cur->next) {
543 Filter *flt = (Filter *)cur->data;
544 gchar *fstr;
546 fstr = filter_get_str(flt);
547 if (fputs(fstr, pfile->fp) == EOF ||
548 fputc('\n', pfile->fp) == EOF) {
549 FILE_OP_ERROR(rcpath, "fputs || fputc");
550 prefs_write_close_revert(pfile);
551 g_free(rcpath);
552 g_free(fstr);
553 return;
555 g_free(fstr);
558 g_free(rcpath);
560 if (prefs_write_close(pfile) < 0) {
561 g_warning(_("failed to write configuration to file\n"));
562 return;
566 void prefs_filter_rename_path(const gchar *old_path, const gchar *new_path)
568 GSList *cur;
569 gchar *base;
570 gchar *dest_path;
571 gint oldpathlen;
573 g_return_if_fail(old_path != NULL);
574 g_return_if_fail(new_path != NULL);
576 for (cur = prefs_common.fltlist; cur != NULL; cur = cur->next) {
577 Filter *flt = (Filter *)cur->data;
579 oldpathlen = strlen(old_path);
580 if (flt->dest && !strncmp(old_path, flt->dest, oldpathlen)) {
581 base = flt->dest + oldpathlen;
582 while (*base == G_DIR_SEPARATOR) base++;
583 if (*base == '\0')
584 dest_path = g_strdup(new_path);
585 else
586 dest_path = g_strconcat(new_path,
587 G_DIR_SEPARATOR_S,
588 base, NULL);
589 g_free(flt->dest);
590 flt->dest = dest_path;
594 prefs_filter_write_config();
597 void prefs_filter_delete_path(const gchar *path)
599 GSList *cur;
600 GSList *next;
602 g_return_if_fail(path != NULL);
604 for (cur = prefs_common.fltlist; cur != NULL; cur = next) {
605 Filter *flt = (Filter *)cur->data;
606 next = cur->next;
608 if (flt->dest && !strncmp(path, flt->dest, strlen(path))) {
609 filter_free(flt);
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);
621 GSList *cur;
622 gchar *cond_str[1];
623 gint row;
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);
640 g_free(cond_str[0]);
643 gtk_clist_thaw(clist);
645 if (header && key) {
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)
653 gint row = 1;
654 Filter *flt;
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),
660 row)) != NULL) {
661 prefs_common.fltlist = g_slist_append(prefs_common.fltlist,
662 flt);
663 row++;
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);
673 Filter *flt;
674 gchar *entry_text;
675 gchar *cond_str[1];
677 g_return_val_if_fail(row != 0, -1);
679 if (GTK_WIDGET_IS_SENSITIVE(filter.dest_entry))
680 GET_ENTRY(filter.dest_entry);
681 else
682 entry_text = FILTER_NOT_RECEIVE;
683 if (entry_text[0] == '\0') {
684 alertpanel_error(_("Destination is not set."));
685 return -1;
687 GET_ENTRY(filter.hdr_entry1);
688 if (entry_text[0] == '\0') {
689 alertpanel_error(_("Header name is not set."));
690 return -1;
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"))
723 flt->cond = FLT_AND;
724 else
725 flt->cond = FLT_OR;
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;
731 } else
732 flt->action = FLT_NOTRECV;
734 cond_str[0] = filter_get_str(flt);
735 subst_char(cond_str[0], '\t', ':');
737 if (row < 0)
738 row = gtk_clist_append(clist, cond_str);
739 else {
740 Filter *tmpflt;
742 gtk_clist_set_text(clist, row, 0, cond_str[0]);
743 tmpflt = gtk_clist_get_row_data(clist, row);
744 if (tmpflt)
745 filter_free(tmpflt);
748 gtk_clist_set_row_data(clist, row, flt);
750 g_free(cond_str[0]);
752 prefs_filter_set_list();
754 return row;
757 static void prefs_filter_select_dest_cb(void)
759 FolderItem *dest;
760 gchar *id;
762 dest = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL);
763 if (!dest || !dest->path) return;
765 id = folder_item_get_identifier(dest);
766 if (id) {
767 gtk_entry_set_text(GTK_ENTRY(filter.dest_entry), id);
768 g_free(id);
772 static void prefs_filter_register_cb(void)
774 GtkCList *clist = GTK_CLIST(filter.cond_clist);
775 gint row;
777 row = prefs_filter_clist_set_row(-1);
778 if (gtk_clist_row_is_visible(clist, row) != GTK_VISIBILITY_FULL)
779 gtk_clist_moveto(clist, row, -1, 0.5, 0);
780 gtk_clist_select_row(clist, row, -1);
781 gtkut_clist_set_focus_row(clist, row);
784 static void prefs_filter_substitute_cb(void)
786 GtkCList *clist = GTK_CLIST(filter.cond_clist);
787 Filter *flt;
788 gint row;
790 if (!clist->selection) return;
792 row = GPOINTER_TO_INT(clist->selection->data);
793 if (row == 0) return;
795 flt = gtk_clist_get_row_data(clist, row);
796 if (!flt) return;
798 prefs_filter_clist_set_row(row);
801 static void prefs_filter_delete_cb(void)
803 GtkCList *clist = GTK_CLIST(filter.cond_clist);
804 Filter *flt;
805 gint row;
807 if (!clist->selection) return;
808 row = GPOINTER_TO_INT(clist->selection->data);
809 if (row == 0) return;
811 if (alertpanel(_("Delete rule"),
812 _("Do you really want to delete this rule?"),
813 _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
814 return;
816 flt = gtk_clist_get_row_data(clist, row);
817 filter_free(flt);
818 gtk_clist_remove(clist, row);
819 prefs_common.fltlist = g_slist_remove(prefs_common.fltlist, flt);
822 static void prefs_filter_up(void)
824 GtkCList *clist = GTK_CLIST(filter.cond_clist);
825 gint row;
827 if (!clist->selection) return;
829 row = GPOINTER_TO_INT(clist->selection->data);
830 if (row > 1)
831 gtk_clist_row_move(clist, row, row - 1);
834 static void prefs_filter_down(void)
836 GtkCList *clist = GTK_CLIST(filter.cond_clist);
837 gint row;
839 if (!clist->selection) return;
841 row = GPOINTER_TO_INT(clist->selection->data);
842 if (row > 0 && row < clist->rows - 1)
843 gtk_clist_row_move(clist, row, row + 1);
846 #define ENTRY_SET_TEXT(entry, str) \
847 gtk_entry_set_text(GTK_ENTRY(entry), str ? str : "")
849 static void prefs_filter_select(GtkCList *clist, gint row, gint column,
850 GdkEvent *event)
852 Filter *flt;
853 Filter default_flt = {"Subject", NULL, NULL, NULL,
854 FLT_CONTAIN, FLT_CONTAIN, FLT_AND,
855 NULL, FLT_MOVE};
856 gboolean is_regex;
858 default_flt.name2 = _("(none)");
860 flt = gtk_clist_get_row_data(clist, row);
861 if (!flt)
862 flt = &default_flt;
864 ENTRY_SET_TEXT(filter.dest_entry, flt->dest);
865 ENTRY_SET_TEXT(filter.hdr_entry1, flt->name1);
866 ENTRY_SET_TEXT(filter.key_entry1, flt->body1);
867 ENTRY_SET_TEXT(filter.hdr_entry2,
868 flt->name2 ? flt->name2 : _("(none)"));
869 ENTRY_SET_TEXT(filter.key_entry2, flt->body2);
871 ENTRY_SET_TEXT(filter.pred_entry1,
872 FLT_IS_CONTAIN(flt->flag1)
873 ? _("contains") : _("not contain"));
874 ENTRY_SET_TEXT(filter.pred_entry2,
875 FLT_IS_CONTAIN(flt->flag2)
876 ? _("contains") : _("not contain"));
878 is_regex = FLT_IS_REGEX(flt->flag1);
879 gtk_widget_set_sensitive(filter.pred_combo1, !is_regex);
880 gtk_widget_set_sensitive(filter.pred_combo2, !is_regex);
881 gtk_toggle_button_set_active
882 (GTK_TOGGLE_BUTTON(filter.regex_chkbtn), is_regex);
884 gtk_entry_set_text(GTK_ENTRY(filter.cond_entry),
885 flt->cond == FLT_OR ? "or" : "and");
886 if (flt->action == FLT_NOTRECV)
887 gtk_toggle_button_set_active
888 (GTK_TOGGLE_BUTTON(filter.notrecv_radiobtn), TRUE);
889 else
890 gtk_toggle_button_set_active
891 (GTK_TOGGLE_BUTTON(filter.dest_radiobtn), TRUE);
894 static void prefs_filter_row_move(GtkCList *clist, gint source_row,
895 gint dest_row)
897 prefs_filter_set_list();
898 if (gtk_clist_row_is_visible(clist, dest_row) != GTK_VISIBILITY_FULL) {
899 gtk_clist_moveto(clist, dest_row, -1,
900 source_row < dest_row ? 1.0 : 0.0, 0.0);
904 static void prefs_filter_dest_radio_button_toggled(void)
906 gtk_widget_set_sensitive(filter.dest_entry, TRUE);
907 gtk_widget_set_sensitive(filter.destsel_btn, TRUE);
910 static void prefs_filter_notrecv_radio_button_toggled(void)
912 gtk_widget_set_sensitive(filter.dest_entry, FALSE);
913 gtk_widget_set_sensitive(filter.destsel_btn, FALSE);
916 static void prefs_filter_regex_check_button_toggled(void)
918 gboolean is_regex;
920 is_regex = gtk_toggle_button_get_active
921 (GTK_TOGGLE_BUTTON(filter.regex_chkbtn));
922 gtk_widget_set_sensitive(filter.pred_combo1, !is_regex);
923 gtk_widget_set_sensitive(filter.pred_combo2, !is_regex);
926 static gint prefs_filter_deleted(GtkWidget *widget, GdkEventAny *event,
927 gpointer data)
929 prefs_filter_cancel();
930 return TRUE;
933 static void prefs_filter_key_pressed(GtkWidget *widget, GdkEventKey *event,
934 gpointer data)
936 if (event && event->keyval == GDK_Escape)
937 prefs_filter_cancel();
940 static void prefs_filter_ok(void)
942 prefs_filter_write_config();
943 gtk_widget_hide(filter.window);
944 inc_unlock();
947 static void prefs_filter_cancel(void)
949 prefs_filter_read_config();
950 gtk_widget_hide(filter.window);
951 inc_unlock();