]> granicus.if.org Git - mutt/commitdiff
Display matching new messages in a thread-limited index.
authorKevin McCarthy <kevin@8t8.us>
Fri, 20 Jul 2018 03:28:38 +0000 (20:28 -0700)
committerKevin McCarthy <kevin@8t8.us>
Fri, 20 Jul 2018 20:38:27 +0000 (13:38 -0700)
Previously, the index performed pattern matching first, and then
resorted new mail.  The problem was that thread-limiting patterns,
e.g. ~(pattern), require threading data to properly match against the
new messages.

We already save new messages for the purposes of uncollapsing threads.
To keep the code cleaner, split off update_index() into
update_index_threaded()/unthreaded().  Then for threaded mode, save
the new messages first.  We can then sort (before pattern matching),
and use the save_new array to pattern match the new messages
afterwards.

The $uncollapse_new loop was unnecessarily performing a n^2 search.
Simplify to just iteratate over the save_new instead.

curs_main.c

index 703a0660488c81a36b32dc977344a64c5ef6476f..12a2eaf216e5342049533b96f2215110b095e0c1 100644 (file)
@@ -351,62 +351,53 @@ static int mx_toggle_write (CONTEXT *ctx)
   return 0;
 }
 
-static void update_index (MUTTMENU *menu, CONTEXT *ctx, int check,
-                         int oldcount, int index_hint)
+static void update_index_threaded (CONTEXT *ctx, int check, int oldcount)
 {
-  /* store pointers to the newly added messages */
-  HEADER  **save_new = NULL;
+  HEADER **save_new = NULL;
   int j;
 
-  /* take note of the current message */
-  if (oldcount)
+  /* save the list of new messages */
+  if ((check != MUTT_REOPENED) && oldcount &&
+      (ctx->pattern || option (OPTUNCOLLAPSENEW)))
   {
-    if (menu->current < ctx->vcount)
-      menu->oldcurrent = index_hint;
-    else
-      oldcount = 0; /* invalid message number! */
+    save_new = (HEADER **) safe_malloc (sizeof (HEADER *) * (ctx->msgcount - oldcount));
+    for (j = oldcount; j < ctx->msgcount; j++)
+      save_new[j-oldcount] = ctx->hdrs[j];
   }
 
-  /* We are in a limited view. Check if the new message(s) satisfy
-   * the limit criteria. If they do, set their virtual msgno so that
-   * they will be visible in the limited view */
+  /* Sort first to thread the new messages, because some patterns
+   * require the threading information.
+   *
+   * If the mailbox was reopened, need to rethread from scratch. */
+  mutt_sort_headers (ctx, (check == MUTT_REOPENED));
+
   if (ctx->pattern)
   {
-#define THIS_BODY ctx->hdrs[j]->content
     for (j = (check == MUTT_REOPENED) ? 0 : oldcount; j < ctx->msgcount; j++)
     {
-      if (!j)
-       ctx->vcount = 0;
+      HEADER *h;
+
+      if ((check != MUTT_REOPENED) && oldcount)
+        h = save_new[j-oldcount];
+      else
+        h = ctx->hdrs[j];
 
       if (mutt_pattern_exec (ctx->limit_pattern,
                             MUTT_MATCH_FULL_ADDRESS,
-                            ctx, ctx->hdrs[j], NULL))
+                            ctx, h, NULL))
       {
-       assert (ctx->vcount < ctx->msgcount);
-       ctx->hdrs[j]->virtual = ctx->vcount;
-       ctx->v2r[ctx->vcount] = j;
-       ctx->hdrs[j]->limited = 1;
-       ctx->vcount++;
-       ctx->vsize += THIS_BODY->length + THIS_BODY->offset - THIS_BODY->hdr_offset;
+        /* virtual will get properly set by mutt_set_virtual(), which
+         * is called by mutt_sort_headers() just below. */
+        h->virtual = 1;
+        h->limited = 1;
       }
     }
