NeoMutt  2022-04-29-145-g9b6a0e
Teaching an old dog new tricks
sort.h File Reference

Assorted sorting methods. More...

#include <stdbool.h>
#include <sys/types.h>
#include "core/lib.h"
#include "options.h"
+ Include dependency graph for sort.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.


#define mutt_numeric_cmp(a, b)   ((a) < (b) ? -1 : ((a) > (b) ? 1 : 0))


typedef int(* sort_t) (const void *a, const void *b)
typedef int(* sort_mail_t) (const struct Email *a, const struct Email *b, bool reverse)


int mutt_compare_emails (const struct Email *a, const struct Email *b, enum MailboxType type, short sort, short sort_aux)
 Compare two emails using up to two sort methods. More...
void mutt_sort_headers (struct Mailbox *m, struct ThreadsContext *threads, bool init, off_t *vsize)
 Sort emails by their headers. More...
const char * mutt_get_name (const struct Address *a)
 Pick the best name to display from an address. More...

Detailed Description

Assorted sorting methods.

  • Michael R. Elkins
  • Pietro Cerutti

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, see

Definition in file sort.h.

Macro Definition Documentation

◆ mutt_numeric_cmp

#define mutt_numeric_cmp (   a,
)    ((a) < (b) ? -1 : ((a) > (b) ? 1 : 0))

Definition at line 36 of file sort.h.

Typedef Documentation

◆ sort_t

typedef int(* sort_t) (const void *a, const void *b)

Definition at line 49 of file sort.h.

◆ sort_mail_t

typedef int(* sort_mail_t) (const struct Email *a, const struct Email *b, bool reverse)

Definition at line 63 of file sort.h.

Function Documentation

◆ mutt_compare_emails()

