mutt_mktemp--
[apps/madmutt.git] / score.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
4  *
5  * This file is part of mutt-ng, see http://www.muttng.org/.
6  * It's licensed under the GNU General Public License,
7  * please see the file GPL in the top level source directory.
8  */
9
10 #include <lib-lib/lib-lib.h>
11
12 #include "mutt.h"
13 #include "sort.h"
14
15 typedef struct score_t {
16   char *str;
17   pattern_t *pat;
18   int val;
19   int exact;                    /* if this rule matches, don't evaluate any more */
20   struct score_t *next;
21 } SCORE;
22
23 SCORE *Score = NULL;
24
25 void mutt_check_rescore (CONTEXT * ctx)
26 {
27   int i;
28
29   if (option (OPTNEEDRESCORE) && option (OPTSCORE)) {
30     if ((Sort & SORT_MASK) == SORT_SCORE ||
31         (SortAux & SORT_MASK) == SORT_SCORE) {
32       set_option (OPTNEEDRESORT);
33       if ((Sort & SORT_MASK) == SORT_THREADS)
34         set_option (OPTSORTSUBTHREADS);
35     }
36
37     /* must redraw the index since the user might have %N in it */
38     set_option (OPTFORCEREDRAWINDEX);
39     set_option (OPTFORCEREDRAWPAGER);
40
41     for (i = 0; ctx && i < ctx->msgcount; i++) {
42       mutt_score_message (ctx, ctx->hdrs[i], 1);
43       ctx->hdrs[i]->pair = 0;
44     }
45   }
46   unset_option (OPTNEEDRESCORE);
47 }
48
49 int mutt_parse_score (BUFFER * buf, BUFFER * s, unsigned long data,
50                       BUFFER * err)
51 {
52   SCORE *ptr, *last;
53   char *pattern, *pc;
54   struct pattern_t *pat;
55
56   mutt_extract_token (buf, s, 0);
57   if (!MoreArgs (s)) {
58     m_strcpy(err->data, err->dsize, _("score: too few arguments"));
59     return (-1);
60   }
61   pattern = buf->data;
62   p_clear(buf, 1);
63   mutt_extract_token (buf, s, 0);
64   if (MoreArgs (s)) {
65     p_delete(&pattern);
66     m_strcpy(err->data, err->dsize, _("score: too many arguments"));
67     return (-1);
68   }
69
70   /* look for an existing entry and update the value, else add it to the end
71      of the list */
72   for (ptr = Score, last = NULL; ptr; last = ptr, ptr = ptr->next)
73     if (m_strcmp(pattern, ptr->str) == 0)
74       break;
75   if (!ptr) {
76     if ((pat = mutt_pattern_comp (pattern, 0, err)) == NULL) {
77       p_delete(&pattern);
78       return (-1);
79     }
80     ptr = p_new(SCORE, 1);
81     if (last)
82       last->next = ptr;
83     else
84       Score = ptr;
85     ptr->pat = pat;
86     ptr->str = pattern;
87   }
88   pc = buf->data;
89   if (*pc == '=') {
90     ptr->exact = 1;
91     pc++;
92   }
93   ptr->val = atoi (pc);
94   set_option (OPTNEEDRESCORE);
95   return 0;
96 }
97
98 void mutt_score_message (CONTEXT * ctx, HEADER * hdr, int upd_ctx)
99 {
100   SCORE *tmp;
101
102   hdr->score = 0;               /* in case of re-scoring */
103   for (tmp = Score; tmp; tmp = tmp->next) {
104     if (mutt_pattern_exec (tmp->pat, M_MATCH_FULL_ADDRESS, NULL, hdr) > 0) {
105       if (tmp->exact || tmp->val == 9999 || tmp->val == -9999) {
106         hdr->score = tmp->val;
107         break;
108       }
109       hdr->score += tmp->val;
110     }
111   }
112   if (hdr->score < 0)
113     hdr->score = 0;
114
115   if (hdr->score <= ScoreThresholdDelete)
116     _mutt_set_flag (ctx, hdr, M_DELETE, 1, upd_ctx);
117   if (hdr->score <= ScoreThresholdRead)
118     _mutt_set_flag (ctx, hdr, M_READ, 1, upd_ctx);
119   if (hdr->score >= ScoreThresholdFlag)
120     _mutt_set_flag (ctx, hdr, M_FLAG, 1, upd_ctx);
121 }
122
123 int mutt_parse_unscore (BUFFER * buf, BUFFER * s, unsigned long data,
124                         BUFFER * err)
125 {
126   SCORE *tmp, *last = NULL;
127
128   while (MoreArgs (s)) {
129     mutt_extract_token (buf, s, 0);
130     if (!m_strcmp("*", buf->data)) {
131       for (tmp = Score; tmp;) {
132         last = tmp;
133         tmp = tmp->next;
134         mutt_pattern_free (&last->pat);
135         p_delete(&last);
136       }
137       Score = NULL;
138     }
139     else {
140       for (tmp = Score; tmp; last = tmp, tmp = tmp->next) {
141         if (!m_strcmp(buf->data, tmp->str)) {
142           if (last)
143             last->next = tmp->next;
144           else
145             Score = tmp->next;
146           mutt_pattern_free (&tmp->pat);
147           p_delete(&tmp);
148           /* there should only be one score per pattern, so we can stop here */
149           break;
150         }
151       }
152     }
153   }
154   set_option (OPTNEEDRESCORE);
155   return 0;
156 }