diff -rU5 mutt-1.3.8-dist/doc/manual.sgml.head mutt-1.3.8/doc/manual.sgml.head --- mutt-1.3.8-dist/doc/manual.sgml.head Tue Aug 22 09:52:42 2000 +++ mutt-1.3.8/doc/manual.sgml.head Sat Sep 9 22:07:26 2000 @@ -1657,10 +1657,11 @@ ~s SUBJECT messages having SUBJECT in the ``Subject'' field. ~T tagged messages ~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 -rU5 mutt-1.3.8-dist/doc/manual.txt mutt-1.3.8/doc/manual.txt --- mutt-1.3.8-dist/doc/manual.txt Wed Aug 30 05:10:06 2000 +++ mutt-1.3.8/doc/manual.txt Sat Sep 9 22:07:26 2000 @@ -1904,10 +1904,11 @@ ~e EXPR message which contains EXPR in the ``Sender'' field ~F flagged messages ~f USER messages originating from USER ~g PGP signed messages ~G PGP encrypted messages + ~V [MIN]-[MAX] messages with MIN - MAX attachments *) ~h EXPR messages which contain EXPR in the message header ~k message contains PGP key material ~i ID message which match ID in the ``Message-ID'' field ~L EXPR message is either originated or received by EXPR ~l message is addressed to a known mailing list @@ -3841,10 +3842,12 @@ %%uu user (login) name of the author %%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 %%YY `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 diff -rU5 mutt-1.3.8-dist/doc/muttrc.man.head mutt-1.3.8/doc/muttrc.man.head --- mutt-1.3.8-dist/doc/muttrc.man.head Tue Jun 20 07:39:38 2000 +++ mutt-1.3.8/doc/muttrc.man.head Sat Sep 9 22:07:26 2000 @@ -346,17 +346,18 @@ ~s \fIEXPR\fP messages having \fIEXPR\fP in the \(lqSubject\(rq field. ~T tagged messages ~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 .PP The \fB~d\fP and \fB~r\fP operators are used to match date ranges, diff -rU5 mutt-1.3.8-dist/hdrline.c mutt-1.3.8/hdrline.c --- mutt-1.3.8-dist/hdrline.c Mon Aug 28 04:38:01 2000 +++ mutt-1.3.8/hdrline.c Sat Sep 9 22:10:20 2000 @@ -217,10 +217,11 @@ * %S = short message status (e.g., N/O/D/!/r/-) * %t = `to:' field (recipients) * %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 */ struct hdr_format_info @@ -632,10 +633,36 @@ (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; + + 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 'y': if (optional) optional = hdr->env->x_label ? 1 : 0; mutt_format_s (dest, destlen, prefix, NONULL (hdr->env->x_label)); diff -rU5 mutt-1.3.8-dist/init.h mutt-1.3.8/init.h --- mutt-1.3.8-dist/init.h Mon Aug 21 10:42:09 2000 +++ mutt-1.3.8/init.h Sat Sep 9 22:07:26 2000 @@ -215,10 +215,29 @@ ** etc) on a list of tagged attachments, Mutt will concatenate the ** attachments and will operate on them as a single attachment. The ** ``$$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 ** This is the string that will precede a message which has been included ** in a reply. For a full listing of defined escape sequences see the @@ -787,10 +806,11 @@ ** .dt %S .dd status of the message (N/D/d/!/r/\(as) ** .dt %t .dd `to:' field (recipients) ** .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 ** preceding message's `x-label'. ** .dt %Z .dd message status flags diff -rU5 mutt-1.3.8-dist/mutt.h mutt-1.3.8/mutt.h --- mutt-1.3.8-dist/mutt.h Fri Jul 28 03:52:12 2000 +++ mutt-1.3.8/mutt.h Sat Sep 9 22:07:26 2000 @@ -209,10 +209,11 @@ M_PGP_SIGN, M_PGP_ENCRYPT, M_PGP_KEY, #endif M_XLABEL, + M_MIMEATTACH, /* Options for Mailcap lookup */ M_EDIT, M_COMPOSE, M_PRINT, @@ -366,10 +367,14 @@ OPTWRAP, OPTWRAPSEARCH, OPTWRITEBCC, /* write out a bcc header? */ OPTXMAILER, + OPTATINLINEOK, /* Count inline attachments? */ + OPTATCONTAINERSOK, /* Count containing messages? */ + OPTATRECURSE, /* Recurse message/\* types? */ + /* PGP options */ #ifdef HAVE_PGP OPTPGPAUTOSIGN, OPTPGPAUTOENCRYPT, @@ -730,9 +735,15 @@ #define state_puts(x,y) fputs(x,(y)->fpout) #define state_putc(x,y) fputc(x,(y)->fpout) 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" #include "globals.h" diff -rU5 mutt-1.3.8-dist/parse.c mutt-1.3.8/parse.c --- mutt-1.3.8-dist/parse.c Tue Aug 22 16:26:25 2000 +++ mutt-1.3.8/parse.c Sat Sep 9 22:07:26 2000 @@ -1365,5 +1365,100 @@ else 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; +} diff -rU5 mutt-1.3.8-dist/pattern.c mutt-1.3.8/pattern.c --- mutt-1.3.8-dist/pattern.c Fri Jun 9 12:42:14 2000 +++ mutt-1.3.8/pattern.c Sat Sep 9 22:07:26 2000 @@ -85,10 +85,11 @@ { 'S', M_SUPERSEDED, 0, NULL }, { 'T', M_TAG, 0, NULL }, { '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 }, { 0 } }; @@ -891,10 +892,27 @@ case M_PGP_KEY: return (pat->not ^ (h->pgp & PGPKEY)); #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 -rU5 mutt-1.3.8-dist/protos.h mutt-1.3.8/protos.h --- mutt-1.3.8-dist/protos.h Mon Aug 28 04:38:01 2000 +++ mutt-1.3.8/protos.h Sat Sep 9 22:07:26 2000 @@ -137,10 +137,11 @@ void mutt_block_signals_system (void); void mutt_body_handler (BODY *, STATE *); 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 *); void mutt_decode_attachment (BODY *, STATE *); void mutt_default_save (char *, size_t, HEADER *);