diff -r -p -u mutt-1.5.20/OPS mutt-1.5.20.patched/OPS --- mutt-1.5.20/OPS 2009-05-13 01:01:13.000000000 -0400 +++ mutt-1.5.20.patched/OPS 2009-07-23 16:41:04.000000000 -0400 @@ -178,3 +178,4 @@ OP_WHAT_KEY "display the keycode for a k OP_MAIN_SHOW_LIMIT "show currently active limit pattern" OP_MAIN_COLLAPSE_THREAD "collapse/uncollapse current thread" OP_MAIN_COLLAPSE_ALL "collapse/uncollapse all threads" +OP_MAIN_IGNORE_THREAD "toggle a message's 'ignore-thread' flag" diff -r -p -u mutt-1.5.20/copy.c mutt-1.5.20.patched/copy.c --- mutt-1.5.20/copy.c 2009-06-12 19:38:52.000000000 -0400 +++ mutt-1.5.20.patched/copy.c 2009-07-23 16:49:06.000000000 -0400 @@ -393,7 +393,7 @@ mutt_copy_header (FILE *in, HEADER *h, F fputc ('\n', out); } - if (h->flagged || h->replied) + if (h->flagged || h->replied || h->ignore_thread) { fputs ("X-Status: ", out); if (h->replied) @@ -404,6 +404,11 @@ mutt_copy_header (FILE *in, HEADER *h, F } } + if (h->ignore_thread) + { + fputc (M_XSTATUS_IGNORE_THREAD, out); + } + if (flags & CH_UPDATE_LEN && (flags & CH_NOLEN) == 0) { Only in mutt-1.5.20.patched: copy.c.orig Only in mutt-1.5.20.patched: copy.c.rej diff -r -p -u mutt-1.5.20/curs_main.c mutt-1.5.20.patched/curs_main.c --- mutt-1.5.20/curs_main.c 2009-06-13 22:48:36.000000000 -0400 +++ mutt-1.5.20.patched/curs_main.c 2009-07-23 16:50:31.000000000 -0400 @@ -321,6 +321,7 @@ static void update_index (MUTTMENU *menu mutt_sort_headers (ctx, (check == M_REOPENED)); /* uncollapse threads with new mail */ + /* let threads collapsed if they have the ignore-thread flag */ if ((Sort & SORT_MASK) == SORT_THREADS) { if (check == M_REOPENED) @@ -333,7 +334,8 @@ static void update_index (MUTTMENU *menu { for (j = h; !j->message; j = j->child) ; - mutt_uncollapse_thread (ctx, j->message); + if (!(j->message)->ignore_thread) + mutt_uncollapse_thread (ctx, j->message); } mutt_set_virtual (ctx); } @@ -346,7 +348,8 @@ static void update_index (MUTTMENU *menu for (k = 0; k < ctx->msgcount; k++) { HEADER *h = ctx->hdrs[k]; - if (h == save_new[j] && (!ctx->pattern || h->limited)) + if (h == save_new[j] && (!ctx->pattern || h->limited) && + !h->ignore_thread) mutt_uncollapse_thread (ctx, h); } } @@ -420,6 +423,7 @@ int mutt_index_menu (void) { char buf[LONG_STRING], helpstr[LONG_STRING]; int op = OP_NULL; + int prev_op = OP_NULL; int done = 0; /* controls when to exit the "event" loop */ int i = 0, j; int tag = 0; /* has the tag-prefix command been pressed? */ @@ -1170,13 +1174,15 @@ int mutt_index_menu (void) unset_option (OPTNEEDRESORT); - if ((Sort & SORT_MASK) == SORT_THREADS && CURHDR->collapsed) + if ((Sort & SORT_MASK) == SORT_THREADS && CURHDR->collapsed && + !CURHDR->ignore_thread && prev_op != OP_MAIN_COLLAPSE_THREAD) { mutt_uncollapse_thread (Context, CURHDR); mutt_set_virtual (Context); if (option (OPTUNCOLLAPSEJUMP)) menu->current = mutt_thread_next_unread (Context, CURHDR); } + prev_op = OP_NULL; if (option (OPTPGPAUTODEC) && (tag || !(CURHDR->security & PGP_TRADITIONAL_CHECKED))) mutt_check_traditional_pgp (tag ? NULL : CURHDR, &menu->redraw); @@ -1466,10 +1472,14 @@ int mutt_index_menu (void) if (CURHDRi->collapsed && (Sort & SORT_MASK) == SORT_THREADS) { - if (UNREAD (CURHDRi) && first_unread == -1) - first_unread = i; - if (UNREAD (CURHDRi) == 1 && first_new == -1) - first_new = i; + /* include collapsed threads only if they dont have the ignore-thread flag */ + if (!CURHDRi->ignore_thread) + { + if (UNREAD (CURHDRi) && first_unread == -1) + first_unread = i; + if (UNREAD (CURHDRi) == 1 && first_new == -1) + first_new = i; + } } else if ((!CURHDRi->deleted && !CURHDRi->read)) { @@ -1718,6 +1728,51 @@ int mutt_index_menu (void) break; } + if (menu->menu == MENU_PAGER) + { + prev_op = op; + op = OP_DISPLAY_MESSAGE; + continue; + } + + menu->redraw = REDRAW_INDEX | REDRAW_STATUS; + + break; + + case OP_MAIN_IGNORE_THREAD: + CHECK_MSGCOUNT; + CHECK_VISIBLE; + CHECK_READONLY; + + if ((Sort & SORT_MASK) != SORT_THREADS) + { + mutt_error _("Threading is not enabled."); + break; + } + + if (CURHDR->ignore_thread) + { + mutt_unignore_thread (Context, CURHDR); + if (CURHDR->collapsed) + menu->current = mutt_uncollapse_thread (Context, CURHDR); + mutt_set_virtual (Context); + if (option (OPTUNCOLLAPSEJUMP)) + menu->current = mutt_thread_next_unread (Context, CURHDR); + } + else + { + mutt_ignore_thread (Context, CURHDR); + if (!CURHDR->collapsed) + menu->current = mutt_collapse_thread (Context, CURHDR); + mutt_set_virtual (Context); + } + + if (menu->menu == MENU_PAGER) + { + op = OP_DISPLAY_MESSAGE; + continue; + } + menu->redraw = REDRAW_INDEX | REDRAW_STATUS; break; @@ -1732,6 +1787,12 @@ int mutt_index_menu (void) break; } + if (CURHDR->ignore_thread) + { + mutt_error _("'un/collapse-all' cannot start from a ignored thread."); + break; + } + { HEADER *h, *base; THREAD *thread, *top; @@ -1757,7 +1818,10 @@ int mutt_index_menu (void) if (h->collapsed != Context->collapsed) { if (h->collapsed) - mutt_uncollapse_thread (Context, h); + { + if (!h->ignore_thread) + mutt_uncollapse_thread (Context, h); + } else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (h)) mutt_collapse_thread (Context, h); } Only in mutt-1.5.20.patched: curs_main.c.orig Only in mutt-1.5.20.patched: curs_main.c.rej diff -r -p -u mutt-1.5.20/flags.c mutt-1.5.20.patched/flags.c --- mutt-1.5.20/flags.c 2008-12-16 22:50:09.000000000 -0500 +++ mutt-1.5.20.patched/flags.c 2009-07-23 16:41:04.000000000 -0400 @@ -252,6 +252,30 @@ void _mutt_set_flag (CONTEXT *ctx, HEADE if (upd_ctx) ctx->tagged--; } break; + + case M_IGNORE_THREAD: + + if (!mutt_bit_isset(ctx->rights,M_ACL_WRITE)) + return; + + if (bf) + { + if (!h->ignore_thread) + { + h->ignore_thread = 1; + h->changed = 1; + if (upd_ctx) ctx->changed = 1; + update = 1; + } + } + else if (h->ignore_thread) + { + update = 1; + h->ignore_thread = 0; + h->changed = 1; + if (upd_ctx) ctx->changed = 1; + } + break; } if (update) Only in mutt-1.5.20.patched: flags.c.orig diff -r -p -u mutt-1.5.20/functions.h mutt-1.5.20.patched/functions.h --- mutt-1.5.20/functions.h 2009-04-30 01:36:17.000000000 -0400 +++ mutt-1.5.20.patched/functions.h 2009-07-23 16:41:04.000000000 -0400 @@ -166,6 +166,7 @@ struct binding_t OpMain[] = { /* map: in { "mail-key", OP_MAIL_KEY, "\033k" }, { "decrypt-copy", OP_DECRYPT_COPY, NULL }, { "decrypt-save", OP_DECRYPT_SAVE, NULL }, + { "ignore-thread", OP_MAIN_IGNORE_THREAD, NULL }, { NULL, 0, NULL } @@ -209,6 +210,8 @@ struct binding_t OpPager[] = { /* map: p { "print-message", OP_PRINT, "p" }, { "previous-thread", OP_MAIN_PREV_THREAD, "\020" }, { "previous-subthread",OP_MAIN_PREV_SUBTHREAD, "\033p" }, + { "collapse-thread", OP_MAIN_COLLAPSE_THREAD, "\033v" }, + { "ignore-thread", OP_MAIN_IGNORE_THREAD, NULL }, { "quit", OP_QUIT, "Q" }, { "exit", OP_EXIT, "q" }, { "reply", OP_REPLY, "r" }, Only in mutt-1.5.20.patched: functions.h.orig diff -r -p -u mutt-1.5.20/hdrline.c mutt-1.5.20.patched/hdrline.c --- mutt-1.5.20/hdrline.c 2009-04-13 12:24:55.000000000 -0400 +++ mutt-1.5.20.patched/hdrline.c 2009-07-23 16:41:04.000000000 -0400 @@ -252,6 +252,8 @@ hdr_format_str (char *dest, int is_index = (flags & M_FORMAT_INDEX); #define THREAD_NEW (threads && hdr->collapsed && hdr->num_hidden > 1 && mutt_thread_contains_unread (ctx, hdr) == 1) #define THREAD_OLD (threads && hdr->collapsed && hdr->num_hidden > 1 && mutt_thread_contains_unread (ctx, hdr) == 2) +#define THREAD_IGNORE_NEW (THREAD_NEW && hdr->ignore_thread) +#define THREAD_IGNORE_UNREAD (THREAD_OLD && hdr->ignore_thread) size_t len; hdr = hfi->hdr; @@ -574,6 +576,11 @@ hdr_format_str (char *dest, ch = '*'; else if (hdr->flagged) ch = '!'; + else if (hdr->ignore_thread) + if (hdr->read) + ch = 'i'; + else + ch = 'I'; else if (hdr->replied) ch = 'r'; else if (hdr->read && (ctx && ctx->msgnotreadyet != hdr->msgno)) @@ -651,9 +658,12 @@ hdr_format_str (char *dest, ch = 'K'; snprintf (buf2, sizeof (buf2), - "%c%c%c", (THREAD_NEW ? 'n' : (THREAD_OLD ? 'o' : + "%c%c%c", ((THREAD_IGNORE_NEW || THREAD_IGNORE_UNREAD || + (threads && hdr->ignore_thread && !hdr->read)) ? 'I' : + (threads && hdr->ignore_thread ? 'i' : ( + THREAD_NEW ? 'n' : (THREAD_OLD ? 'o' : ((hdr->read && (ctx && ctx->msgnotreadyet != hdr->msgno)) - ? (hdr->replied ? 'r' : ' ') : (hdr->old ? 'O' : 'N')))), + ? (hdr->replied ? 'r' : ' ') : (hdr->old ? 'O' : 'N')))))), hdr->deleted ? 'D' : (hdr->attach_del ? 'd' : ch), hdr->tagged ? '*' : (hdr->flagged ? '!' : @@ -724,6 +734,8 @@ hdr_format_str (char *dest, return (src); #undef THREAD_NEW #undef THREAD_OLD +#undef THREAD_IGNORE_NEW +#undef THREAD_IGNORE_UNREAD } void Only in mutt-1.5.20.patched: hdrline.c.orig diff -r -p -u mutt-1.5.20/imap/imap.c mutt-1.5.20.patched/imap/imap.c --- mutt-1.5.20/imap/imap.c 2009-06-14 13:19:16.000000000 -0400 +++ mutt-1.5.20.patched/imap/imap.c 2009-07-23 16:51:17.000000000 -0400 @@ -897,6 +897,9 @@ static int imap_make_msg_set (IMAP_DATA* if (hdrs[n]->flagged != HEADER_DATA(hdrs[n])->flagged) match = invert ^ hdrs[n]->flagged; break; + case M_IGNORE_THREAD: + if (hdrs[n]->ignore_thread != HEADER_DATA(hdrs[n])->ignore_thread) + match = invert ^ hdrs[n]->ignore_thread; case M_OLD: if (hdrs[n]->old != HEADER_DATA(hdrs[n])->old) match = invert ^ hdrs[n]->old; @@ -1039,6 +1042,8 @@ static int compare_flags (HEADER* h) return 1; if (h->deleted != hd->deleted) return 1; + if (h->ignore_thread != hd->ignore_thread) + return 1; return 0; } @@ -1071,6 +1076,8 @@ int imap_sync_message (IMAP_DATA *idata, "Old ", flags, sizeof (flags)); imap_set_flag (idata, M_ACL_WRITE, hdr->flagged, "\\Flagged ", flags, sizeof (flags)); + imap_set_flag (idata, M_ACL_WRITE, hdr->ignore_thread, + "ignoreThread ", flags, sizeof (flags)); imap_set_flag (idata, M_ACL_WRITE, hdr->replied, "\\Answered ", flags, sizeof (flags)); imap_set_flag (idata, M_ACL_DELETE, hdr->deleted, @@ -1089,6 +1096,8 @@ int imap_sync_message (IMAP_DATA *idata, imap_set_flag (idata, M_ACL_SEEN, 1, "\\Seen ", flags, sizeof (flags)); imap_set_flag (idata, M_ACL_WRITE, 1, "Old ", flags, sizeof (flags)); imap_set_flag (idata, M_ACL_WRITE, 1, "\\Flagged ", flags, sizeof (flags)); + imap_set_flag (idata, M_ACL_WRITE, 1, "ignoreThread ", flags, sizeof + (flags)); imap_set_flag (idata, M_ACL_WRITE, 1, "\\Answered ", flags, sizeof (flags)); imap_set_flag (idata, M_ACL_DELETE, 1, "\\Deleted ", flags, sizeof (flags)); @@ -1264,6 +1273,7 @@ int imap_sync_mailbox (CONTEXT* ctx, int rc += sync_helper (idata, M_ACL_WRITE, M_OLD, "Old"); rc += sync_helper (idata, M_ACL_SEEN, M_READ, "\\Seen"); rc += sync_helper (idata, M_ACL_WRITE, M_REPLIED, "\\Answered"); + rc += sync_helper (idata, M_ACL_WRITE, M_IGNORE_THREAD, "ignoreThread"); if (oldsort != Sort) { Only in mutt-1.5.20.patched/imap: imap.c.orig Only in mutt-1.5.20.patched/imap: imap.c.rej diff -r -p -u mutt-1.5.20/imap/message.c mutt-1.5.20.patched/imap/message.c --- mutt-1.5.20/imap/message.c 2009-06-07 13:52:57.000000000 -0400 +++ mutt-1.5.20.patched/imap/message.c 2009-07-23 16:41:04.000000000 -0400 @@ -196,6 +196,7 @@ int imap_read_headers (IMAP_DATA* idata, ctx->hdrs[idx]->old = h.data->old; ctx->hdrs[idx]->deleted = h.data->deleted; ctx->hdrs[idx]->flagged = h.data->flagged; + ctx->hdrs[idx]->ignore_thread = h.data->ignore_thread; ctx->hdrs[idx]->replied = h.data->replied; ctx->hdrs[idx]->changed = h.data->changed; /* ctx->hdrs[msgno]->received is restored from mutt_hcache_restore */ @@ -305,6 +306,7 @@ int imap_read_headers (IMAP_DATA* idata, ctx->hdrs[idx]->old = h.data->old; ctx->hdrs[idx]->deleted = h.data->deleted; ctx->hdrs[idx]->flagged = h.data->flagged; + ctx->hdrs[idx]->ignore_thread = h.data->ignore_thread; ctx->hdrs[idx]->replied = h.data->replied; ctx->hdrs[idx]->changed = h.data->changed; ctx->hdrs[idx]->received = h.received; @@ -1043,6 +1045,7 @@ char* imap_set_flags (IMAP_DATA* idata, mutt_set_flag (ctx, h, M_READ, hd->read); mutt_set_flag (ctx, h, M_DELETE, hd->deleted); mutt_set_flag (ctx, h, M_FLAG, hd->flagged); + mutt_set_flag (ctx, h, M_IGNORE_THREAD, hd->ignore_thread); mutt_set_flag (ctx, h, M_REPLIED, hd->replied); /* this message is now definitively *not* changed (mutt_set_flag @@ -1212,7 +1215,7 @@ static char* msg_parse_flags (IMAP_HEADE s++; mutt_free_list (&hd->keywords); - hd->deleted = hd->flagged = hd->replied = hd->read = hd->old = 0; + hd->deleted = hd->flagged = hd->replied = hd->read = hd->old = hd->ignore_thread = 0; /* start parsing */ while (*s && *s != ')') @@ -1227,6 +1230,11 @@ static char* msg_parse_flags (IMAP_HEADE s += 8; hd->flagged = 1; } + else if (ascii_strncasecmp ("ignorethread", s, 12) == 0) + { + s += 12; + hd->ignore_thread = 1; + } else if (ascii_strncasecmp ("\\answered", s, 9) == 0) { s += 9; Only in mutt-1.5.20.patched/imap: message.c.orig diff -r -p -u mutt-1.5.20/imap/message.h mutt-1.5.20.patched/imap/message.h --- mutt-1.5.20/imap/message.h 2009-01-04 17:27:34.000000000 -0500 +++ mutt-1.5.20.patched/imap/message.h 2009-07-23 16:41:04.000000000 -0400 @@ -33,6 +33,7 @@ typedef struct imap_header_data unsigned int flagged : 1; unsigned int replied : 1; unsigned int changed : 1; + unsigned int ignore_thread : 1; unsigned int parsed : 1; diff -r -p -u mutt-1.5.20/mailbox.h mutt-1.5.20.patched/mailbox.h --- mutt-1.5.20/mailbox.h 2009-04-30 01:36:17.000000000 -0400 +++ mutt-1.5.20.patched/mailbox.h 2009-07-23 16:41:04.000000000 -0400 @@ -28,6 +28,9 @@ * safe_fopen() for mbox-style folders. */ +#define M_XSTATUS_IGNORE_THREAD 'I' /* char for saving ignore-thread to X-Status */ + + /* mx_open_new_message() */ #define M_ADD_FROM 1 /* add a From_ line */ diff -r -p -u mutt-1.5.20/mbox.c mutt-1.5.20.patched/mbox.c --- mutt-1.5.20/mbox.c 2009-06-11 00:29:41.000000000 -0400 +++ mutt-1.5.20.patched/mbox.c 2009-07-23 16:41:04.000000000 -0400 @@ -1198,6 +1198,7 @@ int mutt_reopen_mailbox (CONTEXT *ctx, i */ mutt_set_flag (ctx, ctx->hdrs[i], M_FLAG, old_hdrs[j]->flagged); mutt_set_flag (ctx, ctx->hdrs[i], M_REPLIED, old_hdrs[j]->replied); + mutt_set_flag (ctx, ctx->hdrs[i], M_IGNORE_THREAD, old_hdrs[j]->ignore_thread); mutt_set_flag (ctx, ctx->hdrs[i], M_OLD, old_hdrs[j]->old); mutt_set_flag (ctx, ctx->hdrs[i], M_READ, old_hdrs[j]->read); } Only in mutt-1.5.20.patched: mbox.c.orig diff -r -p -u mutt-1.5.20/mutt.h mutt-1.5.20.patched/mutt.h --- mutt-1.5.20/mutt.h 2009-06-12 18:15:42.000000000 -0400 +++ mutt-1.5.20.patched/mutt.h 2009-07-23 16:41:04.000000000 -0400 @@ -168,6 +168,9 @@ typedef enum #define M_THREAD_GET_HIDDEN (1<<2) #define M_THREAD_UNREAD (1<<3) #define M_THREAD_NEXT_UNREAD (1<<4) +#define M_THREAD_IGNORE (1<<5) +#define M_THREAD_UNIGNORE (1<<6) + enum { @@ -193,6 +196,7 @@ enum M_LIMIT, M_EXPIRED, M_SUPERSEDED, + M_IGNORE_THREAD, /* actions for mutt_pattern_comp/mutt_pattern_exec */ M_AND, @@ -734,6 +738,7 @@ typedef struct header /* the following are used to support collapsing threads */ unsigned int collapsed : 1; /* is this message part of a collapsed thread? */ unsigned int limited : 1; /* is this message in a limited view? */ + unsigned int ignore_thread : 1; /* is this message part of a ignored thread? */ size_t num_hidden; /* number of hidden messages in this view */ short recipient; /* user_is_recipient()'s return value, cached */ Only in mutt-1.5.20.patched: mutt.h.orig diff -r -p -u mutt-1.5.20/pager.c mutt-1.5.20.patched/pager.c --- mutt-1.5.20/pager.c 2009-06-03 16:48:31.000000000 -0400 +++ mutt-1.5.20.patched/pager.c 2009-07-23 16:41:04.000000000 -0400 @@ -2261,6 +2261,19 @@ search_next: km_error_key (MENU_PAGER); break; + case OP_MAIN_COLLAPSE_THREAD: + CHECK_MODE(IsHeader (extra)); + rc = OP_MAIN_COLLAPSE_THREAD; + ch = -1; + break; + + case OP_MAIN_IGNORE_THREAD: + CHECK_MODE(IsHeader (extra)); + CHECK_READONLY; + rc = OP_MAIN_IGNORE_THREAD; + ch = -1; + break; + /* -------------------------------------------------------------------- * The following are operations on the current message rather than * adjusting the view of the message. Only in mutt-1.5.20.patched: pager.c.orig diff -r -p -u mutt-1.5.20/parse.c mutt-1.5.20.patched/parse.c --- mutt-1.5.20/parse.c 2009-06-01 12:29:32.000000000 -0400 +++ mutt-1.5.20.patched/parse.c 2009-07-23 16:41:04.000000000 -0400 @@ -1244,6 +1244,9 @@ int mutt_parse_rfc822_line (ENVELOPE *e, case 'F': hdr->flagged = 1; break; + case M_XSTATUS_IGNORE_THREAD: + hdr->ignore_thread = 1; + break; default: break; } Only in mutt-1.5.20.patched: parse.c.orig diff -r -p -u mutt-1.5.20/protos.h mutt-1.5.20.patched/protos.h --- mutt-1.5.20/protos.h 2009-06-12 19:38:52.000000000 -0400 +++ mutt-1.5.20.patched/protos.h 2009-07-23 16:41:04.000000000 -0400 @@ -62,6 +62,8 @@ int _mutt_aside_thread (HEADER *, short, #define mutt_get_hidden(x,y)_mutt_traverse_thread (x,y,M_THREAD_GET_HIDDEN) #define mutt_thread_contains_unread(x,y) _mutt_traverse_thread (x,y,M_THREAD_UNREAD) #define mutt_thread_next_unread(x,y) _mutt_traverse_thread(x,y,M_THREAD_NEXT_UNREAD) +#define mutt_ignore_thread(x,y) _mutt_traverse_thread (x,y,M_THREAD_IGNORE) +#define mutt_unignore_thread(x,y) _mutt_traverse_thread (x,y,M_THREAD_UNIGNORE) int _mutt_traverse_thread (CONTEXT *ctx, HEADER *hdr, int flag); diff -r -p -u mutt-1.5.20/sort.c mutt-1.5.20.patched/sort.c --- mutt-1.5.20/sort.c 2008-11-11 14:55:47.000000000 -0500 +++ mutt-1.5.20.patched/sort.c 2009-07-23 16:41:04.000000000 -0400 @@ -321,6 +321,7 @@ void mutt_sort_headers (CONTEXT *ctx, in } /* re-collapse threads marked as collapsed */ + /* and threads marked for ignoring if it is a "init-sort" */ if ((Sort & SORT_MASK) == SORT_THREADS) { top = ctx->tree; @@ -330,7 +331,7 @@ void mutt_sort_headers (CONTEXT *ctx, in thread = thread->child; h = thread->message; - if (h->collapsed) + if (h->collapsed || (h->ignore_thread && init)) mutt_collapse_thread (ctx, h); top = top->next; } diff -r -p -u mutt-1.5.20/thread.c mutt-1.5.20.patched/thread.c --- mutt-1.5.20/thread.c 2009-03-31 02:52:43.000000000 -0400 +++ mutt-1.5.20.patched/thread.c 2009-07-23 16:41:04.000000000 -0400 @@ -116,6 +116,69 @@ static void linearize_tree (CONTEXT *ctx } } +/* check if all messages in a ignored thread have the ignore-tread status */ +static void mutt_check_ignore_thread (CONTEXT *ctx) +{ + THREAD *thread, *top; + HEADER *roothdr; + int ignore_thread, missing_count; + + thread = ctx->tree; + while (thread) + { + ignore_thread = 0; + missing_count = 0; + roothdr = NULL; + + top = thread; + while (!thread->message) + thread = thread->child; + + FOREVER + { + if (thread->message) + { + if (!roothdr) + roothdr = thread->message; + + if ((thread->message)->ignore_thread) + ignore_thread = 1; + else + missing_count++; + } + + if (thread->child) + thread = thread->child; + else if (thread == top) + break; + else if (thread->next) + thread = thread->next; + else + { + int done = 0; + while (!thread->next) + { + thread = thread->parent; + if (thread == top) + { + done = 1; + break; + } + } + if (done) + break; + thread = thread->next; + } + } + if (ignore_thread && missing_count) + { + mutt_ignore_thread(ctx, roothdr); + } + thread = thread->next; + } +} + + /* this calculates whether a node is the root of a subtree that has visible * nodes, whether a node itself is visible, whether, if invisible, it has * depth anyway, and whether any of its later siblings are roots of visible @@ -971,6 +1034,10 @@ void mutt_sort_threads (CONTEXT *ctx, in /* Draw the thread tree. */ mutt_draw_tree (ctx); + + /* check if all messages in a ignored tree have the ignore-thread status */ + mutt_check_ignore_thread(ctx); + } } @@ -1175,6 +1242,13 @@ int _mutt_traverse_thread (CONTEXT *ctx, } } + if (flag & (M_THREAD_IGNORE | M_THREAD_UNIGNORE)) + { + cur->pair = 0; /* force index entry's color to be re-evaluated */ + mutt_set_flag (ctx, cur, M_IGNORE_THREAD, flag & M_THREAD_IGNORE); + } + + if (thread == top && (thread = thread->child) == NULL) { /* return value depends on action requested */ @@ -1186,6 +1260,8 @@ int _mutt_traverse_thread (CONTEXT *ctx, return (num_hidden); else if (flag & M_THREAD_NEXT_UNREAD) return (min_unread); + else if (flag & (M_THREAD_IGNORE | M_THREAD_UNIGNORE)) + return (1); } FOREVER @@ -1224,6 +1300,13 @@ int _mutt_traverse_thread (CONTEXT *ctx, } + if (flag & (M_THREAD_IGNORE | M_THREAD_UNIGNORE)) + { + cur->pair = 0; /* force index entry's color to be re-evaluated */ + mutt_set_flag (ctx, cur, M_IGNORE_THREAD, flag & M_THREAD_IGNORE); + } + + if (!cur->read && CHECK_LIMIT) { if (cur->old) @@ -1272,6 +1355,8 @@ int _mutt_traverse_thread (CONTEXT *ctx, return (num_hidden+1); else if (flag & M_THREAD_NEXT_UNREAD) return (min_unread); + else if (flag & (M_THREAD_IGNORE | M_THREAD_UNIGNORE)) + return (1); return (0); #undef CHECK_LIMIT