⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thread.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 3 页
字号:
}/* add cur as a prior sibling of *new, with parent newparent */static void insert_message (THREAD **new, THREAD *newparent, THREAD *cur){  if (*new)    (*new)->prev = cur;  cur->parent = newparent;  cur->next = *new;  cur->prev = NULL;  *new = cur;}/* thread by subject things that didn't get threaded by message-id */static void pseudo_threads (CONTEXT *ctx){  THREAD *tree = ctx->tree, *top = tree;  THREAD *tmp, *cur, *parent, *curchild, *nextchild;  if (!ctx->subj_hash)    ctx->subj_hash = mutt_make_subj_hash (ctx);  while (tree)  {    cur = tree;    tree = tree->next;    if ((parent = find_subject (ctx, cur)) != NULL)    {      cur->fake_thread = 1;      unlink_message (&top, cur);      insert_message (&parent->child, parent, cur);      parent->sort_children = 1;      tmp = cur;      FOREVER      {	while (!tmp->message)	  tmp = tmp->child;	/* if the message we're attaching has pseudo-children, they	 * need to be attached to its parent, so move them up a level.	 * but only do this if they have the same real subject as the	 * parent, since otherwise they rightly belong to the message	 * we're attaching. */	if (tmp == cur	    || !mutt_strcmp (tmp->message->env->real_subj,			     parent->message->env->real_subj))	{	  tmp->message->subject_changed = 0;	  for (curchild = tmp->child; curchild; )	  {	    nextchild = curchild->next;	    if (curchild->fake_thread)	    {	      unlink_message (&tmp->child, curchild);	      insert_message (&parent->child, parent, curchild);	    }	    curchild = nextchild;	  }	}	while (!tmp->next && tmp != cur)	{	  tmp = tmp->parent;	}	if (tmp == cur)	  break;	tmp = tmp->next;      }    }  }  ctx->tree = top;}void mutt_clear_threads (CONTEXT *ctx){  int i;  for (i = 0; i < ctx->msgcount; i++)  {    ctx->hdrs[i]->thread = NULL;    ctx->hdrs[i]->threaded = 0;  }  ctx->tree = NULL;  if (ctx->thread_hash)    hash_destroy (&ctx->thread_hash, *free);}int compare_threads (const void *a, const void *b){  static sort_t *sort_func = NULL;  if (a || b)    return ((*sort_func) (&(*((THREAD **) a))->sort_key,			  &(*((THREAD **) b))->sort_key));  /* a hack to let us reset sort_func even though we can't   * have extra arguments because of qsort   */  else  {    sort_func = NULL;    sort_func = mutt_get_sort_func (Sort);    return (sort_func ? 1 : 0);  }}THREAD *mutt_sort_subthreads (THREAD *thread, int init){  THREAD **array, *sort_key, *top, *tmp;  HEADER *oldsort_key;  int i, array_size, sort_top = 0;    /* we put things into the array backwards to save some cycles,   * but we want to have to move less stuff around if we're    * resorting, so we sort backwards and then put them back   * in reverse order so they're forwards   */  Sort ^= SORT_REVERSE;  if (!compare_threads (NULL, NULL))    return (thread);  top = thread;  array = safe_calloc ((array_size = 256), sizeof (THREAD *));  while (1)  {    if (init || !thread->sort_key)    {      thread->sort_key = NULL;      if (thread->parent)        thread->parent->sort_children = 1;      else	sort_top = 1;    }    if (thread->child)    {      thread = thread->child;      continue;    }    else    {      /* if it has no children, it must be real. sort it on its own merits */      thread->sort_key = thread->message;      if (thread->next)      {	thread = thread->next;	continue;      }    }    while (!thread->next)    {      /* if it has siblings and needs to be sorted, sort it... */      if (thread->prev && (thread->parent ? thread->parent->sort_children : sort_top))      {	/* 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 *));	  array[i] = thread;	}	qsort ((void *) array, i, sizeof (THREAD *), *compare_threads);	/* attach them back together.  make thread the last sibling. */	thread = array[0];	thread->next = NULL;	array[i - 1]->prev = NULL;	if (thread->parent)	  thread->parent->child = array[i - 1];	else	  top = array[i - 1];	while (--i)	{	  array[i - 1]->prev = array[i];	  array[i]->next = array[i - 1];	}      }      if (thread->parent)      {	tmp = thread;	thread = thread->parent;	if (!thread->sort_key || thread->sort_children)	{	  /* make sort_key the first or last sibling, as appropriate */	  sort_key = (!(Sort & SORT_LAST) ^ !(Sort & SORT_REVERSE)) ? thread->child : tmp;	  /* we just sorted its children */	  thread->sort_children = 0;	  oldsort_key = thread->sort_key;	  thread->sort_key = thread->message;	  if (Sort & SORT_LAST)	  {	    if (!thread->sort_key		|| ((((Sort & SORT_REVERSE) ? 1 : -1)		     * compare_threads ((void *) &thread,					(void *) &sort_key))		    > 0))	      thread->sort_key = sort_key->sort_key;	  }	  else if (!thread->sort_key)	    thread->sort_key = sort_key->sort_key;	  /* if its sort_key has changed, we need to resort it and siblings */	  if (oldsort_key != thread->sort_key)	  {	    if (thread->parent)	      thread->parent->sort_children = 1;	    else	      sort_top = 1;	  }	}      }      else      {	Sort ^= SORT_REVERSE;	FREE (&array);	return (top);      }    }    thread = thread->next;  }}static void check_subjects (CONTEXT *ctx, int init){  HEADER *cur;  THREAD *tmp;  int i;  for (i = 0; i < ctx->msgcount; i++)  {    cur = ctx->hdrs[i];    if (cur->thread->check_subject)      cur->thread->check_subject = 0;    else if (!init)      continue;    /* figure out which messages have subjects different than their parents' */    tmp = cur->thread->parent;    while (tmp && !tmp->message)    {      tmp = tmp->parent;    }    if (!tmp)      cur->subject_changed = 1;    else if (cur->env->real_subj && tmp->message->env->real_subj)      cur->subject_changed = mutt_strcmp (cur->env->real_subj,					  tmp->message->env->real_subj) ? 1 : 0;    else      cur->subject_changed = (cur->env->real_subj			      || tmp->message->env->real_subj) ? 1 : 0;  }}void mutt_sort_threads (CONTEXT *ctx, int init){  HEADER *cur;  int i, oldsort, using_refs = 0;  THREAD *thread, *new, *tmp, top;  LIST *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   * SORT_REVERSE   */  oldsort = Sort;  Sort = SortAux;    if (!ctx->thread_hash)    init = 1;  if (init)    ctx->thread_hash = hash_create (ctx->msgcount * 2);  /* we want a quick way to see if things are actually attached to the top of the   * thread tree or if they're just dangling, so we attach everything to a top   * node temporarily */  top.parent = top.next = top.prev = NULL;  top.child = ctx->tree;  for (thread = ctx->tree; thread; thread = thread->next)    thread->parent = &top;  /* put each new message together with the matching messageless THREAD if it   * exists.  otherwise, if there is a THREAD that already has a message, thread   * new message as an identical child.  if we didn't attach the message to a   * THREAD, make a new one for it. */  for (i = 0; i < ctx->msgcount; i++)  {    cur = ctx->hdrs[i];    if (!cur->thread)    {      if ((!init || option (OPTDUPTHREADS)) && cur->env->message_id)	thread = hash_find (ctx->thread_hash, cur->env->message_id);      else	thread = NULL;      if (thread && !thread->message)      {	/* this is a message which was missing before */	thread->message = cur;	cur->thread = thread;	thread->check_subject = 1;	/* mark descendants as needing subject_changed checked */	for (tmp = (thread->child ? thread->child : thread); tmp != thread; )	{	  while (!tmp->message)	    tmp = tmp->child;	  tmp->check_subject = 1;	  while (!tmp->next && tmp != thread)	    tmp = tmp->parent;	  if (tmp != thread)	    tmp = tmp->next;	}	if (thread->parent)	{	  /* remove threading info above it based on its children, which we'll	   * recalculate based on its headers.  make sure not to leave	   * dangling missing messages.  note that we haven't kept track	   * of what info came from its children and what from its siblings'	   * children, so we just remove the stuff that's definitely from it */	  do	  {	    tmp = thread->parent;	    unlink_message (&tmp->child, thread);	    thread->parent = NULL;	    thread->sort_key = NULL;	    thread->fake_thread = 0;	    thread = tmp;	  } while (thread != &top && !thread->child && !thread->message);	}      }      else      {	new = (option (OPTDUPTHREADS) ? thread : NULL);	thread = safe_calloc (1, sizeof (THREAD));	thread->message = cur;	thread->check_subject = 1;	cur->thread = thread;	hash_insert (ctx->thread_hash,		     cur->env->message_id ? cur->env->message_id : "",		     thread, 1);	if (new)	{	  if (new->duplicate_thread)	    new = new->parent;	  thread = cur->thread;	  insert_message (&new->child, new, thread);	  thread->duplicate_thread = 1;	  thread->message->threaded = 1;	}      }    }    else    {      /* unlink pseudo-threads because they might be children of newly       * arrived messages */      thread = cur->thread;      for (new = thread->child; new; )      {	tmp = new->next;	if (new->fake_thread)	{	  unlink_message (&thread->child, new);	  insert_message (&top.child, &top, new);	  new->fake_thread = 0;	}	new = tmp;      }    }  }  /* thread by references */  for (i = 0; i < ctx->msgcount; i++)  {    cur = ctx->hdrs[i];    if (cur->threaded)      continue;    cur->threaded = 1;    thread = cur->thread;    using_refs = 0;    while (1)    {      if (using_refs == 0)      {	/* look at the beginning of in-reply-to: */	if ((ref = cur->env->in_reply_to) != NULL)	  using_refs = 1;	else	{	  ref = cur->env->references;	  using_refs = 2;	}      }      else if (using_refs == 1)      {	/* if there's no references header, use all the in-reply-to:	 * data that we have.  otherwise, use the first reference	 * if it's different than the first in-reply-to, otherwise use	 * the second reference (since at least eudora puts the most	 * recent reference in in-reply-to and the rest in references)	 */	if (!cur->env->references)	  ref = ref->next;	else	{	  if (mutt_strcmp (ref->data, cur->env->references->data))	    ref = cur->env->references;	  else	    ref = cur->env->references->next;	  	  using_refs = 2;	}      }      else	ref = ref->next; /* go on with references */            if (!ref)	break;      if ((new = hash_find (ctx->thread_hash, ref->data)) == NULL)      {	new = safe_calloc (1, sizeof (THREAD));	hash_insert (ctx->thread_hash, ref->data, new, 1);      }      else      {	if (new->duplicate_thread)	  new = new->parent;	if (is_descendant (new, thread)) /* no loops! */	  continue;      }      if (thread->parent)	unlink_message (&top.child, thread);      insert_message (&new->child, new, thread);      thread = new;      if (thread->message || (thread->parent && thread->parent != &top))	break;    }    if (!thread->parent)      insert_message (&top.child, &top, thread);  }  /* detach everything from the temporary top node */  for (thread = top.child; thread; thread = thread->next)  {    thread->parent = NULL;  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -