]> granicus.if.org Git - mutt/commitdiff
Implement RFC 2822's idea of the In-Reply-To header. In particular,
authorThomas Roessler <roessler@does-not-exist.org>
Wed, 25 Apr 2001 22:08:41 +0000 (22:08 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Wed, 25 Apr 2001 22:08:41 +0000 (22:08 +0000)
we have to drop the $in_reply_to configuration variable.  Also, the
change in the specification makes some changes to the threading code
reasonable.

globals.h
init.h
mutt.h
parse.c
protos.h
send.c
sendlib.c
thread.c
url.c

index 9a38542d2cec18a226a7518b0fe5c269b7ac054e..5697061ead1a845a6064f969e4f6eb910c5585e7 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -55,7 +55,6 @@ WHERE char *ImapHomeNamespace INITVAL (NULL);
 WHERE char *ImapPass INITVAL (NULL);
 WHERE char *ImapUser INITVAL (NULL);
 #endif
-WHERE char *InReplyTo;
 WHERE char *Inbox;
 WHERE char *Ispell;
 WHERE char *Locale;
diff --git a/init.h b/init.h
index dc1f7920c76fe9baaf7535d5954e0c66c0ab54c0..87298215ac7e36a01e7ffcbc70d6feaaf541c859 100644 (file)
--- a/init.h
+++ b/init.h
@@ -764,17 +764,6 @@ struct option_t MuttVars[] = {
   ** message to which you are replying.  You are strongly encouraged not to
   ** change this value, as it tends to agitate the more fanatical netizens.
   */
-  { "in_reply_to",     DT_STR,  R_NONE, UL &InReplyTo, UL "%i; from %a on %{!%a, %b %d, %Y at %I:%M:%S%p %Z}" },
-  /*
-  ** .pp
-  ** This specifies the format of the \fIIn-Reply-To\fP header field
-  ** added when replying to a message.  For a full listing of
-  ** defined escape sequences, see the section on $$index_format.
-  ** .pp
-  ** \fBNote:\fP Don't use any sequences in this format string which
-  ** may include 8-bit characters.  Using such escape sequences may
-  ** lead to bad headers.
-  */
   { "indent_str",      DT_SYN,  R_NONE, UL "indent_string", 0 },
   /*
   */
diff --git a/mutt.h b/mutt.h
index 1d3065bff7c1117c606d283357f982f7943b4daf..e7bb18a8a4839899f6cf1e8d9ede410cbf2ec9a5 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -501,6 +501,7 @@ typedef struct envelope
   char *date;
   char *x_label;
   LIST *references;            /* message references (in reverse order) */
+  LIST *in_reply_to;           /* in-reply-to header content */
   LIST *userhdrs;              /* user defined headers */
 } ENVELOPE;
 
diff --git a/parse.c b/parse.c
index b87da402ac2042f80b8d85a07a5f9aca80a4a62e..b3888fecf5fc6abb56f218aa612ff155590a115b 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -903,7 +903,7 @@ void mutt_parse_mime_message (CONTEXT *ctx, HEADER *cur)
 }
 
 int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short user_hdrs, short weed,
-                           short do_2047, LIST **lastp, char **in_reply_to)
+                           short do_2047, LIST **lastp)
 {
   int matched = 0;
   LIST *last = NULL;
@@ -1008,12 +1008,9 @@ int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short
     case 'i':
     if (!mutt_strcasecmp (line+1, "n-reply-to"))
     {
-      if (hdr && in_reply_to)
-      {
-       mutt_str_replace (in_reply_to, p);
-       if (do_2047)
-         rfc2047_decode (in_reply_to);
-      }
+      mutt_free_list (&e->in_reply_to);
+      e->in_reply_to = mutt_parse_references (p);
+      matched = 1;
     }
     break;
     
@@ -1223,7 +1220,6 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr, short user_hdrs,
   LIST *last = NULL;
   char *line = safe_malloc (LONG_STRING);
   char *p;
-  char *in_reply_to = 0;
   long loc;
   int matched;
   size_t linelen = LONG_STRING;
@@ -1276,7 +1272,7 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr, short user_hdrs,
     if (!*p)
       continue; /* skip empty header fields */
 
-    matched = mutt_parse_rfc822_line (e, hdr, line, p, user_hdrs, weed, 1, &last, &in_reply_to);
+    matched = mutt_parse_rfc822_line (e, hdr, line, p, user_hdrs, weed, 1, &last);
     
   }
 
@@ -1287,24 +1283,6 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr, short user_hdrs,
     hdr->content->hdr_offset = hdr->offset;
     hdr->content->offset = ftell (f);
 
