mutt stable branch with some hacks
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
29typedef 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
38static SCORE *Score = NULL;
39
40void 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
67int 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
131void 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
161int 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}