NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
thread.c File Reference
#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, int 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
trueIf b 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 }
+ 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_key)
80  {
81  for (tmp = cur->parent; tmp && (tmp->sort_key == cur->sort_key); tmp = tmp->parent)
82  tmp->sort_key = NULL;
83  }
84 }
+ 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 94 of file thread.c.

95 {
96  if (!cur || !add)
97  return;
98 
99  if (*add)
100  (*add)->prev = cur;
101 
102  cur->parent = parent;
103  cur->next = *add;
104  cur->prev = NULL;
105  *add = cur;
106 }
+ 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 111 of file thread.c.

112 {
113  FREE(&obj);
114 }
+ Here is the caller graph for this function:

◆ find_virtual()

struct Email* find_virtual ( struct MuttThread cur,
int  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 122 of file thread.c.

123 {
124  if (!cur)
125  return NULL;
126 
127  struct MuttThread *top = NULL;
128 
129  if (cur->message && (cur->message->vnum >= 0))
130  return cur->message;
131 
132  top = cur;
133  cur = cur->child;
134  if (!cur)
135  return NULL;
136 
137  while (reverse && cur->next)
138  cur = cur->next;
139 
140  while (true)
141  {
142  if (cur->message && (cur->message->vnum >= 0))
143  return cur->message;
144 
145  if (cur->child)
146  {
147  cur = cur->child;
148 
149  while (reverse && cur->next)
150  cur = cur->next;
151  }
152  else if (reverse ? cur->prev : cur->next)
153  cur = reverse ? cur->prev : cur->next;
154  else
155  {
156  while (!(reverse ? cur->prev : cur->next))
157  {
158  cur = cur->parent;
159  if (cur == top)
160  return NULL;
161  }
162  cur = reverse ? cur->prev : cur->next;
163  }
164  /* not reached */
165  }
166 }
+ 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 173 of file thread.c.

174 {
175  struct ListNode *ref = NULL;
176  bool done = false;
177 
178  for (; cur; cur = cur->next, done = false)
179  {
180  /* parse subthread recursively */
181  clean_references(brk, cur->child);
182 
183  if (!cur->message)
184  break; /* skip pseudo-message */
185 
186  /* Looking for the first bad reference according to the new threading.
187  * Optimal since NeoMutt stores the references in reverse order, and the
188  * first loop should match immediately for mails respecting RFC2822. */
189  for (struct MuttThread *p = brk; !done && p; p = p->parent)
190  {
191  for (ref = STAILQ_FIRST(&cur->message->env->references);
192  p->message && ref; ref = STAILQ_NEXT(ref, entries))
193  {
194  if (mutt_istr_equal(ref->data, p->message->env->message_id))
195  {
196  done = true;
197  break;
198  }
199  }
200  }
201 
202  if (done)
203  {
204  struct Email *e = cur->message;
205 
206  /* clearing the References: header from obsolete Message-ID(s) */
207  struct ListNode *np = NULL;
208  while ((np = STAILQ_NEXT(ref, entries)))
209  {
210  STAILQ_REMOVE_AFTER(&cur->message->env->references, ref, entries);
211  FREE(&np->data);
212  FREE(&np);
213  }
214 
215  e->changed = true;
217  }
218  }
219 }
+ 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 225 of file thread.c.

226 {
227  if (!e)
228  return;
229 
232  e->changed = true;
234 
236 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:
MUTT_ENV_CHANGED_IRT
#define MUTT_ENV_CHANGED_IRT
In-Reply-To changed to link/break threads.
Definition: envelope.h:32
Envelope::in_reply_to
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:82
ListNode
A List node for strings.
Definition: list.h:34
Email::thread
struct MuttThread * thread
Thread of Emails.
Definition: email.h:95
FREE
#define FREE(x)
Definition: memory.h:40
STAILQ_FIRST
#define STAILQ_FIRST(head)
Definition: queue.h:347
MuttThread::prev
struct MuttThread * prev
Previous sibling Thread.
Definition: thread.h:48
mutt_istr_equal
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
MuttThread::parent
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
MuttThread::child
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
Envelope::changed
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
Definition: envelope.h:88
MuttThread::message
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
Email::env
struct Envelope * env
Envelope information.
Definition: email.h:90
MuttThread
An Email conversation.
Definition: thread.h:34
STAILQ_REMOVE_AFTER
#define STAILQ_REMOVE_AFTER(head, elm, field)
Definition: queue.h:413
MuttThread::sort_key
struct Email * sort_key
Email that this Thread is sorted against.
Definition: thread.h:50
MUTT_ENV_CHANGED_REFS
#define MUTT_ENV_CHANGED_REFS
References changed to break thread.
Definition: envelope.h:33
Email::vnum
int vnum
Virtual message number.
Definition: email.h:88
ListNode::data
char * data
String.
Definition: list.h:36
MuttThread::next
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
STAILQ_NEXT
#define STAILQ_NEXT(elm, field)
Definition: queue.h:397
Email
The envelope/body of an email.
Definition: email.h:37
Envelope::references
struct ListHead references
message references (in reverse order)
Definition: envelope.h:81
mutt_list_free
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
clean_references
void clean_references(struct MuttThread *brk, struct MuttThread *cur)
Update email references for a broken Thread.
Definition: thread.c:173
Email::changed
bool changed
Email has been edited.
Definition: email.h:48