mutt stable branch with some hacks
at master 197 lines 4.9 kB view raw
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 28typedef 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 37static SCORE *Score = NULL; 38 39void 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 66int 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 mutt_buffer_init (buf); 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 if (mutt_atoi (pc, &ptr->val) < 0) 120 { 121 FREE (&pattern); 122 strfcpy (err->data, _("Error: score: invalid number"), err->dsize); 123 return (-1); 124 } 125 set_option (OPTNEEDRESCORE); 126 return 0; 127} 128 129void mutt_score_message (CONTEXT *ctx, HEADER *hdr, int upd_ctx) 130{ 131 SCORE *tmp; 132 pattern_cache_t cache; 133 134 memset (&cache, 0, sizeof (cache)); 135 hdr->score = 0; /* in case of re-scoring */ 136 for (tmp = Score; tmp; tmp = tmp->next) 137 { 138 if (mutt_pattern_exec (tmp->pat, 0, NULL, hdr, &cache) > 0) 139 { 140 if (tmp->exact || tmp->val == 9999 || tmp->val == -9999) 141 { 142 hdr->score = tmp->val; 143 break; 144 } 145 hdr->score += tmp->val; 146 } 147 } 148 if (hdr->score < 0) 149 hdr->score = 0; 150 151 if (hdr->score <= ScoreThresholdDelete) 152 _mutt_set_flag (ctx, hdr, MUTT_DELETE, 1, upd_ctx); 153 if (hdr->score <= ScoreThresholdRead) 154 _mutt_set_flag (ctx, hdr, MUTT_READ, 1, upd_ctx); 155 if (hdr->score >= ScoreThresholdFlag) 156 _mutt_set_flag (ctx, hdr, MUTT_FLAG, 1, upd_ctx); 157} 158 159int mutt_parse_unscore (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) 160{ 161 SCORE *tmp, *last = NULL; 162 163 while (MoreArgs (s)) 164 { 165 mutt_extract_token (buf, s, 0); 166 if (!mutt_strcmp ("*", buf->data)) 167 { 168 for (tmp = Score; tmp; ) 169 { 170 last = tmp; 171 tmp = tmp->next; 172 mutt_pattern_free (&last->pat); 173 FREE (&last); 174 } 175 Score = NULL; 176 } 177 else 178 { 179 for (tmp = Score; tmp; last = tmp, tmp = tmp->next) 180 { 181 if (!mutt_strcmp (buf->data, tmp->str)) 182 { 183 if (last) 184 last->next = tmp->next; 185 else 186 Score = tmp->next; 187 mutt_pattern_free (&tmp->pat); 188 FREE (&tmp); 189 /* there should only be one score per pattern, so we can stop here */ 190 break; 191 } 192 } 193 } 194 } 195 set_option (OPTNEEDRESCORE); 196 return 0; 197}