sync with 0.7.4cvs49
[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         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 (_("Register"));
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 (_(" Substitute "));
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] = ("Registered 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 (_("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                         prop = matcher_parser_get_scoring(scoring_str);
456                         if (prop != NULL)
457                                 prefs_scoring = g_slist_append(prefs_scoring,
458                                                                prop);
459                 }
460                 row++;
461         }
462
463         cur_kill_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.kill_score_entry)));
464         cur_important_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.important_score_entry)));
465
466         if (cur_item == NULL) {
467                 global_scoring = prefs_scoring;
468                 prefs_common.kill_score = cur_kill_score;
469                 prefs_common.important_score = cur_important_score;
470         }
471         else {
472                 cur_item->prefs->scoring = prefs_scoring;
473                 cur_item->prefs->kill_score = cur_kill_score;
474                 cur_item->prefs->important_score = cur_important_score;
475         }
476 }
477
478 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop)
479 {
480         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
481         gchar * str;
482         gchar *cond_str[1];
483
484         if (prop == NULL) {
485                 cond_str[0] = _("(New)");
486                 return gtk_clist_append(clist, cond_str);
487         }
488
489         str = scoringprop_to_string(prop);
490         if (str == NULL) {
491                 return -1;
492         }
493         cond_str[0] = str;
494
495         if (row < 0)
496                 row = gtk_clist_append(clist, cond_str);
497         else
498                 gtk_clist_set_text(clist, row, 0, cond_str[0]);
499         g_free(str);
500
501         return row;
502 }
503
504 static void prefs_scoring_condition_define_done(MatcherList * matchers)
505 {
506         gchar * str;
507
508         if (matchers == NULL)
509                 return;
510
511         str = matcherlist_to_string(matchers);
512
513         if (str != NULL) {
514                 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), str);
515                 g_free(str);
516         }
517 }
518
519 static void prefs_scoring_condition_define(void)
520 {
521         gchar * cond_str;
522         MatcherList * matchers = NULL;
523
524         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
525
526         if (*cond_str != '\0') {
527                 gchar * tmp;
528                 
529                 matchers = matcher_parser_get_cond(cond_str);
530                 if (matchers == NULL)
531                         alertpanel_error(_("Match string is not valid."));
532         }
533
534         prefs_matcher_open(matchers, prefs_scoring_condition_define_done);
535
536         if (matchers != NULL)
537                 matcherlist_free(matchers);
538 }
539
540
541 /* register / substitute delete buttons */
542
543 static void prefs_scoring_register_cb(void)
544 {
545         MatcherList * cond;
546         gchar * cond_str;
547         gchar * score_str;
548         ScoringProp * prop;
549         gint score;
550         gchar * tmp;
551
552         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
553         if (*cond_str == '\0') {
554                 alertpanel_error(_("Score is not set."));
555                 return;
556         }
557
558         score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
559         if (*score_str == '\0') {
560                 alertpanel_error(_("Match string is not set."));
561                 return;
562         }
563
564         score = atoi(score_str);
565         cond = matcher_parser_get_cond(cond_str);
566
567         if (cond == NULL) {
568                 alertpanel_error(_("Match string is not valid."));
569                 return;
570         }
571
572         prop = scoringprop_new(cond, score);
573
574         prefs_scoring_clist_set_row(-1, prop);
575
576         scoringprop_free(prop);
577
578         prefs_scoring_reset_dialog();
579 }
580
581 static void prefs_scoring_substitute_cb(void)
582 {
583         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
584         gint row;
585         MatcherList * cond;
586         gchar * cond_str;
587         gchar * score_str;
588         ScoringProp * prop;
589         gint score;
590         gchar * tmp;
591
592         if (!clist->selection) return;
593
594         row = GPOINTER_TO_INT(clist->selection->data);
595         if (row == 0) return;
596
597         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
598         if (*cond_str == '\0') {
599                 alertpanel_error(_("Score is not set."));
600                 return;
601         }
602
603         score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
604         if (*score_str == '\0') {
605                 alertpanel_error(_("Match string is not set."));
606                 return;
607         }
608
609         score = atoi(score_str);
610         cond = matcher_parser_get_cond(cond_str);
611
612         if (cond == NULL) {
613                 alertpanel_error(_("Match string is not valid."));
614                 return;
615         }
616
617         prop = scoringprop_new(cond, score);
618
619         prefs_scoring_clist_set_row(row, prop);
620
621         scoringprop_free(prop);
622
623         prefs_scoring_reset_dialog();
624 }
625
626 static void prefs_scoring_delete_cb(void)
627 {
628         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
629         gint row;
630
631         if (!clist->selection) return;
632         row = GPOINTER_TO_INT(clist->selection->data);
633         if (row == 0) return;
634
635         if (alertpanel(_("Delete rule"),
636                        _("Do you really want to delete this rule?"),
637                        _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
638                 return;
639
640         gtk_clist_remove(clist, row);
641 }
642
643 static void prefs_scoring_up(void)
644 {
645         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
646         gint row;
647
648         if (!clist->selection) return;
649
650         row = GPOINTER_TO_INT(clist->selection->data);
651         if (row > 1) {
652                 gtk_clist_row_move(clist, row, row - 1);
653                 if(gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL) {
654                         gtk_clist_moveto(clist, row - 1, 0, 0, 0);
655                 } 
656         }
657 }
658
659 static void prefs_scoring_down(void)
660 {
661         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
662         gint row;
663
664         if (!clist->selection) return;
665
666         row = GPOINTER_TO_INT(clist->selection->data);
667         if (row > 0 && row < clist->rows - 1) {
668                 gtk_clist_row_move(clist, row, row + 1);
669                 if(gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL) {
670                         gtk_clist_moveto(clist, row + 1, 0, 1, 0);
671                 } 
672         }
673 }
674
675 static void prefs_scoring_select_set_dialog(ScoringProp * prop)
676 {
677         gchar * matcher_str;
678         gchar * score_str;
679
680         if (prop == NULL)
681                 return;
682
683         matcher_str = matcherlist_to_string(prop->matchers);
684         if (matcher_str == NULL) {
685                 scoringprop_free(prop);
686                 return;
687         }
688
689         score_str = itos(prop->score);
690
691         gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), matcher_str);
692         gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
693
694         g_free(matcher_str);
695 }
696
697 static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
698                                 GdkEvent *event)
699 {
700         ScoringProp * prop;
701         gchar * tmp;
702
703         gchar * scoring_str;
704
705         if (row == 0) {
706                 prefs_scoring_reset_dialog();
707                 return;
708         }
709
710         if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
711                                 row, 0, &scoring_str))
712                 return;
713
714         prop = matcher_parser_get_scoring(scoring_str);
715         if (prop == NULL)
716                 return;
717
718         prefs_scoring_select_set_dialog(prop);
719
720         scoringprop_free(prop);
721 }
722
723 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
724                                  gpointer data)
725 {
726         prefs_scoring_cancel();
727         return TRUE;
728 }
729
730 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
731                                      gpointer data)
732 {
733         if (event && event->keyval == GDK_Escape)
734                 prefs_scoring_cancel();
735 }
736
737 static void prefs_scoring_ok(void)
738 {
739         prefs_common_save_config();
740         prefs_scoring_set_list();
741         prefs_matcher_write_config();
742         if (cur_item != NULL)
743                 prefs_folder_item_save_config(cur_item);
744         gtk_widget_hide(scoring.window);
745         inc_unlock();
746 }
747
748 static void prefs_scoring_cancel(void)
749 {
750         prefs_matcher_read_config();
751         gtk_widget_hide(scoring.window);
752         inc_unlock();
753 }