Index: libbalsa/mailbox.c
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/mailbox.c,v
retrieving revision 1.190.2.13
diff -u -r1.190.2.13 mailbox.c
--- libbalsa/mailbox.c	2002/05/28 18:17:13	1.190.2.13
+++ libbalsa/mailbox.c	2002/07/09 09:53:39
@@ -83,6 +83,7 @@
     MESSAGES_NEW,
     MESSAGE_DELETE,
     MESSAGES_DELETE,
+    MESSAGES_DELETE_ALL,
     GET_MESSAGE_STREAM,
     CHECK,
     GET_MATCHING,
@@ -196,6 +197,14 @@
 		       gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1,
 		       GTK_TYPE_POINTER);
 
+    libbalsa_mailbox_signals[MESSAGES_DELETE_ALL] =
+	gtk_signal_new("messages-delete-all",
+		       GTK_RUN_FIRST,
+		       GTK_CLASS_TYPE(object_class),
+		       GTK_SIGNAL_OFFSET(LibBalsaMailboxClass,
+					 messages_delete),
+		       gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0);
+
     libbalsa_mailbox_signals[SET_UNREAD_MESSAGES_FLAG] =
 	gtk_signal_new("set-unread-messages-flag",
 		       GTK_RUN_FIRST,
@@ -771,7 +780,7 @@
 
     if(list){
       gtk_signal_emit(GTK_OBJECT(mailbox),
-		      libbalsa_mailbox_signals[MESSAGES_DELETE], list);
+		      libbalsa_mailbox_signals[MESSAGES_DELETE_ALL]);
     }
 
     while (list) {
Index: src/balsa-app.c
===================================================================
RCS file: /cvs/gnome/balsa/src/balsa-app.c,v
retrieving revision 1.215.2.20
diff -u -r1.215.2.20 balsa-app.c
--- src/balsa-app.c	2002/06/13 08:37:45	1.215.2.20
+++ src/balsa-app.c	2002/07/09 09:53:39
@@ -893,15 +893,16 @@
 BalsaIndex*
 balsa_find_index_by_mailbox(LibBalsaMailbox * mailbox)
 {
+    GtkWidget *page;
     GtkWidget *index;
     guint i;
     g_return_val_if_fail(balsa_app.notebook, NULL);
 
     for (i = 0;
-	 (index =
+	 (page =
 	  gtk_notebook_get_nth_page(GTK_NOTEBOOK(balsa_app.notebook), i));
 	 i++) {
-        
+        index = gtk_bin_get_child(GTK_BIN(page));
 	if (BALSA_INDEX(index)->mailbox_node != NULL
             && BALSA_INDEX(index)->mailbox_node->mailbox == mailbox)
 	    return BALSA_INDEX(index);
Index: src/balsa-icons.c
===================================================================
RCS file: /cvs/gnome/balsa/src/balsa-icons.c,v
retrieving revision 1.25.6.4
diff -u -r1.25.6.4 balsa-icons.c
--- src/balsa-icons.c	2002/06/23 21:50:39	1.25.6.4
+++ src/balsa-icons.c	2002/07/09 09:53:39
@@ -63,8 +63,6 @@
 #include "pixmaps/mbox_dir_open.xpm"
 
 #include "pixmaps/info_replied.xpm"
-#include "pixmaps/info_read.xpm"
-#include "pixmaps/info_forward.xpm"
 #include "pixmaps/info_flagged.xpm"
 #include "pixmaps/info_new.xpm"
 #include "pixmaps/info_attachment.xpm"
@@ -94,31 +92,6 @@
 
 #define ELEMENTS(x) (sizeof (x) / sizeof (x[0]))
 
-typedef struct _BalsaIcon BalsaIcon;
-struct _BalsaIcon {
-    GdkPixmap *p;
-    GdkBitmap *b;
-};
-
-static BalsaIcon mbox_draft;
-static BalsaIcon mbox_in;
-static BalsaIcon mbox_out;
-static BalsaIcon mbox_sent;
-static BalsaIcon mbox_trash;
-
-static BalsaIcon mbox_tray_empty;
-static BalsaIcon mbox_tray_full;
-
-static BalsaIcon mbox_dir_open;
-static BalsaIcon mbox_dir_closed;
-
-static BalsaIcon info_replied;
-static BalsaIcon info_read;
-static BalsaIcon info_forward;
-static BalsaIcon info_flagged;
-static BalsaIcon info_new;
-static BalsaIcon info_attachment;
-
 void
 balsa_icon_create(const gchar ** data, GdkPixmap ** pmap, GdkBitmap ** bmap)
 {
@@ -127,63 +100,6 @@
                                          (gchar **) data);
 }
 
-void
-balsa_icons_init(void)
-{
-    balsa_icon_create(mbox_draft_xpm,		&mbox_draft.p,		&mbox_draft.b);
-    balsa_icon_create(mbox_in_xpm,		&mbox_in.p,		&mbox_in.b);
-    balsa_icon_create(mbox_out_xpm,		&mbox_out.p,		&mbox_out.b);
-    balsa_icon_create(mbox_sent_xpm,		&mbox_sent.p,		&mbox_sent.b);
-    balsa_icon_create(mbox_trash_xpm,		&mbox_trash.p,		&mbox_trash.b);
-
-    balsa_icon_create(mbox_tray_empty_xpm,	&mbox_tray_empty.p,	&mbox_tray_empty.b);
-    balsa_icon_create(mbox_tray_full_xpm,	&mbox_tray_full.p,	&mbox_tray_full.b);
-
-    balsa_icon_create(mbox_dir_closed_xpm,	&mbox_dir_closed.p,	&mbox_dir_closed.b);
-    balsa_icon_create(mbox_dir_open_xpm,	&mbox_dir_open.p,	&mbox_dir_open.b);
-
-    balsa_icon_create(info_replied_xpm,	&info_replied.p,	&info_replied.b);
-    balsa_icon_create(info_read_xpm,		&info_read.p,		&info_read.b);
-    balsa_icon_create(info_forward_xpm,	&info_forward.p,	&info_forward.b);
-    balsa_icon_create(info_flagged_xpm,	&info_flagged.p,	&info_flagged.b);
-    balsa_icon_create(info_new_xpm,		&info_new.p,		&info_new.b);
-    balsa_icon_create(info_attachment_xpm,	&info_attachment.p,	&info_attachment.b);
-}
-
-GdkPixmap *
-balsa_icon_get_pixmap(BalsaIconName name)
-{
-    switch (name) {
-	case BALSA_ICON_MBOX_TRASH:		return mbox_trash.p;
-
-	case BALSA_ICON_INFO_REPLIED:		return info_replied.p;
-	case BALSA_ICON_INFO_READ:		return info_read.p;
-	case BALSA_ICON_INFO_FORWARD:		return info_forward.p;
-	case BALSA_ICON_INFO_FLAGGED:		return info_flagged.p;
-	case BALSA_ICON_INFO_NEW:		return info_new.p;
-	case BALSA_ICON_INFO_ATTACHMENT:	return info_attachment.p;
-    }
-
-    return NULL;
-}
-
-GdkBitmap *
-balsa_icon_get_bitmap(BalsaIconName name)
-{
-    switch (name) {
-	case BALSA_ICON_MBOX_TRASH:		return mbox_trash.b;
-
-	case BALSA_ICON_INFO_REPLIED:		return info_replied.b;
-	case BALSA_ICON_INFO_READ:		return info_read.b;
-	case BALSA_ICON_INFO_FORWARD:		return info_forward.b;
-	case BALSA_ICON_INFO_FLAGGED:		return info_flagged.b;
-	case BALSA_ICON_INFO_NEW:		return info_new.b;
-	case BALSA_ICON_INFO_ATTACHMENT:	return info_attachment.b;
-    }
-
-    return NULL;
-}
-
 static void
 register_balsa_pixmap(const gchar * stock_id, const char ** data,
                       GtkIconFactory * factory)
@@ -263,6 +179,12 @@
         { BALSA_PIXMAP_MBOX_TRAY_FULL,  mbox_tray_full_xpm },
         { BALSA_PIXMAP_MBOX_DIR_OPEN,   mbox_dir_open_xpm },
         { BALSA_PIXMAP_MBOX_DIR_CLOSED, mbox_dir_closed_xpm },
+
+        /* BalsaIndex icons */
+        { BALSA_PIXMAP_INFO_FLAGGED,    info_flagged_xpm },
+        { BALSA_PIXMAP_INFO_REPLIED,    info_replied_xpm },
+        { BALSA_PIXMAP_INFO_NEW,        info_new_xpm },
+        { BALSA_PIXMAP_INFO_ATTACHMENT, info_attachment_xpm },
     };
 
     unsigned i;
Index: src/balsa-icons.h
===================================================================
RCS file: /cvs/gnome/balsa/src/balsa-icons.h,v
retrieving revision 1.19.6.2
diff -u -r1.19.6.2 balsa-icons.h
--- src/balsa-icons.h	2002/06/01 19:22:29	1.19.6.2
+++ src/balsa-icons.h	2002/07/09 09:53:39
@@ -48,53 +48,44 @@
 #define BALSA_PIXMAP_IDENTITY			"balsa_identity"
 #define BALSA_PIXMAP_CLOSE_MBOX			"balsa_close_mbox"
 
-#define BALSA_PIXMAP_MENU_NEW			"menu_new"
-#define BALSA_PIXMAP_MENU_FLAGGED		"menu_flagged"
-#define BALSA_PIXMAP_MENU_IDENTITY		"menu_identity"
-#define BALSA_PIXMAP_MENU_FORWARD		"menu_forward"
-#define BALSA_PIXMAP_MENU_REPLY	                "menu_reply"
-#define BALSA_PIXMAP_MENU_REPLY_ALL		"menu_reply_all"
-#define BALSA_PIXMAP_MENU_REPLY_GROUP		"menu_reply_group"
-#define BALSA_PIXMAP_MENU_POSTPONE		"menu_postpone"
-#define BALSA_PIXMAP_MENU_PRINT	                "menu_print"
-#define BALSA_PIXMAP_MENU_NEXT			"menu_next"
-#define BALSA_PIXMAP_MENU_PREVIOUS		"menu_previous"
-#define BALSA_PIXMAP_MENU_SAVE			"menu_save"
-#define BALSA_PIXMAP_MENU_SEND			"menu_send"
-#define BALSA_PIXMAP_MENU_SEND_RECEIVE		"menu_send_receive"
-#define BALSA_PIXMAP_MENU_COMPOSE		"menu_compose"
-#define BALSA_PIXMAP_MENU_ATTACHMENT		"menu_attachment"
-#define BALSA_PIXMAP_MENU_RECEIVE		"menu_receive"
-#define BALSA_PIXMAP_MENU_NEXT_FLAGGED		"menu_next_flagged"
-#define BALSA_PIXMAP_MENU_NEXT_UNREAD		"menu_next_unread"
-#define BALSA_PIXMAP_MENU_MARK_ALL		"menu_mark_all"
+#define BALSA_PIXMAP_MENU_NEW			"balsa_menu_new"
+#define BALSA_PIXMAP_MENU_FLAGGED		"balsa_menu_flagged"
+#define BALSA_PIXMAP_MENU_IDENTITY		"balsa_menu_identity"
+#define BALSA_PIXMAP_MENU_FORWARD		"balsa_menu_forward"
+#define BALSA_PIXMAP_MENU_REPLY	                "balsa_menu_reply"
+#define BALSA_PIXMAP_MENU_REPLY_ALL		"balsa_menu_reply_all"
+#define BALSA_PIXMAP_MENU_REPLY_GROUP		"balsa_menu_reply_group"
+#define BALSA_PIXMAP_MENU_POSTPONE		"balsa_menu_postpone"
+#define BALSA_PIXMAP_MENU_PRINT	                "balsa_menu_print"
+#define BALSA_PIXMAP_MENU_NEXT			"balsa_menu_next"
+#define BALSA_PIXMAP_MENU_PREVIOUS		"balsa_menu_previous"
+#define BALSA_PIXMAP_MENU_SAVE			"balsa_menu_save"
+#define BALSA_PIXMAP_MENU_SEND			"balsa_menu_send"
+#define BALSA_PIXMAP_MENU_SEND_RECEIVE		"balsa_menu_send_receive"
+#define BALSA_PIXMAP_MENU_COMPOSE		"balsa_menu_compose"
+#define BALSA_PIXMAP_MENU_ATTACHMENT		"balsa_menu_attachment"
+#define BALSA_PIXMAP_MENU_RECEIVE		"balsa_menu_receive"
+#define BALSA_PIXMAP_MENU_NEXT_FLAGGED		"balsa_menu_next_flagged"
+#define BALSA_PIXMAP_MENU_NEXT_UNREAD		"balsa_menu_next_unread"
+#define BALSA_PIXMAP_MENU_MARK_ALL		"balsa_menu_mark_all"
 
-#define BALSA_PIXMAP_OTHER_CLOSE		"other_close"
+#define BALSA_PIXMAP_OTHER_CLOSE		"balsa_other_close"
 
-#define BALSA_PIXMAP_MBOX_DRAFT                 "mbox_draft"
-#define BALSA_PIXMAP_MBOX_IN                    "mbox_in"
-#define BALSA_PIXMAP_MBOX_OUT                   "mbox_out"
-#define BALSA_PIXMAP_MBOX_SENT                  "mbox_sent"
-#define BALSA_PIXMAP_MBOX_TRASH                 "mbox_trash"
-#define BALSA_PIXMAP_MBOX_TRAY_EMPTY            "mbox_tray_empty"
-#define BALSA_PIXMAP_MBOX_TRAY_FULL             "mbox_tray_full"
-#define BALSA_PIXMAP_MBOX_DIR_OPEN              "mbox_dir_open"
-#define BALSA_PIXMAP_MBOX_DIR_CLOSED            "mbox_dir_closed"
+#define BALSA_PIXMAP_MBOX_DRAFT                 "balsa_mbox_draft"
+#define BALSA_PIXMAP_MBOX_IN                    "balsa_mbox_in"
+#define BALSA_PIXMAP_MBOX_OUT                   "balsa_mbox_out"
+#define BALSA_PIXMAP_MBOX_SENT                  "balsa_mbox_sent"
+#define BALSA_PIXMAP_MBOX_TRASH                 "balsa_mbox_trash"
+#define BALSA_PIXMAP_MBOX_TRAY_EMPTY            "balsa_mbox_tray_empty"
+#define BALSA_PIXMAP_MBOX_TRAY_FULL             "balsa_mbox_tray_full"
+#define BALSA_PIXMAP_MBOX_DIR_OPEN              "balsa_mbox_dir_open"
+#define BALSA_PIXMAP_MBOX_DIR_CLOSED            "balsa_mbox_dir_closed"
 
-typedef enum {
-    BALSA_ICON_MBOX_TRASH,
+#define BALSA_PIXMAP_INFO_FLAGGED               "balsa_info_flagged"
+#define BALSA_PIXMAP_INFO_REPLIED               "balsa_info_replied"
+#define BALSA_PIXMAP_INFO_NEW                   "balsa_info_new"
+#define BALSA_PIXMAP_INFO_ATTACHMENT            "balsa_info_attachment"
 
-    BALSA_ICON_INFO_REPLIED,
-    BALSA_ICON_INFO_READ,
-    BALSA_ICON_INFO_FORWARD,
-    BALSA_ICON_INFO_FLAGGED,
-    BALSA_ICON_INFO_NEW,
-    BALSA_ICON_INFO_ATTACHMENT,
-} BalsaIconName;
-
-void balsa_icons_init(void);
-GdkPixmap *balsa_icon_get_pixmap(BalsaIconName icon);
-GdkBitmap *balsa_icon_get_bitmap(BalsaIconName icon);
 void register_balsa_pixmaps(void);
 void balsa_icon_create(const gchar ** data, GdkPixmap ** pmap,
                        GdkBitmap ** bmap);
Index: src/balsa-index-threading.c
===================================================================
RCS file: /cvs/gnome/balsa/src/balsa-index-threading.c,v
retrieving revision 1.13.6.3
diff -u -r1.13.6.3 balsa-index-threading.c
--- src/balsa-index-threading.c	2002/05/18 14:12:50	1.13.6.3
+++ src/balsa-index-threading.c	2002/07/09 09:53:40
@@ -29,6 +29,20 @@
  * message threading functionality, just specify 'BALSA_INDEX_THREADING_FLAT'. 
  *
  * ymnk@jcraft.com
+ *
+ * This version is based on a BalsaIndex that subclasses GtkTreeView,
+ * and differs in some ways from the original GtkCTree code.
+ * GtkTreeRowReferences are used to keep track of rows (messages) as
+ * threads are constructed. However, moving a row or subtree isn't
+ * supported, so we have to do it the hard way: copy the rows one at a
+ * time to the new location, then delete the old copy. Of course, the
+ * GtkTreeRowReferences to the rows are lost, so we have to update them
+ * ourselves.
+ *
+ * To cope with all this, the message is used as the key, and when we
+ * need to access the row, the row reference is looked up and converted
+ * to a path. The hash table is passed to balsa_index_move_subtree,
+ * which updates it.
  */
 
 #include "config.h"
@@ -43,43 +57,46 @@
 #include "balsa-index-threading.h"
 #include "main-window.h"
 
-#define MESSAGE(node) ((LibBalsaMessage *)(GTK_CTREE_ROW(node)->row.data))
+struct ThreadingInfo {
+    GHashTable *subject_table;
+    GHashTable *id_table;
+    GHashTable *ref_table;
+    GtkTreeModel *model;
+};
 
-static void threading_jwz(BalsaIndex* bindex);
+static void threading_jwz(BalsaIndex* index);
 static gboolean is_cyclic_tree(GNode* root, GNode* child);
-static void gen_container(GtkCTree *ctree, 
-			  GtkCTreeNode *node, 
-			  GHashTable* id_table);
-static GNode* get_container(GtkCTreeNode *node, 
-			    GHashTable* id_table);
+static gboolean gen_container(GtkTreeModel * model, GtkTreePath * path,
+                              GtkTreeIter * iter, gpointer data);
+static GNode *get_container(LibBalsaMessage * message,
+                            GHashTable * id_table);
 static GNode* check_references(LibBalsaMessage* message,
 			       GHashTable *id_table);
 static void adopt_child(GNode* parent, GNode* container);
 static void find_root_set(gpointer key, GNode* value, GSList ** root_set);
 static gboolean prune(GNode *node, GSList *root_set);
 static gboolean node_equal(GNode *node1, GNode **node2);
-static gboolean construct(GNode *node, GtkCTree *ctree);
-static void subject_gather(GNode *node, GHashTable* subject_table);
-static void subject_merge(GNode *node, GHashTable* subject_table, 
-			  GSList* root_set, GSList** save_node);
+static gboolean construct(GNode * node, struct ThreadingInfo * ti);
+static void subject_gather(GNode * node, struct ThreadingInfo * ti);
+static void subject_merge(GNode * node, GSList * root_set,
+                          GSList ** save_node, GHashTable * subject_table);
 static void reparent(GNode* node, GNode* children);
-static void free_node(gpointer key, GNode* value, gpointer data);
+static void free_node(GNode* value);
 static const gchar* chop_re(const gchar* str);
 
-static void threading_simple(BalsaIndex* bindex);
-static void add_message(GtkCTree *ctree, 
-			GtkCTreeNode *node, 
-			GHashTable* msg_table);
+static void threading_simple(BalsaIndex* index);
+static gboolean add_message(GtkTreeModel * model, GtkTreePath * path,
+                            GtkTreeIter * iter, gpointer data);
 
 void
-balsa_index_threading(BalsaIndex* bindex)
+balsa_index_threading(BalsaIndex* index)
 {
-    switch (bindex->threading_type){
+    switch (index->threading_type){
     case BALSA_INDEX_THREADING_SIMPLE:
-	threading_simple(bindex);
+	threading_simple(index);
 	break;
     case BALSA_INDEX_THREADING_JWZ:
-	threading_jwz(bindex);
+	threading_jwz(index);
 	break;
     case BALSA_INDEX_THREADING_FLAT:
 	break;
@@ -89,26 +106,27 @@
 }
 
 static void
-threading_jwz(BalsaIndex* bindex)
+threading_jwz(BalsaIndex* index)
 {
-    GHashTable *id_table;
-    GHashTable *subject_table;
     GSList *root_set=NULL;
     GSList *save_node=NULL;
     GSList *foo=NULL;
-    GtkCTree* ctree=GTK_CTREE(bindex->ctree);
+    struct ThreadingInfo ti;
 
-    id_table=g_hash_table_new(g_str_hash, g_str_equal);
-    gtk_ctree_pre_recursive(ctree, 
-			    (GtkCTreeNode *)NULL, 
-			    (GtkCTreeFunc)gen_container, 
-			    (gpointer)id_table);
+    ti.id_table =
+        g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+                              (GDestroyNotify) free_node);
+    ti.ref_table =
+        g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
+                              (GDestroyNotify) gtk_tree_row_reference_free);
+    ti.model = gtk_tree_view_get_model(GTK_TREE_VIEW(index));
+    gtk_tree_model_foreach(ti.model, gen_container, &ti);
 
-    g_hash_table_foreach(id_table, 
+    g_hash_table_foreach(ti.id_table, 
 			 (GHFunc)find_root_set,
 			 &root_set);
 
-    balsa_window_setup_progress(BALSA_WINDOW(bindex->window), 
+    balsa_window_setup_progress(BALSA_WINDOW(index->window), 
                                 g_slist_length(root_set));
     
     for(foo=root_set; foo; foo=g_slist_next(foo)) {
@@ -121,12 +139,13 @@
 			root_set);
     }
 
-    subject_table = g_hash_table_new(g_str_hash, g_str_equal);
-    g_slist_foreach(root_set, (GFunc)subject_gather, subject_table);
+    ti.subject_table = g_hash_table_new(g_str_hash, g_str_equal);
+    g_slist_foreach(root_set, (GFunc)subject_gather, &ti);
 
-    for(foo = root_set; foo; foo=g_slist_next(foo)) {
-	if(foo->data!=NULL)
-	    subject_merge(foo->data, subject_table, root_set, &save_node);
+    for (foo = root_set; foo; foo = g_slist_next(foo)) {
+        if (foo->data != NULL)
+            subject_merge(foo->data, root_set, &save_node,
+                          ti.subject_table);
     }
 
     for(foo = root_set; foo; foo=g_slist_next(foo)) {
@@ -136,8 +155,8 @@
 			    G_TRAVERSE_ALL,
 			    -1,
 			    (GNodeTraverseFunc)construct,
-			    ctree);
-        balsa_window_increment_progress(BALSA_WINDOW(bindex->window));
+			    &ti);
+        balsa_window_increment_progress(BALSA_WINDOW(index->window));
     }
 
     for(foo=save_node; foo; foo=g_slist_next(foo)) {
@@ -149,27 +168,36 @@
     if(save_node!=NULL)
 	g_slist_free(save_node);
 
-    balsa_window_clear_progress(BALSA_WINDOW(bindex->window));
-    g_hash_table_destroy(subject_table);
-    g_hash_table_foreach(id_table, (GHFunc)free_node, NULL);
-    g_hash_table_destroy(id_table);
+    balsa_window_clear_progress(BALSA_WINDOW(index->window));
+    g_hash_table_destroy(ti.subject_table);
+    g_hash_table_destroy(ti.ref_table);
+    g_hash_table_destroy(ti.id_table);
 
     if(root_set!=NULL)
 	g_slist_free(root_set);
 }
 
-static void
-gen_container(GtkCTree *ctree, GtkCTreeNode *node, GHashTable *id_table)
+static gboolean
+gen_container(GtkTreeModel * model, GtkTreePath * path,
+              GtkTreeIter * iter, gpointer data)
 {
-    LibBalsaMessage* message=MESSAGE(node);
-    GNode* container=NULL;
+    GtkTreeRowReference *reference =
+        gtk_tree_row_reference_new(model, path);
+    struct ThreadingInfo *ti = data;
+    LibBalsaMessage *message = NULL;
+    GNode *container;
+
+    gtk_tree_model_get(model, iter, BNDX_MESSAGE_COLUMN, &message, -1);
+    g_hash_table_insert(ti->ref_table, message, reference);
 
-    container=get_container(node, id_table);
+    container = get_container(message, ti->id_table);
     if(container) {
-        GNode* parent = check_references(message, id_table);
+        GNode* parent = check_references(message, ti->id_table);
         if(parent)
             adopt_child(parent, container);
     }
+
+    return FALSE;
 }
 
 static GNode*
@@ -374,9 +402,8 @@
 }
 
 static GNode*
-get_container(GtkCTreeNode *node, GHashTable* id_table)
+get_container(LibBalsaMessage * message, GHashTable* id_table)
 {
-    LibBalsaMessage* message=MESSAGE(node);
     GNode* container=NULL;
 
     /*
@@ -393,10 +420,10 @@
 
     container=g_hash_table_lookup(id_table, message->message_id);
     if(container!=NULL) {
-	container->data=node;
+	container->data = message;
     }
     else{
-	container=g_node_new(node);
+	container=g_node_new(message);
 	g_hash_table_insert(id_table, message->message_id, container);
     }
     return container;
@@ -509,43 +536,60 @@
     return FALSE;
 }
 
-static gboolean 
-construct(GNode *node, GtkCTree *ctree)
+/*
+ * check_parent: find the paths to the messages, and if the parent isn't
+ * the immediate parent of the child, move the child
+ */
+static void
+check_parent(struct ThreadingInfo *ti, LibBalsaMessage * parent,
+             LibBalsaMessage * child)
 {
-    GtkCTreeNode *ctreenode=NULL;
-    GtkCTreeNode *ctreeparent=NULL;
-    GtkCTreeNode *sibling=NULL;
+    GtkTreeRowReference *parent_ref;
+    GtkTreeRowReference *child_ref;
+    GtkTreePath *parent_path;
+    GtkTreePath *child_path;
+    GtkTreePath *test;
 
-    if(node->parent!=NULL && node->parent->data!=NULL) {
-	ctreeparent=GTK_CTREE_NODE(node->parent->data);
-    }
+    if (parent == NULL)
+        return;
+    g_return_if_fail(child != NULL);
 
-    if(node->data!=NULL) {
-        ctreenode = GTK_CTREE_NODE(node->data);
-	gtk_ctree_move(ctree, ctreenode, ctreeparent, NULL);
-    }
+    parent_ref = g_hash_table_lookup(ti->ref_table, parent);
+    g_return_if_fail(parent_ref != NULL);
 
-    if(node->next!=NULL) {
-        sibling = GTK_CTREE_NODE(node->next->data);
-	gtk_ctree_move(ctree, sibling, ctreeparent, ctreenode);
-    }
+    child_ref = g_hash_table_lookup(ti->ref_table, child);
+    g_return_if_fail(child_ref != NULL);
 
-    if(node->children!=NULL) {
-	GNode *children;
-	for(children=node->children; children; children=children->next) {
-            GtkCTreeNode *foo = GTK_CTREE_NODE(children->data);
-	    if(foo)
-		gtk_ctree_move(ctree, foo, ctreenode, NULL);
-	}
+    parent_path = gtk_tree_row_reference_get_path(parent_ref);
+    g_return_if_fail(parent_path != NULL);
+
+    child_path = gtk_tree_row_reference_get_path(child_ref);
+    g_return_if_fail(child_path != NULL);
+
+    test = gtk_tree_path_copy(child_path);
+
+    if (!gtk_tree_path_up(test) || gtk_tree_path_get_depth(test) <= 0
+        || gtk_tree_path_compare(test, parent_path)) {
+        balsa_index_move_subtree(ti->model, child_path, parent_path,
+                                 ti->ref_table);
     }
+    gtk_tree_path_free(test);
+    gtk_tree_path_free(child_path);
+    gtk_tree_path_free(parent_path);
+}
+
+static gboolean
+construct(GNode * node, struct ThreadingInfo * ti)
+{
+    if (node->parent)
+        check_parent(ti, node->parent->data, node->data);
 
     return FALSE;
 }
 
 static void
-subject_gather(GNode *node, GHashTable* subject_table)
+subject_gather(GNode * node, struct ThreadingInfo * ti)
 {
-    GtkCTreeNode *ctnode, *old_node;
     LibBalsaMessage *message, *old_message;
     const gchar *subject=NULL, *old_subject;
     const gchar *chopped_subject=NULL;
@@ -621,8 +665,7 @@
 
     if(node==NULL) return;
 
-    ctnode = GTK_CTREE_NODE(node->data ? node->data : node->children->data);
-    message = MESSAGE(ctnode);
+    message = node->data ? node->data : node->children->data;
     
     g_return_if_fail(message!=NULL);
 
@@ -637,27 +680,25 @@
       printf("subject_gather: subject %s, %s\n", subject, chopped_subject);
     */
 
-    old=g_hash_table_lookup(subject_table, chopped_subject);
+    old=g_hash_table_lookup(ti->subject_table, chopped_subject);
     if(old==NULL ||
        (node->data==NULL&&old->data!=NULL)) {
-	g_hash_table_insert(subject_table, (char*)chopped_subject, node);
+	g_hash_table_insert(ti->subject_table, (char*)chopped_subject, node);
 	return;
     }
 
-    old_node = GTK_CTREE_NODE(old->data ? old->data : old->children->data);
-    old_message = MESSAGE(old_node);
+    old_message = old->data ? old->data : old->children->data;
     g_return_if_fail(old_message!=NULL);
     old_subject = LIBBALSA_MESSAGE_GET_SUBJECT(old_message);
 
     if( old_subject != chop_re(old_subject) && subject==chopped_subject)
-        g_hash_table_insert(subject_table, (gchar*)chopped_subject, node);
+        g_hash_table_insert(ti->subject_table, (gchar*)chopped_subject, node);
 }
 
 static void
-subject_merge(GNode *node, GHashTable* subject_table, 
-	      GSList* root_set, GSList** save_node)
+subject_merge(GNode *node, GSList * root_set, GSList ** save_node,
+              GHashTable * subject_table)
 {
-    GtkCTreeNode *ctnode=NULL, *ctnode2;
     LibBalsaMessage *message, *message2;
     const gchar *subject, *subject2;
     const gchar *chopped_subject, *chopped_subject2;
@@ -666,8 +707,7 @@
     if(node==NULL) return;
 
     
-    ctnode = GTK_CTREE_NODE(node->data ? node->data : node->children->data);
-    message = MESSAGE(ctnode);
+    message = node->data ? node->data : node->children->data;
 
     g_return_if_fail(message!=NULL);
 
@@ -695,8 +735,7 @@
 	return;
     }
 
-    ctnode2  = GTK_CTREE_NODE(node2->data);
-    message2 = MESSAGE(ctnode2);
+    message2 = node2->data;
     subject2 = LIBBALSA_MESSAGE_GET_SUBJECT(message2);
     chopped_subject2= chop_re(subject2);
 
@@ -782,7 +821,7 @@
 }
 
 static void
-free_node(gpointer key, GNode* node, gpointer data)
+free_node(GNode* node)
 {
     node->data=NULL;
     node->children=NULL;
@@ -790,55 +829,70 @@
 }
 
 /* yet another message threading function */
+
 static void
-threading_simple(BalsaIndex* bindex)
+threading_simple(BalsaIndex * index)
 {
-    LibBalsaMessage* message;
-    GtkCTreeNode* sibling;
-    GtkCTreeNode* parent;
-    GList *root_children=NULL;
-    GList *p=NULL;
-    GtkCTree* ctree=GTK_CTREE(bindex->ctree);
-    GHashTable *msg_table;
-    gint length=0;
-
-    msg_table=g_hash_table_new(g_str_hash, g_str_equal);
-
-    gtk_ctree_pre_recursive(ctree, 
-			    (GtkCTreeNode *)NULL, 
-			    (GtkCTreeFunc)add_message,
-			    (gpointer)msg_table);
-    sibling=gtk_ctree_node_nth(ctree, 0);
-    while(sibling!=NULL) {
-	root_children=g_list_append(root_children, sibling);
-	sibling=GTK_CTREE_ROW(sibling)->sibling;
-	length++;
-    }
-    balsa_window_setup_progress(BALSA_WINDOW(bindex->window),
-                                length);
-    for(p=root_children; p; p=g_list_next(p)) {
-	parent=NULL;
-	message=MESSAGE(p->data);
-	if(message->references_for_threading!=NULL) {
-	    parent = 
-                g_hash_table_lookup(msg_table, 
-                                    g_list_last(message->references_for_threading)->data);
-	    if(parent!=NULL)
-		gtk_ctree_move(ctree, p->data, parent, NULL);
-	}
-        balsa_window_increment_progress(BALSA_WINDOW(bindex->window));
-    }
-    balsa_window_clear_progress(BALSA_WINDOW(bindex->window));
-    g_list_free(root_children);
-    g_hash_table_destroy(msg_table);
+    GtkTreeIter iter;
+    GSList *root_children = NULL;
+    GSList *p;
+    struct ThreadingInfo ti;
+    gint length = 0;
+
+    ti.model = gtk_tree_view_get_model(GTK_TREE_VIEW(index));
+    if (!gtk_tree_model_get_iter_first(ti.model, &iter))
+        return;
+
+    ti.id_table = g_hash_table_new(g_str_hash, g_str_equal);
+    ti.ref_table =
+        g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
+                              (GDestroyNotify) gtk_tree_row_reference_free);
+    gtk_tree_model_foreach(ti.model, add_message, &ti);
+
+    do {
+        LibBalsaMessage *message = NULL;
+
+        gtk_tree_model_get(ti.model, &iter,
+                           BNDX_MESSAGE_COLUMN, &message,
+                           -1);
+        root_children = g_slist_prepend(root_children, message);
+        length++;
+    } while (gtk_tree_model_iter_next(ti.model, &iter));
+
+    balsa_window_setup_progress(BALSA_WINDOW(index->window), length);
+    for (p = root_children; p; p = g_slist_next(p)) {
+        LibBalsaMessage *message = p->data;
+
+        if (message->references_for_threading != NULL) {
+            LibBalsaMessage *parent =
+                g_hash_table_lookup(ti.id_table,
+                                    g_list_last(message->
+                                                references_for_threading)->
+                                    data);
+
+            check_parent(&ti, parent, message);
+        }
+        balsa_window_increment_progress(BALSA_WINDOW(index->window));
+    }
+    balsa_window_clear_progress(BALSA_WINDOW(index->window));
+    g_slist_free(root_children);
+    g_hash_table_destroy(ti.id_table);
+    g_hash_table_destroy(ti.ref_table);
 }
 
-static void
-add_message(GtkCTree *ctree, GtkCTreeNode *node, GHashTable *msg_table)
+static gboolean
+add_message(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter,
+            gpointer data)
 {
-    LibBalsaMessage* message=MESSAGE(node);
-    if(!message->message_id)
-	return;
-    if(!g_hash_table_lookup(msg_table, message->message_id))
-	g_hash_table_insert(msg_table, message->message_id, node);
+    struct ThreadingInfo *ti = data;
+    LibBalsaMessage *message = NULL;
+
+    gtk_tree_model_get(model, iter, BNDX_MESSAGE_COLUMN, &message, -1);
+    g_hash_table_insert(ti->ref_table, message,
+                        gtk_tree_row_reference_new(model, path));
+    if (message->message_id
+        && !g_hash_table_lookup(ti->id_table, message->message_id))
+        g_hash_table_insert(ti->id_table, message->message_id, message);
+
+    return FALSE;
 }
Index: src/balsa-index.c
===================================================================
RCS file: /cvs/gnome/balsa/src/balsa-index.c,v
retrieving revision 1.226.2.19
diff -u -r1.226.2.19 balsa-index.c
--- src/balsa-index.c	2002/06/27 08:42:33	1.226.2.19
+++ src/balsa-index.c	2002/07/09 09:53:40
@@ -50,93 +50,77 @@
 
 #include "filter.h"
 
-#define CLIST_WORKAROUND
-#if defined(CLIST_WORKAROUND)
-#define DO_CLIST_WORKAROUND(s) if((s)->row_list) (s)->row_list->prev = NULL;
-#else
-#define DO_CLIST_WORKAROUND(s)
-#endif
-
 /* gtk widget */
 static void balsa_index_class_init(BalsaIndexClass * klass);
-static void balsa_index_init(BalsaIndex * bindex);
+static void balsa_index_init(BalsaIndex * index);
 static void balsa_index_close_and_destroy(GtkObject * obj);
 
-static gint date_compare(GtkCList * clist, gconstpointer ptr1,
-			 gconstpointer ptr2);
-static gint numeric_compare(GtkCList * clist, gconstpointer ptr1,
-			    gconstpointer ptr2);
-static gint size_compare(GtkCList * clist, gconstpointer ptr1,
-                            gconstpointer ptr2);
-static void clist_click_column(GtkCList * clist, gint column,
-			       gpointer data);
+static gint date_compare(LibBalsaMessage * m1, LibBalsaMessage * m2);
+static gint numeric_compare(LibBalsaMessage * m1, LibBalsaMessage * m2);
+static gint size_compare(LibBalsaMessage * m1, LibBalsaMessage * m2);
+static void bndx_column_click(GtkTreeViewColumn * column, gpointer data);
 
 /* statics */
-static void balsa_index_set_sort_order(BalsaIndex * bindex, int column, 
-				    GtkSortType order);
-static void balsa_index_set_first_new_message(BalsaIndex * bindex);
+static void bndx_set_sort_order(BalsaIndex * index, int col_id, 
+				GtkSortType order);
 /* adds a new message */
-static void balsa_index_add(BalsaIndex * bindex, LibBalsaMessage * message);
+static void balsa_index_add(BalsaIndex * index, LibBalsaMessage * message);
 /* retrieve the selection */
-static void balsa_index_set_col_images(BalsaIndex *, GtkCTreeNode*,
-				       LibBalsaMessage *);
-static void balsa_index_set_style(BalsaIndex * bindex, GtkCTreeNode *node);
-static void balsa_index_set_style_recursive(BalsaIndex * bindex, GtkCTreeNode *node);
-static void balsa_index_set_parent_style(BalsaIndex *bindex, GtkCTreeNode *node);
-static void balsa_index_check_visibility(GtkCList * clist,
-                                         GtkCTreeNode * node,
-                                         gfloat row_align);
-static GtkCTreeNode *balsa_index_find_node(BalsaIndex * bindex,
-                                           gboolean previous,
-                                           LibBalsaMessageFlag flag,
-					   gint op,GSList * conditions);
-static void balsa_index_select_next_threaded(BalsaIndex * bindex);
-static void balsa_index_transfer_messages(BalsaIndex * bindex,
+static void bndx_set_col_images(BalsaIndex * index, GtkTreeIter * iter,
+                                LibBalsaMessage * message);
+static gboolean bndx_set_style(BalsaIndex * index, GtkTreePath * path);
+static gboolean bndx_set_style_recursive(BalsaIndex * index,
+                                         GtkTreePath * path);
+static void bndx_set_parent_style(BalsaIndex * index, GtkTreePath * path);
+static void bndx_check_visibility(BalsaIndex * index, GtkTreePath * path);
+static gboolean bndx_find_iter(BalsaIndex * index, GtkTreeIter * iter,
+                               gboolean previous, LibBalsaMessageFlag flag,
+                               gint op, GSList * conditions);
+static void bndx_select_next_threaded(BalsaIndex * index);
+static void bndx_select_iter(BalsaIndex * index, GtkTreeIter * iter);
+static void balsa_index_transfer_messages(BalsaIndex * index,
                                           LibBalsaMailbox * mailbox);
 static void balsa_index_idle_remove(gpointer data);
 static void balsa_index_idle_add(gpointer data, gpointer message);
 static gboolean balsa_index_idle_clear(gpointer data);
-static gint balsa_index_most_recent_message(GtkCList * clist);
-static void refresh_size(GtkCTree * ctree,
-			 GtkCTreeNode *node,
-			 gpointer data);
-static void refresh_date(GtkCTree * ctree,
-			 GtkCTreeNode *node,
-			 gpointer data);
-
-
 
 /* mailbox callbacks */
-static void balsa_index_del (BalsaIndex * bindex, LibBalsaMessage * message);
+static void bndx_messages_remove(BalsaIndex * index, GList * messages);
 static void mailbox_message_changed_status_cb(LibBalsaMailbox * mb,
 					      LibBalsaMessage * message,
-					      BalsaIndex * bindex);
-static void mailbox_message_new_cb(BalsaIndex * bindex,
+					      BalsaIndex * index);
+static void mailbox_message_new_cb(BalsaIndex * index,
 				   LibBalsaMessage * message);
-static void mailbox_messages_new_cb(BalsaIndex * bindex, GList* messages);
-static void mailbox_message_delete_cb(BalsaIndex * bindex, 
+static void mailbox_messages_new_cb(BalsaIndex * index, GList* messages);
+static void mailbox_message_delete_cb(BalsaIndex * index, 
 				      LibBalsaMessage * message);
-static void mailbox_messages_delete_cb(BalsaIndex * bindex, 
+static void mailbox_messages_delete_cb(BalsaIndex * index, 
 				       GList  * message);
+static void mailbox_messages_delete_all_cb(BalsaIndex * index);
 
-/* clist callbacks */
-static gboolean button_event_press_cb(GtkWidget * clist,
-                                      GdkEventButton * event,
-                                      gpointer data);
-static void select_message(GtkWidget * widget, GtkCTreeNode *row, gint column,
-			   gpointer data);
-static void unselect_message(GtkWidget * widget, GtkCTreeNode *row, 
-                             gint column,
-			     gpointer data);
-static void unselect_all_messages (GtkCList* clist, gpointer user_data);
-
-static void resize_column_event_cb(GtkCList * clist, gint column,
-				   gint width, gpointer data);
-static void tree_expand_cb(GtkCTree * ctree, GList * node,
-                           gpointer user_data);
-static void tree_collapse_cb(GtkCTree * ctree, GList * node,
-                           gpointer user_data);
-static void hide_deleted(BalsaIndex * bindex, gboolean hide);
+/* GtkTree* callbacks */
+static void bndx_selection_changed(GtkTreeSelection * selection,
+                                   gpointer data);
+static gboolean bndx_button_event_press_cb(GtkWidget * tree_view,
+                                           GdkEventButton * event,
+                                           gpointer data);
+static void bndx_row_activated(GtkTreeView * tree_view, GtkTreePath * path,
+                               GtkTreeViewColumn * column,
+                               gpointer user_data);
+
+static void bndx_column_resize(GtkWidget * widget,
+                               GtkAllocation * allocation, gpointer data);
+static void bndx_tree_expand_cb(GtkTreeView * tree_view,
+                                GtkTreeIter * iter, GtkTreePath * path,
+                                gpointer user_data);
+static void bndx_tree_collapse_cb(GtkTreeView * tree_view,
+                                  GtkTreeIter * iter, GtkTreePath * path,
+                                  gpointer user_data);
+static void hide_deleted(BalsaIndex * index, gboolean hide);
+static gboolean bndx_path_is_viewable(GtkTreeView * tree_view,
+                                      GtkTreePath * path);
+static gint bndx_row_compare(GtkTreeModel * model, GtkTreeIter * iter1,
+                             GtkTreeIter * iter2, gpointer data);
 
 /* formerly balsa-index-page stuff */
 enum {
@@ -148,7 +132,7 @@
 };
 
 static gboolean idle_handler_cb(GtkWidget * widget);
-static void balsa_index_drag_cb(GtkWidget* widget,
+static void bndx_drag_cb(GtkWidget* widget,
                                 GdkDragContext* drag_context,
                                 GtkSelectionData* data,
                                 guint info,
@@ -156,10 +140,12 @@
                                 gpointer user_data);
 static void replace_attached_data(GtkObject * obj, const gchar * key, 
                                   GtkObject * data);
-static GtkWidget* create_menu(BalsaIndex * bindex);
-static void create_stock_menu_item(GtkWidget * menu, const gchar * type,
-                                   const gchar * label, GtkSignalFunc cb,
-                                   gpointer data, gboolean sensitive);
+static GtkWidget* bndx_popup_menu_create(BalsaIndex * index);
+static GtkWidget* bndx_popup_menu_prepare(BalsaIndex * index);
+static GtkWidget *create_stock_menu_item(GtkWidget * menu,
+                                         const gchar * type,
+                                         const gchar * label,
+                                         GtkSignalFunc cb, gpointer data);
 
 /* static void index_button_press_cb(GtkWidget * widget, */
 /* 				  GdkEventButton * event, gpointer data); */
@@ -183,27 +169,29 @@
     0
 };
 
-static GtkScrolledWindowClass *parent_class = NULL;
+static GtkTreeViewClass *parent_class = NULL;
 
 GtkType
-balsa_index_get_type()
+balsa_index_get_type(void)
 {
     static guint balsa_index_type = 0;
 
     if (!balsa_index_type) {
-	GtkTypeInfo balsa_index_info = {
-	    "BalsaIndex",
-	    sizeof(BalsaIndex),
-	    sizeof(BalsaIndexClass),
-	    (GtkClassInitFunc) balsa_index_class_init,
-	    (GtkObjectInitFunc) balsa_index_init,
-	    (gpointer) NULL,
-	    (gpointer) NULL,
-	    (GtkClassInitFunc) NULL
-	};
-
-	balsa_index_type =
-	    gtk_type_unique(gtk_scrolled_window_get_type(), &balsa_index_info);
+        static const GTypeInfo balsa_index_info = {
+            sizeof(BalsaIndexClass),
+            NULL,               /* base_init */
+            NULL,               /* base_finalize */
+            (GClassInitFunc) balsa_index_class_init,
+            NULL,               /* class_finalize */
+            NULL,               /* class_data */
+            sizeof(BalsaIndex),
+            0,                  /* n_preallocs */
+            (GInstanceInitFunc) balsa_index_init
+        };
+
+        balsa_index_type =
+            g_type_register_static(GTK_TYPE_TREE_VIEW,
+                                   "BalsaIndex", &balsa_index_info, 0);
     }
 
     return balsa_index_type;
@@ -215,37 +203,39 @@
 {
     GtkObjectClass *object_class;
     GtkWidgetClass *widget_class;
-    GtkContainerClass *container_class;
 
     object_class = (GtkObjectClass *) klass;
     widget_class = (GtkWidgetClass *) klass;
-    container_class = (GtkContainerClass *) klass;
 
-    parent_class = gtk_type_class(GTK_TYPE_SCROLLED_WINDOW);
+    parent_class = gtk_type_class(GTK_TYPE_TREE_VIEW);
 
     balsa_index_signals[SELECT_MESSAGE] =
-	gtk_signal_new("select_message",
-		       GTK_RUN_FIRST,
-		       balsa_index_get_type(),
-		       GTK_SIGNAL_OFFSET(BalsaIndexClass, select_message),
-		       gtk_marshal_NONE__POINTER,
-		       GTK_TYPE_NONE, 1, GTK_TYPE_POINTER);
+	g_signal_new("select-message",
+                     G_TYPE_FROM_CLASS(object_class),   
+		     G_SIGNAL_RUN_FIRST,
+		     G_STRUCT_OFFSET(BalsaIndexClass,
+                                     select_message),
+                     NULL, NULL,
+		     g_cclosure_marshal_VOID__OBJECT,
+		     G_TYPE_NONE, 1, G_TYPE_OBJECT);
     balsa_index_signals[UNSELECT_MESSAGE] =
-	gtk_signal_new("unselect_message",
-		       GTK_RUN_FIRST,
-		       balsa_index_get_type(),
-		       GTK_SIGNAL_OFFSET(BalsaIndexClass,
-					 unselect_message),
-		       gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1,
-		       GTK_TYPE_POINTER);
+	g_signal_new("unselect_message",
+                     G_TYPE_FROM_CLASS(object_class),   
+		     G_SIGNAL_RUN_FIRST,
+		     G_STRUCT_OFFSET(BalsaIndexClass,
+                                     unselect_message),
+                     NULL, NULL,
+		     g_cclosure_marshal_VOID__OBJECT,
+                     G_TYPE_NONE, 1, G_TYPE_OBJECT);
     balsa_index_signals[UNSELECT_ALL_MESSAGES] = 
-        gtk_signal_new ("unselect_all_messages",
-                        GTK_RUN_FIRST,
-                        balsa_index_get_type(),
-                        GTK_SIGNAL_OFFSET (BalsaIndexClass, 
-                                           unselect_all_messages),
-                        gtk_marshal_NONE__NONE, 
-                        GTK_TYPE_NONE, 0);
+        g_signal_new("unselect_all_messages",
+                     G_TYPE_FROM_CLASS(object_class),   
+		     G_SIGNAL_RUN_FIRST,
+                     G_STRUCT_OFFSET(BalsaIndexClass, 
+                                     unselect_all_messages),
+                     NULL, NULL,
+		     g_cclosure_marshal_VOID__VOID,
+                     G_TYPE_NONE, 0);
 
     object_class->destroy = balsa_index_close_and_destroy;
     klass->select_message = NULL;
@@ -253,13 +243,13 @@
 }
 
 static void
-balsa_index_init(BalsaIndex * bindex)
+balsa_index_init(BalsaIndex * index)
 {
-    GtkCList *clist;
-    GtkObject* adj;
-    GdkFont *font;
-    int row_height;
-
+    GtkTreeView *tree_view = GTK_TREE_VIEW(index);
+    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
+    GtkTreeStore *tree_store;
+    GtkCellRenderer *renderer;
+    GtkTreeViewColumn *column;
     
     /* status
      * priority
@@ -269,141 +259,196 @@
 	"#",
 	"S",
 	"A",
-	NULL,
-	NULL,
-	NULL,
-	NULL
+        N_("From"),
+        N_("Subject"),
+        N_("Date"),
+        N_("Size")
     };
 
-    /* FIXME: */
-    titles[3] = _("From");
-    titles[4] = _("Subject");
-    titles[5] = _("Date");
-    titles[6] = _("Size");
-
-    bindex->mailbox_node = NULL;
-    adj = gtk_adjustment_new (0.0, 0.0, 10.0, 1.0, 1.0, 1.0);
-    gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (bindex), 
-                                         GTK_ADJUSTMENT (adj));
-    adj = gtk_adjustment_new (0.0, 0.0, 10.0, 1.0, 1.0, 1.0);
-    gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (bindex), 
-                                         GTK_ADJUSTMENT (adj));
-    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (bindex),
-                                    GTK_POLICY_AUTOMATIC,
-                                    GTK_POLICY_AUTOMATIC);
+    tree_store =
+        gtk_tree_store_new(BNDX_N_COLUMNS,
+                           G_TYPE_OBJECT,    /* BNDX_MESSAGE_COLUMN */
+                           G_TYPE_STRING,    /* BNDX_INDEX_COLUMN   */
+                           GDK_TYPE_PIXBUF,  /* BNDX_STATUS_COLUMN  */
+                           GDK_TYPE_PIXBUF,  /* BNDX_ATTACH_COLUMN  */
+                           G_TYPE_STRING,    /* BNDX_FROM_COLUMN    */
+                           G_TYPE_STRING,    /* BNDX_SUBJECT_COLUMN */
+                           G_TYPE_STRING,    /* BNDX_DATE_COLUMN    */
+                           G_TYPE_STRING,    /* BNDX_SIZE_COLUMN    */
+                           GDK_TYPE_COLOR,   /* BNDX_COLOR_COLUMN   */
+                           PANGO_TYPE_WEIGHT /* BNDX_WEIGHT_COLUMN  */
+            );
+    gtk_tree_view_set_model(tree_view, GTK_TREE_MODEL(tree_store));
+    /* the BalsaIndex will hold the only ref on tree_store: */
+    g_object_unref(tree_store);
+
+    /* Index column */
+    column = gtk_tree_view_column_new();
+    gtk_tree_view_column_set_title(column, _(titles[0]));
+    gtk_tree_view_column_set_alignment(column, 0.5);
+    renderer = gtk_cell_renderer_text_new();
+    g_object_set(renderer, "xalign", 1.0, NULL);
+    gtk_tree_view_column_pack_start(column, renderer, FALSE);
+    gtk_tree_view_column_set_attributes(column, renderer,
+                                        "text", BNDX_INDEX_COLUMN,
+                                        NULL);
+    gtk_tree_view_column_set_clickable(column, TRUE);
+    g_signal_connect(G_OBJECT(column), "clicked",
+                     G_CALLBACK(bndx_column_click),
+                     index);
+    gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(tree_store),
+                                    0, bndx_row_compare,
+                                    GINT_TO_POINTER(0), NULL);
+    gtk_tree_view_append_column(tree_view, column);
+
+    /* Status icon column */
+    renderer = gtk_cell_renderer_pixbuf_new();
+    column =
+        gtk_tree_view_column_new_with_attributes(_(titles[1]),
+                                                 renderer,
+                                                 "pixbuf", BNDX_STATUS_COLUMN,
+                                                 NULL);
+    gtk_tree_view_column_set_alignment(column, 0.5);
+    gtk_tree_view_append_column(tree_view, column);
+
+    /* Attachment icon column */
+    renderer = gtk_cell_renderer_pixbuf_new();
+    column =
+        gtk_tree_view_column_new_with_attributes(_(titles[2]),
+                                                 renderer,
+                                                 "pixbuf", BNDX_ATTACH_COLUMN,
+                                                 NULL);
+    gtk_tree_view_column_set_alignment(column, 0.5);
+    gtk_tree_view_append_column(tree_view, column);
+    
+    /* From/To column */
+    renderer = gtk_cell_renderer_text_new();
+    column = 
+        gtk_tree_view_column_new_with_attributes(_(titles[3]),
+                                                 renderer,
+                                                 "text", BNDX_FROM_COLUMN,
+                                                 NULL);
+    gtk_tree_view_column_set_alignment(column, 0.5);
+    gtk_tree_view_column_set_resizable(column, TRUE);
+    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+    gtk_tree_view_append_column(tree_view, column);
+
+    /* Subject column--contains tree expanders */
+    renderer = gtk_cell_renderer_text_new();
+    column = 
+        gtk_tree_view_column_new_with_attributes(_(titles[4]),
+                                                 renderer,
+                                                 "text",
+                                                 BNDX_SUBJECT_COLUMN,
+                                                 "foreground-gdk",
+                                                 BNDX_COLOR_COLUMN,
+                                                 "weight",
+                                                 BNDX_WEIGHT_COLUMN,
+                                                 NULL);
+    gtk_tree_view_column_set_alignment(column, 0.5);
+    gtk_tree_view_column_set_resizable(column, TRUE);
+    gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
+    gtk_tree_view_append_column(tree_view, column);
+    gtk_tree_view_set_expander_column(tree_view, column);
+
+    /* Date column */
+    renderer = gtk_cell_renderer_text_new();
+    column = 
+        gtk_tree_view_column_new_with_attributes(_(titles[5]),
+                                                 renderer,
+                                                 "text", BNDX_DATE_COLUMN,
+                                                 NULL);
+    gtk_tree_view_column_set_alignment(column, 0.5);
+    gtk_tree_view_column_set_resizable(column, TRUE);
+    gtk_tree_view_column_set_clickable(column, TRUE);
+    g_signal_connect(G_OBJECT(column), "clicked",
+                     G_CALLBACK(bndx_column_click),
+                     index);
+    gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(tree_store),
+                                    5, bndx_row_compare,
+                                    GINT_TO_POINTER(5), NULL);
+    gtk_tree_view_append_column(tree_view, column);
+
+    /* Size column */
+    column = gtk_tree_view_column_new();
+    gtk_tree_view_column_set_title(column, _(titles[6]));
+    gtk_tree_view_column_set_alignment(column, 0.5);
+    renderer = gtk_cell_renderer_text_new();
+    g_object_set(renderer, "xalign", 1.0, NULL);
+    gtk_tree_view_column_pack_start(column, renderer, FALSE);
+    gtk_tree_view_column_set_attributes(column, renderer,
+                                        "text", BNDX_SIZE_COLUMN,
+                                        NULL);
+    gtk_tree_view_column_set_clickable(column, TRUE);
+    g_signal_connect(G_OBJECT(column), "clicked",
+                     G_CALLBACK(bndx_column_click),
+                     index);
+    gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(tree_store),
+                                    6, bndx_row_compare,
+                                    GINT_TO_POINTER(6), NULL);
+    gtk_tree_view_append_column(tree_view, column);
+
+    /* Initialize some other members */
+    index->mailbox_node = NULL;
+    index->popup_menu = bndx_popup_menu_create(index);
     
-    /* create the clist */
-    bindex->ctree = GTK_CTREE (gtk_ctree_new_with_titles (7, 4, titles));
-    clist = GTK_CLIST(bindex->ctree);
-    gtk_container_add (GTK_CONTAINER (bindex), GTK_WIDGET (bindex->ctree));
-
-    gtk_signal_connect(GTK_OBJECT(clist), "click_column",
-		       GTK_SIGNAL_FUNC(clist_click_column), bindex);
-
-    gtk_clist_set_selection_mode(clist, GTK_SELECTION_EXTENDED);
-    gtk_clist_set_column_justification(clist, 0, GTK_JUSTIFY_RIGHT);
-    gtk_clist_set_column_justification(clist, 1, GTK_JUSTIFY_CENTER);
-    gtk_clist_set_column_justification(clist, 2, GTK_JUSTIFY_CENTER);
-    gtk_clist_set_column_justification(clist, 6, GTK_JUSTIFY_RIGHT);
-
-    /* Set the width of any new columns to the current column widths being used */
-    gtk_clist_set_column_width(clist, 0, balsa_app.index_num_width);
-    gtk_clist_set_column_width(clist, 1, balsa_app.index_status_width);
-    gtk_clist_set_column_width(clist, 2, balsa_app.index_attachment_width);
-    gtk_clist_set_column_width(clist, 3, balsa_app.index_from_width);
-    gtk_clist_set_column_width(clist, 4, balsa_app.index_subject_width);
-    gtk_clist_set_column_width(clist, 5, balsa_app.index_date_width);
-    gtk_clist_set_column_width(clist, 6, balsa_app.index_size_width);
-#if BALSA_MAJOR < 2
-    font = gtk_widget_get_style (GTK_WIDGET(clist))->font;
-#else
-    font = gtk_style_get_font(gtk_widget_get_style (GTK_WIDGET(clist)));
-#endif                          /* BALSA_MAJOR < 2 */
-    row_height = font->ascent + font->descent+2;
-    
-    if(row_height<16) /* pixmap height */
-	gtk_clist_set_row_height(clist, 16);
+    gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
 
     /* Set default sorting behaviour */
-    gtk_clist_set_sort_column(clist, 5);
-    gtk_clist_set_compare_func(clist, date_compare);
-    gtk_clist_set_sort_type(clist, GTK_SORT_DESCENDING);
+    gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(tree_store),
+                                         5, GTK_SORT_ASCENDING);
 
     /* handle select row signals to display message in the window
      * preview pane */
