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