and less size_t's
[apps/madmutt.git] / mh.c
diff --git a/mh.c b/mh.c
index 56ff8b4..5ca542f 100644 (file)
--- a/mh.c
+++ b/mh.c
@@ -1,20 +1,11 @@
 /*
+ * Copyright notice from original mutt:
  * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org>
  * Copyright (C) 1999-2002 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.
  */
 
 /*
  * mailboxes.
  */
 
-#include "mutt.h"
-#include "mailbox.h"
-#include "mx.h"
-#include "copy.h"
-#include "buffy.h"
-#include "sort.h"
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
 
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <string.h>
 #include <utime.h>
 
-struct maildir
-{
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <lib-lib/mem.h>
+#include <lib-lib/str.h>
+#include <lib-lib/macros.h>
+#include <lib-lib/file.h>
+#include <lib-lib/debug.h>
+
+#include "mutt.h"
+#include "mx.h"
+#include "mh.h"
+#include "mbox.h"
+#include "copy.h"
+#include "buffy.h"
+#include "sort.h"
+#include "thread.h"
+#include "hcache.h"
+
+struct maildir {
   HEADER *h;
   char *canon_fname;
   unsigned header_parsed:1;
-  ino_t inode;
   struct maildir *next;
 };
 
-struct mh_sequences
-{
+struct mh_sequences {
   int max;
   short *flags;
 };
@@ -64,15 +69,19 @@ struct mh_sequences
 #define MH_SEQ_REPLIED (1 << 1)
 #define MH_SEQ_FLAGGED (1 << 2)
 
+/* prototypes */
+static int maildir_check_empty (const char*);
+static int maildir_check_mailbox (CONTEXT*, int*, int);
+static int mh_check_mailbox (CONTEXT*, int*, int);
+
 static void mhs_alloc (struct mh_sequences *mhs, int i)
 {
   int j;
   int newmax;
 
-  if (i > mhs->max || !mhs->flags)
-  {
+  if (i > mhs->max || !mhs->flags) {
     newmax = i + 128;
-    safe_realloc (&mhs->flags, sizeof (mhs->flags[0]) * (newmax + 1));
+    p_realloc(&mhs->flags, newmax + 1);
     for (j = mhs->max + 1; j <= newmax; j++)
       mhs->flags[j] = 0;
 
@@ -82,7 +91,7 @@ static void mhs_alloc (struct mh_sequences *mhs, int i)
 
 static void mhs_free_sequences (struct mh_sequences *mhs)
 {
-  FREE (&mhs->flags);
+  p_delete(&mhs->flags);
 }
 
 static short mhs_check (struct mh_sequences *mhs, int i)
@@ -116,8 +125,8 @@ static short mhs_unset (struct mh_sequences *mhs, int i, short f)
 static void mh_read_token (char *t, int *first, int *last)
 {
   char *p;
-  if ((p = strchr (t, '-')))
-  {
+
+  if ((p = strchr (t, '-'))) {
     *p++ = '\0';
     *first = atoi (t);
     *last = atoi (p);
@@ -132,40 +141,39 @@ static void mh_read_sequences (struct mh_sequences *mhs, const char *path)
   int line = 1;
   char *buff = NULL;
   char *t;
-  size_t sz = 0;
+  ssize_t sz = 0;
 
   short f;
   int first, last;
 
   char pathname[_POSIX_PATH_MAX];
+
   snprintf (pathname, sizeof (pathname), "%s/.mh_sequences", path);
 
   if (!(fp = fopen (pathname, "r")))
     return;
 
-  while ((buff = mutt_read_line (buff, &sz, fp, &line)))
-  {
+  while ((buff = mutt_read_line (buff, &sz, fp, &line))) {
     if (!(t = strtok (buff, " \t:")))
       continue;
 
-    if (!mutt_strcmp (t, MhUnseen))
+    if (!m_strcmp(t, MhUnseen))
       f = MH_SEQ_UNSEEN;
-    else if (!mutt_strcmp (t, MhFlagged))
+    else if (!m_strcmp(t, MhFlagged))
       f = MH_SEQ_FLAGGED;
-    else if (!mutt_strcmp (t, MhReplied))
+    else if (!m_strcmp(t, MhReplied))
       f = MH_SEQ_REPLIED;
-    else                       /* unknown sequence */
+    else                        /* unknown sequence */
       continue;
 
-    while ((t = strtok (NULL, " \t:")))
-    {
+    while ((t = strtok (NULL, " \t:"))) {
       mh_read_token (t, &first, &last);
       for (; first <= last; first++)
-       mhs_set (mhs, first, f);
+        mhs_set (mhs, first, f);
     }
   }
 
-  FREE (&buff);
+  p_delete(&buff);
   safe_fclose (&fp);
 }
 
@@ -173,7 +181,8 @@ int mh_buffy (const char *path)
 {
   int i, r = 0;
   struct mh_sequences mhs;
-  memset (&mhs, 0, sizeof (mhs));
+
+  p_clear(&mhs, 1);
 
   mh_read_sequences (&mhs, path);
   for (i = 0; !r && i <= mhs.max; i++)
@@ -188,29 +197,24 @@ static int mh_mkstemp (CONTEXT * dest, FILE ** fp, char **tgt)
   int fd;
   char path[_POSIX_PATH_MAX];
 
-  FOREVER
-  {
+  for (;;) {
     snprintf (path, _POSIX_PATH_MAX, "%s/.mutt-%s-%d-%d",
-             dest->path, NONULL (Hostname), (int) getpid (), Counter++);
-    umask(Umask);
-    if ((fd = open (path, O_WRONLY | O_EXCL | O_CREAT, 0666)) == -1)
-    {
-      if (errno != EEXIST)
-      {
-       mutt_perror (path);
-       return -1;
+              dest->path, NONULL (Hostname), (int) getpid (), Counter++);
+    umask (Umask);
+    if ((fd = open (path, O_WRONLY | O_EXCL | O_CREAT, 0666)) == -1) {
+      if (errno != EEXIST) {
+        mutt_perror (path);
+        return -1;
       }
     }
-    else
-    {
-      *tgt = safe_strdup (path);
+    else {
+      *tgt = m_strdup(path);
       break;
     }
   }
 
-  if ((*fp = fdopen (fd, "w")) == NULL)
-  {
-    FREE (tgt);
+  if ((*fp = fdopen (fd, "w")) == NULL) {
+    p_delete(tgt);
     close (fd);
     unlink (path);
     return (-1);
@@ -220,38 +224,35 @@ static int mh_mkstemp (CONTEXT * dest, FILE ** fp, char **tgt)
 }
 
 static void mhs_write_one_sequence (FILE * fp, struct mh_sequences *mhs,
-                                   short f, const char *tag)
+                                    short f, const char *tag)
 {
   int i;
   int first, last;
+
   fprintf (fp, "%s:", tag);
 
   first = -1;
   last = -1;
 
-  for (i = 0; i <= mhs->max; i++)
-  {
-    if ((mhs_check (mhs, i) & f))
-    {
+  for (i = 0; i <= mhs->max; i++) {
+    if ((mhs_check (mhs, i) & f)) {
       if (first < 0)
-       first = i;
+        first = i;
       else
-       last = i;
+        last = i;
     }
-    else if (first >= 0)
-    {
+    else if (first >= 0) {
       if (last < 0)
-       fprintf (fp, " %d", first);
+        fprintf (fp, " %d", first);
       else
-       fprintf (fp, " %d-%d", first, last);
+        fprintf (fp, " %d-%d", first, last);
 
       first = -1;
       last = -1;
     }
   }
 
-  if (first >= 0)
-  {
+  if (first >= 0) {
     if (last < 0)
       fprintf (fp, " %d", first);
     else
@@ -271,7 +272,7 @@ void mh_update_sequences (CONTEXT * ctx)
   char *tmpfname;
   char *buff = NULL;
   char *p;
-  size_t s;
+  ssize_t s;
   int l = 0;
   int i;
 
@@ -285,14 +286,14 @@ void mh_update_sequences (CONTEXT * ctx)
 
 
   struct mh_sequences mhs;
-  memset (&mhs, 0, sizeof (mhs));
+
+  p_clear(&mhs, 1);
 
   snprintf (seq_unseen, sizeof (seq_unseen), "%s:", NONULL (MhUnseen));
   snprintf (seq_replied, sizeof (seq_replied), "%s:", NONULL (MhReplied));
   snprintf (seq_flagged, sizeof (seq_flagged), "%s:", NONULL (MhFlagged));
 
-  if (mh_mkstemp (ctx, &nfp, &tmpfname) != 0)
-  {
+  if (mh_mkstemp (ctx, &nfp, &tmpfname) != 0) {
     /* error message? */
     return;
   }
@@ -301,16 +302,14 @@ void mh_update_sequences (CONTEXT * ctx)
 
 
   /* first, copy unknown sequences */
-  if ((ofp = fopen (sequences, "r")))
-  {
-    while ((buff = mutt_read_line (buff, &s, ofp, &l)))
-    {
-      if (!mutt_strncmp (buff, seq_unseen, mutt_strlen (seq_unseen)))
-       continue;
-      if (!mutt_strncmp (buff, seq_flagged, mutt_strlen (seq_flagged)))
-       continue;
-      if (!mutt_strncmp (buff, seq_replied, mutt_strlen (seq_replied)))
-       continue;
+  if ((ofp = fopen (sequences, "r"))) {
+    while ((buff = mutt_read_line (buff, &s, ofp, &l))) {
+      if (!m_strncmp(buff, seq_unseen, m_strlen(seq_unseen)))
+        continue;
+      if (!m_strncmp(buff, seq_flagged, m_strlen(seq_flagged)))
+        continue;
+      if (!m_strncmp(buff, seq_replied, m_strlen(seq_replied)))
+        continue;
 
       fprintf (nfp, "%s\n", buff);
     }
@@ -318,8 +317,7 @@ void mh_update_sequences (CONTEXT * ctx)
   safe_fclose (&ofp);
 
   /* now, update our unseen, flagged, and replied sequences */
-  for (l = 0; l < ctx->msgcount; l++)
-  {
+  for (l = 0; l < ctx->msgcount; l++) {
     if (ctx->hdrs[l]->deleted)
       continue;
 
@@ -330,18 +328,15 @@ void mh_update_sequences (CONTEXT * ctx)
 
     i = atoi (p);
 
-    if (!ctx->hdrs[l]->read)
-    {
+    if (!ctx->hdrs[l]->read) {
       mhs_set (&mhs, i, MH_SEQ_UNSEEN);
       unseen++;
     }
-    if (ctx->hdrs[l]->flagged)
-    {
+    if (ctx->hdrs[l]->flagged) {
       mhs_set (&mhs, i, MH_SEQ_FLAGGED);
       flagged++;
     }
-    if (ctx->hdrs[l]->replied)
-    {
+    if (ctx->hdrs[l]->replied) {
       mhs_set (&mhs, i, MH_SEQ_REPLIED);
       replied++;
     }
@@ -362,17 +357,16 @@ void mh_update_sequences (CONTEXT * ctx)
   safe_fclose (&nfp);
 
   unlink (sequences);
-  if (safe_rename (tmpfname, sequences) != 0)
-  {
+  if (safe_rename (tmpfname, sequences) != 0) {
     /* report an error? */
     unlink (tmpfname);
   }
 
-  FREE (&tmpfname);
+  p_delete(&tmpfname);
 }
 
 static void mh_sequences_add_one (CONTEXT * ctx, int n, short unseen,
-                                 short flagged, short replied)
+                                  short flagged, short replied)
 {
   short unseen_done = 0;
   short flagged_done = 0;
@@ -389,7 +383,7 @@ static void mh_sequences_add_one (CONTEXT * ctx, int n, short unseen,
 
   char *buff = NULL;
   int line;
-  size_t sz;
+  ssize_t sz;
 
   if (mh_mkstemp (ctx, &nfp, &tmpfname) == -1)
     return;
@@ -399,33 +393,28 @@ static void mh_sequences_add_one (CONTEXT * ctx, int n, short unseen,
   snprintf (seq_flagged, sizeof (seq_flagged), "%s:", NONULL (MhFlagged));
 
   snprintf (sequences, sizeof (sequences), "%s/.mh_sequences", ctx->path);
-  if ((ofp = fopen (sequences, "r")))
-  {
-    while ((buff = mutt_read_line (buff, &sz, ofp, &line)))
-    {
-      if (unseen && !strncmp (buff, seq_unseen, mutt_strlen (seq_unseen)))
-      {
-       fprintf (nfp, "%s %d\n", buff, n);
-       unseen_done = 1;
+  if ((ofp = fopen (sequences, "r"))) {
+    while ((buff = mutt_read_line (buff, &sz, ofp, &line))) {
+      if (unseen && !strncmp (buff, seq_unseen, m_strlen(seq_unseen))) {
+        fprintf (nfp, "%s %d\n", buff, n);
+        unseen_done = 1;
       }
       else if (flagged
-              && !strncmp (buff, seq_flagged, mutt_strlen (seq_flagged)))
-      {
-       fprintf (nfp, "%s %d\n", buff, n);
-       flagged_done = 1;
+               && !strncmp (buff, seq_flagged, m_strlen(seq_flagged))) {
+        fprintf (nfp, "%s %d\n", buff, n);
+        flagged_done = 1;
       }
       else if (replied
-              && !strncmp (buff, seq_replied, mutt_strlen (seq_replied)))
-      {
-       fprintf (nfp, "%s %d\n", buff, n);
-       replied_done = 1;
+               && !strncmp (buff, seq_replied, m_strlen(seq_replied))) {
+        fprintf (nfp, "%s %d\n", buff, n);
+        replied_done = 1;
       }
       else
-       fprintf (nfp, "%s\n", buff);
+        fprintf (nfp, "%s\n", buff);
     }
   }
   safe_fclose (&ofp);
-  FREE (&buff);
+  p_delete(&buff);
 
   if (!unseen_done && unseen)
     fprintf (nfp, "%s: %d\n", NONULL (MhUnseen), n);
@@ -440,7 +429,7 @@ static void mh_sequences_add_one (CONTEXT * ctx, int n, short unseen,
   if (safe_rename (tmpfname, sequences) != 0)
     unlink (tmpfname);
 
-  FREE (&tmpfname);
+  p_delete(&tmpfname);
 }
 
 static void mh_update_maildir (struct maildir *md, struct mh_sequences *mhs)
@@ -449,8 +438,7 @@ static void mh_update_maildir (struct maildir *md, struct mh_sequences *mhs)
   short f;
   char *p;
 
-  for (; md; md = md->next)
-  {
+  for (; md; md = md->next) {
     if ((p = strrchr (md->h->path, '/')))
       p++;
     else
@@ -472,11 +460,11 @@ static void maildir_free_entry (struct maildir **md)
   if (!md || !*md)
     return;
 
-  FREE (&(*md)->canon_fname);
+  p_delete(&(*md)->canon_fname);
   if ((*md)->h)
-    mutt_free_header (&(*md)->h);
+    header_delete(&(*md)->h);
 
-  FREE (md);
+  p_delete(md);
 }
 
 static void maildir_free_maildir (struct maildir **md)
@@ -486,8 +474,7 @@ static void maildir_free_maildir (struct maildir **md)
   if (!md || !*md)
     return;
 
-  for (p = *md; p; p = q)
-  {
+  for (p = *md; p; p = q) {
     q = p->next;
     maildir_free_entry (&p);
   }
@@ -501,47 +488,44 @@ static void maildir_parse_flags (HEADER * h, const char *path)
   h->read = 0;
   h->replied = 0;
 
-  if ((p = strrchr (path, ':')) != NULL && mutt_strncmp (p + 1, "2,", 2) == 0)
-  {
+  if ((p = strrchr (path, ':')) != NULL && m_strncmp(p + 1, "2,", 2) == 0) {
     p += 3;
-    
-    mutt_str_replace (&h->maildir_flags, p);
+
+    m_strreplace(&h->maildir_flags, p);
     q = h->maildir_flags;
 
-    while (*p)
-    {
-      switch (*p)
-      {
+    while (*p) {
+      switch (*p) {
       case 'F':
 
-       h->flagged = 1;
-       break;
+        h->flagged = 1;
+        break;
 
-      case 'S':                /* seen */
+      case 'S':                /* seen */
 
-       h->read = 1;
-       break;
+        h->read = 1;
+        break;
 
-      case 'R':                /* replied */
+      case 'R':                /* replied */
 
-       h->replied = 1;
-       break;
+        h->replied = 1;
+        break;
+
+      case 'T':                /* trashed */
+        h->trash = 1;
+        h->deleted = 1;
+        break;
 
-      case 'T':                /* trashed */
-       h->trash = 1;
-       h->deleted = 1;
-       break;
-      
       default:
-       *q++ = *p;
-       break;
+        *q++ = *p;
+        break;
       }
       p++;
     }
   }
-  
+
   if (q == h->maildir_flags)
-    FREE (&h->maildir_flags);
+    p_delete(&h->maildir_flags);
   else if (q)
     *q = '\0';
 }
@@ -551,20 +535,18 @@ static void maildir_update_mtime (CONTEXT * ctx)
   char buf[_POSIX_PATH_MAX];
   struct stat st;
 
-  if (ctx->magic == M_MAILDIR)
-  {
+  if (ctx->magic == M_MAILDIR) {
     snprintf (buf, sizeof (buf), "%s/%s", ctx->path, "cur");
     if (stat (buf, &st) == 0)
       ctx->mtime_cur = st.st_mtime;
     snprintf (buf, sizeof (buf), "%s/%s", ctx->path, "new");
   }
-  else
-  {
+  else {
     snprintf (buf, sizeof (buf), "%s/.mh_sequences", ctx->path);
     if (stat (buf, &st) == 0)
       ctx->mtime_cur = st.st_mtime;
 
-    strfcpy (buf, ctx->path, sizeof (buf));
+    m_strcpy(buf, sizeof(buf), ctx->path);
   }
 
   if (stat (buf, &st) == 0)
@@ -576,16 +558,15 @@ static void maildir_update_mtime (CONTEXT * ctx)
  * out a fake header structure generated by lazy maildir parsing.
  */
 static HEADER *maildir_parse_message (int magic, const char *fname,
-                                     int is_old, HEADER * _h)
+                                      int is_old, HEADER * _h)
 {
   FILE *f;
   HEADER *h = _h;
   struct stat st;
 
-  if ((f = fopen (fname, "r")) != NULL)
-  {
+  if ((f = fopen (fname, "r")) != NULL) {
     if (!h)
-      h = mutt_new_header ();
+      h = header_new();
     h->env = mutt_read_rfc822_header (f, h, 0, 0);
 
     fstat (fileno (f), &st);
@@ -599,8 +580,7 @@ static HEADER *maildir_parse_message (int magic, const char *fname,
 
     h->index = -1;
 
-    if (magic == M_MAILDIR)
-    {
+    if (magic == M_MAILDIR) {
       /* 
        * maildir stores its flags in the filename, so ignore the
        * flags in the header of the message 
@@ -628,8 +608,8 @@ static HEADER *maildir_parse_message (int magic, const char *fname,
  */
 
 static int maildir_parse_entry (CONTEXT * ctx, struct maildir ***last,
-                               const char *subdir, const char *fname,
-                               int *count, int is_old, ino_t inode)
+                                const char *subdir, const char *fname,
+                                int *count, int is_old, ino_t inode __attribute__ ((unused)))
 {
   struct maildir *entry;
   HEADER *h = NULL;
@@ -642,34 +622,29 @@ static int maildir_parse_entry (CONTEXT * ctx, struct maildir ***last,
 
   if (ctx->magic == M_MH)
     h = maildir_parse_message (ctx->magic, buf, is_old, NULL);
-  else
-  {
-    h = mutt_new_header ();
+  else {
+    h = header_new();
     h->old = is_old;
     maildir_parse_flags (h, buf);
   }
 
-  if (h != NULL)
-  {
-    if (count)
-    {
+  if (h != NULL) {
+    if (count) {
       (*count)++;
       if (!ctx->quiet && ReadInc && ((*count % ReadInc) == 0 || *count == 1))
-       mutt_message (_("Reading %s... %d"), ctx->path, *count);
+        mutt_message (_("Reading %s... %d"), ctx->path, *count);
     }
 
-    if (subdir)
-    {
+    if (subdir) {
       snprintf (buf, sizeof (buf), "%s/%s", subdir, fname);
-      h->path = safe_strdup (buf);
+      h->path = m_strdup(buf);
     }
     else
-      h->path = safe_strdup (fname);
+      h->path = m_strdup(fname);
 
-    entry = safe_calloc (sizeof (struct maildir), 1);
+    entry = p_new(struct maildir, 1);
     entry->h = h;
     entry->header_parsed = (ctx->magic == M_MH);
-    entry->inode = inode;
     **last = entry;
     *last = &entry->next;
 
@@ -688,8 +663,7 @@ static int maildir_parse_entry (CONTEXT * ctx, struct maildir ***last,
 
 int mh_valid_message (const char *s)
 {
-  for (; *s; s++)
-  {
+  for (; *s; s++) {
     if (!isdigit ((unsigned char) *s))
       return 0;
   }
@@ -697,38 +671,39 @@ int mh_valid_message (const char *s)
 }
 
 static int maildir_parse_dir (CONTEXT * ctx, struct maildir ***last,
-                             const char *subdir, int *count)
+                              const char *subdir, int *count)
 {
   DIR *dirp;
   struct dirent *de;
   char buf[_POSIX_PATH_MAX];
   int is_old = 0;
 
-  if (subdir)
-  {
+  if (subdir) {
     snprintf (buf, sizeof (buf), "%s/%s", ctx->path, subdir);
-    is_old = (mutt_strcmp ("cur", subdir) == 0);
+    is_old = (m_strcmp("cur", subdir) == 0);
   }
   else
-    strfcpy (buf, ctx->path, sizeof (buf));
+    m_strcpy(buf, sizeof(buf), ctx->path);
 
   if ((dirp = opendir (buf)) == NULL)
     return -1;
 
-  while ((de = readdir (dirp)) != NULL)
-  {
+  while ((de = readdir (dirp)) != NULL) {
 
     if ((ctx->magic == M_MH && !mh_valid_message (de->d_name))
-       || (ctx->magic == M_MAILDIR && *de->d_name == '.'))
+        || (ctx->magic == M_MAILDIR && *de->d_name == '.'))
       continue;
 
     /* FOO - really ignore the return value? */
 
-    dprint (2,
-           (debugfile, "%s:%d: parsing %s\n", __FILE__, __LINE__,
-            de->d_name));
-    maildir_parse_entry (ctx, last, subdir, de->d_name, count, is_old, 
-                        de->d_ino);
+    debug_print (2, ("parsing %s\n", de->d_name));
+    maildir_parse_entry (ctx, last, subdir, de->d_name, count, is_old,
+#if HAVE_DIRENT_D_INO
+                         de->d_ino
+#else
+                         0
+#endif
+                        );
   }
 
   closedir (dirp);
@@ -739,28 +714,22 @@ static int maildir_add_to_context (CONTEXT * ctx, struct maildir *md)
 {
   int oldmsgcount = ctx->msgcount;
 
-  while (md)
-  {
+  while (md) {
+
+    debug_print (2, ("considering %s\n", NONULL (md->canon_fname)));
 
-    dprint (2, (debugfile, "%s:%d maildir_add_to_context(): Considering %s\n",
-               __FILE__, __LINE__, NONULL (md->canon_fname)));
-
-    if (md->h)
-    {
-      dprint (2,
-             (debugfile,
-              "%s:%d Adding header structure. Flags: %s%s%s%s%s\n", __FILE__,
-              __LINE__, md->h->flagged ? "f" : "", md->h->deleted ? "D" : "",
-              md->h->replied ? "r" : "", md->h->old ? "O" : "",
-              md->h->read ? "R" : ""));
+    if (md->h) {
+      debug_print (2, ("flags: %s%s%s%s%s\n", md->h->flagged ? "f" : "",
+                  md->h->deleted ? "D" : "", md->h->replied ? "r" : "",
+                  md->h->old ? "O" : "", md->h->read ? "R" : ""));
       if (ctx->msgcount == ctx->hdrmax)
-       mx_alloc_memory (ctx);
+        mx_alloc_memory (ctx);
 
       ctx->hdrs[ctx->msgcount] = md->h;
       ctx->hdrs[ctx->msgcount]->index = ctx->msgcount;
       ctx->size +=
-       md->h->content->length + md->h->content->offset -
-       md->h->content->hdr_offset;
+        md->h->content->length + md->h->content->offset -
+        md->h->content->hdr_offset;
 
       md->h = NULL;
       ctx->msgcount++;
@@ -768,8 +737,7 @@ static int maildir_add_to_context (CONTEXT * ctx, struct maildir *md)
     md = md->next;
   }
 
-  if (ctx->msgcount > oldmsgcount)
-  {
+  if (ctx->msgcount > oldmsgcount) {
     mx_update_context (ctx, ctx->msgcount - oldmsgcount);
     return 1;
   }
@@ -779,104 +747,16 @@ static int maildir_add_to_context (CONTEXT * ctx, struct maildir *md)
 static int maildir_move_to_context (CONTEXT * ctx, struct maildir **md)
 {
   int r;
+
   r = maildir_add_to_context (ctx, *md);
   maildir_free_maildir (md);
   return r;
 }
 
-/*
- * Merge two maildir lists according to the inode numbers.
- */
-static struct maildir*  maildir_merge_inode (struct maildir *left,
-                                            struct maildir *right)
+#ifdef USE_HCACHE
+static ssize_t maildir_hcache_keylen (const char *fn)
 {
-  struct maildir* head;
-  struct maildir* tail;
-
-  if (left && right) 
-  {
-    if (left->inode < right->inode)
-    {
-      head = left;
-      left = left->next;
-    }
-    else 
-    {
-      head = right;
-      right = right->next;
-    }
-  } 
-  else 
-  {
-    if (left) 
-      return left;
-    else 
-      return right;
-  }
-    
-  tail = head;
-
-  while (left && right) 
-  {
-    if (left->inode < right->inode) 
-    {
-      tail->next = left;
-      left = left->next;
-    } 
-    else 
-    {
-      tail->next = right;
-      right = right->next;
-    }
-    tail = tail->next;
-  }
-
-  if (left) 
-  {
-    tail->next = left;
-  }
-  else
-  {
-    tail->next = right;
-  }
-
-  return head;
-}
-
-/*
- * Sort maildir list according to inode.
- */
-static struct maildir* maildir_sort_inode(struct maildir* list)
-{
-  struct maildir* left = list;
-  struct maildir* right = list;
-
-  if (!list || !list->next) 
-  {
-    return list;
-  }
-
-  list = list->next;
-  while (list && list->next) 
-  {
-    right = right->next;
-    list = list->next->next;
-  }
-
-  list = right;
-  right = right->next;
-  list->next = 0;
-
-  left = maildir_sort_inode(left);
-  right = maildir_sort_inode(right);
-  return maildir_merge_inode(left, right);
-}
-
-#if USE_HCACHE
-static size_t maildir_hcache_keylen (const char *fn)
-{
-  const char * p = strchr (fn, ':');
-  return p ? (size_t) (p - fn) : mutt_strlen(fn);
+    return m_strchrnul(fn, ':') - fn;
 }
 #endif
 
@@ -890,10 +770,9 @@ void maildir_delayed_parsing (CONTEXT * ctx, struct maildir *md)
   char fn[_POSIX_PATH_MAX];
   int count;
 
-#if USE_HCACHE
+#ifdef USE_HCACHE
   void *hc = NULL;
   void *data;
-  unsigned int size;
   struct timeval *when = NULL;
   struct stat lastchanged;
   int ret;
@@ -901,48 +780,48 @@ void maildir_delayed_parsing (CONTEXT * ctx, struct maildir *md)
   hc = mutt_hcache_open (HeaderCache, ctx->path);
 #endif
 
-  for (p = md, count = 0; p; p = p->next, count++)
-  {
-    if (! (p && p->h && !p->header_parsed))
-       continue;
+  for (p = md, count = 0; p; p = p->next, count++) {
+    if (!(p && p->h && !p->header_parsed))
+      continue;
 
-#if USE_HCACHE
-    data      = mutt_hcache_fetch (hc, p->h->path + 3, &maildir_hcache_keylen);
-    when      = (struct timeval *) data;
+#ifdef USE_HCACHE
+    data = mutt_hcache_fetch (hc, p->h->path + 3, &maildir_hcache_keylen);
+    when = (struct timeval *) data;
 #endif
 
     if (!ctx->quiet && ReadInc && ((count % ReadInc) == 0 || count == 1))
       mutt_message (_("Reading %s... %d"), ctx->path, count);
     snprintf (fn, sizeof (fn), "%s/%s", ctx->path, p->h->path);
 
-#if USE_HCACHE
-    if (option(OPTHCACHEVERIFY)) {
-      ret = stat(fn, &lastchanged);
-    } else {
+#ifdef USE_HCACHE
+    if (option (OPTHCACHEVERIFY)) {
+      ret = stat (fn, &lastchanged);
+    }
+    else {
       lastchanged.st_mtime = 0;
       ret = 0;
     }
 
-    if (data != NULL && !ret && lastchanged.st_mtime <= when->tv_sec)
-    {
-      p->h = mutt_hcache_restore ((unsigned char *)data, &p->h);
+    if (data != NULL && !ret && lastchanged.st_mtime <= when->tv_sec) {
+      p->h = mutt_hcache_restore ((unsigned char *) data, &p->h);
       maildir_parse_flags (p->h, fn);
-    } else
+    }
+    else
 #endif
-    if (maildir_parse_message (ctx->magic, fn, p->h->old, p->h))
-    {
+    if (maildir_parse_message (ctx->magic, fn, p->h->old, p->h)) {
       p->header_parsed = 1;
       maildir_parse_flags (p->h, fn);
-#if USE_HCACHE
+#ifdef USE_HCACHE
       mutt_hcache_store (hc, p->h->path + 3, p->h, 0, &maildir_hcache_keylen);
 #endif
-    } else
-      mutt_free_header (&p->h);
-#if USE_HCACHE
-    FREE(&data);
+    }
+    else
+      header_delete(&p->h);
+#ifdef USE_HCACHE
+    p_delete(&data);
 #endif
   }
-#if USE_HCACHE
+#ifdef USE_HCACHE
   mutt_hcache_close (hc);
 #endif
 }
@@ -954,7 +833,7 @@ void maildir_delayed_parsing (CONTEXT * ctx, struct maildir *md)
  *     subdir [IN]     NULL for MH mailboxes, otherwise the subdir of the
  *                     maildir mailbox to read from
  */
-int mh_read_dir (CONTEXT * ctx, const char *subdir)
+static int _mh_read_dir (CONTEXT * ctx, const char *subdir)
 {
   struct maildir *md;
   struct mh_sequences mhs;
@@ -962,7 +841,7 @@ int mh_read_dir (CONTEXT * ctx, const char *subdir)
   int count;
 
 
-  memset (&mhs, 0, sizeof (mhs));
+  p_clear(&mhs, 1);
 
   maildir_update_mtime (ctx);
 
@@ -972,15 +851,12 @@ int mh_read_dir (CONTEXT * ctx, const char *subdir)
   if (maildir_parse_dir (ctx, &last, subdir, &count) == -1)
     return -1;
 
-  if (ctx->magic == M_MH)
-  {
+  if (ctx->magic == M_MH) {
     mh_read_sequences (&mhs, ctx->path);
     mh_update_maildir (md, &mhs);
     mhs_free_sequences (&mhs);
   }
 
-  md = maildir_sort_inode(md);
-
   if (ctx->magic == M_MAILDIR)
     maildir_delayed_parsing (ctx, md);
 
@@ -988,13 +864,17 @@ int mh_read_dir (CONTEXT * ctx, const char *subdir)
   return 0;
 }
 
+static int mh_read_dir (CONTEXT* ctx) {
+  return (_mh_read_dir (ctx, NULL));
+}
+
 /* read a maildir style mailbox */
-int maildir_read_dir (CONTEXT * ctx)
+static int maildir_read_dir (CONTEXT * ctx)
 {
   /* maildir looks sort of like MH, except that there are two subdirectories
    * of the main folder path from which to read messages
    */
-  if (mh_read_dir (ctx, "new") == -1 || mh_read_dir (ctx, "cur") == -1)
+  if (_mh_read_dir (ctx, "new") == -1 || _mh_read_dir (ctx, "cur") == -1)
     return (-1);
 
   return 0;
@@ -1004,17 +884,17 @@ int maildir_read_dir (CONTEXT * ctx)
  * Open a new (temporary) message in an MH folder.
  */
 
-int mh_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr)
+static int mh_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr __attribute__ ((unused)))
 {
   return mh_mkstemp (dest, &msg->fp, &msg->path);
 }
 
 int ch_compar (const void *a, const void *b)
 {
-  return (int)*((const char *) a) - *((const char *) b));
+  return (int) (*((const char *) a) - *((const char *) b));
 }
 
-static void maildir_flags (char *dest, size_t destlen, HEADER * hdr)
+static void maildir_flags (char *dest, ssize_t destlen, HEADER * hdr)
 {
   *dest = '\0';
 
@@ -1025,18 +905,20 @@ static void maildir_flags (char *dest, size_t destlen, HEADER * hdr)
    * will end up in the cur directory, so we include it in the following
    * test even though there is no associated flag.
    */
-  
-  if (hdr && (hdr->flagged || hdr->replied || hdr->read || hdr->deleted || hdr->old || hdr->maildir_flags))
-  {
+
+  if (hdr
+      && (hdr->flagged || hdr->replied || hdr->read || hdr->deleted
+          || hdr->old || hdr->maildir_flags)) {
     char tmp[LONG_STRING];
+
     snprintf (tmp, sizeof (tmp),
-             "%s%s%s%s%s",
-             hdr->flagged ? "F" : "",
-             hdr->replied ? "R" : "",
-             hdr->read ? "S" : "", hdr->deleted ? "T" : "",
-             NONULL(hdr->maildir_flags));
+              "%s%s%s%s%s",
+              hdr->flagged ? "F" : "",
+              hdr->replied ? "R" : "",
+              hdr->read ? "S" : "", hdr->deleted ? "T" : "",
+              NONULL (hdr->maildir_flags));
     if (hdr->maildir_flags)
-      qsort (tmp, strlen (tmp), 1, ch_compar);
+      qsort (tmp, m_strlen(tmp), 1, ch_compar);
     snprintf (dest, destlen, ":2,%s", tmp);
   }
 }
@@ -1050,16 +932,16 @@ static void maildir_flags (char *dest, size_t destlen, HEADER * hdr)
  *
  */
 
-int maildir_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr)
+static int maildir_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr)
 {
   int fd;
   char path[_POSIX_PATH_MAX];
   char suffix[16];
   char subdir[16];
 
-  if (hdr)
-  {
+  if (hdr) {
     short deleted = hdr->deleted;
+
     hdr->deleted = 0;
 
     maildir_flags (suffix, sizeof (suffix), hdr);
@@ -1070,39 +952,33 @@ int maildir_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr)
     *suffix = '\0';
 
   if (hdr && (hdr->read || hdr->old))
-    strfcpy (subdir, "cur", sizeof (subdir));
+    m_strcpy(subdir, sizeof(subdir), "cur");
   else
-    strfcpy (subdir, "new", sizeof (subdir));
+    m_strcpy(subdir, sizeof(subdir), "new");
 
-  FOREVER
-  {
+  for (;;) {
     snprintf (path, _POSIX_PATH_MAX, "%s/tmp/%s.%ld.%u_%d.%s%s",
-             dest->path, subdir, time (NULL), (unsigned int)getpid (),
-             Counter++, NONULL (Hostname), suffix);
-
-    dprint (2, (debugfile, "maildir_open_new_message (): Trying %s.\n",
-               path));
-
-    umask(Umask);
-    if ((fd = open (path, O_WRONLY | O_EXCL | O_CREAT, 0666)) == -1)
-    {
-      if (errno != EEXIST)
-      {
-       mutt_perror (path);
-       return -1;
+              dest->path, subdir, (long) time (NULL),
+              (unsigned int) getpid (), Counter++, NONULL (Hostname), suffix);
+
+    debug_print (2, ("trying %s.\n", path));
+
+    umask (Umask);
+    if ((fd = open (path, O_WRONLY | O_EXCL | O_CREAT, 0666)) == -1) {
+      if (errno != EEXIST) {
+        mutt_perror (path);
+        return -1;
       }
     }
-    else
-    {
-      dprint (2, (debugfile, "maildir_open_new_message (): Success.\n"));
-      msg->path = safe_strdup (path);
+    else {
+      debug_print (2, ("success.\n"));
+      msg->path = m_strdup(path);
       break;
     }
   }
 
-  if ((msg->fp = fdopen (fd, "w")) == NULL)
-  {
-    FREE (&msg->path);
+  if ((msg->fp = fdopen (fd, "w")) == NULL) {
+    p_delete(&msg->path);
     close (fd);
     unlink (path);
     return (-1);
@@ -1134,7 +1010,7 @@ int maildir_open_new_message (MESSAGE * msg, CONTEXT * dest, HEADER * hdr)
  * 
  */
 
-int maildir_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr)
+static int maildir_commit_message (MESSAGE * msg, CONTEXT * ctx, HEADER * hdr)
 {
   char subdir[4];
   char suffix[16];
@@ -1147,30 +1023,27 @@ int maildir_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr)
 
   /* extract the subdir */
   s = strrchr (msg->path, '/') + 1;
-  strfcpy (subdir, s, 4);
+  m_strcpy(subdir, sizeof(subdir), s);
 
   /* extract the flags */
   if ((s = strchr (s, ':')))
-    strfcpy (suffix, s, sizeof (suffix));
+    m_strcpy(suffix, sizeof(suffix), s);
   else
     suffix[0] = '\0';
 
   /* construct a new file name. */
-  FOREVER
-  {
+  for (;;) {
     snprintf (path, _POSIX_PATH_MAX, "%s/%ld.%u_%d.%s%s", subdir,
-             time (NULL), (unsigned int)getpid (), Counter++, 
-             NONULL (Hostname), suffix);
+              (long) time (NULL), (unsigned int) getpid (), Counter++,
+              NONULL (Hostname), suffix);
     snprintf (full, _POSIX_PATH_MAX, "%s/%s", ctx->path, path);
 
-    dprint (2, (debugfile, "maildir_commit_message (): renaming %s to %s.\n",
-               msg->path, full));
+    debug_print (2, ("renaming %s to %s.\n", msg->path, full));
 
-    if (safe_rename (msg->path, full) == 0)
-    {
+    if (safe_rename (msg->path, full) == 0) {
       if (hdr)
-       mutt_str_replace (&hdr->path, path);
-      FREE (&msg->path);
+        m_strreplace(&hdr->path, path);
+      p_delete(&msg->path);
 
       /*
        * Adjust the mtime on the file to match the time at which this
@@ -1178,23 +1051,21 @@ int maildir_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr)
        * messages between mailboxes, so we test to ensure that it is
        * actually set.
        */
-      if (msg->received)
-      {
-       struct utimbuf ut;
-
-       ut.actime = msg->received;
-       ut.modtime = msg->received;
-       if (utime (full, &ut))
-       {
-         mutt_perror (_("maildir_commit_message(): unable to set time on file"));
-         return -1;
-       }
+      if (msg->received) {
+        struct utimbuf ut;
+
+        ut.actime = msg->received;
+        ut.modtime = msg->received;
+        if (utime (full, &ut)) {
+          mutt_perror (_
+                       ("maildir_commit_message(): unable to set time on file"));
+          return -1;
+        }
       }
 
       return 0;
     }
-    else if (errno != EEXIST)
-    {
+    else if (errno != EEXIST) {
       mutt_perror (ctx->path);
       return -1;
     }
@@ -1207,8 +1078,8 @@ int maildir_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr)
  */
 
 
-static int _mh_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr,
-                              short updseq)
+static int _mh_commit_message (MESSAGE * msg, CONTEXT * ctx, HEADER * hdr,
+                               short updseq)
 {
   DIR *dirp;
   struct dirent *de;
@@ -1220,30 +1091,26 @@ static int _mh_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr,
   if (safe_fclose (&msg->fp) != 0)
     return -1;
 
-  if ((dirp = opendir (ctx->path)) == NULL)
-  {
+  if ((dirp = opendir (ctx->path)) == NULL) {
     mutt_perror (ctx->path);
     return (-1);
   }
 
   /* figure out what the next message number is */
-  while ((de = readdir (dirp)) != NULL)
-  {
+  while ((de = readdir (dirp)) != NULL) {
     dep = de->d_name;
     if (*dep == ',')
       dep++;
     cp = dep;
-    while (*cp)
-    {
+    while (*cp) {
       if (!isdigit ((unsigned char) *cp))
-       break;
+        break;
       cp++;
     }
-    if (!*cp)
-    {
+    if (!*cp) {
       n = atoi (dep);
       if (n > hi)
-       hi = n;
+        hi = n;
     }
   }
   closedir (dirp);
@@ -1255,36 +1122,31 @@ static int _mh_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr,
    * slot.
    */
 
-  FOREVER
-  {
+  for (;;) {
     hi++;
     snprintf (tmp, sizeof (tmp), "%d", hi);
     snprintf (path, sizeof (path), "%s/%s", ctx->path, tmp);
-    if (safe_rename (msg->path, path) == 0)
-    {
+    if (safe_rename (msg->path, path) == 0) {
       if (hdr)
-       mutt_str_replace (&hdr->path, tmp);
-      FREE (&msg->path);
+        m_strreplace(&hdr->path, tmp);
+      p_delete(&msg->path);
       break;
     }
-    else if (errno != EEXIST)
-    {
+    else if (errno != EEXIST) {
       mutt_perror (ctx->path);
       return -1;
     }
   }
   if (updseq)
     mh_sequences_add_one (ctx, hi, !msg->flags.read, msg->flags.flagged,
-                         msg->flags.replied);
+                          msg->flags.replied);
   return 0;
 }
 
-int mh_commit_message (CONTEXT * ctx, MESSAGE * msg, HEADER * hdr)
-{
-  return _mh_commit_message (ctx, msg, hdr, 1);
+static int mh_commit_message (MESSAGE * msg, CONTEXT * ctx, HEADER * hdr) {
+  return _mh_commit_message (msg, ctx, hdr, 1);
 }
 
-
 /* Sync a message in an MH folder.
  * 
  * This code is also used for attachment deletion in maildir
@@ -1310,20 +1172,19 @@ static int mh_rewrite_message (CONTEXT * ctx, int msgno)
     return -1;
 
   if ((rc = mutt_copy_message (dest->fp, ctx, h,
-                              M_CM_UPDATE, CH_UPDATE | CH_UPDATE_LEN)) == 0)
+                               M_CM_UPDATE, CH_UPDATE | CH_UPDATE_LEN)) == 0)
   {
-    snprintf (oldpath, _POSIX_PATH_MAX, "%s/%s", ctx->path, h->path);
-    strfcpy (partpath, h->path, _POSIX_PATH_MAX);
+    snprintf (oldpath, sizeof(oldpath), "%s/%s", ctx->path, h->path);
+    m_strcpy(partpath, sizeof(partpath), h->path);
 
     if (ctx->magic == M_MAILDIR)
-      rc = maildir_commit_message (ctx, dest, h);
+      rc = maildir_commit_message (dest, ctx, h);
     else
-      rc = _mh_commit_message (ctx, dest, h, 0);
+      rc = _mh_commit_message (dest, ctx, h, 0);
 
     mx_close_message (&dest);
 
-    if (rc == 0)
-    {
+    if (rc == 0) {
       unlink (oldpath);
       restore = 0;
     }
@@ -1343,18 +1204,16 @@ static int mh_rewrite_message (CONTEXT * ctx, int msgno)
      * lose flag modifications.
      */
 
-    if (ctx->magic == M_MH && rc == 0)
-    {
+    if (ctx->magic == M_MH && rc == 0) {
       snprintf (newpath, _POSIX_PATH_MAX, "%s/%s", ctx->path, h->path);
       if ((rc = safe_rename (newpath, oldpath)) == 0)
-       mutt_str_replace (&h->path, partpath);
+        m_strreplace(&h->path, partpath);
     }
   }
   else
     mx_close_message (&dest);
 
-  if (rc == -1 && restore)
-  {
+  if (rc == -1 && restore) {
     h->content->offset = old_body_offset;
     h->content->length = old_body_length;
     h->lines = old_hdr_lines;
@@ -1368,7 +1227,8 @@ static int mh_sync_message (CONTEXT * ctx, int msgno)
 {
   HEADER *h = ctx->hdrs[msgno];
 
-  if (h->attach_del || h->refs_changed || h->irt_changed)
+  if (h->attach_del || 
+      (h->env && (h->env->refs_changed || h->env->irt_changed)))
     if (mh_rewrite_message (ctx, msgno) != 0)
       return -1;
 
@@ -1379,14 +1239,13 @@ static int maildir_sync_message (CONTEXT * ctx, int msgno)
 {
   HEADER *h = ctx->hdrs[msgno];
 
-  if (h->attach_del || h->refs_changed || h->irt_changed)
-  {
+  if (h->attach_del || 
+      (h->env && (h->env->refs_changed || h->env->irt_changed))) {
     /* when doing attachment deletion/rethreading, fall back to the MH case. */
     if (mh_rewrite_message (ctx, msgno) != 0)
       return (-1);
   }
-  else
-  {
+  else {
     /* we just have to rename the file. */
 
     char newpath[_POSIX_PATH_MAX];
@@ -1396,16 +1255,12 @@ static int maildir_sync_message (CONTEXT * ctx, int msgno)
     char suffix[16];
     char *p;
 
-    if ((p = strrchr (h->path, '/')) == NULL)
-    {
-      dprint (1,
-             (debugfile,
-              "maildir_sync_message: %s: unable to find subdir!\n",
-              h->path));
+    if ((p = strrchr (h->path, '/')) == NULL) {
+      debug_print (1, ("%s: unable to find subdir!\n", h->path));
       return (-1);
     }
     p++;
-    strfcpy (newpath, p, sizeof (newpath));
+    m_strcpy(newpath, sizeof(newpath), p);
 
     /* kill the previous flags */
     if ((p = strchr (newpath, ':')) != NULL)
@@ -1414,12 +1269,11 @@ static int maildir_sync_message (CONTEXT * ctx, int msgno)
     maildir_flags (suffix, sizeof (suffix), h);
 
     snprintf (partpath, sizeof (partpath), "%s/%s%s",
-             (h->read || h->old) ? "cur" : "new", newpath, suffix);
+              (h->read || h->old) ? "cur" : "new", newpath, suffix);
     snprintf (fullpath, sizeof (fullpath), "%s/%s", ctx->path, partpath);
     snprintf (oldpath, sizeof (oldpath), "%s/%s", ctx->path, h->path);
 
-    if (mutt_strcmp (fullpath, oldpath) == 0)
-    {
+    if (m_strcmp(fullpath, oldpath) == 0) {
       /* message hasn't really changed */
       return 0;
     }
@@ -1427,84 +1281,77 @@ static int maildir_sync_message (CONTEXT * ctx, int msgno)
     /* record that the message is possibly marked as trashed on disk */
     h->trash = h->deleted;
 
-    if (rename (oldpath, fullpath) != 0)
-    {
+    if (rename (oldpath, fullpath) != 0) {
       mutt_perror ("rename");
       return (-1);
     }
-    mutt_str_replace (&h->path, partpath);
+    m_strreplace(&h->path, partpath);
   }
   return (0);
 }
 
-int mh_sync_mailbox (CONTEXT * ctx, int *index_hint)
+static int mh_sync_mailbox (CONTEXT * ctx, int unused __attribute__ ((unused)), int *index_hint)
 {
   char path[_POSIX_PATH_MAX], tmp[_POSIX_PATH_MAX];
   int i, j;
-#if USE_HCACHE
+
+#ifdef USE_HCACHE
   void *hc = NULL;
 #endif /* USE_HCACHE */
 
   if (ctx->magic == M_MH)
-    i = mh_check_mailbox (ctx, index_hint);
-  else 
-    i = maildir_check_mailbox (ctx, index_hint);
-      
+    i = mh_check_mailbox (ctx, index_hint, 0);
+  else
+    i = maildir_check_mailbox (ctx, index_hint, 0);
+
   if (i != 0)
     return i;
 
-#if USE_HCACHE
+#ifdef USE_HCACHE
   if (ctx->magic == M_MAILDIR)
-    hc = mutt_hcache_open(HeaderCache, ctx->path);
+    hc = mutt_hcache_open (HeaderCache, ctx->path);
 #endif /* USE_HCACHE */
 
-  for (i = 0; i < ctx->msgcount; i++)
-  {
+  for (i = 0; i < ctx->msgcount; i++) {
     if (ctx->hdrs[i]->deleted
-       && (ctx->magic != M_MAILDIR || !option (OPTMAILDIRTRASH)))
-    {
+        && (ctx->magic != M_MAILDIR || !option (OPTMAILDIRTRASH))) {
       snprintf (path, sizeof (path), "%s/%s", ctx->path, ctx->hdrs[i]->path);
       if (ctx->magic == M_MAILDIR
-         || (option (OPTMHPURGE) && ctx->magic == M_MH))
-      {
-#if USE_HCACHE
+          || (option (OPTMHPURGE) && ctx->magic == M_MH)) {
+#ifdef USE_HCACHE
         if (ctx->magic == M_MAILDIR)
-          mutt_hcache_delete (hc, ctx->hdrs[i]->path + 3, &maildir_hcache_keylen);
+          mutt_hcache_delete (hc, ctx->hdrs[i]->path + 3,
+                              &maildir_hcache_keylen);
 #endif /* USE_HCACHE */
-       unlink (path);
+        unlink (path);
       }
-      else if (ctx->magic == M_MH)
-      {
-       /* MH just moves files out of the way when you delete them */
-       if (*ctx->hdrs[i]->path != ',')
-       {
-         snprintf (tmp, sizeof (tmp), "%s/,%s", ctx->path,
-                   ctx->hdrs[i]->path);
-         unlink (tmp);
-         rename (path, tmp);
-       }
+      else if (ctx->magic == M_MH) {
+        /* MH just moves files out of the way when you delete them */
+        if (*ctx->hdrs[i]->path != ',') {
+          snprintf (tmp, sizeof (tmp), "%s/,%s", ctx->path,
+                    ctx->hdrs[i]->path);
+          unlink (tmp);
+          rename (path, tmp);
+        }
 
       }
     }
     else if (ctx->hdrs[i]->changed || ctx->hdrs[i]->attach_del ||
-            (ctx->magic == M_MAILDIR
-             && (option (OPTMAILDIRTRASH) || ctx->hdrs[i]->trash)
-             && (ctx->hdrs[i]->deleted != ctx->hdrs[i]->trash)))
-    {
-      if (ctx->magic == M_MAILDIR)
-      {
-       if (maildir_sync_message (ctx, i) == -1)
-         goto err;
+             (ctx->magic == M_MAILDIR
+              && (option (OPTMAILDIRTRASH) || ctx->hdrs[i]->trash)
+              && (ctx->hdrs[i]->deleted != ctx->hdrs[i]->trash))) {
+      if (ctx->magic == M_MAILDIR) {
+        if (maildir_sync_message (ctx, i) == -1)
+          goto err;
       }
-      else
-      {
-       if (mh_sync_message (ctx, i) == -1)
-         goto err;
+      else {
+        if (mh_sync_message (ctx, i) == -1)
+          goto err;
       }
     }
   }
 
-#if USE_HCACHE
+#ifdef USE_HCACHE
   if (ctx->magic == M_MAILDIR)
     mutt_hcache_close (hc);
 #endif /* USE_HCACHE */
@@ -1518,60 +1365,56 @@ int mh_sync_mailbox (CONTEXT * ctx, int *index_hint)
 
   /* adjust indices */
 
-  if (ctx->deleted)
-  {
-    for (i = 0, j = 0; i < ctx->msgcount; i++)
-    {
+  if (ctx->deleted) {
+    for (i = 0, j = 0; i < ctx->msgcount; i++) {
       if (!ctx->hdrs[i]->deleted
-         || (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))
-       ctx->hdrs[i]->index = j++;
+          || (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))
+        ctx->hdrs[i]->index = j++;
     }
   }
 
   return 0;
 
 err:
-#if USE_HCACHE
+#ifdef USE_HCACHE
   if (ctx->magic == M_MAILDIR)
     mutt_hcache_close (hc);
 #endif /* USE_HCACHE */
   return -1;
 }
 
-static char *maildir_canon_filename (char *dest, const char *src, size_t l)
+static char *maildir_canon_filename (char *dest, const char *src, ssize_t l)
 {
   char *t, *u;
 
   if ((t = strrchr (src, '/')))
     src = t + 1;
 
-  strfcpy (dest, src, l);
+  m_strcpy(dest, l, src);
   if ((u = strrchr (dest, ':')))
     *u = '\0';
 
   return dest;
 }
 
-static void maildir_update_tables (CONTEXT *ctx, int *index_hint)
+static void maildir_update_tables (CONTEXT * ctx, int *index_hint)
 {
   short old_sort;
   int old_count;
   int i, j;
-  
-  if (Sort != SORT_ORDER)
-  {
+
+  if (Sort != SORT_ORDER) {
     old_sort = Sort;
     Sort = SORT_ORDER;
     mutt_sort_headers (ctx, 1);
     Sort = old_sort;
   }
-  
+
   old_count = ctx->msgcount;
-  for (i = 0, j = 0; i < old_count; i++)
-  {
+  for (i = 0, j = 0; i < old_count; i++) {
     if (ctx->hdrs[i]->active && index_hint && *index_hint == i)
       *index_hint = j;
-    
+
     if (ctx->hdrs[i]->active)
       ctx->hdrs[i]->index = j++;
   }
@@ -1580,13 +1423,13 @@ static void maildir_update_tables (CONTEXT *ctx, int *index_hint)
   mutt_clear_threads (ctx);
 }
 
-static void maildir_update_flags (CONTEXT *ctx, HEADER *o, HEADER *n)
+static void maildir_update_flags (CONTEXT * ctx, HEADER * o, HEADER * n)
 {
   /* save the global state here so we can reset it at the
    * end of list block if required.
    */
   int context_changed = ctx->changed;
-  
+
   /* user didn't modify this message.  alter the flags to
    * match the current state on disk.  This may not actually
    * do anything, but we can't tell right now.  mutt_set_flag()
@@ -1604,7 +1447,7 @@ static void maildir_update_flags (CONTEXT *ctx, HEADER *o, HEADER *n)
    * message.
    */
   o->changed = 0;
-  
+
   /* if the mailbox was not modified before we made these
    * changes, unset the changed flag since nothing needs to
    * be synchronized.
@@ -1622,24 +1465,21 @@ static void maildir_update_flags (CONTEXT *ctx, HEADER *o, HEADER *n)
  * either subdirectory differently, as mail could be copied directly into
  * the cur directory from another agent.
  */
-int maildir_check_mailbox (CONTEXT * ctx, int *index_hint)
+static int maildir_check_mailbox (CONTEXT * ctx, int *index_hint, int unused __attribute__ ((unused)))
 {
-  struct stat st_new;          /* status of the "new" subdirectory */
-  struct stat st_cur;          /* status of the "cur" subdirectory */
+  struct stat st_new;           /* status of the "new" subdirectory */
+  struct stat st_cur;           /* status of the "cur" subdirectory */
   char buf[_POSIX_PATH_MAX];
-  int changed = 0;             /* bitmask representing which subdirectories
-                                  have changed.  0x1 = new, 0x2 = cur */
-  int occult = 0;              /* messages were removed from the mailbox */
-  int have_new = 0;            /* messages were added to the mailbox */
-  struct maildir *md;          /* list of messages in the mailbox */
+  int changed = 0;              /* bitmask representing which subdirectories
+                                   have changed.  0x1 = new, 0x2 = cur */
+  int occult = 0;               /* messages were removed from the mailbox */
+  int have_new = 0;             /* messages were added to the mailbox */
+  struct maildir *md;           /* list of messages in the mailbox */
   struct maildir **last, *p;
   int i;
-  HASH *fnames;                        /* hash table for quickly looking up the base filename
-                                  for a maildir message */
+  HASH *fnames;                 /* hash table for quickly looking up the base filename
+                                   for a maildir message */
 
-  /* XXX seems like this check belongs in mx_check_mailbox()
-   * rather than here.
-   */
   if (!option (OPTCHECKNEW))
     return 0;
 
@@ -1658,7 +1498,7 @@ int maildir_check_mailbox (CONTEXT * ctx, int *index_hint)
     changed |= 2;
 
   if (!changed)
-    return 0;                  /* nothing to do */
+    return 0;                   /* nothing to do */
 
   /* update the modification times on the mailbox */
   ctx->mtime_cur = st_cur.st_mtime;
@@ -1680,58 +1520,53 @@ int maildir_check_mailbox (CONTEXT * ctx, int *index_hint)
    */
   fnames = hash_create (1031);
 
-  for (p = md; p; p = p->next)
-  {
+  for (p = md; p; p = p->next) {
     maildir_canon_filename (buf, p->h->path, sizeof (buf));
-    p->canon_fname = safe_strdup (buf);
+    p->canon_fname = m_strdup(buf);
     hash_insert (fnames, p->canon_fname, p, 0);
   }
 
   /* check for modifications and adjust flags */
-  for (i = 0; i < ctx->msgcount; i++)
-  {
+  for (i = 0; i < ctx->msgcount; i++) {
     ctx->hdrs[i]->active = 0;
     maildir_canon_filename (buf, ctx->hdrs[i]->path, sizeof (buf));
     p = hash_find (fnames, buf);
-    if (p && p->h)
-    {
+    if (p && p->h) {
       /* message already exists, merge flags */
       ctx->hdrs[i]->active = 1;
 
       /* check to see if the message has moved to a different
        * subdirectory.  If so, update the associated filename.
        */
-      if (mutt_strcmp (ctx->hdrs[i]->path, p->h->path))
-       mutt_str_replace (&ctx->hdrs[i]->path, p->h->path);
+      if (m_strcmp(ctx->hdrs[i]->path, p->h->path))
+        m_strreplace(&ctx->hdrs[i]->path, p->h->path);
 
       /* if the user hasn't modified the flags on this message, update
        * the flags we just detected.
        */
       if (!ctx->hdrs[i]->changed)
-       maildir_update_flags (ctx, ctx->hdrs[i], p->h);
+        maildir_update_flags (ctx, ctx->hdrs[i], p->h);
 
       if (ctx->hdrs[i]->deleted == ctx->hdrs[i]->trash)
-       ctx->hdrs[i]->deleted = p->h->deleted;
+        ctx->hdrs[i]->deleted = p->h->deleted;
       ctx->hdrs[i]->trash = p->h->trash;
 
       /* this is a duplicate of an existing header, so remove it */
-      mutt_free_header (&p->h);
+      header_delete(&p->h);
     }
     /* This message was not in the list of messages we just scanned.
      * Check to see if we have enough information to know if the
      * message has disappeared out from underneath us.
      */
     else if (((changed & 1) && (!strncmp (ctx->hdrs[i]->path, "new/", 4))) ||
-            ((changed & 2) && (!strncmp (ctx->hdrs[i]->path, "cur/", 4))))
-    {
+             ((changed & 2) && (!strncmp (ctx->hdrs[i]->path, "cur/", 4)))) {
       /* This message disappeared, so we need to simulate a "reopen"
        * event.  We know it disappeared because we just scanned the
        * subdirectory it used to reside in.
        */
       occult = 1;
     }
-    else
-    {
+    else {
       /* This message resides in a subdirectory which was not
        * modified, so we assume that it is still present and
        * unchanged.
@@ -1746,7 +1581,7 @@ int maildir_check_mailbox (CONTEXT * ctx, int *index_hint)
   /* If we didn't just get new mail, update the tables. */
   if (occult)
     maildir_update_tables (ctx, index_hint);
-  
+
   /* do any delayed parsing we need to do. */
   maildir_delayed_parsing (ctx, md);
 
@@ -1767,7 +1602,7 @@ int maildir_check_mailbox (CONTEXT * ctx, int *index_hint)
  *
  */
 
-int mh_check_mailbox (CONTEXT * ctx, int *index_hint)
+static int mh_check_mailbox (CONTEXT * ctx, int *index_hint, int unused __attribute__ ((unused)))
 {
   char buf[_POSIX_PATH_MAX];
   struct stat st, st_cur;
@@ -1781,23 +1616,21 @@ int mh_check_mailbox (CONTEXT * ctx, int *index_hint)
   if (!option (OPTCHECKNEW))
     return 0;
 
-  strfcpy (buf, ctx->path, sizeof (buf));
+  m_strcpy(buf, sizeof(buf), ctx->path);
   if (stat (buf, &st) == -1)
     return -1;
-  
+
   /* create .mh_sequences when there isn't one. */
   snprintf (buf, sizeof (buf), "%s/.mh_sequences", ctx->path);
-  if ((i = stat (buf, &st_cur) == -1) && errno == ENOENT)
-  {
+  if ((i = stat (buf, &st_cur) == -1) && errno == ENOENT) {
     char *tmp;
     FILE *fp = NULL;
-    
-    if (mh_mkstemp (ctx, &fp, &tmp) == 0)
-    {
+
+    if (mh_mkstemp (ctx, &fp, &tmp) == 0) {
       safe_fclose (&fp);
       if (safe_rename (tmp, buf) == -1)
-       unlink (tmp);
-      FREE (&tmp);
+        unlink (tmp);
+      p_delete(&tmp);
     }
   }
 
@@ -1813,9 +1646,9 @@ int mh_check_mailbox (CONTEXT * ctx, int *index_hint)
   ctx->mtime_cur = st_cur.st_mtime;
   ctx->mtime = st.st_mtime;
 
-  memset (&mhs, 0, sizeof (mhs));
-  
-  md   = NULL;
+  p_clear(&mhs, 1);
+
+  md = NULL;
   last = &md;
   maildir_parse_dir (ctx, &last, NULL, NULL);
   mh_read_sequences (&mhs, ctx->path);
@@ -1828,21 +1661,19 @@ int mh_check_mailbox (CONTEXT * ctx, int *index_hint)
   for (p = md; p; p = p->next)
     hash_insert (fnames, p->h->path, p, 0);
 
-  for (i = 0; i < ctx->msgcount; i++)
-  {
+  for (i = 0; i < ctx->msgcount; i++) {
     ctx->hdrs[i]->active = 0;
 
     if ((p = hash_find (fnames, ctx->hdrs[i]->path)) && p->h &&
-       (mbox_strict_cmp_headers (ctx->hdrs[i], p->h)))
-    {
+        (mutt_cmp_header (ctx->hdrs[i], p->h))) {
       ctx->hdrs[i]->active = 1;
       /* found the right message */
       if (!ctx->hdrs[i]->changed)
-       maildir_update_flags (ctx, ctx->hdrs[i], p->h);
+        maildir_update_flags (ctx, ctx->hdrs[i], p->h);
 
-      mutt_free_header (&p->h);
+      header_delete(&p->h);
     }
-    else /* message has disappeared */
+    else                        /* message has disappeared */
       occult = 1;
   }
 
@@ -1870,7 +1701,7 @@ int mh_check_mailbox (CONTEXT * ctx, int *index_hint)
  */
 
 FILE *_maildir_open_find_message (const char *folder, const char *unique,
-                                 const char *subfolder)
+                                  const char *subfolder)
 {
   char dir[_POSIX_PATH_MAX];
   char tunique[_POSIX_PATH_MAX];
@@ -1884,21 +1715,18 @@ FILE *_maildir_open_find_message (const char *folder, const char *unique,
 
   snprintf (dir, sizeof (dir), "%s/%s", folder, subfolder);
 
-  if ((dp = opendir (dir)) == NULL)
-  {
+  if ((dp = opendir (dir)) == NULL) {
     errno = ENOENT;
     return NULL;
   }
 
-  while ((de = readdir (dp)))
-  {
+  while ((de = readdir (dp))) {
     maildir_canon_filename (tunique, de->d_name, sizeof (tunique));
 
-    if (!mutt_strcmp (tunique, unique))
-    {
+    if (!m_strcmp(tunique, unique)) {
       snprintf (fname, sizeof (fname), "%s/%s/%s", folder, subfolder,
-               de->d_name);
-      fp = fopen (fname, "r"); /* __FOPEN_CHECKED__ */
+                de->d_name);
+      fp = fopen (fname, "r");  /* __FOPEN_CHECKED__ */
       oe = errno;
       break;
     }
@@ -1915,32 +1743,26 @@ FILE *maildir_open_find_message (const char *folder, const char *msg)
   char unique[_POSIX_PATH_MAX];
   FILE *fp;
 
-  static unsigned int new_hits = 0, cur_hits = 0;      /* simple dynamic optimization */
+  static unsigned int new_hits = 0, cur_hits = 0;       /* simple dynamic optimization */
 
   maildir_canon_filename (unique, msg, sizeof (unique));
 
-  if (
-      (fp =
+  if ((fp =
        _maildir_open_find_message (folder, unique,
-                                  new_hits > cur_hits ? "new" : "cur"))
-      || errno != ENOENT)
-  {
-    if (new_hits < UINT_MAX && cur_hits < UINT_MAX)
-    {
+                                   new_hits > cur_hits ? "new" : "cur"))
+      || errno != ENOENT) {
+    if (new_hits < UINT_MAX && cur_hits < UINT_MAX) {
       new_hits += (new_hits > cur_hits ? 1 : 0);
       cur_hits += (new_hits > cur_hits ? 0 : 1);
     }
 
     return fp;
   }
-  if (
-      (fp =
+  if ((fp =
        _maildir_open_find_message (folder, unique,
-                                  new_hits > cur_hits ? "cur" : "new"))
-      || errno != ENOENT)
-  {
-    if (new_hits < UINT_MAX && cur_hits < UINT_MAX)
-    {
+                                   new_hits > cur_hits ? "cur" : "new"))
+      || errno != ENOENT) {
+    if (new_hits < UINT_MAX && cur_hits < UINT_MAX) {
       new_hits += (new_hits > cur_hits ? 0 : 1);
       cur_hits += (new_hits > cur_hits ? 1 : 0);
     }
@@ -1958,12 +1780,12 @@ FILE *maildir_open_find_message (const char *folder, const char *msg)
  * 0 if there are messages in the mailbox
  * -1 on error
  */
-int maildir_check_empty (const char *path)
+static int maildir_check_empty (const char *path)
 {
   DIR *dp;
   struct dirent *de;
-  int r = 1; /* assume empty until we find a message */
-  char realpath[_POSIX_PATH_MAX];
+  int r = 1;                    /* assume empty until we find a message */
+  char frealpath[_POSIX_PATH_MAX];
   int iter = 0;
 
   /* Strategy here is to look for any file not beginning with a period */
@@ -1972,16 +1794,14 @@ int maildir_check_empty (const char *path)
     /* we do "cur" on the first iteration since its more likely that we'll
      * find old messages without having to scan both subdirs
      */
-    snprintf (realpath, sizeof (realpath), "%s/%s", path,
-             iter == 0 ? "cur" : "new");
-    if ((dp = opendir (realpath)) == NULL)
+    snprintf (frealpath, sizeof (frealpath), "%s/%s", path,
+              iter == 0 ? "cur" : "new");
+    if ((dp = opendir (frealpath)) == NULL)
       return -1;
-    while ((de = readdir (dp)))
-    {
-      if (*de->d_name != '.')
-      {
-       r = 0;
-       break;
+    while ((de = readdir (dp))) {
+      if (*de->d_name != '.') {
+        r = 0;
+        break;
       }
     }
     closedir (dp);
@@ -2001,19 +1821,106 @@ int mh_check_empty (const char *path)
 {
   DIR *dp;
   struct dirent *de;
-  int r = 1; /* assume empty until we find a message */
-  
+  int r = 1;                    /* assume empty until we find a message */
+
   if ((dp = opendir (path)) == NULL)
     return -1;
-  while ((de = readdir (dp)))
-  {
-    if (mh_valid_message (de->d_name))
-    {
+  while ((de = readdir (dp))) {
+    if (mh_valid_message (de->d_name)) {
       r = 0;
       break;
     }
   }
   closedir (dp);
-  
+
   return r;
 }
+
+static int mh_is_magic (const char* path, struct stat* st) {
+  char tmp[_POSIX_PATH_MAX];
+
+  if (S_ISDIR (st->st_mode)) {
+    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);
+  }
+  return (-1);
+}
+
+static int maildir_is_magic (const char* path, struct stat* st) {
+  struct stat sb;
+  char tmp[_POSIX_PATH_MAX];
+
+  if (S_ISDIR (st->st_mode)) {
+    snprintf (tmp, sizeof (tmp), "%s/cur", path);
+    if (stat (tmp, &sb) == 0 && S_ISDIR (sb.st_mode))
+      return (M_MAILDIR);
+  }
+  return (-1);
+}
+
+/* routines common to maildir and mh */
+static mx_t* reg_mx (void) {
+  mx_t* fmt = p_new(mx_t, 1);
+  fmt->local = 1;
+  fmt->mx_access = access;
+  fmt->mx_sync_mailbox = mh_sync_mailbox;
+  return (fmt);
+}
+
+static int mh_commit (MESSAGE* msg, CONTEXT* ctx) {
+  return (mh_commit_message (msg, ctx, NULL));
+}
+
+static int maildir_commit (MESSAGE* msg, CONTEXT* ctx) {
+  return (maildir_commit_message (msg, ctx, NULL));
+}
+
+mx_t* mh_reg_mx (void) {
+  mx_t* fmt = reg_mx ();
+  fmt->type = M_MH;
+  fmt->mx_check_empty = mh_check_empty;
+  fmt->mx_is_magic = mh_is_magic;
+  fmt->mx_open_mailbox = mh_read_dir;
+  fmt->mx_open_new_message = mh_open_new_message;
+  fmt->mx_check_mailbox = mh_check_mailbox;
+  fmt->mx_commit_message = mh_commit;
+  return (fmt);
+}
+
+mx_t* maildir_reg_mx (void) {
+  mx_t* fmt = reg_mx ();
+  fmt->type = M_MAILDIR;
+  fmt->mx_check_empty = maildir_check_empty;
+  fmt->mx_is_magic = maildir_is_magic;
+  fmt->mx_open_mailbox = maildir_read_dir;
+  fmt->mx_open_new_message = maildir_open_new_message;
+  fmt->mx_check_mailbox = maildir_check_mailbox;
+  fmt->mx_commit_message = maildir_commit;
+  return (fmt);
+}