Move score_* to mod_score
[apps/madmutt.git] / score.cpkg
diff --git a/score.cpkg b/score.cpkg
new file mode 100644 (file)
index 0000000..40adf78
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright notice from original mutt:
+ * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
+ *
+ * This file is part of mutt-ng, see http://www.muttng.org/.
+ * It's licensed under the GNU General Public License,
+ * please see the file GPL in the top level source directory.
+ */
+
+#include <lib-lib/lib-lib.h>
+
+#include "mutt.h"
+#include "sort.h"
+#include "pattern.h"
+#include "score.h"
+@import  "lib-lua/base.cpkg"
+
+@package mod_score {
+    bool enable = 1;
+    /*
+     ** .pp
+     ** When this variable is \fIunset\fP, scoring is turned off.  This can
+     ** be useful to selectively disable scoring for certain folders when the
+     ** ``$$score_threshold_delete'' variable and friends are used.
+     **
+     */
+    int threshold_flag = 9999;
+    /*
+     ** .pp
+     ** Messages which have been assigned a score greater than or equal to this
+     ** variable's value are automatically marked ``flagged''.
+     */
+    int threshold_delete = -1;
+    /*
+     ** .pp
+     ** Messages which have been assigned a score equal to or lower than the value
+     ** of this variable are automatically marked for deletion by Madmutt.  Since
+     ** Madmutt scores are always greater than or equal to zero, the default setting
+     ** of this variable will never mark a message for deletion.
+     */
+    int threshold_read   = -1;
+    /*
+     ** .pp
+     ** Messages which have been assigned a score equal to or lower than the value
+     ** of this variable are automatically marked as read by Madmutt.  Since
+     ** Madmutt scores are always greater than or equal to zero, the default setting
+     ** of this variable will never mark a message read.
+     */
+};
+
+typedef struct score_t {
+  char *str;
+  pattern_t *pat;
+  int val;
+  int exact;                    /* if this rule matches, don't evaluate any more */
+  struct score_t *next;
+} score_t;
+DO_INIT(score_t, score);
+static void score_wipe(score_t *sc)
+{
+    pattern_list_wipe(&sc->pat);
+    p_delete(&sc->str);
+}
+DO_NEW(score_t, score);
+DO_DELETE(score_t, score);
+DO_SLIST(score_t, score, score_delete);
+
+static score_t *Score = NULL;
+
+void mutt_check_rescore (CONTEXT * ctx)
+{
+  int i;
+
+  if (option (OPTNEEDRESCORE) && mod_score.enable) {
+    if ((Sort & SORT_MASK) == SORT_SCORE ||
+        (SortAux & SORT_MASK) == SORT_SCORE) {
+      set_option (OPTNEEDRESORT);
+      if ((Sort & SORT_MASK) == SORT_THREADS)
+        set_option (OPTSORTSUBTHREADS);
+    }
+
+    /* must redraw the index since the user might have %N in it */
+    set_option (OPTFORCEREDRAWINDEX);
+    set_option (OPTFORCEREDRAWPAGER);
+
+    for (i = 0; ctx && i < ctx->msgcount; i++) {
+      mutt_score_message (ctx, ctx->hdrs[i], 1);
+      ctx->hdrs[i]->pair = 0;
+    }
+  }
+  unset_option (OPTNEEDRESCORE);
+}
+
+int mutt_parse_score (BUFFER * buf, BUFFER * s,
+                      unsigned long data __attribute__ ((unused)),
+                      BUFFER * err)
+{
+  char *pattern, *pc;
+  struct pattern_t *pat;
+  score_t **last;
+
+  mutt_extract_token (buf, s, 0);
+  if (!MoreArgs (s)) {
+    m_strcpy(err->data, err->dsize, _("score: too few arguments"));
+    return (-1);
+  }
+  pattern = buf->data;
+  p_clear(buf, 1);
+  mutt_extract_token (buf, s, 0);
+  if (MoreArgs (s)) {
+    p_delete(&pattern);
+    m_strcpy(err->data, err->dsize, _("score: too many arguments"));
+    return (-1);
+  }
+
+  /* look for an existing entry and update the value, else add it to the end
+     of the list */
+  for (last = &Score; *last; last = &(*last)->next) {
+    if (m_strcmp(pattern, (*last)->str) == 0)
+      break;
+  }
+  if (!*last) {
+    if (!(pat = mutt_pattern_comp(pattern, 0, err))) {
+      p_delete(&pattern);
+      return (-1);
+    }
+    *last = score_new();
+    (*last)->pat = pat;
+    (*last)->str = pattern;
+  }
+  pc = buf->data;
+  pc += (*last)->exact = (*pc == '=');
+  (*last)->val = atoi(pc);
+  set_option(OPTNEEDRESCORE);
+  return 0;
+}
+
+void mutt_score_message (CONTEXT * ctx, HEADER * hdr, int upd_ctx)
+{
+  score_t *tmp;
+
+  hdr->score = 0;               /* in case of re-scoring */
+  for (tmp = Score; tmp; tmp = tmp->next) {
+    if (mutt_pattern_exec (tmp->pat, M_MATCH_FULL_ADDRESS, NULL, hdr) > 0) {
+      if (tmp->exact || tmp->val == 9999 || tmp->val == -9999) {
+        hdr->score = tmp->val;
+        break;
+      }
+      hdr->score += tmp->val;
+    }
+  }
+  if (hdr->score < 0)
+    hdr->score = 0;
+
+  if (hdr->score <= mod_score.threshold_delete)
+    _mutt_set_flag (ctx, hdr, M_DELETE, 1, upd_ctx);
+  if (hdr->score <= mod_score.threshold_flag)
+    _mutt_set_flag (ctx, hdr, M_READ, 1, upd_ctx);
+  if (hdr->score >= mod_score.threshold_flag)
+    _mutt_set_flag (ctx, hdr, M_FLAG, 1, upd_ctx);
+}
+
+int mutt_parse_unscore(BUFFER * buf, BUFFER * s,
+                       unsigned long data __attribute__ ((unused)),
+                       BUFFER * err __attribute__ ((unused)))
+{
+    while (MoreArgs(s)) {
+        mutt_extract_token(buf, s, 0);
+        if (!m_strcmp("*", buf->data)) {
+            score_list_wipe(&Score);
+        } else {
+            score_t **last;
+
+            for (last = &Score; *last; last = &(*last)->next) {
+                if (!m_strcmp(buf->data, (*last)->str)) {
+                    score_t *tmp = score_list_pop(last);
+                    score_delete(&tmp);
+                    break;
+                }
+            }
+        }
+    }
+    set_option (OPTNEEDRESCORE);
+    return 0;
+}
+
+/* vim:set ft=c: */