NeoMutt  2023-03-22
Teaching an old dog new tricks
DOXYGEN
sort.c File Reference

Assorted sorting methods. More...

#include "config.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "sort.h"
#include "globals.h"
#include "mutt_logging.h"
#include "mutt_thread.h"
#include "mx.h"
#include "score.h"
#include "nntp/lib.h"
+ Include dependency graph for sort.c:

Go to the source code of this file.

Data Structures

struct  EmailCompare
 Context for compare_email_shim() More...
 

Functions

static int compare_email_shim (const void *a, const void *b, void *arg)
 qsort_r() comparator to drive mutt_compare_emails More...
 
static int compare_score (const struct Email *a, const struct Email *b, bool reverse)
 Compare two emails using their scores - Implements sort_mail_t -. More...
 
static int compare_size (const struct Email *a, const struct Email *b, bool reverse)
 Compare the size of two emails - Implements sort_mail_t -. More...
 
static int compare_date_sent (const struct Email *a, const struct Email *b, bool reverse)
 Compare the sent date of two emails - Implements sort_mail_t -. More...
 
static int compare_subject (const struct Email *a, const struct Email *b, bool reverse)
 Compare the subject of two emails - Implements sort_mail_t -. More...
 
const char * mutt_get_name (const struct Address *a)
 Pick the best name to display from an address. More...
 
static int compare_to (const struct Email *a, const struct Email *b, bool reverse)
 Compare the 'to' fields of two emails - Implements sort_mail_t -. More...
 
static int compare_from (const struct Email *a, const struct Email *b, bool reverse)
 Compare the 'from' fields of two emails - Implements sort_mail_t -. More...
 
static int compare_date_received (const struct Email *a, const struct Email *b, bool reverse)
 Compare the date received of two emails - Implements sort_mail_t -. More...
 
static int compare_order (const struct Email *a, const struct Email *b, bool reverse)
 Restore the 'unsorted' order of emails - Implements sort_mail_t -. More...
 
static int compare_spam (const struct Email *a, const struct Email *b, bool reverse)
 Compare the spam values of two emails - Implements sort_mail_t -. More...
 
static int compare_label (const struct Email *a, const struct Email *b, bool reverse)
 Compare the labels of two emails - Implements sort_mail_t -. More...
 
static sort_mail_t get_sort_func (enum SortType method, enum MailboxType type)
 Get the sort function for a given sort id. More...
 
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...
 

Detailed Description

Assorted sorting methods.

Authors
  • Michael R. Elkins
  • Pietro Cerutti
  • R Primus

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 http://www.gnu.org/licenses/.

Definition in file sort.c.

Function Documentation

◆ compare_email_shim()

static int compare_email_shim ( const void *  a,
const void *  b,
void *  arg 
)
static

qsort_r() comparator to drive mutt_compare_emails

Parameters
aPointer to first email
bPointer to second email
argEmailCompare with needed context
Return values
<0a precedes b
0a identical to b (should not happen in practice)
>0b precedes a

Definition at line 70 of file sort.c.

71{
72 const struct Email *ea = *(struct Email const *const *) a;
73 const struct Email *eb = *(struct Email const *const *) b;
74 const struct EmailCompare *cmp = arg;
75 return mutt_compare_emails(ea, eb, cmp->type, cmp->sort, cmp->sort_aux);
76}
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.
Definition: sort.c:328
Context for compare_email_shim()
Definition: sort.c:55
short sort_aux
Secondary sort.
Definition: sort.c:58
short sort
Primary sort.
Definition: sort.c:57
enum MailboxType type
Current mailbox type.
Definition: sort.c:56
The envelope/body of an email.
Definition: email.h:37
+ Here is the call graph for this function:
+ 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.

Parameters
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;
139
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
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
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
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ get_sort_func()

static sort_mail_t get_sort_func ( enum SortType  method,
enum MailboxType  type 
)
static

Get the sort function for a given sort id.

Parameters
methodSort type, see SortType
typeThe Mailbox type
Return values
ptrsort function - Implements sort_mail_t

Definition at line 281 of file sort.c.

