]> git.llucax.com Git - software/mutt-debian.git/blob - score.c
Move Mutt with NNTP support to mutt-nntp package
[software/mutt-debian.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */ 
18
19 #if HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include "mutt.h"
24 #include "sort.h"
25 #include <string.h>
26 #include <stdlib.h>
27
28 typedef struct score_t
29 {
30   char *str;
31   pattern_t *pat;
32   int val;
33   int exact;            /* if this rule matches, don't evaluate any more */
34   struct score_t *next;
35 } SCORE;
36
37 static SCORE *Score = NULL;
38
39 void mutt_check_rescore (CONTEXT *ctx)
40 {
41   int i;
42
43   if (option (OPTNEEDRESCORE) && option (OPTSCORE))
44   {
45     if ((Sort & SORT_MASK) == SORT_SCORE ||
46         (SortAux & SORT_MASK) == SORT_SCORE)
47     {
48       set_option (OPTNEEDRESORT);
49       if ((Sort & SORT_MASK) == SORT_THREADS)
50         set_option (OPTSORTSUBTHREADS);
51     }
52
53     /* must redraw the index since the user might have %N in it */
54     set_option (OPTFORCEREDRAWINDEX);
55     set_option (OPTFORCEREDRAWPAGER);
56
57     for (i = 0; ctx && i < ctx->msgcount; i++)
58     {
59       mutt_score_message (ctx, ctx->hdrs[i], 1);
60       ctx->hdrs[i]->pair = 0;
61     }
62   }
63   unset_option (OPTNEEDRESCORE);
64 }
65
66 int mutt_parse_score (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
67 {
68   SCORE *ptr, *last;
69   char *pattern, *pc;
70   struct pattern_t *pat;
71
72   mutt_extract_token (buf, s, 0);
73   if (!MoreArgs (s))
74   {
75     strfcpy (err->data, _("score: too few arguments"), err->dsize);
76     return (-1);
77   }
78   pattern = buf->data;
79   memset (buf, 0, sizeof (BUFFER));
80   mutt_extract_token (buf, s, 0);
81   if (MoreArgs (s))
82   {
83     FREE (&pattern);
84     strfcpy (err->data, _("score: too many arguments"), err->dsize);
85     return (-1);
86   }
87
88   /* look for an existing entry and update the value, else add it to the end
89      of the list */
90   for (ptr = Score, last = NULL; ptr; last = ptr, ptr = ptr->next)
91     if (mutt_strcmp (pattern, ptr->str) == 0)
92       break;
93   if (!ptr)
94   {
95     if ((pat = mutt_pattern_comp (pattern, 0, err)) == NULL)
96     {
97       FREE (&pattern);
98       return (-1);
99     }
100     ptr = safe_calloc (1, sizeof (SCORE));
101     if (last)
102       last->next = ptr;
103     else
104       Score = ptr;
105     ptr->pat = pat;
106     ptr->str = pattern;
107   } else
108     /* 'buf' arg was cleared and 'pattern' holds the only reference;
109      * as here 'ptr' != NULL -> update the value only in which case
110      * ptr->str already has the string, so pattern should be freed.
111      */
112     FREE (&pattern);
113   pc = buf->data;
114   if (*pc == '=')
115   {
116     ptr->exact = 1;
117     pc++;
118   }
119   if (mutt_atoi (pc, &ptr->val) < 0)
120   {
121     FREE (&pattern);
122     strfcpy (err->data, _("Error: score: invalid number"), err->dsize);
123     return (-1);
124   }
125   set_option (OPTNEEDRESCORE);
126   return 0;
127 }
128
129 void mutt_score_message (CONTEXT *ctx, HEADER *hdr, int upd_ctx)
130 {
131   SCORE *tmp;
132
133   hdr->score = 0; /* in case of re-scoring */
134   for (tmp = Score; tmp; tmp = tmp->next)
135   {
136     if (mutt_pattern_exec (tmp->pat, 0, NULL, hdr) > 0)
137     {
138       if (tmp->exact || tmp->val == 9999 || tmp->val == -9999)
139       {
140         hdr->score = tmp->val;
141         break;
142       }
143       hdr->score += tmp->val;
144     }
145   }
146   if (hdr->score < 0)
147     hdr->score = 0;
148   
149   if (hdr->score <= ScoreThresholdDelete)
150     _mutt_set_flag (ctx, hdr, M_DELETE, 1, upd_ctx);
151   if (hdr->score <= ScoreThresholdRead)
152     _mutt_set_flag (ctx, hdr, M_READ, 1, upd_ctx);
153   if (hdr->score >= ScoreThresholdFlag)
154     _mutt_set_flag (ctx, hdr, M_FLAG, 1, upd_ctx);
155 }
156
157 int mutt_parse_unscore (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
158 {
159   SCORE *tmp, *last = NULL;
160
161   while (MoreArgs (s))
162   {
163     mutt_extract_token (buf, s, 0);
164     if (!mutt_strcmp ("*", buf->data))
165     {
166       for (tmp = Score; tmp; )
167       {
168         last = tmp;
169         tmp = tmp->next;
170         mutt_pattern_free (&last->pat);
171         FREE (&last);
172       }
173       Score = NULL;
174     }
175     else
176     {
177       for (tmp = Score; tmp; last = tmp, tmp = tmp->next)
178       {
179         if (!mutt_strcmp (buf->data, tmp->str))
180         {
181           if (last)
182             last->next = tmp->next;
183           else
184             Score = tmp->next;
185           mutt_pattern_free (&tmp->pat);
186           FREE (&tmp);
187           /* there should only be one score per pattern, so we can stop here */
188           break;
189         }
190       }
191     }
192   }
193   set_option (OPTNEEDRESCORE);
194   return 0;
195 }