NeoMutt  2021-02-05-666-ge300cd
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, 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,
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 }
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
struct Email * sort_thread_key
Email that controls how top thread sorts.
Definition: thread.h:50
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
An Email conversation.
Definition: thread.h:34
+ 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 }
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
struct MuttThread * prev
Previous sibling Thread.
Definition: thread.h:48
+ Here is the caller graph for this function:

◆ thread_hash_destructor()

void thread_hash_destructor ( int  type,
void *  obj,
intptr_t  data 
)

Hash Destructor callback - Implements hash_hdata_free_t.

Definition at line 119 of file thread.c.

120 {
121  FREE(&obj);
122 }
#define FREE(x)
Definition: memory.h:40
+ 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 }
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
struct MuttThread * prev
Previous sibling Thread.
Definition: thread.h:48
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
int vnum
Virtual message number.
Definition: email.h:88
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
An Email conversation.
Definition: thread.h:34
+ 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 }
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
The envelope/body of an email.
Definition: email.h:37
bool changed
Email has been edited.
Definition: email.h:48
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:88
struct Envelope * env
Envelope information.
Definition: email.h:90
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
void clean_references(struct MuttThread *brk, struct MuttThread *cur)
Update email references for a broken Thread.
Definition: thread.c:181
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
An Email conversation.
Definition: thread.h:34
char * data
String.
Definition: list.h:36
#define FREE(x)
Definition: memory.h:40
#define MUTT_ENV_CHANGED_REFS
References changed to break thread.
Definition: envelope.h:33
struct ListHead references
message references (in reverse order)
Definition: envelope.h:81
A List node for strings.
Definition: list.h:34
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define STAILQ_REMOVE_AFTER(head, elm, field)
Definition: queue.h:416
+ 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 }
struct MuttThread * thread
Thread of Emails.
Definition: email.h:95
bool changed
Email has been edited.
Definition: email.h:48
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:88
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:82
struct Envelope * env
Envelope information.
Definition: email.h:90
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
void clean_references(struct MuttThread *brk, struct MuttThread *cur)
Update email references for a broken Thread.
Definition: thread.c:181
#define MUTT_ENV_CHANGED_REFS
References changed to break thread.
Definition: envelope.h:33
#define MUTT_ENV_CHANGED_IRT
In-Reply-To changed to link/break threads.
Definition: envelope.h:32
struct ListHead references
message references (in reverse order)
Definition: envelope.h:81
+ Here is the call graph for this function:
+ Here is the caller graph for this function: