109 buf_printf(err,
_(
"Cannot use 'last-' prefix with 'threads' for %s"), cdef->
name);
144 if (!c_hide_thread_subject)
153 for (tmp = tree->
prev; tmp; tmp = tmp->
prev)
199 while (!
tree->message)
202 *array =
tree->message;
203 array += reverse ? -1 : 1;
248 int hide_top_missing = c_hide_top_missing && !c_hide_missing;
251 int hide_top_limited = c_hide_top_limited && !c_hide_limited;
262 if (depth > *max_depth)
271 mutt_debug(
LL_DEBUG1,
"thread<->message mismatch: Email index=%d, thread=%p, message->thread=%p\n",
280 for (tmp = tree; tmp; tmp = tmp->
parent)
297 tree->
deep = !c_hide_limited;
303 tree->
deep = !c_hide_missing;
323 while (tree && !tree->
prev)
335 if (hide_top_limited || hide_top_missing)
341 ((tree->
message && hide_top_limited) || (!tree->
message && hide_top_missing)))
355 while (tree && !tree->
next)
423 mutt_debug(
LL_DEBUG1,
"repairing thread<->message: Email index=%d, expected=%p, actual=%p\n",
467 if (!tctx || !tctx->
tree)
470 char *pfx = NULL, *mypfx = NULL, *arrow = NULL, *myarrow = NULL, *new_tree = NULL;
475 int depth = 0, start_depth = 0, max_depth = 0, width = c_narrow_tree ? 1 : 2;
494 myarrow = arrow + (depth - start_depth - ((start_depth != 0) ? 0 : 1)) * width;
495 if (start_depth == depth)
511 myarrow[width + 1] = 0;
515 strncpy(new_tree, pfx, (
size_t) width * (start_depth - 1));
517 (1 + depth - start_depth) * width + 2);
521 mutt_str_copy(new_tree, arrow, ((
size_t) depth * width) + 2);
526 if (tree->
child && (depth != 0))
528 mypfx = pfx + (depth - 1) * width;
558 if (tree == nextdisp)
565 if (start_depth == depth)
572 if (tree == nextdisp)
584 }
while (!tree->
deep);
618 if ((*dateptr == 0) || (thisdate < *dateptr))
638 while (!cur->
next && (cur != start))
681 (!last || (c_thread_received ?
735 struct MuttThread *tmp = NULL, *cur = NULL, *
parent = NULL, *curchild = NULL,
748 cur->fake_thread =
true;
768 for (curchild = tmp->
child; curchild;)
770 nextchild = curchild->next;
771 if (curchild->fake_thread)
776 curchild = nextchild;
780 while (!tmp->
next && (tmp != cur))
799 if (!tctx || !tctx->
tree)
861 struct MuttThread **array = NULL, *top = NULL, *tmp = NULL;
862 struct Email *sort_aux_key = NULL, *oldsort_aux_key = NULL;
863 struct Email *oldsort_thread_key = NULL;
865 bool sort_top =
false;
925 while (!thread->
next)
931 for (i = 0; thread; i++, thread = thread->
prev)
947 array[i - 1]->prev = NULL;
950 thread->parent->child = array[i - 1];
956 array[i - 1]->prev = array[i];
957 array[i]->next = array[i - 1];
1017 for (tmp = thread->
child; tmp; tmp = tmp->
next)
1049 thread = thread->
next;
1118 struct Email *e = NULL;
1119 int i, using_refs = 0;
1120 struct MuttThread *thread = NULL, *tnew = NULL, *tmp = NULL;
1142 for (thread = tctx->
tree; thread; thread = thread->
next)
1161 for (tnew = thread->
child; tnew;)
1164 if (tnew->fake_thread)
1168 tnew->fake_thread =
false;
1180 if (thread && !thread->
message)
1188 for (tmp = (thread->
child ? thread->
child : thread); tmp != thread;)
1190 while (!tmp->message)
1192 tmp->check_subject =
true;
1193 while (!tmp->next && (tmp != thread))
1215 }
while (thread != &top && !thread->
child && !thread->
message);
1220 tnew = (c_duplicate_threads ? thread : NULL);
1230 if (tnew->duplicate_thread)
1231 tnew = tnew->parent;
1261 if (using_refs == 0)
1275 else if (using_refs == 1)
1307 if (tnew->duplicate_thread)
1308 tnew = tnew->parent;
1331 for (thread = top.
child; thread; thread = thread->
next)
1340 if (!c_strict_threads)
1372 struct Email *e_tmp = NULL;
1439 struct Email *e_parent = NULL;
1470 mutt_error(
_(
"Root message is not visible in this limited view"));
1472 mutt_error(
_(
"Parent message is not visible in this limited view"));
1475 return e_parent->
vnum;
1519 struct MuttThread *thread = NULL, *top = NULL;
1520 struct Email *e_root = NULL;
1523 int num_hidden = 0, new_mail = 0, old_mail = 0;
1525 int min_unread_msgno = INT_MAX, min_unread = e_cur->
vnum;
1538 final = e_cur->
vnum;
1546 minmsgno = e_cur->
msgno;
1554 if (e_cur->
msgno < min_unread_msgno)
1556 min_unread = e_cur->
vnum;
1557 min_unread_msgno = e_cur->
msgno;
1571 if (e_cur->
vnum != -1)
1575 final = e_root->
vnum;
1588 return (old_mail && new_mail) ? new_mail : (old_mail ? old_mail : new_mail);
1605 if (!e_root && e_cur->
visible)
1609 final = e_root->
vnum;
1615 minmsgno = e_cur->
msgno;
1616 final = e_cur->
vnum;
1621 if (e_cur != e_root)
1637 if (e_cur->
msgno < min_unread_msgno)
1639 min_unread = e_cur->
vnum;
1640 min_unread_msgno = e_cur->
msgno;
1720 return (old_mail && new_mail) ? new_mail : (old_mail ? old_mail : new_mail);
1749 while (threads[0]->
parent)
1750 threads[0] = threads[0]->
parent;
1754 for (
int i = 0; i < (((mit ==
MIT_POSITION) || !threads[1]) ? 1 : 2); i++)
1757 threads[i] = threads[i]->
child;
1807 if (child == parent)
1828 if (!parent || !children || !m)
1833 struct Email **ep = NULL;
1836 struct Email *e = *ep;
1851 while ((thread = top))
1854 thread = thread->
child;
1872 while ((thread = top))
1875 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.
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.
#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 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 -.
#define mutt_warning(...)
#define mutt_debug(LEVEL,...)
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 -.
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.
static int thread_check_integrity(struct MuttThread *tree)
Verify and repair thread<->message back-pointers.
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.
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.
@ LL_DEBUG1
Log at debug level 1.
const char * mutt_map_get_name(int val, const struct Mapping *map)
Lookup a string for a constant.
#define FREE(x)
Free memory and set the pointer to NULL.
#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.
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.
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.
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.
int index
The absolute (unsorted) message number.
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.