/* step 1: create the containers, connect them, and fill the id_table */ static GHashTable* create_containers (MuMsgIter *iter) { GHashTable *id_table; id_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)mu_container_destroy); for (mu_msg_iter_reset (iter); !mu_msg_iter_is_done (iter); mu_msg_iter_next (iter)) { MuContainer *c; MuMsg *msg; unsigned docid; /* 1.A */ msg = mu_msg_iter_get_msg_floating (iter); /* don't unref */ docid = mu_msg_iter_get_docid (iter); c = find_or_create (id_table, msg, docid); /* 1.B and C */ if (c) handle_references (id_table, c); } return id_table; }
/* msg threading algorithm, based on JWZ's algorithm, * http://www.jwz.org/doc/threading.html */ GHashTable* mu_threader_calculate (MuMsgIter *iter, size_t matchnum, MuMsgFieldId sortfield, gboolean descending) { GHashTable *id_table, *thread_ids; MuContainer *root_set; g_return_val_if_fail (iter, FALSE); g_return_val_if_fail (mu_msg_field_id_is_valid (sortfield) || sortfield == MU_MSG_FIELD_ID_NONE, FALSE); /* step 1 */ id_table = create_containers (iter); if (matchnum == 0) return id_table; /* just return an empty table */ /* step 2 -- the root_set is the list of children without parent */ root_set = find_root_set (id_table); /* step 3: skip until the end; we still need to containers */ /* step 4: prune empty containers */ root_set = prune_empty_containers (root_set); /* sort root set */ if (sortfield != MU_MSG_FIELD_ID_NONE) root_set = mu_container_sort (root_set, sortfield, descending, NULL); /* step 5: group root set by subject */ /* group_root_set_by_subject (root_set); */ /* sort */ mu_msg_iter_reset (iter); /* go all the way back */ /* finally, deliver the docid => thread-path hash */ thread_ids = mu_container_thread_info_hash_new (root_set, matchnum); g_hash_table_destroy (id_table); /* step 3*/ return thread_ids; }