-    gtk_signal_connect(GTK_OBJECT(bindex->ctree),
-		       "tree-select-row",
-		       (GtkSignalFunc) select_message, (gpointer) bindex);
-
-    gtk_signal_connect(GTK_OBJECT(bindex->ctree),
-		       "tree-unselect-row",
-		       (GtkSignalFunc) unselect_message,
-		       (gpointer) bindex);
-
-    gtk_signal_connect (GTK_OBJECT(bindex->ctree),
-                        "unselect-all",
-                        (GtkSignalFunc) unselect_all_messages, 
-                        (gpointer) bindex);
-    
+    g_signal_connect(selection, "changed",
+		     G_CALLBACK(bndx_selection_changed), index);
+
     /* we want to handle button presses to pop up context menus if
      * necessary */
-    gtk_signal_connect(GTK_OBJECT(bindex->ctree),
-		       "button_press_event",
-		       (GtkSignalFunc) button_event_press_cb,
-		       (gpointer) bindex);
+    g_signal_connect(tree_view, "button_press_event",
+		     G_CALLBACK(bndx_button_event_press_cb), NULL);
+    g_signal_connect(tree_view, "row-activated",
+		     G_CALLBACK(bndx_row_activated), NULL);
 
     /* catch thread expand/collapse events, to set the head node style
      * for unread messages */
