<<< Date Index >>>     <<< Thread Index >>>

Re: [PATCH] pattern groups



I'm attaching a slightly revised version of the patch.  This
oncea gain applies against current CVS.

On 2006-01-09 14:47:00 +0100, Thomas Roessler wrote:

> To match against a pattern group, use '$' instead of '~'
> (better character suggestions would be much appreciated.)

The attached version uses '%' instead.

> Missing features include support for multiple groups in a
> single alias / alternates / lists, 

Done in the attached version of the patch.

> and some group maintenance commands (such as "add / remove
> this regexp / address to this group").  Documentation is
> also missing.

These are still missing.

I'm thinking of a pair of commands named group / ungroup with
the following syntaxes (Brendan will be able to teach me the
correct plural here ;):

  group -group a -group b -group c -rx a b c -addr d e f -rx h j k
  ungroup -group a -group b -group c -rx a b c -addr d e f

This would re-use the group context code that is now shared
between alias / alternates / lists / subscribe.

The -rx and -addr switches to group and ungroup would switch
between manipulating the regexp and address part of a group.
ungroup would have a special "*" parameter which can be used
without specifying a mode, and would empty the group entirely.

Thoughts?

Regards,
-- 
Thomas Roessler · Personal soap box at <http://log.does-not-exist.org/>.
Index: Makefile.am
===================================================================
RCS file: /cvs/mutt/mutt/Makefile.am,v
retrieving revision 3.39
diff -u -r3.39 Makefile.am
--- Makefile.am 20 Dec 2005 17:50:46 -0000      3.39
+++ Makefile.am 9 Jan 2006 18:48:26 -0000
@@ -20,7 +20,8 @@
        addrbook.c alias.c attach.c base64.c browser.c buffy.c color.c \
         crypt.c cryptglue.c \
        commands.c complete.c compose.c copy.c curs_lib.c curs_main.c date.c \
-       edit.c enter.c flags.c init.c filter.c from.c getdomain.c \
+       edit.c enter.c flags.c init.c filter.c from.c \
+       getdomain.c group.c \
        handler.c hash.c hdrline.c headers.c help.c hook.c keymap.c \
        main.c mbox.c menu.c mh.c mx.c pager.c parse.c pattern.c \
        postpone.c query.c recvattach.c recvcmd.c \
Index: globals.h
===================================================================
RCS file: /cvs/mutt/mutt/globals.h,v
retrieving revision 3.27
diff -u -r3.27 globals.h
--- globals.h   22 Dec 2005 17:46:40 -0000      3.27
+++ globals.h   9 Jan 2006 18:48:26 -0000
@@ -139,6 +139,8 @@
 WHERE char *CurrentFolder;
 WHERE char *LastFolder;
 
+WHERE HASH *Groups;
+
 WHERE LIST *AutoViewList INITVAL(0);
 WHERE LIST *AlternativeOrderList INITVAL(0);
 WHERE LIST *AttachAllow INITVAL(0);
Index: group.c
===================================================================
RCS file: group.c
diff -N group.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ group.c     9 Jan 2006 18:48:26 -0000
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2006 Thomas Roessler <roessler@xxxxxxxxxxxxxxxxxx>
+ * 
+ *     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., 51 Franklin Street, Fifth Floor, Boston, MA  
02110-1301, USA.
+ */ 
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "mutt.h"
+#include "mapping.h"
+#include "mutt_curses.h"
+#include "mutt_regex.h"
+#include "history.h"
+#include "keymap.h"
+#include "mbyte.h"
+#include "charset.h"
+#include "mutt_crypt.h"
+#include "mutt_idna.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/utsname.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+group_t *mutt_pattern_group (const char *k)
+{
+  group_t *p;
+  
+  if (!k)
+    return 0;
+  
+  if (!(p = hash_find (Groups, k)))
+  {
+    dprint (2, (debugfile, "mutt_pattern_group: Creating group %s.\n", k));
+    p = safe_calloc (1, sizeof (group_t));
+    p->name = safe_strdup (k);
+    hash_insert (Groups, p->name, p, 0);
+  }
+  
+  return p;
+}
+
+void mutt_group_context_add (group_context_t **ctx, group_t *group)
+{
+  for (; *ctx; ctx = &((*ctx)->next))
+  {
+    if ((*ctx)->g == group)
+      return;
+  }
+  
+  *ctx = safe_calloc (1, sizeof (group_context_t));
+  (*ctx)->g = group;
+}
+
+void mutt_group_context_destroy (group_context_t **ctx)
+{
+  group_context_t *p;
+  for (; *ctx; *ctx = p)
+  {
+    p = (*ctx)->next;
+    FREE (ctx);
+  }
+}
+
+void mutt_group_add_adrlist (group_t *g, ADDRESS *a)
+{
+  ADDRESS **p, *q;
+
+  if (!g)
+    return;
+  if (!a)
+    return;
+  
+  for (p = &g->as; *p; p = &((*p)->next))
+    ;
+  
+  q = rfc822_cpy_adr (a);
+  q = mutt_remove_xrefs (g->as, q);
+  *p = q;
+}
+
+int mutt_group_add_rx (group_t *g, const char *s, int flags, BUFFER *err)
+{
+  return mutt_add_to_rx_list (&g->rs, s, flags, err);
+}
+
+void mutt_group_context_add_adrlist (group_context_t *ctx, ADDRESS *a)
+{
+  for (; ctx; ctx = ctx->next)
+    mutt_group_add_adrlist (ctx->g, a);
+}
+
+int mutt_group_context_add_rx (group_context_t *ctx, const char *s, int flags, 
BUFFER *err)
+{
+  int rv = 0;
+  
+  for (; (!rv) && ctx; ctx = ctx->next)
+    rv = mutt_group_add_rx (ctx->g, s, flags, err);
+
+  return rv;
+}
+
+int mutt_group_match (group_t *g, const char *s)
+{
+  ADDRESS *ap;
+  
+  if (s && g)
+  {
+    if (mutt_match_rx_list (s, g->rs))
+      return 1;
+    for (ap = g->as; ap; ap = ap->next)
+      if (ap->mailbox && !mutt_strcasecmp (s, ap->mailbox))
+       return 1;
+  }
+  return 0;
+}
+
Index: init.c
===================================================================
RCS file: /cvs/mutt/mutt/init.c,v
retrieving revision 3.47
diff -u -r3.47 init.c
--- init.c      16 Dec 2005 18:49:40 -0000      3.47
+++ init.c      9 Jan 2006 18:48:28 -0000
@@ -134,7 +134,7 @@
          (ch == '#' && !(flags & M_TOKEN_COMMENT)) ||
          (ch == '=' && (flags & M_TOKEN_EQUAL)) ||
          (ch == ';' && !(flags & M_TOKEN_SEMICOLON)) ||
-         ((flags & M_TOKEN_PATTERN) && strchr ("~=!|", ch)))
+         ((flags & M_TOKEN_PATTERN) && strchr ("~%=!|", ch)))
        break;
     }
 
