* please see the file GPL in the top level source directory.
*/
-#if HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include <lib-lib/lib-lib.h>
#include "mutt.h"
#include "sort.h"
-
-#include "lib/mem.h"
-#include "lib/intl.h"
-
-#include <string.h>
-#include <ctype.h>
+#include "thread.h"
#define VISIBLE(hdr, ctx) (hdr->virtual >= 0 || (hdr->collapsed && (!ctx->pattern || hdr->limited)))
tree = tree->next;
*max_depth = 0;
- FOREVER {
+ for (;;) {
if (depth > *max_depth)
*max_depth = depth;
tree->subtree_visible = 0;
if (tree->message) {
- FREE (&tree->message->tree);
+ p_delete(&tree->message->tree);
if (VISIBLE (tree->message, ctx)) {
tree->deep = 1;
tree->visible = 1;
/* now fix up for the OPTHIDETOP* options if necessary */
if (hide_top_limited || hide_top_missing) {
tree = ctx->tree;
- FOREVER {
+ for (;;) {
if (!tree->visible && tree->deep && tree->subtree_visible < 2
&& ((tree->message && hide_top_limited)
|| (!tree->message && hide_top_missing)))
* From now on we can simply ignore invisible subtrees
*/
calculate_visibility (ctx, &max_depth);
- pfx = safe_malloc (width * max_depth + 2);
- arrow = safe_malloc (width * max_depth + 2);
+ pfx = p_new(char, width * max_depth + 2);
+ arrow = p_new(char, width * max_depth + 2);
while (tree) {
if (depth) {
myarrow = arrow + (depth - start_depth - (start_depth ? 0 : 1)) * width;
if (tree->visible) {
myarrow[width] = M_TREE_RARROW;
myarrow[width + 1] = 0;
- new_tree = safe_malloc ((2 + depth * width));
+ new_tree = p_new(char, (2 + depth * width));
if (start_depth > 1) {
- strncpy (new_tree, pfx, (start_depth - 1) * width);
- strfcpy (new_tree + (start_depth - 1) * width,
- arrow, (1 + depth - start_depth) * width + 2);
+ memcpy(new_tree, pfx, (start_depth - 1) * width);
+ m_strcpy(new_tree + (start_depth - 1) * width,
+ (1 + depth - start_depth) * width + 2, arrow);
}
else
- strfcpy (new_tree, arrow, 2 + depth * width);
+ m_strcpy(new_tree, 2 + depth * width, arrow);
tree->message->tree = new_tree;
}
}
while (!tree->deep);
}
- FREE (&pfx);
- FREE (&arrow);
+ p_delete(&pfx);
+ p_delete(&arrow);
}
/* since we may be trying to attach as a pseudo-thread a THREAD that
* has no message, we have to make a list of all the subjects of its
* most immediate existing descendants. we also note the earliest
* date on any of the parents and put it in *dateptr. */
-static LIST *make_subject_list (THREAD * cur, time_t * dateptr)
+static string_list_t *make_subject_list (THREAD * cur, time_t * dateptr)
{
THREAD *start = cur;
ENVELOPE *env;
time_t thisdate;
- LIST *curlist, *oldlist, *newlist, *subjects = NULL;
+ string_list_t *curlist, *oldlist, *newlist, *subjects = NULL;
int rc = 0;
- FOREVER {
+ for (;;) {
while (!cur->message)
cur = cur->child;
((env->real_subj != env->subject) || (!option (OPTSORTRE)))) {
for (curlist = subjects, oldlist = NULL;
curlist; oldlist = curlist, curlist = curlist->next) {
- rc = str_cmp (env->real_subj, curlist->data);
+ rc = m_strcmp(env->real_subj, curlist->data);
if (rc >= 0)
break;
}
if (!curlist || rc > 0) {
- newlist = safe_calloc (1, sizeof (LIST));
+ newlist = p_new(string_list_t, 1);
newlist->data = env->real_subj;
if (oldlist) {
newlist->next = oldlist->next;
struct hash_elem *ptr;
THREAD *tmp, *last = NULL;
int hash;
- LIST *subjects = NULL, *oldlist;
+ string_list_t *subjects = NULL, *oldlist;
time_t date = 0;
subjects = make_subject_list (cur, &date);
(last->message->received < tmp->message->received) :
(last->message->date_sent < tmp->message->date_sent))) &&
tmp->message->env->real_subj &&
- str_cmp (subjects->data, tmp->message->env->real_subj) == 0)
+ m_strcmp(subjects->data, tmp->message->env->real_subj) == 0)
last = tmp; /* best match so far */
}
oldlist = subjects;
subjects = subjects->next;
- FREE (&oldlist);
+ p_delete(&oldlist);
}
return (last);
}
insert_message (&parent->child, parent, cur);
parent->sort_children = 1;
tmp = cur;
- FOREVER {
+ for (;;) {
while (!tmp->message)
tmp = tmp->child;
* parent, since otherwise they rightly belong to the message
* we're attaching. */
if (tmp == cur
- || !str_cmp (tmp->message->env->real_subj,
+ || !m_strcmp(tmp->message->env->real_subj,
parent->message->env->real_subj)) {
tmp->message->subject_changed = 0;
hash_destroy (&ctx->thread_hash, free);
}
-int compare_threads (const void *a, const void *b)
+static int compare_threads (const void *a, const void *b)
{
static sort_t *sort_func = NULL;
top = thread;
- array = safe_calloc ((array_size = 256), sizeof (THREAD *));
+ array = p_new(THREAD *, (array_size = 256));
while (1) {
if (init || !thread->sort_key) {
thread->sort_key = NULL;
/* put them into the array */
for (i = 0; thread; i++, thread = thread->prev) {
if (i >= array_size)
- safe_realloc (&array, (array_size *= 2) * sizeof (THREAD *));
+ p_realloc(&array, array_size *= 2);
array[i] = thread;
}
}
else {
Sort ^= SORT_REVERSE;
- FREE (&array);
+ p_delete(&array);
return (top);
}
}
if (!tmp)
cur->subject_changed = 1;
else if (cur->env->real_subj && tmp->message->env->real_subj)
- cur->subject_changed = str_cmp (cur->env->real_subj,
+ cur->subject_changed = m_strcmp(cur->env->real_subj,
tmp->message->env->
real_subj) ? 1 : 0;
else
HEADER *cur;
int i, oldsort, using_refs = 0;
THREAD *thread, *new, *tmp, top;
- LIST *ref = NULL;
+ string_list_t *ref = NULL;
/* set Sort to the secondary method to support the set sort_aux=reverse-*
* settings. The sorting functions just look at the value of
else {
new = (option (OPTDUPTHREADS) ? thread : NULL);
- thread = safe_calloc (1, sizeof (THREAD));
+ thread = p_new(THREAD, 1);
thread->message = cur;
thread->check_subject = 1;
cur->thread = thread;
if (!cur->env->references)
ref = ref->next;
else {
- if (str_cmp (ref->data, cur->env->references->data))
+ if (m_strcmp(ref->data, cur->env->references->data))
ref = cur->env->references;
else
ref = cur->env->references->next;
break;
if ((new = hash_find (ctx->thread_hash, ref->data)) == NULL) {
- new = safe_calloc (1, sizeof (THREAD));
+ new = p_new(THREAD, 1);
hash_insert (ctx->thread_hash, ref->data, new, 1);
}
else {
while (reverse && cur->next)
cur = cur->next;
- FOREVER {
+ for (;;) {
if (cur->message && cur->message->virtual >= 0)
return (cur->message);
return (min_unread);
}
- FOREVER {
+ for (;;) {
cur = thread->message;
if (cur) {
return hash;
}
-static void clean_references (THREAD * brk, THREAD * cur)
+static void clean_references (THREAD * tbrk, THREAD * cur)
{
THREAD *p;
- LIST *ref = NULL;
+ string_list_t *ref = NULL;
int done = 0;
for (; cur; cur = cur->next, done = 0) {
/* parse subthread recursively */
- clean_references (brk, cur->child);
+ clean_references (tbrk, cur->child);
if (!cur->message)
break; /* skip pseudo-message */
/* Looking for the first bad reference according to the new threading.
* Optimal since Mutt stores the references in reverse order, and the
* first loop should match immediatly for mails respecting RFC2822. */
- for (p = brk; !done && p; p = p->parent)
+ for (p = tbrk; !done && p; p = p->parent)
for (ref = cur->message->env->references; p->message && ref;
ref = ref->next)
- if (!str_casecmp (ref->data, p->message->env->message_id)) {
+ if (!m_strcasecmp(ref->data, p->message->env->message_id)) {
done = 1;
break;
}
if (done) {
HEADER *h = cur->message;
- /* clearing the References: header from obsolete Message-Id(s) */
- mutt_free_list (&ref->next);
+ /* clearing the References: header from obsolete Message-ID(s) */
+ string_list_wipe(&ref->next);
h->env->refs_changed = h->changed = 1;
}
void mutt_break_thread (HEADER * hdr)
{
- mutt_free_list (&hdr->env->in_reply_to);
- mutt_free_list (&hdr->env->references);
- hdr->env->irt_changed = hdr->env->refs_changed = 1;
+ string_list_wipe(&hdr->env->in_reply_to);
+ string_list_wipe(&hdr->env->references);
+ hdr->env->irt_changed = hdr->env->refs_changed = hdr->changed = 1;
clean_references (hdr->thread, hdr->thread->child);
}
mutt_break_thread (child);
- child->env->in_reply_to = mutt_new_list ();
- child->env->in_reply_to->data = str_dup (parent->env->message_id);
+ child->env->in_reply_to = string_item_new();
+ child->env->in_reply_to->data = m_strdup(parent->env->message_id);
mutt_set_flag (ctx, child, M_TAG, 0);
return changed;
}
+
+void mutt_adjust_subject (ENVELOPE* e) {
+ regmatch_t pmatch[1];
+
+ if (e && e->subject) {
+ if (regexec (ReplyRegexp.rx, e->subject, 1, pmatch, 0) == 0)
+ e->real_subj = e->subject + pmatch[0].rm_eo;
+ else
+ e->real_subj = e->subject;
+ }
+}
+
+void mutt_adjust_all_subjects (void) {
+ int i = 0;
+
+ if (!Context || !Context->msgcount)
+ return;
+
+ for (i = 0; i < Context->msgcount; i++)
+ mutt_adjust_subject (Context->hdrs[i]->env);
+}