Rocco Rutte:
[apps/madmutt.git] / curs_main.c
index fb85a50..f2b6cb2 100644 (file)
@@ -1,20 +1,18 @@
 /*
+ * 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.
- */ 
+ *
+ * Parts were written/modified by:
+ * Nico Golde <nico@ngolde.de>
+ *
+ * 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.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
 
 #include "mutt.h"
 #include "mutt_curses.h"
@@ -25,6 +23,7 @@
 #include "sort.h"
 #include "buffy.h"
 #include "mx.h"
+#include "sidebar.h"
 
 #ifdef USE_POP
 #include "pop.h"
@@ -40,6 +39,9 @@
 #include "nntp.h"
 #endif
 
+#include "lib/mem.h"
+#include "lib/intl.h"
+#include "lib/str.h"
 
 #include <ctype.h>
 #include <stdlib.h>
 static const char *No_mailbox_is_open = N_("No mailbox is open.");
 static const char *There_are_no_messages = N_("There are no messages.");
 static const char *Mailbox_is_read_only = N_("Mailbox is read-only.");
-static const char *Function_not_permitted_in_attach_message_mode = N_("Function not permitted in attach-message mode.");
+static const char *Function_not_permitted_in_attach_message_mode =
+N_("Function not permitted in attach-message mode.");
 static const char *No_visible = N_("No visible messages.");
 
 #define CHECK_MSGCOUNT if (!Context) \
-       { \
-               mutt_flushinp (); \
-               mutt_error _(No_mailbox_is_open); \
-               break; \
-       } \
-       else if (!Context->msgcount) \
-       { \
-               mutt_flushinp (); \
-               mutt_error _(There_are_no_messages); \
-               break; \
-       }
+        { \
+                  mutt_flushinp (); \
+                mutt_error(_(No_mailbox_is_open)); \
+                break; \
+        } \
+        else if (!Context->msgcount) \
+        { \
+                  mutt_flushinp (); \
+                mutt_error(_(There_are_no_messages)); \
+                break; \
+        }
 
 #define CHECK_VISIBLE if (Context && menu->current >= Context->vcount) \
-       {\
-               mutt_flushinp (); \
-               mutt_error _(No_visible); \
-               break; \
-       }
-    
+          {\
+                  mutt_flushinp (); \
+                  mutt_error(_(No_visible)); \
+                  break; \
+        }
+
 
 #define CHECK_READONLY if (Context->readonly) \
-                       { \
-                               mutt_flushinp (); \
-                               mutt_error _(Mailbox_is_read_only); \
-                               break; \
-                       }
+                        { \
+                                  mutt_flushinp (); \
+                                mutt_error(_(Mailbox_is_read_only)); \
+                                break; \
+                        }
 
-#ifdef USE_IMAP 
+#ifdef USE_IMAP
 /* the error message returned here could be better. */
 #define CHECK_IMAP_ACL(aclbit) if (Context->magic == M_IMAP) \
-               if (mutt_bit_isset (((IMAP_DATA *)Context->data)->capabilities, ACL) \
-               && !mutt_bit_isset(((IMAP_DATA *)Context->data)->rights,aclbit)){ \
-                       mutt_flushinp(); \
-                       mutt_error ("Operation not permitted by the IMAP ACL for this mailbox"); \
-                       break; \
-               }
+                if (mutt_bit_isset (((IMAP_DATA *)Context->data)->capabilities, ACL) \
+                && !mutt_bit_isset(((IMAP_DATA *)Context->data)->rights,aclbit)){ \
+                        mutt_flushinp(); \
+                        mutt_error ("Operation not permitted by the IMAP ACL for this mailbox"); \
+                        break; \
+                }
 #endif
 
 #define CHECK_ATTACH if(option(OPTATTACHMSG)) \
-                    {\
-                       mutt_flushinp (); \
-                       mutt_error _(Function_not_permitted_in_attach_message_mode); \
-                       break; \
-                    }
+                     {\
+                        mutt_flushinp (); \
+                        mutt_error(_(Function_not_permitted_in_attach_message_mode)); \
+                        break; \
+                     }
 
 #define CURHDR Context->hdrs[Context->v2r[menu->current]]
 #define OLDHDR Context->hdrs[Context->v2r[menu->oldcurrent]]
@@ -108,61 +111,72 @@ static const char *No_visible = N_("No visible messages.");
 extern const char *ReleaseDate;
 extern size_t UngetCount;
 
