pattern groups, v3
This version of the patch is in the CVS, too; it feels useful
enough. This adds a "group" configuration command along the
lines of what I outlined in my last message.
I hope that I'll be doing "ungroup" tomorrow; meanwhile, if
anyone feels like doing it, you're welcome. ;-)
--
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 19:42:57 -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 19:42:58 -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 19:42:58 -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 19:42:59 -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,95 @@
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;
+}
+
+typedef enum group_state_t {
+ NONE, RX, ADDR
+} group_state_t;
+
+static int parse_group (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER
*err)
+{
+ group_context_t *gc = NULL;
+ group_state_t state = NONE;
+ ADDRESS *addr = NULL;
+ char *estr = NULL;
+
+ do
+ {
+ mutt_extract_token (buf, s, 0);
+ if (parse_group_context (&gc, buf, s, data, err) == -1)
+ goto bail;
+
+ if (!mutt_strcasecmp (buf->data, "-rx"))
+ state = RX;
+ else if (!mutt_strcasecmp (buf->data, "-addr"))
+ state = ADDR;
+ else
+ {
+ switch (state)
+ {
+ case NONE:
+ strfcpy (err->data, _("Missing -rx or -addr."), err->dsize);
+ goto bail;
+
+ case RX:
+ if (mutt_group_context_add_rx (gc, buf->data, REG_ICASE, err) != 0)
+ goto bail;
+ break;
+
+ case ADDR:
+ if ((addr = mutt_parse_adrlist (NULL, buf->data)) == NULL)
+ goto bail;
+ if (mutt_addrlist_to_idna (addr, &estr))
+ {
+ snprintf (err->data, err->dsize, _("Warning: Bad IDN '%s'.\n"),
+ estr);
+ goto bail;
+ }
+ mutt_group_context_add_adrlist (gc, addr);
+ rfc822_free_address (&addr);
+ break;
+ }
+ }
+ } while (MoreArgs (s));
+
+ mutt_group_context_destroy (&gc);
+ return 0;
+
+ bail:
+ mutt_group_context_destroy (&gc);
+ return -1;
+}
+
+static int parse_ungroup (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER
*err)
+{
+ strfcpy (err->data, "not implemented", err->dsize);
+ return -1;
}
/* always wise to do what someone else did before */
@@ -1067,7 +1160,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 +1170,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 +1207,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 +1267,7 @@
ALIAS *tmp = Aliases;
ALIAS *last = NULL;
char *estr = NULL;
+ group_context_t *gc = NULL;
if (!MoreArgs (s))
{
@@ -1170,8 +1277,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 +1309,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 +1320,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 +1342,12 @@
}
}
#endif
+ mutt_group_context_destroy (&gc);
return 0;
+
+ bail:
+ mutt_group_context_destroy (&gc);
+ return -1;
}
static int
@@ -2541,6 +2659,8 @@
err.data = error;
err.dsize = sizeof (error);
+ Groups = hash_create (1031);
+
/*
* XXX - use something even more difficult to predict?
*/
@@ -2802,3 +2922,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 19:43:00 -0000
@@ -2989,6 +2989,9 @@
static int parse_spam_list (BUFFER *, BUFFER *, unsigned long, BUFFER *);
static int parse_unlist (BUFFER *, BUFFER *, unsigned long, BUFFER *);
+static int parse_group (BUFFER *, BUFFER *, unsigned long, BUFFER *);
+static int parse_ungroup (BUFFER *, BUFFER *, unsigned long, BUFFER *);
+
static int parse_lists (BUFFER *, BUFFER *, unsigned long, BUFFER *);
static int parse_unlists (BUFFER *, BUFFER *, unsigned long, BUFFER *);
static int parse_alias (BUFFER *, BUFFER *, unsigned long, BUFFER *);
@@ -3008,6 +3011,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;
@@ -3037,6 +3044,8 @@
{ "fcc-hook", mutt_parse_hook, M_FCCHOOK },
{ "fcc-save-hook", mutt_parse_hook, M_FCCHOOK | M_SAVEHOOK },
{ "folder-hook", mutt_parse_hook, M_FOLDERHOOK },
+ { "group", parse_group, 0 },
+ { "ungroup", parse_ungroup, 0 },
{ "hdr_order", parse_list, UL &HeaderOrderList },
#ifdef HAVE_ICONV
{ "iconv-hook", mutt_parse_hook, M_ICONVHOOK },
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 19:43:00 -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 19:43:01 -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 19:43:01 -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 19:43:01 -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 19:43:02 -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;
}