-    gtk_signal_connect_after(GTK_OBJECT(bindex->ctree),
-                             "tree-expand",
-                             (GtkSignalFunc) tree_expand_cb,
-                             (gpointer) bindex);
-    gtk_signal_connect_after(GTK_OBJECT(bindex->ctree),
-                             "tree-collapse",
-                             (GtkSignalFunc) tree_collapse_cb,
-                             (gpointer) bindex);
+    g_signal_connect_after(tree_view, "row-expanded",
+                           G_CALLBACK(bndx_tree_expand_cb), NULL);
+    g_signal_connect_after(tree_view, "row-collapsed",
+                           G_CALLBACK(bndx_tree_collapse_cb), NULL);
 
     /* We want to catch column resize attempts to store the new value */
-    gtk_signal_connect(GTK_OBJECT(clist),
-		       "resize_column",
-		       GTK_SIGNAL_FUNC(resize_column_event_cb), NULL);
+    g_signal_connect_after(tree_view, "size-allocate",
+                           G_CALLBACK(bndx_column_resize),
+                           NULL);
 
-    gtk_drag_source_set(GTK_WIDGET (bindex->ctree), 
+    gtk_drag_source_set(GTK_WIDGET (index), 
                         GDK_BUTTON1_MASK | GDK_SHIFT_MASK | GDK_CONTROL_MASK,
                         index_drag_types, ELEMENTS(index_drag_types),
                         GDK_ACTION_DEFAULT | GDK_ACTION_COPY | 
                         GDK_ACTION_MOVE);
-    gtk_signal_connect(GTK_OBJECT(bindex->ctree), "drag-data-get",
-                       GTK_SIGNAL_FUNC(balsa_index_drag_cb), NULL);
+    g_signal_connect(index, "drag-data-get",
+                     G_CALLBACK(bndx_drag_cb), NULL);
 
-    g_get_current_time (&bindex->last_use);
-    GTK_OBJECT_UNSET_FLAGS (bindex->ctree, GTK_CAN_FOCUS);
-    gtk_widget_show_all (GTK_WIDGET(bindex));
-    gtk_widget_ref (GTK_WIDGET(bindex));
+    balsa_index_set_column_widths(index);
+    g_get_current_time (&index->last_use);
+    GTK_OBJECT_UNSET_FLAGS (index, GTK_CAN_FOCUS);
+    gtk_widget_show_all (GTK_WIDGET(index));
+    gtk_widget_ref (GTK_WIDGET(index));
 }
 
 GtkWidget *
 balsa_index_new(void)
 {
-    BalsaIndex* bindex;
-    bindex = BALSA_INDEX (gtk_type_new(BALSA_TYPE_INDEX));
-#if BALSA_MAJOR < 2
-    gtk_object_default_construct (GTK_OBJECT(bindex));
-#endif                          /* BALSA_MAJOR < 2 */
+    BalsaIndex* index = g_object_new(BALSA_TYPE_INDEX, NULL);
 
-    return GTK_WIDGET(bindex);
+    return GTK_WIDGET(index);
 }
 
 
 static gint
-date_compare(GtkCList * clist, gconstpointer ptr1, gconstpointer ptr2)
+date_compare(LibBalsaMessage * m1, LibBalsaMessage * m2)
 {
-    LibBalsaMessage *m1, *m2;
-    GtkCListRow *row1 = (GtkCListRow *) ptr1;
-    GtkCListRow *row2 = (GtkCListRow *) ptr2;
-
-    m1 = row1->data;
-    m2 = row2->data;
     g_return_val_if_fail(m1 && m2, 0);
 
     return m2->date - m1->date;
@@ -411,17 +456,10 @@
 
 
 static gint
-numeric_compare(GtkCList * clist, gconstpointer ptr1, gconstpointer ptr2)
+numeric_compare(LibBalsaMessage * m1, LibBalsaMessage * m2)
 {
-    LibBalsaMessage *m1, *m2;
     glong t1, t2;
 
-    GtkCListRow *row1 = (GtkCListRow *) ptr1;
-    GtkCListRow *row2 = (GtkCListRow *) ptr2;
-
-    m1 = row1->data;
-    m2 = row2->data;
-
     g_return_val_if_fail(m1 && m2, 0);
 
     t1 = LIBBALSA_MESSAGE_GET_NO(m1);
@@ -431,19 +469,11 @@
 }
 
 static gint
-size_compare(GtkCList * clist, gconstpointer ptr1, gconstpointer ptr2)
+size_compare(LibBalsaMessage * m1, LibBalsaMessage * m2)
 {
-    LibBalsaMessage *m1, *m2;
     glong t1, t2;
 
-    GtkCListRow *row1 = (GtkCListRow *) ptr1;
-    GtkCListRow *row2 = (GtkCListRow *) ptr2;
-
-    m1 = row1->data;
-    m2 = row2->data;
-
-    g_return_val_if_fail(m1, 0);
-    g_return_val_if_fail(m2, 0);
+    g_return_val_if_fail(m1 && m2, 0);
 
     if (balsa_app.line_length) {
         t1 = LIBBALSA_MESSAGE_GET_LINES(m1);
@@ -456,69 +486,61 @@
     return t2-t1;
 }
 
-/* balsa_index_most_recent_message:
-   helper function, finds the message most recently selected and
-   fails with -1, if the selection is empty.
-*/
-static gint
-balsa_index_most_recent_message(GtkCList * clist)
+static void
+bndx_column_click(GtkTreeViewColumn * column, gpointer data)
 {
-    if (clist->selection == NULL)
-        return -1;
-    else {
-        GtkCTreeNode *node = g_list_last(clist->selection)->data;
-        gpointer data =
-            gtk_ctree_node_get_row_data(GTK_CTREE(clist), node);
-        return gtk_clist_find_row_from_data(clist, data);
+    GtkSortType order = GTK_SORT_ASCENDING;
+    GtkTreeView *tree_view = GTK_TREE_VIEW(data);
+    GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+    GtkTreeSortable *sortable = GTK_TREE_SORTABLE(model);
+    GList *columns = gtk_tree_view_get_columns(tree_view);
+    gint col_id = g_list_index(columns, column);
+    gint current_col_id;
+
+    g_list_free(columns);
+    if (gtk_tree_sortable_get_sort_column_id(sortable,
+                                             &current_col_id, &order)) {
+        GtkTreeViewColumn *current_column =
+            gtk_tree_view_get_column(tree_view, current_col_id);
+
+        gtk_tree_view_column_set_sort_indicator(current_column, FALSE);
+        if (current_col_id == col_id)
+            order = (order == GTK_SORT_DESCENDING ?
+                    GTK_SORT_ASCENDING : GTK_SORT_DESCENDING);
     }
-}
 
+    BALSA_INDEX(tree_view)->mailbox_node->sort_field = col_id;
+    BALSA_INDEX(tree_view)->mailbox_node->sort_type  = order;
+
+    gtk_tree_sortable_set_sort_column_id(sortable, col_id, order);
+    gtk_tree_view_column_set_sort_indicator(column, TRUE);
+    gtk_tree_view_column_set_sort_order(column, order);
+}
 
 static void
-clist_click_column(GtkCList * clist, gint column, gpointer data)
+bndx_expand_to_path(GtkTreeView * tree_view, GtkTreePath * path)
 {
-    GtkSortType sort_type = clist->sort_type;
+    GtkTreePath *tmp = gtk_tree_path_copy(path);
 
-    if (column == clist->sort_column)
-	sort_type = (sort_type == GTK_SORT_ASCENDING) ?
-	    GTK_SORT_DESCENDING : GTK_SORT_ASCENDING;
-	
-    balsa_index_set_sort_order(BALSA_INDEX(data), column, sort_type);
-    gtk_clist_sort(clist);
-    DO_CLIST_WORKAROUND(clist);
+    while (gtk_tree_path_up(tmp) && gtk_tree_path_get_depth(tmp) > 0)
+        gtk_tree_view_expand_row(tree_view, tmp, FALSE);
 
-    balsa_index_check_visibility(clist, NULL, 0.5);
+    gtk_tree_path_free(tmp);
 }
-
 
-/* 
- * Search the index, locate the first unread message, and update the
- * index's first_new_message field to point at that message.  If no
- * unread messages are found, first_new_message is set to NULL
- */
-static void
-balsa_index_set_first_new_message(BalsaIndex * bindex)
-{
-    GtkCTreeNode *node =
-        balsa_index_find_node(bindex, FALSE, LIBBALSA_MESSAGE_FLAG_NEW,
-			      FILTER_NOOP, NULL);
-    if (node)
-        bindex->first_new_message =
-            LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data
-                             (bindex->ctree, node));
-}
-
-struct BalsaIndexScanInfo {
-    gpointer node;                      /* current ctree node */
-    GList *selection;                   /* copy of clist->selection */
-    GHashTable* matching;               /* matching messages */
-    LibBalsaMessageFlag flag;           /* look only for matching nodes */
-    GtkCTreeNode *first;                /* returns first matching */
-    GtkCTreeNode *previous;             /* returns last matching
-                                           before selection */
-    GtkCTreeNode *next;                 /* returns first matching
-                                           after selection */
-    GtkCTreeNode *last;                 /* returns last matching */
+struct BndxScanInfo {
+    GtkTreeView *tree_view;     /* the tree                     */
+    LibBalsaMessage *message;   /* current message              */
+    GHashTable *matching;       /* matching messages            */
+    LibBalsaMessageFlag flag;   /* look only for matching nodes */
+    GtkTreeIter first;          /* returns first matching       */
+    gboolean first_valid;
+    GtkTreeIter previous;       /* returns last matching        */
+    gboolean prev_valid;        /* before selection             */
+    GtkTreeIter next;           /* returns first matching       */
+    gboolean next_valid;        /* after selection              */
+    GtkTreeIter last;           /* returns last matching        */
+    gboolean last_valid;
 };
 
 /* 
@@ -528,49 +550,42 @@
  * selects it.
  */
 static gboolean
-moveto_handler(BalsaIndex * bindex)
+moveto_handler(BalsaIndex * index)
 {
-    gint row = -1;
-    gpointer row_data = NULL;
-    GList* list = NULL;
-    GtkCTreeNode *node;
+    GtkTreeView *tree_view = GTK_TREE_VIEW(index);
+    GtkTreeModel *model;
+    gint rows;
+    GtkTreeIter iter;
     
-    if (!GTK_WIDGET_VISIBLE(GTK_WIDGET(bindex)))
-	return TRUE;
-
     gdk_threads_enter();
 
-    if (bindex->first_new_message != NULL) {
-        row_data = bindex->first_new_message;
-    } else if ((list = GTK_CLIST (bindex->ctree)->selection) != NULL) {
-        list = g_list_last (list);
-        row_data = list->data;
-    } else {
-        row_data = gtk_clist_get_row_data(GTK_CLIST(bindex->ctree),
-                                          GTK_CLIST(bindex->ctree)->rows - 1);
+    if (!GTK_WIDGET_VISIBLE(GTK_WIDGET(index))) {
+        gdk_threads_leave();
+	return TRUE;
     }
-        
-    node = gtk_ctree_find_by_row_data(bindex->ctree, NULL, row_data);
-    while (node && !gtk_ctree_is_viewable(bindex->ctree, node)) {
-        node = GTK_CTREE_ROW(node)->parent;
-        if (balsa_app.view_message_on_open)
-            gtk_ctree_expand(bindex->ctree, node);
-    }
-    if (!balsa_app.view_message_on_open)
-        row_data = gtk_ctree_node_get_row_data(bindex->ctree, node);
-
-    if (row_data) {
-        row = gtk_clist_find_row_from_data (GTK_CLIST (bindex->ctree),
-                                            row_data);
-	
-        if (balsa_app.view_message_on_open)
-            balsa_index_select_row (bindex, row);
-	else
-	   gtk_clist_moveto (GTK_CLIST (bindex->ctree), row, -1, 0.5, 0.0);
+
+    model = gtk_tree_view_get_model(tree_view);
+    rows = gtk_tree_model_iter_n_children(model, NULL);
+    if (rows <= 0) {
+        gdk_threads_leave();
+        return FALSE;
     }
+
+    if (!bndx_find_iter(index, &iter, FALSE, LIBBALSA_MESSAGE_FLAG_NEW,
+                        FILTER_NOOP, NULL))
+        gtk_tree_model_iter_nth_child(model, &iter, NULL, rows - 1);
+
+    if (balsa_app.view_message_on_open)
+        bndx_select_iter(index, &iter);
+    else {
+        GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
+
+        bndx_expand_to_path(tree_view, path);
+        gtk_tree_view_scroll_to_cell(tree_view, path, NULL, FALSE, 0, 0);
+        gtk_tree_path_free(path);
+    }
     
     gdk_threads_leave();
-
     return FALSE;
 }
 
@@ -588,13 +603,15 @@
 */
 
 gboolean
-balsa_index_load_mailbox_node (BalsaIndex * bindex, BalsaMailboxNode* mbnode)
+balsa_index_load_mailbox_node (BalsaIndex * index, BalsaMailboxNode* mbnode)
 {
+    GtkTreeView *tree_view = GTK_TREE_VIEW(index);
+    GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
     LibBalsaMailbox* mailbox;
     gchar *msg;
     gboolean successp;
 
-    g_return_val_if_fail (bindex != NULL, TRUE);
+    g_return_val_if_fail (index != NULL, TRUE);
     g_return_val_if_fail (mbnode != NULL, TRUE);
     g_return_val_if_fail (mbnode->mailbox != NULL, TRUE);
 
@@ -612,81 +629,86 @@
     /*
      * release the old mailbox
      */
-    if (bindex->mailbox_node && bindex->mailbox_node->mailbox) {
-        mailbox = bindex->mailbox_node->mailbox;
+    if (index->mailbox_node && index->mailbox_node->mailbox) {
+        mailbox = index->mailbox_node->mailbox;
 
 	/* This will disconnect all of our signals */
-	gtk_signal_disconnect_by_data(GTK_OBJECT(mailbox), bindex);
+	gtk_signal_disconnect_by_data(GTK_OBJECT(mailbox), index);
 	libbalsa_mailbox_close(mailbox);
-	gtk_clist_clear(GTK_CLIST(bindex->ctree));
+	gtk_tree_store_clear(GTK_TREE_STORE(model));
     }
 
     /*
      * set the new mailbox
      */
-    bindex->mailbox_node = mbnode;
+    index->mailbox_node = mbnode;
     /*
      * rename "from" column to "to" for outgoing mail
      */
     if (mailbox == balsa_app.sentbox ||
 	mailbox == balsa_app.draftbox || mailbox == balsa_app.outbox) {
+        GtkTreeViewColumn *column = gtk_tree_view_get_column(tree_view, 3);
 
-	gtk_clist_set_column_title(GTK_CLIST(bindex->ctree), 3, _("To"));
+        gtk_tree_view_column_set_title(column, _("To"));
     }
 
     gtk_signal_connect(GTK_OBJECT(mailbox), "message-status-changed",
 		       GTK_SIGNAL_FUNC(mailbox_message_changed_status_cb),
-		       (gpointer) bindex);
+		       (gpointer) index);
     gtk_signal_connect_object(GTK_OBJECT(mailbox), "message-new",
 		       GTK_SIGNAL_FUNC(mailbox_message_new_cb),
-		       (gpointer) bindex);
+		       (gpointer) index);
     gtk_signal_connect_object(GTK_OBJECT(mailbox), "messages-new",
 		       GTK_SIGNAL_FUNC(mailbox_messages_new_cb),
-		       (gpointer) bindex);
+		       (gpointer) index);
     gtk_signal_connect_object(GTK_OBJECT(mailbox), "message-delete",
 		       GTK_SIGNAL_FUNC(mailbox_message_delete_cb),
-		       (gpointer) bindex);
+		       (gpointer) index);
     gtk_signal_connect_object(GTK_OBJECT(mailbox), "messages-delete",
 		       GTK_SIGNAL_FUNC(mailbox_messages_delete_cb),
-		       (gpointer) bindex);
+		       (gpointer) index);
+    gtk_signal_connect_object(GTK_OBJECT(mailbox), "messages-delete-all",
+		       GTK_SIGNAL_FUNC(mailbox_messages_delete_all_cb),
+		       (gpointer) index);
 
     /* do threading */
-    balsa_index_set_sort_order(bindex, mbnode->sort_field, 
-			       mbnode->sort_type);
+    bndx_set_sort_order(index, mbnode->sort_field, mbnode->sort_type);
     /* FIXME: this is an ugly way of doing it:
        override default mbost threading type with the global balsa
        default setting
     */
-    balsa_index_set_threading_type(bindex, balsa_app.threading_type);
-    balsa_index_set_first_new_message(bindex);
+    balsa_index_set_threading_type(index, balsa_app.threading_type);
 
-    gtk_idle_add((GtkFunction) moveto_handler, bindex);
+    gtk_idle_add((GtkFunction) moveto_handler, index);
 
     return FALSE;
 }
 
 
 static void
