029902f70f8f632b68e94d8374d6984da9858882
[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 configuration window...\n");
185
186         window = gtk_window_new (GTK_WINDOW_DIALOG);
187         gtk_container_set_border_width (GTK_CONTAINER (window), 8);
188         gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
189         gtk_window_set_modal (GTK_WINDOW (window), TRUE);
190         gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
191
192         vbox = gtk_vbox_new (FALSE, 6);
193         gtk_widget_show (vbox);
194         gtk_container_add (GTK_CONTAINER (window), vbox);
195
196         gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
197                                 &cancel_btn, _("Cancel"), NULL, NULL);
198         gtk_widget_show (confirm_area);
199         gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
200         gtk_widget_grab_default (ok_btn);
201
202         gtk_window_set_title (GTK_WINDOW(window),
203                               _("Scoring configuration"));
204         gtk_signal_connect (GTK_OBJECT(window), "delete_event",
205                             GTK_SIGNAL_FUNC(prefs_scoring_deleted), NULL);
206         gtk_signal_connect (GTK_OBJECT(window), "key_press_event",
207                             GTK_SIGNAL_FUNC(prefs_scoring_key_pressed), NULL);
208         MANAGE_WINDOW_SIGNALS_CONNECT (window);
209         gtk_signal_connect (GTK_OBJECT(ok_btn), "clicked",
210                             GTK_SIGNAL_FUNC(prefs_scoring_ok), NULL);
211         gtk_signal_connect (GTK_OBJECT(cancel_btn), "clicked",
212                             GTK_SIGNAL_FUNC(prefs_scoring_cancel), NULL);
213
214         vbox1 = gtk_vbox_new (FALSE, VSPACING);
215         gtk_widget_show (vbox1);
216         gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
217         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
218
219         cond_label = gtk_label_new (_("Condition"));
220         gtk_widget_show (cond_label);
221         gtk_misc_set_alignment (GTK_MISC (cond_label), 0, 0.5);
222         gtk_box_pack_start (GTK_BOX (vbox1), cond_label, FALSE, FALSE, 0);
223
224         hbox1 = gtk_hbox_new (FALSE, VSPACING);
225         gtk_widget_show (vbox1);
226         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
227         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
228
229         cond_entry = gtk_entry_new ();
230         gtk_widget_show (cond_entry);
231         gtk_widget_set_usize (cond_entry, 300, -1);
232         gtk_box_pack_start (GTK_BOX (hbox1), cond_entry, TRUE, TRUE, 0);
233
234         cond_btn = gtk_button_new_with_label (_("Define ..."));
235         gtk_widget_show (cond_btn);
236         gtk_box_pack_start (GTK_BOX (hbox1), cond_btn, FALSE, FALSE, 0);
237         gtk_signal_connect (GTK_OBJECT (cond_btn), "clicked",
238                             GTK_SIGNAL_FUNC (prefs_scoring_condition_define),
239                             NULL);
240
241         hbox1 = gtk_hbox_new (FALSE, VSPACING);
242         gtk_widget_show (vbox1);
243         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, FALSE, 0);
244         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
245
246         score_label = gtk_label_new (_("Score"));
247         gtk_widget_show (score_label);
248         gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
249         gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
250
251         score_entry = gtk_entry_new ();
252         gtk_widget_show (score_entry);
253         gtk_widget_set_usize (score_entry, 50, -1);
254         gtk_box_pack_start (GTK_BOX (hbox1), score_entry, FALSE, FALSE, 0);
255
256         /* register / substitute / delete */
257
258         reg_hbox = gtk_hbox_new (FALSE, 4);
259         gtk_widget_show (reg_hbox);
260         gtk_box_pack_start (GTK_BOX (vbox1), reg_hbox, FALSE, FALSE, 0);
261
262         arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
263         gtk_widget_show (arrow);
264         gtk_box_pack_start (GTK_BOX (reg_hbox), arrow, FALSE, FALSE, 0);
265         gtk_widget_set_usize (arrow, -1, 16);
266
267         btn_hbox = gtk_hbox_new (TRUE, 4);
268         gtk_widget_show (btn_hbox);
269         gtk_box_pack_start (GTK_BOX (reg_hbox), btn_hbox, FALSE, FALSE, 0);
270
271         reg_btn = gtk_button_new_with_label (_("Add"));
272         gtk_widget_show (reg_btn);
273         gtk_box_pack_start (GTK_BOX (btn_hbox), reg_btn, FALSE, TRUE, 0);
274         gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
275                             GTK_SIGNAL_FUNC (prefs_scoring_register_cb), NULL);
276
277         subst_btn = gtk_button_new_with_label (_("  Replace  "));
278         gtk_widget_show (subst_btn);
279         gtk_box_pack_start (GTK_BOX (btn_hbox), subst_btn, FALSE, TRUE, 0);
280         gtk_signal_connect (GTK_OBJECT (subst_btn), "clicked",
281                             GTK_SIGNAL_FUNC (prefs_scoring_substitute_cb),
282                             NULL);
283
284         del_btn = gtk_button_new_with_label (_("Delete"));
285         gtk_widget_show (del_btn);
286         gtk_box_pack_start (GTK_BOX (btn_hbox), del_btn, FALSE, TRUE, 0);
287         gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
288                             GTK_SIGNAL_FUNC (prefs_scoring_delete_cb), NULL);
289
290         cond_hbox = gtk_hbox_new (FALSE, 8);
291         gtk_widget_show (cond_hbox);
292         gtk_box_pack_start (GTK_BOX (vbox1), cond_hbox, TRUE, TRUE, 0);
293
294         cond_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
295         gtk_widget_show (cond_scrolledwin);
296         gtk_widget_set_usize (cond_scrolledwin, -1, 150);
297         gtk_box_pack_start (GTK_BOX (cond_hbox), cond_scrolledwin,
298                             TRUE, TRUE, 0);
299         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cond_scrolledwin),
300                                         GTK_POLICY_AUTOMATIC,
301                                         GTK_POLICY_AUTOMATIC);
302
303         title[0] = _("Current scoring rules");
304         cond_clist = gtk_clist_new_with_titles(1, title);
305         gtk_widget_show (cond_clist);
306         gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
307         gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
308         gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
309                                       GTK_SELECTION_BROWSE);
310         GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
311                                 GTK_CAN_FOCUS);
312         gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
313                             GTK_SIGNAL_FUNC (prefs_scoring_select), NULL);
314
315         btn_vbox = gtk_vbox_new (FALSE, 8);
316         gtk_widget_show (btn_vbox);
317         gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
318
319         up_btn = gtk_button_new_with_label (_("Up"));
320         gtk_widget_show (up_btn);
321         gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
322         gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
323                             GTK_SIGNAL_FUNC (prefs_scoring_up), NULL);
324
325         down_btn = gtk_button_new_with_label (_("Down"));
326         gtk_widget_show (down_btn);
327         gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
328         gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
329                             GTK_SIGNAL_FUNC (prefs_scoring_down), NULL);
330
331         hbox1 = gtk_hbox_new (FALSE, 8);
332         gtk_widget_show (hbox1);
333         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
334
335         kill_score_label = gtk_label_new (_("Hide score"));
336         gtk_widget_show (kill_score_label);
337         gtk_misc_set_alignment (GTK_MISC (kill_score_label), 0, 0.5);
338         gtk_box_pack_start (GTK_BOX (hbox1), kill_score_label,
339                             FALSE, FALSE, 0);
340
341         kill_score_entry = gtk_entry_new ();
342         gtk_widget_show (kill_score_entry);
343         gtk_widget_set_usize (kill_score_entry, 50, -1);
344         gtk_box_pack_start (GTK_BOX (hbox1), kill_score_entry,
345                             FALSE, FALSE, 0);
346
347         score_label = gtk_label_new (_("Important score"));
348         gtk_widget_show (score_label);
349         gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
350         gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
351
352         important_score_entry = gtk_entry_new ();
353         gtk_widget_show (important_score_entry);
354         gtk_widget_set_usize (important_score_entry, 50, -1);
355         gtk_box_pack_start (GTK_BOX (hbox1), important_score_entry,
356                             FALSE, FALSE, 0);
357
358         gtk_widget_show_all(window);
359
360         scoring.window    = window;
361         scoring.ok_btn = ok_btn;
362
363         scoring.cond_entry = cond_entry;
364         scoring.score_entry = score_entry;
365         scoring.kill_score_entry = kill_score_entry;
366         scoring.kill_score_label = kill_score_label;
367         scoring.important_score_entry = important_score_entry;
368
369         scoring.cond_clist   = cond_clist;
370 }
371
372 static void prefs_scoring_set_dialog(ScoringProp * cond)
373 {
374         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
375         GSList *cur;
376         GSList * prefs_scoring;
377         gchar * score_str;
378
379         if (cond == NULL)
380                 prefs_scoring_reset_dialog();
381         else
382                 prefs_scoring_select_set_dialog(cond);
383
384         gtk_clist_freeze(clist);
385         gtk_clist_clear(clist);
386
387         prefs_scoring_clist_set_row(-1, NULL);
388         if (cur_item == NULL) {
389                 prefs_scoring = global_scoring;
390                 cur_kill_score = prefs_common.kill_score;
391                 cur_important_score = prefs_common.important_score;
392                 gtk_widget_show(scoring.kill_score_label);
393                 gtk_widget_show(scoring.kill_score_entry);
394         }
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         GSList * prefs_scoring;
439
440         if (cur_item == NULL)
441                 prefs_scoring = global_scoring;
442         else
443                 prefs_scoring = cur_item->prefs->scoring;
444
445         for(cur = prefs_scoring ; cur != NULL ;
446             cur = g_slist_next(cur))
447                 scoringprop_free((ScoringProp *) cur->data);
448         g_slist_free(prefs_scoring);
449         prefs_scoring = NULL;
450
451         while (gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
452                                   row, 0, &scoring_str)) {
453                 if (strcmp(scoring_str, _("(New)")) != 0) {
454                         prop = matcher_parser_get_scoring(scoring_str);
455                         if (prop != NULL)
456                                 prefs_scoring = g_slist_append(prefs_scoring,
457                                                                prop);
458                 }
459                 row++;
460         }
461
462         cur_kill_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.kill_score_entry)));
463         cur_important_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.important_score_entry)));
464
465         if (cur_item == NULL) {
466                 global_scoring = prefs_scoring;
467                 prefs_common.kill_score = cur_kill_score;
468                 prefs_common.important_score = cur_important_score;
469         }
470         else {
471                 cur_item->prefs->scoring = prefs_scoring;
472                 cur_item->prefs->kill_score = cur_kill_score;
473                 cur_item->prefs->important_score = cur_important_score;
474         }
475 }
476
477 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop)
478 {
479         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
480         gchar * str;
481         gchar *cond_str[1];
482
483         if (prop == NULL) {
484                 cond_str[0] = _("(New)");
485                 return gtk_clist_append(clist, cond_str);
486         }
487
488         str = scoringprop_to_string(prop);
489         if (str == NULL) {
490                 return -1;
491         }
492         cond_str[0] = str;
493
494         if (row < 0)
495                 row = gtk_clist_append(clist, cond_str);
496         else
497                 gtk_clist_set_text(clist, row, 0, cond_str[0]);
498         g_free(str);
499
500         return row;
501 }
502
503 static void prefs_scoring_condition_define_done(MatcherList * matchers)
504 {
505         gchar * str;
506
507         if (matchers == NULL)
508                 return;
509
510         str = matcherlist_to_string(matchers);
511
512         if (str != NULL) {
513                 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), str);
514                 g_free(str);
515         }
516 }
517
518 static void prefs_scoring_condition_define(void)
519 {
520         gchar * cond_str;
521         MatcherList * matchers = NULL;
522
523         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
524
525         if (*cond_str != '\0') {
526                 matchers = matcher_parser_get_cond(cond_str);
527                 if (matchers == NULL)
528                         alertpanel_error(_("Match string is not valid."));
529         }
530
531         prefs_matcher_open(matchers, prefs_scoring_condition_define_done);
532
533         if (matchers != NULL)
534                 matcherlist_free(matchers);
535 }
536
537
538 /* register / substitute delete buttons */
539
540 static void prefs_scoring_register_cb(void)
541 {
542         MatcherList * cond;
543         gchar * cond_str;
544         gchar * score_str;
545         ScoringProp * prop;
546         gint score;
547
548         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
549         if (*cond_str == '\0') {
550                 alertpanel_error(_("Condition string is empty."));
551                 return;
552         }
553
554         score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
555         if (*score_str == '\0') {
556                 alertpanel_error(_("Score is not set."));
557                 return;
558         }
559
560         score = atoi(score_str);
561         cond = matcher_parser_get_cond(cond_str);
562
563         if (cond == NULL) {
564                 alertpanel_error(_("Condition string is not valid."));
565                 return;
566         }
567
568         prop = scoringprop_new(cond, score);
569
570         prefs_scoring_clist_set_row(-1, prop);
571
572         scoringprop_free(prop);
573
574         prefs_scoring_reset_dialog();
575 }
576
577 static void prefs_scoring_substitute_cb(void)
578 {
579         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
580         gint row;
581         MatcherList * cond;
582         gchar * cond_str;
583         gchar * score_str;
584         ScoringProp * prop;
585         gint score;
586
587         if (!clist->selection) return;
588
589         row = GPOINTER_TO_INT(clist->selection->data);
590         if (row == 0) return;
591
592         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
593         if (*cond_str == '\0') {
594                 alertpanel_error(_("Condition string is empty."));
595                 return;
596         }
597
598         score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
599         if (*score_str == '\0') {
600                 alertpanel_error(_("Score is not set."));
601                 return;
602         }
603
604         score = atoi(score_str);
605         cond = matcher_parser_get_cond(cond_str);
606
607         if (cond == NULL) {
608                 alertpanel_error(_("Condition string is not valid."));
609                 return;
610         }
611
612         prop = scoringprop_new(cond, score);
613
614         prefs_scoring_clist_set_row(row, prop);
615
616         scoringprop_free(prop);
617
618         prefs_scoring_reset_dialog();
619 }
620
621 static void prefs_scoring_delete_cb(void)
622 {
623         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
624         gint row;
625
626         if (!clist->selection) return;
627         row = GPOINTER_TO_INT(clist->selection->data);
628         if (row == 0) return;
629
630         if (alertpanel(_("Delete rule"),
631                        _("Do you really want to delete this rule?"),
632                        _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
633                 return;
634
635         gtk_clist_remove(clist, row);
636 }
637
638 static void prefs_scoring_up(void)
639 {
640         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
641         gint row;
642
643         if (!clist->selection) return;
644
645         row = GPOINTER_TO_INT(clist->selection->data);
646         if (row > 1) {
647                 gtk_clist_row_move(clist, row, row - 1);
648                 if(gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL) {
649                         gtk_clist_moveto(clist, row - 1, 0, 0, 0);
650                 } 
651         }
652 }
653
654 static void prefs_scoring_down(void)
655 {
656         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
657         gint row;
658
659         if (!clist->selection) return;
660
661         row = GPOINTER_TO_INT(clist->selection->data);
662         if (row > 0 && row < clist->rows - 1) {
663                 gtk_clist_row_move(clist, row, row + 1);
664                 if(gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL) {
665                         gtk_clist_moveto(clist, row + 1, 0, 1, 0);
666                 } 
667         }
668 }
669
670 static void prefs_scoring_select_set_dialog(ScoringProp * prop)
671 {
672         gchar * matcher_str;
673         gchar * score_str;
674
675         if (prop == NULL)
676                 return;
677
678         matcher_str = matcherlist_to_string(prop->matchers);
679         if (matcher_str == NULL) {
680                 scoringprop_free(prop);
681                 return;
682         }
683
684         score_str = itos(prop->score);
685
686         gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), matcher_str);
687         gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
688
689         g_free(matcher_str);
690 }
691
692 static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
693                                 GdkEvent *event)
694 {
695         ScoringProp * prop;
696
697         gchar * scoring_str;
698
699         if (row == 0) {
700                 prefs_scoring_reset_dialog();
701                 return;
702         }
703
704         if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
705                                 row, 0, &scoring_str))
706                 return;
707
708         prop = matcher_parser_get_scoring(scoring_str);
709         if (prop == NULL)
710                 return;
711
712         prefs_scoring_select_set_dialog(prop);
713
714         scoringprop_free(prop);
715 }
716
717 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
718                                  gpointer data)
719 {
720         prefs_scoring_cancel();
721         return TRUE;
722 }
723
724 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
725                                      gpointer data)
726 {
727         if (event && event->keyval == GDK_Escape)
728                 prefs_scoring_cancel();
729 }
730
731 static void prefs_scoring_ok(void)
732 {
733         MatcherList * cond;
734         gchar * cond_str;
735         gchar * score_str;
736         gchar * scoring_str;
737         gchar * str;
738         ScoringProp * prop;
739         gint score;
740         gint row = 1;
741         AlertValue val;
742
743         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
744         score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
745         if (*cond_str != '\0' && *score_str != '\0') {
746                 score = atoi(score_str);
747                 cond = matcher_parser_get_cond(cond_str);
748
749                 if (cond == NULL) {
750                         prefs_common_save_config();
751                         prefs_scoring_set_list();
752                         prefs_matcher_write_config();
753                         if (cur_item != NULL)
754                                 prefs_folder_item_save_config(cur_item);
755                         gtk_widget_hide(scoring.window);
756                         inc_unlock();
757                         return;
758                 }
759                 prop = scoringprop_new(cond, score);
760                 str = scoringprop_to_string(prop);
761                 while (gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
762                                   row, 0, &scoring_str)) {
763                         if (strcmp(scoring_str, str) == 0) break;
764                         row++;
765                 }
766                 if (strcmp(scoring_str, str) != 0) {
767                         val = alertpanel(_("Entry not registered"),
768                                  _("The entry was not registered\nAre you really finish?"),
769                                  _("Yes"), _("No"), NULL);
770                         if (G_ALERTDEFAULT != val) {
771                                 g_free(str);
772                                 return;
773                         }
774                 }
775                 g_free(str);
776         }
777         prefs_common_save_config();
778         prefs_scoring_set_list();
779         prefs_matcher_write_config();
780         if (cur_item != NULL)
781                 prefs_folder_item_save_config(cur_item);
782         gtk_widget_hide(scoring.window);
783         inc_unlock();
784 }
785
786 static void prefs_scoring_cancel(void)
787 {
788         prefs_matcher_read_config();
789         gtk_widget_hide(scoring.window);
790         inc_unlock();
791 }