]> git.llucax.com Git - software/mutt-debian.git/blob - score.c
restoring .gitignore
[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   ptr->val = atoi (pc);
120   set_option (OPTNEEDRESCORE);
121   return 0;
122 }
123
124 void mutt_score_message (CONTEXT *ctx, HEADER *hdr, int upd_ctx)
125 {
126   SCORE *tmp;
127
128   hdr->score = 0; /* in case of re-scoring */
129   for (tmp = Score; tmp; tmp = tmp->next)
130   {
131     if (mutt_pattern_exec (tmp->pat, 0, NULL, hdr) > 0)
132     {
133       if (tmp->exact || tmp->val == 9999 || tmp->val == -9999)
134       {
135         hdr->score = tmp->val;
136         break;
137       }
138       hdr->score += tmp->val;
139     }
140   }
141   if (hdr->score < 0)
142     hdr->score = 0;
143   
144   if (hdr->score <= ScoreThresholdDelete)
145     _mutt_set_flag (ctx, hdr, M_DELETE, 1, upd_ctx);
146   if (hdr->score <= ScoreThresholdRead)
147     _mutt_set_flag (ctx, hdr, M_READ, 1, upd_ctx);
148   if (hdr->score >= ScoreThresholdFlag)
149     _mutt_set_flag (ctx, hdr, M_FLAG, 1, upd_ctx);
150 }
151
152 int mutt_parse_unscore (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
153 {
154   SCORE *tmp, *last = NULL;
155
156   while (MoreArgs (s))
157   {
158     mutt_extract_token (buf, s, 0);
159     if (!mutt_strcmp ("*", buf->data))
160     {
161       for (tmp = Score; tmp; )
162       {
163         last = tmp;
164         tmp = tmp->next;
165         mutt_pattern_free (&last->pat);
166         FREE (&last);
167       }
168       Score = NULL;
169     }
170     else
171     {
172       for (tmp = Score; tmp; last = tmp, tmp = tmp->next)
173       {
174         if (!mutt_strcmp (buf->data, tmp->str))
175         {
176           if (last)
177             last->next = tmp->next;
178           else
179             Score = tmp->next;
180           mutt_pattern_free (&tmp->pat);
181           FREE (&tmp);
182           /* there should only be one score per pattern, so we can stop here */
183           break;
184         }
185       }
186     }
187   }
188   set_option (OPTNEEDRESCORE);
189   return 0;
190 }