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