Use selected text on reply/forward.
[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[] = {_("Registered rules")};
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         cond_clist = gtk_clist_new_with_titles(1, title);
307         gtk_widget_show (cond_clist);
308         gtk_container_add (GTK_CONTAINER (cond_scrolledwin), cond_clist);
309         gtk_clist_set_column_width (GTK_CLIST (cond_clist), 0, 80);
310         gtk_clist_set_selection_mode (GTK_CLIST (cond_clist),
311                                       GTK_SELECTION_BROWSE);
312         GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (cond_clist)->column[0].button,
313                                 GTK_CAN_FOCUS);
314         gtk_signal_connect (GTK_OBJECT (cond_clist), "select_row",
315                             GTK_SIGNAL_FUNC (prefs_scoring_select), NULL);
316
317         btn_vbox = gtk_vbox_new (FALSE, 8);
318         gtk_widget_show (btn_vbox);
319         gtk_box_pack_start (GTK_BOX (cond_hbox), btn_vbox, FALSE, FALSE, 0);
320
321         up_btn = gtk_button_new_with_label (_("Up"));
322         gtk_widget_show (up_btn);
323         gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
324         gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
325                             GTK_SIGNAL_FUNC (prefs_scoring_up), NULL);
326
327         down_btn = gtk_button_new_with_label (_("Down"));
328         gtk_widget_show (down_btn);
329         gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
330         gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
331                             GTK_SIGNAL_FUNC (prefs_scoring_down), NULL);
332
333         hbox1 = gtk_hbox_new (FALSE, 8);
334         gtk_widget_show (hbox1);
335         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
336
337         kill_score_label = gtk_label_new (_("Kill score"));
338         gtk_widget_show (kill_score_label);
339         gtk_misc_set_alignment (GTK_MISC (kill_score_label), 0, 0.5);
340         gtk_box_pack_start (GTK_BOX (hbox1), kill_score_label,
341                             FALSE, FALSE, 0);
342
343         kill_score_entry = gtk_entry_new ();
344         gtk_widget_show (kill_score_entry);
345         gtk_widget_set_usize (kill_score_entry, 50, -1);
346         gtk_box_pack_start (GTK_BOX (hbox1), kill_score_entry,
347                             FALSE, FALSE, 0);
348
349         score_label = gtk_label_new (_("Important score"));
350         gtk_widget_show (score_label);
351         gtk_misc_set_alignment (GTK_MISC (score_label), 0, 0.5);
352         gtk_box_pack_start (GTK_BOX (hbox1), score_label, FALSE, FALSE, 0);
353
354         important_score_entry = gtk_entry_new ();
355         gtk_widget_show (important_score_entry);
356         gtk_widget_set_usize (important_score_entry, 50, -1);
357         gtk_box_pack_start (GTK_BOX (hbox1), important_score_entry,
358                             FALSE, FALSE, 0);
359
360         gtk_widget_show_all(window);
361
362         scoring.window    = window;
363         scoring.ok_btn = ok_btn;
364
365         scoring.cond_entry = cond_entry;
366         scoring.score_entry = score_entry;
367         scoring.kill_score_entry = kill_score_entry;
368         scoring.kill_score_label = kill_score_label;
369         scoring.important_score_entry = important_score_entry;
370
371         scoring.cond_clist   = cond_clist;
372 }
373
374 static void prefs_scoring_set_dialog(ScoringProp * cond)
375 {
376         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
377         GSList *cur;
378         GSList * prefs_scoring;
379         gchar * score_str;
380
381         if (cond == NULL)
382                 prefs_scoring_reset_dialog();
383         else
384                 prefs_scoring_select_set_dialog(cond);
385
386         gtk_clist_freeze(clist);
387         gtk_clist_clear(clist);
388
389         prefs_scoring_clist_set_row(-1, NULL);
390         if (cur_item == NULL) {
391                 prefs_scoring = global_scoring;
392                 cur_kill_score = prefs_common.kill_score;
393                 cur_important_score = prefs_common.important_score;
394                 gtk_widget_show(scoring.kill_score_label);
395                 gtk_widget_show(scoring.kill_score_entry);
396         }
397         else {
398                 prefs_scoring = cur_item->prefs->scoring;
399                 cur_kill_score = cur_item->prefs->kill_score;
400                 cur_important_score = cur_item->prefs->important_score;
401                 if (cur_item->folder->type != F_NEWS) {
402                         gtk_widget_hide(scoring.kill_score_label);
403                         gtk_widget_hide(scoring.kill_score_entry);
404                 }
405                 else {
406                         gtk_widget_show(scoring.kill_score_label);
407                         gtk_widget_show(scoring.kill_score_entry);
408                 }
409         }
410
411         for(cur = prefs_scoring ; cur != NULL ;
412             cur = g_slist_next(cur)) {
413                 ScoringProp * prop = (ScoringProp *) cur->data;
414                 
415                 prefs_scoring_clist_set_row(-1, prop);
416         }
417
418         score_str = itos(cur_kill_score);
419         gtk_entry_set_text(GTK_ENTRY(scoring.kill_score_entry),
420                            score_str);
421         score_str = itos(cur_important_score);
422         gtk_entry_set_text(GTK_ENTRY(scoring.important_score_entry),
423                            score_str);
424
425         gtk_clist_thaw(clist);
426 }
427
428 static void prefs_scoring_reset_dialog(void)
429 {
430         gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), "");
431         gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), "");
432 }
433
434 static void prefs_scoring_set_list(void)
435 {
436         gint row = 1;
437         ScoringProp *prop;
438         GSList * cur;
439         gchar * scoring_str;
440         gchar * tmp;
441         GSList * prefs_scoring;
442
443         if (cur_item == NULL)
444                 prefs_scoring = global_scoring;
445         else
446                 prefs_scoring = cur_item->prefs->scoring;
447
448         for(cur = prefs_scoring ; cur != NULL ;
449             cur = g_slist_next(cur))
450                 scoringprop_free((ScoringProp *) cur->data);
451         g_slist_free(prefs_scoring);
452         prefs_scoring = NULL;
453
454         while (gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
455                                   row, 0, &scoring_str)) {
456                 if (strcmp(scoring_str, _("(New)")) != 0) {
457                         prop = matcher_parser_get_scoring(scoring_str);
458                         if (prop != NULL)
459                                 prefs_scoring = g_slist_append(prefs_scoring,
460                                                                prop);
461                 }
462                 row++;
463         }
464
465         cur_kill_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.kill_score_entry)));
466         cur_important_score = atoi(gtk_entry_get_text(GTK_ENTRY(scoring.important_score_entry)));
467
468         if (cur_item == NULL) {
469                 global_scoring = prefs_scoring;
470                 prefs_common.kill_score = cur_kill_score;
471                 prefs_common.important_score = cur_important_score;
472         }
473         else {
474                 cur_item->prefs->scoring = prefs_scoring;
475                 cur_item->prefs->kill_score = cur_kill_score;
476                 cur_item->prefs->important_score = cur_important_score;
477         }
478 }
479
480 static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop)
481 {
482         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
483         gchar * str;
484         gchar *cond_str[1];
485
486         if (prop == NULL) {
487                 cond_str[0] = _("(New)");
488                 return gtk_clist_append(clist, cond_str);
489         }
490
491         str = scoringprop_to_string(prop);
492         if (str == NULL) {
493                 return -1;
494         }
495         cond_str[0] = str;
496
497         if (row < 0)
498                 row = gtk_clist_append(clist, cond_str);
499         else
500                 gtk_clist_set_text(clist, row, 0, cond_str[0]);
501         g_free(str);
502
503         return row;
504 }
505
506 static void prefs_scoring_condition_define_done(MatcherList * matchers)
507 {
508         gchar * str;
509
510         if (matchers == NULL)
511                 return;
512
513         str = matcherlist_to_string(matchers);
514
515         if (str != NULL) {
516                 gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), str);
517                 g_free(str);
518         }
519 }
520
521 static void prefs_scoring_condition_define(void)
522 {
523         gchar * cond_str;
524         MatcherList * matchers = NULL;
525
526         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
527
528         if (*cond_str != '\0') {
529                 gchar * tmp;
530                 
531                 matchers = matcher_parser_get_cond(cond_str);
532                 if (matchers == 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         cond = matcher_parser_get_cond(cond_str);
568
569         if (cond == NULL) {
570                 alertpanel_error(_("Match string is not valid."));
571                 return;
572         }
573
574         prop = scoringprop_new(cond, score);
575
576         prefs_scoring_clist_set_row(-1, prop);
577
578         scoringprop_free(prop);
579
580         prefs_scoring_reset_dialog();
581 }
582
583 static void prefs_scoring_substitute_cb(void)
584 {
585         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
586         gint row;
587         MatcherList * cond;
588         gchar * cond_str;
589         gchar * score_str;
590         ScoringProp * prop;
591         gint score;
592         gchar * tmp;
593
594         if (!clist->selection) return;
595
596         row = GPOINTER_TO_INT(clist->selection->data);
597         if (row == 0) return;
598
599         cond_str = gtk_entry_get_text(GTK_ENTRY(scoring.cond_entry));
600         if (*cond_str == '\0') {
601                 alertpanel_error(_("Score is not set."));
602                 return;
603         }
604
605         score_str = gtk_entry_get_text(GTK_ENTRY(scoring.score_entry));
606         if (*score_str == '\0') {
607                 alertpanel_error(_("Match string is not set."));
608                 return;
609         }
610
611         score = atoi(score_str);
612         cond = matcher_parser_get_cond(cond_str);
613
614         if (cond == NULL) {
615                 alertpanel_error(_("Match string is not valid."));
616                 return;
617         }
618
619         prop = scoringprop_new(cond, score);
620
621         prefs_scoring_clist_set_row(row, prop);
622
623         scoringprop_free(prop);
624
625         prefs_scoring_reset_dialog();
626 }
627
628 static void prefs_scoring_delete_cb(void)
629 {
630         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
631         gint row;
632
633         if (!clist->selection) return;
634         row = GPOINTER_TO_INT(clist->selection->data);
635         if (row == 0) return;
636
637         if (alertpanel(_("Delete rule"),
638                        _("Do you really want to delete this rule?"),
639                        _("Yes"), _("No"), NULL) == G_ALERTALTERNATE)
640                 return;
641
642         gtk_clist_remove(clist, row);
643 }
644
645 static void prefs_scoring_up(void)
646 {
647         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
648         gint row;
649
650         if (!clist->selection) return;
651
652         row = GPOINTER_TO_INT(clist->selection->data);
653         if (row > 1) {
654                 gtk_clist_row_move(clist, row, row - 1);
655                 if(gtk_clist_row_is_visible(clist, row - 1) != GTK_VISIBILITY_FULL) {
656                         gtk_clist_moveto(clist, row - 1, 0, 0, 0);
657                 } 
658         }
659 }
660
661 static void prefs_scoring_down(void)
662 {
663         GtkCList *clist = GTK_CLIST(scoring.cond_clist);
664         gint row;
665
666         if (!clist->selection) return;
667
668         row = GPOINTER_TO_INT(clist->selection->data);
669         if (row > 0 && row < clist->rows - 1) {
670                 gtk_clist_row_move(clist, row, row + 1);
671                 if(gtk_clist_row_is_visible(clist, row + 1) != GTK_VISIBILITY_FULL) {
672                         gtk_clist_moveto(clist, row + 1, 0, 1, 0);
673                 } 
674         }
675 }
676
677 static void prefs_scoring_select_set_dialog(ScoringProp * prop)
678 {
679         gchar * matcher_str;
680         gchar * score_str;
681
682         if (prop == NULL)
683                 return;
684
685         matcher_str = matcherlist_to_string(prop->matchers);
686         if (matcher_str == NULL) {
687                 scoringprop_free(prop);
688                 return;
689         }
690
691         score_str = itos(prop->score);
692
693         gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), matcher_str);
694         gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
695
696         g_free(matcher_str);
697 }
698
699 static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
700                                 GdkEvent *event)
701 {
702         ScoringProp * prop;
703         gchar * tmp;
704
705         gchar * scoring_str;
706
707         if (row == 0) {
708                 prefs_scoring_reset_dialog();
709                 return;
710         }
711
712         if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
713                                 row, 0, &scoring_str))
714                 return;
715
716         prop = matcher_parser_get_scoring(scoring_str);
717         if (prop == NULL)
718                 return;
719
720         prefs_scoring_select_set_dialog(prop);
721
722         scoringprop_free(prop);
723 }
724
725 static gint prefs_scoring_deleted(GtkWidget *widget, GdkEventAny *event,
726                                  gpointer data)
727 {
728         prefs_scoring_cancel();
729         return TRUE;
730 }
731
732 static void prefs_scoring_key_pressed(GtkWidget *widget, GdkEventKey *event,
733                                      gpointer data)
734 {
735         if (event && event->keyval == GDK_Escape)
736                 prefs_scoring_cancel();
737 }
738
739 static void prefs_scoring_ok(void)
740 {
741         prefs_common_save_config();
742         prefs_scoring_set_list();
743         prefs_matcher_write_config();
744         if (cur_item != NULL)
745                 prefs_folder_item_save_config(cur_item);
746         gtk_widget_hide(scoring.window);
747         inc_unlock();
748 }
749
750 static void prefs_scoring_cancel(void)
751 {
752         prefs_matcher_read_config();
753         gtk_widget_hide(scoring.window);
754         inc_unlock();
755 }