@@ -377,7 +377,7 @@
   }
 }
 
-static int add_to_rx_list (RX_LIST **list, const char *s, int flags, BUFFER 
*err)
+int mutt_add_to_rx_list (RX_LIST **list, const char *s, int flags, BUFFER *err)
 {
   RX_LIST *t, *last = NULL;
   REGEXP *rx;
@@ -652,18 +652,33 @@
 
 static int parse_alternates (BUFFER *buf, BUFFER *s, unsigned long data, 
BUFFER *err)
 {
+  group_context_t *gc = NULL;
+  
   _alternates_clean();
+
   do
   {
     mutt_extract_token (buf, s, 0);
+
+    if (parse_group_context (&gc, buf, s, data, err) == -1)
+      goto bail;
+
     remove_from_rx_list (&UnAlternates, buf->data);
 
-    if (add_to_rx_list (&Alternates, buf->data, REG_ICASE, err) != 0)
-      return -1;
+    if (mutt_add_to_rx_list (&Alternates, buf->data, REG_ICASE, err) != 0)
+      goto bail;
+
+    if (mutt_group_context_add_rx (gc, buf->data, REG_ICASE, err) != 0)
+      goto bail;
   }
   while (MoreArgs (s));
-
+  
+  mutt_group_context_destroy (&gc);
   return 0;
+  
+ bail:
+  mutt_group_context_destroy (&gc);
+  return -1;
 }
 
 static int parse_unalternates (BUFFER *buf, BUFFER *s, unsigned long data, 
BUFFER *err)
@@ -675,7 +690,7 @@
     remove_from_rx_list (&Alternates, buf->data);
 
     if (mutt_strcmp (buf->data, "*") &&
-       add_to_rx_list (&UnAlternates, buf->data, REG_ICASE, err) != 0)
+       mutt_add_to_rx_list (&UnAlternates, buf->data, REG_ICASE, err) != 0)
       return -1;
 
   }
