Andreas Krennmair:
[apps/madmutt.git] / score.c
1 /*
2  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
3  * 
4  *     This program is free software; you can redistribute it and/or modify
5  *     it under the terms of the GNU General Public License as published by
6  *     the Free Software Foundation; either version 2 of the License, or
7  *     (at your option) any later version.
8  * 
9  *     This program is distributed in the hope that it will be useful,
10  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *     GNU General Public License for more details.
13  * 
14  *     You should have received a copy of the GNU General Public License
15  *     along with this program; if not, write to the Free Software
16  *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17  */ 
18
19 #include "mutt.h"
20 #include "sort.h"
21 #include <string.h>
22 #include <stdlib.h>
23
24 typedef struct score_t
25 {
26   char *str;
27   pattern_t *pat;
28   int val;
29   int exact;            /* if this rule matches, don't evaluate any more */
30   struct score_t *next;
31 } SCORE;
32
33 SCORE *Score = NULL;
34
35 void mutt_check_rescore (CONTEXT *ctx)
36 {
37   int i;
38
39   if (option (OPTNEEDRESCORE) && option (OPTSCORE))
40   {
41     if ((Sort & SORT_MASK) == SORT_SCORE ||
42         (SortAux & SORT_MASK) == SORT_SCORE)
43     {
44       set_option (OPTNEEDRESORT);
45       if ((Sort & SORT_MASK) == SORT_THREADS)
46         set_option (OPTSORTSUBTHREADS);
47     }
48
49     /* must redraw the index since the user might have %N in it */
50     set_option (OPTFORCEREDRAWINDEX);
51     set_option (OPTFORCEREDRAWPAGER);
52
53     for (i = 0; ctx && i < ctx->msgcount; i++)
54     {
55       mutt_score_message (ctx, ctx->hdrs[i], 1);
56       ctx->hdrs[i]->pair = 0;
57     }
58   }
59   unset_option (OPTNEEDRESCORE);
60 }
61
62 int mutt_parse_score (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
63 {
64   SCORE *ptr, *last;
65   char *pattern, *pc;
66   struct pattern_t *pat;
67
68   mutt_extract_token (buf, s, 0);
69   if (!MoreArgs (s))
70   {
71     strfcpy (err->data, _("score: too few arguments"), err->dsize);
72     return (-1);
73   }
74   pattern = buf->data;
75   memset (buf, 0, sizeof (BUFFER));
76   mutt_extract_token (buf, s, 0);
77   if (MoreArgs (s))
78   {
79     FREE (&pattern);
80     strfcpy (err->data, _("score: too many arguments"), err->dsize);
81     return (-1);
82   }
83
84   /* look for an existing entry and update the value, else add it to the end
85      of the list */
86   for (ptr = Score, last = NULL; ptr; last = ptr, ptr = ptr->next)
87     if (mutt_strcmp (pattern, ptr->str) == 0)
88       break;
89   if (!ptr)
90   {
91     if ((pat = mutt_pattern_comp (pattern, 0, err)) == NULL)
92     {
93       FREE (&pattern);
94       return (-1);
95     }
96     ptr = safe_calloc (1, sizeof (SCORE));
97     if (last)
98       last->next = ptr;
99     else
100       Score = ptr;
101     ptr->pat = pat;
102     ptr->str = pattern;
103   }
104   pc = buf->data;
105   if (*pc == '=')
106   {
107     ptr->exact = 1;
108     pc++;
109   }
110   ptr->val = atoi (pc);
111   set_option (OPTNEEDRESCORE);
112   return 0;
113 }
114
115 void mutt_score_message (CONTEXT *ctx, HEADER *hdr, int upd_ctx)
116 {
117   SCORE *tmp;
118
119   hdr->score = 0; /* in case of re-scoring */
120   for (tmp = Score; tmp; tmp = tmp->next)
121   {
122     if (mutt_pattern_exec (tmp->pat, 0, NULL, hdr) > 0)
123     {
124       if (tmp->exact || tmp->val == 9999 || tmp->val == -9999)
125       {
126         hdr->score = tmp->val;
127         break;
128       }
129       hdr->score += tmp->val;
130     }
131   }
132   if (hdr->score < 0)
133     hdr->score = 0;
134   
135   if (hdr->score <= ScoreThresholdDelete)
136     _mutt_set_flag (ctx, hdr, M_DELETE, 1, upd_ctx);
137   if (hdr->score <= ScoreThresholdRead)
138     _mutt_set_flag (ctx, hdr, M_READ, 1, upd_ctx);
139   if (hdr->score >= ScoreThresholdFlag)
140     _mutt_set_flag (ctx, hdr, M_FLAG, 1, upd_ctx);
141 }
142
143 int mutt_parse_unscore (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
144 {
145   SCORE *tmp, *last = NULL;
146
147   while (MoreArgs (s))
148   {
149     mutt_extract_token (buf, s, 0);
150     if (!mutt_strcmp ("*", buf->data))
151     {
152       for (tmp = Score; tmp; )
153       {
154         last = tmp;
155         tmp = tmp->next;
156         mutt_pattern_free (&last->pat);
157         FREE (&last);
158       }
159       Score = NULL;
160     }
161     else
162     {
163       for (tmp = Score; tmp; last = tmp, tmp = tmp->next)
164       {
165         if (!mutt_strcmp (buf->data, tmp->str))
166         {
167           if (last)
168             last->next = tmp->next;
169           else
170             Score = tmp->next;
171           mutt_pattern_free (&tmp->pat);
172           FREE (&tmp);
173           /* there should only be one score per pattern, so we can stop here */
174           break;
175         }
176       }
177     }
178   }
179   set_option (OPTNEEDRESCORE);
180   return 0;
181 }