diff -Nru a/PATCHES b/PATCHES
--- PATCHES
+++ PATCHES
@@ -0,0 +1 @@
+patch-1.5.6+20040904.tg.mutt-thread.3
diff -Nru a/mutt.h b/mutt.h
--- mutt.h	2004-07-24 12:27:21 +02:00
+++ mutt.h	2004-09-04 12:36:18 +02:00
@@ -211,6 +211,7 @@
   /* actions for mutt_pattern_comp/mutt_pattern_exec */
   M_AND,
   M_OR,
+  M_THREAD,
   M_TO,
   M_CC,
   M_COLLAPSED,
diff -Nru a/pattern.c b/pattern.c
--- pattern.c	2004-07-24 12:27:23 +02:00
+++ pattern.c	2004-09-04 12:37:52 +02:00
@@ -700,7 +700,7 @@
 pattern_t *mutt_pattern_comp (/* const */ char *s, int flags, BUFFER *err)
 {
   pattern_t *curlist = NULL;
-  pattern_t *tmp;
+  pattern_t *tmp, *tmp2;
   pattern_t *last = NULL;
   int not = 0;
   int alladdr = 0;
@@ -755,6 +755,39 @@
 	alladdr = 0;
 	break;
       case '~':
+	if (*(ps.dptr + 1) == '(') {
+		ps.dptr ++; /* skip ~ */
+		p = find_matching_paren (ps.dptr + 1);
+		if (*p != ')')
+		{
+		  snprintf (err->data, err->dsize, _("mismatched brackets: %s"), ps.dptr);
+		  mutt_pattern_free (&curlist);
+		  return NULL;
+		}
+		tmp = new_pattern ();
+		tmp->op = M_THREAD;
+		if (last)
+		  last->next = tmp;
+		else
+		  curlist = tmp;
+		last = tmp;
+		tmp->not ^= not;
+		tmp->alladdr |= alladdr;
+		not = 0;
+		alladdr = 0;
+		/* compile the sub-expression */
+		buf = mutt_substrdup (ps.dptr + 1, p);
+		if ((tmp2 = mutt_pattern_comp (buf, flags, err)) == NULL)
+		{
+		  FREE (&buf);
+		  mutt_pattern_free (&curlist);
+		  return NULL;
+		}
+		FREE (&buf);
+		tmp->child = tmp2;
+		ps.dptr = p + 1; /* restore location */
+		break;
+	}
 	if (implicit && or)
 	{
 	  /* A | B & C == (A | B) & C */
@@ -945,6 +978,29 @@
   return alladdr;
 }
 
+static int match_threadcomplete(struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, THREAD *t,int left,int up,int right,int down)
+{
+  int a;
+  HEADER *h;
+
+  if(!t)
+    return 0;
+  h = t->message;
+  if(h)
+    if(mutt_pattern_exec(pat, flags, ctx, h))
+      return 1;
+
+  if(up && (a=match_threadcomplete(pat, flags, ctx, t->parent,1,1,1,0)))
+    return a;
+  if(right && t->parent && (a=match_threadcomplete(pat, flags, ctx, t->next,0,0,1,1)))
+    return a;
+  if(left && t->parent && (a=match_threadcomplete(pat, flags, ctx, t->prev,1,0,0,1)))
+    return a;
+  if(down && (a=match_threadcomplete(pat, flags, ctx, t->child,1,0,1,1)))
+    return a;
+  return 0;
+}
+
 /* flags
    	M_MATCH_FULL_ADDRESS	match both personal and machine address */
 int
@@ -958,6 +1014,8 @@
       return (pat->not ^ (perform_and (pat->child, flags, ctx, h) > 0));
     case M_OR:
       return (pat->not ^ (perform_or (pat->child, flags, ctx, h) > 0));
+    case M_THREAD:
+      return (pat->not ^ match_threadcomplete(pat->child, flags, ctx, h->thread, 1, 1, 1, 1));
     case M_ALL:
       return (!pat->not);
     case M_EXPIRED:
--- mutt.h.orig2	Mon Sep  6 09:24:17 2004
+++ mutt.h	Mon Sep  6 09:27:04 2004
@@ -212,6 +212,7 @@
   M_LIMIT,
   M_EXPIRED,
   M_SUPERSEDED,
+  M_THREADCOMPLETE,
 
   /* actions for mutt_pattern_comp/mutt_pattern_exec */
   M_AND,
--- pattern.c.orig2	Sun Sep 18 15:17:46 2005
+++ pattern.c	Sun Sep 18 15:19:48 2005
@@ -54,6 +54,7 @@
 }
 Flags[] =
 {
+  { 'a', M_THREADCOMPLETE,	0,		NULL },
   { 'A', M_ALL,			0,		NULL },
   { 'b', M_BODY,		M_FULL_MSG,	eat_regexp },
   { 'B', M_WHOLE_MSG,		M_FULL_MSG,	eat_regexp },
@@ -1139,6 +1140,16 @@
                                              2, h->env->to, h->env->cc));
     case M_LIST:	/* known list, subscribed or not */
       return (pat->not ^ mutt_is_list_cc (pat->alladdr, h->env->to, h->env->cc));
+    case M_THREADCOMPLETE:
+      { static pattern_t tmp;
+        static short pattern_set = 0;
+        if(! pattern_set) {
+          memset (&tmp, 0, sizeof (tmp));
+          tmp.op = M_TAG;
+          pattern_set = 1;
+        }
+        return (pat->not ^ (h->env && match_threadcomplete(&tmp, flags, ctx, h->thread, 1, 1, 1, 1)));
+      } 
     case M_SUBSCRIBED_LIST:
       return (pat->not ^ mutt_is_list_recipient (pat->alladdr, h->env->to, h->env->cc));
     case M_PERSONAL_RECIP:
