0.9.3claws34
[claws.git] / src / prefs_scoring.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 <gdk/gdkkeysyms.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33
34 #include "intl.h"
35 #include "main.h"
36 #include "prefs_gtk.h"
37 #include "prefs_matcher.h"
38 #include "prefs_scoring.h"
39 #include "prefs_common.h"
40 #include "mainwindow.h"
41 #include "foldersel.h"
42 #include "manage_window.h"
43 #include "inc.h"
44 #include "utils.h"
45 #include "gtkutils.h"
46 #include "alertpanel.h"
47 #include "folder.h"
48 #include "scoring.h"
49
50 #include "matcher_parser.h"
51
52 static struct Scoring {
53         GtkWidget *window;
54
55         GtkWidget *ok_btn;
56         GtkWidget *cond_entry;
57         GtkWidget *score_entry;
58         GtkWidget *kill_score_label;
59         GtkWidget *kill_score_entry;
60         GtkWidget *important_score_entry;
61
62         GtkWidget *cond_clist;
63 } scoring;
64
65 /*
66    parameter name, default value, pointer to the prefs variable, data type,
67    pointer to the widget pointer,
68    pointer to the function for data setting,
69    pointer to the function for widget setting
70  */
71
72 /* widget creating functions */
73 static void prefs_scoring_create                (void);
74
75 static void prefs_scoring_set_dialog    (ScoringProp * prop);
76 static void prefs_scoring_set_list      (void);
77
78 /* callback functions */
79 /* static void prefs_scoring_select_dest_cb     (void); */
80 static void prefs_scoring_register_cb   (void);
81 static void prefs_scoring_substitute_cb (void);
82 static void prefs_scoring_delete_cb     (void);
83 static void prefs_scoring_up            (void);
84 static void prefs_scoring_down          (void);
85 static void prefs_scoring_select                (GtkCList       *clist,
86                                          gint            row,
87                                          gint            column,
88                                          GdkEvent       *event);
89
90 static gint prefs_scoring_deleted       (GtkWidget      *widget,
91                                          GdkEventAny    *event,
92                                          gpointer        data);
93 static void prefs_scoring_key_pressed   (GtkWidget      *widget,
94                                          GdkEventKey    *event,
95                                          gpointer        data);
96 static void prefs_scoring_cancel                (void);
97 static void prefs_scoring_ok            (void);
98
99 static void prefs_scoring_condition_define      (void);
100 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop);
101 static void prefs_scoring_select_set_dialog(ScoringProp * prop);
102 static void prefs_scoring_reset_dialog(void);
103
104
105 static FolderItem * cur_item = NULL;
106 static gint cur_important_score;
107 static gint cur_kill_score;
108
109 void prefs_scoring_open(FolderItem * item)
110 {
111         if (prefs_rc_is_readonly(SCORING_RC))
112                 return;
113
114         inc_lock();
115
116         if (!scoring.window) {
117                 prefs_scoring_create();
118         }
119
120         manage_window_set_transient(GTK_WINDOW(scoring.window));
121         gtk_widget_grab_focus(scoring.ok_btn);
122
123         cur_item = item;
124
125         prefs_scoring_set_dialog(NULL);
126
127         gtk_widget_show(scoring.window);
128 }
129
130 void prefs_scoring_open_with_scoring(ScoringProp * prop)
131 {
132         inc_lock();
133
134         if (!scoring.window) {
135                 prefs_scoring_create();
136         }
137
138         manage_window_set_transient(GTK_WINDOW(scoring.window));
139         gtk_widget_grab_focus(scoring.ok_btn);
140
141         prefs_scoring_set_dialog(prop);
142
143         gtk_widget_show(scoring.window);
144 }
145
146 static void prefs_scoring_create(void)
147 {
148         GtkWidget *window;
149         GtkWidget *vbox;
150         GtkWidget *ok_btn;
151         GtkWidget *cancel_btn;
152         GtkWidget *confirm_area;
153
154         GtkWidget *vbox1;
155         GtkWidget *hbox1;
156         GtkWidget *reg_hbox;
157         GtkWidget *arrow;
158         GtkWidget *btn_hbox;
159
160         GtkWidget *cond_label;
161         GtkWidget *cond_entry;
162         GtkWidget *cond_btn;
163         GtkWidget *score_label;
164         GtkWidget *score_entry;
165
166         GtkWidget *reg_btn;
167         GtkWidget *subst_btn;
168         GtkWidget *del_btn;
169
170         GtkWidget *cond_hbox;
171         GtkWidget *cond_scrolledwin;
172         GtkWidget *cond_clist;
173
174         GtkWidget *btn_vbox;
175         GtkWidget *up_btn;
176         GtkWidget *down_btn;
177
178         GtkWidget *important_score_entry;
179         GtkWidget *kill_score_entry;
180         GtkWidget *kill_score_label;
181
182         gchar *title[1];
183
184         debug_print("Creating scoring configuration window...\n");
185
186         window = gtk_window_new (GTK_WINDOW_DIALOG);
187         gtk_container_set_border_width (GTK_CONTAINER (window), 8);
188         gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
189         gtk_window_set_modal (GTK_WINDOW (window), TRUE);
190         gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
191
192         vbox = gtk_vbox_new (FALSE, 6);
193         gtk_widget_show (vbox);
194         gtk_container_add (GTK_CONTAINER (window), vbox);
195
196         gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
197                                 &cancel_btn, _("Cancel"), NULL, NULL);
198         gtk_widget_show (confirm_area);
199         gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
200         gtk_widget_grab_default (ok_btn);
201
202         gtk_window_set_title (GTK_WINDOW(window),
203                               _("Scoring configuration"));
204         gtk_signal_connect (GTK_OBJECT(window), "delete_event",
205                             GTK_SIGNAL_FUNC(prefs_scoring_deleted), NULL);
206         gtk_signal_connect (GTK_OBJECT(window), "key_press_event",
207                             GTK_SIGNAL_FUNC(prefs_scoring_key_pressed), NULL);
208         MANAGE_WINDOW_SIGNALS_CONNECT (window);
209         gtk_signal_connect (GTK_OBJECT(ok_btn), "clicked",
210                             GTK_SIGNAL_FUNC(prefs_scoring_ok), NULL);
211         gtk_signal_connect (GTK_OBJECT(cancel_btn), "clicked",
212                             GTK_SIGNAL_FUNC(prefs_scoring_cancel), NULL);
213
214         vbox1 = gtk_vbox_new (FALSE, VSPACING);
215         gtk_widget_show (vbox1);
216         gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
217         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
218
219         cond_label = gtk_label_new (_("Condition"));
220         gtk_widget_show (cond_label);
221         gtk_misc_set_alignment (GTK_MISC (cond_label), 0, 0.5);
222         gtk_box_pack_start (GTK_BOX (vbox1), cond_label, FALSE, FALSE, 0);
223
224         hbox1 = gtk_hbox_new (FALSE, VSPACING);
225         gtk_widget_show (vbox1);
226         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
227         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
228
229         cond_entry = gtk_entry_new ();
230         gtk_widget_show (cond_entry);
231         gtk_widget_set_usize (cond_entry, 300, -1);
232         gtk_box_pack_start (GTK_BOX (hbox1), cond_entry, TRUE, TRUE, 0);
233
234         cond_btn = gtk_button_new_with_label (_("Define ..."));
235         gtk_widget_show (cond_btn);
236         gtk_box_pack_start (GTK_BOX (hbox1), cond_btn, FALSE, FALSE, 0);
237         gtk_signal_connect (GTK_OBJECT (cond_btn), "clicked",
238                             GTK_SIGNAL_FUNC (prefs_scoring_condition_define),
239                             NULL);
240
241         hbox1 = gtk_hbox_new (FALSE, VSPACING);
242         gtk_widget_show (vbox1);
243         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
244         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
245
246         score_label = gtk_label_new (_("Score"));
247         gtk_widget_show (score_label);
248         gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
249         gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
250
251         score_entry = gtk_entry_new ();
252         gtk_widget_show (score_entry);
253         gtk_widget_set_usize (score_entry, 50, -1);
254         gtk_box_pack_start (GTK_BOX (hbox1), score_entry, FALSE, FALSE, 0);
255
256         /* register / substitute / delete */
257
258         reg_hbox = gtk_hbox_new (FALSE, 4);
259         gtk_widget_show (reg_hbox);
260         gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
261
262         arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
263         gtk_widget_show (arrow);
264         gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
265         gtk_widget_set_usize (arrow, -1, 16);
266
267         btn_hbox = gtk_hbox_new (TRUE, 4);
268         gtk_widget_show (btn_hbox);
269         gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
270
271         reg_btn = gtk_button_new_with_label (_("Add"));
272         gtk_widget_show (reg_btn);
273         gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
274         gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
275                             GTK_SIGNAL_FUNC (prefs_scoring_register_cb), NULL);
276
277         subst_btn = gtk_button_new_with_label (_("  Replace  "));
278         gtk_widget_show (subst_btn);
279         gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
280         gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
281                             GTK_SIGNAL_FUNC (prefs_scoring_substitute_cb),
282                             NULL);
283
284         del_btn = gtk_button_new_with_label (_("Delete"));
285         gtk_widget_show (del_btn);
286         gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
287         gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
288                             GTK_SIGNAL_FUNC (prefs_scoring_delete_cb), NULL);
289
290         cond_hbox = gtk_hbox_new (FALSE, 8);
291         gtk_widget_show (cond_hbox);
292         gtk_box_pack_start (GTK_BOX (vbox1), cond_hbox, TRUE, TRUE, 0);
293
294         cond_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
295         gtk_widget_show (cond_scrolledwin);
296         gtk_widget_set_usize (cond_scrolledwin, -1, 150);
297         gtk_box_pack_start (GTK_BOX (cond_hbox), cond_scrolledwin,
298                             TRUE, TRUE, 0);
299         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cond_scrolledwin),
300                                         GTK_POLICY_AUTOMATIC,
301                                         GTK_POLICY_AUTOMATIC);
302
303         title[0] = _("Current scoring rules");
304         cond_clist = gtk_clist_new_with_titles(1, title);
305         gtk_widget_show (cond_clist);
306         gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
307         gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
308         gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
309                                       GTK_SELECTION_BROWSE);
310         GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
311                                 GTK_CAN_FOCUS);
312         gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
313                             GTK_SIGNAL_FUNC (prefs_scoring_select), NULL);
314
315         btn_vbox = gtk_vbox_new (FALSE, 8);
316         gtk_widget_show (btn_vbox);
317         gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
318
319         up_btn = gtk_button_new_with_label (_("Up"));
320         gtk_widget_show (up_btn);
321         gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
322         gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
323                             GTK_SIGNAL_FUNC (prefs_scoring_up), NULL);
324
325         down_btn = gtk_button_new_with_label (_("Down"));
326         gtk_widget_show (down_btn);
327         gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
328         gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
329                             GTK_SIGNAL_FUNC (prefs_scoring_down), NULL);
330
331         hbox1 = gtk_hbox_new (FALSE, 8);
332         gtk_widget_show (hbox1);
333         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
334
335         kill_score_label = gtk_label_new (_("Hide score"));
336         gtk_widget_show (kill_score_label);
337         gtk_misc_set_alignment (GTK_MISC (kill_score_label), 0, 0.5);
338         gtk_box_pack_start (GTK_BOX (hbox1), kill_score_label,
339                             FALSE, FALSE, 0);
340
341         kill_score_entry = gtk_entry_new ();
342         gtk_widget_show (kill_score_entry);
343         gtk_widget_set_usize (kill_score_entry, 50, -1);
344         gtk_box_pack_start (GTK_BOX (hbox1), kill_score_entry,
345                             FALSE, FALSE, 0);
346
347         score_label = gtk_label_new (_("Important score"));
348         gtk_widget_show (score_label);
349         gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
350         gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
351
352         important_score_entry = gtk_entry_new ();
353         gtk_widget_show (important_score_entry);
354         gtk_widget_set_usize (important_score_entry, 50, -1);
355         gtk_box_pack_start (GTK_BOX (hbox1), important_score_entry,
356                             FALSE, FALSE, 0);
357
358         gtk_widget_show_all(window);
359
360         scoring.window    = window;
361         scoring.ok_btn = ok_btn;
362
363         scoring.cond_entry = cond_entry;
364         scoring.score_entry = score_entry;
365         scoring.kill_score_entry = kill_score_entry;
366         scoring.kill_score_label = kill_score_label;
367         scoring.important_score_entry = important_score_entry;
368
369         scoring.cond_clist   = cond_clist;
370 }
371
372 static void prefs_scoring_set_dialog(ScoringProp * cond)
373 {
374         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
375         GSList *cur;
376         GSList * prefs_scoring;
377         gchar * score_str;
378
379         if (cond == NULL)
380                 prefs_scoring_reset_dialog();
381         else
382                 prefs_scoring_select_set_dialog(cond);
383
384         gtk_clist_freeze(clist);
385         gtk_clist_clear(clist);
386
387         prefs_scoring_clist_set_row(-1, NULL);
388         if (cur_item == NULL) {
389                 prefs_scoring = global_scoring;
390                 cur_kill_score = prefs_common.kill_score;
391                 cur_important_score = prefs_common.important_score;
392                 gtk_widget_show(scoring.kill_score_label);
393                 gtk_widget_show(scoring.kill_score_entry);
394         } else {
395                 prefs_scoring = cur_item->prefs->scoring;
396                 cur_kill_score = cur_item->prefs->kill_score;
397                 cur_important_score = cur_item->prefs->important_score;
398         }
399
400         for(cur = prefs_scoring ; cur != NULL ;
401             cur = g_slist_next(cur)) {
402                 ScoringProp * prop = (ScoringProp *) cur->data;
403                 
404                 prefs_scoring_clist_set_row(-1, prop);
405         }
406
407         score_str = itos(cur_kill_score);
408         gtk_entry_set_text(GTK_ENTRY(scoring.kill_score_entry),
409                            score_str);
410         score_str = itos(cur_important_score);
411         gtk_entry_set_text(GTK_ENTRY(scoring.important_score_entry),
412                            score_str);
413
414         gtk_clist_thaw(clist);
415 }
416
417 static void prefs_scoring_reset_dialog(void)
418 {
419         gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), "");
420         gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), "");
421 }
422
423 static void prefs_scoring_set_list(void)
424 {
425         gint row = 1;
426         ScoringProp *prop;
427         GSList * cur;
428         gchar * scoring_str;
429         GSList * prefs_scoring;
430
431         if (cur_item == NULL)
432                 prefs_scoring = global_scoring;
433         else
434                 prefs_scoring = cur_item->prefs->scoring;
435
436         for(cur = prefs_scoring ; cur != NULL ;
437             cur = g_slist_next(cur))
438                 scoringprop_free((ScoringProp *) cur->data);
439         g_slist_free(prefs_scoring);
440         prefs_scoring = NULL;
441
442         while (gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
443                                   row, 0, &scoring_str)) {
444                 if (strcmp(scoring_str, _("(New)")) != 0) {
445                         prop = matcher_parser_get_scoring(scoring_str);
446                         if (prop != NULL)
447                                 prefs_scoring = g_slist_append(prefs_scoring,
448                                                                prop);
449                 }
450                 row++;
451         }
452
453         cur_kill_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.kill_score_entry)));
454         cur_important_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.important_score_entry)));
455
456         if (cur_item == NULL) {
457                 global_scoring = prefs_scoring;
458                 prefs_common.kill_score = cur_kill_score;
459                 prefs_common.important_score = cur_important_score;
460         }
461         else {
462                 cur_item->prefs->scoring = prefs_scoring;
463                 cur_item->prefs->kill_score = cur_kill_score;
464                 cur_item->prefs->important_score = cur_important_score;
465         }
466 }
467
468 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop)
469 {
470         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
471         gchar * str;
472         gchar *cond_str[1];
473
474         if (prop == NULL) {
475                 cond_str[0] = _("(New)");
476                 return gtk_clist_append(clist, cond_str);
477         }
478
479         str = scoringprop_to_string(prop);
480         if (str == NULL) {
481                 return -1;
482         }
483         cond_str[0] = str;
484
485         if (row < 0)
486                 row = gtk_clist_append(clist, cond_str);
487         else
488                 gtk_clist_set_text(clist, row, 0, cond_str[0]);
489         g_free(str);
490
491         return row;
492 }
493
494 static void prefs_scoring_condition_define_done(MatcherList * matchers)
495 {
496         gchar * str;
497
498         if (matchers == NULL)
499                 return;
500
501         str = matcherlist_to_string(matchers);
502
503         if (str != NULL) {
504                 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), str);
505                 g_free(str);
506         }
507 }
508
509 static void prefs_scoring_condition_define(void)
510 {
511         gchar * cond_str;
512         MatcherList * matchers = NULL;
513
514         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
515
516         if (*cond_str != '\0') {
517                 matchers = matcher_parser_get_cond(cond_str);
518                 if (matchers == NULL)
519                         alertpanel_error(_("Match string is not valid."));
520         }
521
522         prefs_matcher_open(matchers, prefs_scoring_condition_define_done);
523
524         if (matchers != NULL)
525                 matcherlist_free(matchers);
526 }
527
528
529 /* register / substitute delete buttons */
530
531 static void prefs_scoring_register_cb(void)
532 {
533         MatcherList * cond;
534         gchar * cond_str;
535         gchar * score_str;
536         ScoringProp * prop;
537         gint score;
538
539         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
540         if (*cond_str == '\0') {
541                 alertpanel_error(_("Condition string is empty."));
542                 return;
543         }
544
545         score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
546         if (*score_str == '\0') {
547                 alertpanel_error(_("Score is not set."));
548                 return;
549         }
550
551         score = atoi(score_str);
552         cond = matcher_parser_get_cond(cond_str);
553
554         if (cond == NULL) {
555                 alertpanel_error(_("Condition string is not valid."));
556                 return;
557         }
558
559         prop = scoringprop_new(cond, score);
560
561         prefs_scoring_clist_set_row(-1, prop);
562
563         scoringprop_free(prop);
564
565         prefs_scoring_reset_dialog();
566 }
567
568 static void prefs_scoring_substitute_cb(void)
569 {
570         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
571         gint row;
572         MatcherList * cond;
573         gchar * cond_str;
574         gchar * score_str;
575         ScoringProp * prop;
576         gint score;
577
578         if (!clist->selection) return;
579
580         row = GPOINTER_TO_INT(clist->selection->data);
581         if (row == 0) return;
582
583         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
584         if (*cond_str == '\0') {
585                 alertpanel_error(_("Condition string is empty."));
586                 return;
587         }
588
589         score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
590         if (*score_str == '\0') {
591                 alertpanel_error(_("Score is not set."));
592                 return;
593         }
594
595         score = atoi(score_str);
596         cond = matcher_parser_get_cond(cond_str);
597
598         if (cond == NULL) {
599                 alertpanel_error(_("Condition string is not valid."));
600                 return;
601         }
602
603         prop = scoringprop_new(cond, score);
604
605         prefs_scoring_clist_set_row(row, prop);
606
607         scoringprop_free(prop);
608
609         prefs_scoring_reset_dialog();
610 }
611
612 static void prefs_scoring_delete_cb(void)
613 {
614         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
615         gint row;
616
617         if (!clist->selection) return;
618         row = GPOINTER_TO_INT(clist->selection->data);
619         if (row == 0) return;
620
621         if (alertpanel(_("Delete rule"),
622                        _("Do you really want to delete this rule?"),
623                        _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
624                 return;
625
626         gtk_clist_remove(clist, row);
627 }
628
629 static void prefs_scoring_up(void)
630 {
631         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
632         gint row;
633
634         if (!clist->selection) return;
635
636         row = GPOINTER_TO_INT(clist->selection->data);
637         if (row > 1) {
638                 gtk_clist_row_move(clist, row, row - 1);
639                 if(gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL) {
640                         gtk_clist_moveto(clist, row - 1, 0, 0, 0);
641                 } 
642         }
643 }
644
645 static void prefs_scoring_down(void)
646 {
647         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
648         gint row;
649
650         if (!clist->selection) return;
651
652         row = GPOINTER_TO_INT(clist->selection->data);
653         if (row > 0 && row < clist->rows - 1) {
654                 gtk_clist_row_move(clist, row, row + 1);
655                 if(gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL) {
656                         gtk_clist_moveto(clist, row + 1, 0, 1, 0);
657                 } 
658         }
659 }
660
661 static void prefs_scoring_select_set_dialog(ScoringProp * prop)
662 {
663         gchar * matcher_str;
664         gchar * score_str;
665
666         if (prop == NULL)
667                 return;
668
669         matcher_str = matcherlist_to_string(prop->matchers);
670         if (matcher_str == NULL) {
671                 scoringprop_free(prop);
672                 return;
673         }
674
675         score_str = itos(prop->score);
676
677         gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), matcher_str);
678         gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
679
680         g_free(matcher_str);
681 }
682
683 static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
684                                 GdkEvent *event)
685 {
686         ScoringProp * prop;
687
688         gchar * scoring_str;
689
690         if (row == 0) {
691                 prefs_scoring_reset_dialog();
692                 return;
693         }
694
695         if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
696                                 row, 0, &scoring_str))
697                 return;
698
699         prop = matcher_parser_get_scoring(scoring_str);
700         if (prop == NULL)
701                 return;
702
703         prefs_scoring_select_set_dialog(prop);
704
705         scoringprop_free(prop);
706 }
707
708 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
709                                  gpointer data)
710 {
711         prefs_scoring_cancel();
712         return TRUE;
713 }
714
715 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
716                                      gpointer data)
717 {
718         if (event && event->keyval == GDK_Escape)
719                 prefs_scoring_cancel();
720 }
721
722 static void prefs_scoring_ok(void)
723 {
724         MatcherList * cond;
725         gchar * cond_str;
726         gchar * score_str;
727         gchar * scoring_str;
728         gchar * str;
729         ScoringProp * prop;
730         gint score;
731         gint row = 1;
732         AlertValue val;
733
734         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
735         score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
736         if (*cond_str != '\0' && *score_str != '\0') {
737                 score = atoi(score_str);
738                 cond = matcher_parser_get_cond(cond_str);
739
740                 if (cond == NULL) {
741                         prefs_common_save_config();
742                         prefs_scoring_set_list();
743                         prefs_matcher_write_config();
744                         if (cur_item != NULL)
745                                 folder_item_prefs_save_config(cur_item);
746                         gtk_widget_hide(scoring.window);
747                         inc_unlock();
748                         return;
749                 }
750                 prop = scoringprop_new(cond, score);
751                 str = scoringprop_to_string(prop);
752                 while (gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
753                                   row, 0, &scoring_str)) {
754                         if (strcmp(scoring_str, str) == 0) break;
755                         row++;
756                 }
757                 if (strcmp(scoring_str, str) != 0) {
758                         val = alertpanel(_("Entry not saved"),
759                                  _("The entry was not saved\nHave you really finished?"),
760                                  _("Yes"), _("No"), NULL);
761                         if (G_ALERTDEFAULT != val) {
762                                 g_free(str);
763                                 return;
764                         }
765                 }
766                 g_free(str);
767         }
768         prefs_common_save_config();
769         prefs_scoring_set_list();
770         prefs_matcher_write_config();
771         if (cur_item != NULL)
772                 folder_item_prefs_save_config(cur_item);
773         gtk_widget_hide(scoring.window);
774         inc_unlock();
775 }
776
777 static void prefs_scoring_cancel(void)
778 {
779         prefs_matcher_read_config();
780         gtk_widget_hide(scoring.window);
781         inc_unlock();
782 }