NeoMutt  2024-12-12-14-g7b49f7
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
thread.c File Reference

Create/manipulate threading in emails. More...

#include "config.h"
#include <stdbool.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 (const struct MuttThread *a, const struct MuttThread *b)
 Is one thread a descendant of another.
 
void unlink_message (struct MuttThread **old, struct MuttThread *cur)
 Break the message out of the thread.
 
void insert_message (struct MuttThread **add, struct MuttThread *parent, struct MuttThread *cur)
 Insert a message into a thread.
 
struct Emailfind_virtual (struct MuttThread *cur, bool reverse)
 Find an email with a Virtual message number.
 
void clean_references (struct MuttThread *brk, struct MuttThread *cur)
 Update email references for a broken Thread.
 
void mutt_break_thread (struct Email *e)
 Break the email Thread.
 

Detailed Description

Create/manipulate threading in emails.

Authors
  • Richard Russon
  • Federico Kircheis
  • Pietro Cerutti
  • Eric Blake

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 ( const 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 46 of file thread.c.

47{
48 while (a)
49 {
50 if (a == b)
51 return true;
52 a = a->parent;
53 }
54 return false;
55}
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:44
+ 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 66 of file thread.c.

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}
An Email conversation.
Definition: thread.h:34
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 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
+ 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 104 of file thread.c.

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}
+ 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 124 of file thread.c.

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}
int vnum
Virtual message number.
Definition: email.h:114
struct MuttThread * child
Child of this Thread.
Definition: thread.h:45
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 177 of file thread.c.

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}
#define MUTT_ENV_CHANGED_REFS
References changed to break thread.
Definition: envelope.h:35
#define FREE(x)
Definition: memory.h:55
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:672
#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
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
A List node for strings.
Definition: list.h:37
char * data
String.
Definition: list.h:38
void clean_references(struct MuttThread *brk, struct MuttThread *cur)
Update email references for a broken Thread.
Definition: thread.c:177
+ 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 229 of file thread.c.

230{
231 if (!e)
232 return;
233
236 e->changed = true;
238
240}
#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:123
struct MuttThread * thread
Thread of Emails.
Definition: email.h:119
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:84
+ Here is the call graph for this function:
+ Here is the caller graph for this function: