diff -ruP mutt-1.3.3-orig/doc/manual.sgml.head mutt-1.3.3/doc/manual.sgml.head --- mutt-1.3.3-orig/doc/manual.sgml.head Sun Jun 4 13:18:45 2000 +++ mutt-1.3.3/doc/manual.sgml.head Wed Jun 21 11:37:18 2000 @@ -1630,6 +1630,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 -ruP mutt-1.3.3-orig/doc/muttrc.man.head mutt-1.3.3/doc/muttrc.man.head --- mutt-1.3.3-orig/doc/muttrc.man.head Thu Jun 8 07:20:14 2000 +++ mutt-1.3.3/doc/muttrc.man.head Wed Jun 21 11:37:45 2000 @@ -347,13 +347,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 -ruP mutt-1.3.3-orig/hdrline.c mutt-1.3.3/hdrline.c --- mutt-1.3.3-orig/hdrline.c Thu May 25 03:12:30 2000 +++ mutt-1.3.3/hdrline.c Wed Jun 21 09:28:24 2000 @@ -219,6 +220,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 */ @@ -631,6 +633,32 @@ if ((p = strpbrk (buf2, " %@"))) *p = 0; hdr_format_s (dest, destlen, prefix, buf2); + break; + + case 'V': + { + int i, flags; + + 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, hdr); + i = mutt_count_body_parts(hdr->content, flags); + 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 'Z': diff -ruP mutt-1.3.3-orig/init.h mutt-1.3.3/init.h --- mutt-1.3.3-orig/init.h Sun May 28 15:28:09 2000 +++ mutt-1.3.3/init.h Wed Jun 21 11:39:22 2000 @@ -177,6 +177,25 @@ ** If set, Mutt will prompt you for carbon-copy (Cc) recipients before ** editing the body of an outgoing message. */ + { "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. + */ { "attach_format", DT_STR, R_NONE, UL &AttachFormat, UL "%u%D%I %t%4n %T%.40d%> [%.7m/%.10M, %.6e%?C?, %C?, %s] " }, /* ** .pp @@ -812,6 +831,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 -ruP mutt-1.3.3-orig/mutt.h mutt-1.3.3/mutt.h --- mutt-1.3.3-orig/mutt.h Sun May 28 15:28:09 2000 +++ mutt-1.3.3/mutt.h Wed Jun 21 06:47:00 2000 @@ -208,6 +209,7 @@ M_PGP_KEY, #endif M_XLABEL, + M_MIMEATTACH, /* Options for Mailcap lookup */ M_EDIT, @@ -365,6 +367,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 @@ -723,6 +730,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 "protos.h" #include "lib.h" diff -ruP mutt-1.3.3-orig/pattern.c mutt-1.3.3/pattern.c --- mutt-1.3.3-orig/pattern.c Thu May 25 03:12:30 2000 +++ mutt-1.3.3/pattern.c Wed Jun 21 07:05:36 2000 @@ -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 }, @@ -893,6 +894,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 -ruP mutt-1.3.3-orig/protos.h mutt-1.3.3/protos.h --- mutt-1.3.3-orig/protos.h Mon May 22 05:06:32 2000 +++ mutt-1.3.3/protos.h Mon Jun 19 16:58:57 2000 @@ -139,6 +139,7 @@ void mutt_bounce_message (FILE *fp, HEADER *, ADDRESS *); void mutt_buffy (char *); 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 *); diff -ruP mutt-1.3.3-orig/doc/manual.txt mutt-1.3.3/doc/manual.txt --- mutt-1.3.3-orig/doc/manual.txt Fri Jun 9 06:39:10 2000 +++ mutt-1.3.3/doc/manual.txt Wed Jun 21 11:49:24 2000 @@ -1906,6 +1906,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 *) @@ -3845,6 +3846,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 -ruP mutt-1.3.3-orig/parse.c mutt-1.3.3/parse.c --- mutt-1.3.3-orig/parse.c Thu May 25 03:12:30 2000 +++ mutt-1.3.3/parse.c Wed Jun 21 11:47:50 2000 @@ -1345,4 +1352,99 @@ p = rfc822_parse_adrlist (p, s); 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; }