--- dbmail-mailbox.c.orig	Wed Apr 12 13:57:49 2006
+++ dbmail-mailbox.c	Thu Apr 13 14:59:10 2006
@@ -890,8 +890,8 @@
 		value->type = IST_SUBSEARCH_NOT;
 		(*idx)++;
 	
-		if ((result = dbmail_mailbox_build_imap_search(self, search_keys, idx, 0)) < 0) 
-			return result;
+		append_search(self, value, 1);
+		return dbmail_mailbox_build_imap_search(self, search_keys, idx, 0);
 		
 	} else if ( MATCH(key, "or") ) {
 		value->type = IST_SUBSEARCH_OR;
@@ -1466,11 +1466,19 @@
 
 	return FALSE;
 }	
+
+gboolean g_tree_copy(gpointer key, gpointer val, GTree *tree)
+{
+	g_tree_insert(tree, key, val);
+	return FALSE;
+}
+
 static gboolean _merge_search(GNode *node, GTree *found)
 {
 	search_key_t *s = (search_key_t *)node->data;
 	search_key_t *a, *b;
 	GNode *x, *y;
+	GTree *z;
 
 	trace(TRACE_DEBUG,"%s,%s: node depth [%d]", __FILE__, __func__, g_node_depth(node));
 	switch(s->type) {
@@ -1479,8 +1487,19 @@
 			break;
 			
 		case IST_SUBSEARCH_NOT:
-			if (s->found && found)
-				g_tree_merge(found, s->found, IST_SUBSEARCH_NOT);
+			if (found) {
+				/* NOT (foo EXP bar) can't be handled by this approach.
+				x = g_node_nth_child(node, 0);
+				a = (search_key_t *) x->data;
+				g_tree_merge(found, a->found, IST_SUBSEARCH_NOT); */
+				z = g_tree_new((GCompareFunc)ucmp);
+				g_tree_foreach(found, (GTraverseFunc) g_tree_copy, z);
+				g_node_children_foreach(node, G_TRAVERSE_ALL, 
+					(GNodeForeachFunc)_merge_search, (gpointer) z);
+				if (z) 
+					g_tree_merge(found, z, IST_SUBSEARCH_NOT);
+				g_tree_destroy(z);
+			}
 			break;
 			
 		case IST_SUBSEARCH_OR:
@@ -1518,12 +1537,18 @@
 
 int dbmail_mailbox_search(struct DbmailMailbox *self) 
 {
+	GTraverseFlags tr_flag = G_TRAVERSE_ALL;
+
 	if (! self->search)
 		return 0;
 	
-	g_node_traverse(g_node_get_root(self->search), G_PRE_ORDER, G_TRAVERSE_ALL, -1, 
+
+	if (g_node_n_nodes(g_node_get_root(self->search), G_TRAVERSE_ALL) > 1)
+		tr_flag = G_TRAVERSE_NON_LEAFS;
+
+	g_node_traverse(g_node_get_root(self->search), G_PRE_ORDER, tr_flag, -1, 
 			(GNodeTraverseFunc)_do_search, (gpointer)self);
-	g_node_traverse(g_node_get_root(self->search), G_PRE_ORDER, G_TRAVERSE_ALL, -1, 
+	g_node_traverse(g_node_get_root(self->search), G_PRE_ORDER, tr_flag, -1, 
 			(GNodeTraverseFunc)_merge_search, (gpointer)self->ids);
 	
 	trace(TRACE_DEBUG,"%s,%s: found [%d] ids\n", 