@@ -746,7 +761,7 @@
       return 0;
 
     /* Otherwise, add it to the nospam list. */
-    if (add_to_rx_list (&NoSpamList, buf->data, REG_ICASE, err) != 0)
+    if (mutt_add_to_rx_list (&NoSpamList, buf->data, REG_ICASE, err) != 0)
       return -1;
 
     return 0;
@@ -780,17 +795,31 @@
 
 static int parse_lists (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER 
*err)
 {
+  group_context_t *gc = NULL;
+
   do
   {
     mutt_extract_token (buf, s, 0);
+    
+    if (parse_group_context (&gc, buf, s, data, err) == -1)
+      goto bail;
+    
     remove_from_rx_list (&UnMailLists, buf->data);
     
-    if (add_to_rx_list (&MailLists, buf->data, REG_ICASE, err) != 0)
-      return -1;
+    if (mutt_add_to_rx_list (&MailLists, buf->data, REG_ICASE, err) != 0)
+      goto bail;
+    
+    if (mutt_group_context_add_rx (gc, buf->data, REG_ICASE, err) != 0)
+      goto bail;
   }
   while (MoreArgs (s));
 
+  mutt_group_context_destroy (&gc);
   return 0;
+  
+ bail:
+  mutt_group_context_destroy (&gc);
+  return -1;
 }
 
 /* always wise to do what someone else did before */
@@ -1067,7 +1096,7 @@
     remove_from_rx_list (&MailLists, buf->data);
     
     if (mutt_strcmp (buf->data, "*") && 
-       add_to_rx_list (&UnMailLists, buf->data, REG_ICASE, err) != 0)
+       mutt_add_to_rx_list (&UnMailLists, buf->data, REG_ICASE, err) != 0)
       return -1;
   }
   while (MoreArgs (s));
@@ -1077,20 +1106,33 @@
 
 static int parse_subscribe (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER 
*err)
 {
+  group_context_t *gc = NULL;
+  
   do
   {
     mutt_extract_token (buf, s, 0);
+
+    if (parse_group_context (&gc, buf, s, data, err) == -1)
+      goto bail;
+    
     remove_from_rx_list (&UnMailLists, buf->data);
     remove_from_rx_list (&UnSubscribedLists, buf->data);
 
-    if (add_to_rx_list (&MailLists, buf->data, REG_ICASE, err) != 0)
-      return -1;
-    if (add_to_rx_list (&SubscribedLists, buf->data, REG_ICASE, err) != 0)
-      return -1;
+    if (mutt_add_to_rx_list (&MailLists, buf->data, REG_ICASE, err) != 0)
+      goto bail;
+    if (mutt_add_to_rx_list (&SubscribedLists, buf->data, REG_ICASE, err) != 0)
+      goto bail;
+    if (mutt_group_context_add_rx (gc, buf->data, REG_ICASE, err) != 0)
+      goto bail;
   }
   while (MoreArgs (s));
-
+  
+  mutt_group_context_destroy (&gc);
   return 0;
+  
+ bail:
+  mutt_group_context_destroy (&gc);
+  return -1;
 }
 
 static int parse_unsubscribe (BUFFER *buf, BUFFER *s, unsigned long data, 
BUFFER *err)
@@ -1101,7 +1143,7 @@
     remove_from_rx_list (&SubscribedLists, buf->data);
     
     if (mutt_strcmp (buf->data, "*") &&
-       add_to_rx_list (&UnSubscribedLists, buf->data, REG_ICASE, err) != 0)
+       mutt_add_to_rx_list (&UnSubscribedLists, buf->data, REG_ICASE, err) != 
0)
       return -1;
   }
   while (MoreArgs (s));
@@ -1161,6 +1203,7 @@
   ALIAS *tmp = Aliases;
   ALIAS *last = NULL;
   char *estr = NULL;
