2b53377cc22d3dd4d93e0bfccb167ba9e7655d0f
[apps/madmutt.git] / score.cpkg
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 #include "pattern.h"
15 #include "score.h"
16 @import  "lib-lua/base.cpkg"
17
18 typedef struct score_t {
19   char *str;
20   pattern_t *pat;
21   int val;
22   int exact;                    /* if this rule matches, don't evaluate any more */
23   struct score_t *next;
24 } score_t;
25 DO_INIT(score_t, score);
26 static void score_wipe(score_t *sc)
27 {
28     pattern_list_wipe(&sc->pat);
29     p_delete(&sc->str);
30 }
31 DO_NEW(score_t, score);
32 DO_DELETE(score_t, score);
33 DO_SLIST(score_t, score, score_delete);
34
35 static score_t *Score = NULL;
36
37 @package mod_score {
38     bool enable = 1;
39     /*
40      ** .pp
41      ** When this variable is \fIunset\fP, scoring is turned off.  This can
42      ** be useful to selectively disable scoring for certain folders when the
43      ** ``$$score_threshold_delete'' variable and friends are used.
44      **
45      */
46     int threshold_flag = 9999;
47     /*
48      ** .pp
49      ** Messages which have been assigned a score greater than or equal to this
50      ** variable's value are automatically marked ``flagged''.
51      */
52     int threshold_delete = -1;
53     /*
54      ** .pp
55      ** Messages which have been assigned a score equal to or lower than the value
56      ** of this variable are automatically marked for deletion by Madmutt.  Since
57      ** Madmutt scores are always greater than or equal to zero, the default setting
58      ** of this variable will never mark a message for deletion.
59      */
60     int threshold_read   = -1;
61     /*
62      ** .pp
63      ** Messages which have been assigned a score equal to or lower than the value
64      ** of this variable are automatically marked as read by Madmutt.  Since
65      ** Madmutt scores are always greater than or equal to zero, the default setting
66      ** of this variable will never mark a message read.
67      */
68
69     void score(string_t pattern, int value) {
70         const char *pc;
71         score_t **last;
72
73         for (last = &Score; *last; last = &(*last)->next) {
74             if (!m_strcmp(pattern, (*last)->str))
75                 break;
76         }
77         if (!*last) {
78             /* FIXME need a buffer for error */
79             struct pattern_t *pat = mutt_pattern_comp(pattern, 0, NULL);
80
81             if (!pat) {
82                 p_delete(&pattern);
83                 RETURN();
84             }
85             *last = score_new();
86             (*last)->pat = pat;
87             (*last)->str = pattern;
88         }
89         pc  = pattern;
90         pc += (*last)->exact = (*pc == '=');
91         (*last)->val = value;
92         set_option(OPTNEEDRESCORE);
93         RETURN();
94     };
95
96     void unscore(const string_t pattern) {
97         if (!m_strcmp(pattern, "*")) {
98             score_list_wipe(&Score);
99             set_option(OPTNEEDRESCORE);
100             RETURN();
101         }
102         for (score_t **last = &Score; *last; last = &(*last)->next) {
103             if (!m_strcmp(pattern, (*last)->str)) {
104                 score_t *tmp = score_list_pop(last);
105                 score_delete(&tmp);
106                 set_option(OPTNEEDRESCORE);
107                 break;
108             }
109         }
110         RETURN();
111     };
112 };
113
114 void mutt_check_rescore (CONTEXT * ctx)
115 {
116   int i;
117
118   if (option (OPTNEEDRESCORE) && mod_score.enable) {
119     if ((Sort & SORT_MASK) == SORT_SCORE ||
120         (SortAux & SORT_MASK) == SORT_SCORE) {
121       set_option (OPTNEEDRESORT);
122       if ((Sort & SORT_MASK) == SORT_THREADS)
123         set_option (OPTSORTSUBTHREADS);
124     }
125
126     /* must redraw the index since the user might have %N in it */
127     set_option (OPTFORCEREDRAWINDEX);
128     set_option (OPTFORCEREDRAWPAGER);
129
130     for (i = 0; ctx && i < ctx->msgcount; i++) {
131       mutt_score_message (ctx, ctx->hdrs[i], 1);
132       ctx->hdrs[i]->pair = 0;
133     }
134   }
135   unset_option (OPTNEEDRESCORE);
136 }
137
138 void mutt_score_message (CONTEXT * ctx, HEADER * hdr, int upd_ctx)
139 {
140   score_t *tmp;
141
142   hdr->score = 0;               /* in case of re-scoring */
143   for (tmp = Score; tmp; tmp = tmp->next) {
144     if (mutt_pattern_exec (tmp->pat, M_MATCH_FULL_ADDRESS, NULL, hdr) > 0) {
145       if (tmp->exact || tmp->val == 9999 || tmp->val == -9999) {
146         hdr->score = tmp->val;
147         break;
148       }
149       hdr->score += tmp->val;
150     }
151   }
152   if (hdr->score < 0)
153     hdr->score = 0;
154
155   if (hdr->score <= mod_score.threshold_delete)
156     _mutt_set_flag (ctx, hdr, M_DELETE, 1, upd_ctx);
157   if (hdr->score <= mod_score.threshold_flag)
158     _mutt_set_flag (ctx, hdr, M_READ, 1, upd_ctx);
159   if (hdr->score >= mod_score.threshold_flag)
160     _mutt_set_flag (ctx, hdr, M_FLAG, 1, upd_ctx);
161 }
162
163 /* vim:set ft=c: */