-balsa_index_add(BalsaIndex * bindex, LibBalsaMessage * message)
+balsa_index_add(BalsaIndex * index, LibBalsaMessage * message)
 {
+    GtkTreeView *tree_view = GTK_TREE_VIEW(index);
+    GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+    GtkTreeIter iter;
     gchar buff1[32];
     gchar *text[7];
     gchar *name_str=NULL;
-    GtkCTreeNode *node, *sibling;
     GList *list;
     LibBalsaAddress *addy = NULL;
     LibBalsaMailbox* mailbox;
     gboolean append_dots;
+    GtkTreePath *path;
     
 
-    g_return_if_fail(bindex != NULL);
+    g_return_if_fail(index != NULL);
     g_return_if_fail(message != NULL);
 
     if (balsa_app.hide_deleted 
         && message->flags & LIBBALSA_MESSAGE_FLAG_DELETED)
         return;
 
-    mailbox = bindex->mailbox_node->mailbox;
+    mailbox = index->mailbox_node->mailbox;
     
     if (mailbox == NULL)
 	return;
@@ -717,157 +739,199 @@
     if(!name_str)		/* !addy, or addy contained no name/address */
 	name_str = "";
 
-    text[3] = append_dots ? g_strconcat(name_str, ",...", NULL)
-	: name_str; 
-
+    text[3] = append_dots ? g_strconcat(name_str, ",...", NULL) : name_str;
     text[4] = (gchar*)LIBBALSA_MESSAGE_GET_SUBJECT(message);
     text[5] =
 	libbalsa_message_date_to_gchar(message, balsa_app.date_string);
     text[6] =
 	libbalsa_message_size_to_gchar(message, balsa_app.line_length);
+
+    gtk_tree_store_insert_before(GTK_TREE_STORE(model), &iter, NULL, NULL);
+    gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
+                       BNDX_MESSAGE_COLUMN, message,
+                       BNDX_INDEX_COLUMN, text[0],
+                       BNDX_FROM_COLUMN, text[3],
+                       BNDX_SUBJECT_COLUMN, text[4],
+                       BNDX_DATE_COLUMN, text[5],
+                       BNDX_SIZE_COLUMN, text[6],
+                       BNDX_COLOR_COLUMN, NULL,
+                       BNDX_WEIGHT_COLUMN, PANGO_WEIGHT_NORMAL,
+                       -1);
 
-    sibling = GTK_CTREE_NODE(GTK_CLIST(bindex->ctree)->row_list);
-    node = gtk_ctree_insert_node(GTK_CTREE(bindex->ctree), NULL, sibling, 
-                                 text, 2, NULL, NULL, NULL, NULL, 
-                                 FALSE, TRUE);
     if(append_dots) g_free(text[3]);
     g_free(text[5]);
     g_free(text[6]);
-
-    gtk_ctree_node_set_row_data (GTK_CTREE (bindex->ctree), node, 
-                                 (gpointer) message);
 
-    balsa_index_set_col_images(bindex, node, message);
-    balsa_index_set_parent_style(bindex, node);
+    bndx_set_col_images(index, &iter, message);
+    path = gtk_tree_model_get_path(model, &iter);
+    bndx_set_parent_style(index, path);
+    gtk_tree_path_free(path);
 }
 
+struct BndxFindInfo {
+    LibBalsaMessage *message;
+    GtkTreePath **path;
+    GtkTreeIter *iter;
+    gboolean valid;
+};
+
 /*
-  See: http://mail.gnome.org/archives/balsa-list/2000-November/msg00212.html
-  for discussion of the GtkCtree bug. The bug is triggered when one
-  attempts to delete a collapsed message thread.
-*/
-static void
-balsa_index_del(BalsaIndex * bindex, LibBalsaMessage * message)
+ * bndx_find_message
+ *
+ * index:       the BalsaIndex to be searched;
+ * path:        location to store the GtkTreePath to the message (may be
+ *              NULL);
+ * iter:        location to store a GtkTreeIter for accessing the
+ *              message (may be NULL);
+ * message:     the LibBalsaMessage for which we're searching.
+ *
+ * bndx_find_func is a callback.
+ */
+static gboolean
+bndx_find_func(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter,
+              gpointer data)
 {
-    gint row;
-    gpointer row_data;
-    GtkCTreeNode *node;
+    struct BndxFindInfo *bfi = data;
+    LibBalsaMessage *message = NULL;
 
-    g_return_if_fail(bindex != NULL);
-    g_return_if_fail(message != NULL);
+    gtk_tree_model_get(model, iter, BNDX_MESSAGE_COLUMN, &message, -1);
+    if (message == bfi->message) {
+        if (bfi->path)
+            *bfi->path = gtk_tree_path_copy(path);
+        if (bfi->iter)
+            *bfi->iter = *iter;
+        bfi->valid = TRUE;
+    }
 
-    if (bindex->mailbox_node->mailbox == NULL)
-	return;
+    return bfi->valid;
+}
 
-    node = gtk_ctree_find_by_row_data (GTK_CTREE (bindex->ctree), NULL, 
-                                       (gpointer) message);
+static gboolean
+bndx_find_message(BalsaIndex * index, GtkTreePath ** path,
+                  GtkTreeIter * iter, LibBalsaMessage *message)
+{
+    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(index));
+    struct BndxFindInfo bfi;
 
-    if (node == NULL)
-	return;
+    bfi.message = message;
+    bfi.path = path;
+    bfi.iter = iter;
+    bfi.valid = FALSE;
+    gtk_tree_model_foreach(model, bndx_find_func, &bfi);
 
-    if(bindex->first_new_message == message){
-	bindex->first_new_message=NULL;
-    }
+    return bfi.valid;
+}
 
-    {
-	GtkCTreeNode *children=GTK_CTREE_ROW(node)->children;
-	if(children!=NULL){
-	    GtkCTreeNode *sibling=GTK_CTREE_ROW(node)->parent;
-	    GtkCTreeNode *next;
-	    while(sibling!=NULL){
-		if(GTK_CTREE_ROW(sibling)->parent==NULL)break;
-		sibling=GTK_CTREE_ROW(sibling)->parent;
-	    }
-	    
-	    if(sibling!=NULL)sibling=GTK_CTREE_ROW(sibling)->sibling;
-	    else{sibling=GTK_CTREE_ROW(node)->sibling;}
-
-
-	    /* BEGIN GtkCTree bug workaround. */
-           if(sibling==NULL){
-             gboolean expanded;
-             gtk_ctree_get_node_info(GTK_CTREE(bindex->ctree), node,
-                                     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-                                     &expanded);
-             if(!expanded)
-               gtk_ctree_expand(GTK_CTREE(bindex->ctree), node);
-           }
-	   /* end GtkCTRee bug workaround. */
-
-	    while(1){
-		if(children==NULL)break;
-		next=GTK_CTREE_ROW(children)->sibling;
-		gtk_ctree_move(GTK_CTREE (bindex->ctree), 
-                               children, NULL, sibling);
-		children=next;
-	    }
-	    node=gtk_ctree_find_by_row_data (GTK_CTREE (bindex->ctree), 
-					     NULL, (gpointer) message);
-	}
+static void
+bndx_messages_remove(BalsaIndex * index, GList * messages)
+{
+    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(index));
+    GtkTreeSelection *selection =
+        gtk_tree_view_get_selection(GTK_TREE_VIEW(index));
+    GtkTreeIter iter;
+    LibBalsaMessage *message;
+    GList *children = NULL;
+    GList *list;
+
+    g_return_if_fail(index != NULL);
+
+    if (index->mailbox_node->mailbox == NULL)
+        return;
+
+    /* make a list of children that need to be moved up */
+    for (list = messages; list; list = g_list_next(list)) {
+        message = list->data;
+        if (bndx_find_message(index, NULL, &iter, message)) {
+            GtkTreeIter child_iter;
+
+            if (gtk_tree_model_iter_children(model, &child_iter, &iter)) {
+                do {
+                    gtk_tree_model_get(model, &child_iter, 
+                                       BNDX_MESSAGE_COLUMN, &message,
+                                       -1);
+                    if (!g_list_find(messages, message))
+                        children = g_list_prepend(children, message);
+                } while (gtk_tree_model_iter_next(model, &child_iter));
+            }
+        }
     }
 
+    g_signal_handlers_block_by_func(selection,
+                                    G_CALLBACK(bndx_selection_changed),
+                                    index);
+
+    /* move the children to the top level */
+    for (list = children; list; list = g_list_next(list)) {
+        GtkTreePath *path;
+
+        if (bndx_find_message(index, &path, NULL, message)) {
+            balsa_index_move_subtree(model, path, NULL, NULL);
+            gtk_tree_path_free(path);
+        }
+    }
+    g_list_free(children);
 
-    row_data = gtk_ctree_node_get_row_data (bindex->ctree, node);
-    row = gtk_clist_find_row_from_data (GTK_CLIST (bindex->ctree), row_data);
-    gtk_clist_unselect_row (GTK_CLIST (bindex->ctree), row, -1);
-    gtk_ctree_remove_node(GTK_CTREE(bindex->ctree), node);
+    /* remove the messages */
+    for (list = messages; list; list = g_list_next(list)) {
+        if (bndx_find_message(index, NULL, &iter, message)) {
+            gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
+        }
+    }
 
+    g_signal_handlers_unblock_by_func(selection,
+                                      G_CALLBACK(bndx_selection_changed),
+                                      index);
 
     /* if last message is removed, clear the preview */
-    if (GTK_CLIST (bindex->ctree)->rows <= 0) {
-        balsa_index_idle_add(bindex, NULL);
-    }
+    if (!gtk_tree_model_get_iter_first(model, &iter))
+        balsa_index_idle_add(index, NULL);
 }
 
 
-/* balsa_index_select_row ()
+/* bndx_select_path ()
  * 
  * Takes care of the actual selection, unselecting other messages and
  * making sure the selected row is within bounds and made visible.
  * */
-void
-balsa_index_select_row(BalsaIndex * bindex, gint row)
+static void
+bndx_select_path(BalsaIndex * index, GtkTreePath * path)
 {
-    GtkCList *clist;
+    GtkTreeView *tree_view;
+    GtkTreeSelection *selection;
 
-    g_return_if_fail(bindex != NULL);
-    g_return_if_fail(BALSA_IS_INDEX(bindex));
+    g_return_if_fail(index != NULL);
+    g_return_if_fail(BALSA_IS_INDEX(index));
 
-    clist = GTK_CLIST(bindex->ctree);
-
-    if (row < 0) {
-	if (clist->rows > 0)
-	    row = 0;
-	else
-	    return;
-    }
+    tree_view = GTK_TREE_VIEW(index);
+    selection = gtk_tree_view_get_selection(tree_view);
+    gtk_tree_selection_unselect_all(selection);
+    gtk_tree_selection_select_path(selection, path);
 
-    if (row >= clist->rows) {
-	if (clist->rows > 0)
-	    row = clist->rows - 1;
-	else
-	    return;
-    }
-
-    gtk_clist_unselect_all(clist);
-    gtk_clist_select_row(clist, row, -1);
-
-    if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_FULL) 
-	gtk_clist_moveto(clist, row, -1, 0.5, 0.0);
+    gtk_tree_view_scroll_to_cell(tree_view, path, NULL, FALSE, 0, 0);
 }
 
 static void
-balsa_index_check_visibility(GtkCList *clist, GtkCTreeNode * node,
-                             gfloat row_align)
+bndx_check_visibility(BalsaIndex * index, GtkTreePath * path)
 {
-    gint row;
-    if (node) {
-        gpointer tmp = gtk_ctree_node_get_row_data(GTK_CTREE(clist), node);
-        row = gtk_clist_find_row_from_data(clist, tmp);
-    } else
-        row = balsa_index_most_recent_message(clist);
-    if (gtk_clist_row_is_visible(clist, row) != GTK_VISIBILITY_FULL) 
-	gtk_clist_moveto(clist, row, -1, row_align, 0.0);
+    GtkTreeView *tree_view = GTK_TREE_VIEW(index);
+    GtkTreePath *tmp;
+
+    if (path)
+        tmp = gtk_tree_path_copy(path);
+    else {
+        BalsaMessage *msg;
+
+        if (!balsa_app.previewpane)
+            return;
+        msg = BALSA_MESSAGE(balsa_app.main_window->preview);
+        if (!msg)
+            return;
+        if (!bndx_find_message(index, &tmp, NULL, msg->message))
+            return;
+    }
+
+    gtk_tree_view_scroll_to_cell(tree_view, tmp, NULL, FALSE, 0, 0);
+    gtk_tree_path_free(tmp);
 }
 
 /*
@@ -891,7 +955,7 @@
  *   callback for `previous message' menu item and `open previous'
  *   toolbar button
  *
- * - balsa_index_select_next_threaded: 
+ * - bndx_select_next_threaded: 
  *   - selects first unselected message after first selected message,
  *     expanding thread if necessary
  *   - if none, falls back to last viewable message before first
@@ -919,220 +983,227 @@
  * - b->next is first viewable message after current, NULL if none,
  *     first message if no current message
  */
-static void
-balsa_index_scan_node(GtkCTree * ctree, GtkCTreeNode * node,
-                      struct BalsaIndexScanInfo *b)
+static gboolean
+bndx_find_iter_func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
 {
-    if (node == b->node) {
+    struct BndxScanInfo *b = data;
+    LibBalsaMessage *message;
+
+    gtk_tree_model_get(model, iter, BNDX_MESSAGE_COLUMN, &message, -1);
+
+    if (message == b->message) {
         b->previous = b->last;
-        b->next = NULL;
+        b->prev_valid = b->last_valid;
+        b->next_valid = FALSE;
     } else {
-        LibBalsaMessage *message =
-            LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data(ctree, node));
+	gboolean found = FALSE;
+
         /* if we're not looking for flagged messages or we are called
          * by a search function, we want only viewable messages if we
          * are looking for flagged messages, we want those that match,
          * viewable or not */
-	gboolean found = (b->flag & message->flags);
-	/* FIXME: simplify this. It  is not clear what is the scanning
-           search  condition combinations  are  valid: matching  flag,
-           matching filter, or something else. This makes this chunk
-	   ambigous. */
-	found |= (b->flag == 0 && !b->matching && 
-             gtk_ctree_is_viewable(ctree, node))
-	    || (b->matching && g_hash_table_lookup(b->matching,message));
+        if (b->flag & message->flags)
+            found = TRUE;
+        if (b->flag == 0 && !b->matching
+            && bndx_path_is_viewable(b->tree_view, path))
+            found = TRUE;
+        if (b->matching && g_hash_table_lookup(b->matching, message))
+            found = TRUE;
+
         if (found) {
-            if (b->first == NULL)
+            if (!b->first_valid) {
                 /* first matching message */
-                b->first = node;
-            if (b->next == NULL)
+                b->first = *iter;
+                b->first_valid = TRUE;
+            }
+            if (!b->next_valid) {
                 /* first message, or first after current */
-                b->next = node;
-            b->last = node;
+                b->next = *iter;
+                b->next_valid = TRUE;
+            }
+            b->last = *iter;
+            b->last_valid = TRUE;
         }
     }
+
+    return FALSE;
 }
 
-/* balsa_index_select_node:
- * make sure it's viewable, then pass it to balsa_index_select_row
+/* bndx_select_iter:
+ * make sure it's viewable, then pass it to bndx_select_path
  * no-op if it's NULL
  */
 static void
-balsa_index_select_node(BalsaIndex * bindex, GtkCTreeNode * node)
+bndx_select_iter(BalsaIndex * index, GtkTreeIter * iter)
 {
-    if (node) {
-        gpointer tmp = gtk_ctree_node_get_row_data(bindex->ctree, node);
-        GtkCList *clist = GTK_CLIST(bindex->ctree);
-        gint row;
-
-        while (node && !gtk_ctree_is_viewable(bindex->ctree, node)) {
-            node = GTK_CTREE_ROW(node)->parent;
-            gtk_ctree_expand(bindex->ctree, node);
-            balsa_index_set_style(bindex, node);
-        }
-        /* now that the row we want is viewable, we can look up its
-         * number */
-        row = gtk_clist_find_row_from_data(clist, tmp);
-        balsa_index_select_row(bindex, row);
-    }
+    GtkTreeView *tree_view = GTK_TREE_VIEW(index);
+    GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+    GtkTreePath *path;
+
+    path = gtk_tree_model_get_path(model, iter);
+    bndx_expand_to_path(tree_view, path);
+    bndx_select_path(index, path);
+    gtk_tree_path_free(path);
 }
 
-/* balsa_index_find_node:
+/* bndx_find_iter:
  * common search code--look for next or previous, with or without flag
  */
-static GtkCTreeNode *
-balsa_index_find_node(BalsaIndex * bindex, gboolean previous,
-                      LibBalsaMessageFlag flag, gint op, GSList* conditions)
+static gboolean
+bndx_find_iter(BalsaIndex * index, GtkTreeIter * iter, gboolean previous,
+               LibBalsaMessageFlag flag, gint op, GSList * conditions)
 {
-    GtkCTreeNode *node;
-    struct BalsaIndexScanInfo *bi;
-    
-    g_return_val_if_fail(bindex != NULL, NULL);
+    GtkTreeView *tree_view = GTK_TREE_VIEW(index);
+    GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+    struct BndxScanInfo bi;
+
+    g_return_val_if_fail(index != NULL, FALSE);
 
     printf("Balsa idnex find node\n");
-    bi = g_new0(struct BalsaIndexScanInfo, 1);
-    bi->node =
-        GTK_CLIST(bindex->ctree)->selection
-        ? g_list_last(GTK_CLIST(bindex->ctree)->selection)->data : NULL;
-    bi->flag = flag;
-    if(conditions) {
-        bi->matching = 
-            libbalsa_mailbox_get_matching(bindex->mailbox_node->mailbox, 
-                                          op, conditions);
-    }
-    gtk_ctree_pre_recursive(bindex->ctree, NULL, (GtkCTreeFunc)
-                            balsa_index_scan_node, bi);
-    node = previous ? bi->previous : bi->next;
-    if (node == NULL && flag != 0)
+    bi.tree_view = tree_view;
+    bi.message = index->current_message;
+    bi.flag = flag;
+    bi.prev_valid = bi.next_valid = bi.first_valid = bi.last_valid = FALSE;
+    bi.matching =
+        conditions ? libbalsa_mailbox_get_matching(index->mailbox_node->
+                                                   mailbox, op,
+                                                   conditions) : NULL;
+    gtk_tree_model_foreach(model, bndx_find_iter_func, &bi);
+    if (bi.matching)
+        g_hash_table_destroy(bi.matching);
+
+    if (previous && bi.prev_valid)
+        *iter = bi.previous;
+    else if (bi.next_valid)
+        *iter = bi.next;
+    else if (flag != 0 && bi.first_valid)
         /* if looking for new or flagged messages, fall back to first
          * matching */
-        node = bi->first;
-    g_free(bi);
-    if(bi->matching) g_hash_table_destroy(bi->matching);
-    return node;
+        *iter = bi.first;
+    else
+        return FALSE;
+
+    return TRUE;
 }
 
 void
-balsa_index_select_next(BalsaIndex * bindex)
+balsa_index_select_next(BalsaIndex * index)
 {
-    balsa_index_select_node(bindex, 
-			    balsa_index_find_node(bindex, FALSE, 0, 
-                                                  FILTER_NOOP, NULL));
+    GtkTreeIter iter;
+
+    if (bndx_find_iter(index, &iter, FALSE, 0,
+                       FILTER_NOOP, NULL))
+        bndx_select_iter(index, &iter);
 }
 
 void
-balsa_index_select_previous(BalsaIndex * bindex)
+balsa_index_select_previous(BalsaIndex * index)
 {
-    balsa_index_select_node(bindex,
-			    balsa_index_find_node(bindex, TRUE, 0,
-						  FILTER_NOOP, NULL));
+    GtkTreeIter iter;
+
+    if (bndx_find_iter(index, &iter, TRUE, 0,
+                       FILTER_NOOP, NULL))
+        bndx_select_iter(index, &iter);
 }
 
 void
-balsa_index_select_next_unread(BalsaIndex * bindex)
+balsa_index_select_next_unread(BalsaIndex * index)
 {
-    balsa_index_select_node(bindex,
-			    balsa_index_find_node(bindex, FALSE, 
-                                                  LIBBALSA_MESSAGE_FLAG_NEW,
-						  FILTER_NOOP, NULL));
+    GtkTreeIter iter;
+
+    if (bndx_find_iter(index, &iter, FALSE,
+                       LIBBALSA_MESSAGE_FLAG_NEW,
+                       FILTER_NOOP, NULL))
+        bndx_select_iter(index, &iter);
 }
 
 void
-balsa_index_select_next_flagged(BalsaIndex * bindex)
+balsa_index_select_next_flagged(BalsaIndex * index)
 {
-    balsa_index_select_node(bindex,
-			    balsa_index_find_node(bindex, FALSE, 
-                                                  LIBBALSA_MESSAGE_FLAG_FLAGGED,
-						  FILTER_NOOP, NULL));
+    GtkTreeIter iter;
+
+    if (bndx_find_iter(index, &iter, FALSE,
+                       LIBBALSA_MESSAGE_FLAG_FLAGGED,
+                       FILTER_NOOP, NULL))
+        bndx_select_iter(index, &iter);
 }
 
 void
-balsa_index_find(BalsaIndex * bindex,gint op,GSList* conditions,
+balsa_index_find(BalsaIndex * index, gint op, GSList * conditions,
                  gboolean previous)
 {
-    balsa_index_select_node(bindex,
-                            balsa_index_find_node(bindex, previous, 0, op,
-                                                  conditions));
+    GtkTreeIter iter;
+
+    if (bndx_find_iter(index, &iter, previous, 0,
+                       op, conditions))
+        bndx_select_iter(index, &iter);
 }
 
-/* balsa_index_scan_selection:
- * callback for pre-recursive search for next message after moving one
- * or more message out of the mailbox
- * after search:
- * - b->next is next unselected message after first selected message,
- *     which may be currently non-viewable
- * - b->first is first unselected viewable message
- * - b->last is last unselected viewable message
- * any or all may be NULL--we'll use them in the order next, first, last
+/* bndx_select_next_threaded:
+ * Finds and selects a message after moving one or more message out of
+ * the index. The selected message is the first unselected message after
+ * the first selected message, which may be currently non-viewable, or
+ * if there isn't one, the last unselected message before the selected
+ * message(s).
  */
+struct BndxThreaded {
+    GtkTreeSelection *selection;
+    gboolean next_valid;
+    gboolean prev_valid;
+    GtkTreeIter iter;
+};
+
 static void
-balsa_index_scan_selection(GtkCTree * ctree, GtkCTreeNode * node,
-                           struct BalsaIndexScanInfo *b)
+bndx_select_next_threaded_func(GtkTreeModel * model, GtkTreePath * path,
+                               GtkTreeIter * iter, gpointer data)
 {
-    GList *list;
-    LibBalsaMessage *message;
+    struct BndxThreaded *bt = data;
+    GtkTreeIter tmp_iter;
+    GtkTreePath *tmp_path;
 
-    for (list = b->selection; list; list = g_list_next(list)) {
-        if (list->data == node) {
-            if (b->previous == NULL) {
-                /* this is the first time we found a selected node */
-                b->previous = b->last;
-                /* clear any `next' node we found before */
-                b->next = NULL;
-            }
-            b->selection = g_list_remove_link(b->selection, list);
-            g_list_free_1(list);
-            return;
-        }
-    }
+    if (bt->next_valid)
+        return;
 
-    /* this node isn't selected */
-    message = LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data(ctree, node));
-    /* skip any DELETED message, as it may really be deleted before we
-     * get a chance to show it */
-    if (message->flags & LIBBALSA_MESSAGE_FLAG_DELETED)
+    tmp_iter = *iter;
+    if (gtk_tree_model_iter_next(model, &tmp_iter)
+        && !gtk_tree_selection_iter_is_selected(bt->selection,
+                                                &tmp_iter)) {
+        bt->next_valid = TRUE;
+        bt->iter = tmp_iter;
         return;
+    }
 
-    if (b->next == NULL)
-        /* save it whether or not it's viewable */
-        b->next = node;
+    if (bt->prev_valid)
+        return;
 
-    if (gtk_ctree_is_viewable(ctree, node))
-        b->last = node;
+    tmp_path = gtk_tree_path_copy(path);
+    if ((gtk_tree_path_prev(tmp_path) || gtk_tree_path_up(tmp_path))
+        && gtk_tree_path_get_depth(tmp_path) > 0
+        && gtk_tree_model_get_iter(model, &tmp_iter, tmp_path)
+        && !gtk_tree_selection_iter_is_selected(bt->selection,
+                                                &tmp_iter)) {
+        bt->prev_valid = TRUE;
+        bt->iter = tmp_iter;
+    }
+    gtk_tree_path_free(tmp_path);
 }
 
