]> granicus.if.org Git - neomutt/commitdiff
revamp sorting
authorRichard Russon <rich@flatcap.org>
Fri, 18 Dec 2015 18:40:19 +0000 (18:40 +0000)
committerRichard Russon <rich@flatcap.org>
Mon, 4 Apr 2016 02:37:43 +0000 (03:37 +0100)
sidebar.c

index 58b1ac79ffe2097d82c0587dea9e2d236333fe6e..7c29bffd68323784f749c04efa0efe4401db627a 100644 (file)
--- a/sidebar.c
+++ b/sidebar.c
@@ -31,6 +31,7 @@
 /* Previous values for some sidebar config */
 static short  OldVisible;      /* sidebar_visible */
 static short  OldWidth;                /* sidebar_width */
+static short  PreviousSort;    /* sidebar_sort */
 static time_t LastRefresh;     /* Time of last refresh */
 
 /* Keep track of various BUFFYs */
@@ -40,8 +41,6 @@ static BUFFY *HilBuffy;               /* Highlighted mailbox */
 static BUFFY *BotBuffy;                /* Last mailbox visible in sidebar */
 static BUFFY *Outgoing;                /* Last mailbox in the linked list */
 
-static int    known_lines;
-
 /**
  * struct sidebar_entry - Info about folders in the sidebar
  *
@@ -123,58 +122,6 @@ find_prev_new (int wrap)
        return NULL;
 }
 
-/**
- * calc_boundaries - Keep our TopBuffy/BotBuffy up-to-date
- *
- * Whenever the sidebar's view of the BUFFYs changes, or the screen changes
- * size, we should check TopBuffy and BotBuffy still have the correct
- * values.
- *
- * Ideally, this should happen in the core of mutt.
- */
-static void
-calc_boundaries (void)
-{
-       BUFFY *b = Incoming;
-       if (!b)
-               return;
-
-       int count = LINES - 2;
-       if (option (OPTHELP))
-               count--;
-
-       if (known_lines != LINES) {
-               TopBuffy = BotBuffy = NULL;
-               known_lines = LINES;
-       }
-       for (; b->next; b = b->next)
-               b->next->prev = b;
-
-       if (!TopBuffy && !BotBuffy)
-               TopBuffy = Incoming;
-
-       if (!BotBuffy) {
-               BotBuffy = TopBuffy;
-               while (--count && BotBuffy->next) {
-                       BotBuffy = BotBuffy->next;
-               }
-       } else if (TopBuffy == CurBuffy->next) {
-               BotBuffy = CurBuffy;
-               b = BotBuffy;
-               while (--count && b->prev) {
-                       b = b->prev;
-               }
-               TopBuffy = b;
-       } else if (BotBuffy == CurBuffy->prev) {
-               TopBuffy = CurBuffy;
-               b = TopBuffy;
-               while (--count && b->next) {
-                       b = b->next;
-               }
-               BotBuffy = b;
-       }
-}
-
 /**
  * cb_format_str - Create the string to show in the sidebar
  * @dest:        Buffer in which to save string
@@ -391,6 +338,56 @@ buffy_going (const BUFFY *b)
        return b->prev;
 }
 
+/**
+ * update_buffy_visibility - Should a BUFFY be displayed in the sidebar
+ * @arr:     array of BUFFYs
+ * @arr_len: number of BUFFYs in array
+ *
+ * For each BUFFY in the array, check whether we should display it.
+ * This is determined by several criteria.  If the BUFFY:
+ *     is the currently open mailbox
+ *     is the currently highlighted mailbox
+ *     has unread messages
+ *     has flagged messages
+ *     is whitelisted
+ */
+static void
+update_buffy_visibility (BUFFY **arr, int arr_len)
+{
+       if (!arr)
+               return;
+
+       short new_only = option (OPTSIDEBARNEWMAILONLY);
+
+       BUFFY *b;
+       int i;
+       for (i = 0; i < arr_len; i++) {
+               b = arr[i];
+
+               b->is_hidden = 0;
+
+               if (!new_only)
+                       continue;
+
+               if ((b == OpnBuffy) || (b->msg_unread  > 0) ||
+                   (b == HilBuffy) || (b->msg_flagged > 0)) {
+                       continue;
+               }
+
+               if (Context && (strcmp (b->path, Context->path) == 0)) {
+                       /* Spool directory */
+                       continue;
+               }
+
+               if (mutt_find_list (SidebarWhitelist, b->path)) {
+                       /* Explicitly asked to be visible */
+                       continue;
+               }
+
+               b->is_hidden = 1;
+       }
+}
+
 /**
  * sort_buffy_array - Sort an array of BUFFY pointers
  * @arr:     array of BUFFYs
@@ -422,6 +419,93 @@ sort_buffy_array (BUFFY **arr, int arr_len)
        arr[0]->prev = NULL;
 }
 
+/**
+ * prepare_sidebar - Prepare the list of BUFFYs for the sidebar display
+ * @page_size:  The number of lines on a page
+ *
+ * Before painting the sidebar, we count the BUFFYs, determine which are
+ * visible, sort them and set up our page pointers.
+ *
+ * This is a lot of work to do each refresh, but there are many things that
+ * can change outside of the sidebar that we don't hear about.
+ *
+ * Returns:
+ *     0:  No, don't draw the sidebar
+ *     1: Yes, draw the sidebar
+ */
+static int
+prepare_sidebar (int page_size)
+{
+       BUFFY *b = Incoming;
+       if (!b)
+               return 0;
+
+       int count = 0;
+       for (; b; b = b->next)
+               count++;
+
+       if (count == 0)
+               return 0;
+
+       BUFFY **arr = safe_malloc (count * sizeof (*arr));
+       if (!arr)
+               return 0;
+
+       int i = 0;
+       for (b = Incoming; b; b = b->next, i++) {
+               arr[i] = b;
+       }
+
+       update_buffy_visibility (arr, count);
+       sort_buffy_array        (arr, count);
+
+       Incoming = arr[0];
+
+       int top_index =  0;
+       int opn_index = -1;
+       int hil_index = -1;
+       int bot_index = -1;
+
+       for (i = 0; i < count; i++) {
+               if (TopBuffy == arr[i])
+                       top_index = i;
+               if (OpnBuffy == arr[i])
+                       opn_index = i;
+               if (HilBuffy == arr[i])
+                       hil_index = i;
+               if (BotBuffy == arr[i])
+                       bot_index = i;
+       }
+
+       if (!HilBuffy || (SidebarSort != PreviousSort)) {
+               if (OpnBuffy) {
+                       HilBuffy  = OpnBuffy;
+                       hil_index = opn_index;
+               } else {
+                       HilBuffy  = arr[0];
+                       hil_index = 0;
+               }
+       }
+       if (TopBuffy) {
+               top_index = (hil_index / page_size) * page_size;
+       } else {
+               top_index = hil_index;
+       }
+       TopBuffy = arr[top_index];
+
+       bot_index = top_index + page_size - 1;
+       if (bot_index > (count - 1)) {
+               bot_index = count - 1;
+       }
+       BotBuffy  = arr[bot_index];
+
+       Outgoing = arr[count - 1];
+
+       PreviousSort = SidebarSort;
+       free (arr);
+       return 1;
+}
+
 /**
  * visible - Should we display the sidebar?
  *
@@ -529,15 +613,6 @@ sb_draw (void)
        if (option (OPTSTATUSONTOP) || option (OPTHELP))
                row++; /* either one will occupy the first line */
 