+  group_context_t *gc = NULL;
   
   if (!MoreArgs (s))
   {
@@ -1170,8 +1213,8 @@
 
   mutt_extract_token (buf, s, 0);
 
-  dprint (2, (debugfile, "parse_alias: First token is '%s'.\n",
-             buf->data));
+  if (parse_group_context (&gc, buf, s, data, err) == -1)
+    return -1;
   
   /* check to see if an alias with this name already exists */
   for (; tmp; tmp = tmp->next)
@@ -1202,7 +1245,9 @@
   mutt_extract_token (buf, s, M_TOKEN_QUOTE | M_TOKEN_SPACE | 
M_TOKEN_SEMICOLON);
   dprint (2, (debugfile, "parse_alias: Second token is '%s'.\n",
              buf->data));
+
   tmp->addr = mutt_parse_adrlist (tmp->addr, buf->data);
+
   if (last)
     last->next = tmp;
   else
@@ -1211,8 +1256,12 @@
   {
     snprintf (err->data, err->dsize, _("Warning: Bad IDN '%s' in alias 
'%s'.\n"),
              estr, tmp->name);
-    return -1;
+    goto bail;
   }
+
+  mutt_group_context_add_adrlist (gc, tmp->addr);
+
+
 #ifdef DEBUG
   if (debuglevel >= 2) 
   {
@@ -1229,7 +1278,12 @@
     }
   }
 #endif
+  mutt_group_context_destroy (&gc);
   return 0;
+  
+  bail:
+  mutt_group_context_destroy (&gc);
+  return -1;
 }
 
 static int
@@ -2541,6 +2595,8 @@
   err.data = error;
   err.dsize = sizeof (error);
 
+  Groups = hash_create (1031);
+  
   /* 
    * XXX - use something even more difficult to predict?
    */
@@ -2802,3 +2858,33 @@
       return c->data;
   return 0;
 }
