Further pop_mx_ng work
[apps/madmutt.git] / flags.c
diff --git a/flags.c b/flags.c
index e46ee8a..d25aca7 100644 (file)
--- a/flags.c
+++ b/flags.c
 /*
+ * Copyright notice from original mutt:
  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
- * 
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- * 
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- */ 
+ *
+ * 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 <lib-ui/lib-ui.h>
+#include <lib-ui/menu.h>
+#include <lib-mx/mx.h>
+#include <imap/imap.h>
 
 #include "mutt.h"
-#include "mutt_curses.h"
 #include "sort.h"
-#include "mx.h"
 
-#ifdef USE_IMAP
-#include "imap_private.h"
-#endif
 
-void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
+void _mutt_set_flag (CONTEXT * ctx, HEADER * h, int flag, int bf, int upd_ctx)
 {
   int changed = h->changed;
   int deleted = ctx->deleted;
   int tagged = ctx->tagged;
+  int flagged = ctx->flagged;
 
   if (ctx->readonly && flag != M_TAG)
-    return; /* don't modify anything if we are read-only */
-
-  switch (flag)
-  {
-    case M_DELETE:
-
-#ifdef USE_IMAP
-       if (ctx && ctx->magic == M_IMAP)
-               if (mutt_bit_isset (((IMAP_DATA *)ctx->data)->capabilities, ACL) \
-               && !mutt_bit_isset(((IMAP_DATA *)ctx->data)->rights,IMAP_ACL_DELETE))
-                       return;
-#endif
-
-      if (bf)
-      {
-       if (!h->deleted && !ctx->readonly)
-       {
-         h->deleted = 1;
-         if (upd_ctx) ctx->deleted++;
-#ifdef USE_IMAP
-          /* deleted messages aren't treated as changed elsewhere so that the
-           * purge-on-sync option works correctly. This isn't applicable here */
-          if (ctx && ctx->magic == M_IMAP)
-          {
-            h->changed = 1;
-           if (upd_ctx) ctx->changed = 1;
-          }
-#endif
-       }
-      }
-      else if (h->deleted)
-      {
-       h->deleted = 0;
-       if (upd_ctx)
-       {
-         ctx->deleted--;
-         if (h->appended)
-           ctx->appended--;
-       }
-       h->appended = 0; /* when undeleting, also reset the appended flag */
-#ifdef USE_IMAP
-        /* see my comment above */
-       if (ctx->magic == M_IMAP) 
-       {
-         h->changed = 1;
-         if (upd_ctx) ctx->changed = 1;
-       }
-#endif
-       /* 
-        * If the user undeletes a message which is marked as
-        * "trash" in the maildir folder on disk, the folder has
-        * been changed, and is marked accordingly.  However, we do
-        * _not_ mark the message itself changed, because trashing
-        * is checked in specific code in the maildir folder
-        * driver. 
-        */
-       if (ctx->magic == M_MAILDIR && upd_ctx && h->trash)
-         ctx->changed = 1;
-      }
-      break;
-
-    case M_APPENDED:
-      if (bf)
-      {
-       if (!h->appended)
-       {
-         h->appended = 1;
-         if (upd_ctx) ctx->appended++;
-       }
-      }
-      break;
-
-    case M_PURGED:
-      if (bf)
-      {
-       if (!h->purged)
-         h->purged = 1;
-      }
-      else if (h->purged)
-       h->purged = 0;
-      break;
-
-    case M_NEW:
-
-#ifdef USE_IMAP
-       if (ctx && ctx->magic == M_IMAP)
-               if (mutt_bit_isset (((IMAP_DATA *)ctx->data)->capabilities, ACL) \
-               && !mutt_bit_isset(((IMAP_DATA *)ctx->data)->rights,IMAP_ACL_SEEN))
-                       return;
-#endif
-
-      if (bf)
-      {
-       if (h->read || h->old)
-       {
-         h->old = 0;
-         if (upd_ctx) ctx->new++;
-         if (h->read)
-         {
-           h->read = 0;
-           if (upd_ctx) ctx->unread++;
-         }
-         h->changed = 1;
-         if (upd_ctx) ctx->changed = 1;
-       }
-      }
-      else if (!h->read)
-      {
-       if (!h->old)
-         if (upd_ctx) ctx->new--;
-       h->read = 1;
-       if (upd_ctx) ctx->unread--;
-       h->changed = 1;
-       if (upd_ctx) ctx->changed = 1;
+    return;                     /* don't modify anything if we are read-only */
+
+  switch (flag) {
+  case M_DELETE:
+
+    if (!mx_acl_check (ctx, ACL_DELETE))
+      return;
+
+    if (bf) {
+      if (!h->deleted && !ctx->readonly) {
+        h->deleted = 1;
+        if (upd_ctx)
+          ctx->deleted++;
+        /* deleted messages aren't treated as changed elsewhere so that the
+         * purge-on-sync option works correctly. This isn't applicable here */
+        if (ctx && ctx->magic == M_IMAP) {
+          h->changed = 1;
+          if (upd_ctx)
+            ctx->changed = 1;
+        }
       }
-      break;
-
-    case M_OLD:
-
-#ifdef USE_IMAP
-       if (ctx && ctx->magic == M_IMAP)
-               if (mutt_bit_isset (((IMAP_DATA *)ctx->data)->capabilities, ACL) \
-               && !mutt_bit_isset(((IMAP_DATA *)ctx->data)->rights,IMAP_ACL_SEEN))
-                       return;
-#endif
-
-      if (bf)
-      {
-       if (!h->old)
-       {
-         h->old = 1;
-         if (!h->read)
-           if (upd_ctx) ctx->new--;
-         h->changed = 1;
-         if (upd_ctx) ctx->changed = 1;
-       }
-      }
-      else if (h->old)
-      {
-       h->old = 0;
-       if (!h->read)
-         if (upd_ctx) ctx->new++;
-       h->changed = 1;
-       if (upd_ctx) ctx->changed = 1;
+    }
+    else if (h->deleted) {
+      h->deleted = 0;
+      if (upd_ctx) {
+        ctx->deleted--;
+        if (h->appended)
+          ctx->appended--;
       }
-      break;
-
-    case M_READ:
-
-#ifdef USE_IMAP
-       if (ctx && ctx->magic == M_IMAP)
-               if (mutt_bit_isset (((IMAP_DATA *)ctx->data)->capabilities, ACL) \
-               && !mutt_bit_isset(((IMAP_DATA *)ctx->data)->rights,IMAP_ACL_SEEN))
-                       return;
-#endif
-
-      if (bf)
-      {
-       if (!h->read)
-       {
-         h->read = 1;
-         if (upd_ctx) ctx->unread--;
-         if (!h->old)
-           if (upd_ctx) ctx->new--;
-         h->changed = 1;
-         if (upd_ctx) ctx->changed = 1;
-       }
+      h->appended = 0;          /* when undeleting, also reset the appended flag */
+      /* see my comment above */
+      if (ctx->magic == M_IMAP) {
+        h->changed = 1;
+        if (upd_ctx)
+          ctx->changed = 1;
       }
-      else if (h->read)
-      {
-       h->read = 0;
-       if (upd_ctx) ctx->unread++;
-       if (!h->old)
-         if (upd_ctx) ctx->new++;
-       h->changed = 1;
-       if (upd_ctx) ctx->changed = 1;
+      /* 
+       * If the user undeletes a message which is marked as
+       * "trash" in the maildir folder on disk, the folder has
+       * been changed, and is marked accordingly.  However, we do
+       * _not_ mark the message itself changed, because trashing
+       * is checked in specific code in the maildir folder
+       * driver. 
+       */
+      if (ctx->magic == M_MAILDIR && upd_ctx && h->trash)
+        ctx->changed = 1;
+    }
+    break;
+
+  case M_APPENDED:
+    if (bf) {
+      if (!h->appended) {
+        h->appended = 1;
+        if (upd_ctx)
+          ctx->appended++;
       }
-      break;
-
-    case M_REPLIED:
-
-#ifdef USE_IMAP
-       if (ctx && ctx->magic == M_IMAP)
-               if (mutt_bit_isset (((IMAP_DATA *)ctx->data)->capabilities, ACL) \
-               && !mutt_bit_isset(((IMAP_DATA *)ctx->data)->rights,IMAP_ACL_WRITE))
-                       return;
-#endif
-
-      if (bf)
-      {
-       if (!h->replied)
-       {
-         h->replied = 1;
-         if (!h->read)
-         {
-           h->read = 1;
-           if (upd_ctx) ctx->unread--;
-           if (!h->old)
-             if (upd_ctx) ctx->new--;
-         }
-         h->changed = 1;
-         if (upd_ctx) ctx->changed = 1;
-       }
+    }
+    break;
+
+  case M_PURGED:
+    if (bf) {
+      if (!h->purged)
+        h->purged = 1;
+    }
+    else if (h->purged)
+      h->purged = 0;
+    break;
+
+  case M_NEW:
+
+    if (!mx_acl_check (ctx, ACL_SEEN))
+      return;
+
+    if (bf) {
+      if (h->read || h->old) {
+        h->old = 0;
+        if (upd_ctx)
+          ctx->new++;
+        if (h->read) {
+          h->read = 0;
+          if (upd_ctx)
+            ctx->unread++;
+        }
+        h->changed = 1;
+        if (upd_ctx)
+          ctx->changed = 1;
       }
-      else if (h->replied)
-      {
-       h->replied = 0;
-       h->changed = 1;
-       if (upd_ctx) ctx->changed = 1;
+    }
+    else if (!h->read) {
+      if (!h->old)
+        if (upd_ctx)
+          ctx->new--;
+      h->read = 1;
+      if (upd_ctx)
+        ctx->unread--;
+      h->changed = 1;
+      if (upd_ctx)
+        ctx->changed = 1;
+    }
+    break;
+
+  case M_OLD:
+
+    if (!mx_acl_check (ctx, ACL_SEEN))
+      return;
+
+    if (bf) {
+      if (!h->old) {
+        h->old = 1;
+        if (!h->read)
+          if (upd_ctx)
+            ctx->new--;
+        h->changed = 1;
+        if (upd_ctx)
+          ctx->changed = 1;
       }
-      break;
-
-    case M_FLAG:
-
-#ifdef USE_IMAP
-       if (ctx && ctx->magic == M_IMAP)
-               if (mutt_bit_isset (((IMAP_DATA *)ctx->data)->capabilities, ACL) \
-               && !mutt_bit_isset(((IMAP_DATA *)ctx->data)->rights,IMAP_ACL_WRITE))
-                       return;
-#endif
-
-      if (bf)
-      {
-       if (!h->flagged)
-       {
-         h->flagged = bf;
-         if (upd_ctx) ctx->flagged++;
-         h->changed = 1;
-         if (upd_ctx) ctx->changed = 1;
-       }
+    }
+    else if (h->old) {
+      h->old = 0;
+      if (!h->read)
+        if (upd_ctx)
+          ctx->new++;
+      h->changed = 1;
+      if (upd_ctx)
+        ctx->changed = 1;
+    }
+    break;
+
+  case M_READ:
+
+    if (!mx_acl_check (ctx, ACL_SEEN))
+      return;
+
+    if (bf) {
+      if (!h->read) {
+        h->read = 1;
+        if (upd_ctx)
+          ctx->unread--;
+        if (!h->old)
+          if (upd_ctx)
+            ctx->new--;
+        h->changed = 1;
+        if (upd_ctx)
+          ctx->changed = 1;
       }
-      else if (h->flagged)
-      {
-       h->flagged = 0;
-       if (upd_ctx) ctx->flagged--;
-       h->changed = 1;
-       if (upd_ctx) ctx->changed = 1;
+    }
+    else if (h->read) {
+      h->read = 0;
+      if (upd_ctx)
+        ctx->unread++;
+      if (!h->old)
+        if (upd_ctx)
+          ctx->new++;
+      h->changed = 1;
+      if (upd_ctx)
+        ctx->changed = 1;
+    }
+    break;
+
+  case M_REPLIED:
+
+    if (!mx_acl_check (ctx, ACL_WRITE))
+      return;
+
+    if (bf) {
+      if (!h->replied) {
+        h->replied = 1;
+        if (!h->read) {
+          h->read = 1;
+          if (upd_ctx)
+            ctx->unread--;
+          if (!h->old)
+            if (upd_ctx)
+              ctx->new--;
+        }
+        h->changed = 1;
+        if (upd_ctx)
+          ctx->changed = 1;
       }
-      break;
-
-    case M_TAG:
-      if (bf)
-      {
-       if (!h->tagged)
-       {
-         h->tagged = 1;
-         if (upd_ctx) ctx->tagged++;
-       }
+    }
+    else if (h->replied) {
+      h->replied = 0;
+      h->changed = 1;
+      if (upd_ctx)
+        ctx->changed = 1;
+    }
+    break;
+
+  case M_FLAG:
+
+    if (!mx_acl_check (ctx, ACL_WRITE))
+      return;
+
+    if (bf) {
+      if (!h->flagged) {
+        h->flagged = bf;
+        if (upd_ctx)
+          ctx->flagged++;
+        h->changed = 1;
+        if (upd_ctx)
+          ctx->changed = 1;
       }
-      else if (h->tagged)
-      {
-       h->tagged = 0;
-       if (upd_ctx) ctx->tagged--;
+    }
+    else if (h->flagged) {
+      h->flagged = 0;
+      if (upd_ctx)
+        ctx->flagged--;
+      h->changed = 1;
+      if (upd_ctx)
+        ctx->changed = 1;
+    }
+    break;
+
+  case M_TAG:
+    if (bf) {
+      if (!h->tagged) {
+        h->tagged = 1;
+        if (upd_ctx)
+          ctx->tagged++;
       }
-      break;
+    }
+    else if (h->tagged) {
+      h->tagged = 0;
+      if (upd_ctx)
+        ctx->tagged--;
+    }
+    break;
   }
 
-  mutt_set_header_color(ctx, h);
+  mutt_set_header_color (ctx, h);
 
   /* if the message status has changed, we need to invalidate the cached
    * search results so that any future search will match the current status
    * of this message and not what it was at the time it was last searched.
    */
-  if (h->searched && (changed != h->changed || deleted != ctx->deleted || tagged != ctx->tagged))
+  if (h->searched && (changed != h->changed || deleted != ctx->deleted ||
+                      tagged != ctx->tagged || flagged != ctx->flagged))
     h->searched = 0;
+  sidebar_draw ();
 }
 
 void mutt_tag_set_flag (int flag, int bf)
@@ -307,29 +275,28 @@ void mutt_tag_set_flag (int flag, int bf)
     if (Context->hdrs[Context->v2r[j]]->tagged)
       mutt_set_flag (Context, Context->hdrs[Context->v2r[j]], flag, bf);
 }
-int mutt_thread_set_flag (HEADER *hdr, int flag, int bf, int subthread)
+int mutt_thread_set_flag (HEADER * hdr, int flag, int bf, int subthread)
 {
   THREAD *start, *cur = hdr->thread;
-  
-  if ((Sort & SORT_MASK) != SORT_THREADS)
-  {
+
+  if ((Sort & SORT_MASK) != SORT_THREADS) {
     mutt_error _("Threading is not enabled.");
-    return (-1);
+
+    return -1;
   }
 
   if (!subthread)
     while (cur->parent)
       cur = cur->parent;
   start = cur;
-  
+
   if (cur->message)
     mutt_set_flag (Context, cur->message, flag, bf);
 
   if ((cur = cur->child) == NULL)
-    return (0);
+    return 0;
 
-  FOREVER
-  {
+  for (;;) {
     if (cur->message)
       mutt_set_flag (Context, cur->message, flag, bf);
 
@@ -337,13 +304,11 @@ int mutt_thread_set_flag (HEADER *hdr, int flag, int bf, int subthread)
       cur = cur->child;
     else if (cur->next)
       cur = cur->next;
-    else 
-    {
-      while (!cur->next)
-      {
-       cur = cur->parent;
-       if (cur == start)
-         return (0);
+    else {
+      while (!cur->next) {
+        cur = cur->parent;
+        if (cur == start)
+          return 0;
       }
       cur = cur->next;
     }
@@ -351,67 +316,40 @@ int mutt_thread_set_flag (HEADER *hdr, int flag, int bf, int subthread)
   /* not reached */
 }
 
-int mutt_change_flag (HEADER *h, int bf)
+int mutt_change_flag(HEADER * h, int bf)
 {
-  int i, flag;
-  event_t event;
-
-  mvprintw (LINES - 1, 0, "%s? (D/N/O/r/*/!): ", bf ? _("Set flag") : _("Clear flag"));
-  clrtoeol ();
-
-  event = mutt_getch();
-  i = event.ch;
-  if (i == -1)
-  {
-    CLEARLINE (LINES-1);
-    return (-1);
-  }
-
-  CLEARLINE (LINES-1);
-
-  switch (i)
-  {
-    case 'd':
-    case 'D':
-      flag = M_DELETE;
-      break;
-
-    case 'N':
-    case 'n':
-      flag = M_NEW;
-      break;
-
-    case 'o':
-    case 'O':
-      if (h)
-       mutt_set_flag (Context, h, M_READ, !bf);
-      else
-       mutt_tag_set_flag (M_READ, !bf);
-      flag = M_OLD;
-      break;
-
-    case 'r':
-    case 'R':
-      flag = M_REPLIED;
-      break;
-
-    case '*':
-      flag = M_TAG;
-      break;
-
-    case '!':
-      flag = M_FLAG;
-      break;
-
-    default:
-      BEEP ();
-      return (-1);
-  }
+    char buf[STRING];
+    const char letters[] = "dDnNoOrR*!";
+    static char const actions[] = {
+        ['d'] = M_DELETE,       ['D'] = M_DELETE,
+        ['n'] = M_NEW,          ['N'] = M_NEW,
+        ['o'] = M_OLD,          ['O'] = M_OLD,
+        ['r'] = M_REPLIED,      ['R'] = M_REPLIED,
+        ['*'] = M_TAG,
+        ['!'] = M_FLAG,
+    };
+
+    int c;
+
+    snprintf(buf, sizeof(buf), "%s? (D/N/O/r/*/!): ",
+             bf ? _("Set flag") : _("Clear flag"));
+    c = mutt_multi_choice(buf, letters);
+    if (c <= 0)
+        return -1;
+    c = letters[c - 1];
+    if (actions[c] == M_OLD) {
+        if (h) {
+            mutt_set_flag(Context, h, M_READ, !bf);
+        } else {
+            mutt_tag_set_flag(M_READ, !bf);
+        }
+    }
 
-  if (h)
-    mutt_set_flag (Context, h, flag, bf);
-  else
-    mutt_tag_set_flag (flag, bf);
+    if (h) {
+        mutt_set_flag(Context, h, actions[c], bf);
+    } else {
+        mutt_tag_set_flag(actions[c], bf);
+    }
 
-  return 0;
+    return 0;
 }