Use good m_ functions, because it smell like a flower, version 2.
[apps/madmutt.git] / thread.c
index d3c33c7..e34c543 100644 (file)
--- a/thread.c
+++ b/thread.c
@@ -1,34 +1,24 @@
 /*
+ * Copyright notice from original mutt:
  * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org>
  *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- * 
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- */ 
+ * This file is part of mutt-ng, see http://www.muttng.org/.
+ * It's licensed under the GNU General Public License,
+ * please see the file GPL in the top level source directory.
+ */
+
+#include <lib-lib/lib-lib.h>
 
 #include "mutt.h"
 #include "sort.h"
-
-#include <string.h>
-#include <ctype.h>
+#include "thread.h"
 
 #define VISIBLE(hdr, ctx) (hdr->virtual >= 0 || (hdr->collapsed && (!ctx->pattern || hdr->limited)))
 
 /* determine whether a is a descendant of b */
-static int is_descendant (THREAD *a, THREAD *b)
+static int is_descendant (THREAD * a, THREAD * b)
 {
-  while (a)
-  {
+  while (a) {
     if (a == b)
       return (1);
     a = a->parent;
@@ -37,39 +27,39 @@ static int is_descendant (THREAD *a, THREAD *b)
 }
 
 /* Determines whether to display a message's subject. */
-static int need_display_subject (CONTEXT *ctx, HEADER *hdr)
+static int need_display_subject (CONTEXT * ctx, HEADER * hdr)
 {
   THREAD *tmp, *tree = hdr->thread;
 
+  /* if the user disabled subject hiding, display it */
+  if (!option (OPTHIDETHREADSUBJECT))
+    return (1);
+
   /* if our subject is different from our parent's, display it */
   if (hdr->subject_changed)
     return (1);
 
   /* if our subject is different from that of our closest previously displayed
    * sibling, display the subject */
-  for (tmp = tree->prev; tmp; tmp = tmp->prev)
-  {
+  for (tmp = tree->prev; tmp; tmp = tmp->prev) {
     hdr = tmp->message;
-    if (hdr && VISIBLE (hdr, ctx))
-    {
+    if (hdr && VISIBLE (hdr, ctx)) {
       if (hdr->subject_changed)
-       return (1);
+        return (1);
       else
-       break;
+        break;
     }
   }
-  
+
   /* if there is a parent-to-child subject change anywhere between us and our
    * closest displayed ancestor, display the subject */
-  for (tmp = tree->parent; tmp; tmp = tmp->parent)
-  {
+  for (tmp = tree->parent; tmp; tmp = tmp->parent) {
     hdr = tmp->message;
-    if (hdr)
-    {
+    if (hdr) {
       if (VISIBLE (hdr, ctx))
-       return (0);
+        return (0);
       else if (hdr->subject_changed)
-       return (1);
+        return (1);
     }
   }
 
@@ -77,13 +67,12 @@ static int need_display_subject (CONTEXT *ctx, HEADER *hdr)
   return (1);
 }
 
-static void linearize_tree (CONTEXT *ctx)
+static void linearize_tree (CONTEXT * ctx)
 {
   THREAD *tree = ctx->tree;
   HEADER **array = ctx->hdrs + (Sort & SORT_REVERSE ? ctx->msgcount - 1 : 0);
 
-  while (tree)
-  {
+  while (tree) {
     while (!tree->message)
       tree = tree->child;
 
@@ -92,17 +81,14 @@ static void linearize_tree (CONTEXT *ctx)
 
     if (tree->child)
       tree = tree->child;
-    else
-    {
-      while (tree)
-      {
-       if (tree->next)
-       {
-         tree = tree->next;
-         break;
-       }
-       else
-         tree = tree->parent;
+    else {
+      while (tree) {
+        if (tree->next) {
+          tree = tree->next;
+          break;
+        }
+        else
+          tree = tree->parent;
       }
     }
   }
@@ -115,11 +101,13 @@ static void linearize_tree (CONTEXT *ctx)
  * skip parts of the tree in mutt_draw_tree() if we've decided here that we
  * don't care about them any more.
  */
-static void calculate_visibility (CONTEXT *ctx, int *max_depth)
+static void calculate_visibility (CONTEXT * ctx, int *max_depth)
 {
   THREAD *tmp, *tree = ctx->tree;
-  int hide_top_missing = option (OPTHIDETOPMISSING) && !option (OPTHIDEMISSING);
-  int hide_top_limited = option (OPTHIDETOPLIMITED) && !option (OPTHIDELIMITED);
+  int hide_top_missing = option (OPTHIDETOPMISSING)
+    && !option (OPTHIDEMISSING);
+  int hide_top_limited = option (OPTHIDETOPLIMITED)
+    && !option (OPTHIDELIMITED);
   int depth = 0;
 
   /* we walk each level backwards to make it easier to compute next_subtree_visible */
@@ -127,89 +115,78 @@ static void calculate_visibility (CONTEXT *ctx, int *max_depth)
     tree = tree->next;
   *max_depth = 0;
 
-  FOREVER
-  {
+  for (;;) {
     if (depth > *max_depth)
       *max_depth = depth;
 
     tree->subtree_visible = 0;
-    if (tree->message)
-    {
-      FREE (&tree->message->tree);
-      if (VISIBLE (tree->message, ctx))
-      {
-       tree->deep = 1;
-       tree->visible = 1;
-       tree->message->display_subject = need_display_subject (ctx, tree->message);
-       for (tmp = tree; tmp; tmp = tmp->parent)
-       {
-         if (tmp->subtree_visible)
-         {
-           tmp->deep = 1;
-           tmp->subtree_visible = 2;
-           break;
-         }
-         else
-           tmp->subtree_visible = 1;
-       }
+    if (tree->message) {
+      p_delete(&tree->message->tree);
+      if (VISIBLE (tree->message, ctx)) {
+        tree->deep = 1;
+        tree->visible = 1;
+        tree->message->display_subject =
+          need_display_subject (ctx, tree->message);
+        for (tmp = tree; tmp; tmp = tmp->parent) {
+          if (tmp->subtree_visible) {
+            tmp->deep = 1;
+            tmp->subtree_visible = 2;
+            break;
+          }
+          else
+            tmp->subtree_visible = 1;
+        }
       }
-      else
-      {
-       tree->visible = 0;
-       tree->deep = !option (OPTHIDELIMITED);
+      else {
+        tree->visible = 0;
+        tree->deep = !option (OPTHIDELIMITED);
       }
     }
-    else
-    {
+    else {
       tree->visible = 0;
       tree->deep = !option (OPTHIDEMISSING);
     }
-    tree->next_subtree_visible = tree->next && (tree->next->next_subtree_visible
-                                               || tree->next->subtree_visible);
-    if (tree->child)
-    {
+    tree->next_subtree_visible = tree->next
+      && (tree->next->next_subtree_visible || tree->next->subtree_visible);
+    if (tree->child) {
       depth++;
       tree = tree->child;
       while (tree->next)
-       tree = tree->next;
+        tree = tree->next;
     }
     else if (tree->prev)
       tree = tree->prev;
-    else
-    {
-      while (tree && !tree->prev)
-      {
-       depth--;
-       tree = tree->parent;
+    else {
+      while (tree && !tree->prev) {
+        depth--;
+        tree = tree->parent;
       }
       if (!tree)
-       break;
+        break;
       else
-       tree = tree->prev;
+        tree = tree->prev;
     }
   }
-  
+
   /* now fix up for the OPTHIDETOP* options if necessary */
-  if (hide_top_limited || hide_top_missing)
-  {
+  if (hide_top_limited || hide_top_missing) {
     tree = ctx->tree;
-    FOREVER
-    {
-      if (!tree->visible && tree->deep && tree->subtree_visible < 2 
-         && ((tree->message && hide_top_limited) || (!tree->message && hide_top_missing)))
-       tree->deep = 0;
+    for (;;) {
+      if (!tree->visible && tree->deep && tree->subtree_visible < 2
+          && ((tree->message && hide_top_limited)
+              || (!tree->message && hide_top_missing)))
+        tree->deep = 0;
       if (!tree->deep && tree->child && tree->subtree_visible)
-       tree = tree->child;
+        tree = tree->child;
       else if (tree->next)
-       tree = tree->next;
-      else
-      {
-       while (tree && !tree->next)
-         tree = tree->parent;
-       if (!tree)
-         break;
-       else
-         tree = tree->next;
+        tree = tree->next;
+      else {
+        while (tree && !tree->next)
+          tree = tree->parent;
+        if (!tree)
+          break;
+        else
+          tree = tree->next;
       }
     }
   }
@@ -223,173 +200,156 @@ static void calculate_visibility (CONTEXT *ctx, int *max_depth)
  * graphics chars on terminals which don't support them (see the man page
  * for curs_addch).
  */
-void mutt_draw_tree (CONTEXT *ctx)
+void mutt_draw_tree (CONTEXT * ctx)
 {
   char *pfx = NULL, *mypfx = NULL, *arrow = NULL, *myarrow = NULL, *new_tree;
   char corner = (Sort & SORT_REVERSE) ? M_TREE_ULCORNER : M_TREE_LLCORNER;
   char vtee = (Sort & SORT_REVERSE) ? M_TREE_BTEE : M_TREE_TTEE;
-  int depth = 0, start_depth = 0, max_depth = 0, width = option (OPTNARROWTREE) ? 1 : 2;
+  int depth = 0, start_depth = 0, max_depth = 0, width =
+    option (OPTNARROWTREE) ? 1 : 2;
   THREAD *nextdisp = NULL, *pseudo = NULL, *parent = NULL, *tree = ctx->tree;
 
   /* Do the visibility calculations and free the old thread chars.
    * From now on we can simply ignore invisible subtrees
    */
   calculate_visibility (ctx, &max_depth);
-  pfx = safe_malloc (width * max_depth + 2);
-  arrow = safe_malloc (width * max_depth + 2);
-  while (tree)
-  {
-    if (depth)
-    {
+  pfx = p_new(char, width * max_depth + 2);
+  arrow = p_new(char, width * max_depth + 2);
+  while (tree) {
+    if (depth) {
       myarrow = arrow + (depth - start_depth - (start_depth ? 0 : 1)) * width;
       if (depth && start_depth == depth)
-       myarrow[0] = nextdisp ? M_TREE_LTEE : corner;
+        myarrow[0] = nextdisp ? M_TREE_LTEE : corner;
       else if (parent->message && !option (OPTHIDELIMITED))
-       myarrow[0] = M_TREE_HIDDEN;
+        myarrow[0] = M_TREE_HIDDEN;
       else if (!parent->message && !option (OPTHIDEMISSING))
-       myarrow[0] = M_TREE_MISSING;
+        myarrow[0] = M_TREE_MISSING;
       else
-       myarrow[0] = vtee;
+        myarrow[0] = vtee;
       if (width == 2)
-       myarrow[1] = pseudo ?  M_TREE_STAR
-                            : (tree->duplicate_thread ? M_TREE_EQUALS : M_TREE_HLINE);
-      if (tree->visible)
-      {
-       myarrow[width] = M_TREE_RARROW;
-       myarrow[width + 1] = 0;
-       new_tree = safe_malloc ((2 + depth * width));
-       if (start_depth > 1)
-       {
-         strncpy (new_tree, pfx, (start_depth - 1) * width);
-         strfcpy (new_tree + (start_depth - 1) * width,
-                  arrow, (1 + depth - start_depth) * width + 2);
-       }
-       else
-         strfcpy (new_tree, arrow, 2 + depth * width);
-       tree->message->tree = new_tree;
+        myarrow[1] = pseudo ? M_TREE_STAR
+          : (tree->duplicate_thread ? M_TREE_EQUALS : M_TREE_HLINE);
+      if (tree->visible) {
+        myarrow[width] = M_TREE_RARROW;
+        myarrow[width + 1] = 0;
+        new_tree = p_new(char, (2 + depth * width));
+        if (start_depth > 1) {
+          memcpy(new_tree, pfx, (start_depth - 1) * width);
+          m_strcpy(new_tree + (start_depth - 1) * width,
+                   (1 + depth - start_depth) * width + 2, arrow);
+        }
+        else
+          m_strcpy(new_tree, 2 + depth * width, arrow);
+        tree->message->tree = new_tree;
       }
     }
-    if (tree->child && depth)
-    {
+    if (tree->child && depth) {
       mypfx = pfx + (depth - 1) * width;
       mypfx[0] = nextdisp ? M_TREE_VLINE : M_TREE_SPACE;
       if (width == 2)
-       mypfx[1] = M_TREE_SPACE;
+        mypfx[1] = M_TREE_SPACE;
     }
     parent = tree;
     nextdisp = NULL;
     pseudo = NULL;
-    do
-    {
-      if (tree->child && tree->subtree_visible)
-      {
-       if (tree->deep)
-         depth++;
-       if (tree->visible)
-         start_depth = depth;
-       tree = tree->child;
-
-       /* we do this here because we need to make sure that the first child thread
-        * of the old tree that we deal with is actually displayed if any are,
-        * or we might set the parent variable wrong while going through it. */
-       while (!tree->subtree_visible && tree->next)
-         tree = tree->next;
+    do {
+      if (tree->child && tree->subtree_visible) {
+        if (tree->deep)
+          depth++;
+        if (tree->visible)
+          start_depth = depth;
+        tree = tree->child;
+
+        /* we do this here because we need to make sure that the first child thread
+         * of the old tree that we deal with is actually displayed if any are,
+         * or we might set the parent variable wrong while going through it. */
+        while (!tree->subtree_visible && tree->next)
+          tree = tree->next;
       }
-      else
-      {
-       while (!tree->next && tree->parent)
-       {
-         if (tree == pseudo)
-           pseudo = NULL;
-         if (tree == nextdisp)
-           nextdisp = NULL;
-         if (tree->visible)
-           start_depth = depth;
-         tree = tree->parent;
-         if (tree->deep)
-         {
-           if (start_depth == depth)
-             start_depth--;
-           depth--;
-         }
-       }
-       if (tree == pseudo)
-         pseudo = NULL;
-       if (tree == nextdisp)
-         nextdisp = NULL;
-       if (tree->visible)
-         start_depth = depth;
-       tree = tree->next;
-       if (!tree)
-         break;
+      else {
+        while (!tree->next && tree->parent) {
+          if (tree == pseudo)
+            pseudo = NULL;
+          if (tree == nextdisp)
+            nextdisp = NULL;
+          if (tree->visible)
+            start_depth = depth;
+          tree = tree->parent;
+          if (tree->deep) {
+            if (start_depth == depth)
+              start_depth--;
+            depth--;
+          }
+        }
+        if (tree == pseudo)
+          pseudo = NULL;
+        if (tree == nextdisp)
+          nextdisp = NULL;
+        if (tree->visible)
+          start_depth = depth;
+        tree = tree->next;
+        if (!tree)
+          break;
       }
       if (!pseudo && tree->fake_thread)
-       pseudo = tree;
+        pseudo = tree;
       if (!nextdisp && tree->next_subtree_visible)
-       nextdisp = tree;
+        nextdisp = tree;
     }
     while (!tree->deep);
   }
 
-  FREE (&pfx);
-  FREE (&arrow);
+  p_delete(&pfx);
+  p_delete(&arrow);
 }
 
 /* since we may be trying to attach as a pseudo-thread a THREAD that
  * has no message, we have to make a list of all the subjects of its
  * most immediate existing descendants.  we also note the earliest
  * date on any of the parents and put it in *dateptr. */
-static LIST *make_subject_list (THREAD *cur, time_t *dateptr)
+static string_list_t *make_subject_list (THREAD * cur, time_t * dateptr)
 {
   THREAD *start = cur;
   ENVELOPE *env;
   time_t thisdate;
-  LIST *curlist, *oldlist, *newlist, *subjects = NULL;
+  string_list_t *curlist, *oldlist, *newlist, *subjects = NULL;
   int rc = 0;
-  
-  FOREVER
-  {
+
+  for (;;) {
     while (!cur->message)
       cur = cur->child;
 
-    if (dateptr)
-    {
+    if (dateptr) {
       thisdate = option (OPTTHREADRECEIVED)
-       ? cur->message->received : cur->message->date_sent;
+        ? cur->message->received : cur->message->date_sent;
       if (!*dateptr || thisdate < *dateptr)
-       *dateptr = thisdate;
+        *dateptr = thisdate;
     }
 
     env = cur->message->env;
     if (env->real_subj &&
-       ((env->real_subj != env->subject) || (!option (OPTSORTRE))))
-    {
+        ((env->real_subj != env->subject) || (!option (OPTSORTRE)))) {
       for (curlist = subjects, oldlist = NULL;
-          curlist; oldlist = curlist, curlist = curlist->next)
-      {
-       rc = mutt_strcmp (env->real_subj, curlist->data);
-       if (rc >= 0)
-         break;
+           curlist; oldlist = curlist, curlist = curlist->next) {
+        rc = m_strcmp(env->real_subj, curlist->data);
+        if (rc >= 0)
+          break;
       }
-      if (!curlist || rc > 0)
-      {
-       newlist = safe_calloc (1, sizeof (LIST));
-       newlist->data = env->real_subj;
-       if (oldlist)
-       {
-         newlist->next = oldlist->next;
-         oldlist->next = newlist;
-       }
-       else
-       {
-         newlist->next = subjects;
-         subjects = newlist;
-       }
+      if (!curlist || rc > 0) {
+        newlist = p_new(string_list_t, 1);
+        newlist->data = env->real_subj;
+        if (oldlist) {
+          newlist->next = oldlist->next;
+          oldlist->next = newlist;
+        }
+        else {
+          newlist->next = subjects;
+          subjects = newlist;
+        }
       }
     }
 
-    while (!cur->next && cur != start)
-    {
+    while (!cur->next && cur != start) {
       cur = cur->parent;
     }
     if (cur == start)
@@ -404,42 +364,40 @@ static LIST *make_subject_list (THREAD *cur, time_t *dateptr)
  * if there are multiple matches, the one which was sent the latest, but
  * before the current message, is used. 
  */
-static THREAD *find_subject (CONTEXT *ctx, THREAD *cur)
+static THREAD *find_subject (CONTEXT * ctx, THREAD * cur)
 {
   struct hash_elem *ptr;
   THREAD *tmp, *last = NULL;
   int hash;
-  LIST *subjects = NULL, *oldlist;
-  time_t date = 0;  
+  string_list_t *subjects = NULL, *oldlist;
+  time_t date = 0;
 
   subjects = make_subject_list (cur, &date);
 
-  while (subjects)
-  {
+  while (subjects) {
     hash = hash_string ((unsigned char *) subjects->data,
-                       ctx->subj_hash->nelem);
-    for (ptr = ctx->subj_hash->table[hash]; ptr; ptr = ptr->next)
-    {
+                        ctx->subj_hash->nelem);
+    for (ptr = ctx->subj_hash->table[hash]; ptr; ptr = ptr->next) {
       tmp = ((HEADER *) ptr->data)->thread;
-      if (tmp != cur &&                           /* don't match the same message */
-         !tmp->fake_thread &&             /* don't match pseudo threads */
-         tmp->message->subject_changed && /* only match interesting replies */
-         !is_descendant (tmp, cur) &&     /* don't match in the same thread */
-         (date >= (option (OPTTHREADRECEIVED) ?
-                   tmp->message->received :
-                   tmp->message->date_sent)) &&
-         (!last ||
-          (option (OPTTHREADRECEIVED) ?
-           (last->message->received < tmp->message->received) :
-           (last->message->date_sent < tmp->message->date_sent))) &&
-         tmp->message->env->real_subj &&
-         mutt_strcmp (subjects->data, tmp->message->env->real_subj) == 0)
-       last = tmp; /* best match so far */
+      if (tmp != cur &&         /* don't match the same message */
+          !tmp->fake_thread &&  /* don't match pseudo threads */
+          tmp->message->subject_changed &&      /* only match interesting replies */
+          !is_descendant (tmp, cur) &&  /* don't match in the same thread */
+          (date >= (option (OPTTHREADRECEIVED) ?
+                    tmp->message->received :
+                    tmp->message->date_sent)) &&
+          (!last ||
+           (option (OPTTHREADRECEIVED) ?
+            (last->message->received < tmp->message->received) :
+            (last->message->date_sent < tmp->message->date_sent))) &&
+          tmp->message->env->real_subj &&
+          m_strcmp(subjects->data, tmp->message->env->real_subj) == 0)
+        last = tmp;             /* best match so far */
     }
 
     oldlist = subjects;
     subjects = subjects->next;
-    FREE (&oldlist);
+    p_delete(&oldlist);
   }
   return (last);
 }
@@ -447,7 +405,7 @@ static THREAD *find_subject (CONTEXT *ctx, THREAD *cur)
 /* remove cur and its descendants from their current location.
  * also make sure ancestors of cur no longer are sorted by the
  * fact that cur is their descendant. */
-static void unlink_message (THREAD **old, THREAD *cur)
+static void unlink_message (THREAD ** old, THREAD * cur)
 {
   THREAD *tmp;
 
@@ -459,16 +417,15 @@ static void unlink_message (THREAD **old, THREAD *cur)
   if (cur->next)
     cur->next->prev = cur->prev;
 
-  if (cur->sort_key)
-  {
+  if (cur->sort_key) {
     for (tmp = cur->parent; tmp && tmp->sort_key == cur->sort_key;
-        tmp = tmp->parent)
+         tmp = tmp->parent)
       tmp->sort_key = NULL;
   }
 }
 
 /* add cur as a prior sibling of *new, with parent newparent */
-static void insert_message (THREAD **new, THREAD *newparent, THREAD *cur)
+static void insert_message (THREAD ** new, THREAD * newparent, THREAD * cur)
 {
   if (*new)
     (*new)->prev = cur;
@@ -480,7 +437,7 @@ static void insert_message (THREAD **new, THREAD *newparent, THREAD *cur)
 }
 
 /* thread by subject things that didn't get threaded by message-id */
-static void pseudo_threads (CONTEXT *ctx)
+static void pseudo_threads (CONTEXT * ctx)
 {
   THREAD *tree = ctx->tree, *top = tree;
   THREAD *tmp, *cur, *parent, *curchild, *nextchild;
@@ -488,52 +445,45 @@ static void pseudo_threads (CONTEXT *ctx)
   if (!ctx->subj_hash)
     ctx->subj_hash = mutt_make_subj_hash (ctx);
 
-  while (tree)
-  {
+  while (tree) {
     cur = tree;
     tree = tree->next;
-    if ((parent = find_subject (ctx, cur)) != NULL)
-    {
+    if ((parent = find_subject (ctx, cur)) != NULL) {
       cur->fake_thread = 1;
       unlink_message (&top, cur);
       insert_message (&parent->child, parent, cur);
       parent->sort_children = 1;
       tmp = cur;
-      FOREVER
-      {
-       while (!tmp->message)
-         tmp = tmp->child;
-
-       /* if the message we're attaching has pseudo-children, they
-        * need to be attached to its parent, so move them up a level.
-        * but only do this if they have the same real subject as the
-        * parent, since otherwise they rightly belong to the message
-        * we're attaching. */
-       if (tmp == cur
-           || !mutt_strcmp (tmp->message->env->real_subj,
-                            parent->message->env->real_subj))
-       {
-         tmp->message->subject_changed = 0;
-
-         for (curchild = tmp->child; curchild; )
-         {
-           nextchild = curchild->next;
-           if (curchild->fake_thread)
-           {
-             unlink_message (&tmp->child, curchild);
-             insert_message (&parent->child, parent, curchild);
-           }
-           curchild = nextchild;
-         }
-       }
-
-       while (!tmp->next && tmp != cur)
-       {
-         tmp = tmp->parent;
-       }
-       if (tmp == cur)
-         break;
-       tmp = tmp->next;
+      for (;;) {
+        while (!tmp->message)
+          tmp = tmp->child;
+
+        /* if the message we're attaching has pseudo-children, they
+         * need to be attached to its parent, so move them up a level.
+         * but only do this if they have the same real subject as the
+         * parent, since otherwise they rightly belong to the message
+         * we're attaching. */
+        if (tmp == cur
+            || !m_strcmp(tmp->message->env->real_subj,
+                             parent->message->env->real_subj)) {
+          tmp->message->subject_changed = 0;
+
+          for (curchild = tmp->child; curchild;) {
+            nextchild = curchild->next;
+            if (curchild->fake_thread) {
+              unlink_message (&tmp->child, curchild);
+              insert_message (&parent->child, parent, curchild);
+            }
+            curchild = nextchild;
+          }
+        }
+
+        while (!tmp->next && tmp != cur) {
+          tmp = tmp->parent;
+        }
+        if (tmp == cur)
+          break;
+        tmp = tmp->next;
       }
     }
   }
@@ -541,45 +491,43 @@ static void pseudo_threads (CONTEXT *ctx)
 }
 
 
-void mutt_clear_threads (CONTEXT *ctx)
+void mutt_clear_threads (CONTEXT * ctx)
 {
   int i;
 
-  for (i = 0; i < ctx->msgcount; i++)
-  {
+  for (i = 0; i < ctx->msgcount; i++) {
     ctx->hdrs[i]->thread = NULL;
     ctx->hdrs[i]->threaded = 0;
   }
   ctx->tree = NULL;
 
   if (ctx->thread_hash)
-    hash_destroy (&ctx->thread_hash, *free);
+    hash_destroy (&ctx->thread_hash, free);
 }
 
-int compare_threads (const void *a, const void *b)
+static int compare_threads (const void *a, const void *b)
 {
   static sort_t *sort_func = NULL;
 
   if (a || b)
     return ((*sort_func) (&(*((THREAD **) a))->sort_key,
-                         &(*((THREAD **) b))->sort_key));
+                          &(*((THREAD **) b))->sort_key));
   /* a hack to let us reset sort_func even though we can't
    * have extra arguments because of qsort
    */
-  else
-  {
+  else {
     sort_func = NULL;
     sort_func = mutt_get_sort_func (Sort);
     return (sort_func ? 1 : 0);
   }
 }
 
-THREAD *mutt_sort_subthreads (THREAD *thread, int init)
+THREAD *mutt_sort_subthreads (THREAD * thread, int init)
 {
   THREAD **array, *sort_key, *top, *tmp;
   HEADER *oldsort_key;
   int i, array_size, sort_top = 0;
-  
+
   /* we put things into the array backwards to save some cycles,
    * but we want to have to move less stuff around if we're 
    * resorting, so we sort backwards and then put them back
@@ -591,112 +539,100 @@ THREAD *mutt_sort_subthreads (THREAD *thread, int init)
 
   top = thread;
 
-  array = safe_calloc ((array_size = 256), sizeof (THREAD *));
-  while (1)
-  {
-    if (init || !thread->sort_key)
-    {
+  array = p_new(THREAD *, (array_size = 256));
+  while (1) {
+    if (init || !thread->sort_key) {
       thread->sort_key = NULL;
 
       if (thread->parent)
         thread->parent->sort_children = 1;
       else
-       sort_top = 1;
+        sort_top = 1;
     }
 
-    if (thread->child)
-    {
+    if (thread->child) {
       thread = thread->child;
       continue;
     }
-    else
-    {
+    else {
       /* if it has no children, it must be real. sort it on its own merits */
       thread->sort_key = thread->message;
 
-      if (thread->next)
-      {
-       thread = thread->next;
-       continue;
+      if (thread->next) {
+        thread = thread->next;
+        continue;
       }
     }
 
-    while (!thread->next)
-    {
+    while (!thread->next) {
       /* if it has siblings and needs to be sorted, sort it... */
-      if (thread->prev && (thread->parent ? thread->parent->sort_children : sort_top))
-      {
-       /* put them into the array */
-       for (i = 0; thread; i++, thread = thread->prev)
-       {
-         if (i >= array_size)
-           safe_realloc (&array, (array_size *= 2) * sizeof (THREAD *));
-
-         array[i] = thread;
-       }
-
-       qsort ((void *) array, i, sizeof (THREAD *), *compare_threads);
-
-       /* attach them back together.  make thread the last sibling. */
-       thread = array[0];
-       thread->next = NULL;
-       array[i - 1]->prev = NULL;
-
-       if (thread->parent)
-         thread->parent->child = array[i - 1];
-       else
-         top = array[i - 1];
-
-       while (--i)
-       {
-         array[i - 1]->prev = array[i];
-         array[i]->next = array[i - 1];
-       }
+      if (thread->prev
+          && (thread->parent ? thread->parent->sort_children : sort_top)) {
+        /* put them into the array */
+        for (i = 0; thread; i++, thread = thread->prev) {
+          if (i >= array_size)
+            p_realloc(&array, array_size *= 2);
+
+          array[i] = thread;
+        }
+
+        qsort ((void *) array, i, sizeof (THREAD *), compare_threads);
+
+        /* attach them back together.  make thread the last sibling. */
+        thread = array[0];
+        thread->next = NULL;
+        array[i - 1]->prev = NULL;
+
+        if (thread->parent)
+          thread->parent->child = array[i - 1];
+        else
+          top = array[i - 1];
+
+        while (--i) {
+          array[i - 1]->prev = array[i];
+          array[i]->next = array[i - 1];
+        }
       }
 
-      if (thread->parent)
-      {
-       tmp = thread;
-       thread = thread->parent;
-
-       if (!thread->sort_key || thread->sort_children)
-       {
-         /* make sort_key the first or last sibling, as appropriate */
-         sort_key = (!(Sort & SORT_LAST) ^ !(Sort & SORT_REVERSE)) ? thread->child : tmp;
-
-         /* we just sorted its children */
-         thread->sort_children = 0;
-
-         oldsort_key = thread->sort_key;
-         thread->sort_key = thread->message;
-
-         if (Sort & SORT_LAST)
-         {
-           if (!thread->sort_key
-               || ((((Sort & SORT_REVERSE) ? 1 : -1)
-                    * compare_threads ((void *) &thread,
-                                       (void *) &sort_key))
-                   > 0))
-             thread->sort_key = sort_key->sort_key;
-         }
-         else if (!thread->sort_key)
-           thread->sort_key = sort_key->sort_key;
-
-         /* if its sort_key has changed, we need to resort it and siblings */
-         if (oldsort_key != thread->sort_key)
-         {
-           if (thread->parent)
-             thread->parent->sort_children = 1;
-           else
-             sort_top = 1;
-         }
-       }
+      if (thread->parent) {
+        tmp = thread;
+        thread = thread->parent;
+
+        if (!thread->sort_key || thread->sort_children) {
+          /* make sort_key the first or last sibling, as appropriate */
+          sort_key =
+            (!(Sort & SORT_LAST) ^ !(Sort & SORT_REVERSE)) ? thread->
+            child : tmp;
+
+          /* we just sorted its children */
+          thread->sort_children = 0;
+
+          oldsort_key = thread->sort_key;
+          thread->sort_key = thread->message;
+
+          if (Sort & SORT_LAST) {
+            if (!thread->sort_key || ((((Sort & SORT_REVERSE) ? 1 : -1)
+                                       * compare_threads ((void *) &thread,
+                                                          (void *) &sort_key))
+                                      > 0))
+              thread->sort_key = sort_key->sort_key;
+          }
+          else if (!thread->sort_key)
+            thread->sort_key = sort_key->sort_key;
+
+          /* if its sort_key has changed, we need to resort it and siblings */
+          if (oldsort_key != thread->sort_key) {
+            if (thread->parent)
+              thread->parent->sort_children = 1;
+            else
+              sort_top = 1;
+          }
+        }
       }
-      else
-      {
-       Sort ^= SORT_REVERSE;
-       FREE (&array);
-       return (top);
+      else {
+        Sort ^= SORT_REVERSE;
+        p_delete(&array);
+        return (top);
       }
     }
 
@@ -704,14 +640,13 @@ THREAD *mutt_sort_subthreads (THREAD *thread, int init)
   }
 }
 
-static void check_subjects (CONTEXT *ctx, int init)
+static void check_subjects (CONTEXT * ctx, int init)
 {
   HEADER *cur;
   THREAD *tmp;
   int i;
 
-  for (i = 0; i < ctx->msgcount; i++)
-  {
+  for (i = 0; i < ctx->msgcount; i++) {
     cur = ctx->hdrs[i];
     if (cur->thread->check_subject)
       cur->thread->check_subject = 0;
@@ -720,36 +655,36 @@ static void check_subjects (CONTEXT *ctx, int init)
 
     /* figure out which messages have subjects different than their parents' */
     tmp = cur->thread->parent;
-    while (tmp && !tmp->message)
-    {
+    while (tmp && !tmp->message) {
       tmp = tmp->parent;
     }
 
     if (!tmp)
       cur->subject_changed = 1;
     else if (cur->env->real_subj && tmp->message->env->real_subj)
-      cur->subject_changed = mutt_strcmp (cur->env->real_subj,
-                                         tmp->message->env->real_subj) ? 1 : 0;
+      cur->subject_changed = m_strcmp(cur->env->real_subj,
+                                          tmp->message->env->
+                                          real_subj) ? 1 : 0;
     else
       cur->subject_changed = (cur->env->real_subj
-                             || tmp->message->env->real_subj) ? 1 : 0;
+                              || tmp->message->env->real_subj) ? 1 : 0;
   }
 }
 
-void mutt_sort_threads (CONTEXT *ctx, int init)
+void mutt_sort_threads (CONTEXT * ctx, int init)
 {
   HEADER *cur;
   int i, oldsort, using_refs = 0;
   THREAD *thread, *new, *tmp, top;
-  LIST *ref = NULL;
-  
+  string_list_t *ref = NULL;
+
   /* set Sort to the secondary method to support the set sort_aux=reverse-*
    * settings.  The sorting functions just look at the value of
    * SORT_REVERSE
    */
   oldsort = Sort;
   Sort = SortAux;
-  
+
   if (!ctx->thread_hash)
     init = 1;
 
@@ -768,101 +703,89 @@ void mutt_sort_threads (CONTEXT *ctx, int init)
    * exists.  otherwise, if there is a THREAD that already has a message, thread
    * new message as an identical child.  if we didn't attach the message to a
    * THREAD, make a new one for it. */
-  for (i = 0; i < ctx->msgcount; i++)
-  {
+  for (i = 0; i < ctx->msgcount; i++) {
     cur = ctx->hdrs[i];
 
-    if (!cur->thread)
-    {
+    if (!cur->thread) {
       if ((!init || option (OPTDUPTHREADS)) && cur->env->message_id)
-       thread = hash_find (ctx->thread_hash, cur->env->message_id);
+        thread = hash_find (ctx->thread_hash, cur->env->message_id);
       else
-       thread = NULL;
-
-      if (thread && !thread->message)
-      {
-       /* this is a message which was missing before */
-       thread->message = cur;
-       cur->thread = thread;
-       thread->check_subject = 1;
-
-       /* mark descendants as needing subject_changed checked */
-       for (tmp = (thread->child ? thread->child : thread); tmp != thread; )
-       {
-         while (!tmp->message)
-           tmp = tmp->child;
-         tmp->check_subject = 1;
-         while (!tmp->next && tmp != thread)
-           tmp = tmp->parent;
-         if (tmp != thread)
-           tmp = tmp->next;
-       }
-
-       if (thread->parent)
-       {
-         /* remove threading info above it based on its children, which we'll
-          * recalculate based on its headers.  make sure not to leave
-          * dangling missing messages.  note that we haven't kept track
-          * of what info came from its children and what from its siblings'
-          * children, so we just remove the stuff that's definitely from it */
-         do
-         {
-           tmp = thread->parent;
-           unlink_message (&tmp->child, thread);
-           thread->parent = NULL;
-           thread->sort_key = NULL;
-           thread->fake_thread = 0;
-           thread = tmp;
-         } while (thread != &top && !thread->child && !thread->message);
-       }
+        thread = NULL;
+
+      if (thread && !thread->message) {
+        /* this is a message which was missing before */
+        thread->message = cur;
+        cur->thread = thread;
+        thread->check_subject = 1;
+
+        /* mark descendants as needing subject_changed checked */
+        for (tmp = (thread->child ? thread->child : thread); tmp != thread;) {
+          while (!tmp->message)
+            tmp = tmp->child;
+          tmp->check_subject = 1;
+          while (!tmp->next && tmp != thread)
+            tmp = tmp->parent;
+          if (tmp != thread)
+            tmp = tmp->next;
+        }
+
+        if (thread->parent) {
+          /* remove threading info above it based on its children, which we'll
+           * recalculate based on its headers.  make sure not to leave
+           * dangling missing messages.  note that we haven't kept track
+           * of what info came from its children and what from its siblings'
+           * children, so we just remove the stuff that's definitely from it */
+          do {
+            tmp = thread->parent;
+            unlink_message (&tmp->child, thread);
+            thread->parent = NULL;
+            thread->sort_key = NULL;
+            thread->fake_thread = 0;
+            thread = tmp;
+          } while (thread != &top && !thread->child && !thread->message);
+        }
       }
-      else
-      {
-       new = (option (OPTDUPTHREADS) ? thread : NULL);
-
-       thread = safe_calloc (1, sizeof (THREAD));
-       thread->message = cur;
-       thread->check_subject = 1;
-       cur->thread = thread;
-       hash_insert (ctx->thread_hash,
-                    cur->env->message_id ? cur->env->message_id : "",
-                    thread, 1);
-
-       if (new)
-       {
-         if (new->duplicate_thread)
-           new = new->parent;
-
-         thread = cur->thread;
-
-         insert_message (&new->child, new, thread);
-         thread->duplicate_thread = 1;
-         thread->message->threaded = 1;
-       }
+      else {
+        new = (option (OPTDUPTHREADS) ? thread : NULL);
+
+        thread = p_new(THREAD, 1);
+        thread->message = cur;
+        thread->check_subject = 1;
+        cur->thread = thread;
+        hash_insert (ctx->thread_hash,
+                     cur->env->message_id ? cur->env->message_id : "",
+                     thread, 1);
+
+        if (new) {
+          if (new->duplicate_thread)
+            new = new->parent;
+
+          thread = cur->thread;
+
+          insert_message (&new->child, new, thread);
+          thread->duplicate_thread = 1;
+          thread->message->threaded = 1;
+        }
       }
     }
-    else
-    {
+    else {
       /* unlink pseudo-threads because they might be children of newly
        * arrived messages */
       thread = cur->thread;
-      for (new = thread->child; new; )
-      {
-       tmp = new->next;
-       if (new->fake_thread)
-       {
-         unlink_message (&thread->child, new);
-         insert_message (&top.child, &top, new);
-         new->fake_thread = 0;
-       }
-       new = tmp;
+      for (new = thread->child; new;) {
+        tmp = new->next;
+        if (new->fake_thread) {
+          unlink_message (&thread->child, new);
+          insert_message (&top.child, &top, new);
+          new->fake_thread = 0;
+        }
+        new = tmp;
       }
     }
   }
 
   /* thread by references */
-  for (i = 0; i < ctx->msgcount; i++)
-  {
+  for (i = 0; i < ctx->msgcount; i++) {
     cur = ctx->hdrs[i];
     if (cur->threaded)
       continue;
@@ -871,64 +794,57 @@ void mutt_sort_threads (CONTEXT *ctx, int init)
     thread = cur->thread;
     using_refs = 0;
 
-    while (1)
-    {
-      if (using_refs == 0)
-      {
-       /* look at the beginning of in-reply-to: */
-       if ((ref = cur->env->in_reply_to) != NULL)
-         using_refs = 1;
-       else
-       {
-         ref = cur->env->references;
-         using_refs = 2;
-       }
+    while (1) {
+      if (using_refs == 0) {
+        /* look at the beginning of in-reply-to: */
+        if ((ref = cur->env->in_reply_to) != NULL)
+          using_refs = 1;
+        else {
+          ref = cur->env->references;
+          using_refs = 2;
+        }
       }
-      else if (using_refs == 1)
-      {
-       /* if there's no references header, use all the in-reply-to:
-        * data that we have.  otherwise, use the first reference
-        * if it's different than the first in-reply-to, otherwise use
-        * the second reference (since at least eudora puts the most
-        * recent reference in in-reply-to and the rest in references)
-        */
-       if (!cur->env->references)
-         ref = ref->next;
-       else
-       {
-         if (mutt_strcmp (ref->data, cur->env->references->data))
-           ref = cur->env->references;
-         else
-           ref = cur->env->references->next;
-         
-         using_refs = 2;
-       }
+      else if (using_refs == 1) {
+        /* if there's no references header, use all the in-reply-to:
+         * data that we have.  otherwise, use the first reference
+         * if it's different than the first in-reply-to, otherwise use
+         * the second reference (since at least eudora puts the most
+         * recent reference in in-reply-to and the rest in references)
+         */
+        if (!cur->env->references)
+          ref = ref->next;
+        else {
+          if (m_strcmp(ref->data, cur->env->references->data))
+            ref = cur->env->references;
+          else
+            ref = cur->env->references->next;
+
+          using_refs = 2;
+        }
       }
       else
-       ref = ref->next; /* go on with references */
-      
+        ref = ref->next;        /* go on with references */
+
       if (!ref)
-       break;
+        break;
 
-      if ((new = hash_find (ctx->thread_hash, ref->data)) == NULL)
-      {
-       new = safe_calloc (1, sizeof (THREAD));
-       hash_insert (ctx->thread_hash, ref->data, new, 1);
+      if ((new = hash_find (ctx->thread_hash, ref->data)) == NULL) {
+        new = p_new(THREAD, 1);
+        hash_insert (ctx->thread_hash, ref->data, new, 1);
       }
-      else
-      {
-       if (new->duplicate_thread)
-         new = new->parent;
-       if (is_descendant (new, thread)) /* no loops! */
-         break;
+      else {
+        if (new->duplicate_thread)
+          new = new->parent;
+        if (is_descendant (new, thread))        /* no loops! */
+          continue;
       }
 
       if (thread->parent)
-       unlink_message (&top.child, thread);
+        unlink_message (&top.child, thread);
       insert_message (&new->child, new, thread);
       thread = new;
       if (thread->message || (thread->parent && thread->parent != &top))
-       break;
+        break;
     }
 
     if (!thread->parent)
@@ -936,8 +852,7 @@ void mutt_sort_threads (CONTEXT *ctx, int init)
   }
 
   /* detach everything from the temporary top node */
-  for (thread = top.child; thread; thread = thread->next)
-  {
+  for (thread = top.child; thread; thread = thread->next) {
     thread->parent = NULL;
   }
   ctx->tree = top.child;
@@ -947,13 +862,12 @@ void mutt_sort_threads (CONTEXT *ctx, int init)
   if (!option (OPTSTRICTTHREADS))
     pseudo_threads (ctx);
 
-  if (ctx->tree)
-  {
+  if (ctx->tree) {
     ctx->tree = mutt_sort_subthreads (ctx->tree, init);
 
     /* restore the oldsort order. */
     Sort = oldsort;
-    
+
     /* Put the list into an array. */
     linearize_tree (ctx);
 
@@ -962,7 +876,7 @@ void mutt_sort_threads (CONTEXT *ctx, int init)
   }
 }
 
-static HEADER *find_virtual (THREAD *cur, int reverse)
+static HEADER *find_virtual (THREAD * cur, int reverse)
 {
   THREAD *top;
 
@@ -976,27 +890,23 @@ static HEADER *find_virtual (THREAD *cur, int reverse)
   while (reverse && cur->next)
     cur = cur->next;
 
-  FOREVER
-  {
+  for (;;) {
     if (cur->message && cur->message->virtual >= 0)
       return (cur->message);
 
-    if (cur->child)
-    {
+    if (cur->child) {
       cur = cur->child;
 
       while (reverse && cur->next)
-       cur = cur->next;
+        cur = cur->next;
     }
     else if (reverse ? cur->prev : cur->next)
       cur = reverse ? cur->prev : cur->next;
-    else
-    {
-      while (!(reverse ? cur->prev : cur->next))
-      {
-       cur = cur->parent;
-       if (cur == top)
-         return (NULL);
+    else {
+      while (!(reverse ? cur->prev : cur->next)) {
+        cur = cur->parent;
+        if (cur == top)
+          return (NULL);
       }
       cur = reverse ? cur->prev : cur->next;
     }
@@ -1004,55 +914,47 @@ static HEADER *find_virtual (THREAD *cur, int reverse)
   }
 }
 
-int _mutt_aside_thread (HEADER *hdr, short dir, short subthreads)
+int _mutt_aside_thread (HEADER * hdr, short dir, short subthreads)
 {
   THREAD *cur;
   HEADER *tmp;
 
-  if ((Sort & SORT_MASK) != SORT_THREADS)
-  {
+  if ((Sort & SORT_MASK) != SORT_THREADS) {
     mutt_error _("Threading is not enabled.");
+
     return (hdr->virtual);
   }
 
   cur = hdr->thread;
 
-  if (!subthreads)
-  {
+  if (!subthreads) {
     while (cur->parent)
       cur = cur->parent;
   }
-  else
-  {
-    if ((dir != 0) ^ ((Sort & SORT_REVERSE) != 0))
-    {
+  else {
+    if ((dir != 0) ^ ((Sort & SORT_REVERSE) != 0)) {
       while (!cur->next && cur->parent)
-       cur = cur->parent;
+        cur = cur->parent;
     }
-    else
-    {
+    else {
       while (!cur->prev && cur->parent)
-       cur = cur->parent;
+        cur = cur->parent;
     }
   }
 
-  if ((dir != 0) ^ ((Sort & SORT_REVERSE) != 0))
-  {
-    do
-    { 
+  if ((dir != 0) ^ ((Sort & SORT_REVERSE) != 0)) {
+    do {
       cur = cur->next;
       if (!cur)
-       return (-1);
+        return (-1);
       tmp = find_virtual (cur, 0);
     } while (!tmp);
   }
-  else
-  {
-    do
-    { 
+  else {
+    do {
       cur = cur->prev;
       if (!cur)
-       return (-1);
+        return (-1);
       tmp = find_virtual (cur, 1);
     } while (!tmp);
   }
@@ -1060,35 +962,34 @@ int _mutt_aside_thread (HEADER *hdr, short dir, short subthreads)
   return (tmp->virtual);
 }
 
-int mutt_parent_message (CONTEXT *ctx, HEADER *hdr)
+int mutt_parent_message (CONTEXT * ctx, HEADER * hdr)
 {
   THREAD *thread;
 
-  if ((Sort & SORT_MASK) != SORT_THREADS)
-  {
+  if ((Sort & SORT_MASK) != SORT_THREADS) {
     mutt_error _("Threading is not enabled.");
+
     return (hdr->virtual);
   }
 
-  for (thread = hdr->thread->parent; thread; thread = thread->parent)
-  {
-    if ((hdr = thread->message) != NULL)
-    {
+  for (thread = hdr->thread->parent; thread; thread = thread->parent) {
+    if ((hdr = thread->message) != NULL) {
       if (VISIBLE (hdr, ctx))
-       return (hdr->virtual);
-      else
-      {
-       mutt_error _("Parent message is not visible in this limited view.");
-       return (-1);
+        return (hdr->virtual);
+      else {
+        mutt_error _("Parent message is not visible in this limited view.");
+
+        return (-1);
       }
     }
   }
-  
+
   mutt_error _("Parent message is not available.");
+
   return (-1);
 }
 
-void mutt_set_virtual (CONTEXT *ctx)
+void mutt_set_virtual (CONTEXT * ctx)
 {
   int i;
   HEADER *cur;
@@ -1096,31 +997,31 @@ void mutt_set_virtual (CONTEXT *ctx)
   ctx->vcount = 0;
   ctx->vsize = 0;
 
-  for (i = 0; i < ctx->msgcount; i++)
-  {
+  for (i = 0; i < ctx->msgcount; i++) {
     cur = ctx->hdrs[i];
-    if (cur->virtual >= 0)
-    {
+    if (cur->virtual >= 0) {
       cur->virtual = ctx->vcount;
       ctx->v2r[ctx->vcount] = i;
       ctx->vcount++;
-      ctx->vsize += cur->content->length + cur->content->offset - cur->content->hdr_offset;
+      ctx->vsize +=
+        cur->content->length + cur->content->offset -
+        cur->content->hdr_offset;
       cur->num_hidden = mutt_get_hidden (ctx, cur);
     }
   }
 }
 
-int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, int flag)
+int _mutt_traverse_thread (CONTEXT * ctx, HEADER * cur, int flag)
 {
   THREAD *thread, *top;
   HEADER *roothdr = NULL;
   int final, reverse = (Sort & SORT_REVERSE), minmsgno;
   int num_hidden = 0, new = 0, old = 0;
   int min_unread_msgno = INT_MAX, min_unread = cur->virtual;
+
 #define CHECK_LIMIT (!ctx->pattern || cur->limited)
 
-  if ((Sort & SORT_MASK) != SORT_THREADS && !(flag & M_THREAD_GET_HIDDEN))
-  {
+  if ((Sort & SORT_MASK) != SORT_THREADS && !(flag & M_THREAD_GET_HIDDEN)) {
     mutt_error (_("Threading is not enabled."));
     return (cur->virtual);
   }
@@ -1135,14 +1036,12 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, int flag)
   cur = thread->message;
   minmsgno = cur->msgno;
 
-  if (!cur->read && CHECK_LIMIT)
-  {
+  if (!cur->read && CHECK_LIMIT) {
     if (cur->old)
       old = 2;
     else
       new = 1;
-    if (cur->msgno < min_unread_msgno)
-    {
+    if (cur->msgno < min_unread_msgno) {
       min_unread = cur->virtual;
       min_unread_msgno = cur->msgno;
     }
@@ -1151,20 +1050,17 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, int flag)
   if (cur->virtual == -1 && CHECK_LIMIT)
     num_hidden++;
 
-  if (flag & (M_THREAD_COLLAPSE | M_THREAD_UNCOLLAPSE))
-  {
-    cur->pair = 0; /* force index entry's color to be re-evaluated */
+  if (flag & (M_THREAD_COLLAPSE | M_THREAD_UNCOLLAPSE)) {
+    cur->pair = 0;              /* force index entry's color to be re-evaluated */
     cur->collapsed = flag & M_THREAD_COLLAPSE;
-    if (cur->virtual != -1)
-    {
+    if (cur->virtual != -1) {
       roothdr = cur;
       if (flag & M_THREAD_COLLAPSE)
-       final = roothdr->virtual;
+        final = roothdr->virtual;
     }
   }
 
-  if (thread == top && (thread = thread->child) == NULL)
-  {
+  if (thread == top && (thread = thread->child) == NULL) {
     /* return value depends on action requested */
     if (flag & (M_THREAD_COLLAPSE | M_THREAD_UNCOLLAPSE))
       return (final);
@@ -1175,78 +1071,68 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, int flag)
     else if (flag & M_THREAD_NEXT_UNREAD)
       return (min_unread);
   }
-  
-  FOREVER
-  {
+
+  for (;;) {
     cur = thread->message;
 
-    if (cur)
-    {
-      if (flag & (M_THREAD_COLLAPSE | M_THREAD_UNCOLLAPSE))
-      {
-       cur->pair = 0; /* force index entry's color to be re-evaluated */
-       cur->collapsed = flag & M_THREAD_COLLAPSE;
-       if (!roothdr && CHECK_LIMIT)
-       {
-         roothdr = cur;
-         if (flag & M_THREAD_COLLAPSE)
-           final = roothdr->virtual;
-       }
-
-       if (reverse && (flag & M_THREAD_COLLAPSE) && (cur->msgno < minmsgno) && CHECK_LIMIT)
-       {
-         minmsgno = cur->msgno;
-         final = cur->virtual;
-       }
-
-       if (flag & M_THREAD_COLLAPSE)
-       {
-         if (cur != roothdr)
-           cur->virtual = -1;
-       }
-       else 
-       {
-         if (CHECK_LIMIT)
-           cur->virtual = cur->msgno;
-       }
+    if (cur) {
+      if (flag & (M_THREAD_COLLAPSE | M_THREAD_UNCOLLAPSE)) {
+        cur->pair = 0;          /* force index entry's color to be re-evaluated */
+        cur->collapsed = flag & M_THREAD_COLLAPSE;
+        if (!roothdr && CHECK_LIMIT) {
+          roothdr = cur;
+          if (flag & M_THREAD_COLLAPSE)
+            final = roothdr->virtual;
+        }
+
+        if (reverse && (flag & M_THREAD_COLLAPSE) && (cur->msgno < minmsgno)
+            && CHECK_LIMIT) {
+          minmsgno = cur->msgno;
+          final = cur->virtual;
+        }
+
+        if (flag & M_THREAD_COLLAPSE) {
+          if (cur != roothdr)
+            cur->virtual = -1;
+        }
+        else {
+          if (CHECK_LIMIT)
+            cur->virtual = cur->msgno;
+        }
       }
 
 
-      if (!cur->read && CHECK_LIMIT)
-      {
-       if (cur->old)
-         old = 2;
-       else
-         new = 1;
-       if (cur->msgno < min_unread_msgno)
-       {
-         min_unread = cur->virtual;
-         min_unread_msgno = cur->msgno;
-       }
+      if (!cur->read && CHECK_LIMIT) {
+        if (cur->old)
+          old = 2;
+        else
+          new = 1;
+        if (cur->msgno < min_unread_msgno) {
+          min_unread = cur->virtual;
+          min_unread_msgno = cur->msgno;
+        }
       }
 
       if (cur->virtual == -1 && CHECK_LIMIT)
-       num_hidden++;
+        num_hidden++;
     }
 
     if (thread->child)
       thread = thread->child;
     else if (thread->next)
       thread = thread->next;
-    else
-    {
+    else {
       int done = 0;
-      while (!thread->next)
-      {
-       thread = thread->parent;
-       if (thread == top)
-       {
-         done = 1;
-         break;
-       }
+
+      while (!thread->next) {
+        thread = thread->parent;
+        if (thread == top) {
+          done = 1;
+          break;
+        }
       }
       if (done)
-       break;
+        break;
       thread = thread->next;
     }
   }
@@ -1257,7 +1143,7 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, int flag)
   else if (flag & M_THREAD_UNREAD)
     return ((old && new) ? new : (old ? old : new));
   else if (flag & M_THREAD_GET_HIDDEN)
-    return (num_hidden+1);
+    return (num_hidden + 1);
   else if (flag & M_THREAD_NEXT_UNREAD)
     return (min_unread);
 
@@ -1269,7 +1155,7 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, int flag)
 /* if flag is 0, we want to know how many messages
  * are in the thread.  if flag is 1, we want to know
  * our position in the thread. */
-int mutt_messages_in_thread (CONTEXT *ctx, HEADER *hdr, int flag)
+int mutt_messages_in_thread (CONTEXT * ctx, HEADER * hdr, int flag)
 {
   THREAD *threads[2];
   int i, rc;
@@ -1283,25 +1169,28 @@ int mutt_messages_in_thread (CONTEXT *ctx, HEADER *hdr, int flag)
 
   threads[1] = flag ? hdr->thread : threads[0]->next;
 
-  for (i = 0; i < ((flag || !threads[1]) ? 1 : 2); i++)
-  {
+  for (i = 0; i < ((flag || !threads[1]) ? 1 : 2); i++) {
     while (!threads[i]->message)
       threads[i] = threads[i]->child;
-  } 
+  }
 
   if (Sort & SORT_REVERSE)
-    rc = threads[0]->message->msgno - (threads[1] ? threads[1]->message->msgno : -1);
+    rc =
+      threads[0]->message->msgno -
+      (threads[1] ? threads[1]->message->msgno : -1);
   else
-    rc = (threads[1] ? threads[1]->message->msgno : ctx->msgcount) - threads[0]->message->msgno;
-  
+    rc =
+      (threads[1] ? threads[1]->message->msgno : ctx->msgcount) -
+      threads[0]->message->msgno;
+
   if (flag)
     rc += 1;
-  
+
   return (rc);
 }
 
 
-HASH *mutt_make_id_hash (CONTEXT *ctx)
+HASH *mutt_make_id_hash (CONTEXT * ctx)
 {
   int i;
   HEADER *hdr;
@@ -1309,8 +1198,7 @@ HASH *mutt_make_id_hash (CONTEXT *ctx)
 
   hash = hash_create (ctx->msgcount * 2);
 
-  for (i = 0; i < ctx->msgcount; i++)
-  {
+  for (i = 0; i < ctx->msgcount; i++) {
     hdr = ctx->hdrs[i];
     if (hdr->env->message_id)
       hash_insert (hash, hdr->env->message_id, hdr, 0);
@@ -1319,7 +1207,7 @@ HASH *mutt_make_id_hash (CONTEXT *ctx)
   return hash;
 }
 
-HASH *mutt_make_subj_hash (CONTEXT *ctx)
+HASH *mutt_make_subj_hash (CONTEXT * ctx)
 {
   int i;
   HEADER *hdr;
@@ -1327,8 +1215,7 @@ HASH *mutt_make_subj_hash (CONTEXT *ctx)
 
   hash = hash_create (ctx->msgcount * 2);
 
-  for (i = 0; i < ctx->msgcount; i++)
-  {
+  for (i = 0; i < ctx->msgcount; i++) {
     hdr = ctx->hdrs[i];
     if (hdr->env->real_subj)
       hash_insert (hash, hdr->env->real_subj, hdr, 1);
@@ -1337,104 +1224,97 @@ HASH *mutt_make_subj_hash (CONTEXT *ctx)
   return hash;
 }
 
-static void clean_references (THREAD *brk, THREAD *cur)
+static void clean_references (THREAD * tbrk, THREAD * cur)
 {
   THREAD *p;
-  LIST *ref = NULL;
+  string_list_t *ref = NULL;
   int done = 0;
 
-  for (; cur; cur = cur->next, done = 0)
-  {
+  for (; cur; cur = cur->next, done = 0) {
     /* parse subthread recursively */
-    clean_references (brk, cur->child);
+    clean_references (tbrk, cur->child);
 
     if (!cur->message)
-      break; /* skip pseudo-message */
+      break;                    /* skip pseudo-message */
 
     /* Looking for the first bad reference according to the new threading.
      * Optimal since Mutt stores the references in reverse order, and the
      * first loop should match immediatly for mails respecting RFC2822. */
-    for (p = brk; !done && p; p = p->parent)
-      for (ref = cur->message->env->references; p->message && ref; ref = ref->next)
-       if (!mutt_strcasecmp (ref->data, p->message->env->message_id))
-       {
-         done = 1;
-         break;
-       }
-
-    if (done)
-    {
+    for (p = tbrk; !done && p; p = p->parent)
+      for (ref = cur->message->env->references; p->message && ref;
+           ref = ref->next)
+        if (!m_strcasecmp(ref->data, p->message->env->message_id)) {
+          done = 1;
+          break;
+        }
+
+    if (done) {
       HEADER *h = cur->message;
 
-      /* clearing the References: header from obsolete Message-Id(s) */
-      mutt_free_list (&ref->next);
+      /* clearing the References: header from obsolete Message-ID(s) */
+      string_list_wipe(&ref->next);
 
-#ifdef IMAP_EDIT_THREADS
-      if (h->new_env)
-       mutt_free_list (&h->new_env->references);
-      else
-       h->new_env = mutt_new_envelope ();
-
-      h->new_env->references = mutt_copy_list (h->env->references);
-#endif
-
-      h->refs_changed = h->changed = 1;
+      h->env->refs_changed = h->changed = 1;
     }
   }
 }
 
-void mutt_break_thread (HEADER *hdr)
+void mutt_break_thread (HEADER * hdr)
 {
-  mutt_free_list (&hdr->env->in_reply_to);
-  mutt_free_list (&hdr->env->references);
-  hdr->irt_changed = hdr->refs_changed = hdr->changed = 1;
-
-#ifdef IMAP_EDIT_THREADS
-  if (hdr->new_env)
-  {
-    mutt_free_list (&hdr->new_env->in_reply_to);
-    mutt_free_list (&hdr->new_env->references);
-  }
-  else
-    hdr->new_env = mutt_new_envelope ();
-#endif
-
+  string_list_wipe(&hdr->env->in_reply_to);
+  string_list_wipe(&hdr->env->references);
+  hdr->env->irt_changed = hdr->env->refs_changed = hdr->changed = 1;
   clean_references (hdr->thread, hdr->thread->child);
 }
 
-static int link_threads (HEADER *parent, HEADER *child, CONTEXT *ctx)
+static int link_threads (HEADER * parent, HEADER * child, CONTEXT * ctx)
 {
   if (child == parent)
     return 0;
 
   mutt_break_thread (child);
 
-  child->env->in_reply_to = mutt_new_list ();
-  child->env->in_reply_to->data = safe_strdup (parent->env->message_id);
+  child->env->in_reply_to = string_item_new();
+  child->env->in_reply_to->data = m_strdup(parent->env->message_id);
 
-#ifdef IMAP_EDIT_THREADS
-  child->new_env->in_reply_to = mutt_new_list ();
-  child->new_env->in_reply_to->data = safe_strdup (parent->env->message_id);
-#endif
-  
   mutt_set_flag (ctx, child, M_TAG, 0);
-  
-  child->irt_changed = child->changed = 1;
+
+  child->env->irt_changed = child->changed = 1;
   return 1;
 }
 
-int mutt_link_threads (HEADER *cur, HEADER *last, CONTEXT *ctx)
+int mutt_link_threads (HEADER * cur, HEADER * last, CONTEXT * ctx)
 {
   int i, changed = 0;
 
-  if (!last)
-  {
+  if (!last) {
     for (i = 0; i < ctx->vcount; i++)
       if (ctx->hdrs[Context->v2r[i]]->tagged)
-       changed |= link_threads (cur, ctx->hdrs[Context->v2r[i]], ctx);
+        changed |= link_threads (cur, ctx->hdrs[Context->v2r[i]], ctx);
   }
   else
     changed = link_threads (cur, last, ctx);
 
   return changed;
 }
+
+void mutt_adjust_subject (ENVELOPE* e) {
+  regmatch_t pmatch[1];
+
+  if (e && e->subject) {
+    if (regexec (ReplyRegexp.rx, e->subject, 1, pmatch, 0) == 0)
+      e->real_subj = e->subject + pmatch[0].rm_eo;
+    else
+      e->real_subj = e->subject;
+  }
+}
+
+void mutt_adjust_all_subjects (void) {
+  int i = 0;
+
+  if (!Context || !Context->msgcount)
+    return;
+
+  for (i = 0; i < Context->msgcount; i++)
+    mutt_adjust_subject (Context->hdrs[i]->env);
+}