NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
mutt_thread.h File Reference
#include <stdbool.h>
#include <stdint.h>
+ Include dependency graph for mutt_thread.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define MUTT_THREAD_NO_FLAGS   0
 No flags are set. More...
 
#define MUTT_THREAD_COLLAPSE   (1 << 0)
 Collapse an email thread. More...
 
#define MUTT_THREAD_UNCOLLAPSE   (1 << 1)
 Uncollapse an email thread. More...
 
#define MUTT_THREAD_UNREAD   (1 << 2)
 Count unread emails in a thread. More...
 
#define MUTT_THREAD_NEXT_UNREAD   (1 << 3)
 Find the next unread email. More...
 
#define MUTT_THREAD_FLAGGED   (1 << 4)
 Count flagged emails in a thread. More...
 
#define mutt_collapse_thread(e)   mutt_traverse_thread(e, MUTT_THREAD_COLLAPSE)
 
#define mutt_uncollapse_thread(e)   mutt_traverse_thread(e, MUTT_THREAD_UNCOLLAPSE)
 
#define mutt_thread_contains_unread(e)   mutt_traverse_thread(e, MUTT_THREAD_UNREAD)
 
#define mutt_thread_contains_flagged(e)   mutt_traverse_thread(e, MUTT_THREAD_FLAGGED)
 
#define mutt_thread_next_unread(e)   mutt_traverse_thread(e, MUTT_THREAD_NEXT_UNREAD)
 
#define mutt_next_thread(e)   mutt_aside_thread(e, true, false)
 
#define mutt_previous_thread(e)   mutt_aside_thread(e, false, false)
 
#define mutt_next_subthread(e)   mutt_aside_thread(e, true, true)
 
#define mutt_previous_subthread(e)   mutt_aside_thread(e, false, true)
 

Typedefs

typedef uint8_t MuttThreadFlags
 Flags, e.g. MUTT_THREAD_COLLAPSE. More...
 

Enumerations

enum  TreeChar {
  MUTT_TREE_LLCORNER = 1, MUTT_TREE_ULCORNER, MUTT_TREE_LTEE, MUTT_TREE_HLINE,
  MUTT_TREE_VLINE, MUTT_TREE_SPACE, MUTT_TREE_RARROW, MUTT_TREE_STAR,
  MUTT_TREE_HIDDEN, MUTT_TREE_EQUALS, MUTT_TREE_TTEE, MUTT_TREE_BTEE,
  MUTT_TREE_MISSING, MUTT_TREE_MAX, MUTT_SPECIAL_INDEX = MUTT_TREE_MAX
}
 Tree characters for menus. More...
 
enum  MessageInThread { MIT_NUM_MESSAGES, MIT_POSITION }
 

Functions

int mutt_traverse_thread (struct Email *e, MuttThreadFlags flag)
 Recurse through an email thread, matching messages. More...
 
int mutt_aside_thread (struct Email *e, bool forwards, bool subthreads)
 Find the next/previous (sub)thread. More...
 
struct ThreadsContextmutt_thread_ctx_init (struct Mailbox *m)
 Initialize a threading context. More...
 
void mutt_thread_ctx_free (struct ThreadsContext **tctx)
 Finalize a threading context. More...
 
void mutt_thread_collapse_collapsed (struct ThreadsContext *tctx)
 re-collapse threads marked as collapsed More...
 
void mutt_thread_collapse (struct ThreadsContext *tctx, bool collapse)
 toggle collapse More...
 
bool mutt_thread_can_collapse (struct Email *e)
 Check whether a thread can be collapsed. More...
 
void mutt_clear_threads (struct ThreadsContext *tctx)
 Clear the threading of message in a mailbox. More...
 
void mutt_draw_tree (struct ThreadsContext *tctx)
 Draw a tree of threaded emails. More...
 
bool mutt_link_threads (struct Email *parent, struct EmailList *children, struct Mailbox *m)
 Forcibly link threads together. More...
 
struct HashTablemutt_make_id_hash (struct Mailbox *m)
 Create a Hash Table for message-ids. More...
 
int mutt_messages_in_thread (struct Mailbox *m, struct Email *e, enum MessageInThread mit)
 Count the messages in a thread. More...
 
int mutt_parent_message (struct Email *e, bool find_root)
 Find the parent of a message. More...
 
off_t mutt_set_vnum (struct Mailbox *m)
 Set the virtual index number of all the messages in a mailbox. More...
 
void mutt_sort_subthreads (struct ThreadsContext *tctx, bool init)
 Sort the children of a thread. More...
 
void mutt_sort_threads (struct ThreadsContext *tctx, bool init)
 Sort email threads. More...
 

Variables

bool C_CollapseFlagged
 Config: Prevent the collapse of threads with flagged emails. More...
 
bool C_CollapseUnread
 Config: Prevent the collapse of threads with unread emails. More...
 
bool C_DuplicateThreads
 Config: Highlight messages with duplicated message IDs. More...
 
bool C_HideLimited
 Config: Don't indicate hidden messages, in the thread tree. More...
 
bool C_HideMissing
 Config: Don't indicate missing messages, in the thread tree. More...
 
bool C_HideThreadSubject
 Config: Hide subjects that are similar to that of the parent message. More...
 
bool C_HideTopLimited
 Config: Don't indicate hidden top message, in the thread tree. More...
 
bool C_HideTopMissing
 Config: Don't indicate missing top message, in the thread tree. More...
 
bool C_NarrowTree
 Config: Draw a narrower thread tree in the index. More...
 
bool C_SortRe
 Config: Sort method for the sidebar. More...
 
bool C_StrictThreads
 Config: Thread messages using 'In-Reply-To' and 'References' headers. More...
 
bool C_ThreadReceived
 Config: Sort threaded messages by their received date. More...
 

Detailed Description

Create/manipulate threading in emails

Authors
  • Richard Russon

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 mutt_thread.h.

Macro Definition Documentation

◆ MUTT_THREAD_NO_FLAGS

#define MUTT_THREAD_NO_FLAGS   0

No flags are set.

Definition at line 75 of file mutt_thread.h.

◆ MUTT_THREAD_COLLAPSE

#define MUTT_THREAD_COLLAPSE   (1 << 0)

Collapse an email thread.

Definition at line 76 of file mutt_thread.h.

◆ MUTT_THREAD_UNCOLLAPSE

#define MUTT_THREAD_UNCOLLAPSE   (1 << 1)

Uncollapse an email thread.

Definition at line 77 of file mutt_thread.h.

◆ MUTT_THREAD_UNREAD

#define MUTT_THREAD_UNREAD   (1 << 2)

Count unread emails in a thread.

Definition at line 78 of file mutt_thread.h.

◆ MUTT_THREAD_NEXT_UNREAD

#define MUTT_THREAD_NEXT_UNREAD   (1 << 3)

Find the next unread email.

Definition at line 79 of file mutt_thread.h.

◆ MUTT_THREAD_FLAGGED

#define MUTT_THREAD_FLAGGED   (1 << 4)

Count flagged emails in a thread.

Definition at line 80 of file mutt_thread.h.

◆ mutt_collapse_thread

#define mutt_collapse_thread (   e)    mutt_traverse_thread(e, MUTT_THREAD_COLLAPSE)

