Link Here
|
|
|
1 |
diff -ru work.old/mutt-1.5.6/OPS work/mutt-1.5.6/OPS |
2 |
--- OPS Wed Nov 5 10:41:31 2003 |
3 |
+++ OPS Tue Feb 10 14:40:41 2004 |
4 |
@@ -96,6 +96,7 @@ |
5 |
OP_LIST_REPLY "reply to specified mailing list" |
6 |
OP_MACRO "execute a macro" |
7 |
OP_MAIL "compose a new mail message" |
8 |
+OP_MAIN_BREAK_THREAD "break the thread in two" |
9 |
OP_MAIN_CHANGE_FOLDER "open a different folder" |
10 |
OP_MAIN_CHANGE_FOLDER_READONLY "open a different folder in read only mode" |
11 |
OP_MAIN_CLEAR_FLAG "clear a status flag from a message" |
12 |
@@ -105,6 +106,7 @@ |
13 |
OP_MAIN_FIRST_MESSAGE "move to the first message" |
14 |
OP_MAIN_LAST_MESSAGE "move to the last message" |
15 |
OP_MAIN_LIMIT "show only messages matching a pattern" |
16 |
+OP_MAIN_LINK_THREADS "link tagged message to the current one" |
17 |
OP_MAIN_NEXT_NEW "jump to the next new message" |
18 |
OP_MAIN_NEXT_NEW_THEN_UNREAD "jump to the next new or unread message" |
19 |
OP_MAIN_NEXT_SUBTHREAD "jump to the next subthread" |
20 |
diff -ru work.old/mutt-1.5.6/acconfig.h work/mutt-1.5.6/acconfig.h |
21 |
--- acconfig.h Tue Jan 21 11:50:49 2003 |
22 |
+++ acconfig.h Tue Feb 10 14:40:41 2004 |
23 |
@@ -36,3 +36,7 @@ |
24 |
* all return values other than (size_t)(-1) as equivalent. */ |
25 |
#undef ICONV_NONTRANS |
26 |
|
27 |
+/* Do you want to use the rethreading functions with IMAP |
28 |
+ * (--enable-imap-edit-threads) */ |
29 |
+#undef IMAP_EDIT_THREADS |
30 |
+ |
31 |
diff -ru work.old/mutt-1.5.6/config.h.in work/mutt-1.5.6/config.h.in |
32 |
--- config.h.in Sun Feb 1 18:18:21 2004 |
33 |
+++ config.h.in Tue Feb 10 14:40:41 2004 |
34 |
@@ -549,3 +549,7 @@ |
35 |
* all return values other than (size_t)(-1) as equivalent. */ |
36 |
#undef ICONV_NONTRANS |
37 |
|
38 |
+/* Do you want to use the rethreading functions with IMAP |
39 |
+ * (--enable-imap-edit-threads) */ |
40 |
+#undef IMAP_EDIT_THREADS |
41 |
+ |
42 |
diff -ru work.old/mutt-1.5.6/configure work/mutt-1.5.6/configure |
43 |
--- configure Sun Feb 1 19:22:06 2004 |
44 |
+++ configure Tue Feb 10 14:40:41 2004 |
45 |
@@ -40,6 +40,8 @@ |
46 |
ac_help="$ac_help |
47 |
--with-gss[=PFX] Compile in GSSAPI authentication for IMAP" |
48 |
ac_help="$ac_help |
49 |
+ --enable-imap-edit-threads Enable editing threads support for IMAP" |
50 |
+ac_help="$ac_help |
51 |
--with-ssl[=PFX] Compile in SSL support for POP/IMAP" |
52 |
ac_help="$ac_help |
53 |
--with-nss[=PFX] Compile in SSL support for POP/IMAP via NSS" |
54 |
@@ -5383,6 +5385,23 @@ |
55 |
else |
56 |
USE_GSS_TRUE='#' |
57 |
USE_GSS_FALSE= |
58 |
+fi |
59 |
+ |
60 |
+ |
61 |
+# Check whether --enable-imap-edit-threads or --disable-imap-edit-threads was given. |
62 |
+if test "${enable_imap_edit_threads+set}" = set; then |
63 |
+ enableval="$enable_imap_edit_threads" |
64 |
+ |
65 |
+ if test "$enableval" = "yes"; then |
66 |
+ if test "$need_imap" = "yes"; then |
67 |
+ cat >> confdefs.h <<\EOF |
68 |
+#define IMAP_EDIT_THREADS 1 |
69 |
+EOF |
70 |
+ |
71 |
+ else |
72 |
+ echo "configure: warning: IMAP support for edit_threads is only useful with IMAP support" 1>&2 |
73 |
+ fi |
74 |
+fi |
75 |
fi |
76 |
|
77 |
|
78 |
diff -ru work.old/mutt-1.5.6/configure.in work/mutt-1.5.6/configure.in |
79 |
--- configure.in Sun Feb 1 19:22:05 2004 |
80 |
+++ configure.in Tue Feb 10 14:40:41 2004 |
81 |
@@ -559,6 +559,16 @@ |
82 |
|
83 |
dnl -- end imap dependencies -- |
84 |
|
85 |
+AC_ARG_ENABLE(imap-edit-threads, [ --enable-imap-edit-threads Enable editing threads support for IMAP], |
86 |
+[ |
87 |
+ if test "$enableval" = "yes"; then |
88 |
+ if test "$need_imap" = "yes"; then |
89 |
+ AC_DEFINE(IMAP_EDIT_THREADS) |
90 |
+ else |
91 |
+ AC_MSG_WARN([IMAP support for edit_threads is only useful with IMAP support]) |
92 |
+ fi |
93 |
+fi]) |
94 |
+ |
95 |
AC_ARG_WITH(ssl, [ --with-ssl[=PFX] Compile in SSL support for POP/IMAP], |
96 |
[ if test "$with_ssl" != "no" |
97 |
then |
98 |
diff -ru work.old/mutt-1.5.6/copy.c work/mutt-1.5.6/copy.c |
99 |
--- copy.c Wed Nov 5 10:41:31 2003 |
100 |
+++ copy.c Tue Feb 10 14:40:41 2004 |
101 |
@@ -95,6 +95,12 @@ |
102 |
(ascii_strncasecmp ("Content-Length:", buf, 15) == 0 || |
103 |
ascii_strncasecmp ("Lines:", buf, 6) == 0)) |
104 |
continue; |
105 |
+ if ((flags & CH_UPDATE_REFS) && |
106 |
+ ascii_strncasecmp ("References:", buf, 11) == 0) |
107 |
+ continue; |
108 |
+ if ((flags & CH_UPDATE_IRT) && |
109 |
+ ascii_strncasecmp ("In-Reply-To:", buf, 12) == 0) |
110 |
+ continue; |
111 |
ignore = 0; |
112 |
} |
113 |
|
114 |
@@ -193,6 +199,12 @@ |
115 |
ascii_strncasecmp ("type:", buf + 8, 5) == 0)) || |
116 |
ascii_strncasecmp ("mime-version:", buf, 13) == 0)) |
117 |
continue; |
118 |
+ if ((flags & CH_UPDATE_REFS) && |
119 |
+ ascii_strncasecmp ("References:", buf, 11) == 0) |
120 |
+ continue; |
121 |
+ if ((flags & CH_UPDATE_IRT) && |
122 |
+ ascii_strncasecmp ("In-Reply-To:", buf, 12) == 0) |
123 |
+ continue; |
124 |
|
125 |
/* Find x -- the array entry where this header is to be saved */ |
126 |
if (flags & CH_REORDER) |
127 |
@@ -326,6 +338,8 @@ |
128 |
CH_XMIT ignore Lines: and Content-Length: |
129 |
CH_WEED do header weeding |
130 |
CH_NOQFROM ignore ">From " line |
131 |
+ CH_UPDATE_IRT update the In-Reply-To: header |
132 |
+ CH_UPDATE_REFS update the References: header |
133 |
|
134 |
prefix |
135 |
string to use if CH_PREFIX is set |
136 |
@@ -335,6 +349,9 @@ |
137 |
mutt_copy_header (FILE *in, HEADER *h, FILE *out, int flags, const char *prefix) |
138 |
{ |
139 |
char buffer[SHORT_STRING]; |
140 |
+ |
141 |
+ flags |= (h->irt_changed ? CH_UPDATE_IRT : 0) |
142 |
+ | (h->refs_changed ? CH_UPDATE_REFS : 0); |
143 |
|
144 |
if (mutt_copy_hdr (in, out, h->offset, h->content->offset, flags, prefix) == -1) |
145 |
return (-1); |
146 |
@@ -358,7 +375,56 @@ |
147 |
if (flags & CH_UPDATE) |
148 |
{ |
149 |
if ((flags & CH_NOSTATUS) == 0) |
150 |
+#ifdef IMAP_EDIT_THREADS |
151 |
+#define NEW_ENV new_env |
152 |
+#else |
153 |
+#define NEW_ENV env |
154 |
+#endif |
155 |
{ |
156 |
+ if (h->irt_changed && h->NEW_ENV->in_reply_to) |
157 |
+ { |
158 |
+ LIST *listp = h->NEW_ENV->in_reply_to; |
159 |
+ |
160 |
+ if (fputs ("In-Reply-To: ", out) == EOF) |
161 |
+ return (-1); |
162 |
+ |
163 |
+ for (; listp; listp = listp->next) |
164 |
+ if ((fputs (listp->data, out) == EOF) || (fputc (' ', out) == EOF)) |
165 |
+ return (-1); |
166 |
+ |
167 |
+ if (fputc ('\n', out) == EOF) |
168 |
+ return (-1); |
169 |
+ } |
170 |
+ |
171 |
+ if (h->refs_changed && h->NEW_ENV->references) |
172 |
+ { |
173 |
+ LIST *listp = h->NEW_ENV->references, *refs = NULL, *t; |
174 |
+ |
175 |
+ if (fputs ("References: ", out) == EOF) |
176 |
+ return (-1); |
177 |
+ |
178 |
+ /* Mutt stores references in reverse order, thus we create |
179 |
+ * a reordered refs list that we can put in the headers */ |
180 |
+ for (; listp; listp = listp->next, refs = t) |
181 |
+ { |
182 |
+ t = (LIST *)safe_malloc (sizeof (LIST)); |
183 |
+ t->data = listp->data; |
184 |
+ t->next = refs; |
185 |
+ } |
186 |
+ |
187 |
+ for (; refs; refs = refs->next) |
188 |
+ if ((fputs (refs->data, out) == EOF) || (fputc (' ', out) == EOF)) |
189 |
+ return (-1); |
190 |
+ |
191 |
+ /* clearing refs from memory */ |
192 |
+ for (t = refs; refs; refs = t->next, t = refs) |
193 |
+ safe_free ((void **)&refs); |
194 |
+ |
195 |
+ if (fputc ('\n', out) == EOF) |
196 |
+ return (-1); |
197 |
+ } |
198 |
+#undef NEW_ENV |
199 |
+ |
200 |
if (h->old || h->read) |
201 |
{ |
202 |
if (fputs ("Status: ", out) == EOF) |
203 |
diff -ru work.old/mutt-1.5.6/curs_main.c work/mutt-1.5.6/curs_main.c |
204 |
--- curs_main.c Wed Nov 5 10:41:31 2003 |
205 |
+++ curs_main.c Tue Feb 10 14:40:41 2004 |
206 |
@@ -930,6 +930,11 @@ |
207 |
else |
208 |
{ |
209 |
mutt_set_flag (Context, CURHDR, M_TAG, !CURHDR->tagged); |
210 |
+ |
211 |
+ Context->last_tag = CURHDR->tagged ? CURHDR : |
212 |
+ ((Context->last_tag == CURHDR && !CURHDR->tagged) |
213 |
+ ? NULL : Context->last_tag); |
214 |
+ |
215 |
menu->redraw = REDRAW_STATUS; |
216 |
if (option (OPTRESOLVE) && menu->current < Context->vcount - 1) |
217 |
{ |
218 |
@@ -1162,6 +1167,89 @@ |
219 |
} |
220 |
done = 1; |
221 |
} |
222 |
+ break; |
223 |
+ |
224 |
+ case OP_MAIN_BREAK_THREAD: |
225 |
+ |
226 |
+ CHECK_MSGCOUNT; |
227 |
+ CHECK_VISIBLE; |
228 |
+ CHECK_READONLY; |
229 |
+ |
230 |
+ if ((Sort & SORT_MASK) != SORT_THREADS) |
231 |
+ mutt_error _("Threading is not enabled."); |
232 |
+ |
233 |
+#if defined (USE_IMAP) && ! defined (IMAP_EDIT_THREADS) |
234 |
+ else if (Context->magic == M_IMAP) |
235 |
+ mutt_error _("Compile Mutt with --enable-imap-edit-threads for break-thread support"); |
236 |
+#endif |
237 |
+ |
238 |
+ else |
239 |
+ { |
240 |
+ { |
241 |
+ HEADER *oldcur = CURHDR; |
242 |
+ |
243 |
+ mutt_break_thread (CURHDR); |
244 |
+ mutt_sort_headers (Context, 1); |
245 |
+ menu->current = oldcur->virtual; |
246 |
+ } |
247 |
+ |
248 |
+ Context->changed = 1; |
249 |
+ mutt_message _("Thread broken"); |
250 |
+ |
251 |
+ if (menu->menu == MENU_PAGER) |
252 |
+ { |
253 |
+ op = OP_DISPLAY_MESSAGE; |
254 |
+ continue; |
255 |
+ } |
256 |
+ else |
257 |
+ menu->redraw |= REDRAW_INDEX; |
258 |
+ } |
259 |
+ |
260 |
+ break; |
261 |
+ |
262 |
+ case OP_MAIN_LINK_THREADS: |
263 |
+ |
264 |
+ CHECK_MSGCOUNT; |
265 |
+ CHECK_VISIBLE; |
266 |
+ CHECK_READONLY; |
267 |
+ |
268 |
+ if ((Sort & SORT_MASK) != SORT_THREADS) |
269 |
+ mutt_error _("Threading is not enabled."); |
270 |
+ |
271 |
+#if defined (USE_IMAP) && ! defined (IMAP_EDIT_THREADS) |
272 |
+ else if (Context->magic == M_IMAP) |
273 |
+ mutt_error _("Compile Mutt with --enable-imap-edit-threads for link-threads support"); |
274 |
+#endif |
275 |
+ |
276 |
+ else if (!CURHDR->env->message_id) |
277 |
+ mutt_error _("No Message-ID: header available to link thread"); |
278 |
+ else if (!tag && (!Context->last_tag || !Context->last_tag->tagged)) |
279 |
+ mutt_error _("First, please tag a message to be linked here"); |
280 |
+ else |
281 |
+ { |
282 |
+ HEADER *oldcur = CURHDR; |
283 |
+ |
284 |
+ if (mutt_link_threads (CURHDR, tag ? NULL : Context->last_tag, |
285 |
+ Context)) |
286 |
+ { |
287 |
+ mutt_sort_headers (Context, 1); |
288 |
+ menu->current = oldcur->virtual; |
289 |
+ |
290 |
+ Context->changed = 1; |
291 |
+ mutt_message _("Threads linked"); |
292 |
+ } |
293 |
+ else |
294 |
+ mutt_error _("No thread linked"); |
295 |
+ } |
296 |
+ |
297 |
+ if (menu->menu == MENU_PAGER) |
298 |
+ { |
299 |
+ op = OP_DISPLAY_MESSAGE; |
300 |
+ continue; |
301 |
+ } |
302 |
+ else |
303 |
+ menu->redraw |= REDRAW_STATUS | REDRAW_INDEX; |
304 |
+ |
305 |
break; |
306 |
|
307 |
case OP_EDIT_TYPE: |
308 |
diff -ru work.old/mutt-1.5.6/doc/manual.sgml.head work/mutt-1.5.6/doc/manual.sgml.head |
309 |
--- doc/manual.sgml.head Sun Feb 1 18:49:53 2004 |
310 |
+++ doc/manual.sgml.head Tue Feb 10 14:40:41 2004 |
311 |
@@ -2197,8 +2197,43 @@ |
312 |
with large volume mailing lists easier because you can easily delete |
313 |
uninteresting threads and quickly find topics of value. |
314 |
|
315 |
+<sect1>Editing threads |
316 |
+<p> |
317 |
+Mutt has the ability to dynamically restructure threads that are broken |
318 |
+either by misconfigured software or bad behaviour from some |
319 |
+correspondents. This allows to clean your mailboxes formats) from these |
320 |
+annoyances which make it hard to follow a discussion. |
321 |
+ |
322 |
+If you want to use these functions with IMAP, you need to compile Mutt |
323 |
+with the <em/--enable-imap-edit-threads/ configure flag. |
324 |
+ |
325 |
+<sect2>Linking threads |
326 |
+<p> |
327 |
+ |
328 |
+Some mailers tend to "forget" to correctly set the "In-Reply-To:" and |
329 |
+"References:" headers when replying to a message. This results in broken |
330 |
+discussions because Mutt has not enough information to guess the correct |
331 |
+threading. |
332 |
+You can fix this by tagging the reply, then moving to the parent message |
333 |
+and using the ``link-threads'' function (bound to & by default). The |
334 |
+reply will then be connected to this "parent" message. |
335 |
+ |
336 |
+You can also connect multiple childs at once, tagging them and using the |
337 |
+tag-prefix command (';') or the auto_tag option. |
338 |
+ |
339 |
+<sect2>Breaking threads |
340 |
+<p> |
341 |
+ |
342 |
+On mailing lists, some people are in the bad habit of starting a new |
343 |
+discussion by hitting "reply" to any message from the list and changing |
344 |
+the subject to a totally unrelated one. |
345 |
+You can fix such threads by using the ``break-thread'' function (bound |
346 |
+by default to #), which will turn the subthread starting from the |
347 |
+current message into a whole different thread. |
348 |
+ |
349 |
<sect1>Delivery Status Notification (DSN) Support |
350 |
<p> |
351 |
+ |
352 |
RFC1894 defines a set of MIME content types for relaying information |
353 |
about the status of electronic mail messages. These can be thought of as |
354 |
``return receipts.'' Berkeley sendmail 8.8.x currently has some command |
355 |
diff -ru work.old/mutt-1.5.6/functions.h work/mutt-1.5.6/functions.h |
356 |
--- functions.h Wed Nov 5 10:41:31 2003 |
357 |
+++ functions.h Tue Feb 10 14:40:41 2004 |
358 |
@@ -69,6 +69,7 @@ |
359 |
struct binding_t OpMain[] = { |
360 |
{ "create-alias", OP_CREATE_ALIAS, "a" }, |
361 |
{ "bounce-message", OP_BOUNCE_MESSAGE, "b" }, |
362 |
+ { "break-thread", OP_MAIN_BREAK_THREAD, "#" }, |
363 |
{ "change-folder", OP_MAIN_CHANGE_FOLDER, "c" }, |
364 |
{ "change-folder-readonly", OP_MAIN_CHANGE_FOLDER_READONLY, "\033c" }, |
365 |
{ "collapse-thread", OP_MAIN_COLLAPSE_THREAD, "\033v" }, |
366 |
@@ -95,6 +96,7 @@ |
367 |
{ "next-undeleted", OP_MAIN_NEXT_UNDELETED, "j" }, |
368 |
{ "previous-undeleted", OP_MAIN_PREV_UNDELETED, "k" }, |
369 |
{ "limit", OP_MAIN_LIMIT, "l" }, |
370 |
+ { "link-threads", OP_MAIN_LINK_THREADS, "&" }, |
371 |
{ "list-reply", OP_LIST_REPLY, "L" }, |
372 |
{ "mail", OP_MAIL, "m" }, |
373 |
{ "toggle-new", OP_TOGGLE_NEW, "N" }, |
374 |
@@ -153,6 +155,7 @@ |
375 |
}; |
376 |
|
377 |
struct binding_t OpPager[] = { |
378 |
+ { "break-thread", OP_MAIN_BREAK_THREAD, "#" }, |
379 |
{ "create-alias", OP_CREATE_ALIAS, "a" }, |
380 |
{ "bounce-message", OP_BOUNCE_MESSAGE, "b" }, |
381 |
{ "change-folder", OP_MAIN_CHANGE_FOLDER, "c" }, |
382 |
@@ -175,6 +178,7 @@ |
383 |
{ "next-entry", OP_NEXT_ENTRY, "J" }, |
384 |
{ "previous-undeleted",OP_MAIN_PREV_UNDELETED, "k" }, |
385 |
{ "previous-entry", OP_PREV_ENTRY, "K" }, |
386 |
+ { "link-threads", OP_MAIN_LINK_THREADS, "&" }, |
387 |
{ "list-reply", OP_LIST_REPLY, "L" }, |
388 |
{ "redraw-screen", OP_REDRAW, "\014" }, |
389 |
{ "mail", OP_MAIL, "m" }, |
390 |
diff -ru work.old/mutt-1.5.6/imap/imap.c work/mutt-1.5.6/imap/imap.c |
391 |
--- imap/imap.c Sun Feb 1 18:10:58 2004 |
392 |
+++ imap/imap.c Tue Feb 10 14:40:41 2004 |
393 |
@@ -981,9 +981,11 @@ |
394 |
mutt_buffer_addstr (&cmd, "UID STORE "); |
395 |
mutt_buffer_addstr (&cmd, uid); |
396 |
|
397 |
- /* if attachments have been deleted we delete the message and reupload |
398 |
- * it. This works better if we're expunging, of course. */ |
399 |
- if (ctx->hdrs[n]->attach_del) |
400 |
+ /* if the message has been rethreaded or attachments have been deleted |
401 |
+ * we delete the message and reupload it. |
402 |
+ * This works better if we're expunging, of course. */ |
403 |
+ if (ctx->hdrs[n]->refs_changed || ctx->hdrs[n]->irt_changed || |
404 |
+ ctx->hdrs[n]->attach_del) |
405 |
{ |
406 |
dprint (3, (debugfile, "imap_sync_mailbox: Attachments to be deleted, falling back to _mutt_save_message\n")); |
407 |
if (!appendctx) |
408 |
diff -ru work.old/mutt-1.5.6/main.c work/mutt-1.5.6/main.c |
409 |
--- main.c Tue Mar 4 08:49:48 2003 |
410 |
+++ main.c Tue Feb 10 14:40:41 2004 |
411 |
@@ -228,6 +228,12 @@ |
412 |
"-USE_IMAP " |
413 |
#endif |
414 |
|
415 |
+#ifdef IMAP_EDIT_THREADS |
416 |
+ "+IMAP_EDIT_THREADS " |
417 |
+#else |
418 |
+ "-IMAP_EDIT_THREADS " |
419 |
+#endif |
420 |
+ |
421 |
#ifdef USE_GSS |
422 |
"+USE_GSS " |
423 |
#else |
424 |
diff -ru work.old/mutt-1.5.6/mh.c work/mutt-1.5.6/mh.c |
425 |
--- mh.c Sun Feb 1 18:10:57 2004 |
426 |
+++ mh.c Tue Feb 10 14:40:41 2004 |
427 |
@@ -1220,7 +1220,7 @@ |
428 |
{ |
429 |
HEADER *h = ctx->hdrs[msgno]; |
430 |
|
431 |
- if (h->attach_del) |
432 |
+ if (h->attach_del || h->refs_changed || h->irt_changed) |
433 |
if (mh_rewrite_message (ctx, msgno) != 0) |
434 |
return -1; |
435 |
|
436 |
@@ -1231,9 +1231,9 @@ |
437 |
{ |
438 |
HEADER *h = ctx->hdrs[msgno]; |
439 |
|
440 |
- if (h->attach_del) |
441 |
+ if (h->attach_del || h->refs_changed || h->irt_changed) |
442 |
{ |
443 |
- /* when doing attachment deletion, fall back to the MH case. */ |
444 |
+ /* when doing attachment deletion/rethreading, fall back to the MH case. */ |
445 |
if (mh_rewrite_message (ctx, msgno) != 0) |
446 |
return (-1); |
447 |
} |
448 |
diff -ru work.old/mutt-1.5.6/mutt.h work/mutt-1.5.6/mutt.h |
449 |
--- mutt.h Sun Feb 1 18:15:17 2004 |
450 |
+++ mutt.h Tue Feb 10 14:41:33 2004 |
451 |
@@ -94,6 +94,8 @@ |
452 |
#define CH_WEED_DELIVERED (1<<13) /* weed eventual Delivered-To headers */ |
453 |
#define CH_FORCE_FROM (1<<14) /* give CH_FROM precedence over CH_WEED? */ |
454 |
#define CH_NOQFROM (1<<15) /* give CH_FROM precedence over CH_WEED? */ |
455 |
+#define CH_UPDATE_IRT (1<<16) /* update In-Reply-To: */ |
456 |
+#define CH_UPDATE_REFS (1<<17) /* update References: */ |
457 |
|
458 |
/* flags for mutt_enter_string() */ |
459 |
#define M_ALIAS 1 /* do alias "completion" by calling up the alias-menu */ |
460 |
@@ -518,6 +520,8 @@ |
461 |
void mutt_free_rx_list (RX_LIST **); |
462 |
int mutt_matches_ignore (const char *, LIST *); |
463 |
|
464 |
+LIST *mutt_copy_list (LIST *); |
465 |
+ |
466 |
/* add an element to a list */ |
467 |
LIST *mutt_add_list (LIST *, const char *); |
468 |
|
469 |
@@ -657,6 +661,8 @@ |
470 |
unsigned int subject_changed : 1; /* used for threading */ |
471 |
unsigned int threaded : 1; /* used for threading */ |
472 |
unsigned int display_subject : 1; /* used for threading */ |
473 |
+ unsigned int irt_changed : 1; /* In-Reply-To changed to link/break threads */ |
474 |
+ unsigned int refs_changed : 1; /* References changed to break thread */ |
475 |
unsigned int recip_valid : 1; /* is_recipient is valid */ |
476 |
unsigned int active : 1; /* message is not to be removed */ |
477 |
unsigned int trash : 1; /* message is marked as trashed on disk. |
478 |
@@ -697,6 +703,10 @@ |
479 |
char *tree; /* character string to print thread tree */ |
480 |
struct thread *thread; |
481 |
|
482 |
+#ifdef IMAP_EDIT_THREADS |
483 |
+ ENVELOPE *new_env; /* envelope information for rethreading */ |
484 |
+#endif |
485 |
+ |
486 |
#ifdef MIXMASTER |
487 |
LIST *chain; |
488 |
#endif |
489 |
@@ -761,6 +771,7 @@ |
490 |
char *pattern; /* limit pattern string */ |
491 |
pattern_t *limit_pattern; /* compiled limit pattern */ |
492 |
HEADER **hdrs; |
493 |
+ HEADER *last_tag; /* last tagged msg. used to link threads */ |
494 |
THREAD *tree; /* top of thread tree */ |
495 |
HASH *id_hash; /* hash table by msg id */ |
496 |
HASH *subj_hash; /* hash table by subject */ |
497 |
diff -ru work.old/mutt-1.5.6/mx.c work/mutt-1.5.6/mx.c |
498 |
--- mx.c Wed Nov 5 10:41:32 2003 |
499 |
+++ mx.c Tue Feb 10 14:40:41 2004 |
500 |
@@ -1161,6 +1161,8 @@ |
501 |
ctx->deleted = 0; |
502 |
} |
503 |
} |
504 |
+ else if (ctx->last_tag && ctx->last_tag->deleted) |
505 |
+ ctx->last_tag = NULL; /* reset last tagged msg now useless */ |
506 |
} |
507 |
|
508 |
/* really only for IMAP - imap_sync_mailbox results in a call to |
509 |
diff -ru work.old/mutt-1.5.6/pager.c work/mutt-1.5.6/pager.c |
510 |
--- pager.c Sun Feb 1 18:10:57 2004 |
511 |
+++ pager.c Tue Feb 10 14:40:41 2004 |
512 |
@@ -2481,6 +2481,11 @@ |
513 |
case OP_TAG: |
514 |
CHECK_MODE(IsHeader (extra)); |
515 |
mutt_set_flag (Context, extra->hdr, M_TAG, !extra->hdr->tagged); |
516 |
+ |
517 |
+ Context->last_tag = extra->hdr->tagged ? extra->hdr : |
518 |
+ ((Context->last_tag == extra->hdr && !extra->hdr->tagged) |
519 |
+ ? NULL : Context->last_tag); |
520 |
+ |
521 |
redraw = REDRAW_STATUS | REDRAW_INDEX; |
522 |
if (option (OPTRESOLVE)) |
523 |
{ |
524 |
diff -ru work.old/mutt-1.5.6/protos.h work/mutt-1.5.6/protos.h |
525 |
--- protos.h Sun Feb 1 18:15:17 2004 |
526 |
+++ protos.h Tue Feb 10 14:40:41 2004 |
527 |
@@ -148,6 +148,7 @@ |
528 |
void mutt_block_signals_system (void); |
529 |
void mutt_body_handler (BODY *, STATE *); |
530 |
int mutt_bounce_message (FILE *fp, HEADER *, ADDRESS *); |
531 |
+void mutt_break_thread (HEADER *); |
532 |
void mutt_buffy (char *, size_t); |
533 |
int mutt_buffy_list (void); |
534 |
void mutt_canonical_charset (char *, size_t, const char *); |
535 |
@@ -289,6 +290,7 @@ |
536 |
int mutt_is_subscribed_list (ADDRESS *); |
537 |
int mutt_is_text_part (BODY *); |
538 |
int mutt_is_valid_mailbox (const char *); |
539 |
+int mutt_link_threads (HEADER *, HEADER *, CONTEXT *); |
540 |
int mutt_lookup_mime_type (BODY *, const char *); |
541 |
int mutt_match_rx_list (const char *, RX_LIST *); |
542 |
int mutt_messages_in_thread (CONTEXT *, HEADER *, int); |
543 |
diff -ru work.old/mutt-1.5.6/thread.c work/mutt-1.5.6/thread.c |
544 |
--- thread.c Sun Feb 1 18:10:58 2004 |
545 |
+++ thread.c Tue Feb 10 14:40:41 2004 |
546 |
@@ -1336,3 +1336,105 @@ |
547 |
|
548 |
return hash; |
549 |
} |
550 |
+ |
551 |
+static void clean_references (THREAD *brk, THREAD *cur) |
552 |
+{ |
553 |
+ THREAD *p; |
554 |
+ LIST *ref = NULL; |
555 |
+ int done = 0; |
556 |
+ |
557 |
+ for (; cur; cur = cur->next, done = 0) |
558 |
+ { |
559 |
+ /* parse subthread recursively */ |
560 |
+ clean_references (brk, cur->child); |
561 |
+ |
562 |
+ if (!cur->message) |
563 |
+ break; /* skip pseudo-message */ |
564 |
+ |
565 |
+ /* Looking for the first bad reference according to the new threading. |
566 |
+ * Optimal since Mutt stores the references in reverse order, and the |
567 |
+ * first loop should match immediatly for mails respecting RFC2822. */ |
568 |
+ for (p = brk; !done && p; p = p->parent) |
569 |
+ for (ref = cur->message->env->references; p->message && ref; ref = ref->next) |
570 |
+ if (!mutt_strcasecmp (ref->data, p->message->env->message_id)) |
571 |
+ { |
572 |
+ done = 1; |
573 |
+ break; |
574 |
+ } |
575 |
+ |
576 |
+ if (done) |
577 |
+ { |
578 |
+ HEADER *h = cur->message; |
579 |
+ |
580 |
+ /* clearing the References: header from obsolete Message-Id(s) */ |
581 |
+ mutt_free_list (&ref->next); |
582 |
+ |
583 |
+#ifdef IMAP_EDIT_THREADS |
584 |
+ if (h->new_env) |
585 |
+ mutt_free_list (&h->new_env->references); |
586 |
+ else |
587 |
+ h->new_env = mutt_new_envelope (); |
588 |
+ |
589 |
+ h->new_env->references = mutt_copy_list (h->env->references); |
590 |
+#endif |
591 |
+ |
592 |
+ h->refs_changed = h->changed = 1; |
593 |
+ } |
594 |
+ } |
595 |
+} |
596 |
+ |
597 |
+void mutt_break_thread (HEADER *hdr) |
598 |
+{ |
599 |
+ mutt_free_list (&hdr->env->in_reply_to); |
600 |
+ mutt_free_list (&hdr->env->references); |
601 |
+ hdr->irt_changed = hdr->refs_changed = hdr->changed = 1; |
602 |
+ |
603 |
+#ifdef IMAP_EDIT_THREADS |
604 |
+ if (hdr->new_env) |
605 |
+ { |
606 |
+ mutt_free_list (&hdr->new_env->in_reply_to); |
607 |
+ mutt_free_list (&hdr->new_env->references); |
608 |
+ } |
609 |
+ else |
610 |
+ hdr->new_env = mutt_new_envelope (); |
611 |
+#endif |
612 |
+ |
613 |
+ clean_references (hdr->thread, hdr->thread->child); |
614 |
+} |
615 |
+ |
616 |
+static int link_threads (HEADER *parent, HEADER *child, CONTEXT *ctx) |
617 |
+{ |
618 |
+ if (child == parent) |
619 |
+ return 0; |
620 |
+ |
621 |
+ mutt_break_thread (child); |
622 |
+ |
623 |
+ child->env->in_reply_to = mutt_new_list (); |
624 |
+ child->env->in_reply_to->data = safe_strdup (parent->env->message_id); |
625 |
+ |
626 |
+#ifdef IMAP_EDIT_THREADS |
627 |
+ child->new_env->in_reply_to = mutt_new_list (); |
628 |
+ child->new_env->in_reply_to->data = safe_strdup (parent->env->message_id); |
629 |
+#endif |
630 |
+ |
631 |
+ mutt_set_flag (ctx, child, M_TAG, 0); |
632 |
+ |
633 |
+ child->irt_changed = child->changed = 1; |
634 |
+ return 1; |
635 |
+} |
636 |
+ |
637 |
+int mutt_link_threads (HEADER *cur, HEADER *last, CONTEXT *ctx) |
638 |
+{ |
639 |
+ int i, changed = 0; |
640 |
+ |
641 |
+ if (!last) |
642 |
+ { |
643 |
+ for (i = 0; i < ctx->vcount; i++) |
644 |
+ if (ctx->hdrs[Context->v2r[i]]->tagged) |
645 |
+ changed |= link_threads (cur, ctx->hdrs[Context->v2r[i]], ctx); |
646 |
+ } |
647 |
+ else |
648 |
+ changed = link_threads (cur, last, ctx); |
649 |
+ |
650 |
+ return changed; |
651 |
+} |