-       if ((SidebarWidth == 0) || !option (OPTSIDEBAR)) {
-               if (SidebarWidth > 0) {
-                       OldWidth = SidebarWidth;
-                       SidebarWidth = 0;
-               }
-               unset_option (OPTSIDEBAR);
-               return;
-       }
-
        /* draw the divider */
        SidebarHeight = LINES - 1;
        if (option (OPTHELP) || !option (OPTSTATUSONTOP))
@@ -561,19 +636,12 @@ sb_draw (void)
 #endif
        }
 
-       row = 0;
-       if (option (OPTSTATUSONTOP) || option (OPTHELP))
-               row++; /* either one will occupy the first line */
-
-       if ((known_lines != LINES) || !TopBuffy || !BotBuffy)
-               calc_boundaries();
-       if (!CurBuffy)
-               CurBuffy = Incoming;
-
-       SETCOLOR(MT_COLOR_NORMAL);
-
        BUFFY *b;
        for (b = TopBuffy; b && (row < SidebarHeight); b = b->next) {
+               if (b->is_hidden) {
+                       continue;
+               }
+
                if (b == OpnBuffy) {
                        SETCOLOR(MT_COLOR_INDICATOR);
                } else if (b == HilBuffy) {
@@ -582,16 +650,6 @@ sb_draw (void)
                        SETCOLOR(MT_COLOR_NEW);
                } else if (b->msg_flagged > 0) {
                        SETCOLOR(MT_COLOR_FLAGGED);
-               } else if (option (OPTSIDEBARNEWMAILONLY)) {
-                       /* sidebar_newmail_only is enabled... */
-                       if (b == Incoming ||
-                                       (Context && (strcmp (b->path, Context->path) == 0)) ||
-                                       mutt_find_list (SidebarWhitelist, b->path)) {
-                               SETCOLOR(MT_COLOR_NORMAL);
-                       } else {
-                               /* but mailbox isn't whitelisted */
-                               continue;
-                       }
                } else {
                        SETCOLOR(MT_COLOR_NORMAL);
                }
@@ -768,7 +826,6 @@ sb_change_mailbox (int op)
                default:
                        return;
        }
-       calc_boundaries();
        sb_draw();
 }