-/* balsa_index_select_next_threaded:
- * finds and selects a message after moving one or more message out of
- * the index
- */
 static void
-balsa_index_select_next_threaded(BalsaIndex * bindex)
-{
-    GtkCTreeNode *node;
-    GtkCList *clist;
-    struct BalsaIndexScanInfo *bi;
-    
-    g_return_if_fail(bindex != NULL);
-    
-    clist = GTK_CLIST(bindex->ctree);
-    bi = g_new0(struct BalsaIndexScanInfo, 1);
-
-    bi->selection = g_list_copy(clist->selection);
-    gtk_ctree_pre_recursive(bindex->ctree, NULL, (GtkCTreeFunc)
-                            balsa_index_scan_selection, bi);
-
-    node = bi->next;
-    if (node == NULL)
-        node = bi->first;
-    if (node == NULL)
-        node = bi->last;
-    g_free(bi);
-    if (node)
-        balsa_index_select_node(bindex, node);
+bndx_select_next_threaded(BalsaIndex * index)
+{
+    struct BndxThreaded bt;
+
+    bt.selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(index));
+    bt.next_valid = bt.prev_valid = FALSE;
+    gtk_tree_selection_selected_foreach(bt.selection,
+                                        bndx_select_next_threaded_func,
+                                        &bt);
+    if (bt.next_valid || bt.prev_valid)
+        bndx_select_iter(index, &bt.iter);
     else
         /* we're emptying the index, so we must set up the idle handler
          * appropriately */
-        balsa_index_idle_add(bindex, NULL);
+        balsa_index_idle_add(index, NULL);
 }
 
 /* balsa_index_redraw_current redraws currently selected message,
@@ -1141,363 +1212,340 @@
    FIXME: find a simpler way to do it.
 */
 void
-balsa_index_redraw_current(BalsaIndex * bindex)
+balsa_index_redraw_current(BalsaIndex * index)
 {
-    GtkCList *clist;
-    gint h = 0;
-
-    g_return_if_fail(bindex != NULL);
-
-    clist = GTK_CLIST(bindex->ctree);
-
-    if (!clist->selection)
-	return;
+    GtkTreeSelection *selection =
+        gtk_tree_view_get_selection(GTK_TREE_VIEW(index));
+    GtkTreeIter iter;
 
-    h = gtk_clist_find_row_from_data(clist,
-				     LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data(bindex->ctree, g_list_first(clist->selection)->data)));
-    gtk_clist_select_row(clist, h, -1);
+    if (bndx_find_message(index, NULL, &iter, index->current_message)) {
+        gtk_tree_selection_unselect_iter(selection, &iter);
+        gtk_tree_selection_select_iter(selection, &iter);
+    }
 }
 
 static void
-balsa_index_update_flag(BalsaIndex * bindex, LibBalsaMessage * message)
+balsa_index_update_flag(BalsaIndex * index, LibBalsaMessage * message)
 {
-    GtkCTreeNode* node;
-    g_return_if_fail(bindex != NULL);
+    GtkTreeIter iter;
+
+    g_return_if_fail(index != NULL);
     g_return_if_fail(message != NULL);
 
-    if( (node=gtk_ctree_find_by_row_data(GTK_CTREE(bindex->ctree), 
-					 NULL, message)) ) {
-	balsa_index_set_col_images(bindex, node, message);
-    }
+    if (bndx_find_message(index, NULL, &iter, message))
+	bndx_set_col_images(index, &iter, message);
 }
 
 static void
-balsa_index_set_col_images(BalsaIndex * bindex, GtkCTreeNode *node,
-			   LibBalsaMessage * message)
+bndx_set_col_images(BalsaIndex * index, GtkTreeIter * iter,
+		    LibBalsaMessage * message)
 {
+    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(index));
+    GdkPixbuf *status_pixbuf = NULL;
+    GdkPixbuf *attach_pixbuf = NULL;
     guint tmp;
-    GtkCTree* ctree;
     /* only ony status icon is shown; they are ordered from most important. */
     const static struct {
         int mask;
-        BalsaIconName icon_name;
+        const gchar *icon_name;
     } flags[] = {
-        { LIBBALSA_MESSAGE_FLAG_DELETED, BALSA_ICON_MBOX_TRASH   },
-        { LIBBALSA_MESSAGE_FLAG_FLAGGED, BALSA_ICON_INFO_FLAGGED },
-        { LIBBALSA_MESSAGE_FLAG_REPLIED, BALSA_ICON_INFO_REPLIED },
-        { LIBBALSA_MESSAGE_FLAG_NEW,     BALSA_ICON_INFO_NEW } };
-
-    ctree = bindex->ctree;
+        { LIBBALSA_MESSAGE_FLAG_DELETED, BALSA_PIXMAP_TRASH   },
+        { LIBBALSA_MESSAGE_FLAG_FLAGGED, BALSA_PIXMAP_INFO_FLAGGED },
+        { LIBBALSA_MESSAGE_FLAG_REPLIED, BALSA_PIXMAP_INFO_REPLIED },
+        { LIBBALSA_MESSAGE_FLAG_NEW,     BALSA_PIXMAP_INFO_NEW } };
 
     for(tmp=0; tmp<ELEMENTS(flags) && !(message->flags & flags[tmp].mask);
         tmp++);
-    if(tmp<ELEMENTS(flags))
-	gtk_ctree_node_set_pixmap(ctree, node, 1,
-				  balsa_icon_get_pixmap(flags[tmp].icon_name),
-				  balsa_icon_get_bitmap(flags[tmp].icon_name));
-    else
-        gtk_ctree_node_set_text(ctree, node, 1, NULL);
+
+    if (tmp < ELEMENTS(flags))
+        status_pixbuf =
+            gtk_widget_render_icon(GTK_WIDGET(balsa_app.main_window),
+                                   flags[tmp].icon_name,
+                                   GTK_ICON_SIZE_MENU, NULL);
     /* Alternatively, we could show an READ icon:
      * gtk_ctree_node_set_pixmap(ctree, node, 1,
-     * balsa_icon_get_pixmap(BALSA_ICON_INFO_READ),
-     * balsa_icon_get_bitmap(BALSA_ICON_INFO_READ)); 
+     * balsa_icon_get_pixmap(BALSA_PIXMAP_INFO_READ),
+     * balsa_icon_get_bitmap(BALSA_PIXMAP_INFO_READ)); 
      */
 
-    if (libbalsa_message_has_attachment(message)) {
-	gtk_ctree_node_set_pixmap(ctree, node, 2,
-				  balsa_icon_get_pixmap(BALSA_ICON_INFO_ATTACHMENT),
-				  balsa_icon_get_bitmap(BALSA_ICON_INFO_ATTACHMENT));
-    }
+    if (libbalsa_message_has_attachment(message))
+        attach_pixbuf =
+            gtk_widget_render_icon(GTK_WIDGET(balsa_app.main_window),
+                                   BALSA_PIXMAP_INFO_ATTACHMENT,
+                                   GTK_ICON_SIZE_MENU, NULL);
+
+    gtk_tree_store_set(GTK_TREE_STORE(model), iter,
+                       BNDX_STATUS_COLUMN, status_pixbuf,
+                       BNDX_ATTACH_COLUMN, attach_pixbuf,
+                       -1);
 }
 
 static gboolean
-thread_has_unread(GtkCTree *ctree, GtkCTreeNode *node)
+thread_has_unread(GtkTreeView * tree_view, GtkTreePath * path)
 {
-    GtkCTreeNode *child;
+    GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+    GtkTreePath *child_path;
+    GtkTreeIter iter;
+    gboolean ret_val = FALSE;
 
-    for(child=GTK_CTREE_ROW(node)->children; child; 
-	child=GTK_CTREE_ROW(child)->sibling) {
-	LibBalsaMessage *message=
-	    LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data(ctree, child));
-
-	if((message && message->flags & LIBBALSA_MESSAGE_FLAG_NEW) ||
-	   thread_has_unread(ctree, child)) 
-	    return TRUE;
+    child_path = gtk_tree_path_copy(path);
+    gtk_tree_path_down(child_path);
+
+    while (gtk_tree_model_get_iter(model, &iter, child_path)) {
+        LibBalsaMessage *message;
+
+        gtk_tree_model_get(model, &iter, BNDX_MESSAGE_COLUMN, &message, -1);
+
+        if ((message && message->flags & LIBBALSA_MESSAGE_FLAG_NEW) ||
+            thread_has_unread(tree_view, child_path)) {
+            ret_val = TRUE;
+            break;
+        }
+
+        gtk_tree_path_next(child_path);
     }
-    return FALSE;
-} 
 
+    gtk_tree_path_free(child_path);
+    return ret_val;
+}
 
-static void
-balsa_index_set_style(BalsaIndex * bindex, GtkCTreeNode *node)
+
+static gboolean
+bndx_set_style(BalsaIndex * index, GtkTreePath * path)
 {
-    GtkCTree *ctree;
-    /* GtkStyle *style; FIXME */
-    
-    ctree = bindex->ctree;
+    GtkTreeView *tree_view = GTK_TREE_VIEW(index);
+    GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+    GtkTreeStore *store = GTK_TREE_STORE(model);
+    GtkTreeIter iter;
 
     /* FIXME: Improve style handling;
               - Consider storing styles locally, with or config setting
-	        separate from the "mailbox" one.
-	      - Find better way of obtaining default style. Note that ctree
-	        style can't be use as it isn't initialised yet the first time
-		we call this. */
+	        separate from the "mailbox" one.  */
     
-#if 0 /* FIXME */
-    if(!GTK_CTREE_ROW(node)->expanded && thread_has_unread(ctree, node)) {
-	style = balsa_app.mblist->unread_mailbox_style;
+    if (!gtk_tree_model_get_iter(model, &iter, path))
+        return FALSE;
+
+    if (!gtk_tree_view_row_expanded(tree_view, path)
+        && thread_has_unread(tree_view, path)) {
+        gtk_tree_store_set(store, &iter,
+                           BNDX_COLOR_COLUMN, &balsa_app.mblist_unread_color,
+                           BNDX_WEIGHT_COLUMN, PANGO_WEIGHT_BOLD,
+                           -1);
     } else
-	style = gtk_widget_get_style(GTK_WIDGET(balsa_app.mblist));
+        gtk_tree_store_set(store, &iter,
+                           BNDX_COLOR_COLUMN, NULL,
+                           BNDX_WEIGHT_COLUMN, PANGO_WEIGHT_NORMAL,
+                           -1);
+
+    return TRUE;
+}
+
+static gboolean
+bndx_set_style_recursive(BalsaIndex * index, GtkTreePath * path)
+{
+    GtkTreePath *child_path;
+
+    if (gtk_tree_path_get_depth(path) > 0 && !bndx_set_style(index, path))
+        return FALSE;
 
-    gtk_ctree_node_set_row_style(ctree, node, style);
-#endif
+    child_path = gtk_tree_path_copy(path);
+    gtk_tree_path_down(child_path);
 
+    while (bndx_set_style_recursive(index, child_path))
+        gtk_tree_path_next(child_path);
+
+    gtk_tree_path_free(child_path);
+    return TRUE;
 }
 
+
 static void
-balsa_index_set_style_recursive(BalsaIndex * bindex, GtkCTreeNode *node)
+bndx_set_parent_style(BalsaIndex * index, GtkTreePath * path)
 {
-    GtkCTreeNode *child;
+    GtkTreePath *parent_path;
 
-    balsa_index_set_style(bindex, node);
+    parent_path = gtk_tree_path_copy(path);
 
-    for(child=GTK_CTREE_ROW(node)->children; child; 
-	child=GTK_CTREE_ROW(child)->sibling) {
-	balsa_index_set_style_recursive(bindex, child);
-    }
+    while (gtk_tree_path_up(parent_path)
+           && gtk_tree_path_get_depth(parent_path) > 0)
+	bndx_set_style(index, parent_path);
+
+    gtk_tree_path_free(parent_path);
 }
 
+/* GtkTree* callbacks */
 
+/*
+ * bndx_selection_changed
+ *
+ * Callback for the selection "changed" signal.
+ *
+ * Display the last (in tree order) selected message.
+ */
+
 static void
-balsa_index_set_parent_style(BalsaIndex * bindex, GtkCTreeNode *node)
+bndx_selection_changed_func(GtkTreeModel * model, GtkTreePath * path,
+                            GtkTreeIter * iter, gpointer data)
 {
-    GtkCTreeNode *parent;
+    LibBalsaMessage **message = data;
 
-    for(parent=GTK_CTREE_ROW(node)->parent; parent; 
-	parent=GTK_CTREE_ROW(parent)->parent) {
-	balsa_index_set_style(bindex, parent);
-    }
+    gtk_tree_model_get(model, iter, BNDX_MESSAGE_COLUMN, message, -1);
 }
 
-/* CLIST callbacks */
+static void
+bndx_selection_changed(GtkTreeSelection * selection, gpointer data)
+{
+    BalsaIndex *index = BALSA_INDEX(data);
+    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(index));
+    GtkTreeIter iter;
+    LibBalsaMessage *message = NULL;
 
+    gtk_tree_selection_selected_foreach(selection,
+                                        bndx_selection_changed_func,
+                                        &message);
+
+    /* in case a message was unselected: */
+    gtk_signal_emit(GTK_OBJECT(index),
+                    balsa_index_signals[UNSELECT_MESSAGE], NULL);
+    if (message)
+        gtk_signal_emit(GTK_OBJECT(index),
+                        balsa_index_signals[SELECT_MESSAGE], message);
+    else if (gtk_tree_model_get_iter_first(model, &iter))
+        gtk_signal_emit(GTK_OBJECT(index),
+                        balsa_index_signals[UNSELECT_ALL_MESSAGES], NULL);
+
+    index->current_message = message;
+    balsa_index_idle_add(index, message);
+}
+
 static gboolean
-button_event_press_cb(GtkWidget * ctree, GdkEventButton * event,
-                      gpointer data)
+bndx_button_event_press_cb(GtkWidget * widget, GdkEventButton * event,
+                           gpointer data)
 {
-    gint row, column;
-    LibBalsaMessage *message = NULL;
-    BalsaIndex *bindex;
-    GtkCList *clist = GTK_CLIST(ctree);
+    GtkTreeView *tree_view = GTK_TREE_VIEW(widget);
+    GtkTreePath *path;
+    GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view);
+    BalsaIndex *index = BALSA_INDEX(widget);
 
     g_return_val_if_fail(event, FALSE);
-    if (clist->rows <= 0)
+    if (event->button != 3)
         return FALSE;
 
-    bindex = BALSA_INDEX(data);
-    if (gtk_clist_get_selection_info(clist, event->x, event->y,
-                                     &row, &column))
-        message = gtk_clist_get_row_data(clist, row);
-
-    if (event->button == 1 && event->type == GDK_2BUTTON_PRESS && message) {
-        /* double click on a message means open a message window,
-         * unless we're in the draftbox, in which case it means open
-         * a sendmsg window */
-        if (bindex->mailbox_node->mailbox == balsa_app.draftbox) {
-            /* the simplest way to get a sendmsg window would be:
-             * balsa_message_continue(widget, (gpointer) bindex);
-             * but it doesn't work--the selection info seems to
-             * become invisible
-             *
-             * instead we'll just use the guts of
-             * balsa_message_continue: */
-            BalsaSendmsg *sm =
-                sendmsg_window_new(GTK_WIDGET(balsa_app.main_window),
-                                   message, SEND_CONTINUE);
-            gtk_signal_connect(GTK_OBJECT(sm->window), "destroy",
-                               GTK_SIGNAL_FUNC
-                               (sendmsg_window_destroy_cb), NULL);
-        } else
-            message_window_new(message);
-        return TRUE;
-    } else if (event->button == 3) {
-        /* pop up the context menu:
-         * - if the clicked-on message is already selected, don't change
-         *   the selection;
-         * - if it isn't, select it (cancelling any previous selection)
-         * - create and show the menu only if some message is selected,
-         *   at the end of all this */
-        if (message) {
-            /* select this message, if it's not already selected */
-            GtkCTreeNode *node =
-                gtk_ctree_find_by_row_data(GTK_CTREE(ctree), NULL,
-                                           message);
-            if (!g_list_find(clist->selection, node))
-                balsa_index_select_row(bindex, row);
-        }
-
-        if (clist->selection) {
-            balsa_index_idle_remove(bindex);
-            gtk_menu_popup(GTK_MENU(create_menu(bindex)),
-                           NULL, NULL, NULL, NULL,
-                           event->button, event->time);
-            return TRUE;
-        }
+    /* pop up the context menu:
+     * - if the clicked-on message is already selected, don't change
+     *   the selection;
+     * - if it isn't, select it (cancelling any previous selection)
+     * - then create and show the menu */
+    if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tree_view),
+                                      event->x, event->y, &path,
+                                      NULL, NULL, NULL)) {
+        if (!gtk_tree_selection_path_is_selected(selection, path))
+            bndx_select_path(index, path);
+        gtk_tree_path_free(path);
     }
-    return FALSE;
-}
 
-/* tree_expand_cb:
- * callback on expand events
- * set/reset unread style, as appropriate
- * if current message has become viewable, check its visibility,
- * scrolling only until it is at foot of window;
- * otherwise find last viewable message in thread and check its
- * visibility, scrolling only until node is at foot of window, but not
- * so far that the clicked-on message scrolls off the top */
-static void
-tree_expand_cb(GtkCTree * ctree, GList * node, gpointer user_data)
-{
-    GtkCTreeNode *child = NULL;
-    GtkCTreeNode *parent = NULL;
-    if (GTK_CLIST(ctree)->selection) {
-        /* current message... */
-        GtkCTreeNode *current =
-            g_list_last(GTK_CLIST(ctree)->selection)->data;
-        if (gtk_ctree_is_ancestor(ctree, GTK_CTREE_NODE(node), current)
-            /* ...is in thread... */
-            && gtk_ctree_is_viewable(ctree, current))
-            /* ...and viewable:
-             * check visibility of current only */
-            child = current;
-    }
-    if (child == NULL) {
-        /* get last child... */
-        child = gtk_ctree_last(ctree, GTK_CTREE_ROW(node)->children);
-        while (child && !gtk_ctree_is_viewable(ctree, child))
-            /* ...that is viewable */
-            child = GTK_CTREE_ROW(child)->parent;
-        /* check visibility of parent, too */
-        parent = GTK_CTREE_NODE(node);
-    }
-    if (child)
-        balsa_index_check_visibility(GTK_CLIST(ctree), child, 1.0);
-    if (parent)
-        balsa_index_check_visibility(GTK_CLIST(ctree), parent, 0.0);
-    balsa_index_set_style(BALSA_INDEX(user_data), GTK_CTREE_NODE(node));
-}
+    gtk_menu_popup(GTK_MENU(bndx_popup_menu_prepare(index)),
+                   NULL, NULL, NULL, NULL,
+                   event->button, event->time);
 
-/* tree_collapse_cb:
- * callback on collapse events
- * set/reset unread style, as appropriate */
-static void
-tree_collapse_cb(GtkCTree * ctree, GList * node, gpointer user_data)
-{
-    balsa_index_set_style(BALSA_INDEX(user_data), GTK_CTREE_NODE(node));
+    return TRUE;
 }
 
 static void
-select_message(GtkWidget * widget, GtkCTreeNode *row, gint column,
-	       gpointer data)
+bndx_row_activated(GtkTreeView * tree_view, GtkTreePath * path,
+                   GtkTreeViewColumn * column, gpointer user_data)
 {
-    BalsaIndex *bindex;
-    LibBalsaMessage *message;
+    GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
+    GtkTreeIter iter;
+    LibBalsaMessage *message = NULL;
 
-    bindex = BALSA_INDEX(data);
-    message = 
-	LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data (GTK_CTREE(widget), row));
-    if (message) {
-	gtk_signal_emit(GTK_OBJECT(bindex),
-			balsa_index_signals[SELECT_MESSAGE],
-			message);
-    }
+    gtk_tree_model_get_iter(model, &iter, path);
+    gtk_tree_model_get(model, &iter, BNDX_MESSAGE_COLUMN, &message, -1);
 
-    balsa_index_idle_add(bindex, message);
+    /* activate a message means open a message window,
+     * unless we're in the draftbox, in which case it means open
+     * a sendmsg window */
+    if (message->mailbox == balsa_app.draftbox) {
+        /* the simplest way to get a sendmsg window would be:
+         * balsa_message_continue(widget, (gpointer) index);
+         *
+         * instead we'll just use the guts of
+         * balsa_message_continue: */
+        BalsaSendmsg *sm =
+            sendmsg_window_new(GTK_WIDGET(balsa_app.main_window),
+                               message, SEND_CONTINUE);
+        gtk_signal_connect(GTK_OBJECT(sm->window), "destroy",
+                           GTK_SIGNAL_FUNC
+                           (sendmsg_window_destroy_cb), NULL);
+    } else
+        message_window_new(message);
 }
 
-
+/* bndx_tree_expand_cb:
+ * callback on expand events
+ * set/reset unread style, as appropriate
+ */
 static void
-unselect_message(GtkWidget * widget, GtkCTreeNode *row, gint column,
-		 gpointer data)
+bndx_tree_expand_cb(GtkTreeView * tree_view, GtkTreeIter * iter,
+                    GtkTreePath * path, gpointer user_data)
 {
-    BalsaIndex *bindex;
-    LibBalsaMessage *message;
-    GList *sel;
-
-    bindex = BALSA_INDEX (data);
-    message =
-	LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data (GTK_CTREE(widget), row));
-
-    if (message)
-	gtk_signal_emit(GTK_OBJECT(bindex),
-			balsa_index_signals[UNSELECT_MESSAGE],
-			message);
-
-    if ((sel = GTK_CLIST(widget)->selection) && !g_list_next(sel)) {
-        message =
-            LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data
-                             (GTK_CTREE(widget),
-                              GTK_CTREE_NODE(sel->data)));
-        balsa_index_idle_add(bindex, message);
-    }
+    bndx_set_style(BALSA_INDEX(tree_view), path);
 }
 
-
+/* bndx_tree_collapse_cb:
+ * callback on collapse events
+ * set/reset unread style, as appropriate */
 static void
-unselect_all_messages(GtkCList* clist, gpointer user_data)
+bndx_tree_collapse_cb(GtkTreeView * tree_view, GtkTreeIter * iter,
+                      GtkTreePath * path, gpointer user_data)
 {
-    BalsaIndex *bindex;
-    LibBalsaMessage *message;
-
-    bindex = BALSA_INDEX (user_data);
-    message =
-	LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data (GTK_CTREE(clist), 0));
-
-    if (message)
-	gtk_signal_emit(GTK_OBJECT(bindex),
-			balsa_index_signals[UNSELECT_ALL_MESSAGES], 
-                        NULL);
+    bndx_set_style(BALSA_INDEX(tree_view), path);
 }
 
-
 /* When a column is resized, store the new size for later use */
 static void
-resize_column_event_cb(GtkCList * clist, gint column, gint width,
-		       gpointer data)
+bndx_column_resize(GtkWidget * widget, GtkAllocation * allocation,
+                   gpointer data)
 {
-    switch (column) {
-    case 0:
-	balsa_app.index_num_width = width;
-	break;
-
-    case 1:
-	balsa_app.index_status_width = width;
-	break;
-
-    case 2:
-	balsa_app.index_attachment_width = width;
-	break;
-
-    case 3:
-	balsa_app.index_from_width = width;
-	break;
-
-    case 4:
-	balsa_app.index_subject_width = width;
-	break;
-
-    case 5:
-	balsa_app.index_date_width = width;
-	break;
-
-    case 6:
-	balsa_app.index_size_width = width;
-	break;
-
-    default:
-	if (balsa_app.debug)
-	    fprintf(stderr, "** Error: Unknown column resize\n");
-    }
+    GtkTreeView *tree_view = GTK_TREE_VIEW(widget);
+
+    balsa_app.index_num_width =
+        gtk_tree_view_column_get_width(gtk_tree_view_get_column
+                                       (tree_view, 0));
+    balsa_app.index_status_width =
+        gtk_tree_view_column_get_width(gtk_tree_view_get_column
+                                       (tree_view, 1));
+    balsa_app.index_attachment_width =
+        gtk_tree_view_column_get_width(gtk_tree_view_get_column
+                                       (tree_view, 2));
+    balsa_app.index_from_width =
+        gtk_tree_view_column_get_width(gtk_tree_view_get_column
+                                       (tree_view, 3));
+    balsa_app.index_subject_width =
+        gtk_tree_view_column_get_width(gtk_tree_view_get_column
+                                       (tree_view, 4));
+    balsa_app.index_date_width =
+        gtk_tree_view_column_get_width(gtk_tree_view_get_column
+                                       (tree_view, 5));
+    balsa_app.index_size_width =
+        gtk_tree_view_column_get_width(gtk_tree_view_get_column
+                                       (tree_view, 6));
+}
+
+void
+balsa_index_set_column_widths(BalsaIndex * index)
+{
+    GtkTreeView *tree_view = GTK_TREE_VIEW(index);
+
+    gtk_tree_view_column_set_fixed_width(gtk_tree_view_get_column
+                                         (tree_view, 3),
+                                         balsa_app.index_from_width);
+    gtk_tree_view_column_set_fixed_width(gtk_tree_view_get_column
+                                         (tree_view, 4),
+                                         balsa_app.index_subject_width);
+    gtk_tree_view_column_set_fixed_width(gtk_tree_view_get_column
+                                         (tree_view, 5),
+                                         balsa_app.index_date_width);
 }
 
 /* Mailbox Callbacks... */