Definition at line 89 of file mutt_thread.h.

◆ mutt_uncollapse_thread

#define mutt_uncollapse_thread (   e)    mutt_traverse_thread(e, MUTT_THREAD_UNCOLLAPSE)

Definition at line 90 of file mutt_thread.h.

◆ mutt_thread_contains_unread

#define mutt_thread_contains_unread (   e)    mutt_traverse_thread(e, MUTT_THREAD_UNREAD)

Definition at line 91 of file mutt_thread.h.

◆ mutt_thread_contains_flagged

#define mutt_thread_contains_flagged (   e)    mutt_traverse_thread(e, MUTT_THREAD_FLAGGED)

Definition at line 92 of file mutt_thread.h.

◆ mutt_thread_next_unread

#define mutt_thread_next_unread (   e)    mutt_traverse_thread(e, MUTT_THREAD_NEXT_UNREAD)

Definition at line 93 of file mutt_thread.h.

◆ mutt_next_thread

#define mutt_next_thread (   e)    mutt_aside_thread(e, true, false)

Definition at line 96 of file mutt_thread.h.

◆ mutt_previous_thread

#define mutt_previous_thread (   e)    mutt_aside_thread(e, false, false)

Definition at line 97 of file mutt_thread.h.

◆ mutt_next_subthread

#define mutt_next_subthread (   e)    mutt_aside_thread(e, true, true)

Definition at line 98 of file mutt_thread.h.

◆ mutt_previous_subthread

#define mutt_previous_subthread (   e)    mutt_aside_thread(e, false, true)

Definition at line 99 of file mutt_thread.h.

Typedef Documentation

◆ MuttThreadFlags

typedef uint8_t MuttThreadFlags

Flags, e.g. MUTT_THREAD_COLLAPSE.

Definition at line 74 of file mutt_thread.h.

Enumeration Type Documentation

◆ TreeChar

enum TreeChar

Tree characters for menus.

See also
linearize_tree(), print_enriched_string()
Enumerator
MUTT_TREE_LLCORNER 

Lower left corner.

MUTT_TREE_ULCORNER 

Upper left corner.

MUTT_TREE_LTEE 

Left T-piece.

MUTT_TREE_HLINE 

Horizontal line.

MUTT_TREE_VLINE 

Vertical line.

MUTT_TREE_SPACE 

Blank space.

MUTT_TREE_RARROW 

Right arrow.

MUTT_TREE_STAR 

Star character (for threads)

MUTT_TREE_HIDDEN 

Ampersand character (for threads)

MUTT_TREE_EQUALS 

Equals (for threads)

MUTT_TREE_TTEE 

Top T-piece.

MUTT_TREE_BTEE 

Bottom T-piece.

MUTT_TREE_MISSING 

Question mark.

MUTT_TREE_MAX 
MUTT_SPECIAL_INDEX 

Colour indicator.

Definition at line 54 of file mutt_thread.h.

◆ MessageInThread

Enumerator
MIT_NUM_MESSAGES 
MIT_POSITION 

Definition at line 82 of file mutt_thread.h.

83 {
84  MIT_NUM_MESSAGES, // How many messages are in the thread
85  MIT_POSITION, // Our position in the thread
86 };

Function Documentation

◆ mutt_traverse_thread()

int mutt_traverse_thread ( struct Email e_cur,
MuttThreadFlags  flag 
)

Recurse through an email thread, matching messages.

Parameters
e_curCurrent Email
flagFlag to set, see MuttThreadFlags
Return values
numNumber of matches

Definition at line 1266 of file mutt_thread.c.

1267 {
1268  struct MuttThread *thread = NULL, *top = NULL;
1269  struct Email *e_root = NULL;
1270  int final, reverse = (C_Sort & SORT_REVERSE), minmsgno;
1271  int num_hidden = 0, new_mail = 0, old_mail = 0;
1272  bool flagged = false;
1273  int min_unread_msgno = INT_MAX, min_unread = e_cur->vnum;
1274 
1275  if ((C_Sort & SORT_MASK) != SORT_THREADS)
1276  {
1277  mutt_error(_("Threading is not enabled"));
1278  return e_cur->vnum;
1279  }
1280 
1281  if (!e_cur->thread)
1282  {
1283  return e_cur->vnum;
1284  }
1285 
1286  final = e_cur->vnum;
1287  thread = e_cur->thread;
1288  while (thread->parent)
1289  thread = thread->parent;
1290  top = thread;
1291  while (!thread->message)
1292  thread = thread->child;
1293  e_cur = thread->message;
1294  minmsgno = e_cur->msgno;
1295 
1296  if (!e_cur->read && e_cur->visible)
1297  {
1298  if (e_cur->old)
1299  old_mail = 2;
1300  else
1301  new_mail = 1;
1302  if (e_cur->msgno < min_unread_msgno)
1303  {
1304  min_unread = e_cur->vnum;
1305  min_unread_msgno = e_cur->msgno;
1306  }
1307  }
1308 
1309  if (e_cur->flagged && e_cur->visible)
1310  flagged = true;
1311 
1312  if ((e_cur->vnum == -1) && e_cur->visible)
1313  num_hidden++;
1314 
1316  {
1317  e_cur->pair = 0; /* force index entry's color to be re-evaluated */
1318  e_cur->collapsed = flag & MUTT_THREAD_COLLAPSE;
1319  if (e_cur->vnum != -1)
1320  {
1321  e_root = e_cur;
1322  if (flag & MUTT_THREAD_COLLAPSE)
1323  final = e_root->vnum;
1324  }
1325  }
1326 
1327  if ((thread == top) && !(thread = thread->child))
1328  {
1329  /* return value depends on action requested */
1331  {
1332  e_cur->num_hidden = num_hidden;
1333  return final;
1334  }
1335  if (flag & MUTT_THREAD_UNREAD)
1336  return (old_mail && new_mail) ? new_mail : (old_mail ? old_mail : new_mail);
1337  if (flag & MUTT_THREAD_NEXT_UNREAD)
1338  return min_unread;
1339  if (flag & MUTT_THREAD_FLAGGED)
1340  return flagged;
1341  }
1342 
1343  while (true)
1344  {
1345  e_cur = thread->message;
1346 
1347  if (e_cur)
1348  {
1350  {
1351  e_cur->pair = 0; /* force index entry's color to be re-evaluated */
1352  e_cur->collapsed = flag & MUTT_THREAD_COLLAPSE;
1353  if (!e_root && e_cur->visible)
1354  {
1355  e_root = e_cur;
1356  if (flag & MUTT_THREAD_COLLAPSE)
1357  final = e_root->vnum;
1358  }
1359 
1360  if (reverse && (flag & MUTT_THREAD_COLLAPSE) &&
1361  (e_cur->msgno < minmsgno) && e_cur->visible)
1362  {
1363  minmsgno = e_cur->msgno;
1364  final = e_cur->vnum;
1365  }
1366 
1367  if (flag & MUTT_THREAD_COLLAPSE)
1368  {
1369  if (e_cur != e_root)
1370  e_cur->vnum = -1;
1371  }
1372  else
1373  {
1374  if (e_cur->visible)
1375  e_cur->vnum = e_cur->msgno;
1376  }
1377  }
1378 
1379  if (!e_cur->read && e_cur->visible)
1380  {
1381  if (e_cur->old)
1382  old_mail = 2;
1383  else
1384  new_mail = 1;
1385  if (e_cur->msgno < min_unread_msgno)
1386  {
1387  min_unread = e_cur->vnum;
1388  min_unread_msgno = e_cur->msgno;
1389  }
1390  }
1391 
1392  if (e_cur->flagged && e_cur->visible)
1393  flagged = true;
1394 
1395  if ((e_cur->vnum == -1) && e_cur->visible)
1396  num_hidden++;
1397  }
1398 
1399  if (thread->child)
1400  thread = thread->child;
1401  else if (thread->next)
1402  thread = thread->next;
1403  else
1404  {
1405  bool done = false;
1406  while (!thread->next)
1407  {
1408  thread = thread->parent;
1409  if (thread == top)
1410  {
1411  done = true;
1412  break;
1413  }
1414  }
1415  if (done)
1416  break;
1417  thread = thread->next;
1418  }
1419  }
1420 
1421  /* re-traverse the thread and store num_hidden in all headers, with or
1422  * without a virtual index. this will allow ~v to match all collapsed
1423  * messages when switching sort order to non-threaded. */
1424  if (flag & MUTT_THREAD_COLLAPSE)
1425  {
1426  thread = top;
1427  while (true)
1428  {
1429  e_cur = thread->message;
1430  if (e_cur)
1431  e_cur->num_hidden = num_hidden + 1;
1432 
1433  if (thread->child)
1434  thread = thread->child;
1435  else if (thread->next)
1436  thread = thread->next;
1437  else
1438  {
1439  bool done = false;
1440  while (!thread->next)
1441  {
1442  thread = thread->parent;
1443  if (thread == top)
1444  {
1445  done = true;
1446  break;
1447  }
1448  }
1449  if (done)
1450  break;
1451  thread = thread->next;
1452  }
1453  }
1454  }
1455 
1456  /* return value depends on action requested */
1458  return final;
1459  if (flag & MUTT_THREAD_UNREAD)
1460  return (old_mail && new_mail) ? new_mail : (old_mail ? old_mail : new_mail);
1461  if (flag & MUTT_THREAD_NEXT_UNREAD)
1462  return min_unread;
1463  if (flag & MUTT_THREAD_FLAGGED)
1464  return flagged;
1465 
1466  return 0;
1467 }

