NeoMutt  2023-03-22
Teaching an old dog new tricks
DOXYGEN
thread.c File Reference

Create/manipulate threading in emails. More...

#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "mutt/lib.h"
#include "thread.h"
#include "email.h"
#include "envelope.h"
+ Include dependency graph for thread.c:

Go to the source code of this file.

Functions

bool is_descendant (struct MuttThread *a, const struct MuttThread *b)
 Is one thread a descendant of another. More...
 
void unlink_message (struct MuttThread **old, struct MuttThread *cur)
 Break the message out of the thread. More...
 
void insert_message (struct MuttThread **add, struct MuttThread *parent, struct MuttThread *cur)
 Insert a message into a thread. More...
 
void thread_hash_destructor (int type, void *obj, intptr_t data)
 Hash Destructor callback - Implements hash_hdata_free_t -. More...
 
struct Emailfind_virtual (struct MuttThread *cur, bool reverse)
 Find an email with a Virtual message number. More...
 
void clean_references (struct MuttThread *brk, struct MuttThread *cur)
 Update email references for a broken Thread. More...
 
void mutt_break_thread (struct Email *e)
 Break the email Thread. More...
 

Detailed Description

Create/manipulate threading in emails.

Authors
  • Michael R. Elkins

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file thread.c.

Function Documentation

◆ is_descendant()

bool is_descendant ( struct MuttThread a,
const struct MuttThread b 
)

Is one thread a descendant of another.

Parameters
aParent thread
bChild thread
Return values
trueb is a descendent of a (child, grandchild, etc)

Definition at line 44 of file thread.c.

45{
46 while (a)
47 {
48 if (a == b)
49 return true;
50 a = a->parent;
51 }
52 return false;
53}
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
+ Here is the caller graph for this function:

◆ unlink_message()

void unlink_message ( struct MuttThread **  old,
struct MuttThread cur 
)

Break the message out of the thread.

Parameters
[in,out]oldRoot of thread
[in]curChild thread to separate

Remove cur and its descendants from their current location. Also make sure ancestors of cur no longer are sorted by the fact that cur is their descendant.

Definition at line 64 of file thread.c.

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}
An Email conversation.
Definition: thread.h:35
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 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
+ Here is the caller graph for this function:

◆ insert_message()

void insert_message ( struct MuttThread **  add,
struct MuttThread parent,
struct MuttThread cur 
)

Insert a message into a thread.

Parameters
[in,out]addNew thread to add
[in]parentParent of new thread
[in]curCurrent thread to add after

add cur as a prior sibling of *add, with parent parent

Definition at line 102 of file thread.c.

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}
+ Here is the caller graph for this function:

◆ find_virtual()

struct Email * find_virtual ( struct MuttThread cur,
bool  reverse 
)

Find an email with a Virtual message number.

Parameters
curThread to search
reverseIf true, reverse the direction of the search
Return values
ptrMatching Email

Definition at line 130 of file thread.c.

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}
int vnum
Virtual message number.
Definition: email.h:113
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
+ Here is the caller graph for this function:

◆ clean_references()

void clean_references ( struct MuttThread brk,
struct MuttThread cur 
)

Update email references for a broken Thread.

Parameters
brkBroken thread
curCurrent thread

Definition at line 181 of file thread.c.

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}
#define MUTT_ENV_CHANGED_REFS
References changed to break thread.
Definition: envelope.h:35
#define FREE(x)
Definition: memory.h:43
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
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
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
void clean_references(struct MuttThread *brk, struct MuttThread *cur)
Update email references for a broken Thread.
Definition: thread.c:181
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_break_thread()

void mutt_break_thread ( struct Email e)

Break the email Thread.

Parameters
eEmail to break at

Definition at line 233 of file thread.c.

234{
235 if (!e)
236 return;
237
240 e->changed = true;
242
244}
#define MUTT_ENV_CHANGED_IRT
In-Reply-To changed to link/break threads.
Definition: envelope.h:34
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
struct MuttThread * thread
Thread of Emails.
Definition: email.h:118
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:86
+ Here is the call graph for this function:
+ Here is the caller graph for this function: