On 08/26/01 04:02 AM, Louis LeBlanc sat at the `puter and typed:
> <SNIP> 
> 
> Ok, Cedric.  Sorry it took me so long to get any feedback to you but
> here it is:
> I am using the latest mutt (1.3.21_2) port on FreeBSD 4.3 PreRelease.
> I took your patch file and broke it down into the attached patches to
> be dropped as is into the ports files directory along with the other
> patches.  No other mods needed.
> 
> Anyway, I realize your patch was intended for 1.3.20, but I hadn't any
> opportunity to play with it until I convinced myself to upgrade mutt.
> But that's neither here nor there.
> 
> I got the patches applied clean right from the port makefile, so it
> came off pretty well.  The other build options I applied are as
> follows:
> 
> WITH_MUTT_NNTP=yes WITH_MUTT_QUOTE_PATCH=yes WITH_MUTT_SSL=yes
> WITH_MUTT_IMAP=yes WITH_MUTT_SLANG=yes
> 
> As well as the default port and FreeBSD patches, of course.
> 
> Now for the details.  It works great.  Exactly as I expected.  Except
> for one thing.  It seems either function doesn't apply itself unless I
> also happen to be deleting another message in the same folder.  If I do,
> everything comes up threaded as expected.  Here is what I've done:
> 
> select a subthread head (a single message in the middle of a thread)
> and hit '#' to break it.  The message comes up, but if I hit '$' to
> sync the mailbox, nothing changes.  If I change mailboxes and come
> back, nothing is changed.  If I then delete a message, nothing
> changes.  If I delete a message before changing folders, then sync, it
> all works.
> 
> The same behavior is demonstrated with link-thread, I tag the head of
> the rogue thread and then move the select arrow to the message I want
> it to hang off of, then hit '&'.  Same apply behavior is shown.
> 
> I realize this may be because I applied a 1.3.20 patch to 1.3.21, and
> a clean patch and build can't guarantee clean behavior, but I thought
> this might at least help you get it ready for 1.3.21 more easily.
> 
> Thanks for the effort!  I have followed all the 'main branch
> submission' controversy that has been flowing around, and personally,
> I'd like to see it set up as an available patch (especially for
> FreeBSD make options like I used above - hint hint to David O'Brien,
> who maintains the port :).
> 
> Lou

Of course it would help if I could remember to attach the files I
promised :)

L
-- 
Louis LeBlanc       [EMAIL PROTECTED]
Fully Funded Hobbyist, KeySlapper Extrordinaire :)
http://acadia.ne.mediaone.net                 ԿԬ

Genetics explains why you look like your father, and if you don't, why
you should.

--- OPS Sat Jan 27 14:07:59 2001
+++ OPS Tue Aug  7 15:14:54 2001
@@ -94,6 +94,7 @@
 OP_LIST_REPLY "reply to specified mailing list"
 OP_MACRO "execute a macro"
 OP_MAIL "compose a new mail message"
+OP_MAIN_BREAK_THREAD "break the thread in two"
 OP_MAIN_CHANGE_FOLDER "open a different folder"
 OP_MAIN_CHANGE_FOLDER_READONLY "open a different folder in read only mode"
 OP_MAIN_CLEAR_FLAG "clear a status flag from a message"
@@ -103,6 +104,7 @@
 OP_MAIN_FIRST_MESSAGE "move to the first message"
 OP_MAIN_LAST_MESSAGE "move to the last message"
 OP_MAIN_LIMIT "show only messages matching a pattern"
+OP_MAIN_LINK_THREADS "link tagged messages to the current one"
 OP_MAIN_NEXT_NEW "jump to the next new message"
 OP_MAIN_NEXT_SUBTHREAD "jump to the next subthread"
 OP_MAIN_NEXT_THREAD "jump to the next thread"
--- copy.c      Fri May 11 16:04:24 2001
+++ copy.c      Tue Aug  7 15:14:54 2001
@@ -91,6 +91,12 @@
            (ascii_strncasecmp ("Content-Length:", buf, 15) == 0 ||
             ascii_strncasecmp ("Lines:", buf, 6) == 0))
          continue;
+       if ((flags & CH_UPDATE_REFS) &&
+            ascii_strncasecmp ("References:", buf, 11) == 0)
+         continue;
+       if ((flags & CH_UPDATE_IRT) &&
+            ascii_strncasecmp ("In-Reply-To:", buf, 12) == 0)
+         continue;
        ignore = 0;
       }

@@ -167,6 +173,12 @@
             ascii_strncasecmp ("type:", buf + 8, 5) == 0)) ||
           ascii_strncasecmp ("mime-version:", buf, 13) == 0))
        continue;
+      if ((flags & CH_UPDATE_REFS) &&
+         ascii_strncasecmp ("References:", buf, 11) == 0)
+       continue;
+      if ((flags & CH_UPDATE_IRT) &&
+         ascii_strncasecmp ("In-Reply-To:", buf, 12) == 0)
+       continue;

       /* Find x -- the array entry where this header is to be saved */
       if (flags & CH_REORDER)
@@ -276,6 +288,8 @@
        CH_UPDATE_LEN   write new Content-Length: and Lines:
        CH_XMIT         ignore Lines: and Content-Length:
        CH_WEED         do header weeding
+       CH_UPDATE_IRT   update the In-Reply-To: header
+       CH_UPDATE_REFS  update the References: header
 
    prefix
        string to use if CH_PREFIX is set
@@ -285,6 +299,9 @@
 mutt_copy_header (FILE *in, HEADER *h, FILE *out, int flags, const char *prefix)
 {
   char buffer[SHORT_STRING];
+
+  flags |= (h->irt_changed ? CH_UPDATE_IRT : 0)
+        | (h->refs_changed ? CH_UPDATE_REFS : 0);
   
   if (mutt_copy_hdr (in, out, h->offset, h->content->offset, flags, prefix) == -1)
     return (-1);
@@ -309,6 +326,49 @@
   {
     if ((flags & CH_NOSTATUS) == 0)
     {
+      if (h->irt_changed && h->env->in_reply_to)
+      {
+       LIST *listp = h->env->in_reply_to;
+
+       if (fputs ("In-Reply-To: ", out) == EOF)
+         return (-1);
+
+       for (; listp; listp = listp->next)
+         if ((fputs (listp->data, out) == EOF) || (fputc (' ', out) == EOF))
+           return (-1);
+
+       if (fputc ('\n', out) == EOF)
+         return (-1);
+      }
+
+      if (h->refs_changed && h->env->references)
+      {
+       LIST *listp = h->env->references, *refs = NULL, *t;
+
+       if (fputs ("References: ", out) == EOF)
+         return (-1);
+
+       /* Mutt stores references in reverse order, thus we create
+        * a reordered refs list that we can put in the headers */
+       for (; listp; listp = listp->next, refs = t)
+       {
+         t = (LIST *)safe_malloc (sizeof (LIST));
+         t->data = listp->data;
+         t->next = refs;
+       }
+
+       for (; refs; refs = refs->next)
+         if ((fputs (refs->data, out) == EOF) || (fputc (' ', out) == EOF))
+           return (-1);
+
+       /* clearing refs from memory */
+       for (t = refs; refs; refs = t->next, t = refs)
+         safe_free ((void **)&refs);
+
+       if (fputc ('\n', out) == EOF)
+         return (-1);
+      }
+
       if (h->old || h->read)
       {
        if (fputs ("Status: ", out) == EOF)
--- curs_main.c Thu Jul 19 16:49:51 2001
+++ curs_main.c Tue Aug  7 15:14:54 2001
@@ -1179,6 +1179,64 @@
        else
          menu->redraw = REDRAW_MOTION;
        break;
+       
+      case OP_MAIN_LINK_THREADS:
+
+       CHECK_MSGCOUNT;
+        CHECK_VISIBLE;
+       CHECK_READONLY;
+
+       if (!CURHDR->env->message_id)
+         mutt_error _("No Message-ID: header available to link thread");
+       else
+       {
+         int changed = 0;
+
+         for (i = 0; i < Context->vcount; i++)
+         {
+           HEADER *hdr = Context->hdrs[Context->v2r[i]];
+
+           if (i != menu->current && hdr->tagged)
+           {
+             mutt_free_list (&hdr->env->in_reply_to);
+             hdr->env->in_reply_to = mutt_new_list ();
+             hdr->env->in_reply_to->data =
+               safe_strdup (CURHDR->env->message_id);
+
+             mutt_set_flag (Context, hdr, M_TAG, 0);
+
+             hdr->irt_changed = hdr->changed = 1;
+             changed = 1;
+           }
+         }
+
+         if (changed)
+         {
+           Context->changed = 1;
+           mutt_message _("Threads linked");
+           menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
+         }
+         else
+           mutt_error _("No thread linked");
+       }
+       break;
+
+      case OP_MAIN_BREAK_THREAD:
+
+       CHECK_MSGCOUNT;
+        CHECK_VISIBLE;
+       CHECK_READONLY;
+
+       mutt_free_list (&CURHDR->env->in_reply_to);
+       mutt_free_list (&CURHDR->env->references);
+       CURHDR->irt_changed = CURHDR->refs_changed = CURHDR->changed = 1;
+       Context->changed = 1;
+
+       /* cleaning References: for obsolete Message-Ids */
+       mutt_break_thread (CURHDR, CURHDR->child);
+       
+       mutt_message _("Thread broken");
+       break;
 
       case OP_COPY_MESSAGE:
       case OP_SAVE:
--- functions.h Tue Feb 13 16:00:26 2001
+++ functions.h Tue Aug  7 15:14:54 2001
@@ -66,6 +66,7 @@
 struct binding_t OpMain[] = {
   { "create-alias",            OP_CREATE_ALIAS,                "a" },
   { "bounce-message",          OP_BOUNCE_MESSAGE,              "b" },
+  { "break-thread",            OP_MAIN_BREAK_THREAD,           "#" },
   { "change-folder",           OP_MAIN_CHANGE_FOLDER,          "c" },
   { "change-folder-readonly",  OP_MAIN_CHANGE_FOLDER_READONLY, "\033c" },
   { "collapse-thread",         OP_MAIN_COLLAPSE_THREAD,        "\033v" },
@@ -92,6 +93,7 @@
   { "next-undeleted",          OP_MAIN_NEXT_UNDELETED,         "j" },
   { "previous-undeleted",      OP_MAIN_PREV_UNDELETED,         "k" },
   { "limit",                   OP_MAIN_LIMIT,                  "l" },
+  { "link-threads",            OP_MAIN_LINK_THREADS,           "&" },
   { "list-reply",              OP_LIST_REPLY,                  "L" },
   { "mail",                    OP_MAIL,                        "m" },
   { "toggle-new",              OP_TOGGLE_NEW,                  "N" },
--- mutt.h      Fri Jun 29 12:05:50 2001
+++ mutt.h      Tue Aug  7 15:14:54 2001
@@ -81,6 +81,8 @@
 #define CH_NOLEN       (1<<12) /* don't write Content-Length: and Lines: */
 #define CH_WEED_DELIVERED (1<<13) /* weed eventual Delivered-To headers */
 #define CH_FORCE_FROM  (1<<14) /* give CH_FROM precedence over CH_WEED? */
+#define CH_UPDATE_IRT  (1<<15) /* update In-Reply-To: */
+#define CH_UPDATE_REFS (1<<16) /* update References: */
 
 /* flags for mutt_enter_string() */
 #define  M_ALIAS   1      /* do alias "completion" by calling up the alias-menu */
@@ -616,6 +618,8 @@
   unsigned int display_subject : 1; /* used for threading */
   unsigned int fake_thread : 1;     /* no ref matched, but subject did */
   unsigned int threaded : 1;        /* message has been threaded */
+  unsigned int irt_changed : 1; /* In-Reply-To changed to link/break threads */
+  unsigned int refs_changed : 1; /* References changed to break thread */
   unsigned int recip_valid : 1;  /* is_recipient is valid */
   unsigned int active : 1;         /* message is not to be removed */
   
--- protos.h    Tue Jul  3 21:31:16 2001
+++ protos.h    Tue Aug  7 15:14:54 2001
@@ -146,6 +146,7 @@
 void mutt_block_signals_system (void);
 void mutt_body_handler (BODY *, STATE *);
 void mutt_bounce_message (FILE *fp, HEADER *, ADDRESS *);
+void mutt_break_thread (HEADER *, HEADER *);
 void mutt_buffy (char *, size_t);
 void mutt_canonical_charset (char *, size_t, const char *);
 void mutt_check_rescore (CONTEXT *);
--- thread.c    Thu Apr 26 00:06:58 2001
+++ thread.c    Tue Aug  7 15:14:54 2001
@@ -999,3 +999,35 @@
   } 
   /* not reached */
 }
+
+void mutt_break_thread (HEADER *brk, HEADER *cur)
+{
+  HEADER *p;
+  LIST *ref;
+  int done = 0;
+
+  for (; cur; cur = cur->next, done = 0)
+  {
+    /* parse subthread recursively */
+    mutt_break_thread (brk, cur->child);
+
+    /* Looking for the first bad reference according to the new threading.
+     * Optimal since Mutt stores the references in reverse order, and the
+     * first loop should match immediatly for mails respecting RFC2822. */
+    for (p = brk; !done && p; p = p->parent)
+      for (ref = cur->env->references; ref; ref = ref->next)
+       if (!mutt_strcasecmp (ref->data, p->env->message_id))
+       {
+         done = 1;
+         break;
+       }
+
+    if (done)
+    {
+      /* clearing the References: header from obsolete Message-Id(s) */
+      mutt_free_list (&ref->next);
+
+      cur->refs_changed = cur->changed = 1;
+    }
+  }
+}

Reply via email to