282{
283 switch (method)
284 {
285 case SORT_DATE:
286 return compare_date_sent;
287 case SORT_FROM:
288 return compare_from;
289 case SORT_LABEL:
290 return compare_label;
291 case SORT_ORDER:
292#ifdef USE_NNTP
293 if (type == MUTT_NNTP)
294 return nntp_compare_order;
295 else
296#endif
297 return compare_order;
298 case SORT_RECEIVED:
300 case SORT_SCORE:
301 return compare_score;
302 case SORT_SIZE:
303 return compare_size;
304 case SORT_SPAM:
305 return compare_spam;
306 case SORT_SUBJECT:
307 return compare_subject;
308 case SORT_TO:
309 return compare_to;
310 default:
311 mutt_error(_("Could not find sorting function [report this bug]"));
312 return NULL;
313 }
314 /* not reached */
315}
#define mutt_error(...)
Definition: logging.h:87
static int compare_to(const struct Email *a, const struct Email *b, bool reverse)
Compare the 'to' fields of two emails - Implements sort_mail_t -.
Definition: sort.c:157
int nntp_compare_order(const struct Email *a, const struct Email *b, bool reverse)
Sort to mailbox order - Implements sort_mail_t -.
Definition: nntp.c:2271
static int compare_label(const struct Email *a, const struct Email *b, bool reverse)
Compare the labels of two emails - Implements sort_mail_t -.
Definition: sort.c:250
static int compare_spam(const struct Email *a, const struct Email *b, bool reverse)
Compare the spam values of two emails - Implements sort_mail_t -.
Definition: sort.c:201
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
static int compare_date_sent(const struct Email *a, const struct Email *b, bool reverse)
Compare the sent date of two emails - Implements sort_mail_t -.
Definition: sort.c:99
static int compare_subject(const struct Email *a, const struct Email *b, bool reverse)
Compare the subject of two emails - Implements sort_mail_t -.
Definition: sort.c:108
static int compare_score(const struct Email *a, const struct Email *b, bool reverse)
Compare two emails using their scores - Implements sort_mail_t -.
Definition: sort.c:81
static int compare_from(const struct Email *a, const struct Email *b, bool reverse)
Compare the 'from' fields of two emails - Implements sort_mail_t -.
Definition: sort.c:170
static int compare_size(const struct Email *a, const struct Email *b, bool reverse)
Compare the size of two emails - Implements sort_mail_t -.
Definition: sort.c:90
static int compare_date_received(const struct Email *a, const struct Email *b, bool reverse)
Compare the date received of two emails - Implements sort_mail_t -.
Definition: sort.c:183
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition: mailbox.h:49
#define _(a)
Definition: message.h:28
@ SORT_SUBJECT
Sort by the email's subject.
Definition: sort2.h:42
@ SORT_ORDER
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:44
@ SORT_SPAM
Sort by the email's spam score.
Definition: sort2.h:53
@ SORT_LABEL
Sort by the emails label.
Definition: sort2.h:58
@ SORT_FROM
Sort by the email's From field.
Definition: sort2.h:43
@ SORT_SIZE
Sort by the size of the email.
Definition: sort2.h:40
@ SORT_RECEIVED
Sort by when the message were delivered locally.
Definition: sort2.h:46
@ SORT_TO
Sort by the email's To field.
Definition: sort2.h:47
@ SORT_DATE
Sort by the date the email was sent.
Definition: sort2.h:39
@ SORT_SCORE
Sort by the email's score.
Definition: sort2.h:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ 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.

Parameters
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}
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:74
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:75
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:62
+ 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.

Parameters
mMailbox
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;
361
362 OptNeedResort = false;
363
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 }
374
375 if (m->verbose)
376 mutt_message(_("Sorting mailbox..."));
377
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;
390
391 if (OptResortInit)
392 {
393 OptResortInit = false;
394 init = true;
395 }
396
397 if (init)
398 mutt_clear_threads(threads);
399
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 }
414
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;
422
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 }
431
432 /* re-collapse threads marked as collapsed */
433 if (threaded)
434 {
436 *vsize = mutt_set_vnum(m);
437 }
438
439 if (m->verbose)
441
442 return;
443}
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
bool OptNeedRescore
(pseudo) set when the 'score' command is used
Definition: globals.c:75
bool OptResortInit
(pseudo) used to force the next resort to be from scratch
Definition: globals.c:84
bool OptNeedResort
(pseudo) used to force a re-sort
Definition: globals.c:76
#define mutt_message(...)
Definition: logging.h:86
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
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:1836
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
bool visible
Is this message part of the view?
Definition: email.h:120
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:119
bool threaded
Used for threading.
Definition: email.h:107
int vnum
Virtual message number.
Definition: email.h:113
int msgno
Number displayed to the user.
Definition: email.h:110
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:114
+ Here is the call graph for this function:
+ Here is the caller graph for this function: