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