missing statics
[apps/madmutt.git] / sort.c
diff --git a/sort.c b/sort.c
index e6942ba..dc1ab61 100644 (file)
--- a/sort.c
+++ b/sort.c
@@ -1,30 +1,22 @@
 /*
+ * Copyright notice from original mutt:
  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
- * 
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- * 
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- */ 
+ *
+ * This file is part of mutt-ng, see http://www.muttng.org/.
+ * It's licensed under the GNU General Public License,
+ * please see the file GPL in the top level source directory.
+ */
+
+#include <lib-lib/lib-lib.h>
+
+#include <lib-ui/curses.h>
 
 #include "mutt.h"
+#include "alias.h"
 #include "sort.h"
+#include "thread.h"
 #include "mutt_idna.h"
 
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-
 #define SORTCODE(x) (Sort & SORT_REVERSE) ? -(x) : x
 
 /* function to use as discriminator when normal sort method is equal */
@@ -38,41 +30,43 @@ static sort_t *AuxSort = NULL;
 if (!code) \
   code = (*((HEADER **)a))->index - (*((HEADER **)b))->index;
 
-int compare_score (const void *a, const void *b)
+static int compare_score (const void *a, const void *b)
 {
   HEADER **pa = (HEADER **) a;
   HEADER **pb = (HEADER **) b;
-  int result = (*pb)->score - (*pa)->score; /* note that this is reverse */
-  AUXSORT(result,a,b);
+  int result = (*pb)->score - (*pa)->score;     /* note that this is reverse */
+
+  AUXSORT (result, a, b);
   return (SORTCODE (result));
 }
 
-int compare_size (const void *a, const void *b)
+static int compare_size (const void *a, const void *b)
 {
   HEADER **pa = (HEADER **) a;
   HEADER **pb = (HEADER **) b;
   int result = (*pa)->content->length - (*pb)->content->length;
-  AUXSORT(result,a,b);
+
+  AUXSORT (result, a, b);
   return (SORTCODE (result));
 }
 
-int compare_date_sent (const void *a, const void *b)
+static int compare_date_sent (const void *a, const void *b)
 {
   HEADER **pa = (HEADER **) a;
   HEADER **pb = (HEADER **) b;
   int result = (*pa)->date_sent - (*pb)->date_sent;
-  AUXSORT(result,a,b);
+
+  AUXSORT (result, a, b);
   return (SORTCODE (result));
 }
 
