From c1e4750541083940f093a5959dbad5fd23326390 Mon Sep 17 00:00:00 2001 From: Brendan Cully Date: Sun, 24 Jul 2005 18:28:36 +0000 Subject: [PATCH] Merge full envelope from message fetch into original sparse envelope, instead of replacing it. This should be gentler on the various threading hashes and may (knock on wood) fix the threading segfault. Threading behaviour is observably better. --- imap/message.c | 20 +++----------------- muttlib.c | 43 +++++++++++++++++++++++++++++++++++++++++++ protos.h | 1 + 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/imap/message.c b/imap/message.c index 990f156c9..f3be17d4c 100644 --- a/imap/message.c +++ b/imap/message.c @@ -326,6 +326,7 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno) { IMAP_DATA* idata; HEADER* h; + ENVELOPE* newenv; char buf[LONG_STRING]; char path[_POSIX_PATH_MAX]; char *pc; @@ -463,23 +464,8 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno) * picked up in mutt_read_rfc822_header, we mark the message (and context * changed). Another possiblity: ignore Status on IMAP?*/ read = h->read; - /* I hate do this here, since it's so low-level, but I'm not sure where - * I can abstract it. Problem: the id and subj hashes lose their keys when - * mutt_free_envelope gets called, but keep their spots in the hash. This - * confuses threading. Alternatively we could try to merge the new - * envelope into the old one. Also messy and lowlevel. */ - if (ctx->id_hash && h->env->message_id) - hash_delete (ctx->id_hash, h->env->message_id, h, NULL); - if (ctx->subj_hash && h->env->real_subj) - hash_delete (ctx->subj_hash, h->env->real_subj, h, NULL); - if (ctx->thread_hash && h->env->message_id) - hash_delete (ctx->thread_hash, h->env->message_id, NULL, NULL); - mutt_free_envelope (&h->env); - h->env = mutt_read_rfc822_header (msg->fp, h, 0, 0); - if (ctx->id_hash && h->env->message_id) - hash_insert (ctx->id_hash, h->env->message_id, h, 0); - if (ctx->subj_hash && h->env->real_subj) - hash_insert (ctx->subj_hash, h->env->real_subj, h, 1); + newenv = mutt_read_rfc822_header (msg->fp, h, 0, 0); + mutt_merge_envelopes(h->env, &newenv); /* see above. We want the new status in h->read, so we unset it manually * and let mutt_set_flag set it correctly, updating context. */ diff --git a/muttlib.c b/muttlib.c index a86bdd6b5..89669d6be 100644 --- a/muttlib.c +++ b/muttlib.c @@ -673,6 +673,49 @@ void mutt_free_envelope (ENVELOPE **p) FREE (p); } +/* move all the headers from extra not present in base into base */ +void mutt_merge_envelopes(ENVELOPE* base, ENVELOPE** extra) +{ + /* copies each existing element if necessary, and sets the element + * to NULL in the source so that mutt_free_envelope doesn't leave us + * with dangling pointers. */ +#define MOVE_ELEM(h) if (!base->h) { base->h = (*extra)->h; (*extra)->h = NULL; } + MOVE_ELEM(return_path); + MOVE_ELEM(from); + MOVE_ELEM(to); + MOVE_ELEM(cc); + MOVE_ELEM(bcc); + MOVE_ELEM(sender); + MOVE_ELEM(reply_to); + MOVE_ELEM(mail_followup_to); + MOVE_ELEM(list_post); + MOVE_ELEM(subject); + MOVE_ELEM(real_subj); + MOVE_ELEM(message_id); + MOVE_ELEM(supersedes); + MOVE_ELEM(date); + MOVE_ELEM(x_label); + MOVE_ELEM(references); + MOVE_ELEM(in_reply_to); + /* real_subj is subordinate to subject */ + if (!base->subject) + { + base->subject = (*extra)->subject; + base->real_subj = (*extra)->real_subj; + (*extra)->subject = NULL; + (*extra)->real_subj = NULL; + } + /* spam and user headers should never be hashed, and the new envelope may + * have better values. Use new versions regardless. */ + mutt_buffer_free (&base->spam); + mutt_free_list (&base->userhdrs); + MOVE_ELEM(spam); + MOVE_ELEM(userhdrs); +#undef MOVE_ELEM + + mutt_free_envelope(extra); +} + void _mutt_mktemp (char *s, const char *src, int line) { snprintf (s, _POSIX_PATH_MAX, "%s/mutt-%s-%d-%d-%d", NONULL (Tempdir), NONULL(Hostname), (int) getuid(), (int) getpid (), Counter++); diff --git a/protos.h b/protos.h index 5dcb72737..9826e0b42 100644 --- a/protos.h +++ b/protos.h @@ -211,6 +211,7 @@ void mutt_make_forward_subject (ENVELOPE *env, CONTEXT *ctx, HEADER *cur); void mutt_make_help (char *, size_t, char *, int, int); void mutt_make_misc_reply_headers (ENVELOPE *env, CONTEXT *ctx, HEADER *cur, ENVELOPE *curenv); void mutt_make_post_indent (CONTEXT *ctx, HEADER *cur, FILE *out); +void mutt_merge_envelopes(ENVELOPE* base, ENVELOPE** extra); void mutt_message_to_7bit (BODY *, FILE *); #define mutt_mktemp(a) _mutt_mktemp (a, __FILE__, __LINE__) void _mutt_mktemp (char *, const char *, int); -- 2.40.0