]> git.pld-linux.org Git - packages/mutt.git/commitdiff
Split&join threads.
authorjojoro <jojoro@poczta.onet.pl>
Thu, 24 Jan 2002 21:12:15 +0000 (21:12 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    mutt-cd.edit_threads.patch -> 1.1

mutt-cd.edit_threads.patch [new file with mode: 0644]

diff --git a/mutt-cd.edit_threads.patch b/mutt-cd.edit_threads.patch
new file mode 100644 (file)
index 0000000..5cc130a
--- /dev/null
@@ -0,0 +1,417 @@
+diff -pruN2 mutt-1.3.27.orig/thread.c mutt-1.3.27/thread.c
+--- mutt-1.3.27.orig/thread.c  Wed Jan 16 21:43:59 2002
++++ mutt-1.3.27/thread.c       Wed Jan 23 22:26:56 2002
+@@ -1285,2 +1285,78 @@ HASH *mutt_make_subj_hash (CONTEXT *ctx)
+   return hash;
+ }
++
++static void clean_references (THREAD *brk, THREAD *cur)
++{
++  THREAD *p;
++  LIST *ref = NULL;
++  int done = 0;
++
++  for (; cur; cur = cur->next, done = 0)
++  {
++    /* parse subthread recursively */
++    clean_references (brk, cur->child);
++
++    if (!cur->message)
++      break; /* skip pseudo-message */
++
++    /* 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->message->env->references; p->message && ref; ref = ref->next)
++      if (!mutt_strcasecmp (ref->data, p->message->env->message_id))
++      {
++        done = 1;
++        break;
++      }
++
++    if (done)
++    {
++      /* clearing the References: header from obsolete Message-Id(s) */
++      mutt_free_list (&ref->next);
++
++      cur->message->refs_changed = cur->message->changed = 1;
++    }
++  }
++}
++
++void mutt_break_thread (HEADER *hdr)
++{
++  mutt_free_list (&hdr->env->in_reply_to);
++  mutt_free_list (&hdr->env->references);
++  hdr->irt_changed = hdr->refs_changed = hdr->changed = 1;
++
++  clean_references (hdr->thread, hdr->thread->child);
++}
++
++static int link_threads (HEADER *parent, HEADER *child, CONTEXT *ctx)
++{
++  if (child == parent)
++    return 0;
++
++  mutt_break_thread (child);
++
++  child->env->in_reply_to = mutt_new_list ();
++  child->env->in_reply_to->data = safe_strdup (parent->env->message_id);
++  
++  mutt_set_flag (ctx, child, M_TAG, 0);
++  
++  child->irt_changed = child->changed = 1;
++  return 1;
++}
++
++int mutt_link_threads (HEADER *cur, HEADER *last, CONTEXT *ctx)
++{
++  int i, changed = 0;
++
++  if (!last)
++  {
++    for (i = 0; i < ctx->vcount; i++)
++      if (ctx->hdrs[Context->v2r[i]]->tagged)
++      changed |= link_threads (cur, ctx->hdrs[Context->v2r[i]], ctx);
++  }
++  else
++    changed = link_threads (cur, last, ctx);
++
++  return changed;
++}
+diff -pruN2 mutt-1.3.27.orig/OPS mutt-1.3.27/OPS
+--- mutt-1.3.27.orig/OPS       Tue Sep 11 12:50:50 2001
++++ mutt-1.3.27/OPS    Wed Jan 23 22:26:56 2002
+@@ -95,4 +95,5 @@ OP_LIST_REPLY "reply to specified mailin
+ 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"
+@@ -104,4 +105,5 @@ OP_MAIN_FIRST_MESSAGE "move to the first
+ OP_MAIN_LAST_MESSAGE "move to the last message"
+ OP_MAIN_LIMIT "show only messages matching a pattern"
++OP_MAIN_LINK_THREADS "link tagged message to the current one"
+ OP_MAIN_NEXT_NEW "jump to the next new message"
+ OP_MAIN_NEXT_SUBTHREAD "jump to the next subthread"
+diff -pruN2 mutt-1.3.27.orig/copy.c mutt-1.3.27/copy.c
+--- mutt-1.3.27.orig/copy.c    Mon Dec  3 11:17:57 2001
++++ mutt-1.3.27/copy.c Wed Jan 23 22:26:56 2002
+@@ -92,4 +92,10 @@ mutt_copy_hdr (FILE *in, FILE *out, long
+            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;
+       }
+@@ -168,4 +174,10 @@ mutt_copy_hdr (FILE *in, FILE *out, long
+          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 */
+@@ -277,4 +289,6 @@ mutt_copy_hdr (FILE *in, FILE *out, long
+       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
+@@ -286,4 +300,7 @@ mutt_copy_header (FILE *in, HEADER *h, F
+ {
+   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)
+@@ -310,4 +327,47 @@ mutt_copy_header (FILE *in, HEADER *h, F
+     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)
+       {
+diff -pruN2 mutt-1.3.27.orig/curs_main.c mutt-1.3.27/curs_main.c
+--- mutt-1.3.27.orig/curs_main.c       Wed Jan 16 21:43:58 2002
++++ mutt-1.3.27/curs_main.c    Wed Jan 23 22:26:56 2002
+@@ -878,4 +878,9 @@ int mutt_index_menu (void)
+       {
+         mutt_set_flag (Context, CURHDR, M_TAG, !CURHDR->tagged);
++
++        Context->last_tag = CURHDR->tagged ? CURHDR :
++          ((Context->last_tag == CURHDR && !CURHDR->tagged)
++           ? NULL : Context->last_tag);
++
+         menu->redraw = REDRAW_STATUS;
+         if (option (OPTRESOLVE) && menu->current < Context->vcount - 1)
+@@ -1098,4 +1103,83 @@ int mutt_index_menu (void)
+         done = 1;
+       }
++      break;
++
++      case OP_MAIN_BREAK_THREAD:
++
++      CHECK_MSGCOUNT;
++        CHECK_VISIBLE;
++      CHECK_READONLY;
++
++        if ((Sort & SORT_MASK) != SORT_THREADS)
++      {
++        mutt_error _("Threading is not enabled.");
++        break;
++      }
++      if (Context->magic != M_MBOX && Context->magic != M_MMDF)
++      {
++        mutt_error _("break-thread: only for mbox and mmdf mailbox formats");
++        break;
++      }
++
++        {
++          HEADER *oldcur = CURHDR;
++
++        mutt_break_thread (CURHDR);
++          mutt_sort_headers (Context, 1);
++          menu->current = oldcur->virtual;
++        }
++
++      Context->changed = 1;
++        mutt_message _("Thread broken");
++
++      if (menu->menu == MENU_PAGER)
++      {
++        op = OP_DISPLAY_MESSAGE;
++        continue;
++      }
++      else
++        menu->redraw |= REDRAW_INDEX;
++
++        break;
++
++      case OP_MAIN_LINK_THREADS:
++
++      CHECK_MSGCOUNT;
++        CHECK_VISIBLE;
++      CHECK_READONLY;
++
++        if ((Sort & SORT_MASK) != SORT_THREADS)
++        mutt_error _("Threading is not enabled.");
++      else if (Context->magic != M_MBOX && Context->magic != M_MMDF)
++        mutt_error _("link-threads: only for mbox and mmdf mailbox formats");
++      else if (!CURHDR->env->message_id)
++        mutt_error _("No Message-ID: header available to link thread");
++      else if (!tag && (!Context->last_tag || !Context->last_tag->tagged))
++        mutt_error _("First, please tag a message to be linked here");
++      else 
++      {
++        HEADER *oldcur = CURHDR;
++
++        if (mutt_link_threads (CURHDR, tag ? NULL : Context->last_tag,
++                               Context))
++        {
++          mutt_sort_headers (Context, 1);
++          menu->current = oldcur->virtual;
++          
++          Context->changed = 1;
++          mutt_message _("Threads linked");
++        }
++        else
++          mutt_error _("No thread linked");
++      }
++
++      if (menu->menu == MENU_PAGER)
++      {
++        op = OP_DISPLAY_MESSAGE;
++        continue;
++      }
++      else
++        menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
++
+       break;
+diff -pruN2 mutt-1.3.27.orig/doc/manual.sgml.head mutt-1.3.27/doc/manual.sgml.head
+--- mutt-1.3.27.orig/doc/manual.sgml.head      Sat Jan 12 12:35:43 2002
++++ mutt-1.3.27/doc/manual.sgml.head   Wed Jan 23 22:26:56 2002
+@@ -2116,6 +2116,38 @@ with large volume mailing lists easier b
+ uninteresting threads and quickly find topics of value.
++<sect1>Editing threads
++<p>
++Mutt has the ability to dynamically restructure threads that are broken
++either by misconfigured software or bad behaviour from some
++correspondents. This allows to clean your mailboxes (<em/mbox/ and <em/mmdf/
++formats) from these annoyances which make it hard to follow a discussion.
++
++<sect2>Linking threads
++<p>
++
++Some mailers tend to "forget" to correctly set the "In-Reply-To:" and
++"References:" headers when replying to a message. This results in broken
++discussions because Mutt has not enough information to guess the correct
++threading.
++You can fix this by tagging the reply to a mail, then go onto this mail
++and use the ``link-threads'' function (bound to & by default). The
++reply will then be connected to its "parent" message.
++
++You can also connect multiple childs at once, tagging them and using the
++tag-prefix command (';') or the auto_tag option.
++
++<sect2>Breaking threads
++<p>
++
++On mailing lists, some people are in the bad habit of starting a new
++discussion by hitting "reply" to any message from the list and changing
++the subject to a totally unrelated one.
++You can fix such threads by using the ``break-thread'' function (bound
++by default to #), which will turn the subthread starting from the
++current message into a whole different thread.
++
+ <sect1>Delivery Status Notification (DSN) Support
+ <p>
++
+ RFC1894 defines a set of MIME content types for relaying information
+ about the status of electronic mail messages.  These can be thought of as
+diff -pruN2 mutt-1.3.27.orig/functions.h mutt-1.3.27/functions.h
+--- mutt-1.3.27.orig/functions.h       Tue Sep 11 12:51:39 2001
++++ mutt-1.3.27/functions.h    Wed Jan 23 22:26:56 2002
+@@ -67,4 +67,5 @@ 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" },
+@@ -93,4 +94,5 @@ struct binding_t OpMain[] = {
+   { "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" },
+@@ -151,4 +153,5 @@ struct binding_t OpMain[] = {
+ struct binding_t OpPager[] = {
++  { "break-thread",   OP_MAIN_BREAK_THREAD,           "#" },
+   { "create-alias",   OP_CREATE_ALIAS,                "a" },
+   { "bounce-message", OP_BOUNCE_MESSAGE,              "b" },
+@@ -173,4 +176,5 @@ struct binding_t OpPager[] = {
+   { "previous-undeleted",OP_MAIN_PREV_UNDELETED,      "k" },
+   { "previous-entry", OP_PREV_ENTRY,                  "K" },
++  { "link-threads",   OP_MAIN_LINK_THREADS,           "&" },
+   { "list-reply",     OP_LIST_REPLY,                  "L" },
+   { "redraw-screen",  OP_REDRAW,                      "\014" },
+diff -pruN2 mutt-1.3.27.orig/mutt.h mutt-1.3.27/mutt.h
+--- mutt-1.3.27.orig/mutt.h    Tue Jan 15 22:00:32 2002
++++ mutt-1.3.27/mutt.h Wed Jan 23 22:26:56 2002
+@@ -82,4 +82,6 @@
+ #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() */
+@@ -629,4 +631,6 @@ typedef struct header
+   unsigned int threaded : 1;          /* used for threading */
+   unsigned int display_subject : 1;   /* used for threading */
++  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 */
+@@ -728,4 +732,5 @@ typedef struct
+   pattern_t *limit_pattern;     /* compiled limit pattern */
+   HEADER **hdrs;
++  HEADER *last_tag;           /* last tagged msg. used to link threads */
+   THREAD *tree;                       /* top of thread tree */
+   HASH *id_hash;              /* hash table by msg id */
+diff -pruN2 mutt-1.3.27.orig/mx.c mutt-1.3.27/mx.c
+--- mutt-1.3.27.orig/mx.c      Tue Jan 15 22:09:53 2002
++++ mutt-1.3.27/mx.c   Wed Jan 23 22:26:56 2002
+@@ -1163,4 +1163,6 @@ int mx_sync_mailbox (CONTEXT *ctx, int *
+       }
+     }
++    else if (ctx->last_tag && ctx->last_tag->deleted)
++      ctx->last_tag = NULL; /* reset last tagged msg now useless */
+   }
+diff -pruN2 mutt-1.3.27.orig/pager.c mutt-1.3.27/pager.c
+--- mutt-1.3.27.orig/pager.c   Sun Jan 13 09:49:39 2002
++++ mutt-1.3.27/pager.c        Wed Jan 23 22:26:56 2002
+@@ -2436,4 +2436,9 @@ mutt_pager (const char *banner, const ch
+       CHECK_MODE(IsHeader (extra));
+       mutt_set_flag (Context, extra->hdr, M_TAG, !extra->hdr->tagged);
++
++      Context->last_tag = extra->hdr->tagged ? extra->hdr :
++        ((Context->last_tag == extra->hdr && !extra->hdr->tagged)
++         ? NULL : Context->last_tag);
++
+       redraw = REDRAW_STATUS | REDRAW_INDEX;
+       if (option (OPTRESOLVE))
+diff -pruN2 mutt-1.3.27.orig/protos.h mutt-1.3.27/protos.h
+--- mutt-1.3.27.orig/protos.h  Wed Jan 16 21:43:58 2002
++++ mutt-1.3.27/protos.h       Wed Jan 23 22:26:56 2002
+@@ -154,4 +154,5 @@ 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 *);
+ void mutt_buffy (char *, size_t);
+ void mutt_canonical_charset (char *, size_t, const char *);
+@@ -289,4 +290,5 @@ int mutt_is_subscribed_list (ADDRESS *);
+ int mutt_is_text_type (int, char *);
+ int mutt_is_valid_mailbox (const char *);
++int mutt_link_threads (HEADER *, HEADER *, CONTEXT *);
+ int mutt_messages_in_thread (CONTEXT *, HEADER *, int);
+ int mutt_multi_choice (char *prompt, char *letters);
+diff -pruN mutt-1.3.27.orig/PATCHES mutt-1.3.27/PATCHES
+--- mutt-1.3.27.orig/PATCHES    Mon Nov 26 20:16:52 2001
++++ mutt-1.3.27/PATCHES Thu Dec  6 16:27:55 2001
+@@ -1,0 +1 @@
++patch-1.3.27.cd.edit_threads.9.1
This page took 0.096862 seconds and 4 git commands to generate.