View | Details | Raw Unified | Return to bug 62651
Collapse All | Expand All

(-)./Makefile (-4 / +5 lines)
Lines 125-133 Link Here
125
125
126
.include <bsd.port.pre.mk>
126
.include <bsd.port.pre.mk>
127
127
128
.if defined(WITH_MUTT_EDIT_THREADS)
129
BROKEN=		"mutt-devel's edit threads patch appears to be broken"
130
.endif
131
CD_PATCH_VERSION=	1.5.5.1
128
CD_PATCH_VERSION=	1.5.5.1
132
CD_IFDEF_PATCH_VERSION=	1.5.4
129
CD_IFDEF_PATCH_VERSION=	1.5.4
133
.if !defined(VVV_PATCH_VERSION)
130
.if !defined(VVV_PATCH_VERSION)
Lines 213-218 Link Here
213
	@${PATCH} ${PATCH_ARGS} < ${PATCHDIR}/extra-patch-pgp-dw
210
	@${PATCH} ${PATCH_ARGS} < ${PATCHDIR}/extra-patch-pgp-dw
214
.endif
211
.endif
215
212
213
.if defined(WITH_MUTT_EDIT_THREADS)
214
pre-configure::
215
	@${PATCH} ${PATCH_ARGS} < ${PATCHDIR}/extra-patch-edit-threads
216
.endif
217
216
.if defined(WITH_MUTT_LOCALES_FIX)
218
.if defined(WITH_MUTT_LOCALES_FIX)
217
CONFIGURE_ARGS+=	--enable-locales-fix
219
CONFIGURE_ARGS+=	--enable-locales-fix
218
.endif
220
.endif
Lines 247-253 Link Here
247
SGML_NEEDED=	yes
249
SGML_NEEDED=	yes
248
.endif
250
.endif
249
.if defined(WITH_MUTT_EDIT_THREADS)
251
.if defined(WITH_MUTT_EDIT_THREADS)
250
PATCHFILES+=	patch-${CD_PATCH_VERSION}.cd.edit_threads.9.5:cd
251
CONFIGURE_ARGS+=	--enable-imap-edit-threads
252
CONFIGURE_ARGS+=	--enable-imap-edit-threads
252
SGML_NEEDED=	yes
253
SGML_NEEDED=	yes
253
.endif
254
.endif
(-)./distinfo (-1 / +9 lines)
Lines 1-10 Link Here
1
MD5 (mutt/mutt-1.5.6i.tar.gz) = aa1433635d7c86beba1675a3408b0324
1
MD5 (mutt/mutt-1.5.6i.tar.gz) = aa1433635d7c86beba1675a3408b0324
2
SIZE (mutt/mutt-1.5.6i.tar.gz) = 2910730
2
MD5 (mutt/patch-1.5.6.vvv.slang.gz) = 11dccb4b178d63d0dbf51afcea3b30c8
3
MD5 (mutt/patch-1.5.6.vvv.slang.gz) = 11dccb4b178d63d0dbf51afcea3b30c8
4
SIZE (mutt/patch-1.5.6.vvv.slang.gz) = 347
3
MD5 (mutt/patch-1.5.6.rr.compressed.gz) = 0d57a62f17c93eb1d2eff60e070933b3
5
MD5 (mutt/patch-1.5.6.rr.compressed.gz) = 0d57a62f17c93eb1d2eff60e070933b3
6
SIZE (mutt/patch-1.5.6.rr.compressed.gz) = 10077
4
MD5 (mutt/patch-1.5.6.vvv.nntp.gz) = b32ef18006ce8a211ad2d1dabc62bfcb
7
MD5 (mutt/patch-1.5.6.vvv.nntp.gz) = b32ef18006ce8a211ad2d1dabc62bfcb
8
SIZE (mutt/patch-1.5.6.vvv.nntp.gz) = 106691
5
MD5 (mutt/patch-1.5.6.vvv.initials.gz) = eecaa646227609b52e5267178b3bc462
9
MD5 (mutt/patch-1.5.6.vvv.initials.gz) = eecaa646227609b52e5267178b3bc462
10
SIZE (mutt/patch-1.5.6.vvv.initials.gz) = 667
6
MD5 (mutt/patch-1.5.6.vvv.quote.gz) = f262968775cf5c37ba49b29248fcf170
11
MD5 (mutt/patch-1.5.6.vvv.quote.gz) = f262968775cf5c37ba49b29248fcf170
7
MD5 (mutt/patch-1.5.5.1.cd.edit_threads.9.5) = a8a3a973d8693f8af526cecf7edbd71f
12
SIZE (mutt/patch-1.5.6.vvv.quote.gz) = 1558
8
MD5 (mutt/patch-1.5.5.1.cd.signatures_menu.2.1) = 22caeffb4a612f5fa6e1f585b40c51a6
13
MD5 (mutt/patch-1.5.5.1.cd.signatures_menu.2.1) = 22caeffb4a612f5fa6e1f585b40c51a6
14
SIZE (mutt/patch-1.5.5.1.cd.signatures_menu.2.1) = 22637
9
MD5 (mutt/patch-1.5.4.cd.ifdef.1) = a545036cdb55519154d0b35465f52daa
15
MD5 (mutt/patch-1.5.4.cd.ifdef.1) = a545036cdb55519154d0b35465f52daa
16
SIZE (mutt/patch-1.5.4.cd.ifdef.1) = 3545
10
MD5 (mutt/p0-patch-1.5.6.dw.mbox-hook.1) = 9e29a6778ab07a4de3442691e4573fea
17
MD5 (mutt/p0-patch-1.5.6.dw.mbox-hook.1) = 9e29a6778ab07a4de3442691e4573fea
18
SIZE (mutt/p0-patch-1.5.6.dw.mbox-hook.1) = 6405
(-)./files/extra-patch-edit-threads (+651 lines)
Line 0 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
+}

Return to bug 62651