Exemplo n.º 1
0
Arquivo: mu-threader.c Projeto: nd/mu
static gboolean
child_elligible (MuContainer *parent, MuContainer *child, gboolean created)
{
	if (!parent || !child)
		return FALSE;
	if (child->parent)
		return FALSE;
	/* if (created) */
	/* 	return TRUE; */
	if (mu_container_reachable (parent, child))
		return FALSE;
	if (mu_container_reachable (child, parent))
		return FALSE;

	return TRUE;
}
Exemplo n.º 2
0
static void /* 1B */
handle_references (GHashTable *id_table, MuContainer *c)
{
	const GSList *refs, *cur;
	MuContainer *parent;
	gboolean created;

	refs = mu_msg_get_references (c->msg);
	if (!refs)
		return; /* nothing to do */

	/* For each element in the message's References field:

	   Find a MuContainer object for the given Message-ID: If
	   there's one in id_table use that; Otherwise, make (and
	   index) one with a null Message. */

	/* go over over our list of refs, until 1 before the last... */
	created = FALSE;
	for (parent = NULL, cur = refs; cur; cur = g_slist_next (cur)) {

		MuContainer *child;
		child = find_or_create_referred (id_table, (gchar*)cur->data,
						 &created);

		/* if we find the current message in their own refs, break now
		   so that parent != c in next step */
		if (child == c)
			break;

		/*Link the References field's MuContainers together in
		 * the order implied by the References header.

		 If they are already linked, don't change the existing
		 links.  Do not add a link if adding that link would
		 introduce a loop: that is, before asserting A->B,
		 search down the children of B to see if A is
		 reachable, and also search down the children of A to
		 see if B is reachable. If either is already reachable
		 as a child of the other, don't add the link. */

		if (child_elligible (parent, child, created))
			/*parent =*/
			mu_container_append_children (parent, child);

		parent = child;
	}

	/* 'parent' points to the last ref: our direct parent;

	   Set the parent of this message to be the last element in
	   References. Note that this message may have a parent
	   already: this can happen because we saw this ID in a
	   References field, and presumed a parent based on the other
	   entries in that field. Now that we have the actual message,
	   we can be more definitive, so throw away the old parent and
	   use this new one. Find this MuContainer in the parent's
	   children list, and unlink it.

	   Note that this could cause this message to now have no
	   parent, if it has no references field, but some message
	   referred to it as the non-first element of its
	   references. (Which would have been some kind of lie...)

	   Note that at all times, the various ``parent'' and ``child'' fields
	   must be kept inter-consistent. */

        /* optimization: if the the message was newly added, it's by
   	   definition not reachable yet */

	/* So, we move c and its descendants to become a child of parent if:
	   * both are not NULL
	   * parent is not a descendant of c.
	   * both are different from each other (guaranteed in last loop) */

	if (parent && c && !(c->child && mu_container_reachable (c->child, parent))) {

		/* if c already has a parent, remove c from its parent children
		   and reparent it, as now we know who is c's parent reliably */
		if (c->parent) {
			mu_container_remove_child(c->parent, c);
			c->next = c->last = c->parent = NULL;
		}

		/*parent = */mu_container_append_children (parent, c);
	}
}