make toolbar refresh smoother
[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 #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 setting 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 setting"));
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         gtk_signal_connect (GTK_OBJECT(window), "focus_in_event",
209                             GTK_SIGNAL_FUNC(manage_window_focus_in), NULL);
210         gtk_signal_connect (GTK_OBJECT(window), "focus_out_event",
211                             GTK_SIGNAL_FUNC(manage_window_focus_out), NULL);
212         gtk_signal_connect (GTK_OBJECT(ok_btn), "clicked",
213                             GTK_SIGNAL_FUNC(prefs_scoring_ok), NULL);
214         gtk_signal_connect (GTK_OBJECT(cancel_btn), "clicked",
215                             GTK_SIGNAL_FUNC(prefs_scoring_cancel), NULL);
216
217         vbox1 = gtk_vbox_new (FALSE, VSPACING);
218         gtk_widget_show (vbox1);
219         gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
220         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
221
222         cond_label = gtk_label_new (_("Condition"));
223         gtk_widget_show (cond_label);
224         gtk_misc_set_alignment (GTK_MISC (cond_label), 0, 0.5);
225         gtk_box_pack_start (GTK_BOX (vbox1), cond_label, FALSE, FALSE, 0);
226
227         hbox1 = gtk_hbox_new (FALSE, VSPACING);
228         gtk_widget_show (vbox1);
229         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
230         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
231
232         cond_entry = gtk_entry_new ();
233         gtk_widget_show (cond_entry);
234         gtk_widget_set_usize (cond_entry, 300, -1);
235         gtk_box_pack_start (GTK_BOX (hbox1), cond_entry, TRUE, TRUE, 0);
236
237         cond_btn = gtk_button_new_with_label (_("Define ..."));
238         gtk_widget_show (cond_btn);
239         gtk_box_pack_start (GTK_BOX (hbox1), cond_btn, FALSE, FALSE, 0);
240         gtk_signal_connect (GTK_OBJECT (cond_btn), "clicked",
241                             GTK_SIGNAL_FUNC (prefs_scoring_condition_define),
242                             NULL);
243
244         hbox1 = gtk_hbox_new (FALSE, VSPACING);
245         gtk_widget_show (vbox1);
246         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
247         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
248
249         score_label = gtk_label_new (_("Score"));
250         gtk_widget_show (score_label);
251         gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
252         gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
253
254         score_entry = gtk_entry_new ();
255         gtk_widget_show (score_entry);
256         gtk_widget_set_usize (score_entry, 50, -1);
257         gtk_box_pack_start (GTK_BOX (hbox1), score_entry, FALSE, FALSE, 0);
258
259         /* register / substitute / delete */
260
261         reg_hbox = gtk_hbox_new (FALSE, 4);
262         gtk_widget_show (reg_hbox);
263         gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
264
265         arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
266         gtk_widget_show (arrow);
267         gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
268         gtk_widget_set_usize (arrow, -1, 16);
269
270         btn_hbox = gtk_hbox_new (TRUE, 4);
271         gtk_widget_show (btn_hbox);
272         gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
273
274         reg_btn = gtk_button_new_with_label (_("Register"));
275         gtk_widget_show (reg_btn);
276         gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
277         gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
278                             GTK_SIGNAL_FUNC (prefs_scoring_register_cb), NULL);
279
280         subst_btn = gtk_button_new_with_label (_(" Substitute "));
281         gtk_widget_show (subst_btn);
282         gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
283         gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
284                             GTK_SIGNAL_FUNC (prefs_scoring_substitute_cb),
285                             NULL);
286
287         del_btn = gtk_button_new_with_label (_("Delete"));
288         gtk_widget_show (del_btn);
289         gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
290         gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
291                             GTK_SIGNAL_FUNC (prefs_scoring_delete_cb), NULL);
292
293         cond_hbox = gtk_hbox_new (FALSE, 8);
294         gtk_widget_show (cond_hbox);
295         gtk_box_pack_start (GTK_BOX (vbox1), cond_hbox, TRUE, TRUE, 0);
296
297         cond_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
298         gtk_widget_show (cond_scrolledwin);
299         gtk_widget_set_usize (cond_scrolledwin, -1, 150);
300         gtk_box_pack_start (GTK_BOX (cond_hbox), cond_scrolledwin,
301                             TRUE, TRUE, 0);
302         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cond_scrolledwin),
303                                         GTK_POLICY_AUTOMATIC,
304                                         GTK_POLICY_AUTOMATIC);
305
306         title[0] = ("Registered rules");
307         cond_clist = gtk_clist_new_with_titles(1, title);
308         gtk_widget_show (cond_clist);
309         gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
310         gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
311         gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
312                                       GTK_SELECTION_BROWSE);
313         GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
314                                 GTK_CAN_FOCUS);
315         gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
316                             GTK_SIGNAL_FUNC (prefs_scoring_select), NULL);
317
318         btn_vbox = gtk_vbox_new (FALSE, 8);
319         gtk_widget_show (btn_vbox);
320         gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
321
322         up_btn = gtk_button_new_with_label (_("Up"));
323         gtk_widget_show (up_btn);
324         gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
325         gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
326                             GTK_SIGNAL_FUNC (prefs_scoring_up), NULL);
327
328         down_btn = gtk_button_new_with_label (_("Down"));
329         gtk_widget_show (down_btn);
330         gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
331         gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
332                             GTK_SIGNAL_FUNC (prefs_scoring_down), NULL);
333
334         hbox1 = gtk_hbox_new (FALSE, 8);
335         gtk_widget_show (hbox1);
336         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
337
338         kill_score_label = gtk_label_new (_("Kill score"));
339         gtk_widget_show (kill_score_label);
340         gtk_misc_set_alignment (GTK_MISC (kill_score_label), 0, 0.5);
341         gtk_box_pack_start (GTK_BOX (hbox1), kill_score_label,
342                             FALSE, FALSE, 0);
343
344         kill_score_entry = gtk_entry_new ();
345         gtk_widget_show (kill_score_entry);
346         gtk_widget_set_usize (kill_score_entry, 50, -1);
347         gtk_box_pack_start (GTK_BOX (hbox1), kill_score_entry,
348                             FALSE, FALSE, 0);
349
350         score_label = gtk_label_new (_("Important score"));
351         gtk_widget_show (score_label);
352         gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
353         gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
354
355         important_score_entry = gtk_entry_new ();
356         gtk_widget_show (important_score_entry);
357         gtk_widget_set_usize (important_score_entry, 50, -1);
358         gtk_box_pack_start (GTK_BOX (hbox1), important_score_entry,
359                             FALSE, FALSE, 0);
360
361         gtk_widget_show_all(window);
362
363         scoring.window    = window;
364         scoring.ok_btn = ok_btn;
365
366         scoring.cond_entry = cond_entry;
367         scoring.score_entry = score_entry;
368         scoring.kill_score_entry = kill_score_entry;
369         scoring.kill_score_label = kill_score_label;
370         scoring.important_score_entry = important_score_entry;
371
372         scoring.cond_clist   = cond_clist;
373 }
374
375 static void prefs_scoring_set_dialog(ScoringProp * cond)
376 {
377         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
378         GSList *cur;
379         GSList * prefs_scoring;
380         gchar * score_str;
381
382         if (cond == NULL)
383                 prefs_scoring_reset_dialog();
384         else
385                 prefs_scoring_select_set_dialog(cond);
386
387         gtk_clist_freeze(clist);
388         gtk_clist_clear(clist);
389
390         prefs_scoring_clist_set_row(-1, NULL);
391         if (cur_item == NULL) {
392                 prefs_scoring = global_scoring;
393                 cur_kill_score = prefs_common.kill_score;
394                 cur_important_score = prefs_common.important_score;
395                 gtk_widget_show(scoring.kill_score_label);
396                 gtk_widget_show(scoring.kill_score_entry);
397         }
398         else {
399                 prefs_scoring = cur_item->prefs->scoring;
400                 cur_kill_score = cur_item->prefs->kill_score;
401                 cur_important_score = cur_item->prefs->important_score;
402                 if (cur_item->folder->type != F_NEWS) {
403                         gtk_widget_hide(scoring.kill_score_label);
404                         gtk_widget_hide(scoring.kill_score_entry);
405                 }
406                 else {
407                         gtk_widget_show(scoring.kill_score_label);
408                         gtk_widget_show(scoring.kill_score_entry);
409                 }
410         }
411
412         for(cur = prefs_scoring ; cur != NULL ;
413             cur = g_slist_next(cur)) {
414                 ScoringProp * prop = (ScoringProp *) cur->data;
415                 
416                 prefs_scoring_clist_set_row(-1, prop);
417         }
418
419         score_str = itos(cur_kill_score);
420         gtk_entry_set_text(GTK_ENTRY(scoring.kill_score_entry),
421                            score_str);
422         score_str = itos(cur_important_score);
423         gtk_entry_set_text(GTK_ENTRY(scoring.important_score_entry),
424                            score_str);
425
426         gtk_clist_thaw(clist);
427 }
428
429 static void prefs_scoring_reset_dialog(void)
430 {
431         gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), "");
432         gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), "");
433 }
434
435 static void prefs_scoring_set_list(void)
436 {
437         gint row = 1;
438         ScoringProp *prop;
439         GSList * cur;
440         gchar * scoring_str;
441         gchar * tmp;
442         GSList * prefs_scoring;
443
444         if (cur_item == NULL)
445                 prefs_scoring = global_scoring;
446         else
447                 prefs_scoring = cur_item->prefs->scoring;
448
449         for(cur = prefs_scoring ; cur != NULL ;
450             cur = g_slist_next(cur))
451                 scoringprop_free((ScoringProp *) cur->data);
452         g_slist_free(prefs_scoring);
453         prefs_scoring = NULL;
454
455         while (gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
456                                   row, 0, &scoring_str)) {
457                 if (strcmp(scoring_str, _("(New)")) != 0) {
458                         prop = matcher_parser_get_scoring(scoring_str);
459                         if (prop != NULL)
460                                 prefs_scoring = g_slist_append(prefs_scoring,
461                                                                prop);
462                 }
463                 row++;
464         }
465
466         cur_kill_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.kill_score_entry)));
467         cur_important_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.important_score_entry)));
468
469         if (cur_item == NULL) {
470                 global_scoring = prefs_scoring;
471                 prefs_common.kill_score = cur_kill_score;
472                 prefs_common.important_score = cur_important_score;
473         }
474         else {
475                 cur_item->prefs->scoring = prefs_scoring;
476                 cur_item->prefs->kill_score = cur_kill_score;
477                 cur_item->prefs->important_score = cur_important_score;
478         }
479 }
480
481 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop)
482 {
483         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
484         gchar * str;
485         gchar *cond_str[1];
486
487         if (prop == NULL) {
488                 cond_str[0] = _("(New)");
489                 return gtk_clist_append(clist, cond_str);
490         }
491
492         str = scoringprop_to_string(prop);
493         if (str == NULL) {
494                 return -1;
495         }
496         cond_str[0] = str;
497
498         if (row < 0)
499                 row = gtk_clist_append(clist, cond_str);
500         else
501                 gtk_clist_set_text(clist, row, 0, cond_str[0]);
502         g_free(str);
503
504         return row;
505 }
506
507 static void prefs_scoring_condition_define_done(MatcherList * matchers)
508 {
509         gchar * str;
510
511         if (matchers == NULL)
512                 return;
513
514         str = matcherlist_to_string(matchers);
515
516         if (str != NULL) {
517                 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), str);
518                 g_free(str);
519         }
520 }
521
522 static void prefs_scoring_condition_define(void)
523 {
524         gchar * cond_str;
525         MatcherList * matchers = NULL;
526
527         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
528
529         if (*cond_str != '\0') {
530                 gchar * tmp;
531                 
532                 matchers = matcher_parser_get_cond(cond_str);
533                 if (matchers == NULL)
534                         alertpanel_error(_("Match string is not valid."));
535         }
536
537         prefs_matcher_open(matchers, prefs_scoring_condition_define_done);
538
539         if (matchers != NULL)
540                 matcherlist_free(matchers);
541 }
542
543
544 /* register / substitute delete buttons */
545
546 static void prefs_scoring_register_cb(void)
547 {
548         MatcherList * cond;
549         gchar * cond_str;
550         gchar * score_str;
551         ScoringProp * prop;
552         gint score;
553         gchar * tmp;
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         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         cond = matcher_parser_get_cond(cond_str);
614
615         if (cond == NULL) {
616                 alertpanel_error(_("Match string is not valid."));
617                 return;
618         }
619
620         prop = scoringprop_new(cond, score);
621
622         prefs_scoring_clist_set_row(row, prop);
623
624         scoringprop_free(prop);
625
626         prefs_scoring_reset_dialog();
627 }
628
629 static void prefs_scoring_delete_cb(void)
630 {
631         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
632         gint row;
633
634         if (!clist->selection) return;
635         row = GPOINTER_TO_INT(clist->selection->data);
636         if (row == 0) return;
637
638         if (alertpanel(_("Delete rule"),
639                        _("Do you really want to delete this rule?"),
640                        _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
641                 return;
642
643         gtk_clist_remove(clist, row);
644 }
645
646 static void prefs_scoring_up(void)
647 {
648         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
649         gint row;
650
651         if (!clist->selection) return;
652
653         row = GPOINTER_TO_INT(clist->selection->data);
654         if (row > 1) {
655                 gtk_clist_row_move(clist, row, row - 1);
656                 if(gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL) {
657                         gtk_clist_moveto(clist, row - 1, 0, 0, 0);
658                 } 
659         }
660 }
661
662 static void prefs_scoring_down(void)
663 {
664         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
665         gint row;
666
667         if (!clist->selection) return;
668
669         row = GPOINTER_TO_INT(clist->selection->data);
670         if (row > 0 && row < clist->rows - 1) {
671                 gtk_clist_row_move(clist, row, row + 1);
672                 if(gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL) {
673                         gtk_clist_moveto(clist, row + 1, 0, 1, 0);
674                 } 
675         }
676 }
677
678 static void prefs_scoring_select_set_dialog(ScoringProp * prop)
679 {
680         gchar * matcher_str;
681         gchar * score_str;
682
683         if (prop == NULL)
684                 return;
685
686         matcher_str = matcherlist_to_string(prop->matchers);
687         if (matcher_str == NULL) {
688                 scoringprop_free(prop);
689                 return;
690         }
691
692         score_str = itos(prop->score);
693
694         gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), matcher_str);
695         gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
696
697         g_free(matcher_str);
698 }
699
700 static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
701                                 GdkEvent *event)
702 {
703         ScoringProp * prop;
704         gchar * tmp;
705
706         gchar * scoring_str;
707
708         if (row == 0) {
709                 prefs_scoring_reset_dialog();
710                 return;
711         }
712
713         if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
714                                 row, 0, &scoring_str))
715                 return;
716
717         prop = matcher_parser_get_scoring(scoring_str);
718         if (prop == NULL)
719                 return;
720
721         prefs_scoring_select_set_dialog(prop);
722
723         scoringprop_free(prop);
724 }
725
726 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
727                                  gpointer data)
728 {
729         prefs_scoring_cancel();
730         return TRUE;
731 }
732
733 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
734                                      gpointer data)
735 {
736         if (event && event->keyval == GDK_Escape)
737                 prefs_scoring_cancel();
738 }
739
740 static void prefs_scoring_ok(void)
741 {
742         prefs_common_save_config();
743         prefs_scoring_set_list();
744         prefs_matcher_write_config();
745         if (cur_item != NULL)
746                 prefs_folder_item_save_config(cur_item);
747         gtk_widget_hide(scoring.window);
748         inc_unlock();
749 }
750
751 static void prefs_scoring_cancel(void)
752 {
753         prefs_matcher_read_config();
754         gtk_widget_hide(scoring.window);
755         inc_unlock();
756 }