NeoMutt  2022-04-29-249-gaae397
Teaching an old dog new tricks
DOXYGEN
thread.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <stdbool.h>
31#include <stdint.h>
32#include <stdlib.h>
33#include "mutt/lib.h"
34#include "thread.h"
35#include "email.h"
36#include "envelope.h"
37
44bool is_descendant(struct MuttThread *a, const struct MuttThread *b)
45{
46 while (a)
47 {
48 if (a == b)
49 return true;
50 a = a->parent;
51 }
52 return false;
53}
54
64void unlink_message(struct MuttThread **old, struct MuttThread *cur)
65{
66 if (!old || !cur)
67 return;
68
69 struct MuttThread *tmp = NULL;
70
71 if (cur->prev)
72 cur->prev->next = cur->next;
73 else
74 *old = cur->next;
75
76 if (cur->next)
77 cur->next->prev = cur->prev;
78
79 if (cur->sort_thread_key)
80 {
81 for (tmp = cur->parent;
82 tmp && (tmp->sort_thread_key == cur->sort_thread_key); tmp = tmp->parent)
83 {
84 tmp->sort_thread_key = NULL;
85 }
86 }
87 if (cur->sort_aux_key)
88 {
89 for (tmp = cur->parent; tmp && (tmp->sort_aux_key == cur->sort_aux_key); tmp = tmp->parent)
90 tmp->sort_aux_key = NULL;
91 }
92}
93
102void insert_message(struct MuttThread **add, struct MuttThread *parent, struct MuttThread *cur)
103{
104 if (!cur || !add)
105 return;
106
107 if (*add)
108 (*add)->prev = cur;
109
110 cur->parent = parent;
111 cur->next = *add;
112 cur->prev = NULL;
113 *add = cur;
114}
115
119void thread_hash_destructor(int type, void *obj, intptr_t data)
120{
121 FREE(&obj);
122}
123
130struct Email *find_virtual(struct MuttThread *cur, bool reverse)
131{
132 if (!cur)
133 return NULL;
134
135 struct MuttThread *top = NULL;
136
137 if (cur->message && (cur->message->vnum >= 0))
138 return cur->message;
139
140 top = cur;
141 cur = cur->child;
142 if (!cur)
143 return NULL;
144
145 while (reverse && cur->next)
146 cur = cur->next;
147
148 while (true)
149 {
150 if (cur->message && (cur->message->vnum >= 0))
151 return cur->message;
152
153 if (cur->child)
154 {
155 cur = cur->child;
156
157 while (reverse && cur->next)
158 cur = cur->next;
159 }
160 else if (reverse ? cur->prev : cur->next)
161 cur = reverse ? cur->prev : cur->next;
162 else
163 {
164 while (!(reverse ? cur->prev : cur->next))
165 {
166 cur = cur->parent;
167 if (cur == top)
168 return NULL;
169 }
170 cur = reverse ? cur->prev : cur->next;
171 }
172 /* not reached */
173 }
174}
175
181void clean_references(struct MuttThread *brk, struct MuttThread *cur)
182{
183 struct ListNode *ref = NULL;
184 bool done = false;
185
186 for (; cur; cur = cur->next, done = false)
187 {
188 /* parse subthread recursively */
189 clean_references(brk, cur->child);
190
191 if (!cur->message)
192 break; /* skip pseudo-message */
193
194 /* Looking for the first bad reference according to the new threading.
195 * Optimal since NeoMutt stores the references in reverse order, and the
196 * first loop should match immediately for mails respecting RFC2822. */
197 for (struct MuttThread *p = brk; !done && p; p = p->parent)
198 {
199 for (ref = STAILQ_FIRST(&cur->message->env->references);
200 p->message && ref; ref = STAILQ_NEXT(ref, entries))
201 {
202 if (mutt_istr_equal(ref->data, p->message->env->message_id))
203 {
204 done = true;
205 break;
206 }
207 }
208 }
209
210 if (done)
211 {
212 struct Email *e = cur->message;
213
214 /* clearing the References: header from obsolete Message-ID(s) */
215 struct ListNode *np = NULL;
216 while ((np = STAILQ_NEXT(ref, entries)))
217 {
218 STAILQ_REMOVE_AFTER(&cur->message->env->references, ref, entries);
219 FREE(&np->data);
220 FREE(&np);
221 }
222
223 e->changed = true;
225 }
226 }
227}
228
234{
235 if (!e)
236 return;
237
240 e->changed = true;
242
244}
Representation of an email.
Representation of an email header (envelope)
#define MUTT_ENV_CHANGED_IRT
In-Reply-To changed to link/break threads.
Definition: envelope.h:34
#define MUTT_ENV_CHANGED_REFS
References changed to break thread.
Definition: envelope.h:35
void thread_hash_destructor(int type, void *obj, intptr_t data)
Hash Destructor callback - Implements hash_hdata_free_t -.
Definition: thread.c:119
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
#define FREE(x)
Definition: memory.h:43
Convenience wrapper for the library headers.
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define STAILQ_REMOVE_AFTER(head, elm, field)
Definition: queue.h:416
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
The envelope/body of an email.
Definition: email.h:37
struct Envelope * env
Envelope information.
Definition: email.h:66
bool changed
Email has been edited.
Definition: email.h:75
int vnum
Virtual message number.
Definition: email.h:114
struct MuttThread * thread
Thread of Emails.
Definition: email.h:119
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:92
struct ListHead references
message references (in reverse order)
Definition: envelope.h:85
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:86
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
An Email conversation.
Definition: thread.h:35
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
struct Email * sort_aux_key
Email that controls how subthread siblings sort.
Definition: thread.h:51
struct MuttThread * prev
Previous sibling Thread.
Definition: thread.h:48
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
struct Email * sort_thread_key
Email that controls how top thread sorts.
Definition: thread.h:50
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
void unlink_message(struct MuttThread **old, struct MuttThread *cur)
Break the message out of the thread.
Definition: thread.c:64
bool is_descendant(struct MuttThread *a, const struct MuttThread *b)
Is one thread a descendant of another.
Definition: thread.c:44
void insert_message(struct MuttThread **add, struct MuttThread *parent, struct MuttThread *cur)
Insert a message into a thread.
Definition: thread.c:102
void mutt_break_thread(struct Email *e)
Break the email Thread.
Definition: thread.c:233
struct Email * find_virtual(struct MuttThread *cur, bool reverse)
Find an email with a Virtual message number.
Definition: thread.c:130
void clean_references(struct MuttThread *brk, struct MuttThread *cur)
Update email references for a broken Thread.
Definition: thread.c:181
Create/manipulate threading in emails.