int mutt_compare_emails ( const struct Email a,
const struct Email b,
enum MailboxType  type,
short  sort,
short  sort_aux 

Compare two emails using up to two sort methods.

aFirst email
bSecond email
typeMailbox type
sortPrimary sort to use (generally $sort)
sort_auxSecondary sort (generally $sort_aux or SORT_ORDER)
Return values
<0a precedes b
0a and b are identical (should not happen in practice)
>0b precedes a

Definition at line 328 of file sort.c.

330 {
331  sort_mail_t func = get_sort_func(sort & SORT_MASK, type);
332  int retval = func(a, b, (sort & SORT_REVERSE) != 0);
333  if (retval == 0)
334  {
335  func = get_sort_func(sort_aux & SORT_MASK, type);
336  retval = func(a, b, (sort_aux & SORT_REVERSE) != 0);
337  }
338  if (retval == 0)
339  {
340  /* Fallback of last resort to preserve stable order; will only
341  * return 0 if a and b have the same index, which is probably a
342  * bug in the code. */
343  func = compare_order;
344  retval = func(a, b, false);
345  }
346  return retval;
347 }
static int compare_order(const struct Email *a, const struct Email *b, bool reverse)
Restore the 'unsorted' order of emails - Implements sort_mail_t -.
Definition: sort.c:192
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:78
Reverse the order of the sort.
Definition: sort2.h:79
static sort_mail_t get_sort_func(enum SortType method, enum MailboxType type)
Get the sort function for a given sort id.
Definition: sort.c:281
int(* sort_mail_t)(const struct Email *a, const struct Email *b, bool reverse)
Definition: sort.h:63
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_sort_headers()

void mutt_sort_headers ( struct Mailbox m,
struct ThreadsContext threads,
bool  init,
off_t *  vsize 

Sort emails by their headers.

threadsThreads context
initIf true, rebuild the thread
[out]vsizeSize in bytes of the messages in view

Definition at line 356 of file sort.c.

358 {
359  if (!m || !m->emails[0])
360  return;
362  OptNeedResort = false;
364  if (m->msg_count == 0)
365  {
366  /* this function gets called by mutt_sync_mailbox(), which may have just
367  * deleted all the messages. the virtual message numbers are not updated
368  * in that routine, so we must make sure to zero the vcount member. */
369  m->vcount = 0;
370  mutt_clear_threads(threads);
371  *vsize = 0;
372  return; /* nothing to do! */
373  }
375  if (m->verbose)
376  mutt_message(_("Sorting mailbox..."));
378  const bool c_score = cs_subset_bool(NeoMutt->sub, "score");
379  if (OptNeedRescore && c_score)
380  {
381  for (int i = 0; i < m->msg_count; i++)
382  {
383  struct Email *e = m->emails[i];
384  if (!e)
385  break;
386  mutt_score_message(m, e, true);
387  }
388  }
389  OptNeedRescore = false;
391  if (OptResortInit)
392  {
393  OptResortInit = false;
394  init = true;
395  }
397  if (init)
398  mutt_clear_threads(threads);
400  const bool threaded = mutt_using_threads();
401  if (threaded)
402  {
403  mutt_sort_threads(threads, init);
404  }
405  else
406  {
407  struct EmailCompare cmp;
408  cmp.type = mx_type(m);
409  cmp.sort = cs_subset_sort(NeoMutt->sub, "sort");
410  cmp.sort_aux = cs_subset_sort(NeoMutt->sub, "sort_aux");
411  mutt_qsort_r((void *) m->emails, m->msg_count, sizeof(struct Email *),
412  compare_email_shim, &cmp);
413  }
415  /* adjust the virtual message numbers */
416  m->vcount = 0;
417  for (int i = 0; i < m->msg_count; i++)
418  {
419  struct Email *e_cur = m->emails[i];
420  if (!e_cur)
421  break;
423  if ((e_cur->vnum != -1) || (e_cur->collapsed && e_cur->visible))
424  {
425  e_cur->vnum = m->vcount;
426  m->v2r[m->vcount] = i;
427  m->vcount++;
428  }
429  e_cur->msgno = i;
430  }
432  /* re-collapse threads marked as collapsed */
433  if (threaded)
434  {
436  *vsize = mutt_set_vnum(m);
437  }
439  if (m->verbose)
442  return;
443 }
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
#define mutt_message(...)
Definition: logging.h:86
#define _(a)
Definition: message.h:28
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
void mutt_clear_threads(struct ThreadsContext *tctx)
Clear the threading of message in a mailbox.
Definition: mutt_thread.c:708
void mutt_thread_collapse_collapsed(struct ThreadsContext *tctx)
Re-collapse threads marked as collapsed.
Definition: mutt_thread.c:1716
void mutt_sort_threads(struct ThreadsContext *tctx, bool init)
Sort email threads.
Definition: mutt_thread.c:1001
off_t mutt_set_vnum(struct Mailbox *m)
Set the virtual index number of all the messages in a mailbox.
Definition: mutt_thread.c:1363
#define mutt_using_threads()
Definition: mutt_thread.h:100
enum MailboxType mx_type(struct Mailbox *m)
Return the type of the Mailbox.
Definition: mx.c:1837
bool OptNeedRescore
(pseudo) set when the 'score' command is used
Definition: options.h:47
bool OptResortInit
(pseudo) used to force the next resort to be from scratch
Definition: options.h:56
bool OptNeedResort
(pseudo) used to force a re-sort
Definition: options.h:48
void mutt_qsort_r(void *base, size_t nmemb, size_t size, qsort_r_compar_t compar, void *arg)
Sort an array, where the comparator has access to opaque data rather than requiring global variables.
Definition: qsort_r.c:76
void mutt_score_message(struct Mailbox *m, struct Email *e, bool upd_mbox)
Apply scoring to an email.
Definition: score.c:159
static int compare_email_shim(const void *a, const void *b, void *arg)
qsort_r() comparator to drive mutt_compare_emails
Definition: sort.c:70
Context for compare_email_shim()
Definition: sort.c:55
enum MailboxType type
Current mailbox type.
Definition: sort.c:56
The envelope/body of an email.
Definition: email.h:37
bool visible
Is this message part of the view?
Definition: email.h:121
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:120
bool threaded
Used for threading.
Definition: email.h:108
int vnum
Virtual message number.
Definition: email.h:114
int msgno
Number displayed to the user.
Definition: email.h:111
int vcount
The number of virtual messages.
Definition: mailbox.h:99
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:98
int msg_count
Total number of messages.
Definition: mailbox.h:88
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
bool verbose
Display status messages?
Definition: mailbox.h:115
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the caller graph for this function:

◆ mutt_get_name()

const char* mutt_get_name ( const struct Address a)

Pick the best name to display from an address.

aAddress to use
Return values
ptrDisplay name

This function uses:

  1. Alias for email address
  2. Personal name
  3. Email address

Definition at line 136 of file sort.c.

137 {
138  struct Address *ali = NULL;
140  if (a)
141  {
142  const bool c_reverse_alias = cs_subset_bool(NeoMutt->sub, "reverse_alias");
143  if (c_reverse_alias && (ali = alias_reverse_lookup(a)) && ali->personal)
144  return ali->personal;
145  if (a->personal)
146  return a->personal;
147  if (a->mailbox)
148  return mutt_addr_for_display(a);
149  }
150  /* don't return NULL to avoid segfault when printing/comparing */
151  return "";
152 }
const char * mutt_addr_for_display(const struct Address *a)
Convert an Address for display purposes.
Definition: address.c:986
struct Address * alias_reverse_lookup(const struct Address *addr)
Does the user have an alias for the given address.
Definition: reverse.c:105
An email address.
Definition: address.h:36
char * mailbox
Mailbox and host address.
Definition: address.h:38
char * personal
Real name of address.
Definition: address.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function: