NeoMutt  2024-03-23-147-g885fbc
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
thread.c
Go to the documentation of this file.
1
32#include "config.h"
33#include <stdbool.h>
34#include <stdlib.h>
35#include "mutt/lib.h"
36#include "thread.h"
37#include "email.h"
38#include "envelope.h"
39
46bool is_descendant(const struct MuttThread *a, const struct MuttThread *b)
47{
48 while (a)
49 {
50 if (a == b)
51 return true;
52 a = a->parent;
53 }
54 return false;
55}
56
66void unlink_message(struct MuttThread **old, struct MuttThread *cur)
67{
68 if (!old || !cur)
69 return;
70
71 struct MuttThread *tmp = NULL;
72
73 if (cur->prev)
74 cur->prev->next = cur->next;
75 else
76 *old = cur->next;
77
78 if (cur->next)
79 cur->next->prev = cur->prev;
80
81 if (cur->sort_thread_key)
82 {
83 for (tmp = cur->parent;
84 tmp && (tmp->sort_thread_key == cur->sort_thread_key); tmp = tmp->parent)
85 {
86 tmp->sort_thread_key = NULL;
87 }
88 }
89 if (cur->sort_aux_key)
90 {
91 for (tmp = cur->parent; tmp && (tmp->sort_aux_key == cur->sort_aux_key); tmp = tmp->parent)
92 tmp->sort_aux_key = NULL;
93 }
94}
95
104void insert_message(struct MuttThread **add, struct MuttThread *parent, struct MuttThread *cur)
105{
106 if (!cur || !add)
107 return;
108
109 if (*add)
110 (*add)->prev = cur;
111
112 cur->parent = parent;
113 cur->next = *add;
114 cur->prev = NULL;
115 *add = cur;
116}
117
124struct Email *find_virtual(struct MuttThread *cur, bool reverse)
125{
126 if (!cur)
127 return NULL;
128
129 struct MuttThread *top = NULL;
130
131 if (cur->message && (cur->message->vnum >= 0))
132 return cur->message;
133
134 top = cur;
135 cur = cur->child;
136 if (!cur)
137 return NULL;
138
139 while (reverse && cur->next)
140 cur = cur->next;
141
142 while (true)
143 {
144 if (cur->message && (cur->message->vnum >= 0))
145 return cur->message;
146
147 if (cur->child)
148 {
149 cur = cur->child;
150
151 while (reverse && cur->next)
152 cur = cur->next;
153 }
154 else if (reverse ? cur->prev : cur->next)
155 {
156 cur = reverse ? cur->prev : cur->next;
157 }
158 else
159 {
160 while (!(reverse ? cur->prev : cur->next))
161 {
162 cur = cur->parent;
163 if (cur == top)
164 return NULL;
165 }
166 cur = reverse ? cur->prev : cur->next;
167 }
168 /* not reached */
169 }
170}
171
177void clean_references(struct MuttThread *brk, struct MuttThread *cur)
178{
179 struct ListNode *ref = NULL;
180 bool done = false;
181
182 for (; cur; cur = cur->next, done = false)
183 {
184 /* parse subthread recursively */
185 clean_references(brk, cur->child);
186
187 if (!cur->message)
188 break; /* skip pseudo-message */
189
190 /* Looking for the first bad reference according to the new threading.
191 * Optimal since NeoMutt stores the references in reverse order, and the
192 * first loop should match immediately for mails respecting RFC2822. */
193 for (struct MuttThread *p = brk; !done && p; p = p->parent)
194 {
195 for (ref = STAILQ_FIRST(&cur->message->env->references);
196 p->message && ref; ref = STAILQ_NEXT(ref, entries))
197 {
198 if (mutt_istr_equal(ref->data, p->message->env->message_id))
199 {
200 done = true;
201 break;
202 }
203 }
204 }
205
206 if (done)
207 {
208 struct Email *e = cur->message;
209
210 /* clearing the References: header from obsolete Message-ID(s) */
211 struct ListNode *np = NULL;
212 while ((np = STAILQ_NEXT(ref, entries)))
213 {
214 STAILQ_REMOVE_AFTER(&cur->message->env->references, ref, entries);
215 FREE(&np->data);
216 FREE(&np);
217 }
218
219 e->changed = true;
221 }
222 }
223}
224
230{
231 if (!e)
232 return;
233
236 e->changed = true;
238
240}
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:45
Convenience wrapper for the library headers.
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:721
#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:39
struct Envelope * env
Envelope information.
Definition: email.h:68
bool changed
Email has been edited.
Definition: email.h:77
int vnum
Virtual message number.
Definition: email.h:117
struct MuttThread * thread
Thread of Emails.
Definition: email.h:122
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:90
struct ListHead references
message references (in reverse order)
Definition: envelope.h:83
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:84
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:66
bool is_descendant(const struct MuttThread *a, const struct MuttThread *b)
Is one thread a descendant of another.
Definition: thread.c:46
void insert_message(struct MuttThread **add, struct MuttThread *parent, struct MuttThread *cur)
Insert a message into a thread.
Definition: thread.c:104
void mutt_break_thread(struct Email *e)
Break the email Thread.
Definition: thread.c:229
struct Email * find_virtual(struct MuttThread *cur, bool reverse)
Find an email with a Virtual message number.
Definition: thread.c:124
void clean_references(struct MuttThread *brk, struct MuttThread *cur)
Update email references for a broken Thread.
Definition: thread.c:177
Create/manipulate threading in emails.