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; + } + } +}