NeoMutt  2023-05-17-16-g61469c
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 <stdlib.h>
32#include "mutt/lib.h"
33#include "thread.h"
34#include "email.h"
35#include "envelope.h"
36
43bool is_descendant(const struct MuttThread *a, const struct MuttThread *b)
44{
45 while (a)
46 {
47 if (a == b)
48 return true;
49 a = a->parent;
50 }
51 return false;
52}
53
63void unlink_message(struct MuttThread **old, struct MuttThread *cur)
64{
65 if (!old || !cur)
66 return;
67
68 struct MuttThread *tmp = NULL;
69
70 if (cur->prev)
71 cur->prev->next = cur->next;
72 else
73 *old = cur->next;
74
75 if (cur->next)
76 cur->next->prev = cur->prev;
77
78 if (cur->sort_thread_key)
79 {
80 for (tmp = cur->parent;
81 tmp && (tmp->sort_thread_key == cur->sort_thread_key); tmp = tmp->parent)
82 {
83 tmp->sort_thread_key = NULL;
84 }
85 }
86 if (cur->sort_aux_key)
87 {
88 for (tmp = cur->parent; tmp && (tmp->sort_aux_key == cur->sort_aux_key); tmp = tmp->parent)
89 tmp->sort_aux_key = NULL;
90 }
91}
92
101void insert_message(struct MuttThread **add, struct MuttThread *parent, struct MuttThread *cur)
102{
103 if (!cur || !add)
104 return;
105
106 if (*add)
107 (*add)->prev = cur;
108
109 cur->parent = parent;
110 cur->next = *add;
111 cur->prev = NULL;
112 *add = cur;
113}
114
121struct Email *find_virtual(struct MuttThread *cur, bool reverse)
122{
123 if (!cur)
124 return NULL;
125
126 struct MuttThread *top = NULL;
127
128 if (cur->message && (cur->message->vnum >= 0))
129 return cur->message;
130
131 top = cur;
132 cur = cur->child;
133 if (!cur)
134 return NULL;
135
136 while (reverse && cur->next)
137 cur = cur->next;
138
139 while (true)
140 {
141 if (cur->message && (cur->message->vnum >= 0))
142 return cur->message;
143
144 if (cur->child)
145 {
146 cur = cur->child;
147
148 while (reverse && cur->next)
149 cur = cur->next;
150 }
151 else if (reverse ? cur->prev : cur->next)
152 {
153 cur = reverse ? cur->prev : cur->next;
154 }
155 else
156 {
157 while (!(reverse ? cur->prev : cur->next))
158 {
159 cur = cur->parent;
160 if (cur == top)
161 return NULL;
162 }
163 cur = reverse ? cur->prev : cur->next;
164 }
165 /* not reached */
166 }
167}
168
174void clean_references(struct MuttThread *brk, struct MuttThread *cur)
175{
176 struct ListNode *ref = NULL;
177 bool done = false;
178
179 for (; cur; cur = cur->next, done = false)
180 {
181 /* parse subthread recursively */
182 clean_references(brk, cur->child);
183
184 if (!cur->message)
185 break; /* skip pseudo-message */
186
187 /* Looking for the first bad reference according to the new threading.
188 * Optimal since NeoMutt stores the references in reverse order, and the
189 * first loop should match immediately for mails respecting RFC2822. */
190 for (struct MuttThread *p = brk; !done && p; p = p->parent)
191 {
192 for (ref = STAILQ_FIRST(&cur->message->env->references);
193 p->message && ref; ref = STAILQ_NEXT(ref, entries))
194 {
195 if (mutt_istr_equal(ref->data, p->message->env->message_id))
196 {
197 done = true;
198 break;
199 }
200 }
201 }
202
203 if (done)
204 {
205 struct Email *e = cur->message;
206
207 /* clearing the References: header from obsolete Message-ID(s) */
208 struct ListNode *np = NULL;
209 while ((np = STAILQ_NEXT(ref, entries)))
210 {
211 STAILQ_REMOVE_AFTER(&cur->message->env->references, ref, entries);
212 FREE(&np->data);
213 FREE(&np);
214 }
215
216 e->changed = true;
218 }
219 }
220}
221
227{
228 if (!e)
229 return;
230
233 e->changed = true;
235
237}
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 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:810
#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:113
struct MuttThread * thread
Thread of Emails.
Definition: email.h:118
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:34
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:44
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:47
struct MuttThread * child
Child of this Thread.
Definition: thread.h:45
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:46
void unlink_message(struct MuttThread **old, struct MuttThread *cur)
Break the message out of the thread.
Definition: thread.c:63
bool is_descendant(const struct MuttThread *a, const struct MuttThread *b)
Is one thread a descendant of another.
Definition: thread.c:43
void insert_message(struct MuttThread **add, struct MuttThread *parent, struct MuttThread *cur)
Insert a message into a thread.
Definition: thread.c:101
void mutt_break_thread(struct Email *e)
Break the email Thread.
Definition: thread.c:226
struct Email * find_virtual(struct MuttThread *cur, bool reverse)
Find an email with a Virtual message number.
Definition: thread.c:121
void clean_references(struct MuttThread *brk, struct MuttThread *cur)
Update email references for a broken Thread.
Definition: thread.c:174
Create/manipulate threading in emails.