-void index_make_entry (char *s, size_t l, MUTTMENU *menu, int num)
+static void set_xterm_title_bar (char *title)
+{
+  fputs ("\033]2;", stdout);
+  fputs (title, stdout);
+  fputs ("\007", stdout);
+  fflush (stdout);
+}
+
+static void set_xterm_icon_name (char *name)
+{
+  fputs ("\033]1;", stdout);
+  fputs (name, stdout);
+  fputs ("\007", stdout);
+  fflush (stdout);
+}
+
+void index_make_entry (char *s, size_t l, MUTTMENU * menu, int num)
 {
-  format_flag flag = M_FORMAT_MAKEPRINT | M_FORMAT_ARROWCURSOR | M_FORMAT_INDEX;
+  format_flag flag =
+    M_FORMAT_MAKEPRINT | M_FORMAT_ARROWCURSOR | M_FORMAT_INDEX;
   int edgemsgno, reverse = Sort & SORT_REVERSE;
   HEADER *h = Context->hdrs[Context->v2r[num]];
   THREAD *tmp;
 
-  if ((Sort & SORT_MASK) == SORT_THREADS && h->tree)
-  {
-    flag |= M_FORMAT_TREE; /* display the thread tree */
+  if ((Sort & SORT_MASK) == SORT_THREADS && h->tree) {
+    flag |= M_FORMAT_TREE;      /* display the thread tree */
     if (h->display_subject)
       flag |= M_FORMAT_FORCESUBJ;
-    else
-    {
-      if (reverse)
-      {
-       if (menu->top + menu->pagelen > menu->max)
-         edgemsgno = Context->v2r[menu->max - 1];
-       else
-         edgemsgno = Context->v2r[menu->top + menu->pagelen - 1];
+    else {
+      if (reverse) {
+        if (menu->top + menu->pagelen > menu->max)
+          edgemsgno = Context->v2r[menu->max - 1];
+        else
+          edgemsgno = Context->v2r[menu->top + menu->pagelen - 1];
       }
       else
-       edgemsgno = Context->v2r[menu->top];
+        edgemsgno = Context->v2r[menu->top];
 
-      for (tmp = h->thread->parent; tmp; tmp = tmp->parent)
-      {
-       if (!tmp->message)
-         continue;
-
-       /* if no ancestor is visible on current screen, provisionally force
-        * subject... */
-       if (reverse ? tmp->message->msgno > edgemsgno : tmp->message->msgno < edgemsgno)
-       {
-         flag |= M_FORMAT_FORCESUBJ;
-         break;
-       }
-       else if (tmp->message->virtual >= 0)
-         break;
-      }
-      if (flag & M_FORMAT_FORCESUBJ)
-      {
-       for (tmp = h->thread->prev; tmp; tmp = tmp->prev)
-       {
-         if (!tmp->message)
-           continue;
-
-         /* ...but if a previous sibling is available, don't force it */
-         if (reverse ? tmp->message->msgno > edgemsgno : tmp->message->msgno < edgemsgno)
-           break;
-         else if (tmp->message->virtual >= 0)
-         {
-           flag &= ~M_FORMAT_FORCESUBJ;
-           break;
-         }
-       }
+      for (tmp = h->thread->parent; tmp; tmp = tmp->parent) {
+        if (!tmp->message)
+          continue;
+
+        /* if no ancestor is visible on current screen, provisionally force
+         * subject... */
+        if (reverse ? tmp->message->msgno > edgemsgno : tmp->message->msgno <
+            edgemsgno) {
+          flag |= M_FORMAT_FORCESUBJ;
+          break;
+        }
+        else if (tmp->message->virtual >= 0)
+          break;
+      }
+      if (flag & M_FORMAT_FORCESUBJ) {
+        for (tmp = h->thread->prev; tmp; tmp = tmp->prev) {
+          if (!tmp->message)
+            continue;
+
+          /* ...but if a previous sibling is available, don't force it */
+          if (reverse ? tmp->message->msgno >
+              edgemsgno : tmp->message->msgno < edgemsgno)
+            break;
+          else if (tmp->message->virtual >= 0) {
+            flag &= ~M_FORMAT_FORCESUBJ;
+            break;
+          }
+        }
       }
     }
   }
@@ -174,7 +188,7 @@ int index_color (int index_no)
 {
   HEADER *h = Context->hdrs[Context->v2r[index_no]];
 
-  if (h->pair)
+  if (h && h->pair)
     return h->pair;
 
   mutt_set_header_color (Context, h);
@@ -185,8 +199,8 @@ static int ci_next_undeleted (int msgno)
 {
   int i;
 
-  for (i=msgno+1; i < Context->vcount; i++)
-    if (! Context->hdrs[Context->v2r[i]]->deleted)
+  for (i = msgno + 1; i < Context->vcount; i++)
+    if (!Context->hdrs[Context->v2r[i]]->deleted)
       return (i);
   return (-1);
 }
@@ -195,8 +209,8 @@ static int ci_previous_undeleted (int msgno)
 {
   int i;
 
-  for (i=msgno-1; i>=0; i--)
-    if (! Context->hdrs[Context->v2r[i]]->deleted)
+  for (i = msgno - 1; i >= 0; i--)
+    if (!Context->hdrs[Context->v2r[i]]->deleted)
       return (i);
   return (-1);
 }
@@ -208,17 +222,14 @@ static int ci_first_message (void)
 {
   int old = -1, i;
 
-  if (Context && Context->msgcount)
-  {
-    for (i=0; i < Context->vcount; i++)
-    {
-      if (! Context->hdrs[Context->v2r[i]]->read &&
-         ! Context->hdrs[Context->v2r[i]]->deleted)
-      {
-       if (! Context->hdrs[Context->v2r[i]]->old)
-         return (i);
-       else if (old == -1)
-         old = i;
+  if (Context && Context->msgcount) {
+    for (i = 0; i < Context->vcount; i++) {
+      if (!Context->hdrs[Context->v2r[i]]->read &&
+          !Context->hdrs[Context->v2r[i]]->deleted) {
+        if (!Context->hdrs[Context->v2r[i]]->old)
+          return (i);
+        else if (old == -1)
+          old = i;
       }
     }
     if (old != -1)
@@ -229,8 +240,8 @@ static int ci_first_message (void)
      * of Sort and SortAux are reverse.
      */
     if (((Sort & SORT_REVERSE) && (Sort & SORT_MASK) != SORT_THREADS) ||
-       ((Sort & SORT_MASK) == SORT_THREADS &&
-        ((Sort ^ SortAux) & SORT_REVERSE)))
+        ((Sort & SORT_MASK) == SORT_THREADS &&
+         ((Sort ^ SortAux) & SORT_REVERSE)))
       return 0;
     else
       return (Context->vcount ? Context->vcount - 1 : 0);
@@ -239,139 +250,125 @@ static int ci_first_message (void)
 }
 
 /* This should be in mx.c, but it only gets used here. */
-static int mx_toggle_write (CONTEXT *ctx)
+static int mx_toggle_write (CONTEXT * ctx)
 {
   if (!ctx)
     return -1;
 
-  if (ctx->readonly)
-  {
-    mutt_error _("Cannot toggle write on a readonly mailbox!");
+  if (ctx->readonly) {
+    mutt_error (_("Cannot toggle write on a readonly mailbox!"));
+
     return -1;
   }
 
-  if (ctx->dontwrite)
-  {
+  if (ctx->dontwrite) {
     ctx->dontwrite = 0;
-    mutt_message _("Changes to folder will be written on folder exit.");
+    mutt_message (_("Changes to folder will be written on folder exit."));
   }
-  else
-  {
+  else {
     ctx->dontwrite = 1;
-    mutt_message _("Changes to folder will not be written.");
+    mutt_message (_("Changes to folder will not be written."));
   }
 
   return 0;
 }
 
-static void update_index (MUTTMENU *menu, CONTEXT *ctx, int check,
-                         int oldcount, int index_hint)
+static void update_index (MUTTMENU * menu, CONTEXT * ctx, int check,
+                          int oldcount, int index_hint)
 {
   /* store pointers to the newly added messages */
-  HEADER  **save_new = NULL;
+  HEADER **save_new = NULL;
   int j;
-  
+
   /* take note of the current message */
-  if (oldcount)
-  {
+  if (oldcount) {
     if (menu->current < Context->vcount)
       menu->oldcurrent = index_hint;
     else
-      oldcount = 0; /* invalid message number! */
+      oldcount = 0;             /* invalid message number! */
   }
-  
+
   /* We are in a limited view. Check if the new message(s) satisfy
    * the limit criteria. If they do, set their virtual msgno so that
    * they will be visible in the limited view */
-  if (Context->pattern)
-  {
+  if (Context->pattern) {
 #define THIS_BODY Context->hdrs[j]->content
-    if (oldcount || check == M_REOPENED)
-    {
-      for (j = (check == M_REOPENED) ? 0 : oldcount; j < Context->msgcount; j++)
-      {
-       if (mutt_pattern_exec (Context->limit_pattern,
-                              M_MATCH_FULL_ADDRESS, 
-                              Context, Context->hdrs[j]))
-       {
-         Context->hdrs[j]->virtual = Context->vcount;
-         Context->v2r[Context->vcount] = j;
-         Context->hdrs[j]->limited = 1;
-         Context->vcount++;
-         Context->vsize += THIS_BODY->length + THIS_BODY->offset - THIS_BODY->hdr_offset;
-       }
+    if (oldcount || check == M_REOPENED) {
+      for (j = (check == M_REOPENED) ? 0 : oldcount; j < Context->msgcount;
+           j++) {
+        if (mutt_pattern_exec
+            (Context->limit_pattern, M_MATCH_FULL_ADDRESS, Context,
+             Context->hdrs[j])) {
+          Context->hdrs[j]->virtual = Context->vcount;
+          Context->v2r[Context->vcount] = j;
+          Context->hdrs[j]->limited = 1;
+          Context->vcount++;
+          Context->vsize +=
+            THIS_BODY->length + THIS_BODY->offset - THIS_BODY->hdr_offset;
+        }
       }
     }
 #undef THIS_BODY
   }
-    
+
   /* save the list of new messages */
-  if (oldcount && check != M_REOPENED
-      && ((Sort & SORT_MASK) == SORT_THREADS))
-  {
-    save_new = (HEADER **) safe_malloc (sizeof (HEADER *) * (Context->msgcount - oldcount));
+  if (oldcount && check != M_REOPENED && ((Sort & SORT_MASK) == SORT_THREADS)) {
+    save_new =
+      (HEADER **) safe_malloc (sizeof (HEADER *) *
+                               (Context->msgcount - oldcount));
     for (j = oldcount; j < Context->msgcount; j++)
-      save_new[j-oldcount] = Context->hdrs[j];
+      save_new[j - oldcount] = Context->hdrs[j];
   }
-  
+
   /* if the mailbox was reopened, need to rethread from scratch */
   mutt_sort_headers (Context, (check == M_REOPENED));
 
   /* uncollapse threads with new mail */
-  if ((Sort & SORT_MASK) == SORT_THREADS)
-  {
-    if (check == M_REOPENED)
-    {
+  if ((Sort & SORT_MASK) == SORT_THREADS) {
+    if (check == M_REOPENED) {
       THREAD *h, *j;
-      
+
       Context->collapsed = 0;
-      
-      for (h = Context->tree; h; h = h->next)
-      {
-       for (j = h; !j->message; j = j->child)
-         ;
-       mutt_uncollapse_thread (Context, j->message);
+
+      for (h = Context->tree; h; h = h->next) {
+        for (j = h; !j->message; j = j->child);
+        mutt_uncollapse_thread (Context, j->message);
       }
       mutt_set_virtual (Context);
     }
-    else if (oldcount)
-    {
-      for (j = 0; j < Context->msgcount - oldcount; j++)
-      {
-       int k;
-       
-       for (k = 0; k < Context->msgcount; k++)
-       {
-         HEADER *h = Context->hdrs[k];
-         if (h == save_new[j] && (!Context->pattern || h->limited))
-           mutt_uncollapse_thread (Context, h);
-       }
+    else if (oldcount) {
+      for (j = 0; j < Context->msgcount - oldcount; j++) {
+        int k;
+
+        for (k = 0; k < Context->msgcount; k++) {
+          HEADER *h = Context->hdrs[k];
+
+          if (h == save_new[j] && (!Context->pattern || h->limited))
+            mutt_uncollapse_thread (Context, h);
+        }
       }
       FREE (&save_new);
       mutt_set_virtual (Context);
     }
   }
-  
+
   menu->current = -1;
-  if (oldcount)
-  {
+  if (oldcount) {
     /* restore the current message to the message it was pointing to */
-    for (j = 0; j < Context->vcount; j++)
-    {
-      if (Context->hdrs[Context->v2r[j]]->index == menu->oldcurrent)
-      {
-       menu->current = j;
-       break;
+    for (j = 0; j < Context->vcount; j++) {
+      if (Context->hdrs[Context->v2r[j]]->index == menu->oldcurrent) {
+        menu->current = j;
+        break;
       }
     }
   }
-  
+
   if (menu->current < 0)
     menu->current = ci_first_message ();
-  
+
 }
 
-static void resort_index (MUTTMENU *menu)
+static void resort_index (MUTTMENU * menu)
 {
   int i;
   HEADER *current = CURHDR;
@@ -380,47 +377,45 @@ static void resort_index (MUTTMENU *menu)
   mutt_sort_headers (Context, 0);
   /* Restore the current message */
 
-  for (i = 0; i < Context->vcount; i++)
-  {
-    if (Context->hdrs[Context->v2r[i]] == current)
-    {
+  for (i = 0; i < Context->vcount; i++) {
+    if (Context->hdrs[Context->v2r[i]] == current) {
       menu->current = i;
       break;
     }
   }
-  
+
   if ((Sort & SORT_MASK) == SORT_THREADS && menu->current < 0)
     menu->current = mutt_parent_message (Context, current);
-  
+
   if (menu->current < 0)
     menu->current = ci_first_message ();
-  
+
   menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
 }
 
 struct mapping_t IndexHelp[] = {
-  { N_("Quit"),  OP_QUIT },
-  { N_("Del"),   OP_DELETE },
-  { N_("Undel"), OP_UNDELETE },
-  { N_("Save"),  OP_SAVE },
-  { N_("Mail"),  OP_MAIL },
-  { N_("Reply"), OP_REPLY },
-  { N_("Group"), OP_GROUP_REPLY },
-  { N_("Help"),  OP_HELP },
-  { NULL }
+  {N_("Quit"), OP_QUIT},
+  {N_("Del"), OP_DELETE},
+  {N_("Undel"), OP_UNDELETE},
+  {N_("Save"), OP_SAVE},
+  {N_("Mail"), OP_MAIL},
+  {N_("Reply"), OP_REPLY},
+  {N_("Group"), OP_GROUP_REPLY},
+  {N_("Help"), OP_HELP},
+  {NULL}
 };
 
 #ifdef USE_NNTP
 struct mapping_t IndexNewsHelp[] = {
-  { N_("Quit"),     OP_QUIT },
-  { N_("Del"),      OP_DELETE },
-  { N_("Undel"),    OP_UNDELETE },
-  { N_("Save"),     OP_SAVE },
-  { N_("Post"),     OP_POST },
-  { N_("Followup"), OP_FOLLOWUP },
-  { N_("Catchup"),  OP_CATCHUP },
-  { N_("Help"),     OP_HELP },
-  { NULL }
+  {N_("Quit"), OP_QUIT},
+  {N_("Del"), OP_DELETE},
+  {N_("Undel"), OP_UNDELETE},
+  {N_("Save"), OP_SAVE},
+  {N_("Post"), OP_POST},
+  {N_("Followup"), OP_FOLLOWUP},
+  {N_("Catchup"), OP_CATCHUP},
+  {N_("Help"), OP_HELP},
+  {NULL}
 };
 #endif
 
@@ -432,19 +427,19 @@ int mutt_index_menu (void)
   char buf[LONG_STRING], helpstr[SHORT_STRING];
   int flags;
   int op = OP_NULL;
-  int done = 0;                /* controls when to exit the "event" loop */
+  int done = 0;                 /* controls when to exit the "event" loop */
   int i = 0, j;
-  int tag = 0;                 /* has the tag-prefix command been pressed? */
+  int tag = 0;                  /* has the tag-prefix command been pressed? */
   int newcount = -1;
   int oldcount = -1;
   int rc = -1;
   MUTTMENU *menu;
-  char *cp;                    /* temporary variable. */
-  int index_hint;   /* used to restore cursor position */
+  char *cp;                     /* temporary variable. */
+  int index_hint;               /* used to restore cursor position */
   int do_buffy_notify = 1;
-  int close = 0; /* did we OP_QUIT or OP_EXIT out of this menu? */
-  int attach_msg = option(OPTATTACHMSG);
-  
+  int close = 0;                /* did we OP_QUIT or OP_EXIT out of this menu? */
+  int attach_msg = option (OPTATTACHMSG);
+
   menu = mutt_new_menu ();
   menu->menu = MENU_MAIN;
   menu->offset = 1;
@@ -454,16 +449,21 @@ int mutt_index_menu (void)
   menu->current = ci_first_message ();
   menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN,
 #ifdef USE_NNTP
-       (Context && (Context->magic == M_NNTP)) ? IndexNewsHelp :
+                                  (Context
+                                   && (Context->magic ==
+                                       M_NNTP)) ? IndexNewsHelp :
 #endif
-       IndexHelp);
-  
-  if (!attach_msg) 
-    mutt_buffy_check(1); /* force the buffy check after we enter the folder */
+                                  IndexHelp);
+
+  if (!attach_msg) {
+    mutt_buffy_check (1);       /* force the buffy check after we enter the folder */
+    /* record folder we open to place sidebar indicator properly */
+    if (Context && Context->path)
+      sidebar_set_current (Context->path);
+  }
 
-  FOREVER
-  {
-    tag = 0; /* clear the tag-prefix */
+  FOREVER {
+    tag = 0;                    /* clear the tag-prefix */
 
     menu->max = Context ? Context->vcount : 0;
     oldcount = Context ? Context->msgcount : 0;
@@ -474,17 +474,17 @@ int mutt_index_menu (void)
      */
     if (option (OPTNEEDRESORT) && Context && Context->msgcount)
       resort_index (menu);
-    
-    if (option (OPTREDRAWTREE) && Context && Context->msgcount && (Sort & SORT_MASK) == SORT_THREADS)
-    {
+
+    if (option (OPTREDRAWTREE) && Context && Context->msgcount
+        && (Sort & SORT_MASK) == SORT_THREADS) {
       mutt_draw_tree (Context);
       menu->redraw |= REDRAW_STATUS;
       unset_option (OPTREDRAWTREE);
     }
 
-    if (Context && !attach_msg)
-    {
+    if (Context && !attach_msg) {
       int check;
+
       /* check for new mail in the mailbox.  If nonzero, then something has
        * changed about the file (either we got new mail or the file was
        * modified underneath us.)
@@ -493,42 +493,43 @@ int mutt_index_menu (void)
 #ifdef USE_IMAP
       imap_allow_reopen (Context);
 #endif
-    
-      index_hint = (Context->vcount && menu->current >= 0 && menu->current < Context->vcount) ? CURHDR->index : 0;
 
-      if ((check = mx_check_mailbox (Context, &index_hint, 0)) < 0)
-      {
-       if (!Context->path)
-       {
-         /* fatal error occurred */
-         FREE (&Context);
-         menu->redraw = REDRAW_FULL;
-       }
+      index_hint = (Context->vcount && menu->current >= 0
+                    && menu->current < Context->vcount) ? CURHDR->index : 0;
 
-       set_option (OPTSEARCHINVALID);
+      if ((check = mx_check_mailbox (Context, &index_hint, 0)) < 0) {
+        if (!Context->path) {
+          /* fatal error occurred */
+          FREE (&Context);
+          menu->redraw = REDRAW_FULL;
+        }
+        set_option (OPTSEARCHINVALID);
       }
-      else if (check == M_NEW_MAIL || check == M_REOPENED || check == M_FLAGS)
-      {
-       update_index (menu, Context, check, oldcount, index_hint);
-       
-       /* notify the user of new mail */
-       if (check == M_REOPENED)
-         mutt_error _("Mailbox was externally modified.  Flags may be wrong.");
-       else if (check == M_NEW_MAIL)
-       {
-         mutt_message _("New mail in this mailbox.");
-         if (option (OPTBEEPNEW))
-           beep ();
-       } else if (check == M_FLAGS)
-         mutt_message _("Mailbox was externally modified.");
-
-       /* avoid the message being overwritten by buffy */
-       do_buffy_notify = 0;
-       
-       menu->redraw = REDRAW_FULL;
-       menu->max = Context->vcount;
-       
-       set_option (OPTSEARCHINVALID);
+      else if (check == M_NEW_MAIL || check == M_REOPENED || check == M_FLAGS) {
+        update_index (menu, Context, check, oldcount, index_hint);
+
+        /* notify the user of new mail */
+        if (check == M_REOPENED)
+          mutt_error (_
+                      ("Mailbox was externally modified.  Flags may be wrong."));
+        else if (check == M_NEW_MAIL) {
+          /* on new mail: redraw sidebar */
+          sidebar_draw (CurrentMenu);
+          mutt_message (_("New mail in this mailbox."));
+
+          if (option (OPTBEEPNEW))
+            beep ();
+        }
+        else if (check == M_FLAGS)
+          mutt_message (_("Mailbox was externally modified."));
+
+        /* avoid the message being overwritten by buffy */
+        do_buffy_notify = 0;
+
+        menu->redraw = REDRAW_FULL;
+        menu->max = Context->vcount;
+
+        set_option (OPTSEARCHINVALID);
       }
     }
 
@@ -537,1820 +538,1860 @@ int mutt_index_menu (void)
     imap_disallow_reopen (Context);
 #endif
 
-    if (!attach_msg)
-    {
-     /* check for new mail in the incoming folders */
-     oldcount = newcount;
-     if ((newcount = mutt_buffy_check (0)) != oldcount)
-       menu->redraw |= REDRAW_STATUS;
-     if (do_buffy_notify)
-     {
-       if (mutt_buffy_notify () && option (OPTBEEPNEW))
-       beep ();
-     }
-     else
-       do_buffy_notify = 1;
+    if (!attach_msg) {
+      /* check for new mail in the incoming folders */
+      oldcount = newcount;
+      if ((newcount = mutt_buffy_check (0)) != oldcount) {
+        menu->redraw |= REDRAW_STATUS;
+        menu->redraw |= REDRAW_SIDEBAR;
+      }
+      if (do_buffy_notify) {
+        if (mutt_buffy_notify () && option (OPTBEEPNEW))
+          beep ();
+      }
+      else
+        do_buffy_notify = 1;
     }
 
     if (op != -1)
       mutt_curs_set (0);
-
-    if (menu->redraw & REDRAW_FULL)
-    {
+    if (menu->redraw & REDRAW_SIDEBAR)
+      sidebar_draw (menu->menu);
+    if (menu->redraw & REDRAW_FULL) {
       menu_redraw_full (menu);
+      sidebar_draw (menu->menu);
       mutt_show_error ();
     }
 
-    if (menu->menu == MENU_MAIN)
-    {
-      if (Context && Context->hdrs && !(menu->current >= Context->vcount))
-      {
-       menu_check_recenter (menu);
+    if (menu->menu == MENU_MAIN) {
+      if (Context && Context->hdrs && !(menu->current >= Context->vcount)) {
+        menu_check_recenter (menu);
 
-       if (menu->redraw & REDRAW_INDEX)
-       {
-         menu_redraw_index (menu);
-         menu->redraw |= REDRAW_STATUS;
-       }
-       else if (menu->redraw & (REDRAW_MOTION_RESYNCH | REDRAW_MOTION))
-         menu_redraw_motion (menu);
-       else if (menu->redraw & REDRAW_CURRENT)
-         menu_redraw_current (menu);
+        if (menu->redraw & REDRAW_INDEX) {
+          menu_redraw_index (menu);
+          menu->redraw |= REDRAW_STATUS;
+        }
+        else if (menu->redraw & (REDRAW_MOTION_RESYNCH | REDRAW_MOTION))
+          menu_redraw_motion (menu);
+        else if (menu->redraw & REDRAW_CURRENT)
+          menu_redraw_current (menu);
       }
 
-      if (menu->redraw & REDRAW_STATUS) 
-      {
-       menu_status_line (buf, sizeof (buf), menu, NONULL (Status));
-       CLEARLINE (option (OPTSTATUSONTOP) ? 0 : LINES-2);
-       SETCOLOR (MT_COLOR_STATUS);
-       mutt_paddstr (COLS, buf);
-       SETCOLOR (MT_COLOR_NORMAL);
-       menu->redraw &= ~REDRAW_STATUS;
+      if (menu->redraw & REDRAW_STATUS) {
+        DrawFullLine = 1;
+        menu_status_line (buf, sizeof (buf), menu, NONULL (Status));
+        DrawFullLine = 0;
+        CLEARLINE (option (OPTSTATUSONTOP) ? 0 : LINES - 2);
+        SETCOLOR (MT_COLOR_STATUS);
+        mutt_paddstr (COLS, buf);
+        SETCOLOR (MT_COLOR_NORMAL);
+        sidebar_set_buffystats (Context);
+        menu->redraw &= ~REDRAW_STATUS;
+        if (option (OPTXTERMSETTITLES)) {
+          menu_status_line (buf, sizeof (buf), menu, NONULL (XtermTitle));
+          set_xterm_title_bar (buf);
+          menu_status_line (buf, sizeof (buf), menu, NONULL (XtermIcon));
+          set_xterm_icon_name (buf);
+        }
       }
 
       menu->redraw = 0;
       if (menu->current < menu->max)
-       menu->oldcurrent = menu->current;
+        menu->oldcurrent = menu->current;
       else
-       menu->oldcurrent = -1;
+        menu->oldcurrent = -1;
 
       if (option (OPTARROWCURSOR))
-       move (menu->current - menu->top + menu->offset, 2);
+        move (menu->current - menu->top + menu->offset, 2);
       else
-       move (menu->current - menu->top + menu->offset, COLS - 1);
+        move (menu->current - menu->top + menu->offset, COLS - 1);
       mutt_refresh ();
 
       op = km_dokey (MENU_MAIN);
 
-      dprint(4, (debugfile, "mutt_index_menu[%d]: Got op %d\n", __LINE__, op));
+      dprint (4,
+              (debugfile, "mutt_index_menu[%d]: Got op %d\n", __LINE__, op));
 
 #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
-      if (SigWinch)
-      {
-       mutt_flushinp ();
-       mutt_resize_screen ();
-       menu->redraw = REDRAW_FULL;
-       menu->menu = MENU_MAIN;
-       SigWinch = 0;
-       menu->top = 0; /* so we scroll the right amount */
-       /*
-        * force a real complete redraw.  clrtobot() doesn't seem to be able
-        * to handle every case without this.
-        */
-       clearok(stdscr,TRUE);
-       continue;
+      if (SigWinch) {
+        mutt_flushinp ();
+        mutt_resize_screen ();
+        menu->redraw = REDRAW_FULL;
+        menu->menu = MENU_MAIN;
+        SigWinch = 0;
+        menu->top = 0;          /* so we scroll the right amount */
+        /*
+         * force a real complete redraw.  clrtobot() doesn't seem to be able
+         * to handle every case without this.
+         */
+        clearok (stdscr, TRUE);
+        continue;
       }
 #endif
 
       if (op == -1)
-       continue; /* either user abort or timeout */
-      
+        continue;               /* either user abort or timeout */
+
       mutt_curs_set (1);
-      
+
       /* special handling for the tag-prefix function */
-      if (op == OP_TAG_PREFIX)
-      {
-       if (!Context)
-       {
-         mutt_error _("No mailbox is open.");
-         continue;
-       }
-
-       if (!Context->tagged)
-       {
-         mutt_error _("No tagged messages.");
-         continue;
-       }
-       tag = 1;
-
-       /* give visual indication that the next command is a tag- command */
-       mvaddstr (LINES - 1, 0, "tag-");
-       clrtoeol ();
-
-       /* get the real command */
-       if ((op = km_dokey (MENU_MAIN)) == OP_TAG_PREFIX)
-       {
-         /* abort tag sequence */
-         CLEARLINE (LINES-1);
-         continue;
-       }
+      if (op == OP_TAG_PREFIX) {
+        if (!Context) {
+          mutt_error (_("No mailbox is open."));
+
+          continue;
+        }
+
+        if (!Context->tagged) {
+          mutt_error (_("No tagged messages."));
+
+          continue;
+        }
+        tag = 1;
+
+        /* give visual indication that the next command is a tag- command */
+        mvaddstr (LINES - 1, 0, "tag-");
+        clrtoeol ();
+
+        /* get the real command */
+        if ((op = km_dokey (MENU_MAIN)) == OP_TAG_PREFIX) {
+          /* abort tag sequence */
+          CLEARLINE (LINES - 1);
+          continue;
+        }
       }
       else if (option (OPTAUTOTAG) && Context && Context->tagged)
-       tag = 1;
+        tag = 1;
 
-      if (op == OP_TAG_PREFIX_COND)
-      {
-       if (!Context)
-       {
-         mutt_error _("No mailbox is open.");
-         continue;
-       }
-
-       if (!Context->tagged)
-       {
-         event_t tmp;
-         while(UngetCount>0)
-         {
-           tmp=mutt_getch();
-           if(tmp.op==OP_END_COND)break;
-         }
-         mutt_message  _("Nothing to do.");
-         continue;
-       }
-       tag = 1;
-
-       /* give visual indication that the next command is a tag- command */
-       mvaddstr (LINES - 1, 0, "tag-");
-       clrtoeol ();
-
-       /* get the real command */
-       if ((op = km_dokey (MENU_MAIN)) == OP_TAG_PREFIX)
-       {
-         /* abort tag sequence */
-         CLEARLINE (LINES-1);
-         continue;
-       }
+      if (op == OP_TAG_PREFIX_COND) {
+        if (!Context) {
+          mutt_error (_("No mailbox is open."));
+
+          continue;
+        }
+
+        if (!Context->tagged) {
+          event_t tmp;
+
+          while (UngetCount > 0) {
+            tmp = mutt_getch ();
+            if (tmp.op == OP_END_COND)
+              break;
+          }
+          mutt_message (_("Nothing to do."));
+
+          continue;
+        }
+        tag = 1;
+
+        /* give visual indication that the next command is a tag- command */
+        mvaddstr (LINES - 1, 0, "tag-");
+        clrtoeol ();
+
+        /* get the real command */
+        if ((op = km_dokey (MENU_MAIN)) == OP_TAG_PREFIX) {
+          /* abort tag sequence */
+          CLEARLINE (LINES - 1);
+          continue;
+        }
       }
 
       mutt_clear_error ();
     }
-    else
-    {
+    else {
       if (menu->current < menu->max)
-       menu->oldcurrent = menu->current;
+        menu->oldcurrent = menu->current;
       else
-       menu->oldcurrent = -1;
-      
-      mutt_curs_set (1);       /* fallback from the pager */
+        menu->oldcurrent = -1;
+
+      mutt_curs_set (1);        /* fallback from the pager */
     }
 
 #ifdef USE_NNTP
-    unset_option (OPTNEWS);    /* for any case */
+    unset_option (OPTNEWS);     /* for any case */
 #endif
-    switch (op)
-    {
+
+    switch (op) {
 
       /* ----------------------------------------------------------------------
        * movement commands
        */
 
-      case OP_BOTTOM_PAGE:
-       menu_bottom_page (menu);
-       break;
-      case OP_FIRST_ENTRY:
-       menu_first_entry (menu);
-       break;
-      case OP_MIDDLE_PAGE:
-       menu_middle_page (menu);
-       break;
-      case OP_HALF_UP:
-       menu_half_up (menu);
-       break;
-      case OP_HALF_DOWN:
-       menu_half_down (menu);
-       break;
-      case OP_NEXT_LINE:
-       menu_next_line (menu);
-       break;
-      case OP_PREV_LINE:
-       menu_prev_line (menu);
-       break;
-      case OP_NEXT_PAGE:
-       menu_next_page (menu);
-       break;
-      case OP_PREV_PAGE:
-       menu_prev_page (menu);
-       break;
-      case OP_LAST_ENTRY:
-       menu_last_entry (menu);
-       break;
-      case OP_TOP_PAGE:
-       menu_top_page (menu);
-       break;
-      case OP_CURRENT_TOP:
-       menu_current_top (menu);
-       break;
-      case OP_CURRENT_MIDDLE:
-       menu_current_middle (menu);
-       break;
-      case OP_CURRENT_BOTTOM:
-       menu_current_bottom (menu);
-       break;
+    case OP_BOTTOM_PAGE:
+      menu_bottom_page (menu);
+      break;
+    case OP_FIRST_ENTRY:
+      menu_first_entry (menu);
+      break;
+    case OP_MIDDLE_PAGE:
+      menu_middle_page (menu);
+      break;
+    case OP_HALF_UP:
+      menu_half_up (menu);
+      break;
+    case OP_HALF_DOWN:
+      menu_half_down (menu);
+      break;
+    case OP_NEXT_LINE:
+      menu_next_line (menu);
+      break;
+    case OP_PREV_LINE:
+      menu_prev_line (menu);
+      break;
+    case OP_NEXT_PAGE:
+      menu_next_page (menu);
+      break;
+    case OP_PREV_PAGE:
+      menu_prev_page (menu);
+      break;
+    case OP_LAST_ENTRY:
+      menu_last_entry (menu);
+      break;
+    case OP_TOP_PAGE:
+      menu_top_page (menu);
+      break;
+    case OP_CURRENT_TOP:
+      menu_current_top (menu);
+      break;
+    case OP_CURRENT_MIDDLE:
+      menu_current_middle (menu);
+      break;
+    case OP_CURRENT_BOTTOM:
+      menu_current_bottom (menu);
+      break;
 
 #ifdef USE_NNTP
-      case OP_GET_MESSAGE:
-      case OP_GET_PARENT:
-       CHECK_MSGCOUNT;
-       if (Context->magic == M_NNTP)
-       {
-         HEADER *h;
-
-         if (op == OP_GET_MESSAGE)
-         {
-           buf[0] = 0;
-           if (mutt_get_field (_("Enter Message-Id: "), buf, sizeof (buf), 0) != 0
-                 || !buf[0])
-             break;
-         }
-         else
-         {
-           LIST *ref = CURHDR->env->references;
-           if (!ref)
-           {
-             mutt_error _("Article has no parent reference!");
-             break;
-           }
-           strfcpy (buf, ref->data, sizeof (buf));
-         }
-         if (!Context->id_hash)
-           Context->id_hash = mutt_make_id_hash (Context);
-         if ((h = hash_find (Context->id_hash, buf)))
-         {
-           if (h->virtual != -1)
-           {
-             menu->current = h->virtual;
-             menu->redraw = REDRAW_MOTION_RESYNCH;
-           }
-           else if (h->collapsed)
-           {
-             mutt_uncollapse_thread (Context, h);
-             mutt_set_virtual (Context);
-             menu->current = h->virtual;
-             menu->redraw = REDRAW_MOTION_RESYNCH;
-           }
-           else
-             mutt_error _("Message not visible in limited view.");
-         }
-         else
-         {
-           if (nntp_check_msgid (Context, buf) == 0)
-           {
-             h = Context->hdrs[Context->msgcount-1];
-             mutt_sort_headers (Context, 0);
-             menu->current = h->virtual;
-             menu->redraw = REDRAW_FULL;
-           }
-           else
-             mutt_error (_("Article %s not found on server"), buf); 
-         }
-       }
-       break;
-
-      case OP_GET_CHILDREN:
-      case OP_RECONSTRUCT_THREAD:
-       CHECK_MSGCOUNT;
-       if (Context->magic == M_NNTP)
-       {
-         HEADER *h;
-         int old = CURHDR->index, i;
-
-         if (!CURHDR->env->message_id)
-         {
-           mutt_error _("No Message-Id. Unable to perform operation");
-           break;
-         }
-
-         if (!Context->id_hash)
-           Context->id_hash = mutt_make_id_hash (Context);
-         strfcpy (buf, CURHDR->env->message_id, sizeof (buf));
-
-         if (op == OP_RECONSTRUCT_THREAD)
-         {
-           LIST *ref = CURHDR->env->references;
-           while (ref)
-           {
-             nntp_check_msgid (Context, ref->data);
-             /* the last msgid in References is the root message */
-             if (!ref->next)
-               strfcpy (buf, ref->data, sizeof (buf));
-             ref = ref->next;
-           }
-         }
-         mutt_message _("Check for children of message...");
-         if (nntp_check_children (Context, buf) == 0)
-         {
-           mutt_sort_headers (Context, (op == OP_RECONSTRUCT_THREAD));
-           h = hash_find (Context->id_hash, buf);
-           /* if the root message was retrieved, move to it */
-           if (h)
-             menu->current = h->virtual;
-           else /* try to restore old position */
-             for (i = 0; i < Context->msgcount; i++)
-               if (Context->hdrs[i]->index == old)
-               {
-                 menu->current = Context->hdrs[i]->virtual;
-                 /* As an added courtesy, recenter the menu
-                  * with the current entry at the middle of the screen */
-                 menu_check_recenter (menu);
-                 menu_current_middle (menu);
-               }
-         }
-         menu->redraw = REDRAW_FULL;
-         mutt_clear_error ();
-       }
-       break;
-#endif
+    case OP_GET_MESSAGE:
+    case OP_GET_PARENT:
+      CHECK_MSGCOUNT;
+      if (Context->magic == M_NNTP) {
+        HEADER *h;
+
+        if (op == OP_GET_MESSAGE) {
+          buf[0] = 0;
+          if (mutt_get_field (_("Enter Message-Id: "), buf, sizeof (buf), 0)
+              != 0 || !buf[0])
+            break;
+        }
+        else {
+          LIST *ref = CURHDR->env->references;
 
-      case OP_JUMP:
+          if (!ref) {
+            mutt_error (_("Article has no parent reference!"));
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-        if (isdigit (LastKey)) mutt_ungetch (LastKey, 0);
-       buf[0] = 0;
-       if (mutt_get_field (_("Jump to message: "), buf, sizeof (buf), 0) != 0
-           || !buf[0])
-         break;
-
-       if (! isdigit ((unsigned char) buf[0]))
-       {
-         mutt_error _("Argument must be a message number.");
-         break;
-       }
-
-       i = atoi (buf);
-       if (i > 0 && i <= Context->msgcount)
-       {
-         for (j = i-1; j < Context->msgcount; j++)
-         {
-           if (Context->hdrs[j]->virtual != -1)
-             break;
-         }
-         if (j >= Context->msgcount)
-         {
-           for (j = i-2; j >= 0; j--)
-           {
-             if (Context->hdrs[j]->virtual != -1)
-               break;
-           }
-         }
-
-         if (j >= 0)
-         {
-           menu->current = Context->hdrs[j]->virtual;
-           if (menu->menu == MENU_PAGER)
-           {
-             op = OP_DISPLAY_MESSAGE;
-             continue;
-           }
-           else
-           menu->redraw = REDRAW_MOTION;
-         }
-         else
-           mutt_error _("That message is not visible.");
-       }
-       else
-         mutt_error _("Invalid message number.");
-
-       break;
-
-       /* --------------------------------------------------------------------
-        * `index' specific commands
-        */
-
-      case OP_MAIN_DELETE_PATTERN:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_READONLY;
+            break;
+          }
+          strfcpy (buf, ref->data, sizeof (buf));
+        }
+        if (!Context->id_hash)
+          Context->id_hash = mutt_make_id_hash (Context);
+        if ((h = hash_find (Context->id_hash, buf))) {
+          if (h->virtual != -1) {
+            menu->current = h->virtual;
+            menu->redraw = REDRAW_MOTION_RESYNCH;
+          }
+          else if (h->collapsed) {
+            mutt_uncollapse_thread (Context, h);
+            mutt_set_virtual (Context);
+            menu->current = h->virtual;
+            menu->redraw = REDRAW_MOTION_RESYNCH;
+          }
+          else
+            mutt_error (_("Message not visible in limited view."));
+        }
+        else {
+          if (nntp_check_msgid (Context, buf) == 0) {
+            h = Context->hdrs[Context->msgcount - 1];
+            mutt_sort_headers (Context, 0);
+            menu->current = h->virtual;
+            menu->redraw = REDRAW_FULL;
+          }
+          else
+            mutt_error (_("Article %s not found on server"), buf);
+        }
+      }
+      break;
 
-#ifdef USE_IMAP
-CHECK_IMAP_ACL(IMAP_ACL_DELETE);
-#endif
+    case OP_GET_CHILDREN:
+    case OP_RECONSTRUCT_THREAD:
+      CHECK_MSGCOUNT;
+      if (Context->magic == M_NNTP) {
+        HEADER *h;
+        int old = CURHDR->index, i;
 
-       CHECK_ATTACH;
-       mutt_pattern_func (M_DELETE, _("Delete messages matching: "));
-       menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-       break;
+        if (!CURHDR->env->message_id) {
+          mutt_error (_("No Message-Id. Unable to perform operation"));
 
-#ifdef USE_POP
-      case OP_MAIN_FETCH_MAIL:
+          break;
+        }
 
-       CHECK_ATTACH;
-       pop_fetch_mail ();
-       menu->redraw = REDRAW_FULL;
-       break;
-#endif /* USE_POP */
+        if (!Context->id_hash)
+          Context->id_hash = mutt_make_id_hash (Context);
+        strfcpy (buf, CURHDR->env->message_id, sizeof (buf));
 
-      case OP_HELP:
+        if (op == OP_RECONSTRUCT_THREAD) {
+          LIST *ref = CURHDR->env->references;
+
+          while (ref) {
+            nntp_check_msgid (Context, ref->data);
+            /* the last msgid in References is the root message */
+            if (!ref->next)
+              strfcpy (buf, ref->data, sizeof (buf));
+            ref = ref->next;
+          }
+        }
+        mutt_message (_("Check for children of message..."));
+
+        if (nntp_check_children (Context, buf) == 0) {
+          mutt_sort_headers (Context, (op == OP_RECONSTRUCT_THREAD));
+          h = hash_find (Context->id_hash, buf);
+          /* if the root message was retrieved, move to it */
+          if (h)
+            menu->current = h->virtual;
+          else                  /* try to restore old position */
+            for (i = 0; i < Context->msgcount; i++)
+              if (Context->hdrs[i]->index == old) {
+                menu->current = Context->hdrs[i]->virtual;
+                /* As an added courtesy, recenter the menu
+                 * with the current entry at the middle of the screen */
+                menu_check_recenter (menu);
+                menu_current_middle (menu);
+              }
+        }
+        menu->redraw = REDRAW_FULL;
+        mutt_clear_error ();
+      }
+      break;
+#endif
 
-       mutt_help (MENU_MAIN);
-       menu->redraw = REDRAW_FULL;
-       break;
+    case OP_JUMP:
 
-      case OP_MAIN_SHOW_LIMIT:
-        CHECK_MSGCOUNT;
-       if (!Context->pattern)
-          mutt_message _("No limit pattern is in effect.");
-       else
-       {
-          char buf[STRING];
-          /* i18n: ask for a limit to apply */
-          snprintf (buf, sizeof(buf), _("Limit: %s"),Context->pattern);
-           mutt_message ("%s", buf);
-       }
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      if (isdigit (LastKey))
+        mutt_ungetch (LastKey, 0);
+      buf[0] = 0;
+      if (mutt_get_field (_("Jump to message: "), buf, sizeof (buf), 0) != 0
+          || !buf[0])
         break;
 
-      case OP_MAIN_LIMIT:
-      case OP_TOGGLE_READ:
-
-       CHECK_MSGCOUNT;
-       menu->oldcurrent = (Context->vcount && menu->current >= 0 && menu->current < Context->vcount) ?
-               CURHDR->index : -1;
-       if (op == OP_TOGGLE_READ)
-       {
-         char buf[LONG_STRING];
-
-         if (!Context->pattern || strncmp (Context->pattern, "!~R!~D~s", 8) != 0)
-         {
-           snprintf (buf, sizeof (buf), "!~R!~D~s%s",
-                     Context->pattern ? Context->pattern : ".*");
-           set_option (OPTHIDEREAD);
-         }
-         else
-         {
-           strfcpy (buf, Context->pattern + 8, sizeof(buf));
-           if (!*buf || strncmp (buf, ".*", 2) == 0)
-             snprintf (buf, sizeof(buf), "~A");
-           unset_option (OPTHIDEREAD);
-         }
-         FREE (&Context->pattern);
-         Context->pattern = safe_strdup (buf);
-       }
-       if ((op == OP_TOGGLE_READ && mutt_pattern_func (M_LIMIT, NULL) == 0) ||
-           mutt_pattern_func (M_LIMIT, _("Limit to messages matching: ")) == 0)
-       {
-         if (menu->oldcurrent >= 0)
-         {
-           /* try to find what used to be the current message */
-           menu->current = -1;
-           for (i = 0; i < Context->vcount; i++)
-             if (Context->hdrs[Context->v2r[i]]->index == menu->oldcurrent)
-             {
-               menu->current = i;
-               break;
-             }
-           if (menu->current < 0) menu->current = 0;
-         }
-         else
-           menu->current = 0;
-         menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-         if ((Sort & SORT_MASK) == SORT_THREADS)
-           mutt_draw_tree (Context);
-         menu->redraw = REDRAW_FULL;
-       }
-       break;    
-
-      case OP_QUIT:
-
-       close = op;
-       if (attach_msg)
-       {
-        done = 1;
-        break;
-       }
-
-       if (query_quadoption (OPT_QUIT, _("Quit Mutt?")) == M_YES)
-       {
-         int check;
-         
-         oldcount = Context ? Context->msgcount : 0;
-
-         if (!Context || (check = mx_close_mailbox (Context, &index_hint)) == 0)
-           done = 1;
-         else
-         {
-           if (check == M_NEW_MAIL || check == M_REOPENED)
-             update_index (menu, Context, check, oldcount, index_hint);
-
-           menu->redraw = REDRAW_FULL; /* new mail arrived? */
-           set_option (OPTSEARCHINVALID);
-         }
-       }
-       break;
-
-      case OP_REDRAW:
-
-       clearok (stdscr, TRUE);
-       menu->redraw = REDRAW_FULL;
-       break;
-
-      case OP_SEARCH:
-      case OP_SEARCH_REVERSE:
-      case OP_SEARCH_NEXT:
-      case OP_SEARCH_OPPOSITE:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       if ((menu->current = mutt_search_command (menu->current, op)) == -1)
-         menu->current = menu->oldcurrent;
-       else
-         menu->redraw = REDRAW_MOTION;
-       break;
-
-      case OP_SORT:
-      case OP_SORT_REVERSE:
-
-       if (mutt_select_sort ((op == OP_SORT_REVERSE)) == 0)
-       {
-         if (Context && Context->msgcount)
-         {
-           resort_index (menu);
-           set_option (OPTSEARCHINVALID);
-         }
-       }
-       break;
-
-      case OP_TAG:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       if (tag && !option (OPTAUTOTAG))
-       {
-         for (j = 0; j < Context->vcount; j++)
-           mutt_set_flag (Context, Context->hdrs[Context->v2r[j]], M_TAG, 0);
-         menu->redraw = REDRAW_STATUS | REDRAW_INDEX;
-       }
-       else
-       {
-         mutt_set_flag (Context, CURHDR, M_TAG, !CURHDR->tagged);
-         menu->redraw = REDRAW_STATUS;
-         if (option (OPTRESOLVE) && menu->current < Context->vcount - 1)
-         {
-           menu->current++;
-           menu->redraw |= REDRAW_MOTION_RESYNCH;
-         }
-         else
-           menu->redraw |= REDRAW_CURRENT;
-       }
-       break;
-
-      case OP_MAIN_TAG_PATTERN:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       mutt_pattern_func (M_TAG, _("Tag messages matching: "));
-       menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-       break;
+      if (!isdigit ((unsigned char) buf[0])) {
+        mutt_error (_("Argument must be a message number."));
 
-      case OP_MAIN_UNDELETE_PATTERN:
+        break;
+      }
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_READONLY;
+      i = atoi (buf);
+      if (i > 0 && i <= Context->msgcount) {
+        for (j = i - 1; j < Context->msgcount; j++) {
+          if (Context->hdrs[j]->virtual != -1)
+            break;
+        }
+        if (j >= Context->msgcount) {
+          for (j = i - 2; j >= 0; j--) {
+            if (Context->hdrs[j]->virtual != -1)
+              break;
+          }
+        }
 
-#ifdef USE_IMAP
-CHECK_IMAP_ACL(IMAP_ACL_DELETE);
-#endif
+        if (j >= 0) {
+          menu->current = Context->hdrs[j]->virtual;
+          if (menu->menu == MENU_PAGER) {
+            op = OP_DISPLAY_MESSAGE;
+            continue;
+          }
+          else
+            menu->redraw = REDRAW_MOTION;
+        }
+        else
+          mutt_error (_("That message is not visible."));
+      }
+      else
+        mutt_error (_("Invalid message number."));
 
-       if (mutt_pattern_func (M_UNDELETE, _("Undelete messages matching: ")) == 0)
-         menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-       break;
+      break;
 
-      case OP_MAIN_UNTAG_PATTERN:
+      /* --------------------------------------------------------------------
+       * `index' specific commands
+       */
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       if (mutt_pattern_func (M_UNTAG, _("Untag messages matching: ")) == 0)
-         menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-       break;
+    case OP_MAIN_DELETE_PATTERN:
 
-       /* --------------------------------------------------------------------
-        * The following operations can be performed inside of the pager.
-        */
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
 
 #ifdef USE_IMAP
-      case OP_MAIN_IMAP_FETCH:
-       if (Context->magic == M_IMAP)
-         imap_check_mailbox (Context, &index_hint, 1);
-        break;
+      CHECK_IMAP_ACL (IMAP_ACL_DELETE);
 #endif
-      
-      case OP_MAIN_SYNC_FOLDER:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_READONLY;
-       {
-         int oldvcount = Context->vcount;
-         int oldcount  = Context->msgcount;
-         int dcount = 0;
-         int check;
-
-         /* calculate the number of messages _above_ the cursor,
-          * so we can keep the cursor on the current message
-          */ 
-         for (j = 0; j <= menu->current; j++)
-         {
-           if (Context->hdrs[Context->v2r[j]]->deleted)
-             dcount++;
-         }
-
-         if ((check = mx_sync_mailbox (Context, &index_hint)) == 0)
-         {
-           if (Context->vcount != oldvcount)
-             menu->current -= dcount;
-           set_option (OPTSEARCHINVALID);
-         }
-         else if (check == M_NEW_MAIL || check == M_REOPENED)
-           update_index (menu, Context, check, oldcount, index_hint);
-
-         /* 
-          * do a sanity check even if mx_sync_mailbox failed.
-          */
-
-         if (menu->current < 0 || menu->current >= Context->vcount)
-           menu->current = ci_first_message ();
-       }
-
-       /* check for a fatal error, or all messages deleted */
-       if (!Context->path)
-         FREE (&Context);
-
-       /* if we were in the pager, redisplay the message */
-       if (menu->menu == MENU_PAGER)
-       {
-         op = OP_DISPLAY_MESSAGE;
-         continue;
-       }
-        else
-         menu->redraw = REDRAW_FULL;
-       break;
 
-      case OP_MAIN_CHANGE_FOLDER:
-      case OP_MAIN_CHANGE_FOLDER_READONLY:
-#ifdef USE_NNTP
-      case OP_MAIN_CHANGE_GROUP:
-      case OP_MAIN_CHANGE_GROUP_READONLY:
-#endif
+      CHECK_ATTACH;
+      mutt_pattern_func (M_DELETE, _("Delete messages matching: "));
+      menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
+      break;
 
-       if (attach_msg || option (OPTREADONLY) ||
-#ifdef USE_NNTP
-           op == OP_MAIN_CHANGE_GROUP_READONLY ||
-#endif
-           op == OP_MAIN_CHANGE_FOLDER_READONLY)
-         flags = M_READONLY;
-       else
-         flags = 0;
+#ifdef USE_POP
+    case OP_MAIN_FETCH_MAIL:
 
-       if (flags)
-          cp = _("Open mailbox in read-only mode");
-        else
-          cp = _("Open mailbox");
+      CHECK_ATTACH;
+      pop_fetch_mail ();
+      menu->redraw = REDRAW_FULL;
+      break;
+#endif /* USE_POP */
 
-       buf[0] = '\0';
-#ifdef USE_NNTP
-       unset_option (OPTNEWS);
-       if (op == OP_MAIN_CHANGE_GROUP ||
-           op == OP_MAIN_CHANGE_GROUP_READONLY)
-       {
-         set_option (OPTNEWS);
-         if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer)))
-           break;
-         if (flags)
-           cp = _("Open newsgroup in read-only mode");
-         else
-           cp = _("Open newsgroup");
-         nntp_buffy (buf);
-       }
-       else
-#endif
-       mutt_buffy (buf, sizeof (buf));
+    case OP_HELP:
 
-       if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1)
-         break;
-       if (!buf[0])
-       {
-         CLEARLINE (LINES-1);
-         break;
-       }
+      mutt_help (MENU_MAIN);
+      menu->redraw = REDRAW_FULL;
+      break;
 
-#ifdef USE_NNTP
-        if (option (OPTNEWS))
-       {
-         unset_option (OPTNEWS);
-          nntp_expand_path (buf, sizeof (buf), &CurrentNewsSrv->conn->account);
-       }
-        else
-#endif
-       mutt_expand_path (buf, sizeof (buf));
-       if (mx_get_magic (buf) <= 0)
-       {
-         mutt_error (_("%s is not a mailbox."), buf);
-         break;
-       }
-
-        if (Context)
-        {
-         int check;
-
-         mutt_str_replace (&LastFolder, Context->path);
-         oldcount = Context ? Context->msgcount : 0;
-
-         if ((check = mx_close_mailbox (Context, &index_hint)) != 0)
-         {
-           if (check == M_NEW_MAIL || check == M_REOPENED)
-             update_index (menu, Context, check, oldcount, index_hint);
-               
-           set_option (OPTSEARCHINVALID);
-           menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-           break;
-         }
-         FREE (&Context);
-       }
-
-        mutt_sleep (0);
-      
-       /* Set CurrentMenu to MENU_MAIN before executing any folder
-        * hooks so that all the index menu functions are available to
-        * the exec command.
-        */
-
-       CurrentMenu = MENU_MAIN;
-       mutt_folder_hook (buf);
-
-       if ((Context = mx_open_mailbox (buf, flags, NULL)) != NULL)
-       {
-         menu->current = ci_first_message ();
-       }
-       else
-         menu->current = 0;
+    case OP_MAIN_SHOW_LIMIT:
+      CHECK_MSGCOUNT;
+      if (!Context->pattern)
+        mutt_message (_("No limit pattern is in effect."));
 
-#ifdef USE_NNTP
-       /* mutt_buffy_check() must be done with mail-reader mode! */
-       menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN,
-         (Context && (Context->magic == M_NNTP)) ? IndexNewsHelp : IndexHelp);
-#endif
-       mutt_clear_error ();
-       mutt_buffy_check(1); /* force the buffy check after we have changed
-                             the folder */
-       menu->redraw = REDRAW_FULL;
-       set_option (OPTSEARCHINVALID);
-       break;
+      else {
+        char buf[STRING];
 
-      case OP_DISPLAY_MESSAGE:
-      case OP_DISPLAY_HEADERS: /* don't weed the headers */
+        /* i18n: ask for a limit to apply */
+        snprintf (buf, sizeof (buf), _("Limit: %s"), Context->pattern);
+        mutt_message ("%s", buf);
+      }
+      break;
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       /*
-        * toggle the weeding of headers so that a user can press the key
-        * again while reading the message.
-        */
-       if (op == OP_DISPLAY_HEADERS)
-         toggle_option (OPTWEED);
-
-       unset_option (OPTNEEDRESORT);
-
-       if ((Sort & SORT_MASK) == SORT_THREADS && CURHDR->collapsed)
-       {
-         mutt_uncollapse_thread (Context, CURHDR);
-         mutt_set_virtual (Context);
-         if (option (OPTUNCOLLAPSEJUMP))
-           menu->current = mutt_thread_next_unread (Context, CURHDR);
-       }
-       if ((op = mutt_display_message (CURHDR)) == -1)
-       {
-         unset_option (OPTNEEDRESORT);
-         break;
-       }
-
-       menu->menu = MENU_PAGER;
-       menu->oldcurrent = menu->current;
-       continue;
-
-      case OP_EXIT:
-
-       close = op;
-       if (menu->menu == MENU_MAIN && attach_msg)
-       {
-        done = 1;
-        break;
-       }
-
-       if ((menu->menu == MENU_MAIN)
-           && (query_quadoption (OPT_QUIT, 
-                                 _("Exit Mutt without saving?")) == M_YES))
-       {
-         if (Context)
-         {
-           mx_fastclose_mailbox (Context);
-           FREE (&Context);
-         }
-         done = 1;
-       }
-       break;
-
-      case OP_EDIT_TYPE:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_ATTACH;
-       mutt_edit_content_type (CURHDR, CURHDR->content, NULL);
-       /* if we were in the pager, redisplay the message */
-       if (menu->menu == MENU_PAGER)
-       {
-         op = OP_DISPLAY_MESSAGE;
-         continue;
-       }
+    case OP_MAIN_LIMIT:
+    case OP_TOGGLE_READ:
+
+      CHECK_MSGCOUNT;
+      menu->oldcurrent = (Context->vcount && menu->current >= 0
+                          && menu->current <
+                          Context->vcount) ? CURHDR->index : -1;
+      if (op == OP_TOGGLE_READ) {
+        char buf[LONG_STRING];
+
+        if (!Context->pattern
+            || strncmp (Context->pattern, "!~R!~D~s", 8) != 0) {
+          snprintf (buf, sizeof (buf), "!~R!~D~s%s",
+                    Context->pattern ? Context->pattern : ".*");
+          set_option (OPTHIDEREAD);
+        }
+        else {
+          strfcpy (buf, Context->pattern + 8, sizeof (buf));
+          if (!*buf || strncmp (buf, ".*", 2) == 0)
+            snprintf (buf, sizeof (buf), "~A");
+          unset_option (OPTHIDEREAD);
+        }
+        FREE (&Context->pattern);
+        Context->pattern = safe_strdup (buf);
+      }
+      if ((op == OP_TOGGLE_READ && mutt_pattern_func (M_LIMIT, NULL) == 0) ||
+          mutt_pattern_func (M_LIMIT, _("Limit to messages matching: ")) == 0)
+      {
+        if (menu->oldcurrent >= 0) {
+          /* try to find what used to be the current message */
+          menu->current = -1;
+          for (i = 0; i < Context->vcount; i++)
+            if (Context->hdrs[Context->v2r[i]]->index == menu->oldcurrent) {
+              menu->current = i;
+              break;
+            }
+          if (menu->current < 0)
+            menu->current = 0;
+        }
         else
-         menu->redraw = REDRAW_CURRENT;
-       break;
+          menu->current = 0;
+        menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
+        if ((Sort & SORT_MASK) == SORT_THREADS)
+          mutt_draw_tree (Context);
+        menu->redraw = REDRAW_FULL;
+      }
+      break;
 
-      case OP_MAIN_NEXT_UNDELETED:
+    case OP_QUIT:
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       if (menu->current >= Context->vcount - 1)
-       {
-         if (menu->menu == MENU_MAIN)
-           mutt_error _("You are on the last message.");
-         break;
-       }
-       if ((menu->current = ci_next_undeleted (menu->current)) == -1)
-       {
-         menu->current = menu->oldcurrent;
-         if (menu->menu == MENU_MAIN)
-           mutt_error _("No undeleted messages.");
-       }
-       else if (menu->menu == MENU_PAGER)
-       {
-         op = OP_DISPLAY_MESSAGE;
-         continue;
-       }
-       else
-         menu->redraw = REDRAW_MOTION;
-       break;
-
-      case OP_NEXT_ENTRY:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       if (menu->current >= Context->vcount - 1)
-       {
-         if (menu->menu == MENU_MAIN)
-           mutt_error _("You are on the last message.");
-         break;
-       }
-       menu->current++;
-       if (menu->menu == MENU_PAGER)
-       {
-         op = OP_DISPLAY_MESSAGE;
-         continue;
-       }
-       else
-         menu->redraw = REDRAW_MOTION;
-       break;
-
-      case OP_MAIN_PREV_UNDELETED:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       if (menu->current < 1)
-       {
-         mutt_error _("You are on the first message.");
-         break;
-       }
-       if ((menu->current = ci_previous_undeleted (menu->current)) == -1)
-       {
-         menu->current = menu->oldcurrent;
-         if (menu->menu == MENU_MAIN)
-           mutt_error _("No undeleted messages.");
-       }
-       else if (menu->menu == MENU_PAGER)
-       {
-         op = OP_DISPLAY_MESSAGE;
-         continue;
-       }
-       else
-         menu->redraw = REDRAW_MOTION;
-       break;
-
-      case OP_PREV_ENTRY:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       if (menu->current < 1)
-       {
-         if (menu->menu == MENU_MAIN) mutt_error _("You are on the first message.");
-         break;
-       }
-       menu->current--;
-       if (menu->menu == MENU_PAGER)
-       {
-         op = OP_DISPLAY_MESSAGE;
-         continue;
-       }
-       else
-         menu->redraw = REDRAW_MOTION;
-       break;
-
-      case OP_DECRYPT_COPY:
-      case OP_DECRYPT_SAVE:
-        if (!WithCrypto)
-          break;   
-        /* fall thru */
-      case OP_COPY_MESSAGE:
-      case OP_SAVE:
-      case OP_DECODE_COPY:
-      case OP_DECODE_SAVE:
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-        if (mutt_save_message (tag ? NULL : CURHDR,
-                              (op == OP_DECRYPT_SAVE) ||
-                              (op == OP_SAVE) || (op == OP_DECODE_SAVE),
-                              (op == OP_DECODE_SAVE) || (op == OP_DECODE_COPY),
-                              (op == OP_DECRYPT_SAVE) || (op == OP_DECRYPT_COPY) ||
-                              0,
-                              &menu->redraw) == 0 &&
-            (op == OP_SAVE || op == OP_DECODE_SAVE || op == OP_DECRYPT_SAVE)
-           )
-       {
-         if (tag)
-           menu->redraw |= REDRAW_INDEX;
-         else if (option (OPTRESOLVE))
-         {
-           if ((menu->current = ci_next_undeleted (menu->current)) == -1)
-           {
-             menu->current = menu->oldcurrent;
-             menu->redraw |= REDRAW_CURRENT;
-           }
-           else
-             menu->redraw |= REDRAW_MOTION_RESYNCH;
-         }
-         else
-           menu->redraw |= REDRAW_CURRENT;
-       }
-       break;
-
-      case OP_MAIN_NEXT_NEW:
-      case OP_MAIN_NEXT_UNREAD:
-      case OP_MAIN_PREV_NEW:
-      case OP_MAIN_PREV_UNREAD:
-      case OP_MAIN_NEXT_NEW_THEN_UNREAD:
-      case OP_MAIN_PREV_NEW_THEN_UNREAD:
+      close = op;
+      if (attach_msg) {
+        done = 1;
+        break;
+      }
 
-      {
-       int first_unread = -1;
-       int first_new    = -1;
-       
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
+      if (query_quadoption (OPT_QUIT, _("Quit Mutt-ng?")) == M_YES) {
+        int check;
 
-       i = menu->current;
-       menu->current = -1;
-       for (j = 0; j != Context->vcount; j++)
-       {
-#define CURHDRi Context->hdrs[Context->v2r[i]] 
-         if (op == OP_MAIN_NEXT_NEW || op == OP_MAIN_NEXT_UNREAD || op == OP_MAIN_NEXT_NEW_THEN_UNREAD)
-         {
-           i++;
-           if (i > Context->vcount - 1)
-           {
-             mutt_message _("Search wrapped to top.");
-             i = 0;
-           }
-         }
-         else
-         {
-           i--;
-           if (i < 0)
-           {
-             mutt_message _("Search wrapped to bottom.");
-             i = Context->vcount - 1;
-           }
-         }
-
-         if (CURHDRi->collapsed && (Sort & SORT_MASK) == SORT_THREADS)
-         {
-           if (UNREAD (CURHDRi) && first_unread == -1)
-             first_unread = i;
-           if (UNREAD (CURHDRi) == 1 && first_new == -1)
-             first_new = i;
-         }
-         else if ((!CURHDRi->deleted && !CURHDRi->read))
-         {
-           if (first_unread == -1)
-             first_unread = i;
-           if ((!CURHDRi->old) && first_new == -1)
-             first_new = i;
-         }
-         
-         if ((op == OP_MAIN_NEXT_UNREAD || op == OP_MAIN_PREV_UNREAD) &&
-             first_unread != -1)
-           break;
-         if ((op == OP_MAIN_NEXT_NEW || op == OP_MAIN_PREV_NEW ||
-              op == OP_MAIN_NEXT_NEW_THEN_UNREAD || op == OP_MAIN_PREV_NEW_THEN_UNREAD)
-             && first_new != -1)
-           break;
-       }
-#undef CURHDRi
-       if ((op == OP_MAIN_NEXT_NEW || op == OP_MAIN_PREV_NEW ||
-            op == OP_MAIN_NEXT_NEW_THEN_UNREAD || op == OP_MAIN_PREV_NEW_THEN_UNREAD) 
-           && first_new != -1)
-         menu->current = first_new;
-       else if ((op == OP_MAIN_NEXT_UNREAD || op == OP_MAIN_PREV_UNREAD ||
-                 op == OP_MAIN_NEXT_NEW_THEN_UNREAD || op == OP_MAIN_PREV_NEW_THEN_UNREAD)
-                && first_unread != -1)
-         menu->current = first_unread;
-
-       if (menu->current == -1)
-       {
-         menu->current = menu->oldcurrent;
-         mutt_error ("%s%s.", (op == OP_MAIN_NEXT_NEW || op == OP_MAIN_PREV_NEW) ? _("No new messages") : _("No unread messages"),
-                     Context->pattern ? _(" in this limited view") : "");
-       }
-       else if (menu->menu == MENU_PAGER)
-       {
-         op = OP_DISPLAY_MESSAGE;
-         continue;
-       }
-       else
-         menu->redraw = REDRAW_MOTION;
-       break;
-      }
-      case OP_FLAG_MESSAGE:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_READONLY;
+        oldcount = Context ? Context->msgcount : 0;
 
-#ifdef USE_POP
-       if (Context->magic == M_POP)
-       {
-         mutt_flushinp ();
-         mutt_error _("Can't change 'important' flag on POP server.");
-         break;
-       }
-#endif
+        if (!Context
+            || (check = mx_close_mailbox (Context, &index_hint)) == 0)
+          done = 1;
+        else {
+          if (check == M_NEW_MAIL || check == M_REOPENED)
+            update_index (menu, Context, check, oldcount, index_hint);
 
-#ifdef USE_IMAP
-CHECK_IMAP_ACL(IMAP_ACL_WRITE);
-#endif
+          menu->redraw = REDRAW_FULL;   /* new mail arrived? */
+          set_option (OPTSEARCHINVALID);
+        }
+      }
+      break;
 
-#ifdef USE_NNTP
-       if (Context->magic == M_NNTP)
-       {
-         mutt_flushinp ();
-         mutt_error _("Can't change 'important' flag on NNTP server.");
-         break;
-       }
-#endif
+    case OP_REDRAW:
 
-        if (tag)
-        {
-         for (j = 0; j < Context->vcount; j++)
-         {
-           if (Context->hdrs[Context->v2r[j]]->tagged)
-             mutt_set_flag (Context, Context->hdrs[Context->v2r[j]],
-                            M_FLAG, !Context->hdrs[Context->v2r[j]]->flagged);
-         }
-
-         menu->redraw |= REDRAW_INDEX;
-       }
-        else
-        {
-         mutt_set_flag (Context, CURHDR, M_FLAG, !CURHDR->flagged);
-         if (option (OPTRESOLVE))
-         {
-           if ((menu->current = ci_next_undeleted (menu->current)) == -1)
-           {
-             menu->current = menu->oldcurrent;
-             menu->redraw = REDRAW_CURRENT;
-           }
-           else
-             menu->redraw = REDRAW_MOTION_RESYNCH;
-         }
-         else
-           menu->redraw = REDRAW_CURRENT;
-       }
-       menu->redraw |= REDRAW_STATUS;
-       break;
-
-      case OP_TOGGLE_NEW:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_READONLY;
+      clearok (stdscr, TRUE);
+      menu->redraw = REDRAW_FULL;
+      break;
 
-#ifdef USE_IMAP
-CHECK_IMAP_ACL(IMAP_ACL_SEEN);
-#endif
+    case OP_SEARCH:
+    case OP_SEARCH_REVERSE:
+    case OP_SEARCH_NEXT:
+    case OP_SEARCH_OPPOSITE:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      if ((menu->current = mutt_search_command (menu->current, op)) == -1)
+        menu->current = menu->oldcurrent;
+      else
+        menu->redraw = REDRAW_MOTION;
+      break;
 
-       if (tag)
-       {
-         for (j = 0; j < Context->vcount; j++)
-         {
-           if (Context->hdrs[Context->v2r[j]]->tagged)
-           {
-             if (Context->hdrs[Context->v2r[j]]->read ||
-                 Context->hdrs[Context->v2r[j]]->old)
-               mutt_set_flag (Context, Context->hdrs[Context->v2r[j]], M_NEW, 1);
-             else
-               mutt_set_flag (Context, Context->hdrs[Context->v2r[j]], M_READ, 1);
-           }
-         }
-         menu->redraw = REDRAW_STATUS | REDRAW_INDEX;
-       }
-       else
-       {
-         if (CURHDR->read || CURHDR->old)
-           mutt_set_flag (Context, CURHDR, M_NEW, 1);
-         else
-           mutt_set_flag (Context, CURHDR, M_READ, 1);
-
-         if (option (OPTRESOLVE))
-         {
-           if ((menu->current = ci_next_undeleted (menu->current)) == -1)
-           {
-             menu->current = menu->oldcurrent;
-             menu->redraw = REDRAW_CURRENT;
-           }
-           else
-             menu->redraw = REDRAW_MOTION_RESYNCH;
-         }
-         else
-           menu->redraw = REDRAW_CURRENT;
-         menu->redraw |= REDRAW_STATUS;
-       }
-       break;
-
-      case OP_TOGGLE_WRITE:
-
-       CHECK_MSGCOUNT;
-       if (mx_toggle_write (Context) == 0)
-         menu->redraw |= REDRAW_STATUS;
-       break;
+    case OP_SORT:
+    case OP_SORT_REVERSE:
 
-      case OP_MAIN_NEXT_THREAD:
-      case OP_MAIN_NEXT_SUBTHREAD:
-      case OP_MAIN_PREV_THREAD:
-      case OP_MAIN_PREV_SUBTHREAD:
+      if (mutt_select_sort ((op == OP_SORT_REVERSE)) == 0) {
+        if (Context && Context->msgcount) {
+          resort_index (menu);
+          set_option (OPTSEARCHINVALID);
+        }
+      }
+      break;
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       switch (op)
-       {
-         case OP_MAIN_NEXT_THREAD:
-           menu->current = mutt_next_thread (CURHDR);
-           break;
-
-         case OP_MAIN_NEXT_SUBTHREAD:
-           menu->current = mutt_next_subthread (CURHDR);
-           break;
-           
-         case OP_MAIN_PREV_THREAD:
-           menu->current = mutt_previous_thread (CURHDR);
-           break;
-
-         case OP_MAIN_PREV_SUBTHREAD:
-           menu->current = mutt_previous_subthread (CURHDR);
-           break;
-       }
-
-       if (menu->current < 0)
-       {
-         menu->current = menu->oldcurrent;
-         if (op == OP_MAIN_NEXT_THREAD || op == OP_MAIN_NEXT_SUBTHREAD)
-           mutt_error _("No more threads.");
-         else
-           mutt_error _("You are on the first thread.");
-       }
-       else if (menu->menu == MENU_PAGER)
-       {
-         op = OP_DISPLAY_MESSAGE;
-         continue;
-       }
-       else
-         menu->redraw = REDRAW_MOTION;
-       break;
-
-      case OP_MAIN_PARENT_MESSAGE:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
+    case OP_TAG:
 
-       if ((menu->current = mutt_parent_message (Context, CURHDR)) < 0)
-       {
-         menu->current = menu->oldcurrent;
-       }
-       else if (menu->menu == MENU_PAGER)
-        {
-          op = OP_DISPLAY_MESSAGE;
-          continue;
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      if (tag && !option (OPTAUTOTAG)) {
+        for (j = 0; j < Context->vcount; j++)
+          mutt_set_flag (Context, Context->hdrs[Context->v2r[j]], M_TAG, 0);
+        menu->redraw = REDRAW_STATUS | REDRAW_INDEX;
+      }
+      else {
+        mutt_set_flag (Context, CURHDR, M_TAG, !CURHDR->tagged);
+        Context->last_tag = CURHDR->tagged ? CURHDR :
+          ((Context->last_tag == CURHDR && !CURHDR->tagged)
+           ? NULL : Context->last_tag);
+        menu->redraw = REDRAW_STATUS;
+        if (option (OPTRESOLVE) && menu->current < Context->vcount - 1) {
+          menu->current++;
+          menu->redraw |= REDRAW_MOTION_RESYNCH;
         }
         else
-          menu->redraw = REDRAW_MOTION;
-       break;
+          menu->redraw |= REDRAW_CURRENT;
+      }
+      break;
 
-      case OP_MAIN_SET_FLAG:
-      case OP_MAIN_CLEAR_FLAG:
+    case OP_MAIN_TAG_PATTERN:
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_READONLY;
-       
-/* #ifdef USE_IMAP
-CHECK_IMAP_ACL(IMAP_ACL_WRITE);
-#endif */
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      mutt_pattern_func (M_TAG, _("Tag messages matching: "));
+      menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
+      break;
 
-       if (mutt_change_flag (tag ? NULL : CURHDR, (op == OP_MAIN_SET_FLAG)) == 0)
-       {
-         menu->redraw = REDRAW_STATUS;
-         if (tag)
-           menu->redraw |= REDRAW_INDEX;
-         else if (option (OPTRESOLVE))
-         {
-           if ((menu->current = ci_next_undeleted (menu->current)) == -1)
-           {
-             menu->current = menu->oldcurrent;
-             menu->redraw |= REDRAW_CURRENT;
-           }
-           else
-             menu->redraw |= REDRAW_MOTION_RESYNCH;
-         }
-         else
-           menu->redraw |= REDRAW_CURRENT;
-       }
-       break;
-
-      case OP_MAIN_COLLAPSE_THREAD:
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
+    case OP_MAIN_UNDELETE_PATTERN:
 
-        if ((Sort & SORT_MASK) != SORT_THREADS)
-        {
-         mutt_error _("Threading is not enabled.");
-         break;
-       }
-      
-       if (CURHDR->collapsed)
-       {
-         menu->current = mutt_uncollapse_thread (Context, CURHDR);
-         mutt_set_virtual (Context);
-         if (option (OPTUNCOLLAPSEJUMP))
-           menu->current = mutt_thread_next_unread (Context, CURHDR);
-       }
-       else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (CURHDR))
-       {
-         menu->current = mutt_collapse_thread (Context, CURHDR);
-         mutt_set_virtual (Context);
-       }
-       else
-       {
-         mutt_error _("Thread contains unread messages.");
-         break;
-       }
-
-       menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-
-       break;
-
-      case OP_MAIN_COLLAPSE_ALL:
-        CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
 
-        if ((Sort & SORT_MASK) != SORT_THREADS)
-        {
-         mutt_error _("Threading is not enabled.");
-         break;
-       }
+#ifdef USE_IMAP
+      CHECK_IMAP_ACL (IMAP_ACL_DELETE);
+#endif
 
-        {
-         HEADER *h, *base;
-         THREAD *thread, *top;
-         int final;
-         
-         if (CURHDR->collapsed)
-           final = mutt_uncollapse_thread (Context, CURHDR);
-         else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (CURHDR))
-           final = mutt_collapse_thread (Context, CURHDR);
-         else
-           final = CURHDR->virtual;
-         
-         base = Context->hdrs[Context->v2r[final]];
-         
-         top = Context->tree;
-         Context->collapsed = !Context->collapsed;
-         while ((thread = top) != NULL)
-         {
-           while (!thread->message)
-             thread = thread->child;
-           h = thread->message;
-
-           if (h->collapsed != Context->collapsed)
-           {
-             if (h->collapsed)
-               mutt_uncollapse_thread (Context, h);
-             else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (h))
-               mutt_collapse_thread (Context, h);
-           }
-           top = top->next;
-         }
-         
-         mutt_set_virtual (Context);
-         for (j = 0; j < Context->vcount; j++)
-         {
-           if (Context->hdrs[Context->v2r[j]]->index == base->index)
-           {
-             menu->current = j;
-             break;
-           }
-         }
-         
-         menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-       }
-       break;
-      
-      /* --------------------------------------------------------------------
-       * These functions are invoked directly from the internal-pager
+      if (mutt_pattern_func (M_UNDELETE, _("Undelete messages matching: ")) ==
+          0)
+        menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
+      break;
+
+    case OP_MAIN_UNTAG_PATTERN:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      if (mutt_pattern_func (M_UNTAG, _("Untag messages matching: ")) == 0)
+        menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
+      break;
+
+      /* --------------------------------------------------------------------
+       * The following operations can be performed inside of the pager.
        */
 
-      case OP_BOUNCE_MESSAGE:
+#ifdef USE_IMAP
+    case OP_MAIN_IMAP_FETCH:
+      if (Context->magic == M_IMAP)
+        imap_check_mailbox (Context, &index_hint, 1);
+      break;
+#endif
+
+    case OP_MAIN_SYNC_FOLDER:
 
-       CHECK_ATTACH;
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       ci_bounce_message (tag ? NULL : CURHDR, &menu->redraw);
-       break;
+      if (Context && !Context->msgcount)
+        break;
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
+      {
+        int oldvcount = Context->vcount;
+        int oldcount = Context->msgcount;
+        int dcount = 0;
+        int check;
+
+        /* calculate the number of messages _above_ the cursor,
+         * so we can keep the cursor on the current message
+         */
+        for (j = 0; j <= menu->current; j++) {
+          if (Context->hdrs[Context->v2r[j]]->deleted)
+            dcount++;
+        }
 
-      case OP_CREATE_ALIAS:
+        if ((check = mx_sync_mailbox (Context, &index_hint)) == 0) {
+          if (Context->vcount != oldvcount)
+            menu->current -= dcount;
+          set_option (OPTSEARCHINVALID);
+        }
+        else if (check == M_NEW_MAIL || check == M_REOPENED)
+          update_index (menu, Context, check, oldcount, index_hint);
 
-        mutt_create_alias (Context && Context->vcount ? CURHDR->env : NULL, NULL);
-       MAYBE_REDRAW (menu->redraw);
-        menu->redraw |= REDRAW_CURRENT;
-       break;
+        /* 
+         * do a sanity check even if mx_sync_mailbox failed.
+         */
 
-      case OP_QUERY:
-       CHECK_ATTACH;
-       mutt_query_menu (NULL, 0);
-       MAYBE_REDRAW (menu->redraw);
-       break;
+        if (menu->current < 0 || menu->current >= Context->vcount)
+          menu->current = ci_first_message ();
+      }
 
-      case OP_PURGE_MESSAGE:
-      case OP_DELETE:
+      /* check for a fatal error, or all messages deleted */
+      if (!Context->path)
+        FREE (&Context);
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_READONLY;
-       
-#ifdef USE_IMAP
-CHECK_IMAP_ACL(IMAP_ACL_DELETE);
+      /* if we were in the pager, redisplay the message */
+      if (menu->menu == MENU_PAGER) {
+        op = OP_DISPLAY_MESSAGE;
+        continue;
+      }
+      else
+        menu->redraw = REDRAW_FULL;
+      break;
+
+    case OP_SIDEBAR_OPEN:
+    case OP_MAIN_CHANGE_FOLDER:
+    case OP_MAIN_CHANGE_FOLDER_READONLY:
+#ifdef USE_NNTP
+    case OP_MAIN_CHANGE_GROUP:
+    case OP_MAIN_CHANGE_GROUP_READONLY:
 #endif
+      if (attach_msg || option (OPTREADONLY) ||
+#ifdef USE_NNTP
+          op == OP_MAIN_CHANGE_GROUP_READONLY ||
+#endif
+          op == OP_MAIN_CHANGE_FOLDER_READONLY)
+        flags = M_READONLY;
+      else
+        flags = 0;
 
-       if (tag)
-       {
-         mutt_tag_set_flag (M_DELETE, 1);
-         mutt_tag_set_flag (M_PURGED, (op != OP_PURGE_MESSAGE) ? 0 : 1);
-         if (option (OPTDELETEUNTAG))
-           mutt_tag_set_flag (M_TAG, 0);
-         menu->redraw = REDRAW_INDEX;
-       }
-       else
-       {
-         mutt_set_flag (Context, CURHDR, M_DELETE, 1);
-         mutt_set_flag (Context, CURHDR, M_PURGED,
-                        (op != OP_PURGE_MESSAGE) ? 0 : 1);
-         if (option (OPTDELETEUNTAG))
-           mutt_set_flag (Context, CURHDR, M_TAG, 0);
-         if (option (OPTRESOLVE))
-         {
-           if ((menu->current = ci_next_undeleted (menu->current)) == -1)
-           {
-             menu->current = menu->oldcurrent;
-             menu->redraw = REDRAW_CURRENT;
-           }
-           else if (menu->menu == MENU_PAGER)
-           {
-             op = OP_DISPLAY_MESSAGE;
-             continue;
-           }
-           else
-             menu->redraw |= REDRAW_MOTION_RESYNCH;
-         }
-         else
-           menu->redraw = REDRAW_CURRENT;
-       }
-       menu->redraw |= REDRAW_STATUS;
-       break;
-
-      case OP_DELETE_THREAD:
-      case OP_DELETE_SUBTHREAD:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_READONLY;
+      if (flags)
+        cp = _("Open mailbox in read-only mode");
+      else
+        cp = _("Open mailbox");
 
-#ifdef USE_IMAP
-CHECK_IMAP_ACL(IMAP_ACL_DELETE);
+      buf[0] = '\0';
+#ifdef USE_NNTP
+      unset_option (OPTNEWS);
+      if (op == OP_MAIN_CHANGE_GROUP || op == OP_MAIN_CHANGE_GROUP_READONLY) {
+        set_option (OPTNEWS);
+        if (!(CurrentNewsSrv = mutt_select_newsserver (NewsServer)))
+          break;
+        if (flags)
+          cp = _("Open newsgroup in read-only mode");
+        else
+          cp = _("Open newsgroup");
+        nntp_buffy (buf);
+      }
+      else
 #endif
+      {
+        if (Context && Context->path)
+          strncpy (buf, Context->path, sizeof (buf));
+        mutt_buffy (buf, sizeof (buf));
+      }
 
-       rc = mutt_thread_set_flag (CURHDR, M_DELETE, 1,
-                                  op == OP_DELETE_THREAD ? 0 : 1);
-
-       if (rc != -1)
-       {
-         if (option (OPTDELETEUNTAG))
-           mutt_thread_set_flag (CURHDR, M_TAG, 0, 
-                                 op == OP_DELETE_THREAD ? 0 : 1);
-         if (option (OPTRESOLVE))
-           if ((menu->current = ci_next_undeleted (menu->current)) == -1)
-             menu->current = menu->oldcurrent;
-         menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-       }
-       break;
+      if (op == OP_SIDEBAR_OPEN) {
+        strncpy (buf, NONULL(sidebar_get_current ()), sizeof (buf));
+      }
+      else if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) ==
+               -1)
+        break;
+      if (!buf[0]) {
+        CLEARLINE (LINES - 1);
+        break;
+      }
 
 #ifdef USE_NNTP
-      case OP_CATCHUP:
-       if (Context && Context->magic == M_NNTP)
-       {
-         if (mutt_newsgroup_catchup (CurrentNewsSrv,
-               ((NNTP_DATA *)Context->data)->group))
-           menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-       }
-       break;
+      if (option (OPTNEWS)) {
+        unset_option (OPTNEWS);
+        nntp_expand_path (buf, sizeof (buf), &CurrentNewsSrv->conn->account);
+      }
+      else
 #endif
+        mutt_expand_path (buf, sizeof (buf));
+      sidebar_set_current (buf);
+      if (mx_get_magic (buf) <= 0) {
+        mutt_error (_("%s is not a mailbox."), buf);
+        break;
+      }
+      mutt_str_replace (&CurrentFolder, buf);
 
-      case OP_DISPLAY_ADDRESS:
+      if (Context) {
+        int check;
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       mutt_display_address (CURHDR->env);
-       break;
+#ifdef USE_COMPRESSED
+        if (Context->compressinfo && Context->realpath)
+          mutt_str_replace (&LastFolder, Context->realpath);
+        else
+#endif
+
+          mutt_str_replace (&LastFolder, Context->path);
+        oldcount = Context ? Context->msgcount : 0;
+
+        if ((check = mx_close_mailbox (Context, &index_hint)) != 0) {
+          if (check == M_NEW_MAIL || check == M_REOPENED)
+            update_index (menu, Context, check, oldcount, index_hint);
+
+          set_option (OPTSEARCHINVALID);
+          menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
+          break;
+        }
+        FREE (&Context);
+      }
+
+      mutt_sleep (0);
+
+      /* Set CurrentMenu to MENU_MAIN before executing any folder
+       * hooks so that all the index menu functions are available to
+       * the exec command.
+       */
+
+      CurrentMenu = MENU_MAIN;
+      mutt_folder_hook (buf);
+
+      if ((Context = mx_open_mailbox (buf, flags, NULL)) != NULL) {
+        menu->current = ci_first_message ();
+      }
+      else
+        menu->current = 0;
+
+#ifdef USE_NNTP
+      /* mutt_buffy_check() must be done with mail-reader mode! */
+      menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN,
+                                      (Context
+                                       && (Context->magic ==
+                                           M_NNTP)) ? IndexNewsHelp :
+                                      IndexHelp);
+#endif
+      mutt_clear_error ();
+      mutt_buffy_check (1);     /* force the buffy check after we have changed
+                                   the folder */
+      menu->redraw = REDRAW_FULL;
+      set_option (OPTSEARCHINVALID);
+      break;
+
+    case OP_DISPLAY_MESSAGE:
+    case OP_DISPLAY_HEADERS:   /* don't weed the headers */
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      /*
+       * toggle the weeding of headers so that a user can press the key
+       * again while reading the message.
+       */
+      if (op == OP_DISPLAY_HEADERS)
+        toggle_option (OPTWEED);
+
+      unset_option (OPTNEEDRESORT);
+
+      if ((Sort & SORT_MASK) == SORT_THREADS && CURHDR->collapsed) {
+        mutt_uncollapse_thread (Context, CURHDR);
+        mutt_set_virtual (Context);
+        if (option (OPTUNCOLLAPSEJUMP))
+          menu->current = mutt_thread_next_unread (Context, CURHDR);
+      }
+
+      if ((op = mutt_display_message (CURHDR)) == -1) {
+        unset_option (OPTNEEDRESORT);
+        break;
+      }
+
+      menu->menu = MENU_PAGER;
+      menu->oldcurrent = menu->current;
+      continue;
+
+    case OP_EXIT:
+
+      close = op;
+      if (menu->menu == MENU_MAIN && attach_msg) {
+        done = 1;
+        break;
+      }
+
+      if ((menu->menu == MENU_MAIN)
+          && (query_quadoption (OPT_QUIT,
+                                _("Exit Mutt-ng without saving?")) == M_YES))
+      {
+        if (Context) {
+          mx_fastclose_mailbox (Context);
+          FREE (&Context);
+        }
+        done = 1;
+      }
+      break;
+
+    case OP_EDIT_TYPE:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_ATTACH;
+      mutt_edit_content_type (CURHDR, CURHDR->content, NULL);
+      /* if we were in the pager, redisplay the message */
+      if (menu->menu == MENU_PAGER) {
+        op = OP_DISPLAY_MESSAGE;
+        continue;
+      }
+      else
+        menu->redraw = REDRAW_CURRENT;
+      break;
+
+    case OP_MAIN_BREAK_THREAD:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
+
+      if ((Sort & SORT_MASK) != SORT_THREADS)
+        mutt_error (_("Threading is not enabled."));
+
+      else {
+        {
+          HEADER *oldcur = CURHDR;
+
+          mutt_break_thread (CURHDR);
+          mutt_sort_headers (Context, 1);
+          menu->current = oldcur->virtual;
+        }
+
+        Context->changed = 1;
+        mutt_message _("Thread broken");
+
+        if (menu->menu == MENU_PAGER) {
+          op = OP_DISPLAY_MESSAGE;
+          continue;
+        }
+        else
+          menu->redraw |= REDRAW_INDEX;
+      }
+      break;
+
+    case OP_MAIN_LINK_THREADS:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
+
+      if ((Sort & SORT_MASK) != SORT_THREADS)
+        mutt_error (_("Threading is not enabled."));
+
+      else if (!CURHDR->env->message_id)
+        mutt_error (_("No Message-ID: header available to link thread"));
+
+      else if (!tag && (!Context->last_tag || !Context->last_tag->tagged))
+        mutt_error (_("First, please tag a message to be linked here"));
 
-      case OP_ENTER_COMMAND:
+      else {
+        HEADER *oldcur = CURHDR;
 
-       CurrentMenu = MENU_MAIN;
-       mutt_enter_command ();
-       mutt_check_rescore (Context);
-       if (option (OPTFORCEREDRAWINDEX))
-         menu->redraw = REDRAW_FULL;
-       unset_option (OPTFORCEREDRAWINDEX);
-       unset_option (OPTFORCEREDRAWPAGER);
-       break;
+        if (mutt_link_threads (CURHDR, tag ? NULL : Context->last_tag,
+                               Context)) {
+          mutt_sort_headers (Context, 1);
+          menu->current = oldcur->virtual;
 
-      case OP_EDIT_MESSAGE:
+          Context->changed = 1;
+          mutt_message _("Threads linked");
+        }
+        else
+          mutt_error (_("No thread linked"));
+      }
+
+      if (menu->menu == MENU_PAGER) {
+        op = OP_DISPLAY_MESSAGE;
+        continue;
+      }
+      else
+        menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
+      break;
+
+    case OP_MAIN_NEXT_UNDELETED:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      if (menu->current >= Context->vcount - 1) {
+        if (menu->menu == MENU_MAIN)
+          mutt_error (_("You are on the last message."));
+
+        break;
+      }
+      if ((menu->current = ci_next_undeleted (menu->current)) == -1) {
+        menu->current = menu->oldcurrent;
+        if (menu->menu == MENU_MAIN)
+          mutt_error (_("No undeleted messages."));
+      }
+      else if (menu->menu == MENU_PAGER) {
+        op = OP_DISPLAY_MESSAGE;
+        continue;
+      }
+      else
+        menu->redraw = REDRAW_MOTION;
+      break;
+
+    case OP_NEXT_ENTRY:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      if (menu->current >= Context->vcount - 1) {
+        if (menu->menu == MENU_MAIN)
+          mutt_error (_("You are on the last message."));
+
+        break;
+      }
+      menu->current++;
+      if (menu->menu == MENU_PAGER) {
+        op = OP_DISPLAY_MESSAGE;
+        continue;
+      }
+      else
+        menu->redraw = REDRAW_MOTION;
+      break;
+
+    case OP_MAIN_PREV_UNDELETED:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      if (menu->current < 1) {
+        mutt_error (_("You are on the first message."));
+
+        break;
+      }
+      if ((menu->current = ci_previous_undeleted (menu->current)) == -1) {
+        menu->current = menu->oldcurrent;
+        if (menu->menu == MENU_MAIN)
+          mutt_error (_("No undeleted messages."));
+      }
+      else if (menu->menu == MENU_PAGER) {
+        op = OP_DISPLAY_MESSAGE;
+        continue;
+      }
+      else
+        menu->redraw = REDRAW_MOTION;
+      break;
+
+    case OP_PREV_ENTRY:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      if (menu->current < 1) {
+        if (menu->menu == MENU_MAIN)
+          mutt_error (_("You are on the first message."));
+
+        break;
+      }
+      menu->current--;
+      if (menu->menu == MENU_PAGER) {
+        op = OP_DISPLAY_MESSAGE;
+        continue;
+      }
+      else
+        menu->redraw = REDRAW_MOTION;
+      break;
+
+    case OP_DECRYPT_COPY:
+    case OP_DECRYPT_SAVE:
+      if (!WithCrypto)
+        break;
+      /* fall thru */
+    case OP_COPY_MESSAGE:
+    case OP_SAVE:
+    case OP_DECODE_COPY:
+    case OP_DECODE_SAVE:
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      if (mutt_save_message (tag ? NULL : CURHDR,
+                             (op == OP_DECRYPT_SAVE) ||
+                             (op == OP_SAVE) || (op == OP_DECODE_SAVE),
+                             (op == OP_DECODE_SAVE) || (op == OP_DECODE_COPY),
+                             (op == OP_DECRYPT_SAVE)
+                             || (op == OP_DECRYPT_COPY)
+                             || 0, &menu->redraw) == 0 && (op == OP_SAVE
+                                                           || op ==
+                                                           OP_DECODE_SAVE
+                                                           || op ==
+                                                           OP_DECRYPT_SAVE)
+        ) {
+        if (tag)
+          menu->redraw |= REDRAW_INDEX;
+        else if (option (OPTRESOLVE)) {
+          if ((menu->current = ci_next_undeleted (menu->current)) == -1) {
+            menu->current = menu->oldcurrent;
+            menu->redraw |= REDRAW_CURRENT;
+          }
+          else
+            menu->redraw |= REDRAW_MOTION_RESYNCH;
+        }
+        else
+          menu->redraw |= REDRAW_CURRENT;
+      }
+      break;
+
+    case OP_MAIN_NEXT_NEW:
+    case OP_MAIN_NEXT_UNREAD:
+    case OP_MAIN_PREV_NEW:
+    case OP_MAIN_PREV_UNREAD:
+    case OP_MAIN_NEXT_NEW_THEN_UNREAD:
+    case OP_MAIN_PREV_NEW_THEN_UNREAD:
 
-       CHECK_MSGCOUNT;
+      {
+        int first_unread = -1;
+        int first_new = -1;
+
+        CHECK_MSGCOUNT;
         CHECK_VISIBLE;
-       CHECK_READONLY;
-       CHECK_ATTACH;
+
+        i = menu->current;
+        menu->current = -1;
+        for (j = 0; j != Context->vcount; j++) {
+#define CURHDRi Context->hdrs[Context->v2r[i]]
+          if (op == OP_MAIN_NEXT_NEW || op == OP_MAIN_NEXT_UNREAD
+              || op == OP_MAIN_NEXT_NEW_THEN_UNREAD) {
+            i++;
+            if (i > Context->vcount - 1) {
+              mutt_message _("Search wrapped to top.");
+
+              i = 0;
+            }
+          }
+          else {
+            i--;
+            if (i < 0) {
+              mutt_message _("Search wrapped to bottom.");
+
+              i = Context->vcount - 1;
+            }
+          }
+
+          if (CURHDRi->collapsed && (Sort & SORT_MASK) == SORT_THREADS) {
+            if (UNREAD (CURHDRi) && first_unread == -1)
+              first_unread = i;
+            if (UNREAD (CURHDRi) == 1 && first_new == -1)
+              first_new = i;
+          }
+          else if ((!CURHDRi->deleted && !CURHDRi->read)) {
+            if (first_unread == -1)
+              first_unread = i;
+            if ((!CURHDRi->old) && first_new == -1)
+              first_new = i;
+          }
+
+          if ((op == OP_MAIN_NEXT_UNREAD || op == OP_MAIN_PREV_UNREAD) &&
+              first_unread != -1)
+            break;
+          if ((op == OP_MAIN_NEXT_NEW || op == OP_MAIN_PREV_NEW ||
+               op == OP_MAIN_NEXT_NEW_THEN_UNREAD
+               || op == OP_MAIN_PREV_NEW_THEN_UNREAD)
+              && first_new != -1)
+            break;
+        }
+#undef CURHDRi
+        if ((op == OP_MAIN_NEXT_NEW || op == OP_MAIN_PREV_NEW ||
+             op == OP_MAIN_NEXT_NEW_THEN_UNREAD
+             || op == OP_MAIN_PREV_NEW_THEN_UNREAD)
+            && first_new != -1)
+          menu->current = first_new;
+        else if ((op == OP_MAIN_NEXT_UNREAD || op == OP_MAIN_PREV_UNREAD ||
+                  op == OP_MAIN_NEXT_NEW_THEN_UNREAD
+                  || op == OP_MAIN_PREV_NEW_THEN_UNREAD)
+                 && first_unread != -1)
+          menu->current = first_unread;
+
+        if (menu->current == -1) {
+          menu->current = menu->oldcurrent;
+          mutt_error ("%s%s.",
+                      (op == OP_MAIN_NEXT_NEW
+                       || op ==
+                       OP_MAIN_PREV_NEW) ? _("No new messages") :
+                      _("No unread messages"),
+                      Context->pattern ? _(" in this limited view") : "");
+        }
+        else if (menu->menu == MENU_PAGER) {
+          op = OP_DISPLAY_MESSAGE;
+          continue;
+        }
+        else
+          menu->redraw = REDRAW_MOTION;
+        break;
+      }
+    case OP_FLAG_MESSAGE:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
 
 #ifdef USE_POP
-       if (Context->magic == M_POP)
-       {
-         mutt_flushinp ();
-         mutt_error _("Can't edit message on POP server.");
-         break;
-       }
+      if (Context->magic == M_POP) {
+        mutt_flushinp ();
+        mutt_error (_("Can't change 'important' flag on POP server."));
+
+        break;
+      }
 #endif
 
 #ifdef USE_IMAP
-CHECK_IMAP_ACL(IMAP_ACL_INSERT);
+      CHECK_IMAP_ACL (IMAP_ACL_WRITE);
 #endif
 
 #ifdef USE_NNTP
-       if (Context->magic == M_NNTP)
-       {
-         mutt_flushinp ();
-         mutt_error _("Can't edit message on newsserver.");
-         break;
-       }
+      if (Context->magic == M_NNTP) {
+        mutt_flushinp ();
+        mutt_error (_("Can't change 'important' flag on NNTP server."));
+
+        break;
+      }
 #endif
 
-        mutt_edit_message (Context, tag ? NULL : CURHDR);
-       menu->redraw = REDRAW_FULL;
+      if (tag) {
+        for (j = 0; j < Context->vcount; j++) {
+          if (Context->hdrs[Context->v2r[j]]->tagged)
+            mutt_set_flag (Context, Context->hdrs[Context->v2r[j]],
+                           M_FLAG, !Context->hdrs[Context->v2r[j]]->flagged);
+        }
 
-       break;
+        menu->redraw |= REDRAW_INDEX;
+      }
+      else {
+        mutt_set_flag (Context, CURHDR, M_FLAG, !CURHDR->flagged);
+        if (option (OPTRESOLVE)) {
+          if ((menu->current = ci_next_undeleted (menu->current)) == -1) {
+            menu->current = menu->oldcurrent;
+            menu->redraw = REDRAW_CURRENT;
+          }
+          else
+            menu->redraw = REDRAW_MOTION_RESYNCH;
+        }
+        else
+          menu->redraw = REDRAW_CURRENT;
+      }
+      menu->redraw |= REDRAW_STATUS;
+      break;
 
-      case OP_FORWARD_MESSAGE:
+    case OP_TOGGLE_NEW:
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_ATTACH;
-       ci_send_message (SENDFORWARD, NULL, NULL, Context, tag ? NULL : CURHDR);
-       menu->redraw = REDRAW_FULL;
-       break;
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
 
+#ifdef USE_IMAP
+      CHECK_IMAP_ACL (IMAP_ACL_SEEN);
+#endif
 
-      case OP_FORGET_PASSPHRASE:
-       crypt_forget_passphrase ();
-       break;
+      if (tag) {
+        for (j = 0; j < Context->vcount; j++) {
+          if (Context->hdrs[Context->v2r[j]]->tagged) {
+            if (Context->hdrs[Context->v2r[j]]->read ||
+                Context->hdrs[Context->v2r[j]]->old)
+              mutt_set_flag (Context, Context->hdrs[Context->v2r[j]], M_NEW,
+                             1);
+            else
+              mutt_set_flag (Context, Context->hdrs[Context->v2r[j]], M_READ,
+                             1);
+          }
+        }
+        menu->redraw = REDRAW_STATUS | REDRAW_INDEX;
+      }
+      else {
+        if (CURHDR->read || CURHDR->old)
+          mutt_set_flag (Context, CURHDR, M_NEW, 1);
+        else
+          mutt_set_flag (Context, CURHDR, M_READ, 1);
+
+        if (option (OPTRESOLVE)) {
+          if ((menu->current = ci_next_undeleted (menu->current)) == -1) {
+            menu->current = menu->oldcurrent;
+            menu->redraw = REDRAW_CURRENT;
+          }
+          else
+            menu->redraw = REDRAW_MOTION_RESYNCH;
+        }
+        else
+          menu->redraw = REDRAW_CURRENT;
+        menu->redraw |= REDRAW_STATUS;
+      }
+      break;
 
-      case OP_GROUP_REPLY:
+    case OP_TOGGLE_WRITE:
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_ATTACH;
-       ci_send_message (SENDREPLY|SENDGROUPREPLY, NULL, NULL, Context, tag ? NULL : CURHDR);
-       menu->redraw = REDRAW_FULL;
-       break;
+      CHECK_MSGCOUNT;
+      if (mx_toggle_write (Context) == 0)
+        menu->redraw |= REDRAW_STATUS;
+      break;
 
-      case OP_LIST_REPLY:
+    case OP_MAIN_NEXT_THREAD:
+    case OP_MAIN_NEXT_SUBTHREAD:
+    case OP_MAIN_PREV_THREAD:
+    case OP_MAIN_PREV_SUBTHREAD:
 
-       CHECK_ATTACH;
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       ci_send_message (SENDREPLY|SENDLISTREPLY, NULL, NULL, Context, tag ? NULL : CURHDR);
-       menu->redraw = REDRAW_FULL;
-       break;
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      switch (op) {
+      case OP_MAIN_NEXT_THREAD:
+        menu->current = mutt_next_thread (CURHDR);
+        break;
 
-      case OP_MAIL:
+      case OP_MAIN_NEXT_SUBTHREAD:
+        menu->current = mutt_next_subthread (CURHDR);
+        break;
 
-       CHECK_ATTACH;
-       ci_send_message (0, NULL, NULL, Context, NULL);
-       menu->redraw = REDRAW_FULL;
-       break;
+      case OP_MAIN_PREV_THREAD:
+        menu->current = mutt_previous_thread (CURHDR);
+        break;
 
-      case OP_MAIL_KEY:
-        if (!(WithCrypto & APPLICATION_PGP))
-          break;
-       CHECK_ATTACH;
-       ci_send_message (SENDKEY, NULL, NULL, NULL, NULL);
-       menu->redraw = REDRAW_FULL;
-       break;
-
-      
-      case OP_EXTRACT_KEYS:
-        if (!WithCrypto)
-          break;
-        CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-        crypt_extract_keys_from_messages(tag ? NULL : CURHDR);
-        menu->redraw = REDRAW_FULL;
+      case OP_MAIN_PREV_SUBTHREAD:
+        menu->current = mutt_previous_subthread (CURHDR);
         break;
+      }
 
+      if (menu->current < 0) {
+        menu->current = menu->oldcurrent;
+        if (op == OP_MAIN_NEXT_THREAD || op == OP_MAIN_NEXT_SUBTHREAD)
+          mutt_error (_("No more threads."));
+
+        else
+          mutt_error (_("You are on the first thread."));
+      }
+      else if (menu->menu == MENU_PAGER) {
+        op = OP_DISPLAY_MESSAGE;
+        continue;
+      }
+      else
+        menu->redraw = REDRAW_MOTION;
+      break;
+
+    case OP_MAIN_PARENT_MESSAGE:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+
+      if ((menu->current = mutt_parent_message (Context, CURHDR)) < 0) {
+        menu->current = menu->oldcurrent;
+      }
+      else if (menu->menu == MENU_PAGER) {
+        op = OP_DISPLAY_MESSAGE;
+        continue;
+      }
+      else
+        menu->redraw = REDRAW_MOTION;
+      break;
+
+    case OP_MAIN_SET_FLAG:
+    case OP_MAIN_CLEAR_FLAG:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
+
+/* #ifdef USE_IMAP
+CHECK_IMAP_ACL(IMAP_ACL_WRITE);
+#endif */
+
+      if (mutt_change_flag (tag ? NULL : CURHDR, (op == OP_MAIN_SET_FLAG)) ==
+          0) {
+        menu->redraw = REDRAW_STATUS;
+        if (tag)
+          menu->redraw |= REDRAW_INDEX;
+        else if (option (OPTRESOLVE)) {
+          if ((menu->current = ci_next_undeleted (menu->current)) == -1) {
+            menu->current = menu->oldcurrent;
+            menu->redraw |= REDRAW_CURRENT;
+          }
+          else
+            menu->redraw |= REDRAW_MOTION_RESYNCH;
+        }
+        else
+          menu->redraw |= REDRAW_CURRENT;
+      }
+      break;
+
+    case OP_MAIN_COLLAPSE_THREAD:
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+
+      if ((Sort & SORT_MASK) != SORT_THREADS) {
+        mutt_error (_("Threading is not enabled."));
 
-      case OP_CHECK_TRADITIONAL:
-        if (!(WithCrypto & APPLICATION_PGP))
-          break;
-        CHECK_MSGCOUNT; 
-        CHECK_VISIBLE;
-        mutt_check_traditional_pgp (tag ? NULL : CURHDR, &menu->redraw);
-        if (menu->menu == MENU_PAGER)
-        {
-         op = OP_DISPLAY_MESSAGE;
-         continue;
-       }
         break;
-      
-      case OP_PIPE:
+      }
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       mutt_pipe_message (tag ? NULL : CURHDR);
-       MAYBE_REDRAW (menu->redraw);
-       break;
+      if (CURHDR->collapsed) {
+        menu->current = mutt_uncollapse_thread (Context, CURHDR);
+        mutt_set_virtual (Context);
+        if (option (OPTUNCOLLAPSEJUMP))
+          menu->current = mutt_thread_next_unread (Context, CURHDR);
+      }
+      else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (CURHDR)) {
+        menu->current = mutt_collapse_thread (Context, CURHDR);
+        mutt_set_virtual (Context);
+      }
+      else {
+        mutt_error (_("Thread contains unread messages."));
+
+        break;
+      }
 
-      case OP_PRINT:
+      menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       mutt_print_message (tag ? NULL : CURHDR);
-       break;
+      break;
 
-      case OP_MAIN_READ_THREAD:
-      case OP_MAIN_READ_SUBTHREAD:
+    case OP_MAIN_COLLAPSE_ALL:
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_READONLY;
+      if ((Sort & SORT_MASK) != SORT_THREADS) {
+        mutt_error (_("Threading is not enabled."));
+
+        break;
+      }
+
+      {
+        HEADER *h, *base;
+        THREAD *thread, *top;
+        int final;
+
+        if (CURHDR->collapsed)
+          final = mutt_uncollapse_thread (Context, CURHDR);
+        else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (CURHDR))
+          final = mutt_collapse_thread (Context, CURHDR);
+        else
+          final = CURHDR->virtual;
+
+        base = Context->hdrs[Context->v2r[final]];
+
+        top = Context->tree;
+        Context->collapsed = !Context->collapsed;
+        while ((thread = top) != NULL) {
+          while (!thread->message)
+            thread = thread->child;
+          h = thread->message;
+
+          if (h->collapsed != Context->collapsed) {
+            if (h->collapsed)
+              mutt_uncollapse_thread (Context, h);
+            else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (h))
+              mutt_collapse_thread (Context, h);
+          }
+          top = top->next;
+        }
+
+        mutt_set_virtual (Context);
+        for (j = 0; j < Context->vcount; j++) {
+          if (Context->hdrs[Context->v2r[j]]->index == base->index) {
+            menu->current = j;
+            break;
+          }
+        }
+
+        menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
+      }
+      break;
+
+      /* --------------------------------------------------------------------
+       * These functions are invoked directly from the internal-pager
+       */
+
+    case OP_BOUNCE_MESSAGE:
+
+      CHECK_ATTACH;
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      ci_bounce_message (tag ? NULL : CURHDR, &menu->redraw);
+      break;
+
+    case OP_CREATE_ALIAS:
+
+      mutt_create_alias (Context
+                         && Context->vcount ? CURHDR->env : NULL, NULL);
+      MAYBE_REDRAW (menu->redraw);
+      menu->redraw |= REDRAW_CURRENT;
+      break;
+
+    case OP_QUERY:
+      CHECK_ATTACH;
+      mutt_query_menu (NULL, 0);
+      MAYBE_REDRAW (menu->redraw);
+      break;
+
+    case OP_PURGE_MESSAGE:
+    case OP_DELETE:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
 
 #ifdef USE_IMAP
-CHECK_IMAP_ACL(IMAP_ACL_SEEN);
+      CHECK_IMAP_ACL (IMAP_ACL_DELETE);
 #endif
 
-       rc = mutt_thread_set_flag (CURHDR, M_READ, 1,
-                                  op == OP_MAIN_READ_THREAD ? 0 : 1);
-
-       if (rc != -1)
-       {
-         if (option (OPTRESOLVE))
-         {
-           if ((menu->current = (op == OP_MAIN_READ_THREAD ? 
-                                 mutt_next_thread (CURHDR) : mutt_next_subthread (CURHDR))) == -1)
-             menu->current = menu->oldcurrent;
-         }
-         menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-       }
-       break;
-
-      case OP_RECALL_MESSAGE:
-
-       CHECK_ATTACH;
-       ci_send_message (SENDPOSTPONED, NULL, NULL, Context, NULL);
-       menu->redraw = REDRAW_FULL;
-       break;
-
-      case OP_RESEND:
-      
-        CHECK_ATTACH;
-        CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-      
-        if (tag)
-        {
-         for (j = 0; j < Context->vcount; j++)
-         {
-           if (Context->hdrs[Context->v2r[j]]->tagged)
-             mutt_resend_message (NULL, Context, Context->hdrs[Context->v2r[j]]);
-         }
-       }
+      if (tag) {
+        mutt_tag_set_flag (M_DELETE, 1);
+        mutt_tag_set_flag (M_PURGED, (op != OP_PURGE_MESSAGE) ? 0 : 1);
+        if (option (OPTDELETEUNTAG))
+          mutt_tag_set_flag (M_TAG, 0);
+        menu->redraw = REDRAW_INDEX;
+      }
+      else {
+        mutt_set_flag (Context, CURHDR, M_DELETE, 1);
+        mutt_set_flag (Context, CURHDR, M_PURGED,
+                       (op != OP_PURGE_MESSAGE) ? 0 : 1);
+        if (option (OPTDELETEUNTAG))
+          mutt_set_flag (Context, CURHDR, M_TAG, 0);
+        if (option (OPTRESOLVE)) {
+          if ((menu->current = ci_next_undeleted (menu->current)) == -1) {
+            menu->current = menu->oldcurrent;
+            menu->redraw = REDRAW_CURRENT;
+          }
+          else if (menu->menu == MENU_PAGER) {
+            op = OP_DISPLAY_MESSAGE;
+            continue;
+          }
+          else
+            menu->redraw |= REDRAW_MOTION_RESYNCH;
+        }
         else
-         mutt_resend_message (NULL, Context, CURHDR);
-      
+          menu->redraw = REDRAW_CURRENT;
+      }
+      menu->redraw |= REDRAW_STATUS;
+      break;
+
+    case OP_DELETE_THREAD:
+    case OP_DELETE_SUBTHREAD:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
+
+#ifdef USE_IMAP
+      CHECK_IMAP_ACL (IMAP_ACL_DELETE);
+#endif
+
+      rc = mutt_thread_set_flag (CURHDR, M_DELETE, 1,
+                                 op == OP_DELETE_THREAD ? 0 : 1);
+
+      if (rc != -1) {
+        if (option (OPTDELETEUNTAG))
+          mutt_thread_set_flag (CURHDR, M_TAG, 0,
+                                op == OP_DELETE_THREAD ? 0 : 1);
+        if (option (OPTRESOLVE))
+          if ((menu->current = ci_next_undeleted (menu->current)) == -1)
+            menu->current = menu->oldcurrent;
+        menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
+      }
+      break;
+
+#ifdef USE_NNTP
+    case OP_CATCHUP:
+      if (Context && Context->magic == M_NNTP) {
+        if (mutt_newsgroup_catchup (CurrentNewsSrv,
+                                    ((NNTP_DATA *) Context->data)->group))
+          menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
+      }
+      break;
+#endif
+
+    case OP_DISPLAY_ADDRESS:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      mutt_display_address (CURHDR->env);
+      break;
+
+    case OP_ENTER_COMMAND:
+
+      CurrentMenu = MENU_MAIN;
+      mutt_enter_command ();
+      mutt_check_rescore (Context);
+      if (option (OPTFORCEREDRAWINDEX))
         menu->redraw = REDRAW_FULL;
+      unset_option (OPTFORCEREDRAWINDEX);
+      unset_option (OPTFORCEREDRAWPAGER);
+      break;
+
+    case OP_EDIT_MESSAGE:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
+      CHECK_ATTACH;
+
+#ifdef USE_POP
+      if (Context->magic == M_POP) {
+        mutt_flushinp ();
+        mutt_error (_("Can't edit message on POP server."));
+
         break;
+      }
+#endif
+
+#ifdef USE_IMAP
+      CHECK_IMAP_ACL (IMAP_ACL_INSERT);
+#endif
 
 #ifdef USE_NNTP
-      case OP_POST:
-      case OP_FOLLOWUP:
-      case OP_FORWARD_TO_GROUP:
-
-       CHECK_ATTACH;
-       if (op != OP_FOLLOWUP || !CURHDR->env->followup_to ||
-           mutt_strcasecmp (CURHDR->env->followup_to, "poster") ||
-           query_quadoption (OPT_FOLLOWUPTOPOSTER,_("Reply by mail as poster prefers?")) != M_YES)
-       {
-         if (Context && Context->magic == M_NNTP &&
-             !((NNTP_DATA *)Context->data)->allowed &&
-             query_quadoption (OPT_TOMODERATED, _("Posting to this group not allowed, may be moderated. Continue?")) != M_YES)
-           break;
-         if (op == OP_POST)
-           ci_send_message (SENDNEWS, NULL, NULL, Context, NULL);
-         else
-         {
-           CHECK_MSGCOUNT;
-           if (op == OP_FOLLOWUP)
-             ci_send_message (SENDNEWS|SENDREPLY, NULL, NULL, Context,
-                              tag ? NULL : CURHDR);
-           else
-             ci_send_message (SENDNEWS|SENDFORWARD, NULL, NULL, Context,
-                              tag ? NULL : CURHDR);
-         }
-         menu->redraw = REDRAW_FULL;
-         break;
-       }
+      if (Context->magic == M_NNTP) {
+        mutt_flushinp ();
+        mutt_error (_("Can't edit message on newsserver."));
+
+        break;
+      }
 #endif
-      
-      case OP_REPLY:
 
-       CHECK_ATTACH;
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       ci_send_message (SENDREPLY, NULL, NULL, Context, tag ? NULL : CURHDR);
-       menu->redraw = REDRAW_FULL;
-       break;
+      if (option (OPTPGPAUTODEC)
+          && (tag || !(CURHDR->security & PGP_TRADITIONAL_CHECKED)))
+        mutt_check_traditional_pgp (tag ? NULL : CURHDR, &menu->redraw);
+      mutt_edit_message (Context, tag ? NULL : CURHDR);
+      menu->redraw = REDRAW_FULL;
+
+      break;
+
+    case OP_FORWARD_MESSAGE:
 
-      case OP_SHELL_ESCAPE:
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_ATTACH;
+      ci_send_message (SENDFORWARD, NULL, NULL, Context, tag ? NULL : CURHDR);
+      menu->redraw = REDRAW_FULL;
+      break;
 
-       mutt_shell_escape ();
-       MAYBE_REDRAW (menu->redraw);
-       break;
 
-      case OP_TAG_THREAD:
-      case OP_TAG_SUBTHREAD:
+    case OP_FORGET_PASSPHRASE:
+      crypt_forget_passphrase ();
+      break;
 
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       rc = mutt_thread_set_flag (CURHDR, M_TAG, !CURHDR->tagged,
-                                  op == OP_TAG_THREAD ? 0 : 1);
-       
-       if (rc != -1)
-       {
-         if (option (OPTRESOLVE))
-         {
-           menu->current = mutt_next_thread (CURHDR);
-
-           if (menu->current == -1)
-             menu->current = menu->oldcurrent;
-         }
-         menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-       }
-       break;
-
-      case OP_UNDELETE:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_READONLY;
+    case OP_GROUP_REPLY:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_ATTACH;
+      ci_send_message (SENDREPLY | SENDGROUPREPLY, NULL, NULL, Context,
+                       tag ? NULL : CURHDR);
+      menu->redraw = REDRAW_FULL;
+      break;
+
+    case OP_LIST_REPLY:
+
+      CHECK_ATTACH;
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      ci_send_message (SENDREPLY | SENDLISTREPLY, NULL, NULL, Context,
+                       tag ? NULL : CURHDR);
+      menu->redraw = REDRAW_FULL;
+      break;
+
+    case OP_MAIL:
+
+      CHECK_ATTACH;
+      ci_send_message (0, NULL, NULL, Context, NULL);
+      menu->redraw = REDRAW_FULL;
+      break;
+
+    case OP_MAIL_KEY:
+      if (!(WithCrypto & APPLICATION_PGP))
+        break;
+      CHECK_ATTACH;
+      ci_send_message (SENDKEY, NULL, NULL, NULL, NULL);
+      menu->redraw = REDRAW_FULL;
+      break;
+
+
+    case OP_EXTRACT_KEYS:
+      if (!WithCrypto)
+        break;
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      crypt_extract_keys_from_messages (tag ? NULL : CURHDR);
+      menu->redraw = REDRAW_FULL;
+      break;
+
+
+    case OP_CHECK_TRADITIONAL:
+      if (!(WithCrypto & APPLICATION_PGP))
+        break;
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      if (tag || !(CURHDR->security & PGP_TRADITIONAL_CHECKED))
+        mutt_check_traditional_pgp (tag ? NULL : CURHDR, &menu->redraw);
+
+      if (menu->menu == MENU_PAGER) {
+        op = OP_DISPLAY_MESSAGE;
+        continue;
+      }
+      break;
+
+    case OP_PIPE:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      mutt_pipe_message (tag ? NULL : CURHDR);
+      MAYBE_REDRAW (menu->redraw);
+      break;
+
+    case OP_PRINT:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      mutt_print_message (tag ? NULL : CURHDR);
+      break;
+
+    case OP_MAIN_READ_THREAD:
+    case OP_MAIN_READ_SUBTHREAD:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
 
 #ifdef USE_IMAP
-CHECK_IMAP_ACL(IMAP_ACL_DELETE);
+      CHECK_IMAP_ACL (IMAP_ACL_SEEN);
 #endif
-       
-       if (tag)
-       {
-         mutt_tag_set_flag (M_DELETE, 0);
-         mutt_tag_set_flag (M_PURGED, 0);
-         menu->redraw = REDRAW_INDEX;
-       }
-       else
-       {
-         mutt_set_flag (Context, CURHDR, M_DELETE, 0);
-         mutt_set_flag (Context, CURHDR, M_PURGED, 0);
-         if (option (OPTRESOLVE) && menu->current < Context->vcount - 1)
-         {
-           menu->current++;
-           menu->redraw = REDRAW_MOTION_RESYNCH;
-         }
-         else
-           menu->redraw = REDRAW_CURRENT;
-       }
-       menu->redraw |= REDRAW_STATUS;
-       break;
-
-      case OP_UNDELETE_THREAD:
-      case OP_UNDELETE_SUBTHREAD:
-
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       CHECK_READONLY;
+
+      rc = mutt_thread_set_flag (CURHDR, M_READ, 1,
+                                 op == OP_MAIN_READ_THREAD ? 0 : 1);
+
+      if (rc != -1) {
+        if (option (OPTRESOLVE)) {
+          if ((menu->current = (op == OP_MAIN_READ_THREAD ?
+                                mutt_next_thread (CURHDR) :
+                                mutt_next_subthread (CURHDR))) == -1)
+            menu->current = menu->oldcurrent;
+        }
+        menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
+      }
+      break;
+
+    case OP_RECALL_MESSAGE:
+
+      CHECK_ATTACH;
+      ci_send_message (SENDPOSTPONED, NULL, NULL, Context, NULL);
+      menu->redraw = REDRAW_FULL;
+      break;
+
+    case OP_RESEND:
+
+      CHECK_ATTACH;
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+
+      if (tag) {
+        for (j = 0; j < Context->vcount; j++) {
+          if (Context->hdrs[Context->v2r[j]]->tagged)
+            mutt_resend_message (NULL, Context,
+                                 Context->hdrs[Context->v2r[j]]);
+        }
+      }
+      else
+        mutt_resend_message (NULL, Context, CURHDR);
+
+      menu->redraw = REDRAW_FULL;
+      break;
+
+#ifdef USE_NNTP
+    case OP_POST:
+    case OP_FOLLOWUP:
+    case OP_FORWARD_TO_GROUP:
+
+      CHECK_ATTACH;
+      if ((op == OP_FOLLOWUP || op == OP_FORWARD_TO_GROUP) &&
+          Context && Context->msgcount == 0) {
+        mutt_error (_("There are no messages."));
+        sleep (2);
+      }
+      else if (op != OP_FOLLOWUP || !CURHDR->env->followup_to ||
+               mutt_strcasecmp (CURHDR->env->followup_to, "poster") ||
+               query_quadoption (OPT_FOLLOWUPTOPOSTER,
+                                 _("Reply by mail as poster prefers?")) !=
+               M_YES) {
+        if (Context && Context->magic == M_NNTP
+            && !((NNTP_DATA *) Context->data)->allowed
+            && query_quadoption (OPT_TOMODERATED,
+                                 _
+                                 ("Posting to this group not allowed, may be moderated. Continue?"))
+            != M_YES)
+          break;
+        if (op == OP_POST)
+          ci_send_message (SENDNEWS, NULL, NULL, Context, NULL);
+        else {
+          CHECK_MSGCOUNT;
+          if (op == OP_FOLLOWUP)
+            ci_send_message (SENDNEWS | SENDREPLY, NULL, NULL, Context,
+                             tag ? NULL : CURHDR);
+          else
+            ci_send_message (SENDNEWS | SENDFORWARD, NULL, NULL, Context,
+                             tag ? NULL : CURHDR);
+        }
+        menu->redraw = REDRAW_FULL;
+        break;
+      }
+#endif
+
+    case OP_REPLY:
+
+      CHECK_ATTACH;
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      ci_send_message (SENDREPLY, NULL, NULL, Context, tag ? NULL : CURHDR);
+      menu->redraw = REDRAW_FULL;
+      break;
+
+    case OP_SHELL_ESCAPE:
+
+      mutt_shell_escape ();
+      MAYBE_REDRAW (menu->redraw);
+      break;
+
+    case OP_TAG_THREAD:
+    case OP_TAG_SUBTHREAD:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      rc = mutt_thread_set_flag (CURHDR, M_TAG, !CURHDR->tagged,
+                                 op == OP_TAG_THREAD ? 0 : 1);
+
+      if (rc != -1) {
+        if (option (OPTRESOLVE)) {
+          menu->current = mutt_next_thread (CURHDR);
+
+          if (menu->current == -1)
+            menu->current = menu->oldcurrent;
+        }
+        menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
+      }
+      break;
+
+    case OP_UNDELETE:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
 
 #ifdef USE_IMAP
-CHECK_IMAP_ACL(IMAP_ACL_DELETE);
+      CHECK_IMAP_ACL (IMAP_ACL_DELETE);
 #endif
 
-       rc = mutt_thread_set_flag (CURHDR, M_DELETE, 0,
-                                  op == OP_UNDELETE_THREAD ? 0 : 1)
-         + mutt_thread_set_flag (CURHDR, M_PURGED, 0,
-                                 op == OP_UNDELETE_THREAD ? 0 : 1);
-
-       if (rc > -1)
-       {
-         if (option (OPTRESOLVE))
-         {
-           if (op == OP_UNDELETE_THREAD)
-             menu->current = mutt_next_thread (CURHDR);
-           else
-             menu->current = mutt_next_subthread (CURHDR);
-
-           if (menu->current == -1)
-             menu->current = menu->oldcurrent;
-         }
-         menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
-       }
-       break;
-
-      case OP_VERSION:
-       mutt_version ();
-       break;
-
-      case OP_BUFFY_LIST:
-       mutt_buffy_list ();
-       break;
-
-      case OP_VIEW_ATTACHMENTS:
-       CHECK_MSGCOUNT;
-        CHECK_VISIBLE;
-       mutt_view_attachments (CURHDR);
-       if (CURHDR->attach_del)
-         Context->changed = 1;
-       menu->redraw = REDRAW_FULL;
-       break;
-
-      case OP_END_COND:
-       break;
-
-      case OP_WHAT_KEY:
-       mutt_what_key();
-       break;
-
-      default:
-       if (menu->menu == MENU_MAIN)
-         km_error_key (MENU_MAIN);
+      if (tag) {
+        mutt_tag_set_flag (M_DELETE, 0);
+        mutt_tag_set_flag (M_PURGED, 0);
+        menu->redraw = REDRAW_INDEX;
+      }
+      else {
+        mutt_set_flag (Context, CURHDR, M_DELETE, 0);
+        mutt_set_flag (Context, CURHDR, M_PURGED, 0);
+        if (option (OPTRESOLVE) && menu->current < Context->vcount - 1) {
+          menu->current++;
+          menu->redraw = REDRAW_MOTION_RESYNCH;
+        }
+        else
+          menu->redraw = REDRAW_CURRENT;
+      }
+      menu->redraw |= REDRAW_STATUS;
+      break;
+
+    case OP_UNDELETE_THREAD:
+    case OP_UNDELETE_SUBTHREAD:
+
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      CHECK_READONLY;
+
+#ifdef USE_IMAP
+      CHECK_IMAP_ACL (IMAP_ACL_DELETE);
+#endif
+
+      rc = mutt_thread_set_flag (CURHDR, M_DELETE, 0,
+                                 op == OP_UNDELETE_THREAD ? 0 : 1)
+        + mutt_thread_set_flag (CURHDR, M_PURGED, 0,
+                                op == OP_UNDELETE_THREAD ? 0 : 1);
+
+      if (rc > -1) {
+        if (option (OPTRESOLVE)) {
+          if (op == OP_UNDELETE_THREAD)
+            menu->current = mutt_next_thread (CURHDR);
+          else
+            menu->current = mutt_next_subthread (CURHDR);
+
+          if (menu->current == -1)
+            menu->current = menu->oldcurrent;
+        }
+        menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
+      }
+      break;
+
+    case OP_VERSION:
+      mutt_version ();
+      break;
+
+    case OP_BUFFY_LIST:
+      mutt_buffy_list ();
+      menu->redraw = REDRAW_FULL;
+      break;
+
+    case OP_VIEW_ATTACHMENTS:
+      CHECK_MSGCOUNT;
+      CHECK_VISIBLE;
+      mutt_view_attachments (CURHDR);
+      if (CURHDR->attach_del)
+        Context->changed = 1;
+      menu->redraw = REDRAW_FULL;
+      break;
+
+    case OP_END_COND:
+      break;
+
+    case OP_WHAT_KEY:
+      mutt_what_key ();
+      break;
+
+    case OP_SIDEBAR_SCROLL_UP:
+    case OP_SIDEBAR_SCROLL_DOWN:
+    case OP_SIDEBAR_NEXT:
+    case OP_SIDEBAR_PREV:
+    case OP_SIDEBAR_NEXT_NEW:
+    case OP_SIDEBAR_PREV_NEW:
+      sidebar_scroll (op, menu->menu);
+      break;
+    default:
+      if (menu->menu == MENU_MAIN)
+        km_error_key (MENU_MAIN);
     }
 
-    if (menu->menu == MENU_PAGER)
-    {
+    if (menu->menu == MENU_PAGER) {
       menu->menu = MENU_MAIN;
       menu->redraw = REDRAW_FULL;
 #if 0
-      set_option (OPTWEED); /* turn header weeding back on. */
+      set_option (OPTWEED);     /* turn header weeding back on. */
 #endif
     }
 
-    if (done) break;
+    if (done)
+      break;
   }
 
 #ifdef USE_IMAP
@@ -2368,18 +2409,18 @@ CHECK_IMAP_ACL(IMAP_ACL_DELETE);
   return (close);
 }
 
-void mutt_set_header_color (CONTEXT *ctx, HEADER *curhdr)
+void mutt_set_header_color (CONTEXT * ctx, HEADER * curhdr)
 {
   COLOR_LINE *color;
 
   if (!curhdr)
     return;
-  
+
   for (color = ColorIndexList; color; color = color->next)
-   if (mutt_pattern_exec (color->color_pattern, M_MATCH_FULL_ADDRESS, ctx, curhdr))
-   {
+    if (mutt_pattern_exec
+        (color->color_pattern, M_MATCH_FULL_ADDRESS, ctx, curhdr)) {
       curhdr->pair = color->pair;
       return;
-   }
+    }
   curhdr->pair = ColorDefs[MT_COLOR_NORMAL];
 }