-#undef THIS_BODY
-  }
-
-  /* save the list of new messages */
-  if (option(OPTUNCOLLAPSENEW) && oldcount && check != MUTT_REOPENED
-      && ((Sort & SORT_MASK) == SORT_THREADS))
-  {
-    save_new = (HEADER **) safe_malloc (sizeof (HEADER *) * (ctx->msgcount - oldcount));
-    for (j = oldcount; j < ctx->msgcount; j++)
-      save_new[j-oldcount] = ctx->hdrs[j];
+    /* Need a second sort to set virtual numbers and redraw the tree */
+    mutt_sort_headers (ctx, 0);
   }
 
-  /* if the mailbox was reopened, need to rethread from scratch */
-  mutt_sort_headers (ctx, (check == MUTT_REOPENED));
-
   /* uncollapse threads with new mail */
-  if (option(OPTUNCOLLAPSENEW) && ((Sort & SORT_MASK) == SORT_THREADS))
+  if (option(OPTUNCOLLAPSENEW))
   {
     if (check == MUTT_REOPENED)
     {
@@ -425,21 +416,68 @@ static void update_index (MUTTMENU *menu, CONTEXT *ctx, int check,
     else if (oldcount)
     {
       for (j = 0; j < ctx->msgcount - oldcount; j++)
-      {
-       int k;
+        if (!ctx->pattern || save_new[j]->limited)
+          mutt_uncollapse_thread (ctx, save_new[j]);
+      mutt_set_virtual (ctx);
+    }
+  }
 
-       for (k = 0; k < ctx->msgcount; k++)
-       {
-         HEADER *h = ctx->hdrs[k];
-         if (h == save_new[j] && (!ctx->pattern || h->limited))
-           mutt_uncollapse_thread (ctx, h);
-       }
+  FREE (&save_new);
+}
+
+static void update_index_unthreaded (CONTEXT *ctx, int check, int oldcount)
+{
+  int j;
+
+  /* We are in a limited view. Check if the new message(s) satisfy
+   * the limit criteria. If they do, set their virtual msgno so that
+   * they will be visible in the limited view */
+  if (ctx->pattern)
+  {
+#define THIS_BODY ctx->hdrs[j]->content
+    for (j = (check == MUTT_REOPENED) ? 0 : oldcount; j < ctx->msgcount; j++)
+    {
+      if (!j)
+       ctx->vcount = 0;
+
+      if (mutt_pattern_exec (ctx->limit_pattern,
+                            MUTT_MATCH_FULL_ADDRESS,
+                            ctx, ctx->hdrs[j], NULL))
+      {
+       assert (ctx->vcount < ctx->msgcount);
+       ctx->hdrs[j]->virtual = ctx->vcount;
+       ctx->v2r[ctx->vcount] = j;
+       ctx->hdrs[j]->limited = 1;
+       ctx->vcount++;
+       ctx->vsize += THIS_BODY->length + THIS_BODY->offset - THIS_BODY->hdr_offset;
       }
-      FREE (&save_new);
-      mutt_set_virtual (ctx);
     }
+#undef THIS_BODY
   }
 
+  /* if the mailbox was reopened, need to rethread from scratch */
+  mutt_sort_headers (ctx, (check == MUTT_REOPENED));
+}
+
+static void update_index (MUTTMENU *menu, CONTEXT *ctx, int check,
+                         int oldcount, int index_hint)
+{
+  int j;
+
+  /* take note of the current message */
+  if (oldcount)
+  {
+    if (menu->current < ctx->vcount)
+      menu->oldcurrent = index_hint;
+    else
+      oldcount = 0; /* invalid message number! */
+  }
+
+  if ((Sort & SORT_MASK) == SORT_THREADS)
+    update_index_threaded (ctx, check, oldcount);
+  else
+    update_index_unthreaded (ctx, check, oldcount);
+
   menu->current = -1;
   if (oldcount)
   {
@@ -456,7 +494,6 @@ static void update_index (MUTTMENU *menu, CONTEXT *ctx, int check,
 
   if (menu->current < 0)
     menu->current = ci_first_message ();
-
 }
 
 static void resort_index (MUTTMENU *menu)