From 73dedef32ccc7133082e3482d14c763346eba827 Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Thu, 28 Feb 2002 07:58:56 +0000 Subject: [PATCH] Threading enhancements from Daniel Eisenbud. --- init.h | 25 +++++- mutt.h | 7 ++ thread.c | 231 +++++++++++++++++++++++++++++++++---------------------- 3 files changed, 167 insertions(+), 96 deletions(-) diff --git a/init.h b/init.h index 564ca1a5..75431869 100644 --- a/init.h +++ b/init.h @@ -663,12 +663,31 @@ struct option_t MuttVars[] = { ** affect the generation of Message-IDs, and it will not lead to the ** cut-off of first-level domains. */ + { "hide_limited", DT_BOOL, R_RESORT|R_INDEX, OPTHIDELIMITED, 0 }, + /* + ** .pp + ** When set, mutt will not show the presence of missing messages in the + ** thread tree. + */ { "hide_missing", DT_BOOL, R_RESORT|R_INDEX, OPTHIDEMISSING, 1 }, /* ** .pp - ** When set, mutt will not indicate the presence of missing messages - ** whose ancestors neither have siblings nor are in the current mailbox, - ** in the thread tree. + ** When set, mutt will not show the presence of messages that are hidden + ** by limiting, in the thread tree. + */ + { "hide_top_limited", DT_BOOL, R_RESORT|R_INDEX, OPTHIDETOPLIMITED, 0 }, + /* + ** .pp + ** When set, mutt will not show the presence of missing messages at the + ** top of threads in the thread tree. Note that when $$hide_limited is + ** set, this option will have no effect. + */ + { "hide_top_missing", DT_BOOL, R_RESORT|R_INDEX, OPTHIDETOPMISSING, 1 }, + /* + ** .pp + ** When set, mutt will not show the presence of messages that are hidden + ** by limiting, at the top of threads in the thread tree.Note that when + ** $$hide_missing is set, this option will have no effect. */ { "history", DT_NUM, R_NONE, UL &HistSize, 10 }, /* diff --git a/mutt.h b/mutt.h index b8e2df4c..b380b3e5 100644 --- a/mutt.h +++ b/mutt.h @@ -341,7 +341,10 @@ enum OPTHEADER, OPTHELP, OPTHIDDENHOST, + OPTHIDELIMITED, OPTHIDEMISSING, + OPTHIDETOPLIMITED, + OPTHIDETOPMISSING, OPTIGNORELISTREPLYTO, #ifdef USE_IMAP OPTIMAPLSUB, @@ -700,6 +703,10 @@ typedef struct thread unsigned int duplicate_thread : 1; unsigned int sort_children : 1; unsigned int check_subject : 1; + unsigned int visible : 1; + unsigned int deep : 1; + unsigned int subtree_visible : 2; + unsigned int next_subtree_visible : 1; struct thread *parent; struct thread *child; struct thread *next; diff --git a/thread.c b/thread.c index a43067c3..7e0ced86 100644 --- a/thread.c +++ b/thread.c @@ -77,42 +77,6 @@ static int need_display_subject (CONTEXT *ctx, HEADER *hdr) return (1); } -/* determines whether a later sibling or the child of a later - * sibling is displayed. - */ -static int is_next_displayed (CONTEXT *ctx, THREAD *tree) -{ - int depth = 0; - HEADER *hdr; - - if ((tree = tree->next) == NULL) - return (0); - - FOREVER - { - hdr = tree->message; - if (hdr && VISIBLE (hdr, ctx)) - return (1); - - if (tree->child) - { - tree = tree->child; - depth++; - } - else - { - while (!tree->next && depth > 0) - { - tree = tree->parent; - depth--; - } - if ((tree = tree->next) == NULL) - break; - } - } - return (0); -} - static void linearize_tree (CONTEXT *ctx) { THREAD *tree = ctx->tree; @@ -144,6 +108,104 @@ static void linearize_tree (CONTEXT *ctx) } } +/* 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 + * subtrees. while it's at it, it frees the old thread display, so we can + * skip parts of the tree in mutt_draw_tree() if we've decided here that we + * don't care about them any more. + */ +static void calculate_visibility (CONTEXT *ctx) +{ + THREAD *tmp, *tree = ctx->tree; + int hide_top_missing = option (OPTHIDETOPMISSING) && !option (OPTHIDEMISSING); + int hide_top_limited = option (OPTHIDETOPLIMITED) && !option (OPTHIDELIMITED); + + /* we walk each level backwards to make it easier to compute next_subtree_visible */ + while (tree->next) + tree = tree->next; + + FOREVER + { + tree->subtree_visible = 0; + if (tree->message) + { + safe_free ((void **) &tree->message->tree); + if (VISIBLE (tree->message, ctx)) + { + tree->deep = 1; + tree->visible = 1; + tree->message->display_subject = need_display_subject (ctx, tree->message); + for (tmp = tree; tmp; tmp = tmp->parent) + { + if (tmp->subtree_visible) + { + tmp->deep = 1; + tmp->subtree_visible = 2; + break; + } + else + tmp->subtree_visible = 1; + } + } + else + { + tree->visible = 0; + tree->deep = !option (OPTHIDELIMITED); + } + } + else + { + tree->visible = 0; + tree->deep = !option (OPTHIDEMISSING); + } + tree->next_subtree_visible = tree->next && (tree->next->next_subtree_visible + || tree->next->subtree_visible); + if (tree->child) + { + tree = tree->child; + while (tree->next) + tree = tree->next; + } + else if (tree->prev) + tree = tree->prev; + else + { + while (tree && !tree->prev) + tree = tree->parent; + if (!tree) + break; + else + tree = tree->prev; + } + } + + /* now fix up for the OPTHIDETOP* options if necessary */ + if (hide_top_limited || hide_top_missing) + { + tree = ctx->tree; + FOREVER + { + if (!tree->visible && tree->deep && tree->subtree_visible < 2 + && ((tree->message && hide_top_limited) || (!tree->message && hide_top_missing))) + tree->deep = 0; + if (!tree->deep && tree->child && tree->subtree_visible) + tree = tree->child; + else if (tree->next) + tree = tree->next; + else + { + while (tree && !tree->next) + tree = tree->parent; + if (!tree) + break; + else + tree = tree->next; + } + } + } +} + /* Since the graphics characters have a value >255, I have to resort to * using escape sequences to pass the information to print_enriched_string(). * These are the macros M_TREE_* defined in mutt.h. @@ -158,53 +220,39 @@ void mutt_draw_tree (CONTEXT *ctx) char corner = (Sort & SORT_REVERSE) ? M_TREE_ULCORNER : M_TREE_LLCORNER; char vtee = (Sort & SORT_REVERSE) ? M_TREE_BTEE : M_TREE_TTEE; int depth = 0, start_depth = 0, max_depth = 0, max_width = 0; - int nextdisp = 0, visible, pseudo = 0, hidden = 0; - THREAD *tree = ctx->tree; + THREAD *nextdisp = NULL, *pseudo = NULL, *parent = NULL, *tree = ctx->tree; HEADER *hdr; + /* Do the visibility calculations and free the old thread chars. + * From now on we can simply ignore invisible subtrees + */ + calculate_visibility (ctx); while (tree) { if (depth >= max_depth) safe_realloc ((void **) &pfx, (max_depth += 32) * 2 * sizeof (char)); - if (depth - start_depth >= max_width) safe_realloc ((void **) &arrow, (max_width += 16) * 2 * sizeof (char)); - hdr = tree->message; - - if (hdr) - { - if ((visible = VISIBLE (hdr, ctx)) != 0) - hdr->display_subject = need_display_subject (ctx, hdr); - else hidden = 1; - - safe_free ((void **) &hdr->tree); - } - else - visible = 0; - if (depth) { myarrow = arrow + (depth - start_depth - (start_depth ? 0 : 1)) * 2; - if (depth && start_depth == depth) myarrow[0] = nextdisp ? M_TREE_LTEE : corner; - else if (tree->parent->message) + else if (parent->message && !option (OPTHIDELIMITED)) myarrow[0] = M_TREE_HIDDEN; - else if (option (OPTHIDEMISSING)) - myarrow[0] = nextdisp ? vtee : M_TREE_HLINE; - else + else if (!parent->message && !option (OPTHIDEMISSING)) myarrow[0] = M_TREE_MISSING; + else + myarrow[0] = vtee; myarrow[1] = pseudo ? M_TREE_STAR : (tree->duplicate_thread ? M_TREE_EQUALS : M_TREE_HLINE); - - if (visible) + if (tree->visible) { myarrow[2] = M_TREE_RARROW; myarrow[3] = 0; - hdr->tree = safe_malloc ((2 + depth * 2) * sizeof (char)); if (start_depth > 1) { @@ -216,69 +264,66 @@ void mutt_draw_tree (CONTEXT *ctx) strfcpy (hdr->tree, arrow, 2 + depth * 2); } } - if (tree->child && depth) { mypfx = pfx + (depth - 1) * 2; mypfx[0] = nextdisp ? M_TREE_VLINE : M_TREE_SPACE; mypfx[1] = M_TREE_SPACE; } - - nextdisp = 0; - pseudo = 0; - hidden = 0; - + parent = tree; + nextdisp = NULL; + pseudo = NULL; do { - if (tree->child) + if (tree->child && tree->subtree_visible) { - if (hdr || !option (OPTHIDEMISSING) || tree->child->next) - { + if (tree->deep) depth++; - if (visible) - start_depth = depth; - else - hidden = 1; - } - + if (tree->visible) + start_depth = depth; tree = tree->child; - if (tree->fake_thread) - pseudo = 1; - if (depth && !nextdisp) - nextdisp = is_next_displayed (ctx, tree); - hdr = tree->message; + + /* we do this here because we need to make sure that the first child thread + * of the old tree that we deal with is actually displayed if any are, + * or we might set the parent variable wrong while going through it. */ + while (!tree->subtree_visible && tree->next) + tree = tree->next; } else { while (!tree->next && tree->parent) { - if (hdr && VISIBLE (hdr, ctx)) + if (tree == pseudo) + pseudo = NULL; + if (tree == nextdisp) + nextdisp = NULL; + if (tree->visible) start_depth = depth; - tree = tree->parent; - hdr = tree->message; - - if (hdr || !option (OPTHIDEMISSING) || tree->child->next) + if (tree->deep) { if (start_depth == depth) start_depth--; depth--; } } - - if (hdr && VISIBLE (hdr, ctx)) + if (tree == pseudo) + pseudo = NULL; + if (tree == nextdisp) + nextdisp = NULL; + if (tree->visible) start_depth = depth; tree = tree->next; if (!tree) break; - if (tree->fake_thread) - pseudo = 1; - if (depth && !nextdisp) - nextdisp = is_next_displayed (ctx, tree); - hdr = tree->message; } + hdr = tree->message; + if (!pseudo && tree->fake_thread) + pseudo = tree; + if (!nextdisp && tree->next_subtree_visible) + nextdisp = tree; } - while (!(hdr || !option (OPTHIDEMISSING) || tree->child->next)); + while (!tree->deep); } safe_free ((void **) &pfx); -- 2.40.0