@@ -1510,70 +1558,60 @@
 static void
 mailbox_message_changed_status_cb(LibBalsaMailbox * mb,
 				  LibBalsaMessage * message,
-				  BalsaIndex * bindex)
+				  BalsaIndex * index)
 {
     if(libbalsa_mailbox_is_valid(mb))
-        balsa_index_update_flag(bindex, message);
+        balsa_index_update_flag(index, message);
 }
 
 static void
-mailbox_message_new_cb(BalsaIndex * bindex, LibBalsaMessage * message)
+mailbox_message_new_cb(BalsaIndex * index, LibBalsaMessage * message)
 {
-    gtk_clist_freeze(GTK_CLIST (bindex->ctree));
-    balsa_index_add(bindex, message);
-    if(bindex->mailbox_node->mailbox->new_messages==0){
-      balsa_index_threading(bindex);
-      gtk_clist_sort (GTK_CLIST (bindex->ctree));
-      DO_CLIST_WORKAROUND(GTK_CLIST (bindex->ctree));
-    }
-    gtk_clist_thaw (GTK_CLIST (bindex->ctree));
-    balsa_mblist_update_mailbox(balsa_app.mblist_tree_store, 
-                                bindex->mailbox_node->mailbox);
+    balsa_index_add(index, message);
+    balsa_index_threading(index);
+    balsa_mblist_update_mailbox(balsa_app.mblist_tree_store,
+                                index->mailbox_node->mailbox);
 }
 
 static void
