Rocco Rutte:
[apps/madmutt.git] / mx.c
diff --git a/mx.c b/mx.c
index 2186651..51fc1b3 100644 (file)
--- a/mx.c
+++ b/mx.c
@@ -1,41 +1,44 @@
 /*
+ * Copyright notice from original mutt:
  * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org>
  * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.org>
- * 
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- * 
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- */ 
+ *
+ * This file is part of mutt-ng, see http://www.muttng.org/.
+ * It's licensed under the GNU General Public License,
+ * please see the file GPL in the top level source directory.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
 
 #include "mutt.h"
 #include "mx.h"
+#include "mbox.h"
+#include "mh.h"
 #include "rfc2047.h"
 #include "sort.h"
-#include "mailbox.h"
 #include "copy.h"
 #include "keymap.h"
 #include "url.h"
 
+#ifdef USE_COMPRESSED
+#include "compress.h"
+#endif
+
 #ifdef USE_IMAP
-#include "imap.h"
+#include "imap/imap.h"
+#include "imap/mx_imap.h"
 #endif
 
 #ifdef USE_POP
-#include "pop.h"
+#include "pop/pop.h"
+#include "pop/mx_pop.h"
 #endif
 
 #ifdef USE_NNTP
-#include "nntp.h"
+#include "nntp/nntp.h"
+#include "nntp/mx_nntp.h"
 #endif
 
 #ifdef BUFFY_SIZE
 
 #include "mutt_crypt.h"
 
+#include "lib/mem.h"
+#include "lib/intl.h"
+#include "lib/str.h"
+#include "lib/list.h"
+
 #include <dirent.h>
 #include <fcntl.h>
 #include <sys/file.h>
 #include <utime.h>
 #endif
 
+static list2_t* MailboxFormats = NULL;
+#define MX_COMMAND(idx,cmd) ((mx_t*) MailboxFormats->data[idx])->cmd
+#define MX_IDX(idx) (idx >= 0 && idx < MailboxFormats->length)
 
-#define mutt_is_spool(s)  (mutt_strcmp (Spoolfile, s) == 0)
+#define mutt_is_spool(s)  (safe_strcmp (Spoolfile, s) == 0)
 
 #ifdef USE_DOTLOCK
 /* parameters: 
@@ -77,27 +88,26 @@ static int invoke_dotlock (const char *path, int dummy, int flags, int retry)
   char cmd[LONG_STRING + _POSIX_PATH_MAX];
   char f[SHORT_STRING + _POSIX_PATH_MAX];
   char r[SHORT_STRING];
-  
+
   if (flags & DL_FL_RETRY)
     snprintf (r, sizeof (r), "-r %d ", retry ? MAXLOCKATTEMPT : 0);
-  
+
   mutt_quote_filename (f, sizeof (f), path);
-  
+
   snprintf (cmd, sizeof (cmd),
-           "%s %s%s%s%s%s%s%s",
-           NONULL (MuttDotlock),
-           flags & DL_FL_TRY ? "-t " : "",
-           flags & DL_FL_UNLOCK ? "-u " : "",
-           flags & DL_FL_USEPRIV ? "-p " : "",
-           flags & DL_FL_FORCE ? "-f " : "",
-           flags & DL_FL_UNLINK ? "-d " : "",
-           flags & DL_FL_RETRY ? r : "",
-           f);
-  
+            "%s %s%s%s%s%s%s%s",
+            NONULL (MuttDotlock),
+            flags & DL_FL_TRY ? "-t " : "",
+            flags & DL_FL_UNLOCK ? "-u " : "",
+            flags & DL_FL_USEPRIV ? "-p " : "",
+            flags & DL_FL_FORCE ? "-f " : "",
+            flags & DL_FL_UNLINK ? "-d " : "",
+            flags & DL_FL_RETRY ? r : "", f);
+
   return mutt_system (cmd);
 }
 
-#else 
+#else
 
 #define invoke_dotlock dotlock_invoke
 
@@ -108,28 +118,25 @@ static int dotlock_file (const char *path, int fd, int retry)
   int r;
   int flags = DL_FL_USEPRIV | DL_FL_RETRY;
 
-  if (retry) retry = 1;
+  if (retry)
+    retry = 1;
 
 retry_lock:
-  if ((r = invoke_dotlock(path, fd, flags, retry)) == DL_EX_EXIST)
-  {
-    if (!option (OPTNOCURSES))
-    {
+  if ((r = invoke_dotlock (path, fd, flags, retry)) == DL_EX_EXIST) {
+    if (!option (OPTNOCURSES)) {
       char msg[LONG_STRING];
-      
-      snprintf(msg, sizeof(msg), _("Lock count exceeded, remove lock for %s?"),
-              path);
-      if(retry && mutt_yesorno(msg, M_YES) == M_YES)
-      {
-       flags |= DL_FL_FORCE;
-       retry--;
-       mutt_clear_error ();
-       goto retry_lock;
+
+      snprintf (msg, sizeof (msg),
+                _("Lock count exceeded, remove lock for %s?"), path);
+      if (retry && mutt_yesorno (msg, M_YES) == M_YES) {
+        flags |= DL_FL_FORCE;
+        retry--;
+        mutt_clear_error ();
+        goto retry_lock;
       }
-    } 
-    else
-    {
-      mutt_error ( _("Can't dotlock %s.\n"), path);
+    }
+    else {
+      mutt_error (_("Can't dotlock %s.\n"), path);
     }
   }
   return (r == DL_EX_OK ? 0 : -1);
@@ -137,12 +144,37 @@ retry_lock:
 
 static int undotlock_file (const char *path, int fd)
 {
-  return (invoke_dotlock(path, fd, DL_FL_USEPRIV | DL_FL_UNLOCK, 0) == DL_EX_OK ? 
-         0 : -1);
+  return (invoke_dotlock (path, fd, DL_FL_USEPRIV | DL_FL_UNLOCK, 0) ==
+          DL_EX_OK ? 0 : -1);
 }
 
 #endif /* USE_DOTLOCK */
 
+/* looks up index of type for path in MailboxFormats */
+static int mx_get_idx (const char* path) {
+  int i = 0, t = 0;
+  struct stat st;
+
+  /* first, test all non-local folders to avoid stat() call */
+  for (i = 0; i < MailboxFormats->length; i++) {
+    if (!MX_COMMAND(i,local))
+      t = MX_COMMAND(i,mx_is_magic)(path, NULL);
+    if (t >= 1)
+      return (t-1);
+  }
+  if (stat (path, &st) == 0) {
+    /* if stat() succeeded, keep testing until success and
+     * pass stat() info so that we only need to do it once */
+    for (i = 0; i < MailboxFormats->length; i++) {
+      if (MX_COMMAND(i,local))
+        t = MX_COMMAND(i,mx_is_magic)(path, &st);
+      if (t >= 1)
+        return (t-1);
+    }
+  }
+  return (-1);
+}
+
 /* Args:
  *     excl            if excl != 0, request an exclusive lock
  *     dot             if dot != 0, try to dotlock the file
@@ -159,7 +191,7 @@ int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout)
 
 #ifdef USE_FCNTL
   struct flock lck;
-  
+
 
   memset (&lck, 0, sizeof (struct flock));
   lck.l_type = excl ? F_WRLCK : F_RDLCK;
@@ -167,27 +199,27 @@ int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout)
 
   count = 0;
   attempt = 0;
-  while (fcntl (fd, F_SETLK, &lck) == -1)
-  {
+  while (fcntl (fd, F_SETLK, &lck) == -1) {
     struct stat sb;
-    dprint(1,(debugfile, "mx_lock_file(): fcntl errno %d.\n", errno));
-    if (errno != EAGAIN && errno != EACCES)
-    {
+
+    dprint (1, (debugfile, "mx_lock_file(): fcntl errno %d.\n", errno));
+    if (errno != EAGAIN && errno != EACCES) {
       mutt_perror ("fcntl");
       return (-1);
     }
 
     if (fstat (fd, &sb) != 0)
-     sb.st_size = 0;
-    
+      sb.st_size = 0;
+
     if (count == 0)
       prev_sb = sb;
 
     /* only unlock file if it is unchanged */
-    if (prev_sb.st_size == sb.st_size && ++count >= (timeout?MAXLOCKATTEMPT:0))
-    {
+    if (prev_sb.st_size == sb.st_size
+        && ++count >= (timeout ? MAXLOCKATTEMPT : 0)) {
       if (timeout)
-       mutt_error _("Timeout exceeded while attempting fcntl lock!");
+        mutt_error _("Timeout exceeded while attempting fcntl lock!");
+
       return (-1);
     }
 
@@ -201,27 +233,27 @@ int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout)
 #ifdef USE_FLOCK
   count = 0;
   attempt = 0;