-int compare_subject (const void *a, const void *b)
+static int compare_subject (const void *a, const void *b)
 {
   HEADER **pa = (HEADER **) a;
   HEADER **pb = (HEADER **) b;
   int rc;
 
-  if (!(*pa)->env->real_subj)
-  {
+  if (!(*pa)->env->real_subj) {
     if (!(*pb)->env->real_subj)
       rc = compare_date_sent (pa, pb);
     else
@@ -81,19 +75,19 @@ int compare_subject (const void *a, const void *b)
   else if (!(*pb)->env->real_subj)
     rc = 1;
   else
-    rc = mutt_strcasecmp ((*pa)->env->real_subj, (*pb)->env->real_subj);
-  AUXSORT(rc,a,b);
+    rc = m_strcasecmp((*pa)->env->real_subj, (*pb)->env->real_subj);
+  AUXSORT (rc, a, b);
   return (SORTCODE (rc));
 }
 
-const char *mutt_get_name (ADDRESS *a)
+const char *mutt_get_name (address_t * a)
 {
-  ADDRESS *ali;
-  const char * name = "";
+  const address_t *ali;
+  const char *name = "";
 
-  if (a)
-  {
-    if (option (OPTREVALIAS) && (ali = alias_reverse_lookup (a)) && ali->personal)
+  if (a) {
+    if (option (OPTREVALIAS) && (ali = alias_reverse_lookup(a))
+        && ali->personal)
       name = ali->personal;
     else if (a->personal)
       name = a->personal;
@@ -104,7 +98,7 @@ const char *mutt_get_name (ADDRESS *a)
   return name;
 }
 
-int compare_to (const void *a, const void *b)
+static int compare_to (const void *a, const void *b)
 {
   HEADER **ppa = (HEADER **) a;
   HEADER **ppb = (HEADER **) b;
@@ -116,18 +110,15 @@ int compare_to (const void *a, const void *b)
    * On the next call that pointer may get smashed so we copy the return value
    * to our own memory space. */
 
-  strncpy(fa,mutt_get_name ((*ppa)->env->to),sizeof(fa));
-  fa[sizeof(fa)-1] = '\0';
+  m_strcpy(fa, sizeof(fa), mutt_get_name((*ppa)->env->to));
+  m_strcpy(fb, sizeof(fb), mutt_get_name((*ppb)->env->to));
 
-  strncpy(fb,mutt_get_name ((*ppb)->env->to),sizeof(fb));
-  fb[sizeof(fb)-1] = '\0';
-
-  result = mutt_strcasecmp (fa, fb);
-  AUXSORT(result,a,b);
+  result = m_strcasecmp(fa, fb);
+  AUXSORT (result, a, b);
   return (SORTCODE (result));
 }
 
-int compare_from (const void *a, const void *b)
+static int compare_from (const void *a, const void *b)
 {
   HEADER **ppa = (HEADER **) a;
   HEADER **ppb = (HEADER **) b;
@@ -139,105 +130,150 @@ int compare_from (const void *a, const void *b)
    * On the next call that pointer may get smashed so we copy the return value
    * to our own memory space. */
 
-  strncpy(fa,mutt_get_name ((*ppa)->env->from),sizeof(fa));
-  fa[sizeof(fa)-1] = '\0';
-
-  strncpy(fb,mutt_get_name ((*ppb)->env->from),sizeof(fb));
-  fb[sizeof(fb)-1] = '\0';
+  m_strcpy(fa, sizeof(fa), mutt_get_name((*ppa)->env->from));
+  m_strcpy(fb, sizeof(fb), mutt_get_name((*ppb)->env->from));
 
-  result = mutt_strcasecmp (fa, fb);
-  AUXSORT(result,a,b);
+  result = m_strcasecmp(fa, fb);
+  AUXSORT (result, a, b);
   return (SORTCODE (result));
 }
 
-int compare_date_received (const void *a, const void *b)
+static int compare_date_received (const void *a, const void *b)
 {
   HEADER **pa = (HEADER **) a;
   HEADER **pb = (HEADER **) b;
   int result = (*pa)->received - (*pb)->received;
-  AUXSORT(result,a,b);
+
+  AUXSORT (result, a, b);
   return (SORTCODE (result));
 }
 
-int compare_order (const void *a, const void *b)
+static int compare_order (const void *a, const void *b)
 {
   HEADER **ha = (HEADER **) a;
   HEADER **hb = (HEADER **) b;
 
 #ifdef USE_NNTP
-  if ((*ha)->article_num && (*hb)->article_num)
-  {
+  if ((*ha)->article_num && (*hb)->article_num) {
     int result = (*ha)->article_num - (*hb)->article_num;
-    AUXSORT(result,a,b);
+
+    AUXSORT (result, a, b);
     return (SORTCODE (result));
   }
   else
 #endif
-  /* no need to auxsort because you will never have equality here */
-  return (SORTCODE ((*ha)->index - (*hb)->index));
+    /* no need to auxsort because you will never have equality here */
+    return (SORTCODE ((*ha)->index - (*hb)->index));
+}
+
+static int compare_spam (const void *a, const void *b)
+{
+  HEADER **ppa = (HEADER **) a;
+  HEADER **ppb = (HEADER **) b;
+  char *aptr, *bptr;
+  int ahas, bhas;
+  int result = 0;
+
+  /* Firstly, require spam attributes for both msgs */
+  /* to compare. Determine which msgs have one.     */
+  ahas = (*ppa)->env && (*ppa)->env->spam;
+  bhas = (*ppb)->env && (*ppb)->env->spam;
+
+  /* If one msg has spam attr but other does not, sort the one with first. */
+  if (ahas && !bhas)
+    return (SORTCODE (1));
+  if (!ahas && bhas)
+    return (SORTCODE (-1));
+
+  /* Else, if neither has a spam attr, presume equality. Fall back on aux. */
+  if (!ahas && !bhas) {
+    AUXSORT (result, a, b);
+    return (SORTCODE (result));
+  }
+
+
+  /* Both have spam attrs. */
+
+  /* preliminary numeric examination */
+  result = (strtoul ((*ppa)->env->spam->data, &aptr, 10) -
+            strtoul ((*ppb)->env->spam->data, &bptr, 10));
+
+  /* If either aptr or bptr is equal to data, there is no numeric    */
+  /* value for that spam attribute. In this case, compare lexically. */
+  if ((aptr == (*ppa)->env->spam->data) || (bptr == (*ppb)->env->spam->data))
+    return (SORTCODE (m_strcmp(aptr, bptr)));
+
+  /* Otherwise, we have numeric value for both attrs. If these values */
+  /* are equal, then we first fall back upon string comparison, then  */
+  /* upon auxiliary sort.                                             */
+  if (result == 0) {
+    result = m_strcmp(aptr, bptr);
+    if (result == 0)
+      AUXSORT (result, a, b);
+  }
+
+  return (SORTCODE (result));
 }
 
 sort_t *mutt_get_sort_func (int method)
 {
-  switch (method & SORT_MASK)
-  {
-    case SORT_RECEIVED:
-      return (compare_date_received);
-    case SORT_ORDER:
-      return (compare_order);
-    case SORT_DATE:
-      return (compare_date_sent);
-    case SORT_SUBJECT:
-      return (compare_subject);
-    case SORT_FROM:
-      return (compare_from);
-    case SORT_SIZE:
-      return (compare_size);
-    case SORT_TO:
-      return (compare_to);
-    case SORT_SCORE:
-      return (compare_score);
-    default:
-      return (NULL);
+  switch (method & SORT_MASK) {
+  case SORT_RECEIVED:
+    return (compare_date_received);
+  case SORT_ORDER:
+    return (compare_order);
+  case SORT_DATE:
+    return (compare_date_sent);
+  case SORT_SUBJECT:
+    return (compare_subject);
+  case SORT_FROM:
+    return (compare_from);
+  case SORT_SIZE:
+    return (compare_size);
+  case SORT_TO:
+    return (compare_to);
+  case SORT_SCORE:
+    return (compare_score);
+  case SORT_SPAM:
+    return (compare_spam);
+  default:
+    return (NULL);
   }
   /* not reached */
 }
 
-void mutt_sort_headers (CONTEXT *ctx, int init)
+void mutt_sort_headers (CONTEXT * ctx, int init)
 {
   int i;
   HEADER *h;
   THREAD *thread, *top;
   sort_t *sortfunc;
-  
+
   unset_option (OPTNEEDRESORT);
 
   if (!ctx)
     return;
 
-  if (!ctx->msgcount)
-  {
+  if (!ctx->msgcount) {
     /* this function gets called by mutt_sync_mailbox(), which may have just
      * deleted all the messages.  the virtual message numbers are not updated
      * in that routine, so we must make sure to zero the vcount member.
      */
     ctx->vcount = 0;
     mutt_clear_threads (ctx);
-    return; /* nothing to do! */
+    return;                     /* nothing to do! */
   }
 
   if (!ctx->quiet)
     mutt_message _("Sorting mailbox...");
 
-  if (option (OPTNEEDRESCORE) && option (OPTSCORE))
-  {
+  if (option (OPTNEEDRESCORE) && option (OPTSCORE)) {
     for (i = 0; i < ctx->msgcount; i++)
       mutt_score_message (ctx, ctx->hdrs[i], 1);
   }
   unset_option (OPTNEEDRESCORE);
 
-  if (option (OPTRESORTINIT))
-  {
+  if (option (OPTRESORTINIT)) {
     unset_option (OPTRESORTINIT);
     init = 1;
   }
@@ -245,39 +281,37 @@ void mutt_sort_headers (CONTEXT *ctx, int init)
   if (init && ctx->tree)
     mutt_clear_threads (ctx);
 
-  if ((Sort & SORT_MASK) == SORT_THREADS)
-  {
+  if ((Sort & SORT_MASK) == SORT_THREADS) {
     AuxSort = NULL;
     /* if $sort_aux changed after the mailbox is sorted, then all the
        subthreads need to be resorted */
-    if (option (OPTSORTSUBTHREADS))
-    {
+    if (option (OPTSORTSUBTHREADS)) {
       i = Sort;
       Sort = SortAux;
       if (ctx->tree)
-       ctx->tree = mutt_sort_subthreads (ctx->tree, 1);
+        ctx->tree = mutt_sort_subthreads (ctx->tree, 1);
       Sort = i;
       unset_option (OPTSORTSUBTHREADS);
     }
     mutt_sort_threads (ctx, init);
   }
   else if ((sortfunc = mutt_get_sort_func (Sort)) == NULL ||
-          (AuxSort = mutt_get_sort_func (SortAux)) == NULL)
-  {
+           (AuxSort = mutt_get_sort_func (SortAux)) == NULL) {
     mutt_error _("Could not find sorting function! [report this bug]");
+
     mutt_sleep (1);
     return;
   }
-  else 
+  else
     qsort ((void *) ctx->hdrs, ctx->msgcount, sizeof (HEADER *), sortfunc);
 
   /* adjust the virtual message numbers */
   ctx->vcount = 0;
-  for (i = 0; i < ctx->msgcount; i++)
-  {
+  for (i = 0; i < ctx->msgcount; i++) {
     HEADER *cur = ctx->hdrs[i];
-    if (cur->virtual != -1 || (cur->collapsed && (!ctx->pattern || cur->limited)))
-    {
+
+    if (cur->virtual != -1
+        || (cur->collapsed && (!ctx->pattern || cur->limited))) {
       cur->virtual = ctx->vcount;
       ctx->v2r[ctx->vcount] = i;
       ctx->vcount++;
@@ -286,17 +320,15 @@ void mutt_sort_headers (CONTEXT *ctx, int init)
   }
 
   /* re-collapse threads marked as collapsed */
-  if ((Sort & SORT_MASK) == SORT_THREADS)
-  {
+  if ((Sort & SORT_MASK) == SORT_THREADS) {
     top = ctx->tree;
-    while ((thread = top) != NULL)
-    {
+    while ((thread = top) != NULL) {
       while (!thread->message)
-       thread = thread->child;
+        thread = thread->child;
       h = thread->message;
 
       if (h->collapsed)
-       mutt_collapse_thread (ctx, h);
+        mutt_collapse_thread (ctx, h);
       top = top->next;
     }
     mutt_set_virtual (ctx);