~kevin8t8/mutt

50954c4ab74084815513ce8262946ab71e680e33 — Kevin McCarthy 5 months ago e0e92c3
Fix <collapse-all> behavior for sort=reverse-threads.

When uncollapsing, _mutt_traverse_thread() returns the virtual number
of the root message in the thread.  <collapse-thread> directly sets
menu->current to this value to cause the cursor to be on the *first*
message of the thread (which isn't the same as the root message when
sort=reverse-threads).  <collapse-all> finds the corresponding message
by searching for it after re-indexing.

However, when collapsing, _mutt_traverse_thread() had code to try and
find the *first* message in the thread and return that virtual number.
<collapse-thread> then did the same trick, because the old first
message is now the new root message for sort=reverse-threads.

However, that cleverness caused a bug for <collapse-all> - it can't
use that virtual number directly, and it can't "find" the message at
the index after reindexing.

To fix this, remove the cleverness from _mutt_traverse_thread() when
collapsing.  Return the virtual number of the root.  Add searching
behavior for <collapse-thread> to fix its behavior.
2 files changed, 21 insertions(+), 9 deletions(-)

M curs_main.c
M thread.c
M curs_main.c => curs_main.c +20 -1
@@ 2071,6 2071,11 @@ int mutt_index_menu (void)

	if (CURHDR->collapsed)
	{
          /* Note this returns the *old* virtual index of the root message.
           *
           * For sort=reverse-threads this trick allows uncollapsing a
           * single thread to position on the first (not root) message
           * in the thread */
	  menu->current = mutt_uncollapse_thread (Context, CURHDR);
	  mutt_set_virtual (Context);
	  if (option (OPTUNCOLLAPSEJUMP))


@@ 2078,8 2083,22 @@ int mutt_index_menu (void)
	}
	else if (option (OPTCOLLAPSEUNREAD) || !UNREAD (CURHDR))
	{
	  menu->current = mutt_collapse_thread (Context, CURHDR);
	  HEADER *base;
	  int final;
          /* This also returns the *old* virtual index of the root, but now
           * we have to find the new position of the root, which isn't
           * the same for sort=reverse-threads. */
          final = mutt_collapse_thread (Context, CURHDR);
	  base = Context->hdrs[Context->v2r[final]];
	  mutt_set_virtual (Context);
	  for (j = 0; j < Context->vcount; j++)
	  {
	    if (Context->hdrs[Context->v2r[j]]->index == base->index)
	    {
	      menu->current = j;
	      break;
	    }
	  }
	}
	else
	{

M thread.c => thread.c +1 -8
@@ 1321,7 1321,7 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, int flag)
{
  THREAD *thread, *top;
  HEADER *roothdr = NULL;
  int final, reverse = (Sort & SORT_REVERSE), minmsgno;
  int final;
  int num_hidden = 0, new = 0, old = 0;
  int min_unread_msgno = INT_MAX, min_unread = cur->virtual;
#define CHECK_LIMIT (!ctx->pattern || cur->limited)


@@ 1340,7 1340,6 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, int flag)
  while (!thread->message)
    thread = thread->child;
  cur = thread->message;
  minmsgno = cur->msgno;

  if (!cur->read && CHECK_LIMIT)
  {


@@ 1401,12 1400,6 @@ int _mutt_traverse_thread (CONTEXT *ctx, HEADER *cur, int flag)
	    final = roothdr->virtual;
	}

	if (reverse && (flag & MUTT_THREAD_COLLAPSE) && (cur->msgno < minmsgno) && CHECK_LIMIT)
	{
	  minmsgno = cur->msgno;
	  final = cur->virtual;
	}

	if (flag & MUTT_THREAD_COLLAPSE)
	{
	  if (cur != roothdr)