-  while (flock (fd, (excl ? LOCK_EX : LOCK_SH) | LOCK_NB) == -1)
-  {
+  while (flock (fd, (excl ? LOCK_EX : LOCK_SH) | LOCK_NB) == -1) {
     struct stat sb;
-    if (errno != EWOULDBLOCK)
-    {
+
+    if (errno != EWOULDBLOCK) {
       mutt_perror ("flock");
       r = -1;
       break;
     }
 
-    if (fstat(fd,&sb) != 0 )
-     sb.st_size=0;
-    
+    if (fstat (fd, &sb) != 0)
+      sb.st_size = 0;
+
     if (count == 0)
-      prev_sb=sb;
+      prev_sb = sb;
 
     /* only unlock file if it is unchanged */
-    if (prev_sb.st_size == sb.st_size && ++count >= (timeout?MAXLOCKATTEMPT:0))
-    {
+    if (prev_sb.st_size == sb.st_size
+        && ++count >= (timeout ? MAXLOCKATTEMPT : 0)) {
       if (timeout)
-       mutt_error _("Timeout exceeded while attempting flock lock!");
+        mutt_error _("Timeout exceeded while attempting flock lock!");
+
       r = -1;
       break;
     }
@@ -238,8 +270,7 @@ int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout)
     r = dotlock_file (path, fd, timeout);
 #endif /* USE_DOTLOCK */
 
-  if (r == -1)
-  {
+  if (r == -1) {
     /* release any other locks obtained in this routine */
 
 #ifdef USE_FCNTL
@@ -276,13 +307,14 @@ int mx_unlock_file (const char *path, int fd, int dot)
   if (dot)
     undotlock_file (path, fd);
 #endif
-  
+
   return 0;
 }
 
 void mx_unlink_empty (const char *path)
 {
   int fd;
+
 #ifndef USE_DOTLOCK
   struct stat sb;
 #endif
@@ -290,8 +322,7 @@ void mx_unlink_empty (const char *path)
   if ((fd = open (path, O_RDWR)) == -1)
     return;
 
-  if (mx_lock_file (path, fd, 1, 0, 1) == -1)
-  {
+  if (mx_lock_file (path, fd, 1, 0, 1) == -1) {
     close (fd);
     return;
   }
@@ -307,175 +338,21 @@ void mx_unlink_empty (const char *path)
   close (fd);
 }
 
-/* try to figure out what type of mailbox ``path'' is
- *
- * return values:
- *     M_*     mailbox type
- *     0       not a mailbox
- *     -1      error
- */
-
-#ifdef USE_IMAP
-
-int mx_is_imap(const char *p)
-{
-  url_scheme_t scheme;
-
-  if (!p)
-    return 0;
+/* try to figure out what type of mailbox ``path'' is */
+int mx_get_magic (const char *path) {
+  int i = 0;
 
-  if (*p == '{')
-    return 1;
-
-  scheme = url_check_scheme (p);
-  if (scheme == U_IMAP || scheme == U_IMAPS)
-    return 1;
-
-  return 0;
-}
-
-#endif
-
-#ifdef USE_POP
-int mx_is_pop (const char *p)
-{
-  url_scheme_t scheme;
-
-  if (!p)
-    return 0;
-
-  scheme = url_check_scheme (p);
-  if (scheme == U_POP || scheme == U_POPS)
-    return 1;
-
-  return 0;
-}
-#endif
-
-#ifdef USE_NNTP
-int mx_is_nntp (const char *p)
-{
-  url_scheme_t scheme;
-
-  if (!p)
-    return 0;
-
-  scheme = url_check_scheme (p);
-  if (scheme == U_NNTP || scheme == U_NNTPS)
-    return 1;
-
-  return 0;
-}
-#endif
-
-int mx_get_magic (const char *path)
-{
-  struct stat st;
-  int magic = 0;
-  char tmp[_POSIX_PATH_MAX];
-  FILE *f;
-
-#ifdef USE_IMAP
-  if(mx_is_imap(path))
-    return M_IMAP;
-#endif /* USE_IMAP */
-
-#ifdef USE_POP
-  if (mx_is_pop (path))
-    return M_POP;
-#endif /* USE_POP */
-
-#ifdef USE_NNTP
-  if (mx_is_nntp (path))
-    return M_NNTP;
-#endif /* USE_NNTP */
-
-  if (stat (path, &st) == -1)
-  {
-    dprint (1, (debugfile, "mx_get_magic(): unable to stat %s: %s (errno %d).\n",
-               path, strerror (errno), errno));
+  if (safe_strlen (path) == 0)
     return (-1);
-  }
-
-  if (S_ISDIR (st.st_mode))
-  {
-    /* check for maildir-style mailbox */
-
-    snprintf (tmp, sizeof (tmp), "%s/cur", path);
-    if (stat (tmp, &st) == 0 && S_ISDIR (st.st_mode))
-      return (M_MAILDIR);
-
-    /* check for mh-style mailbox */
-
-    snprintf (tmp, sizeof (tmp), "%s/.mh_sequences", path);
-    if (access (tmp, F_OK) == 0)
-      return (M_MH);
-
-    snprintf (tmp, sizeof (tmp), "%s/.xmhcache", path);
-    if (access (tmp, F_OK) == 0)
-      return (M_MH);
-    
-    snprintf (tmp, sizeof (tmp), "%s/.mew_cache", path);
-    if (access (tmp, F_OK) == 0)
-      return (M_MH);
-
-    snprintf (tmp, sizeof (tmp), "%s/.mew-cache", path);
-    if (access (tmp, F_OK) == 0)
-      return (M_MH);
-    
-    snprintf (tmp, sizeof (tmp), "%s/.sylpheed_cache", path);
-    if (access (tmp, F_OK) == 0)
-      return (M_MH);
-
-    /* 
-     * ok, this isn't an mh folder, but mh mode can be used to read
-     * Usenet news from the spool. ;-) 
-     */
-
-    snprintf (tmp, sizeof (tmp), "%s/.overview", path);
-    if (access (tmp, F_OK) == 0)
-      return (M_MH);
-
-  }
-  else if (st.st_size == 0)
-  {
-    /* hard to tell what zero-length files are, so assume the default magic */
-    if (DefaultMagic == M_MBOX || DefaultMagic == M_MMDF)
-      return (DefaultMagic);
-    else
-      return (M_MBOX);
-  }
-  else if ((f = fopen (path, "r")) != NULL)
-  {
-#ifndef BUFFY_SIZE
-    struct utimbuf times;
-#endif
-
-    fgets (tmp, sizeof (tmp), f);
-    if (mutt_strncmp ("From ", tmp, 5) == 0)
-      magic = M_MBOX;
-    else if (mutt_strcmp (MMDF_SEP, tmp) == 0)
-      magic = M_MMDF;
-    safe_fclose (&f);
-#ifndef BUFFY_SIZE
-    /* need to restore the times here, the file was not really accessed,
-     * only the type was accessed.  This is important, because detection
-     * of "new mail" depends on those times set correctly.
-     */
-    times.actime = st.st_atime;
-    times.modtime = st.st_mtime;
-    utime (path, &times);
-#endif
-  }
-  else
-  {
-    dprint (1, (debugfile, "mx_get_magic(): unable to open file %s for reading.\n",
-               path));
-    mutt_perror (path);
-    return (-1);
-  }
+  if ((i = mx_get_idx (path)) >= 0)
+    return (MX_COMMAND(i,type));
+  return (-1);
+}
 
-  return (magic);
+int mx_is_local (int m) {
+  if (!MX_IDX(m))
+    return (0);
+  return (MX_COMMAND(m,local));
 }
 
 /*
@@ -500,134 +377,126 @@ int mx_set_magic (const char *s)
 /* mx_access: Wrapper for access, checks permissions on a given mailbox.
  *   We may be interested in using ACL-style flags at some point, currently
  *   we use the normal access() flags. */
-int mx_access (const charpath, int flags)
+int mx_access (const char *path, int flags)
 {
-#ifdef USE_IMAP
-  if (mx_is_imap (path))
-    return imap_access (path, flags);
-#endif
+  int i = 0;
 
-  return access (path, flags);
+  if ((i = mx_get_idx (path)) >= 0 && MX_COMMAND(i,mx_access))
+    return (MX_COMMAND(i,mx_access)(path,flags));
+  return (0);
 }
 
-static int mx_open_mailbox_append (CONTEXT *ctx, int flags)
+static int mx_open_mailbox_append (CONTEXT * ctx, int flags)
 {
   struct stat sb;
 
+#ifdef USE_COMPRESSED
+  /* special case for appending to compressed folders -
+   * even if we can not open them for reading */
+  if (mutt_can_append_compressed (ctx->path))
+    mutt_open_append_compressed (ctx);
+#endif
+
   ctx->append = 1;
 
 #ifdef USE_IMAP
-  
-  if(mx_is_imap(ctx->path))  
+
+  if (mx_get_magic (ctx->path) == M_IMAP)
     return imap_open_mailbox_append (ctx);
 
 #endif
-  
-  if(stat(ctx->path, &sb) == 0)
-  {
+
+  if (stat (ctx->path, &sb) == 0) {
     ctx->magic = mx_get_magic (ctx->path);
-    
-    switch (ctx->magic)
-    {
-      case 0:
-       mutt_error (_("%s is not a mailbox."), ctx->path);
-       /* fall through */
-      case -1:
-       return (-1);
+
+    switch (ctx->magic) {
+    case 0:
+      mutt_error (_("%s is not a mailbox."), ctx->path);
+      /* fall through */
+    case -1:
+      return (-1);
     }
   }
-  else if (errno == ENOENT)
-  {
+  else if (errno == ENOENT) {
     ctx->magic = DefaultMagic;
 
-    if (ctx->magic == M_MH || ctx->magic == M_MAILDIR)
-    {
+    if (ctx->magic == M_MH || ctx->magic == M_MAILDIR) {
       char tmp[_POSIX_PATH_MAX];
 
-      if (mkdir (ctx->path, S_IRWXU))
-      {
-       mutt_perror (ctx->path);
-       return (-1);
+      if (mkdir (ctx->path, S_IRWXU)) {
+        mutt_perror (ctx->path);
+        return (-1);
       }
 
-      if (ctx->magic == M_MAILDIR)
-      {
-       snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path);
-       if (mkdir (tmp, S_IRWXU))
-       {
-         mutt_perror (tmp);
-         rmdir (ctx->path);
-         return (-1);
-       }
-
-       snprintf (tmp, sizeof (tmp), "%s/new", ctx->path);
-       if (mkdir (tmp, S_IRWXU))
-       {
-         mutt_perror (tmp);
-         snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path);
-         rmdir (tmp);
-         rmdir (ctx->path);
-         return (-1);
-       }
-       snprintf (tmp, sizeof (tmp), "%s/tmp", ctx->path);
-       if (mkdir (tmp, S_IRWXU))
-       {
-         mutt_perror (tmp);
-         snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path);
-         rmdir (tmp);
-         snprintf (tmp, sizeof (tmp), "%s/new", ctx->path);
-         rmdir (tmp);
-         rmdir (ctx->path);
-         return (-1);
-       }
+      if (ctx->magic == M_MAILDIR) {
+        snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path);
+        if (mkdir (tmp, S_IRWXU)) {
+          mutt_perror (tmp);
+          rmdir (ctx->path);
+          return (-1);
+        }
+
+        snprintf (tmp, sizeof (tmp), "%s/new", ctx->path);
+        if (mkdir (tmp, S_IRWXU)) {
+          mutt_perror (tmp);
+          snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path);
+          rmdir (tmp);
+          rmdir (ctx->path);
+          return (-1);
+        }
+        snprintf (tmp, sizeof (tmp), "%s/tmp", ctx->path);
+        if (mkdir (tmp, S_IRWXU)) {
+          mutt_perror (tmp);
+          snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path);
+          rmdir (tmp);
+          snprintf (tmp, sizeof (tmp), "%s/new", ctx->path);
+          rmdir (tmp);
+          rmdir (ctx->path);
+          return (-1);
+        }
       }
-      else
-      {
-       int i;
-
-       snprintf (tmp, sizeof (tmp), "%s/.mh_sequences", ctx->path);
-       if ((i = creat (tmp, S_IRWXU)) == -1)
-       {
-         mutt_perror (tmp);
-         rmdir (ctx->path);
-         return (-1);
-       }
-       close (i);
+      else {
+        int i;
+
+        snprintf (tmp, sizeof (tmp), "%s/.mh_sequences", ctx->path);
+        if ((i = creat (tmp, S_IRWXU)) == -1) {
+          mutt_perror (tmp);
+          rmdir (ctx->path);
+          return (-1);
+        }
+        close (i);
       }
     }
   }
-  else
-  {
+  else {
     mutt_perror (ctx->path);
     return (-1);
   }
 
-  switch (ctx->magic)
-  {
-    case M_MBOX:
-    case M_MMDF:
-    if ((ctx->fp = safe_fopen (ctx->path, flags & M_NEWFOLDER ? "w" : "a")) == NULL ||
-         mbox_lock_mailbox (ctx, 1, 1) != 0)
-      {
-       if (!ctx->fp)
-         mutt_perror (ctx->path);
-       else
-       {
-         mutt_error (_("Couldn't lock %s\n"), ctx->path);
-         safe_fclose (&ctx->fp);
-       }
-       return (-1);
+  switch (ctx->magic) {
+  case M_MBOX:
+  case M_MMDF:
+    if ((ctx->fp =
+         safe_fopen (ctx->path, flags & M_NEWFOLDER ? "w" : "a")) == NULL
+        || mbox_lock_mailbox (ctx, 1, 1) != 0) {
+      if (!ctx->fp)
+        mutt_perror (ctx->path);
+      else {
+        mutt_error (_("Couldn't lock %s\n"), ctx->path);
+        safe_fclose (&ctx->fp);
       }
-      fseek (ctx->fp, 0, 2);
-      break;
+      return (-1);
+    }
+    fseek (ctx->fp, 0, 2);
+    break;
 
-    case M_MH:
-    case M_MAILDIR:
-      /* nothing to do */
-      break;
+  case M_MH:
+  case M_MAILDIR:
+    /* nothing to do */
+    break;
 
-    default:
-      return (-1);
+  default:
+    return (-1);
   }
 
   return 0;
@@ -643,7 +512,7 @@ static int mx_open_mailbox_append (CONTEXT *ctx, int flags)
  *             M_QUIET         only print error messages
  *     ctx     if non-null, context struct to use
  */
-CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx)
+CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT * pctx)
 {
   CONTEXT *ctx = pctx;
   int rc;
@@ -655,40 +524,43 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx)
 
   ctx->msgnotreadyet = -1;
   ctx->collapsed = 0;
-  
+
   if (flags & M_QUIET)
     ctx->quiet = 1;
   if (flags & M_READONLY)
     ctx->readonly = 1;
 
-  if (flags & (M_APPEND|M_NEWFOLDER))
-  {
-    if (mx_open_mailbox_append (ctx, flags) != 0)
-    {
+  if (flags & (M_APPEND | M_NEWFOLDER)) {
+    if (mx_open_mailbox_append (ctx, flags) != 0) {
       mx_fastclose_mailbox (ctx);
       if (!pctx)
-       FREE (&ctx);
+        FREE (&ctx);
       return NULL;
     }
     return ctx;
   }
 
-  ctx->magic = mx_get_magic (path);
-  
-  if(ctx->magic == 0)
+  if (!MX_IDX(ctx->magic-1))
+    ctx->magic = mx_get_magic (path);
+
+#ifdef USE_COMPRESSED
+  if (ctx->magic == M_COMPRESSED)
+    mutt_open_read_compressed (ctx);
+#endif
+
+  if (ctx->magic == 0)
     mutt_error (_("%s is not a mailbox."), path);
 
-  if(ctx->magic == -1)
-    mutt_perror(path);
-  
-  if(ctx->magic <= 0)
-  {
+  if (ctx->magic == -1)
+    mutt_perror (path);
+
+  if (ctx->magic <= 0) {
     mx_fastclose_mailbox (ctx);
     if (!pctx)
       FREE (&ctx);
     return (NULL);
   }
-  
+
   /* if the user has a `push' command in their .muttrc, or in a folder-hook,
    * it will cause the progress messages not to be displayed because
    * mutt_refresh() will think we are in the middle of a macro.  so set a
@@ -699,50 +571,12 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx)
   if (!ctx->quiet)
     mutt_message (_("Reading %s..."), ctx->path);
 
-  switch (ctx->magic)
-  {
-    case M_MH:
-      rc = mh_read_dir (ctx, NULL);
-      break;
-
-    case M_MAILDIR:
-      rc = maildir_read_dir (ctx);
-      break;
-
-    case M_MMDF:
-    case M_MBOX:
-      rc = mbox_open_mailbox (ctx);
-      break;
-
-#ifdef USE_IMAP
-    case M_IMAP:
-      rc = imap_open_mailbox (ctx);
-      break;
-#endif /* USE_IMAP */
-
-#ifdef USE_POP
-    case M_POP:
-      rc = pop_open_mailbox (ctx);
-      break;
-#endif /* USE_POP */
-
-#ifdef USE_NNTP
-    case M_NNTP:
-      rc = nntp_open_mailbox (ctx);
-      break;
-#endif /* USE_NNTP */
-
-    default:
-      rc = -1;
-      break;
-  }
+  rc = MX_COMMAND(ctx->magic-1,mx_open_mailbox)(ctx);
 
-  if (rc == 0)
-  {
-    if ((flags & M_NOSORT) == 0)
-    {
+  if (rc == 0) {
+    if ((flags & M_NOSORT) == 0) {
       /* avoid unnecessary work since the mailbox is completely unthreaded
-        to begin with */
+         to begin with */
       unset_option (OPTSORTSUBTHREADS);
       unset_option (OPTNEEDRESCORE);
       mutt_sort_headers (ctx, 1);
@@ -750,8 +584,7 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx)
     if (!ctx->quiet)
       mutt_clear_error ();
   }
-  else
-  {
+  else {
     mx_fastclose_mailbox (ctx);
     if (!pctx)
       FREE (&ctx);
@@ -762,13 +595,13 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx)
 }
 
 /* free up memory associated with the mailbox context */
-void mx_fastclose_mailbox (CONTEXT *ctx)
+void mx_fastclose_mailbox (CONTEXT * ctx)
 {
   int i;
 
-  if(!ctx) 
+  if (!ctx)
     return;
-  
+
 #ifdef USE_IMAP
   if (ctx->magic == M_IMAP)
     imap_close_mailbox (ctx);
@@ -790,16 +623,20 @@ void mx_fastclose_mailbox (CONTEXT *ctx)
     mutt_free_header (&ctx->hdrs[i]);
   FREE (&ctx->hdrs);
   FREE (&ctx->v2r);
+#ifdef USE_COMPRESSED
+  if (ctx->compressinfo)
+    mutt_fast_close_compressed (ctx);
+#endif
   FREE (&ctx->path);
   FREE (&ctx->pattern);
-  if (ctx->limit_pattern) 
+  if (ctx->limit_pattern)
     mutt_pattern_free (&ctx->limit_pattern);
   safe_fclose (&ctx->fp);
   memset (ctx, 0, sizeof (CONTEXT));
 }
 
 /* save changes to disk */
-static int sync_mailbox (CONTEXT *ctx, int *index_hint)
+static int sync_mailbox (CONTEXT * ctx, int *index_hint)
 {
 #ifdef BUFFY_SIZE
   BUFFY *tmp = NULL;
@@ -809,103 +646,106 @@ static int sync_mailbox (CONTEXT *ctx, int *index_hint)
   if (!ctx->quiet)
     mutt_message (_("Writing %s..."), ctx->path);
 
-  switch (ctx->magic)
-  {
-    case M_MBOX:
-    case M_MMDF:
-      rc = mbox_sync_mailbox (ctx, index_hint);
+  switch (ctx->magic) {
+  case M_MBOX:
+  case M_MMDF:
+    rc = mbox_sync_mailbox (ctx, index_hint);
 #ifdef BUFFY_SIZE
-      tmp = mutt_find_mailbox (ctx->path);
+    tmp = mutt_find_mailbox (ctx->path);
 #endif
-      break;
-      
-    case M_MH:
-    case M_MAILDIR:
-      rc = mh_sync_mailbox (ctx, index_hint);
-      break;
-      
+    break;
+
+  case M_MH:
+  case M_MAILDIR:
+    rc = mh_sync_mailbox (ctx, index_hint);
+    break;
+
 #ifdef USE_IMAP
-    case M_IMAP:
-      /* extra argument means EXPUNGE */
-      rc = imap_sync_mailbox (ctx, 1, index_hint);
-      break;
+  case M_IMAP:
+    /* extra argument means EXPUNGE */
+    rc = imap_sync_mailbox (ctx, 1, index_hint);
+    break;
 #endif /* USE_IMAP */
 
 #ifdef USE_POP
-    case M_POP:
-      rc = pop_sync_mailbox (ctx, index_hint);
-      break;
+  case M_POP:
+    rc = pop_sync_mailbox (ctx, index_hint);
+    break;
 #endif /* USE_POP */
 
 #ifdef USE_NNTP
-    case M_NNTP:
-      rc = nntp_sync_mailbox (ctx);
-      break;
+  case M_NNTP:
+    rc = nntp_sync_mailbox (ctx);
+    break;
 #endif /* USE_NNTP */
   }
 
 #if 0
   if (!ctx->quiet && !ctx->shutup && rc == -1)
-    mutt_error ( _("Could not synchronize mailbox %s!"), ctx->path);
+    mutt_error (_("Could not synchronize mailbox %s!"), ctx->path);
 #endif
-  
+
 #ifdef BUFFY_SIZE
   if (tmp && tmp->new == 0)
     mutt_update_mailbox (tmp);
 #endif
+
+#ifdef USE_COMPRESSED
+  if (rc == 0 && ctx->compressinfo)
+    return mutt_sync_compressed (ctx);
+#endif
+
   return rc;
 }
 
 /* move deleted mails to the trash folder */
-static int trash_append (CONTEXT *ctx)
+static int trash_append (CONTEXT * ctx)
 {
-    CONTEXT *ctx_trash;
-    int i = 0;
-    struct stat st, stc;
+  CONTEXT *ctx_trash;
+  int i = 0;
+  struct stat st, stc;
 
-    if (!TrashPath || !ctx->deleted ||
-       (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))
-      return 0;
+  if (!TrashPath || !ctx->deleted ||
+      (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))
+    return 0;
 
-    for (;i < ctx->msgcount && (!ctx->hdrs[i]->deleted ||
-                               ctx->hdrs[i]->appended); i++);
-    if (i == ctx->msgcount)
-      return 0; /* nothing to be done */
+  for (; i < ctx->msgcount && (!ctx->hdrs[i]->deleted ||
+                               ctx->hdrs[i]->appended); i++);
+  if (i == ctx->msgcount)
+    return 0;                   /* nothing to be done */
 
-    if (mutt_save_confirm (TrashPath, &st) != 0)
-    {
-      mutt_error _("message(s) not deleted");
-      return -1;
-    }
+  if (mutt_save_confirm (TrashPath, &st) != 0) {
+    mutt_error _("message(s) not deleted");
 
-    if (lstat (ctx->path, &stc) == 0 && stc.st_ino == st.st_ino
-       && stc.st_dev == st.st_dev && stc.st_rdev == st.st_rdev)
-      return 0;  /* we are in the trash folder: simple sync */
+    return -1;
+  }
 
-    if ((ctx_trash = mx_open_mailbox (TrashPath, M_APPEND, NULL)) != NULL)
-    {
-      for (i = 0 ; i < ctx->msgcount ; i++)
-       if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->appended
-           && !ctx->hdrs[i]->purged
-           && mutt_append_message (ctx_trash, ctx, ctx->hdrs[i], 0, 0) == -1)
-         {
-           mx_close_mailbox (ctx_trash, NULL);
-           return -1;
-         }
-
-      mx_close_mailbox (ctx_trash, NULL);
-    }
-    else
-    {
-      mutt_error _("Can't open trash folder");
-      return -1;
-    }
+  if (lstat (ctx->path, &stc) == 0 && stc.st_ino == st.st_ino
+      && stc.st_dev == st.st_dev && stc.st_rdev == st.st_rdev)
+    return 0;                   /* we are in the trash folder: simple sync */
 
-    return 0;
+  if ((ctx_trash = mx_open_mailbox (TrashPath, M_APPEND, NULL)) != NULL) {
+    for (i = 0; i < ctx->msgcount; i++)
+      if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->appended
+          && !ctx->hdrs[i]->purged
+          && mutt_append_message (ctx_trash, ctx, ctx->hdrs[i], 0, 0) == -1) {
+        mx_close_mailbox (ctx_trash, NULL);
+        return -1;
+      }
+
+    mx_close_mailbox (ctx_trash, NULL);
+  }
+  else {
+    mutt_error _("Can't open trash folder");
+
+    return -1;
+  }
+
+  return 0;
 }
 
 /* save changes and close mailbox */
-int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
+int mx_close_mailbox (CONTEXT * ctx, int *index_hint)
 {
   int i, move_messages = 0, purge = 1, read_msgs = 0;
   int check;
@@ -914,13 +754,13 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
   char mbox[_POSIX_PATH_MAX];
   char buf[SHORT_STRING];
 
-  if (!ctx) return 0;
+  if (!ctx)
+    return 0;
 
   ctx->closing = 1;
 
 #ifdef USE_NNTP
-  if (ctx->magic == M_NNTP)
-  {
+  if (ctx->magic == M_NNTP) {
     int ret;
 
     ret = nntp_close_mailbox (ctx);
@@ -928,15 +768,13 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
     return ret;
   }
 #endif
-  if (ctx->readonly || ctx->dontwrite)
-  {
+  if (ctx->readonly || ctx->dontwrite) {
     /* mailbox is readonly or we don't want to write */
     mx_fastclose_mailbox (ctx);
     return 0;
   }
 
-  if (ctx->append)
-  {
+  if (ctx->append) {
     /* mailbox was opened in write-mode */
     if (ctx->magic == M_MBOX || ctx->magic == M_MMDF)
       mbox_close_mailbox (ctx);
@@ -945,36 +783,30 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
     return 0;
   }
 
-  for (i = 0; i < ctx->msgcount; i++)
-  {
-    if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->read 
+  for (i = 0; i < ctx->msgcount; i++) {
+    if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->read
         && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED)))
       read_msgs++;
   }
 
-  if (read_msgs && quadoption (OPT_MOVE) != M_NO)
-  {
+  if (read_msgs && quadoption (OPT_MOVE) != M_NO) {
     char *p;
 
-    if ((p = mutt_find_hook (M_MBOXHOOK, ctx->path)))
-    {
+    if ((p = mutt_find_hook (M_MBOXHOOK, ctx->path))) {
       isSpool = 1;
       strfcpy (mbox, p, sizeof (mbox));
     }
-    else
-    {
-      strfcpy (mbox, NONULL(Inbox), sizeof (mbox));
+    else {
+      strfcpy (mbox, NONULL (Inbox), sizeof (mbox));
       isSpool = mutt_is_spool (ctx->path) && !mutt_is_spool (mbox);
     }
     mutt_expand_path (mbox, sizeof (mbox));
 
-    if (isSpool)
-    {
+    if (isSpool) {
       snprintf (buf, sizeof (buf), _("Move read messages to %s?"), mbox);
-      if ((move_messages = query_quadoption (OPT_MOVE, buf)) == -1)
-      {
-       ctx->closing = 0;
-       return (-1);
+      if ((move_messages = query_quadoption (OPT_MOVE, buf)) == -1) {
+        ctx->closing = 0;
+        return (-1);
       }
     }
   }
@@ -983,13 +815,11 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
    * There is no point in asking whether or not to purge if we are
    * just marking messages as "trash".
    */
-  if (ctx->deleted && !(ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))
-  {
+  if (ctx->deleted && !(ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) {
     snprintf (buf, sizeof (buf), ctx->deleted == 1
-            ? _("Purge %d deleted message?") : _("Purge %d deleted messages?"),
-             ctx->deleted);
-    if ((purge = query_quadoption (OPT_DELETE, buf)) < 0)
-    {
+              ? _("Purge %d deleted message?") :
+              _("Purge %d deleted messages?"), ctx->deleted);
+    if ((purge = query_quadoption (OPT_DELETE, buf)) < 0) {
       ctx->closing = 0;
       return (-1);
     }
@@ -999,96 +829,84 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
   /* IMAP servers manage the OLD flag themselves */
   if (ctx->magic != M_IMAP)
 #endif
-  if (option (OPTMARKOLD))
-  {
-    for (i = 0; i < ctx->msgcount; i++)
-    {
-      if (!ctx->hdrs[i]->deleted && !ctx->hdrs[i]->old)
-       mutt_set_flag (ctx, ctx->hdrs[i], M_OLD, 1);
+    if (option (OPTMARKOLD)) {
+      for (i = 0; i < ctx->msgcount; i++) {
+        if (!ctx->hdrs[i]->deleted && !ctx->hdrs[i]->old)
+          mutt_set_flag (ctx, ctx->hdrs[i], M_OLD, 1);
+      }
     }
-  }
 
-  if (move_messages)
-  {
+  if (move_messages) {
     mutt_message (_("Moving read messages to %s..."), mbox);
 
 #ifdef USE_IMAP
     /* try to use server-side copy first */
     i = 1;
-    
-    if (ctx->magic == M_IMAP && mx_is_imap (mbox))
-    {
+
+    if (ctx->magic == M_IMAP && imap_is_magic (mbox, NULL) == M_IMAP) {
       /* tag messages for moving, and clear old tags, if any */
       for (i = 0; i < ctx->msgcount; i++)
-       if (ctx->hdrs[i]->read && !ctx->hdrs[i]->deleted
-            && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) 
-         ctx->hdrs[i]->tagged = 1;
-       else
-         ctx->hdrs[i]->tagged = 0;
-      
+        if (ctx->hdrs[i]->read && !ctx->hdrs[i]->deleted
+            && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED)))
+          ctx->hdrs[i]->tagged = 1;
+        else
+          ctx->hdrs[i]->tagged = 0;
+
       i = imap_copy_messages (ctx, NULL, mbox, 1);
     }
-    
-    if (i == 0) /* success */
+
+    if (i == 0)                 /* success */
       mutt_clear_error ();
-    else if (i == -1) /* horrible error, bail */
-    {
-      ctx->closing=0;
+    else if (i == -1) {         /* horrible error, bail */
+      ctx->closing = 0;
       return -1;
     }
-    else /* use regular append-copy mode */
+    else                        /* use regular append-copy mode */
 #endif
     {
-      if (mx_open_mailbox (mbox, M_APPEND, &f) == NULL)
-      {
-       ctx->closing = 0;
-       return -1;
+      if (mx_open_mailbox (mbox, M_APPEND, &f) == NULL) {
+        ctx->closing = 0;
+        return -1;
       }
 
-      for (i = 0; i < ctx->msgcount; i++)
-      {
-       if (ctx->hdrs[i]->read && !ctx->hdrs[i]->deleted
-            && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED)))
-        {
-         if (mutt_append_message (&f, ctx, ctx->hdrs[i], 0, CH_UPDATE_LEN) == 0)
-         {
-           mutt_set_flag (ctx, ctx->hdrs[i], M_DELETE, 1);
-           mutt_set_flag (ctx, ctx->hdrs[i], M_APPENDED, 1);
-         }
-         else
-         {
-           mx_close_mailbox (&f, NULL);
-           ctx->closing = 0;
-           return -1;
-         }
-       }
+      for (i = 0; i < ctx->msgcount; i++) {
+        if (ctx->hdrs[i]->read && !ctx->hdrs[i]->deleted
+            && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED))) {
+          if (mutt_append_message (&f, ctx, ctx->hdrs[i], 0, CH_UPDATE_LEN) ==
+              0) {
+            mutt_set_flag (ctx, ctx->hdrs[i], M_DELETE, 1);
+            mutt_set_flag (ctx, ctx->hdrs[i], M_APPENDED, 1);
+          }
+          else {
+            mx_close_mailbox (&f, NULL);
+            ctx->closing = 0;
+            return -1;
+          }
+        }
       }
-    
+
       mx_close_mailbox (&f, NULL);
     }
-    
+
   }
-  else if (!ctx->changed && ctx->deleted == 0)
-  {
+  else if (!ctx->changed && ctx->deleted == 0) {
     mutt_message _("Mailbox is unchanged.");
+
     mx_fastclose_mailbox (ctx);
     return 0;
   }
-  
+
   /* copy mails to the trash before expunging */
   if (purge && ctx->deleted)
-    if (trash_append (ctx) != 0)
-    {
+    if (trash_append (ctx) != 0) {
       ctx->closing = 0;
       return -1;
     }
 
 #ifdef USE_IMAP
   /* allow IMAP to preserve the deleted flag across sessions */
-  if (ctx->magic == M_IMAP)
-  {
-    if ((check = imap_sync_mailbox (ctx, purge, index_hint)) != 0)
-    {
+  if (ctx->magic == M_IMAP) {
+    if ((check = imap_sync_mailbox (ctx, purge, index_hint)) != 0) {
       ctx->closing = 0;
       return check;
     }
@@ -1096,35 +914,37 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
   else
 #endif
   {
-    if (!purge)
-    {
+    if (!purge) {
       for (i = 0; i < ctx->msgcount; i++)
         ctx->hdrs[i]->deleted = 0;
       ctx->deleted = 0;
     }
 
-    if (ctx->changed || ctx->deleted)
-    {
-      if ((check = sync_mailbox (ctx, index_hint)) != 0)
-      {
-       ctx->closing = 0;
-       return check;
+    if (ctx->changed || ctx->deleted) {
+      if ((check = sync_mailbox (ctx, index_hint)) != 0) {
+        ctx->closing = 0;
+        return check;
       }
     }
   }
 
   if (move_messages)
-     mutt_message (_("%d kept, %d moved, %d deleted."),
-       ctx->msgcount - ctx->deleted, read_msgs, ctx->deleted);
+    mutt_message (_("%d kept, %d moved, %d deleted."),
+                  ctx->msgcount - ctx->deleted, read_msgs, ctx->deleted);
   else
     mutt_message (_("%d kept, %d deleted."),
-      ctx->msgcount - ctx->deleted, ctx->deleted);
+                  ctx->msgcount - ctx->deleted, ctx->deleted);
 
   if (ctx->msgcount == ctx->deleted &&
       (ctx->magic == M_MMDF || ctx->magic == M_MBOX) &&
-      !mutt_is_spool(ctx->path) && !option (OPTSAVEEMPTY))
+      !mutt_is_spool (ctx->path) && !option (OPTSAVEEMPTY))
     mx_unlink_empty (ctx->path);
 
+#ifdef USE_COMPRESSED
+  if (ctx->compressinfo && mutt_slow_close_compressed (ctx))
+    return (-1);
+#endif
+
   mx_fastclose_mailbox (ctx);
 
   return 0;
@@ -1133,10 +953,10 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
 
 /* update a Context structure's internal tables. */
 
-void mx_update_tables(CONTEXT *ctx, int committing)
+void mx_update_tables (CONTEXT * ctx, int committing)
 {
   int i, j;
-  
+
   /* update memory to reflect the new state of the mailbox */
   ctx->vcount = 0;
   ctx->vsize = 0;
@@ -1147,61 +967,59 @@ void mx_update_tables(CONTEXT *ctx, int committing)
   ctx->changed = 0;
   ctx->flagged = 0;
 #define this_body ctx->hdrs[j]->content
-  for (i = 0, j = 0; i < ctx->msgcount; i++)
-  {
-    if ((committing && (!ctx->hdrs[i]->deleted || 
-                       (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))) ||
-       (!committing && ctx->hdrs[i]->active))
-    {
-      if (i != j)
-      {
-       ctx->hdrs[j] = ctx->hdrs[i];
-       ctx->hdrs[i] = NULL;
+  for (i = 0, j = 0; i < ctx->msgcount; i++) {
+    if ((committing && (!ctx->hdrs[i]->deleted ||
+                        (ctx->magic == M_MAILDIR
+                         && option (OPTMAILDIRTRASH)))) || (!committing
+                                                            && ctx->hdrs[i]->
+                                                            active)) {
+      if (i != j) {
+        ctx->hdrs[j] = ctx->hdrs[i];
+        ctx->hdrs[i] = NULL;
       }
       ctx->hdrs[j]->msgno = j;
-      if (ctx->hdrs[j]->virtual != -1)
-      {
-       ctx->v2r[ctx->vcount] = j;
-       ctx->hdrs[j]->virtual = ctx->vcount++;
-       ctx->vsize += this_body->length + this_body->offset -
-         this_body->hdr_offset;
+      if (ctx->hdrs[j]->virtual != -1) {
+        ctx->v2r[ctx->vcount] = j;
+        ctx->hdrs[j]->virtual = ctx->vcount++;
+        ctx->vsize += this_body->length + this_body->offset -
+          this_body->hdr_offset;
       }
 
       if (committing)
-       ctx->hdrs[j]->changed = 0;
+        ctx->hdrs[j]->changed = 0;
       else if (ctx->hdrs[j]->changed)
-       ctx->changed++;
-      
-      if (!committing || (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))
-      {
-       if (ctx->hdrs[j]->deleted)
-         ctx->deleted++;
+        ctx->changed++;
+
+      if (!committing
+          || (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH))) {
+        if (ctx->hdrs[j]->deleted)
+          ctx->deleted++;
       }
 
       if (ctx->hdrs[j]->tagged)
-       ctx->tagged++;
+        ctx->tagged++;
       if (ctx->hdrs[j]->flagged)
-       ctx->flagged++;
-      if (!ctx->hdrs[j]->read)
-      { 
-       ctx->unread++;
-       if (!ctx->hdrs[j]->old)
-         ctx->new++;
-      } 
+        ctx->flagged++;
+      if (!ctx->hdrs[j]->read) {
+        ctx->unread++;
+        if (!ctx->hdrs[j]->old)
+          ctx->new++;
+      }
 
       j++;
     }
-    else
-    {
+    else {
       if (ctx->magic == M_MH || ctx->magic == M_MAILDIR)
-       ctx->size -= (ctx->hdrs[i]->content->length +
-                     ctx->hdrs[i]->content->offset -
-                     ctx->hdrs[i]->content->hdr_offset);
+        ctx->size -= (ctx->hdrs[i]->content->length +
+                      ctx->hdrs[i]->content->offset -
+                      ctx->hdrs[i]->content->hdr_offset);
       /* remove message from the hash tables */
       if (ctx->subj_hash && ctx->hdrs[i]->env->real_subj)
-       hash_delete (ctx->subj_hash, ctx->hdrs[i]->env->real_subj, ctx->hdrs[i], NULL);
+        hash_delete (ctx->subj_hash, ctx->hdrs[i]->env->real_subj,
+                     ctx->hdrs[i], NULL);
       if (ctx->id_hash && ctx->hdrs[i]->env->message_id)
-       hash_delete (ctx->id_hash, ctx->hdrs[i]->env->message_id, ctx->hdrs[i], NULL);
+        hash_delete (ctx->id_hash, ctx->hdrs[i]->env->message_id,
+                     ctx->hdrs[i], NULL);
       mutt_free_header (&ctx->hdrs[i]);
     }
   }
@@ -1216,59 +1034,60 @@ void mx_update_tables(CONTEXT *ctx, int committing)
  *     0               success
  *     -1              error
  */
-int mx_sync_mailbox (CONTEXT *ctx, int *index_hint)
+int mx_sync_mailbox (CONTEXT * ctx, int *index_hint)
 {
   int rc, i;
   int purge = 1;
   int msgcount, deleted;
 
-  if (ctx->dontwrite)
-  {
+  if (ctx->dontwrite) {
     char buf[STRING], tmp[STRING];
-    if (km_expand_key (buf, sizeof(buf),
+
+    if (km_expand_key (buf, sizeof (buf),
                        km_find_func (MENU_MAIN, OP_TOGGLE_WRITE)))
-      snprintf (tmp, sizeof(tmp), _(" Press '%s' to toggle write"), buf);
+      snprintf (tmp, sizeof (tmp), _(" Press '%s' to toggle write"), buf);
     else
-      strfcpy (tmp, _("Use 'toggle-write' to re-enable write!"), sizeof(tmp));
+      strfcpy (tmp, _("Use 'toggle-write' to re-enable write!"),
+               sizeof (tmp));
 
     mutt_error (_("Mailbox is marked unwritable. %s"), tmp);
     return -1;
   }
-  else if (ctx->readonly)
-  {
+  else if (ctx->readonly) {
     mutt_error _("Mailbox is read-only.");
+
     return -1;
   }
 
-  if (!ctx->changed && !ctx->deleted)
-  {
+  if (!ctx->changed && !ctx->deleted) {
     mutt_message _("Mailbox is unchanged.");
+
     return (0);
   }
 
-  if (ctx->deleted)
-  {
+  if (ctx->deleted) {
     char buf[SHORT_STRING];
 
     snprintf (buf, sizeof (buf), ctx->deleted == 1
-            ? _("Purge %d deleted message?") : _("Purge %d deleted messages?"),
-             ctx->deleted);
+              ? _("Purge %d deleted message?") :
+              _("Purge %d deleted messages?"), ctx->deleted);
     if ((purge = query_quadoption (OPT_DELETE, buf)) < 0)
       return (-1);
-    else if (purge == M_NO)
-    {
+    else if (purge == M_NO) {
       if (!ctx->changed)
-       return 0; /* nothing to do! */
+        return 0;               /* nothing to do! */
 #ifdef USE_IMAP
       /* let IMAP servers hold on to D flags */
       if (ctx->magic != M_IMAP)
 #endif
       {
-        for (i = 0 ; i < ctx->msgcount ; i++)
+        for (i = 0; i < ctx->msgcount; i++)
           ctx->hdrs[i]->deleted = 0;
         ctx->deleted = 0;
       }
     }
+    else if (ctx->last_tag && ctx->last_tag->deleted)
+      ctx->last_tag = NULL;     /* reset last tagged msg now useless */
   }
 
   /* really only for IMAP - imap_sync_mailbox results in a call to
@@ -1276,11 +1095,10 @@ int mx_sync_mailbox (CONTEXT *ctx, int *index_hint)
   msgcount = ctx->msgcount;
   deleted = ctx->deleted;
 
-  if (purge && ctx->deleted)
-  {
+  if (purge && ctx->deleted) {
     if (trash_append (ctx) == -1)
       return -1;
-  } 
+  }
 
 #ifdef USE_IMAP
   if (ctx->magic == M_IMAP)
@@ -1288,22 +1106,20 @@ int mx_sync_mailbox (CONTEXT *ctx, int *index_hint)
   else
 #endif
     rc = sync_mailbox (ctx, index_hint);
-  if (rc == 0)
-  {
+  if (rc == 0) {
 #ifdef USE_IMAP
     if (ctx->magic == M_IMAP && !purge)
-      mutt_message _("Mailbox checkpointed.");
+      mutt_message (_("Mailbox checkpointed."));
+
     else
 #endif
-    mutt_message (_("%d kept, %d deleted."), msgcount - deleted,
-      deleted);
+      mutt_message (_("%d kept, %d deleted."), msgcount - deleted, deleted);
 
     mutt_sleep (0);
-    
+
     if (ctx->msgcount == ctx->deleted &&
-       (ctx->magic == M_MBOX || ctx->magic == M_MMDF) &&
-       !mutt_is_spool (ctx->path) && !option (OPTSAVEEMPTY))
-    {
+        (ctx->magic == M_MBOX || ctx->magic == M_MMDF) &&
+        !mutt_is_spool (ctx->path) && !option (OPTSAVEEMPTY)) {
       unlink (ctx->path);
       mx_fastclose_mailbox (ctx);
       return 0;
@@ -1316,15 +1132,14 @@ int mx_sync_mailbox (CONTEXT *ctx, int *index_hint)
      * MH and maildir are safe.  mbox-style seems to need re-sorting,
      * at least with the new threading code.
      */
-    if (purge || (ctx->magic != M_MAILDIR && ctx->magic != M_MH))
-    {
+    if (purge || (ctx->magic != M_MAILDIR && ctx->magic != M_MH)) {
 #ifdef USE_IMAP
       /* IMAP does this automatically after handling EXPUNGE */
       if (ctx->magic != M_IMAP)
 #endif
       {
-       mx_update_tables (ctx, 1);
-       mutt_sort_headers (ctx, 1); /* rethread from scratch */
+        mx_update_tables (ctx, 1);
+        mutt_sort_headers (ctx, 1);     /* rethread from scratch */
       }
     }
   }
@@ -1332,24 +1147,15 @@ int mx_sync_mailbox (CONTEXT *ctx, int *index_hint)
   return (rc);
 }
 
-
-/* {maildir,mh}_open_new_message are in mh.c. */
-
-int mbox_open_new_message (MESSAGE *msg, CONTEXT *dest, HEADER *hdr)
-{
-  msg->fp = dest->fp;
-  return 0;
-}
-
 #ifdef USE_IMAP
-int imap_open_new_message (MESSAGE *msg, CONTEXT *dest, HEADER *hdr)
+int imap_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr)
 {
   char tmp[_POSIX_PATH_MAX];
 
-  mutt_mktemp(tmp);
+  mutt_mktemp (tmp);
   if ((msg->fp = safe_fopen (tmp, "w")) == NULL)
     return (-1);
-  msg->path = safe_strdup(tmp);
+  msg->path = safe_strdup (tmp);
   return 0;
 }
 #endif
@@ -1359,69 +1165,66 @@ int imap_open_new_message (MESSAGE *msg, CONTEXT *dest, HEADER *hdr)
  *     hdr     message being copied (required for maildir support, because
  *             the filename depends on the message flags)
  */
-MESSAGE *mx_open_new_message (CONTEXT *dest, HEADER *hdr, int flags)
+MESSAGE *mx_open_new_message (CONTEXT * dest, HEADER * hdr, int flags)
 {
   MESSAGE *msg;
   int (*func) (MESSAGE *, CONTEXT *, HEADER *);
   ADDRESS *p = NULL;
 
-  switch (dest->magic)
-  {
-    case M_MMDF:
-    case M_MBOX:
-      func = mbox_open_new_message;
-      break;
-    case M_MAILDIR:
-      func = maildir_open_new_message;
-      break;
-    case M_MH:
-      func = mh_open_new_message;
-      break;
+  switch (dest->magic) {
+  case M_MMDF:
+  case M_MBOX:
+    func = mbox_open_new_message;
+    break;
+  case M_MAILDIR:
+    func = maildir_open_new_message;
+    break;
+  case M_MH:
+    func = mh_open_new_message;
+    break;
 #ifdef USE_IMAP
-    case M_IMAP:
-      func = imap_open_new_message;
-      break;
+  case M_IMAP:
+    func = imap_open_new_message;
+    break;
 #endif
-    default:
-      dprint (1, (debugfile, "mx_open_new_message(): function unimplemented for mailbox type %d.\n",
-                 dest->magic));
-      return (NULL);
+  default:
+    dprint (1,
+            (debugfile,
+             "mx_open_new_message(): function unimplemented for mailbox type %d.\n",
+             dest->magic));
+    return (NULL);
   }
 
   msg = safe_calloc (1, sizeof (MESSAGE));
   msg->magic = dest->magic;
   msg->write = 1;
 
-  if (hdr)
-  {
+  if (hdr) {
     msg->flags.flagged = hdr->flagged;
     msg->flags.replied = hdr->replied;
-    msg->flags.read    = hdr->read;
+    msg->flags.read = hdr->read;
     msg->received = hdr->received;
   }
 
-  if(msg->received == 0)
-    time(&msg->received);
-  
-  if (func (msg, dest, hdr) == 0)
-  {
+  if (msg->received == 0)
+    time (&msg->received);
+
+  if (func (msg, dest, hdr) == 0) {
     if (dest->magic == M_MMDF)
       fputs (MMDF_SEP, msg->fp);
 
-    if ((msg->magic == M_MBOX || msg->magic ==  M_MMDF) &&
-       flags & M_ADD_FROM)
-    {
-      if (hdr)
-      {
-       if (hdr->env->return_path)
-         p = hdr->env->return_path;
-       else if (hdr->env->sender)
-         p = hdr->env->sender;
-       else
-         p = hdr->env->from;
+    if ((msg->magic == M_MBOX || msg->magic == M_MMDF) && flags & M_ADD_FROM) {
+      if (hdr) {
+        if (hdr->env->return_path)
+          p = hdr->env->return_path;
+        else if (hdr->env->sender)
+          p = hdr->env->sender;
+        else
+          p = hdr->env->from;
       }
 
-      fprintf (msg->fp, "From %s %s", p ? p->mailbox : NONULL(Username), ctime (&msg->received));
+      fprintf (msg->fp, "From %s %s", p ? p->mailbox : NONULL (Username),
+               ctime (&msg->received));
     }
   }
   else
@@ -1431,58 +1234,59 @@ MESSAGE *mx_open_new_message (CONTEXT *dest, HEADER *hdr, int flags)
 }
 
 /* check for new mail */
-int mx_check_mailbox (CONTEXT *ctx, int *index_hint, int lock)
+int mx_check_mailbox (CONTEXT * ctx, int *index_hint, int lock)
 {
   int rc;
 
-  if (ctx)
-  {
-    if (ctx->locked) lock = 0;
+#ifdef USE_COMPRESSED
+  if (ctx->compressinfo)
+    return mutt_check_mailbox_compressed (ctx);
+#endif
 
-    switch (ctx->magic)
-    {
-      case M_MBOX:
-      case M_MMDF:
-
-       if (lock)
-       {
-         mutt_block_signals ();
-         if (mbox_lock_mailbox (ctx, 0, 0) == -1)
-         {
-           mutt_unblock_signals ();
-           return M_LOCKED;
-         }
-       }
-       
-       rc = mbox_check_mailbox (ctx, index_hint);
-
-       if (lock)
-       {
-         mutt_unblock_signals ();
-         mbox_unlock_mailbox (ctx);
-       }
-       
-       return rc;
-
-
-      case M_MH:
-       return (mh_check_mailbox (ctx, index_hint));
-      case M_MAILDIR:
-       return (maildir_check_mailbox (ctx, index_hint));
+  if (ctx) {
+    if (ctx->locked)
+      lock = 0;
+
+    switch (ctx->magic) {
+    case M_MBOX:
+    case M_MMDF:
+
+      if (lock) {
+        mutt_block_signals ();
+        if (mbox_lock_mailbox (ctx, 0, 0) == -1) {
+          mutt_unblock_signals ();
+          return M_LOCKED;
+        }
+      }
+
+      rc = mbox_check_mailbox (ctx, index_hint);
+
+      if (lock) {
+        mutt_unblock_signals ();
+        mbox_unlock_mailbox (ctx);
+      }
+
+      return rc;
+
+
+    case M_MH:
+      return (mh_check_mailbox (ctx, index_hint));
+    case M_MAILDIR:
+      return (maildir_check_mailbox (ctx, index_hint));
 
 #ifdef USE_IMAP
-      case M_IMAP:
-       return (imap_check_mailbox (ctx, index_hint, 0));
+    case M_IMAP:
+      return (imap_check_mailbox (ctx, index_hint, 0));
 #endif /* USE_IMAP */
 
 #ifdef USE_POP
-      case M_POP:
-       return (pop_check_mailbox (ctx, index_hint));
+    case M_POP:
+      return (pop_check_mailbox (ctx, index_hint));
 #endif /* USE_POP */
 
 #ifdef USE_NNTP
-      case M_NNTP:
-       return (nntp_check_mailbox (ctx));
+    case M_NNTP:
+      return (nntp_check_mailbox (ctx));
 #endif /* USE_NNTP */
     }
   }
@@ -1492,138 +1296,139 @@ int mx_check_mailbox (CONTEXT *ctx, int *index_hint, int lock)
 }
 
 /* return a stream pointer for a message */
-MESSAGE *mx_open_message (CONTEXT *ctx, int msgno)
+MESSAGE *mx_open_message (CONTEXT * ctx, int msgno)
 {
   MESSAGE *msg;
-  
+
   msg = safe_calloc (1, sizeof (MESSAGE));
-  switch (msg->magic = ctx->magic)
-  {
-    case M_MBOX:
-    case M_MMDF:
-      msg->fp = ctx->fp;
-      break;
+  switch (msg->magic = ctx->magic) {
+  case M_MBOX:
+  case M_MMDF:
+    msg->fp = ctx->fp;
+    break;
 
-    case M_MH:
-    case M_MAILDIR:
+  case M_MH:
+  case M_MAILDIR:
     {
       HEADER *cur = ctx->hdrs[msgno];
       char path[_POSIX_PATH_MAX];
-      
+
       snprintf (path, sizeof (path), "%s/%s", ctx->path, cur->path);
-      
+
       if ((msg->fp = fopen (path, "r")) == NULL && errno == ENOENT &&
-         ctx->magic == M_MAILDIR)
-       msg->fp = maildir_open_find_message (ctx->path, cur->path);
-      
-      if (msg->fp == NULL)
-      {
-       mutt_perror (path);
-       dprint (1, (debugfile, "mx_open_message: fopen: %s: %s (errno %d).\n",
-                   path, strerror (errno), errno));
-       FREE (&msg);
+          ctx->magic == M_MAILDIR)
+        msg->fp = maildir_open_find_message (ctx->path, cur->path);
+
+      if (msg->fp == NULL) {
+        mutt_perror (path);
+        dprint (1, (debugfile, "mx_open_message: fopen: %s: %s (errno %d).\n",
+                    path, strerror (errno), errno));
+        FREE (&msg);
       }
     }
     break;
-    
+
 #ifdef USE_IMAP
-    case M_IMAP:
+  case M_IMAP:
     {
       if (imap_fetch_message (msg, ctx, msgno) != 0)
-       FREE (&msg);
+        FREE (&msg);
       break;
     }
 #endif /* USE_IMAP */
 
 #ifdef USE_POP
-    case M_POP:
+  case M_POP:
     {
       if (pop_fetch_message (msg, ctx, msgno) != 0)
-       FREE (&msg);
+        FREE (&msg);
       break;
     }
 #endif /* USE_POP */
 
 #ifdef USE_NNTP
-    case M_NNTP:
+  case M_NNTP:
     {
       if (nntp_fetch_message (msg, ctx, msgno) != 0)
-       FREE (&msg);
+        FREE (&msg);
       break;
     }
 #endif /* USE_NNTP */
 
-    default:
-      dprint (1, (debugfile, "mx_open_message(): function not implemented for mailbox type %d.\n", ctx->magic));
-      FREE (&msg);
-      break;
+  default:
+    dprint (1,
+            (debugfile,
+             "mx_open_message(): function not implemented for mailbox type %d.\n",
+             ctx->magic));
+    FREE (&msg);
+    break;
   }
   return (msg);
 }
 
 /* commit a message to a folder */
 
-int mx_commit_message (MESSAGE *msg, CONTEXT *ctx)
+int mx_commit_message (MESSAGE * msg, CONTEXT * ctx)
 {
   int r = 0;
 
-  if (!(msg->write && ctx->append))
-  {
-    dprint (1, (debugfile, "mx_commit_message(): msg->write = %d, ctx->append = %d\n",
-               msg->write, ctx->append));
+  if (!(msg->write && ctx->append)) {
+    dprint (1,
+            (debugfile,
+             "mx_commit_message(): msg->write = %d, ctx->append = %d\n",
+             msg->write, ctx->append));
     return -1;
   }
 
-  switch (msg->magic)
-  {
-    case M_MMDF:
+  switch (msg->magic) {
+  case M_MMDF:
     {
       if (fputs (MMDF_SEP, msg->fp) == EOF)
-       r = -1;
+        r = -1;
       break;
     }
-    
-    case M_MBOX:
+
+  case M_MBOX:
     {
       if (fputc ('\n', msg->fp) == EOF)
-       r = -1;
+        r = -1;
       break;
     }
 
 #ifdef USE_IMAP
-    case M_IMAP:
+  case M_IMAP:
     {
       if ((r = safe_fclose (&msg->fp)) == 0)
-       r = imap_append_message (ctx, msg);
+        r = imap_append_message (ctx, msg);
       break;
     }
 #endif
-    
-    case M_MAILDIR:
+
+  case M_MAILDIR:
     {
       r = maildir_commit_message (ctx, msg, NULL);
       break;
     }
-    
-    case M_MH:
+
+  case M_MH:
     {
       r = mh_commit_message (ctx, msg, NULL);
       break;
     }
   }
-  
+
   if (r == 0 && (ctx->magic == M_MBOX || ctx->magic == M_MMDF)
-      && (fflush (msg->fp) == EOF || fsync (fileno (msg->fp)) == -1))
-  {
-    mutt_perror _("Can't write message");
+      && (fflush (msg->fp) == EOF || fsync (fileno (msg->fp)) == -1)) {
+    mutt_perror (_("Can't write message"));
+
     r = -1;
   }
+
   return r;
 }
 
 /* close a pointer to a message */
-int mx_close_message (MESSAGE **msg)
+int mx_close_message (MESSAGE ** msg)
 {
   int r = 0;
 
@@ -1637,17 +1442,15 @@ int mx_close_message (MESSAGE **msg)
 #ifdef USE_NNTP
       || (*msg)->magic == M_NNTP
 #endif
-      )
-  {
+    ) {
     r = safe_fclose (&(*msg)->fp);
   }
   else
     (*msg)->fp = NULL;
 
-  if ((*msg)->path)
-  {
+  if ((*msg)->path) {
     dprint (1, (debugfile, "mx_close_message (): unlinking %s\n",
-               (*msg)->path));
+                (*msg)->path));
     unlink ((*msg)->path);
     FREE (&(*msg)->path);
   }
@@ -1656,30 +1459,27 @@ int mx_close_message (MESSAGE **msg)
   return (r);
 }
 
-void mx_alloc_memory (CONTEXT *ctx)
+void mx_alloc_memory (CONTEXT * ctx)
 {
   int i;
   size_t s = MAX (sizeof (HEADER *), sizeof (int));
-  
-  if ((ctx->hdrmax + 25) * s < ctx->hdrmax * s)
-  {
+
+  if ((ctx->hdrmax + 25) * s < ctx->hdrmax * s) {
     mutt_error _("Integer overflow -- can't allocate memory.");
+
     sleep (1);
     mutt_exit (1);
   }
-  
-  if (ctx->hdrs)
-  {
+
+  if (ctx->hdrs) {
     safe_realloc (&ctx->hdrs, sizeof (HEADER *) * (ctx->hdrmax += 25));
     safe_realloc (&ctx->v2r, sizeof (int) * ctx->hdrmax);
   }
-  else
-  {
+  else {
     ctx->hdrs = safe_calloc ((ctx->hdrmax += 25), sizeof (HEADER *));
     ctx->v2r = safe_calloc (ctx->hdrmax, sizeof (int));
   }
-  for (i = ctx->msgcount ; i < ctx->hdrmax ; i++)
-  {
+  for (i = ctx->msgcount; i < ctx->hdrmax; i++) {
     ctx->hdrs[i] = NULL;
     ctx->v2r[i] = -1;
   }
@@ -1688,23 +1488,20 @@ void mx_alloc_memory (CONTEXT *ctx)
 /* this routine is called to update the counts in the context structure for
  * the last message header parsed.
  */
-void mx_update_context (CONTEXT *ctx, int new_messages)
+void mx_update_context (CONTEXT * ctx, int new_messages)
 {
   HEADER *h;
   int msgno;
 
-  for (msgno = ctx->msgcount - new_messages; msgno < ctx->msgcount; msgno++)
-  {
+  for (msgno = ctx->msgcount - new_messages; msgno < ctx->msgcount; msgno++) {
     h = ctx->hdrs[msgno];
 
-    if (WithCrypto)
-    {
+    if (WithCrypto) {
       /* NOTE: this _must_ be done before the check for mailcap! */
       h->security = crypt_query (h->content);
     }
 
-    if (!ctx->pattern)
-    {
+    if (!ctx->pattern) {
       ctx->v2r[ctx->vcount] = msgno;
       h->virtual = ctx->vcount++;
     }
@@ -1712,21 +1509,19 @@ void mx_update_context (CONTEXT *ctx, int new_messages)
       h->virtual = -1;
     h->msgno = msgno;
 
-    if (h->env->supersedes)
-    {
+    if (h->env->supersedes) {
       HEADER *h2;
 
-      if (!ctx->id_hash)       
-       ctx->id_hash = mutt_make_id_hash (ctx);
+      if (!ctx->id_hash)
+        ctx->id_hash = mutt_make_id_hash (ctx);
 
       h2 = hash_find (ctx->id_hash, h->env->supersedes);
 
       /* FREE (&h->env->supersedes); should I ? */
-      if (h2)
-      {
-       h2->superseded = 1;
-       if (option (OPTSCORE)) 
-         mutt_score_message (ctx, h2, 1);
+      if (h2) {
+        h2->superseded = 1;
+        if (option (OPTSCORE))
+          mutt_score_message (ctx, h2, 1);
       }
     }
 
@@ -1736,7 +1531,7 @@ void mx_update_context (CONTEXT *ctx, int new_messages)
     if (ctx->subj_hash && h->env->real_subj)
       hash_insert (ctx->subj_hash, h->env->real_subj, h, 1);
 
-    if (option (OPTSCORE)) 
+    if (option (OPTSCORE))
       mutt_score_message (ctx, h, 0);
 
     if (h->changed)
@@ -1745,11 +1540,10 @@ void mx_update_context (CONTEXT *ctx, int new_messages)
       ctx->flagged++;
     if (h->deleted)
       ctx->deleted++;
-    if (!h->read)
-    {
+    if (!h->read) {
       ctx->unread++;
       if (!h->old)
-       ctx->new++;
+        ctx->new++;
     }
   }
 }
@@ -1762,18 +1556,50 @@ void mx_update_context (CONTEXT *ctx, int new_messages)
  */
 int mx_check_empty (const char *path)
 {
-  switch (mx_get_magic (path))
-  {
-    case M_MBOX:
-    case M_MMDF:
-      return mbox_check_empty (path);
-    case M_MH:
-      return mh_check_empty (path);
-    case M_MAILDIR:
-      return maildir_check_empty (path);
-    default:
-      errno = EINVAL;
-      return -1;
+  int i = 0;
+  if ((i = mx_get_idx (path)) >= 0 && MX_COMMAND(i,mx_check_empty))
+    return (MX_COMMAND(i,mx_check_empty)(path));
+  errno = EINVAL;
+  return (-1);
+}
+
+int mx_acl_check (CONTEXT* ctx, int flag) {
+  if (!ctx || !MX_IDX(ctx->magic-1))
+    return (0);
+  /* if no acl_check defined for module, assume permission is granted */
+  if (!MX_COMMAND(ctx->magic-1,mx_acl_check))
+    return (1);
+  return (MX_COMMAND(ctx->magic-1,mx_acl_check)(ctx,flag));
+}
+
+void mx_init (void) {
+#ifdef DEBUG
+  int i = 0;
+#endif
+  list_push_back (&MailboxFormats, (void*) mbox_reg_mx ());
+  list_push_back (&MailboxFormats, (void*) mmdf_reg_mx ());
+  list_push_back (&MailboxFormats, (void*) mh_reg_mx ());
+  list_push_back (&MailboxFormats, (void*) maildir_reg_mx ());
+#ifdef USE_IMAP
+  list_push_back (&MailboxFormats, (void*) imap_reg_mx ());
+#endif
+#ifdef USE_POP
+  list_push_back (&MailboxFormats, (void*) pop_reg_mx ());
+#endif
+#ifdef USE_NNTP
+  list_push_back (&MailboxFormats, (void*) nntp_reg_mx ());
+#endif
+#ifdef USE_COMPRESSED
+  list_push_back (&MailboxFormats, (void*) compress_reg_mx ());
+#endif
+#ifdef DEBUG
+  /* check module registration for completeness with debug versions */
+#define EXITWITHERR(m) do { fprintf(stderr, "error: incomplete mx module: %s is missing for type %i\n",m,i);exit(1); } while (0)
+  for (i = 0; i < MailboxFormats->length; i++) {
+    if (MX_COMMAND(i,type) < 1)         EXITWITHERR("type");
+    if (!MX_COMMAND(i,mx_is_magic))     EXITWITHERR("mx_is_magic");
+    if (!MX_COMMAND(i,mx_open_mailbox)) EXITWITHERR("mx_open_mailbox");
   }
-  /* not reached */
+#undef EXITWITHERR
+#endif /* DEBUG */
 }