-mailbox_messages_new_cb(BalsaIndex * bindex, GList *messages)
+mailbox_messages_new_cb(BalsaIndex * index, GList * messages)
 {
-    LibBalsaMessage * message;
+    LibBalsaMessage *message;
 
-    gtk_clist_freeze(GTK_CLIST (bindex->ctree));
-    while(messages){
-	message=(LibBalsaMessage *)(messages->data);
-	balsa_index_add(bindex, message);
-	messages=g_list_next(messages);
+    while (messages) {
+        message = (LibBalsaMessage *) (messages->data);
+        balsa_index_add(index, message);
+        messages = g_list_next(messages);
     }
-    balsa_index_threading(bindex);
-    gtk_clist_sort (GTK_CLIST (bindex->ctree));
-    DO_CLIST_WORKAROUND(GTK_CLIST (bindex->ctree));
-    gtk_clist_thaw (GTK_CLIST (bindex->ctree));
 
-    balsa_mblist_update_mailbox(balsa_app.mblist_tree_store, 
-                                bindex->mailbox_node->mailbox);
+    balsa_index_threading(index);
+    balsa_mblist_update_mailbox(balsa_app.mblist_tree_store,
+                                index->mailbox_node->mailbox);
 }
 
 static void
-mailbox_message_delete_cb(BalsaIndex * bindex, LibBalsaMessage * message)
+mailbox_message_delete_cb(BalsaIndex * index, LibBalsaMessage * message)
 {
-    balsa_index_del(bindex, message);
-    balsa_index_check_visibility(GTK_CLIST(bindex->ctree), NULL, 0.5);
+    GList *messages = g_list_prepend(NULL, message);
+
+    bndx_messages_remove(index, messages);
+    g_list_free_1(messages);
+    bndx_check_visibility(index, NULL);
 }
 
 static void
-mailbox_messages_delete_cb(BalsaIndex * bindex, GList * messages)
+mailbox_messages_delete_cb(BalsaIndex * index, GList * messages)
 {
-    LibBalsaMessage * message;
-    gtk_clist_freeze(GTK_CLIST(bindex->ctree));
-
-    while(messages){
-	message=(LibBalsaMessage *)(messages->data);
-	balsa_index_del(bindex, message);
-	messages=g_list_next(messages);
-    }
-
-    balsa_index_check_visibility(GTK_CLIST(bindex->ctree), NULL, 0.5);
-    gtk_clist_thaw(GTK_CLIST(bindex->ctree));
+    bndx_messages_remove(index, messages);
+    bndx_check_visibility(index, NULL);
 }
 
+static void
+mailbox_messages_delete_all_cb(BalsaIndex * index)
+{
+    gtk_tree_store_clear(GTK_TREE_STORE
+                         (gtk_tree_view_get_model(GTK_TREE_VIEW(index))));
+}
 
 /* balsa_index_close_and_destroy:
  */
@@ -1581,15 +1619,15 @@
 static void
 balsa_index_close_and_destroy(GtkObject * obj)
 {
-    BalsaIndex *bindex;
+    BalsaIndex *index;
     LibBalsaMailbox* mailbox;
     GtkObject* message;
 
     g_return_if_fail(obj != NULL);
-    bindex = BALSA_INDEX(obj);
+    index = BALSA_INDEX(obj);
 
     /* remove idle callbacks and attached data */
-    balsa_index_idle_remove(bindex);
+    balsa_index_idle_remove(index);
     message = gtk_object_get_data(obj, "message");
     if (message != NULL) {
         gtk_object_remove_data (obj, "message");
@@ -1597,127 +1635,172 @@
     }
 
     /*page->window references our owner */
-    if (bindex->mailbox_node && (mailbox = bindex->mailbox_node->mailbox) ) {
-        gtk_signal_disconnect_by_data (GTK_OBJECT (mailbox), bindex);
+    if (index->mailbox_node && (mailbox = index->mailbox_node->mailbox) ) {
+        gtk_signal_disconnect_by_data (GTK_OBJECT (mailbox), index);
 	libbalsa_mailbox_close(mailbox);
-	bindex->mailbox_node = NULL;
+	index->mailbox_node = NULL;
     }
 
+    /* destroy the popup menu */
+    gtk_widget_destroy(index->popup_menu);
+    index->popup_menu = NULL;
+
     if (GTK_OBJECT_CLASS(parent_class)->destroy)
         (*GTK_OBJECT_CLASS(parent_class)->destroy) (obj);
 }
 
 static void
-balsa_message_view_source(GtkWidget * widget, gpointer user_data)
+bndx_view_source_func(GtkTreeModel *model, GtkTreePath *path,
+                      GtkTreeIter *iter, gpointer data)
 {
-    GList *list;
-    BalsaIndex* index;
-    LibBalsaMessage *message;
+    LibBalsaMessage *message = NULL;
+
+    gtk_tree_model_get(model, iter, BNDX_MESSAGE_COLUMN, &message, -1);
+    libbalsa_show_message_source(message);
+}
+
+static void
+bndx_view_source(GtkWidget * widget, gpointer data)
+{
+    GtkTreeSelection *selection =
+        gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
     
-    index = BALSA_INDEX (user_data);
-    list = GTK_CLIST(index->ctree)->selection;
-    while (list) {
-	message = gtk_ctree_node_get_row_data(index->ctree, list->data);
-	list = list->next;
-	libbalsa_show_message_source(message);
-    }	
+    gtk_tree_selection_selected_foreach(selection, bndx_view_source_func,
+                                        NULL);
 }
 
+
 static void
-compose_foreach(GtkWidget* w, BalsaIndex* index, SendType send_type)
+balsa_index_selected_list_func(GtkTreeModel * model, GtkTreePath * path,
+                        GtkTreeIter * iter, gpointer data)
 {
-    GList *list;
-    LibBalsaMessage *message;
-    BalsaSendmsg *sm;
+    GList **list = data;
+    LibBalsaMessage *message = NULL;
 
-    for(list = GTK_CLIST(index->ctree)->selection; list; list = list->next) {
-	message = gtk_ctree_node_get_row_data(index->ctree, list->data);
-	sm = sendmsg_window_new(w, message, send_type);
-	gtk_signal_connect(GTK_OBJECT(sm->window), "destroy",
-			   GTK_SIGNAL_FUNC(sendmsg_window_destroy_cb),
-			   NULL);
+    gtk_tree_model_get(model, iter, BNDX_MESSAGE_COLUMN, &message, -1);
+    *list = g_list_prepend(*list, message);
+}
+
+/*
+ * balsa_index_selected_list: create a GList of selected messages
+ */
+GList *
+balsa_index_selected_list(BalsaIndex * index)
+{
+    GtkTreeSelection *selection =
+        gtk_tree_view_get_selection(GTK_TREE_VIEW(index));
+    GList *list = NULL;
+
+    gtk_tree_selection_selected_foreach(selection,
+                                        balsa_index_selected_list_func,
+                                        &list);
+
+    return list;
+}
+
+/*
+ * bndx_compose_foreach: create a compose window for each selected
+ * message
+ */
+static void
+bndx_compose_foreach(GtkWidget * w, BalsaIndex * index,
+                     SendType send_type)
+{
+    GList *list, *l = balsa_index_selected_list(index);
+
+    for (list = l; list; list = g_list_next(list)) {
+        LibBalsaMessage *message = list->data;
+        BalsaSendmsg *sm = sendmsg_window_new(NULL, message, send_type);
+
+        gtk_signal_connect(GTK_OBJECT(sm->window), "destroy",
+                           GTK_SIGNAL_FUNC(sendmsg_window_destroy_cb),
+                           NULL);
     }
+    g_list_free(l);
 }
 
+/*
+ * Public `reply' methods
+ */
 void
 balsa_message_reply(GtkWidget * widget, gpointer user_data)
 {
-    compose_foreach(widget, BALSA_INDEX (user_data), SEND_REPLY);
+    bndx_compose_foreach(widget, BALSA_INDEX (user_data), SEND_REPLY);
 }
 
 void
 balsa_message_replytoall(GtkWidget * widget, gpointer user_data)
 {
-    compose_foreach(widget, BALSA_INDEX (user_data), SEND_REPLY_ALL);
+    bndx_compose_foreach(widget, BALSA_INDEX (user_data), SEND_REPLY_ALL);
 }
 
 void
 balsa_message_replytogroup(GtkWidget * widget, gpointer user_data)
 {
-    compose_foreach(widget, BALSA_INDEX (user_data), SEND_REPLY_GROUP);
+    bndx_compose_foreach(widget, BALSA_INDEX (user_data), SEND_REPLY_GROUP);
 }
 
+void
+balsa_message_continue(GtkWidget * widget, gpointer user_data)
+{
+    bndx_compose_foreach(widget, BALSA_INDEX (user_data), SEND_CONTINUE);
+}
+
+/*
+ * bndx_compose_from_list: create a single compose window for the
+ * selected messages
+ */
 static void
-compose_from_list(GtkWidget * w, BalsaIndex * index, SendType send_type)
+bndx_compose_from_list(GtkWidget * w, BalsaIndex * index,
+                       SendType send_type)
 {
-    GList *sel = GTK_CLIST(index->ctree)->selection;
-    GList *list = NULL;
     BalsaSendmsg *sm;
+    GList *list = balsa_index_selected_list(index);
 
-    while (sel) {
-        LibBalsaMessage *message =
-            gtk_ctree_node_get_row_data(index->ctree,
-                                        GTK_CTREE_NODE(sel->data));
-        list = g_list_append(list, message);
-        sel = g_list_next(sel);
-    }
-    sm = sendmsg_window_new_from_list(w, list, send_type);
-    gtk_signal_connect(GTK_OBJECT(sm->window), "destroy",
-                       GTK_SIGNAL_FUNC(sendmsg_window_destroy_cb),
-                       NULL);
+    if (list) {
+        sm = sendmsg_window_new_from_list(w, list, send_type);
+        gtk_signal_connect(GTK_OBJECT(sm->window), "destroy",
+                           GTK_SIGNAL_FUNC(sendmsg_window_destroy_cb),
+                           NULL);
 
-    g_list_free(list);
+        g_list_free(list);
+    }
 }
 
+/*
+ * Public forwarding methods
+ */
 void
 balsa_message_forward_attached(GtkWidget * widget, gpointer user_data)
 {
-    compose_from_list(widget, BALSA_INDEX (user_data), SEND_FORWARD_ATTACH);
+    bndx_compose_from_list(widget, BALSA_INDEX(user_data),
+                           SEND_FORWARD_ATTACH);
 }
 
 void
 balsa_message_forward_inline(GtkWidget * widget, gpointer user_data)
 {
-    compose_from_list(widget, BALSA_INDEX (user_data), SEND_FORWARD_INLINE);
+    bndx_compose_from_list(widget, BALSA_INDEX(user_data),
+                           SEND_FORWARD_INLINE);
 }
 
 void
 balsa_message_forward_default(GtkWidget * widget, gpointer user_data)
 {
-    compose_from_list(widget, BALSA_INDEX (user_data), 
-                      balsa_app.forward_attached 
-                      ? SEND_FORWARD_ATTACH : SEND_FORWARD_INLINE);
+    bndx_compose_from_list(widget, BALSA_INDEX(user_data),
+                           balsa_app.forward_attached
+                           ? SEND_FORWARD_ATTACH : SEND_FORWARD_INLINE);
 }
 
-void
-balsa_message_continue(GtkWidget * widget, gpointer user_data)
-{
-    compose_foreach(widget, BALSA_INDEX (user_data), SEND_CONTINUE);
-}
-
-
+/*
+ * bndx_do_delete: helper for message delete methods
+ */
 static void
-do_delete(BalsaIndex* index, gboolean move_to_trash)
+bndx_do_delete(BalsaIndex* index, gboolean move_to_trash)
 {
-    GList *list;
     BalsaIndex *trash = balsa_find_index_by_mailbox(balsa_app.trash);
-    LibBalsaMessage *message;
-    GList *messages = NULL;
+    GList *messages = balsa_index_selected_list(index);
 
-    for(list = GTK_CLIST(index->ctree)->selection; list; list = list->next) {
-	message = gtk_ctree_node_get_row_data(index->ctree, list->data);
-	messages= g_list_append(messages, message);
-    }
     if(messages) {
 	if (move_to_trash && (index != trash)) {
 	    libbalsa_messages_move(messages, balsa_app.trash);
@@ -1731,7 +1814,7 @@
 
         /* select another message depending on where we are in the list
          */
-        balsa_index_select_next_threaded(index);
+        bndx_select_next_threaded(index);
 
         /* sync with backend AFTER adjacent message is selected.
          * Update the style and message counts in the mailbox list */
@@ -1741,57 +1824,58 @@
         /* balsa_index_redraw_current(index); */
     }
 }
-
 
+/*
+ * Public message delete methods
+ */
 void
 balsa_message_move_to_trash(GtkWidget * widget, gpointer user_data)
 {
     g_return_if_fail(user_data != NULL);
-    do_delete(BALSA_INDEX(user_data), TRUE);
+    bndx_do_delete(BALSA_INDEX(user_data), TRUE);
 }
 
 void
 balsa_message_delete(GtkWidget * widget, gpointer user_data)
 {
     g_return_if_fail(user_data != NULL);
-    do_delete(BALSA_INDEX(user_data), FALSE);
+    bndx_do_delete(BALSA_INDEX(user_data), FALSE);
 }
 
 void
 balsa_message_undelete(GtkWidget * widget, gpointer user_data)
 {
-    GList *list;
+    GList *list, *l;
     LibBalsaMessage *message;
     BalsaIndex* index;
 
-
     g_return_if_fail(widget != NULL);
     g_return_if_fail(user_data != NULL);
 
     index = BALSA_INDEX (user_data);
-    list = GTK_CLIST(index->ctree)->selection;
 
-    while (list) {
-	message = gtk_ctree_node_get_row_data(index->ctree, list->data);
+    l = balsa_index_selected_list(index);
+    for (list = l; list; list = g_list_next(list)) {
+	message = list->data;
 	libbalsa_message_delete(message, FALSE);
-	list = list->next;
     }
+    g_list_free(l);
 }
 
 gint
 balsa_find_notebook_page_num(LibBalsaMailbox * mailbox)
 {
-    GtkWidget *index;
+    GtkWidget *page;
     guint i;
 
     for (i = 0;
-	 (index =
-	  gtk_notebook_get_nth_page(GTK_NOTEBOOK(balsa_app.notebook), i));
-	 i++) {
+         (page =
+          gtk_notebook_get_nth_page(GTK_NOTEBOOK(balsa_app.notebook), i));
+         i++) {
+        GtkWidget *index = gtk_bin_get_child(GTK_BIN(page));
 
-	if (BALSA_INDEX(index)->mailbox_node->mailbox == mailbox)
-
-	    return i;
+        if (BALSA_INDEX(index)->mailbox_node->mailbox == mailbox)
+            return i;
     }
 
     /* didn't find a matching mailbox */
@@ -1805,19 +1889,21 @@
 balsa_message_toggle_flag(BalsaIndex* index, LibBalsaMessageFlag flag,
                           void(*cb)(LibBalsaMessage*, gboolean))
 {
-    GList *list;
+    GList *list, *l;
     LibBalsaMessage *message;
     int is_all_flagged = TRUE;
     gboolean new_flag;
 
     /* First see if we should set given flag or unset */
-    for(list=GTK_CLIST(index->ctree)->selection; list; list=list->next) {
-	message = gtk_ctree_node_get_row_data(index->ctree, list->data);
+    l = balsa_index_selected_list(index);
+    for (list = l; list; list = g_list_next(list)) {
+	message = list->data;
 	if (!(message->flags & flag)) {
 	    is_all_flagged = FALSE;
 	    break;
 	}
     }
+    g_list_free(l);
 
     /* If they all have the flag set, then unset them. Otherwise, set
      * them all.
@@ -1829,10 +1915,12 @@
         (flag ==
          LIBBALSA_MESSAGE_FLAG_NEW ? is_all_flagged : !is_all_flagged);
 
-    for (list=GTK_CLIST(index->ctree)->selection; list; list=list->next) {
-	message = gtk_ctree_node_get_row_data(index->ctree, list->data);
+    l = balsa_index_selected_list(index);
+    for (list = l; list; list = g_list_next(list)) {
+	message = list->data;
         (*cb) (message, new_flag);
     }
+    g_list_free(l);
     balsa_index_sync_backend(index->mailbox_node->mailbox);
 }
 
@@ -1868,21 +1956,18 @@
 void
 balsa_index_update_message(BalsaIndex * index)
 {
-    gint row;
     GtkObject *message;
-    GtkCList *list;
-
-    list = GTK_CLIST(index->ctree);
-    row = balsa_index_most_recent_message(list);
+    GList *list;
 
-    message = 
-	(row < 0) ? NULL : GTK_OBJECT(gtk_clist_get_row_data(list, row));
+    list = balsa_index_selected_list(index);
+    message = list ? list->data : NULL;
+    g_list_free(list);
 
     balsa_index_idle_add(index, message);
 }
 
 
-/* balsa_index_drag_cb 
+/* bndx_drag_cb 
  * 
  * This is the drag_data_get callback for the index widgets.  It
  * copies the list of selected messages to a pointer array, then sets
@@ -1890,27 +1975,26 @@
  * application.
  *  */
 static void 
-balsa_index_drag_cb (GtkWidget* widget, GdkDragContext* drag_context, 
+bndx_drag_cb (GtkWidget* widget, GdkDragContext* drag_context, 
                GtkSelectionData* data, guint info, guint time, 
                gpointer user_data)
 { 
     LibBalsaMessage* message;
     GPtrArray* message_array = NULL;
-    GList* list = NULL;
-    GtkCTree* ctree = NULL;
+    GList* list, *l;
+    GtkTreeView *tree_view = NULL;
     
 
     g_return_if_fail (widget != NULL);
-    ctree = GTK_CTREE (widget);
-    list = GTK_CLIST (ctree)->selection;
-    message_array = g_ptr_array_new ();
+    tree_view = GTK_TREE_VIEW(widget);
     
-    while (list) {
-        message = gtk_ctree_node_get_row_data (ctree, 
-                                               list->data);
+    message_array = g_ptr_array_new ();
+    l = balsa_index_selected_list(BALSA_INDEX(widget));
+    for (list = l; list; list = g_list_next(list)) {
+        message = list->data;
         g_ptr_array_add (message_array, message);
-        list = list->next;
     }
+    g_list_free(l);
     
     if (message_array) {
         g_ptr_array_add (message_array, NULL);
@@ -1983,111 +2067,139 @@
     g_return_if_fail(mailbox != NULL);
     balsa_index_transfer_messages(data, mailbox);
 }
-
 
+/*
+ * bndx_popup_menu_create: create the popup menu at init time
+ */
 static GtkWidget *
-create_menu(BalsaIndex * bindex)
+bndx_popup_menu_create(BalsaIndex * index)
 {
-    const static struct {             /* this is a invariable part of */
-        const char* icon, *label;     /* the context message menu.    */
+    const static struct {       /* this is a invariable part of */
+        const char *icon, *label;       /* the context message menu.    */
         GtkSignalFunc func;
     } entries[] = {
-        { GNOME_STOCK_MENU_BOOK_OPEN,    N_("View Source"), 
-          GTK_SIGNAL_FUNC(balsa_message_view_source) },
-        { BALSA_PIXMAP_MENU_REPLY,       N_("Reply..."), 
-          GTK_SIGNAL_FUNC(balsa_message_reply) },
-        { BALSA_PIXMAP_MENU_REPLY_ALL,   N_("Reply To All..."), 
-          GTK_SIGNAL_FUNC(balsa_message_replytoall) },
-        { BALSA_PIXMAP_MENU_REPLY_GROUP, N_("Reply To Group..."), 
-          GTK_SIGNAL_FUNC(balsa_message_replytogroup) },
-        { BALSA_PIXMAP_MENU_FORWARD,     N_("Forward Attached..."), 
-          GTK_SIGNAL_FUNC(balsa_message_forward_attached) },
-        { BALSA_PIXMAP_MENU_FORWARD,     N_("Forward Inline..."), 
-          GTK_SIGNAL_FUNC(balsa_message_forward_inline) },
-        { GNOME_STOCK_MENU_BOOK_RED,     N_("Store Address..."), 
-          GTK_SIGNAL_FUNC(balsa_store_address) } };
+        {
+        GNOME_STOCK_MENU_BOOK_OPEN, N_("View Source"),
+                GTK_SIGNAL_FUNC(bndx_view_source)}, {
+        BALSA_PIXMAP_MENU_REPLY, N_("Reply..."),
+                GTK_SIGNAL_FUNC(balsa_message_reply)}, {
+        BALSA_PIXMAP_MENU_REPLY_ALL, N_("Reply To All..."),
+                GTK_SIGNAL_FUNC(balsa_message_replytoall)}, {
+        BALSA_PIXMAP_MENU_REPLY_GROUP, N_("Reply To Group..."),
+                GTK_SIGNAL_FUNC(balsa_message_replytogroup)}, {
+        BALSA_PIXMAP_MENU_FORWARD, N_("Forward Attached..."),
+                GTK_SIGNAL_FUNC(balsa_message_forward_attached)}, {
+        BALSA_PIXMAP_MENU_FORWARD, N_("Forward Inline..."),
+                GTK_SIGNAL_FUNC(balsa_message_forward_inline)}, {
+    GNOME_STOCK_MENU_BOOK_RED, N_("Store Address..."),
+                GTK_SIGNAL_FUNC(balsa_store_address)}};
     GtkWidget *menu, *menuitem, *submenu;
-    LibBalsaMailbox* mailbox;
     unsigned i;
-    GList *list;
-    gboolean any_deleted = FALSE;
-    gboolean any_not_deleted = FALSE;
- 
-    BALSA_DEBUG();
-    mailbox = bindex->mailbox_node->mailbox;
 
     menu = gtk_menu_new();
-    /* it's a single-use menu, so we must destroy it when we're done */
-    gtk_signal_connect(GTK_OBJECT(menu), "selection-done",
-                       GTK_SIGNAL_FUNC(gtk_object_destroy), NULL);
 
-    for(i=0; i<ELEMENTS(entries); i++)
+    for (i = 0; i < ELEMENTS(entries); i++)
         create_stock_menu_item(menu, entries[i].icon, _(entries[i].label),
-                               entries[i].func, bindex, TRUE);
+                               entries[i].func, index);
 
-    for (list = GTK_CLIST(bindex->ctree)->selection; list;
-         list = g_list_next(list)) {
-        LibBalsaMessage *message =
-            LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data
-                             (GTK_CTREE(bindex->ctree), list->data));
-        if (message->flags & LIBBALSA_MESSAGE_FLAG_DELETED)
-            any_deleted = TRUE;
-        else
-            any_not_deleted = TRUE;
-    }
-    if (any_not_deleted) {
+    index->delete_item =
         create_stock_menu_item(menu, GNOME_STOCK_MENU_TRASH,
                                _("Delete"),
                                GTK_SIGNAL_FUNC(balsa_message_delete),
-                               bindex, !mailbox->readonly);
-    }
-    if (any_deleted) {
-	create_stock_menu_item(menu, GNOME_STOCK_MENU_UNDELETE,
-			       _("Undelete"),
+                               index);
+    index->undelete_item =
+        create_stock_menu_item(menu, GNOME_STOCK_MENU_UNDELETE,
+                               _("Undelete"),
                                GTK_SIGNAL_FUNC(balsa_message_undelete),
-			       bindex, !mailbox->readonly);
-    }
-    if (mailbox != balsa_app.trash) {
-	create_stock_menu_item(menu, GNOME_STOCK_MENU_TRASH,
-			       _("Move To Trash"),
-                               GTK_SIGNAL_FUNC(balsa_message_move_to_trash),
-			       bindex, !mailbox->readonly);
-    }
+                               index);
+    index->move_to_trash_item =
+        create_stock_menu_item(menu, GNOME_STOCK_MENU_TRASH,
+                               _("Move To Trash"),
+                               GTK_SIGNAL_FUNC
+                               (balsa_message_move_to_trash), index);
 
     menuitem = gtk_menu_item_new_with_label(_("Toggle"));
     submenu = gtk_menu_new();
-
-    create_stock_menu_item( submenu, BALSA_PIXMAP_MENU_FLAGGED, _("Flagged"),
-			    GTK_SIGNAL_FUNC(balsa_message_toggle_flagged),
-                            bindex, TRUE);
-
-    create_stock_menu_item( submenu, BALSA_PIXMAP_MENU_NEW, _("Unread"),
-			    GTK_SIGNAL_FUNC(balsa_message_toggle_new),
-                            bindex, TRUE);
+    create_stock_menu_item(submenu, BALSA_PIXMAP_MENU_FLAGGED,
+                           _("Flagged"),
+                           GTK_SIGNAL_FUNC(balsa_message_toggle_flagged),
+                           index);
+    create_stock_menu_item(submenu, BALSA_PIXMAP_MENU_NEW, _("Unread"),
+                           GTK_SIGNAL_FUNC(balsa_message_toggle_new),
+                           index);
 
     gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
 
     gtk_menu_append(GTK_MENU(menu), menuitem);
 
     menuitem = gtk_menu_item_new_with_label(_("Move to"));
-    gtk_widget_set_sensitive(menuitem, !mailbox->readonly);
+    index->move_to_item = menuitem;
     gtk_menu_append(GTK_MENU(menu), menuitem);
 
+    return menu;
+}
+
+/*
+ * bndx_popup_menu_prepare: set sensitivity of menuitems on the popup
+ * menu, and populate the mru submenu
+ */
+static GtkWidget *
+bndx_popup_menu_prepare(BalsaIndex * index)
+{
+    GtkWidget *menu = index->popup_menu;
+    GtkWidget *submenu;
+    LibBalsaMailbox* mailbox;
+    GList *list, *l;
+    gboolean any;
+    gboolean any_deleted = FALSE;
+    gboolean any_not_deleted = FALSE;
+ 
+    BALSA_DEBUG();
+
+    l = balsa_index_selected_list(index);
+    for (list = l; list; list = g_list_next(list)) {
+        LibBalsaMessage *message = list->data;
+
+        if (message->flags & LIBBALSA_MESSAGE_FLAG_DELETED)
+            any_deleted = TRUE;
+        else
+            any_not_deleted = TRUE;
+    }
+    g_list_free(l);
+    any = (l != NULL);
+
+    l = gtk_container_get_children(GTK_CONTAINER(menu));
+    for (list = l; list; list = g_list_next(list))
+        gtk_widget_set_sensitive(GTK_WIDGET(list->data), any);
+    g_list_free(l);
+
+    mailbox = index->mailbox_node->mailbox;
+    gtk_widget_set_sensitive(index->delete_item,
+                             any_not_deleted && !mailbox->readonly);
+    gtk_widget_set_sensitive(index->undelete_item,
+                             any_deleted && !mailbox->readonly);
+    gtk_widget_set_sensitive(index->move_to_trash_item,
+                             any && mailbox != balsa_app.trash
+                             && !mailbox->readonly);
+    gtk_widget_set_sensitive(index->move_to_item,
+                             any && !mailbox->readonly);
+
     submenu = balsa_mblist_mru_menu(GTK_WINDOW(balsa_app.main_window),
                                     &balsa_app.folder_mru,
                                     G_CALLBACK(mru_menu_cb),
-                                    bindex);
-    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
+                                    index);
+    gtk_menu_item_set_submenu(GTK_MENU_ITEM(index->move_to_item),
+                              submenu);
 
     gtk_widget_show_all(menu);
 
     return menu;
 }
 
-static void
+static GtkWidget *
 create_stock_menu_item(GtkWidget * menu, const gchar * type,
 		       const gchar * label, GtkSignalFunc cb,
-		       gpointer data, gboolean sensitive)
+		       gpointer data)
 {
 #if BALSA_MAJOR < 2
     GtkWidget *menuitem = gnome_stock_menu_item(type, label);
@@ -2097,40 +2209,32 @@
 
     gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
 #endif                          /* BALSA_MAJOR < 2 */
-    gtk_widget_set_sensitive(menuitem, sensitive);
 
     gtk_signal_connect(GTK_OBJECT(menuitem),
 		       "activate", (GtkSignalFunc) cb, data);
 
     gtk_menu_append(GTK_MENU(menu), menuitem);
+
+    return menuitem;
 }
 
 static void
-balsa_index_transfer_messages(BalsaIndex * bindex,
+balsa_index_transfer_messages(BalsaIndex * index,
                               LibBalsaMailbox * mailbox)
 {
-    GtkCList* clist;
-    GList *list, *messages;
-    LibBalsaMessage* message;
+    GList *messages;
 
-    g_return_if_fail(bindex != NULL);
+    g_return_if_fail(index != NULL);
     if (mailbox == NULL)
         return;
-    clist = GTK_CLIST(bindex->ctree);
 
     /*Transferring to same mailbox? */
-    if (bindex->mailbox_node->mailbox == mailbox)
+    if (index->mailbox_node->mailbox == mailbox)
 	return;
-
-    messages=NULL;
-    for (list = clist->selection; list;list = list->next) {
-	message = gtk_ctree_node_get_row_data(GTK_CTREE(bindex->ctree), 
-					      list->data);
-	messages=g_list_append(messages, message);
-    }
 
-    balsa_index_transfer(messages, bindex->mailbox_node->mailbox,
-                         mailbox, bindex, FALSE);
+    messages = balsa_index_selected_list(index);
+    balsa_index_transfer(messages, index->mailbox_node->mailbox,
+                         mailbox, index, FALSE);
     g_list_free(messages);
 }
 
@@ -2164,50 +2268,42 @@
 }
 
 void
-balsa_index_update_tree(BalsaIndex *bindex, gboolean expand)
+balsa_index_update_tree(BalsaIndex * index, gboolean expand)
 /* Remarks: In the "collapse" case, we still expand current thread to the
 	    extent where viewed message is visible. An alternative
 	    approach would be to change preview, e.g. to top of thread. */
 {
-    GtkCTree *tree=GTK_CTREE(bindex->ctree);
-    GtkCList *clist=GTK_CLIST(bindex->ctree);
-    BalsaMessage *msg=BALSA_MESSAGE(balsa_app.main_window->preview);
-    GtkCTreeNode *node, *msg_node=NULL;
+    GtkTreeView *tree_view = GTK_TREE_VIEW(index);
+    GtkTreePath *path;
+    BalsaMessage *msg = BALSA_MESSAGE(balsa_app.main_window->preview);
 
-    gtk_clist_freeze(clist);
-    gtk_signal_handler_block_by_func(GTK_OBJECT(bindex->ctree),
+    gtk_signal_handler_block_by_func(GTK_OBJECT(index),
                                      GTK_SIGNAL_FUNC(expand ?
-                                                     tree_expand_cb :
-                                                     tree_collapse_cb),
-                                     bindex);
-    for(node=gtk_ctree_node_nth(tree, 0); node; 
-	node=GTK_CTREE_NODE_NEXT(node)) {
-	if(expand)
-	    gtk_ctree_expand_recursive(tree, node);
-	else
-	    gtk_ctree_collapse_recursive(tree, node);
-	if(!msg_node && msg && msg->message)
-	    msg_node=gtk_ctree_find_by_row_data(tree, node, msg->message);
+                                                     bndx_tree_expand_cb :
+                                                     bndx_tree_collapse_cb),
+                                     NULL);
+
+    if (expand)
+        gtk_tree_view_expand_all(tree_view);
+    else
+        gtk_tree_view_collapse_all(tree_view);
 
-	balsa_index_set_style_recursive( bindex, node); /* chbm */
+    path = gtk_tree_path_new();
+    bndx_set_style_recursive(index, path);     /* chbm */
+    gtk_tree_path_free(path);
+
+    if (msg && bndx_find_message(index, &path, NULL, msg->message)) {
+        if (!expand)           /* Re-expand msg_node's thread; cf. Remarks */
+            bndx_expand_to_path(tree_view, path);
+        bndx_check_visibility(index, path);
+        gtk_tree_path_free(path);
     }
-    
-    if (msg_node) {
-	if(!expand) {		/* Re-expand msg_node's thread; cf. Remarks */
-	    for(node=GTK_CTREE_ROW(msg_node)->parent; node;
-		node=GTK_CTREE_ROW(node)->parent) {
-		gtk_ctree_expand(tree, node);
-	    }
-	}
-        gtk_clist_thaw(clist);
-        balsa_index_check_visibility(clist, msg_node, 0.5);
-    } else
-        gtk_clist_thaw(clist);
-    gtk_signal_handler_unblock_by_func(GTK_OBJECT(bindex->ctree),
+
+    gtk_signal_handler_unblock_by_func(GTK_OBJECT(index),
                                        GTK_SIGNAL_FUNC(expand ?
-                                                       tree_expand_cb :
-                                                       tree_collapse_cb),
-                                       bindex);
+                                                       bndx_tree_expand_cb :
+                                                       bndx_tree_collapse_cb),
+                                       NULL);
 }
 
 /* balsa_index_set_threading_type:
@@ -2215,169 +2311,118 @@
    recreated. This should not be necessary.
 */
 void
-balsa_index_set_threading_type(BalsaIndex * bindex, int thtype)
+balsa_index_set_threading_type(BalsaIndex * index, int thtype)
 {
     GList *list;
     LibBalsaMailbox* mailbox = NULL;
-    GtkCList *clist;
 
-    g_return_if_fail (bindex);
-    g_return_if_fail (GTK_IS_CLIST(bindex->ctree));
-    g_return_if_fail (bindex->mailbox_node != NULL);
-    g_return_if_fail (bindex->mailbox_node->mailbox != NULL);
-
-    clist = GTK_CLIST(bindex->ctree);
-    bindex->threading_type = thtype;
-    bindex->mailbox_node->threading_type = thtype;
-    
-    gtk_ctree_set_line_style (
-            bindex->ctree,
-            (thtype == BALSA_INDEX_THREADING_FLAT)?
-                GTK_CTREE_LINES_NONE: GTK_CTREE_LINES_SOLID);
-    
-    mailbox = bindex->mailbox_node->mailbox;
+    g_return_if_fail (index);
+    g_return_if_fail (index->mailbox_node != NULL);
+    g_return_if_fail (index->mailbox_node->mailbox != NULL);
 
-    gtk_clist_freeze(clist);
-    gtk_clist_clear(clist);
+    index->threading_type = thtype;
+    index->mailbox_node->threading_type = thtype;
+    
+    gtk_tree_store_clear(GTK_TREE_STORE
+                         (gtk_tree_view_get_model(GTK_TREE_VIEW(index))));
     
+    mailbox = index->mailbox_node->mailbox;
     for (list = mailbox->message_list; list; list = list->next)
-	balsa_index_add(bindex, LIBBALSA_MESSAGE(list->data));
+	balsa_index_add(index, LIBBALSA_MESSAGE(list->data));
     /* do threading */
-    balsa_index_threading(bindex);
-    gtk_clist_sort(clist);
-    DO_CLIST_WORKAROUND(clist);
-    gtk_clist_thaw(clist);
-    balsa_index_update_tree(bindex, 
-                            balsa_app.expand_tree 
-                            /* *** Config: "Expand tree by default" */);
+    balsa_index_threading(index);
+    /* expand tree if specified in config */
+    balsa_index_update_tree(index, balsa_app.expand_tree);
 
-
     /* set the menu apriopriately */
     balsa_window_set_threading_menu(thtype);
 }
 
 static void
-balsa_index_set_sort_order(BalsaIndex * bindex, int column, GtkSortType order)
+bndx_set_sort_order(BalsaIndex * index, int col_id, GtkSortType order)
 {
-    GtkCList * clist;
-    g_return_if_fail(bindex->mailbox_node);
-    g_return_if_fail(column>=0 && column <=6);
+    GtkTreeView *tree_view = GTK_TREE_VIEW(index);
+    GtkTreeSortable *sortable =
+        GTK_TREE_SORTABLE(gtk_tree_view_get_model(tree_view));
+    GtkTreeViewColumn *column =
+        gtk_tree_view_get_column(tree_view, col_id);
+
+    g_return_if_fail(index->mailbox_node);
+    g_return_if_fail(col_id >= 0 && col_id <= 6);
     g_return_if_fail(order == GTK_SORT_DESCENDING || 
 		     order == GTK_SORT_ASCENDING);
 
-    clist = GTK_CLIST(bindex->ctree);
-    bindex->mailbox_node->sort_field = column;
-    bindex->mailbox_node->sort_type  = order;
-    clist->sort_type = order;
-    gtk_clist_set_sort_column(clist, column);
-
-    switch (column) {
-    case 0:
-	gtk_clist_set_compare_func(clist, numeric_compare);
-	break;
-    case 5:
-	gtk_clist_set_compare_func(clist, date_compare);
-	break;
-    case 6:
-        gtk_clist_set_compare_func(clist, size_compare);
-        break;
-    default:
-	gtk_clist_set_compare_func(clist, NULL);
-    }
+    index->mailbox_node->sort_field = col_id;
+    index->mailbox_node->sort_type  = order;
+
+    gtk_tree_sortable_set_sort_column_id(sortable, col_id, order);
+    gtk_tree_view_column_set_sort_indicator(column, TRUE);
+    gtk_tree_view_column_set_sort_order(column, order);
 }
 
-static void
-refresh_size(GtkCTree * ctree,
-	     GtkCTreeNode *node,
-	     gpointer data)
+static gboolean
+bndx_refresh_size_func(GtkTreeModel * model, GtkTreePath * path,
+                       GtkTreeIter * iter, gpointer data)
 {
     gchar *txt_new;
-    LibBalsaMessage * message;
-    
-    message = LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data (ctree, node));
-    txt_new = libbalsa_message_size_to_gchar(message,
-					     GPOINTER_TO_INT(data));
-    gtk_ctree_node_set_text (ctree, node, 6, txt_new);
-    g_free (txt_new);
+    LibBalsaMessage *message = NULL;
+
+    gtk_tree_model_get(model, iter, BNDX_MESSAGE_COLUMN, &message, -1);
+    txt_new =
+        libbalsa_message_size_to_gchar(message, GPOINTER_TO_INT(data));
+    gtk_tree_store_set(GTK_TREE_STORE(model), iter,
+                       BNDX_SIZE_COLUMN, txt_new,
+                       -1);
+    g_free(txt_new);
+
+    return FALSE;
 }
 
 void
-balsa_index_refresh_size(GtkNotebook *notebook,
-			 GtkNotebookPage *page,
-                         gint page_num,
-                         gpointer data)
+balsa_index_refresh_size(BalsaIndex * index)
 {
-    BalsaIndex *bindex;
-    GtkWidget *index;
-    GtkCTree *ctree;
+    GtkTreeModel *model;
 
-    if (page)
-	index = gtk_notebook_get_nth_page(notebook, page_num);
-    else
-	index = GTK_WIDGET(data);
-
-    bindex = BALSA_INDEX(index);
-    if (!bindex)
-        return;
-
-    if (bindex->line_length == balsa_app.line_length)
+    if (index->line_length == balsa_app.line_length)
         return;
 
-    bindex->line_length = balsa_app.line_length;
-    ctree = GTK_CTREE(bindex->ctree);
-    if (ctree)
-	gtk_ctree_pre_recursive(ctree,
-				NULL,
-				refresh_size,
-				GINT_TO_POINTER(bindex->line_length));
+    index->line_length = balsa_app.line_length;
+    model = gtk_tree_view_get_model(GTK_TREE_VIEW(index));
+    gtk_tree_model_foreach(model, bndx_refresh_size_func,
+                           GINT_TO_POINTER(index->line_length));
 }
 
-static void
-refresh_date(GtkCTree * ctree,
-	     GtkCTreeNode *node,
-	     gpointer data)
+static gboolean
+bndx_refresh_date_func(GtkTreeModel * model, GtkTreePath * path,
+                       GtkTreeIter * iter, gpointer data)
 {
-    LibBalsaMessage * message;
     gchar *txt_new;
+    LibBalsaMessage *message = NULL;
+
+    gtk_tree_model_get(model, iter, BNDX_MESSAGE_COLUMN, &message, -1);
+    txt_new = libbalsa_message_date_to_gchar(message, (gchar*) data);
+    gtk_tree_store_set(GTK_TREE_STORE(model), iter,
+                       BNDX_DATE_COLUMN, txt_new,
+                       -1);
+    g_free(txt_new);
 
-    message = LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data (ctree, node));
-    txt_new = libbalsa_message_date_to_gchar(message,
-					     (gchar*) data);
-    gtk_ctree_node_set_text (ctree, node, 5, txt_new);
-    g_free (txt_new);
+    return FALSE;
 }
 
 void
-balsa_index_refresh_date (GtkNotebook *notebook,
-			  GtkNotebookPage *page,
-                          gint page_num,
-                          gpointer data)
+balsa_index_refresh_date(BalsaIndex * index)
 {
-    BalsaIndex *bindex;
-    GtkWidget *index;
-    GtkCTree *ctree;
-
-    if (page)
-	index = gtk_notebook_get_nth_page(notebook, page_num);
-    else
-	index = GTK_WIDGET(data);
+    GtkTreeModel *model;
 
-    bindex = BALSA_INDEX(index);
-    if (!bindex)
+    if (!strcmp (index->date_string, balsa_app.date_string))
         return;
 
-    if (!strcmp (bindex->date_string, balsa_app.date_string))
-        return;
-
-    g_free (bindex->date_string);
-    bindex->date_string = g_strdup (balsa_app.date_string);
+    g_free (index->date_string);
+    index->date_string = g_strdup (balsa_app.date_string);
 
-    ctree = GTK_CTREE(bindex->ctree);
-    if (ctree)	
-	gtk_ctree_pre_recursive(ctree,
-				NULL,
-				refresh_date,
-				bindex->date_string);
+    model = gtk_tree_view_get_model(GTK_TREE_VIEW(index));
+    gtk_tree_model_foreach(model, bndx_refresh_date_func,
+                           index->date_string);
 }
 
 /* idle handler wrappers
@@ -2449,9 +2494,9 @@
  * hide (or show, if hide is FALSE) deleted messages.
  */
 static void
-hide_deleted(BalsaIndex * bindex, gboolean hide)
+hide_deleted(BalsaIndex * index, gboolean hide)
 {
-    LibBalsaMailbox *mailbox = bindex->mailbox_node->mailbox;
+    LibBalsaMailbox *mailbox = index->mailbox_node->mailbox;
     GList *list;
     GList *messages = NULL;
 
@@ -2463,9 +2508,9 @@
     }
 
     if (hide)
-        mailbox_messages_delete_cb(bindex, messages);
+        mailbox_messages_delete_cb(index, messages);
     else
-        mailbox_messages_new_cb(bindex, messages);
+        mailbox_messages_new_cb(index, messages);
 
     g_list_free(messages);
 }
@@ -2483,7 +2528,7 @@
 
 void
 balsa_index_transfer(GList * messages, LibBalsaMailbox * from_mailbox,
-                     LibBalsaMailbox * to_mailbox, BalsaIndex *bindex,
+                     LibBalsaMailbox * to_mailbox, BalsaIndex *index,
                      gboolean copy)
 {
     if (messages == NULL)
@@ -2493,7 +2538,7 @@
         libbalsa_messages_copy(messages, to_mailbox);
     else {
         libbalsa_messages_move(messages, to_mailbox);
-        balsa_index_select_next_threaded(bindex);
+        bndx_select_next_threaded(index);
         balsa_index_sync_backend(from_mailbox);
     }
 
@@ -2505,4 +2550,163 @@
         enable_empty_trash(TRASH_CHECK);
     else if (to_mailbox == balsa_app.trash)
         enable_empty_trash(TRASH_FULL);
+}
+
+static gboolean
+bndx_path_is_viewable(GtkTreeView * tree_view, GtkTreePath * path)
+{
+    GtkTreePath *tmp_path = gtk_tree_path_copy(path);
+    gboolean ret_val = TRUE;
+
+    while (gtk_tree_path_up(tmp_path)
+           && gtk_tree_path_get_depth(tmp_path) > 0)
+        if (!gtk_tree_view_row_expanded(tree_view, tmp_path))
+            ret_val = FALSE;
+
+    gtk_tree_path_free(tmp_path);
+    return ret_val;
+}
+
+static gint
+bndx_row_compare(GtkTreeModel * model, GtkTreeIter * iter1,
+                 GtkTreeIter * iter2, gpointer data)
+{
+    gint sort_column = GPOINTER_TO_INT(data);
+    LibBalsaMessage *m1 = NULL;
+    LibBalsaMessage *m2 = NULL;
+
+    gtk_tree_model_get(model, iter1, BNDX_MESSAGE_COLUMN, &m1, -1);
+    gtk_tree_model_get(model, iter2, BNDX_MESSAGE_COLUMN, &m2, -1);
+
+    switch (sort_column) {
+        case 0:
+            return numeric_compare(m1, m2);
+        case 5:
+            return date_compare(m1, m2);
+        case 6:
+            return size_compare(m1, m2);
+        default:
+            return 0;
+    }
+}
+
+/*
+ * balsa_index_move_subtree
+ *
+ * model:       the GtkTreeModel for the index's tree;
+ * root:        GtkTreePath pointing to the root of the subtree to be
+ *              moved;
+ * new_parent:  GtkTreePath pointing to the row that will be the new
+ *              parent of the subtree;
+ * ref_table:   a GHashTable used by the threading code; ignored if
+ *              NULL.
+ *
+ * balsa_index_move_subtre moves the subtree.
+ * bndx_make_tree and bndx_copy_tree are helpers.
+ */
+
+static GNode *
+bndx_make_tree(GtkTreeModel * model, GtkTreeIter * iter)
+{
+    GtkTreePath *path = gtk_tree_model_get_path(model, iter);
+    GtkTreeRowReference *reference =
+        gtk_tree_row_reference_new(model, path);
+    GNode *node = g_node_new(reference);
+    GtkTreeIter child_iter;
+    
+    if (gtk_tree_model_iter_children(model, &child_iter, iter))
+        do
+            g_node_prepend(node, bndx_make_tree(model, &child_iter));
+        while (gtk_tree_model_iter_next(model, &child_iter));
+
+    gtk_tree_path_free(path);
+    return node;
+}
+
+static void
+bndx_copy_tree(GNode * node, GtkTreeModel * model,
+               GtkTreePath * parent_path, GHashTable * ref_table)
+{
+    GtkTreeRowReference *reference = node->data;
+    GtkTreePath *path;
+    GNode *child_node;
+    LibBalsaMessage *message;
+    gchar *index, *from, *subject, *date, *size;
+    GdkPixbuf *status, *attach;
+    GdkColor *color;
+    PangoWeight weight;
+    GtkTreeIter iter, parent_iter, new_iter;
+
+    path = gtk_tree_row_reference_get_path(reference);
+    gtk_tree_row_reference_free(reference);
+    gtk_tree_model_get_iter(model, &iter, path);
+
+    gtk_tree_model_get(model, &iter,
+                       BNDX_MESSAGE_COLUMN, &message,
+                       BNDX_INDEX_COLUMN, &index,
+                       BNDX_STATUS_COLUMN, &status,
+                       BNDX_ATTACH_COLUMN, &attach,
+                       BNDX_FROM_COLUMN, &from,
+                       BNDX_SUBJECT_COLUMN, &subject,
+                       BNDX_DATE_COLUMN, &date,
+                       BNDX_SIZE_COLUMN, &size,
+                       BNDX_COLOR_COLUMN, &color,
+                       BNDX_WEIGHT_COLUMN, &weight, -1);
+
+    if (parent_path && gtk_tree_path_get_depth(parent_path) > 0) {
+        /* create a new child row of parent_path */
+        gtk_tree_model_get_iter(model, &parent_iter, parent_path);
+        gtk_tree_store_append(GTK_TREE_STORE(model), &new_iter,
+                              &parent_iter);
+    } else {
+        /* create a new row at the top level, immediately after the
+         * top of the thread on which we're working */
+        while (gtk_tree_path_get_depth(path) > 1)
+            gtk_tree_path_up(path);
+        gtk_tree_model_get_iter(model, &parent_iter, path);
+        gtk_tree_store_insert_after(GTK_TREE_STORE(model), &new_iter,
+                                    NULL, &parent_iter);
+    }
+    gtk_tree_path_free(path);
+
+    gtk_tree_store_set(GTK_TREE_STORE(model), &new_iter,
+                       BNDX_MESSAGE_COLUMN, message,
+                       BNDX_INDEX_COLUMN, index,
+                       BNDX_STATUS_COLUMN, status,
+                       BNDX_ATTACH_COLUMN, attach,
+                       BNDX_FROM_COLUMN, from,
+                       BNDX_SUBJECT_COLUMN, subject,
+                       BNDX_DATE_COLUMN, date,
+                       BNDX_SIZE_COLUMN, size,
+                       BNDX_COLOR_COLUMN, color,
+                       BNDX_WEIGHT_COLUMN, weight, -1);
+
+    path = gtk_tree_model_get_path(model, &new_iter);
+    if (ref_table)
+        g_hash_table_replace(ref_table, message,
+                             gtk_tree_row_reference_new(model, path));
+
+    for (child_node = node->children; child_node;
+         child_node = child_node->next)
+        bndx_copy_tree(child_node, model, path, ref_table);
+
+    gtk_tree_path_free(path);
+}
+
+void gtk_tree_store_move(GtkTreeStore * store, 
+                         GtkTreeIter * root_iter,
+                         GtkTreeIter * new_iter);
+
+void
+balsa_index_move_subtree(GtkTreeModel * model, GtkTreePath * root, 
+                         GtkTreePath * new_parent, GHashTable * ref_table)
+{
+    GtkTreeIter root_iter;
+    GNode *node;
+
+    gtk_tree_model_get_iter(model, &root_iter, root);
+    node = bndx_make_tree(model, &root_iter);
+    bndx_copy_tree(node, model, new_parent, ref_table);
+    g_node_destroy(node);
+    gtk_tree_store_remove(GTK_TREE_STORE(model), &root_iter);
 }
Index: src/balsa-index.h
===================================================================
RCS file: /cvs/gnome/balsa/src/balsa-index.h,v
retrieving revision 1.44.2.5
diff -u -r1.44.2.5 balsa-index.h
--- src/balsa-index.h	2002/05/18 14:12:50	1.44.2.5
+++ src/balsa-index.h	2002/07/09 09:53:40
@@ -33,9 +33,9 @@
     GtkType balsa_index_get_type(void);
 
 #define BALSA_TYPE_INDEX          (balsa_index_get_type ())
-#define BALSA_INDEX(obj)          (GTK_CHECK_CAST (obj, balsa_index_get_type (), BalsaIndex))
-#define BALSA_INDEX_CLASS(klass)  (GTK_CHECK_CLASS_CAST (klass, balsa_index_get_type (), BalsaIndexClass))
-#define BALSA_IS_INDEX(obj)       (GTK_CHECK_TYPE (obj, balsa_index_get_type ()))
+#define BALSA_INDEX(obj)          (GTK_CHECK_CAST (obj, BALSA_TYPE_INDEX, BalsaIndex))
+#define BALSA_INDEX_CLASS(klass)  (GTK_CHECK_CLASS_CAST (klass, BALSA_TYPE_INDEX, BalsaIndexClass))
+#define BALSA_IS_INDEX(obj)       (GTK_CHECK_TYPE (obj, BALSA_TYPE_INDEX))
 #define BALSA_IS_INDEX_CLASS(klass) (GTK_CHECK_CLASS_TYPE (klass, BALSA_TYPE_INDEX))
 
 
@@ -43,13 +43,20 @@
     typedef struct _BalsaIndexClass BalsaIndexClass;
 
     struct _BalsaIndex {
-        GtkScrolledWindow sw;    
+        GtkTreeView tree_view;
         
-        GtkCTree* ctree;
         GtkWidget* window;       
 
+        /* the popup menu and some items we need to refer to */
+        GtkWidget *popup_menu;
+        GtkWidget *delete_item;
+        GtkWidget *undelete_item;
+        GtkWidget *move_to_trash_item;
+        GtkWidget *move_to_item;
+
         BalsaMailboxNode* mailbox_node;
         LibBalsaMessage* first_new_message;
+        LibBalsaMessage* current_message;
 
         int threading_type;
         GTimeVal last_use;
@@ -59,7 +66,7 @@
     };
 
     struct _BalsaIndexClass {
-	GtkScrolledWindowClass parent_class;
+	GtkTreeViewClass parent_class;
 
 	void (*select_message) (BalsaIndex * bindex,
 				LibBalsaMessage * message);
@@ -68,6 +75,20 @@
         void (*unselect_all_messages) (BalsaIndex* bindex);
     };
 
+/* tree model columns */
+    enum {
+        BNDX_MESSAGE_COLUMN,
+        BNDX_INDEX_COLUMN,
+        BNDX_STATUS_COLUMN,
+        BNDX_ATTACH_COLUMN,
+        BNDX_FROM_COLUMN,
+        BNDX_SUBJECT_COLUMN,
+        BNDX_DATE_COLUMN,
+        BNDX_SIZE_COLUMN,
+        BNDX_COLOR_COLUMN,
+        BNDX_WEIGHT_COLUMN,
+        BNDX_N_COLUMNS
+    };
 
 /* function prototypes */
     
@@ -119,12 +140,15 @@
     void balsa_index_reset(BalsaIndex * index);
     gint balsa_find_notebook_page_num(LibBalsaMailbox * mailbox);
     void balsa_index_update_message(BalsaIndex * index);
+    void balsa_index_set_column_widths(BalsaIndex * index);
+    GList * balsa_index_selected_list(BalsaIndex * index);
+    void balsa_index_move_subtree(GtkTreeModel * model, GtkTreePath * root,
+                                  GtkTreePath * new_parent,
+                                  GHashTable * ref_table);
 
     /* Updating index columns when preferences change */
-    void balsa_index_refresh_date (GtkNotebook *, GtkNotebookPage *,
-				   gint, gpointer);
-    void balsa_index_refresh_size (GtkNotebook *, GtkNotebookPage *,
-				   gint, gpointer);
+    void balsa_index_refresh_date (BalsaIndex * index);
+    void balsa_index_refresh_size (BalsaIndex * index);
 
     /* Change the display of all indexes when balsa_app.hide_deleted is
      * changed */
Index: src/balsa-mblist.c
===================================================================
RCS file: /cvs/gnome/balsa/src/balsa-mblist.c,v
retrieving revision 1.134.2.15
diff -u -r1.134.2.15 balsa-mblist.c
--- src/balsa-mblist.c	2002/06/27 08:42:33	1.134.2.15
+++ src/balsa-mblist.c	2002/07/09 09:53:41
@@ -162,7 +162,7 @@
     static guint mblist_type = 0;
 
     if (!mblist_type) {
-	GTypeInfo mblist_info = {
+	static const GTypeInfo mblist_info = {
 	    sizeof(BalsaMBListClass),
             NULL,               /* base_init */
             NULL,               /* base_finalize */
@@ -902,9 +902,9 @@
 void
 balsa_mblist_open_mailbox(LibBalsaMailbox * mailbox)
 {
-    GtkWidget *page = NULL;
-    int i, c;
+    int i;
     GNode *gnode;
+    GtkWidget *index;
     BalsaMailboxNode *mbnode;
 
     gdk_threads_leave();
@@ -921,47 +921,19 @@
     if (!gnode)
         return;
 
-    c = gtk_notebook_get_current_page(GTK_NOTEBOOK(balsa_app.notebook));
+    index = balsa_window_find_current_index(balsa_app.main_window);
 
     /* If we currently have a page open, update the time last visited */
-    if (c != -1) {
-	page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(balsa_app.notebook), c);
-	g_get_current_time(&BALSA_INDEX(page)->last_use);
+    if (index) {
+	g_get_current_time(&BALSA_INDEX(index)->last_use);
     }
     
     i = balsa_find_notebook_page_num(mailbox);
     if (i != -1) {
 	gtk_notebook_set_current_page(GTK_NOTEBOOK(balsa_app.notebook), i);
-	page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(balsa_app.notebook), i);
-	g_get_current_time(&BALSA_INDEX(page)->last_use);
-	
-/* This nasty looking piece of code is for the column resizing patch, it needs
-   to change the size of the columns before they get displayed.  To do this we
-   need to get the reference to the index page, which gives us a reference to
-   the index, which gives us the clist, which we then reference.  Looks ugly
-   but works well. */
-	gtk_clist_set_column_width(GTK_CLIST
-				   ((BALSA_INDEX(page)->ctree)),
-				   0, balsa_app.index_num_width);
-	gtk_clist_set_column_width(GTK_CLIST
-				   ((BALSA_INDEX(page)->ctree)),
-				   1, balsa_app.index_status_width);
-	gtk_clist_set_column_width(GTK_CLIST
-				   ((BALSA_INDEX(page)->ctree)),
-				   2,
-				   balsa_app.index_attachment_width);
-	gtk_clist_set_column_width(GTK_CLIST
-				   ((BALSA_INDEX(page)->ctree)),
-				   3, balsa_app.index_from_width);
-	gtk_clist_set_column_width(GTK_CLIST
-				   ((BALSA_INDEX(page)->ctree)),
-				   4, balsa_app.index_subject_width);
-	gtk_clist_set_column_width(GTK_CLIST
-				   ((BALSA_INDEX(page)->ctree)),
-				   5, balsa_app.index_date_width);
-	gtk_clist_set_column_width(GTK_CLIST
-				   ((BALSA_INDEX(page)->ctree)),
-				   6, balsa_app.index_size_width);
+        index = balsa_window_find_current_index(balsa_app.main_window);
+	g_get_current_time(&BALSA_INDEX(index)->last_use);
+        balsa_index_set_column_widths(BALSA_INDEX(index));
     } else { /* page with mailbox not found, open it */
 	balsa_window_open_mbnode(balsa_app.main_window, mbnode);
 
@@ -1375,8 +1347,10 @@
    if (index == NULL)
       return;
    
-   label = gtk_notebook_get_tab_label(
-      GTK_NOTEBOOK(balsa_app.main_window->notebook), GTK_WIDGET(index));
+   label = gtk_notebook_get_tab_label(GTK_NOTEBOOK
+                                      (balsa_app.main_window->notebook),
+                                      gtk_widget_get_parent(GTK_WIDGET
+                                                            (index)));
    
    list = gtk_container_get_children(GTK_CONTAINER (label));
     
Index: src/main-window.c
===================================================================
RCS file: /cvs/gnome/balsa/src/main-window.c,v
retrieving revision 1.446.2.20
diff -u -r1.446.2.20 main-window.c
--- src/main-window.c	2002/06/27 08:42:33	1.446.2.20
+++ src/main-window.c	2002/07/09 09:53:43
@@ -1271,6 +1271,7 @@
 {
     BalsaIndex * index;
     GtkWidget *label;
+    GtkWidget *scroll;
     gint page_num;
     gboolean failurep;
 
@@ -1325,13 +1326,19 @@
     index->line_length = balsa_app.line_length;
 
     /* store for easy access */
+    scroll = gtk_scrolled_window_new(NULL, NULL);
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
+                                   GTK_POLICY_AUTOMATIC,
+                                   GTK_POLICY_AUTOMATIC);
+    gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(index));
+    gtk_widget_show(scroll);
     gtk_notebook_append_page(GTK_NOTEBOOK(balsa_app.main_window->notebook),
-                             GTK_WIDGET(index), label);
+                             scroll, label);
 
     /* change the page to the newly selected notebook item */
-    page_num = gtk_notebook_page_num
-        (GTK_NOTEBOOK (balsa_app.main_window->notebook),
-         GTK_WIDGET (index));
+    page_num = gtk_notebook_page_num(GTK_NOTEBOOK
+                                     (balsa_app.main_window->notebook),
+                                     scroll);
     gtk_notebook_set_page(GTK_NOTEBOOK(balsa_app.main_window->notebook),
                           page_num);
     register_open_mailbox(mbnode->mailbox);
@@ -1373,18 +1380,18 @@
     i = balsa_find_notebook_page_num(mbnode->mailbox);
 
     if (i != -1) {
-        index = gtk_notebook_get_nth_page(GTK_NOTEBOOK(balsa_app.notebook), i);
-        gtk_notebook_remove_page(GTK_NOTEBOOK(window->notebook), i);
+        GtkWidget *page =
+            gtk_notebook_get_nth_page(GTK_NOTEBOOK(balsa_app.notebook), i);
 
-        gtk_object_destroy(GTK_OBJECT(index));
+        gtk_notebook_remove_page(GTK_NOTEBOOK(window->notebook), i);
         unregister_open_mailbox(mbnode->mailbox);
 
         /* If this is the last notebook page clear the message preview
            and the status bar */
-        index =
+        page =
             gtk_notebook_get_nth_page(GTK_NOTEBOOK(balsa_app.notebook), 0);
 
-        if (index == NULL) {
+        if (page == NULL) {
             gtk_window_set_title(GTK_WINDOW(window), "Balsa");
             balsa_message_clear(BALSA_MESSAGE(window->preview));
             gnome_appbar_set_default(balsa_app.appbar, "Mailbox closed");
@@ -1410,7 +1417,8 @@
 balsa_close_mailbox_on_timer(GtkWidget * widget, gpointer * data)
 {
     GTimeVal current_time;
-    GtkWidget *index;
+    GtkWidget *page;
+    BalsaIndex *index;
     int i, c, time;
 
     if (! balsa_app.close_mailbox_auto)
@@ -1421,20 +1429,19 @@
     c = gtk_notebook_get_current_page(GTK_NOTEBOOK(balsa_app.notebook));
 
     for (i = 0;
-         (index =
+         (page =
           gtk_notebook_get_nth_page(GTK_NOTEBOOK(balsa_app.notebook), i));
          i++) {
         if (i == c)
             continue;
-        time =
-            current_time.tv_sec -
-            BALSA_INDEX(index)->last_use.tv_sec;
+        index = BALSA_INDEX(gtk_bin_get_child(GTK_BIN(page)));
+        time = current_time.tv_sec - index->last_use.tv_sec;
         if (time > (balsa_app.close_mailbox_timeout * 60)) {
             if (balsa_app.debug)
                 fprintf(stderr, "Closing Page %d, time: %d\n", i, time);
             gtk_notebook_remove_page(GTK_NOTEBOOK(balsa_app.notebook), i);
-            unregister_open_mailbox(BALSA_INDEX(index)->mailbox_node->mailbox);
-            gtk_object_destroy(GTK_OBJECT(index));
+            unregister_open_mailbox(index->mailbox_node->mailbox);
+            gtk_object_destroy(GTK_OBJECT(page));
             if (i < c)
                 c--;
             i--;
@@ -1482,11 +1489,9 @@
     index = balsa_window_find_current_index(window);
     if (index) {
         /* update the date column, only in the current page */
-        balsa_index_refresh_date(GTK_NOTEBOOK(balsa_app.notebook),
-				 NULL, 0, index);
+        balsa_index_refresh_date(BALSA_INDEX(index));
         /* update the size column, only in the current page */
-        balsa_index_refresh_size(GTK_NOTEBOOK(balsa_app.notebook),
-                                 NULL, 0, index);
+        balsa_index_refresh_size(BALSA_INDEX(index));
 
     }
     if (balsa_app.alternative_layout)
@@ -2218,16 +2223,19 @@
 GtkWidget *
 balsa_window_find_current_index(BalsaWindow * window)
 {
+    GtkWidget *page;
     GtkWidget *index;
 
     g_return_val_if_fail(window != NULL, NULL);
 
-    index = gtk_notebook_get_nth_page(GTK_NOTEBOOK(window->notebook),
+    page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(window->notebook),
                                      gtk_notebook_get_current_page
                                      (GTK_NOTEBOOK(window->notebook)));
-    if (!index)
+    if (!page)
         return NULL;
 
+    index = gtk_bin_get_child(GTK_BIN(page));
+
     return GTK_WIDGET(BALSA_INDEX(index));
 }
 
@@ -3012,20 +3020,19 @@
  */
 static void
 notebook_switch_page_cb(GtkWidget * notebook,
-                        GtkNotebookPage * page, guint page_num)
+                        GtkNotebookPage * notebookpage, guint page_num)
 {
+    GtkWidget *page;
     GtkWidget *index;
     GtkWidget *window;
-    GtkWidget* clist;
     LibBalsaMailbox *mailbox;
-    LibBalsaMessage *message;
     gchar *title;
 
-    index = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
+    page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
+    index = gtk_bin_get_child(GTK_BIN(page));
 
     mailbox = BALSA_INDEX(index)->mailbox_node->mailbox;
     window = BALSA_INDEX(index)->window;
-    clist = GTK_WIDGET (BALSA_INDEX (index)->ctree);
 
     if (mailbox->name) {
         if (mailbox->readonly) {
@@ -3041,27 +3048,14 @@
     }
 
     balsa_index_update_message(BALSA_INDEX(index));
-
-    if (GTK_CLIST(clist)->selection) {
-        message =
-            gtk_ctree_node_get_row_data(GTK_CTREE(clist),
-                                        (g_list_last
-                                         (GTK_CLIST(clist)->selection)->
-                                         data));
-        enable_message_menus(message);
-    } else {
-        enable_message_menus(NULL);
-    }
-
+    enable_message_menus(BALSA_INDEX(index)->current_message);
     enable_mailbox_menus(BALSA_INDEX(index)->mailbox_node);
 
     balsa_mblist_focus_mailbox(balsa_app.mblist, mailbox);
     balsa_mblist_set_status_bar(mailbox);
 
-    balsa_index_refresh_date(GTK_NOTEBOOK(balsa_app.notebook),
-			     NULL, 0, index);
-    balsa_index_refresh_size(GTK_NOTEBOOK(balsa_app.notebook),
-			     NULL, 0, index);
+    balsa_index_refresh_date(BALSA_INDEX(index));
+    balsa_index_refresh_size(BALSA_INDEX(index));
 }
 
 static void
@@ -3086,7 +3080,7 @@
 {
     BalsaIndex *index = BALSA_INDEX(widget);
     /* we need to disable menus in case there was no other message selected */
-    if(GTK_CLIST(index->ctree)->selection == NULL) {
+    if(index->current_message == NULL) {
         enable_message_menus(NULL);
         enable_edit_menus(NULL);
     }
@@ -3134,7 +3128,7 @@
             label_height = label->allocation.height;
             
             if (y > label_y && y < label_y + label_height) {
-                return BALSA_INDEX (page);
+                return BALSA_INDEX(gtk_bin_get_child(GTK_BIN(page)));
             }
         }
         ++page_num;
@@ -3444,14 +3438,14 @@
 static void
 mark_all_cb(GtkWidget * widget, gpointer data)
 {
-    GtkCList *clist;
-    BalsaIndex *bindex;
+    GtkWidget *index;
+    GtkTreeSelection *selection;
 
-    bindex=BALSA_INDEX(balsa_window_find_current_index(balsa_app.main_window));
-    g_return_if_fail(bindex != NULL);
-    clist = GTK_CLIST(bindex->ctree);
+    index = balsa_window_find_current_index(balsa_app.main_window);
+    g_return_if_fail(index != NULL);
 
-    gtk_clist_select_all(clist);
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(index));
+    gtk_tree_selection_select_all(selection);
 }
 
 static void
Index: src/main.c
===================================================================
RCS file: /cvs/gnome/balsa/src/main.c,v
retrieving revision 1.127.2.10
diff -u -r1.127.2.10 main.c
--- src/main.c	2002/06/25 07:43:53	1.127.2.10
+++ src/main.c	2002/07/09 09:53:43
@@ -376,9 +376,6 @@
     /* load mailboxes */
     mailboxes_init();
 
-    /* create all the pretty icons that balsa uses that
-     * arn't part of gnome-libs */
-    balsa_icons_init();
     default_icon = balsa_pixmap_finder("balsa_icon.png");
 #ifdef HAVE_LIBGNOMEUI_GNOME_WINDOW_ICON_H
     gnome_window_icon_set_default_from_file(default_icon);
Index: src/message-window.c
===================================================================
RCS file: /cvs/gnome/balsa/src/message-window.c,v
retrieving revision 1.42.2.6
diff -u -r1.42.2.6 message-window.c
--- src/message-window.c	2002/06/27 08:42:34	1.42.2.6
+++ src/message-window.c	2002/07/09 09:53:43
@@ -593,19 +593,21 @@
 {
     MessageWindow *mw = (MessageWindow *) (data);
     BalsaIndex *idx;
-    GtkCList *list;
+    GList *list;
     LibBalsaMessage *msg;
 
     balsa_index_select_next_unread(
 	idx=BALSA_INDEX(
 	    balsa_window_find_current_index(balsa_app.main_window)));
 
-    list=GTK_CLIST(idx->ctree);
-    if(g_list_length(list->selection) != 1)
-	return;
+    list = balsa_index_selected_list(idx);
+    if (g_list_length(list) != 1) {
+        g_list_free(list);
+        return;
+    }
 
-    msg=LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data(GTK_CTREE(list),
-						     list->selection->data));
+    msg = LIBBALSA_MESSAGE(list->data);
+    g_list_free(list);
     if(!msg)
 	return;
 
@@ -617,19 +619,21 @@
 {
     MessageWindow *mw = (MessageWindow *) (data);
     BalsaIndex *idx;
-    GtkCList *list;
+    GList *list;
     LibBalsaMessage *msg;
 
     balsa_index_select_next_flagged(
 	idx=BALSA_INDEX(
 	    balsa_window_find_current_index(balsa_app.main_window)));
 
-    list=GTK_CLIST(idx->ctree);
-    if(g_list_length(list->selection) != 1)
-	return;
+    list = balsa_index_selected_list(idx);
+    if (g_list_length(list) != 1) {
+        g_list_free(list);
+        return;
+    }
 
-    msg=LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data(GTK_CTREE(list),
-						     list->selection->data));
+    msg = LIBBALSA_MESSAGE(list->data);
+    g_list_free(list);
     if(!msg)
 	return;
 
Index: src/print.c
===================================================================
RCS file: /cvs/gnome/balsa/src/print.c,v
retrieving revision 1.37.2.9
diff -u -r1.37.2.9 print.c
--- src/print.c	2002/06/13 08:37:45	1.37.2.9
+++ src/print.c	2002/07/09 09:53:44
@@ -1030,21 +1030,17 @@
 message_print_cb(GtkWidget * widget, gpointer cbdata)
 {
     BalsaIndex *index;
-    GList *list;
     LibBalsaMessage *msg;
 
     g_return_if_fail(cbdata);
 
     index = BALSA_INDEX(balsa_window_find_current_index(BALSA_WINDOW(cbdata)));
-    if (!index || (list = GTK_CLIST(index->ctree)->selection) == NULL)
-	return;
+    if (!index)
+        return;
 
-    msg =
-	LIBBALSA_MESSAGE(gtk_ctree_node_get_row_data(
-	    GTK_CTREE(index->ctree), list->data));
-    /* print only first selected message */
-
-    message_print(msg);
+    msg = index->current_message;
+    if (msg)
+        message_print(msg);
 }
 
 
Index: src/sendmsg-window.c
===================================================================
RCS file: /cvs/gnome/balsa/src/sendmsg-window.c,v
retrieving revision 1.341.2.28
diff -u -r1.341.2.28 sendmsg-window.c
--- src/sendmsg-window.c	2002/06/23 21:50:41	1.341.2.28
+++ src/sendmsg-window.c	2002/07/09 09:53:45
@@ -1525,18 +1525,16 @@
 	balsa_window_find_current_index(balsa_app.main_window);
     
     if (index) {
-	GList *node;
-	GtkCTree *ctree = GTK_CTREE(BALSA_INDEX(index)->ctree);
+	GList *node, *l = balsa_index_selected_list(BALSA_INDEX(index));
     
-	for (node = GTK_CLIST(ctree)->selection; node;
-	     node = g_list_next(node)) {
-	    LibBalsaMessage *message =
-		gtk_ctree_node_get_row_data(ctree, GTK_CTREE_NODE(node->data));
+	for (node = l; node; node = g_list_next(node)) {
+	    LibBalsaMessage *message = node->data;
 	    GString *body = quoteBody(msg, message, type);
 	    
             gtk_text_buffer_insert_at_cursor(buffer, body->str, body->len);
 	    g_string_free(body, TRUE);
 	}
+        g_list_free(l);
     }
     
     return TRUE;
@@ -1555,13 +1553,10 @@
 	balsa_window_find_current_index(balsa_app.main_window);
     
     if (index) {
-	GList *node;
-	GtkCTree *ctree = GTK_CTREE(BALSA_INDEX(index)->ctree);
+	GList *node, *l = balsa_index_selected_list(BALSA_INDEX(index));
     
-	for (node = GTK_CLIST(ctree)->selection; node;
-	     node = g_list_next(node)) {
-	    LibBalsaMessage *message =
-		gtk_ctree_node_get_row_data(ctree, GTK_CTREE_NODE(node->data));
+	for (node = l; node; node = g_list_next(node)) {
+	    LibBalsaMessage *message = node->data;
 
 	    if(!attach_message(msg, message)) {
                 libbalsa_information(LIBBALSA_INFORMATION_WARNING,
@@ -1570,6 +1565,7 @@
                 break;
             }
 	}
+        g_list_free(l);
     }
     
     return TRUE;
Index: src/store-address.c
===================================================================
RCS file: /cvs/gnome/balsa/src/store-address.c,v
retrieving revision 1.13.6.4
diff -u -r1.13.6.4 store-address.c
--- src/store-address.c	2002/05/22 09:02:15	1.13.6.4
+++ src/store-address.c	2002/07/09 09:53:45
@@ -259,24 +259,22 @@
 {
     GtkWidget *frame = gtk_frame_new(_("Choose Address"));
     LibBalsaMessage *message;
-    GList *list = GTK_CLIST(info->index->ctree)->selection;
+    GList *list, *l = balsa_index_selected_list(info->index);
 
     info->notebook = gtk_notebook_new();
     gtk_notebook_set_scrollable(GTK_NOTEBOOK(info->notebook), TRUE);
     gtk_container_set_border_width(GTK_CONTAINER(info->notebook), 5);
     gtk_container_add(GTK_CONTAINER(frame), info->notebook);
 
-    list = g_list_last(list);
-    while (list) {
-        message = gtk_ctree_node_get_row_data(info->index->ctree,
-                                              list->data);
+    for (list = g_list_last(l); list; list = g_list_previous(list)) {
+        message = list->data;
         if (message->from)
             store_address_add_address(info, _("From:"), message->from);
         store_address_add_glist(info, _("To:"), message->to_list);
         store_address_add_glist(info, _("Cc:"), message->cc_list);
         store_address_add_glist(info, _("Bcc:"), message->bcc_list);
-        list = g_list_previous(list);
     }
+    g_list_free(l);
     return frame;
 }
 
