113 buf_printf(err,
_(
"Cannot use 'last-' prefix with 'threads' for %s"), cdef->
name);
141 if (!c_hide_thread_subject)
150 for (tmp = tree->
prev; tmp; tmp = tmp->
prev)
196 while (!
tree->message)
199 *array =
tree->message;
200 array += reverse ? -1 : 1;
245 int hide_top_missing = c_hide_top_missing && !c_hide_missing;
248 int hide_top_limited = c_hide_top_limited && !c_hide_limited;
258 if (depth > *max_depth)
270 for (tmp = tree; tmp; tmp = tmp->
parent)
287 tree->
deep = !c_hide_limited;
293 tree->
deep = !c_hide_missing;
310 while (tree && !tree->
prev)
322 if (hide_top_limited || hide_top_missing)
328 ((tree->
message && hide_top_limited) || (!tree->
message && hide_top_missing)))
342 while (tree && !tree->
next)
396 char *pfx = NULL, *mypfx = NULL, *arrow = NULL, *myarrow = NULL, *new_tree = NULL;
401 int depth = 0, start_depth = 0, max_depth = 0, width = c_narrow_tree ? 1 : 2;
417 myarrow = arrow + (depth - start_depth - ((start_depth != 0) ? 0 : 1)) * width;
418 if (start_depth == depth)
434 myarrow[width + 1] = 0;
438 strncpy(new_tree, pfx, (
size_t) width * (start_depth - 1));
440 (1 + depth - start_depth) * width + 2);
444 mutt_str_copy(new_tree, arrow, ((
size_t) depth * width) + 2);
449 if (tree->
child && (depth != 0))
451 mypfx = pfx + (depth - 1) * width;
481 if (tree == nextdisp)
488 if (start_depth == depth)
495 if (tree == nextdisp)
507 }
while (!tree->
deep);
541 if ((*dateptr == 0) || (thisdate < *dateptr))
561 while (!cur->
next && (cur != start))
598 tmp = ((
struct Email *) he->
data)->thread;
604 (!last || (c_thread_received ?
658 struct MuttThread *tmp = NULL, *cur = NULL, *
parent = NULL, *curchild = NULL,
671 cur->fake_thread =
true;
691 for (curchild = tmp->
child; curchild;)
693 nextchild = curchild->next;
694 if (curchild->fake_thread)
699 curchild = nextchild;
703 while (!tmp->
next && (tmp != cur))
722 if (!tctx || !tctx->
tree)
784 struct MuttThread **array = NULL, *top = NULL, *tmp = NULL;
785 struct Email *sort_aux_key = NULL, *oldsort_aux_key = NULL;
786 struct Email *oldsort_thread_key = NULL;
788 bool sort_top =
false;
849 while (!thread->
next)
855 for (i = 0; thread; i++, thread = thread->
prev)
868 array[i - 1]->prev = NULL;
871 thread->parent->child = array[i - 1];
877 array[i - 1]->prev = array[i];
878 array[i]->next = array[i - 1];
918 if ((c_sort_aux & ~
SORT_REVERSE) == (c_sort & ~SORT_REVERSE))
938 for (tmp = thread->
child; tmp; tmp = tmp->
next)
970 thread = thread->
next;
1039 struct Email *e = NULL;
1040 int i, using_refs = 0;
1041 struct MuttThread *thread = NULL, *tnew = NULL, *tmp = NULL;
1063 for (thread = tctx->
tree; thread; thread = thread->
next)
1082 for (tnew = thread->
child; tnew;)
1085 if (tnew->fake_thread)
1089 tnew->fake_thread =
false;
1101 if (thread && !thread->
message)
1109 for (tmp = (thread->
child ? thread->
child : thread); tmp != thread;)
1111 while (!tmp->message)
1113 tmp->check_subject =
true;
1114 while (!tmp->next && (tmp != thread))
1136 }
while (thread != &top && !thread->
child && !thread->
message);
1141 tnew = (c_duplicate_threads ? thread : NULL);
1151 if (tnew->duplicate_thread)
1152 tnew = tnew->parent;
1182 if (using_refs == 0)
1196 else if (using_refs == 1)
1228 if (tnew->duplicate_thread)
1229 tnew = tnew->parent;
1252 for (thread = top.
child; thread; thread = thread->
next)
1261 if (!c_strict_threads)
1293 struct Email *e_tmp = NULL;
1360 struct Email *e_parent = NULL;
1391 mutt_error(
_(
"Root message is not visible in this limited view"));
1393 mutt_error(
_(
"Parent message is not visible in this limited view"));
1396 return e_parent->
vnum;
1440 struct MuttThread *thread = NULL, *top = NULL;
1441 struct Email *e_root = NULL;
1444 int num_hidden = 0, new_mail = 0, old_mail = 0;
1446 int min_unread_msgno = INT_MAX, min_unread = e_cur->
vnum;
1459 final = e_cur->
vnum;
1467 minmsgno = e_cur->
msgno;
1475 if (e_cur->
msgno < min_unread_msgno)
1477 min_unread = e_cur->
vnum;
1478 min_unread_msgno = e_cur->
msgno;
1492 if (e_cur->
vnum != -1)
1496 final = e_root->
vnum;
1509 return (old_mail && new_mail) ? new_mail : (old_mail ? old_mail : new_mail);
1526 if (!e_root && e_cur->
visible)
1530 final = e_root->
vnum;
1536 minmsgno = e_cur->
msgno;
1537 final = e_cur->
vnum;
1542 if (e_cur != e_root)
1558 if (e_cur->
msgno < min_unread_msgno)
1560 min_unread = e_cur->
vnum;
1561 min_unread_msgno = e_cur->
msgno;
1641 return (old_mail && new_mail) ? new_mail : (old_mail ? old_mail : new_mail);
1670 while (threads[0]->
parent)
1671 threads[0] = threads[0]->
parent;
1675 for (
int i = 0; i < (((mit ==
MIT_POSITION) || !threads[1]) ? 1 : 2); i++)
1678 threads[i] = threads[i]->
child;
1728 if (child == parent)
1749 if (!parent || !children || !m)
1754 struct Email **ep = NULL;
1757 struct Email *e = *ep;
1772 while ((thread = top))
1775 thread = thread->
child;
1793 while ((thread = top))
1796 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.
Convenience wrapper for the core headers.
MailboxType
Supported mailbox formats.
Structs that make up an email.
#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.
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
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)
#define SORT_MASK
Mask for the sort id.
#define SORT_LAST
Sort thread by last-X, e.g. received date.
SortType
Methods for sorting.
@ SORT_ORDER
Sort by the order the messages appear in the mailbox.
@ SORT_THREADS
Sort by email threads.
#define SORT_REVERSE
Reverse the order of the sort.
Assorted sorting methods.
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.
struct HashTable * hash
Hash Table: "message-id" -> MuttThread.
enum SortType c_sort_aux
Last sort_aux method.
enum SortType c_sort
Last sort 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.