◆ mutt_aside_thread()

int mutt_aside_thread ( struct Email e,
bool  forwards,
bool  subthreads 
)

Find the next/previous (sub)thread.

Parameters
eSearch from this Email
forwardsDirection to search: 'true' forwards, 'false' backwards
subthreadsSearch subthreads: 'true' subthread, 'false' not
Return values
numIndex into the virtual email table

Definition at line 1119 of file mutt_thread.c.

1120 {
1121  struct MuttThread *cur = NULL;
1122  struct Email *e_tmp = NULL;
1123 
1124  if ((C_Sort & SORT_MASK) != SORT_THREADS)
1125  {
1126  mutt_error(_("Threading is not enabled"));
1127  return e->vnum;
1128  }
1129 
1130  cur = e->thread;
1131 
1132  if (subthreads)
1133  {
1134  if (forwards ^ ((C_Sort & SORT_REVERSE) != 0))
1135  {
1136  while (!cur->next && cur->parent)
1137  cur = cur->parent;
1138  }
1139  else
1140  {
1141  while (!cur->prev && cur->parent)
1142  cur = cur->parent;
1143  }
1144  }
1145  else
1146  {
1147  while (cur->parent)
1148  cur = cur->parent;
1149  }
1150 
1151  if (forwards ^ ((C_Sort & SORT_REVERSE) != 0))
1152  {
1153  do
1154  {
1155  cur = cur->next;
1156  if (!cur)
1157  return -1;
1158  e_tmp = find_virtual(cur, 0);
1159  } while (!e_tmp);
1160  }
1161  else
1162  {
1163  do
1164  {
1165  cur = cur->prev;
1166  if (!cur)
1167  return -1;
1168  e_tmp = find_virtual(cur, 1);
1169  } while (!e_tmp);
1170  }
1171 
1172  return e_tmp->vnum;
1173 }
+ Here is the call graph for this function:

◆ mutt_thread_ctx_init()

struct ThreadsContext* mutt_thread_ctx_init ( struct Mailbox m)

Initialize a threading context.

Parameters
mCurrent mailbox
Return values
tctxThreading context

Definition at line 288 of file mutt_thread.c.

