diff -Pur mutt-1.3.23-base/doc/manual.sgml.head mutt-1.3.23/doc/manual.sgml.head --- mutt-1.3.23-base/doc/manual.sgml.head Sun Oct 7 01:43:43 2001 +++ mutt-1.3.23/doc/manual.sgml.head Thu Oct 25 18:38:59 2001 @@ -1714,6 +1714,7 @@ ~t USER messages addressed to USER ~U unread messages ~v message is part of a collapsed thread. +~V [MIN]-[MAX] messages with MIN to MAX attachments *) ~x EXPR messages which contain EXPR in the `References' field ~y EXPR messages which contain EXPR in the `X-Label' field ~z [MIN]-[MAX] messages with a size in the range MIN to MAX *) diff -Pur mutt-1.3.23-base/doc/manual.txt mutt-1.3.23/doc/manual.txt --- mutt-1.3.23-base/doc/manual.txt Tue Oct 9 03:44:25 2001 +++ mutt-1.3.23/doc/manual.txt Thu Oct 25 18:38:59 2001 @@ -1996,6 +1996,7 @@ ~t USER messages addressed to USER ~U unread messages ~v message is part of a collapsed thread. + ~V [MIN]-[MAX] messages with MIN - MAX attachments *) ~x EXPR messages which contain EXPR in the `References' field ~y EXPR messages which contain EXPR in the `X-Label' field ~z [MIN]-[MAX] messages with a size in the range MIN to MAX *) @@ -4066,6 +4067,8 @@ %%vv first name of the author, or the recipient if the message is from you + + %%VV number of attachments (%-V: number of top-level attachments) %%yy `x-label:' field, if present diff -Pur mutt-1.3.23-base/doc/muttrc.man.head mutt-1.3.23/doc/muttrc.man.head --- mutt-1.3.23-base/doc/muttrc.man.head Thu Aug 30 15:28:35 2001 +++ mutt-1.3.23/doc/muttrc.man.head Thu Oct 25 18:38:59 2001 @@ -365,13 +365,14 @@ ~t \fIEXPR\fP messages addressed to \fIEXPR\fP ~U unread messages ~v message is part of a collapsed thread. +~V \fIMIN\fP-\fIMAX\fP messages with MIN - MAX attachments ~x \fIEXPR\fP messages which contain \fIEXPR\fP in the \(lqReferences\(rq field ~z \fIMIN\fP-\fIMAX\fP messages with a size in the range \fIMIN\fP to \fIMAX\fP .TE .PP In the above, \fIEXPR\fP is a regular expression. .PP -With the \fB~m\fP, \fB~n\fP, and \fB~z\fP operators, you can also +With the \fB~m\fP, \fB~n\fP, \fB~V\fP, and \fB~z\fP operators, you can also specify ranges in the forms \fB<\fP\fIMAX\fP, \fB>\fP\fIMIN\fP, \fIMIN\fP\fB-\fP, and \fB-\fP\fIMAX\fP. .SS Matching dates diff -Pur mutt-1.3.23-base/hdrline.c mutt-1.3.23/hdrline.c --- mutt-1.3.23-base/hdrline.c Thu May 10 08:11:22 2001 +++ mutt-1.3.23/hdrline.c Thu Oct 25 18:42:35 2001 @@ -224,6 +224,7 @@ * %T = $to_chars * %u = user (login) name of author * %v = first name of author, unless from self + * %V = number of MIME attachments * %y = `x-label:' field (if present) * %Y = `x-label:' field (if present, tree unfolded, and != parent's x-label) * %Z = status flags */ @@ -638,6 +639,48 @@ (hdr->flagged ? '!' : (Tochars && ((i = mutt_user_is_recipient (hdr)) < mutt_strlen (Tochars)) ? Tochars[i] : ' '))); mutt_format_s (dest, destlen, prefix, buf2); + break; + + case 'V': + { + int i, flags; + struct body *parts; + + flags = 0; + + if (option(OPTATRECURSE)) + flags |= M_PARTS_MSGTRANS; + if (option(OPTATINLINEOK)) + flags |= M_PARTS_INLINEOK; + if (option(OPTATCONTAINERSOK)) + flags |= M_PARTS_CONTAINS; + + + /* Find whether MIME structure is parsed. */ + parts = hdr->content->parts; + + /* If not then parse it. */ + if (parts == NULL) + { + mutt_parse_mime_message(ctx, hdr); + } + + /* Count parts. */ + i = mutt_count_body_parts(hdr->content, flags); + + /* If not pre-parsed, throw out our work. */ + if (parts == NULL) + { + mutt_free_body(&hdr->content->parts); + } + + /* The recursion allows messages without depth to return 0. */ + if (optional) + optional = i ? 1 : 0; + + snprintf (fmt, sizeof (fmt), "%%%sd", prefix); + snprintf (dest, destlen, fmt, i); + } break; case 'y': diff -Pur mutt-1.3.23-base/init.h mutt-1.3.23/init.h --- mutt-1.3.23-base/init.h Tue Sep 11 05:38:00 2001 +++ mutt-1.3.23/init.h Thu Oct 25 18:39:00 2001 @@ -218,6 +218,25 @@ ** ``$$attach_sep'' separator is added after each attachment. When set, ** Mutt will operate on the attachments one by one. */ + { "attach_count_containers_ok", DT_BOOL, R_INDEX, OPTATCONTAINERSOK, 0 }, + /* + ** .pp + ** If set, Mutt's attachment counter (%V/~V) will consider MIME components + ** which contain other components (e.g., multipart/* and message/*) as + ** attachments. + */ + { "attach_count_inline_ok", DT_BOOL, R_INDEX, OPTATINLINEOK, 0 }, + /* + ** .pp + ** If set, Mutt's attachment counter (%V/~V) will consider MIME components + ** with a disposition of "inline" as attachments. + */ + { "attach_count_recurse", DT_BOOL, R_INDEX, OPTATRECURSE, 1 }, + /* + ** .pp + ** If set, Mutt's attachment counter (%V/~V) will examine message/* + ** components for attachments. + */ { "attribution", DT_STR, R_NONE, UL &Attribution, UL "On %d, %n wrote:" }, /* ** .pp @@ -826,6 +845,7 @@ ** .dt %T .dd the appropriate character from the $$to_chars string ** .dt %u .dd user (login) name of the author ** .dt %v .dd first name of the author, or the recipient if the message is from you + ** .dt %V .dd number of attachments ** .dt %y .dd `x-label:' field, if present ** .dt %Y .dd `x-label' field, if present, and (1) not at part of a thread tree, ** (2) at the top of a thread, or (3) `x-label' is different from diff -Pur mutt-1.3.23-base/mutt.h mutt-1.3.23/mutt.h --- mutt-1.3.23-base/mutt.h Wed Sep 26 05:15:51 2001 +++ mutt-1.3.23/mutt.h Thu Oct 25 18:39:00 2001 @@ -217,6 +217,7 @@ M_PGP_KEY, #endif M_XLABEL, + M_MIMEATTACH, /* Options for Mailcap lookup */ M_EDIT, @@ -400,6 +401,10 @@ OPTWRITEBCC, /* write out a bcc header? */ OPTXMAILER, + OPTATINLINEOK, /* Count inline attachments? */ + OPTATCONTAINERSOK, /* Count containing messages? */ + OPTATRECURSE, /* Recurse message/\* types? */ + /* PGP options */ #ifdef HAVE_PGP @@ -786,6 +791,12 @@ void state_prefix_putc(char, STATE *); int state_printf(STATE *, const char *, ...); + +/* Flags for mutt_count_body_parts() */ +#define M_PARTS_MSGTRANS (1<<0) /* message/rfc822 is transparent */ +#define M_PARTS_CONTAINS (1<<1) /* Count containers */ +#define M_PARTS_INLINEOK (1<<2) /* Inline dispositions (except PGP) */ +#define M_PARTS_PGPOK (1<<3) /* Count PGP */ #include "ascii.h" #include "protos.h" diff -Pur mutt-1.3.23-base/parse.c mutt-1.3.23/parse.c --- mutt-1.3.23-base/parse.c Sun Apr 29 17:00:19 2001 +++ mutt-1.3.23/parse.c Thu Oct 25 18:39:00 2001 @@ -1338,3 +1338,98 @@ return p; } + +int count_body_parts (BODY *body, int flags) +{ + int count = 0; + int shallcount, shallrecurse; + BODY *bp; + + if (body == NULL) + return 0; + + for (bp = body; bp != NULL; bp = bp->next) + { + /* Initial disposition is to count and not to recurse this part. */ + shallcount = 1; + shallrecurse = 0; + + dprint(30, (debugfile, "bp: desc=\"%s\"; fn=\"%s\", type=\"%d/%s\"\n", + bp->description ? bp->description : ("none"), + bp->filename ? bp->filename : + bp->d_filename ? bp->d_filename : "(none)", + bp->type, bp->subtype ? bp->subtype : "*")); + if (bp->type == TYPEMESSAGE) + { + /* If messages are "transparent", recursively examine their parts. */ + if (flags & M_PARTS_MSGTRANS) + shallrecurse = 1; + /* Do not count messages if they are transparent + and we are not told to count containers. */ + if (shallrecurse && !(flags & M_PARTS_CONTAINS)) + shallcount = 0; + } + else if (bp->type == TYPEMULTIPART) + { + /* Always recurse multiparts. */ + shallrecurse = 1; + /* If told to count containers, then consider this one. */ + if (!(flags & M_PARTS_CONTAINS)) + shallcount = 0; + } + + /* These are just different reasons to turn off shallcount, so ignore + * them if it's already off. + */ + if (shallcount && bp->disposition != DISPATTACH) + { + /* Are we allowed to count inline disposition? */ + if (flags & M_PARTS_INLINEOK) + { + /* Inline is OK */ +#ifdef HAVE_PGP + /* no good lib routines for this on a per-component basis */ + if (!(flags & M_PARTS_PGPOK) && + bp->type == TYPEAPPLICATION && + !mutt_strncmp(bp->subtype, "pgp", 3)) + shallcount = 0; +#endif + dprint(30, (debugfile, "cbp: inlineok shallcount = %d\n", shallcount)); + } + else + { + /* Inline not OK */ + shallcount = 0; + dprint(30, (debugfile, "cbp: inlinebad shallcount = %d\n", shallcount)); + } + } + + if (shallcount) + count++; + + if (shallrecurse) + { + dprint(30, (debugfile, "cbp: %08x pre count = %d\n", bp, shallcount)); + count += count_body_parts(bp->parts, flags); + dprint(30, (debugfile, "cbp: %08x post count = %d\n", bp, shallcount)); + } + } + + dprint(30, (debugfile, "bp: return %d\n", count < 0 ? 0 : count)); + return count < 0 ? 0 : count; +} + +int mutt_count_body_parts (BODY *body, int flags) +{ + int count; + + count = count_body_parts(body, flags); + + /* Never count the fundamental document. If inlineok, we will have + * counted it, so count will be inflated. Discount this before returning. + */ + if (count > 0 && (flags & M_PARTS_INLINEOK)) + --count; + + return count; +} diff -Pur mutt-1.3.23-base/pattern.c mutt-1.3.23/pattern.c --- mutt-1.3.23-base/pattern.c Thu Aug 23 03:53:32 2001 +++ mutt-1.3.23/pattern.c Thu Oct 25 18:39:00 2001 @@ -87,6 +87,7 @@ { 't', M_TO, 0, eat_regexp }, { 'U', M_UNREAD, 0, NULL }, { 'v', M_COLLAPSED, 0, NULL }, + { 'V', M_MIMEATTACH, 0, eat_range }, { 'x', M_REFERENCE, 0, eat_regexp }, { 'y', M_XLABEL, 0, eat_regexp }, { 'z', M_SIZE, 0, eat_range }, @@ -1050,6 +1051,23 @@ #endif case M_XLABEL: return (pat->not ^ (h->env->x_label && regexec (pat->rx, h->env->x_label, 0, NULL, 0) == 0)); + case M_MIMEATTACH: + { + int i, flags = 0; + + if (option(OPTATRECURSE)) + flags |= M_PARTS_MSGTRANS; + if (option(OPTATINLINEOK)) + flags |= M_PARTS_INLINEOK; + if (option(OPTATCONTAINERSOK)) + flags |= M_PARTS_CONTAINS; + + mutt_parse_mime_message(ctx, h); + i = mutt_count_body_parts(h->content->parts, flags); + mutt_free_body(&h->content->parts); + return (pat->not ^ (i >= pat->min && (pat->max == M_MAXRANGE || + i <= pat->max))); + } } mutt_error (_("error: unknown op %d (report this error)."), pat->op); return (-1); diff -Pur mutt-1.3.23-base/protos.h mutt-1.3.23/protos.h --- mutt-1.3.23-base/protos.h Tue Jul 3 14:31:16 2001 +++ mutt-1.3.23/protos.h Thu Oct 25 18:39:00 2001 @@ -148,6 +148,7 @@ void mutt_bounce_message (FILE *fp, HEADER *, ADDRESS *); void mutt_buffy (char *, size_t); void mutt_canonical_charset (char *, size_t, const char *); +int mutt_count_body_parts (BODY *body, int flags); void mutt_check_rescore (CONTEXT *); void mutt_clear_error (void); void mutt_create_alias (ENVELOPE *, ADDRESS *);