-    /* if an in-reply-to was given, check to see if it is in the references
-     * list already.  if not, add it so we can do a better job of threading.
-     */
-    if (in_reply_to && (p = extract_message_id (in_reply_to)) != NULL)
-    {
-      if (!e->references ||
-         (e->references && mutt_strcmp (e->references->data, p) != 0))
-      {
-       LIST *tmp = mutt_new_list ();
-
-       tmp->data = p;
-       tmp->next = e->references;
-       e->references = tmp;
-      }
-      else
-       safe_free ((void **) &p);
-    }
-
     /* do RFC2047 decoding */
     rfc2047_decode_adrlist (e->from);
     rfc2047_decode_adrlist (e->to);
@@ -1334,7 +1312,6 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr, short user_hdrs,
     }
   }
 
-  safe_free ((void *) &in_reply_to);
   return (e);
 }
 
index 2c38809146f7ee3db221bc1223d55e95333f036f..a221e5f64032ae36e8539eacfa2db01396060dbb 100644 (file)
--- a/protos.h
+++ b/protos.h
@@ -296,7 +296,7 @@ int mutt_parse_unmono (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 int mutt_parse_push (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 int mutt_parse_rc_line (/* const */ char *, BUFFER *, BUFFER *);
 int mutt_parse_rfc822_line (ENVELOPE *e, HEADER *hdr, char *line, char *p, short user_hdrs, short weed,
-                           short do_2047, LIST **lastp, char **in_reply_to);
+                           short do_2047, LIST **lastp);
 int mutt_parse_score (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 int mutt_parse_unscore (BUFFER *, BUFFER *, unsigned long, BUFFER *);
 int mutt_parse_unhook (BUFFER *, BUFFER *, unsigned long, BUFFER *);
diff --git a/send.c b/send.c
index 848d9a1ea2935bcaefed8e8be2730fd0497461ba..56082ca08fa2cdda6cf1ebd86c4a0799bb1a366a 100644 (file)
--- a/send.c
+++ b/send.c
@@ -586,9 +586,6 @@ void mutt_make_forward_subject (ENVELOPE *env, CONTEXT *ctx, HEADER *cur)
 void mutt_make_misc_reply_headers (ENVELOPE *env, CONTEXT *ctx,
                                    HEADER *cur, ENVELOPE *curenv)
 {
-  LIST *tmp;
-  char buffer[STRING];
-
   if (curenv->real_subj)
   {
     env->subject = safe_malloc (mutt_strlen (curenv->real_subj) + 5);
@@ -597,22 +594,44 @@ void mutt_make_misc_reply_headers (ENVELOPE *env, CONTEXT *ctx,
   else
     env->subject = safe_strdup ("Re: your mail");
   
-  /* add the In-Reply-To field */
-  if (InReplyTo)
+}
+
+static void 
+mutt_make_reference_headers (ENVELOPE *curenv, ENVELOPE *env, CONTEXT *ctx)
+{
+  HEADER *h;
+  LIST **p, **q;
+  int i;
+  
+  if (!curenv)
   {
-    strfcpy (buffer, "In-Reply-To: ", sizeof (buffer));
-    mutt_make_string (buffer + 13, sizeof (buffer) - 13, InReplyTo, ctx, cur);
-    tmp = env->userhdrs;
-    while (tmp && tmp->next)
-      tmp = tmp->next;
-    if (tmp)
+    env->references = NULL;
+    env->in_reply_to = NULL;
+    p = &env->references;
+    q = &env->in_reply_to;
+    
+    for(i = 0; i < ctx->vcount; i++)
     {
-      tmp->next = mutt_new_list ();
-      tmp = tmp->next;
+      while(*p) p = &(*p)->next;
+      while (*q) q = &(*q)->next;
+      
+      h = ctx->hdrs[ctx->v2r[i]];
+      if(h->tagged)
+      {
+       *p = mutt_make_references(h->env);
+       if (h->env->message_id)
+       {
+         *q = mutt_new_list ();
+         (*q)->data = safe_strdup (h->env->message_id);
+       }
+      }
     }
-    else
-      tmp = env->userhdrs = mutt_new_list ();
-    tmp->data = safe_strdup (buffer);
+  }
+  else
+  {
+    env->references = mutt_make_references (curenv);
+    env->in_reply_to = mutt_new_list ();
+    env->in_reply_to->data = safe_strdup (curenv->message_id);
   }
 }
 
@@ -669,26 +688,7 @@ envelope_defaults (ENVELOPE *env, CONTEXT *ctx, HEADER *cur, int flags)
 
     mutt_fix_reply_recipients (env);
     mutt_make_misc_reply_headers (env, ctx, cur, curenv);
-    
-    if(tag)
-    {
-      HEADER *h;
-      LIST **p;
-
-      env->references = NULL;
-      p = &env->references;
-
-      for(i = 0; i < ctx->vcount; i++)
-      {
-       while(*p) p = &(*p)->next;
-       h = ctx->hdrs[ctx->v2r[i]];
-       if(h->tagged)
-         *p = mutt_make_references(h->env);
-      }
-    }
-    else
-      env->references = mutt_make_references(curenv);
-
+    mutt_make_reference_headers (tag ? NULL : curenv, env, ctx);
   }
   else if (flags & SENDFORWARD)
     mutt_make_forward_subject (env, ctx, cur);
index 532f40948f0f22fc82c122e3b5e9f3f414529c78..ee19d3a8e4f8b4bcd6f997a70d022a8d0058b6ce 100644 (file)
--- a/sendlib.c
+++ b/sendlib.c
@@ -1624,6 +1624,13 @@ int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach,
     mutt_write_mime_header (attach, fp);
   }
 
+  if (env->in_reply_to)
+  {
+    fputs ("In-Reply-To:", fp);
+    write_references (env->in_reply_to, fp);
+    fputc ('\n', fp);
+  }
+  
   if (mode == 0 && !privacy && option (OPTXMAILER))
   {
     /* Add a vanity header */
index f13f6cd4ee54b8bfdc91186bdc7e8a41f7f3c8e1..1228af0f43ad6e3d8f6e83f5129526d2cb01f7fc 100644 (file)
--- a/thread.c
+++ b/thread.c
@@ -1,8 +1,3 @@
-/*
- * WORK IN PROGRESS ALERT: Daniel Eisenbud <daniel@math.berkeley.edu>
- * is currently working on this code.  Contact him before working on it!
- */
-
 /*
  * Copyright (C) 1996-2000 Michael R. Elkins <me@cs.hmc.edu>
  *
@@ -41,9 +36,8 @@ static int is_descendant (HEADER *a, HEADER *b)
  * to find the most recent message to which "cur" refers itself.  
  */
 
-static HEADER *find_reference (HEADER *cur, CONTEXT *ctx)
+static HEADER *find_ref (LIST *refs, HEADER *cur, CONTEXT *ctx)
 {
-  LIST *refs = cur->env->references;
   HEADER *ptr;
 
   for (; refs; refs = refs->next)
@@ -51,7 +45,7 @@ static HEADER *find_reference (HEADER *cur, CONTEXT *ctx)
     /* ups, this message is in a reference loop. bad. */
     if (cur->env->message_id && !strcmp (cur->env->message_id, refs->data))
       continue;
-    
+
     if ((ptr = hash_find (ctx->id_hash, refs->data)))
     {
       if (is_descendant (ptr, cur))
@@ -64,6 +58,24 @@ static HEADER *find_reference (HEADER *cur, CONTEXT *ctx)
   return NULL;
 }
 
+/*
+ * In-Reply-To contains the direct parents according to RFC 2822.
+ * References is second best, since it may contain indirect parents,
+ * too.
+ */
+
+static HEADER *find_reference (HEADER *cur, CONTEXT *ctx)
+{
+  HEADER *ptr;
+  
+  if ((ptr = find_ref (cur->env->in_reply_to, cur, ctx)))
+    return ptr;
+  if ((ptr = find_ref (cur->env->references, cur, ctx)))
+    return ptr;
+  
+  return NULL;
+}
+
 /* Determines whether to display a message's subject. */
 static int need_display_subject (CONTEXT *ctx, HEADER *tree)
 {
@@ -465,15 +477,26 @@ static HEADER *sort_last (HEADER *top)
   return top;
 }
 
+static int matches_in_reply_to (HEADER *t, const char *p)
+{
+  LIST *irt;
+  
+  for (irt = t->env->in_reply_to; irt; irt = irt->next)
+    if (mutt_strcmp (irt->data, p) == 0)
+      return 1;
+  
+  return 0;
+}
+
 static void move_descendants (HEADER **tree, HEADER *cur, sort_t *usefunc)
 {
   HEADER *ptr, *tmp = *tree;
 
   while (tmp)
   {
-    /* only need to look at the last reference */
-    if (tmp->env->references &&
-       mutt_strcmp (tmp->env->references->data, cur->env->message_id) == 0)
+    /* Look at the entire in-reply-to header, and at the last (!) reference. */
+    if (matches_in_reply_to (tmp, cur->env->message_id) ||
+       (tmp->env->references && mutt_strcmp (tmp->env->references->data, cur->env->message_id) == 0))
     {
       /* remove message from current location */
       unlink_message (tree, tmp);
diff --git a/url.c b/url.c
index 5eb552b09e9b09a6025174289b339d381e99ba54..d28a25b3051c79a9df83f32832ea9746ea49b68a 100644 (file)
--- a/url.c
+++ b/url.c
@@ -236,7 +236,7 @@ int url_parse_mailto (ENVELOPE *e, char **body, const char *src)
       scratch[taglen] = '\0';
       value = &scratch[taglen+1];
       SKIPWS (value);
-      mutt_parse_rfc822_line (e, NULL, scratch, value, 1, 0, 0, &last, NULL);
+      mutt_parse_rfc822_line (e, NULL, scratch, value, 1, 0, 0, &last);
     }
   }