workaround a stupid issue in how decoding is performed in mutt *sigh*
[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_score_message (CONTEXT * ctx, HEADER * hdr, int upd_ctx)
115 {
116     hdr->score = 0;               /* in case of re-scoring */
117     for (score_t *tmp = Score; tmp; tmp = tmp->next) {
118         if (mutt_pattern_exec (tmp->pat, M_MATCH_FULL_ADDRESS, NULL, hdr) > 0) {
119             if (tmp->exact || tmp->val == 9999 || tmp->val == -9999) {
120                 hdr->score = tmp->val;
121                 break;
122             }
123             hdr->score += tmp->val;
124         }
125     }
126     if (hdr->score < 0)
127         hdr->score = 0;
128
129     if (hdr->score <= mod_score.threshold_delete)
130         _mutt_set_flag(ctx, hdr, M_DELETE, 1, upd_ctx);
131     if (hdr->score <= mod_score.threshold_read)
132         _mutt_set_flag(ctx, hdr, M_READ, 1, upd_ctx);
133     if (hdr->score >= mod_score.threshold_flag)
134         _mutt_set_flag(ctx, hdr, M_FLAG, 1, upd_ctx);
135 }
136
137 void mutt_check_rescore (CONTEXT * ctx)
138 {
139     if (option(OPTNEEDRESCORE) && mod_score.enable) {
140         if (((Sort | SortAux) & SORT_MASK) == SORT_SCORE) {
141             set_option(OPTNEEDRESORT);
142             if ((Sort & SORT_MASK) == SORT_THREADS)
143                 set_option(OPTSORTSUBTHREADS);
144         }
145
146         /* must redraw the index since the user might have %N in it */
147         set_option(OPTFORCEREDRAWINDEX);
148         set_option(OPTFORCEREDRAWPAGER);
149
150         for (int i = 0; ctx && i < ctx->msgcount; i++) {
151             mutt_score_message(ctx, ctx->hdrs[i], 1);
152             ctx->hdrs[i]->pair = 0;
153         }
154     }
155     unset_option(OPTNEEDRESCORE);
156 }
157
158 /* vim:set ft=c: */