112 buf_printf(err,
_(
"Cannot use 'last-' prefix with 'threads' for %s"), cdef->
name);
140 if (!c_hide_thread_subject)
149 for (tmp = tree->
prev; tmp; tmp = tmp->
prev)
195 while (!
tree->message)
198 *array =
tree->message;
199 array += reverse ? -1 : 1;
244 int hide_top_missing = c_hide_top_missing && !c_hide_missing;
247 int hide_top_limited = c_hide_top_limited && !c_hide_limited;
257 if (depth > *max_depth)
269 for (tmp = tree; tmp; tmp = tmp->
parent)
286 tree->
deep = !c_hide_limited;
292 tree->
deep = !c_hide_missing;
309 while (tree && !tree->
prev)
321 if (hide_top_limited || hide_top_missing)
327 ((tree->
message && hide_top_limited) || (!tree->
message && hide_top_missing)))
341 while (tree && !tree->
next)
395 char *pfx = NULL, *mypfx = NULL, *arrow = NULL, *myarrow = NULL, *new_tree = NULL;
400 int depth = 0, start_depth = 0, max_depth = 0, width = c_narrow_tree ? 1 : 2;
416 myarrow = arrow + (depth - start_depth - ((start_depth != 0) ? 0 : 1)) * width;
417 if (start_depth == depth)
433 myarrow[width + 1] = 0;
437 strncpy(new_tree, pfx, (
size_t) width * (start_depth - 1));
439 (1 + depth - start_depth) * width + 2);
443 mutt_str_copy(new_tree, arrow, ((
size_t) depth * width) + 2);
448 if (tree->
child && (depth != 0))
450 mypfx = pfx + (depth - 1) * width;
480 if (tree == nextdisp)
487 if (start_depth == depth)
494 if (tree == nextdisp)
506 }
while (!tree->
deep);
540 if ((*dateptr == 0) || (thisdate < *dateptr))
560 while (!cur->
next && (cur != start))
597 tmp = ((
struct Email *) he->
data)->thread;
603 (!last || (c_thread_received ?
657 struct MuttThread *tmp = NULL, *cur = NULL, *
parent = NULL, *curchild = NULL,
670 cur->fake_thread =
true;
690 for (curchild = tmp->
child; curchild;)
692 nextchild = curchild->next;
693 if (curchild->fake_thread)
698 curchild = nextchild;
702 while (!tmp->
next && (tmp != cur))
721 if (!tctx || !tctx->
tree)
783 struct MuttThread **array = NULL, *top = NULL, *tmp = NULL;
784 struct Email *sort_aux_key = NULL, *oldsort_aux_key = NULL;
785 struct Email *oldsort_thread_key = NULL;
787 bool sort_top =
false;
847 while (!thread->
next)
853 for (i = 0; thread; i++, thread = thread->
prev)
869 array[i - 1]->prev = NULL;
872 thread->parent->child = array[i - 1];
878 array[i - 1]->prev = array[i];
879 array[i]->next = array[i - 1];
919 if ((c_sort_aux & ~
SORT_REVERSE) == (c_sort & ~SORT_REVERSE))
939 for (tmp = thread->
child; tmp; tmp = tmp->
next)
971 thread = thread->
next;
1040 struct Email *e = NULL;
1041 int i, using_refs = 0;
1042 struct MuttThread *thread = NULL, *tnew = NULL, *tmp = NULL;
1064 for (thread = tctx->
tree; thread; thread = thread->
next)
1083 for (tnew = thread->
child; tnew;)
1086 if (tnew->fake_thread)
1090 tnew->fake_thread =
false;
1102 if (thread && !thread->
message)
1110 for (tmp = (thread->
child ? thread->
child : thread); tmp != thread;)
1112 while (!tmp->message)
1114 tmp->check_subject =
true;
1115 while (!tmp->next && (tmp != thread))
1137 }
while (thread != &top && !thread->
child && !thread->
message);
1142 tnew = (c_duplicate_threads ? thread : NULL);
1152 if (tnew->duplicate_thread)
1153 tnew = tnew->parent;
1183 if (using_refs == 0)
1197 else if (using_refs == 1)
1229 if (tnew->duplicate_thread)
1230 tnew = tnew->parent;
1253 for (thread = top.
child; thread; thread = thread->
next)
1262 if (!c_strict_threads)
1294 struct Email *e_tmp = NULL;
1361 struct Email *e_parent = NULL;
1392 mutt_error(
_(
"Root message is not visible in this limited view"));
1394 mutt_error(
_(
"Parent message is not visible in this limited view"));
1397 return e_parent->
vnum;
1441 struct MuttThread *thread = NULL, *top = NULL;
1442 struct Email *e_root = NULL;
1445 int num_hidden = 0, new_mail = 0, old_mail = 0;
1447 int min_unread_msgno = INT_MAX, min_unread = e_cur->
vnum;
1460 final = e_cur->
vnum;
1468 minmsgno = e_cur->
msgno;
1476 if (e_cur->
msgno < min_unread_msgno)
1478 min_unread = e_cur->
vnum;
1479 min_unread_msgno = e_cur->
msgno;
1493 if (e_cur->
vnum != -1)
1497 final = e_root->
vnum;
1510 return (old_mail && new_mail) ? new_mail : (old_mail ? old_mail : new_mail);
1527 if (!e_root && e_cur->
visible)
1531 final = e_root->
vnum;
1537 minmsgno = e_cur->
msgno;
1538 final = e_cur->
vnum;
1543 if (e_cur != e_root)
1559 if (e_cur->
msgno < min_unread_msgno)
1561 min_unread = e_cur->
vnum;
1562 min_unread_msgno = e_cur->
msgno;
1642 return (old_mail && new_mail) ? new_mail : (old_mail ? old_mail : new_mail);
1671 while (threads[0]->
parent)
1672 threads[0] = threads[0]->
parent;
1676 for (
int i = 0; i < (((mit ==
MIT_POSITION) || !threads[1]) ? 1 : 2); i++)
1679 threads[i] = threads[i]->
child;
1729 if (child == parent)
1750 if (!parent || !children || !m)
1755 struct Email **ep = NULL;
1758 struct Email *e = *ep;
1773 while ((thread = top))
1776 thread = thread->
child;
1794 while ((thread = top))
1797 thread = thread->
child;
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Convenience wrapper for the config headers.
#define CSR_ERR_INVALID
Value hasn't been set.
#define CSR_SUCCESS
Action completed successfully.
#define SORT_MASK
Mask for the sort id.
#define SORT_LAST
Sort thread by last-X, e.g. received date.
#define SORT_REVERSE
Reverse the order of the sort.
Convenience wrapper for the core headers.
MailboxType
Supported mailbox formats.
Structs that make up an email.
EmailSortType
Methods for sorting Emails.
@ EMAIL_SORT_THREADS
Sort by email threads.
@ EMAIL_SORT_UNSORTED
Sort by the order the messages appear in the mailbox.
#define MUTT_ENV_CHANGED_IRT
In-Reply-To changed to link/break threads.
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
bool OptSortSubthreads
(pseudo) used when $sort_aux changes
int sort_validator(const struct ConfigSet *cs, const struct ConfigDef *cdef, intptr_t value, struct Buffer *err)
Validate the "sort" config variable - Implements ConfigDef::validator() -.
static void thread_hash_destructor(int type, void *obj, intptr_t data)
Free our hash table data - Implements hash_hdata_free_t -.
static int compare_threads(const void *a, const void *b, void *sdata)
Helper to sort email threads - Implements sort_t -.
int mutt_compare_emails(const struct Email *a, const struct Email *b, enum MailboxType type, short sort, short sort_aux)
Compare two emails using up to two sort methods -.
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
struct HashElem * mutt_hash_find_bucket(const struct HashTable *table, const char *strkey)
Find the HashElem in a Hash Table element using a key.
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
void mutt_hash_set_destructor(struct HashTable *table, hash_hdata_free_t fn, intptr_t fn_data)
Set the destructor for a Hash Table.
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
#define MUTT_HASH_NO_FLAGS
No flags are set.
#define MUTT_HASH_ALLOW_DUPS
allow duplicate keys to be inserted
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
void mutt_list_clear(struct ListHead *h)
Free a list, but NOT its strings.
struct ListNode * mutt_list_insert_after(struct ListHead *h, struct ListNode *n, char *s)
Insert a string after a given ListNode.
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
#define MUTT_MEM_CALLOC(n, type)
#define MUTT_MEM_REALLOC(pptr, n, type)
#define MUTT_MEM_MALLOC(n, type)
Convenience wrapper for the library headers.
int mutt_str_cmp(const char *a, const char *b)
Compare two strings, safely.
char * mutt_str_dup(const char *str)
Copy a string, safely.
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Many unsorted constants and some structs.
@ MUTT_TAG
Tagged messages.
static void linearize_tree(struct ThreadsContext *tctx)
Flatten an email thread.
static void calculate_visibility(struct MuttThread *tree, int *max_depth)
Are tree nodes visible.
void mutt_clear_threads(struct ThreadsContext *tctx)
Clear the threading of message in a mailbox.
int mutt_traverse_thread(struct Email *e_cur, MuttThreadFlags flag)
Recurse through an email thread, matching messages.
static void mutt_sort_subthreads(struct ThreadsContext *tctx, bool init)
Sort the children of a thread.
void mutt_thread_collapse(struct ThreadsContext *tctx, bool collapse)
Toggle collapse.
struct ThreadsContext * mutt_thread_ctx_init(struct MailboxView *mv)
Initialize a threading context.
void mutt_thread_collapse_collapsed(struct ThreadsContext *tctx)
Re-collapse threads marked as collapsed.
static const struct Mapping UseThreadsMethods[]
Choices for '$use_threads' for the index.
bool mutt_link_threads(struct Email *parent, struct EmailArray *children, struct Mailbox *m)
Forcibly link threads together.
void mutt_draw_tree(struct ThreadsContext *tctx)
Draw a tree of threaded emails.
int mutt_messages_in_thread(struct Mailbox *m, struct Email *e, enum MessageInThread mit)
Count the messages in a thread.
static void make_subject_list(struct ListHead *subjects, struct MuttThread *cur, time_t *dateptr)
Create a sorted list of all subjects in a thread.
void mutt_thread_ctx_free(struct ThreadsContext **ptr)
Finalize a threading context.
const char * get_use_threads_str(enum UseThreads value)
Convert UseThreads enum to string.
enum UseThreads mutt_thread_style(void)
Which threading style is active?
static void pseudo_threads(struct ThreadsContext *tctx)
Thread messages by subject.
static struct HashTable * make_subj_hash(struct Mailbox *m)
Create a Hash Table for the email subjects.
static void check_subjects(struct MailboxView *mv, bool init)
Find out which emails' subjects differ from their parent's.
void mutt_sort_threads(struct ThreadsContext *tctx, bool init)
Sort email threads.
static bool need_display_subject(struct Email *e)
Determines whether to display a message's subject.
const struct EnumDef UseThreadsTypeDef
Data for the $use_threads enumeration.
off_t mutt_set_vnum(struct Mailbox *m)
Set the virtual index number of all the messages in a mailbox.
int mutt_aside_thread(struct Email *e, bool forwards, bool subthreads)
Find the next/previous (sub)thread.
bool mutt_thread_can_collapse(struct Email *e)
Check whether a thread can be collapsed.
static struct MuttThread * find_subject(struct Mailbox *m, struct MuttThread *cur)
Find the best possible match for a parent based on subject.
int mutt_parent_message(struct Email *e, bool find_root)
Find the parent of a message.
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
static bool link_threads(struct Email *parent, struct Email *child, struct Mailbox *m)
Forcibly link messages together.
static bool is_visible(struct Email *e)
Is the message visible?
Create/manipulate threading in emails.
#define MUTT_THREAD_UNREAD
Count unread emails in a thread.
uint8_t MuttThreadFlags
Flags, e.g. MUTT_THREAD_COLLAPSE.
#define mutt_thread_contains_flagged(e)
UseThreads
Which threading style is active, $use_threads.
@ UT_UNSET
Not yet set by user, stick to legacy semantics.
@ UT_THREADS
Normal threading (root above subthreads)
@ UT_REVERSE
Reverse threading (subthreads above root)
#define mutt_using_threads()
#define mutt_uncollapse_thread(e)
MessageInThread
Flags for mutt_messages_in_thread()
@ MIT_POSITION
Our position in the thread.
#define MUTT_THREAD_UNCOLLAPSE
Uncollapse an email thread.
#define MUTT_THREAD_NEXT_UNREAD
Find the next unread email.
#define mutt_thread_contains_unread(e)
#define MUTT_THREAD_COLLAPSE
Collapse an email thread.
#define mutt_collapse_thread(e)
#define MUTT_THREAD_FLAGGED
Count flagged emails in a thread.
TreeChar
Tree characters for menus.
@ MUTT_TREE_LLCORNER
Lower left corner.
@ MUTT_TREE_RARROW
Right arrow.
@ MUTT_TREE_ULCORNER
Upper left corner.
@ MUTT_TREE_EQUALS
Equals (for threads)
@ MUTT_TREE_HIDDEN
Ampersand character (for threads)
@ MUTT_TREE_STAR
Star character (for threads)
@ MUTT_TREE_LTEE
Left T-piece.
@ MUTT_TREE_VLINE
Vertical line.
@ MUTT_TREE_MISSING
Question mark.
@ MUTT_TREE_TTEE
Top T-piece.
@ MUTT_TREE_HLINE
Horizontal line.
@ MUTT_TREE_SPACE
Blank space.
@ MUTT_TREE_BTEE
Bottom T-piece.
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size()
enum MailboxType mx_type(struct Mailbox *m)
Return the type of the Mailbox.
Prototypes for many functions.
void mutt_qsort_r(void *base, size_t nmemb, size_t size, sort_t compar, void *sdata)
Sort an array, where the comparator has access to opaque data rather than requiring global variables.
#define STAILQ_HEAD_INITIALIZER(head)
#define STAILQ_FIRST(head)
#define STAILQ_FOREACH(var, head, field)
#define STAILQ_EMPTY(head)
#define STAILQ_NEXT(elm, field)
LOFF_T offset
offset where the actual data begins
LOFF_T length
length (in bytes) of attachment
long hdr_offset
Offset in stream where the headers begin.
String manipulation buffer.
const char * name
User-visible name.
Container for lots of config items.
The envelope/body of an email.
bool display_subject
Used for threading.
bool visible
Is this message part of the view?
struct Envelope * env
Envelope information.
bool collapsed
Is this message part of a collapsed thread?
struct Body * body
List of MIME parts.
bool subject_changed
Used for threading.
char * tree
Character string to print thread tree.
bool old
Email is seen, but unread.
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
bool changed
Email has been edited.
bool flagged
Marked important?
bool threaded
Used for threading.
const struct AttrColor * attr_color
Color-pair to use when displaying in the index.
time_t date_sent
Time when the message was sent (UTC)
int vnum
Virtual message number.
int msgno
Number displayed to the user.
time_t received
Time when the message was placed in the mailbox.
struct MuttThread * thread
Thread of Emails.
char *const subject
Email's subject.
unsigned char changed
Changed fields, e.g. MUTT_ENV_CHANGED_SUBJECT.
char * message_id
Message ID.
struct ListHead references
message references (in reverse order)
struct ListHead in_reply_to
in-reply-to header content
char *const real_subj
Offset of the real subject.
The item stored in a Hash Table.
struct HashElem * next
Linked List.
void * data
User-supplied data.
struct Mailbox * mailbox
Current Mailbox.
int vcount
The number of virtual messages.
int * v2r
Mapping from virtual to real msgno.
int msg_count
Total number of messages.
struct HashTable * subj_hash
Hash Table: "subject" -> Email.
struct Email ** emails
Array of Emails.
Mapping between user-readable string and a constant.
bool sort_children
Sort the children.
bool visible
Is this Thread visible?
struct MuttThread * parent
Parent of this Thread.
struct Email * sort_aux_key
Email that controls how subthread siblings sort.
struct MuttThread * prev
Previous sibling Thread.
bool fake_thread
Emails grouped by Subject.
struct MuttThread * child
Child of this Thread.
struct Email * message
Email this Thread refers to.
bool deep
Is the Thread deeply nested?
unsigned int subtree_visible
Is this Thread subtree visible?
bool duplicate_thread
Duplicated Email in Thread.
bool next_subtree_visible
Is the next Thread subtree visible?
bool check_subject
Should the Subject be checked?
struct Email * sort_thread_key
Email that controls how top thread sorts.
struct MuttThread * next
Next sibling Thread.
Container for Accounts, Notifications.
struct ConfigSubset * sub
Inherited config items.
The "current" threading state.
struct MailboxView * mailbox_view
Current mailbox.
struct MuttThread * tree
Top of thread tree.
enum EmailSortType c_sort
Last sort method.
struct HashTable * hash
Hash Table: "message-id" -> MuttThread.
enum EmailSortType c_sort_aux
Last sort_aux method.
void unlink_message(struct MuttThread **old, struct MuttThread *cur)
Break the message out of the thread.
bool is_descendant(const struct MuttThread *a, const struct MuttThread *b)
Is one thread a descendant of another.
void insert_message(struct MuttThread **add, struct MuttThread *parent, struct MuttThread *cur)
Insert a message into a thread.
void mutt_break_thread(struct Email *e)
Break the email Thread.
struct Email * find_virtual(struct MuttThread *cur, bool reverse)
Find an email with a Virtual message number.