289 {
290  struct ThreadsContext *tctx = mutt_mem_calloc(1, sizeof(struct ThreadsContext));
291  tctx->mailbox = m;
292  tctx->tree = NULL;
293  tctx->hash = NULL;
294  return tctx;
295 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_thread_ctx_free()

void mutt_thread_ctx_free ( struct ThreadsContext **  tctx)

Finalize a threading context.

Parameters
tctxThreading context to finalize

Definition at line 301 of file mutt_thread.c.

302 {
303  (*tctx)->mailbox = NULL;
304  mutt_hash_free(&(*tctx)->hash);
305  FREE(tctx);
306 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_thread_collapse_collapsed()

void mutt_thread_collapse_collapsed ( struct ThreadsContext tctx)

re-collapse threads marked as collapsed

Parameters
tctxThreading context

Definition at line 1583 of file mutt_thread.c.

1584 {
1585  struct MuttThread *thread = NULL;
1586  struct MuttThread *top = tctx->tree;
1587  while ((thread = top))
1588  {
1589  while (!thread->message)
1590  thread = thread->child;
1591 
1592  struct Email *e = thread->message;
1593  if (e->collapsed)
1595  top = top->next;
1596  }
1597 }
+ Here is the caller graph for this function:

◆ mutt_thread_collapse()

void mutt_thread_collapse ( struct ThreadsContext tctx,
bool  collapse 
)

toggle collapse

Parameters
tctxThreading context
collapseCollapse / uncollapse

Definition at line 1604 of file mutt_thread.c.

1605 {
1606  struct MuttThread *thread = NULL;
1607  struct MuttThread *top = tctx->tree;
1608  while ((thread = top))
1609  {
1610  while (!thread->message)
1611  thread = thread->child;
1612 
1613  struct Email *e = thread->message;
1614 
1615  if (e->collapsed != collapse)
1616  {
1617  if (e->collapsed)
1619  else if (mutt_thread_can_collapse(e))
1621  }
1622  top = top->next;
1623  }
1624 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_thread_can_collapse()

bool mutt_thread_can_collapse ( struct Email e)

Check whether a thread can be collapsed.

Parameters
eHead of the thread
Return values
trueCan be collapsed
falseCannot be collapsed

Definition at line 1632 of file mutt_thread.c.

1633 {
1636 }
+ Here is the caller graph for this function:

◆ mutt_clear_threads()

void mutt_clear_threads ( struct ThreadsContext tctx)

Clear the threading of message in a mailbox.

Parameters
tctxThreading context

Definition at line 637 of file mutt_thread.c.

638 {
639  if (!tctx || !tctx->mailbox || !tctx->mailbox->emails || !tctx->tree)
640  return;
641 
642  for (int i = 0; i < tctx->mailbox->msg_count; i++)
643  {
644  struct Email *e = tctx->mailbox->emails[i];
645  if (!e)
646  break;
647 
648  /* mailbox may have been only partially read */
649  e->thread = NULL;
650  e->threaded = false;
651  }
652  tctx->tree = NULL;
653  mutt_hash_free(&tctx->hash);
654 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_draw_tree()

void mutt_draw_tree ( struct ThreadsContext tctx)

Draw a tree of threaded emails.

Parameters
tctxThreading context

Since the graphics characters have a value >255, I have to resort to using escape sequences to pass the information to print_enriched_string(). These are the macros MUTT_TREE_* defined in mutt.h.

ncurses should automatically use the default ASCII characters instead of graphics chars on terminals which don't support them (see the man page for curs_addch).

Definition at line 320 of file mutt_thread.c.

321 {
322  char *pfx = NULL, *mypfx = NULL, *arrow = NULL, *myarrow = NULL, *new_tree = NULL;
325  int depth = 0, start_depth = 0, max_depth = 0, width = C_NarrowTree ? 1 : 2;
326  struct MuttThread *nextdisp = NULL, *pseudo = NULL, *parent = NULL;
327 
328  struct MuttThread *tree = tctx->tree;
329 
330  /* Do the visibility calculations and free the old thread chars.
331  * From now on we can simply ignore invisible subtrees */
332  calculate_visibility(tree, &max_depth);
333  pfx = mutt_mem_malloc((width * max_depth) + 2);
334  arrow = mutt_mem_malloc((width * max_depth) + 2);
335  while (tree)
336  {
337  if (depth != 0)
338  {
339  myarrow = arrow + (depth - start_depth - ((start_depth != 0) ? 0 : 1)) * width;
340  if (start_depth == depth)
341  myarrow[0] = nextdisp ? MUTT_TREE_LTEE : corner;
342  else if (parent->message && !C_HideLimited)
343  myarrow[0] = MUTT_TREE_HIDDEN;
344  else if (!parent->message && !C_HideMissing)
345  myarrow[0] = MUTT_TREE_MISSING;
346  else
347  myarrow[0] = vtee;
348  if (width == 2)
349  {
350  myarrow[1] = pseudo ? MUTT_TREE_STAR :
352  }
353  if (tree->visible)
354  {
355  myarrow[width] = MUTT_TREE_RARROW;
356  myarrow[width + 1] = 0;
357  new_tree = mutt_mem_malloc(((size_t) depth * width) + 2);
358  if (start_depth > 1)
359  {
360  strncpy(new_tree, pfx, (size_t) width * (start_depth - 1));
361  mutt_str_copy(new_tree + (start_depth - 1) * width, arrow,
362  (1 + depth - start_depth) * width + 2);
363  }
364  else
365  mutt_str_copy(new_tree, arrow, ((size_t) depth * width) + 2);
366  tree->message->tree = new_tree;
367  }
368  }
369  if (tree->child && (depth != 0))
370  {
371  mypfx = pfx + (depth - 1) * width;
372  mypfx[0] = nextdisp ? MUTT_TREE_VLINE : MUTT_TREE_SPACE;
373  if (width == 2)
374  mypfx[1] = MUTT_TREE_SPACE;
375  }
376  parent = tree;
377  nextdisp = NULL;
378  pseudo = NULL;
379  do
380  {
381  if (tree->child && tree->subtree_visible)
382  {
383  if (tree->deep)
384  depth++;
385  if (tree->visible)
386  start_depth = depth;
387  tree = tree->child;
388 
389  /* we do this here because we need to make sure that the first child thread
390  * of the old tree that we deal with is actually displayed if any are,
391  * or we might set the parent variable wrong while going through it. */
392  while (!tree->subtree_visible && tree->next)
393  tree = tree->next;
394  }
395  else
396  {
397  while (!tree->next && tree->parent)
398  {
399  if (tree == pseudo)
400  pseudo = NULL;
401  if (tree == nextdisp)
402  nextdisp = NULL;
403  if (tree->visible)
404  start_depth = depth;
405  tree = tree->parent;
406  if (tree->deep)
407  {
408  if (start_depth == depth)
409  start_depth--;
410  depth--;
411  }
412  }
413  if (tree == pseudo)
414  pseudo = NULL;
415  if (tree == nextdisp)
416  nextdisp = NULL;
417  if (tree->visible)
418  start_depth = depth;
419  tree = tree->next;
420  if (!tree)
421  break;
422  }
423  if (!pseudo && tree->fake_thread)
424  pseudo = tree;
425  if (!nextdisp && tree->next_subtree_visible)
426  nextdisp = tree;
427  } while (!tree->deep);
428  }
429 
430  FREE(&pfx);
431  FREE(&arrow);
432 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_link_threads()

bool mutt_link_threads ( struct Email parent,
struct EmailList *  children,
struct Mailbox m 
)

Forcibly link threads together.

Parameters
parentParent Email
childrenList of children Emails
mMailbox
Return values
trueOn success

Definition at line 1563 of file mutt_thread.c.

1564 {
1565  if (!parent || !children || !m)
1566  return false;
1567 
1568  bool changed = false;
1569 
1570  struct EmailNode *en = NULL;
1571  STAILQ_FOREACH(en, children, entries)
1572  {
1573  changed |= link_threads(parent, en->email, m);
1574  }
1575 
1576  return changed;
1577 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_make_id_hash()

struct HashTable* mutt_make_id_hash ( struct Mailbox m)

Create a Hash Table for message-ids.

Parameters
mMailbox
Return values
ptrNewly allocated Hash Table

Definition at line 1518 of file mutt_thread.c.

1519 {
1520  struct HashTable *hash = mutt_hash_new(m->msg_count * 2, MUTT_HASH_NO_FLAGS);
1521 
1522  for (int i = 0; i < m->msg_count; i++)
1523  {
1524  struct Email *e = m->emails[i];
1525  if (!e || !e->env)
1526  continue;
1527 
1528  if (e->env->message_id)
1529  mutt_hash_insert(hash, e->env->message_id, e);
1530  }
1531 
1532  return hash;
1533 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_messages_in_thread()

int mutt_messages_in_thread ( struct Mailbox m,
struct Email e,
enum MessageInThread  mit 
)

Count the messages in a thread.

Parameters
mMailbox
eEmail
mitFlag, e.g. MIT_NUM_MESSAGES
Return values
numNumber of message / Our position

Definition at line 1476 of file mutt_thread.c.

1477 {
1478  if (!m || !e)
1479  return 1;
1480 
1481  struct MuttThread *threads[2];
1482  int rc;
1483 
1484  if (((C_Sort & SORT_MASK) != SORT_THREADS) || !e->thread)
1485  return 1;
1486 
1487  threads[0] = e->thread;
1488  while (threads[0]->parent)
1489  threads[0] = threads[0]->parent;
1490 
1491  threads[1] = (mit == MIT_POSITION) ? e->thread : threads[0]->next;
1492 
1493  for (int i = 0; i < (((mit == MIT_POSITION) || !threads[1]) ? 1 : 2); i++)
1494  {
1495  while (!threads[i]->message)
1496  threads[i] = threads[i]->child;
1497  }
1498 
1499  if (C_Sort & SORT_REVERSE)
1500  rc = threads[0]->message->msgno - (threads[1] ? threads[1]->message->msgno : -1);
1501  else
1502  {
1503  rc = (threads[1] ? threads[1]->message->msgno : m->msg_count) -
1504  threads[0]->message->msgno;
1505  }
1506 
1507  if (mit == MIT_POSITION)
1508  rc += 1;
1509 
1510  return rc;
1511 }
+ Here is the caller graph for this function:

◆ mutt_parent_message()

int mutt_parent_message ( struct Email e,
bool  find_root 
)

Find the parent of a message.

Parameters
eCurrent Email
find_rootIf true, find the root message
Return values
>=0Virtual index number of parent/root message
-1Error

Definition at line 1182 of file mutt_thread.c.

1183 {
1184  if (!e)
1185  return -1;
1186 
1187  struct MuttThread *thread = NULL;
1188  struct Email *e_parent = NULL;
1189 
1190  if ((C_Sort & SORT_MASK) != SORT_THREADS)
1191  {
1192  mutt_error(_("Threading is not enabled"));
1193  return e->vnum;
1194  }
1195 
1196  /* Root may be the current message */
1197  if (find_root)
1198  e_parent = e;
1199 
1200  for (thread = e->thread->parent; thread; thread = thread->parent)
1201  {
1202  e = thread->message;
1203  if (e)
1204  {
1205  e_parent = e;
1206  if (!find_root)
1207  break;
1208  }
1209  }
1210 
1211  if (!e_parent)
1212  {
1213  mutt_error(_("Parent message is not available"));
1214  return -1;
1215  }
1216  if (!is_visible(e_parent))
1217  {
1218  if (find_root)
1219  mutt_error(_("Root message is not visible in this limited view"));
1220  else
1221  mutt_error(_("Parent message is not visible in this limited view"));
1222  return -1;
1223  }
1224  return e_parent->vnum;
1225 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_set_vnum()

off_t mutt_set_vnum ( struct Mailbox m)

Set the virtual index number of all the messages in a mailbox.

Parameters
mMailbox
Return values
mumSize in bytes of all messages shown

Definition at line 1232 of file mutt_thread.c.

1233 {
1234  if (!m)
1235  return 0;
1236 
1237  off_t vsize = 0;
1238  const int padding = mx_msg_padding_size(m);
1239 
1240  m->vcount = 0;
1241 
1242  for (int i = 0; i < m->msg_count; i++)
1243  {
1244  struct Email *e = m->emails[i];
1245  if (!e)
1246  break;
1247 
1248  if (e->vnum >= 0)
1249  {
1250  e->vnum = m->vcount;
1251  m->v2r[m->vcount] = i;
1252  m->vcount++;
1253  vsize += e->body->length + e->body->offset - e->body->hdr_offset + padding;
1254  }
1255  }
1256 
1257  return vsize;
1258 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_sort_subthreads()

void mutt_sort_subthreads ( struct ThreadsContext tctx,
bool  init 
)

Sort the children of a thread.

Parameters
tctxThreading context
initIf true, rebuild the thread

Definition at line 687 of file mutt_thread.c.

688 {
689  struct MuttThread *thread = tctx->tree;
690  if (!thread)
691  return;
692 
693  struct MuttThread **array = NULL, *sort_key = NULL, *top = NULL, *tmp = NULL;
694  struct Email *oldsort_key = NULL;
695  int i, array_size, sort_top = 0;
696 
697  /* we put things into the array backwards to save some cycles,
698  * but we want to have to move less stuff around if we're
699  * resorting, so we sort backwards and then put them back
700  * in reverse order so they're forwards */
701  C_Sort ^= SORT_REVERSE;
702  if (compare_threads(NULL, NULL) == 0)
703  return;
704 
705  top = thread;
706 
707  array_size = 256;
708  array = mutt_mem_calloc(array_size, sizeof(struct MuttThread *));
709  while (true)
710  {
711  if (init || !thread->sort_key)
712  {
713  thread->sort_key = NULL;
714 
715  if (thread->parent)
716  thread->parent->sort_children = true;
717  else
718  sort_top = 1;
719  }
720 
721  if (thread->child)
722  {
723  thread = thread->child;
724  continue;
725  }
726  else
727  {
728  /* if it has no children, it must be real. sort it on its own merits */
730 
731  if (thread->next)
732  {
733  thread = thread->next;
734  continue;
735  }
736  }
737 
738  while (!thread->next)
739  {
740  /* if it has siblings and needs to be sorted, sort it... */
741  if (thread->prev && (thread->parent ? thread->parent->sort_children : sort_top))
742  {
743  /* put them into the array */
744  for (i = 0; thread; i++, thread = thread->prev)
745  {
746  if (i >= array_size)
747  mutt_mem_realloc(&array, (array_size *= 2) * sizeof(struct MuttThread *));
748 
749  array[i] = thread;
750  }
751 
752  qsort((void *) array, i, sizeof(struct MuttThread *), *compare_threads);
753 
754  /* attach them back together. make thread the last sibling. */
755  thread = array[0];
756  thread->next = NULL;
757  array[i - 1]->prev = NULL;
758 
759  if (thread->parent)
760  thread->parent->child = array[i - 1];
761  else
762  top = array[i - 1];
763 
764  while (--i)
765  {
766  array[i - 1]->prev = array[i];
767  array[i]->next = array[i - 1];
768  }
769  }
770 
771  if (thread->parent)
772  {
773  tmp = thread;
774  thread = thread->parent;
775 
777  {
778  /* make sort_key the first or last sibling, as appropriate */
779  sort_key = ((!(C_Sort & SORT_LAST)) ^ (!(C_Sort & SORT_REVERSE))) ?
780  thread->child :
781  tmp;
782 
783  /* we just sorted its children */
784  thread->sort_children = false;
785 
786  oldsort_key = thread->sort_key;
788 
789  if (C_Sort & SORT_LAST)
790  {
791  if (!thread->sort_key ||
792  ((((C_Sort & SORT_REVERSE) ? 1 : -1) *
793  compare_threads((void *) &thread, (void *) &sort_key)) > 0))
794  {
795  thread->sort_key = sort_key->sort_key;
796  }
797  }
798  else if (!thread->sort_key)
799  thread->sort_key = sort_key->sort_key;
800 
801  /* if its sort_key has changed, we need to resort it and siblings */
802  if (oldsort_key != thread->sort_key)
803  {
804  if (thread->parent)
805  thread->parent->sort_children = true;
806  else
807  sort_top = 1;
808  }
809  }
810  }
811  else
812  {
813  C_Sort ^= SORT_REVERSE;
814  FREE(&array);
815  tctx->tree = top;
816  return;
817  }
818  }
819 
820  thread = thread->next;
821  }
822 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_sort_threads()

void mutt_sort_threads ( struct ThreadsContext tctx,
bool  init 
)

Sort email threads.

Parameters
tctxThreading context
initIf true, rebuild the thread

Definition at line 870 of file mutt_thread.c.

871 {
872  if (!tctx || !tctx->mailbox)
873  return;
874 
875  struct Mailbox *m = tctx->mailbox;
876 
877  struct Email *e = NULL;
878  int i, oldsort, using_refs = 0;
879  struct MuttThread *thread = NULL, *tnew = NULL, *tmp = NULL;
880  struct MuttThread top = { 0 };
881  struct ListNode *ref = NULL;
882 
883  /* Set `$sort` to the secondary method to support the set sort_aux=reverse-*
884  * settings. The sorting functions just look at the value of SORT_REVERSE */
885  oldsort = C_Sort;
886  C_Sort = C_SortAux;
887 
888  if (!tctx->hash)
889  init = true;
890 
891  if (init)
892  {
895  }
896 
897  /* we want a quick way to see if things are actually attached to the top of the
898  * thread tree or if they're just dangling, so we attach everything to a top
899  * node temporarily */
900  top.parent = NULL;
901  top.next = NULL;
902  top.prev = NULL;
903 
904  top.child = tctx->tree;
905  for (thread = tctx->tree; thread; thread = thread->next)
906  thread->parent = &top;
907 
908  /* put each new message together with the matching messageless MuttThread if it
909  * exists. otherwise, if there is a MuttThread that already has a message, thread
910  * new message as an identical child. if we didn't attach the message to a
911  * MuttThread, make a new one for it. */
912  for (i = 0; i < m->msg_count; i++)
913  {
914  e = m->emails[i];
915  if (!e)
916  continue;
917 
918  if (!e->thread)
919  {
920  if ((!init || C_DuplicateThreads) && e->env->message_id)
921  thread = mutt_hash_find(tctx->hash, e->env->message_id);
922  else
923  thread = NULL;
924 
925  if (thread && !thread->message)
926  {
927  /* this is a message which was missing before */
928  thread->message = e;
929  e->thread = thread;
930  thread->check_subject = true;
931 
932  /* mark descendants as needing subject_changed checked */
933  for (tmp = (thread->child ? thread->child : thread); tmp != thread;)
934  {
935  while (!tmp->message)
936  tmp = tmp->child;
937  tmp->check_subject = true;
938  while (!tmp->next && (tmp != thread))
939  tmp = tmp->parent;
940  if (tmp != thread)
941  tmp = tmp->next;
942  }
943 
944  if (thread->parent)
945  {
946  /* remove threading info above it based on its children, which we'll
947  * recalculate based on its headers. make sure not to leave
948  * dangling missing messages. note that we haven't kept track
949  * of what info came from its children and what from its siblings'
950  * children, so we just remove the stuff that's definitely from it */
951  do
952  {
953  tmp = thread->parent;
954  unlink_message(&tmp->child, thread);
955  thread->parent = NULL;
956  thread->sort_key = NULL;
957  thread->fake_thread = false;
958  thread = tmp;
959  } while (thread != &top && !thread->child && !thread->message);
960  }
961  }
962  else
963  {
964  tnew = (C_DuplicateThreads ? thread : NULL);
965 
966  thread = mutt_mem_calloc(1, sizeof(struct MuttThread));
967  thread->message = e;
968  thread->check_subject = true;
969  e->thread = thread;
970  mutt_hash_insert(tctx->hash, e->env->message_id ? e->env->message_id : "", thread);
971 
972  if (tnew)
973  {
974  if (tnew->duplicate_thread)
975  tnew = tnew->parent;
976 
977  thread = e->thread;
978 
979  insert_message(&tnew->child, tnew, thread);
980  thread->duplicate_thread = true;
981  thread->message->threaded = true;
982  }
983  }
984  }
985  else
986  {
987  /* unlink pseudo-threads because they might be children of newly
988  * arrived messages */
989  thread = e->thread;
990  for (tnew = thread->child; tnew;)
991  {
992  tmp = tnew->next;
993  if (tnew->fake_thread)
994  {
995  unlink_message(&thread->child, tnew);
996  insert_message(&top.child, &top, tnew);
997  tnew->fake_thread = false;
998  }
999  tnew = tmp;
1000  }
1001  }
1002  }
1003 
1004  /* thread by references */
1005  for (i = 0; i < m->msg_count; i++)
1006  {
1007  e = m->emails[i];
1008  if (!e)
1009  break;
1010 
1011  if (e->threaded)
1012  continue;
1013  e->threaded = true;
1014 
1015  thread = e->thread;
1016  if (!thread)
1017  continue;
1018  using_refs = 0;
1019 
1020  while (true)
1021  {
1022  if (using_refs == 0)
1023  {
1024  /* look at the beginning of in-reply-to: */
1025  ref = STAILQ_FIRST(&e->env->in_reply_to);
1026  if (ref)
1027  using_refs = 1;
1028  else
1029  {
1030  ref = STAILQ_FIRST(&e->env->references);
1031  using_refs = 2;
1032  }
1033  }
1034  else if (using_refs == 1)
1035  {
1036  /* if there's no references header, use all the in-reply-to:
1037  * data that we have. otherwise, use the first reference
1038  * if it's different than the first in-reply-to, otherwise use
1039  * the second reference (since at least eudora puts the most
1040  * recent reference in in-reply-to and the rest in references) */
1041  if (STAILQ_EMPTY(&e->env->references))
1042  ref = STAILQ_NEXT(ref, entries);
1043  else
1044  {
1045  if (!mutt_str_equal(ref->data, STAILQ_FIRST(&e->env->references)->data))
1046  ref = STAILQ_FIRST(&e->env->references);
1047  else
1048  ref = STAILQ_NEXT(STAILQ_FIRST(&e->env->references), entries);
1049 
1050  using_refs = 2;
1051  }
1052  }
1053  else
1054  ref = STAILQ_NEXT(ref, entries); /* go on with references */
1055 
1056  if (!ref)
1057  break;
1058 
1059  tnew = mutt_hash_find(tctx->hash, ref->data);
1060  if (tnew)
1061  {
1062  if (tnew->duplicate_thread)
1063  tnew = tnew->parent;
1064  if (is_descendant(tnew, thread)) /* no loops! */
1065  continue;
1066  }
1067  else
1068  {
1069  tnew = mutt_mem_calloc(1, sizeof(struct MuttThread));
1070  mutt_hash_insert(tctx->hash, ref->data, tnew);
1071  }
1072 
1073  if (thread->parent)
1074  unlink_message(&top.child, thread);
1075  insert_message(&tnew->child, tnew, thread);
1076  thread = tnew;
1077  if (thread->message || (thread->parent && (thread->parent != &top)))
1078  break;
1079  }
1080 
1081  if (!thread->parent)
1082  insert_message(&top.child, &top, thread);
1083  }
1084 
1085  /* detach everything from the temporary top node */
1086  for (thread = top.child; thread; thread = thread->next)
1087  {
1088  thread->parent = NULL;
1089  }
1090  tctx->tree = top.child;
1091 
1092  check_subjects(tctx->mailbox, init);
1093 
1094  if (!C_StrictThreads)
1095  pseudo_threads(tctx);
1096 
1097  if (tctx->tree)
1098  {
1099  mutt_sort_subthreads(tctx, init);
1100 
1101  /* restore the oldsort order. */
1102  C_Sort = oldsort;
1103 
1104  /* Put the list into an array. */
1105  linearize_tree(tctx);
1106 
1107  /* Draw the thread tree. */
1108  mutt_draw_tree(tctx);
1109  }
1110 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_CollapseFlagged

bool C_CollapseFlagged

Config: Prevent the collapse of threads with flagged emails.

Definition at line 45 of file mutt_thread.c.

◆ C_CollapseUnread

bool C_CollapseUnread

Config: Prevent the collapse of threads with unread emails.

Definition at line 46 of file mutt_thread.c.

◆ C_DuplicateThreads

bool C_DuplicateThreads

Config: Highlight messages with duplicated message IDs.

Definition at line 47 of file mutt_thread.c.

◆ C_HideLimited

bool C_HideLimited

Config: Don't indicate hidden messages, in the thread tree.

Definition at line 48 of file mutt_thread.c.

◆ C_HideMissing

bool C_HideMissing

Config: Don't indicate missing messages, in the thread tree.

Definition at line 49 of file mutt_thread.c.

◆ C_HideThreadSubject

bool C_HideThreadSubject

Config: Hide subjects that are similar to that of the parent message.

Definition at line 50 of file mutt_thread.c.

◆ C_HideTopLimited

bool C_HideTopLimited

Config: Don't indicate hidden top message, in the thread tree.

Definition at line 51 of file mutt_thread.c.

◆ C_HideTopMissing

bool C_HideTopMissing

Config: Don't indicate missing top message, in the thread tree.

Definition at line 52 of file mutt_thread.c.

◆ C_NarrowTree

bool C_NarrowTree

Config: Draw a narrower thread tree in the index.

Definition at line 53 of file mutt_thread.c.

◆ C_SortRe

bool C_SortRe

Config: Sort method for the sidebar.

Definition at line 54 of file mutt_thread.c.

◆ C_StrictThreads

bool C_StrictThreads

Config: Thread messages using 'In-Reply-To' and 'References' headers.

Definition at line 55 of file mutt_thread.c.

◆ C_ThreadReceived

bool C_ThreadReceived

Config: Sort threaded messages by their received date.

Definition at line 56 of file mutt_thread.c.

pseudo_threads
static void pseudo_threads(struct ThreadsContext *tctx)
Thread messages by subject.
Definition: mutt_thread.c:566
Body::hdr_offset
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
link_threads
static bool link_threads(struct Email *parent, struct Email *child, struct Mailbox *m)
Forcibly link messages together.
Definition: mutt_thread.c:1542
Email::msgno
int msgno
Number displayed to the user.
Definition: email.h:87
MUTT_THREAD_FLAGGED
#define MUTT_THREAD_FLAGGED
Count flagged emails in a thread.
Definition: mutt_thread.h:80
ThreadsContext
The "current" threading state.
Definition: mutt_thread.c:61
mutt_hash_new
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:251
insert_message
void insert_message(struct MuttThread **add, struct MuttThread *parent, struct MuttThread *cur)
Insert a message into a thread.
Definition: thread.c:94
mutt_mem_calloc
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
_
#define _(a)
Definition: message.h:28
Mailbox
A mailbox.
Definition: mailbox.h:81
SORT_THREADS
@ SORT_THREADS
Sort by email threads.
Definition: sort2.h:51
Envelope::in_reply_to
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:82
Envelope::message_id
char * message_id
Message ID.
Definition: envelope.h:69
Mailbox::v2r
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:101
MUTT_THREAD_NEXT_UNREAD
#define MUTT_THREAD_NEXT_UNREAD
Find the next unread email.
Definition: mutt_thread.h:79
Mailbox::emails
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
ListNode
A List node for strings.
Definition: list.h:34
Email::thread
struct MuttThread * thread
Thread of Emails.
Definition: email.h:95
thread_hash_destructor
void thread_hash_destructor(int type, void *obj, intptr_t data)
Hash Destructor callback - Implements hash_hdata_free_t.
Definition: thread.c:111
mutt_thread_contains_flagged
#define mutt_thread_contains_flagged(e)
Definition: mutt_thread.h:92
Body::offset
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
mutt_hash_set_destructor
void mutt_hash_set_destructor(struct HashTable *table, hash_hdata_free_t fn, intptr_t fn_data)
Set the destructor for a Hash Table.
Definition: hash.c:293
ThreadsContext::hash
struct HashTable * hash
Hash table for threads.
Definition: mutt_thread.c:65
MUTT_TREE_LLCORNER
@ MUTT_TREE_LLCORNER
Lower left corner.
Definition: mutt_thread.h:56
Email::num_hidden
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
Definition: email.h:75
EmailNode::email
struct Email * email
Email in the list.
Definition: email.h:127
is_descendant
bool is_descendant(struct MuttThread *a, struct MuttThread *b)
Is one thread a descendant of another.
Definition: thread.c:44
C_NarrowTree
bool C_NarrowTree
Config: Draw a narrower thread tree in the index.
Definition: mutt_thread.c:53
FREE
#define FREE(x)
Definition: memory.h:40
EmailNode
List of Emails.
Definition: email.h:125
SORT_REVERSE
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:81
STAILQ_FIRST
#define STAILQ_FIRST(head)
Definition: queue.h:347
mutt_sort_subthreads
void mutt_sort_subthreads(struct ThreadsContext *tctx, bool init)
Sort the children of a thread.
Definition: mutt_thread.c:687
mutt_draw_tree
void mutt_draw_tree(struct ThreadsContext *tctx)
Draw a tree of threaded emails.
Definition: mutt_thread.c:320
SORT_MASK
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:80
C_CollapseFlagged
bool C_CollapseFlagged
Config: Prevent the collapse of threads with flagged emails.
Definition: mutt_thread.c:45
find_virtual
struct Email * find_virtual(struct MuttThread *cur, int reverse)
Find an email with a Virtual message number.
Definition: thread.c:122
STAILQ_EMPTY
#define STAILQ_EMPTY(head)
Definition: queue.h:345
SORT_LAST
#define SORT_LAST
Sort thread by last-X, e.g. received date.
Definition: sort2.h:82
check_subjects
static void check_subjects(struct Mailbox *m, bool init)
Find out which emails' subjects differ from their parent's.
Definition: mutt_thread.c:829
MUTT_TREE_STAR
@ MUTT_TREE_STAR
Star character (for threads)
Definition: mutt_thread.h:63
STAILQ_FOREACH
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
Mailbox::vcount
int vcount
The number of virtual messages.
Definition: mailbox.h:102
MIT_NUM_MESSAGES
@ MIT_NUM_MESSAGES
Definition: mutt_thread.h:84
mutt_thread_can_collapse
bool mutt_thread_can_collapse(struct Email *e)
Check whether a thread can be collapsed.
Definition: mutt_thread.c:1632
Email::tree
char * tree
Character string to print thread tree.
Definition: email.h:94
MuttThread::prev
struct MuttThread * prev
Previous sibling Thread.
Definition: thread.h:48
mutt_hash_find
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:354
MuttThread::parent
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
mutt_str_equal
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
MuttThread::child
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
MUTT_HASH_ALLOW_DUPS
#define MUTT_HASH_ALLOW_DUPS
allow duplicate keys to be inserted
Definition: hash.h:100
MuttThread::next_subtree_visible
bool next_subtree_visible
Is the next Thread subtree visible?
Definition: thread.h:43
Email::old
bool old
Email is seen, but unread.
Definition: email.h:50
MIT_POSITION
@ MIT_POSITION
Definition: mutt_thread.h:85
MUTT_TREE_MISSING
@ MUTT_TREE_MISSING
Question mark.
Definition: mutt_thread.h:68
MUTT_TREE_RARROW
@ MUTT_TREE_RARROW
Right arrow.
Definition: mutt_thread.h:62
MUTT_TREE_HLINE
@ MUTT_TREE_HLINE
Horizontal line.
Definition: mutt_thread.h:59
Email::visible
bool visible
Is this message part of the view?
Definition: email.h:74
calculate_visibility
static void calculate_visibility(struct MuttThread *tree, int *max_depth)
Are tree nodes visible.
Definition: mutt_thread.c:179
MuttThread::fake_thread
bool fake_thread
Emails grouped by Subject.
Definition: thread.h:36
Body::length
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
MUTT_TREE_BTEE
@ MUTT_TREE_BTEE
Bottom T-piece.
Definition: mutt_thread.h:67
MuttThread::subtree_visible
unsigned int subtree_visible
Is this Thread subtree visible?
Definition: thread.h:42
MuttThread::message
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
Mailbox::msg_count
int msg_count
Total number of messages.
Definition: mailbox.h:91
mutt_hash_insert
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
Definition: hash.c:327
MuttThread::duplicate_thread
bool duplicate_thread
Duplicated Email in Thread.
Definition: thread.h:37
MUTT_THREAD_UNREAD
#define MUTT_THREAD_UNREAD
Count unread emails in a thread.
Definition: mutt_thread.h:78
MUTT_TREE_ULCORNER
@ MUTT_TREE_ULCORNER
Upper left corner.
Definition: mutt_thread.h:57
C_HideMissing
bool C_HideMissing
Config: Don't indicate missing messages, in the thread tree.
Definition: mutt_thread.c:49
mutt_collapse_thread
#define mutt_collapse_thread(e)
Definition: mutt_thread.h:89
mutt_mem_realloc
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
MUTT_TREE_MAX
@ MUTT_TREE_MAX
Definition: mutt_thread.h:69
Email::env
struct Envelope * env
Envelope information.
Definition: email.h:90
MuttThread
An Email conversation.
Definition: thread.h:34
ThreadsContext::tree
struct MuttThread * tree
Top of thread tree.
Definition: mutt_thread.c:64
ThreadsContext::mailbox
struct Mailbox * mailbox
Current mailbox.
Definition: mutt_thread.c:63
is_visible
static bool is_visible(struct Email *e)
Is the message visible?
Definition: mutt_thread.c:73
Email::flagged
bool flagged
Marked important?
Definition: email.h:43
Email::collapsed
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:73
mutt_uncollapse_thread
#define mutt_uncollapse_thread(e)
Definition: mutt_thread.h:90
MUTT_THREAD_UNCOLLAPSE
#define MUTT_THREAD_UNCOLLAPSE
Uncollapse an email thread.
Definition: mutt_thread.h:77
MuttThread::sort_key
struct Email * sort_key
Email that this Thread is sorted against.
Definition: thread.h:50
MUTT_HASH_NO_FLAGS
#define MUTT_HASH_NO_FLAGS
No flags are set.
Definition: hash.h:97
MUTT_TREE_EQUALS
@ MUTT_TREE_EQUALS
Equals (for threads)
Definition: mutt_thread.h:65
MUTT_TREE_TTEE
@ MUTT_TREE_TTEE
Top T-piece.
Definition: mutt_thread.h:66
MUTT_SPECIAL_INDEX
@ MUTT_SPECIAL_INDEX
Colour indicator.
Definition: mutt_thread.h:71
C_Sort
WHERE short C_Sort
Config: Sort method for the index.
Definition: sort.h:60
linearize_tree
static void linearize_tree(struct ThreadsContext *tctx)
Flatten an email thread.
Definition: mutt_thread.c:131
mutt_mem_malloc
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
MuttThread::visible
bool visible
Is this Thread visible?
Definition: thread.h:40
C_DuplicateThreads
bool C_DuplicateThreads
Config: Highlight messages with duplicated message IDs.
Definition: mutt_thread.c:47
MUTT_TREE_LTEE
@ MUTT_TREE_LTEE
Left T-piece.
Definition: mutt_thread.h:58
MuttThread::sort_children
bool sort_children
Sort the children.
Definition: thread.h:38
MUTT_TREE_HIDDEN
@ MUTT_TREE_HIDDEN
Ampersand character (for threads)
Definition: mutt_thread.h:64
MUTT_TREE_VLINE
@ MUTT_TREE_VLINE
Vertical line.
Definition: mutt_thread.h:60
MuttThread::check_subject
bool check_subject
Should the Subject be checked?
Definition: thread.h:39
Email::vnum
int vnum
Virtual message number.
Definition: email.h:88
ListNode::data
char * data
String.
Definition: list.h:36
unlink_message
void unlink_message(struct MuttThread **old, struct MuttThread *cur)
Break the message out of the thread.
Definition: thread.c:64
C_CollapseUnread
bool C_CollapseUnread
Config: Prevent the collapse of threads with unread emails.
Definition: mutt_thread.c:46
MuttThread::next
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
STAILQ_NEXT
#define STAILQ_NEXT(elm, field)
Definition: queue.h:397
C_HideLimited
bool C_HideLimited
Config: Don't indicate hidden messages, in the thread tree.
Definition: mutt_thread.c:48
Email
The envelope/body of an email.
Definition: email.h:37
Email::threaded
bool threaded
Used for threading.
Definition: email.h:56
HashTable
A Hash Table.
Definition: hash.h:84
C_SortAux
WHERE short C_SortAux
Config: Secondary sort method for the index.
Definition: sort.h:61
mx_msg_padding_size
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
Definition: mx.c:1554
compare_threads
static int compare_threads(const void *a, const void *b)
Sorting function for email threads.
Definition: mutt_thread.c:664
Envelope::references
struct ListHead references
message references (in reverse order)
Definition: envelope.h:81
MUTT_THREAD_COLLAPSE
#define MUTT_THREAD_COLLAPSE
Collapse an email thread.
Definition: mutt_thread.h:76
Email::read
bool read
Email is read.
Definition: email.h:51
mutt_hash_free
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
TreeChar
TreeChar
Tree characters for menus.
Definition: mutt_thread.h:54
MuttThread::deep
bool deep
Is the Thread deeply nested?
Definition: thread.h:41
Email::pair
int pair
Color-pair to use when displaying in the index.
Definition: email.h:80
Email::body
struct Body * body
List of MIME parts.
Definition: email.h:91
mutt_thread_contains_unread
#define mutt_thread_contains_unread(e)
Definition: mutt_thread.h:91
MUTT_TREE_SPACE
@ MUTT_TREE_SPACE
Blank space.
Definition: mutt_thread.h:61
mutt_error
#define mutt_error(...)
Definition: logging.h:84
C_StrictThreads
bool C_StrictThreads
Config: Thread messages using 'In-Reply-To' and 'References' headers.
Definition: mutt_thread.c:55
mutt_str_copy
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716