Commit a56c4be8 authored by Thomas Roessler's avatar Thomas Roessler

[patch-0.94.4.vikas.collapse.2] Vikas' collapse-thread

patch.
parent 31beda39
......@@ -144,3 +144,5 @@ OP_VERSION "show the Mutt version number and date"
OP_VIEW_ATTACH "view attachment using mailcap entry if necessary"
OP_VIEW_ATTACHMENTS "show MIME attachments"
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"
......@@ -69,6 +69,7 @@
#define CURHDR Context->hdrs[Context->v2r[menu->current]]
#define OLDHDR Context->hdrs[Context->v2r[menu->oldcurrent]]
#define UNREAD(h) mutt_thread_contains_unread (Context, h)
extern const char *ReleaseDate;
......@@ -124,7 +125,7 @@ void index_make_entry (char *s, size_t l, MUTTMENU *menu, int num)
}
}
_mutt_make_string (s, l, NONULL (HdrFmt), Context, h, flag);
_mutt_make_string (s, l, NONULL (HdrFmt), Context, h, flag | M_FORMAT_INDEX);
}
int index_color (int index_no)
......@@ -267,13 +268,14 @@ int mutt_index_menu (int attach_msg /* invoked while attaching a message */)
if (Context && !attach_msg)
{
int check;
/* check for new mail in the mailbox. If nonzero, then something has
* changed about the file (either we got new mail or the file was
* modified underneath us.)
*/
index_hint = (Context->vcount) ? CURHDR->index : 0;
if ((i = mx_check_mailbox (Context, &index_hint)) < 0)
if ((check = mx_check_mailbox (Context, &index_hint)) < 0)
{
if (!Context->path)
{
......@@ -284,8 +286,10 @@ int mutt_index_menu (int attach_msg /* invoked while attaching a message */)
set_option (OPTSEARCHINVALID);
}
else if (i == M_NEW_MAIL || i == M_REOPENED)
else if (check == M_NEW_MAIL || check == M_REOPENED)
{
int *save_new;
/* take note of the current message */
if (oldcount)
{
......@@ -300,32 +304,75 @@ int mutt_index_menu (int attach_msg /* invoked while attaching a message */)
* they will be visible in the limited view */
if (Context->pattern)
{
#define this_body Context->hdrs[i]->content
if (oldcount)
for (i = oldcount; i < Context->msgcount; i++)
#define THIS_BODY Context->hdrs[j]->content
if (oldcount || check == M_REOPENED)
for (j = (check == M_REOPENED) ? 0 : oldcount; j < Context->msgcount; j++)
{
if (mutt_pattern_exec (Context->limit_pattern,
M_MATCH_FULL_ADDRESS,
Context, Context->hdrs[i]))
Context, Context->hdrs[j]))
{
Context->hdrs[i]->virtual = Context->vcount;
Context->v2r[Context->vcount] = i;
Context->vcount++;
Context->vsize+=this_body->length + this_body->offset -
this_body->hdr_offset;
Context->hdrs[j]->virtual = Context->vcount;
Context->v2r[Context->vcount] = j;
Context->hdrs[j]->limited = 1;
Context->vcount++;
Context->vsize += THIS_BODY->length + THIS_BODY->offset - THIS_BODY->hdr_offset;
}
}
#undef this_body
#undef THIS_BODY
}
/* save the list of new messages */
if (oldcount && check != M_REOPENED)
{
save_new = (int *) safe_malloc (sizeof (int) * (Context->msgcount - oldcount));
for (j = oldcount; j < Context->msgcount; j++)
save_new[j-oldcount] = Context->hdrs[j]->index;
}
/* if the mailbox was reopened, need to rethread from scratch */
mutt_sort_headers (Context, (i == M_REOPENED));
set_option (OPTSORTCOLLAPSE);
mutt_sort_headers (Context, (check == M_REOPENED));
unset_option (OPTSORTCOLLAPSE);
/* uncollapse threads with new mail */
if ((Sort & SORT_MASK) == SORT_THREADS)
{
if (check == M_REOPENED)
{
HEADER *h;
h = Context->tree;
Context->collapsed = 0;
while (h)
{
mutt_uncollapse_thread (Context, h);
h = h->next;
}
mutt_set_virtual (Context);
}
else if (oldcount)
{
for (j = 0; j < Context->msgcount - oldcount; j++)
{
int k;
for (k = 0; k < Context->msgcount; k++)
{
HEADER *h = Context->hdrs[k];
if (h->index == save_new[j] && (!Context->pattern || h->limited))
mutt_uncollapse_thread (Context, h);
}
}
FREE (&save_new);
mutt_set_virtual (Context);
}
}
menu->current = -1;
if (oldcount)
{
int j;
/* restore the current message to the message it was pointing to */
for (j = 0; j < Context->vcount; j++)
if (Context->hdrs[Context->v2r[j]]->index == menu->oldcurrent)
......@@ -339,7 +386,7 @@ int mutt_index_menu (int attach_msg /* invoked while attaching a message */)
menu->current = ci_first_message ();
/* notify the user of new mail */
if (i == M_REOPENED)
if (check == M_REOPENED)
mutt_error ("Mailbox was externally modified. Flags may be wrong.");
else
{
......@@ -882,7 +929,14 @@ int mutt_index_menu (int attach_msg /* invoked while attaching a message */)
toggle_option (OPTWEED);
unset_option (OPTNEEDRESORT);
if ((Sort & SORT_MASK) == SORT_THREADS && CURHDR->collapsed)
{
mutt_uncollapse_thread (Context, CURHDR);
mutt_set_virtual (Context);
if (option (OPTUNCOLLAPSEJUMPNEW))
menu->current = mutt_thread_next_new (Context, CURHDR);
}
if ((op = mutt_display_message (CURHDR, attach_msg_status)) == -1)
{
unset_option (OPTNEEDRESORT);
......@@ -1045,6 +1099,7 @@ int mutt_index_menu (int attach_msg /* invoked while attaching a message */)
menu->current = -1;
for (j = 0; j != Context->vcount; j++)
{
#define CUR Context->hdrs[Context->v2r[i]]
if (op == OP_MAIN_NEXT_NEW || op == OP_MAIN_NEXT_UNREAD)
{
i++;
......@@ -1064,22 +1119,25 @@ int mutt_index_menu (int attach_msg /* invoked while attaching a message */)
}
}
if (! Context->hdrs[Context->v2r[i]]->deleted &&
! Context->hdrs[Context->v2r[i]]->read)
if ((!CUR->deleted && !CUR->read) ||
(CUR->collapsed && !CUR->deleted && UNREAD (CUR)))
{
if (op == OP_MAIN_NEXT_UNREAD || op == OP_MAIN_PREV_UNREAD ||
! Context->hdrs[Context->v2r[i]]->old)
!CUR->old)
{
menu->current = i;
break;
}
}
}
#undef CUR
if (menu->current == -1)
{
char *tmp = "";
menu->current = menu->oldcurrent;
mutt_error ((op == OP_MAIN_NEXT_NEW || op == OP_MAIN_PREV_NEW) ?
"No new messages." : "No unread messages.");
if (Context->pattern)
tmp = " in this limited view";
mutt_error ("%s%s.", (op == OP_MAIN_NEXT_NEW || op == OP_MAIN_PREV_NEW) ? "No new messages" : "No unread messages", NONULL (tmp));
}
else if (menu->menu == MENU_PAGER)
{
......@@ -1227,6 +1285,81 @@ int mutt_index_menu (int attach_msg /* invoked while attaching a message */)
}
break;
case OP_MAIN_COLLAPSE_THREAD:
CHECK_MSGCOUNT;
if (CURHDR->collapsed)
{
menu->current = mutt_uncollapse_thread (Context, CURHDR);
mutt_set_virtual (Context);
if (option (OPTUNCOLLAPSEJUMPNEW))
menu->current = mutt_thread_next_new (Context, CURHDR);
}
else if (option (OPTCOLLAPSENEW) || !UNREAD (CURHDR))
{
menu->current = mutt_collapse_thread (Context, CURHDR);
mutt_set_virtual (Context);
}
else
{
mutt_error ("Thread contains unread messages.");
break;
}
menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
break;
case OP_MAIN_COLLAPSE_ALL:
CHECK_MSGCOUNT;
if ((Sort & SORT_MASK) != SORT_THREADS)
{
mutt_error ("Threading is not enabled.");
break;
}
{
HEADER *h, *base;
int final;
if (CURHDR->collapsed)
final = mutt_uncollapse_thread (Context, CURHDR);
else if (option (OPTCOLLAPSENEW) || !UNREAD (CURHDR))
final = mutt_collapse_thread (Context, CURHDR);
else
final = CURHDR->virtual;
base = Context->hdrs[Context->v2r[final]];
h = Context->tree;
Context->collapsed = !Context->collapsed;
while (h)
{
if (h->collapsed != Context->collapsed)
{
if (h->collapsed)
mutt_uncollapse_thread (Context, h);
else if (option (OPTCOLLAPSENEW) || !UNREAD (h))
mutt_collapse_thread (Context, h);
}
h = h->next;
}
mutt_set_virtual (Context);
for (j = 0; j < Context->vcount; j++)
{
if (Context->hdrs[Context->v2r[j]]->index == base->index)
{
menu->current = j;
break;
}
}
menu->redraw = REDRAW_INDEX | REDRAW_STATUS;
break;
}
/* --------------------------------------------------------------------
* These functions are invoked directly from the internal-pager
*/
......
......@@ -68,6 +68,8 @@ struct binding_t OpMain[] = {
{ "bounce-message", OP_BOUNCE_MESSAGE, "b" },
{ "change-folder", OP_MAIN_CHANGE_FOLDER, "c" },
{ "change-folder-readonly", OP_MAIN_CHANGE_FOLDER_READONLY, "\033c" },
{ "collapse-thread", OP_MAIN_COLLAPSE_THREAD, "\033v" },
{ "collapse-all", OP_MAIN_COLLAPSE_ALL, "\033V" },
{ "copy-message", OP_COPY_MESSAGE, "C" },
{ "decode-copy", OP_DECODE_COPY, "\033C" },
{ "decode-save", OP_DECODE_SAVE, "\033s" },
......
......@@ -18,7 +18,7 @@
#include "mutt.h"
#include "mutt_curses.h"
#include "sort.h"
#ifdef _PGPPATH
......@@ -224,6 +224,9 @@ hdr_format_str (char *dest,
char fmt[SHORT_STRING], buf2[SHORT_STRING], ch, *p;
int do_locales, i;
int optional = (flags & M_FORMAT_OPTIONAL);
int threads = ((Sort & SORT_MASK) == SORT_THREADS);
int is_index = (flags & M_FORMAT_INDEX);
#define NEW (threads && hdr->collapsed && hdr->num_hidden > 1 && mutt_thread_contains_unread (ctx, hdr))
size_t len;
hdr = hfi->hdr;
......@@ -446,22 +449,22 @@ hdr_format_str (char *dest,
break;
case 's':
snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
if (flags & M_FORMAT_TREE)
snprintf (fmt, sizeof (fmt), "%s%%%ss", threads && is_index ? " " : "", prefix);
if (threads && is_index && hdr->collapsed && hdr->num_hidden > 1)
snprintf (dest, destlen, "%2d %s", hdr->num_hidden, NONULL(hdr->env->subject));
else if (flags & M_FORMAT_TREE)
{
if (flags & M_FORMAT_FORCESUBJ)
{
snprintf (buf2, sizeof (buf2), "%s%s", hdr->tree,
hdr->env->subject ? hdr->env->subject : "");
snprintf (buf2, sizeof (buf2), "%s%s", hdr->tree, NONULL (hdr->env->subject));
snprintf (dest, destlen, fmt, buf2);
}
else
snprintf (dest, destlen, fmt, hdr->tree);
}
else
{
snprintf (dest, destlen, fmt, hdr->env->subject ? hdr->env->subject : "");
}
snprintf (dest, destlen, fmt, NONULL (hdr->env->subject));
break;
case 'S':
......@@ -544,7 +547,7 @@ hdr_format_str (char *dest,
snprintf (buf2, sizeof (buf2),
"%c%c%c",
(hdr->read && (ctx && ctx->msgnotreadyet != hdr->msgno))
? (hdr->replied ? 'r' : ' ') : (hdr->old ? 'O' : 'N'),
? (NEW ? 'n' : (hdr->replied ? 'r' : ' ')) : (hdr->old ? 'O' : (NEW ? 'n' : 'N')),
hdr->deleted ? 'D' : (hdr->attach_del ? 'd' : ch),
hdr->tagged ? '*' :
(hdr->flagged ? '!' :
......@@ -563,6 +566,7 @@ hdr_format_str (char *dest,
mutt_FormatString (dest, destlen, elsestring, hdr_format_str, (unsigned long) hfi, flags);
return (src);
#undef NEW
}
void
......
......@@ -87,6 +87,9 @@ struct option_t MuttVars[] = {
{ "beep_new", DT_BOOL, R_NONE, OPTBEEPNEW, 0 },
{ "charset", DT_STR, R_NONE, UL &Charset, UL "iso-8859-1" },
{ "check_new", DT_BOOL, R_NONE, OPTCHECKNEW, 1 },
{ "collapse_new", DT_BOOL, R_NONE, OPTCOLLAPSENEW, 1 },
{ "uncollapse_jump_new", DT_BOOL, R_NONE, OPTUNCOLLAPSEJUMPNEW, 0 },
{ "auto_collapse", DT_BOOL, R_NONE, OPTAUTOCOLLAPSE, 0 },
{ "confirmappend", DT_BOOL, R_NONE, OPTCONFIRMAPPEND, 1 },
{ "confirmcreate", DT_BOOL, R_NONE, OPTCONFIRMCREATE, 1 },
{ "copy", DT_QUAD, R_NONE, OPT_COPY, M_YES },
......
......@@ -649,7 +649,9 @@ int mbox_sync_mailbox (CONTEXT *ctx)
{
save_sort = Sort;
Sort = SORT_ORDER;
set_option (OPTSORTCOLLAPSE);
mutt_sort_headers (ctx, 0);
unset_option (OPTSORTCOLLAPSE);
}
/* need to open the file for writing in such a way that it does not truncate
......@@ -890,7 +892,9 @@ bail: /* Come here in case of disaster */
Sort = save_sort;
/* if the mailbox was reopened, the thread tree will be invalid so make
* sure to start threading from scratch. */
set_option (OPTSORTCOLLAPSE);
mutt_sort_headers (ctx, (need_sort == M_REOPENED));
unset_option (OPTSORTCOLLAPSE);
}
return (-1);
......
......@@ -100,7 +100,8 @@ typedef enum
M_FORMAT_MAKEPRINT = (1<<2), /* make sure that all chars are printable */
M_FORMAT_OPTIONAL = (1<<3),
M_FORMAT_STAT_FILE = (1<<4), /* used by mutt_attach_fmt */
M_FORMAT_ARROWCURSOR = (1<<5) /* reserve space for arrow_cursor */
M_FORMAT_ARROWCURSOR = (1<<5), /* reserve space for arrow_cursor */
M_FORMAT_INDEX = (1<<6) /* this is a main index entry */
} format_flag;
/* types for mutt_add_hook() */
......@@ -123,6 +124,12 @@ typedef enum
#define M_TREE_HIDDEN 9
#define M_TREE_MAX 10
#define M_THREAD_COLLAPSE (1<<0)
#define M_THREAD_UNCOLLAPSE (1<<1)
#define M_THREAD_GET_HIDDEN (1<<2)
#define M_THREAD_UNREAD (1<<3)
#define M_THREAD_NEXT_NEW (1<<4)
enum
{
/* modes for mutt_view_attachment() */
......@@ -236,11 +243,13 @@ enum
OPTASKBCC,
OPTASKCC,
OPTATTACHSPLIT,
OPTAUTOCOLLAPSE,
OPTAUTOEDIT,
OPTAUTOTAG,
OPTBEEP,
OPTBEEPNEW,
OPTCHECKNEW,
OPTCOLLAPSENEW,
OPTCONFIRMAPPEND,
OPTCONFIRMCREATE,
OPTEDITHDRS,
......@@ -280,6 +289,7 @@ enum
OPTSUSPEND,
OPTTHOROUGHSRC,
OPTTILDE,
OPTUNCOLLAPSEJUMPNEW,
OPTUSE8BITMIME,
OPTUSEDOMAIN,
OPTUSEFROM,
......@@ -288,7 +298,7 @@ enum
OPTWRAP,
OPTWRAPSEARCH,
OPTWRITEBCC, /* write out a bcc header? */
/* PGP options */
#ifdef _PGPPATH
......@@ -318,6 +328,7 @@ enum
OPTFORCEREDRAWPAGER, /* (pseudo) used to force a redraw in the pager */
OPTSORTSUBTHREADS, /* (pseudo) used when $sort_aux changes */
OPTNEEDRESCORE, /* (pseudo) set when the `score' command is used */
OPTSORTCOLLAPSE, /* (pseudo) used by mutt_sort_headers() */
#ifdef _PGPPATH
OPTPGPCHECKTRUST, /* (pseudo) used by pgp_select_key () */
......@@ -502,6 +513,11 @@ typedef struct header
unsigned int searched : 1;
unsigned int matched : 1;
/* 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? */
size_t num_hidden; /* number of hidden messages in this view */
int pair; /* color-pair to use when displaying in the index */
time_t date_sent; /* time when the message was sent (UTC) */
......@@ -583,6 +599,7 @@ typedef struct
unsigned int setgid : 1;
unsigned int quiet : 1; /* inhibit status messages? */
unsigned int revsort : 1; /* mailbox sorted in reverse? */
unsigned int collapsed : 1; /* are all threads collapsed? */
} CONTEXT;
typedef struct attachptr
......
......@@ -540,6 +540,7 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx)
ctx->path = safe_strdup (path);
ctx->msgnotreadyet = -1;
ctx->collapsed = 0;
if (flags & M_QUIET)
ctx->quiet = 1;
......@@ -956,7 +957,9 @@ int mx_sync_mailbox (CONTEXT *ctx)
#undef this_body
ctx->msgcount = j;
set_option (OPTSORTCOLLAPSE);
mutt_sort_headers (ctx, 1); /* rethread from scratch */
unset_option (OPTSORTCOLLAPSE);
}
return (rc);
......
......@@ -899,12 +899,18 @@ int mutt_pattern_func (int op, char *prompt)
if (op == M_LIMIT)
{
for (i = 0; i < Context->msgcount; i++)
{
Context->hdrs[i]->virtual = -1;
Context->hdrs[i]->limited = 0;
Context->hdrs[i]->collapsed = 0;
Context->hdrs[i]->num_hidden = 0;
}
Context->vcount = 0;
Context->vsize = 0;
Context->collapsed = 0;
}
#define this_body Context->hdrs[i]->content
#define THIS_BODY Context->hdrs[i]->content
for (i = 0; i < Context->msgcount; i++)
if (mutt_pattern_exec (pat, M_MATCH_FULL_ADDRESS, Context, Context->hdrs[i]))
......@@ -925,19 +931,21 @@ int mutt_pattern_func (int op, char *prompt)
break;
case M_LIMIT:
Context->hdrs[i]->virtual = Context->vcount;
Context->hdrs[i]->limited = 1;
Context->v2r[Context->vcount] = i;
Context->vcount++;
Context->vsize+=this_body->length + this_body->offset -
this_body->hdr_offset;
Context->vsize+=THIS_BODY->length + THIS_BODY->offset -
THIS_BODY->hdr_offset;
break;
}
}
#undef this_body
#undef THIS_BODY
mutt_clear_error ();
if (op == M_LIMIT)
{
Context->collapsed = 0;
safe_free ((void **) &Context->pattern);
if (Context->limit_pattern)
mutt_pattern_free (&Context->limit_pattern);
......@@ -948,6 +956,9 @@ int mutt_pattern_func (int op, char *prompt)
for (i = 0; i < Context->msgcount; i++)
{
Context->hdrs[i]->virtual = i;
Context->hdrs[i]->limited = 0;
Context->hdrs[i]->num_hidden = 0;
Context->hdrs[i]->collapsed = 0;
Context->v2r[i] = i;
}
......
......@@ -46,6 +46,13 @@ int _mutt_system (const char *, int);
#define mutt_previous_subthread(x) _mutt_aside_thread(x,0,1)
int _mutt_aside_thread (HEADER *, short, short);
#define mutt_collapse_thread(x,y) _mutt_traverse_thread (x,y,M_THREAD_COLLAPSE)
#define mutt_uncollapse_thread(x,y) _mutt_traverse_thread (x,y,M_THREAD_UNCOLLAPSE)
#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_new(x,y) _mutt_traverse_thread(x,y,M_THREAD_NEXT_NEW)
int _mutt_traverse_thread (CONTEXT *ctx, HEADER *hdr, int flag);
#define ISSPACE(c) isspace((unsigned char)c)
#define mutt_new_parameter() safe_calloc (1, sizeof (PARAMETER))
......@@ -123,7 +130,7 @@ void mutt_block_signals_system (void);
void mutt_body_handler (BODY *, STATE *);
void mutt_bounce_message (HEADER *, ADDRESS *);
void mutt_buffy (char *);
void mutt_check_rescore (CONTEXT *ctx);
void mutt_check_rescore (CONTEXT *);
void mutt_clear_error (void);
void mutt_create_alias (ENVELOPE *, ADDRESS *);
void mutt_decode_attachment (BODY *, STATE *);
......@@ -185,6 +192,7 @@ void mutt_update_encoding (BODY *a);
void mutt_update_tree (ATTACHPTR **, short);
void mutt_version (void);
void mutt_view_attachments (HEADER *);
void mutt_set_virtual (CONTEXT *);
int mutt_addr_is_user (ADDRESS *);
int mutt_alias_complete (char *, size_t);
......
......@@ -176,6 +176,7 @@ void mutt_sort_headers (CONTEXT *ctx, int init)
{
int i;
sort_t *sortfunc;
int collapse = (option (OPTSORTCOLLAPSE)) ? 0 : 1;
unset_option (OPTNEEDRESORT);
......@@ -236,15 +237,21 @@ void mutt_sort_headers (CONTEXT *ctx, int init)
/* adjust the virtual message numbers */
ctx->vcount = 0;
if (collapse)
ctx->collapsed = 0;
for (i = 0; i < ctx->msgcount; i++)
{
if (ctx->hdrs[i]->virtual != -1)
HEADER *cur = ctx->hdrs[i];
if (cur->virtual != -1 || (collapse && cur->collapsed && (!ctx->pattern || cur->limited)))
{
ctx->hdrs[i]->virtual = ctx->vcount;
cur->virtual = ctx->vcount;
ctx->v2r[ctx->vcount] = i;
ctx->vcount++;
}
ctx->hdrs[i]->msgno = i;
cur->msgno = i;
cur->num_hidden = mutt_get_hidden (ctx, cur);
if (collapse)
cur->collapsed = 0;
}
mutt_cache_index_colors(ctx);
......
......@@ -17,7 +17,18 @@
*/
#include "mutt.h"
#include "mutt_curses.h"
#include "mutt_menu.h"
#include "sort.h"
#include "mailbox.h"
#include "copy.h"
#include "mx.h"
#include <sys/stat.h>
#include <utime.h>
#ifdef BUFFY_SIZE
#include "buffy.h"
#endif
#include <string.h>
#include <ctype.h>
......@@ -38,7 +49,7 @@ static HEADER *find_reference (HEADER *cur, CONTEXT *ctx)
}
/* Determines whether to display a message's subject. */
static int need_display_subject (HEADER *tree)
static int need_display_subject (CONTEXT *ctx, HEADER *tree)
{
HEADER *tmp;
......@@ -46,7 +57,7 @@ static int need_display_subject (HEADER *tree)
return (1);
for (tmp = tree->prev; tmp; tmp = tmp->prev)
{
if (tmp->virtual >= 0)
if (tmp->virtual >= 0 || (tmp->collapsed && (!ctx->pattern || tmp->limited)))
{
if (!tmp->subject_changed)
return (0);
......@@ -56,7 +67,7 @@ static int need_display_subject (HEADER *tree)
}
for (tmp = tree->parent; tmp; tmp = tmp->parent)
{
if (tmp->virtual >= 0)
if (tmp->virtual >= 0 || (tmp->collapsed && (!ctx->pattern || tmp->limited)))
return (0);
else if (tmp->subject_changed)
return (1);
......@@ -66,7 +77,7 @@ static int need_display_subject (HEADER *tree)
/* determines whether a later sibling or the child of a later
sibling is displayed. */
int is_next_displayed (HEADER *tree)
static int is_next_displayed (CONTEXT *ctx, HEADER *tree)
{
int depth = 0;
......@@ -75,7 +86,7 @@ int is_next_displayed (HEADER *tree)
FOREVER
{
if (tree->virtual >= 0)
if (tree->virtual >= 0 || (tree->collapsed && (!ctx->pattern || tree->limited)))
return (1);
if (tree->child)
......@@ -122,8 +133,8 @@ void mutt_linearize_tree (CONTEXT *ctx, int linearize)
FOREVER
{
if (tree->virtual >= 0)
tree->display_subject = need_display_subject (tree);
if (tree->virtual >= 0 || (tree->collapsed && (!ctx->pattern || tree->limited)))
tree->display_subject = need_display_subject (ctx, tree);
if (depth >= max_depth)
safe_realloc ((void **) &pfx,
......@@ -136,26 +147,26 @@ void mutt_linearize_tree (CONTEXT *ctx, int linearize)
safe_free ((void **) &tree->tree);
if (!depth)
{
if (tree->virtual >= 0)
if (tree->virtual >= 0 || (tree->collapsed && (!ctx->pattern || tree->limited)))
tree->tree = safe_strdup ("");
}
else
{
myarrow = arrow + (depth - start_depth - (start_depth ? 0 : 1)) * 2;
nextdisp = is_next_displayed (tree);
nextdisp = is_next_displayed (ctx, tree);
if (depth && start_depth == depth)
myarrow[0] = nextdisp ? M_TREE_LTEE : corner;
else
myarrow[0] = M_TREE_HIDDEN;
myarrow[1] = tree->fake_thread ? M_TREE_STAR : M_TREE_HLINE;
if (tree->virtual >= 0)
if (tree->virtual >= 0 || (tree->collapsed && (!ctx->pattern || tree->limited)))
{
myarrow[2] = M_TREE_RARROW;
myarrow[3] = 0;
}
if (tree->virtual >= 0)
if (tree->virtual >= 0 || (tree->collapsed && (!ctx->pattern || tree->limited)))
{
tree->tree = safe_malloc ((2 + depth * 2) * sizeof (char));
if (start_depth > 1)
......@@ -184,7 +195,7 @@ void mutt_linearize_tree (CONTEXT *ctx, int linearize)
mypfx[1] = M_TREE_SPACE;
}
depth++;
if (tree->virtual >= 0)
if (tree->virtual >= 0 || (tree->collapsed && (!ctx->pattern || tree->limited)))
start_depth = depth;
tree = tree->child;
}
......@@ -192,14 +203,14 @@ void mutt_linearize_tree (CONTEXT *ctx, int linearize)
{
while (!tree->next && tree->parent)
{
if (tree->virtual >= 0)
if (tree->virtual >= 0 || (tree->collapsed && (!ctx->pattern || tree->limited)))
start_depth = depth;
tree = tree->parent;
if (start_depth == depth)
start_depth--;
depth--;
}
if (tree->virtual >= 0)
if (tree->virtual >= 0 || (tree->collapsed && (!ctx->pattern || tree->limited)))
start_depth = depth;
if ((tree = tree->next) == NULL)
break;
......@@ -671,3 +682,166 @@ int _mutt_aside_thread (HEADER *hdr, short dir, short subthreads)
return (tmp->virtual);
}
void mutt_set_virtual (CONTEXT *ctx)
{