+
+static int parse_group_context (group_context_t **ctx, BUFFER *buf, BUFFER *s, 
unsigned long data, BUFFER *err)
+{
+  while (!mutt_strcasecmp (buf->data, "-group"))
+  {
+    if (!MoreArgs (s)) 
+    {
+      strfcpy (err->data, _("-group: no group name"), err->dsize);
+      goto bail;
+    }
+    
+    mutt_extract_token (buf, s, 0);
+
+    mutt_group_context_add (ctx, mutt_pattern_group (buf->data));
+    
+    if (!MoreArgs (s))
+    {
+      strfcpy (err->data, _("out of arguments"), err->dsize);
+      goto bail;
+    }
+    
+    mutt_extract_token (buf, s, 0);
+  }
+  
+  return 0;
+  
+  bail:
+  mutt_group_context_destroy (ctx);
+  return -1;
+}
Index: init.h
===================================================================
RCS file: /cvs/mutt/mutt/init.h,v
retrieving revision 3.94
diff -u -r3.94 init.h
--- init.h      22 Dec 2005 17:46:40 -0000      3.94
+++ init.h      9 Jan 2006 18:48:29 -0000
@@ -3008,6 +3008,10 @@
 static int parse_alternates (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 static int parse_unalternates (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 
+/* Parse -group arguments */
+static int parse_group_context (group_context_t **ctx, BUFFER *buf, BUFFER *s, 
unsigned long data, BUFFER *err);
+
+
 struct command_t
 {
   char *name;
Index: mutt.h
===================================================================
RCS file: /cvs/mutt/mutt/mutt.h,v
retrieving revision 3.62
diff -u -r3.62 mutt.h
--- mutt.h      12 Dec 2005 17:24:11 -0000      3.62
+++ mutt.h      9 Jan 2006 18:48:29 -0000
@@ -798,18 +798,36 @@
   M_MATCH_FULL_ADDRESS = 1
 } pattern_exec_flag;
 
+typedef struct group_t
+{
+  ADDRESS *as;
+  RX_LIST *rs;
+  char *name;
+} group_t;
+
+typedef struct group_context_t
+{
+  group_t *g;
+  struct group_context_t *next;
+} group_context_t;
+
 typedef struct pattern_t
 {
   short op;
   unsigned int not : 1;
   unsigned int alladdr : 1;
   unsigned int stringmatch : 1;
+  unsigned int groupmatch : 1;
   int min;
   int max;
   struct pattern_t *next;
   struct pattern_t *child;             /* arguments to logical op */
-  char *str;
-  regex_t *rx;
+  union 
+  {
+    regex_t *rx;
+    group_t *g;
+    char *str;
+  } p;
 } pattern_t;
 
 typedef struct
Index: pattern.c
===================================================================
RCS file: /cvs/mutt/mutt/pattern.c,v
retrieving revision 3.27
diff -u -r3.27 pattern.c
--- pattern.c   24 Nov 2005 12:50:27 -0000      3.27
+++ pattern.c   9 Jan 2006 18:48:29 -0000
@@ -278,19 +278,24 @@
 
   if (pat->stringmatch)
   {
-    pat->str = safe_strdup (buf.data);
+    pat->p.str = safe_strdup (buf.data);
+    FREE (&buf.data);
+  }
+  else if (pat->groupmatch)
+  {
+    pat->p.g = mutt_pattern_group (buf.data);
     FREE (&buf.data);
   }
   else
   {
-    pat->rx = safe_malloc (sizeof (regex_t));
-    r = REGCOMP (pat->rx, buf.data, REG_NEWLINE | REG_NOSUB | mutt_which_case 
(buf.data));
+    pat->p.rx = safe_malloc (sizeof (regex_t));
+    r = REGCOMP (pat->p.rx, buf.data, REG_NEWLINE | REG_NOSUB | 
mutt_which_case (buf.data));
     FREE (&buf.data);
     if (r)
     {
-      regerror (r, pat->rx, err->data, err->dsize);
-      regfree (pat->rx);
-      FREE (&pat->rx);
+      regerror (r, pat->p.rx, err->data, err->dsize);
+      regfree (pat->p.rx);
+      FREE (&pat->p.rx);
       return (-1);
     }
   }
@@ -697,9 +702,11 @@
 static int patmatch (const pattern_t* pat, const char* buf)
 {
   if (pat->stringmatch)
-    return !strstr (buf, pat->str);
+    return !strstr (buf, pat->p.str);
+  else if (pat->groupmatch)
+    return !mutt_group_match (pat->p.g, buf);
   else
-    return regexec (pat->rx, buf, 0, NULL, 0);
+    return regexec (pat->p.rx, buf, 0, NULL, 0);
 }
 
 static struct pattern_flags *lookup_tag (char tag)
@@ -739,12 +746,16 @@
     tmp = *pat;
     *pat = (*pat)->next;
 
-    if (tmp->rx)
+    if (tmp->stringmatch)
+      FREE (&tmp->p.str);
+    else if (tmp->groupmatch)
+      tmp->p.g = NULL;
+    else if (tmp->p.rx)
     {
-      regfree (tmp->rx);
-      FREE (&tmp->rx);
+      regfree (tmp->p.rx);
+      FREE (&tmp->p.rx);
     }
-    FREE (&tmp->str);
+
     if (tmp->child)
       mutt_pattern_free (&tmp->child);
     FREE (&tmp);
@@ -808,6 +819,7 @@
        not = 0;
        alladdr = 0;
        break;
+      case '%':
       case '=':
       case '~':
        if (implicit && or)
@@ -825,6 +837,7 @@
        tmp->not = not;
        tmp->alladdr = alladdr;
         tmp->stringmatch = (*ps.dptr == '=') ? 1 : 0;
+        tmp->groupmatch  = (*ps.dptr == '%') ? 1 : 0;
        not = 0;
        alladdr = 0;
 
@@ -1164,7 +1177,7 @@
    * equivalences?
    */
   
-  if (!strchr (s, '~') && !strchr (s, '=')) /* yup, so spoof a real request */
+  if (!strchr (s, '~') && !strchr (s, '=') && !strchr (s, '%')) /* yup, so 
spoof a real request */
   {
     /* convert old tokens into the new format */
     if (ascii_strcasecmp ("all", s) == 0 ||
Index: protos.h
===================================================================
RCS file: /cvs/mutt/mutt/protos.h,v
retrieving revision 3.42
diff -u -r3.42 protos.h
--- protos.h    20 Dec 2005 17:50:47 -0000      3.42
+++ protos.h    9 Jan 2006 18:48:30 -0000
@@ -72,6 +72,11 @@
 void mutt_FormatString (char *, size_t, const char *, format_t *, unsigned 
long, format_flag);
 void mutt_parse_content_type (char *, BODY *);
 void mutt_generate_boundary (PARAMETER **);
+void mutt_group_add_adrlist (group_t *, ADDRESS *);
+void mutt_group_context_add (group_context_t **ctx, group_t *group);
+void mutt_group_context_destroy (group_context_t **ctx);
+void mutt_group_add_adrlist (group_t *g, ADDRESS *a);
+void mutt_group_context_add_adrlist (group_context_t *ctx, ADDRESS *a);
 void mutt_delete_parameter (const char *attribute, PARAMETER **p);
 void mutt_set_parameter (const char *, const char *, PARAMETER **);
 
@@ -86,6 +91,7 @@
 ADDRESS *mutt_get_address (ENVELOPE *, char **);
 ADDRESS *mutt_lookup_alias (const char *s);
 ADDRESS *mutt_remove_duplicates (ADDRESS *);
+ADDRESS *mutt_remove_xrefs (ADDRESS *, ADDRESS *);
 ADDRESS *mutt_expand_aliases (ADDRESS *);
 ADDRESS *mutt_parse_adrlist (ADDRESS *, const char *);
 
@@ -144,6 +150,8 @@
 
 const char *mutt_fqdn(short);
 
+group_t *mutt_pattern_group (const char *);
+
 REGEXP *mutt_compile_regexp (const char *, int);
 
 void mutt_account_hook (const char* url);
@@ -245,6 +253,7 @@
 void mutt_write_address_list (ADDRESS *adr, FILE *fp, int linelen, int 
display);
 void mutt_set_virtual (CONTEXT *);
 
+int mutt_add_to_rx_list (RX_LIST **list, const char *s, int flags, BUFFER 
*err);
 int mutt_addr_is_user (ADDRESS *);
 int mutt_addwch (wchar_t);
 int mutt_alias_complete (char *, size_t);
@@ -291,6 +300,8 @@
 #define mutt_get_password(A,B,C) mutt_get_field_unbuffered(A,B,C,M_PASS)
 int mutt_get_postponed (CONTEXT *, HEADER *, HEADER **, char *, size_t);
 int mutt_get_tmp_attachment (BODY *);
+int mutt_group_match (group_t *g, const char *s);
+int mutt_group_context_add_rx (group_context_t *ctx, const char *s, int flags, 
BUFFER *err);
 int mutt_index_menu (void);
 int mutt_invoke_sendmail (ADDRESS *, ADDRESS *, ADDRESS *, ADDRESS *, const 
char *, int);
 int mutt_is_autoview (BODY *, const char *);
Index: send.c
===================================================================
RCS file: /cvs/mutt/mutt/send.c,v
retrieving revision 3.44
diff -u -r3.44 send.c
--- send.c      3 Oct 2005 07:52:00 -0000       3.44
+++ send.c      9 Jan 2006 18:48:30 -0000
@@ -87,7 +87,7 @@
 }
 
 /* removes addresses from "b" which are contained in "a" */
-static ADDRESS *mutt_remove_xrefs (ADDRESS *a, ADDRESS *b)
+ADDRESS *mutt_remove_xrefs (ADDRESS *a, ADDRESS *b)
 {
   ADDRESS *top, *p, *prev = NULL;
 
Index: imap/imap.c
===================================================================
RCS file: /cvs/mutt/mutt/imap/imap.c,v
retrieving revision 3.77
diff -u -r3.77 imap.c
--- imap/imap.c 3 Jan 2006 17:35:18 -0000       3.77
+++ imap/imap.c 9 Jan 2006 18:48:31 -0000
@@ -1657,13 +1657,13 @@
         mutt_buffer_addstr (buf, "HEADER ");
 
         /* extract header name */
-        if (! (delim = strchr (pat->str, ':')))
+        if (! (delim = strchr (pat->p.str, ':')))
         {
-          mutt_error (_("Header search without header name: %s"), pat->str);
+          mutt_error (_("Header search without header name: %s"), pat->p.str);
           return -1;
         }
         *delim = '\0';
-        imap_quote_string (term, sizeof (term), pat->str);
+        imap_quote_string (term, sizeof (term), pat->p.str);
         mutt_buffer_addstr (buf, term);
         mutt_buffer_addch (buf, ' ');
         
@@ -1676,12 +1676,12 @@
         break;
       case M_BODY:
         mutt_buffer_addstr (buf, "BODY ");
-        imap_quote_string (term, sizeof (term), pat->str);
+        imap_quote_string (term, sizeof (term), pat->p.str);
         mutt_buffer_addstr (buf, term);
         break;
       case M_WHOLE_MSG:
         mutt_buffer_addstr (buf, "TEXT ");
-        imap_quote_string (term, sizeof (term), pat->str);
+        imap_quote_string (term, sizeof (term), pat->p.str);
         mutt_buffer_addstr (buf, term);
         break;
     }

Attachment: pgpLbgWDSHMAd.pgp
Description: PGP signature