balsa r7831 - in branches/mailbox-gsequence: . libbalsa src
- From: PeterB svn gnome org
- To: svn-commits-list gnome org
- Subject: balsa r7831 - in branches/mailbox-gsequence: . libbalsa src
- Date: Sun, 27 Jan 2008 01:03:06 +0000 (GMT)
Author: PeterB
Date: Sun Jan 27 01:03:05 2008
New Revision: 7831
URL: http://svn.gnome.org/viewvc/balsa?rev=7831&view=rev
Log:
Initial commit on mailbox-gsequence branch
Modified:
branches/mailbox-gsequence/ChangeLog
branches/mailbox-gsequence/libbalsa/mailbox.c
branches/mailbox-gsequence/libbalsa/mailbox.h
branches/mailbox-gsequence/libbalsa/mailbox_imap.c
branches/mailbox-gsequence/libbalsa/mailbox_local.c
branches/mailbox-gsequence/src/balsa-mblist.c
Modified: branches/mailbox-gsequence/libbalsa/mailbox.c
==============================================================================
--- branches/mailbox-gsequence/libbalsa/mailbox.c (original)
+++ branches/mailbox-gsequence/libbalsa/mailbox.c Sun Jan 27 01:03:05 2008
@@ -325,9 +325,6 @@
#ifdef BALSA_USE_THREADS
entry->idle_pending = 0;
#endif /*BALSA_USE_THREADS */
-#if CACHE_UNSEEN_CHILD
- entry->has_unseen_child = 0; /* Find out after threading. */
-#endif /* CACHE_UNSEEN_CHILD */
libbalsa_mailbox_msgno_changed(msg->mailbox, msg->msgno);
}
@@ -562,11 +559,224 @@
{
g_return_val_if_fail(mailbox != NULL, FALSE);
g_return_val_if_fail(LIBBALSA_IS_MAILBOX(mailbox), FALSE);
-
return mailbox->open_ref>0; /* this will break unlisted mailbox types */
}
-
+
+/*
+ * The msg_tree is implemented using GSequence. The messages at a given
+ * level are contained in a GSequence, whose data member is a
+ * LibBalsaMailboxSequenceInfo.
+ */
+typedef struct {
+ guint msgno;
+ GSequenceIter *parent;
+ GSequence *children;
+} LibBalsaMailboxSequenceInfo;
+
+guint
+libbalsa_mailbox_get_msgno(GSequenceIter * node)
+{
+ LibBalsaMailboxSequenceInfo *info = g_sequence_get(node);
+ return info->msgno;
+}
+
+GSequenceIter *
+libbalsa_mailbox_get_parent(GSequenceIter * node)
+{
+ LibBalsaMailboxSequenceInfo *info = g_sequence_get(node);
+ return info->parent;
+}
+
+static void
+lbm_node_set_parent(GSequenceIter * node, GSequenceIter * parent)
+{
+ LibBalsaMailboxSequenceInfo *info = g_sequence_get(node);
+ info->parent = parent;
+}
+
+static GSequence *
+lbm_node_get_children(GSequenceIter * node)
+{
+ LibBalsaMailboxSequenceInfo *info = g_sequence_get(node);
+
+ if (info->children && g_sequence_get_length(info->children) == 0) {
+ g_sequence_free(info->children);
+ info->children = NULL;
+ }
+
+ return info->children;
+}
+
+static void
+lbm_msg_tree_free_info(LibBalsaMailboxSequenceInfo * info)
+{
+ if (info->children)
+ g_sequence_free(info->children);
+ g_free(info);
+}
+
+static GSequence *
+lbm_node_init_children(GSequenceIter * node)
+{
+ LibBalsaMailboxSequenceInfo *info = g_sequence_get(node);
+ if (!info->children)
+ info->children =
+ g_sequence_new((GDestroyNotify) lbm_msg_tree_free_info);
+ return info->children;
+}
+
+/* Called recursively; must cope with an empty GSequence. */
+static GSequenceIter *
+lbm_node_find(GSequence * seq, guint msgno)
+{
+ GSequenceIter *node;
+ GSequenceIter *end = g_sequence_get_end_iter(seq);
+
+ for (node = g_sequence_get_begin_iter(seq);
+ node != end;
+ node = g_sequence_iter_next(node)) {
+ LibBalsaMailboxSequenceInfo *info = g_sequence_get(node);
+ GSequenceIter *child_node;
+
+ if (info->msgno == msgno)
+ return node;
+
+ if (info->children
+ && (child_node = lbm_node_find(info->children, msgno)))
+ return child_node;
+ }
+
+ return NULL;
+}
+
+static gboolean
+lbm_nodes_traverse(GSequence * seq, GTraverseType type,
+ LBMTraverseFunc func, gpointer data)
+{
+ GSequenceIter *node = g_sequence_get_begin_iter(seq);
+ GSequenceIter *end = g_sequence_get_end_iter(seq);
+
+ g_assert(type == G_PRE_ORDER || type == G_POST_ORDER);
+
+ while (node != end) {
+ GSequenceIter *next = g_sequence_iter_next(node);
+ GSequence *children = lbm_node_get_children(node);
+
+ if (children) {
+ if (type == G_PRE_ORDER) {
+ if ((*func) (node, data)
+ || lbm_nodes_traverse(children, type, func, data))
+ return TRUE;
+ } else {
+ if (lbm_nodes_traverse(children, type, func, data)
+ || (*func) (node, data))
+ return TRUE;
+ }
+ } else
+ if ((*func) (node, data))
+ return TRUE;
+
+ node = next;
+ }
+
+ return FALSE;
+}
+
+void
+libbalsa_mailbox_traverse(LibBalsaMailbox * mailbox, GTraverseType type,
+ LBMTraverseFunc func, gpointer data)
+{
+ lbm_nodes_traverse(mailbox->msg_tree, type, func, data);
+}
+
+static gboolean
+lbm_node_count(GSequenceIter * node, gpointer data)
+{
+ ++*(guint *) data;
+
+ return FALSE;
+}
+
+guint
+libbalsa_mailbox_n_nodes(LibBalsaMailbox * mailbox)
+{
+ guint n = 0;
+
+ libbalsa_mailbox_traverse(mailbox, G_PRE_ORDER,
+ lbm_node_count, &n);
+
+ return n;
+}
+
+gboolean
+libbalsa_mailbox_node_is_ancestor(GSequenceIter * node,
+ GSequenceIter * descendant)
+{
+ while (descendant) {
+ if (node == descendant)
+ return TRUE;
+ descendant = libbalsa_mailbox_get_parent(descendant);
+ }
+
+ return FALSE;
+}
+
+/* LBMNode iterators */
+static GSequenceIter *
+lbm_next(GSequenceIter * node)
+{
+ GSequence *children;
+ GSequenceIter *last;
+ /* next is: our first child, if we have one;
+ * else our sibling, if we have one;
+ * else the sibling of our first ancestor who has
+ * one. */
+ if ((children = lbm_node_get_children(node)))
+ return g_sequence_get_begin_iter(children);
+
+ do {
+ last = node;
+ node = g_sequence_iter_next(node);
+ if (!g_sequence_iter_is_end(node))
+ return node;
+ node = libbalsa_mailbox_get_parent(last);
+ } while (node);
+
+ return NULL;
+}
+
+static GSequenceIter *
+lbm_last_descendant(GSequenceIter * node)
+{
+ GSequence *children;
+
+ while ((children = lbm_node_get_children(node)))
+ node = g_sequence_iter_prev(g_sequence_get_end_iter(children));
+
+ return node;
+}
+
+static GSequenceIter *
+lbm_prev(GSequenceIter * node)
+{
+ /* previous is: if we have a sibling,
+ * if it has children, its last descendant;
+ * else the sibling;
+ * else our parent. */
+ if (!g_sequence_iter_is_begin(node))
+ return lbm_last_descendant(g_sequence_iter_prev(node));
+
+ if (libbalsa_mailbox_get_parent(node))
+ return libbalsa_mailbox_get_parent(node);
+
+ return NULL;
+}
+
+/*
+ * End of msg_tree functions.
+ */
+
void
libbalsa_mailbox_close(LibBalsaMailbox * mailbox, gboolean expunge)
{
@@ -583,7 +793,7 @@
LIBBALSA_MAILBOX_GET_CLASS(mailbox)->close_mailbox(mailbox, expunge);
gdk_threads_enter();
if(mailbox->msg_tree) {
- g_node_destroy(mailbox->msg_tree);
+ g_sequence_free(mailbox->msg_tree);
mailbox->msg_tree = NULL;
}
gdk_threads_leave();
@@ -901,7 +1111,7 @@
((gdouble) (mcd->current_idx + 1)) /
((gdouble) mcd->msgnos->len));
mcd->current_idx++;
-
+
*flags = 0;
/* Copy flags. */
if (msgno_has_flags(mailbox, msgno, LIBBALSA_MESSAGE_FLAG_NEW, 0))
@@ -1038,13 +1248,13 @@
if (stat (path, &st) == -1)
return G_TYPE_OBJECT;
-
+
if (S_ISDIR (st.st_mode)) {
/* check for maildir-style mailbox */
snprintf (tmp, sizeof (tmp), "%s/cur", path);
if (stat (tmp, &st) == 0 && S_ISDIR (st.st_mode))
return LIBBALSA_TYPE_MAILBOX_MAILDIR;
-
+
/* check for mh-style mailbox */
snprintf (tmp, sizeof (tmp), "%s/.mh_sequences", path);
if (access (tmp, F_OK) == 0)
@@ -1053,7 +1263,7 @@
snprintf (tmp, sizeof (tmp), "%s/.xmhcache", path);
if (access (tmp, F_OK) == 0)
return LIBBALSA_TYPE_MAILBOX_MH;
-
+
snprintf (tmp, sizeof (tmp), "%s/.mew_cache", path);
if (access (tmp, F_OK) == 0)
return LIBBALSA_TYPE_MAILBOX_MH;
@@ -1094,70 +1304,33 @@
* a GtkTreeView, so the emission must be made holding the gdk lock.
*/
-#if CACHE_UNSEEN_CHILD
-/* Does the node have an unseen child? */
-static gboolean
-lbm_node_has_unseen_child(LibBalsaMailbox * mailbox, GNode * node)
-{
- if (!node)
- return FALSE;
- for (node = node->children; node; node = node->next) {
- guint msgno = GPOINTER_TO_UINT(node->data);
- LibBalsaMailboxIndexEntry *entry =
- g_ptr_array_index(mailbox->mindex, msgno - 1);
- if (entry && (entry->unseen || entry->has_unseen_child))
- return TRUE;
- }
- return FALSE;
-}
-
-/* Called when a row is changed: check ancestors' has_unread_child
- * status. */
-static void
-lbm_entry_check(LibBalsaMailbox * mailbox, guint msgno)
-{
- LibBalsaMailboxIndexEntry *entry;
- GNode *node;
- gboolean unread;
-
- entry = g_ptr_array_index(mailbox->mindex, msgno - 1);
- if (!entry)
- return;
- if (!mailbox->msg_tree)
- return;
- node = g_node_find(mailbox->msg_tree, G_PRE_ORDER, G_TRAVERSE_ALL,
- GUINT_TO_POINTER(msgno));
- if (!node)
- return;
-
- unread = (entry->status_icon == LIBBALSA_MESSAGE_STATUS_UNREAD);
- while ((node = node->parent) && (msgno = GPOINTER_TO_UINT(node->data))) {
- entry = g_ptr_array_index(mailbox->mindex, msgno - 1);
- if(entry) /* We may have info about the children but not about
- * the parent: eg. imap. */
- entry->has_unseen_child =
- unread ? 1 : lbm_node_has_unseen_child(mailbox, node);
- }
-}
-#else /* CACHE_UNSEEN_CHILD */
static LibBalsaMailboxIndexEntry *lbm_get_index_entry(LibBalsaMailbox *
- lmm, GNode * node);
+ lmm,
+ GSequenceIter *
+ node);
/* Does the node (non-NULL) have unseen children? */
static gboolean
-lbm_node_has_unseen_child(LibBalsaMailbox * lmm, GNode * node)
+lbm_node_has_unseen_child(LibBalsaMailbox * lmm, GSequenceIter * node)
{
- for (node = node->children; node; node = node->next) {
- LibBalsaMailboxIndexEntry *entry =
- /* g_ptr_array_index(lmm->mindex, msgno - 1); ?? */
- lbm_get_index_entry(lmm, node);
- if ((entry && entry->unseen) || lbm_node_has_unseen_child(lmm, node))
- return TRUE;
+ GSequence *children;
+
+ if ((children = lbm_node_get_children(node))) {
+ GSequenceIter *end = g_sequence_get_end_iter(children);
+
+ for (node = g_sequence_get_begin_iter(children);
+ node != end; node = g_sequence_iter_next(node)) {
+ LibBalsaMailboxIndexEntry *entry =
+ /* g_ptr_array_index(lmm->mindex, msgno - 1); ?? */
+ lbm_get_index_entry(lmm, node);
+ if ((entry && entry->unseen)
+ || lbm_node_has_unseen_child(lmm, node))
+ return TRUE;
+ }
}
+
return FALSE;
}
-#endif /* CACHE_UNSEEN_CHILD */
-/* Called with gdk lock held. */
static void
lbm_msgno_changed(LibBalsaMailbox * mailbox, guint seqno,
GtkTreeIter * iter)
@@ -1174,9 +1347,7 @@
return;
if (iter->user_data == NULL)
- iter->user_data =
- g_node_find(mailbox->msg_tree, G_PRE_ORDER, G_TRAVERSE_ALL,
- GUINT_TO_POINTER(seqno));
+ iter->user_data = lbm_node_find(mailbox->msg_tree, seqno);
/* trying to modify seqno that is not in the tree? Possible for
* filtered views... Perhaps there is nothing to worry about.
*/
@@ -1188,10 +1359,6 @@
g_signal_emit(mailbox, libbalsa_mbox_model_signals[ROW_CHANGED], 0,
path, iter);
gtk_tree_path_free(path);
-
-#if CACHE_UNSEEN_CHILD
- lbm_entry_check(mailbox, seqno);
-#endif /* CACHE_UNSEEN_CHILD */
}
void
@@ -1210,43 +1377,60 @@
/* Parents' style may need to be changed also. */
while (iter.user_data) {
- GNode *parent = ((GNode *) iter.user_data)->parent;
+ GSequenceIter *parent = libbalsa_mailbox_get_parent(iter.user_data);
iter.user_data = parent;
- if (parent && (seqno = GPOINTER_TO_UINT(parent->data)) > 0)
+ if (parent && (seqno = libbalsa_mailbox_get_msgno(parent)) > 0)
lbm_msgno_changed(mailbox, seqno, &iter);
}
gdk_threads_leave();
}
-void
+/*
+ * Create a node for seqno, after sibling and as a child of parent.
+ * If sibling is NULL, the node will be the first child of parent.
+ * If parent is NULL, the node will be at the top level, in
+ * the GSequence mailbox->msg_tree.
+ * Returns the GSequenceIter pointing to the new node.
+ */
+GSequenceIter *
libbalsa_mailbox_msgno_inserted(LibBalsaMailbox *mailbox, guint seqno,
- GNode * parent, GNode ** sibling)
+ GSequenceIter * parent,
+ GSequenceIter * sibling)
{
- GtkTreeIter iter;
- GtkTreePath *path;
GSList **unthreaded;
+ LibBalsaMailboxSequenceInfo *info;
+ GSequenceIter *insert;
if (!libbalsa_threads_has_lock())
g_warning("Thread is not holding gdk lock");
if (!mailbox->msg_tree)
- return;
-#undef SANITY_CHECK
-#ifdef SANITY_CHECK
- g_return_if_fail(!g_node_find(mailbox->msg_tree,
- G_PRE_ORDER, G_TRAVERSE_ALL,
- GUINT_TO_POINTER(seqno)));
-#endif
+ return NULL;
/* Insert node into the message tree before getting path. */
- iter.user_data = g_node_new(GUINT_TO_POINTER(seqno));
- iter.stamp = mailbox->stamp;
- *sibling = g_node_insert_after(parent, *sibling, iter.user_data);
+ info = g_new(LibBalsaMailboxSequenceInfo, 1);
+ info->parent = parent;
+ info->msgno = seqno;
+ info->children = NULL;
+
+ if (sibling) {
+ insert = g_sequence_iter_next(sibling);
+ insert = g_sequence_insert_before(insert, info);
+ } else {
+ GSequence *seq =
+ parent ? lbm_node_init_children(parent) : mailbox->msg_tree;
+ insert = g_sequence_prepend(seq, info);
+ }
if (g_signal_has_handler_pending(mailbox,
libbalsa_mbox_model_signals
[ROW_INSERTED], 0, FALSE)) {
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ iter.user_data = insert;
+ iter.stamp = mailbox->stamp;
path = gtk_tree_model_get_path(GTK_TREE_MODEL(mailbox), &iter);
g_signal_emit(mailbox, libbalsa_mbox_model_signals[ROW_INSERTED],
0, path, &iter);
@@ -1260,129 +1444,105 @@
g_slist_prepend(*unthreaded, GUINT_TO_POINTER(seqno));
mailbox->msg_tree_changed = TRUE;
+
+ return insert;
}
-void
-libbalsa_mailbox_msgno_filt_in(LibBalsaMailbox *mailbox, guint seqno)
+static void
+lbm_msgno_filt_in(LibBalsaMailbox *mailbox, guint seqno)
{
GtkTreeIter iter;
GtkTreePath *path;
-
- gdk_threads_enter();
- if (!mailbox->msg_tree) {
- gdk_threads_leave();
- return;
- }
+ LibBalsaMailboxSequenceInfo *info;
/* Insert node into the message tree before getting path. */
- iter.user_data = g_node_new(GUINT_TO_POINTER(seqno));
+ info = g_new0(LibBalsaMailboxSequenceInfo, 1);
+ info->msgno = seqno;
+ iter.user_data = g_sequence_prepend(mailbox->msg_tree, info);
iter.stamp = mailbox->stamp;
- g_node_prepend(mailbox->msg_tree, iter.user_data);
- path = gtk_tree_model_get_path(GTK_TREE_MODEL(mailbox), &iter);
+ /* This item is now the first in the tree: */
+ path = gtk_tree_path_new_first();
g_signal_emit(mailbox, libbalsa_mbox_model_signals[ROW_INSERTED], 0,
path, &iter);
gtk_tree_path_free(path);
mailbox->msg_tree_changed = TRUE;
g_signal_emit(mailbox, libbalsa_mailbox_signals[CHANGED], 0);
-
- gdk_threads_leave();
}
-struct remove_data {LibBalsaMailbox *mailbox; unsigned seqno; GNode *node; };
+struct remove_data {
+ LibBalsaMailbox *mailbox;
+ unsigned seqno;
+ GSequenceIter *node;
+};
+
+/* LBMTraverseFunc for finding a deleted message, and updating msgnos. */
static gboolean
-decrease_post(GNode *node, gpointer data)
+decrease_post(GSequenceIter * node, gpointer data)
{
+ LibBalsaMailboxSequenceInfo *info = g_sequence_get(node);
struct remove_data *dt = (struct remove_data*)data;
- unsigned seqno = GPOINTER_TO_UINT(node->data);
+ unsigned seqno = info->msgno;
+
if(seqno == dt->seqno)
dt->node = node;
- else if(seqno>dt->seqno) {
+ else if (seqno > dt->seqno) {
GtkTreeIter iter;
- node->data = GUINT_TO_POINTER(seqno-1);
+
+ --info->msgno;
iter.user_data = node;
lbm_msgno_changed(dt->mailbox, seqno, &iter);
}
+
return FALSE;
}
-void
-libbalsa_mailbox_msgno_removed(LibBalsaMailbox * mailbox, guint seqno)
+static void
+lbm_node_remove(LibBalsaMailbox * mailbox, GSequenceIter * node)
{
GtkTreeIter iter;
GtkTreePath *path;
- struct remove_data dt;
- GNode *child;
- GNode *parent;
-
- g_signal_emit(mailbox, libbalsa_mailbox_signals[MESSAGE_EXPUNGED],
- 0, seqno);
-
- gdk_threads_enter();
- if (!mailbox->msg_tree) {
- gdk_threads_leave();
- return;
- }
+ LibBalsaMailboxSequenceInfo *info = g_sequence_get(node);
+ GSequenceIter *parent = info->parent;
+ GSequence *children = info->children;
+ GSequenceIter *begin, *end;
- dt.mailbox = mailbox;
- dt.seqno = seqno;
- dt.node = NULL;
-
- g_node_traverse(mailbox->msg_tree, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
- decrease_post, &dt);
-
- if (seqno <= mailbox->mindex->len) {
- libbalsa_mailbox_index_entry_free(g_ptr_array_index(mailbox->mindex,
- seqno - 1));
- g_ptr_array_remove_index(mailbox->mindex, seqno - 1);
- }
-
- mailbox->msg_tree_changed = TRUE;
-
- if (!dt.node) {
- /* It's ok, apparently the view did not include this message */
- gdk_threads_leave();
- return;
- }
-
- iter.user_data = dt.node;
+ iter.user_data = node;
iter.stamp = mailbox->stamp;
path = gtk_tree_model_get_path(GTK_TREE_MODEL(mailbox), &iter);
- /* First promote any children to the node's parent; we'll insert
+ /* First promote any children to be the node's siblings; we'll insert
* them all before the current node, to keep the path calculation
* simple. */
- parent = dt.node->parent;
- while ((child = dt.node->children)) {
- GSList **unthreaded;
- /* No need to notify the tree-view about unlinking the child--it
- * will assume we already did that when we notify it about
- * destroying the parent. */
- g_node_unlink(child);
- g_node_insert_before(parent, dt.node, child);
-
- /* Notify the tree-view about the new location of the child. */
- iter.user_data = child;
- g_signal_emit(mailbox, libbalsa_mbox_model_signals[ROW_INSERTED], 0,
- path, &iter);
- if (child->children)
+ if (children
+ && (begin = g_sequence_get_begin_iter(children))
+ != (end = g_sequence_get_end_iter(children))) {
+ g_sequence_move_range(node, begin, end);
+
+ for (; begin != node; begin = g_sequence_iter_next(begin)) {
+ LibBalsaMailboxSequenceInfo *child_info =
+ g_sequence_get(begin);
+
+ child_info->parent = parent;
+ iter.user_data = begin;
g_signal_emit(mailbox,
- libbalsa_mbox_model_signals[ROW_HAS_CHILD_TOGGLED],
- 0, path, &iter);
- gtk_tree_path_next(path);
-
- unthreaded = g_object_get_data(G_OBJECT(mailbox),
- LIBBALSA_MAILBOX_UNTHREADED);
- if (unthreaded)
- *unthreaded = g_slist_prepend(*unthreaded, child->data);
+ libbalsa_mbox_model_signals[ROW_INSERTED], 0,
+ path, &iter);
+ if (lbm_node_get_children(begin))
+ g_signal_emit(mailbox,
+ libbalsa_mbox_model_signals
+ [ROW_HAS_CHILD_TOGGLED], 0, path, &iter);
+ gtk_tree_path_next(path);
+ }
}
/* Now it's safe to destroy the node. */
- g_node_destroy(dt.node);
+ g_sequence_remove(node);
g_signal_emit(mailbox, libbalsa_mbox_model_signals[ROW_DELETED], 0, path);
- if (parent->parent && !parent->children) {
+ if (parent && !lbm_node_get_children(parent)) {
+ /* We just removed the last child */
gtk_tree_path_up(path);
iter.user_data = parent;
g_signal_emit(mailbox,
@@ -1391,75 +1551,45 @@
}
gtk_tree_path_free(path);
- mailbox->stamp++;
- gdk_threads_leave();
+ mailbox->stamp++;
+ mailbox->msg_tree_changed = TRUE;
+ g_signal_emit(mailbox, libbalsa_mailbox_signals[CHANGED], 0);
}
void
-libbalsa_mailbox_msgno_filt_out(LibBalsaMailbox * mailbox, guint seqno)
+libbalsa_mailbox_msgno_removed(LibBalsaMailbox * mailbox, guint seqno)
{
- GtkTreeIter iter;
- GtkTreePath *path;
- GNode *child, *parent, *node;
+ struct remove_data dt;
+
+ g_signal_emit(mailbox, libbalsa_mailbox_signals[MESSAGE_EXPUNGED],
+ 0, seqno);
gdk_threads_enter();
- if (!mailbox->msg_tree) {
- gdk_threads_leave();
- return;
- }
- node = g_node_find(mailbox->msg_tree, G_PRE_ORDER, G_TRAVERSE_ALL,
- GUINT_TO_POINTER(seqno));
- if (!node) {
- g_warning("filt_out: msgno %d not found", seqno);
+ if (!mailbox->msg_tree) {
gdk_threads_leave();
return;
}
- iter.user_data = node;
- iter.stamp = mailbox->stamp;
- path = gtk_tree_model_get_path(GTK_TREE_MODEL(mailbox), &iter);
-
- /* First promote any children to the node's parent; we'll insert
- * them all before the current node, to keep the path calculation
- * simple. */
- parent = node->parent;
- while ((child = node->children)) {
- /* No need to notify the tree-view about unlinking the child--it
- * will assume we already did that when we notify it about
- * destroying the parent. */
- g_node_unlink(child);
- g_node_insert_before(parent, node, child);
-
- /* Notify the tree-view about the new location of the child. */
- iter.user_data = child;
- g_signal_emit(mailbox, libbalsa_mbox_model_signals[ROW_INSERTED], 0,
- path, &iter);
- if (child->children)
- g_signal_emit(mailbox,
- libbalsa_mbox_model_signals[ROW_HAS_CHILD_TOGGLED],
- 0, path, &iter);
- gtk_tree_path_next(path);
+ if (seqno <= mailbox->mindex->len) {
+ libbalsa_mailbox_index_entry_free(g_ptr_array_index(mailbox->mindex,
+ seqno - 1));
+ g_ptr_array_remove_index(mailbox->mindex, seqno - 1);
}
- /* Now it's safe to destroy the node. */
- g_node_destroy(node);
- g_signal_emit(mailbox, libbalsa_mbox_model_signals[ROW_DELETED], 0, path);
+ dt.mailbox = mailbox;
+ dt.seqno = seqno;
+ dt.node = NULL;
+ libbalsa_mailbox_traverse(mailbox, G_PRE_ORDER, decrease_post, &dt);
- if (parent->parent && !parent->children) {
- gtk_tree_path_up(path);
- iter.user_data = parent;
- g_signal_emit(mailbox,
- libbalsa_mbox_model_signals[ROW_HAS_CHILD_TOGGLED], 0,
- path, &iter);
+ if (!dt.node) {
+ /* It's ok, apparently the view did not include this message */
+ gdk_threads_leave();
+ return;
}
-
- gtk_tree_path_free(path);
- mailbox->stamp++;
- mailbox->msg_tree_changed = TRUE;
- g_signal_emit(mailbox, libbalsa_mailbox_signals[CHANGED], 0);
+ lbm_node_remove(mailbox, dt.node);
gdk_threads_leave();
}
@@ -1477,6 +1607,7 @@
gboolean hold_selected)
{
gboolean match;
+ GSequenceIter *node;
g_return_if_fail(LIBBALSA_IS_MAILBOX(mailbox));
@@ -1489,19 +1620,18 @@
match = search_iter ?
libbalsa_mailbox_message_match(mailbox, seqno, search_iter) : TRUE;
- if (g_node_find(mailbox->msg_tree, G_PRE_ORDER, G_TRAVERSE_ALL,
- GUINT_TO_POINTER(seqno))) {
+ if ((node = lbm_node_find(mailbox->msg_tree, seqno)) != NULL) {
if (!match) {
gboolean filt_out = hold_selected ?
libbalsa_mailbox_msgno_has_flags(mailbox, seqno, 0,
LIBBALSA_MESSAGE_FLAG_SELECTED)
: TRUE;
if (filt_out)
- libbalsa_mailbox_msgno_filt_out(mailbox, seqno);
+ lbm_node_remove(mailbox, node);
}
} else {
if (match)
- libbalsa_mailbox_msgno_filt_in(mailbox, seqno);
+ lbm_msgno_filt_in(mailbox, seqno);
}
gdk_threads_leave();
@@ -1550,56 +1680,6 @@
g_free(search_iter);
}
-/* GNode iterators; they return the root node when they run out of nodes,
- * and find the appropriate starting node when called with the root. */
-static GNode *
-lbm_next(GNode * node)
-{
- /* next is: our first child, if we have one;
- * else our sibling, if we have one;
- * else the sibling of our first ancestor who has
- * one. */
- if (node->children)
- return node->children;
-
- do {
- if (node->next)
- return node->next;
- node = node->parent;
- } while (!G_NODE_IS_ROOT(node));
-
- return node;
-}
-
-static GNode *
-lbm_last_descendant(GNode * node)
-{
- if (node->children) {
- GNode *tmp;
-
- node = node->children;
- while ((tmp = node->next) || (tmp = node->children))
- node = tmp;
- }
- return node;
-}
-
-static GNode *
-lbm_prev(GNode * node)
-{
- if (G_NODE_IS_ROOT(node))
- return lbm_last_descendant(node);
-
- /* previous is: if we have a sibling,
- * if it has children, its last descendant;
- * else the sibling;
- * else our parent. */
- if (node->prev)
- return lbm_last_descendant(node->prev);
-
- return node->parent;
-}
-
/* Find a message in the tree-model, by its message number. */
gboolean
libbalsa_mailbox_msgno_find(LibBalsaMailbox * mailbox, guint seqno,
@@ -1613,8 +1693,7 @@
g_return_val_if_fail(seqno > 0, FALSE);
if (!mailbox->msg_tree || !(tmp_iter.user_data =
- g_node_find(mailbox->msg_tree, G_PRE_ORDER, G_TRAVERSE_ALL,
- GINT_TO_POINTER(seqno))))
+ lbm_node_find(mailbox->msg_tree, seqno)))
return FALSE;
tmp_iter.stamp = mailbox->stamp;
@@ -2059,39 +2138,7 @@
return LIBBALSA_MAILBOX_GET_CLASS(mailbox)->can_do(mailbox, cap);
}
-
-#if CACHE_UNSEEN_CHILD
-/* GNode traverse func, called top-down: clear the current node's
- * has_unseen_child flag, and if current node is unseen, set ancestors'
- * flags; break when we find an ancestor with the flag already set,
- * because all further ancestors must also have it set. */
-static gboolean
-lbm_check_unseen_child(GNode * node, LibBalsaMailbox * mailbox)
-{
- LibBalsaMailboxIndexEntry *entry;
- guint msgno = GPOINTER_TO_UINT(node->data);
- if (msgno == 0)
- return FALSE;
- entry = g_ptr_array_index(mailbox->mindex, msgno - 1);
- if (!entry)
- return FALSE;
- entry->has_unseen_child = 0;
- if (entry->status_icon == LIBBALSA_MESSAGE_STATUS_UNREAD) {
- while ((node = node->parent)
- && (msgno = GPOINTER_TO_UINT(node->data))) {
- entry = g_ptr_array_index(mailbox->mindex, msgno - 1);
- if (!entry)
- continue;
- if (entry->has_unseen_child)
- break;
- entry->has_unseen_child = 1;
- }
- }
- return FALSE;
-}
-#endif /* CACHE_UNSEEN_CHILD */
-
-static void lbm_sort(LibBalsaMailbox * mbox, GNode * parent);
+static void lbm_sort_seq(LibBalsaMailbox * mbox, GSequence * seq);
static gboolean
lbm_set_threading(LibBalsaMailbox * mailbox,
LibBalsaMailboxThreadingType thread_type)
@@ -2103,12 +2150,7 @@
thread_type);
gdk_threads_enter();
if (mailbox->msg_tree)
- lbm_sort(mailbox, mailbox->msg_tree);
-
-#if CACHE_UNSEEN_CHILD
- g_node_traverse(mailbox->msg_tree, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
- (GNodeTraverseFunc) lbm_check_unseen_child, mailbox);
-#endif /* CACHE_UNSEEN_CHILD */
+ lbm_sort_seq(mailbox, mailbox->msg_tree);
libbalsa_mailbox_changed(mailbox);
gdk_threads_leave();
@@ -2671,50 +2713,25 @@
}
static GtkTreePath *
-mbox_model_get_path_helper(GNode * node, GNode * msg_tree)
+mbox_model_get_path_helper(GSequenceIter * node)
{
GtkTreePath *path = gtk_tree_path_new();
- while (node->parent) {
- gint i = g_node_child_position(node->parent, node);
- if (i < 0) {
- gtk_tree_path_free(path);
- return NULL;
- }
- gtk_tree_path_prepend_index(path, i);
- node = node->parent;
- }
+ do
+ gtk_tree_path_prepend_index(path, g_sequence_iter_get_position(node));
+ while ((node = libbalsa_mailbox_get_parent(node)) != NULL);
- if (node == msg_tree)
- return path;
- gtk_tree_path_free(path);
- return NULL;
+ return path;
}
static GtkTreePath *
mbox_model_get_path(GtkTreeModel * tree_model, GtkTreeIter * iter)
{
- GNode *node;
-#ifdef SANITY_CHECK
- GNode *parent_node;
-#endif
-
if (!libbalsa_threads_has_lock())
g_warning("Thread is not holding gdk lock");
g_return_val_if_fail(VALID_ITER(iter, tree_model), NULL);
- node = iter->user_data;
-#ifdef SANITY_CHECK
- for (parent_node = node->parent; parent_node;
- parent_node = parent_node->parent)
- g_return_val_if_fail(parent_node != node, NULL);
-#endif
-
- g_return_val_if_fail(node->parent != NULL, NULL);
-
- return mbox_model_get_path_helper(node,
- LIBBALSA_MAILBOX(tree_model)->
- msg_tree);
+ return mbox_model_get_path_helper(iter->user_data);
}
/* mbox_model_get_value:
@@ -2798,9 +2815,9 @@
#endif /*BALSA_USE_THREADS */
static LibBalsaMailboxIndexEntry *
-lbm_get_index_entry(LibBalsaMailbox * lmm, GNode * node)
+lbm_get_index_entry(LibBalsaMailbox * lmm, GSequenceIter * node)
{
- guint msgno = GPOINTER_TO_UINT(node->data);
+ guint msgno = libbalsa_mailbox_get_msgno(node);
LibBalsaMailboxIndexEntry *entry;
if (!lmm->mindex)
@@ -2862,13 +2879,13 @@
LibBalsaMailboxIndexEntry* msg = NULL;
guint msgno;
gchar *tmp;
-
+
g_return_if_fail(VALID_ITER(iter, tree_model));
g_return_if_fail(column >= 0 &&
column < (int) ELEMENTS(mbox_model_col_type));
-
+
g_value_init (value, mbox_model_col_type[column]);
- msgno = GPOINTER_TO_UINT( ((GNode*)iter->user_data)->data );
+ msgno = libbalsa_mailbox_get_msgno(iter->user_data);
if(column == LB_MBOX_MSGNO_COL) {
g_value_set_uint(value, msgno);
@@ -2880,7 +2897,7 @@
/* With gtk-2.8.0, we can finally use fixed-row-height model
without workarounds. */
#if GTK_CHECK_VERSION(2,8,0)
- msg = lbm_get_index_entry(lmm, (GNode *) iter->user_data);
+ msg = lbm_get_index_entry(lmm, iter->user_data);
#else
{ GdkRectangle a, b, c, d;
/* assumed that only one view is showing the mailbox */
@@ -2902,7 +2919,7 @@
&c.width, &c.height);
c.width -= c.x; c.height -= c.y;
if (gdk_rectangle_intersect(&a, &c, &d))
- msg = lbm_get_index_entry(lmm, (GNode *) iter->user_data);
+ msg = lbm_get_index_entry(lmm, iter->user_data);
gtk_tree_path_free(path);
}
}
@@ -2948,15 +2965,9 @@
? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
break;
case LB_MBOX_STYLE_COL:
-#if CACHE_UNSEEN_CHILD
- g_value_set_uint(value, msg && msg->has_unseen_child
- ? PANGO_STYLE_OBLIQUE : PANGO_STYLE_NORMAL);
-#else /* CACHE_UNSEEN_CHILD */
g_value_set_uint(value, msg &&
- lbm_node_has_unseen_child(lmm,
- (GNode *) iter->user_data)
- ? PANGO_STYLE_OBLIQUE : PANGO_STYLE_NORMAL);
-#endif /* CACHE_UNSEEN_CHILD */
+ lbm_node_has_unseen_child(lmm, iter->user_data) ?
+ PANGO_STYLE_OBLIQUE : PANGO_STYLE_NORMAL);
break;
}
}
@@ -2965,18 +2976,22 @@
mbox_model_iter_next(GtkTreeModel *tree_model,
GtkTreeIter *iter)
{
- GNode *node;
+ GSequenceIter *node;
+
g_return_val_if_fail(VALID_ITER(iter, tree_model), FALSE);
node = iter->user_data;
- if(node && (node = node->next)) {
- iter->user_data = node;
- VALIDATE_ITER(iter, tree_model);
- return TRUE;
- } else {
- INVALIDATE_ITER(iter);
- return FALSE;
+ if (node) {
+ node = g_sequence_iter_next(node);
+ if (!g_sequence_iter_is_end(node)) {
+ iter->user_data = node;
+ VALIDATE_ITER(iter, tree_model);
+ return TRUE;
+ }
}
+
+ INVALIDATE_ITER(iter);
+ return FALSE;
}
static gboolean
@@ -2984,17 +2999,17 @@
GtkTreeIter *iter,
GtkTreeIter *parent)
{
- GNode *node;
+ GSequence *seq;
INVALIDATE_ITER(iter);
g_return_val_if_fail(parent == NULL ||
VALID_ITER(parent, tree_model), FALSE);
- node = parent ? parent->user_data
- : LIBBALSA_MAILBOX(tree_model)->msg_tree;
- node = node->children;
- if (node) {
- iter->user_data = node;
+ seq = parent ? lbm_node_get_children(parent->user_data)
+ : LIBBALSA_MAILBOX(tree_model)->msg_tree;
+
+ if (seq && g_sequence_get_length(seq) > 0) {
+ iter->user_data = g_sequence_get_begin_iter(seq);
VALIDATE_ITER(iter, tree_model);
return TRUE;
} else
@@ -3005,28 +3020,24 @@
mbox_model_iter_has_child(GtkTreeModel * tree_model,
GtkTreeIter * iter)
{
- GNode *node;
-
g_return_val_if_fail(VALID_ITER(iter, LIBBALSA_MAILBOX(tree_model)),
FALSE);
- node = iter->user_data;
-
- return (node->children != NULL);
+ return lbm_node_get_children(iter->user_data) != NULL;
}
static gint
mbox_model_iter_n_children(GtkTreeModel *tree_model,
GtkTreeIter *iter)
{
- GNode *node;
+ GSequence *seq;
g_return_val_if_fail(iter == NULL || VALID_ITER(iter, tree_model), 0);
- node = iter ? iter->user_data
- : LIBBALSA_MAILBOX(tree_model)->msg_tree;
+ seq = iter ? lbm_node_get_children(iter->user_data)
+ : LIBBALSA_MAILBOX(tree_model)->msg_tree;
- return node ? g_node_n_children(node) : 0;
+ return seq ? g_sequence_get_length(seq) : 0;
}
static gboolean
@@ -3035,7 +3046,8 @@
GtkTreeIter * parent,
gint n)
{
- GNode *node;
+ GSequence *seq;
+ GSequenceIter *node;
INVALIDATE_ITER(iter);
if(!LIBBALSA_MAILBOX(tree_model)->msg_tree)
@@ -3046,14 +3058,17 @@
g_return_val_if_fail(parent == NULL
||VALID_ITER(parent, tree_model), FALSE);
- node = parent ? parent->user_data
- : LIBBALSA_MAILBOX(tree_model)->msg_tree;
- if(!node) /* the tree has been destroyed already (mailbox has been
+ seq = parent ? lbm_node_get_children(parent->user_data)
+ : LIBBALSA_MAILBOX(tree_model)->msg_tree;
+ if(!seq) /* the tree has been destroyed already (mailbox has been
* closed), there is nothing to iterate over. This happens
* only if mailbox is closed but a view is still active.
*/
return FALSE;
- node = g_node_nth_child(node, n);
+
+ node = g_sequence_get_iter_at_pos(seq, n);
+ if (g_sequence_iter_is_end(node))
+ node = NULL;
if (node) {
iter->user_data = node;
@@ -3068,15 +3083,15 @@
GtkTreeIter * iter,
GtkTreeIter * child)
{
- GNode *node;
+ GSequenceIter *node;
INVALIDATE_ITER(iter);
g_return_val_if_fail(iter != NULL, FALSE);
g_return_val_if_fail(VALID_ITER(child, tree_model), FALSE);
node = child->user_data;
- node = node->parent;
- if (node && node != LIBBALSA_MAILBOX(tree_model)->msg_tree) {
+ node = libbalsa_mailbox_get_parent(node);
+ if (node) {
iter->user_data = node;
VALIDATE_ITER(iter, tree_model);
return TRUE;
@@ -3283,8 +3298,8 @@
guint msgno_b;
gint retval;
- msgno_a = GPOINTER_TO_UINT(a->node->data);
- msgno_b = GPOINTER_TO_UINT(b->node->data);
+ msgno_a = libbalsa_mailbox_get_msgno(a->node);
+ msgno_b = libbalsa_mailbox_get_msgno(b->node);
if (mbox->view->sort_field == LB_MAILBOX_SORT_NO)
retval = msgno_a - msgno_b;
else {
@@ -3342,13 +3357,32 @@
return VALID_ENTRY(entry);
}
+static void lbm_sort_seq_with_parent(LibBalsaMailbox * mbox,
+ GSequence * seq,
+ GSequenceIter * parent);
+
+static void
+lbm_sort_seq(LibBalsaMailbox * mbox, GSequence * seq)
+{
+ lbm_sort_seq_with_parent(mbox, seq, NULL);
+}
+
static void
-lbm_sort(LibBalsaMailbox * mbox, GNode * parent)
+lbm_sort_children(LibBalsaMailbox * mbox, GSequenceIter * parent)
{
+ lbm_sort_seq_with_parent(mbox, lbm_node_get_children(parent), parent);
+}
+
+static void
+lbm_sort_seq_with_parent(LibBalsaMailbox * mbox,
+ GSequence * seq,
+ GSequenceIter * parent)
+{
+ gint seq_length;
GtkTreeIter iter;
GArray *sort_array;
GPtrArray *node_array;
- GNode *node, *tmp_node, *prev;
+ GSequenceIter *node, *tmp_node, *prev, *end;
guint i, j;
gint *new_order;
GtkTreePath *path;
@@ -3358,22 +3392,25 @@
#else
gboolean can_sort_all = 1;
#endif
- node = parent->children;
- if (!node)
+
+ if (!seq || (seq_length = g_sequence_get_length(seq)) == 0)
return;
- if (node->next == NULL) {
- lbm_sort(mbox, node);
+ node = g_sequence_get_begin_iter(seq);
+ if (seq_length == 1) {
+ lbm_sort_children(mbox, node);
return;
}
sort_array = g_array_new(FALSE, FALSE, sizeof(SortTuple));
node_array = g_ptr_array_new();
- for (tmp_node = node; tmp_node; tmp_node = tmp_node->next) {
+ end = g_sequence_get_end_iter(seq);
+ for (tmp_node = node; tmp_node != end;
+ tmp_node = g_sequence_iter_next(tmp_node)) {
SortTuple sort_tuple;
- guint msgno = GPOINTER_TO_UINT(tmp_node->data);
+ guint msgno = libbalsa_mailbox_get_msgno(tmp_node);
- if (can_sort_all || lbm_has_valid_index_entry(mbox, msgno)) {
+ if (can_sort_all || lbm_has_valid_index_entry(mbox, msgno)) {
/* We have the sort fields. */
sort_tuple.offset = node_array->len;
sort_tuple.node = tmp_node;
@@ -3385,7 +3422,7 @@
if (sort_array->len <= 1) {
g_array_free(sort_array, TRUE);
g_ptr_array_free(node_array, TRUE);
- lbm_sort(mbox, node);
+ lbm_sort_children(mbox, node);
return;
}
LIBBALSA_MAILBOX_GET_CLASS(mbox)->sort(mbox, sort_array);
@@ -3396,51 +3433,53 @@
guint msgno;
tmp_node = g_ptr_array_index(node_array, i);
- msgno = GPOINTER_TO_UINT(tmp_node->data);
- if (can_sort_all || lbm_has_valid_index_entry(mbox, msgno)) {
+ msgno = libbalsa_mailbox_get_msgno(tmp_node);
+ if (can_sort_all || lbm_has_valid_index_entry(mbox, msgno)) {
/* This is one of the nodes we sorted: find out which one
* goes here. */
g_assert(j < sort_array->len);
tmp_node = g_array_index(sort_array, SortTuple, j++).node;
}
- if (tmp_node->prev != prev) {
- /* Change the links. */
- if (prev)
- prev->next = tmp_node;
- else
- node = parent->children = tmp_node;
- tmp_node->prev = prev;
+ if ((prev && g_sequence_iter_prev(tmp_node) != prev)
+ || (!prev && !g_sequence_iter_is_begin(tmp_node))) {
+ g_sequence_move(tmp_node,
+ prev ? g_sequence_iter_next(prev)
+ : g_sequence_get_begin_iter(seq));
mbox->msg_tree_changed = TRUE;
} else
- g_assert(prev == NULL || prev->next == tmp_node);
+ g_assert(prev == NULL
+ || g_sequence_iter_next(prev) == tmp_node);
prev = tmp_node;
}
- prev->next = NULL;
+ node = g_sequence_get_begin_iter(seq);
/* Let the world know about our new order */
new_order = g_new(gint, node_array->len);
i = j = 0;
- for (tmp_node = node; tmp_node; tmp_node = tmp_node->next) {
- guint msgno = GPOINTER_TO_UINT(tmp_node->data);
- new_order[j] = can_sort_all || lbm_has_valid_index_entry(mbox, msgno)
- ? g_array_index(sort_array, SortTuple, i++).offset
- : j;
+ for (tmp_node = node; tmp_node != end;
+ tmp_node = g_sequence_iter_next(tmp_node)) {
+ guint msgno = libbalsa_mailbox_get_msgno(tmp_node);
+ new_order[j] =
+ can_sort_all || lbm_has_valid_index_entry(mbox, msgno) ?
+ g_array_index(sort_array, SortTuple, i++).offset : j;
j++;
}
iter.stamp = mbox->stamp;
iter.user_data = parent;
- path = parent->parent ? mbox_model_get_path(GTK_TREE_MODEL(mbox), &iter)
- : gtk_tree_path_new();
- gtk_tree_model_rows_reordered(GTK_TREE_MODEL(mbox),
- path, &iter, new_order);
+ path = parent ? mbox_model_get_path(GTK_TREE_MODEL(mbox), &iter)
+ : gtk_tree_path_new();
+ gtk_tree_model_rows_reordered(GTK_TREE_MODEL(mbox), path,
+ parent ? &iter : NULL,
+ new_order);
gtk_tree_path_free(path);
g_free(new_order);
g_array_free(sort_array, TRUE);
g_ptr_array_free(node_array, TRUE);
- for (tmp_node = node; tmp_node; tmp_node = tmp_node->next)
- lbm_sort(mbox, tmp_node);
+ for (tmp_node = node; tmp_node != end;
+ tmp_node = g_sequence_iter_next(tmp_node))
+ lbm_sort_children(mbox, tmp_node);
}
/* called from gtk-tree-view-column */
@@ -3539,7 +3578,7 @@
/* Prepare-threading failed--perhaps mailbox was closed. */
return;
}
- lbm_sort(mbox, mbox->msg_tree);
+ lbm_sort_seq(mbox, mbox->msg_tree);
libbalsa_mailbox_changed(mbox);
}
@@ -3570,84 +3609,88 @@
/* Helpers for set-threading-type. */
void
-libbalsa_mailbox_unlink_and_prepend(LibBalsaMailbox * mailbox,
- GNode * node, GNode * parent)
+libbalsa_mailbox_check_parent(LibBalsaMailbox * mailbox,
+ GSequenceIter * node,
+ GSequenceIter * parent)
{
GtkTreeIter iter;
GtkTreePath *path;
- GNode *current_parent;
+ GSequenceIter *current_parent;
+ GSequence *children;
+ gboolean first_child = FALSE;
if (!libbalsa_threads_has_lock())
g_warning("Thread is not holding gdk lock");
- g_return_if_fail(node != NULL);
- g_return_if_fail(parent != node);
-#ifdef SANITY_CHECK
- g_return_if_fail(!parent || !g_node_is_ancestor(node, parent));
-#endif
+
+ if (libbalsa_mailbox_get_parent(node) == parent
+ || libbalsa_mailbox_node_is_ancestor(node, parent))
+ return;
iter.stamp = mailbox->stamp;
- path = mbox_model_get_path_helper(node, mailbox->msg_tree);
- current_parent = node->parent;
- g_node_unlink(node);
- if (path) {
- /* The node was in mailbox->msg_tree. */
+ /* Get path before moving the node. */
+ path = mbox_model_get_path_helper(node);
+ current_parent = libbalsa_mailbox_get_parent(node);
+
+ children = parent ? lbm_node_get_children(parent) : mailbox->msg_tree;
+ if (!children) {
+ first_child = TRUE;
+ children = lbm_node_init_children(parent);
+ }
+
+ /* Move the node. */
+ g_sequence_move(node, g_sequence_get_begin_iter(children));
+ lbm_node_set_parent(node, parent);
+
+ /* Announce the removal from the old location. */
+ g_signal_emit(mailbox,
+ libbalsa_mbox_model_signals[ROW_DELETED], 0, path);
+ if (current_parent && !lbm_node_get_children(current_parent)) {
+ /* It was the last child. */
+ gtk_tree_path_up(path);
+ iter.user_data = current_parent;
g_signal_emit(mailbox,
- libbalsa_mbox_model_signals[ROW_DELETED], 0, path);
- if (!current_parent->children) {
- /* It was the last child. */
- gtk_tree_path_up(path);
- iter.user_data = current_parent;
- g_signal_emit(mailbox,
- libbalsa_mbox_model_signals[ROW_HAS_CHILD_TOGGLED],
- 0, path, &iter);
- }
- gtk_tree_path_free(path);
+ libbalsa_mbox_model_signals[ROW_HAS_CHILD_TOGGLED],
+ 0, path, &iter);
}
+ gtk_tree_path_free(path);
- if (!parent) {
- g_node_destroy(node);
- return;
+ path = parent ? mbox_model_get_path_helper(parent) : gtk_tree_path_new();
+ if (first_child) {
+ /* Parent now has a child. */
+ iter.user_data = parent;
+ g_signal_emit(mailbox,
+ libbalsa_mbox_model_signals[ROW_HAS_CHILD_TOGGLED],
+ 0, path, &iter);
}
- g_node_prepend(parent, node);
- path = mbox_model_get_path_helper(parent, mailbox->msg_tree);
- if (path) {
- /* The parent is in mailbox->msg_tree. */
- if (!node->next) {
- /* It is the first child. */
- iter.user_data = parent;
- g_signal_emit(mailbox,
- libbalsa_mbox_model_signals[ROW_HAS_CHILD_TOGGLED],
- 0, path, &iter);
- }
- gtk_tree_path_down(path);
- iter.user_data = node;
+ /* Announce the new row, and that it has children. */
+ gtk_tree_path_down(path);
+ iter.user_data = node;
+ g_signal_emit(mailbox,
+ libbalsa_mbox_model_signals[ROW_INSERTED], 0,
+ path, &iter);
+ if (lbm_node_get_children(node))
g_signal_emit(mailbox,
- libbalsa_mbox_model_signals[ROW_INSERTED], 0,
- path, &iter);
- if (node->children)
- g_signal_emit(mailbox,
- libbalsa_mbox_model_signals[ROW_HAS_CHILD_TOGGLED],
- 0, path, &iter);
- gtk_tree_path_free(path);
+ libbalsa_mbox_model_signals[ROW_HAS_CHILD_TOGGLED],
+ 0, path, &iter);
+ gtk_tree_path_free(path);
- mailbox->msg_tree_changed = TRUE;
- }
+ mailbox->msg_tree_changed = TRUE;
}
struct lbm_update_msg_tree_info {
LibBalsaMailbox *mailbox;
GNode *new_tree;
- GNode **nodes;
+ gpointer *nodes;
guint total;
};
/* GNodeTraverseFunc for making a reverse lookup array into a tree. */
static gboolean
-lbm_update_msg_tree_populate(GNode * node,
- struct lbm_update_msg_tree_info *mti)
+lbm_update_msg_tree_gnode_func(GNode * node, gpointer data)
{
+ struct lbm_update_msg_tree_info *mti = data;
guint msgno;
msgno = GPOINTER_TO_UINT(node->data);
@@ -3658,27 +3701,36 @@
return FALSE;
}
-/* GNodeTraverseFunc for pruning the current tree; mti->nodes is a
+/* LBMTraverseFunc for making a reverse lookup array into a tree. */
+static gboolean
+lbm_update_msg_tree_lbmnode_func(GSequenceIter * node, gpointer data)
+{
+ struct lbm_update_msg_tree_info *mti = data;
+ guint msgno;
+
+ msgno = libbalsa_mailbox_get_msgno(node);
+
+ if (msgno < mti->total)
+ mti->nodes[msgno] = node;
+
+ return FALSE;
+}
+
+/* LBMTraverseFunc for pruning the current tree; mti->nodes is a
* reverse lookup array into the new tree, so a NULL value is a node
* that doesn't appear in the new tree. */
static gboolean
-lbm_update_msg_tree_prune(GNode * node,
- struct lbm_update_msg_tree_info *mti)
+lbm_update_msg_tree_prune(GSequenceIter * node, gpointer data)
{
+ struct lbm_update_msg_tree_info *mti = data;
guint msgno;
- msgno = GPOINTER_TO_UINT(node->data);
- if (msgno >= mti->total || !mti->nodes[msgno]) {
+ msgno = libbalsa_mailbox_get_msgno(node);
+ if (msgno >= mti->total || !mti->nodes[msgno])
/* It's a bottom-up traverse, so the node's remaining children
* are all in the new tree; we'll promote them to be children of
* the node's parent, which might even be where they finish up. */
- while (node->children)
- libbalsa_mailbox_unlink_and_prepend(mti->mailbox,
- node->children,
- node->parent);
- /* Now we can destroy the node. */
- libbalsa_mailbox_unlink_and_prepend(mti->mailbox, node, NULL);
- }
+ lbm_node_remove(mti->mailbox, node);
return FALSE;
}
@@ -3692,11 +3744,12 @@
lbm_update_msg_tree_move(GNode * new_node,
struct lbm_update_msg_tree_info *mti)
{
- guint msgno;
- GNode *node;
- GNode *parent;
+ guint msgno, parent_msgno;
+ GSequenceIter *node;
+ GSequenceIter *parent;
if (!new_node->parent)
+ /* Root node of the new tree. */
return FALSE;
msgno = GPOINTER_TO_UINT(new_node->data);
@@ -3704,17 +3757,18 @@
return FALSE;
node = mti->nodes[msgno];
- if (!node)
- mti->nodes[msgno] = node = g_node_new(new_node->data);
- msgno = GPOINTER_TO_UINT(new_node->parent->data);
- if (msgno >= mti->total)
+ parent_msgno = GPOINTER_TO_UINT(new_node->parent->data);
+ if (parent_msgno >= mti->total)
return FALSE;
- parent = mti->nodes[msgno];
+ parent = mti->nodes[parent_msgno];
- if (parent && parent != node->parent)
- libbalsa_mailbox_unlink_and_prepend(mti->mailbox, node, parent);
+ if (node)
+ libbalsa_mailbox_check_parent(mti->mailbox, node, parent);
+ else
+ mti->nodes[msgno] =
+ libbalsa_mailbox_msgno_inserted(mti->mailbox, msgno, parent, NULL);
return FALSE;
}
@@ -3727,20 +3781,20 @@
mti.mailbox = mailbox;
mti.new_tree = new_tree;
mti.total = 1 + libbalsa_mailbox_total_messages(mailbox);
- mti.nodes = g_new0(GNode *, mti.total);
+ mti.nodes = g_new0(gpointer, mti.total);
/* Populate the nodes array with nodes in the new tree. */
g_node_traverse(new_tree, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
- (GNodeTraverseFunc) lbm_update_msg_tree_populate, &mti);
+ lbm_update_msg_tree_gnode_func, &mti);
/* Remove deadwood. */
- g_node_traverse(mailbox->msg_tree, G_POST_ORDER, G_TRAVERSE_ALL, -1,
- (GNodeTraverseFunc) lbm_update_msg_tree_prune, &mti);
+ libbalsa_mailbox_traverse(mailbox, G_POST_ORDER,
+ lbm_update_msg_tree_prune, &mti);
/* Clear the nodes array and repopulate it with nodes in the current
* tree. */
- memset(mti.nodes, 0, sizeof(GNode *) * mti.total);
- g_node_traverse(mailbox->msg_tree, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
- (GNodeTraverseFunc) lbm_update_msg_tree_populate, &mti);
+ memset(mti.nodes, 0, sizeof(gpointer) * mti.total);
+ libbalsa_mailbox_traverse(mailbox, G_PRE_ORDER,
+ lbm_update_msg_tree_lbmnode_func, &mti);
/* Check parent-child relationships. */
g_node_traverse(new_tree, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
(GNodeTraverseFunc) lbm_update_msg_tree_move, &mti);
@@ -3748,53 +3802,17 @@
g_free(mti.nodes);
}
-static void
-lbm_set_msg_tree(LibBalsaMailbox * mailbox)
-{
- GtkTreeIter iter;
- GNode *node;
- GtkTreePath *path;
-
- if (!libbalsa_threads_has_lock())
- g_warning("Thread is not holding gdk lock");
-
- iter.stamp = ++mailbox->stamp;
-
- if (!mailbox->msg_tree)
- return;
-
- path = gtk_tree_path_new();
- gtk_tree_path_down(path);
-
- for (node = mailbox->msg_tree->children; node; node = node->next) {
- iter.user_data = node;
- g_signal_emit(mailbox,
- libbalsa_mbox_model_signals[ROW_INSERTED], 0, path,
- &iter);
- if (node->children)
- g_signal_emit(mailbox,
- libbalsa_mbox_model_signals
- [ROW_HAS_CHILD_TOGGLED], 0, path, &iter);
- gtk_tree_path_next(path);
- }
-
- gtk_tree_path_free(path);
-}
-
void
libbalsa_mailbox_set_msg_tree(LibBalsaMailbox * mailbox, GNode * new_tree)
{
gdk_threads_enter();
- if (mailbox->msg_tree && mailbox->msg_tree->children) {
- lbm_update_msg_tree(mailbox, new_tree);
- g_node_destroy(new_tree);
- } else {
- if (mailbox->msg_tree)
- g_node_destroy(mailbox->msg_tree);
- mailbox->msg_tree = new_tree;
- lbm_set_msg_tree(mailbox);
- }
+ if (!mailbox->msg_tree)
+ mailbox->msg_tree =
+ g_sequence_new((GDestroyNotify) lbm_msg_tree_free_info);
+
+ lbm_update_msg_tree(mailbox, new_tree);
+ g_node_destroy(new_tree);
mailbox->msg_tree_changed = TRUE;
@@ -4151,7 +4169,7 @@
gboolean forward,
guint stop_msgno)
{
- GNode *node;
+ GSequenceIter *node;
gboolean retval = FALSE;
gint total;
@@ -4160,14 +4178,14 @@
node = iter->user_data;
if (!node)
- node = mailbox->msg_tree;
+ node = g_sequence_get_begin_iter(mailbox->msg_tree);
total = libbalsa_mailbox_total_messages(mailbox);
for (;;) {
guint msgno;
node = forward ? lbm_next(node) : lbm_prev(node);
- msgno = GPOINTER_TO_UINT(node->data);
+ msgno = node ? libbalsa_mailbox_get_msgno(node) : 0;
if (msgno == stop_msgno
|| --total < 0 /* Runaway? */ ) {
retval = FALSE;
Modified: branches/mailbox-gsequence/libbalsa/mailbox.h
==============================================================================
--- branches/mailbox-gsequence/libbalsa/mailbox.h (original)
+++ branches/mailbox-gsequence/libbalsa/mailbox.h Sun Jan 27 01:03:05 2008
@@ -88,7 +88,7 @@
/* Sorting */
struct _SortTuple {
guint offset;
- GNode *node;
+ GSequenceIter *node;
};
typedef enum {
@@ -219,7 +219,7 @@
GPtrArray *mindex; /* the basic message index used for index
* displaying/columns of GtkTreeModel interface
* and NOTHING else. */
- GNode *msg_tree; /* the possibly filtered tree of messages;
+ GSequence *msg_tree; /* the possibly filtered tree of messages;
* gdk lock MUST BE HELD when accessing. */
LibBalsaCondition *view_filter; /* to choose a subset of messages
* to be displayed, e.g., only
@@ -512,15 +512,26 @@
to produce a tree of messages. The tree is put in msg_tree and used
later by GtkTreeModel interface.
libbalsa_mailbox_set_threading() is the public method;
- libbalsa_mailbox_set_msg_tree and libbalsa_mailbox_unlink_and_prepend
+ libbalsa_mailbox_set_msg_tree and libbalsa_mailbox_check_parent
are helpers for the subclass methods.
*/
void libbalsa_mailbox_set_threading(LibBalsaMailbox *mailbox,
LibBalsaMailboxThreadingType thread_type);
void libbalsa_mailbox_set_msg_tree(LibBalsaMailbox * mailbox,
- GNode * msg_tree);
-void libbalsa_mailbox_unlink_and_prepend(LibBalsaMailbox * mailbox,
- GNode * node, GNode * parent);
+ GNode * msg_tree);
+void libbalsa_mailbox_check_parent(LibBalsaMailbox * mailbox,
+ GSequenceIter * node,
+ GSequenceIter * parent);
+
+typedef gboolean (*LBMTraverseFunc) (GSequenceIter * node, gpointer data);
+void libbalsa_mailbox_traverse(LibBalsaMailbox * mailbox,
+ GTraverseType type, LBMTraverseFunc func,
+ gpointer data);
+guint libbalsa_mailbox_n_nodes(LibBalsaMailbox * mailbox);
+guint libbalsa_mailbox_get_msgno(GSequenceIter * node);
+GSequenceIter *libbalsa_mailbox_get_parent(GSequenceIter * node);
+gboolean libbalsa_mailbox_node_is_ancestor(GSequenceIter * node,
+ GSequenceIter * descendant);
/* Mailbox views. */
extern GHashTable *libbalsa_mailbox_view_table;
@@ -579,12 +590,11 @@
/** force update of given msgno */
void libbalsa_mailbox_msgno_changed(LibBalsaMailbox *mailbox, guint seqno);
-void libbalsa_mailbox_msgno_inserted(LibBalsaMailbox * mailbox,
- guint seqno, GNode * parent,
- GNode ** sibling);
+GSequenceIter *libbalsa_mailbox_msgno_inserted(LibBalsaMailbox * mailbox,
+ guint seqno,
+ GSequenceIter * parent,
+ GSequenceIter * sibling);
void libbalsa_mailbox_msgno_removed(LibBalsaMailbox *mailbox, guint seqno);
-void libbalsa_mailbox_msgno_filt_in(LibBalsaMailbox * mailbox, guint seqno);
-void libbalsa_mailbox_msgno_filt_out(LibBalsaMailbox * mailbox, guint seqno);
void libbalsa_mailbox_msgno_filt_check(LibBalsaMailbox * mailbox,
guint seqno,
LibBalsaMailboxSearchIter
Modified: branches/mailbox-gsequence/libbalsa/mailbox_imap.c
==============================================================================
--- branches/mailbox-gsequence/libbalsa/mailbox_imap.c (original)
+++ branches/mailbox-gsequence/libbalsa/mailbox_imap.c Sun Jan 27 01:03:05 2008
@@ -618,12 +618,12 @@
static const unsigned MAX_CHUNK_LENGTH = 20;
static gboolean
-collect_seq_cb(GNode *node, gpointer data)
+collect_seq_cb(GSequenceIter *node, gpointer data)
{
/* We prefetch envelopes in chunks to save on RTTs.
* Try to get the messages both before and after the message. */
struct collect_seq_data *csd = (struct collect_seq_data*)data;
- unsigned msgno = GPOINTER_TO_UINT(node->data);
+ unsigned msgno = libbalsa_mailbox_get_msgno(node);
if(msgno==0) /* root node */
return FALSE;
csd->msgno_arr[(csd->cnt++) % MAX_CHUNK_LENGTH] = msgno;
@@ -658,9 +658,8 @@
csd.cnt = 0;
csd.has_it = 0;
if(LIBBALSA_MAILBOX(mimap)->msg_tree) {
- g_node_traverse(LIBBALSA_MAILBOX(mimap)->msg_tree,
- G_PRE_ORDER, G_TRAVERSE_ALL, -1, collect_seq_cb,
- &csd);
+ libbalsa_mailbox_traverse(LIBBALSA_MAILBOX(mimap),
+ G_PRE_ORDER, collect_seq_cb, &csd);
if(csd.cnt>MAX_CHUNK_LENGTH) csd.cnt = MAX_CHUNK_LENGTH;
qsort(csd.msgno_arr, csd.cnt, sizeof(csd.msgno_arr[0]), cmp_msgno);
} else {
@@ -779,7 +778,7 @@
if(cnt != mimap->messages_info->len) {
unsigned i;
struct message_info a = {0};
- GNode *sibling = NULL;
+ GSequenceIter *sibling = NULL;
if(cnt<mimap->messages_info->len) {
/* remove messages; we probably missed some EXPUNGE responses
@@ -813,12 +812,12 @@
gdk_threads_enter();
if (mailbox->msg_tree)
- sibling = g_node_last_child(mailbox->msg_tree);
+ sibling = g_sequence_get_end_iter(mailbox->msg_tree);
for(i=mimap->messages_info->len+1; i <= cnt; i++) {
g_array_append_val(mimap->messages_info, a);
g_ptr_array_add(mimap->msgids, NULL);
- libbalsa_mailbox_msgno_inserted(mailbox, i, mailbox->msg_tree,
- &sibling);
+ sibling = libbalsa_mailbox_msgno_inserted(mailbox, i,
+ NULL, sibling);
}
++mimap->search_stamp;
@@ -2991,9 +2990,9 @@
int retval;
LibBalsaMailbox *mbox = (LibBalsaMailbox *) mimap;
- seqnoa = GPOINTER_TO_UINT(a->node->data);
+ seqnoa = libbalsa_mailbox_get_msgno(a->node);
g_assert(seqnoa <= mimap->sort_ranks->len);
- seqnob = GPOINTER_TO_UINT(b->node->data);
+ seqnob = libbalsa_mailbox_get_msgno(b->node);
g_assert(seqnob <= mimap->sort_ranks->len);
retval = g_array_index(mimap->sort_ranks, guint, seqnoa - 1) -
g_array_index(mimap->sort_ranks, guint, seqnob - 1);
Modified: branches/mailbox-gsequence/libbalsa/mailbox_local.c
==============================================================================
--- branches/mailbox-gsequence/libbalsa/mailbox_local.c (original)
+++ branches/mailbox-gsequence/libbalsa/mailbox_local.c Sun Jan 27 01:03:05 2008
@@ -306,7 +306,8 @@
LibBalsaCondition * cond);
static void
libbalsa_mailbox_local_load_message(LibBalsaMailboxLocal * local,
- GNode ** sibling, guint msgno,
+ GSequenceIter ** sibling,
+ guint msgno,
LibBalsaMailboxLocalMessageInfo *
msg_info)
{
@@ -339,8 +340,8 @@
match = message_match_real(mbx, msgno, mbx->view_filter);
if (match)
- libbalsa_mailbox_msgno_inserted(mbx, msgno, mbx->msg_tree,
- sibling);
+ *sibling =
+ libbalsa_mailbox_msgno_inserted(mbx, msgno, NULL, *sibling);
}
/* Threading info. */
@@ -482,13 +483,14 @@
}
static gboolean
-lbm_local_save_tree_func(GNode * node, gpointer data)
+lbm_local_save_tree_func(GSequenceIter * node, gpointer data)
{
- return node->parent ?
- lbm_local_save_tree_item(GPOINTER_TO_UINT(node->data),
- GPOINTER_TO_UINT(node->parent->data),
- data) :
- FALSE;
+ GSequenceIter *parent = libbalsa_mailbox_get_parent(node);
+
+ return lbm_local_save_tree_item(libbalsa_mailbox_get_msgno(node),
+ parent ?
+ libbalsa_mailbox_get_msgno(parent) : 0,
+ data);
}
static gchar *
@@ -524,7 +526,7 @@
filename = lbm_local_get_cache_filename(local);
- if (!mailbox->msg_tree->children
+ if (g_sequence_get_length(mailbox->msg_tree) == 0
|| (libbalsa_mailbox_get_threading_type(mailbox) ==
LB_MAILBOX_THREADING_FLAT
&& libbalsa_mailbox_get_sort_field(mailbox) ==
@@ -557,9 +559,9 @@
#endif /* GLIB_CHECK_VERSION(2, 8, 0) */
/* Pre-order is required for the file to be created correctly. */
- g_node_traverse(mailbox->msg_tree, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
- (GNodeTraverseFunc) lbm_local_save_tree_func,
- &save_info);
+ libbalsa_mailbox_traverse(mailbox, G_PRE_ORDER,
+ (LBMTraverseFunc) lbm_local_save_tree_func,
+ &save_info);
#if GLIB_CHECK_VERSION(2, 8, 0)
err = NULL;
@@ -595,7 +597,8 @@
gchar *contents;
gsize length;
GError *err = NULL;
- GNode *parent, *sibling;
+ GSequenceIter *parent, *sibling;
+ guint parent_msgno, sibling_msgno;
LibBalsaMailboxLocalTreeInfo *info;
guint8 *seen;
@@ -646,8 +649,8 @@
gdk_threads_enter();
seen = g_new0(guint8, *total);
- parent = mailbox->msg_tree;
- sibling = NULL;
+ parent = sibling = NULL;
+ parent_msgno = sibling_msgno = 0;
while (++info < (LibBalsaMailboxLocalTreeInfo *) (contents + length)) {
if (info->msgno == 0 || info->msgno > *total
|| seen[info->msgno - 1]) {
@@ -662,32 +665,26 @@
}
seen[info->msgno - 1] = TRUE;
- if (sibling
- && info->value.parent == GPOINTER_TO_UINT(sibling->data)) {
- /* This message is the first child of the previous one. */
- parent = sibling;
- sibling = NULL;
- } else {
- /* Find the parent of this message. */
- while (info->value.parent != GPOINTER_TO_UINT(parent->data)) {
- /* Check one level higher. */
- sibling = parent;
- parent = parent->parent;
- if (!parent) {
- /* We got to the root without finding the parent. */
- libbalsa_information(LIBBALSA_INFORMATION_DEBUG,
- _("Cache file for mailbox %s "
- "will be repaired"), name);
- g_free(seen);
- g_free(contents);
- g_free(name);
- gdk_threads_leave();
- return FALSE;
+ if (sibling) {
+ if (info->value.parent == sibling_msgno) {
+ /* This message is the first child of the previous one. */
+ parent = sibling;
+ parent_msgno = sibling_msgno;
+ sibling = NULL;
+ } else {
+ /* Find the parent of this message. */
+ while (parent && info->value.parent != parent_msgno) {
+ /* Check one level higher. */
+ sibling = parent;
+ parent = libbalsa_mailbox_get_parent(parent);
+ parent_msgno =
+ parent ? libbalsa_mailbox_get_msgno(parent) : 0;
}
}
}
- libbalsa_mailbox_msgno_inserted(mailbox, info->msgno,
- parent, &sibling);
+ sibling = libbalsa_mailbox_msgno_inserted(mailbox, info->msgno,
+ parent, sibling);
+ sibling_msgno = info->msgno;
if (libbalsa_mailbox_msgno_has_flags(mailbox, info->msgno,
LIBBALSA_MESSAGE_FLAG_NEW,
LIBBALSA_MESSAGE_FLAG_DELETED))
@@ -1046,7 +1043,7 @@
guint new_messages;
LibBalsaMailboxLocal *local;
guint lastno;
- GNode *lastn;
+ GSequenceIter *lastn;
LibBalsaMailboxLocalMessageInfo *(*get_info) (LibBalsaMailboxLocal *,
guint);
@@ -1063,7 +1060,7 @@
local = (LibBalsaMailboxLocal *) mailbox;
lastno = libbalsa_mailbox_total_messages(mailbox);
new_messages = lastno - msgno;
- lastn = g_node_last_child(mailbox->msg_tree);
+ lastn = g_sequence_get_end_iter(mailbox->msg_tree);
get_info = LIBBALSA_MAILBOX_LOCAL_GET_CLASS(local)->get_info;
while (++msgno <= lastno){
LibBalsaMailboxLocalMessageInfo *msg_info = get_info(local, msgno);
@@ -1399,8 +1396,8 @@
};
typedef struct _ThreadingInfo ThreadingInfo;
-static gboolean lbml_set_parent(GNode * node, ThreadingInfo * ti);
-static GNode *lbml_insert_node(GNode * node,
+static gboolean lbml_set_parent(GSequenceIter * msg_node, ThreadingInfo * ti);
+static GNode *lbml_insert_node(GSequenceIter * msg_node,
LibBalsaMailboxLocalInfo * info,
ThreadingInfo * ti);
static GNode *lbml_find_parent(LibBalsaMailboxLocalInfo * info,
@@ -1410,15 +1407,12 @@
static void lbml_subject_merge(GNode * node, ThreadingInfo * ti);
static const gchar *lbml_chop_re(const gchar * str);
static gboolean lbml_construct(GNode * node, ThreadingInfo * ti);
-#ifdef MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT
-static void lbml_clear_empty(GNode * root);
-#endif /* MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT */
static void
lbml_info_setup(LibBalsaMailbox * mailbox, ThreadingInfo * ti)
{
ti->mailbox = mailbox;
- ti->root = g_node_new(mailbox->msg_tree);
+ ti->root = g_node_new(NULL);
ti->id_table = g_hash_table_new(g_str_hash, g_str_equal);
ti->subject_table = NULL;
ti->unthreaded =
@@ -1449,8 +1443,8 @@
lbml_info_setup(mailbox, &ti);
/* Traverse the mailbox's msg_tree, to build the second tree. */
- g_node_traverse(mailbox->msg_tree, G_POST_ORDER, G_TRAVERSE_ALL, -1,
- (GNodeTraverseFunc) lbml_set_parent, &ti);
+ libbalsa_mailbox_traverse(mailbox, G_POST_ORDER,
+ (LBMTraverseFunc) lbml_set_parent, &ti);
/* Prune the second tree. */
g_node_traverse(ti.root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
(GNodeTraverseFunc) lbml_prune, &ti);
@@ -1467,17 +1461,13 @@
g_node_traverse(ti.root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
(GNodeTraverseFunc) lbml_construct, &ti);
-#ifdef MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT
- lbml_clear_empty(ti.root);
-#endif /* MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT */
-
lbml_info_free(&ti);
}
static LibBalsaMailboxLocalInfo *
-lbml_get_info(GNode * node, ThreadingInfo * ti)
+lbml_get_info(GSequenceIter * node, ThreadingInfo * ti)
{
- guint msgno = GPOINTER_TO_UINT(node->data);
+ guint msgno = libbalsa_mailbox_get_msgno(node);
LibBalsaMailboxLocalInfo *info;
LibBalsaMailboxLocal *local = LIBBALSA_MAILBOX_LOCAL(ti->mailbox);
@@ -1506,16 +1496,13 @@
}
static gboolean
-lbml_set_parent(GNode * msg_node, ThreadingInfo * ti)
+lbml_set_parent(GSequenceIter * msg_node, ThreadingInfo * ti)
{
LibBalsaMailboxLocalInfo *info;
GNode *node;
GNode *parent;
GNode *child;
- if (!msg_node->parent)
- return FALSE;
-
info = lbml_get_info(msg_node, ti);
if (!info) /* FIXME assert this? */
@@ -1614,15 +1601,16 @@
}
static gboolean
-lbml_is_replied(GNode * msg_node, ThreadingInfo * ti)
+lbml_is_replied(GSequenceIter * msg_node, ThreadingInfo * ti)
{
- guint msgno = GPOINTER_TO_UINT(msg_node->data);
+ guint msgno = libbalsa_mailbox_get_msgno(msg_node);
return libbalsa_mailbox_msgno_get_status(ti->mailbox, msgno)
== LIBBALSA_MESSAGE_STATUS_REPLIED;
}
static GNode *
-lbml_insert_node(GNode * msg_node, LibBalsaMailboxLocalInfo * info,
+lbml_insert_node(GSequenceIter * msg_node,
+ LibBalsaMailboxLocalInfo * info,
ThreadingInfo * ti)
{
/*
@@ -1642,7 +1630,7 @@
node = g_hash_table_lookup(id_table, id);
if (node) {
- GNode *prev_msg_node = node->data;
+ GSequenceIter *prev_msg_node = node->data;
/* If this message has not been replied to, or if the container
* is empty, store it in the container. If there was a message
* in the container already, swap it with this one, otherwise
@@ -1683,17 +1671,8 @@
if (node->data != NULL || node == ti->root)
return FALSE;
-#ifdef MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT
- if (node->children != NULL
- && (node->parent != ti->root || node->children->next == NULL))
- lbml_move_children(node, node->parent);
-
- if (node->children == NULL)
- g_node_destroy(node);
-#else /* MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT */
lbml_move_children(node, node->parent);
g_node_destroy(node);
-#endif /* MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT */
return FALSE;
}
@@ -1701,7 +1680,9 @@
static const gchar *
lbml_get_subject(GNode * node, ThreadingInfo * ti)
{
- guint msgno = GPOINTER_TO_UINT(((GNode *) node->data)->data);
+ GSequenceIter *msg_node = node->data;
+ guint msgno = libbalsa_mailbox_get_msgno(msg_node);
+
return libbalsa_mailbox_msgno_get_subject(ti->mailbox, msgno);
}
@@ -1790,11 +1771,7 @@
return;
old = g_hash_table_lookup(subject_table, chopped_subject);
-#ifdef MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT
- if (old == NULL || (node->data == NULL && old->data != NULL)) {
-#else /* MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT */
if (old == NULL) {
-#endif /* MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT */
g_hash_table_insert(subject_table, (char *) chopped_subject,
node);
return;
@@ -1843,25 +1820,6 @@
if (node2 == NULL || node2 == node)
return;
-#ifdef MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT
- if (node->data == NULL && node2->data == NULL) {
- lbml_move_children(node, node2);
- g_node_destroy(node);
- return;
- }
-
- if (node->data == NULL)
- /* node2 should be made a child of node, but unlinking node2
- * could mess up the foreach, so we'll swap them and fall
- * through to the next case. */
- lbml_swap(node, node2, ti);
-
- if (node2->data == NULL) {
- lbml_unlink_and_prepend(node, node2);
- return;
- }
-#endif /* MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT */
-
subject2 = lbml_get_subject(node2, ti);
chopped_subject2 = lbml_chop_re(subject2);
@@ -1874,19 +1832,6 @@
* unlinking node2. */
lbml_swap(node, node2, ti);
lbml_unlink_and_prepend(node, node2);
-#ifdef MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT
- } else {
- /* Make both node and node2 children of a new empty node; as
- * above, swap node2 and the new node to avoid unlinking node2.
- */
- GNode *new_node = g_node_new(NULL);
-
- lbml_move_children(node2, new_node);
- new_node->data = node2->data;
- node2->data = NULL;
- lbml_unlink_and_prepend(node, node2);
- lbml_unlink_and_prepend(new_node, node2);
-#endif /* MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT */
}
}
@@ -1918,72 +1863,51 @@
static gboolean
lbml_construct(GNode * node, ThreadingInfo * ti)
{
- GNode *msg_node;
+ GSequenceIter *msg_node;
if (node->parent && (msg_node = node->data)) {
- GNode *msg_parent = node->parent->data;
+ GSequenceIter *msg_parent = node->parent->data;
- if (msg_parent && msg_node->parent != msg_parent
- && !g_node_is_ancestor(msg_node, msg_parent))
- libbalsa_mailbox_unlink_and_prepend(ti->mailbox, msg_node,
- msg_parent);
+ libbalsa_mailbox_check_parent(ti->mailbox, msg_node, msg_parent);
}
return FALSE;
}
-#ifdef MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT
-static void
-lbml_clear_empty(GNode * msg_tree)
-{
- GNode *node = msg_tree->children;
- while (node) {
- GNode *next = node->next;
- if (!node->data && !node->children)
- g_node_destroy(node);
- node = next;
- }
-}
-#endif /* MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT */
-
/* yet another message threading function */
-static gboolean lbml_insert_message(GNode * node, ThreadingInfo * ti);
-static gboolean lbml_thread_message(GNode * node, ThreadingInfo * ti);
+static gboolean lbml_insert_message(GSequenceIter * node,
+ ThreadingInfo * ti);
+static gboolean lbml_thread_message(GSequenceIter * node,
+ ThreadingInfo * ti);
static void
lbml_threading_simple(LibBalsaMailbox * mailbox,
LibBalsaMailboxThreadingType type)
{
- GNode *msg_tree = mailbox->msg_tree;
ThreadingInfo ti;
lbml_info_setup(mailbox, &ti);
if (type == LB_MAILBOX_THREADING_SIMPLE)
- g_node_traverse(msg_tree, G_POST_ORDER, G_TRAVERSE_ALL,
- -1, (GNodeTraverseFunc) lbml_insert_message, &ti);
+ libbalsa_mailbox_traverse(mailbox, G_POST_ORDER,
+ (LBMTraverseFunc) lbml_insert_message,
+ &ti);
ti.type = type;
- g_node_traverse(msg_tree, G_POST_ORDER, G_TRAVERSE_ALL, -1,
- (GNodeTraverseFunc) lbml_thread_message, &ti);
-
-#ifdef MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT
- lbml_clear_empty(msg_tree);
-#endif /* MAKE_EMPTY_CONTAINER_FOR_MISSING_PARENT */
+ libbalsa_mailbox_traverse(mailbox, G_POST_ORDER,
+ (LBMTraverseFunc) lbml_thread_message,
+ &ti);
lbml_info_free(&ti);
}
static gboolean
-lbml_insert_message(GNode * node, ThreadingInfo * ti)
+lbml_insert_message(GSequenceIter * node, ThreadingInfo * ti)
{
LibBalsaMailboxLocalInfo *info;
- if (!node->parent)
- return FALSE;
-
info = lbml_get_info(node, ti);
if (!info)
return FALSE;
@@ -1995,19 +1919,14 @@
}
static gboolean
-lbml_thread_message(GNode * node, ThreadingInfo * ti)
+lbml_thread_message(GSequenceIter * node, ThreadingInfo * ti)
{
- if (!node->parent)
- return FALSE;
-
- if (ti->type == LB_MAILBOX_THREADING_FLAT) {
- if (node->parent != ti->mailbox->msg_tree)
- libbalsa_mailbox_unlink_and_prepend(ti->mailbox, node,
- ti->mailbox->msg_tree);
- } else {
+ if (ti->type == LB_MAILBOX_THREADING_FLAT)
+ libbalsa_mailbox_check_parent(ti->mailbox, node, NULL);
+ else {
LibBalsaMailboxLocalInfo *info;
GList *refs;
- GNode *parent = NULL;
+ GSequenceIter *parent = NULL;
info = lbml_get_info(node, ti);
if (!info)
@@ -2018,11 +1937,7 @@
parent = g_hash_table_lookup(ti->id_table,
g_list_last(refs)->data);
- if (!parent)
- parent = ti->mailbox->msg_tree;
- if (parent != node->parent && parent != node
- && !g_node_is_ancestor(node, parent))
- libbalsa_mailbox_unlink_and_prepend(ti->mailbox, node, parent);
+ libbalsa_mailbox_check_parent(ti->mailbox, node, parent);
}
return FALSE;
Modified: branches/mailbox-gsequence/src/balsa-mblist.c
==============================================================================
--- branches/mailbox-gsequence/src/balsa-mblist.c (original)
+++ branches/mailbox-gsequence/src/balsa-mblist.c Sun Jan 27 01:03:05 2008
@@ -2293,7 +2293,7 @@
hidden_messages =
mailbox->msg_tree ? total_messages -
- (g_node_n_nodes(mailbox->msg_tree, G_TRAVERSE_ALL) - 1) : 0;
+ (libbalsa_mailbox_n_nodes(mailbox) - 1) : 0;
/* xgettext: this is the first part of the message
* "Shown mailbox: %s with %d messages, %d new, %d hidden". */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]