Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 342 lines (297 sloc) 8.918 kb
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
1 /*
2 * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
3 *
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.
8 *
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.
13 *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #if HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include "mutt.h"
24 #include "sort.h"
25 #include "mutt_idna.h"
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <unistd.h>
31
32 #define SORTCODE(x) (Sort & SORT_REVERSE) ? -(x) : x
33
34 /* function to use as discriminator when normal sort method is equal */
35 static sort_t *AuxSort = NULL;
36
37 #define AUXSORT(code,a,b) if (!code && AuxSort && !option(OPTAUXSORT)) { \
38 set_option(OPTAUXSORT); \
39 code = AuxSort(a,b); \
40 unset_option(OPTAUXSORT); \
41 } \
42 if (!code) \
43 code = (*((HEADER **)a))->index - (*((HEADER **)b))->index;
44
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
45 static int compare_score (const void *a, const void *b)
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
46 {
47 HEADER **pa = (HEADER **) a;
48 HEADER **pb = (HEADER **) b;
49 int result = (*pb)->score - (*pa)->score; /* note that this is reverse */
50 AUXSORT(result,a,b);
51 return (SORTCODE (result));
52 }
53
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
54 static int compare_size (const void *a, const void *b)
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
55 {
56 HEADER **pa = (HEADER **) a;
57 HEADER **pb = (HEADER **) b;
58 int result = (*pa)->content->length - (*pb)->content->length;
59 AUXSORT(result,a,b);
60 return (SORTCODE (result));
61 }
62
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
63 static int compare_date_sent (const void *a, const void *b)
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
64 {
65 HEADER **pa = (HEADER **) a;
66 HEADER **pb = (HEADER **) b;
67 int result = (*pa)->date_sent - (*pb)->date_sent;
68 AUXSORT(result,a,b);
69 return (SORTCODE (result));
70 }
71
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
72 static int compare_subject (const void *a, const void *b)
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
73 {
74 HEADER **pa = (HEADER **) a;
75 HEADER **pb = (HEADER **) b;
76 int rc;
77
78 if (!(*pa)->env->real_subj)
79 {
80 if (!(*pb)->env->real_subj)
81 rc = compare_date_sent (pa, pb);
82 else
83 rc = -1;
84 }
85 else if (!(*pb)->env->real_subj)
86 rc = 1;
87 else
88 rc = mutt_strcasecmp ((*pa)->env->real_subj, (*pb)->env->real_subj);
89 AUXSORT(rc,a,b);
90 return (SORTCODE (rc));
91 }
92
93 const char *mutt_get_name (ADDRESS *a)
94 {
95 ADDRESS *ali;
96
97 if (a)
98 {
99 if (option (OPTREVALIAS) && (ali = alias_reverse_lookup (a)) && ali->personal)
100 return ali->personal;
101 else if (a->personal)
102 return a->personal;
103 else if (a->mailbox)
104 return (mutt_addr_for_display (a));
105 }
106 /* don't return NULL to avoid segfault when printing/comparing */
107 return ("");
108 }
109
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
110 static int compare_to (const void *a, const void *b)
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
111 {
112 HEADER **ppa = (HEADER **) a;
113 HEADER **ppb = (HEADER **) b;
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
114 char fa[SHORT_STRING];
115 const char *fb;
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
116 int result;
117
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
118 strfcpy (fa, mutt_get_name ((*ppa)->env->to), SHORT_STRING);
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
119 fb = mutt_get_name ((*ppb)->env->to);
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
120 result = mutt_strncasecmp (fa, fb, SHORT_STRING);
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
121 AUXSORT(result,a,b);
122 return (SORTCODE (result));
123 }
124
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
125 static int compare_from (const void *a, const void *b)
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
126 {
127 HEADER **ppa = (HEADER **) a;
128 HEADER **ppb = (HEADER **) b;
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
129 char fa[SHORT_STRING];
130 const char *fb;
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
131 int result;
132
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
133 strfcpy (fa, mutt_get_name ((*ppa)->env->from), SHORT_STRING);
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
134 fb = mutt_get_name ((*ppb)->env->from);
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
135 result = mutt_strncasecmp (fa, fb, SHORT_STRING);
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
136 AUXSORT(result,a,b);
137 return (SORTCODE (result));
138 }
139
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
140 static int compare_date_received (const void *a, const void *b)
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
141 {
142 HEADER **pa = (HEADER **) a;
143 HEADER **pb = (HEADER **) b;
144 int result = (*pa)->received - (*pb)->received;
145 AUXSORT(result,a,b);
146 return (SORTCODE (result));
147 }
148
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
149 static int compare_order (const void *a, const void *b)
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
150 {
151 HEADER **ha = (HEADER **) a;
152 HEADER **hb = (HEADER **) b;
153
154 /* no need to auxsort because you will never have equality here */
155 return (SORTCODE ((*ha)->index - (*hb)->index));
156 }
157
19304f7c » Antonio Radici
2009-05-24 Imported Upstream version 1.5.19
158 static int compare_spam (const void *a, const void *b)
14c29200 » Antonio Radici
2009-05-24 Imported Upstream version 1.5.18
159 {
160 HEADER **ppa = (HEADER **) a;
161 HEADER **ppb = (HEADER **) b;
162 char *aptr, *bptr;
163 int ahas, bhas;
164 int result = 0;
165 double difference;
166
167 /* Firstly, require spam attributes for both msgs */
168 /* to compare. Determine which msgs have one. */
169 ahas = (*ppa)->env && (*ppa)->env->spam;
170 bhas = (*ppb)->env && (*ppb)->env->spam;
171
172 /* If one msg has spam attr but other does not, sort the one with first. */
173 if (ahas && !bhas)
174 return (SORTCODE(1));
175 if (!ahas && bhas)
176 return (SORTCODE(-1));
177
178 /* Else, if neither has a spam attr, presume equality. Fall back on aux. */
179 if (!ahas && !bhas)
180 {
181 AUXSORT(result, a, b);
182 return (SORTCODE(result));
183 }
184
185
186 /* Both have spam attrs. */
187
188 /* preliminary numeric examination */
189 difference = (strtod((*ppa)->env->spam->data, &aptr) -
190 strtod((*ppb)->env->spam->data, &bptr));
191
192 /* map double into comparison (-1, 0, or 1) */
193 result = (difference < 0.0 ? -1 : difference > 0.0 ? 1 : 0);
194
195 /* If either aptr or bptr is equal to data, there is no numeric */
196 /* value for that spam attribute. In this case, compare lexically. */
197 if ((aptr == (*ppa)->env->spam->data) || (bptr == (*ppb)->env->spam->data))
198 return (SORTCODE(strcmp(aptr, bptr)));
199
200 /* Otherwise, we have numeric value for both attrs. If these values */
201 /* are equal, then we first fall back upon string comparison, then */
202 /* upon auxiliary sort. */
203 if (result == 0)
204 {
205 result = strcmp(aptr, bptr);
206 if (result == 0)
207 AUXSORT(result, a, b);
208 }
209
210 return (SORTCODE(result));
211 }
212
213 sort_t *mutt_get_sort_func (int method)
214 {
215 switch (method & SORT_MASK)
216 {
217 case SORT_RECEIVED:
218 return (compare_date_received);
219 case SORT_ORDER:
220 return (compare_order);
221 case SORT_DATE:
222 return (compare_date_sent);
223 case SORT_SUBJECT:
224 return (compare_subject);
225 case SORT_FROM:
226 return (compare_from);
227 case SORT_SIZE:
228 return (compare_size);
229 case SORT_TO:
230 return (compare_to);
231 case SORT_SCORE:
232 return (compare_score);
233 case SORT_SPAM:
234 return (compare_spam);
235 default:
236 return (NULL);
237 }
238 /* not reached */
239 }
240
241 void mutt_sort_headers (CONTEXT *ctx, int init)
242 {
243 int i;
244 HEADER *h;
245 THREAD *thread, *top;
246 sort_t *sortfunc;
247
248 unset_option (OPTNEEDRESORT);
249
250 if (!ctx)
251 return;
252
253 if (!ctx->msgcount)
254 {
255 /* this function gets called by mutt_sync_mailbox(), which may have just
256 * deleted all the messages. the virtual message numbers are not updated
257 * in that routine, so we must make sure to zero the vcount member.
258 */
259 ctx->vcount = 0;
260 mutt_clear_threads (ctx);
261 return; /* nothing to do! */
262 }
263
264 if (!ctx->quiet)
265 mutt_message _("Sorting mailbox...");
266
267 if (option (OPTNEEDRESCORE) && option (OPTSCORE))
268 {
269 for (i = 0; i < ctx->msgcount; i++)
270 mutt_score_message (ctx, ctx->hdrs[i], 1);
271 }
272 unset_option (OPTNEEDRESCORE);
273
274 if (option (OPTRESORTINIT))
275 {
276 unset_option (OPTRESORTINIT);
277 init = 1;
278 }
279
280 if (init && ctx->tree)
281 mutt_clear_threads (ctx);
282
283 if ((Sort & SORT_MASK) == SORT_THREADS)
284 {
285 AuxSort = NULL;
286 /* if $sort_aux changed after the mailbox is sorted, then all the
287 subthreads need to be resorted */
288 if (option (OPTSORTSUBTHREADS))
289 {
290 i = Sort;
291 Sort = SortAux;
292 if (ctx->tree)
293 ctx->tree = mutt_sort_subthreads (ctx->tree, 1);
294 Sort = i;
295 unset_option (OPTSORTSUBTHREADS);
296 }
297 mutt_sort_threads (ctx, init);
298 }
299 else if ((sortfunc = mutt_get_sort_func (Sort)) == NULL ||
300 (AuxSort = mutt_get_sort_func (SortAux)) == NULL)
301 {
302 mutt_error _("Could not find sorting function! [report this bug]");
303 mutt_sleep (1);
304 return;
305 }
306 else
307 qsort ((void *) ctx->hdrs, ctx->msgcount, sizeof (HEADER *), sortfunc);
308
309 /* adjust the virtual message numbers */
310 ctx->vcount = 0;
311 for (i = 0; i < ctx->msgcount; i++)
312 {
313 HEADER *cur = ctx->hdrs[i];
314 if (cur->virtual != -1 || (cur->collapsed && (!ctx->pattern || cur->limited)))
315 {
316 cur->virtual = ctx->vcount;
317 ctx->v2r[ctx->vcount] = i;
318 ctx->vcount++;
319 }
320 cur->msgno = i;
321 }
322
323 /* re-collapse threads marked as collapsed */
324 if ((Sort & SORT_MASK) == SORT_THREADS)
325 {
326 top = ctx->tree;
327 while ((thread = top) != NULL)
328 {
329 while (!thread->message)
330 thread = thread->child;
331 h = thread->message;
332
333 if (h->collapsed)
334 mutt_collapse_thread (ctx, h);
335 top = top->next;
336 }
337 mutt_set_virtual (ctx);
338 }
339
340 if (!ctx->quiet)
341 mutt_clear_error ();
342 }
Something went wrong with that request. Please try again.