2 * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 #include "mutt_idna.h"
28 #define SORTCODE(x) (Sort & SORT_REVERSE) ? -(x) : x
30 /* function to use as discriminator when normal sort method is equal */
31 static sort_t *AuxSort = NULL;
33 #define AUXSORT(code,a,b) if (!code && AuxSort && !option(OPTAUXSORT)) { \
34 set_option(OPTAUXSORT); \
35 code = AuxSort(a,b); \
36 unset_option(OPTAUXSORT); \
39 code = (*((HEADER **)a))->index - (*((HEADER **)b))->index;
41 int compare_score (const void *a, const void *b)
43 HEADER **pa = (HEADER **) a;
44 HEADER **pb = (HEADER **) b;
45 int result = (*pb)->score - (*pa)->score; /* note that this is reverse */
47 return (SORTCODE (result));
50 int compare_size (const void *a, const void *b)
52 HEADER **pa = (HEADER **) a;
53 HEADER **pb = (HEADER **) b;
54 int result = (*pa)->content->length - (*pb)->content->length;
56 return (SORTCODE (result));
59 int compare_date_sent (const void *a, const void *b)
61 HEADER **pa = (HEADER **) a;
62 HEADER **pb = (HEADER **) b;
63 int result = (*pa)->date_sent - (*pb)->date_sent;
65 return (SORTCODE (result));
68 int compare_subject (const void *a, const void *b)
70 HEADER **pa = (HEADER **) a;
71 HEADER **pb = (HEADER **) b;
74 if (!(*pa)->env->real_subj)
76 if (!(*pb)->env->real_subj)
77 rc = compare_date_sent (pa, pb);
81 else if (!(*pb)->env->real_subj)
84 rc = mutt_strcasecmp ((*pa)->env->real_subj, (*pb)->env->real_subj);
86 return (SORTCODE (rc));
89 const char *mutt_get_name (ADDRESS *a)
92 const char * name = "";
96 if (option (OPTREVALIAS) && (ali = alias_reverse_lookup (a)) && ali->personal)
101 name = (mutt_addr_for_display (a));
103 /* don't return NULL to avoid segfault when printing/comparing */
107 int compare_to (const void *a, const void *b)
109 HEADER **ppa = (HEADER **) a;
110 HEADER **ppb = (HEADER **) b;
115 /* mutt_get_name() will sometimes return a pointer to a static buffer.
116 * On the next call that pointer may get smashed so we copy the return value
117 * to our own memory space. */
119 strncpy(fa,mutt_get_name ((*ppa)->env->to),sizeof(fa));
120 fa[sizeof(fa)-1] = '\0';
122 strncpy(fb,mutt_get_name ((*ppb)->env->to),sizeof(fb));
123 fb[sizeof(fb)-1] = '\0';
125 result = mutt_strcasecmp (fa, fb);
127 return (SORTCODE (result));
130 int compare_from (const void *a, const void *b)
132 HEADER **ppa = (HEADER **) a;
133 HEADER **ppb = (HEADER **) b;
138 /* mutt_get_name() will sometimes return a pointer to a static buffer.
139 * On the next call that pointer may get smashed so we copy the return value
140 * to our own memory space. */
142 strncpy(fa,mutt_get_name ((*ppa)->env->from),sizeof(fa));
143 fa[sizeof(fa)-1] = '\0';
145 strncpy(fb,mutt_get_name ((*ppb)->env->from),sizeof(fb));
146 fb[sizeof(fb)-1] = '\0';
148 result = mutt_strcasecmp (fa, fb);
150 return (SORTCODE (result));
153 int compare_date_received (const void *a, const void *b)
155 HEADER **pa = (HEADER **) a;
156 HEADER **pb = (HEADER **) b;
157 int result = (*pa)->received - (*pb)->received;
159 return (SORTCODE (result));
162 int compare_order (const void *a, const void *b)
164 HEADER **ha = (HEADER **) a;
165 HEADER **hb = (HEADER **) b;
168 if ((*ha)->article_num && (*hb)->article_num)
170 int result = (*ha)->article_num - (*hb)->article_num;
172 return (SORTCODE (result));
176 /* no need to auxsort because you will never have equality here */
177 return (SORTCODE ((*ha)->index - (*hb)->index));
180 sort_t *mutt_get_sort_func (int method)
182 switch (method & SORT_MASK)
185 return (compare_date_received);
187 return (compare_order);
189 return (compare_date_sent);
191 return (compare_subject);
193 return (compare_from);
195 return (compare_size);
199 return (compare_score);
206 void mutt_sort_headers (CONTEXT *ctx, int init)
210 THREAD *thread, *top;
213 unset_option (OPTNEEDRESORT);
220 /* this function gets called by mutt_sync_mailbox(), which may have just
221 * deleted all the messages. the virtual message numbers are not updated
222 * in that routine, so we must make sure to zero the vcount member.
225 mutt_clear_threads (ctx);
226 return; /* nothing to do! */
230 mutt_message _("Sorting mailbox...");
232 if (option (OPTNEEDRESCORE) && option (OPTSCORE))
234 for (i = 0; i < ctx->msgcount; i++)
235 mutt_score_message (ctx, ctx->hdrs[i], 1);
237 unset_option (OPTNEEDRESCORE);
239 if (option (OPTRESORTINIT))
241 unset_option (OPTRESORTINIT);
245 if (init && ctx->tree)
246 mutt_clear_threads (ctx);
248 if ((Sort & SORT_MASK) == SORT_THREADS)
251 /* if $sort_aux changed after the mailbox is sorted, then all the
252 subthreads need to be resorted */
253 if (option (OPTSORTSUBTHREADS))
258 ctx->tree = mutt_sort_subthreads (ctx->tree, 1);
260 unset_option (OPTSORTSUBTHREADS);
262 mutt_sort_threads (ctx, init);
264 else if ((sortfunc = mutt_get_sort_func (Sort)) == NULL ||
265 (AuxSort = mutt_get_sort_func (SortAux)) == NULL)
267 mutt_error _("Could not find sorting function! [report this bug]");
272 qsort ((void *) ctx->hdrs, ctx->msgcount, sizeof (HEADER *), sortfunc);
274 /* adjust the virtual message numbers */
276 for (i = 0; i < ctx->msgcount; i++)
278 HEADER *cur = ctx->hdrs[i];
279 if (cur->virtual != -1 || (cur->collapsed && (!ctx->pattern || cur->limited)))
281 cur->virtual = ctx->vcount;
282 ctx->v2r[ctx->vcount] = i;
288 /* re-collapse threads marked as collapsed */
289 if ((Sort & SORT_MASK) == SORT_THREADS)
292 while ((thread = top) != NULL)
294 while (!thread->message)
295 thread = thread->child;
299 mutt_collapse_thread (ctx, h);
302 mutt_set_virtual (ctx);