2008-08-05 [colin] 3.5.0cvs49
authorColin Leroy <colin@colino.net>
Tue, 5 Aug 2008 06:37:13 +0000 (06:37 +0000)
committerColin Leroy <colin@colino.net>
Tue, 5 Aug 2008 06:37:13 +0000 (06:37 +0000)
* src/prefs_account.c
* src/prefs_filtering_action.c
* src/prefs_matcher.c
* src/gtk/Makefile.am
* src/gtk/claws-marshal.list
* src/gtk/colorlabel.c
* src/gtk/colorsel.c
* src/gtk/foldersort.c
* src/gtk/gtkaspell.c
* src/gtk/gtkcmclist.c
* src/gtk/gtkcmclist.h
* src/gtk/gtkcmctree.c
* src/gtk/gtkcmctree.h
* src/gtk/gtkcmoptionmenu.c
* src/gtk/gtkcmoptionmenu.h
* src/gtk/gtksctree.c
* src/gtk/gtksctree.h
* src/gtk/gtkutils.c
* src/gtk/gtkutils.h
* src/gtk/gtkvscrollbutton.c
* src/gtk/menu.c
* src/gtk/menu.h
* src/gtk/quicksearch.c
* src/plugins/dillo_viewer/dillo_viewer.c
* src/plugins/pgpcore/select-keys.c
Try to finish yesterday's commit

28 files changed:
ChangeLog
PATCHSETS
configure.ac
src/gtk/Makefile.am
src/gtk/claws-marshal.list
src/gtk/colorlabel.c
src/gtk/colorsel.c
src/gtk/foldersort.c
src/gtk/gtkaspell.c
src/gtk/gtkcmclist.c [new file with mode: 0644]
src/gtk/gtkcmclist.h [new file with mode: 0644]
src/gtk/gtkcmctree.c [new file with mode: 0644]
src/gtk/gtkcmctree.h [new file with mode: 0644]
src/gtk/gtkcmoptionmenu.c [new file with mode: 0644]
src/gtk/gtkcmoptionmenu.h [new file with mode: 0644]
src/gtk/gtksctree.c
src/gtk/gtksctree.h
src/gtk/gtkutils.c
src/gtk/gtkutils.h
src/gtk/gtkvscrollbutton.c
src/gtk/menu.c
src/gtk/menu.h
src/gtk/quicksearch.c
src/plugins/dillo_viewer/dillo_viewer.c
src/plugins/pgpcore/select-keys.c
src/prefs_account.c
src/prefs_filtering_action.c
src/prefs_matcher.c

index b828d69836ef475e47c5693ee7ca8cf9469235a2..b6c67123463492ca2fcf1fb8b6990985d5d9eb56 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2008-08-05 [colin]     3.5.0cvs49
+
+       * src/prefs_account.c
+       * src/prefs_filtering_action.c
+       * src/prefs_matcher.c
+       * src/gtk/Makefile.am
+       * src/gtk/claws-marshal.list
+       * src/gtk/colorlabel.c
+       * src/gtk/colorsel.c
+       * src/gtk/foldersort.c
+       * src/gtk/gtkaspell.c
+       * src/gtk/gtkcmclist.c
+       * src/gtk/gtkcmclist.h
+       * src/gtk/gtkcmctree.c
+       * src/gtk/gtkcmctree.h
+       * src/gtk/gtkcmoptionmenu.c
+       * src/gtk/gtkcmoptionmenu.h
+       * src/gtk/gtksctree.c
+       * src/gtk/gtksctree.h
+       * src/gtk/gtkutils.c
+       * src/gtk/gtkutils.h
+       * src/gtk/gtkvscrollbutton.c
+       * src/gtk/menu.c
+       * src/gtk/menu.h
+       * src/gtk/quicksearch.c
+       * src/plugins/dillo_viewer/dillo_viewer.c
+       * src/plugins/pgpcore/select-keys.c
+               Try to finish yesterday's commit
+
 2008-08-04 [colin]     3.5.0cvs48
 
        * src/addressadd.c
index 73bdec977af049e8454afd9aeb3c73ec8bc5a4db..ae444cb3a51826140d322de80b043f52d9b00ae2 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.274.2.261 -r 1.274.2.262 src/mainwindow.c;  ) > 3.5.0cvs46.patchset
 ( cvs diff -u -r 1.382.2.462 -r 1.382.2.463 src/compose.c;  cvs diff -u -r 1.50.2.48 -r 1.50.2.49 src/compose.h;  cvs diff -u -r 1.19.2.27 -r 1.19.2.28 src/toolbar.h;  cvs diff -u -r 1.96.2.203 -r 1.96.2.204 src/textview.c;  cvs diff -u -r 1.25.2.58 -r 1.25.2.59 src/stock_pixmap.c;  cvs diff -u -r 1.5.2.21 -r 1.5.2.22 src/statusbar.c;  cvs diff -u -r 1.3.8.8 -r 1.3.8.9 src/noticeview.h;  cvs diff -u -r 1.20.2.25 -r 1.20.2.26 src/mimeview.h;  cvs diff -u -r 1.274.2.262 -r 1.274.2.263 src/mainwindow.c;  cvs diff -u -r 1.1.2.22 -r 1.1.2.23 src/image_viewer.c;  cvs diff -u -r 1.9.2.57 -r 1.9.2.58 src/gtk/gtkaspell.c;  cvs diff -u -r 1.5.2.13 -r 1.5.2.14 src/gtk/gtkvscrollbutton.c;  cvs diff -u -r 1.12.2.26 -r 1.12.2.27 src/plugins/dillo_viewer/dillo_viewer.c;  ) > 3.5.0cvs47.patchset
 ( cvs diff -u -r 1.9.2.23 -r 1.9.2.24 src/addressadd.c;  cvs diff -u -r 1.60.2.122 -r 1.60.2.123 src/addressbook.c;  cvs diff -u -r 1.1.2.11 -r 1.1.2.12 src/addressbook_foldersel.c;  cvs diff -u -r 1.5.2.10 -r 1.5.2.11 src/addressitem.h;  cvs diff -u -r 1.5.10.24 -r 1.5.10.25 src/addrgather.c;  cvs diff -u -r 1.2.4.20 -r 1.2.4.21 src/browseldap.c;  cvs diff -u -r 1.382.2.462 -r 1.382.2.463 src/compose.c;  cvs diff -u -r 1.50.2.48 -r 1.50.2.49 src/compose.h;  cvs diff -u -r 1.14.2.51 -r 1.14.2.52 src/editaddress.c;  cvs diff -u -r 1.1.2.6 -r 1.1.2.7 src/editaddress_other_attributes_ldap.c;  cvs diff -u -r 1.11.2.19 -r 1.11.2.20 src/editgroup.c;  cvs diff -u -r 1.10.2.13 -r 1.10.2.14 src/editldap_basedn.c;  cvs diff -u -r 1.207.2.204 -r 1.207.2.205 src/folderview.c;  cvs diff -u -r 1.20.2.23 -r 1.20.2.24 src/folderview.h;  cvs diff -u -r 1.14.2.20 -r 1.14.2.21 src/grouplistdialog.c;  cvs diff -u -r 1.1.2.22 -r 1.1.2.23 src/image_viewer.c;  cvs diff -u -r 1.1.2.60 -r 1.1.2.61 src/imap_gtk.c;  cvs diff -u -r 1.14.2.18 -r 1.14.2.19 src/importldif.c;  cvs diff -u -r 1.115.2.200 -r 1.115.2.201 src/main.c;  cvs diff -u -r 1.274.2.262 -r 1.274.2.263 src/mainwindow.c;  cvs diff -u -r 1.3.12.30 -r 1.3.12.31 src/message_search.c;  cvs diff -u -r 1.2.2.33 -r 1.2.2.34 src/mh_gtk.c;  cvs diff -u -r 1.83.2.138 -r 1.83.2.139 src/mimeview.c;  cvs diff -u -r 1.20.2.25 -r 1.20.2.26 src/mimeview.h;  cvs diff -u -r 1.2.2.28 -r 1.2.2.29 src/news_gtk.c;  cvs diff -u -r 1.3.8.8 -r 1.3.8.9 src/noticeview.h;  cvs diff -u -r 1.105.2.139 -r 1.105.2.140 src/prefs_account.c;  cvs diff -u -r 1.1.4.53 -r 1.1.4.54 src/prefs_filtering_action.c;  cvs diff -u -r 1.43.2.73 -r 1.43.2.74 src/prefs_matcher.c;  cvs diff -u -r 1.1.2.37 -r 1.1.2.38 src/prefs_msg_colors.c;  cvs diff -u -r 1.1.2.56 -r 1.1.2.57 src/prefs_summaries.c;  cvs diff -u -r 1.5.2.21 -r 1.5.2.22 src/statusbar.c;  cvs diff -u -r 1.25.2.58 -r 1.25.2.59 src/stock_pixmap.c;  cvs diff -u -r 1.15.2.54 -r 1.15.2.55 src/summary_search.c;  cvs diff -u -r 1.395.2.379 -r 1.395.2.380 src/summaryview.c;  cvs diff -u -r 1.68.2.48 -r 1.68.2.49 src/summaryview.h;  cvs diff -u -r 1.96.2.203 -r 1.96.2.204 src/textview.c;  cvs diff -u -r 1.19.2.27 -r 1.19.2.28 src/toolbar.h;  cvs diff -u -r 1.20.2.16 -r 1.20.2.17 src/gtk/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/gtk/claws-marshal.list;  cvs diff -u -r 1.1.4.11 -r 1.1.4.12 src/gtk/colorsel.c;  cvs diff -u -r 1.1.2.16 -r 1.1.2.17 src/gtk/foldersort.c;  cvs diff -u -r 1.9.2.57 -r 1.9.2.58 src/gtk/gtkaspell.c;  diff -u /dev/null src/gtk/gtkcmclist.c;  diff -u /dev/null src/gtk/gtkcmclist.h;  diff -u /dev/null src/gtk/gtkcmctree.c;  diff -u /dev/null src/gtk/gtkcmctree.h;  cvs diff -u -r 1.1.4.46 -r 1.1.4.47 src/gtk/gtksctree.c;  cvs diff -u -r 1.1.4.13 -r 1.1.4.14 src/gtk/gtksctree.h;  cvs diff -u -r 1.5.2.78 -r 1.5.2.79 src/gtk/gtkutils.c;  cvs diff -u -r 1.4.2.42 -r 1.4.2.43 src/gtk/gtkutils.h;  cvs diff -u -r 1.5.2.13 -r 1.5.2.14 src/gtk/gtkvscrollbutton.c;  cvs diff -u -r 1.5.2.34 -r 1.5.2.35 src/gtk/menu.c;  cvs diff -u -r 1.4.2.19 -r 1.4.2.20 src/gtk/menu.h;  cvs diff -u -r 1.1.2.83 -r 1.1.2.84 src/gtk/quicksearch.c;  cvs diff -u -r 1.12.2.26 -r 1.12.2.27 src/plugins/dillo_viewer/dillo_viewer.c;  cvs diff -u -r 1.1.2.20 -r 1.1.2.21 src/plugins/pgpcore/select-keys.c;  ) > 3.5.0cvs48.patchset
+( cvs diff -u -r 1.105.2.140 -r 1.105.2.141 src/prefs_account.c;  cvs diff -u -r 1.1.4.54 -r 1.1.4.55 src/prefs_filtering_action.c;  cvs diff -u -r 1.43.2.74 -r 1.43.2.75 src/prefs_matcher.c;  cvs diff -u -r 1.20.2.16 -r 1.20.2.17 src/gtk/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 src/gtk/claws-marshal.list;  cvs diff -u -r 1.2.2.21 -r 1.2.2.22 src/gtk/colorlabel.c;  cvs diff -u -r 1.1.4.11 -r 1.1.4.12 src/gtk/colorsel.c;  cvs diff -u -r 1.1.2.16 -r 1.1.2.17 src/gtk/foldersort.c;  cvs diff -u -r 1.9.2.57 -r 1.9.2.58 src/gtk/gtkaspell.c;  diff -u /dev/null src/gtk/gtkcmclist.c;  diff -u /dev/null src/gtk/gtkcmclist.h;  diff -u /dev/null src/gtk/gtkcmctree.c;  diff -u /dev/null src/gtk/gtkcmctree.h;  diff -u /dev/null src/gtk/gtkcmoptionmenu.c;  diff -u /dev/null src/gtk/gtkcmoptionmenu.h;  cvs diff -u -r 1.1.4.46 -r 1.1.4.47 src/gtk/gtksctree.c;  cvs diff -u -r 1.1.4.13 -r 1.1.4.14 src/gtk/gtksctree.h;  cvs diff -u -r 1.5.2.78 -r 1.5.2.79 src/gtk/gtkutils.c;  cvs diff -u -r 1.4.2.42 -r 1.4.2.43 src/gtk/gtkutils.h;  cvs diff -u -r 1.5.2.13 -r 1.5.2.14 src/gtk/gtkvscrollbutton.c;  cvs diff -u -r 1.5.2.34 -r 1.5.2.35 src/gtk/menu.c;  cvs diff -u -r 1.4.2.19 -r 1.4.2.20 src/gtk/menu.h;  cvs diff -u -r 1.1.2.83 -r 1.1.2.84 src/gtk/quicksearch.c;  cvs diff -u -r 1.12.2.26 -r 1.12.2.27 src/plugins/dillo_viewer/dillo_viewer.c;  cvs diff -u -r 1.1.2.20 -r 1.1.2.21 src/plugins/pgpcore/select-keys.c;  ) > 3.5.0cvs49.patchset
index f544ef15ec205f968823283c135ef091104b37aa..919943c065859d7ee39f8832e14d997083a1a1c2 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=5
 MICRO_VERSION=0
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=48
+EXTRA_VERSION=49
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
@@ -142,11 +142,19 @@ then
 fi
 
 CFLAGS="$CFLAGS -Wall"
+<<<<<<< configure.ac
+
+if test $USE_MAINTAINER_MODE = yes; then
+       CFLAGS="$CFLAGS -DGTK_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED"
+fi
+
+=======
 
 if test $USE_MAINTAINER_MODE = yes; then
        CFLAGS="$CFLAGS -DGTK_DISABLE_DEPRECATED"
 fi
 
+>>>>>>> 1.654.2.3521
 pthread_name=
 case "$target" in
 *-darwin*)
index a35dc997adc66276efabea27c5239e5f567d3695..dc14e2d12f8eee98b8a10587453bcb7a629a99dd 100644 (file)
@@ -15,7 +15,9 @@ libclawsgtk_la_SOURCES = \
        filesel.c \
        foldersort.c \
        gtkaspell.c \
-       gtksctree.c \
+       gtkcmctree.c \
+       gtkcmclist.c \
+       gtkcmoptionmenu.c \
        gtkshruler.c \
        gtksctree.c \
        gtksourceprintjob.c \
@@ -44,9 +46,11 @@ clawsgtkinclude_HEADERS = \
        filesel.h \
        foldersort.h \
        gtkaspell.h \
+       gtkcmctree.h \
+       gtkcmclist.h \
+       gtkcmoptionmenu.h \
        gtksctree.h \
        gtkshruler.h \
-       gtksctree.h \
        gtksourceprintjob.h \
        gtkutils.h \
        gtkvscrollbutton.h \
index 7e722df0e51ca8f20520ae67d01c84bd6b0cf424..8db25d4b006167d0c13c0e630dcf5e3c0efe28fb 100644 (file)
@@ -1,2 +1,13 @@
 NONE:POINTER
 NONE:INT,POINTER
+NONE:OBJECT,OBJECT
+NONE:INT,INT,BOXED
+NONE:INT,INT
+NONE:INT
+NONE:VOID
+NONE:VOID,VOID
+NONE:ENUM,FLOAT,BOOLEAN
+NONE:ENUM,FLOAT
+NONE:POINTER,INT
+NONE:POINTER,POINTER,POINTER
+NONE:ENUM
index 58a8509c7b3f32c63fce68a594fce3184ae14fe6..df6ec8a405c040d8904b3e7ecaa744eb0dc4e386 100644 (file)
@@ -218,7 +218,7 @@ static gboolean colorlabel_drawing_area_expose_event_cb
                           TRUE, 1, 1, widget->allocation.width - 2,
                           widget->allocation.height - 2);
 
-       gdk_gc_unref(gc);                          
+       g_object_unref(gc);                        
        
        return FALSE;
 }
index 9eed27103ccf6ca18bc6a2f723dba5819e7b3ac0..1b52fa7ac21d2d187a5bb734a0de759ddec208d9 100644 (file)
@@ -17,6 +17,7 @@
  * 
  */
 
+#undef GTK_DISABLE_DEPRECATED /* FIXME set_color */
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
 
index b2cd3088c394da59c88e0597573ede626932086f..e6afabb5be38a00084e89603bbf87e2cc9547767 100644 (file)
@@ -53,7 +53,7 @@ static void ok_clicked(GtkWidget *widget, FolderSortDialog *dialog)
        int i;
 
        for (i = 0; i < dialog->rows; i++) {
-               folder = gtk_clist_get_row_data(GTK_CLIST(dialog->folderlist), i);
+               folder = gtk_cmclist_get_row_data(GTK_CMCLIST(dialog->folderlist), i);
 
                folder_set_sort(folder, dialog->rows - i);
        }
@@ -83,27 +83,27 @@ static void moveup_clicked(GtkWidget *widget, FolderSortDialog *dialog)
 {
        g_return_if_fail(dialog->selected > 0);
 
-       gtk_clist_swap_rows(GTK_CLIST(dialog->folderlist), dialog->selected, dialog->selected - 1);
+       gtk_cmclist_swap_rows(GTK_CMCLIST(dialog->folderlist), dialog->selected, dialog->selected - 1);
 }
 
 static void movedown_clicked(GtkWidget *widget, FolderSortDialog *dialog)
 {
        g_return_if_fail(dialog->selected < (dialog->rows - 1));
 
-       gtk_clist_swap_rows(GTK_CLIST(dialog->folderlist), dialog->selected, dialog->selected + 1);
+       gtk_cmclist_swap_rows(GTK_CMCLIST(dialog->folderlist), dialog->selected, dialog->selected + 1);
 }
 
-static void row_selected(GtkCList *clist, gint row, gint column, GdkEventButton *event, FolderSortDialog *dialog)
+static void row_selected(GtkCMCList *clist, gint row, gint column, GdkEventButton *event, FolderSortDialog *dialog)
 {
        set_selected(dialog, row);
 }
 
-static void row_unselected(GtkCList *clist, gint row, gint column, GdkEventButton *event, FolderSortDialog *dialog)
+static void row_unselected(GtkCMCList *clist, gint row, gint column, GdkEventButton *event, FolderSortDialog *dialog)
 {
        set_selected(dialog, -1);
 }
 
-static void row_moved(GtkCList *clist, gint srcpos, gint destpos, FolderSortDialog *dialog)
+static void row_moved(GtkCMCList *clist, gint srcpos, gint destpos, FolderSortDialog *dialog)
 {
        if (dialog->selected == -1)
                return;
@@ -207,15 +207,15 @@ void foldersort_open()
                                       GTK_POLICY_AUTOMATIC,
                                       GTK_POLICY_AUTOMATIC);
 
-       folderlist = gtk_clist_new(1);
+       folderlist = gtk_cmclist_new(1);
        gtk_widget_show(folderlist);
        gtk_container_add(GTK_CONTAINER(scrolledwindow1), folderlist);
-       gtk_clist_set_column_width(GTK_CLIST(folderlist), 0, 80);
-       gtk_clist_column_titles_show(GTK_CLIST(folderlist));
+       gtk_cmclist_set_column_width(GTK_CMCLIST(folderlist), 0, 80);
+       gtk_cmclist_column_titles_show(GTK_CMCLIST(folderlist));
 
        label2 = gtk_label_new(_("Folders"));
        gtk_widget_show(label2);
-       gtk_clist_set_column_widget(GTK_CLIST(folderlist), 0, label2);
+       gtk_cmclist_set_column_widget(GTK_CMCLIST(folderlist), 0, label2);
        gtk_label_set_justify(GTK_LABEL(label2), GTK_JUSTIFY_LEFT);
        gtk_misc_set_alignment(GTK_MISC(label2), 0, 0.5);
 
@@ -239,7 +239,7 @@ void foldersort_open()
        gtk_widget_show(window);
        gtk_widget_set_sensitive(moveup_btn, FALSE);
        gtk_widget_set_sensitive(movedown_btn, FALSE);
-       gtk_clist_set_reorderable(GTK_CLIST(folderlist), TRUE);
+       gtk_cmclist_set_reorderable(GTK_CMCLIST(folderlist), TRUE);
 
        g_signal_connect(G_OBJECT(moveup_btn), "clicked",
                          G_CALLBACK(moveup_clicked), dialog);
@@ -261,8 +261,8 @@ void foldersort_open()
                gchar *text[1];
 
                text[0] = folder->name;
-               row = gtk_clist_append(GTK_CLIST(folderlist), text);
-               gtk_clist_set_row_data(GTK_CLIST(folderlist), row, folder);
+               row = gtk_cmclist_append(GTK_CMCLIST(folderlist), text);
+               gtk_cmclist_set_row_data(GTK_CMCLIST(folderlist), row, folder);
                dialog->rows++;
        }
 
index 9e707a1267e7a8bd93c8edbd155250bd1e5c976f..4fc3c202775d839635130880ed3c10268c9485ce 100644 (file)
@@ -1536,7 +1536,7 @@ static void replace_with_create_dialog_cb(GtkWidget *w, gpointer data)
        gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
        gtk_window_set_title(GTK_WINDOW(dialog),_("Replace unknown word"));
        gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
-       gtk_widget_set_uposition(dialog, xx, yy);
+       gtk_window_move(GTK_WINDOW(dialog), xx, yy);
 
        g_signal_connect_swapped(G_OBJECT(dialog), "destroy",
                                 G_CALLBACK(gtk_widget_destroy), 
@@ -2274,18 +2274,14 @@ static void set_menu_pos(GtkMenu *menu, gint *x, gint *y,
        wx =  r.width;
        wy =  r.height;
 
-       *x = rect.x + xx +
-            gdk_char_width(gtk_style_get_font(GTK_WIDGET(text)->style), ' ');
+       *x = rect.x + xx + 8;
 
        *y = rect.y + rect.height + yy;
 
        if (*x + wx > sx)
                *x = sx - wx;
        if (*y + wy > sy)
-               *y = *y - wy -
-                    gdk_string_height(gtk_style_get_font(
-                                               GTK_WIDGET(text)->style),
-                                      gtkaspell->theword);
+               *y = *y - wy - 10;
 }
 
 /* change the current dictionary of gtkaspell
diff --git a/src/gtk/gtkcmclist.c b/src/gtk/gtkcmclist.c
new file mode 100644 (file)
index 0000000..f5dd23b
--- /dev/null
@@ -0,0 +1,7842 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald, 
+ * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>  
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include "claws-marshal.h"
+#include "gtkcmclist.h"
+#include <gdk/gdkkeysyms.h>
+
+/* length of button_actions array */
+#define MAX_BUTTON 5
+
+/* the width of the column resize windows */
+#define DRAG_WIDTH  6
+
+/* minimum allowed width of a column */
+#define COLUMN_MIN_WIDTH 5
+
+/* this defigns the base grid spacing */
+#define CELL_SPACING 1
+
+/* added the horizontal space at the beginning and end of a row*/
+#define COLUMN_INSET 3
+
+/* used for auto-scrolling */
+#define SCROLL_TIME  100
+
+/* gives the top pixel of the given row in context of
+ * the clist's voffset */
+#define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
+                                   (((row) + 1) * CELL_SPACING) + \
+                                   (clist)->voffset)
+
+/* returns the row index from a y pixel location in the 
+ * context of the clist's voffset */
+#define ROW_FROM_YPIXEL(clist, y)  (((y) - (clist)->voffset) / \
+                                   ((clist)->row_height + CELL_SPACING))
+
+/* gives the left pixel of the given column in context of
+ * the clist's hoffset */
+#define COLUMN_LEFT_XPIXEL(clist, colnum)  ((clist)->column[(colnum)].area.x + \
+                                           (clist)->hoffset)
+
+/* returns the column index from a x pixel location in the 
+ * context of the clist's hoffset */
+static inline gint
+COLUMN_FROM_XPIXEL (GtkCMCList * clist,
+                   gint x)
+{
+  gint i, cx;
+
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].visible)
+      {
+       cx = clist->column[i].area.x + clist->hoffset;
+
+       if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
+           x <= (cx + clist->column[i].area.width + COLUMN_INSET))
+         return i;
+      }
+
+  /* no match */
+  return -1;
+}
+
+/* returns the top pixel of the given row in the context of
+ * the list height */
+#define ROW_TOP(clist, row)        (((clist)->row_height + CELL_SPACING) * (row))
+
+/* returns the left pixel of the given column in the context of
+ * the list width */
+#define COLUMN_LEFT(clist, colnum) ((clist)->column[(colnum)].area.x)
+
+/* returns the total height of the list */
+#define LIST_HEIGHT(clist)         (((clist)->row_height * ((clist)->rows)) + \
+                                   (CELL_SPACING * ((clist)->rows + 1)))
+
+
+/* returns the total width of the list */
+static inline gint
+LIST_WIDTH (GtkCMCList * clist) 
+{
+  gint last_column;
+
+  for (last_column = clist->columns - 1;
+       last_column >= 0 && !clist->column[last_column].visible; last_column--);
+
+  if (last_column >= 0)
+    return (clist->column[last_column].area.x +
+           clist->column[last_column].area.width +
+           COLUMN_INSET + CELL_SPACING);
+  return 0;
+}
+
+/* returns the GList item for the nth row */
+#define        ROW_ELEMENT(clist, row) (((row) == (clist)->rows - 1) ? \
+                                (clist)->row_list_end : \
+                                g_list_nth ((clist)->row_list, (row)))
+
+
+/* redraw the list if it's not frozen */
+#define CLIST_UNFROZEN(clist)     (((GtkCMCList*) (clist))->freeze_count == 0)
+#define        CLIST_REFRESH(clist)    G_STMT_START { \
+  if (CLIST_UNFROZEN (clist)) \
+    GTK_CMCLIST_GET_CLASS (clist)->refresh ((GtkCMCList*) (clist)); \
+} G_STMT_END
+
+
+/* Signals */
+enum {
+  SELECT_ROW,
+  UNSELECT_ROW,
+  ROW_MOVE,
+  CLICK_COLUMN,
+  RESIZE_COLUMN,
+  TOGGLE_FOCUS_ROW,
+  SELECT_ALL,
+  UNSELECT_ALL,
+  UNDO_SELECTION,
+  START_SELECTION,
+  END_SELECTION,
+  TOGGLE_ADD_MODE,
+  EXTEND_SELECTION,
+  SCROLL_VERTICAL,
+  SCROLL_HORIZONTAL,
+  ABORT_COLUMN_RESIZE,
+  LAST_SIGNAL
+};
+
+enum {
+  SYNC_REMOVE,
+  SYNC_INSERT
+};
+
+enum {
+  ARG_0,
+  ARG_N_COLUMNS,
+  ARG_SHADOW_TYPE,
+  ARG_SELECTION_MODE,
+  ARG_ROW_HEIGHT,
+  ARG_TITLES_ACTIVE,
+  ARG_REORDERABLE,
+  ARG_USE_DRAG_ICONS,
+  ARG_SORT_TYPE
+};
+
+/* GtkCMCList Methods */
+static void     gtk_cmclist_class_init  (GtkCMCListClass         *klass);
+static void     gtk_cmclist_init        (GtkCMCList              *clist);
+static GObject* gtk_cmclist_constructor (GType                  type,
+                                      guint                  n_construct_properties,
+                                      GObjectConstructParam *construct_params);
+
+/* GtkObject Methods */
+static void gtk_cmclist_destroy  (GtkObject *object);
+static void gtk_cmclist_finalize (GObject   *object);
+static void gtk_cmclist_set_arg  (GObject *object,
+                               guint      arg_id,
+                               const GValue *value,
+                               GParamSpec *spec);
+static void gtk_cmclist_get_arg  (GObject *object,
+                               guint      arg_id,
+                               GValue *value,
+                               GParamSpec *spec);
+
+/* GtkWidget Methods */
+static void gtk_cmclist_set_scroll_adjustments (GtkCMCList      *clist,
+                                             GtkAdjustment *hadjustment,
+                                             GtkAdjustment *vadjustment);
+static void gtk_cmclist_realize         (GtkWidget        *widget);
+static void gtk_cmclist_unrealize       (GtkWidget        *widget);
+static void gtk_cmclist_map             (GtkWidget        *widget);
+static void gtk_cmclist_unmap           (GtkWidget        *widget);
+static gint gtk_cmclist_expose          (GtkWidget        *widget,
+                                      GdkEventExpose   *event);
+static gint gtk_cmclist_button_press    (GtkWidget        *widget,
+                                      GdkEventButton   *event);
+static gint gtk_cmclist_button_release  (GtkWidget        *widget,
+                                      GdkEventButton   *event);
+static gint gtk_cmclist_motion          (GtkWidget        *widget, 
+                                      GdkEventMotion   *event);
+static void gtk_cmclist_size_request    (GtkWidget        *widget,
+                                      GtkRequisition   *requisition);
+static void gtk_cmclist_size_allocate   (GtkWidget        *widget,
+                                      GtkAllocation    *allocation);
+static void gtk_cmclist_draw_focus      (GtkWidget        *widget);
+static gint gtk_cmclist_focus_in        (GtkWidget        *widget,
+                                      GdkEventFocus    *event);
+static gint gtk_cmclist_focus_out       (GtkWidget        *widget,
+                                      GdkEventFocus    *event);
+static gint gtk_cmclist_focus           (GtkWidget        *widget,
+                                      GtkDirectionType  direction);
+static void gtk_cmclist_set_focus_child (GtkContainer     *container,
+                                      GtkWidget        *child);
+static void gtk_cmclist_style_set       (GtkWidget        *widget,
+                                      GtkStyle         *previous_style);
+static void gtk_cmclist_drag_begin      (GtkWidget        *widget,
+                                      GdkDragContext   *context);
+static gint gtk_cmclist_drag_motion     (GtkWidget        *widget,
+                                      GdkDragContext   *context,
+                                      gint              x,
+                                      gint              y,
+                                      guint             time);
+static void gtk_cmclist_drag_leave      (GtkWidget        *widget,
+                                      GdkDragContext   *context,
+                                      guint             time);
+static void gtk_cmclist_drag_end        (GtkWidget        *widget,
+                                      GdkDragContext   *context);
+static gboolean gtk_cmclist_drag_drop   (GtkWidget      *widget,
+                                      GdkDragContext *context,
+                                      gint            x,
+                                      gint            y,
+                                      guint           time);
+static void gtk_cmclist_drag_data_get   (GtkWidget        *widget,
+                                      GdkDragContext   *context,
+                                      GtkSelectionData *selection_data,
+                                      guint             info,
+                                      guint             time);
+static void gtk_cmclist_drag_data_received (GtkWidget        *widget,
+                                         GdkDragContext   *context,
+                                         gint              x,
+                                         gint              y,
+                                         GtkSelectionData *selection_data,
+                                         guint             info,
+                                         guint             time);
+
+/* GtkContainer Methods */
+static void gtk_cmclist_forall          (GtkContainer  *container,
+                                      gboolean       include_internals,
+                                      GtkCallback    callback,
+                                      gpointer       callback_data);
+
+/* Selection */
+static void toggle_row                (GtkCMCList      *clist,
+                                      gint           row,
+                                      gint           column,
+                                      GdkEvent      *event);
+static void real_select_row           (GtkCMCList      *clist,
+                                      gint           row,
+                                      gint           column,
+                                      GdkEvent      *event);
+static void real_unselect_row         (GtkCMCList      *clist,
+                                      gint           row,
+                                      gint           column,
+                                      GdkEvent      *event);
+static void update_extended_selection (GtkCMCList      *clist,
+                                      gint           row);
+static GList *selection_find          (GtkCMCList      *clist,
+                                      gint           row_number,
+                                      GList         *row_list_element);
+static void real_select_all           (GtkCMCList      *clist);
+static void real_unselect_all         (GtkCMCList      *clist);
+static void move_vertical             (GtkCMCList      *clist,
+                                      gint           row,
+                                      gfloat         align);
+static void move_horizontal           (GtkCMCList      *clist,
+                                      gint           diff);
+static void real_undo_selection       (GtkCMCList      *clist);
+static void fake_unselect_all         (GtkCMCList      *clist,
+                                      gint           row);
+static void fake_toggle_row           (GtkCMCList      *clist,
+                                      gint           row);
+static void resync_selection          (GtkCMCList      *clist,
+                                      GdkEvent      *event);
+static void sync_selection            (GtkCMCList      *clist,
+                                      gint           row,
+                                       gint           mode);
+static void set_anchor                (GtkCMCList      *clist,
+                                      gboolean       add_mode,
+                                      gint           anchor,
+                                      gint           undo_anchor);
+static void start_selection           (GtkCMCList      *clist);
+static void end_selection             (GtkCMCList      *clist);
+static void toggle_add_mode           (GtkCMCList      *clist);
+static void toggle_focus_row          (GtkCMCList      *clist);
+static void extend_selection          (GtkCMCList      *clist,
+                                      GtkScrollType  scroll_type,
+                                      gfloat         position,
+                                      gboolean       auto_start_selection);
+static gint get_selection_info        (GtkCMCList       *clist,
+                                      gint            x,
+                                      gint            y,
+                                      gint           *row,
+                                      gint           *column);
+
+/* Scrolling */
+static void move_focus_row     (GtkCMCList      *clist,
+                               GtkScrollType  scroll_type,
+                               gfloat         position);
+static void scroll_horizontal  (GtkCMCList      *clist,
+                               GtkScrollType  scroll_type,
+                               gfloat         position);
+static void scroll_vertical    (GtkCMCList      *clist,
+                               GtkScrollType  scroll_type,
+                               gfloat         position);
+static void move_horizontal    (GtkCMCList      *clist,
+                               gint           diff);
+static void move_vertical      (GtkCMCList      *clist,
+                               gint           row,
+                               gfloat         align);
+static gint horizontal_timeout (GtkCMCList      *clist);
+static gint vertical_timeout   (GtkCMCList      *clist);
+static void remove_grab        (GtkCMCList      *clist);
+
+
+/* Resize Columns */
+static void draw_xor_line             (GtkCMCList       *clist);
+static gint new_column_width          (GtkCMCList       *clist,
+                                      gint            column,
+                                      gint           *x);
+static void column_auto_resize        (GtkCMCList       *clist,
+                                      GtkCMCListRow    *clist_row,
+                                      gint            column,
+                                      gint            old_width);
+static void real_resize_column        (GtkCMCList       *clist,
+                                      gint            column,
+                                      gint            width);
+static void abort_column_resize       (GtkCMCList       *clist);
+static void cell_size_request         (GtkCMCList       *clist,
+                                      GtkCMCListRow    *clist_row,
+                                      gint            column,
+                                      GtkRequisition *requisition);
+
+/* Buttons */
+static void column_button_create      (GtkCMCList       *clist,
+                                      gint            column);
+static void column_button_clicked     (GtkWidget      *widget,
+                                      gpointer        data);
+
+/* Adjustments */
+static void adjust_adjustments        (GtkCMCList       *clist,
+                                      gboolean        block_resize);
+static void vadjustment_changed       (GtkAdjustment  *adjustment,
+                                      gpointer        data);
+static void vadjustment_value_changed (GtkAdjustment  *adjustment,
+                                      gpointer        data);
+static void hadjustment_changed       (GtkAdjustment  *adjustment,
+                                      gpointer        data);
+static void hadjustment_value_changed (GtkAdjustment  *adjustment,
+                                      gpointer        data);
+
+/* Drawing */
+static void get_cell_style   (GtkCMCList      *clist,
+                             GtkCMCListRow   *clist_row,
+                             gint           state,
+                             gint           column,
+                             GtkStyle     **style,
+                             GdkGC        **fg_gc,
+                             GdkGC        **bg_gc);
+static gint draw_cell_pixmap (GdkWindow     *window,
+                             GdkRectangle  *clip_rectangle,
+                             GdkGC         *fg_gc,
+                             GdkPixmap     *pixmap,
+                             GdkBitmap     *mask,
+                             gint           x,
+                             gint           y,
+                             gint           width,
+                             gint           height);
+static void draw_row         (GtkCMCList      *clist,
+                             GdkRectangle  *area,
+                             gint           row,
+                             GtkCMCListRow   *clist_row);
+static void draw_rows        (GtkCMCList      *clist,
+                             GdkRectangle  *area);
+static void clist_refresh    (GtkCMCList      *clist);
+static void draw_drag_highlight (GtkCMCList        *clist,
+                                GtkCMCListRow     *dest_row,
+                                gint             dest_row_number,
+                                GtkCMCListDragPos  drag_pos);
+     
+/* Size Allocation / Requisition */
+static void size_allocate_title_buttons (GtkCMCList *clist);
+static void size_allocate_columns       (GtkCMCList *clist,
+                                        gboolean  block_resize);
+static gint list_requisition_width      (GtkCMCList *clist);
+
+/* Memory Allocation/Distruction Routines */
+static GtkCMCListColumn *columns_new (GtkCMCList      *clist);
+static void column_title_new       (GtkCMCList      *clist,
+                                   gint           column,
+                                   const gchar   *title);
+static void columns_delete         (GtkCMCList      *clist);
+static GtkCMCListRow *row_new        (GtkCMCList      *clist);
+static void row_delete             (GtkCMCList      *clist,
+                                   GtkCMCListRow   *clist_row);
+static void set_cell_contents      (GtkCMCList      *clist,
+                                   GtkCMCListRow   *clist_row,
+                                   gint           column,
+                                   GtkCMCellType    type,
+                                   const gchar   *text,
+                                   guint8         spacing,
+                                   GdkPixmap     *pixmap,
+                                   GdkBitmap     *mask);
+static gint real_insert_row        (GtkCMCList      *clist,
+                                   gint           row,
+                                   gchar         *text[]);
+static void real_remove_row        (GtkCMCList      *clist,
+                                   gint           row);
+static void real_clear             (GtkCMCList      *clist);
+
+/* Sorting */
+static gint default_compare        (GtkCMCList      *clist,
+                                   gconstpointer  row1,
+                                   gconstpointer  row2);
+static void real_sort_list         (GtkCMCList      *clist);
+static GList *gtk_cmclist_merge      (GtkCMCList      *clist,
+                                   GList         *a,
+                                   GList         *b);
+static GList *gtk_cmclist_mergesort  (GtkCMCList      *clist,
+                                   GList         *list,
+                                   gint           num);
+/* Misc */
+static gboolean title_focus_in   (GtkCMCList *clist,
+                                 gint      dir);
+static gboolean title_focus_move (GtkCMCList *clist,
+                                 gint      dir);
+
+static void real_row_move             (GtkCMCList  *clist,
+                                      gint       source_row,
+                                      gint       dest_row);
+static gint column_title_passive_func (GtkWidget *widget, 
+                                      GdkEvent  *event,
+                                      gpointer   data);
+static void drag_dest_cell            (GtkCMCList         *clist,
+                                      gint              x,
+                                      gint              y,
+                                      GtkCMCListDestInfo *dest_info);
+
+
+
+static GtkContainerClass *parent_class = NULL;
+static guint clist_signals[LAST_SIGNAL] = {0};
+
+static const GtkTargetEntry clist_target_table = { "gtk-clist-drag-reorder", 0, 0};
+
+GType
+gtk_cmclist_get_type (void)
+{
+  static GType clist_type = 0;
+
+  if (!clist_type)
+    {
+      static const GTypeInfo clist_info =
+      {
+                       sizeof (GtkCMCListClass),
+
+                       (GBaseInitFunc) NULL,
+                       (GBaseFinalizeFunc) NULL,
+
+                       (GClassInitFunc) gtk_cmclist_class_init,
+                       (GClassFinalizeFunc) NULL,
+                       NULL,   /* class_data */
+
+                       sizeof (GtkCMCList),
+                       0,      /* n_preallocs */
+                       (GInstanceInitFunc) gtk_cmclist_init,
+       };
+       clist_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkCMCList", &clist_info, (GTypeFlags)0);
+    }
+
+  return clist_type;
+}
+
+static void
+gtk_cmclist_class_init (GtkCMCListClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkObjectClass *gtk_object_class;
+  GtkWidgetClass *widget_class;
+  GtkContainerClass *container_class;
+  GtkBindingSet *binding_set;
+
+  object_class->constructor = gtk_cmclist_constructor;
+
+  gtk_object_class = (GtkObjectClass *) klass;
+  widget_class = (GtkWidgetClass *) klass;
+  container_class = (GtkContainerClass *) klass;
+
+  parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
+
+  object_class->finalize = gtk_cmclist_finalize;
+  gtk_object_class->destroy = gtk_cmclist_destroy;
+  object_class->set_property = gtk_cmclist_set_arg;
+  object_class->get_property = gtk_cmclist_get_arg;
+  
+
+  widget_class->realize = gtk_cmclist_realize;
+  widget_class->unrealize = gtk_cmclist_unrealize;
+  widget_class->map = gtk_cmclist_map;
+  widget_class->unmap = gtk_cmclist_unmap;
+  widget_class->button_press_event = gtk_cmclist_button_press;
+  widget_class->button_release_event = gtk_cmclist_button_release;
+  widget_class->motion_notify_event = gtk_cmclist_motion;
+  widget_class->expose_event = gtk_cmclist_expose;
+  widget_class->size_request = gtk_cmclist_size_request;
+  widget_class->size_allocate = gtk_cmclist_size_allocate;
+  widget_class->focus_in_event = gtk_cmclist_focus_in;
+  widget_class->focus_out_event = gtk_cmclist_focus_out;
+  widget_class->style_set = gtk_cmclist_style_set;
+  widget_class->drag_begin = gtk_cmclist_drag_begin;
+  widget_class->drag_end = gtk_cmclist_drag_end;
+  widget_class->drag_motion = gtk_cmclist_drag_motion;
+  widget_class->drag_leave = gtk_cmclist_drag_leave;
+  widget_class->drag_drop = gtk_cmclist_drag_drop;
+  widget_class->drag_data_get = gtk_cmclist_drag_data_get;
+  widget_class->drag_data_received = gtk_cmclist_drag_data_received;
+  widget_class->focus = gtk_cmclist_focus;
+  
+  /* container_class->add = NULL; use the default GtkContainerClass warning */
+  /* container_class->remove=NULL; use the default GtkContainerClass warning */
+
+  container_class->forall = gtk_cmclist_forall;
+  container_class->set_focus_child = gtk_cmclist_set_focus_child;
+
+  klass->set_scroll_adjustments = gtk_cmclist_set_scroll_adjustments;
+  klass->refresh = clist_refresh;
+  klass->select_row = real_select_row;
+  klass->unselect_row = real_unselect_row;
+  klass->row_move = real_row_move;
+  klass->undo_selection = real_undo_selection;
+  klass->resync_selection = resync_selection;
+  klass->selection_find = selection_find;
+  klass->click_column = NULL;
+  klass->resize_column = real_resize_column;
+  klass->draw_row = draw_row;
+  klass->draw_drag_highlight = draw_drag_highlight;
+  klass->insert_row = real_insert_row;
+  klass->remove_row = real_remove_row;
+  klass->clear = real_clear;
+  klass->sort_list = real_sort_list;
+  klass->select_all = real_select_all;
+  klass->unselect_all = real_unselect_all;
+  klass->fake_unselect_all = fake_unselect_all;
+  klass->scroll_horizontal = scroll_horizontal;
+  klass->scroll_vertical = scroll_vertical;
+  klass->extend_selection = extend_selection;
+  klass->toggle_focus_row = toggle_focus_row;
+  klass->toggle_add_mode = toggle_add_mode;
+  klass->start_selection = start_selection;
+  klass->end_selection = end_selection;
+  klass->abort_column_resize = abort_column_resize;
+  klass->set_cell_contents = set_cell_contents;
+  klass->cell_size_request = cell_size_request;
+
+  g_object_class_install_property (object_class,
+                               ARG_N_COLUMNS,
+                               g_param_spec_uint ("n-columns",
+                               "N-Columns",
+                               "N-Columns",
+                               1,
+                               G_MAXINT,
+                               1,
+                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class,
+                               ARG_SHADOW_TYPE,
+                               g_param_spec_enum ("shadow-type",
+                               "shadow-type",
+                               "shadow-type",
+                               GTK_TYPE_SHADOW_TYPE, 0,
+                               G_PARAM_READWRITE));
+  g_object_class_install_property (object_class,
+                               ARG_SELECTION_MODE,
+                               g_param_spec_enum ("selection-mode",
+                               "selection-mode",
+                               "selection-mode",
+                               GTK_TYPE_SELECTION_MODE, 0,
+                               G_PARAM_READWRITE));
+  g_object_class_install_property (object_class,
+                               ARG_ROW_HEIGHT,
+                               g_param_spec_uint ("row-height",
+                               "row-height",
+                               "row-height",
+                               0,
+                               G_MAXINT,
+                               0,
+                               G_PARAM_READWRITE));
+  g_object_class_install_property (object_class,
+                               ARG_REORDERABLE,
+                               g_param_spec_boolean ("reorderable",
+                               "reorderable",
+                               "reorderable",
+                               TRUE,
+                               G_PARAM_READWRITE));
+  g_object_class_install_property (object_class,
+                               ARG_TITLES_ACTIVE,
+                               g_param_spec_boolean ("titles-active",
+                               "titles-active",
+                               "titles-active",
+                               TRUE,
+                               G_PARAM_READWRITE));
+  g_object_class_install_property (object_class,
+                               ARG_USE_DRAG_ICONS,
+                               g_param_spec_boolean ("use-drag-icons",
+                               "use-drag-icons",
+                               "use-drag-icons",
+                               TRUE,
+                               G_PARAM_READWRITE));
+  g_object_class_install_property (object_class,
+                               ARG_SORT_TYPE,
+                               g_param_spec_enum ("sort-type",
+                               "sort-type",
+                               "sort-type",
+                               GTK_TYPE_SORT_TYPE, 0,
+                               G_PARAM_READWRITE));
+  widget_class->set_scroll_adjustments_signal =
+               g_signal_new ("set_scroll_adjustments",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GtkCMCListClass, set_scroll_adjustments),
+                             NULL, NULL,
+                             claws_marshal_VOID__OBJECT_OBJECT,
+                             G_TYPE_NONE, 2,
+                             GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
+
+  clist_signals[SELECT_ROW] =
+               g_signal_new ("select_row",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (GtkCMCListClass, select_row),
+                             NULL, NULL,
+                             claws_marshal_VOID__INT_INT_BOXED,
+                             G_TYPE_NONE, 3,
+                             G_TYPE_INT,
+                             G_TYPE_INT,
+                             GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+  clist_signals[UNSELECT_ROW] =
+               g_signal_new ("unselect_row",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (GtkCMCListClass, unselect_row),
+                             NULL, NULL,
+                             claws_marshal_VOID__INT_INT_BOXED,
+                             G_TYPE_NONE, 3,
+                             G_TYPE_INT,
+                             G_TYPE_INT,
+                             GDK_TYPE_EVENT);
+  clist_signals[ROW_MOVE] =
+               g_signal_new ("row_move",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GtkCMCListClass, row_move),
+                             NULL, NULL,
+                             claws_marshal_VOID__INT_INT,
+                             G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+  clist_signals[CLICK_COLUMN] =
+               g_signal_new ("click_column",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (GtkCMCListClass, click_column),
+                             NULL, NULL,
+                             claws_marshal_VOID__INT,
+                             G_TYPE_NONE, 1, G_TYPE_INT);
+  clist_signals[RESIZE_COLUMN] =
+               g_signal_new ("resize_column",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GtkCMCListClass, resize_column),
+                             NULL, NULL,
+                             claws_marshal_VOID__INT_INT,
+                             G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+
+  clist_signals[TOGGLE_FOCUS_ROW] =
+               g_signal_new ("toggle_focus_row",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (GtkCMCListClass, toggle_focus_row),
+                             NULL, NULL,
+                             claws_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+  clist_signals[SELECT_ALL] =
+               g_signal_new ("select_all",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (GtkCMCListClass, select_all),
+                             NULL, NULL,
+                             claws_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+  clist_signals[UNSELECT_ALL] =
+               g_signal_new ("unselect_all",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (GtkCMCListClass, unselect_all),
+                             NULL, NULL,
+                             claws_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+  clist_signals[UNDO_SELECTION] =
+               g_signal_new ("undo_selection",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (GtkCMCListClass, undo_selection),
+                             NULL, NULL,
+                             claws_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+  clist_signals[START_SELECTION] =
+               g_signal_new ("start_selection",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (GtkCMCListClass, start_selection),
+                             NULL, NULL,
+                             claws_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+  clist_signals[END_SELECTION] =
+               g_signal_new ("end_selection",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (GtkCMCListClass, end_selection),
+                             NULL, NULL,
+                             claws_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+  clist_signals[TOGGLE_ADD_MODE] =
+               g_signal_new ("toggle_add_mode",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (GtkCMCListClass, toggle_add_mode),
+                             NULL, NULL,
+                             claws_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+  clist_signals[EXTEND_SELECTION] =
+               g_signal_new ("extend_selection",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (GtkCMCListClass, extend_selection),
+                             NULL, NULL,
+                             claws_marshal_VOID__ENUM_FLOAT_BOOLEAN,
+                             G_TYPE_NONE, 3, GTK_TYPE_SCROLL_TYPE, G_TYPE_FLOAT, G_TYPE_BOOLEAN);
+  clist_signals[SCROLL_VERTICAL] =
+               g_signal_new ("scroll_vertical",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (GtkCMCListClass, scroll_vertical),
+                             NULL, NULL,
+                             claws_marshal_VOID__ENUM_FLOAT,
+                             G_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, G_TYPE_FLOAT);
+  clist_signals[SCROLL_HORIZONTAL] =
+               g_signal_new ("scroll_horizontal",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (GtkCMCListClass, scroll_horizontal),
+                             NULL, NULL,
+                             claws_marshal_VOID__ENUM_FLOAT,
+                             G_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, G_TYPE_FLOAT);
+  clist_signals[ABORT_COLUMN_RESIZE] =
+               g_signal_new ("abort_column_resize",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (GtkCMCListClass, abort_column_resize),
+                             NULL, NULL,
+                             claws_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+
+  binding_set = gtk_binding_set_by_class (klass);
+  gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
+                               "scroll_vertical", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
+                               "scroll_vertical", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
+                               "scroll_vertical", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
+                               "scroll_vertical", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
+                               "scroll_vertical", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, 0,
+                               "scroll_vertical", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
+                               "scroll_vertical", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, 0,
+                               "scroll_vertical", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
+                               "scroll_vertical", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, GDK_CONTROL_MASK,
+                               "scroll_vertical", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
+                               "scroll_vertical", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               G_TYPE_FLOAT, 1.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_End, GDK_CONTROL_MASK,
+                               "scroll_vertical", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               G_TYPE_FLOAT, 1.0);
+  
+  gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
+                               "extend_selection", 3,
+                               G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+                               G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, GDK_SHIFT_MASK,
+                               "extend_selection", 3,
+                               G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+                               G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
+                               "extend_selection", 3,
+                               G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+                               G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, GDK_SHIFT_MASK,
+                               "extend_selection", 3,
+                               G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+                               G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
+                               "extend_selection", 3,
+                               G_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
+                               G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, GDK_SHIFT_MASK,
+                               "extend_selection", 3,
+                               G_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
+                               G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
+                               "extend_selection", 3,
+                               G_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
+                               G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, GDK_SHIFT_MASK,
+                               "extend_selection", 3,
+                               G_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
+                               G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_Home,
+                               GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "extend_selection", 3,
+                               G_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Home,
+                                GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "extend_selection", 3,
+                               G_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               G_TYPE_FLOAT, 0.0, G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_End,
+                               GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "extend_selection", 3,
+                               G_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               G_TYPE_FLOAT, 1.0, G_TYPE_BOOLEAN, TRUE);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_End,
+                               GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "extend_selection", 3,
+                               G_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               G_TYPE_FLOAT, 1.0, G_TYPE_BOOLEAN, TRUE);
+
+  
+  gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
+                               "scroll_horizontal", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
+                               "scroll_horizontal", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
+                               G_TYPE_FLOAT, 0.0);
+  
+  gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
+                               "scroll_horizontal", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
+                               "scroll_horizontal", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
+                               G_TYPE_FLOAT, 0.0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
+                               "scroll_horizontal", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               G_TYPE_FLOAT, 0.0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
+                               "scroll_horizontal", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               G_TYPE_FLOAT, 0.0);
+  
+  gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
+                               "scroll_horizontal", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               G_TYPE_FLOAT, 1.0);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
+                               "scroll_horizontal", 2,
+                               G_TYPE_ENUM, GTK_SCROLL_JUMP,
+                               G_TYPE_FLOAT, 1.0);
+  
+  gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
+                               "undo_selection", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
+                               "abort_column_resize", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
+                               "toggle_focus_row", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
+                               "toggle_focus_row", 0);  
+  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
+                               "toggle_add_mode", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_CONTROL_MASK,
+                               "toggle_add_mode", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK,
+                               "select_all", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Divide, GDK_CONTROL_MASK,
+                               "select_all", 0);
+  gtk_binding_entry_add_signal (binding_set, '\\', GDK_CONTROL_MASK,
+                               "unselect_all", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
+                               GDK_RELEASE_MASK | GDK_SHIFT_MASK,
+                               "end_selection", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
+                               GDK_RELEASE_MASK | GDK_SHIFT_MASK,
+                               "end_selection", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
+                               GDK_RELEASE_MASK | GDK_SHIFT_MASK |
+                               GDK_CONTROL_MASK,
+                               "end_selection", 0);
+  gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
+                               GDK_RELEASE_MASK | GDK_SHIFT_MASK |
+                               GDK_CONTROL_MASK,
+                               "end_selection", 0);
+}
+
+static void
+gtk_cmclist_set_arg (GObject *object,
+                               guint      arg_id,
+                               const GValue *value,
+                               GParamSpec *spec)
+{
+  GtkCMCList *clist;
+
+  clist = GTK_CMCLIST (object);
+
+  switch (arg_id)
+    {
+    case ARG_N_COLUMNS: /* only set at construction time */
+      clist->columns = MAX (1, g_value_get_uint (value));
+      break;
+    case ARG_SHADOW_TYPE:
+      gtk_cmclist_set_shadow_type (clist, g_value_get_enum (value));
+      break;
+    case ARG_SELECTION_MODE:
+      gtk_cmclist_set_selection_mode (clist, g_value_get_enum (value));
+      break;
+    case ARG_ROW_HEIGHT:
+      gtk_cmclist_set_row_height (clist, g_value_get_uint (value));
+      break;
+    case ARG_REORDERABLE:
+      gtk_cmclist_set_reorderable (clist, g_value_get_boolean (value));
+      break;
+    case ARG_TITLES_ACTIVE:
+      if (g_value_get_boolean (value))
+       gtk_cmclist_column_titles_active (clist);
+      else
+       gtk_cmclist_column_titles_passive (clist);
+      break;
+    case ARG_USE_DRAG_ICONS:
+      gtk_cmclist_set_use_drag_icons (clist, g_value_get_boolean (value));
+      break;
+    case ARG_SORT_TYPE:
+      gtk_cmclist_set_sort_type (clist, g_value_get_enum (value));
+      break;
+    }
+}
+
+static void
+gtk_cmclist_get_arg (GObject *object,
+                               guint      arg_id,
+                               GValue *value,
+                               GParamSpec *spec)
+{
+  GtkCMCList *clist;
+
+  clist = GTK_CMCLIST (object);
+
+  switch (arg_id)
+    {
+      guint i;
+
+    case ARG_N_COLUMNS:
+      g_value_set_uint(value, clist->columns);
+      break;
+    case ARG_SHADOW_TYPE:
+      g_value_set_enum(value, clist->shadow_type);
+      break;
+    case ARG_SELECTION_MODE:
+      g_value_set_enum(value, clist->selection_mode);
+      break;
+    case ARG_ROW_HEIGHT:
+      g_value_set_uint(value, GTK_CMCLIST_ROW_HEIGHT_SET(clist) ? clist->row_height : 0);
+      break;
+    case ARG_REORDERABLE:
+      g_value_set_boolean(value, GTK_CMCLIST_REORDERABLE (clist));
+      break;
+    case ARG_TITLES_ACTIVE:
+      g_value_set_boolean(value, TRUE);
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].button &&
+           !GTK_WIDGET_SENSITIVE (clist->column[i].button))
+         {
+           g_value_set_boolean(value, FALSE);
+           break;
+         }
+      break;
+    case ARG_USE_DRAG_ICONS:
+      g_value_set_boolean(value, GTK_CMCLIST_USE_DRAG_ICONS (clist));
+      break;
+    case ARG_SORT_TYPE:
+      g_value_set_enum(value, clist->sort_type);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, spec);
+      break;
+    }
+}
+
+static void
+gtk_cmclist_init (GtkCMCList *clist)
+{
+  clist->flags = 0;
+
+  GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
+  GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
+  GTK_CMCLIST_SET_FLAG (clist, CMCLIST_DRAW_DRAG_LINE);
+  GTK_CMCLIST_SET_FLAG (clist, CMCLIST_USE_DRAG_ICONS);
+
+  clist->freeze_count = 0;
+
+  clist->rows = 0;
+  clist->row_height = 0;
+  clist->row_list = NULL;
+  clist->row_list_end = NULL;
+
+  clist->columns = 0;
+
+  clist->title_window = NULL;
+  clist->column_title_area.x = 0;
+  clist->column_title_area.y = 0;
+  clist->column_title_area.width = 1;
+  clist->column_title_area.height = 1;
+
+  clist->clist_window = NULL;
+  clist->clist_window_width = 1;
+  clist->clist_window_height = 1;
+
+  clist->hoffset = 0;
+  clist->voffset = 0;
+
+  clist->shadow_type = GTK_SHADOW_IN;
+  clist->vadjustment = NULL;
+  clist->hadjustment = NULL;
+
+  clist->button_actions[0] = GTK_CMBUTTON_SELECTS | GTK_CMBUTTON_DRAGS;
+  clist->button_actions[1] = GTK_CMBUTTON_IGNORED;
+  clist->button_actions[2] = GTK_CMBUTTON_IGNORED;
+  clist->button_actions[3] = GTK_CMBUTTON_IGNORED;
+  clist->button_actions[4] = GTK_CMBUTTON_IGNORED;
+
+  clist->cursor_drag = NULL;
+  clist->xor_gc = NULL;
+  clist->fg_gc = NULL;
+  clist->bg_gc = NULL;
+  clist->x_drag = 0;
+
+  clist->selection_mode = GTK_SELECTION_SINGLE;
+  clist->selection = NULL;
+  clist->selection_end = NULL;
+  clist->undo_selection = NULL;
+  clist->undo_unselection = NULL;
+
+  clist->focus_row = -1;
+  clist->focus_header_column = -1;
+  clist->undo_anchor = -1;
+
+  clist->anchor = -1;
+  clist->anchor_state = GTK_STATE_SELECTED;
+  clist->drag_pos = -1;
+  clist->htimer = 0;
+  clist->vtimer = 0;
+
+  clist->click_cell.row = -1;
+  clist->click_cell.column = -1;
+
+  clist->compare = default_compare;
+  clist->sort_type = GTK_SORT_ASCENDING;
+  clist->sort_column = 0;
+
+  clist->drag_highlight_row = -1;
+}
+
+/* Constructor */
+static GObject*
+gtk_cmclist_constructor (GType                  type,
+                      guint                  n_construct_properties,
+                      GObjectConstructParam *construct_properties)
+{
+  GObject *object = G_OBJECT_CLASS (parent_class)->constructor (type,
+                                                               n_construct_properties,
+                                                               construct_properties);
+  GtkCMCList *clist = GTK_CMCLIST (object);
+  
+  /* allocate memory for columns */
+  clist->column = columns_new (clist);
+  
+  /* there needs to be at least one column button 
+   * because there is alot of code that will break if it
+   * isn't there
+   */
+  column_button_create (clist, 0);
+  
+  return object;
+}
+
+/* GTKCLIST PUBLIC INTERFACE
+ *   gtk_cmclist_new
+ *   gtk_cmclist_new_with_titles
+ *   gtk_cmclist_set_hadjustment
+ *   gtk_cmclist_set_vadjustment
+ *   gtk_cmclist_get_hadjustment
+ *   gtk_cmclist_get_vadjustment
+ *   gtk_cmclist_set_shadow_type
+ *   gtk_cmclist_set_selection_mode
+ *   gtk_cmclist_freeze
+ *   gtk_cmclist_thaw
+ */
+GtkWidget*
+gtk_cmclist_new (gint columns)
+{
+  return gtk_cmclist_new_with_titles (columns, NULL);
+}
+GtkWidget*
+gtk_cmclist_new_with_titles (gint   columns,
+                          gchar *titles[])
+{
+  GtkCMCList *clist;
+
+  clist = g_object_new (GTK_TYPE_CMCLIST,
+                       "n_columns", columns,
+                       NULL);
+  if (titles)
+    {
+      guint i;
+
+      for (i = 0; i < clist->columns; i++)
+       gtk_cmclist_set_column_title (clist, i, titles[i]);
+      gtk_cmclist_column_titles_show (clist);
+    }
+  else
+    gtk_cmclist_column_titles_hide (clist);
+
+  return GTK_WIDGET (clist);
+}
+
+void
+gtk_cmclist_set_hadjustment (GtkCMCList      *clist,
+                          GtkAdjustment *adjustment)
+{
+  GtkAdjustment *old_adjustment;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  if (adjustment)
+    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+  
+  if (clist->hadjustment == adjustment)
+    return;
+  
+  old_adjustment = clist->hadjustment;
+
+  if (clist->hadjustment)
+    {
+      g_signal_handlers_disconnect_matched(GTK_OBJECT (clist->hadjustment), G_SIGNAL_MATCH_DATA,
+                       0, 0, 0, 0, clist);
+
+      g_object_unref (GTK_OBJECT (clist->hadjustment));
+    }
+
+  clist->hadjustment = adjustment;
+
+  if (clist->hadjustment)
+    {
+      g_object_ref_sink (clist->hadjustment);
+
+      g_signal_connect (G_OBJECT (clist->hadjustment), "changed",
+                         G_CALLBACK( hadjustment_changed),
+                         (gpointer) clist);
+      g_signal_connect (G_OBJECT (clist->hadjustment), "value_changed",
+                         G_CALLBACK( hadjustment_value_changed),
+                         (gpointer) clist);
+    }
+
+  if (!clist->hadjustment || !old_adjustment)
+    gtk_widget_queue_resize (GTK_WIDGET (clist));
+}
+
+GtkAdjustment *
+gtk_cmclist_get_hadjustment (GtkCMCList *clist)
+{
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+  return clist->hadjustment;
+}
+
+void
+gtk_cmclist_set_vadjustment (GtkCMCList      *clist,
+                          GtkAdjustment *adjustment)
+{
+  GtkAdjustment *old_adjustment;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  if (adjustment)
+    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+
+  if (clist->vadjustment == adjustment)
+    return;
+  
+  old_adjustment = clist->vadjustment;
+
+  if (clist->vadjustment)
+    {
+      g_signal_handlers_disconnect_matched(GTK_OBJECT (clist->vadjustment), G_SIGNAL_MATCH_DATA,
+                       0, 0, 0, 0, clist);
+      g_object_unref (GTK_OBJECT (clist->vadjustment));
+    }
+
+  clist->vadjustment = adjustment;
+
+  if (clist->vadjustment)
+    {
+      g_object_ref_sink (clist->vadjustment);
+
+      g_signal_connect (GTK_OBJECT (clist->vadjustment), "changed",
+                         G_CALLBACK(vadjustment_changed),
+                         (gpointer) clist);
+      g_signal_connect (GTK_OBJECT (clist->vadjustment), "value_changed",
+                         G_CALLBACK(vadjustment_value_changed),
+                         (gpointer) clist);
+    }
+
+  if (!clist->vadjustment || !old_adjustment)
+    gtk_widget_queue_resize (GTK_WIDGET (clist));
+}
+
+GtkAdjustment *
+gtk_cmclist_get_vadjustment (GtkCMCList *clist)
+{
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+  return clist->vadjustment;
+}
+
+static void
+gtk_cmclist_set_scroll_adjustments (GtkCMCList      *clist,
+                                 GtkAdjustment *hadjustment,
+                                 GtkAdjustment *vadjustment)
+{
+  if (clist->hadjustment != hadjustment)
+    gtk_cmclist_set_hadjustment (clist, hadjustment);
+  if (clist->vadjustment != vadjustment)
+    gtk_cmclist_set_vadjustment (clist, vadjustment);
+}
+
+void
+gtk_cmclist_set_shadow_type (GtkCMCList      *clist,
+                          GtkShadowType  type)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  clist->shadow_type = type;
+
+  if (GTK_WIDGET_VISIBLE (clist))
+    gtk_widget_queue_resize (GTK_WIDGET (clist));
+}
+
+void
+gtk_cmclist_set_selection_mode (GtkCMCList         *clist,
+                             GtkSelectionMode  mode)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  g_return_if_fail (mode != GTK_SELECTION_NONE);
+
+  if (mode == clist->selection_mode)
+    return;
+
+  clist->selection_mode = mode;
+  clist->anchor = -1;
+  clist->anchor_state = GTK_STATE_SELECTED;
+  clist->drag_pos = -1;
+  clist->undo_anchor = clist->focus_row;
+
+  g_list_free (clist->undo_selection);
+  g_list_free (clist->undo_unselection);
+  clist->undo_selection = NULL;
+  clist->undo_unselection = NULL;
+
+  switch (mode)
+    {
+    case GTK_SELECTION_MULTIPLE:
+      return;
+    case GTK_SELECTION_BROWSE:
+    case GTK_SELECTION_SINGLE:
+      gtk_cmclist_unselect_all (clist);
+      break;
+    default:
+      /* Someone set it by hand */
+      g_assert_not_reached ();
+    }
+}
+
+void
+gtk_cmclist_freeze (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  clist->freeze_count++;
+}
+
+void
+gtk_cmclist_thaw (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (clist->freeze_count)
+    {
+      clist->freeze_count--;
+      CLIST_REFRESH (clist);
+    }
+}
+
+/* PUBLIC COLUMN FUNCTIONS
+ *   gtk_cmclist_column_titles_show
+ *   gtk_cmclist_column_titles_hide
+ *   gtk_cmclist_column_title_active
+ *   gtk_cmclist_column_title_passive
+ *   gtk_cmclist_column_titles_active
+ *   gtk_cmclist_column_titles_passive
+ *   gtk_cmclist_set_column_title
+ *   gtk_cmclist_get_column_title
+ *   gtk_cmclist_set_column_widget
+ *   gtk_cmclist_set_column_justification
+ *   gtk_cmclist_set_column_visibility
+ *   gtk_cmclist_set_column_resizeable
+ *   gtk_cmclist_set_column_auto_resize
+ *   gtk_cmclist_optimal_column_width
+ *   gtk_cmclist_set_column_width
+ *   gtk_cmclist_set_column_min_width
+ *   gtk_cmclist_set_column_max_width
+ */
+void
+gtk_cmclist_column_titles_show (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (!GTK_CMCLIST_SHOW_TITLES(clist))
+    {
+      GTK_CMCLIST_SET_FLAG (clist, CMCLIST_SHOW_TITLES);
+      if (clist->title_window)
+       gdk_window_show (clist->title_window);
+      gtk_widget_queue_resize (GTK_WIDGET (clist));
+    }
+}
+
+void 
+gtk_cmclist_column_titles_hide (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (GTK_CMCLIST_SHOW_TITLES(clist))
+    {
+      GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_SHOW_TITLES);
+      if (clist->title_window)
+       gdk_window_hide (clist->title_window);
+      gtk_widget_queue_resize (GTK_WIDGET (clist));
+    }
+}
+
+void
+gtk_cmclist_column_title_active (GtkCMCList *clist,
+                              gint      column)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+  if (!clist->column[column].button || !clist->column[column].button_passive)
+    return;
+
+  clist->column[column].button_passive = FALSE;
+
+  g_signal_handlers_disconnect_matched(GTK_OBJECT (clist->column[column].button), G_SIGNAL_MATCH_FUNC,
+                   0, 0, 0, column_title_passive_func, 0);
+
+  GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_CAN_FOCUS);
+  if (GTK_WIDGET_VISIBLE (clist))
+    gtk_widget_queue_draw (clist->column[column].button);
+}
+
+void
+gtk_cmclist_column_title_passive (GtkCMCList *clist,
+                               gint      column)
+{
+  GtkButton *button;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+  if (!clist->column[column].button || clist->column[column].button_passive)
+    return;
+
+  button = GTK_BUTTON (clist->column[column].button);
+
+  clist->column[column].button_passive = TRUE;
+
+  if (button->button_down)
+    gtk_button_released (button);
+  if (button->in_button)
+    gtk_button_leave (button);
+
+  g_signal_connect (G_OBJECT (clist->column[column].button), "event",
+                     G_CALLBACK(column_title_passive_func), NULL);
+
+  GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_CAN_FOCUS);
+  if (GTK_WIDGET_VISIBLE (clist))
+    gtk_widget_queue_draw (clist->column[column].button);
+}
+
+void
+gtk_cmclist_column_titles_active (GtkCMCList *clist)
+{
+  gint i;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  for (i = 0; i < clist->columns; i++)
+    gtk_cmclist_column_title_active (clist, i);
+}
+
+void
+gtk_cmclist_column_titles_passive (GtkCMCList *clist)
+{
+  gint i;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  for (i = 0; i < clist->columns; i++)
+    gtk_cmclist_column_title_passive (clist, i);
+}
+
+void
+gtk_cmclist_set_column_title (GtkCMCList    *clist,
+                           gint         column,
+                           const gchar *title)
+{
+  gint new_button = 0;
+  GtkWidget *old_widget;
+  GtkWidget *alignment = NULL;
+  GtkWidget *label;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  /* if the column button doesn't currently exist,
+   * it has to be created first */
+  if (!clist->column[column].button)
+    {
+      column_button_create (clist, column);
+      new_button = 1;
+    }
+
+  column_title_new (clist, column, title);
+
+  /* remove and destroy the old widget */
+  old_widget = GTK_BIN (clist->column[column].button)->child;
+  if (old_widget)
+    gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
+
+  /* create new alignment based no column justification */
+  switch (clist->column[column].justification)
+    {
+    case GTK_JUSTIFY_LEFT:
+      alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
+      break;
+
+    case GTK_JUSTIFY_RIGHT:
+      alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
+      break;
+
+    case GTK_JUSTIFY_CENTER:
+      alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
+      break;
+
+    case GTK_JUSTIFY_FILL:
+      alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
+      break;
+    }
+
+  gtk_widget_push_composite_child ();
+  label = gtk_label_new (clist->column[column].title);
+  gtk_widget_pop_composite_child ();
+  gtk_container_add (GTK_CONTAINER (alignment), label);
+  gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
+  gtk_widget_show (label);
+  gtk_widget_show (alignment);
+
+  /* if this button didn't previously exist, then the
+   * column button positions have to be re-computed */
+  if (GTK_WIDGET_VISIBLE (clist) && new_button)
+    size_allocate_title_buttons (clist);
+}
+
+gchar *
+gtk_cmclist_get_column_title (GtkCMCList *clist,
+                           gint      column)
+{
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+  if (column < 0 || column >= clist->columns)
+    return NULL;
+
+  return clist->column[column].title;
+}
+
+void
+gtk_cmclist_set_column_widget (GtkCMCList  *clist,
+                            gint       column,
+                            GtkWidget *widget)
+{
+  gint new_button = 0;
+  GtkWidget *old_widget;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  /* if the column button doesn't currently exist,
+   * it has to be created first */
+  if (!clist->column[column].button)
+    {
+      column_button_create (clist, column);
+      new_button = 1;
+    }
+
+  column_title_new (clist, column, NULL);
+
+  /* remove and destroy the old widget */
+  old_widget = GTK_BIN (clist->column[column].button)->child;
+  if (old_widget)
+    gtk_container_remove (GTK_CONTAINER (clist->column[column].button),
+                         old_widget);
+
+  /* add and show the widget */
+  if (widget)
+    {
+      gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
+      gtk_widget_show (widget);
+    }
+
+  /* if this button didn't previously exist, then the
+   * column button positions have to be re-computed */
+  if (GTK_WIDGET_VISIBLE (clist) && new_button)
+    size_allocate_title_buttons (clist);
+}
+
+GtkWidget *
+gtk_cmclist_get_column_widget (GtkCMCList *clist,
+                            gint      column)
+{
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+  if (column < 0 || column >= clist->columns)
+    return NULL;
+
+  if (clist->column[column].button)
+    return GTK_BIN (clist->column[column].button)->child;
+
+  return NULL;
+}
+
+void
+gtk_cmclist_set_column_justification (GtkCMCList         *clist,
+                                   gint              column,
+                                   GtkJustification  justification)
+{
+  GtkWidget *alignment;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  clist->column[column].justification = justification;
+
+  /* change the alinment of the button title if it's not a
+   * custom widget */
+  if (clist->column[column].title)
+    {
+      alignment = GTK_BIN (clist->column[column].button)->child;
+
+      switch (clist->column[column].justification)
+       {
+       case GTK_JUSTIFY_LEFT:
+         gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
+         break;
+
+       case GTK_JUSTIFY_RIGHT:
+         gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
+         break;
+
+       case GTK_JUSTIFY_CENTER:
+         gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
+         break;
+
+       case GTK_JUSTIFY_FILL:
+         gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
+         break;
+
+       default:
+         break;
+       }
+    }
+
+  if (CLIST_UNFROZEN (clist))
+    draw_rows (clist, NULL);
+}
+
+void
+gtk_cmclist_set_column_visibility (GtkCMCList *clist,
+                                gint      column,
+                                gboolean  visible)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+  if (clist->column[column].visible == visible)
+    return;
+
+  /* don't hide last visible column */
+  if (!visible)
+    {
+      gint i;
+      gint vis_columns = 0;
+
+      for (i = 0, vis_columns = 0; i < clist->columns && vis_columns < 2; i++)
+       if (clist->column[i].visible)
+         vis_columns++;
+
+      if (vis_columns < 2)
+       return;
+    }
+
+  clist->column[column].visible = visible;
+
+  if (clist->column[column].button)
+    {
+      if (visible)
+       gtk_widget_show (clist->column[column].button);
+      else
+       gtk_widget_hide (clist->column[column].button);
+    }
+  
+  gtk_widget_queue_resize (GTK_WIDGET(clist));
+}
+
+void
+gtk_cmclist_set_column_resizeable (GtkCMCList *clist,
+                                gint      column,
+                                gboolean  resizeable)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+  if (clist->column[column].resizeable == resizeable)
+    return;
+
+  clist->column[column].resizeable = resizeable;
+  if (resizeable)
+    clist->column[column].auto_resize = FALSE;
+
+  if (GTK_WIDGET_VISIBLE (clist))
+    size_allocate_title_buttons (clist);
+}
+
+void
+gtk_cmclist_set_column_auto_resize (GtkCMCList *clist,
+                                 gint      column,
+                                 gboolean  auto_resize)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+  if (clist->column[column].auto_resize == auto_resize)
+    return;
+
+  clist->column[column].auto_resize = auto_resize;
+  if (auto_resize)
+    {
+      clist->column[column].resizeable = FALSE;
+      if (!GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+       {
+         gint width;
+
+         width = gtk_cmclist_optimal_column_width (clist, column);
+         gtk_cmclist_set_column_width (clist, column, width);
+       }
+    }
+
+  if (GTK_WIDGET_VISIBLE (clist))
+    size_allocate_title_buttons (clist);
+}
+
+gint
+gtk_cmclist_columns_autosize (GtkCMCList *clist)
+{
+  gint i;
+  gint width;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+
+  gtk_cmclist_freeze (clist);
+  width = 0;
+  for (i = 0; i < clist->columns; i++)
+    {
+      gtk_cmclist_set_column_width (clist, i,
+                                 gtk_cmclist_optimal_column_width (clist, i));
+
+      width += clist->column[i].width;
+    }
+
+  gtk_cmclist_thaw (clist);
+  return width;
+}
+
+gint
+gtk_cmclist_optimal_column_width (GtkCMCList *clist,
+                               gint      column)
+{
+  GtkRequisition requisition;
+  GList *list;
+  gint width;
+
+  g_return_val_if_fail (GTK_CMCLIST (clist), 0);
+
+  if (column < 0 || column >= clist->columns)
+    return 0;
+
+  if (GTK_CMCLIST_SHOW_TITLES(clist) && clist->column[column].button)
+    width = (clist->column[column].button->requisition.width)
+#if 0
+            (CELL_SPACING + (2 * COLUMN_INSET)))
+#endif
+               ;
+  else
+    width = 0;
+
+  for (list = clist->row_list; list; list = list->next)
+    {
+  GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+       (clist, GTK_CMCLIST_ROW (list), column, &requisition);
+      width = MAX (width, requisition.width);
+    }
+
+  return width;
+}
+
+void
+gtk_cmclist_set_column_width (GtkCMCList *clist,
+                           gint      column,
+                           gint      width)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  g_signal_emit (GTK_OBJECT (clist), clist_signals[RESIZE_COLUMN], 0,
+                  column, width);
+}
+
+void
+gtk_cmclist_set_column_min_width (GtkCMCList *clist,
+                               gint      column,
+                               gint      min_width)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+  if (clist->column[column].min_width == min_width)
+    return;
+
+  if (clist->column[column].max_width >= 0  &&
+      clist->column[column].max_width < min_width)
+    clist->column[column].min_width = clist->column[column].max_width;
+  else
+    clist->column[column].min_width = min_width;
+
+  if (clist->column[column].area.width < clist->column[column].min_width)
+    gtk_cmclist_set_column_width (clist, column,clist->column[column].min_width);
+}
+
+void
+gtk_cmclist_set_column_max_width (GtkCMCList *clist,
+                               gint      column,
+                               gint      max_width)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+  if (clist->column[column].max_width == max_width)
+    return;
+
+  if (clist->column[column].min_width >= 0 && max_width >= 0 &&
+      clist->column[column].min_width > max_width)
+    clist->column[column].max_width = clist->column[column].min_width;
+  else
+    clist->column[column].max_width = max_width;
+  
+  if (clist->column[column].area.width > clist->column[column].max_width)
+    gtk_cmclist_set_column_width (clist, column,clist->column[column].max_width);
+}
+
+/* PRIVATE COLUMN FUNCTIONS
+ *   column_auto_resize
+ *   real_resize_column
+ *   abort_column_resize
+ *   size_allocate_title_buttons
+ *   size_allocate_columns
+ *   list_requisition_width
+ *   new_column_width
+ *   column_button_create
+ *   column_button_clicked
+ *   column_title_passive_func
+ */
+static void
+column_auto_resize (GtkCMCList    *clist,
+                   GtkCMCListRow *clist_row,
+                   gint         column,
+                   gint         old_width)
+{
+  /* resize column if needed for auto_resize */
+  GtkRequisition requisition;
+
+  if (!clist->column[column].auto_resize ||
+      GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    return;
+
+  if (clist_row)
+    GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+                                                  column, &requisition);
+  else
+    requisition.width = 0;
+
+  if (requisition.width > clist->column[column].width)
+    gtk_cmclist_set_column_width (clist, column, requisition.width);
+  else if (requisition.width < old_width &&
+          old_width == clist->column[column].width)
+    {
+      GList *list;
+      gint new_width = 0;
+
+      /* run a "gtk_cmclist_optimal_column_width" but break, if
+       * the column doesn't shrink */
+      if (GTK_CMCLIST_SHOW_TITLES(clist) && clist->column[column].button)
+       new_width = (clist->column[column].button->requisition.width -
+                    (CELL_SPACING + (2 * COLUMN_INSET)));
+      else
+       new_width = 0;
+
+      for (list = clist->row_list; list; list = list->next)
+       {
+         GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+           (clist, GTK_CMCLIST_ROW (list), column, &requisition);
+         new_width = MAX (new_width, requisition.width);
+         if (new_width == clist->column[column].width)
+           break;
+       }
+      if (new_width < clist->column[column].width)
+       gtk_cmclist_set_column_width
+         (clist, column, MAX (new_width, clist->column[column].min_width));
+    }
+}
+
+static void
+real_resize_column (GtkCMCList *clist,
+                   gint      column,
+                   gint      width)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+  
+  if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
+    width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
+  if (clist->column[column].max_width >= 0 &&
+      width > clist->column[column].max_width)
+    width = clist->column[column].max_width;
+
+  clist->column[column].width = width;
+  clist->column[column].width_set = TRUE;
+
+  /* FIXME: this is quite expensive to do if the widget hasn't
+   *        been size_allocated yet, and pointless. Should
+   *        a flag be kept
+   */
+  size_allocate_columns (clist, TRUE);
+  size_allocate_title_buttons (clist);
+
+  CLIST_REFRESH (clist);
+}
+
+static void
+abort_column_resize (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (!GTK_CMCLIST_IN_DRAG(clist))
+    return;
+
+  GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_IN_DRAG);
+  gtk_grab_remove (GTK_WIDGET (clist));
+  gdk_display_pointer_ungrab (gtk_widget_get_display (GTK_WIDGET (clist)),
+                             GDK_CURRENT_TIME);
+  clist->drag_pos = -1;
+
+  if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
+    draw_xor_line (clist);
+
+  if (GTK_CMCLIST_ADD_MODE(clist))
+    {
+      gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
+      gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
+    }
+}
+
+static void
+size_allocate_title_buttons (GtkCMCList *clist)
+{
+  GtkAllocation button_allocation;
+  gint last_column;
+  gint last_button = 0;
+  gint i;
+
+  if (!GTK_WIDGET_REALIZED (clist))
+    return;
+
+  button_allocation.x = clist->hoffset;
+  button_allocation.y = 0;
+  button_allocation.width = 0;
+  button_allocation.height = clist->column_title_area.height;
+
+  /* find last visible column */
+  for (last_column = clist->columns - 1; last_column >= 0; last_column--)
+    if (clist->column[last_column].visible)
+      break;
+
+  for (i = 0; i < last_column; i++)
+    {
+      if (!clist->column[i].visible)
+       {
+         last_button = i + 1;
+         gdk_window_hide (clist->column[i].window);
+         continue;
+       }
+
+      button_allocation.width += (clist->column[i].area.width +
+                                 CELL_SPACING + 2 * COLUMN_INSET);
+
+      if (!clist->column[i + 1].button)
+       {
+         gdk_window_hide (clist->column[i].window);
+         continue;
+       }
+
+      gtk_widget_size_allocate (clist->column[last_button].button,
+                               &button_allocation);
+      button_allocation.x += button_allocation.width;
+      button_allocation.width = 0;
+
+      if (clist->column[last_button].resizeable)
+       {
+         gdk_window_show (clist->column[last_button].window);
+         gdk_window_move_resize (clist->column[last_button].window,
+                                 button_allocation.x - (DRAG_WIDTH / 2), 
+                                 0, DRAG_WIDTH,
+                                 clist->column_title_area.height);
+       }
+      else
+       gdk_window_hide (clist->column[last_button].window);
+
+      last_button = i + 1;
+    }
+
+  button_allocation.width += (clist->column[last_column].area.width +
+                             2 * (CELL_SPACING + COLUMN_INSET));
+  gtk_widget_size_allocate (clist->column[last_button].button,
+                           &button_allocation);
+
+  if (clist->column[last_button].resizeable)
+    {
+      button_allocation.x += button_allocation.width;
+
+      gdk_window_show (clist->column[last_button].window);
+      gdk_window_move_resize (clist->column[last_button].window,
+                             button_allocation.x - (DRAG_WIDTH / 2), 
+                             0, DRAG_WIDTH, clist->column_title_area.height);
+    }
+  else
+    gdk_window_hide (clist->column[last_button].window);
+}
+
+static void
+size_allocate_columns (GtkCMCList *clist,
+                      gboolean  block_resize)
+{
+  gint xoffset = CELL_SPACING + COLUMN_INSET;
+  gint last_column;
+  gint i;
+
+  /* find last visible column and calculate correct column width */
+  for (last_column = clist->columns - 1;
+       last_column >= 0 && !clist->column[last_column].visible; last_column--);
+
+  if (last_column < 0)
+    return;
+
+  for (i = 0; i <= last_column; i++)
+    {
+      if (!clist->column[i].visible)
+       continue;
+      clist->column[i].area.x = xoffset;
+      if (clist->column[i].width_set)
+       {
+         if (!block_resize && GTK_CMCLIST_SHOW_TITLES(clist) &&
+             clist->column[i].auto_resize && clist->column[i].button)
+           {
+             gint width;
+
+             width = (clist->column[i].button->requisition.width -
+                      (CELL_SPACING + (2 * COLUMN_INSET)));
+
+             if (width > clist->column[i].width)
+               gtk_cmclist_set_column_width (clist, i, width);
+           }
+
+         clist->column[i].area.width = clist->column[i].width;
+         xoffset += clist->column[i].width + CELL_SPACING + (2* COLUMN_INSET);
+       }
+      else if (GTK_CMCLIST_SHOW_TITLES(clist) && clist->column[i].button)
+       {
+         clist->column[i].area.width =
+           clist->column[i].button->requisition.width -
+           (CELL_SPACING + (2 * COLUMN_INSET));
+         xoffset += clist->column[i].button->requisition.width;
+       }
+    }
+
+  clist->column[last_column].area.width = clist->column[last_column].area.width
+    + MAX (0, clist->clist_window_width + COLUMN_INSET - xoffset);
+}
+
+static gint
+list_requisition_width (GtkCMCList *clist) 
+{
+  gint width = CELL_SPACING;
+  gint i;
+
+  for (i = clist->columns - 1; i >= 0; i--)
+    {
+      if (!clist->column[i].visible)
+       continue;
+
+      if (clist->column[i].width_set)
+       width += clist->column[i].width + CELL_SPACING + (2 * COLUMN_INSET);
+      else if (GTK_CMCLIST_SHOW_TITLES(clist) && clist->column[i].button)
+       width += clist->column[i].button->requisition.width;
+    }
+
+  return width;
+}
+
+/* this function returns the new width of the column being resized given
+ * the column and x position of the cursor; the x cursor position is passed
+ * in as a pointer and automagicly corrected if it's beyond min/max limits */
+static gint
+new_column_width (GtkCMCList *clist,
+                 gint      column,
+                 gint     *x)
+{
+  gint xthickness = GTK_WIDGET (clist)->style->xthickness;
+  gint width;
+  gint cx;
+  gint dx;
+  gint last_column;
+
+  /* first translate the x position from widget->window
+   * to clist->clist_window */
+  cx = *x - xthickness;
+
+  for (last_column = clist->columns - 1;
+       last_column >= 0 && !clist->column[last_column].visible; last_column--);
+
+  /* calculate new column width making sure it doesn't end up
+   * less than the minimum width */
+  dx = (COLUMN_LEFT_XPIXEL (clist, column) + COLUMN_INSET +
+       (column < last_column) * CELL_SPACING);
+  width = cx - dx;
+
+  if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
+    {
+      width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
+      cx = dx + width;
+      *x = cx + xthickness;
+    }
+  else if (clist->column[column].max_width >= COLUMN_MIN_WIDTH &&
+          width > clist->column[column].max_width)
+    {
+      width = clist->column[column].max_width;
+      cx = dx + clist->column[column].max_width;
+      *x = cx + xthickness;
+    }      
+
+  if (cx < 0 || cx > clist->clist_window_width)
+    *x = -1;
+
+  return width;
+}
+
+static void
+column_button_create (GtkCMCList *clist,
+                     gint      column)
+{
+  GtkWidget *button;
+
+  gtk_widget_push_composite_child ();
+  button = clist->column[column].button = gtk_button_new ();
+  gtk_container_set_border_width(GTK_CONTAINER(button), 0);
+  gtk_widget_pop_composite_child ();
+
+  if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
+    gtk_widget_set_parent_window (clist->column[column].button,
+                                 clist->title_window);
+  gtk_widget_set_parent (button, GTK_WIDGET (clist));
+
+  g_signal_connect (GTK_OBJECT (button), "clicked",
+                     G_CALLBACK(column_button_clicked),
+                     (gpointer) clist);
+  gtk_widget_show (button);
+}
+
+static void
+column_button_clicked (GtkWidget *widget,
+                      gpointer   data)
+{
+  gint i;
+  GtkCMCList *clist;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CMCLIST (data));
+
+  clist = GTK_CMCLIST (data);
+
+  /* find the column who's button was pressed */
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].button == widget)
+      break;
+
+  g_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], 0, i);
+}
+
+static gint
+column_title_passive_func (GtkWidget *widget, 
+                          GdkEvent  *event,
+                          gpointer   data)
+{
+  g_return_val_if_fail (event != NULL, FALSE);
+  
+  switch (event->type)
+    {
+    case GDK_MOTION_NOTIFY:
+    case GDK_BUTTON_PRESS:
+    case GDK_2BUTTON_PRESS:
+    case GDK_3BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+      return TRUE;
+    default:
+      break;
+    }
+  return FALSE;
+}
+
+
+/* PUBLIC CELL FUNCTIONS
+ *   gtk_cmclist_get_cell_type
+ *   gtk_cmclist_set_text
+ *   gtk_cmclist_get_text
+ *   gtk_cmclist_set_pixmap
+ *   gtk_cmclist_get_pixmap
+ *   gtk_cmclist_set_pixtext
+ *   gtk_cmclist_get_pixtext
+ *   gtk_cmclist_set_shift
+ */
+GtkCMCellType 
+gtk_cmclist_get_cell_type (GtkCMCList *clist,
+                        gint      row,
+                        gint      column)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), -1);
+
+  if (row < 0 || row >= clist->rows)
+    return -1;
+  if (column < 0 || column >= clist->columns)
+    return -1;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  return clist_row->cell[column].type;
+}
+
+void
+gtk_cmclist_set_text (GtkCMCList    *clist,
+                   gint         row,
+                   gint         column,
+                   const gchar *text)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  /* if text is null, then the cell is empty */
+  GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+    (clist, clist_row, column, GTK_CMCELL_TEXT, text, 0, NULL, NULL);
+
+  /* redraw the list if it's not frozen */
+  if (CLIST_UNFROZEN (clist))
+    {
+      if (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+       GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+    }
+}
+
+gint
+gtk_cmclist_get_text (GtkCMCList  *clist,
+                   gint       row,
+                   gint       column,
+                   gchar    **text)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+
+  if (row < 0 || row >= clist->rows)
+    return 0;
+  if (column < 0 || column >= clist->columns)
+    return 0;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (clist_row->cell[column].type != GTK_CMCELL_TEXT)
+    return 0;
+
+  if (text)
+    *text = GTK_CMCELL_TEXT (clist_row->cell[column])->text;
+
+  return 1;
+}
+
+void
+gtk_cmclist_set_pixmap (GtkCMCList  *clist,
+                     gint       row,
+                     gint       column,
+                     GdkPixmap *pixmap,
+                     GdkBitmap *mask)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+  
+  g_object_ref (pixmap);
+  
+  if (mask) g_object_ref (mask);
+  
+  GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+    (clist, clist_row, column, GTK_CMCELL_PIXMAP, NULL, 0, pixmap, mask);
+
+  /* redraw the list if it's not frozen */
+  if (CLIST_UNFROZEN (clist))
+    {
+      if (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+       GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+    }
+}
+
+gint
+gtk_cmclist_get_pixmap (GtkCMCList   *clist,
+                     gint        row,
+                     gint        column,
+                     GdkPixmap **pixmap,
+                     GdkBitmap **mask)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+
+  if (row < 0 || row >= clist->rows)
+    return 0;
+  if (column < 0 || column >= clist->columns)
+    return 0;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (clist_row->cell[column].type != GTK_CMCELL_PIXMAP)
+    return 0;
+
+  if (pixmap)
+  {
+    *pixmap = GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap;
+    /* mask can be NULL */
+    *mask = GTK_CMCELL_PIXMAP (clist_row->cell[column])->mask;
+  }
+
+  return 1;
+}
+
+void
+gtk_cmclist_set_pixtext (GtkCMCList    *clist,
+                      gint         row,
+                      gint         column,
+                      const gchar *text,
+                      guint8       spacing,
+                      GdkPixmap   *pixmap,
+                      GdkBitmap   *mask)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+  
+  g_object_ref (pixmap);
+  if (mask) g_object_ref (mask);
+  GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+    (clist, clist_row, column, GTK_CMCELL_PIXTEXT, text, spacing, pixmap, mask);
+
+  /* redraw the list if it's not frozen */
+  if (CLIST_UNFROZEN (clist))
+    {
+      if (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+       GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+    }
+}
+
+gint
+gtk_cmclist_get_pixtext (GtkCMCList   *clist,
+                      gint        row,
+                      gint        column,
+                      gchar     **text,
+                      guint8     *spacing,
+                      GdkPixmap **pixmap,
+                      GdkBitmap **mask)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+
+  if (row < 0 || row >= clist->rows)
+    return 0;
+  if (column < 0 || column >= clist->columns)
+    return 0;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (clist_row->cell[column].type != GTK_CMCELL_PIXTEXT)
+    return 0;
+
+  if (text)
+    *text = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text;
+  if (spacing)
+    *spacing = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->spacing;
+  if (pixmap)
+    *pixmap = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap;
+
+  /* mask can be NULL */
+  if (mask)
+    *mask = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask;
+
+  return 1;
+}
+
+void
+gtk_cmclist_set_shift (GtkCMCList *clist,
+                    gint      row,
+                    gint      column,
+                    gint      vertical,
+                    gint      horizontal)
+{
+  GtkRequisition requisition = { 0 };
+  GtkCMCListRow *clist_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (clist->column[column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+                                                  column, &requisition);
+
+  clist_row->cell[column].vertical = vertical;
+  clist_row->cell[column].horizontal = horizontal;
+
+  column_auto_resize (clist, clist_row, column, requisition.width);
+
+  if (CLIST_UNFROZEN (clist) && gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+    GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+}
+
+/* PRIVATE CELL FUNCTIONS
+ *   set_cell_contents
+ *   cell_size_request
+ */
+static void
+set_cell_contents (GtkCMCList    *clist,
+                  GtkCMCListRow *clist_row,
+                  gint         column,
+                  GtkCMCellType  type,
+                  const gchar *text,
+                  guint8       spacing,
+                  GdkPixmap   *pixmap,
+                  GdkBitmap   *mask)
+{
+  GtkRequisition requisition;
+  gchar *old_text = NULL;
+  GdkPixmap *old_pixmap = NULL;
+  GdkBitmap *old_mask = NULL;
+  
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  g_return_if_fail (clist_row != NULL);
+
+  if (clist->column[column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+                                                  column, &requisition);
+
+  switch (clist_row->cell[column].type)
+    {
+    case GTK_CMCELL_EMPTY:
+      break;
+    case GTK_CMCELL_TEXT:
+      old_text = GTK_CMCELL_TEXT (clist_row->cell[column])->text;
+      break;
+    case GTK_CMCELL_PIXMAP:
+      old_pixmap = GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap;
+      old_mask = GTK_CMCELL_PIXMAP (clist_row->cell[column])->mask;
+      break;
+    case GTK_CMCELL_PIXTEXT:
+      old_text = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text;
+      old_pixmap = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap;
+      old_mask = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask;
+      break;
+    case GTK_CMCELL_WIDGET:
+      /* unimplemented */
+      break;
+    default:
+      break;
+    }
+
+  clist_row->cell[column].type = GTK_CMCELL_EMPTY;
+
+  /* Note that pixmap and mask were already ref'ed by the caller
+   */
+  switch (type)
+    {
+    case GTK_CMCELL_TEXT:
+      if (text)
+       {
+         clist_row->cell[column].type = GTK_CMCELL_TEXT;
+         GTK_CMCELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
+       }
+      break;
+    case GTK_CMCELL_PIXMAP:
+      if (pixmap)
+       {
+         clist_row->cell[column].type = GTK_CMCELL_PIXMAP;
+         GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
+         /* We set the mask even if it is NULL */
+         GTK_CMCELL_PIXMAP (clist_row->cell[column])->mask = mask;
+       }
+      break;
+    case GTK_CMCELL_PIXTEXT:
+      if (text && pixmap)
+       {
+         clist_row->cell[column].type = GTK_CMCELL_PIXTEXT;
+         GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
+         GTK_CMCELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
+         GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
+         GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask = mask;
+       }
+      break;
+    default:
+      break;
+    }
+
+  if (clist->column[column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    column_auto_resize (clist, clist_row, column, requisition.width);
+
+  g_free (old_text);
+  if (old_pixmap)
+    g_object_unref (old_pixmap);
+  if (old_mask)
+    g_object_unref (old_mask);
+}
+
+PangoLayout *
+_gtk_cmclist_create_cell_layout (GtkCMCList       *clist,
+                              GtkCMCListRow    *clist_row,
+                              gint            column)
+{
+  PangoLayout *layout;
+  GtkStyle *style;
+  GtkCMCell *cell;
+  gchar *text;
+  
+  get_cell_style (clist, clist_row, GTK_STATE_NORMAL, column, &style,
+                 NULL, NULL);
+
+
+  cell = &clist_row->cell[column];
+  switch (cell->type)
+    {
+    case GTK_CMCELL_TEXT:
+    case GTK_CMCELL_PIXTEXT:
+      text = ((cell->type == GTK_CMCELL_PIXTEXT) ?
+             GTK_CMCELL_PIXTEXT (*cell)->text :
+             GTK_CMCELL_TEXT (*cell)->text);
+
+      if (!text)
+       return NULL;
+      
+      layout = gtk_widget_create_pango_layout (GTK_WIDGET (clist),
+                                              ((cell->type == GTK_CMCELL_PIXTEXT) ?
+                                               GTK_CMCELL_PIXTEXT (*cell)->text :
+                                               GTK_CMCELL_TEXT (*cell)->text));
+      pango_layout_set_font_description (layout, style->font_desc);
+      
+      return layout;
+      
+    default:
+      return NULL;
+    }
+}
+
+static void
+cell_size_request (GtkCMCList       *clist,
+                  GtkCMCListRow    *clist_row,
+                  gint            column,
+                  GtkRequisition *requisition)
+{
+  gint width;
+  gint height;
+  PangoLayout *layout;
+  PangoRectangle logical_rect;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  g_return_if_fail (requisition != NULL);
+
+  layout = _gtk_cmclist_create_cell_layout (clist, clist_row, column);
+  if (layout)
+    {
+      pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+      
+      requisition->width = logical_rect.width;
+      requisition->height = logical_rect.height;
+      
+      g_object_unref (G_OBJECT (layout));
+    }
+  else
+    {
+      requisition->width  = 0;
+      requisition->height = 0;
+    }
+
+  if (layout && clist_row->cell[column].type == GTK_CMCELL_PIXTEXT)
+    requisition->width += GTK_CMCELL_PIXTEXT (clist_row->cell[column])->spacing;
+
+  switch (clist_row->cell[column].type)
+    {
+    case GTK_CMCELL_PIXTEXT:
+      gdk_drawable_get_size (GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap,
+                          &width, &height);
+      requisition->width += width;
+      requisition->height = MAX (requisition->height, height);      
+      break;
+    case GTK_CMCELL_PIXMAP:
+      gdk_drawable_get_size (GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap,
+                          &width, &height);
+      requisition->width += width;
+      requisition->height = MAX (requisition->height, height);
+      break;
+      
+    default:
+      break;
+    }
+
+  requisition->width  += clist_row->cell[column].horizontal;
+  requisition->height += clist_row->cell[column].vertical;
+}
+
+/* PUBLIC INSERT/REMOVE ROW FUNCTIONS
+ *   gtk_cmclist_prepend
+ *   gtk_cmclist_append
+ *   gtk_cmclist_insert
+ *   gtk_cmclist_remove
+ *   gtk_cmclist_clear
+ */
+gint
+gtk_cmclist_prepend (GtkCMCList    *clist,
+                  gchar       *text[])
+{
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), -1);
+  g_return_val_if_fail (text != NULL, -1);
+
+  return GTK_CMCLIST_GET_CLASS (clist)->insert_row (clist, 0, text);
+}
+
+gint
+gtk_cmclist_append (GtkCMCList    *clist,
+                 gchar       *text[])
+{
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), -1);
+  g_return_val_if_fail (text != NULL, -1);
+
+  return GTK_CMCLIST_GET_CLASS (clist)->insert_row (clist, clist->rows, text);
+}
+
+gint
+gtk_cmclist_insert (GtkCMCList    *clist,
+                 gint         row,
+                 gchar       *text[])
+{
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), -1);
+  g_return_val_if_fail (text != NULL, -1);
+
+  if (row < 0 || row > clist->rows)
+    row = clist->rows;
+
+  return GTK_CMCLIST_GET_CLASS (clist)->insert_row (clist, row, text);
+}
+
+void
+gtk_cmclist_remove (GtkCMCList *clist,
+                 gint      row)
+{
+  GTK_CMCLIST_GET_CLASS (clist)->remove_row (clist, row);
+}
+
+void
+gtk_cmclist_clear (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  
+  GTK_CMCLIST_GET_CLASS (clist)->clear (clist);
+}
+
+/* PRIVATE INSERT/REMOVE ROW FUNCTIONS
+ *   real_insert_row
+ *   real_remove_row
+ *   real_clear
+ *   real_row_move
+ */
+static gint
+real_insert_row (GtkCMCList *clist,
+                gint      row,
+                gchar    *text[])
+{
+  gint i;
+  GtkCMCListRow *clist_row;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), -1);
+  g_return_val_if_fail (text != NULL, -1);
+
+  /* return if out of bounds */
+  if (row < 0 || row > clist->rows)
+    return -1;
+
+  /* create the row */
+  clist_row = row_new (clist);
+
+  /* set the text in the row's columns */
+  for (i = 0; i < clist->columns; i++)
+    if (text[i])
+      GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+       (clist, clist_row, i, GTK_CMCELL_TEXT, text[i], 0, NULL ,NULL);
+
+  if (!clist->rows)
+    {
+      clist->row_list = g_list_append (clist->row_list, clist_row);
+      clist->row_list_end = clist->row_list;
+    }
+  else
+    {
+      if (GTK_CMCLIST_AUTO_SORT(clist))   /* override insertion pos */
+       {
+         GList *work;
+         
+         row = 0;
+         work = clist->row_list;
+         
+         if (clist->sort_type == GTK_SORT_ASCENDING)
+           {
+             while (row < clist->rows &&
+                    clist->compare (clist, clist_row,
+                                    GTK_CMCLIST_ROW (work)) > 0)
+               {
+                 row++;
+                 work = work->next;
+               }
+           }
+         else
+           {
+             while (row < clist->rows &&
+                    clist->compare (clist, clist_row,
+                                    GTK_CMCLIST_ROW (work)) < 0)
+               {
+                 row++;
+                 work = work->next;
+               }
+           }
+       }
+      
+      /* reset the row end pointer if we're inserting at the end of the list */
+      if (row == clist->rows)
+       clist->row_list_end = (g_list_append (clist->row_list_end,
+                                             clist_row))->next;
+      else
+       clist->row_list = g_list_insert (clist->row_list, clist_row, row);
+
+    }
+  clist->rows++;
+
+  if (row < ROW_FROM_YPIXEL (clist, 0))
+    clist->voffset -= (clist->row_height + CELL_SPACING);
+
+  /* syncronize the selection list */
+  sync_selection (clist, row, SYNC_INSERT);
+
+  if (clist->rows == 1)
+    {
+      clist->focus_row = 0;
+      if (clist->selection_mode == GTK_SELECTION_BROWSE)
+       gtk_cmclist_select_row (clist, 0, -1);
+    }
+
+  /* redraw the list if it isn't frozen */
+  if (CLIST_UNFROZEN (clist))
+    {
+      adjust_adjustments (clist, FALSE);
+
+      if (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+       draw_rows (clist, NULL);
+    }
+
+  return row;
+}
+
+static void
+real_remove_row (GtkCMCList *clist,
+                gint      row)
+{
+  gint was_visible;
+  GList *list;
+  GtkCMCListRow *clist_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  /* return if out of bounds */
+  if (row < 0 || row > (clist->rows - 1))
+    return;
+
+  was_visible = (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
+
+  /* get the row we're going to delete */
+  list = ROW_ELEMENT (clist, row);
+  g_assert (list != NULL);
+  clist_row = list->data;
+
+  /* if we're removing a selected row, we have to make sure
+   * it's properly unselected, and then sync up the clist->selected
+   * list to reflect the deincrimented indexies of rows after the
+   * removal */
+  if (clist_row->state == GTK_STATE_SELECTED)
+    g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+                    row, -1, NULL);
+
+  sync_selection (clist, row, SYNC_REMOVE);
+
+  /* reset the row end pointer if we're removing at the end of the list */
+  clist->rows--;
+  if (clist->row_list == list)
+    clist->row_list = g_list_next (list);
+  if (clist->row_list_end == list)
+    clist->row_list_end = g_list_previous (list);
+  list = g_list_remove (list, clist_row);
+
+  if (row < ROW_FROM_YPIXEL (clist, 0))
+    clist->voffset += clist->row_height + CELL_SPACING;
+
+  if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection &&
+      clist->focus_row >= 0)
+    g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+                    clist->focus_row, -1, NULL);
+
+  /* toast the row */
+  row_delete (clist, clist_row);
+
+  /* redraw the row if it isn't frozen */
+  if (CLIST_UNFROZEN (clist))
+    {
+      adjust_adjustments (clist, FALSE);
+
+      if (was_visible)
+       draw_rows (clist, NULL);
+    }
+}
+
+static void
+real_clear (GtkCMCList *clist)
+{
+  GList *list;
+  GList *free_list;
+  gint i;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  /* free up the selection list */
+  g_list_free (clist->selection);
+  g_list_free (clist->undo_selection);
+  g_list_free (clist->undo_unselection);
+
+  clist->selection = NULL;
+  clist->selection_end = NULL;
+  clist->undo_selection = NULL;
+  clist->undo_unselection = NULL;
+  clist->voffset = 0;
+  clist->focus_row = -1;
+  clist->anchor = -1;
+  clist->undo_anchor = -1;
+  clist->anchor_state = GTK_STATE_SELECTED;
+  clist->drag_pos = -1;
+
+  /* remove all the rows */
+  GTK_CMCLIST_SET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+  free_list = clist->row_list;
+  clist->row_list = NULL;
+  clist->row_list_end = NULL;
+  clist->rows = 0;
+  for (list = free_list; list; list = list->next)
+    row_delete (clist, GTK_CMCLIST_ROW (list));
+  g_list_free (free_list);
+  GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].auto_resize)
+      {
+       if (GTK_CMCLIST_SHOW_TITLES(clist) && clist->column[i].button)
+         gtk_cmclist_set_column_width
+           (clist, i, (clist->column[i].button->requisition.width -
+                       (CELL_SPACING + (2 * COLUMN_INSET))));
+       else
+         gtk_cmclist_set_column_width (clist, i, 0);
+      }
+  /* zero-out the scrollbars */
+  if (clist->vadjustment)
+    {
+      gtk_adjustment_set_value (clist->vadjustment, 0.0);
+      CLIST_REFRESH (clist);
+    }
+  else
+    gtk_widget_queue_resize (GTK_WIDGET (clist));
+}
+
+static void
+real_row_move (GtkCMCList *clist,
+              gint      source_row,
+              gint      dest_row)
+{
+  GtkCMCListRow *clist_row;
+  GList *list;
+  gint first, last;
+  gint d;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (GTK_CMCLIST_AUTO_SORT(clist))
+    return;
+
+  if (source_row < 0 || source_row >= clist->rows ||
+      dest_row   < 0 || dest_row   >= clist->rows ||
+      source_row == dest_row)
+    return;
+
+  gtk_cmclist_freeze (clist);
+
+  /* unlink source row */
+  clist_row = ROW_ELEMENT (clist, source_row)->data;
+  if (source_row == clist->rows - 1)
+    clist->row_list_end = clist->row_list_end->prev;
+  clist->row_list = g_list_remove (clist->row_list, clist_row);
+  clist->rows--;
+
+  /* relink source row */
+  clist->row_list = g_list_insert (clist->row_list, clist_row, dest_row);
+  if (dest_row == clist->rows)
+    clist->row_list_end = clist->row_list_end->next;
+  clist->rows++;
+
+  /* sync selection */
+  if (source_row > dest_row)
+    {
+      first = dest_row;
+      last  = source_row;
+      d = 1;
+    }
+  else
+    {
+      first = source_row;
+      last  = dest_row;
+      d = -1;
+    }
+
+  for (list = clist->selection; list; list = list->next)
+    {
+      if (list->data == GINT_TO_POINTER (source_row))
+       list->data = GINT_TO_POINTER (dest_row);
+      else if (first <= GPOINTER_TO_INT (list->data) &&
+              last >= GPOINTER_TO_INT (list->data))
+       list->data = GINT_TO_POINTER (GPOINTER_TO_INT (list->data) + d);
+    }
+  
+  if (clist->focus_row == source_row)
+    clist->focus_row = dest_row;
+  else if (clist->focus_row > first)
+    clist->focus_row += d;
+
+  gtk_cmclist_thaw (clist);
+}
+
+/* PUBLIC ROW FUNCTIONS
+ *   gtk_cmclist_moveto
+ *   gtk_cmclist_set_row_height
+ *   gtk_cmclist_set_row_data
+ *   gtk_cmclist_set_row_data_full
+ *   gtk_cmclist_get_row_data
+ *   gtk_cmclist_find_row_from_data
+ *   gtk_cmclist_swap_rows
+ *   gtk_cmclist_row_move
+ *   gtk_cmclist_row_is_visible
+ *   gtk_cmclist_set_foreground
+ *   gtk_cmclist_set_background
+ */
+void
+gtk_cmclist_moveto (GtkCMCList *clist,
+                 gint      row,
+                 gint      column,
+                 gfloat    row_align,
+                 gfloat    col_align)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < -1 || row >= clist->rows)
+    return;
+  if (column < -1 || column >= clist->columns)
+    return;
+
+  row_align = CLAMP (row_align, 0, 1);
+  col_align = CLAMP (col_align, 0, 1);
+
+  /* adjust horizontal scrollbar */
+  if (clist->hadjustment && column >= 0)
+    {
+      gint x;
+
+      x = (COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
+          (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
+                        CELL_SPACING - clist->column[column].area.width)));
+      if (x < 0)
+       gtk_adjustment_set_value (clist->hadjustment, 0.0);
+      else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
+       gtk_adjustment_set_value 
+         (clist->hadjustment, LIST_WIDTH (clist) - clist->clist_window_width);
+      else
+       gtk_adjustment_set_value (clist->hadjustment, x);
+    }
+
+  /* adjust vertical scrollbar */
+  if (clist->vadjustment && row >= 0)
+    move_vertical (clist, row, row_align);
+}
+
+void
+gtk_cmclist_set_row_height (GtkCMCList *clist,
+                         guint     height)
+{
+  GtkWidget *widget;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  widget = GTK_WIDGET (clist);
+
+  if (height > 0)
+    {
+      clist->row_height = height;
+      GTK_CMCLIST_SET_FLAG (clist, CMCLIST_ROW_HEIGHT_SET);
+    }
+  else
+    {
+      GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_ROW_HEIGHT_SET);
+      clist->row_height = 0;
+    }
+
+  if (widget->style->font_desc)
+    {
+      PangoContext *context = gtk_widget_get_pango_context (widget);
+      PangoFontMetrics *metrics;
+
+      metrics = pango_context_get_metrics (context,
+                                          widget->style->font_desc,
+                                          pango_context_get_language (context));
+      
+      if (!GTK_CMCLIST_ROW_HEIGHT_SET(clist))
+       {
+         clist->row_height = (pango_font_metrics_get_ascent (metrics) +
+                              pango_font_metrics_get_descent (metrics));
+         clist->row_height = PANGO_PIXELS (clist->row_height);
+       }
+
+      pango_font_metrics_unref (metrics);
+    }
+      
+  CLIST_REFRESH (clist);
+}
+
+void
+gtk_cmclist_set_row_data (GtkCMCList *clist,
+                       gint      row,
+                       gpointer  data)
+{
+  gtk_cmclist_set_row_data_full (clist, row, data, NULL);
+}
+
+void
+gtk_cmclist_set_row_data_full (GtkCMCList         *clist,
+                            gint              row,
+                            gpointer          data,
+                            GtkDestroyNotify  destroy)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row > (clist->rows - 1))
+    return;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (clist_row->destroy)
+    clist_row->destroy (clist_row->data);
+  
+  clist_row->data = data;
+  clist_row->destroy = destroy;
+}
+
+gpointer
+gtk_cmclist_get_row_data (GtkCMCList *clist,
+                       gint      row)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+  if (row < 0 || row > (clist->rows - 1))
+    return NULL;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+  return clist_row->data;
+}
+
+gint
+gtk_cmclist_find_row_from_data (GtkCMCList *clist,
+                             gpointer  data)
+{
+  GList *list;
+  gint n;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), -1);
+
+  for (n = 0, list = clist->row_list; list; n++, list = list->next)
+    if (GTK_CMCLIST_ROW (list)->data == data)
+      return n;
+
+  return -1;
+}
+
+void 
+gtk_cmclist_swap_rows (GtkCMCList *clist,
+                    gint      row1, 
+                    gint      row2)
+{
+  gint first, last;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  g_return_if_fail (row1 != row2);
+
+  if (GTK_CMCLIST_AUTO_SORT(clist))
+    return;
+
+  gtk_cmclist_freeze (clist);
+
+  first = MIN (row1, row2);
+  last  = MAX (row1, row2);
+
+  gtk_cmclist_row_move (clist, last, first);
+  gtk_cmclist_row_move (clist, first + 1, last);
+  
+  gtk_cmclist_thaw (clist);
+}
+
+void
+gtk_cmclist_row_move (GtkCMCList *clist,
+                   gint      source_row,
+                   gint      dest_row)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (GTK_CMCLIST_AUTO_SORT(clist))
+    return;
+
+  if (source_row < 0 || source_row >= clist->rows ||
+      dest_row   < 0 || dest_row   >= clist->rows ||
+      source_row == dest_row)
+    return;
+
+  g_signal_emit (GTK_OBJECT (clist), clist_signals[ROW_MOVE], 0,
+                  source_row, dest_row);
+}
+
+GtkVisibility
+gtk_cmclist_row_is_visible (GtkCMCList *clist,
+                         gint      row)
+{
+  gint top;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+
+  if (row < 0 || row >= clist->rows)
+    return GTK_VISIBILITY_NONE;
+
+  if (clist->row_height == 0)
+    return GTK_VISIBILITY_NONE;
+
+  if (row < ROW_FROM_YPIXEL (clist, 0))
+    return GTK_VISIBILITY_NONE;
+
+  if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
+    return GTK_VISIBILITY_NONE;
+
+  top = ROW_TOP_YPIXEL (clist, row);
+
+  if ((top < 0)
+      || ((top + clist->row_height) >= clist->clist_window_height))
+    return GTK_VISIBILITY_PARTIAL;
+
+  return GTK_VISIBILITY_FULL;
+}
+
+void
+gtk_cmclist_set_foreground (GtkCMCList       *clist,
+                         gint            row,
+                         const GdkColor *color)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (color)
+    {
+      clist_row->foreground = *color;
+      clist_row->fg_set = TRUE;
+      if (GTK_WIDGET_REALIZED (clist))
+       gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (clist)),
+                        &clist_row->foreground, TRUE, TRUE);
+    }
+  else
+    clist_row->fg_set = FALSE;
+
+  if (CLIST_UNFROZEN (clist) && gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+    GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+}
+
+void
+gtk_cmclist_set_background (GtkCMCList       *clist,
+                         gint            row,
+                         const GdkColor *color)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (color)
+    {
+      clist_row->background = *color;
+      clist_row->bg_set = TRUE;
+      if (GTK_WIDGET_REALIZED (clist))
+       gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (clist)),
+                        &clist_row->background, TRUE, TRUE);
+    }
+  else
+    clist_row->bg_set = FALSE;
+
+  if (CLIST_UNFROZEN (clist)
+      && (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+    GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+}
+
+/* PUBLIC ROW/CELL STYLE FUNCTIONS
+ *   gtk_cmclist_set_cell_style
+ *   gtk_cmclist_get_cell_style
+ *   gtk_cmclist_set_row_style
+ *   gtk_cmclist_get_row_style
+ */
+void
+gtk_cmclist_set_cell_style (GtkCMCList *clist,
+                         gint      row,
+                         gint      column,
+                         GtkStyle *style)
+{
+  GtkRequisition requisition = { 0 };
+  GtkCMCListRow *clist_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (clist_row->cell[column].style == style)
+    return;
+
+  if (clist->column[column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+                                                  column, &requisition);
+
+  if (clist_row->cell[column].style)
+    {
+      if (GTK_WIDGET_REALIZED (clist))
+        gtk_style_detach (clist_row->cell[column].style);
+      g_object_unref (clist_row->cell[column].style);
+    }
+
+  clist_row->cell[column].style = style;
+
+  if (clist_row->cell[column].style)
+    {
+      g_object_ref (clist_row->cell[column].style);
+      
+      if (GTK_WIDGET_REALIZED (clist))
+        clist_row->cell[column].style =
+         gtk_style_attach (clist_row->cell[column].style,
+                           clist->clist_window);
+    }
+
+  column_auto_resize (clist, clist_row, column, requisition.width);
+
+  /* redraw the list if it's not frozen */
+  if (CLIST_UNFROZEN (clist))
+    {
+      if (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+       GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+    }
+}
+
+GtkStyle *
+gtk_cmclist_get_cell_style (GtkCMCList *clist,
+                         gint      row,
+                         gint      column)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+  if (row < 0 || row >= clist->rows || column < 0 || column >= clist->columns)
+    return NULL;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  return clist_row->cell[column].style;
+}
+
+void
+gtk_cmclist_set_row_style (GtkCMCList *clist,
+                        gint      row,
+                        GtkStyle *style)
+{
+  GtkRequisition requisition;
+  GtkCMCListRow *clist_row;
+  gint *old_width;
+  gint i;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (clist_row->style == style)
+    return;
+
+  old_width = g_new (gint, clist->columns);
+
+  if (!GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].auto_resize)
+         {
+           GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+                                                          i, &requisition);
+           old_width[i] = requisition.width;
+         }
+    }
+
+  if (clist_row->style)
+    {
+      if (GTK_WIDGET_REALIZED (clist))
+        gtk_style_detach (clist_row->style);
+      g_object_unref (clist_row->style);
+    }
+
+  clist_row->style = style;
+
+  if (clist_row->style)
+    {
+      g_object_ref (clist_row->style);
+      
+      if (GTK_WIDGET_REALIZED (clist))
+        clist_row->style = gtk_style_attach (clist_row->style,
+                                            clist->clist_window);
+    }
+
+  if (GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    for (i = 0; i < clist->columns; i++)
+      column_auto_resize (clist, clist_row, i, old_width[i]);
+
+  g_free (old_width);
+
+  /* redraw the list if it's not frozen */
+  if (CLIST_UNFROZEN (clist))
+    {
+      if (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+       GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+    }
+}
+
+GtkStyle *
+gtk_cmclist_get_row_style (GtkCMCList *clist,
+                        gint      row)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), NULL);
+
+  if (row < 0 || row >= clist->rows)
+    return NULL;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  return clist_row->style;
+}
+
+/* PUBLIC SELECTION FUNCTIONS
+ *   gtk_cmclist_set_selectable
+ *   gtk_cmclist_get_selectable
+ *   gtk_cmclist_select_row
+ *   gtk_cmclist_unselect_row
+ *   gtk_cmclist_select_all
+ *   gtk_cmclist_unselect_all
+ *   gtk_cmclist_undo_selection
+ */
+void
+gtk_cmclist_set_selectable (GtkCMCList *clist,
+                         gint      row,
+                         gboolean  selectable)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (selectable == clist_row->selectable)
+    return;
+
+  clist_row->selectable = selectable;
+
+  if (!selectable && clist_row->state == GTK_STATE_SELECTED)
+    {
+      if (clist->anchor >= 0 &&
+         clist->selection_mode == GTK_SELECTION_MULTIPLE)
+       {
+         clist->drag_button = 0;
+         remove_grab (clist);
+         GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+       }
+      g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+                      row, -1, NULL);
+    }      
+}
+
+gboolean
+gtk_cmclist_get_selectable (GtkCMCList *clist,
+                         gint      row)
+{
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), FALSE);
+
+  if (row < 0 || row >= clist->rows)
+    return FALSE;
+
+  return GTK_CMCLIST_ROW (ROW_ELEMENT (clist, row))->selectable;
+}
+
+void
+gtk_cmclist_select_row (GtkCMCList *clist,
+                     gint      row,
+                     gint      column)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < -1 || column >= clist->columns)
+    return;
+
+  g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+                  row, column, NULL);
+}
+
+void
+gtk_cmclist_unselect_row (GtkCMCList *clist,
+                       gint      row,
+                       gint      column)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < -1 || column >= clist->columns)
+    return;
+
+  g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+                  row, column, NULL);
+}
+
+void
+gtk_cmclist_select_all (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  GTK_CMCLIST_GET_CLASS (clist)->select_all (clist);
+}
+
+void
+gtk_cmclist_unselect_all (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  GTK_CMCLIST_GET_CLASS (clist)->unselect_all (clist);
+}
+
+void
+gtk_cmclist_undo_selection (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (clist->selection_mode == GTK_SELECTION_MULTIPLE &&
+      (clist->undo_selection || clist->undo_unselection))
+    g_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION], 0);
+}
+
+/* PRIVATE SELECTION FUNCTIONS
+ *   selection_find
+ *   toggle_row
+ *   fake_toggle_row
+ *   toggle_focus_row
+ *   toggle_add_mode
+ *   real_select_row
+ *   real_unselect_row
+ *   real_select_all
+ *   real_unselect_all
+ *   fake_unselect_all
+ *   real_undo_selection
+ *   set_anchor
+ *   resync_selection
+ *   update_extended_selection
+ *   start_selection
+ *   end_selection
+ *   extend_selection
+ *   sync_selection
+ */
+static GList *
+selection_find (GtkCMCList *clist,
+               gint      row_number,
+               GList    *row_list_element)
+{
+  return g_list_find (clist->selection, GINT_TO_POINTER (row_number));
+}
+
+static void
+toggle_row (GtkCMCList *clist,
+           gint      row,
+           gint      column,
+           GdkEvent *event)
+{
+  GtkCMCListRow *clist_row;
+
+  switch (clist->selection_mode)
+    {
+    case GTK_SELECTION_MULTIPLE:
+    case GTK_SELECTION_SINGLE:
+      clist_row = ROW_ELEMENT (clist, row)->data;
+
+      if (!clist_row)
+       return;
+
+      if (clist_row->state == GTK_STATE_SELECTED)
+       {
+         g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+                          row, column, event);
+         return;
+       }
+    case GTK_SELECTION_BROWSE:
+      g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+                      row, column, event);
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+fake_toggle_row (GtkCMCList *clist,
+                gint      row)
+{
+  GList *work;
+
+  work = ROW_ELEMENT (clist, row);
+
+  if (!work || !GTK_CMCLIST_ROW (work)->selectable)
+    return;
+  
+  if (GTK_CMCLIST_ROW (work)->state == GTK_STATE_NORMAL)
+    clist->anchor_state = GTK_CMCLIST_ROW (work)->state = GTK_STATE_SELECTED;
+  else
+    clist->anchor_state = GTK_CMCLIST_ROW (work)->state = GTK_STATE_NORMAL;
+  
+  if (CLIST_UNFROZEN (clist) &&
+      gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+    GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row,
+                                         GTK_CMCLIST_ROW (work));
+}
+
+static gboolean
+clist_has_grab (GtkCMCList *clist)
+{
+  return (GTK_WIDGET_HAS_GRAB (clist) &&
+         gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))));
+}
+
+static void
+toggle_focus_row (GtkCMCList *clist)
+{
+  g_return_if_fail (clist != 0);
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (clist_has_grab (clist) ||
+      clist->focus_row < 0 || clist->focus_row >= clist->rows)
+    return;
+
+  switch (clist->selection_mode)
+    {
+    case  GTK_SELECTION_SINGLE:
+      toggle_row (clist, clist->focus_row, 0, NULL);
+      break;
+    case GTK_SELECTION_MULTIPLE:
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+
+      clist->anchor = clist->focus_row;
+      clist->drag_pos = clist->focus_row;
+      clist->undo_anchor = clist->focus_row;
+      
+      if (GTK_CMCLIST_ADD_MODE(clist))
+       fake_toggle_row (clist, clist->focus_row);
+      else
+       GTK_CMCLIST_GET_CLASS (clist)->fake_unselect_all (clist,clist->focus_row);
+
+      GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+toggle_add_mode (GtkCMCList *clist)
+{
+  g_return_if_fail (clist != 0);
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  
+  if (clist_has_grab (clist) ||
+      clist->selection_mode != GTK_SELECTION_MULTIPLE)
+    return;
+
+  gtk_cmclist_draw_focus (GTK_WIDGET (clist));
+  if (!GTK_CMCLIST_ADD_MODE(clist))
+    {
+      GTK_CMCLIST_SET_FLAG (clist, CMCLIST_ADD_MODE);
+      gdk_gc_set_line_attributes (clist->xor_gc, 1,
+                                 GDK_LINE_ON_OFF_DASH, 0, 0);
+      gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
+    }
+  else
+    {
+      GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_ADD_MODE);
+      gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
+      clist->anchor_state = GTK_STATE_SELECTED;
+    }
+  gtk_cmclist_draw_focus (GTK_WIDGET (clist));
+}
+
+static void
+real_select_row (GtkCMCList *clist,
+                gint      row,
+                gint      column,
+                GdkEvent *event)
+{
+  GtkCMCListRow *clist_row;
+  GList *list;
+  gint sel_row;
+  gboolean row_selected;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row > (clist->rows - 1))
+    return;
+
+  switch (clist->selection_mode)
+    {
+    case GTK_SELECTION_SINGLE:
+    case GTK_SELECTION_BROWSE:
+
+      row_selected = FALSE;
+      list = clist->selection;
+
+      while (list)
+       {
+         sel_row = GPOINTER_TO_INT (list->data);
+         list = list->next;
+
+         if (row == sel_row)
+           row_selected = TRUE;
+         else
+           g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+                            sel_row, column, event);
+       }
+
+      if (row_selected)
+       return;
+      
+    default:
+      break;
+    }
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (clist_row->state != GTK_STATE_NORMAL || !clist_row->selectable)
+    return;
+
+  clist_row->state = GTK_STATE_SELECTED;
+  if (!clist->selection)
+    {
+      clist->selection = g_list_append (clist->selection,
+                                       GINT_TO_POINTER (row));
+      clist->selection_end = clist->selection;
+    }
+  else
+    clist->selection_end = 
+      g_list_append (clist->selection_end, GINT_TO_POINTER (row))->next;
+  
+  if (CLIST_UNFROZEN (clist)
+      && (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+    GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+}
+
+static void
+real_unselect_row (GtkCMCList *clist,
+                  gint      row,
+                  gint      column,
+                  GdkEvent *event)
+{
+  GtkCMCListRow *clist_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (row < 0 || row > (clist->rows - 1))
+    return;
+
+  clist_row = ROW_ELEMENT (clist, row)->data;
+
+  if (clist_row->state == GTK_STATE_SELECTED)
+    {
+      clist_row->state = GTK_STATE_NORMAL;
+
+      if (clist->selection_end && 
+         clist->selection_end->data == GINT_TO_POINTER (row))
+       clist->selection_end = clist->selection_end->prev;
+
+      clist->selection = g_list_remove (clist->selection,
+                                       GINT_TO_POINTER (row));
+      
+      if (CLIST_UNFROZEN (clist)
+         && (gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+       GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
+    }
+}
+
+static void
+real_select_all (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (clist_has_grab (clist))
+    return;
+
+  switch (clist->selection_mode)
+    {
+    case GTK_SELECTION_SINGLE:
+    case GTK_SELECTION_BROWSE:
+      return;
+
+    case GTK_SELECTION_MULTIPLE:
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+         
+      if (clist->rows &&
+         ((GtkCMCListRow *) (clist->row_list->data))->state !=
+         GTK_STATE_SELECTED)
+       fake_toggle_row (clist, 0);
+
+      clist->anchor_state =  GTK_STATE_SELECTED;
+      clist->anchor = 0;
+      clist->drag_pos = 0;
+      clist->undo_anchor = clist->focus_row;
+      update_extended_selection (clist, clist->rows);
+      GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+      return;
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+real_unselect_all (GtkCMCList *clist)
+{
+  GList *list;
+  gint i;
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (clist_has_grab (clist))
+    return;
+
+  switch (clist->selection_mode)
+    {
+    case GTK_SELECTION_BROWSE:
+      if (clist->focus_row >= 0)
+       {
+         g_signal_emit (GTK_OBJECT (clist),
+                          clist_signals[SELECT_ROW], 0,
+                          clist->focus_row, -1, NULL);
+         return;
+       }
+      break;
+    case GTK_SELECTION_MULTIPLE:
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+
+      clist->anchor = -1;
+      clist->drag_pos = -1;
+      clist->undo_anchor = clist->focus_row;
+      break;
+    default:
+      break;
+    }
+
+  list = clist->selection;
+  while (list)
+    {
+      i = GPOINTER_TO_INT (list->data);
+      list = list->next;
+      g_signal_emit (GTK_OBJECT (clist),
+                      clist_signals[UNSELECT_ROW], 0, i, -1, NULL);
+    }
+}
+
+static void
+fake_unselect_all (GtkCMCList *clist,
+                  gint      row)
+{
+  GList *list;
+  GList *work;
+  gint i;
+
+  if (row >= 0 && (work = ROW_ELEMENT (clist, row)))
+    {
+      if (GTK_CMCLIST_ROW (work)->state == GTK_STATE_NORMAL &&
+         GTK_CMCLIST_ROW (work)->selectable)
+       {
+         GTK_CMCLIST_ROW (work)->state = GTK_STATE_SELECTED;
+         
+         if (CLIST_UNFROZEN (clist) &&
+             gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+           GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row,
+                                                 GTK_CMCLIST_ROW (work));
+       }  
+    }
+
+  clist->undo_selection = clist->selection;
+  clist->selection = NULL;
+  clist->selection_end = NULL;
+
+  for (list = clist->undo_selection; list; list = list->next)
+    {
+      if ((i = GPOINTER_TO_INT (list->data)) == row ||
+         !(work = g_list_nth (clist->row_list, i)))
+       continue;
+
+      GTK_CMCLIST_ROW (work)->state = GTK_STATE_NORMAL;
+      if (CLIST_UNFROZEN (clist) &&
+         gtk_cmclist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
+       GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, i,
+                                             GTK_CMCLIST_ROW (work));
+    }
+}
+
+static void
+real_undo_selection (GtkCMCList *clist)
+{
+  GList *work;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (clist_has_grab (clist) ||
+      clist->selection_mode != GTK_SELECTION_MULTIPLE)
+    return;
+
+  GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+  if (!(clist->undo_selection || clist->undo_unselection))
+    {
+      gtk_cmclist_unselect_all (clist);
+      return;
+    }
+
+  for (work = clist->undo_selection; work; work = work->next)
+    g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+                    GPOINTER_TO_INT (work->data), -1, NULL);
+
+  for (work = clist->undo_unselection; work; work = work->next)
+    {
+      /* g_print ("unselect %d\n",GPOINTER_TO_INT (work->data)); */
+      g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+                      GPOINTER_TO_INT (work->data), -1, NULL);
+    }
+
+  if (GTK_WIDGET_HAS_FOCUS(clist) && clist->focus_row != clist->undo_anchor)
+    {
+      gtk_cmclist_draw_focus (GTK_WIDGET (clist));
+      clist->focus_row = clist->undo_anchor;
+      gtk_cmclist_draw_focus (GTK_WIDGET (clist));
+    }
+  else
+    clist->focus_row = clist->undo_anchor;
+  
+  clist->undo_anchor = -1;
+  g_list_free (clist->undo_selection);
+  g_list_free (clist->undo_unselection);
+  clist->undo_selection = NULL;
+  clist->undo_unselection = NULL;
+
+  if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
+      clist->clist_window_height)
+    gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+  else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+    gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+}
+
+static void
+set_anchor (GtkCMCList *clist,
+           gboolean  add_mode,
+           gint      anchor,
+           gint      undo_anchor)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  
+  if (clist->selection_mode != GTK_SELECTION_MULTIPLE || clist->anchor >= 0)
+    return;
+
+  g_list_free (clist->undo_selection);
+  g_list_free (clist->undo_unselection);
+  clist->undo_selection = NULL;
+  clist->undo_unselection = NULL;
+
+  if (add_mode)
+    fake_toggle_row (clist, anchor);
+  else
+    {
+      GTK_CMCLIST_GET_CLASS (clist)->fake_unselect_all (clist, anchor);
+      clist->anchor_state = GTK_STATE_SELECTED;
+    }
+
+  clist->anchor = anchor;
+  clist->drag_pos = anchor;
+  clist->undo_anchor = undo_anchor;
+}
+
+static void
+resync_selection (GtkCMCList *clist,
+                 GdkEvent *event)
+{
+  gint i;
+  gint e;
+  gint row;
+  GList *list;
+  GtkCMCListRow *clist_row;
+
+  if (clist->selection_mode != GTK_SELECTION_MULTIPLE)
+    return;
+
+  if (clist->anchor < 0 || clist->drag_pos < 0)
+    return;
+
+  gtk_cmclist_freeze (clist);
+
+  i = MIN (clist->anchor, clist->drag_pos);
+  e = MAX (clist->anchor, clist->drag_pos);
+
+  if (clist->undo_selection)
+    {
+      list = clist->selection;
+      clist->selection = clist->undo_selection;
+      clist->selection_end = g_list_last (clist->selection);
+      clist->undo_selection = list;
+      list = clist->selection;
+      while (list)
+       {
+         row = GPOINTER_TO_INT (list->data);
+         list = list->next;
+         if (row < i || row > e)
+           {
+             clist_row = g_list_nth (clist->row_list, row)->data;
+             if (clist_row->selectable)
+               {
+                 clist_row->state = GTK_STATE_SELECTED;
+                 g_signal_emit (GTK_OBJECT (clist),
+                                  clist_signals[UNSELECT_ROW], 0,
+                                  row, -1, event);
+                 clist->undo_selection = g_list_prepend
+                   (clist->undo_selection, GINT_TO_POINTER (row));
+               }
+           }
+       }
+    }    
+
+  if (clist->anchor < clist->drag_pos)
+    {
+      for (list = g_list_nth (clist->row_list, i); i <= e;
+          i++, list = list->next)
+       if (GTK_CMCLIST_ROW (list)->selectable)
+         {
+           if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
+             {
+               if (GTK_CMCLIST_ROW (list)->state == GTK_STATE_NORMAL)
+                 {
+                   GTK_CMCLIST_ROW (list)->state = GTK_STATE_SELECTED;
+                   g_signal_emit (GTK_OBJECT (clist),
+                                    clist_signals[UNSELECT_ROW], 0,
+                                    i, -1, event);
+                   clist->undo_selection =
+                     g_list_prepend (clist->undo_selection,
+                                     GINT_TO_POINTER (i));
+                 }
+             }
+           else if (GTK_CMCLIST_ROW (list)->state == GTK_STATE_SELECTED)
+             {
+               GTK_CMCLIST_ROW (list)->state = GTK_STATE_NORMAL;
+               clist->undo_unselection =
+                 g_list_prepend (clist->undo_unselection,
+                                 GINT_TO_POINTER (i));
+             }
+         }
+    }
+  else
+    {
+      for (list = g_list_nth (clist->row_list, e); i <= e;
+          e--, list = list->prev)
+       if (GTK_CMCLIST_ROW (list)->selectable)
+         {
+           if (g_list_find (clist->selection, GINT_TO_POINTER(e)))
+             {
+               if (GTK_CMCLIST_ROW (list)->state == GTK_STATE_NORMAL)
+                 {
+                   GTK_CMCLIST_ROW (list)->state = GTK_STATE_SELECTED;
+                   g_signal_emit (GTK_OBJECT (clist),
+                                    clist_signals[UNSELECT_ROW], 0,
+                                    e, -1, event);
+                   clist->undo_selection =
+                     g_list_prepend (clist->undo_selection,
+                                     GINT_TO_POINTER (e));
+                 }
+             }
+           else if (GTK_CMCLIST_ROW (list)->state == GTK_STATE_SELECTED)
+             {
+               GTK_CMCLIST_ROW (list)->state = GTK_STATE_NORMAL;
+               clist->undo_unselection =
+                 g_list_prepend (clist->undo_unselection,
+                                 GINT_TO_POINTER (e));
+             }
+         }
+    }
+  
+  clist->undo_unselection = g_list_reverse (clist->undo_unselection);
+  for (list = clist->undo_unselection; list; list = list->next)
+    g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+                    GPOINTER_TO_INT (list->data), -1, event);
+
+  clist->anchor = -1;
+  clist->drag_pos = -1;
+
+  gtk_cmclist_thaw (clist);
+}
+
+static void
+update_extended_selection (GtkCMCList *clist,
+                          gint      row)
+{
+  gint i;
+  GList *list;
+  GdkRectangle area;
+  gint s1 = -1;
+  gint s2 = -1;
+  gint e1 = -1;
+  gint e2 = -1;
+  gint y1 = clist->clist_window_height;
+  gint y2 = clist->clist_window_height;
+  gint h1 = 0;
+  gint h2 = 0;
+  gint top;
+
+  if (clist->selection_mode != GTK_SELECTION_MULTIPLE || clist->anchor == -1)
+    return;
+
+  if (row < 0)
+    row = 0;
+  if (row >= clist->rows)
+    row = clist->rows - 1;
+
+  /* extending downwards */
+  if (row > clist->drag_pos && clist->anchor <= clist->drag_pos)
+    {
+      s2 = clist->drag_pos + 1;
+      e2 = row;
+    }
+  /* extending upwards */
+  else if (row < clist->drag_pos && clist->anchor >= clist->drag_pos)
+    {
+      s2 = row;
+      e2 = clist->drag_pos - 1;
+    }
+  else if (row < clist->drag_pos && clist->anchor < clist->drag_pos)
+    {
+      e1 = clist->drag_pos;
+      /* row and drag_pos on different sides of anchor :
+        take back the selection between anchor and drag_pos,
+         select between anchor and row */
+      if (row < clist->anchor)
+       {
+         s1 = clist->anchor + 1;
+         s2 = row;
+         e2 = clist->anchor - 1;
+       }
+      /* take back the selection between anchor and drag_pos */
+      else
+       s1 = row + 1;
+    }
+  else if (row > clist->drag_pos && clist->anchor > clist->drag_pos)
+    {
+      s1 = clist->drag_pos;
+      /* row and drag_pos on different sides of anchor :
+        take back the selection between anchor and drag_pos,
+         select between anchor and row */
+      if (row > clist->anchor)
+       {
+         e1 = clist->anchor - 1;
+         s2 = clist->anchor + 1;
+         e2 = row;
+       }
+      /* take back the selection between anchor and drag_pos */
+      else
+       e1 = row - 1;
+    }
+
+  clist->drag_pos = row;
+
+  area.x = 0;
+  area.width = clist->clist_window_width;
+
+  /* restore the elements between s1 and e1 */
+  if (s1 >= 0)
+    {
+      for (i = s1, list = g_list_nth (clist->row_list, i); i <= e1;
+          i++, list = list->next)
+       if (GTK_CMCLIST_ROW (list)->selectable)
+         {
+           if (GTK_CMCLIST_GET_CLASS (clist)->selection_find (clist, i, list))
+             GTK_CMCLIST_ROW (list)->state = GTK_STATE_SELECTED;
+           else
+             GTK_CMCLIST_ROW (list)->state = GTK_STATE_NORMAL;
+         }
+
+      top = ROW_TOP_YPIXEL (clist, clist->focus_row);
+
+      if (top + clist->row_height <= 0)
+       {
+         area.y = 0;
+         area.height = ROW_TOP_YPIXEL (clist, e1) + clist->row_height;
+         draw_rows (clist, &area);
+         gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+       }
+      else if (top >= clist->clist_window_height)
+       {
+         area.y = ROW_TOP_YPIXEL (clist, s1) - 1;
+         area.height = clist->clist_window_height - area.y;
+         draw_rows (clist, &area);
+         gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+       }
+      else if (top < 0)
+       gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+      else if (top + clist->row_height > clist->clist_window_height)
+       gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+
+      y1 = ROW_TOP_YPIXEL (clist, s1) - 1;
+      h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
+    }
+
+  /* extend the selection between s2 and e2 */
+  if (s2 >= 0)
+    {
+      for (i = s2, list = g_list_nth (clist->row_list, i); i <= e2;
+          i++, list = list->next)
+       if (GTK_CMCLIST_ROW (list)->selectable &&
+           GTK_CMCLIST_ROW (list)->state != clist->anchor_state)
+         GTK_CMCLIST_ROW (list)->state = clist->anchor_state;
+
+      top = ROW_TOP_YPIXEL (clist, clist->focus_row);
+
+      if (top + clist->row_height <= 0)
+       {
+         area.y = 0;
+         area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
+         draw_rows (clist, &area);
+         gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+       }
+      else if (top >= clist->clist_window_height)
+       {
+         area.y = ROW_TOP_YPIXEL (clist, s2) - 1;
+         area.height = clist->clist_window_height - area.y;
+         draw_rows (clist, &area);
+         gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+       }
+      else if (top < 0)
+       gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+      else if (top + clist->row_height > clist->clist_window_height)
+       gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+
+      y2 = ROW_TOP_YPIXEL (clist, s2) - 1;
+      h2 = (e2 - s2 + 1) * (clist->row_height + CELL_SPACING);
+    }
+
+  area.y = MAX (0, MIN (y1, y2));
+  if (area.y > clist->clist_window_height)
+    area.y = 0;
+  area.height = MIN (clist->clist_window_height, h1 + h2);
+  if (s1 >= 0 && s2 >= 0)
+    area.height += (clist->row_height + CELL_SPACING);
+  draw_rows (clist, &area);
+}
+
+static void
+start_selection (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (clist_has_grab (clist))
+    return;
+
+  set_anchor (clist, GTK_CMCLIST_ADD_MODE(clist), clist->focus_row,
+             clist->focus_row);
+}
+
+static void
+end_selection (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))) &&
+      GTK_WIDGET_HAS_FOCUS (clist))
+    return;
+
+  GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+}
+
+static void
+extend_selection (GtkCMCList      *clist,
+                 GtkScrollType  scroll_type,
+                 gfloat         position,
+                 gboolean       auto_start_selection)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (clist_has_grab (clist) ||
+      clist->selection_mode != GTK_SELECTION_MULTIPLE)
+    return;
+
+  if (auto_start_selection)
+    set_anchor (clist, GTK_CMCLIST_ADD_MODE(clist), clist->focus_row,
+               clist->focus_row);
+  else if (clist->anchor == -1)
+    return;
+
+  move_focus_row (clist, scroll_type, position);
+
+  if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
+      clist->clist_window_height)
+    gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+  else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+    gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+
+  update_extended_selection (clist, clist->focus_row);
+}
+
+static void
+sync_selection (GtkCMCList *clist,
+               gint      row,
+               gint      mode)
+{
+  GList *list;
+  gint d;
+
+  if (mode == SYNC_INSERT)
+    d = 1;
+  else
+    d = -1;
+      
+  if (clist->focus_row >= row)
+    {
+      if (d > 0 || clist->focus_row > row)
+       clist->focus_row += d;
+      if (clist->focus_row == -1 && clist->rows >= 1)
+       clist->focus_row = 0;
+      else if (d < 0 && clist->focus_row >= clist->rows - 1)
+       clist->focus_row = clist->rows - 2;
+      else if (clist->focus_row >= clist->rows)        /* Paranoia */
+       clist->focus_row = clist->rows - 1;
+    }
+
+  GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+  g_list_free (clist->undo_selection);
+  g_list_free (clist->undo_unselection);
+  clist->undo_selection = NULL;
+  clist->undo_unselection = NULL;
+
+  clist->anchor = -1;
+  clist->drag_pos = -1;
+  clist->undo_anchor = clist->focus_row;
+
+  list = clist->selection;
+
+  while (list)
+    {
+      if (GPOINTER_TO_INT (list->data) >= row)
+       list->data = ((gchar*) list->data) + d;
+      list = list->next;
+    }
+}
+
+/* GTKOBJECT
+ *   gtk_cmclist_destroy
+ *   gtk_cmclist_finalize
+ */
+static void
+gtk_cmclist_destroy (GtkObject *object)
+{
+  gint i;
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCLIST (object));
+
+  clist = GTK_CMCLIST (object);
+
+  /* freeze the list */
+  clist->freeze_count++;
+
+  /* get rid of all the rows */
+  gtk_cmclist_clear (clist);
+
+  /* Since we don't have a _remove method, unparent the children
+   * instead of destroying them so the focus will be unset properly.
+   * (For other containers, the _remove method takes care of the
+   * unparent) The destroy will happen when the refcount drops
+   * to zero.
+   */
+
+  /* unref adjustments */
+  if (clist->hadjustment)
+    {
+      g_signal_handlers_disconnect_matched(GTK_OBJECT (clist->hadjustment), G_SIGNAL_MATCH_DATA,
+                       0, 0, 0, 0, clist);
+      g_object_unref (GTK_OBJECT (clist->hadjustment));
+      clist->hadjustment = NULL;
+    }
+  if (clist->vadjustment)
+    {
+      g_signal_handlers_disconnect_matched(GTK_OBJECT (clist->vadjustment), G_SIGNAL_MATCH_DATA,
+                       0, 0, 0, 0, clist);
+      g_object_unref (GTK_OBJECT (clist->vadjustment));
+      clist->vadjustment = NULL;
+    }
+
+  remove_grab (clist);
+
+  /* destroy the column buttons */
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].button)
+      {
+       gtk_widget_unparent (clist->column[i].button);
+       clist->column[i].button = NULL;
+      }
+
+  if (GTK_OBJECT_CLASS (parent_class)->destroy)
+    (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+gtk_cmclist_finalize (GObject *object)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCLIST (object));
+
+  clist = GTK_CMCLIST (object);
+
+  columns_delete (clist);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/* GTKWIDGET
+ *   gtk_cmclist_realize
+ *   gtk_cmclist_unrealize
+ *   gtk_cmclist_map
+ *   gtk_cmclist_unmap
+ *   gtk_cmclist_expose
+ *   gtk_cmclist_style_set
+ *   gtk_cmclist_button_press
+ *   gtk_cmclist_button_release
+ *   gtk_cmclist_motion
+ *   gtk_cmclist_size_request
+ *   gtk_cmclist_size_allocate
+ */
+static void
+gtk_cmclist_realize (GtkWidget *widget)
+{
+  GtkCMCList *clist;
+  GdkWindowAttr attributes;
+  GdkGCValues values;
+  GtkCMCListRow *clist_row;
+  GList *list;
+  gint attributes_mask;
+  gint border_width;
+  gint i;
+  gint j;
+
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+
+  clist = GTK_CMCLIST (widget);
+
+  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+  border_width = GTK_CONTAINER (widget)->border_width;
+  
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.x = widget->allocation.x + border_width;
+  attributes.y = widget->allocation.y + border_width;
+  attributes.width = widget->allocation.width - border_width * 2;
+  attributes.height = widget->allocation.height - border_width * 2;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+  attributes.visual = gtk_widget_get_visual (widget);
+  attributes.colormap = gtk_widget_get_colormap (widget);
+  attributes.event_mask = gtk_widget_get_events (widget);
+  attributes.event_mask |= (GDK_EXPOSURE_MASK |
+                           GDK_BUTTON_PRESS_MASK |
+                           GDK_BUTTON_RELEASE_MASK |
+                           GDK_KEY_RELEASE_MASK);
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+  /* main window */
+  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+                                  &attributes, attributes_mask);
+  gdk_window_set_user_data (widget->window, clist);
+
+  widget->style = gtk_style_attach (widget->style, widget->window);
+
+  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+
+  /* column-title window */
+
+  attributes.x = clist->column_title_area.x;
+  attributes.y = clist->column_title_area.y;
+  attributes.width = clist->column_title_area.width;
+  attributes.height = clist->column_title_area.height;
+  
+  clist->title_window = gdk_window_new (widget->window, &attributes,
+                                       attributes_mask);
+  gdk_window_set_user_data (clist->title_window, clist);
+
+  gtk_style_set_background (widget->style, clist->title_window,
+                           GTK_STATE_NORMAL);
+  gdk_window_show (clist->title_window);
+
+  /* set things up so column buttons are drawn in title window */
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].button)
+      gtk_widget_set_parent_window (clist->column[i].button,
+                                   clist->title_window);
+
+  /* clist-window */
+  attributes.x = (clist->internal_allocation.x +
+                 widget->style->xthickness);
+  attributes.y = (clist->internal_allocation.y +
+                 widget->style->ythickness +
+                 clist->column_title_area.height);
+  attributes.width = clist->clist_window_width;
+  attributes.height = clist->clist_window_height;
+  
+  clist->clist_window = gdk_window_new (widget->window, &attributes,
+                                       attributes_mask);
+  gdk_window_set_user_data (clist->clist_window, clist);
+
+  gdk_window_set_background (clist->clist_window,
+                            &widget->style->base[GTK_STATE_NORMAL]);
+  gdk_window_show (clist->clist_window);
+  gdk_drawable_get_size (clist->clist_window, &clist->clist_window_width,
+                      &clist->clist_window_height);
+
+  /* create resize windows */
+  attributes.wclass = GDK_INPUT_ONLY;
+  attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
+                          GDK_BUTTON_RELEASE_MASK |
+                          GDK_POINTER_MOTION_MASK |
+                          GDK_POINTER_MOTION_HINT_MASK);
+  attributes_mask = GDK_WA_CURSOR;
+  attributes.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
+                                                 GDK_SB_H_DOUBLE_ARROW);
+  clist->cursor_drag = attributes.cursor;
+
+  attributes.x =  LIST_WIDTH (clist) + 1;
+  attributes.y = 0;
+  attributes.width = 0;
+  attributes.height = 0;
+
+  for (i = 0; i < clist->columns; i++)
+    {
+      clist->column[i].window = gdk_window_new (clist->title_window,
+                                               &attributes, attributes_mask);
+      gdk_window_set_user_data (clist->column[i].window, clist);
+    }
+
+  /* This is slightly less efficient than creating them with the
+   * right size to begin with, but easier
+   */
+  size_allocate_title_buttons (clist);
+
+  /* GCs */
+  clist->fg_gc = gdk_gc_new (widget->window);
+  clist->bg_gc = gdk_gc_new (widget->window);
+  
+  /* We'll use this gc to do scrolling as well */
+  gdk_gc_set_exposures (clist->fg_gc, TRUE);
+
+  values.foreground = (widget->style->white.pixel==0 ?
+                      widget->style->black:widget->style->white);
+  values.function = GDK_XOR;
+  values.subwindow_mode = GDK_INCLUDE_INFERIORS;
+  clist->xor_gc = gdk_gc_new_with_values (widget->window,
+                                         &values,
+                                         GDK_GC_FOREGROUND |
+                                         GDK_GC_FUNCTION |
+                                         GDK_GC_SUBWINDOW);
+
+  /* attach optional row/cell styles, allocate foreground/background colors */
+  list = clist->row_list;
+  for (i = 0; i < clist->rows; i++)
+    {
+      clist_row = list->data;
+      list = list->next;
+
+      if (clist_row->style)
+       clist_row->style = gtk_style_attach (clist_row->style,
+                                            clist->clist_window);
+
+      if (clist_row->fg_set || clist_row->bg_set)
+       {
+         GdkColormap *colormap;
+
+         colormap = gtk_widget_get_colormap (widget);
+         if (clist_row->fg_set)
+           gdk_colormap_alloc_color (colormap, &clist_row->foreground, TRUE, TRUE);
+         if (clist_row->bg_set)
+           gdk_colormap_alloc_color (colormap, &clist_row->background, TRUE, TRUE);
+       }
+      
+      for (j = 0; j < clist->columns; j++)
+       if  (clist_row->cell[j].style)
+         clist_row->cell[j].style =
+           gtk_style_attach (clist_row->cell[j].style, clist->clist_window);
+    }
+}
+
+static void
+gtk_cmclist_unrealize (GtkWidget *widget)
+{
+  gint i;
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+
+  clist = GTK_CMCLIST (widget);
+
+  /* freeze the list */
+  clist->freeze_count++;
+
+  if (GTK_WIDGET_MAPPED (widget))
+    gtk_cmclist_unmap (widget);
+
+  GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+
+  /* detach optional row/cell styles */
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      GtkCMCListRow *clist_row;
+      GList *list;
+      gint j;
+
+      list = clist->row_list;
+      for (i = 0; i < clist->rows; i++)
+       {
+         clist_row = list->data;
+         list = list->next;
+
+         if (clist_row->style)
+           gtk_style_detach (clist_row->style);
+         for (j = 0; j < clist->columns; j++)
+           if  (clist_row->cell[j].style)
+             gtk_style_detach (clist_row->cell[j].style);
+       }
+    }
+
+  gdk_cursor_unref (clist->cursor_drag);
+  g_object_unref (clist->xor_gc);
+  g_object_unref (clist->fg_gc);
+  g_object_unref (clist->bg_gc);
+
+  for (i = 0; i < clist->columns; i++)
+    {
+      if (clist->column[i].button)
+       gtk_widget_unrealize (clist->column[i].button);
+      if (clist->column[i].window)
+       {
+         gdk_window_set_user_data (clist->column[i].window, NULL);
+         gdk_window_destroy (clist->column[i].window);
+         clist->column[i].window = NULL;
+       }
+    }
+
+  gdk_window_set_user_data (clist->clist_window, NULL);
+  gdk_window_destroy (clist->clist_window);
+  clist->clist_window = NULL;
+
+  gdk_window_set_user_data (clist->title_window, NULL);
+  gdk_window_destroy (clist->title_window);
+  clist->title_window = NULL;
+
+  clist->cursor_drag = NULL;
+  clist->xor_gc = NULL;
+  clist->fg_gc = NULL;
+  clist->bg_gc = NULL;
+
+  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
+gtk_cmclist_map (GtkWidget *widget)
+{
+  gint i;
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+
+  clist = GTK_CMCLIST (widget);
+
+  if (!GTK_WIDGET_MAPPED (widget))
+    {
+      GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+
+      /* map column buttons */
+      for (i = 0; i < clist->columns; i++)
+       {
+         if (clist->column[i].button &&
+             GTK_WIDGET_VISIBLE (clist->column[i].button) &&
+             !GTK_WIDGET_MAPPED (clist->column[i].button))
+           gtk_widget_map (clist->column[i].button);
+       }
+      
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].window && clist->column[i].button)
+         {
+           gdk_window_raise (clist->column[i].window);
+           gdk_window_show (clist->column[i].window);
+         }
+
+      gdk_window_show (clist->title_window);
+      gdk_window_show (clist->clist_window);
+      gdk_window_show (widget->window);
+
+      /* unfreeze the list */
+      clist->freeze_count = 0;
+    }
+}
+
+static void
+gtk_cmclist_unmap (GtkWidget *widget)
+{
+  gint i;
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+
+  clist = GTK_CMCLIST (widget);
+
+  if (GTK_WIDGET_MAPPED (widget))
+    {
+      GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+
+      if (clist_has_grab (clist))
+       {
+         remove_grab (clist);
+
+         GTK_CMCLIST_GET_CLASS (widget)->resync_selection (clist, NULL);
+
+         clist->click_cell.row = -1;
+         clist->click_cell.column = -1;
+         clist->drag_button = 0;
+
+         if (GTK_CMCLIST_IN_DRAG(clist))
+           {
+             gpointer drag_data;
+
+             GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_IN_DRAG);
+             drag_data = g_object_get_data (G_OBJECT (clist),
+                                              "gtk-site-data");
+             if (drag_data)
+               g_signal_handlers_unblock_matched(G_OBJECT(clist), G_SIGNAL_MATCH_DATA,
+                                       0, 0, 0, 0, drag_data);
+           }
+       }
+
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].window)
+         gdk_window_hide (clist->column[i].window);
+
+      gdk_window_hide (clist->clist_window);
+      gdk_window_hide (clist->title_window);
+      gdk_window_hide (widget->window);
+
+      /* unmap column buttons */
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].button &&
+           GTK_WIDGET_MAPPED (clist->column[i].button))
+         gtk_widget_unmap (clist->column[i].button);
+
+      /* freeze the list */
+      clist->freeze_count++;
+    }
+}
+
+static gint
+gtk_cmclist_expose (GtkWidget      *widget,
+                 GdkEventExpose *event)
+{
+  GtkCMCList *clist;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  if (GTK_WIDGET_DRAWABLE (widget))
+    {
+      clist = GTK_CMCLIST (widget);
+
+      /* draw border */
+      if (event->window == widget->window)
+       gtk_paint_shadow (widget->style, widget->window,
+                        GTK_STATE_NORMAL, clist->shadow_type,
+                        NULL, NULL, NULL,
+                        0, 0,
+                        clist->clist_window_width +
+                        (2 * widget->style->xthickness),
+                        clist->clist_window_height +
+                        (2 * widget->style->ythickness) +
+                        clist->column_title_area.height);
+
+      /* exposure events on the list */
+      if (event->window == clist->clist_window)
+       draw_rows (clist, &event->area);
+
+      if (event->window == clist->clist_window &&
+         clist->drag_highlight_row >= 0)
+       GTK_CMCLIST_GET_CLASS (clist)->draw_drag_highlight
+         (clist, g_list_nth (clist->row_list,
+                             clist->drag_highlight_row)->data,
+          clist->drag_highlight_row, clist->drag_highlight_pos);
+
+      if (event->window == clist->title_window)
+       {
+         gint i;
+         
+         for (i = 0; i < clist->columns; i++)
+           {
+             if (clist->column[i].button)
+               gtk_container_propagate_expose (GTK_CONTAINER (clist),
+                                               clist->column[i].button,
+                                               event);
+           }
+       }
+    }
+
+  return FALSE;
+}
+
+static void
+gtk_cmclist_style_set (GtkWidget *widget,
+                    GtkStyle  *previous_style)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+
+  if (GTK_WIDGET_CLASS (parent_class)->style_set)
+    (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
+
+  clist = GTK_CMCLIST (widget);
+
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      gtk_style_set_background (widget->style, widget->window, widget->state);
+      gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_NORMAL);
+      gdk_window_set_background (clist->clist_window, &widget->style->base[GTK_STATE_NORMAL]);
+    }
+
+  /* Fill in data after widget has correct style */
+
+  /* text properties */
+  if (!GTK_CMCLIST_ROW_HEIGHT_SET(clist))
+    /* Reset clist->row_height */
+    gtk_cmclist_set_row_height (clist, 0);
+
+  /* Column widths */
+  if (!GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      gint width;
+      gint i;
+
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].auto_resize)
+         {
+           width = gtk_cmclist_optimal_column_width (clist, i);
+           if (width != clist->column[i].width)
+             gtk_cmclist_set_column_width (clist, i, width);
+         }
+    }
+}
+
+static gint
+gtk_cmclist_button_press (GtkWidget      *widget,
+                       GdkEventButton *event)
+{
+  gint i;
+  GtkCMCList *clist;
+  gint x;
+  gint y;
+  gint row;
+  gint column;
+  gint button_actions;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  clist = GTK_CMCLIST (widget);
+
+  button_actions = clist->button_actions[event->button - 1];
+
+  if (button_actions == GTK_CMBUTTON_IGNORED)
+    return FALSE;
+
+  /* selections on the list */
+  if (event->window == clist->clist_window)
+    {
+      x = event->x;
+      y = event->y;
+
+      if (get_selection_info (clist, x, y, &row, &column))
+       {
+         gint old_row = clist->focus_row;
+
+         if (clist->focus_row == -1)
+           old_row = row;
+
+         if (event->type == GDK_BUTTON_PRESS)
+           {
+             GdkEventMask mask = ((1 << (4 + event->button)) |
+                                  GDK_POINTER_MOTION_HINT_MASK |
+                                  GDK_BUTTON_RELEASE_MASK);
+
+             if (gdk_pointer_grab (clist->clist_window, FALSE, mask,
+                                   NULL, NULL, event->time))
+               return FALSE;
+             gtk_grab_add (widget);
+
+             clist->click_cell.row = row;
+             clist->click_cell.column = column;
+             clist->drag_button = event->button;
+           }
+         else
+           {
+             clist->click_cell.row = -1;
+             clist->click_cell.column = -1;
+
+             clist->drag_button = 0;
+             remove_grab (clist);
+           }
+
+         if (button_actions & GTK_CMBUTTON_SELECTS)
+           {
+             if (GTK_CMCLIST_ADD_MODE(clist))
+               {
+                 GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_ADD_MODE);
+                 if (GTK_WIDGET_HAS_FOCUS(widget))
+                   {
+                     gtk_cmclist_draw_focus (widget);
+                     gdk_gc_set_line_attributes (clist->xor_gc, 1,
+                                                 GDK_LINE_SOLID, 0, 0);
+                     clist->focus_row = row;
+                     gtk_cmclist_draw_focus (widget);
+                   }
+                 else
+                   {
+                     gdk_gc_set_line_attributes (clist->xor_gc, 1,
+                                                 GDK_LINE_SOLID, 0, 0);
+                     clist->focus_row = row;
+                   }
+               }
+             else if (row != clist->focus_row)
+               {
+                 if (GTK_WIDGET_HAS_FOCUS(widget))
+                   {
+                     gtk_cmclist_draw_focus (widget);
+                     clist->focus_row = row;
+                     gtk_cmclist_draw_focus (widget);
+                   }
+                 else
+                   clist->focus_row = row;
+               }
+           }
+
+         if (!GTK_WIDGET_HAS_FOCUS(widget))
+           gtk_widget_grab_focus (widget);
+
+         if (button_actions & GTK_CMBUTTON_SELECTS)
+           {
+             switch (clist->selection_mode)
+               {
+               case GTK_SELECTION_SINGLE:
+                 if (event->type != GDK_BUTTON_PRESS)
+                   {
+                     g_signal_emit (GTK_OBJECT (clist),
+                                      clist_signals[SELECT_ROW], 0,
+                                      row, column, event);
+                     clist->anchor = -1;
+                   }
+                 else
+                   clist->anchor = row;
+                 break;
+               case GTK_SELECTION_BROWSE:
+                 g_signal_emit (GTK_OBJECT (clist),
+                                  clist_signals[SELECT_ROW], 0,
+                                  row, column, event);
+                 break;
+               case GTK_SELECTION_MULTIPLE:
+                 if (event->type != GDK_BUTTON_PRESS)
+                   {
+                     if (clist->anchor != -1)
+                       {
+                         update_extended_selection (clist, clist->focus_row);
+                         GTK_CMCLIST_GET_CLASS (clist)->resync_selection
+                           (clist, (GdkEvent *) event);
+                       }
+                     g_signal_emit (GTK_OBJECT (clist),
+                                      clist_signals[SELECT_ROW], 0,
+                                      row, column, event);
+                     break;
+                   }
+             
+                 if (event->state & GDK_CONTROL_MASK)
+                   {
+                     if (event->state & GDK_SHIFT_MASK)
+                       {
+                         if (clist->anchor < 0)
+                           {
+                             g_list_free (clist->undo_selection);
+                             g_list_free (clist->undo_unselection);
+                             clist->undo_selection = NULL;
+                             clist->undo_unselection = NULL;
+                             clist->anchor = old_row;
+                             clist->drag_pos = old_row;
+                             clist->undo_anchor = old_row;
+                           }
+                         update_extended_selection (clist, clist->focus_row);
+                       }
+                     else
+                       {
+                         if (clist->anchor == -1)
+                           set_anchor (clist, TRUE, row, old_row);
+                         else
+                           update_extended_selection (clist,
+                                                      clist->focus_row);
+                       }
+                     break;
+                   }
+
+                 if (event->state & GDK_SHIFT_MASK)
+                   {
+                     set_anchor (clist, FALSE, old_row, old_row);
+                     update_extended_selection (clist, clist->focus_row);
+                     break;
+                   }
+
+                 if (clist->anchor == -1)
+                   set_anchor (clist, FALSE, row, old_row);
+                 else
+                   update_extended_selection (clist, clist->focus_row);
+                 break;
+               default:
+                 break;
+               }
+           }
+       }
+      return TRUE;
+    }
+
+  /* press on resize windows */
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].resizeable && clist->column[i].window &&
+       event->window == clist->column[i].window)
+      {
+       gpointer drag_data;
+
+       if (gdk_pointer_grab (clist->column[i].window, FALSE,
+                             GDK_POINTER_MOTION_HINT_MASK |
+                             GDK_BUTTON1_MOTION_MASK |
+                             GDK_BUTTON_RELEASE_MASK,
+                             NULL, NULL, event->time))
+         return FALSE;
+
+       gtk_grab_add (widget);
+       GTK_CMCLIST_SET_FLAG (clist, CMCLIST_IN_DRAG);
+
+       /* block attached dnd signal handler */
+       drag_data = g_object_get_data (G_OBJECT (clist), "gtk-site-data");
+       if (drag_data)
+               g_signal_handlers_block_matched(G_OBJECT(clist), G_SIGNAL_MATCH_DATA,
+                                       0, 0, 0, 0, drag_data);
+
+       if (!GTK_WIDGET_HAS_FOCUS(widget))
+         gtk_widget_grab_focus (widget);
+
+       clist->drag_pos = i;
+       clist->x_drag = (COLUMN_LEFT_XPIXEL(clist, i) + COLUMN_INSET +
+                        clist->column[i].area.width + CELL_SPACING);
+
+       if (GTK_CMCLIST_ADD_MODE(clist))
+         gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
+       draw_xor_line (clist);
+
+        return TRUE;
+      }
+
+  return FALSE;
+}
+
+static gint
+gtk_cmclist_button_release (GtkWidget      *widget,
+                         GdkEventButton *event)
+{
+  GtkCMCList *clist;
+  gint button_actions;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  clist = GTK_CMCLIST (widget);
+
+  button_actions = clist->button_actions[event->button - 1];
+  if (button_actions == GTK_CMBUTTON_IGNORED)
+    return FALSE;
+
+  /* release on resize windows */
+  if (GTK_CMCLIST_IN_DRAG(clist))
+    {
+      gpointer drag_data;
+      gint width;
+      gint x;
+      gint i;
+
+      i = clist->drag_pos;
+      clist->drag_pos = -1;
+
+      /* unblock attached dnd signal handler */
+      drag_data = g_object_get_data (G_OBJECT (clist), "gtk-site-data");
+      if (drag_data)
+               g_signal_handlers_unblock_matched(G_OBJECT(clist), G_SIGNAL_MATCH_DATA,
+                                       0, 0, 0, 0, drag_data);
+
+      GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_IN_DRAG);
+      gtk_widget_get_pointer (widget, &x, NULL);
+      gtk_grab_remove (widget);
+      gdk_display_pointer_ungrab (gtk_widget_get_display (widget), event->time);
+
+      if (clist->x_drag >= 0)
+       draw_xor_line (clist);
+
+      if (GTK_CMCLIST_ADD_MODE(clist))
+       {
+         gdk_gc_set_line_attributes (clist->xor_gc, 1,
+                                     GDK_LINE_ON_OFF_DASH, 0, 0);
+         gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
+       }
+
+      width = new_column_width (clist, i, &x);
+      gtk_cmclist_set_column_width (clist, i, width);
+
+      return TRUE;
+    }
+
+  if (clist->drag_button == event->button)
+    {
+      gint row;
+      gint column;
+
+      clist->drag_button = 0;
+      clist->click_cell.row = -1;
+      clist->click_cell.column = -1;
+
+      remove_grab (clist);
+
+      if (button_actions & GTK_CMBUTTON_SELECTS)
+       {
+         switch (clist->selection_mode)
+           {
+           case GTK_SELECTION_MULTIPLE:
+             if (!(event->state & GDK_SHIFT_MASK) ||
+                 !GTK_WIDGET_CAN_FOCUS (widget) ||
+                 event->x < 0 || event->x >= clist->clist_window_width ||
+                 event->y < 0 || event->y >= clist->clist_window_height)
+               GTK_CMCLIST_GET_CLASS (clist)->resync_selection
+                 (clist, (GdkEvent *) event);
+             break;
+           case GTK_SELECTION_SINGLE:
+             if (get_selection_info (clist, event->x, event->y,
+                                     &row, &column))
+               {
+                 if (row >= 0 && row < clist->rows && clist->anchor == row)
+                   toggle_row (clist, row, column, (GdkEvent *) event);
+               }
+             clist->anchor = -1;
+             break;
+           default:
+             break;
+           }
+       }
+
+      return TRUE;
+    }
+  
+  return FALSE;
+}
+
+static gint
+gtk_cmclist_motion (GtkWidget      *widget,
+                 GdkEventMotion *event)
+{
+  GtkCMCList *clist;
+  gint x;
+  gint y;
+  gint row;
+  gint new_width;
+  gint button_actions = 0;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
+
+  clist = GTK_CMCLIST (widget);
+  if (!clist_has_grab (clist))
+    return FALSE;
+
+  if (clist->drag_button > 0)
+    button_actions = clist->button_actions[clist->drag_button - 1];
+
+  if (GTK_CMCLIST_IN_DRAG(clist))
+    {
+      if (event->is_hint || event->window != widget->window)
+       gtk_widget_get_pointer (widget, &x, NULL);
+      else
+       x = event->x;
+      
+      new_width = new_column_width (clist, clist->drag_pos, &x);
+      if (x != clist->x_drag)
+       {
+         /* x_drag < 0 indicates that the xor line is already invisible */
+         if (clist->x_drag >= 0)
+           draw_xor_line (clist);
+
+         clist->x_drag = x;
+
+         if (clist->x_drag >= 0)
+           draw_xor_line (clist);
+       }
+
+      if (new_width <= MAX (COLUMN_MIN_WIDTH + 1,
+                           clist->column[clist->drag_pos].min_width + 1))
+       {
+         if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) < 0 && x < 0)
+           gtk_cmclist_moveto (clist, -1, clist->drag_pos, 0, 0);
+         return FALSE;
+       }
+      if (clist->column[clist->drag_pos].max_width >= COLUMN_MIN_WIDTH &&
+         new_width >= clist->column[clist->drag_pos].max_width)
+       {
+         if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) + new_width >
+             clist->clist_window_width && x < 0)
+           move_horizontal (clist,
+                            COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) +
+                            new_width - clist->clist_window_width +
+                            COLUMN_INSET + CELL_SPACING);
+         return FALSE;
+       }
+    }
+
+  if (event->is_hint || event->window != clist->clist_window)
+    gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
+  else
+    {
+      x = event->x;
+      y = event->y;
+    }
+
+  if (GTK_CMCLIST_REORDERABLE(clist) && button_actions & GTK_CMBUTTON_DRAGS)
+    {
+      /* delayed drag start */
+      if (event->window == clist->clist_window &&
+         clist->click_cell.row >= 0 && clist->click_cell.column >= 0 &&
+         (y < 0 || y >= clist->clist_window_height ||
+          x < 0 || x >= clist->clist_window_width  ||
+          y < ROW_TOP_YPIXEL (clist, clist->click_cell.row) ||
+          y >= (ROW_TOP_YPIXEL (clist, clist->click_cell.row) +
+                clist->row_height) ||
+          x < COLUMN_LEFT_XPIXEL (clist, clist->click_cell.column) ||
+          x >= (COLUMN_LEFT_XPIXEL(clist, clist->click_cell.column) + 
+                clist->column[clist->click_cell.column].area.width)))
+       {
+         GtkTargetList  *target_list;
+
+         target_list = gtk_target_list_new (&clist_target_table, 1);
+         gtk_drag_begin (widget, target_list, GDK_ACTION_MOVE,
+                         clist->drag_button, (GdkEvent *)event);
+
+       }
+      return TRUE;
+    }
+
+  /* horizontal autoscrolling */
+  if (clist->hadjustment && LIST_WIDTH (clist) > clist->clist_window_width &&
+      (x < 0 || x >= clist->clist_window_width))
+    {
+      if (clist->htimer)
+       return FALSE;
+
+      clist->htimer = gdk_threads_add_timeout
+       (SCROLL_TIME, (GSourceFunc) horizontal_timeout, clist);
+
+      if (!((x < 0 && clist->hadjustment->value == 0) ||
+           (x >= clist->clist_window_width &&
+            clist->hadjustment->value ==
+            LIST_WIDTH (clist) - clist->clist_window_width)))
+       {
+         if (x < 0)
+           move_horizontal (clist, -1 + (x/2));
+         else
+           move_horizontal (clist, 1 + (x - clist->clist_window_width) / 2);
+       }
+    }
+
+  if (GTK_CMCLIST_IN_DRAG(clist))
+    return FALSE;
+
+  /* vertical autoscrolling */
+  row = ROW_FROM_YPIXEL (clist, y);
+
+  /* don't scroll on last pixel row if it's a cell spacing */
+  if (y == clist->clist_window_height - 1 &&
+      y == ROW_TOP_YPIXEL (clist, row-1) + clist->row_height)
+    return FALSE;
+
+  if (LIST_HEIGHT (clist) > clist->clist_window_height &&
+      (y < 0 || y >= clist->clist_window_height))
+    {
+      if (clist->vtimer)
+       return FALSE;
+
+      clist->vtimer = gdk_threads_add_timeout (SCROLL_TIME,
+                                    (GSourceFunc) vertical_timeout, clist);
+
+      if (clist->drag_button &&
+         ((y < 0 && clist->focus_row == 0) ||
+          (y >= clist->clist_window_height &&
+           clist->focus_row == clist->rows - 1)))
+       return FALSE;
+    }
+
+  row = CLAMP (row, 0, clist->rows - 1);
+
+  if (button_actions & GTK_CMBUTTON_SELECTS &
+      !g_object_get_data (G_OBJECT (widget), "gtk-site-data"))
+    {
+      if (row == clist->focus_row)
+       return FALSE;
+
+      gtk_cmclist_draw_focus (widget);
+      clist->focus_row = row;
+      gtk_cmclist_draw_focus (widget);
+
+      switch (clist->selection_mode)
+       {
+       case GTK_SELECTION_BROWSE:
+         g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+                          clist->focus_row, -1, event);
+         break;
+       case GTK_SELECTION_MULTIPLE:
+         update_extended_selection (clist, clist->focus_row);
+         break;
+       default:
+         break;
+       }
+    }
+  
+  if (ROW_TOP_YPIXEL(clist, row) < 0)
+    move_vertical (clist, row, 0);
+  else if (ROW_TOP_YPIXEL(clist, row) + clist->row_height >
+          clist->clist_window_height)
+    move_vertical (clist, row, 1);
+
+  return FALSE;
+}
+
+static void
+gtk_cmclist_size_request (GtkWidget      *widget,
+                       GtkRequisition *requisition)
+{
+  GtkCMCList *clist;
+  gint i;
+  gint font_height = 0;
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+  g_return_if_fail (requisition != NULL);
+
+  clist = GTK_CMCLIST (widget);
+
+  requisition->width = 0;
+  requisition->height = 0;
+
+  /* compute the size of the column title (title) area */
+  clist->column_title_area.height = 0;
+  if (GTK_CMCLIST_SHOW_TITLES(clist)) {
+    font_height = (pango_font_description_get_size((GTK_WIDGET(clist)->style)->font_desc)/PANGO_SCALE)*2+4;
+    for (i = 0; i < clist->columns; i++)
+      if (clist->column[i].button)
+       {
+         GtkRequisition child_requisition;
+         
+         gtk_widget_size_request (clist->column[i].button,
+                                  &child_requisition);
+         clist->column_title_area.height =
+           MAX (clist->column_title_area.height,
+                child_requisition.height - 2);
+       }
+    clist->column_title_area.height = font_height;
+  }
+  requisition->width += (widget->style->xthickness +
+                        GTK_CONTAINER (widget)->border_width) * 2;
+  requisition->height += (clist->column_title_area.height +
+                         (widget->style->ythickness +
+                          GTK_CONTAINER (widget)->border_width) * 2);
+
+  /* if (!clist->hadjustment) */
+  requisition->width += list_requisition_width (clist);
+  /* if (!clist->vadjustment) */
+  requisition->height += LIST_HEIGHT (clist);
+}
+
+static void
+gtk_cmclist_size_allocate (GtkWidget     *widget,
+                        GtkAllocation *allocation)
+{
+  GtkCMCList *clist;
+  GtkAllocation clist_allocation;
+  gint border_width;
+
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+  g_return_if_fail (allocation != NULL);
+
+  clist = GTK_CMCLIST (widget);
+  widget->allocation = *allocation;
+  border_width = GTK_CONTAINER (widget)->border_width;
+
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      gdk_window_move_resize (widget->window,
+                             allocation->x + border_width,
+                             allocation->y + border_width,
+                             allocation->width - border_width * 2,
+                             allocation->height - border_width * 2);
+    }
+
+  /* use internal allocation structure for all the math
+   * because it's easier than always subtracting the container
+   * border width */
+  clist->internal_allocation.x = 0;
+  clist->internal_allocation.y = 0;
+  clist->internal_allocation.width = MAX (1, (gint)allocation->width -
+                                         border_width * 2);
+  clist->internal_allocation.height = MAX (1, (gint)allocation->height -
+                                          border_width * 2);
+       
+  /* allocate clist window assuming no scrollbars */
+  clist_allocation.x = (clist->internal_allocation.x +
+                       widget->style->xthickness);
+  clist_allocation.y = (clist->internal_allocation.y +
+                       widget->style->ythickness +
+                       clist->column_title_area.height);
+  clist_allocation.width = MAX (1, (gint)clist->internal_allocation.width - 
+                               (2 * (gint)widget->style->xthickness));
+  clist_allocation.height = MAX (1, (gint)clist->internal_allocation.height -
+                                (2 * (gint)widget->style->ythickness) -
+                                (gint)clist->column_title_area.height);
+  
+  clist->clist_window_width = clist_allocation.width;
+  clist->clist_window_height = clist_allocation.height;
+  
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      gdk_window_move_resize (clist->clist_window,
+                             clist_allocation.x,
+                             clist_allocation.y,
+                             clist_allocation.width,
+                             clist_allocation.height);
+    }
+  
+  /* position the window which holds the column title buttons */
+  clist->column_title_area.x = widget->style->xthickness;
+  clist->column_title_area.y = widget->style->ythickness;
+  clist->column_title_area.width = clist_allocation.width;
+  
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      gdk_window_move_resize (clist->title_window,
+                             clist->column_title_area.x,
+                             clist->column_title_area.y,
+                             clist->column_title_area.width,
+                             clist->column_title_area.height);
+    }
+  
+  /* column button allocation */
+  size_allocate_columns (clist, FALSE);
+  size_allocate_title_buttons (clist);
+
+  adjust_adjustments (clist, TRUE);
+}
+
+/* GTKCONTAINER
+ *   gtk_cmclist_forall
+ */
+static void
+gtk_cmclist_forall (GtkContainer *container,
+                 gboolean      include_internals,
+                 GtkCallback   callback,
+                 gpointer      callback_data)
+{
+  GtkCMCList *clist;
+  guint i;
+
+  g_return_if_fail (GTK_IS_CMCLIST (container));
+  g_return_if_fail (callback != NULL);
+
+  if (!include_internals)
+    return;
+
+  clist = GTK_CMCLIST (container);
+      
+  /* callback for the column buttons */
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].button)
+      (*callback) (clist->column[i].button, callback_data);
+}
+
+/* PRIVATE DRAWING FUNCTIONS
+ *   get_cell_style
+ *   draw_cell_pixmap
+ *   draw_row
+ *   draw_rows
+ *   draw_xor_line
+ *   clist_refresh
+ */
+static void
+get_cell_style (GtkCMCList     *clist,
+               GtkCMCListRow  *clist_row,
+               gint          state,
+               gint          column,
+               GtkStyle    **style,
+               GdkGC       **fg_gc,
+               GdkGC       **bg_gc)
+{
+  gint fg_state;
+
+  if ((state == GTK_STATE_NORMAL) &&
+      (GTK_WIDGET (clist)->state == GTK_STATE_INSENSITIVE))
+    fg_state = GTK_STATE_INSENSITIVE;
+  else
+    fg_state = state;
+
+  if (clist_row->cell[column].style)
+    {
+      if (style)
+       *style = clist_row->cell[column].style;
+      if (fg_gc)
+       *fg_gc = clist_row->cell[column].style->fg_gc[fg_state];
+      if (bg_gc) {
+       if (state == GTK_STATE_SELECTED)
+         *bg_gc = clist_row->cell[column].style->bg_gc[state];
+       else
+         *bg_gc = clist_row->cell[column].style->base_gc[state];
+      }
+    }
+  else if (clist_row->style)
+    {
+      if (style)
+       *style = clist_row->style;
+      if (fg_gc)
+       *fg_gc = clist_row->style->fg_gc[fg_state];
+      if (bg_gc) {
+       if (state == GTK_STATE_SELECTED)
+         *bg_gc = clist_row->style->bg_gc[state];
+       else
+         *bg_gc = clist_row->style->base_gc[state];
+      }
+    }
+  else
+    {
+      if (style)
+       *style = GTK_WIDGET (clist)->style;
+      if (fg_gc)
+       *fg_gc = GTK_WIDGET (clist)->style->fg_gc[fg_state];
+      if (bg_gc) {
+       if (state == GTK_STATE_SELECTED)
+         *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
+       else
+         *bg_gc = GTK_WIDGET (clist)->style->base_gc[state];
+      }
+
+      if (state != GTK_STATE_SELECTED)
+       {
+         if (fg_gc && clist_row->fg_set)
+           *fg_gc = clist->fg_gc;
+         if (bg_gc && clist_row->bg_set)
+           *bg_gc = clist->bg_gc;
+       }
+    }
+}
+
+static gint
+draw_cell_pixmap (GdkWindow    *window,
+                 GdkRectangle *clip_rectangle,
+                 GdkGC        *fg_gc,
+                 GdkPixmap    *pixmap,
+                 GdkBitmap    *mask,
+                 gint          x,
+                 gint          y,
+                 gint          width,
+                 gint          height)
+{
+  gint xsrc = 0;
+  gint ysrc = 0;
+
+  if (mask)
+    {
+      gdk_gc_set_clip_mask (fg_gc, mask);
+      gdk_gc_set_clip_origin (fg_gc, x, y);
+    }
+
+  if (x < clip_rectangle->x)
+    {
+      xsrc = clip_rectangle->x - x;
+      width -= xsrc;
+      x = clip_rectangle->x;
+    }
+  if (x + width > clip_rectangle->x + clip_rectangle->width)
+    width = clip_rectangle->x + clip_rectangle->width - x;
+
+  if (y < clip_rectangle->y)
+    {
+      ysrc = clip_rectangle->y - y;
+      height -= ysrc;
+      y = clip_rectangle->y;
+    }
+  if (y + height > clip_rectangle->y + clip_rectangle->height)
+    height = clip_rectangle->y + clip_rectangle->height - y;
+
+  gdk_draw_drawable (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
+  gdk_gc_set_clip_origin (fg_gc, 0, 0);
+  if (mask)
+    gdk_gc_set_clip_mask (fg_gc, NULL);
+
+  return x + MAX (width, 0);
+}
+
+static void
+draw_row (GtkCMCList     *clist,
+         GdkRectangle *area,
+         gint          row,
+         GtkCMCListRow  *clist_row)
+{
+  GtkWidget *widget;
+  GdkRectangle *rect;
+  GdkRectangle row_rectangle;
+  GdkRectangle cell_rectangle;
+  GdkRectangle clip_rectangle;
+  GdkRectangle intersect_rectangle;
+  gint last_column;
+  gint state;
+  gint i;
+
+  g_return_if_fail (clist != NULL);
+
+  /* bail now if we arn't drawable yet */
+  if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
+    return;
+
+  widget = GTK_WIDGET (clist);
+
+  /* if the function is passed the pointer to the row instead of null,
+   * it avoids this expensive lookup */
+  if (!clist_row)
+    clist_row = ROW_ELEMENT (clist, row)->data;
+
+  /* rectangle of the entire row */
+  row_rectangle.x = 0;
+  row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
+  row_rectangle.width = clist->clist_window_width;
+  row_rectangle.height = clist->row_height;
+
+  /* rectangle of the cell spacing above the row */
+  cell_rectangle.x = 0;
+  cell_rectangle.y = row_rectangle.y - CELL_SPACING;
+  cell_rectangle.width = row_rectangle.width;
+  cell_rectangle.height = CELL_SPACING;
+
+  /* rectangle used to clip drawing operations, its y and height
+   * positions only need to be set once, so we set them once here. 
+   * the x and width are set withing the drawing loop below once per
+   * column */
+  clip_rectangle.y = row_rectangle.y;
+  clip_rectangle.height = row_rectangle.height;
+
+  if (clist_row->state == GTK_STATE_NORMAL)
+    {
+      if (clist_row->fg_set)
+       gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
+      if (clist_row->bg_set)
+       gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
+    }
+
+  state = clist_row->state;
+
+  /* draw the cell borders and background */
+  if (area)
+    {
+      rect = &intersect_rectangle;
+      if (gdk_rectangle_intersect (area, &cell_rectangle,
+                                  &intersect_rectangle))
+       gdk_draw_rectangle (clist->clist_window,
+                           widget->style->base_gc[GTK_STATE_NORMAL],
+                           TRUE,
+                           intersect_rectangle.x,
+                           intersect_rectangle.y,
+                           intersect_rectangle.width,
+                           intersect_rectangle.height);
+
+      /* the last row has to clear its bottom cell spacing too */
+      if (clist_row == clist->row_list_end->data)
+       {
+         cell_rectangle.y += clist->row_height + CELL_SPACING;
+
+         if (gdk_rectangle_intersect (area, &cell_rectangle,
+                                      &intersect_rectangle))
+           gdk_draw_rectangle (clist->clist_window,
+                               widget->style->base_gc[GTK_STATE_NORMAL],
+                               TRUE,
+                               intersect_rectangle.x,
+                               intersect_rectangle.y,
+                               intersect_rectangle.width,
+                               intersect_rectangle.height);
+       }
+
+      if (!gdk_rectangle_intersect (area, &row_rectangle,&intersect_rectangle))
+       return;
+
+    }
+  else
+    {
+      rect = &clip_rectangle;
+      gdk_draw_rectangle (clist->clist_window,
+                         widget->style->base_gc[GTK_STATE_NORMAL],
+                         TRUE,
+                         cell_rectangle.x,
+                         cell_rectangle.y,
+                         cell_rectangle.width,
+                         cell_rectangle.height);
+
+      /* the last row has to clear its bottom cell spacing too */
+      if (clist_row == clist->row_list_end->data)
+       {
+         cell_rectangle.y += clist->row_height + CELL_SPACING;
+
+         gdk_draw_rectangle (clist->clist_window,
+                             widget->style->base_gc[GTK_STATE_NORMAL],
+                             TRUE,
+                             cell_rectangle.x,
+                             cell_rectangle.y,
+                             cell_rectangle.width,
+                             cell_rectangle.height);     
+       }         
+    }
+  
+  for (last_column = clist->columns - 1;
+       last_column >= 0 && !clist->column[last_column].visible; last_column--)
+    ;
+
+  /* iterate and draw all the columns (row cells) and draw their contents */
+  for (i = 0; i < clist->columns; i++)
+    {
+      GtkStyle *style;
+      GdkGC *fg_gc;
+      GdkGC *bg_gc;
+      PangoLayout *layout;
+      PangoRectangle logical_rect;
+
+      gint width;
+      gint height;
+      gint pixmap_width;
+      gint offset = 0;
+
+      if (!clist->column[i].visible)
+       continue;
+
+      get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
+
+      clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
+      clip_rectangle.width = clist->column[i].area.width;
+
+      /* calculate clipping region clipping region */
+      clip_rectangle.x -= COLUMN_INSET + CELL_SPACING;
+      clip_rectangle.width += (2 * COLUMN_INSET + CELL_SPACING +
+                              (i == last_column) * CELL_SPACING);
+      
+      if (area && !gdk_rectangle_intersect (area, &clip_rectangle,
+                                           &intersect_rectangle))
+       continue;
+
+      gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
+                         rect->x, rect->y, rect->width, rect->height);
+
+      clip_rectangle.x += COLUMN_INSET + CELL_SPACING;
+      clip_rectangle.width -= (2 * COLUMN_INSET + CELL_SPACING +
+                              (i == last_column) * CELL_SPACING);
+
+
+      /* calculate real width for column justification */
+      
+      layout = _gtk_cmclist_create_cell_layout (clist, clist_row, i);
+      if (layout)
+       {
+         pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+         width = logical_rect.width;
+       }
+      else
+       width = 0;
+
+      pixmap_width = 0;
+      offset = 0;
+      switch (clist_row->cell[i].type)
+       {
+       case GTK_CMCELL_PIXMAP:
+         gdk_drawable_get_size (GTK_CMCELL_PIXMAP (clist_row->cell[i])->pixmap,
+                              &pixmap_width, &height);
+         width += pixmap_width;
+         break;
+       case GTK_CMCELL_PIXTEXT:
+         gdk_drawable_get_size (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+                              &pixmap_width, &height);
+         width += pixmap_width + GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
+         break;
+       default:
+         break;
+       }
+
+      switch (clist->column[i].justification)
+       {
+       case GTK_JUSTIFY_LEFT:
+         offset = clip_rectangle.x + clist_row->cell[i].horizontal;
+         break;
+       case GTK_JUSTIFY_RIGHT:
+         offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
+                   clip_rectangle.width - width);
+         break;
+       case GTK_JUSTIFY_CENTER:
+       case GTK_JUSTIFY_FILL:
+         offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
+                   (clip_rectangle.width / 2) - (width / 2));
+         break;
+       };
+
+      /* Draw Text and/or Pixmap */
+      switch (clist_row->cell[i].type)
+       {
+       case GTK_CMCELL_PIXMAP:
+         draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
+                           GTK_CMCELL_PIXMAP (clist_row->cell[i])->pixmap,
+                           GTK_CMCELL_PIXMAP (clist_row->cell[i])->mask,
+                           offset,
+                           clip_rectangle.y + clist_row->cell[i].vertical +
+                           (clip_rectangle.height - height) / 2,
+                           pixmap_width, height);
+         break;
+       case GTK_CMCELL_PIXTEXT:
+         offset =
+           draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
+                             GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+                             GTK_CMCELL_PIXTEXT (clist_row->cell[i])->mask,
+                             offset,
+                             clip_rectangle.y + clist_row->cell[i].vertical+
+                             (clip_rectangle.height - height) / 2,
+                             pixmap_width, height);
+         offset += GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
+
+         /* Fall through */
+       case GTK_CMCELL_TEXT:
+         if (layout)
+           {
+             gint row_center_offset = (clist->row_height - logical_rect.height - 1) / 2;
+
+             gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
+             gdk_draw_layout (clist->clist_window, fg_gc,
+                              offset,
+                              row_rectangle.y + row_center_offset + clist_row->cell[i].vertical,
+                              layout);
+              g_object_unref (G_OBJECT (layout));
+             gdk_gc_set_clip_rectangle (fg_gc, NULL);
+           }
+         break;
+       default:
+         break;
+       }
+    }
+
+  /* draw focus rectangle */
+  if (clist->focus_row == row &&
+      GTK_WIDGET_CAN_FOCUS (widget) && GTK_WIDGET_HAS_FOCUS(widget))
+    {
+      if (!area)
+       gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
+                           row_rectangle.x, row_rectangle.y,
+                           row_rectangle.width - 1, row_rectangle.height - 1);
+      else if (gdk_rectangle_intersect (area, &row_rectangle,
+                                       &intersect_rectangle))
+       {
+         gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
+         gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
+                             row_rectangle.x, row_rectangle.y,
+                             row_rectangle.width - 1,
+                             row_rectangle.height - 1);
+         gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
+       }
+    }
+}
+
+static void
+draw_rows (GtkCMCList     *clist,
+          GdkRectangle *area)
+{
+  GList *list;
+  GtkCMCListRow *clist_row;
+  gint i;
+  gint first_row;
+  gint last_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (clist->row_height == 0 ||
+      !GTK_WIDGET_DRAWABLE (clist))
+    return;
+
+  if (area)
+    {
+      first_row = ROW_FROM_YPIXEL (clist, area->y);
+      last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
+    }
+  else
+    {
+      first_row = ROW_FROM_YPIXEL (clist, 0);
+      last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
+    }
+
+  /* this is a small special case which exposes the bottom cell line
+   * on the last row -- it might go away if I change the wall the cell
+   * spacings are drawn
+   */
+  if (clist->rows == first_row)
+    first_row--;
+
+  list = ROW_ELEMENT (clist, first_row);
+  i = first_row;
+  while (list)
+    {
+      clist_row = list->data;
+      list = list->next;
+
+      if (i > last_row)
+       return;
+
+      GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, area, i, clist_row);
+      i++;
+    }
+
+  if (!area)
+    gdk_window_clear_area (clist->clist_window, 0,
+                          ROW_TOP_YPIXEL (clist, i), 0, 0);
+}
+
+static void                          
+draw_xor_line (GtkCMCList *clist)
+{
+  GtkWidget *widget;
+
+  g_return_if_fail (clist != NULL);
+
+  widget = GTK_WIDGET (clist);
+
+  gdk_draw_line (widget->window, clist->xor_gc,
+                 clist->x_drag,
+                widget->style->ythickness,
+                 clist->x_drag,
+                 clist->column_title_area.height +
+                clist->clist_window_height + 1);
+}
+
+static void
+clist_refresh (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  
+  if (CLIST_UNFROZEN (clist))
+    { 
+      adjust_adjustments (clist, FALSE);
+      draw_rows (clist, NULL);
+    }
+}
+
+/* get cell from coordinates
+ *   get_selection_info
+ *   gtk_cmclist_get_selection_info
+ */
+static gint
+get_selection_info (GtkCMCList *clist,
+                   gint      x,
+                   gint      y,
+                   gint     *row,
+                   gint     *column)
+{
+  gint trow, tcol;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+
+  /* bounds checking, return false if the user clicked 
+   * on a blank area */
+  trow = ROW_FROM_YPIXEL (clist, y);
+  if (trow >= clist->rows)
+    return 0;
+
+  if (row)
+    *row = trow;
+
+  tcol = COLUMN_FROM_XPIXEL (clist, x);
+  if (tcol >= clist->columns)
+    return 0;
+
+  if (column)
+    *column = tcol;
+
+  return 1;
+}
+
+gint
+gtk_cmclist_get_selection_info (GtkCMCList *clist, 
+                             gint      x, 
+                             gint      y, 
+                             gint     *row, 
+                             gint     *column)
+{
+  g_return_val_if_fail (GTK_IS_CMCLIST (clist), 0);
+  return get_selection_info (clist, x, y, row, column);
+}
+
+/* PRIVATE ADJUSTMENT FUNCTIONS
+ *   adjust_adjustments
+ *   vadjustment_changed
+ *   hadjustment_changed
+ *   vadjustment_value_changed
+ *   hadjustment_value_changed 
+ *   check_exposures
+ */
+static void
+adjust_adjustments (GtkCMCList *clist,
+                   gboolean  block_resize)
+{
+  if (clist->vadjustment)
+    {
+      clist->vadjustment->page_size = clist->clist_window_height;
+      clist->vadjustment->step_increment = clist->row_height;
+      clist->vadjustment->page_increment =
+       MAX (clist->vadjustment->page_size - clist->vadjustment->step_increment,
+            clist->vadjustment->page_size / 2);
+      clist->vadjustment->lower = 0;
+      clist->vadjustment->upper = LIST_HEIGHT (clist);
+
+      if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist) ||
+         (clist->voffset + (gint)clist->vadjustment->value) != 0)
+       {
+         clist->vadjustment->value = MAX (0, (LIST_HEIGHT (clist) -
+                                              clist->clist_window_height));
+         g_signal_emit_by_name (GTK_OBJECT (clist->vadjustment),
+                                  "value_changed");
+       }
+      g_signal_emit_by_name (GTK_OBJECT (clist->vadjustment), "changed");
+    }
+
+  if (clist->hadjustment)
+    {
+      clist->hadjustment->page_size = clist->clist_window_width;
+      clist->hadjustment->step_increment = 10;
+      clist->hadjustment->page_increment =
+       MAX (clist->hadjustment->page_size - clist->hadjustment->step_increment,
+            clist->hadjustment->page_size / 2);
+      clist->hadjustment->lower = 0;
+      clist->hadjustment->upper = LIST_WIDTH (clist);
+
+      if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist) ||
+         (clist->hoffset + (gint)clist->hadjustment->value) != 0)
+       {
+         clist->hadjustment->value = MAX (0, (LIST_WIDTH (clist) -
+                                              clist->clist_window_width));
+         g_signal_emit_by_name (GTK_OBJECT (clist->hadjustment),
+                                  "value_changed");
+       }
+      g_signal_emit_by_name (GTK_OBJECT (clist->hadjustment), "changed");
+    }
+
+  if (!block_resize && (!clist->vadjustment || !clist->hadjustment))
+    {
+      GtkWidget *widget;
+      GtkRequisition requisition;
+
+      widget = GTK_WIDGET (clist);
+      gtk_widget_size_request (widget, &requisition);
+
+      if ((!clist->hadjustment &&
+          requisition.width != widget->allocation.width) ||
+         (!clist->vadjustment &&
+          requisition.height != widget->allocation.height))
+       gtk_widget_queue_resize (widget);
+    }
+}
+
+static void
+vadjustment_changed (GtkAdjustment *adjustment,
+                    gpointer       data)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (adjustment != NULL);
+  g_return_if_fail (data != NULL);
+
+  clist = GTK_CMCLIST (data);
+}
+
+static void
+hadjustment_changed (GtkAdjustment *adjustment,
+                    gpointer       data)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (adjustment != NULL);
+  g_return_if_fail (data != NULL);
+
+  clist = GTK_CMCLIST (data);
+}
+
+static void
+vadjustment_value_changed (GtkAdjustment *adjustment,
+                          gpointer       data)
+{
+  GtkCMCList *clist;
+  gint dy, value;
+
+  g_return_if_fail (adjustment != NULL);
+  g_return_if_fail (GTK_IS_CMCLIST (data));
+
+  clist = GTK_CMCLIST (data);
+
+  if (adjustment != clist->vadjustment)
+    return;
+
+  value = -adjustment->value;
+  dy = value - clist->voffset;
+  clist->voffset = value;
+
+  if (GTK_WIDGET_DRAWABLE (clist))
+    {
+      gdk_window_scroll (clist->clist_window, 0, dy);
+      gdk_window_process_updates (clist->clist_window, FALSE);
+    }
+  
+  return;
+}
+
+typedef struct
+{
+  GdkWindow *window;
+  gint dx;
+} ScrollData;
+
+/* The window to which widget->window is relative */
+#define ALLOCATION_WINDOW(widget)              \
+   (GTK_WIDGET_NO_WINDOW (widget) ?            \
+    (widget)->window :                          \
+     gdk_window_get_parent ((widget)->window))
+
+static void
+adjust_allocation_recurse (GtkWidget *widget,
+                          gpointer   data)
+{
+  ScrollData *scroll_data = data;
+  
+  if (!GTK_WIDGET_REALIZED (widget))
+    {
+      if (GTK_WIDGET_VISIBLE (widget))
+       {
+         GdkRectangle tmp_rectangle = widget->allocation;
+         tmp_rectangle.x += scroll_data->dx;
+      
+         gtk_widget_size_allocate (widget, &tmp_rectangle);
+       }
+    }
+  else
+    {
+      if (ALLOCATION_WINDOW (widget) == scroll_data->window)
+       {
+         widget->allocation.x += scroll_data->dx;
+
+         if (GTK_IS_CONTAINER (widget))
+           gtk_container_forall (GTK_CONTAINER (widget),
+                                 adjust_allocation_recurse,
+                                 data);
+       }
+    }
+}
+
+static void
+adjust_allocation (GtkWidget *widget,
+                  gint       dx)
+{
+  ScrollData scroll_data;
+
+  if (GTK_WIDGET_REALIZED (widget))
+    scroll_data.window = ALLOCATION_WINDOW (widget);
+  else
+    scroll_data.window = NULL;
+    
+  scroll_data.dx = dx;
+  
+  adjust_allocation_recurse (widget, &scroll_data);
+}
+
+static void
+hadjustment_value_changed (GtkAdjustment *adjustment,
+                          gpointer       data)
+{
+  GtkCMCList *clist;
+  GtkContainer *container;
+  GdkRectangle area;
+  gint i;
+  gint y = 0;
+  gint value;
+  gint dx;
+
+  g_return_if_fail (adjustment != NULL);
+  g_return_if_fail (GTK_IS_CMCLIST (data));
+
+  clist = GTK_CMCLIST (data);
+  container = GTK_CONTAINER (data);
+
+  if (adjustment != clist->hadjustment)
+    return;
+
+  value = adjustment->value;
+
+  dx = -value - clist->hoffset;
+
+  if (GTK_WIDGET_REALIZED (clist))
+    gdk_window_scroll (clist->title_window, dx, 0);
+
+  /* adjust the column button's allocations */
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].button)
+      adjust_allocation (clist->column[i].button, dx);
+
+  clist->hoffset = -value;
+
+  if (GTK_WIDGET_DRAWABLE (clist))
+    {
+      if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
+          !container->focus_child && GTK_CMCLIST_ADD_MODE(clist))
+        {
+          y = ROW_TOP_YPIXEL (clist, clist->focus_row);
+      
+          gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
+                              clist->clist_window_width - 1,
+                              clist->row_height - 1);
+        }
+      gdk_window_scroll (clist->clist_window, dx, 0);
+      gdk_window_process_updates (clist->clist_window, FALSE);
+
+      if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
+          !container->focus_child)
+        {
+          if (GTK_CMCLIST_ADD_MODE(clist))
+            {
+              gint focus_row;
+         
+              focus_row = clist->focus_row;
+              clist->focus_row = -1;
+              draw_rows (clist, &area);
+              clist->focus_row = focus_row;
+         
+              gdk_draw_rectangle (clist->clist_window, clist->xor_gc,
+                                  FALSE, 0, y, clist->clist_window_width - 1,
+                                  clist->row_height - 1);
+              return;
+            }
+          else if (ABS(dx) < clist->clist_window_width - 1)
+            {
+              gint x0;
+              gint x1;
+         
+              if (dx > 0)
+                {
+                  x0 = clist->clist_window_width - 1;
+                  x1 = dx;
+                }
+              else
+                {
+                  x0 = 0;
+                  x1 = clist->clist_window_width - 1 + dx;
+                }
+
+              y = ROW_TOP_YPIXEL (clist, clist->focus_row);
+              gdk_draw_line (clist->clist_window, clist->xor_gc,
+                             x0, y + 1, x0, y + clist->row_height - 2);
+              gdk_draw_line (clist->clist_window, clist->xor_gc,
+                             x1, y + 1, x1, y + clist->row_height - 2);
+            }
+        }
+    }
+}
+
+/* PRIVATE 
+ * Memory Allocation/Distruction Routines for GtkCMCList stuctures
+ *
+ * functions:
+ *   columns_new
+ *   column_title_new
+ *   columns_delete
+ *   row_new
+ *   row_delete
+ */
+static GtkCMCListColumn *
+columns_new (GtkCMCList *clist)
+{
+  GtkCMCListColumn *column;
+  gint i;
+
+  column = g_new (GtkCMCListColumn, clist->columns);
+
+  for (i = 0; i < clist->columns; i++)
+    {
+      column[i].area.x = 0;
+      column[i].area.y = 0;
+      column[i].area.width = 0;
+      column[i].area.height = 0;
+      column[i].title = NULL;
+      column[i].button = NULL;
+      column[i].window = NULL;
+      column[i].width = 0;
+      column[i].min_width = -1;
+      column[i].max_width = -1;
+      column[i].visible = TRUE;
+      column[i].width_set = FALSE;
+      column[i].resizeable = TRUE;
+      column[i].auto_resize = FALSE;
+      column[i].button_passive = FALSE;
+      column[i].justification = GTK_JUSTIFY_LEFT;
+    }
+
+  return column;
+}
+
+static void
+column_title_new (GtkCMCList    *clist,
+                 gint         column,
+                 const gchar *title)
+{
+  g_free (clist->column[column].title);
+
+  clist->column[column].title = g_strdup (title);
+}
+
+static void
+columns_delete (GtkCMCList *clist)
+{
+  gint i;
+
+  for (i = 0; i < clist->columns; i++)
+    g_free (clist->column[i].title);
+      
+  g_free (clist->column);
+}
+
+static GtkCMCListRow *
+row_new (GtkCMCList *clist)
+{
+  int i;
+  GtkCMCListRow *clist_row;
+
+  clist_row = g_slice_new (GtkCMCListRow);
+  clist_row->cell = g_slice_alloc (sizeof (GtkCMCell) * clist->columns);
+
+  for (i = 0; i < clist->columns; i++)
+    {
+      clist_row->cell[i].type = GTK_CMCELL_EMPTY;
+      clist_row->cell[i].vertical = 0;
+      clist_row->cell[i].horizontal = 0;
+      clist_row->cell[i].style = NULL;
+    }
+
+  clist_row->fg_set = FALSE;
+  clist_row->bg_set = FALSE;
+  clist_row->style = NULL;
+  clist_row->selectable = TRUE;
+  clist_row->state = GTK_STATE_NORMAL;
+  clist_row->data = NULL;
+  clist_row->destroy = NULL;
+
+  return clist_row;
+}
+
+static void
+row_delete (GtkCMCList    *clist,
+           GtkCMCListRow *clist_row)
+{
+  gint i;
+
+  for (i = 0; i < clist->columns; i++)
+    {
+      GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+       (clist, clist_row, i, GTK_CMCELL_EMPTY, NULL, 0, NULL, NULL);
+      if (clist_row->cell[i].style)
+       {
+         if (GTK_WIDGET_REALIZED (clist))
+           gtk_style_detach (clist_row->cell[i].style);
+         g_object_unref (clist_row->cell[i].style);
+       }
+    }
+
+  if (clist_row->style)
+    {
+      if (GTK_WIDGET_REALIZED (clist))
+        gtk_style_detach (clist_row->style);
+      g_object_unref (clist_row->style);
+    }
+
+  if (clist_row->destroy)
+    clist_row->destroy (clist_row->data);
+
+  g_slice_free1 (sizeof (GtkCMCell) * clist->columns, clist_row->cell);
+  g_slice_free (GtkCMCListRow, clist_row);
+}
+
+/* FOCUS FUNCTIONS
+ *   gtk_cmclist_focus_content_area
+ *   gtk_cmclist_focus
+ *   gtk_cmclist_draw_focus
+ *   gtk_cmclist_focus_in
+ *   gtk_cmclist_focus_out
+ *   title_focus
+ */
+static void
+gtk_cmclist_focus_content_area (GtkCMCList *clist)
+{
+  if (clist->focus_row < 0)
+    {
+      clist->focus_row = 0;
+      
+      if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
+          clist->selection_mode == GTK_SELECTION_MULTIPLE) &&
+         !clist->selection)
+       g_signal_emit (GTK_OBJECT (clist),
+                        clist_signals[SELECT_ROW], 0,
+                        clist->focus_row, -1, NULL);
+    }
+  gtk_widget_grab_focus (GTK_WIDGET (clist));
+}
+
+static gboolean
+gtk_cmclist_focus (GtkWidget        *widget,
+                GtkDirectionType  direction)
+{
+  GtkCMCList *clist = GTK_CMCLIST (widget);
+  GtkWidget *focus_child;
+  gboolean is_current_focus;
+
+  if (!GTK_WIDGET_IS_SENSITIVE (widget))
+    return FALSE;
+
+  focus_child = GTK_CONTAINER (widget)->focus_child;
+  
+  is_current_focus = gtk_widget_is_focus (GTK_WIDGET (clist));
+                         
+  if (focus_child &&
+      gtk_widget_child_focus (focus_child, direction))
+    return TRUE;
+      
+  switch (direction)
+    {
+    case GTK_DIR_LEFT:
+    case GTK_DIR_RIGHT:
+      if (focus_child)
+       {
+         if (title_focus_move (clist, direction))
+           return TRUE;
+       }
+      else if (!is_current_focus)
+       {
+         gtk_cmclist_focus_content_area (clist);
+         return TRUE;
+       }
+      break;
+    case GTK_DIR_DOWN:
+    case GTK_DIR_TAB_FORWARD:
+      if (!focus_child && !is_current_focus)
+       {
+         if (title_focus_in (clist, direction))
+           return TRUE;
+       }
+      
+      if (!is_current_focus && clist->rows)
+       {
+         gtk_cmclist_focus_content_area (clist);
+         return TRUE;
+       }
+      break;
+    case GTK_DIR_UP:
+    case GTK_DIR_TAB_BACKWARD:
+      if (!focus_child && is_current_focus)
+       {
+         if (title_focus_in (clist, direction))
+           return TRUE;
+       }
+      
+      if (!is_current_focus && !focus_child && clist->rows)
+       {
+         gtk_cmclist_focus_content_area (clist);
+         return TRUE;
+       }
+      break;
+    default:
+      break;
+    }
+
+  return FALSE;
+}
+
+static void
+gtk_cmclist_set_focus_child (GtkContainer *container,
+                          GtkWidget    *child)
+{
+  GtkCMCList *clist = GTK_CMCLIST (container);
+  gint i;
+
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].button == child)
+      clist->focus_header_column = i;
+  
+  parent_class->set_focus_child (container, child);
+}
+
+static void
+gtk_cmclist_draw_focus (GtkWidget *widget)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+
+  if (!GTK_WIDGET_DRAWABLE (widget) || !GTK_WIDGET_CAN_FOCUS (widget))
+    return;
+
+  clist = GTK_CMCLIST (widget);
+  if (clist->focus_row >= 0)
+    gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
+                       0, ROW_TOP_YPIXEL(clist, clist->focus_row),
+                       clist->clist_window_width - 1,
+                       clist->row_height - 1);
+}
+
+static gint
+gtk_cmclist_focus_in (GtkWidget     *widget,
+                   GdkEventFocus *event)
+{
+  GtkCMCList *clist = GTK_CMCLIST (widget);
+
+  if (clist->selection_mode == GTK_SELECTION_BROWSE &&
+      clist->selection == NULL && clist->focus_row > -1)
+    {
+      GList *list;
+
+      list = g_list_nth (clist->row_list, clist->focus_row);
+      if (list && GTK_CMCLIST_ROW (list)->selectable)
+       g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+                        clist->focus_row, -1, event);
+      else
+       gtk_cmclist_draw_focus (widget);
+    }
+  else
+    gtk_cmclist_draw_focus (widget);
+
+  return FALSE;
+}
+
+static gint
+gtk_cmclist_focus_out (GtkWidget     *widget,
+                    GdkEventFocus *event)
+{
+  GtkCMCList *clist = GTK_CMCLIST (widget);
+
+  gtk_cmclist_draw_focus (widget);
+  
+  GTK_CMCLIST_GET_CLASS (widget)->resync_selection (clist, (GdkEvent *) event);
+
+  return FALSE;
+}
+
+static gboolean
+focus_column (GtkCMCList *clist, gint column, gint dir)
+{
+  GtkWidget *child = clist->column[column].button;
+  
+  if (gtk_widget_child_focus (child, dir))
+    {
+      return TRUE;
+    }
+  else if (GTK_WIDGET_CAN_FOCUS (child))
+    {
+      gtk_widget_grab_focus (child);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+/* Focus moved onto the headers. Focus first focusable and visible child.
+ * (FIXME: focus the last focused child if visible)
+ */
+static gboolean
+title_focus_in (GtkCMCList *clist, gint dir)
+{
+  gint i;
+  gint left, right;
+
+  if (!GTK_CMCLIST_SHOW_TITLES (clist))
+    return FALSE;
+
+  /* Check last focused column */
+  if (clist->focus_header_column != -1)
+    {
+      i = clist->focus_header_column;
+      
+      left = COLUMN_LEFT_XPIXEL (clist, i);
+      right = left + clist->column[i].area.width;
+      
+      if (left >= 0 && right <= clist->clist_window_width)
+       {
+         if (focus_column (clist, i, dir))
+           return TRUE;
+       }
+    }
+
+  /* Check fully visible columns */
+  for (i = 0 ; i < clist->columns ; i++)
+    {
+      left = COLUMN_LEFT_XPIXEL (clist, i);
+      right = left + clist->column[i].area.width;
+      
+      if (left >= 0 && right <= clist->clist_window_width)
+       {
+         if (focus_column (clist, i, dir))
+           return TRUE;
+       }
+    }
+
+  /* Check partially visible columns */
+  for (i = 0 ; i < clist->columns ; i++)
+    {
+      left = COLUMN_LEFT_XPIXEL (clist, i);
+      right = left + clist->column[i].area.width;
+
+      if ((left < 0 && right > 0) ||
+         (left < clist->clist_window_width && right > clist->clist_window_width))
+       {
+         if (focus_column (clist, i, dir))
+           return TRUE;
+       }
+    }
+      
+  return FALSE;
+}
+
+/* Move the focus right or left within the title buttons, scrolling
+ * as necessary to keep the focused child visible.
+ */
+static gboolean
+title_focus_move (GtkCMCList *clist,
+                 gint      dir)
+{
+  GtkWidget *focus_child;
+  gboolean return_val = FALSE;
+  gint d = 0;
+  gint i = -1;
+  gint j;
+
+  if (!GTK_CMCLIST_SHOW_TITLES(clist))
+    return FALSE;
+
+  focus_child = GTK_CONTAINER (clist)->focus_child;
+  g_assert (focus_child);
+
+  /* Movement direction within headers
+   */
+  switch (dir)
+    {
+    case GTK_DIR_RIGHT:
+      d = 1;
+      break;
+    case GTK_DIR_LEFT:
+      d = -1;
+      break;
+    }
+  
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].button == focus_child)
+      break;
+  
+  g_assert (i != -1);          /* Have a starting column */
+  
+  j = i + d;
+  while (!return_val && j >= 0 && j < clist->columns)
+    {
+      if (clist->column[j].button &&
+         GTK_WIDGET_VISIBLE (clist->column[j].button))
+       {
+         if (focus_column (clist, j, dir))
+           {
+             return_val = TRUE;
+             break;
+           }
+       }
+      j += d;
+    }
+
+  /* If we didn't find it, wrap around and keep looking
+   */
+  if (!return_val)
+    {
+      j = d > 0 ? 0 : clist->columns - 1;
+
+      while (!return_val && j != i)
+       {
+         if (clist->column[j].button &&
+             GTK_WIDGET_VISIBLE (clist->column[j].button))
+           {
+             if (focus_column (clist, j, dir))
+               {
+                 return_val = TRUE;
+                 break;
+               }
+           }
+         j += d;
+       }
+    }
+
+  /* Scroll horizontally so focused column is visible
+   */
+  if (return_val)
+    {
+      if (COLUMN_LEFT_XPIXEL (clist, j) < CELL_SPACING + COLUMN_INSET)
+       gtk_cmclist_moveto (clist, -1, j, 0, 0);
+      else if (COLUMN_LEFT_XPIXEL(clist, j) + clist->column[j].area.width >
+              clist->clist_window_width)
+       {
+         gint last_column;
+         
+         for (last_column = clist->columns - 1;
+              last_column >= 0 && !clist->column[last_column].visible; last_column--);
+
+         if (j == last_column)
+           gtk_cmclist_moveto (clist, -1, j, 0, 0);
+         else
+           gtk_cmclist_moveto (clist, -1, j, 0, 1);
+       }
+    }
+  return TRUE;                 /* Even if we didn't find a new one, we can keep the
+                                * focus in the same place.
+                                */
+}
+
+/* PRIVATE SCROLLING FUNCTIONS
+ *   move_focus_row
+ *   scroll_horizontal
+ *   scroll_vertical
+ *   move_horizontal
+ *   move_vertical
+ *   horizontal_timeout
+ *   vertical_timeout
+ *   remove_grab
+ */
+static void
+move_focus_row (GtkCMCList      *clist,
+               GtkScrollType  scroll_type,
+               gfloat         position)
+{
+  GtkWidget *widget;
+
+  g_return_if_fail (clist != 0);
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  widget = GTK_WIDGET (clist);
+
+  switch (scroll_type)
+    {
+    case GTK_SCROLL_STEP_UP:
+    case GTK_SCROLL_STEP_BACKWARD:
+      if (clist->focus_row <= 0)
+       return;
+      gtk_cmclist_draw_focus (widget);
+      clist->focus_row--;
+      gtk_cmclist_draw_focus (widget);
+      break;
+
+    case GTK_SCROLL_STEP_DOWN:
+    case GTK_SCROLL_STEP_FORWARD:
+      if (clist->focus_row >= clist->rows - 1)
+       return;
+      gtk_cmclist_draw_focus (widget);
+      clist->focus_row++;
+      gtk_cmclist_draw_focus (widget);
+      break;
+    case GTK_SCROLL_PAGE_UP:
+    case GTK_SCROLL_PAGE_BACKWARD:
+      if (clist->focus_row <= 0)
+       return;
+      gtk_cmclist_draw_focus (widget);
+      clist->focus_row = MAX (0, clist->focus_row -
+                             (2 * clist->clist_window_height -
+                              clist->row_height - CELL_SPACING) / 
+                             (2 * (clist->row_height + CELL_SPACING)));
+      gtk_cmclist_draw_focus (widget);
+      break;
+    case GTK_SCROLL_PAGE_DOWN:
+    case GTK_SCROLL_PAGE_FORWARD:
+      if (clist->focus_row >= clist->rows - 1)
+       return;
+      gtk_cmclist_draw_focus (widget);
+      clist->focus_row = MIN (clist->rows - 1, clist->focus_row + 
+                             (2 * clist->clist_window_height -
+                              clist->row_height - CELL_SPACING) / 
+                             (2 * (clist->row_height + CELL_SPACING)));
+      gtk_cmclist_draw_focus (widget);
+      break;
+    case GTK_SCROLL_JUMP:
+      if (position >= 0 && position <= 1)
+       {
+         gtk_cmclist_draw_focus (widget);
+         clist->focus_row = position * (clist->rows - 1);
+         gtk_cmclist_draw_focus (widget);
+       }
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+scroll_horizontal (GtkCMCList      *clist,
+                  GtkScrollType  scroll_type,
+                  gfloat         position)
+{
+  gint column = 0;
+  gint last_column;
+
+  g_return_if_fail (clist != 0);
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (clist_has_grab (clist))
+    return;
+
+  for (last_column = clist->columns - 1;
+       last_column >= 0 && !clist->column[last_column].visible; last_column--)
+    ;
+
+  switch (scroll_type)
+    {
+    case GTK_SCROLL_STEP_BACKWARD:
+      column = COLUMN_FROM_XPIXEL (clist, 0);
+      if (COLUMN_LEFT_XPIXEL (clist, column) - CELL_SPACING - COLUMN_INSET >= 0
+         && column > 0)
+       column--;
+      break;
+    case GTK_SCROLL_STEP_FORWARD:
+      column = COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
+      if (column < 0)
+       return;
+      if (COLUMN_LEFT_XPIXEL (clist, column) +
+         clist->column[column].area.width +
+         CELL_SPACING + COLUMN_INSET - 1 <= clist->clist_window_width &&
+         column < last_column)
+       column++;
+      break;
+    case GTK_SCROLL_PAGE_BACKWARD:
+    case GTK_SCROLL_PAGE_FORWARD:
+      return;
+    case GTK_SCROLL_JUMP:
+      if (position >= 0 && position <= 1)
+       {
+         gint vis_columns = 0;
+         gint i;
+
+         for (i = 0; i <= last_column; i++)
+           if (clist->column[i].visible)
+             vis_columns++;
+
+         column = position * vis_columns;
+
+         for (i = 0; i <= last_column && column > 0; i++)
+           if (clist->column[i].visible)
+             column--;
+
+         column = i;
+       }
+      else
+       return;
+      break;
+    default:
+      break;
+    }
+
+  if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
+    gtk_cmclist_moveto (clist, -1, column, 0, 0);
+  else if (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET - 1
+          + clist->column[column].area.width > clist->clist_window_width)
+    {
+      if (column == last_column)
+       gtk_cmclist_moveto (clist, -1, column, 0, 0);
+      else
+       gtk_cmclist_moveto (clist, -1, column, 0, 1);
+    }
+}
+
+static void
+scroll_vertical (GtkCMCList      *clist,
+                GtkScrollType  scroll_type,
+                gfloat         position)
+{
+  gint old_focus_row;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (clist_has_grab (clist))
+    return;
+
+  switch (clist->selection_mode)
+    {
+    case GTK_SELECTION_MULTIPLE:
+      if (clist->anchor >= 0)
+       return;
+    case GTK_SELECTION_BROWSE:
+
+      old_focus_row = clist->focus_row;
+      move_focus_row (clist, scroll_type, position);
+
+      if (old_focus_row != clist->focus_row)
+       {
+         if (clist->selection_mode == GTK_SELECTION_BROWSE)
+           g_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+                            old_focus_row, -1, NULL);
+         else if (!GTK_CMCLIST_ADD_MODE(clist))
+           {
+             gtk_cmclist_unselect_all (clist);
+             clist->undo_anchor = old_focus_row;
+           }
+       }
+
+      switch (gtk_cmclist_row_is_visible (clist, clist->focus_row))
+       {
+       case GTK_VISIBILITY_NONE:
+         if (old_focus_row != clist->focus_row &&
+             !(clist->selection_mode == GTK_SELECTION_MULTIPLE &&
+               GTK_CMCLIST_ADD_MODE(clist)))
+           g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+                            clist->focus_row, -1, NULL);
+         switch (scroll_type)
+           {
+            case GTK_SCROLL_PAGE_UP:
+            case GTK_SCROLL_STEP_UP:
+           case GTK_SCROLL_STEP_BACKWARD:
+           case GTK_SCROLL_PAGE_BACKWARD:
+             gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+             break;
+            case GTK_SCROLL_PAGE_DOWN:
+            case GTK_SCROLL_STEP_DOWN:
+           case GTK_SCROLL_STEP_FORWARD:
+           case GTK_SCROLL_PAGE_FORWARD:
+             gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+             break;
+           case GTK_SCROLL_JUMP:
+             gtk_cmclist_moveto (clist, clist->focus_row, -1, 0.5, 0);
+             break;
+           default:
+             break;
+           }
+         break;
+       case GTK_VISIBILITY_PARTIAL:
+         switch (scroll_type)
+           {
+           case GTK_SCROLL_STEP_BACKWARD:
+           case GTK_SCROLL_PAGE_BACKWARD:
+             gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+             break;
+           case GTK_SCROLL_STEP_FORWARD:
+           case GTK_SCROLL_PAGE_FORWARD:
+             gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+             break;
+           case GTK_SCROLL_JUMP:
+             gtk_cmclist_moveto (clist, clist->focus_row, -1, 0.5, 0);
+             break;
+           default:
+             break;
+           }
+       default:
+         if (old_focus_row != clist->focus_row &&
+             !(clist->selection_mode == GTK_SELECTION_MULTIPLE &&
+               GTK_CMCLIST_ADD_MODE(clist)))
+           g_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], 0,
+                            clist->focus_row, -1, NULL);
+         break;
+       }
+      break;
+    default:
+      move_focus_row (clist, scroll_type, position);
+
+      if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
+         clist->clist_window_height)
+       gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+      else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+       gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+      break;
+    }
+}
+
+static void
+move_horizontal (GtkCMCList *clist,
+                gint      diff)
+{
+  gdouble value;
+
+  if (!clist->hadjustment)
+    return;
+
+  value = CLAMP (clist->hadjustment->value + diff, 0.0,
+                clist->hadjustment->upper - clist->hadjustment->page_size);
+  gtk_adjustment_set_value (clist->hadjustment, value);
+}
+
+static void
+move_vertical (GtkCMCList *clist,
+              gint      row,
+              gfloat    align)
+{
+  gdouble value;
+
+  if (!clist->vadjustment)
+    return;
+
+  value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset -
+          align * (clist->clist_window_height - clist->row_height) +
+          (2 * align - 1) * CELL_SPACING);
+
+  if (value + clist->vadjustment->page_size > clist->vadjustment->upper)
+    value = clist->vadjustment->upper - clist->vadjustment->page_size;
+
+  gtk_adjustment_set_value (clist->vadjustment, value);
+}
+
+static void
+do_fake_motion (GtkWidget *widget)
+{
+  GdkEvent *event = gdk_event_new (GDK_MOTION_NOTIFY);
+
+  event->motion.send_event = TRUE;
+
+  gtk_cmclist_motion (widget, (GdkEventMotion *)event);
+  gdk_event_free (event);
+}
+
+static gint
+horizontal_timeout (GtkCMCList *clist)
+{
+  clist->htimer = 0;
+  do_fake_motion (GTK_WIDGET (clist));
+
+  return FALSE;
+}
+
+static gint
+vertical_timeout (GtkCMCList *clist)
+{
+  clist->vtimer = 0;
+  do_fake_motion (GTK_WIDGET (clist));
+
+  return FALSE;
+}
+
+static void
+remove_grab (GtkCMCList *clist)
+{
+  GtkWidget *widget = GTK_WIDGET (clist);
+  
+  if (GTK_WIDGET_HAS_GRAB (clist))
+    {
+      GdkDisplay *display = gtk_widget_get_display (widget);
+      
+      gtk_grab_remove (widget);
+      if (gdk_display_pointer_is_grabbed (display))
+       gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+    }
+
+  if (clist->htimer)
+    {
+      g_source_remove (clist->htimer);
+      clist->htimer = 0;
+    }
+
+  if (clist->vtimer)
+    {
+      g_source_remove (clist->vtimer);
+      clist->vtimer = 0;
+    }
+}
+
+/* PUBLIC SORTING FUNCTIONS
+ * gtk_cmclist_sort
+ * gtk_cmclist_set_compare_func
+ * gtk_cmclist_set_auto_sort
+ * gtk_cmclist_set_sort_type
+ * gtk_cmclist_set_sort_column
+ */
+void
+gtk_cmclist_sort (GtkCMCList *clist)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  GTK_CMCLIST_GET_CLASS (clist)->sort_list (clist);
+}
+
+void
+gtk_cmclist_set_compare_func (GtkCMCList            *clist,
+                           GtkCMCListCompareFunc  cmp_func)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  clist->compare = (cmp_func) ? cmp_func : default_compare;
+}
+
+void       
+gtk_cmclist_set_auto_sort (GtkCMCList *clist,
+                        gboolean  auto_sort)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  
+  if (GTK_CMCLIST_AUTO_SORT(clist) && !auto_sort)
+    GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_AUTO_SORT);
+  else if (!GTK_CMCLIST_AUTO_SORT(clist) && auto_sort)
+    {
+      GTK_CMCLIST_SET_FLAG (clist, CMCLIST_AUTO_SORT);
+      gtk_cmclist_sort (clist);
+    }
+}
+
+void       
+gtk_cmclist_set_sort_type (GtkCMCList    *clist,
+                        GtkSortType  sort_type)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  
+  clist->sort_type = sort_type;
+}
+
+void
+gtk_cmclist_set_sort_column (GtkCMCList *clist,
+                          gint      column)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  clist->sort_column = column;
+}
+
+/* PRIVATE SORTING FUNCTIONS
+ *   default_compare
+ *   real_sort_list
+ *   gtk_cmclist_merge
+ *   gtk_cmclist_mergesort
+ */
+static gint
+default_compare (GtkCMCList      *clist,
+                gconstpointer  ptr1,
+                gconstpointer  ptr2)
+{
+  char *text1 = NULL;
+  char *text2 = NULL;
+
+  GtkCMCListRow *row1 = (GtkCMCListRow *) ptr1;
+  GtkCMCListRow *row2 = (GtkCMCListRow *) ptr2;
+
+  switch (row1->cell[clist->sort_column].type)
+    {
+    case GTK_CMCELL_TEXT:
+      text1 = GTK_CMCELL_TEXT (row1->cell[clist->sort_column])->text;
+      break;
+    case GTK_CMCELL_PIXTEXT:
+      text1 = GTK_CMCELL_PIXTEXT (row1->cell[clist->sort_column])->text;
+      break;
+    default:
+      break;
+    }
+  switch (row2->cell[clist->sort_column].type)
+    {
+    case GTK_CMCELL_TEXT:
+      text2 = GTK_CMCELL_TEXT (row2->cell[clist->sort_column])->text;
+      break;
+    case GTK_CMCELL_PIXTEXT:
+      text2 = GTK_CMCELL_PIXTEXT (row2->cell[clist->sort_column])->text;
+      break;
+    default:
+      break;
+    }
+
+  if (!text2)
+    return (text1 != NULL);
+
+  if (!text1)
+    return -1;
+
+  return strcmp (text1, text2);
+}
+
+static void
+real_sort_list (GtkCMCList *clist)
+{
+  GList *list;
+  GList *work;
+  gint i;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (clist->rows <= 1)
+    return;
+
+  if (clist_has_grab (clist))
+    return;
+
+  gtk_cmclist_freeze (clist);
+
+  if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_MULTIPLE)
+    {
+      GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+    }
+   
+  clist->row_list = gtk_cmclist_mergesort (clist, clist->row_list, clist->rows);
+
+  work = clist->selection;
+
+  for (i = 0, list = clist->row_list; i < clist->rows; i++, list = list->next)
+    {
+      if (GTK_CMCLIST_ROW (list)->state == GTK_STATE_SELECTED)
+       {
+         work->data = GINT_TO_POINTER (i);
+         work = work->next;
+       }
+      
+      if (i == clist->rows - 1)
+       clist->row_list_end = list;
+    }
+
+  gtk_cmclist_thaw (clist);
+}
+
+static GList *
+gtk_cmclist_merge (GtkCMCList *clist,
+                GList    *a,         /* first list to merge */
+                GList    *b)         /* second list to merge */
+{
+  GList z = { 0 };                    /* auxiliary node */
+  GList *c;
+  gint cmp;
+
+  c = &z;
+
+  while (a || b)
+    {
+      if (a && !b)
+       {
+         c->next = a;
+         a->prev = c;
+         c = a;
+         a = a->next;
+         break;
+       }
+      else if (!a && b)
+       {
+         c->next = b;
+         b->prev = c;
+         c = b;
+         b = b->next;
+         break;
+       }
+      else /* a && b */
+       {
+         cmp = clist->compare (clist, GTK_CMCLIST_ROW (a), GTK_CMCLIST_ROW (b));
+         if ((cmp >= 0 && clist->sort_type == GTK_SORT_DESCENDING) ||
+             (cmp <= 0 && clist->sort_type == GTK_SORT_ASCENDING) ||
+             (a && !b))
+           {
+             c->next = a;
+             a->prev = c;
+             c = a;
+             a = a->next;
+           }
+         else
+           {
+             c->next = b;
+             b->prev = c;
+             c = b;
+             b = b->next;
+           }
+       }
+    }
+
+  z.next->prev = NULL;
+  return z.next;
+}
+
+static GList *
+gtk_cmclist_mergesort (GtkCMCList *clist,
+                    GList    *list,         /* the list to sort */
+                    gint      num)          /* the list's length */
+{
+  GList *half;
+  gint i;
+
+  if (num <= 1)
+    {
+      return list;
+    }
+  else
+    {
+      /* move "half" to the middle */
+      half = list;
+      for (i = 0; i < num / 2; i++)
+       half = half->next;
+
+      /* cut the list in two */
+      half->prev->next = NULL;
+      half->prev = NULL;
+
+      /* recursively sort both lists */
+      return gtk_cmclist_merge (clist,
+                      gtk_cmclist_mergesort (clist, list, num / 2),
+                      gtk_cmclist_mergesort (clist, half, num - num / 2));
+    }
+}
+
+/************************/
+
+static void
+drag_source_info_destroy (gpointer data)
+{
+  GtkCMCListCellInfo *info = data;
+
+  g_free (info);
+}
+
+static void
+drag_dest_info_destroy (gpointer data)
+{
+  GtkCMCListDestInfo *info = data;
+
+  g_free (info);
+}
+
+static void
+drag_dest_cell (GtkCMCList         *clist,
+               gint              x,
+               gint              y,
+               GtkCMCListDestInfo *dest_info)
+{
+  GtkWidget *widget;
+
+  widget = GTK_WIDGET (clist);
+
+  dest_info->insert_pos = GTK_CMCLIST_DRAG_NONE;
+
+  y -= (GTK_CONTAINER (clist)->border_width +
+       widget->style->ythickness +
+       clist->column_title_area.height);
+
+  dest_info->cell.row = ROW_FROM_YPIXEL (clist, y);
+  if (dest_info->cell.row >= clist->rows)
+    {
+      dest_info->cell.row = clist->rows - 1;
+      y = ROW_TOP_YPIXEL (clist, dest_info->cell.row) + clist->row_height;
+    }
+  if (dest_info->cell.row < -1)
+    dest_info->cell.row = -1;
+  
+  x -= GTK_CONTAINER (widget)->border_width + widget->style->xthickness;
+
+  dest_info->cell.column = COLUMN_FROM_XPIXEL (clist, x);
+
+  if (dest_info->cell.row >= 0)
+    {
+      gint y_delta;
+      gint h = 0;
+
+      y_delta = y - ROW_TOP_YPIXEL (clist, dest_info->cell.row);
+      
+      if (GTK_CMCLIST_DRAW_DRAG_RECT(clist))
+       {
+         dest_info->insert_pos = GTK_CMCLIST_DRAG_INTO;
+         h = clist->row_height / 4;
+       }
+      else if (GTK_CMCLIST_DRAW_DRAG_LINE(clist))
+       {
+         dest_info->insert_pos = GTK_CMCLIST_DRAG_BEFORE;
+         h = clist->row_height / 2;
+       }
+
+      if (GTK_CMCLIST_DRAW_DRAG_LINE(clist))
+       {
+         if (y_delta < h)
+           dest_info->insert_pos = GTK_CMCLIST_DRAG_BEFORE;
+         else if (clist->row_height - y_delta < h)
+           dest_info->insert_pos = GTK_CMCLIST_DRAG_AFTER;
+       }
+    }
+}
+
+static void
+gtk_cmclist_drag_begin (GtkWidget           *widget,
+                     GdkDragContext *context)
+{
+  GtkCMCList *clist;
+  GtkCMCListCellInfo *info;
+
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+  g_return_if_fail (context != NULL);
+
+  clist = GTK_CMCLIST (widget);
+
+  clist->drag_button = 0;
+  remove_grab (clist);
+
+  switch (clist->selection_mode)
+    {
+    case GTK_SELECTION_MULTIPLE:
+      update_extended_selection (clist, clist->focus_row);
+      GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+      break;
+    case GTK_SELECTION_SINGLE:
+      clist->anchor = -1;
+    case GTK_SELECTION_BROWSE:
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  info = g_dataset_get_data (context, "gtk-clist-drag-source");
+
+  if (!info)
+    {
+      info = g_new (GtkCMCListCellInfo, 1);
+
+      if (clist->click_cell.row < 0)
+       clist->click_cell.row = 0;
+      else if (clist->click_cell.row >= clist->rows)
+       clist->click_cell.row = clist->rows - 1;
+      info->row = clist->click_cell.row;
+      info->column = clist->click_cell.column;
+
+      g_dataset_set_data_full (context, "gtk-clist-drag-source", info,
+                              drag_source_info_destroy);
+    }
+
+  if (GTK_CMCLIST_USE_DRAG_ICONS (clist))
+    gtk_drag_set_icon_default (context);
+}
+
+static void
+gtk_cmclist_drag_end (GtkWidget           *widget,
+                   GdkDragContext *context)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+  g_return_if_fail (context != NULL);
+
+  clist = GTK_CMCLIST (widget);
+
+  clist->click_cell.row = -1;
+  clist->click_cell.column = -1;
+}
+
+static void
+gtk_cmclist_drag_leave (GtkWidget      *widget,
+                     GdkDragContext *context,
+                     guint           time)
+{
+  GtkCMCList *clist;
+  GtkCMCListDestInfo *dest_info;
+
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+  g_return_if_fail (context != NULL);
+
+  clist = GTK_CMCLIST (widget);
+
+  dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+  
+  if (dest_info)
+    {
+      if (dest_info->cell.row >= 0 &&
+         GTK_CMCLIST_REORDERABLE(clist) &&
+         gtk_drag_get_source_widget (context) == widget)
+       {
+         GList *list;
+         GdkAtom atom = gdk_atom_intern_static_string ("gtk-clist-drag-reorder");
+
+         list = context->targets;
+         while (list)
+           {
+             if (atom == GDK_POINTER_TO_ATOM (list->data))
+               {
+                 GTK_CMCLIST_GET_CLASS (clist)->draw_drag_highlight
+                   (clist,
+                    g_list_nth (clist->row_list, dest_info->cell.row)->data,
+                    dest_info->cell.row, dest_info->insert_pos);
+                 clist->drag_highlight_row = -1;
+                 break;
+               }
+             list = list->next;
+           }
+       }
+      g_dataset_remove_data (context, "gtk-clist-drag-dest");
+    }
+}
+
+static gint
+gtk_cmclist_drag_motion (GtkWidget      *widget,
+                      GdkDragContext *context,
+                      gint            x,
+                      gint            y,
+                      guint           time)
+{
+  GtkCMCList *clist;
+  GtkCMCListDestInfo new_info;
+  GtkCMCListDestInfo *dest_info;
+
+  g_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
+
+  clist = GTK_CMCLIST (widget);
+
+  dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+
+  if (!dest_info)
+    {
+      dest_info = g_new (GtkCMCListDestInfo, 1);
+
+      dest_info->insert_pos  = GTK_CMCLIST_DRAG_NONE;
+      dest_info->cell.row    = -1;
+      dest_info->cell.column = -1;
+
+      g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info,
+                              drag_dest_info_destroy);
+    }
+
+  drag_dest_cell (clist, x, y, &new_info);
+
+  if (GTK_CMCLIST_REORDERABLE (clist))
+    {
+      GList *list;
+      GdkAtom atom = gdk_atom_intern_static_string ("gtk-clist-drag-reorder");
+
+      list = context->targets;
+      while (list)
+       {
+         if (atom == GDK_POINTER_TO_ATOM (list->data))
+           break;
+         list = list->next;
+       }
+
+      if (list)
+       {
+         if (gtk_drag_get_source_widget (context) != widget ||
+             new_info.insert_pos == GTK_CMCLIST_DRAG_NONE ||
+             new_info.cell.row == clist->click_cell.row ||
+             (new_info.cell.row == clist->click_cell.row - 1 &&
+              new_info.insert_pos == GTK_CMCLIST_DRAG_AFTER) ||
+             (new_info.cell.row == clist->click_cell.row + 1 &&
+              new_info.insert_pos == GTK_CMCLIST_DRAG_BEFORE))
+           {
+             if (dest_info->cell.row < 0)
+               {
+                 gdk_drag_status (context, GDK_ACTION_DEFAULT, time);
+                 return FALSE;
+               }
+             return TRUE;
+           }
+               
+         if (new_info.cell.row != dest_info->cell.row ||
+             (new_info.cell.row == dest_info->cell.row &&
+              dest_info->insert_pos != new_info.insert_pos))
+           {
+             if (dest_info->cell.row >= 0)
+               GTK_CMCLIST_GET_CLASS (clist)->draw_drag_highlight
+                 (clist, g_list_nth (clist->row_list,
+                                     dest_info->cell.row)->data,
+                  dest_info->cell.row, dest_info->insert_pos);
+
+             dest_info->insert_pos  = new_info.insert_pos;
+             dest_info->cell.row    = new_info.cell.row;
+             dest_info->cell.column = new_info.cell.column;
+             
+             GTK_CMCLIST_GET_CLASS (clist)->draw_drag_highlight
+               (clist, g_list_nth (clist->row_list,
+                                   dest_info->cell.row)->data,
+                dest_info->cell.row, dest_info->insert_pos);
+             
+             clist->drag_highlight_row = dest_info->cell.row;
+             clist->drag_highlight_pos = dest_info->insert_pos;
+
+             gdk_drag_status (context, context->suggested_action, time);
+           }
+         return TRUE;
+       }
+    }
+
+  dest_info->insert_pos  = new_info.insert_pos;
+  dest_info->cell.row    = new_info.cell.row;
+  dest_info->cell.column = new_info.cell.column;
+  return TRUE;
+}
+
+static gboolean
+gtk_cmclist_drag_drop (GtkWidget      *widget,
+                    GdkDragContext *context,
+                    gint            x,
+                    gint            y,
+                    guint           time)
+{
+  g_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
+  g_return_val_if_fail (context != NULL, FALSE);
+
+  if (GTK_CMCLIST_REORDERABLE (widget) &&
+      gtk_drag_get_source_widget (context) == widget)
+    {
+      GList *list;
+      GdkAtom atom = gdk_atom_intern_static_string ("gtk-clist-drag-reorder");
+
+      list = context->targets;
+      while (list)
+       {
+         if (atom == GDK_POINTER_TO_ATOM (list->data))
+           return TRUE;
+         list = list->next;
+       }
+    }
+  return FALSE;
+}
+
+static void
+gtk_cmclist_drag_data_received (GtkWidget        *widget,
+                             GdkDragContext   *context,
+                             gint              x,
+                             gint              y,
+                             GtkSelectionData *selection_data,
+                             guint             info,
+                             guint             time)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+  g_return_if_fail (context != NULL);
+  g_return_if_fail (selection_data != NULL);
+
+  clist = GTK_CMCLIST (widget);
+
+  if (GTK_CMCLIST_REORDERABLE (clist) &&
+      gtk_drag_get_source_widget (context) == widget &&
+      selection_data->target ==
+      gdk_atom_intern_static_string ("gtk-clist-drag-reorder") &&
+      selection_data->format == 8 &&
+      selection_data->length == sizeof (GtkCMCListCellInfo))
+    {
+      GtkCMCListCellInfo *source_info;
+
+      source_info = (GtkCMCListCellInfo *)(selection_data->data);
+      if (source_info)
+       {
+         GtkCMCListDestInfo dest_info;
+
+         drag_dest_cell (clist, x, y, &dest_info);
+
+         if (dest_info.insert_pos == GTK_CMCLIST_DRAG_AFTER)
+           dest_info.cell.row++;
+         if (source_info->row < dest_info.cell.row)
+           dest_info.cell.row--;
+         if (dest_info.cell.row != source_info->row)
+           gtk_cmclist_row_move (clist, source_info->row, dest_info.cell.row);
+
+         g_dataset_remove_data (context, "gtk-clist-drag-dest");
+       }
+    }
+}
+
+static void  
+gtk_cmclist_drag_data_get (GtkWidget        *widget,
+                        GdkDragContext   *context,
+                        GtkSelectionData *selection_data,
+                        guint             info,
+                        guint             time)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (widget));
+  g_return_if_fail (context != NULL);
+  g_return_if_fail (selection_data != NULL);
+
+  if (selection_data->target == gdk_atom_intern_static_string ("gtk-clist-drag-reorder"))
+    {
+      GtkCMCListCellInfo *info;
+
+      info = g_dataset_get_data (context, "gtk-clist-drag-source");
+
+      if (info)
+       {
+         GtkCMCListCellInfo ret_info;
+
+         ret_info.row = info->row;
+         ret_info.column = info->column;
+
+         gtk_selection_data_set (selection_data, selection_data->target,
+                                 8, (guchar *) &ret_info,
+                                 sizeof (GtkCMCListCellInfo));
+       }
+    }
+}
+
+static void
+draw_drag_highlight (GtkCMCList        *clist,
+                    GtkCMCListRow     *dest_row,
+                    gint             dest_row_number,
+                    GtkCMCListDragPos  drag_pos)
+{
+  gint y;
+
+  y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
+
+  switch (drag_pos)
+    {
+    case GTK_CMCLIST_DRAG_NONE:
+      break;
+    case GTK_CMCLIST_DRAG_AFTER:
+      y += clist->row_height + 1;
+    case GTK_CMCLIST_DRAG_BEFORE:
+      gdk_draw_line (clist->clist_window, clist->xor_gc,
+                    0, y, clist->clist_window_width, y);
+      break;
+    case GTK_CMCLIST_DRAG_INTO:
+      gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
+                         clist->clist_window_width - 1, clist->row_height);
+      break;
+    }
+}
+
+void
+gtk_cmclist_set_reorderable (GtkCMCList *clist, 
+                          gboolean  reorderable)
+{
+  GtkWidget *widget;
+
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if ((GTK_CMCLIST_REORDERABLE(clist) != 0) == reorderable)
+    return;
+
+  widget = GTK_WIDGET (clist);
+
+  if (reorderable)
+    {
+      GTK_CMCLIST_SET_FLAG (clist, CMCLIST_REORDERABLE);
+      gtk_drag_dest_set (widget,
+                        GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+                        &clist_target_table, 1, GDK_ACTION_MOVE);
+    }
+  else
+    {
+      GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_REORDERABLE);
+      gtk_drag_dest_unset (GTK_WIDGET (clist));
+    }
+}
+
+void
+gtk_cmclist_set_use_drag_icons (GtkCMCList *clist,
+                             gboolean  use_icons)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+
+  if (use_icons != 0)
+    GTK_CMCLIST_SET_FLAG (clist, CMCLIST_USE_DRAG_ICONS);
+  else
+    GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_USE_DRAG_ICONS);
+}
+
+void
+gtk_cmclist_set_button_actions (GtkCMCList *clist,
+                             guint     button,
+                             guint8    button_actions)
+{
+  g_return_if_fail (GTK_IS_CMCLIST (clist));
+  
+  if (button < MAX_BUTTON)
+    {
+      if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))) || 
+         GTK_WIDGET_HAS_GRAB (clist))
+       {
+         remove_grab (clist);
+         clist->drag_button = 0;
+       }
+
+      GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+      clist->button_actions[button] = button_actions;
+    }
+}
diff --git a/src/gtk/gtkcmclist.h b/src/gtk/gtkcmclist.h
new file mode 100644 (file)
index 0000000..c8820da
--- /dev/null
@@ -0,0 +1,789 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald
+ * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GTK_CMCLIST_H__
+#define __GTK_CMCLIST_H__
+
+#include <gdk/gdk.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkalignment.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkhscrollbar.h>
+#include <gtk/gtkvscrollbar.h>
+#include <gtk/gtkenums.h>
+
+
+G_BEGIN_DECLS
+
+
+/* clist flags */
+enum {
+  GTK_CMCLIST_IN_DRAG             = 1 <<  0,
+  GTK_CMCLIST_ROW_HEIGHT_SET      = 1 <<  1,
+  GTK_CMCLIST_SHOW_TITLES         = 1 <<  2,
+  /* Unused */
+  GTK_CMCLIST_ADD_MODE            = 1 <<  4,
+  GTK_CMCLIST_AUTO_SORT           = 1 <<  5,
+  GTK_CMCLIST_AUTO_RESIZE_BLOCKED = 1 <<  6,
+  GTK_CMCLIST_REORDERABLE         = 1 <<  7,
+  GTK_CMCLIST_USE_DRAG_ICONS      = 1 <<  8,
+  GTK_CMCLIST_DRAW_DRAG_LINE      = 1 <<  9,
+  GTK_CMCLIST_DRAW_DRAG_RECT      = 1 << 10
+}; 
+
+/* cell types */
+typedef enum
+{
+  GTK_CMCELL_EMPTY,
+  GTK_CMCELL_TEXT,
+  GTK_CMCELL_PIXMAP,
+  GTK_CMCELL_PIXTEXT,
+  GTK_CMCELL_WIDGET
+} GtkCMCellType;
+
+typedef enum
+{
+  GTK_CMCLIST_DRAG_NONE,
+  GTK_CMCLIST_DRAG_BEFORE,
+  GTK_CMCLIST_DRAG_INTO,
+  GTK_CMCLIST_DRAG_AFTER
+} GtkCMCListDragPos;
+
+typedef enum
+{
+  GTK_CMBUTTON_IGNORED = 0,
+  GTK_CMBUTTON_SELECTS = 1 << 0,
+  GTK_CMBUTTON_DRAGS   = 1 << 1,
+  GTK_CMBUTTON_EXPANDS = 1 << 2
+} GtkCMButtonAction;
+
+#define GTK_TYPE_CMCLIST            (gtk_cmclist_get_type ())
+#define GTK_CMCLIST(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_CMCLIST, GtkCMCList))
+#define GTK_CMCLIST_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CMCLIST, GtkCMCListClass))
+#define GTK_IS_CMCLIST(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_CMCLIST))
+#define GTK_IS_CMCLIST_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CMCLIST))
+#define GTK_CMCLIST_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_CMCLIST, GtkCMCListClass))
+
+
+#define GTK_CMCLIST_FLAGS(clist)             (GTK_CMCLIST (clist)->flags)
+#define GTK_CMCLIST_SET_FLAG(clist,flag)     (GTK_CMCLIST_FLAGS (clist) |= (GTK_ ## flag))
+#define GTK_CMCLIST_UNSET_FLAG(clist,flag)   (GTK_CMCLIST_FLAGS (clist) &= ~(GTK_ ## flag))
+
+#define GTK_CMCLIST_IN_DRAG(clist)           (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_IN_DRAG)
+#define GTK_CMCLIST_ROW_HEIGHT_SET(clist)    (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_ROW_HEIGHT_SET)
+#define GTK_CMCLIST_SHOW_TITLES(clist)       (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_SHOW_TITLES)
+#define GTK_CMCLIST_ADD_MODE(clist)          (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_ADD_MODE)
+#define GTK_CMCLIST_AUTO_SORT(clist)         (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_AUTO_SORT)
+#define GTK_CMCLIST_AUTO_RESIZE_BLOCKED(clist) (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_AUTO_RESIZE_BLOCKED)
+#define GTK_CMCLIST_REORDERABLE(clist)       (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_REORDERABLE)
+#define GTK_CMCLIST_USE_DRAG_ICONS(clist)    (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_USE_DRAG_ICONS)
+#define GTK_CMCLIST_DRAW_DRAG_LINE(clist)    (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_DRAW_DRAG_LINE)
+#define GTK_CMCLIST_DRAW_DRAG_RECT(clist)    (GTK_CMCLIST_FLAGS (clist) & GTK_CMCLIST_DRAW_DRAG_RECT)
+
+#define GTK_CMCLIST_ROW(_glist_) ((GtkCMCListRow *)((_glist_)->data))
+
+/* pointer casting for cells */
+#define GTK_CMCELL_TEXT(cell)     (((GtkCMCellText *) &(cell)))
+#define GTK_CMCELL_PIXMAP(cell)   (((GtkCMCellPixmap *) &(cell)))
+#define GTK_CMCELL_PIXTEXT(cell)  (((GtkCMCellPixText *) &(cell)))
+#define GTK_CMCELL_WIDGET(cell)   (((GtkCMCellWidget *) &(cell)))
+
+typedef struct _GtkCMCList GtkCMCList;
+typedef struct _GtkCMCListClass GtkCMCListClass;
+typedef struct _GtkCMCListColumn GtkCMCListColumn;
+typedef struct _GtkCMCListRow GtkCMCListRow;
+
+typedef struct _GtkCMCell GtkCMCell;
+typedef struct _GtkCMCellText GtkCMCellText;
+typedef struct _GtkCMCellPixmap GtkCMCellPixmap;
+typedef struct _GtkCMCellPixText GtkCMCellPixText;
+typedef struct _GtkCMCellWidget GtkCMCellWidget;
+
+typedef gint (*GtkCMCListCompareFunc) (GtkCMCList     *clist,
+                                    gconstpointer ptr1,
+                                    gconstpointer ptr2);
+
+typedef struct _GtkCMCListCellInfo GtkCMCListCellInfo;
+typedef struct _GtkCMCListDestInfo GtkCMCListDestInfo;
+
+struct _GtkCMCListCellInfo
+{
+  gint row;
+  gint column;
+};
+
+struct _GtkCMCListDestInfo
+{
+  GtkCMCListCellInfo cell;
+  GtkCMCListDragPos  insert_pos;
+};
+
+struct _GtkCMCList
+{
+  GtkContainer container;
+  
+  guint16 flags;
+  
+  gpointer reserved1;
+  gpointer reserved2;
+
+  guint freeze_count;
+  
+  /* allocation rectangle after the conatiner_border_width
+   * and the width of the shadow border */
+  GdkRectangle internal_allocation;
+  
+  /* rows */
+  gint rows;
+  gint row_height;
+  GList *row_list;
+  GList *row_list_end;
+  
+  /* columns */
+  gint columns;
+  GdkRectangle column_title_area;
+  GdkWindow *title_window;
+  
+  /* dynamicly allocated array of column structures */
+  GtkCMCListColumn *column;
+  
+  /* the scrolling window and its height and width to
+   * make things a little speedier */
+  GdkWindow *clist_window;
+  gint clist_window_width;
+  gint clist_window_height;
+  
+  /* offsets for scrolling */
+  gint hoffset;
+  gint voffset;
+  
+  /* border shadow style */
+  GtkShadowType shadow_type;
+  
+  /* the list's selection mode (gtkenums.h) */
+  GtkSelectionMode selection_mode;
+  
+  /* list of selected rows */
+  GList *selection;
+  GList *selection_end;
+  
+  GList *undo_selection;
+  GList *undo_unselection;
+  gint undo_anchor;
+  
+  /* mouse buttons */
+  guint8 button_actions[5];
+
+  guint8 drag_button;
+
+  /* dnd */
+  GtkCMCListCellInfo click_cell;
+
+  /* scroll adjustments */
+  GtkAdjustment *hadjustment;
+  GtkAdjustment *vadjustment;
+  
+  /* xor GC for the vertical drag line */
+  GdkGC *xor_gc;
+  
+  /* gc for drawing unselected cells */
+  GdkGC *fg_gc;
+  GdkGC *bg_gc;
+  
+  /* cursor used to indicate dragging */
+  GdkCursor *cursor_drag;
+  
+  /* the current x-pixel location of the xor-drag line */
+  gint x_drag;
+  
+  /* focus handling */
+  gint focus_row;
+
+  gint focus_header_column;
+  
+  /* dragging the selection */
+  gint anchor;
+  GtkStateType anchor_state;
+  gint drag_pos;
+  gint htimer;
+  gint vtimer;
+  
+  GtkSortType sort_type;
+  GtkCMCListCompareFunc compare;
+  gint sort_column;
+
+  gint drag_highlight_row;
+  GtkCMCListDragPos drag_highlight_pos;
+};
+
+struct _GtkCMCListClass
+{
+  GtkContainerClass parent_class;
+  
+  void  (*set_scroll_adjustments) (GtkCMCList       *clist,
+                                  GtkAdjustment  *hadjustment,
+                                  GtkAdjustment  *vadjustment);
+  void   (*refresh)             (GtkCMCList       *clist);
+  void   (*select_row)          (GtkCMCList       *clist,
+                                gint            row,
+                                gint            column,
+                                GdkEvent       *event);
+  void   (*unselect_row)        (GtkCMCList       *clist,
+                                gint            row,
+                                gint            column,
+                                GdkEvent       *event);
+  void   (*row_move)            (GtkCMCList       *clist,
+                                gint            source_row,
+                                gint            dest_row);
+  void   (*click_column)        (GtkCMCList       *clist,
+                                gint            column);
+  void   (*resize_column)       (GtkCMCList       *clist,
+                                gint            column,
+                                 gint            width);
+  void   (*toggle_focus_row)    (GtkCMCList       *clist);
+  void   (*select_all)          (GtkCMCList       *clist);
+  void   (*unselect_all)        (GtkCMCList       *clist);
+  void   (*undo_selection)      (GtkCMCList       *clist);
+  void   (*start_selection)     (GtkCMCList       *clist);
+  void   (*end_selection)       (GtkCMCList       *clist);
+  void   (*extend_selection)    (GtkCMCList       *clist,
+                                GtkScrollType   scroll_type,
+                                gfloat          position,
+                                gboolean        auto_start_selection);
+  void   (*scroll_horizontal)   (GtkCMCList       *clist,
+                                GtkScrollType   scroll_type,
+                                gfloat          position);
+  void   (*scroll_vertical)     (GtkCMCList       *clist,
+                                GtkScrollType   scroll_type,
+                                gfloat          position);
+  void   (*toggle_add_mode)     (GtkCMCList       *clist);
+  void   (*abort_column_resize) (GtkCMCList       *clist);
+  void   (*resync_selection)    (GtkCMCList       *clist,
+                                GdkEvent       *event);
+  GList* (*selection_find)      (GtkCMCList       *clist,
+                                gint            row_number,
+                                GList          *row_list_element);
+  void   (*draw_row)            (GtkCMCList       *clist,
+                                GdkRectangle   *area,
+                                gint            row,
+                                GtkCMCListRow    *clist_row);
+  void   (*draw_drag_highlight) (GtkCMCList        *clist,
+                                GtkCMCListRow     *target_row,
+                                gint             target_row_number,
+                                GtkCMCListDragPos  drag_pos);
+  void   (*clear)               (GtkCMCList       *clist);
+  void   (*fake_unselect_all)   (GtkCMCList       *clist,
+                                gint            row);
+  void   (*sort_list)           (GtkCMCList       *clist);
+  gint   (*insert_row)          (GtkCMCList       *clist,
+                                gint            row,
+                                gchar          *text[]);
+  void   (*remove_row)          (GtkCMCList       *clist,
+                                gint            row);
+  void   (*set_cell_contents)   (GtkCMCList       *clist,
+                                GtkCMCListRow    *clist_row,
+                                gint            column,
+                                GtkCMCellType     type,
+                                const gchar    *text,
+                                guint8          spacing,
+                                GdkPixmap      *pixmap,
+                                GdkBitmap      *mask);
+  void   (*cell_size_request)   (GtkCMCList       *clist,
+                                GtkCMCListRow    *clist_row,
+                                gint            column,
+                                GtkRequisition *requisition);
+
+};
+
+struct _GtkCMCListColumn
+{
+  gchar *title;
+  GdkRectangle area;
+  
+  GtkWidget *button;
+  GdkWindow *window;
+  
+  gint width;
+  gint min_width;
+  gint max_width;
+  GtkJustification justification;
+  
+  guint visible        : 1;  
+  guint width_set      : 1;
+  guint resizeable     : 1;
+  guint auto_resize    : 1;
+  guint button_passive : 1;
+};
+
+struct _GtkCMCListRow
+{
+  GtkCMCell *cell;
+  GtkStateType state;
+  
+  GdkColor foreground;
+  GdkColor background;
+  
+  GtkStyle *style;
+
+  gpointer data;
+  GtkDestroyNotify destroy;
+  
+  guint fg_set     : 1;
+  guint bg_set     : 1;
+  guint selectable : 1;
+};
+
+/* Cell Structures */
+struct _GtkCMCellText
+{
+  GtkCMCellType type;
+  
+  gint16 vertical;
+  gint16 horizontal;
+  
+  GtkStyle *style;
+
+  gchar *text;
+};
+
+struct _GtkCMCellPixmap
+{
+  GtkCMCellType type;
+  
+  gint16 vertical;
+  gint16 horizontal;
+  
+  GtkStyle *style;
+
+  GdkPixmap *pixmap;
+  GdkBitmap *mask;
+};
+
+struct _GtkCMCellPixText
+{
+  GtkCMCellType type;
+  
+  gint16 vertical;
+  gint16 horizontal;
+  
+  GtkStyle *style;
+
+  gchar *text;
+  guint8 spacing;
+  GdkPixmap *pixmap;
+  GdkBitmap *mask;
+};
+
+struct _GtkCMCellWidget
+{
+  GtkCMCellType type;
+  
+  gint16 vertical;
+  gint16 horizontal;
+  
+  GtkStyle *style;
+
+  GtkWidget *widget;
+};
+
+struct _GtkCMCell
+{
+  GtkCMCellType type;
+  
+  gint16 vertical;
+  gint16 horizontal;
+  
+  GtkStyle *style;
+
+  union {
+    gchar *text;
+    
+    struct {
+      GdkPixmap *pixmap;
+      GdkBitmap *mask;
+    } pm;
+    
+    struct {
+      gchar *text;
+      guint8 spacing;
+      GdkPixmap *pixmap;
+      GdkBitmap *mask;
+    } pt;
+    
+    GtkWidget *widget;
+  } u;
+};
+
+GType gtk_cmclist_get_type (void);
+
+/* create a new GtkCMCList */
+GtkWidget* gtk_cmclist_new             (gint   columns);
+GtkWidget* gtk_cmclist_new_with_titles (gint   columns,
+                                     gchar *titles[]);
+
+/* set adjustments of clist */
+void gtk_cmclist_set_hadjustment (GtkCMCList      *clist,
+                               GtkAdjustment *adjustment);
+void gtk_cmclist_set_vadjustment (GtkCMCList      *clist,
+                               GtkAdjustment *adjustment);
+
+/* get adjustments of clist */
+GtkAdjustment* gtk_cmclist_get_hadjustment (GtkCMCList *clist);
+GtkAdjustment* gtk_cmclist_get_vadjustment (GtkCMCList *clist);
+
+/* set the border style of the clist */
+void gtk_cmclist_set_shadow_type (GtkCMCList      *clist,
+                               GtkShadowType  type);
+
+/* set the clist's selection mode */
+void gtk_cmclist_set_selection_mode (GtkCMCList         *clist,
+                                  GtkSelectionMode  mode);
+
+/* enable clists reorder ability */
+void gtk_cmclist_set_reorderable (GtkCMCList *clist,
+                               gboolean  reorderable);
+void gtk_cmclist_set_use_drag_icons (GtkCMCList *clist,
+                                  gboolean  use_icons);
+void gtk_cmclist_set_button_actions (GtkCMCList *clist,
+                                  guint     button,
+                                  guint8    button_actions);
+
+/* freeze all visual updates of the list, and then thaw the list after
+ * you have made a number of changes and the updates wil occure in a
+ * more efficent mannor than if you made them on a unfrozen list
+ */
+void gtk_cmclist_freeze (GtkCMCList *clist);
+void gtk_cmclist_thaw   (GtkCMCList *clist);
+
+/* show and hide the column title buttons */
+void gtk_cmclist_column_titles_show (GtkCMCList *clist);
+void gtk_cmclist_column_titles_hide (GtkCMCList *clist);
+
+/* set the column title to be a active title (responds to button presses, 
+ * prelights, and grabs keyboard focus), or passive where it acts as just
+ * a title
+ */
+void gtk_cmclist_column_title_active   (GtkCMCList *clist,
+                                     gint      column);
+void gtk_cmclist_column_title_passive  (GtkCMCList *clist,
+                                     gint      column);
+void gtk_cmclist_column_titles_active  (GtkCMCList *clist);
+void gtk_cmclist_column_titles_passive (GtkCMCList *clist);
+
+/* set the title in the column title button */
+void gtk_cmclist_set_column_title (GtkCMCList    *clist,
+                                gint         column,
+                                const gchar *title);
+
+/* returns the title of column. Returns NULL if title is not set */
+gchar * gtk_cmclist_get_column_title (GtkCMCList *clist,
+                                   gint      column);
+
+/* set a widget instead of a title for the column title button */
+void gtk_cmclist_set_column_widget (GtkCMCList  *clist,
+                                 gint       column,
+                                 GtkWidget *widget);
+
+/* returns the column widget */
+GtkWidget * gtk_cmclist_get_column_widget (GtkCMCList *clist,
+                                        gint      column);
+
+/* set the justification on a column */
+void gtk_cmclist_set_column_justification (GtkCMCList         *clist,
+                                        gint              column,
+                                        GtkJustification  justification);
+
+/* set visibility of a column */
+void gtk_cmclist_set_column_visibility (GtkCMCList *clist,
+                                     gint      column,
+                                     gboolean  visible);
+
+/* enable/disable column resize operations by mouse */
+void gtk_cmclist_set_column_resizeable (GtkCMCList *clist,
+                                     gint      column,
+                                     gboolean  resizeable);
+
+/* resize column automatically to its optimal width */
+void gtk_cmclist_set_column_auto_resize (GtkCMCList *clist,
+                                      gint      column,
+                                      gboolean  auto_resize);
+
+gint gtk_cmclist_columns_autosize (GtkCMCList *clist);
+
+/* return the optimal column width, i.e. maximum of all cell widths */
+gint gtk_cmclist_optimal_column_width (GtkCMCList *clist,
+                                    gint      column);
+
+/* set the pixel width of a column; this is a necessary step in
+ * creating a CList because otherwise the column width is chozen from
+ * the width of the column title, which will never be right
+ */
+void gtk_cmclist_set_column_width (GtkCMCList *clist,
+                                gint      column,
+                                gint      width);
+
+/* set column minimum/maximum width. min/max_width < 0 => no restriction */
+void gtk_cmclist_set_column_min_width (GtkCMCList *clist,
+                                    gint      column,
+                                    gint      min_width);
+void gtk_cmclist_set_column_max_width (GtkCMCList *clist,
+                                    gint      column,
+                                    gint      max_width);
+
+/* change the height of the rows, the default (height=0) is
+ * the hight of the current font.
+ */
+void gtk_cmclist_set_row_height (GtkCMCList *clist,
+                              guint     height);
+
+/* scroll the viewing area of the list to the given column and row;
+ * row_align and col_align are between 0-1 representing the location the
+ * row should appear on the screnn, 0.0 being top or left, 1.0 being
+ * bottom or right; if row or column is -1 then then there is no change
+ */
+void gtk_cmclist_moveto (GtkCMCList *clist,
+                      gint      row,
+                      gint      column,
+                      gfloat    row_align,
+                      gfloat    col_align);
+
+/* returns whether the row is visible */
+GtkVisibility gtk_cmclist_row_is_visible (GtkCMCList *clist,
+                                       gint      row);
+
+/* returns the cell type */
+GtkCMCellType gtk_cmclist_get_cell_type (GtkCMCList *clist,
+                                    gint      row,
+                                    gint      column);
+
+/* sets a given cell's text, replacing its current contents */
+void gtk_cmclist_set_text (GtkCMCList    *clist,
+                        gint         row,
+                        gint         column,
+                        const gchar *text);
+
+/* for the "get" functions, any of the return pointer can be
+ * NULL if you are not interested
+ */
+gint gtk_cmclist_get_text (GtkCMCList  *clist,
+                        gint       row,
+                        gint       column,
+                        gchar    **text);
+
+/* sets a given cell's pixmap, replacing its current contents */
+void gtk_cmclist_set_pixmap (GtkCMCList  *clist,
+                          gint       row,
+                          gint       column,
+                          GdkPixmap *pixmap,
+                          GdkBitmap *mask);
+
+gint gtk_cmclist_get_pixmap (GtkCMCList   *clist,
+                          gint        row,
+                          gint        column,
+                          GdkPixmap **pixmap,
+                          GdkBitmap **mask);
+
+/* sets a given cell's pixmap and text, replacing its current contents */
+void gtk_cmclist_set_pixtext (GtkCMCList    *clist,
+                           gint         row,
+                           gint         column,
+                           const gchar *text,
+                           guint8       spacing,
+                           GdkPixmap   *pixmap,
+                           GdkBitmap   *mask);
+
+gint gtk_cmclist_get_pixtext (GtkCMCList   *clist,
+                           gint        row,
+                           gint        column,
+                           gchar     **text,
+                           guint8     *spacing,
+                           GdkPixmap **pixmap,
+                           GdkBitmap **mask);
+
+/* sets the foreground color of a row, the color must already
+ * be allocated
+ */
+void gtk_cmclist_set_foreground (GtkCMCList       *clist,
+                              gint            row,
+                              const GdkColor *color);
+
+/* sets the background color of a row, the color must already
+ * be allocated
+ */
+void gtk_cmclist_set_background (GtkCMCList       *clist,
+                              gint            row,
+                              const GdkColor *color);
+
+/* set / get cell styles */
+void gtk_cmclist_set_cell_style (GtkCMCList *clist,
+                              gint      row,
+                              gint      column,
+                              GtkStyle *style);
+
+GtkStyle *gtk_cmclist_get_cell_style (GtkCMCList *clist,
+                                   gint      row,
+                                   gint      column);
+
+void gtk_cmclist_set_row_style (GtkCMCList *clist,
+                             gint      row,
+                             GtkStyle *style);
+
+GtkStyle *gtk_cmclist_get_row_style (GtkCMCList *clist,
+                                  gint      row);
+
+/* this sets a horizontal and vertical shift for drawing
+ * the contents of a cell; it can be positive or negitive;
+ * this is particulary useful for indenting items in a column
+ */
+void gtk_cmclist_set_shift (GtkCMCList *clist,
+                         gint      row,
+                         gint      column,
+                         gint      vertical,
+                         gint      horizontal);
+
+/* set/get selectable flag of a single row */
+void gtk_cmclist_set_selectable (GtkCMCList *clist,
+                              gint      row,
+                              gboolean  selectable);
+gboolean gtk_cmclist_get_selectable (GtkCMCList *clist,
+                                  gint      row);
+
+/* prepend/append returns the index of the row you just added,
+ * making it easier to append and modify a row
+ */
+gint gtk_cmclist_prepend (GtkCMCList    *clist,
+                       gchar       *text[]);
+gint gtk_cmclist_append  (GtkCMCList    *clist,
+                       gchar       *text[]);
+
+/* inserts a row at index row and returns the row where it was
+ * actually inserted (may be different from "row" in auto_sort mode)
+ */
+gint gtk_cmclist_insert (GtkCMCList    *clist,
+                      gint         row,
+                      gchar       *text[]);
+
+/* removes row at index row */
+void gtk_cmclist_remove (GtkCMCList *clist,
+                      gint      row);
+
+/* sets a arbitrary data pointer for a given row */
+void gtk_cmclist_set_row_data (GtkCMCList *clist,
+                            gint      row,
+                            gpointer  data);
+
+/* sets a data pointer for a given row with destroy notification */
+void gtk_cmclist_set_row_data_full (GtkCMCList         *clist,
+                                 gint              row,
+                                 gpointer          data,
+                                 GtkDestroyNotify  destroy);
+
+/* returns the data set for a row */
+gpointer gtk_cmclist_get_row_data (GtkCMCList *clist,
+                                gint      row);
+
+/* givin a data pointer, find the first (and hopefully only!)
+ * row that points to that data, or -1 if none do
+ */
+gint gtk_cmclist_find_row_from_data (GtkCMCList *clist,
+                                  gpointer  data);
+
+/* force selection of a row */
+void gtk_cmclist_select_row (GtkCMCList *clist,
+                          gint      row,
+                          gint      column);
+
+/* force unselection of a row */
+void gtk_cmclist_unselect_row (GtkCMCList *clist,
+                            gint      row,
+                            gint      column);
+
+/* undo the last select/unselect operation */
+void gtk_cmclist_undo_selection (GtkCMCList *clist);
+
+/* clear the entire list -- this is much faster than removing
+ * each item with gtk_cmclist_remove
+ */
+void gtk_cmclist_clear (GtkCMCList *clist);
+
+/* return the row column corresponding to the x and y coordinates,
+ * the returned values are only valid if the x and y coordinates
+ * are respectively to a window == clist->clist_window
+ */
+gint gtk_cmclist_get_selection_info (GtkCMCList *clist,
+                                  gint      x,
+                                  gint      y,
+                                  gint     *row,
+                                  gint     *column);
+
+/* in multiple or extended mode, select all rows */
+void gtk_cmclist_select_all (GtkCMCList *clist);
+
+/* in all modes except browse mode, deselect all rows */
+void gtk_cmclist_unselect_all (GtkCMCList *clist);
+
+/* swap the position of two rows */
+void gtk_cmclist_swap_rows (GtkCMCList *clist,
+                         gint      row1,
+                         gint      row2);
+
+/* move row from source_row position to dest_row position */
+void gtk_cmclist_row_move (GtkCMCList *clist,
+                        gint      source_row,
+                        gint      dest_row);
+
+/* sets a compare function different to the default */
+void gtk_cmclist_set_compare_func (GtkCMCList            *clist,
+                                GtkCMCListCompareFunc  cmp_func);
+
+/* the column to sort by */
+void gtk_cmclist_set_sort_column (GtkCMCList *clist,
+                               gint      column);
+
+/* how to sort : ascending or descending */
+void gtk_cmclist_set_sort_type (GtkCMCList    *clist,
+                             GtkSortType  sort_type);
+
+/* sort the list with the current compare function */
+void gtk_cmclist_sort (GtkCMCList *clist);
+
+/* Automatically sort upon insertion */
+void gtk_cmclist_set_auto_sort (GtkCMCList *clist,
+                             gboolean  auto_sort);
+
+/* Private function for clist, ctree */
+
+PangoLayout *_gtk_cmclist_create_cell_layout (GtkCMCList       *clist,
+                                           GtkCMCListRow    *clist_row,
+                                           gint            column);
+
+
+G_END_DECLS
+
+
+#endif                         /* __GTK_CMCLIST_H__ */
diff --git a/src/gtk/gtkcmctree.c b/src/gtk/gtkcmctree.c
new file mode 100644 (file)
index 0000000..e5dde6e
--- /dev/null
@@ -0,0 +1,6198 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald, 
+ * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>  
+ *
+ * GtkCMCTree widget for GTK+
+ * Copyright (C) 1998 Lars Hamann and Stefan Jeske
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include "gtkcmctree.h"
+#include "claws-marshal.h"
+
+#define PM_SIZE                    8
+#define TAB_SIZE                   (PM_SIZE + 6)
+#define CELL_SPACING               1
+#define CLIST_OPTIMUM_SIZE         64
+#define COLUMN_INSET               3
+#define DRAG_WIDTH                 6
+
+#define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
+                                   (((row) + 1) * CELL_SPACING) + \
+                                   (clist)->voffset)
+#define ROW_FROM_YPIXEL(clist, y)  (((y) - (clist)->voffset) / \
+                                    ((clist)->row_height + CELL_SPACING))
+#define COLUMN_LEFT_XPIXEL(clist, col)  ((clist)->column[(col)].area.x \
+                                    + (clist)->hoffset)
+#define COLUMN_LEFT(clist, column) ((clist)->column[(column)].area.x)
+
+GType
+gtk_cmctree_pos_get_type (void)
+{
+  static GType etype = 0;
+  if (etype == 0) {
+    static const GEnumValue values[] = {
+      { GTK_CMCTREE_POS_BEFORE, "GTK_CMCTREE_POS_BEFORE", "before" },
+      { GTK_CMCTREE_POS_AS_CHILD, "GTK_CMCTREE_POS_AS_CHILD", "as-child" },
+      { GTK_CMCTREE_POS_AFTER, "GTK_CMCTREE_POS_AFTER", "after" },
+      { 0, NULL, NULL }
+    };
+    etype = g_enum_register_static (g_intern_static_string ("GtkCMCTreePos"), values);
+  }
+  return etype;
+}
+GType
+gtk_cmctree_line_style_get_type (void)
+{
+  static GType etype = 0;
+  if (etype == 0) {
+    static const GEnumValue values[] = {
+      { GTK_CMCTREE_LINES_NONE, "GTK_CMCTREE_LINES_NONE", "none" },
+      { GTK_CMCTREE_LINES_SOLID, "GTK_CMCTREE_LINES_SOLID", "solid" },
+      { GTK_CMCTREE_LINES_DOTTED, "GTK_CMCTREE_LINES_DOTTED", "dotted" },
+      { GTK_CMCTREE_LINES_TABBED, "GTK_CMCTREE_LINES_TABBED", "tabbed" },
+      { 0, NULL, NULL }
+    };
+    etype = g_enum_register_static (g_intern_static_string ("GtkCMCTreeLineStyle"), values);
+  }
+  return etype;
+}
+GType
+gtk_cmctree_expander_style_get_type (void)
+{
+  static GType etype = 0;
+  if (etype == 0) {
+    static const GEnumValue values[] = {
+      { GTK_CMCTREE_EXPANDER_NONE, "GTK_CMCTREE_EXPANDER_NONE", "none" },
+      { GTK_CMCTREE_EXPANDER_SQUARE, "GTK_CMCTREE_EXPANDER_SQUARE", "square" },
+      { GTK_CMCTREE_EXPANDER_TRIANGLE, "GTK_CMCTREE_EXPANDER_TRIANGLE", "triangle" },
+      { GTK_CMCTREE_EXPANDER_CIRCULAR, "GTK_CMCTREE_EXPANDER_CIRCULAR", "circular" },
+      { 0, NULL, NULL }
+    };
+    etype = g_enum_register_static (g_intern_static_string ("GtkCMCTreeExpanderStyle"), values);
+  }
+  return etype;
+}
+GType
+gtk_cmctree_expansion_type_get_type (void)
+{
+  static GType etype = 0;
+  if (etype == 0) {
+    static const GEnumValue values[] = {
+      { GTK_CMCTREE_EXPANSION_EXPAND, "GTK_CMCTREE_EXPANSION_EXPAND", "expand" },
+      { GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE, "GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE", "expand-recursive" },
+      { GTK_CMCTREE_EXPANSION_COLLAPSE, "GTK_CMCTREE_EXPANSION_COLLAPSE", "collapse" },
+      { GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE, "GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE", "collapse-recursive" },
+      { GTK_CMCTREE_EXPANSION_TOGGLE, "GTK_CMCTREE_EXPANSION_TOGGLE", "toggle" },
+      { GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE, "GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE", "toggle-recursive" },
+      { 0, NULL, NULL }
+    };
+    etype = g_enum_register_static (g_intern_static_string ("GtkCMCTreeExpansionType"), values);
+  }
+  return etype;
+}
+
+
+static inline gint
+COLUMN_FROM_XPIXEL (GtkCMCList * clist,
+                   gint x)
+{
+  gint i, cx;
+
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].visible)
+      {
+       cx = clist->column[i].area.x + clist->hoffset;
+
+       if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
+           x <= (cx + clist->column[i].area.width + COLUMN_INSET))
+         return i;
+      }
+
+  /* no match */
+  return -1;
+}
+
+#define CLIST_UNFROZEN(clist)     (((GtkCMCList*) (clist))->freeze_count == 0)
+#define CLIST_REFRESH(clist)    G_STMT_START { \
+  if (CLIST_UNFROZEN (clist)) \
+    GTK_CMCLIST_GET_CLASS (clist)->refresh ((GtkCMCList*) (clist)); \
+} G_STMT_END
+
+
+enum {
+  ARG_0,
+  ARG_N_COLUMNS,
+  ARG_TREE_COLUMN,
+  ARG_INDENT,
+  ARG_SPACING,
+  ARG_SHOW_STUB,
+  ARG_LINE_STYLE,
+  ARG_EXPANDER_STYLE
+};
+
+
+static void     gtk_cmctree_class_init    (GtkCMCTreeClass         *klass);
+static void     gtk_cmctree_init          (GtkCMCTree              *ctree);
+static GObject* gtk_cmctree_constructor   (GType                  type,
+                                        guint                  n_construct_properties,
+                                        GObjectConstructParam *construct_params);
+static void gtk_cmctree_set_arg                (GObject *object,
+                               guint      arg_id,
+                               const GValue *value,
+                               GParamSpec *spec);
+static void gtk_cmctree_get_arg        (GObject *object,
+                               guint      arg_id,
+                               GValue *value,
+                               GParamSpec *spec);
+static void gtk_cmctree_realize           (GtkWidget      *widget);
+static void gtk_cmctree_unrealize         (GtkWidget      *widget);
+static gint gtk_cmctree_button_press      (GtkWidget      *widget,
+                                        GdkEventButton *event);
+static void ctree_attach_styles         (GtkCMCTree       *ctree,
+                                        GtkCMCTreeNode   *node,
+                                        gpointer        data);
+static void ctree_detach_styles         (GtkCMCTree       *ctree,
+                                        GtkCMCTreeNode   *node, 
+                                        gpointer        data);
+static gint draw_cell_pixmap            (GdkWindow      *window,
+                                        GdkRectangle   *clip_rectangle,
+                                        GdkGC          *fg_gc,
+                                        GdkPixmap      *pixmap,
+                                        GdkBitmap      *mask,
+                                        gint            x,
+                                        gint            y,
+                                        gint            width,
+                                        gint            height);
+static void get_cell_style              (GtkCMCList       *clist,
+                                        GtkCMCListRow    *clist_row,
+                                        gint            state,
+                                        gint            column,
+                                        GtkStyle      **style,
+                                        GdkGC         **fg_gc,
+                                        GdkGC         **bg_gc);
+static gint gtk_cmctree_draw_expander     (GtkCMCTree       *ctree,
+                                        GtkCMCTreeRow    *ctree_row,
+                                        GtkStyle       *style,
+                                        GdkRectangle   *clip_rectangle,
+                                        gint            x);
+static gint gtk_cmctree_draw_lines        (GtkCMCTree       *ctree,
+                                        GtkCMCTreeRow    *ctree_row,
+                                        gint            row,
+                                        gint            column,
+                                        gint            state,
+                                        GdkRectangle   *clip_rectangle,
+                                        GdkRectangle   *cell_rectangle,
+                                        GdkRectangle   *crect,
+                                        GdkRectangle   *area,
+                                        GtkStyle       *style);
+static void draw_row                    (GtkCMCList       *clist,
+                                        GdkRectangle   *area,
+                                        gint            row,
+                                        GtkCMCListRow    *clist_row);
+static void draw_drag_highlight         (GtkCMCList        *clist,
+                                        GtkCMCListRow     *dest_row,
+                                        gint             dest_row_number,
+                                        GtkCMCListDragPos  drag_pos);
+static void tree_draw_node              (GtkCMCTree      *ctree,
+                                        GtkCMCTreeNode  *node);
+static void set_cell_contents           (GtkCMCList      *clist,
+                                        GtkCMCListRow   *clist_row,
+                                        gint           column,
+                                        GtkCMCellType    type,
+                                        const gchar   *text,
+                                        guint8         spacing,
+                                        GdkPixmap     *pixmap,
+                                        GdkBitmap     *mask);
+static void set_node_info               (GtkCMCTree      *ctree,
+                                        GtkCMCTreeNode  *node,
+                                        const gchar   *text,
+                                        guint8         spacing,
+                                        GdkPixmap     *pixmap_closed,
+                                        GdkBitmap     *mask_closed,
+                                        GdkPixmap     *pixmap_opened,
+                                        GdkBitmap     *mask_opened,
+                                        gboolean       is_leaf,
+                                        gboolean       expanded);
+static GtkCMCTreeRow *row_new             (GtkCMCTree      *ctree);
+static void row_delete                  (GtkCMCTree      *ctree,
+                                        GtkCMCTreeRow   *ctree_row);
+static void tree_delete                 (GtkCMCTree      *ctree, 
+                                        GtkCMCTreeNode  *node, 
+                                        gpointer       data);
+static void tree_delete_row             (GtkCMCTree      *ctree, 
+                                        GtkCMCTreeNode  *node, 
+                                        gpointer       data);
+static void real_clear                  (GtkCMCList      *clist);
+static void tree_update_level           (GtkCMCTree      *ctree, 
+                                        GtkCMCTreeNode  *node, 
+                                        gpointer       data);
+static void tree_select                 (GtkCMCTree      *ctree, 
+                                        GtkCMCTreeNode  *node, 
+                                        gpointer       data);
+static void tree_unselect               (GtkCMCTree      *ctree, 
+                                        GtkCMCTreeNode  *node, 
+                                        gpointer       data);
+static void real_select_all             (GtkCMCList      *clist);
+static void real_unselect_all           (GtkCMCList      *clist);
+static void tree_expand                 (GtkCMCTree      *ctree, 
+                                        GtkCMCTreeNode  *node,
+                                        gpointer       data);
+static void tree_collapse               (GtkCMCTree      *ctree, 
+                                        GtkCMCTreeNode  *node,
+                                        gpointer       data);
+static void tree_collapse_to_depth      (GtkCMCTree      *ctree, 
+                                        GtkCMCTreeNode  *node, 
+                                        gint           depth);
+static void tree_toggle_expansion       (GtkCMCTree      *ctree,
+                                        GtkCMCTreeNode  *node,
+                                        gpointer       data);
+static void change_focus_row_expansion  (GtkCMCTree      *ctree,
+                                        GtkCMCTreeExpansionType expansion);
+static void real_select_row             (GtkCMCList      *clist,
+                                        gint           row,
+                                        gint           column,
+                                        GdkEvent      *event);
+static void real_unselect_row           (GtkCMCList      *clist,
+                                        gint           row,
+                                        gint           column,
+                                        GdkEvent      *event);
+static void real_tree_select            (GtkCMCTree      *ctree,
+                                        GtkCMCTreeNode  *node,
+                                        gint           column);
+static void real_tree_unselect          (GtkCMCTree      *ctree,
+                                        GtkCMCTreeNode  *node,
+                                        gint           column);
+static void real_tree_expand            (GtkCMCTree      *ctree,
+                                        GtkCMCTreeNode  *node);
+static void real_tree_collapse          (GtkCMCTree      *ctree,
+                                        GtkCMCTreeNode  *node);
+static void real_tree_move              (GtkCMCTree      *ctree,
+                                        GtkCMCTreeNode  *node,
+                                        GtkCMCTreeNode  *new_parent, 
+                                        GtkCMCTreeNode  *new_sibling);
+static void real_row_move               (GtkCMCList      *clist,
+                                        gint           source_row,
+                                        gint           dest_row);
+static void gtk_cmctree_link              (GtkCMCTree      *ctree,
+                                        GtkCMCTreeNode  *node,
+                                        GtkCMCTreeNode  *parent,
+                                        GtkCMCTreeNode  *sibling,
+                                        gboolean       update_focus_row);
+static void gtk_cmctree_unlink            (GtkCMCTree      *ctree, 
+                                        GtkCMCTreeNode  *node,
+                                        gboolean       update_focus_row);
+static GtkCMCTreeNode * gtk_cmctree_last_visible (GtkCMCTree     *ctree,
+                                             GtkCMCTreeNode *node);
+static gboolean ctree_is_hot_spot       (GtkCMCTree      *ctree, 
+                                        GtkCMCTreeNode  *node,
+                                        gint           row, 
+                                        gint           x, 
+                                        gint           y);
+static void tree_sort                   (GtkCMCTree      *ctree,
+                                        GtkCMCTreeNode  *node,
+                                        gpointer       data);
+static void fake_unselect_all           (GtkCMCList      *clist,
+                                        gint           row);
+static GList * selection_find           (GtkCMCList      *clist,
+                                        gint           row_number,
+                                        GList         *row_list_element);
+static void resync_selection            (GtkCMCList      *clist,
+                                        GdkEvent      *event);
+static void real_undo_selection         (GtkCMCList      *clist);
+static void select_row_recursive        (GtkCMCTree      *ctree, 
+                                        GtkCMCTreeNode  *node, 
+                                        gpointer       data);
+static gint real_insert_row             (GtkCMCList      *clist,
+                                        gint           row,
+                                        gchar         *text[]);
+static void real_remove_row             (GtkCMCList      *clist,
+                                        gint           row);
+static void real_sort_list              (GtkCMCList      *clist);
+static void cell_size_request           (GtkCMCList       *clist,
+                                        GtkCMCListRow    *clist_row,
+                                        gint            column,
+                                        GtkRequisition *requisition);
+static void column_auto_resize          (GtkCMCList       *clist,
+                                        GtkCMCListRow    *clist_row,
+                                        gint            column,
+                                        gint            old_width);
+static void auto_resize_columns         (GtkCMCList       *clist);
+
+
+static gboolean check_drag               (GtkCMCTree         *ctree,
+                                         GtkCMCTreeNode     *drag_source,
+                                         GtkCMCTreeNode     *drag_target,
+                                         GtkCMCListDragPos   insert_pos);
+static void gtk_cmctree_drag_begin         (GtkWidget        *widget,
+                                         GdkDragContext   *context);
+static gint gtk_cmctree_drag_motion        (GtkWidget        *widget,
+                                         GdkDragContext   *context,
+                                         gint              x,
+                                         gint              y,
+                                         guint             time);
+static void gtk_cmctree_drag_data_received (GtkWidget        *widget,
+                                         GdkDragContext   *context,
+                                         gint              x,
+                                         gint              y,
+                                         GtkSelectionData *selection_data,
+                                         guint             info,
+                                         guint32           time);
+static void remove_grab                  (GtkCMCList         *clist);
+static void drag_dest_cell               (GtkCMCList         *clist,
+                                         gint              x,
+                                         gint              y,
+                                         GtkCMCListDestInfo *dest_info);
+
+
+enum
+{
+  TREE_SELECT_ROW,
+  TREE_UNSELECT_ROW,
+  TREE_EXPAND,
+  TREE_COLLAPSE,
+  TREE_MOVE,
+  CHANGE_FOCUS_ROW_EXPANSION,
+  LAST_SIGNAL
+};
+
+static GtkCMCListClass *parent_class = NULL;
+static GtkContainerClass *container_class = NULL;
+static guint ctree_signals[LAST_SIGNAL] = {0};
+
+
+GType
+gtk_cmctree_get_type (void)
+{
+  static GType ctree_type = 0;
+
+  if (!ctree_type)
+    {
+      static const GTypeInfo ctree_info =
+      {
+                       sizeof (GtkCMCTreeClass),
+
+                       (GBaseInitFunc) NULL,
+                       (GBaseFinalizeFunc) NULL,
+
+                       (GClassInitFunc) gtk_cmctree_class_init,
+                       (GClassFinalizeFunc) NULL,
+                       NULL,   /* class_data */
+
+                       sizeof (GtkCMCTree),
+                       0,      /* n_preallocs */
+                       (GInstanceInitFunc) gtk_cmctree_init,
+      };
+
+       ctree_type = g_type_register_static (GTK_TYPE_CMCLIST, "GtkCMCTree", &ctree_info, (GTypeFlags)0);
+    }
+
+  return ctree_type;
+}
+
+static void
+gtk_cmctree_class_init (GtkCMCTreeClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GtkObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+  GtkCMCListClass *clist_class;
+  GtkBindingSet *binding_set;
+
+  gobject_class->constructor = gtk_cmctree_constructor;
+
+  object_class = (GtkObjectClass *) klass;
+  widget_class = (GtkWidgetClass *) klass;
+  container_class = (GtkContainerClass *) klass;
+  clist_class = (GtkCMCListClass *) klass;
+
+  parent_class = gtk_type_class (GTK_TYPE_CMCLIST);
+  container_class = gtk_type_class (GTK_TYPE_CONTAINER);
+
+  gobject_class->set_property = gtk_cmctree_set_arg;
+  gobject_class->get_property = gtk_cmctree_get_arg;
+
+  widget_class->realize = gtk_cmctree_realize;
+  widget_class->unrealize = gtk_cmctree_unrealize;
+  widget_class->button_press_event = gtk_cmctree_button_press;
+
+  widget_class->drag_begin = gtk_cmctree_drag_begin;
+  widget_class->drag_motion = gtk_cmctree_drag_motion;
+  widget_class->drag_data_received = gtk_cmctree_drag_data_received;
+
+  clist_class->select_row = real_select_row;
+  clist_class->unselect_row = real_unselect_row;
+  clist_class->row_move = real_row_move;
+  clist_class->undo_selection = real_undo_selection;
+  clist_class->resync_selection = resync_selection;
+  clist_class->selection_find = selection_find;
+  clist_class->click_column = NULL;
+  clist_class->draw_row = draw_row;
+  clist_class->draw_drag_highlight = draw_drag_highlight;
+  clist_class->clear = real_clear;
+  clist_class->select_all = real_select_all;
+  clist_class->unselect_all = real_unselect_all;
+  clist_class->fake_unselect_all = fake_unselect_all;
+  clist_class->insert_row = real_insert_row;
+  clist_class->remove_row = real_remove_row;
+  clist_class->sort_list = real_sort_list;
+  clist_class->set_cell_contents = set_cell_contents;
+  clist_class->cell_size_request = cell_size_request;
+
+  klass->tree_select_row = real_tree_select;
+  klass->tree_unselect_row = real_tree_unselect;
+  klass->tree_expand = real_tree_expand;
+  klass->tree_collapse = real_tree_collapse;
+  klass->tree_move = real_tree_move;
+  klass->change_focus_row_expansion = change_focus_row_expansion;
+
+  g_object_class_install_property (gobject_class,
+                               ARG_N_COLUMNS,
+                               g_param_spec_uint ("n-columns",
+                               "N-Columns",
+                               "N-Columns",
+                               1,
+                               G_MAXINT,
+                               1,
+                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (gobject_class,
+                               ARG_TREE_COLUMN,
+                               g_param_spec_uint ("tree-column",
+                               "tree-column",
+                               "tree-column",
+                               0,
+                               G_MAXINT,
+                               0,
+                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (gobject_class,
+                               ARG_INDENT,
+                               g_param_spec_uint ("indent",
+                               "indent",
+                               "indent",
+                               1,
+                               G_MAXINT,
+                               1,
+                               G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                               ARG_SPACING,
+                               g_param_spec_uint ("spacing",
+                               "spacing",
+                               "spacing",
+                               1,
+                               G_MAXINT,
+                               1,
+                               G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                               ARG_SHOW_STUB,
+                               g_param_spec_boolean ("show-stub",
+                               "show-stub",
+                               "show-stub",
+                               TRUE,
+                               G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                               ARG_LINE_STYLE,
+                               g_param_spec_enum ("line-style",
+                               "line-style",
+                               "line-style",
+                               GTK_TYPE_CMCTREE_LINE_STYLE, 0,
+                               G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+                               ARG_EXPANDER_STYLE,
+                               g_param_spec_enum ("expander-style",
+                               "expander-style",
+                               "expander-style",
+                               GTK_TYPE_CMCTREE_EXPANDER_STYLE, 0,
+                               G_PARAM_READWRITE));
+
+  ctree_signals[TREE_SELECT_ROW] =
+               g_signal_new ("tree_select_row",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (GtkCMCTreeClass, tree_select_row),
+                             NULL, NULL,
+                             claws_marshal_VOID__POINTER_INT,
+                             G_TYPE_NONE, 2,
+                             GTK_TYPE_CMCTREE_NODE,
+                             G_TYPE_INT);
+  ctree_signals[TREE_UNSELECT_ROW] =
+               g_signal_new ("tree_unselect_row",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (GtkCMCTreeClass, tree_unselect_row),
+                             NULL, NULL,
+                             claws_marshal_VOID__POINTER_INT,
+                             G_TYPE_NONE, 2,
+                             GTK_TYPE_CMCTREE_NODE,
+                             G_TYPE_INT);
+  ctree_signals[TREE_EXPAND] =
+               g_signal_new ("tree_expand",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GtkCMCTreeClass, tree_expand),
+                             NULL, NULL,
+                             claws_marshal_VOID__POINTER,
+                             G_TYPE_NONE, 1,
+                             GTK_TYPE_CMCTREE_NODE);
+  ctree_signals[TREE_COLLAPSE] =
+               g_signal_new ("tree_collapse",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GtkCMCTreeClass, tree_collapse),
+                             NULL, NULL,
+                             claws_marshal_VOID__POINTER,
+                             G_TYPE_NONE, 1,
+                             GTK_TYPE_CMCTREE_NODE);
+  ctree_signals[TREE_MOVE] =
+               g_signal_new ("tree_move",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET (GtkCMCTreeClass, tree_move),
+                             NULL, NULL,
+                             claws_marshal_VOID__POINTER_POINTER_POINTER,
+                             G_TYPE_NONE, 3,
+                             GTK_TYPE_CMCTREE_NODE,GTK_TYPE_CMCTREE_NODE,GTK_TYPE_CMCTREE_NODE);
+  ctree_signals[CHANGE_FOCUS_ROW_EXPANSION] =
+               g_signal_new ("change_focus_row_expansion",
+                             G_TYPE_FROM_CLASS (object_class),
+                             G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                             G_STRUCT_OFFSET (GtkCMCTreeClass, change_focus_row_expansion),
+                             NULL, NULL,
+                             claws_marshal_VOID__ENUM,
+                             G_TYPE_NONE, 1, GTK_TYPE_CMCTREE_EXPANSION_TYPE);
+
+  binding_set = gtk_binding_set_by_class (klass);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_plus, 0,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_EXPAND);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_plus, GDK_CONTROL_MASK,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE);
+
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KP_Add, 0,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_EXPAND);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KP_Add, GDK_CONTROL_MASK,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE);
+  
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_minus, 0,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_COLLAPSE);
+  gtk_binding_entry_add_signal (binding_set,
+                                GDK_minus, GDK_CONTROL_MASK,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM,
+                               GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KP_Subtract, 0,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_COLLAPSE);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KP_Subtract, GDK_CONTROL_MASK,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM,
+                               GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_equal, 0,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_TOGGLE);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KP_Equal, 0,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_TOGGLE);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KP_Multiply, 0,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_TOGGLE);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_asterisk, 0,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM, GTK_CMCTREE_EXPANSION_TOGGLE);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_KP_Multiply, GDK_CONTROL_MASK,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM,
+                               GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE);
+  gtk_binding_entry_add_signal (binding_set,
+                               GDK_asterisk, GDK_CONTROL_MASK,
+                               "change_focus_row_expansion", 1,
+                               G_TYPE_ENUM,
+                               GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE);  
+}
+
+static void
+gtk_cmctree_set_arg (GObject *object,
+                               guint      arg_id,
+                               const GValue *value,
+                               GParamSpec *spec)
+{
+  GtkCMCTree *ctree;
+  GtkCMCList *clist;
+
+  ctree = GTK_CMCTREE (object);
+  clist = GTK_CMCLIST (ctree);
+
+  switch (arg_id)
+    {
+    case ARG_N_COLUMNS: /* construct-only arg, only set at construction time */
+      clist->columns = MAX (1, g_value_get_uint (value));
+      ctree->tree_column = CLAMP (ctree->tree_column, 0, clist->columns);
+      break;
+    case ARG_TREE_COLUMN: /* construct-only arg, only set at construction time */
+      ctree->tree_column = g_value_get_uint (value);
+      ctree->tree_column = CLAMP (ctree->tree_column, 0, clist->columns);
+      break;
+    case ARG_INDENT:
+      gtk_cmctree_set_indent (ctree, g_value_get_uint (value));
+      break;
+    case ARG_SPACING:
+      gtk_cmctree_set_spacing (ctree, g_value_get_uint (value));
+      break;
+    case ARG_SHOW_STUB:
+      gtk_cmctree_set_show_stub (ctree, g_value_get_boolean (value));
+      break;
+    case ARG_LINE_STYLE:
+      gtk_cmctree_set_line_style (ctree, g_value_get_enum (value));
+      break;
+    case ARG_EXPANDER_STYLE:
+      gtk_cmctree_set_expander_style (ctree, g_value_get_enum (value));
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+gtk_cmctree_get_arg (GObject *object,
+                               guint      arg_id,
+                               GValue *value,
+                               GParamSpec *spec)
+{
+  GtkCMCTree *ctree;
+
+  ctree = GTK_CMCTREE (object);
+
+  switch (arg_id)
+    {
+    case ARG_N_COLUMNS:
+      g_value_set_uint(value, GTK_CMCLIST (ctree)->columns);
+      break;
+    case ARG_TREE_COLUMN:
+      g_value_set_uint(value, ctree->tree_column);
+      break;
+    case ARG_INDENT:
+      g_value_set_uint(value, ctree->tree_indent);
+      break;
+    case ARG_SPACING:
+      g_value_set_uint(value, ctree->tree_spacing);
+      break;
+    case ARG_SHOW_STUB:
+      g_value_set_boolean(value, ctree->show_stub);
+      break;
+    case ARG_LINE_STYLE:
+      g_value_set_enum(value, ctree->line_style);
+      break;
+    case ARG_EXPANDER_STYLE:
+      g_value_set_enum(value, ctree->expander_style);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, spec);
+      break;
+    }
+}
+
+static void
+gtk_cmctree_init (GtkCMCTree *ctree)
+{
+  GtkCMCList *clist;
+
+  GTK_CMCLIST_SET_FLAG (ctree, CMCLIST_DRAW_DRAG_RECT);
+  GTK_CMCLIST_SET_FLAG (ctree, CMCLIST_DRAW_DRAG_LINE);
+
+  clist = GTK_CMCLIST (ctree);
+
+  ctree->tree_indent    = 20;
+  ctree->tree_spacing   = 5;
+  ctree->tree_column    = 0;
+  ctree->line_style     = GTK_CMCTREE_LINES_SOLID;
+  ctree->expander_style = GTK_CMCTREE_EXPANDER_SQUARE;
+  ctree->drag_compare   = NULL;
+  ctree->show_stub      = TRUE;
+
+  clist->button_actions[0] |= GTK_CMBUTTON_EXPANDS;
+}
+
+static void
+ctree_attach_styles (GtkCMCTree     *ctree,
+                    GtkCMCTreeNode *node,
+                    gpointer      data)
+{
+  GtkCMCList *clist;
+  gint i;
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (GTK_CMCTREE_ROW (node)->row.style)
+    GTK_CMCTREE_ROW (node)->row.style =
+      gtk_style_attach (GTK_CMCTREE_ROW (node)->row.style, clist->clist_window);
+
+  if (GTK_CMCTREE_ROW (node)->row.fg_set || GTK_CMCTREE_ROW (node)->row.bg_set)
+    {
+      GdkColormap *colormap;
+
+      colormap = gtk_widget_get_colormap (GTK_WIDGET (ctree));
+      if (GTK_CMCTREE_ROW (node)->row.fg_set)
+       gdk_colormap_alloc_color (colormap, &(GTK_CMCTREE_ROW (node)->row.foreground), TRUE, TRUE);
+      if (GTK_CMCTREE_ROW (node)->row.bg_set)
+       gdk_colormap_alloc_color (colormap, &(GTK_CMCTREE_ROW (node)->row.background), TRUE, TRUE);
+    }
+
+  for (i = 0; i < clist->columns; i++)
+    if  (GTK_CMCTREE_ROW (node)->row.cell[i].style)
+      GTK_CMCTREE_ROW (node)->row.cell[i].style =
+       gtk_style_attach (GTK_CMCTREE_ROW (node)->row.cell[i].style,
+                         clist->clist_window);
+}
+
+static void
+ctree_detach_styles (GtkCMCTree     *ctree,
+                    GtkCMCTreeNode *node,
+                    gpointer      data)
+{
+  GtkCMCList *clist;
+  gint i;
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (GTK_CMCTREE_ROW (node)->row.style)
+    gtk_style_detach (GTK_CMCTREE_ROW (node)->row.style);
+  for (i = 0; i < clist->columns; i++)
+    if  (GTK_CMCTREE_ROW (node)->row.cell[i].style)
+      gtk_style_detach (GTK_CMCTREE_ROW (node)->row.cell[i].style);
+}
+
+static void
+gtk_cmctree_realize (GtkWidget *widget)
+{
+  GtkCMCTree *ctree;
+  GtkCMCList *clist;
+  GdkGCValues values;
+  GtkCMCTreeNode *node;
+  GtkCMCTreeNode *child;
+  gint i;
+
+  g_return_if_fail (GTK_IS_CMCTREE (widget));
+
+  GTK_WIDGET_CLASS (parent_class)->realize (widget);
+
+  ctree = GTK_CMCTREE (widget);
+  clist = GTK_CMCLIST (widget);
+
+  node = GTK_CMCTREE_NODE (clist->row_list);
+  for (i = 0; i < clist->rows; i++)
+    {
+      if (GTK_CMCTREE_ROW (node)->children && !GTK_CMCTREE_ROW (node)->expanded)
+       for (child = GTK_CMCTREE_ROW (node)->children; child;
+            child = GTK_CMCTREE_ROW (child)->sibling)
+         gtk_cmctree_pre_recursive (ctree, child, ctree_attach_styles, NULL);
+      node = GTK_CMCTREE_NODE_NEXT (node);
+    }
+
+  values.foreground = widget->style->fg[GTK_STATE_NORMAL];
+  values.background = widget->style->base[GTK_STATE_NORMAL];
+  values.subwindow_mode = GDK_INCLUDE_INFERIORS;
+  values.line_style = GDK_LINE_SOLID;
+  ctree->lines_gc = gdk_gc_new_with_values (GTK_CMCLIST(widget)->clist_window, 
+                                           &values,
+                                           GDK_GC_FOREGROUND |
+                                           GDK_GC_BACKGROUND |
+                                           GDK_GC_SUBWINDOW |
+                                           GDK_GC_LINE_STYLE);
+
+  if (ctree->line_style == GTK_CMCTREE_LINES_DOTTED)
+    {
+      gdk_gc_set_line_attributes (ctree->lines_gc, 1, 
+                                 GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_MITER);
+      gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
+    }
+}
+
+static void
+gtk_cmctree_unrealize (GtkWidget *widget)
+{
+  GtkCMCTree *ctree;
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCTREE (widget));
+
+  GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
+
+  ctree = GTK_CMCTREE (widget);
+  clist = GTK_CMCLIST (widget);
+
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      GtkCMCTreeNode *node;
+      GtkCMCTreeNode *child;
+      gint i;
+
+      node = GTK_CMCTREE_NODE (clist->row_list);
+      for (i = 0; i < clist->rows; i++)
+       {
+         if (GTK_CMCTREE_ROW (node)->children &&
+             !GTK_CMCTREE_ROW (node)->expanded)
+           for (child = GTK_CMCTREE_ROW (node)->children; child;
+                child = GTK_CMCTREE_ROW (child)->sibling)
+             gtk_cmctree_pre_recursive(ctree, child, ctree_detach_styles, NULL);
+         node = GTK_CMCTREE_NODE_NEXT (node);
+       }
+    }
+
+  g_object_unref (ctree->lines_gc);
+}
+
+static gint
+gtk_cmctree_button_press (GtkWidget      *widget,
+                       GdkEventButton *event)
+{
+  GtkCMCTree *ctree;
+  GtkCMCList *clist;
+  gint button_actions;
+
+  g_return_val_if_fail (GTK_IS_CMCTREE (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  ctree = GTK_CMCTREE (widget);
+  clist = GTK_CMCLIST (widget);
+
+  button_actions = clist->button_actions[event->button - 1];
+
+  if (button_actions == GTK_CMBUTTON_IGNORED)
+    return FALSE;
+
+  if (event->window == clist->clist_window)
+    {
+      GtkCMCTreeNode *work;
+      gint x;
+      gint y;
+      gint row;
+      gint column;
+
+      x = event->x;
+      y = event->y;
+
+      if (!gtk_cmclist_get_selection_info (clist, x, y, &row, &column))
+       return FALSE;
+
+      work = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, row));
+         
+      if (button_actions & GTK_CMBUTTON_EXPANDS &&
+         (GTK_CMCTREE_ROW (work)->children && !GTK_CMCTREE_ROW (work)->is_leaf  &&
+          (event->type == GDK_2BUTTON_PRESS ||
+           ctree_is_hot_spot (ctree, work, row, x, y))))
+       {
+         if (GTK_CMCTREE_ROW (work)->expanded)
+           gtk_cmctree_collapse (ctree, work);
+         else
+           gtk_cmctree_expand (ctree, work);
+
+         return TRUE;
+       }
+    }
+  
+  return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event);
+}
+
+static void
+draw_drag_highlight (GtkCMCList        *clist,
+                    GtkCMCListRow     *dest_row,
+                    gint             dest_row_number,
+                    GtkCMCListDragPos  drag_pos)
+{
+  GtkCMCTree *ctree;
+  GdkPoint points[4];
+  gint level;
+  gint i;
+  gint y = 0;
+
+  g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+  ctree = GTK_CMCTREE (clist);
+
+  level = ((GtkCMCTreeRow *)(dest_row))->level;
+
+  y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
+
+  switch (drag_pos)
+    {
+    case GTK_CMCLIST_DRAG_NONE:
+      break;
+    case GTK_CMCLIST_DRAG_AFTER:
+      y += clist->row_height + 1;
+    case GTK_CMCLIST_DRAG_BEFORE:
+      
+      if (clist->column[ctree->tree_column].visible)
+       switch (clist->column[ctree->tree_column].justification)
+         {
+         case GTK_JUSTIFY_CENTER:
+         case GTK_JUSTIFY_FILL:
+         case GTK_JUSTIFY_LEFT:
+           if (ctree->tree_column > 0)
+             gdk_draw_line (clist->clist_window, clist->xor_gc, 
+                            COLUMN_LEFT_XPIXEL(clist, 0), y,
+                            COLUMN_LEFT_XPIXEL(clist, ctree->tree_column - 1)+
+                            clist->column[ctree->tree_column - 1].area.width,
+                            y);
+
+           gdk_draw_line (clist->clist_window, clist->xor_gc, 
+                          COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + 
+                          ctree->tree_indent * level -
+                          (ctree->tree_indent - PM_SIZE) / 2, y,
+                          GTK_WIDGET (ctree)->allocation.width, y);
+           break;
+         case GTK_JUSTIFY_RIGHT:
+           if (ctree->tree_column < clist->columns - 1)
+             gdk_draw_line (clist->clist_window, clist->xor_gc, 
+                            COLUMN_LEFT_XPIXEL(clist, ctree->tree_column + 1),
+                            y,
+                            COLUMN_LEFT_XPIXEL(clist, clist->columns - 1) +
+                            clist->column[clist->columns - 1].area.width, y);
+      
+           gdk_draw_line (clist->clist_window, clist->xor_gc, 
+                          0, y, COLUMN_LEFT_XPIXEL(clist, ctree->tree_column)
+                          + clist->column[ctree->tree_column].area.width -
+                          ctree->tree_indent * level +
+                          (ctree->tree_indent - PM_SIZE) / 2, y);
+           break;
+         }
+      else
+       gdk_draw_line (clist->clist_window, clist->xor_gc, 
+                      0, y, clist->clist_window_width, y);
+      break;
+    case GTK_CMCLIST_DRAG_INTO:
+      y = ROW_TOP_YPIXEL (clist, dest_row_number) + clist->row_height;
+
+      if (clist->column[ctree->tree_column].visible)
+       switch (clist->column[ctree->tree_column].justification)
+         {
+         case GTK_JUSTIFY_CENTER:
+         case GTK_JUSTIFY_FILL:
+         case GTK_JUSTIFY_LEFT:
+           points[0].x =  COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) + 
+             ctree->tree_indent * level - (ctree->tree_indent - PM_SIZE) / 2;
+           points[0].y = y;
+           points[3].x = points[0].x;
+           points[3].y = y - clist->row_height - 1;
+           points[1].x = clist->clist_window_width - 1;
+           points[1].y = points[0].y;
+           points[2].x = points[1].x;
+           points[2].y = points[3].y;
+
+           for (i = 0; i < 3; i++)
+             gdk_draw_line (clist->clist_window, clist->xor_gc,
+                            points[i].x, points[i].y,
+                            points[i+1].x, points[i+1].y);
+
+           if (ctree->tree_column > 0)
+             {
+               points[0].x = COLUMN_LEFT_XPIXEL(clist,
+                                                ctree->tree_column - 1) +
+                 clist->column[ctree->tree_column - 1].area.width ;
+               points[0].y = y;
+               points[3].x = points[0].x;
+               points[3].y = y - clist->row_height - 1;
+               points[1].x = 0;
+               points[1].y = points[0].y;
+               points[2].x = 0;
+               points[2].y = points[3].y;
+
+               for (i = 0; i < 3; i++)
+                 gdk_draw_line (clist->clist_window, clist->xor_gc,
+                                points[i].x, points[i].y, points[i+1].x, 
+                                points[i+1].y);
+             }
+           break;
+         case GTK_JUSTIFY_RIGHT:
+           points[0].x =  COLUMN_LEFT_XPIXEL(clist, ctree->tree_column) - 
+             ctree->tree_indent * level + (ctree->tree_indent - PM_SIZE) / 2 +
+             clist->column[ctree->tree_column].area.width;
+           points[0].y = y;
+           points[3].x = points[0].x;
+           points[3].y = y - clist->row_height - 1;
+           points[1].x = 0;
+           points[1].y = points[0].y;
+           points[2].x = 0;
+           points[2].y = points[3].y;
+
+           for (i = 0; i < 3; i++)
+             gdk_draw_line (clist->clist_window, clist->xor_gc,
+                            points[i].x, points[i].y,
+                            points[i+1].x, points[i+1].y);
+
+           if (ctree->tree_column < clist->columns - 1)
+             {
+               points[0].x = COLUMN_LEFT_XPIXEL(clist, ctree->tree_column +1);
+               points[0].y = y;
+               points[3].x = points[0].x;
+               points[3].y = y - clist->row_height - 1;
+               points[1].x = clist->clist_window_width - 1;
+               points[1].y = points[0].y;
+               points[2].x = points[1].x;
+               points[2].y = points[3].y;
+
+               for (i = 0; i < 3; i++)
+                 gdk_draw_line (clist->clist_window, clist->xor_gc,
+                                points[i].x, points[i].y,
+                                points[i+1].x, points[i+1].y);
+             }
+           break;
+         }
+      else
+       gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
+                           0, y - clist->row_height,
+                           clist->clist_window_width - 1, clist->row_height);
+      break;
+    }
+}
+
+static gint
+draw_cell_pixmap (GdkWindow    *window,
+                 GdkRectangle *clip_rectangle,
+                 GdkGC        *fg_gc,
+                 GdkPixmap    *pixmap,
+                 GdkBitmap    *mask,
+                 gint          x,
+                 gint          y,
+                 gint          width,
+                 gint          height)
+{
+  gint xsrc = 0;
+  gint ysrc = 0;
+
+  if (mask)
+    {
+      gdk_gc_set_clip_mask (fg_gc, mask);
+      gdk_gc_set_clip_origin (fg_gc, x, y);
+    }
+  if (x < clip_rectangle->x)
+    {
+      xsrc = clip_rectangle->x - x;
+      width -= xsrc;
+      x = clip_rectangle->x;
+    }
+  if (x + width > clip_rectangle->x + clip_rectangle->width)
+    width = clip_rectangle->x + clip_rectangle->width - x;
+
+  if (y < clip_rectangle->y)
+    {
+      ysrc = clip_rectangle->y - y;
+      height -= ysrc;
+      y = clip_rectangle->y;
+    }
+  if (y + height > clip_rectangle->y + clip_rectangle->height)
+    height = clip_rectangle->y + clip_rectangle->height - y;
+
+  if (width > 0 && height > 0)
+    gdk_draw_drawable (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
+
+  if (mask)
+    {
+      gdk_gc_set_clip_rectangle (fg_gc, NULL);
+      gdk_gc_set_clip_origin (fg_gc, 0, 0);
+    }
+
+  return x + MAX (width, 0);
+}
+
+static void
+get_cell_style (GtkCMCList     *clist,
+               GtkCMCListRow  *clist_row,
+               gint          state,
+               gint          column,
+               GtkStyle    **style,
+               GdkGC       **fg_gc,
+               GdkGC       **bg_gc)
+{
+  gint fg_state;
+
+  if ((state == GTK_STATE_NORMAL) &&
+      (GTK_WIDGET (clist)->state == GTK_STATE_INSENSITIVE))
+    fg_state = GTK_STATE_INSENSITIVE;
+  else
+    fg_state = state;
+
+  if (clist_row->cell[column].style)
+    {
+      if (style)
+       *style = clist_row->cell[column].style;
+      if (fg_gc)
+       *fg_gc = clist_row->cell[column].style->fg_gc[fg_state];
+      if (bg_gc) {
+       if (state == GTK_STATE_SELECTED)
+         *bg_gc = clist_row->cell[column].style->bg_gc[state];
+       else
+         *bg_gc = clist_row->cell[column].style->base_gc[state];
+      }
+    }
+  else if (clist_row->style)
+    {
+      if (style)
+       *style = clist_row->style;
+      if (fg_gc)
+       *fg_gc = clist_row->style->fg_gc[fg_state];
+      if (bg_gc) {
+       if (state == GTK_STATE_SELECTED)
+         *bg_gc = clist_row->style->bg_gc[state];
+       else
+         *bg_gc = clist_row->style->base_gc[state];
+      }
+    }
+  else
+    {
+      if (style)
+       *style = GTK_WIDGET (clist)->style;
+      if (fg_gc)
+       *fg_gc = GTK_WIDGET (clist)->style->fg_gc[fg_state];
+      if (bg_gc) {
+       if (state == GTK_STATE_SELECTED)
+         *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
+       else
+         *bg_gc = GTK_WIDGET (clist)->style->base_gc[state];
+      }
+
+      if (state != GTK_STATE_SELECTED)
+       {
+         if (fg_gc && clist_row->fg_set)
+           *fg_gc = clist->fg_gc;
+         if (bg_gc && clist_row->bg_set)
+           *bg_gc = clist->bg_gc;
+       }
+    }
+}
+
+static gint
+gtk_cmctree_draw_expander (GtkCMCTree     *ctree,
+                        GtkCMCTreeRow  *ctree_row,
+                        GtkStyle     *style,
+                        GdkRectangle *clip_rectangle,
+                        gint          x)
+{
+  GtkCMCList *clist;
+  GdkPoint points[3];
+  gint justification_factor;
+  gint y;
+
+ if (ctree->expander_style == GTK_CMCTREE_EXPANDER_NONE)
+   return x;
+
+  clist = GTK_CMCLIST (ctree);
+  if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
+    justification_factor = -1;
+  else
+    justification_factor = 1;
+  y = (clip_rectangle->y + (clip_rectangle->height - PM_SIZE) / 2 -
+       (clip_rectangle->height + 1) % 2);
+
+  if (!ctree_row->children)
+    {
+      switch (ctree->expander_style)
+       {
+       case GTK_CMCTREE_EXPANDER_NONE:
+         return x;
+       case GTK_CMCTREE_EXPANDER_TRIANGLE:
+         return x + justification_factor * (PM_SIZE + 3);
+       case GTK_CMCTREE_EXPANDER_SQUARE:
+       case GTK_CMCTREE_EXPANDER_CIRCULAR:
+         return x + justification_factor * (PM_SIZE + 1);
+       }
+    }
+
+  gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], clip_rectangle);
+  gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], clip_rectangle);
+
+  switch (ctree->expander_style)
+    {
+    case GTK_CMCTREE_EXPANDER_NONE:
+      break;
+    case GTK_CMCTREE_EXPANDER_TRIANGLE:
+      if (ctree_row->expanded)
+       {
+         points[0].x = x;
+         points[0].y = y + (PM_SIZE + 2) / 6;
+         points[1].x = points[0].x + justification_factor * (PM_SIZE + 2);
+         points[1].y = points[0].y;
+         points[2].x = (points[0].x +
+                        justification_factor * (PM_SIZE + 2) / 2);
+         points[2].y = y + 2 * (PM_SIZE + 2) / 3;
+       }
+      else
+       {
+         points[0].x = x + justification_factor * ((PM_SIZE + 2) / 6 + 2);
+         points[0].y = y - 1;
+         points[1].x = points[0].x;
+         points[1].y = points[0].y + (PM_SIZE + 2);
+         points[2].x = (points[0].x +
+                        justification_factor * (2 * (PM_SIZE + 2) / 3 - 1));
+         points[2].y = points[0].y + (PM_SIZE + 2) / 2;
+       }
+
+      gdk_draw_polygon (clist->clist_window, style->base_gc[GTK_STATE_NORMAL],
+                       TRUE, points, 3);
+      gdk_draw_polygon (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
+                       FALSE, points, 3);
+
+      x += justification_factor * (PM_SIZE + 3);
+      break;
+    case GTK_CMCTREE_EXPANDER_SQUARE:
+    case GTK_CMCTREE_EXPANDER_CIRCULAR:
+      if (justification_factor == -1)
+       x += justification_factor * (PM_SIZE + 1);
+
+      if (ctree->expander_style == GTK_CMCTREE_EXPANDER_CIRCULAR)
+       {
+         gdk_draw_arc (clist->clist_window, style->base_gc[GTK_STATE_NORMAL],
+                       TRUE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64);
+         gdk_draw_arc (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
+                       FALSE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64);
+       }
+      else
+       {
+         gdk_draw_rectangle (clist->clist_window,
+                             style->base_gc[GTK_STATE_NORMAL], TRUE,
+                             x, y, PM_SIZE, PM_SIZE);
+         gdk_draw_rectangle (clist->clist_window,
+                             style->fg_gc[GTK_STATE_NORMAL], FALSE,
+                             x, y, PM_SIZE, PM_SIZE);
+       }
+
+      gdk_draw_line (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL], 
+                    x + 2, y + PM_SIZE / 2, x + PM_SIZE - 2, y + PM_SIZE / 2);
+
+      if (!ctree_row->expanded)
+       gdk_draw_line (clist->clist_window, style->fg_gc[GTK_STATE_NORMAL],
+                      x + PM_SIZE / 2, y + 2,
+                      x + PM_SIZE / 2, y + PM_SIZE - 2);
+
+      if (justification_factor == 1)
+       x += justification_factor * (PM_SIZE + 1);
+      break;
+    }
+
+  gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL);
+  gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL);
+
+  return x;
+}
+
+
+static gint
+gtk_cmctree_draw_lines (GtkCMCTree     *ctree,
+                     GtkCMCTreeRow  *ctree_row,
+                     gint          row,
+                     gint          column,
+                     gint          state,
+                     GdkRectangle *clip_rectangle,
+                     GdkRectangle *cell_rectangle,
+                     GdkRectangle *crect,
+                     GdkRectangle *area,
+                     GtkStyle     *style)
+{
+  GtkCMCList *clist;
+  GtkCMCTreeNode *node;
+  GtkCMCTreeNode *parent;
+  GdkRectangle tree_rectangle;
+  GdkRectangle tc_rectangle;
+  GdkGC *bg_gc;
+  gint offset;
+  gint offset_x;
+  gint offset_y;
+  gint xcenter;
+  gint ycenter;
+  gint next_level;
+  gint column_right;
+  gint column_left;
+  gint justify_right;
+  gint justification_factor;
+  
+  clist = GTK_CMCLIST (ctree);
+  ycenter = clip_rectangle->y + (clip_rectangle->height / 2);
+  justify_right = (clist->column[column].justification == GTK_JUSTIFY_RIGHT);
+
+  if (justify_right)
+    {
+      offset = (clip_rectangle->x + clip_rectangle->width - 1 -
+               ctree->tree_indent * (ctree_row->level - 1));
+      justification_factor = -1;
+    }
+  else
+    {
+      offset = clip_rectangle->x + ctree->tree_indent * (ctree_row->level - 1);
+      justification_factor = 1;
+    }
+
+  switch (ctree->line_style)
+    {
+    case GTK_CMCTREE_LINES_NONE:
+      break;
+    case GTK_CMCTREE_LINES_TABBED:
+      xcenter = offset + justification_factor * TAB_SIZE;
+
+      column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
+                     clist->column[ctree->tree_column].area.width +
+                     COLUMN_INSET);
+      column_left = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) -
+                    COLUMN_INSET - CELL_SPACING);
+
+      if (area)
+       {
+         tree_rectangle.y = crect->y;
+         tree_rectangle.height = crect->height;
+
+         if (justify_right)
+           {
+             tree_rectangle.x = xcenter;
+             tree_rectangle.width = column_right - xcenter;
+           }
+         else
+           {
+             tree_rectangle.x = column_left;
+             tree_rectangle.width = xcenter - column_left;
+           }
+
+         if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle))
+           {
+             offset += justification_factor * 3;
+             break;
+           }
+       }
+
+      gdk_gc_set_clip_rectangle (ctree->lines_gc, crect);
+
+      next_level = ctree_row->level;
+
+      if (!ctree_row->sibling || (ctree_row->children && ctree_row->expanded))
+       {
+         node = gtk_cmctree_find_node_ptr (ctree, ctree_row);
+         if (GTK_CMCTREE_NODE_NEXT (node))
+           next_level = GTK_CMCTREE_ROW (GTK_CMCTREE_NODE_NEXT (node))->level;
+         else
+           next_level = 0;
+       }
+
+      if (ctree->tree_indent > 0)
+       {
+         node = ctree_row->parent;
+         while (node)
+           {
+             xcenter -= (justification_factor * ctree->tree_indent);
+
+             if ((justify_right && xcenter < column_left) ||
+                 (!justify_right && xcenter > column_right))
+               {
+                 node = GTK_CMCTREE_ROW (node)->parent;
+                 continue;
+               }
+
+             tree_rectangle.y = cell_rectangle->y;
+             tree_rectangle.height = cell_rectangle->height;
+             if (justify_right)
+               {
+                 tree_rectangle.x = MAX (xcenter - ctree->tree_indent + 1,
+                                         column_left);
+                 tree_rectangle.width = MIN (xcenter - column_left,
+                                             ctree->tree_indent);
+               }
+             else
+               {
+                 tree_rectangle.x = xcenter;
+                 tree_rectangle.width = MIN (column_right - xcenter,
+                                             ctree->tree_indent);
+               }
+
+             if (!area || gdk_rectangle_intersect (area, &tree_rectangle,
+                                                   &tc_rectangle))
+               {
+                 get_cell_style (clist, &GTK_CMCTREE_ROW (node)->row,
+                                 state, column, NULL, NULL, &bg_gc);
+
+                 if (bg_gc == clist->bg_gc)
+                   gdk_gc_set_foreground
+                     (clist->bg_gc, &GTK_CMCTREE_ROW (node)->row.background);
+
+                 if (!area)
+                   gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
+                                       tree_rectangle.x,
+                                       tree_rectangle.y,
+                                       tree_rectangle.width,
+                                       tree_rectangle.height);
+                 else 
+                   gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
+                                       tc_rectangle.x,
+                                       tc_rectangle.y,
+                                       tc_rectangle.width,
+                                       tc_rectangle.height);
+               }
+             if (next_level > GTK_CMCTREE_ROW (node)->level)
+               gdk_draw_line (clist->clist_window, ctree->lines_gc,
+                              xcenter, crect->y,
+                              xcenter, crect->y + crect->height);
+             else
+               {
+                 gint width;
+
+                 offset_x = MIN (ctree->tree_indent, 2 * TAB_SIZE);
+                 width = offset_x / 2 + offset_x % 2;
+
+                 parent = GTK_CMCTREE_ROW (node)->parent;
+
+                 tree_rectangle.y = ycenter;
+                 tree_rectangle.height = (cell_rectangle->y - ycenter +
+                                          cell_rectangle->height);
+
+                 if (justify_right)
+                   {
+                     tree_rectangle.x = MAX(xcenter + 1 - width, column_left);
+                     tree_rectangle.width = MIN (xcenter + 1 - column_left,
+                                                 width);
+                   }
+                 else
+                   {
+                     tree_rectangle.x = xcenter;
+                     tree_rectangle.width = MIN (column_right - xcenter,
+                                                 width);
+                   }
+
+                 if (!area ||
+                     gdk_rectangle_intersect (area, &tree_rectangle,
+                                              &tc_rectangle))
+                   {
+                     if (parent)
+                       {
+                         get_cell_style (clist, &GTK_CMCTREE_ROW (parent)->row,
+                                         state, column, NULL, NULL, &bg_gc);
+                         if (bg_gc == clist->bg_gc)
+                           gdk_gc_set_foreground
+                             (clist->bg_gc,
+                              &GTK_CMCTREE_ROW (parent)->row.background);
+                       }
+                     else if (state == GTK_STATE_SELECTED)
+                       bg_gc = style->base_gc[state];
+                     else
+                       bg_gc = GTK_WIDGET (clist)->style->base_gc[state];
+
+                     if (!area)
+                       gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
+                                           tree_rectangle.x,
+                                           tree_rectangle.y,
+                                           tree_rectangle.width,
+                                           tree_rectangle.height);
+                     else
+                       gdk_draw_rectangle (clist->clist_window,
+                                           bg_gc, TRUE,
+                                           tc_rectangle.x,
+                                           tc_rectangle.y,
+                                           tc_rectangle.width,
+                                           tc_rectangle.height);
+                   }
+
+                 get_cell_style (clist, &GTK_CMCTREE_ROW (node)->row,
+                                 state, column, NULL, NULL, &bg_gc);
+                 if (bg_gc == clist->bg_gc)
+                   gdk_gc_set_foreground
+                     (clist->bg_gc, &GTK_CMCTREE_ROW (node)->row.background);
+
+                 gdk_gc_set_clip_rectangle (bg_gc, crect);
+                 gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
+                               xcenter - (justify_right * offset_x),
+                               cell_rectangle->y,
+                               offset_x, clist->row_height,
+                               (180 + (justify_right * 90)) * 64, 90 * 64);
+                 gdk_gc_set_clip_rectangle (bg_gc, NULL);
+
+                 gdk_draw_line (clist->clist_window, ctree->lines_gc, 
+                                xcenter, cell_rectangle->y, xcenter, ycenter);
+
+                 if (justify_right)
+                   gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
+                                 xcenter - offset_x, cell_rectangle->y,
+                                 offset_x, clist->row_height,
+                                 270 * 64, 90 * 64);
+                 else
+                   gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
+                                 xcenter, cell_rectangle->y,
+                                 offset_x, clist->row_height,
+                                 180 * 64, 90 * 64);
+               }
+             node = GTK_CMCTREE_ROW (node)->parent;
+           }
+       }
+
+      if (state != GTK_STATE_SELECTED)
+       {
+         tree_rectangle.y = clip_rectangle->y;
+         tree_rectangle.height = clip_rectangle->height;
+         tree_rectangle.width = COLUMN_INSET + CELL_SPACING +
+           MIN (clist->column[ctree->tree_column].area.width + COLUMN_INSET,
+                TAB_SIZE);
+
+         if (justify_right)
+           tree_rectangle.x = MAX (xcenter + 1, column_left);
+         else
+           tree_rectangle.x = column_left;
+
+         if (!area)
+           gdk_draw_rectangle (clist->clist_window,
+                               GTK_WIDGET
+                               (ctree)->style->base_gc[GTK_STATE_NORMAL],
+                               TRUE,
+                               tree_rectangle.x,
+                               tree_rectangle.y,
+                               tree_rectangle.width,
+                               tree_rectangle.height);
+         else if (gdk_rectangle_intersect (area, &tree_rectangle,
+                                           &tc_rectangle))
+           gdk_draw_rectangle (clist->clist_window,
+                               GTK_WIDGET
+                               (ctree)->style->base_gc[GTK_STATE_NORMAL],
+                               TRUE,
+                               tc_rectangle.x,
+                               tc_rectangle.y,
+                               tc_rectangle.width,
+                               tc_rectangle.height);
+       }
+
+      xcenter = offset + (justification_factor * ctree->tree_indent / 2);
+
+      get_cell_style (clist, &ctree_row->row, state, column, NULL, NULL,
+                     &bg_gc);
+      if (bg_gc == clist->bg_gc)
+       gdk_gc_set_foreground (clist->bg_gc, &ctree_row->row.background);
+
+      gdk_gc_set_clip_rectangle (bg_gc, crect);
+      if (ctree_row->is_leaf)
+       {
+         GdkPoint points[6];
+
+         points[0].x = offset + justification_factor * TAB_SIZE;
+         points[0].y = cell_rectangle->y;
+
+         points[1].x = points[0].x - justification_factor * 4;
+         points[1].y = points[0].y;
+
+         points[2].x = points[1].x - justification_factor * 2;
+         points[2].y = points[1].y + 3;
+
+         points[3].x = points[2].x;
+         points[3].y = points[2].y + clist->row_height - 5;
+
+         points[4].x = points[3].x + justification_factor * 2;
+         points[4].y = points[3].y + 3;
+
+         points[5].x = points[4].x + justification_factor * 4;
+         points[5].y = points[4].y;
+
+         gdk_draw_polygon (clist->clist_window, bg_gc, TRUE, points, 6);
+         gdk_draw_lines (clist->clist_window, ctree->lines_gc, points, 6);
+       }
+      else 
+       {
+         gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
+                       offset - (justify_right * 2 * TAB_SIZE),
+                       cell_rectangle->y,
+                       2 * TAB_SIZE, clist->row_height,
+                       (90 + (180 * justify_right)) * 64, 180 * 64);
+         gdk_draw_arc (clist->clist_window, ctree->lines_gc, FALSE,
+                       offset - (justify_right * 2 * TAB_SIZE),
+                       cell_rectangle->y,
+                       2 * TAB_SIZE, clist->row_height,
+                       (90 + (180 * justify_right)) * 64, 180 * 64);
+       }
+      gdk_gc_set_clip_rectangle (bg_gc, NULL);
+      gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
+
+      offset += justification_factor * 3;
+      break;
+    default:
+      xcenter = offset + justification_factor * PM_SIZE / 2;
+
+      if (area)
+       {
+         tree_rectangle.y = crect->y;
+         tree_rectangle.height = crect->height;
+
+         if (justify_right)
+           {
+             tree_rectangle.x = xcenter - PM_SIZE / 2 - 2;
+             tree_rectangle.width = (clip_rectangle->x +
+                                     clip_rectangle->width -tree_rectangle.x);
+           }
+         else
+           {
+             tree_rectangle.x = clip_rectangle->x + PM_SIZE / 2;
+             tree_rectangle.width = (xcenter + PM_SIZE / 2 + 2 -
+                                     clip_rectangle->x);
+           }
+
+         if (!gdk_rectangle_intersect (area, &tree_rectangle, &tc_rectangle))
+           break;
+       }
+
+      offset_x = 1;
+      offset_y = 0;
+      if (ctree->line_style == GTK_CMCTREE_LINES_DOTTED)
+       {
+         offset_x += abs((clip_rectangle->x + clist->hoffset) % 2);
+         offset_y  = abs((cell_rectangle->y + clist->voffset) % 2);
+       }
+
+      clip_rectangle->y--;
+      clip_rectangle->height++;
+      gdk_gc_set_clip_rectangle (ctree->lines_gc, clip_rectangle);
+      gdk_draw_line (clist->clist_window, ctree->lines_gc,
+                    xcenter,
+                    (ctree->show_stub || clist->row_list->data != ctree_row) ?
+                    cell_rectangle->y + offset_y : ycenter,
+                    xcenter,
+                    (ctree_row->sibling) ? crect->y +crect->height : ycenter);
+
+      gdk_draw_line (clist->clist_window, ctree->lines_gc,
+                    xcenter + (justification_factor * offset_x), ycenter,
+                    xcenter + (justification_factor * (PM_SIZE / 2 + 2)),
+                    ycenter);
+
+      node = ctree_row->parent;
+      while (node)
+       {
+         xcenter -= (justification_factor * ctree->tree_indent);
+
+         if (GTK_CMCTREE_ROW (node)->sibling)
+           gdk_draw_line (clist->clist_window, ctree->lines_gc, 
+                          xcenter, cell_rectangle->y + offset_y,
+                          xcenter, crect->y + crect->height);
+         node = GTK_CMCTREE_ROW (node)->parent;
+       }
+      gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
+      clip_rectangle->y++;
+      clip_rectangle->height--;
+      break;
+    }
+  return offset;
+}
+
+static void
+draw_row (GtkCMCList     *clist,
+         GdkRectangle *area,
+         gint          row,
+         GtkCMCListRow  *clist_row)
+{
+  GtkWidget *widget;
+  GtkCMCTree  *ctree;
+  GdkRectangle *crect;
+  GdkRectangle row_rectangle;
+  GdkRectangle cell_rectangle; 
+  GdkRectangle clip_rectangle;
+  GdkRectangle intersect_rectangle;
+  gint last_column;
+  gint column_left = 0;
+  gint column_right = 0;
+  gint offset = 0;
+  gint state;
+  gint i;
+
+  g_return_if_fail (clist != NULL);
+
+  /* bail now if we arn't drawable yet */
+  if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
+    return;
+
+  widget = GTK_WIDGET (clist);
+  ctree  = GTK_CMCTREE  (clist);
+
+  /* if the function is passed the pointer to the row instead of null,
+   * it avoids this expensive lookup */
+  if (!clist_row)
+    clist_row = (g_list_nth (clist->row_list, row))->data;
+
+  /* rectangle of the entire row */
+  row_rectangle.x = 0;
+  row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
+  row_rectangle.width = clist->clist_window_width;
+  row_rectangle.height = clist->row_height;
+
+  /* rectangle of the cell spacing above the row */
+  cell_rectangle.x = 0;
+  cell_rectangle.y = row_rectangle.y - CELL_SPACING;
+  cell_rectangle.width = row_rectangle.width;
+  cell_rectangle.height = CELL_SPACING;
+
+  /* rectangle used to clip drawing operations, its y and height
+   * positions only need to be set once, so we set them once here. 
+   * the x and width are set withing the drawing loop below once per
+   * column */
+  clip_rectangle.y = row_rectangle.y;
+  clip_rectangle.height = row_rectangle.height;
+
+  if (clist_row->state == GTK_STATE_NORMAL)
+    {
+      if (clist_row->fg_set)
+       gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
+      if (clist_row->bg_set)
+       gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
+    }
+  
+  state = clist_row->state;
+
+  gdk_gc_set_foreground (ctree->lines_gc,
+                        &widget->style->fg[clist_row->state]);
+
+  /* draw the cell borders */
+  if (area)
+    {
+      crect = &intersect_rectangle;
+
+      if (gdk_rectangle_intersect (area, &cell_rectangle, crect))
+       gdk_draw_rectangle (clist->clist_window,
+                           widget->style->base_gc[GTK_STATE_NORMAL], TRUE,
+                           crect->x, crect->y, crect->width, crect->height);
+    }
+  else
+    {
+      crect = &cell_rectangle;
+
+      gdk_draw_rectangle (clist->clist_window,
+                         widget->style->base_gc[GTK_STATE_NORMAL], TRUE,
+                         crect->x, crect->y, crect->width, crect->height);
+    }
+
+  /* horizontal black lines */
+  if (ctree->line_style == GTK_CMCTREE_LINES_TABBED)
+    { 
+
+      column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
+                     clist->column[ctree->tree_column].area.width +
+                     COLUMN_INSET);
+      column_left = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) -
+                    COLUMN_INSET - (ctree->tree_column != 0) * CELL_SPACING);
+
+      switch (clist->column[ctree->tree_column].justification)
+       {
+       case GTK_JUSTIFY_CENTER:
+       case GTK_JUSTIFY_FILL:
+       case GTK_JUSTIFY_LEFT:
+         offset = (column_left + ctree->tree_indent *
+                   (((GtkCMCTreeRow *)clist_row)->level - 1));
+
+         gdk_draw_line (clist->clist_window, ctree->lines_gc, 
+                        MIN (offset + TAB_SIZE, column_right),
+                        cell_rectangle.y,
+                        clist->clist_window_width, cell_rectangle.y);
+         break;
+       case GTK_JUSTIFY_RIGHT:
+         offset = (column_right - 1 - ctree->tree_indent *
+                   (((GtkCMCTreeRow *)clist_row)->level - 1));
+
+         gdk_draw_line (clist->clist_window, ctree->lines_gc,
+                        -1, cell_rectangle.y,
+                        MAX (offset - TAB_SIZE, column_left),
+                        cell_rectangle.y);
+         break;
+       }
+    }
+
+  /* the last row has to clear its bottom cell spacing too */
+  if (clist_row == clist->row_list_end->data)
+    {
+      cell_rectangle.y += clist->row_height + CELL_SPACING;
+
+      if (!area || gdk_rectangle_intersect (area, &cell_rectangle, crect))
+       {
+         gdk_draw_rectangle (clist->clist_window,
+                             widget->style->base_gc[GTK_STATE_NORMAL], TRUE,
+                             crect->x, crect->y, crect->width, crect->height);
+
+         /* horizontal black lines */
+         if (ctree->line_style == GTK_CMCTREE_LINES_TABBED)
+           { 
+             switch (clist->column[ctree->tree_column].justification)
+               {
+               case GTK_JUSTIFY_CENTER:
+               case GTK_JUSTIFY_FILL:
+               case GTK_JUSTIFY_LEFT:
+                 gdk_draw_line (clist->clist_window, ctree->lines_gc, 
+                                MIN (column_left + TAB_SIZE + COLUMN_INSET +
+                                     (((GtkCMCTreeRow *)clist_row)->level > 1) *
+                                     MIN (ctree->tree_indent / 2, TAB_SIZE),
+                                     column_right),
+                                cell_rectangle.y,
+                                clist->clist_window_width, cell_rectangle.y);
+                 break;
+               case GTK_JUSTIFY_RIGHT:
+                 gdk_draw_line (clist->clist_window, ctree->lines_gc, 
+                                -1, cell_rectangle.y,
+                                MAX (column_right - TAB_SIZE - 1 -
+                                     COLUMN_INSET -
+                                     (((GtkCMCTreeRow *)clist_row)->level > 1) *
+                                     MIN (ctree->tree_indent / 2, TAB_SIZE),
+                                     column_left - 1), cell_rectangle.y);
+                 break;
+               }
+           }
+       }
+    }    
+
+  for (last_column = clist->columns - 1;
+       last_column >= 0 && !clist->column[last_column].visible; last_column--)
+    ;
+
+  /* iterate and draw all the columns (row cells) and draw their contents */
+  for (i = 0; i < clist->columns; i++)
+    {
+      GtkStyle *style;
+      GdkGC *fg_gc; 
+      GdkGC *bg_gc;
+      PangoLayout *layout = NULL;
+      PangoRectangle logical_rect;
+
+      gint width;
+      gint height;
+      gint pixmap_width;
+      gint string_width;
+      gint old_offset;
+
+      if (!clist->column[i].visible)
+       continue;
+
+      get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
+
+      /* calculate clipping region */
+      clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
+      clip_rectangle.width = clist->column[i].area.width;
+
+      cell_rectangle.x = clip_rectangle.x - COLUMN_INSET - CELL_SPACING;
+      cell_rectangle.width = (clip_rectangle.width + 2 * COLUMN_INSET +
+                             (1 + (i == last_column)) * CELL_SPACING);
+      cell_rectangle.y = clip_rectangle.y;
+      cell_rectangle.height = clip_rectangle.height;
+
+      string_width = 0;
+      pixmap_width = 0;
+
+      if (area && !gdk_rectangle_intersect (area, &cell_rectangle,
+                                           &intersect_rectangle))
+       {
+         if (i != ctree->tree_column)
+           continue;
+       }
+      else
+       {
+         gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
+                             crect->x, crect->y, crect->width, crect->height);
+
+
+         layout = _gtk_cmclist_create_cell_layout (clist, clist_row, i);
+         if (layout)
+           {
+             pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+             width = logical_rect.width;
+           }
+         else
+           width = 0;
+
+         switch (clist_row->cell[i].type)
+           {
+           case GTK_CMCELL_PIXMAP:
+             gdk_drawable_get_size
+               (GTK_CMCELL_PIXMAP (clist_row->cell[i])->pixmap, &pixmap_width,
+                &height);
+             width += pixmap_width;
+             break;
+           case GTK_CMCELL_PIXTEXT:
+             if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+               {
+                 gdk_drawable_get_size 
+                   (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+                    &pixmap_width, &height);
+                 width += pixmap_width;
+               }
+
+             if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->text &&
+                 GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+               width +=  GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
+
+             if (i == ctree->tree_column)
+               width += (ctree->tree_indent *
+                         ((GtkCMCTreeRow *)clist_row)->level);
+             break;
+           default:
+             break;
+           }
+
+         switch (clist->column[i].justification)
+           {
+           case GTK_JUSTIFY_LEFT:
+             offset = clip_rectangle.x + clist_row->cell[i].horizontal;
+             break;
+           case GTK_JUSTIFY_RIGHT:
+             offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
+                       clip_rectangle.width - width);
+             break;
+           case GTK_JUSTIFY_CENTER:
+           case GTK_JUSTIFY_FILL:
+             offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
+                       (clip_rectangle.width / 2) - (width / 2));
+             break;
+           };
+
+         if (i != ctree->tree_column)
+           {
+             offset += clist_row->cell[i].horizontal;
+             switch (clist_row->cell[i].type)
+               {
+               case GTK_CMCELL_PIXMAP:
+                 draw_cell_pixmap
+                   (clist->clist_window, &clip_rectangle, fg_gc,
+                    GTK_CMCELL_PIXMAP (clist_row->cell[i])->pixmap,
+                    GTK_CMCELL_PIXMAP (clist_row->cell[i])->mask,
+                    offset,
+                    clip_rectangle.y + clist_row->cell[i].vertical +
+                    (clip_rectangle.height - height) / 2,
+                    pixmap_width, height);
+                 break;
+               case GTK_CMCELL_PIXTEXT:
+                 offset = draw_cell_pixmap
+                   (clist->clist_window, &clip_rectangle, fg_gc,
+                    GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+                    GTK_CMCELL_PIXTEXT (clist_row->cell[i])->mask,
+                    offset,
+                    clip_rectangle.y + clist_row->cell[i].vertical +
+                    (clip_rectangle.height - height) / 2,
+                    pixmap_width, height);
+                 offset += GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
+
+                 /* Fall through */
+               case GTK_CMCELL_TEXT:
+                 if (layout)
+                   {
+                     gint row_center_offset = (clist->row_height - logical_rect.height) / 2;
+
+                     gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
+                     gdk_draw_layout (clist->clist_window, fg_gc,
+                                      offset,
+                                      row_rectangle.y + row_center_offset + clist_row->cell[i].vertical,
+                                      layout);
+                     gdk_gc_set_clip_rectangle (fg_gc, NULL);
+                     g_object_unref (G_OBJECT (layout));
+                   }
+                 break;
+               default:
+                 break;
+               }
+             continue;
+           }
+       }
+
+      if (bg_gc == clist->bg_gc)
+       gdk_gc_set_background (ctree->lines_gc, &clist_row->background);
+
+      /* draw ctree->tree_column */
+      cell_rectangle.y -= CELL_SPACING;
+      cell_rectangle.height += CELL_SPACING;
+
+      if (area && !gdk_rectangle_intersect (area, &cell_rectangle,
+                                           &intersect_rectangle))
+       {
+         if (layout)
+            g_object_unref (G_OBJECT (layout));
+         continue;
+       }
+
+      /* draw lines */
+      offset = gtk_cmctree_draw_lines (ctree, (GtkCMCTreeRow *)clist_row, row, i,
+                                    state, &clip_rectangle, &cell_rectangle,
+                                    crect, area, style);
+
+      /* draw expander */
+      offset = gtk_cmctree_draw_expander (ctree, (GtkCMCTreeRow *)clist_row,
+                                       style, &clip_rectangle, offset);
+
+      if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
+       offset -= ctree->tree_spacing;
+      else
+       offset += ctree->tree_spacing;
+
+      if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
+       offset -= (pixmap_width + clist_row->cell[i].horizontal);
+      else
+       offset += clist_row->cell[i].horizontal;
+
+      old_offset = offset;
+      offset = draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
+                                GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+                                GTK_CMCELL_PIXTEXT (clist_row->cell[i])->mask,
+                                offset, 
+                                clip_rectangle.y + clist_row->cell[i].vertical
+                                + (clip_rectangle.height - height) / 2,
+                                pixmap_width, height);
+
+      if (layout)
+       {
+         gint row_center_offset = (clist->row_height - logical_rect.height) / 2;
+         
+         if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
+           {
+             offset = (old_offset - string_width);
+             if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+               offset -= GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
+           }
+         else
+           {
+             if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+               offset += GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
+           }
+         
+         gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
+         gdk_draw_layout (clist->clist_window, fg_gc,
+                          offset,
+                          row_rectangle.y + row_center_offset + clist_row->cell[i].vertical,
+                          layout);
+
+          g_object_unref (G_OBJECT (layout));
+       }
+      gdk_gc_set_clip_rectangle (fg_gc, NULL);
+    }
+
+  /* draw focus rectangle */
+  if (clist->focus_row == row &&
+      GTK_WIDGET_CAN_FOCUS (widget) && GTK_WIDGET_HAS_FOCUS (widget))
+    {
+      if (!area)
+       gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
+                           row_rectangle.x, row_rectangle.y,
+                           row_rectangle.width - 1, row_rectangle.height - 1);
+      else if (gdk_rectangle_intersect (area, &row_rectangle,
+                                       &intersect_rectangle))
+       {
+         gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
+         gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
+                             row_rectangle.x, row_rectangle.y,
+                             row_rectangle.width - 1,
+                             row_rectangle.height - 1);
+         gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
+       }
+    }
+}
+
+static void
+tree_draw_node (GtkCMCTree     *ctree, 
+               GtkCMCTreeNode *node)
+{
+  GtkCMCList *clist;
+  
+  clist = GTK_CMCLIST (ctree);
+
+  if (CLIST_UNFROZEN (clist) && gtk_cmctree_is_viewable (ctree, node))
+    {
+      GtkCMCTreeNode *work;
+      gint num = 0;
+      
+      work = GTK_CMCTREE_NODE (clist->row_list);
+      while (work && work != node)
+       {
+         work = GTK_CMCTREE_NODE_NEXT (work);
+         num++;
+       }
+      if (work && gtk_cmclist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE)
+       GTK_CMCLIST_GET_CLASS (clist)->draw_row
+         (clist, NULL, num, GTK_CMCLIST_ROW ((GList *) node));
+    }
+}
+
+static GtkCMCTreeNode *
+gtk_cmctree_last_visible (GtkCMCTree     *ctree,
+                       GtkCMCTreeNode *node)
+{
+  GtkCMCTreeNode *work;
+  
+  if (!node)
+    return NULL;
+
+  work = GTK_CMCTREE_ROW (node)->children;
+
+  if (!work || !GTK_CMCTREE_ROW (node)->expanded)
+    return node;
+
+  while (GTK_CMCTREE_ROW (work)->sibling)
+    work = GTK_CMCTREE_ROW (work)->sibling;
+
+  return gtk_cmctree_last_visible (ctree, work);
+}
+
+static void
+gtk_cmctree_link (GtkCMCTree     *ctree,
+               GtkCMCTreeNode *node,
+               GtkCMCTreeNode *parent,
+               GtkCMCTreeNode *sibling,
+               gboolean      update_focus_row)
+{
+  GtkCMCList *clist;
+  GList *list_end;
+  GList *list;
+  GList *work;
+  gboolean visible = FALSE;
+  gint rows = 0;
+  
+  if (sibling)
+    g_return_if_fail (GTK_CMCTREE_ROW (sibling)->parent == parent);
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (node != sibling);
+  g_return_if_fail (node != parent);
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (update_focus_row && clist->selection_mode == GTK_SELECTION_MULTIPLE)
+    {
+      GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+      
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+    }
+
+  for (rows = 1, list_end = (GList *)node; list_end->next;
+       list_end = list_end->next)
+    rows++;
+
+  GTK_CMCTREE_ROW (node)->parent = parent;
+  GTK_CMCTREE_ROW (node)->sibling = sibling;
+
+  if (!parent || (parent && (gtk_cmctree_is_viewable (ctree, parent) &&
+                            GTK_CMCTREE_ROW (parent)->expanded)))
+    {
+      visible = TRUE;
+      clist->rows += rows;
+    }
+
+  if (parent)
+    work = (GList *)(GTK_CMCTREE_ROW (parent)->children);
+  else
+    work = clist->row_list;
+
+  if (sibling)
+    {
+      if (work != (GList *)sibling)
+       {
+         while (GTK_CMCTREE_ROW (work)->sibling != sibling)
+           work = (GList *)(GTK_CMCTREE_ROW (work)->sibling);
+         GTK_CMCTREE_ROW (work)->sibling = node;
+       }
+
+      if (sibling == GTK_CMCTREE_NODE (clist->row_list))
+       clist->row_list = (GList *) node;
+      if (GTK_CMCTREE_NODE_PREV (sibling) &&
+         GTK_CMCTREE_NODE_NEXT (GTK_CMCTREE_NODE_PREV (sibling)) == sibling)
+       {
+         list = (GList *)GTK_CMCTREE_NODE_PREV (sibling);
+         list->next = (GList *)node;
+       }
+      
+      list = (GList *)node;
+      list->prev = (GList *)GTK_CMCTREE_NODE_PREV (sibling);
+      list_end->next = (GList *)sibling;
+      list = (GList *)sibling;
+      list->prev = list_end;
+      if (parent && GTK_CMCTREE_ROW (parent)->children == sibling)
+       GTK_CMCTREE_ROW (parent)->children = node;
+    }
+  else
+    {
+      if (work)
+       {
+         /* find sibling */
+         while (GTK_CMCTREE_ROW (work)->sibling)
+           work = (GList *)(GTK_CMCTREE_ROW (work)->sibling);
+         GTK_CMCTREE_ROW (work)->sibling = node;
+         
+         /* find last visible child of sibling */
+         work = (GList *) gtk_cmctree_last_visible (ctree,
+                                                  GTK_CMCTREE_NODE (work));
+         
+         list_end->next = work->next;
+         if (work->next)
+           list = work->next->prev = list_end;
+         work->next = (GList *)node;
+         list = (GList *)node;
+         list->prev = work;
+       }
+      else
+       {
+         if (parent)
+           {
+             GTK_CMCTREE_ROW (parent)->children = node;
+             list = (GList *)node;
+             list->prev = (GList *)parent;
+             if (GTK_CMCTREE_ROW (parent)->expanded)
+               {
+                 list_end->next = (GList *)GTK_CMCTREE_NODE_NEXT (parent);
+                 if (GTK_CMCTREE_NODE_NEXT(parent))
+                   {
+                     list = (GList *)GTK_CMCTREE_NODE_NEXT (parent);
+                     list->prev = list_end;
+                   }
+                 list = (GList *)parent;
+                 list->next = (GList *)node;
+               }
+             else
+               list_end->next = NULL;
+           }
+         else
+           {
+             clist->row_list = (GList *)node;
+             list = (GList *)node;
+             list->prev = NULL;
+             list_end->next = NULL;
+           }
+       }
+    }
+
+  gtk_cmctree_pre_recursive (ctree, node, tree_update_level, NULL); 
+
+  if (clist->row_list_end == NULL ||
+      clist->row_list_end->next == (GList *)node)
+    clist->row_list_end = list_end;
+
+  if (visible && update_focus_row)
+    {
+      gint pos;
+         
+      pos = g_list_position (clist->row_list, (GList *)node);
+  
+      if (pos <= clist->focus_row)
+       {
+         clist->focus_row += rows;
+         clist->undo_anchor = clist->focus_row;
+       }
+    }
+}
+
+static void
+gtk_cmctree_unlink (GtkCMCTree     *ctree, 
+                 GtkCMCTreeNode *node,
+                  gboolean      update_focus_row)
+{
+  GtkCMCList *clist;
+  gint rows;
+  gint level;
+  gint visible;
+  GtkCMCTreeNode *work;
+  GtkCMCTreeNode *parent;
+  GList *list;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+
+  clist = GTK_CMCLIST (ctree);
+  
+  if (update_focus_row && clist->selection_mode == GTK_SELECTION_MULTIPLE)
+    {
+      GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+      
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+    }
+
+  visible = gtk_cmctree_is_viewable (ctree, node);
+
+  /* clist->row_list_end unlinked ? */
+  if (visible &&
+      (GTK_CMCTREE_NODE_NEXT (node) == NULL ||
+       (GTK_CMCTREE_ROW (node)->children &&
+       gtk_cmctree_is_ancestor (ctree, node,
+                              GTK_CMCTREE_NODE (clist->row_list_end)))))
+    clist->row_list_end = (GList *) (GTK_CMCTREE_NODE_PREV (node));
+
+  /* update list */
+  rows = 0;
+  level = GTK_CMCTREE_ROW (node)->level;
+  work = GTK_CMCTREE_NODE_NEXT (node);
+  while (work && GTK_CMCTREE_ROW (work)->level > level)
+    {
+      work = GTK_CMCTREE_NODE_NEXT (work);
+      rows++;
+    }
+
+  if (visible)
+    {
+      clist->rows -= (rows + 1);
+
+      if (update_focus_row)
+       {
+         gint pos;
+         
+         pos = g_list_position (clist->row_list, (GList *)node);
+         if (pos + rows < clist->focus_row)
+           clist->focus_row -= (rows + 1);
+         else if (pos <= clist->focus_row)
+           {
+             if (!GTK_CMCTREE_ROW (node)->sibling)
+               clist->focus_row = MAX (pos - 1, 0);
+             else
+               clist->focus_row = pos;
+             
+             clist->focus_row = MIN (clist->focus_row, clist->rows - 1);
+           }
+         clist->undo_anchor = clist->focus_row;
+       }
+    }
+
+  if (work)
+    {
+      list = (GList *)GTK_CMCTREE_NODE_PREV (work);
+      list->next = NULL;
+      list = (GList *)work;
+      list->prev = (GList *)GTK_CMCTREE_NODE_PREV (node);
+    }
+
+  if (GTK_CMCTREE_NODE_PREV (node) &&
+      GTK_CMCTREE_NODE_NEXT (GTK_CMCTREE_NODE_PREV (node)) == node)
+    {
+      list = (GList *)GTK_CMCTREE_NODE_PREV (node);
+      list->next = (GList *)work;
+    }
+
+  /* update tree */
+  parent = GTK_CMCTREE_ROW (node)->parent;
+  if (parent)
+    {
+      if (GTK_CMCTREE_ROW (parent)->children == node)
+       {
+         GTK_CMCTREE_ROW (parent)->children = GTK_CMCTREE_ROW (node)->sibling;
+         if (!GTK_CMCTREE_ROW (parent)->children)
+           gtk_cmctree_collapse (ctree, parent);
+       }
+      else
+       {
+         GtkCMCTreeNode *sibling;
+
+         sibling = GTK_CMCTREE_ROW (parent)->children;
+         while (GTK_CMCTREE_ROW (sibling)->sibling != node)
+           sibling = GTK_CMCTREE_ROW (sibling)->sibling;
+         GTK_CMCTREE_ROW (sibling)->sibling = GTK_CMCTREE_ROW (node)->sibling;
+       }
+    }
+  else
+    {
+      if (clist->row_list == (GList *)node)
+       clist->row_list = (GList *) (GTK_CMCTREE_ROW (node)->sibling);
+      else
+       {
+         GtkCMCTreeNode *sibling;
+
+         sibling = GTK_CMCTREE_NODE (clist->row_list);
+         while (GTK_CMCTREE_ROW (sibling)->sibling != node)
+           sibling = GTK_CMCTREE_ROW (sibling)->sibling;
+         GTK_CMCTREE_ROW (sibling)->sibling = GTK_CMCTREE_ROW (node)->sibling;
+       }
+    }
+}
+
+static void
+real_row_move (GtkCMCList *clist,
+              gint      source_row,
+              gint      dest_row)
+{
+  GtkCMCTree *ctree;
+  GtkCMCTreeNode *node;
+
+  g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+  if (GTK_CMCLIST_AUTO_SORT (clist))
+    return;
+
+  if (source_row < 0 || source_row >= clist->rows ||
+      dest_row   < 0 || dest_row   >= clist->rows ||
+      source_row == dest_row)
+    return;
+
+  ctree = GTK_CMCTREE (clist);
+  node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, source_row));
+
+  if (source_row < dest_row)
+    {
+      GtkCMCTreeNode *work; 
+
+      dest_row++;
+      work = GTK_CMCTREE_ROW (node)->children;
+
+      while (work && GTK_CMCTREE_ROW (work)->level > GTK_CMCTREE_ROW (node)->level)
+       {
+         work = GTK_CMCTREE_NODE_NEXT (work);
+         dest_row++;
+       }
+
+      if (dest_row > clist->rows)
+       dest_row = clist->rows;
+    }
+
+  if (dest_row < clist->rows)
+    {
+      GtkCMCTreeNode *sibling;
+
+      sibling = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, dest_row));
+      gtk_cmctree_move (ctree, node, GTK_CMCTREE_ROW (sibling)->parent, sibling);
+    }
+  else
+    gtk_cmctree_move (ctree, node, NULL, NULL);
+}
+
+static void
+real_tree_move (GtkCMCTree     *ctree,
+               GtkCMCTreeNode *node,
+               GtkCMCTreeNode *new_parent, 
+               GtkCMCTreeNode *new_sibling)
+{
+  GtkCMCList *clist;
+  GtkCMCTreeNode *work;
+  gboolean visible = FALSE;
+
+  g_return_if_fail (ctree != NULL);
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (!new_sibling || 
+                   GTK_CMCTREE_ROW (new_sibling)->parent == new_parent);
+
+  if (new_parent && GTK_CMCTREE_ROW (new_parent)->is_leaf)
+    return;
+
+  /* new_parent != child of child */
+  for (work = new_parent; work; work = GTK_CMCTREE_ROW (work)->parent)
+    if (work == node)
+      return;
+
+  clist = GTK_CMCLIST (ctree);
+
+  visible = gtk_cmctree_is_viewable (ctree, node);
+
+  if (clist->selection_mode == GTK_SELECTION_MULTIPLE)
+    {
+      GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+      
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+    }
+
+  if (GTK_CMCLIST_AUTO_SORT (clist))
+    {
+      if (new_parent == GTK_CMCTREE_ROW (node)->parent)
+       return;
+      
+      if (new_parent)
+       new_sibling = GTK_CMCTREE_ROW (new_parent)->children;
+      else
+       new_sibling = GTK_CMCTREE_NODE (clist->row_list);
+
+      while (new_sibling && clist->compare
+            (clist, GTK_CMCTREE_ROW (node), GTK_CMCTREE_ROW (new_sibling)) > 0)
+       new_sibling = GTK_CMCTREE_ROW (new_sibling)->sibling;
+    }
+
+  if (new_parent == GTK_CMCTREE_ROW (node)->parent && 
+      new_sibling == GTK_CMCTREE_ROW (node)->sibling)
+    return;
+
+  gtk_cmclist_freeze (clist);
+
+  work = NULL;
+  if (gtk_cmctree_is_viewable (ctree, node))
+    work = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
+      
+  gtk_cmctree_unlink (ctree, node, FALSE);
+  gtk_cmctree_link (ctree, node, new_parent, new_sibling, FALSE);
+  
+  if (work)
+    {
+      while (work &&  !gtk_cmctree_is_viewable (ctree, work))
+       work = GTK_CMCTREE_ROW (work)->parent;
+      clist->focus_row = g_list_position (clist->row_list, (GList *)work);
+      clist->undo_anchor = clist->focus_row;
+    }
+
+  if (clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist) &&
+      (visible || gtk_cmctree_is_viewable (ctree, node)))
+    gtk_cmclist_set_column_width
+      (clist, ctree->tree_column,
+       gtk_cmclist_optimal_column_width (clist, ctree->tree_column));
+
+  gtk_cmclist_thaw (clist);
+}
+
+static void
+change_focus_row_expansion (GtkCMCTree          *ctree,
+                           GtkCMCTreeExpansionType action)
+{
+  GtkCMCList *clist;
+  GtkCMCTreeNode *node;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (ctree))) && 
+      GTK_WIDGET_HAS_GRAB (ctree))
+    return;
+  
+  if (!(node =
+       GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row))) ||
+      GTK_CMCTREE_ROW (node)->is_leaf || !(GTK_CMCTREE_ROW (node)->children))
+    return;
+
+  switch (action)
+    {
+    case GTK_CMCTREE_EXPANSION_EXPAND:
+      gtk_cmctree_expand (ctree, node);
+      break;
+    case GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE:
+      gtk_cmctree_expand_recursive (ctree, node);
+      break;
+    case GTK_CMCTREE_EXPANSION_COLLAPSE:
+      gtk_cmctree_collapse (ctree, node);
+      break;
+    case GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE:
+      gtk_cmctree_collapse_recursive (ctree, node);
+      break;
+    case GTK_CMCTREE_EXPANSION_TOGGLE:
+      gtk_cmctree_toggle_expansion (ctree, node);
+      break;
+    case GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE:
+      gtk_cmctree_toggle_expansion_recursive (ctree, node);
+      break;
+    }
+}
+
+static void 
+real_tree_expand (GtkCMCTree     *ctree,
+                 GtkCMCTreeNode *node)
+{
+  GtkCMCList *clist;
+  GtkCMCTreeNode *work;
+  GtkRequisition requisition;
+  gboolean visible;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  if (!node || GTK_CMCTREE_ROW (node)->expanded || GTK_CMCTREE_ROW (node)->is_leaf)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+  
+  GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+
+  GTK_CMCTREE_ROW (node)->expanded = TRUE;
+
+  visible = gtk_cmctree_is_viewable (ctree, node);
+  /* get cell width if tree_column is auto resized */
+  if (visible && clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+      (clist, &GTK_CMCTREE_ROW (node)->row, ctree->tree_column, &requisition);
+
+  /* unref/unset closed pixmap */
+  if (GTK_CMCELL_PIXTEXT 
+      (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
+    {
+      g_object_unref
+       (GTK_CMCELL_PIXTEXT
+        (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
+      
+      GTK_CMCELL_PIXTEXT
+       (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
+      
+      if (GTK_CMCELL_PIXTEXT 
+         (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
+       {
+         g_object_unref
+           (GTK_CMCELL_PIXTEXT 
+            (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
+         GTK_CMCELL_PIXTEXT 
+           (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
+       }
+    }
+
+  /* set/ref opened pixmap */
+  if (GTK_CMCTREE_ROW (node)->pixmap_opened)
+    {
+      GTK_CMCELL_PIXTEXT 
+       (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = 
+       g_object_ref (GTK_CMCTREE_ROW (node)->pixmap_opened);
+
+      if (GTK_CMCTREE_ROW (node)->mask_opened) 
+       GTK_CMCELL_PIXTEXT 
+         (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask = 
+         g_object_ref (GTK_CMCTREE_ROW (node)->mask_opened);
+    }
+
+
+  work = GTK_CMCTREE_ROW (node)->children;
+  if (work)
+    {
+      GList *list = (GList *)work;
+      gint *cell_width = NULL;
+      gint tmp = 0;
+      gint row;
+      gint i;
+      
+      if (visible && !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+       {
+         cell_width = g_new0 (gint, clist->columns);
+         if (clist->column[ctree->tree_column].auto_resize)
+             cell_width[ctree->tree_column] = requisition.width;
+
+         while (work)
+           {
+             /* search maximum cell widths of auto_resize columns */
+             for (i = 0; i < clist->columns; i++)
+               if (clist->column[i].auto_resize)
+                 {
+                   GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+                     (clist, &GTK_CMCTREE_ROW (work)->row, i, &requisition);
+                   cell_width[i] = MAX (requisition.width, cell_width[i]);
+                 }
+
+             list = (GList *)work;
+             work = GTK_CMCTREE_NODE_NEXT (work);
+             tmp++;
+           }
+       }
+      else
+       while (work)
+         {
+           list = (GList *)work;
+           work = GTK_CMCTREE_NODE_NEXT (work);
+           tmp++;
+         }
+
+      list->next = (GList *)GTK_CMCTREE_NODE_NEXT (node);
+
+      if (GTK_CMCTREE_NODE_NEXT (node))
+       {
+         GList *tmp_list;
+
+         tmp_list = (GList *)GTK_CMCTREE_NODE_NEXT (node);
+         tmp_list->prev = list;
+       }
+      else
+       clist->row_list_end = list;
+
+      list = (GList *)node;
+      list->next = (GList *)(GTK_CMCTREE_ROW (node)->children);
+
+      if (visible)
+       {
+         /* resize auto_resize columns if needed */
+         for (i = 0; i < clist->columns; i++)
+           if (clist->column[i].auto_resize &&
+               cell_width[i] > clist->column[i].width)
+             gtk_cmclist_set_column_width (clist, i, cell_width[i]);
+         g_free (cell_width);
+
+         /* update focus_row position */
+         row = g_list_position (clist->row_list, (GList *)node);
+         if (row < clist->focus_row)
+           clist->focus_row += tmp;
+
+         clist->rows += tmp;
+         CLIST_REFRESH (clist);
+       }
+    }
+  else if (visible && clist->column[ctree->tree_column].auto_resize)
+    /* resize tree_column if needed */
+    column_auto_resize (clist, &GTK_CMCTREE_ROW (node)->row, ctree->tree_column,
+                       requisition.width);
+}
+
+static void 
+real_tree_collapse (GtkCMCTree     *ctree,
+                   GtkCMCTreeNode *node)
+{
+  GtkCMCList *clist;
+  GtkCMCTreeNode *work;
+  GtkRequisition requisition;
+  gboolean visible;
+  gint level;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  if (!node || !GTK_CMCTREE_ROW (node)->expanded ||
+      GTK_CMCTREE_ROW (node)->is_leaf)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+
+  GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+  
+  GTK_CMCTREE_ROW (node)->expanded = FALSE;
+  level = GTK_CMCTREE_ROW (node)->level;
+
+  visible = gtk_cmctree_is_viewable (ctree, node);
+  /* get cell width if tree_column is auto resized */
+  if (visible && clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+      (clist, &GTK_CMCTREE_ROW (node)->row, ctree->tree_column, &requisition);
+
+  /* unref/unset opened pixmap */
+  if (GTK_CMCELL_PIXTEXT 
+      (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
+    {
+      g_object_unref
+       (GTK_CMCELL_PIXTEXT
+        (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
+      
+      GTK_CMCELL_PIXTEXT
+       (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
+      
+      if (GTK_CMCELL_PIXTEXT 
+         (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
+       {
+         g_object_unref
+           (GTK_CMCELL_PIXTEXT 
+            (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
+         GTK_CMCELL_PIXTEXT 
+           (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
+       }
+    }
+
+  /* set/ref closed pixmap */
+  if (GTK_CMCTREE_ROW (node)->pixmap_closed)
+    {
+      GTK_CMCELL_PIXTEXT 
+       (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = 
+       g_object_ref (GTK_CMCTREE_ROW (node)->pixmap_closed);
+
+      if (GTK_CMCTREE_ROW (node)->mask_closed) 
+       GTK_CMCELL_PIXTEXT 
+         (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask = 
+         g_object_ref (GTK_CMCTREE_ROW (node)->mask_closed);
+    }
+
+  work = GTK_CMCTREE_ROW (node)->children;
+  if (work)
+    {
+      gint tmp = 0;
+      gint row;
+      GList *list;
+
+      while (work && GTK_CMCTREE_ROW (work)->level > level)
+       {
+         work = GTK_CMCTREE_NODE_NEXT (work);
+         tmp++;
+       }
+
+      if (work)
+       {
+         list = (GList *)node;
+         list->next = (GList *)work;
+         list = (GList *)GTK_CMCTREE_NODE_PREV (work);
+         list->next = NULL;
+         list = (GList *)work;
+         list->prev = (GList *)node;
+       }
+      else
+       {
+         list = (GList *)node;
+         list->next = NULL;
+         clist->row_list_end = (GList *)node;
+       }
+
+      if (visible)
+       {
+         /* resize auto_resize columns if needed */
+         auto_resize_columns (clist);
+
+         row = g_list_position (clist->row_list, (GList *)node);
+         if (row < clist->focus_row)
+           clist->focus_row -= tmp;
+         clist->rows -= tmp;
+         CLIST_REFRESH (clist);
+       }
+    }
+  else if (visible && clist->column[ctree->tree_column].auto_resize &&
+          !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    /* resize tree_column if needed */
+    column_auto_resize (clist, &GTK_CMCTREE_ROW (node)->row, ctree->tree_column,
+                       requisition.width);
+    
+}
+
+static void
+column_auto_resize (GtkCMCList    *clist,
+                   GtkCMCListRow *clist_row,
+                   gint         column,
+                   gint         old_width)
+{
+  /* resize column if needed for auto_resize */
+  GtkRequisition requisition;
+
+  if (!clist->column[column].auto_resize ||
+      GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    return;
+
+  if (clist_row)
+    GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+                                                  column, &requisition);
+  else
+    requisition.width = 0;
+
+  if (requisition.width > clist->column[column].width)
+    gtk_cmclist_set_column_width (clist, column, requisition.width);
+  else if (requisition.width < old_width &&
+          old_width == clist->column[column].width)
+    {
+      GList *list;
+      gint new_width;
+
+      /* run a "gtk_cmclist_optimal_column_width" but break, if
+       * the column doesn't shrink */
+      if (GTK_CMCLIST_SHOW_TITLES (clist) && clist->column[column].button)
+       new_width = (clist->column[column].button->requisition.width -
+                    (CELL_SPACING + (2 * COLUMN_INSET)));
+      else
+       new_width = 0;
+
+      for (list = clist->row_list; list; list = list->next)
+       {
+         GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+           (clist, GTK_CMCLIST_ROW (list), column, &requisition);
+         new_width = MAX (new_width, requisition.width);
+         if (new_width == clist->column[column].width)
+           break;
+       }
+      if (new_width < clist->column[column].width)
+       gtk_cmclist_set_column_width (clist, column, new_width);
+    }
+}
+
+static void
+auto_resize_columns (GtkCMCList *clist)
+{
+  gint i;
+
+  if (GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    return;
+
+  for (i = 0; i < clist->columns; i++)
+    column_auto_resize (clist, NULL, i, clist->column[i].width);
+}
+
+static void
+cell_size_request (GtkCMCList       *clist,
+                  GtkCMCListRow    *clist_row,
+                  gint            column,
+                  GtkRequisition *requisition)
+{
+  GtkCMCTree *ctree;
+  gint width;
+  gint height;
+  PangoLayout *layout;
+  PangoRectangle logical_rect;
+
+  g_return_if_fail (GTK_IS_CMCTREE (clist));
+  g_return_if_fail (requisition != NULL);
+
+  ctree = GTK_CMCTREE (clist);
+
+  layout = _gtk_cmclist_create_cell_layout (clist, clist_row, column);
+  if (layout)
+    {
+      pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+
+      requisition->width = logical_rect.width;
+      requisition->height = logical_rect.height;
+      
+      g_object_unref (G_OBJECT (layout));
+    }
+  else
+    {
+      requisition->width  = 0;
+      requisition->height = 0;
+    }
+
+  switch (clist_row->cell[column].type)
+    {
+    case GTK_CMCELL_PIXTEXT:
+      if (GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap)
+       {
+         gdk_drawable_get_size (GTK_CMCELL_PIXTEXT
+                              (clist_row->cell[column])->pixmap,
+                              &width, &height);
+         width += GTK_CMCELL_PIXTEXT (clist_row->cell[column])->spacing;
+       }
+      else
+       width = height = 0;
+         
+      requisition->width += width;
+      requisition->height = MAX (requisition->height, height);
+      
+      if (column == ctree->tree_column)
+       {
+         requisition->width += (ctree->tree_spacing + ctree->tree_indent *
+                                (((GtkCMCTreeRow *) clist_row)->level - 1));
+         switch (ctree->expander_style)
+           {
+           case GTK_CMCTREE_EXPANDER_NONE:
+             break;
+           case GTK_CMCTREE_EXPANDER_TRIANGLE:
+             requisition->width += PM_SIZE + 3;
+             break;
+           case GTK_CMCTREE_EXPANDER_SQUARE:
+           case GTK_CMCTREE_EXPANDER_CIRCULAR:
+             requisition->width += PM_SIZE + 1;
+             break;
+           }
+         if (ctree->line_style == GTK_CMCTREE_LINES_TABBED)
+           requisition->width += 3;
+       }
+      break;
+    case GTK_CMCELL_PIXMAP:
+      gdk_drawable_get_size (GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap,
+                          &width, &height);
+      requisition->width += width;
+      requisition->height = MAX (requisition->height, height);
+      break;
+    default:
+      break;
+    }
+
+  requisition->width  += clist_row->cell[column].horizontal;
+  requisition->height += clist_row->cell[column].vertical;
+}
+
+static void
+set_cell_contents (GtkCMCList    *clist,
+                  GtkCMCListRow *clist_row,
+                  gint         column,
+                  GtkCMCellType  type,
+                  const gchar *text,
+                  guint8       spacing,
+                  GdkPixmap   *pixmap,
+                  GdkBitmap   *mask)
+{
+  gboolean visible = FALSE;
+  GtkCMCTree *ctree;
+  GtkRequisition requisition;
+  gchar *old_text = NULL;
+  GdkPixmap *old_pixmap = NULL;
+  GdkBitmap *old_mask = NULL;
+
+  g_return_if_fail (GTK_IS_CMCTREE (clist));
+  g_return_if_fail (clist_row != NULL);
+
+  ctree = GTK_CMCTREE (clist);
+
+  if (clist->column[column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      GtkCMCTreeNode *parent;
+
+      parent = ((GtkCMCTreeRow *)clist_row)->parent;
+      if (!parent || (parent && GTK_CMCTREE_ROW (parent)->expanded &&
+                     gtk_cmctree_is_viewable (ctree, parent)))
+       {
+         visible = TRUE;
+         GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+                                                        column, &requisition);
+       }
+    }
+
+  switch (clist_row->cell[column].type)
+    {
+    case GTK_CMCELL_EMPTY:
+      break;
+    case GTK_CMCELL_TEXT:
+      old_text = GTK_CMCELL_TEXT (clist_row->cell[column])->text;
+      break;
+    case GTK_CMCELL_PIXMAP:
+      old_pixmap = GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap;
+      old_mask = GTK_CMCELL_PIXMAP (clist_row->cell[column])->mask;
+      break;
+    case GTK_CMCELL_PIXTEXT:
+      old_text = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text;
+      old_pixmap = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap;
+      old_mask = GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask;
+      break;
+    case GTK_CMCELL_WIDGET:
+      /* unimplemented */
+      break;
+      
+    default:
+      break;
+    }
+
+  clist_row->cell[column].type = GTK_CMCELL_EMPTY;
+  if (column == ctree->tree_column && type != GTK_CMCELL_EMPTY)
+    type = GTK_CMCELL_PIXTEXT;
+
+  /* Note that pixmap and mask were already ref'ed by the caller
+   */
+  switch (type)
+    {
+    case GTK_CMCELL_TEXT:
+      if (text)
+       {
+         clist_row->cell[column].type = GTK_CMCELL_TEXT;
+         GTK_CMCELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
+       }
+      break;
+    case GTK_CMCELL_PIXMAP:
+      if (pixmap)
+       {
+         clist_row->cell[column].type = GTK_CMCELL_PIXMAP;
+         GTK_CMCELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
+         /* We set the mask even if it is NULL */
+         GTK_CMCELL_PIXMAP (clist_row->cell[column])->mask = mask;
+       }
+      break;
+    case GTK_CMCELL_PIXTEXT:
+      if (column == ctree->tree_column)
+       {
+         clist_row->cell[column].type = GTK_CMCELL_PIXTEXT;
+         GTK_CMCELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
+         if (text)
+           GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
+         else
+           GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text = NULL;
+         if (pixmap)
+           {
+             GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
+             GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask = mask;
+           }
+         else
+           {
+             GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap = NULL;
+             GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask = NULL;
+           }
+       }
+      else if (text && pixmap)
+       {
+         clist_row->cell[column].type = GTK_CMCELL_PIXTEXT;
+         GTK_CMCELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
+         GTK_CMCELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
+         GTK_CMCELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
+         GTK_CMCELL_PIXTEXT (clist_row->cell[column])->mask = mask;
+       }
+      break;
+    default:
+      break;
+    }
+  
+  if (visible && clist->column[column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    column_auto_resize (clist, clist_row, column, requisition.width);
+
+  g_free (old_text);
+  if (old_pixmap)
+    g_object_unref (old_pixmap);
+  if (old_mask)
+    g_object_unref (old_mask);
+}
+
+static void 
+set_node_info (GtkCMCTree     *ctree,
+              GtkCMCTreeNode *node,
+              const gchar  *text,
+              guint8        spacing,
+              GdkPixmap    *pixmap_closed,
+              GdkBitmap    *mask_closed,
+              GdkPixmap    *pixmap_opened,
+              GdkBitmap    *mask_opened,
+              gboolean      is_leaf,
+              gboolean      expanded)
+{
+  if (GTK_CMCTREE_ROW (node)->pixmap_opened)
+    {
+      g_object_unref (GTK_CMCTREE_ROW (node)->pixmap_opened);
+      if (GTK_CMCTREE_ROW (node)->mask_opened) 
+       g_object_unref (GTK_CMCTREE_ROW (node)->mask_opened);
+    }
+  if (GTK_CMCTREE_ROW (node)->pixmap_closed)
+    {
+      g_object_unref (GTK_CMCTREE_ROW (node)->pixmap_closed);
+      if (GTK_CMCTREE_ROW (node)->mask_closed) 
+       g_object_unref (GTK_CMCTREE_ROW (node)->mask_closed);
+    }
+
+  GTK_CMCTREE_ROW (node)->pixmap_opened = NULL;
+  GTK_CMCTREE_ROW (node)->mask_opened   = NULL;
+  GTK_CMCTREE_ROW (node)->pixmap_closed = NULL;
+  GTK_CMCTREE_ROW (node)->mask_closed   = NULL;
+
+  if (pixmap_closed)
+    {
+      GTK_CMCTREE_ROW (node)->pixmap_closed = g_object_ref (pixmap_closed);
+      if (mask_closed) 
+       GTK_CMCTREE_ROW (node)->mask_closed = g_object_ref (mask_closed);
+    }
+  if (pixmap_opened)
+    {
+      GTK_CMCTREE_ROW (node)->pixmap_opened = g_object_ref (pixmap_opened);
+      if (mask_opened) 
+       GTK_CMCTREE_ROW (node)->mask_opened = g_object_ref (mask_opened);
+    }
+
+  GTK_CMCTREE_ROW (node)->is_leaf  = is_leaf;
+  GTK_CMCTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
+
+  if (GTK_CMCTREE_ROW (node)->expanded)
+    gtk_cmctree_node_set_pixtext (ctree, node, ctree->tree_column,
+                               text, spacing, pixmap_opened, mask_opened);
+  else 
+    gtk_cmctree_node_set_pixtext (ctree, node, ctree->tree_column,
+                               text, spacing, pixmap_closed, mask_closed);
+}
+
+static void
+tree_delete (GtkCMCTree     *ctree, 
+            GtkCMCTreeNode *node, 
+            gpointer      data)
+{
+  tree_unselect (ctree,  node, NULL);
+  row_delete (ctree, GTK_CMCTREE_ROW (node));
+  g_list_free_1 ((GList *)node);
+}
+
+static void
+tree_delete_row (GtkCMCTree     *ctree, 
+                GtkCMCTreeNode *node, 
+                gpointer      data)
+{
+  row_delete (ctree, GTK_CMCTREE_ROW (node));
+  g_list_free_1 ((GList *)node);
+}
+
+static void
+tree_update_level (GtkCMCTree     *ctree, 
+                  GtkCMCTreeNode *node, 
+                  gpointer      data)
+{
+  if (!node)
+    return;
+
+  if (GTK_CMCTREE_ROW (node)->parent)
+      GTK_CMCTREE_ROW (node)->level = 
+       GTK_CMCTREE_ROW (GTK_CMCTREE_ROW (node)->parent)->level + 1;
+  else
+      GTK_CMCTREE_ROW (node)->level = 1;
+}
+
+static void
+tree_select (GtkCMCTree     *ctree, 
+            GtkCMCTreeNode *node, 
+            gpointer      data)
+{
+  if (node && GTK_CMCTREE_ROW (node)->row.state != GTK_STATE_SELECTED &&
+      GTK_CMCTREE_ROW (node)->row.selectable)
+    g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], 0,
+                    node, -1);
+}
+
+static void
+tree_unselect (GtkCMCTree     *ctree, 
+              GtkCMCTreeNode *node, 
+              gpointer      data)
+{
+  if (node && GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
+    g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW], 0,
+                    node, -1);
+}
+
+static void
+tree_expand (GtkCMCTree     *ctree, 
+            GtkCMCTreeNode *node, 
+            gpointer      data)
+{
+  if (node && !GTK_CMCTREE_ROW (node)->expanded)
+    g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], 0,node);
+}
+
+static void
+tree_collapse (GtkCMCTree     *ctree, 
+              GtkCMCTreeNode *node, 
+              gpointer      data)
+{
+  if (node && GTK_CMCTREE_ROW (node)->expanded)
+    g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], 0,node);
+}
+
+static void
+tree_collapse_to_depth (GtkCMCTree     *ctree, 
+                       GtkCMCTreeNode *node, 
+                       gint          depth)
+{
+  if (node && GTK_CMCTREE_ROW (node)->level == depth)
+    gtk_cmctree_collapse_recursive (ctree, node);
+}
+
+static void
+tree_toggle_expansion (GtkCMCTree     *ctree,
+                      GtkCMCTreeNode *node,
+                      gpointer      data)
+{
+  if (!node)
+    return;
+
+  if (GTK_CMCTREE_ROW (node)->expanded)
+    g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], 0,node);
+  else
+    g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], 0,node);
+}
+
+static GtkCMCTreeRow *
+row_new (GtkCMCTree *ctree)
+{
+  GtkCMCList *clist;
+  GtkCMCTreeRow *ctree_row;
+  int i;
+
+  clist = GTK_CMCLIST (ctree);
+  ctree_row = g_slice_new (GtkCMCTreeRow);
+  ctree_row->row.cell = g_slice_alloc (sizeof (GtkCMCell) * clist->columns);
+
+  for (i = 0; i < clist->columns; i++)
+    {
+      ctree_row->row.cell[i].type = GTK_CMCELL_EMPTY;
+      ctree_row->row.cell[i].vertical = 0;
+      ctree_row->row.cell[i].horizontal = 0;
+      ctree_row->row.cell[i].style = NULL;
+    }
+
+  GTK_CMCELL_PIXTEXT (ctree_row->row.cell[ctree->tree_column])->text = NULL;
+
+  ctree_row->row.fg_set     = FALSE;
+  ctree_row->row.bg_set     = FALSE;
+  ctree_row->row.style      = NULL;
+  ctree_row->row.selectable = TRUE;
+  ctree_row->row.state      = GTK_STATE_NORMAL;
+  ctree_row->row.data       = NULL;
+  ctree_row->row.destroy    = NULL;
+
+  ctree_row->level         = 0;
+  ctree_row->expanded      = FALSE;
+  ctree_row->parent        = NULL;
+  ctree_row->sibling       = NULL;
+  ctree_row->children      = NULL;
+  ctree_row->pixmap_closed = NULL;
+  ctree_row->mask_closed   = NULL;
+  ctree_row->pixmap_opened = NULL;
+  ctree_row->mask_opened   = NULL;
+  
+  return ctree_row;
+}
+
+static void
+row_delete (GtkCMCTree    *ctree,
+           GtkCMCTreeRow *ctree_row)
+{
+  GtkCMCList *clist;
+  gint i;
+
+  clist = GTK_CMCLIST (ctree);
+
+  for (i = 0; i < clist->columns; i++)
+    {
+      GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+       (clist, &(ctree_row->row), i, GTK_CMCELL_EMPTY, NULL, 0, NULL, NULL);
+      if (ctree_row->row.cell[i].style)
+       {
+         if (GTK_WIDGET_REALIZED (ctree))
+           gtk_style_detach (ctree_row->row.cell[i].style);
+         g_object_unref (ctree_row->row.cell[i].style);
+       }
+    }
+
+  if (ctree_row->row.style)
+    {
+      if (GTK_WIDGET_REALIZED (ctree))
+       gtk_style_detach (ctree_row->row.style);
+      g_object_unref (ctree_row->row.style);
+    }
+
+  if (ctree_row->pixmap_closed)
+    {
+      g_object_unref (ctree_row->pixmap_closed);
+      if (ctree_row->mask_closed)
+       g_object_unref (ctree_row->mask_closed);
+    }
+
+  if (ctree_row->pixmap_opened)
+    {
+      g_object_unref (ctree_row->pixmap_opened);
+      if (ctree_row->mask_opened)
+       g_object_unref (ctree_row->mask_opened);
+    }
+
+  if (ctree_row->row.destroy)
+    {
+      GtkDestroyNotify dnotify = ctree_row->row.destroy;
+      gpointer ddata = ctree_row->row.data;
+
+      ctree_row->row.destroy = NULL;
+      ctree_row->row.data = NULL;
+
+      dnotify (ddata);
+    }
+
+  g_slice_free1 (sizeof (GtkCMCell) * clist->columns, ctree_row->row.cell);
+  g_slice_free (GtkCMCTreeRow, ctree_row);
+}
+
+static void
+real_select_row (GtkCMCList *clist,
+                gint      row,
+                gint      column,
+                GdkEvent *event)
+{
+  GList *node;
+
+  g_return_if_fail (GTK_IS_CMCTREE (clist));
+  
+  if ((node = g_list_nth (clist->row_list, row)) &&
+      GTK_CMCTREE_ROW (node)->row.selectable)
+    g_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_SELECT_ROW],0,
+                    node, column);
+}
+
+static void
+real_unselect_row (GtkCMCList *clist,
+                  gint      row,
+                  gint      column,
+                  GdkEvent *event)
+{
+  GList *node;
+
+  g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+  if ((node = g_list_nth (clist->row_list, row)))
+    g_signal_emit (GTK_OBJECT (clist), ctree_signals[TREE_UNSELECT_ROW],0,
+                    node, column);
+}
+
+static void
+real_tree_select (GtkCMCTree     *ctree,
+                 GtkCMCTreeNode *node,
+                 gint          column)
+{
+  GtkCMCList *clist;
+  GList *list;
+  GtkCMCTreeNode *sel_row;
+  gboolean node_selected;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  if (!node || GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
+      !GTK_CMCTREE_ROW (node)->row.selectable)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+
+  switch (clist->selection_mode)
+    {
+    case GTK_SELECTION_SINGLE:
+    case GTK_SELECTION_BROWSE:
+
+      node_selected = FALSE;
+      list = clist->selection;
+
+      while (list)
+       {
+         sel_row = list->data;
+         list = list->next;
+         
+         if (node == sel_row)
+           node_selected = TRUE;
+         else
+           g_signal_emit (GTK_OBJECT (ctree),
+                            ctree_signals[TREE_UNSELECT_ROW], 0, sel_row, column);
+       }
+
+      if (node_selected)
+       return;
+
+    default:
+      break;
+    }
+
+  GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
+
+  if (!clist->selection)
+    {
+      clist->selection = g_list_append (clist->selection, node);
+      clist->selection_end = clist->selection;
+    }
+  else
+    clist->selection_end = g_list_append (clist->selection_end, node)->next;
+
+  tree_draw_node (ctree, node);
+}
+
+static void
+real_tree_unselect (GtkCMCTree     *ctree,
+                   GtkCMCTreeNode *node,
+                   gint          column)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  if (!node || GTK_CMCTREE_ROW (node)->row.state != GTK_STATE_SELECTED)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (clist->selection_end && clist->selection_end->data == node)
+    clist->selection_end = clist->selection_end->prev;
+
+  clist->selection = g_list_remove (clist->selection, node);
+  
+  GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
+
+  tree_draw_node (ctree, node);
+}
+
+static void
+select_row_recursive (GtkCMCTree     *ctree, 
+                     GtkCMCTreeNode *node, 
+                     gpointer      data)
+{
+  if (!node || GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_SELECTED ||
+      !GTK_CMCTREE_ROW (node)->row.selectable)
+    return;
+
+  GTK_CMCLIST (ctree)->undo_unselection = 
+    g_list_prepend (GTK_CMCLIST (ctree)->undo_unselection, node);
+  gtk_cmctree_select (ctree, node);
+}
+
+static void
+real_select_all (GtkCMCList *clist)
+{
+  GtkCMCTree *ctree;
+  GtkCMCTreeNode *node;
+  
+  g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+  ctree = GTK_CMCTREE (clist);
+
+  switch (clist->selection_mode)
+    {
+    case GTK_SELECTION_SINGLE:
+    case GTK_SELECTION_BROWSE:
+      return;
+
+    case GTK_SELECTION_MULTIPLE:
+
+      gtk_cmclist_freeze (clist);
+
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+         
+      clist->anchor_state = GTK_STATE_SELECTED;
+      clist->anchor = -1;
+      clist->drag_pos = -1;
+      clist->undo_anchor = clist->focus_row;
+
+      for (node = GTK_CMCTREE_NODE (clist->row_list); node;
+          node = GTK_CMCTREE_NODE_NEXT (node))
+       gtk_cmctree_pre_recursive (ctree, node, select_row_recursive, NULL);
+
+      gtk_cmclist_thaw (clist);
+      break;
+
+    default:
+      /* do nothing */
+      break;
+    }
+}
+
+static void
+real_unselect_all (GtkCMCList *clist)
+{
+  GtkCMCTree *ctree;
+  GtkCMCTreeNode *node;
+  GList *list;
+  g_return_if_fail (GTK_IS_CMCTREE (clist));
+  
+  ctree = GTK_CMCTREE (clist);
+
+  switch (clist->selection_mode)
+    {
+    case GTK_SELECTION_BROWSE:
+      if (clist->focus_row >= 0)
+       {
+         gtk_cmctree_select
+           (ctree,
+            GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row)));
+         return;
+       }
+      break;
+
+    case GTK_SELECTION_MULTIPLE:
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+
+      clist->anchor = -1;
+      clist->drag_pos = -1;
+      clist->undo_anchor = clist->focus_row;
+      break;
+
+    default:
+      break;
+    }
+
+  list = clist->selection;
+
+  while (list)
+    {
+      node = list->data;
+      list = list->next;
+      gtk_cmctree_unselect (ctree, node);
+    }
+}
+
+static gboolean
+ctree_is_hot_spot (GtkCMCTree     *ctree, 
+                  GtkCMCTreeNode *node,
+                  gint          row, 
+                  gint          x, 
+                  gint          y)
+{
+  GtkCMCTreeRow *tree_row;
+  GtkCMCList *clist;
+  gint xl;
+  gint yu;
+  
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+  g_return_val_if_fail (node != NULL, FALSE);
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (!clist->column[ctree->tree_column].visible ||
+      ctree->expander_style == GTK_CMCTREE_EXPANDER_NONE)
+    return FALSE;
+
+  tree_row = GTK_CMCTREE_ROW (node);
+
+  yu = (ROW_TOP_YPIXEL (clist, row) + (clist->row_height - PM_SIZE) / 2 -
+       (clist->row_height - 1) % 2);
+
+  if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
+    xl = (clist->column[ctree->tree_column].area.x + 
+         clist->column[ctree->tree_column].area.width - 1 + clist->hoffset -
+         (tree_row->level - 1) * ctree->tree_indent - PM_SIZE -
+         (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
+  else
+    xl = (clist->column[ctree->tree_column].area.x + clist->hoffset +
+         (tree_row->level - 1) * ctree->tree_indent +
+         (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
+
+  return (x >= xl && x <= xl + PM_SIZE && y >= yu && y <= yu + PM_SIZE);
+}
+
+/***********************************************************
+ ***********************************************************
+ ***                  Public interface                   ***
+ ***********************************************************
+ ***********************************************************/
+
+
+/***********************************************************
+ *           Creation, insertion, deletion                 *
+ ***********************************************************/
+
+static GObject*
+gtk_cmctree_constructor (GType                  type,
+                      guint                  n_construct_properties,
+                      GObjectConstructParam *construct_properties)
+{
+  GObject *object = G_OBJECT_CLASS (parent_class)->constructor (type,
+                                                               n_construct_properties,
+                                                               construct_properties);
+
+  return object;
+}
+
+GtkWidget*
+gtk_cmctree_new_with_titles (gint         columns, 
+                          gint         tree_column,
+                          gchar       *titles[])
+{
+  GtkWidget *widget;
+
+  g_return_val_if_fail (columns > 0, NULL);
+  g_return_val_if_fail (tree_column >= 0 && tree_column < columns, NULL);
+
+  widget = gtk_widget_new (GTK_TYPE_CMCTREE,
+                          "n_columns", columns,
+                          "tree_column", tree_column,
+                          NULL);
+  if (titles)
+    {
+      GtkCMCList *clist = GTK_CMCLIST (widget);
+      guint i;
+
+      for (i = 0; i < columns; i++)
+       gtk_cmclist_set_column_title (clist, i, titles[i]);
+      gtk_cmclist_column_titles_show (clist);
+    }
+
+  return widget;
+}
+
+GtkWidget *
+gtk_cmctree_new (gint columns, 
+              gint tree_column)
+{
+  return gtk_cmctree_new_with_titles (columns, tree_column, NULL);
+}
+
+static gint
+real_insert_row (GtkCMCList *clist,
+                gint      row,
+                gchar    *text[])
+{
+  GtkCMCTreeNode *parent = NULL;
+  GtkCMCTreeNode *sibling;
+  GtkCMCTreeNode *node;
+
+  g_return_val_if_fail (GTK_IS_CMCTREE (clist), -1);
+
+  sibling = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, row));
+  if (sibling)
+    parent = GTK_CMCTREE_ROW (sibling)->parent;
+
+  node = gtk_cmctree_insert_node (GTK_CMCTREE (clist), parent, sibling, text, 5,
+                               NULL, NULL, NULL, NULL, TRUE, FALSE);
+
+  if (GTK_CMCLIST_AUTO_SORT (clist) || !sibling)
+    return g_list_position (clist->row_list, (GList *) node);
+  
+  return row;
+}
+
+GtkCMCTreeNode * 
+gtk_cmctree_insert_node (GtkCMCTree     *ctree,
+                      GtkCMCTreeNode *parent, 
+                      GtkCMCTreeNode *sibling,
+                      gchar        *text[],
+                      guint8        spacing,
+                      GdkPixmap    *pixmap_closed,
+                      GdkBitmap    *mask_closed,
+                      GdkPixmap    *pixmap_opened,
+                      GdkBitmap    *mask_opened,
+                      gboolean      is_leaf,
+                      gboolean      expanded)
+{
+  GtkCMCList *clist;
+  GtkCMCTreeRow *new_row;
+  GtkCMCTreeNode *node;
+  GList *list;
+  gint i;
+
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+  if (sibling)
+    g_return_val_if_fail (GTK_CMCTREE_ROW (sibling)->parent == parent, NULL);
+
+  if (parent && GTK_CMCTREE_ROW (parent)->is_leaf)
+    return NULL;
+
+  clist = GTK_CMCLIST (ctree);
+
+  /* create the row */
+  new_row = row_new (ctree);
+  list = g_list_alloc ();
+  list->data = new_row;
+  node = GTK_CMCTREE_NODE (list);
+
+  if (text)
+    for (i = 0; i < clist->columns; i++)
+      if (text[i] && i != ctree->tree_column)
+       GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+         (clist, &(new_row->row), i, GTK_CMCELL_TEXT, text[i], 0, NULL, NULL);
+
+  set_node_info (ctree, node, text ?
+                text[ctree->tree_column] : NULL, spacing, pixmap_closed,
+                mask_closed, pixmap_opened, mask_opened, is_leaf, expanded);
+
+  /* sorted insertion */
+  if (GTK_CMCLIST_AUTO_SORT (clist))
+    {
+      if (parent)
+       sibling = GTK_CMCTREE_ROW (parent)->children;
+      else
+       sibling = GTK_CMCTREE_NODE (clist->row_list);
+
+      while (sibling && clist->compare
+            (clist, GTK_CMCTREE_ROW (node), GTK_CMCTREE_ROW (sibling)) > 0)
+       sibling = GTK_CMCTREE_ROW (sibling)->sibling;
+    }
+
+  gtk_cmctree_link (ctree, node, parent, sibling, TRUE);
+
+  if (text && !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist) &&
+      gtk_cmctree_is_viewable (ctree, node))
+    {
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].auto_resize)
+         column_auto_resize (clist, &(new_row->row), i, 0);
+    }
+
+  if (clist->rows == 1)
+    {
+      clist->focus_row = 0;
+      if (clist->selection_mode == GTK_SELECTION_BROWSE)
+       gtk_cmctree_select (ctree, node);
+    }
+
+
+  CLIST_REFRESH (clist);
+
+  return node;
+}
+
+GtkCMCTreeNode *
+gtk_cmctree_insert_gnode (GtkCMCTree          *ctree,
+                       GtkCMCTreeNode      *parent,
+                       GtkCMCTreeNode      *sibling,
+                       GNode             *gnode,
+                       GtkCMCTreeGNodeFunc  func,
+                       gpointer           data)
+{
+  GtkCMCList *clist;
+  GtkCMCTreeNode *cnode = NULL;
+  GtkCMCTreeNode *child = NULL;
+  GtkCMCTreeNode *new_child;
+  GList *list;
+  GNode *work;
+  guint depth = 1;
+
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+  g_return_val_if_fail (gnode != NULL, NULL);
+  g_return_val_if_fail (func != NULL, NULL);
+  if (sibling)
+    g_return_val_if_fail (GTK_CMCTREE_ROW (sibling)->parent == parent, NULL);
+  
+  clist = GTK_CMCLIST (ctree);
+
+  if (parent)
+    depth = GTK_CMCTREE_ROW (parent)->level + 1;
+
+  list = g_list_alloc ();
+  list->data = row_new (ctree);
+  cnode = GTK_CMCTREE_NODE (list);
+
+  gtk_cmclist_freeze (clist);
+
+  set_node_info (ctree, cnode, "", 0, NULL, NULL, NULL, NULL, TRUE, FALSE);
+
+  if (!func (ctree, depth, gnode, cnode, data))
+    {
+      tree_delete_row (ctree, cnode, NULL);
+      gtk_cmclist_thaw (clist);
+      return NULL;
+    }
+
+  if (GTK_CMCLIST_AUTO_SORT (clist))
+    {
+      if (parent)
+       sibling = GTK_CMCTREE_ROW (parent)->children;
+      else
+       sibling = GTK_CMCTREE_NODE (clist->row_list);
+
+      while (sibling && clist->compare
+            (clist, GTK_CMCTREE_ROW (cnode), GTK_CMCTREE_ROW (sibling)) > 0)
+       sibling = GTK_CMCTREE_ROW (sibling)->sibling;
+    }
+
+  gtk_cmctree_link (ctree, cnode, parent, sibling, TRUE);
+
+  for (work = g_node_last_child (gnode); work; work = work->prev)
+    {
+      new_child = gtk_cmctree_insert_gnode (ctree, cnode, child,
+                                         work, func, data);
+      if (new_child)
+       child = new_child;
+    }  
+  
+  gtk_cmclist_thaw (clist);
+
+  return cnode;
+}
+
+GNode *
+gtk_cmctree_export_to_gnode (GtkCMCTree          *ctree,
+                          GNode             *parent,
+                          GNode             *sibling,
+                          GtkCMCTreeNode      *node,
+                          GtkCMCTreeGNodeFunc  func,
+                          gpointer           data)
+{
+  GtkCMCTreeNode *work;
+  GNode *gnode;
+  gint depth;
+
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+  g_return_val_if_fail (node != NULL, NULL);
+  g_return_val_if_fail (func != NULL, NULL);
+  if (sibling)
+    {
+      g_return_val_if_fail (parent != NULL, NULL);
+      g_return_val_if_fail (sibling->parent == parent, NULL);
+    }
+
+  gnode = g_node_new (NULL);
+  depth = g_node_depth (parent) + 1;
+  
+  if (!func (ctree, depth, gnode, node, data))
+    {
+      g_node_destroy (gnode);
+      return NULL;
+    }
+
+  if (parent)
+    g_node_insert_before (parent, sibling, gnode);
+
+  if (!GTK_CMCTREE_ROW (node)->is_leaf)
+    {
+      GNode *new_sibling = NULL;
+
+      for (work = GTK_CMCTREE_ROW (node)->children; work;
+          work = GTK_CMCTREE_ROW (work)->sibling)
+       new_sibling = gtk_cmctree_export_to_gnode (ctree, gnode, new_sibling,
+                                                work, func, data);
+
+      g_node_reverse_children (gnode);
+    }
+
+  return gnode;
+}
+  
+static void
+real_remove_row (GtkCMCList *clist,
+                gint      row)
+{
+  GtkCMCTreeNode *node;
+
+  g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+  node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, row));
+
+  if (node)
+    gtk_cmctree_remove_node (GTK_CMCTREE (clist), node);
+}
+
+void
+gtk_cmctree_remove_node (GtkCMCTree     *ctree, 
+                      GtkCMCTreeNode *node)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  clist = GTK_CMCLIST (ctree);
+
+  gtk_cmclist_freeze (clist);
+
+  if (node)
+    {
+      gtk_cmctree_unlink (ctree, node, TRUE);
+      gtk_cmctree_post_recursive (ctree, node, GTK_CMCTREE_FUNC (tree_delete),
+                               NULL);
+      if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection &&
+         clist->focus_row >= 0)
+       gtk_cmclist_select_row (clist, clist->focus_row, -1);
+
+      auto_resize_columns (clist);
+    }
+  else
+    gtk_cmclist_clear (clist);
+
+  gtk_cmclist_thaw (clist);
+}
+
+static void
+real_clear (GtkCMCList *clist)
+{
+  GtkCMCTree *ctree;
+  GtkCMCTreeNode *work;
+  GtkCMCTreeNode *ptr;
+
+  g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+  ctree = GTK_CMCTREE (clist);
+
+  /* remove all rows */
+  work = GTK_CMCTREE_NODE (clist->row_list);
+  clist->row_list = NULL;
+  clist->row_list_end = NULL;
+
+  GTK_CMCLIST_SET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+  while (work)
+    {
+      ptr = work;
+      work = GTK_CMCTREE_ROW (work)->sibling;
+      gtk_cmctree_post_recursive (ctree, ptr, GTK_CMCTREE_FUNC (tree_delete_row), 
+                               NULL);
+    }
+  GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+
+  parent_class->clear (clist);
+}
+
+
+/***********************************************************
+ *  Generic recursive functions, querying / finding tree   *
+ *  information                                            *
+ ***********************************************************/
+
+
+void
+gtk_cmctree_post_recursive (GtkCMCTree     *ctree, 
+                         GtkCMCTreeNode *node,
+                         GtkCMCTreeFunc  func,
+                         gpointer      data)
+{
+  GtkCMCTreeNode *work;
+  GtkCMCTreeNode *tmp;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (func != NULL);
+
+  if (node)
+    work = GTK_CMCTREE_ROW (node)->children;
+  else
+    work = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+  while (work)
+    {
+      tmp = GTK_CMCTREE_ROW (work)->sibling;
+      gtk_cmctree_post_recursive (ctree, work, func, data);
+      work = tmp;
+    }
+
+  if (node)
+    func (ctree, node, data);
+}
+
+void
+gtk_cmctree_post_recursive_to_depth (GtkCMCTree     *ctree, 
+                                  GtkCMCTreeNode *node,
+                                  gint          depth,
+                                  GtkCMCTreeFunc  func,
+                                  gpointer      data)
+{
+  GtkCMCTreeNode *work;
+  GtkCMCTreeNode *tmp;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (func != NULL);
+
+  if (depth < 0)
+    {
+      gtk_cmctree_post_recursive (ctree, node, func, data);
+      return;
+    }
+
+  if (node)
+    work = GTK_CMCTREE_ROW (node)->children;
+  else
+    work = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+  if (work && GTK_CMCTREE_ROW (work)->level <= depth)
+    {
+      while (work)
+       {
+         tmp = GTK_CMCTREE_ROW (work)->sibling;
+         gtk_cmctree_post_recursive_to_depth (ctree, work, depth, func, data);
+         work = tmp;
+       }
+    }
+
+  if (node && GTK_CMCTREE_ROW (node)->level <= depth)
+    func (ctree, node, data);
+}
+
+void
+gtk_cmctree_pre_recursive (GtkCMCTree     *ctree, 
+                        GtkCMCTreeNode *node,
+                        GtkCMCTreeFunc  func,
+                        gpointer      data)
+{
+  GtkCMCTreeNode *work;
+  GtkCMCTreeNode *tmp;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (func != NULL);
+
+  if (node)
+    {
+      work = GTK_CMCTREE_ROW (node)->children;
+      func (ctree, node, data);
+    }
+  else
+    work = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+  while (work)
+    {
+      tmp = GTK_CMCTREE_ROW (work)->sibling;
+      gtk_cmctree_pre_recursive (ctree, work, func, data);
+      work = tmp;
+    }
+}
+
+void
+gtk_cmctree_pre_recursive_to_depth (GtkCMCTree     *ctree, 
+                                 GtkCMCTreeNode *node,
+                                 gint          depth, 
+                                 GtkCMCTreeFunc  func,
+                                 gpointer      data)
+{
+  GtkCMCTreeNode *work;
+  GtkCMCTreeNode *tmp;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (func != NULL);
+
+  if (depth < 0)
+    {
+      gtk_cmctree_pre_recursive (ctree, node, func, data);
+      return;
+    }
+
+  if (node)
+    {
+      work = GTK_CMCTREE_ROW (node)->children;
+      if (GTK_CMCTREE_ROW (node)->level <= depth)
+       func (ctree, node, data);
+    }
+  else
+    work = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+  if (work && GTK_CMCTREE_ROW (work)->level <= depth)
+    {
+      while (work)
+       {
+         tmp = GTK_CMCTREE_ROW (work)->sibling;
+         gtk_cmctree_pre_recursive_to_depth (ctree, work, depth, func, data);
+         work = tmp;
+       }
+    }
+}
+
+gboolean
+gtk_cmctree_is_viewable (GtkCMCTree     *ctree, 
+                      GtkCMCTreeNode *node)
+{ 
+  GtkCMCTreeRow *work;
+
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+  g_return_val_if_fail (node != NULL, FALSE);
+
+  work = GTK_CMCTREE_ROW (node);
+
+  while (work->parent && GTK_CMCTREE_ROW (work->parent)->expanded)
+    work = GTK_CMCTREE_ROW (work->parent);
+
+  if (!work->parent)
+    return TRUE;
+
+  return FALSE;
+}
+
+GtkCMCTreeNode * 
+gtk_cmctree_last (GtkCMCTree     *ctree,
+               GtkCMCTreeNode *node)
+{
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+
+  if (!node) 
+    return NULL;
+
+  while (GTK_CMCTREE_ROW (node)->sibling)
+    node = GTK_CMCTREE_ROW (node)->sibling;
+  
+  if (GTK_CMCTREE_ROW (node)->children)
+    return gtk_cmctree_last (ctree, GTK_CMCTREE_ROW (node)->children);
+  
+  return node;
+}
+
+GtkCMCTreeNode *
+gtk_cmctree_find_node_ptr (GtkCMCTree    *ctree,
+                        GtkCMCTreeRow *ctree_row)
+{
+  GtkCMCTreeNode *node;
+  
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+  g_return_val_if_fail (ctree_row != NULL, NULL);
+  
+  if (ctree_row->parent)
+    node = GTK_CMCTREE_ROW (ctree_row->parent)->children;
+  else
+    node = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+  while (GTK_CMCTREE_ROW (node) != ctree_row)
+    node = GTK_CMCTREE_ROW (node)->sibling;
+  
+  return node;
+}
+
+GtkCMCTreeNode *
+gtk_cmctree_node_nth (GtkCMCTree *ctree,
+                   guint     row)
+{
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+
+  if ((row >= GTK_CMCLIST(ctree)->rows))
+    return NULL;
+  return GTK_CMCTREE_NODE (g_list_nth (GTK_CMCLIST (ctree)->row_list, row));
+}
+
+gboolean
+gtk_cmctree_find (GtkCMCTree     *ctree,
+               GtkCMCTreeNode *node,
+               GtkCMCTreeNode *child)
+{
+  if (!child)
+    return FALSE;
+
+  if (!node)
+    node = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+  while (node)
+    {
+      if (node == child) 
+       return TRUE;
+      if (GTK_CMCTREE_ROW (node)->children)
+       {
+         if (gtk_cmctree_find (ctree, GTK_CMCTREE_ROW (node)->children, child))
+           return TRUE;
+       }
+      node = GTK_CMCTREE_ROW (node)->sibling;
+    }
+  return FALSE;
+}
+
+gboolean
+gtk_cmctree_is_ancestor (GtkCMCTree     *ctree,
+                      GtkCMCTreeNode *node,
+                      GtkCMCTreeNode *child)
+{
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+  g_return_val_if_fail (node != NULL, FALSE);
+
+  if (GTK_CMCTREE_ROW (node)->children)
+    return gtk_cmctree_find (ctree, GTK_CMCTREE_ROW (node)->children, child);
+
+  return FALSE;
+}
+
+GtkCMCTreeNode *
+gtk_cmctree_find_by_row_data (GtkCMCTree     *ctree,
+                           GtkCMCTreeNode *node,
+                           gpointer      data)
+{
+  GtkCMCTreeNode *work;
+  
+  if (!node)
+    node = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+  
+  while (node)
+    {
+      if (GTK_CMCTREE_ROW (node)->row.data == data) 
+       return node;
+      if (GTK_CMCTREE_ROW (node)->children &&
+         (work = gtk_cmctree_find_by_row_data 
+          (ctree, GTK_CMCTREE_ROW (node)->children, data)))
+       return work;
+      node = GTK_CMCTREE_ROW (node)->sibling;
+    }
+  return NULL;
+}
+
+GList *
+gtk_cmctree_find_all_by_row_data (GtkCMCTree     *ctree,
+                               GtkCMCTreeNode *node,
+                               gpointer      data)
+{
+  GList *list = NULL;
+
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+
+  /* if node == NULL then look in the whole tree */
+  if (!node)
+    node = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+  while (node)
+    {
+      if (GTK_CMCTREE_ROW (node)->row.data == data)
+        list = g_list_append (list, node);
+
+      if (GTK_CMCTREE_ROW (node)->children)
+        {
+         GList *sub_list;
+
+          sub_list = gtk_cmctree_find_all_by_row_data (ctree,
+                                                    GTK_CMCTREE_ROW
+                                                    (node)->children,
+                                                    data);
+          list = g_list_concat (list, sub_list);
+        }
+      node = GTK_CMCTREE_ROW (node)->sibling;
+    }
+  return list;
+}
+
+GtkCMCTreeNode *
+gtk_cmctree_find_by_row_data_custom (GtkCMCTree     *ctree,
+                                  GtkCMCTreeNode *node,
+                                  gpointer      data,
+                                  GCompareFunc  func)
+{
+  GtkCMCTreeNode *work;
+
+  g_return_val_if_fail (func != NULL, NULL);
+
+  if (!node)
+    node = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+  while (node)
+    {
+      if (!func (GTK_CMCTREE_ROW (node)->row.data, data))
+       return node;
+      if (GTK_CMCTREE_ROW (node)->children &&
+         (work = gtk_cmctree_find_by_row_data_custom
+          (ctree, GTK_CMCTREE_ROW (node)->children, data, func)))
+       return work;
+      node = GTK_CMCTREE_ROW (node)->sibling;
+    }
+  return NULL;
+}
+
+GList *
+gtk_cmctree_find_all_by_row_data_custom (GtkCMCTree     *ctree,
+                                      GtkCMCTreeNode *node,
+                                      gpointer      data,
+                                      GCompareFunc  func)
+{
+  GList *list = NULL;
+
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+  g_return_val_if_fail (func != NULL, NULL);
+
+  /* if node == NULL then look in the whole tree */
+  if (!node)
+    node = GTK_CMCTREE_NODE (GTK_CMCLIST (ctree)->row_list);
+
+  while (node)
+    {
+      if (!func (GTK_CMCTREE_ROW (node)->row.data, data))
+        list = g_list_append (list, node);
+
+      if (GTK_CMCTREE_ROW (node)->children)
+        {
+         GList *sub_list;
+
+          sub_list = gtk_cmctree_find_all_by_row_data_custom (ctree,
+                                                           GTK_CMCTREE_ROW
+                                                           (node)->children,
+                                                           data,
+                                                           func);
+          list = g_list_concat (list, sub_list);
+        }
+      node = GTK_CMCTREE_ROW (node)->sibling;
+    }
+  return list;
+}
+
+gboolean
+gtk_cmctree_is_hot_spot (GtkCMCTree *ctree, 
+                      gint      x, 
+                      gint      y)
+{
+  GtkCMCTreeNode *node;
+  gint column;
+  gint row;
+  
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+
+  if (gtk_cmclist_get_selection_info (GTK_CMCLIST (ctree), x, y, &row, &column))
+    if ((node = GTK_CMCTREE_NODE(g_list_nth (GTK_CMCLIST (ctree)->row_list, row))))
+      return ctree_is_hot_spot (ctree, node, row, x, y);
+
+  return FALSE;
+}
+
+
+/***********************************************************
+ *   Tree signals : move, expand, collapse, (un)select     *
+ ***********************************************************/
+
+
+void
+gtk_cmctree_move (GtkCMCTree     *ctree,
+               GtkCMCTreeNode *node,
+               GtkCMCTreeNode *new_parent, 
+               GtkCMCTreeNode *new_sibling)
+{
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+  
+  g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_MOVE], 0, node,
+                  new_parent, new_sibling);
+}
+
+void
+gtk_cmctree_expand (GtkCMCTree     *ctree,
+                 GtkCMCTreeNode *node)
+{
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+  
+  if (GTK_CMCTREE_ROW (node)->is_leaf)
+    return;
+
+  g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_EXPAND], 0, node);
+}
+
+void 
+gtk_cmctree_expand_recursive (GtkCMCTree     *ctree,
+                           GtkCMCTreeNode *node)
+{
+  GtkCMCList *clist;
+  gboolean thaw = FALSE;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (node && GTK_CMCTREE_ROW (node)->is_leaf)
+    return;
+
+  if (CLIST_UNFROZEN (clist) && (!node || gtk_cmctree_is_viewable (ctree, node)))
+    {
+      gtk_cmclist_freeze (clist);
+      thaw = TRUE;
+    }
+
+  gtk_cmctree_post_recursive (ctree, node, GTK_CMCTREE_FUNC (tree_expand), NULL);
+
+  if (thaw)
+    gtk_cmclist_thaw (clist);
+}
+
+void 
+gtk_cmctree_expand_to_depth (GtkCMCTree     *ctree,
+                          GtkCMCTreeNode *node,
+                          gint          depth)
+{
+  GtkCMCList *clist;
+  gboolean thaw = FALSE;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (node && GTK_CMCTREE_ROW (node)->is_leaf)
+    return;
+
+  if (CLIST_UNFROZEN (clist) && (!node || gtk_cmctree_is_viewable (ctree, node)))
+    {
+      gtk_cmclist_freeze (clist);
+      thaw = TRUE;
+    }
+
+  gtk_cmctree_post_recursive_to_depth (ctree, node, depth,
+                                    GTK_CMCTREE_FUNC (tree_expand), NULL);
+
+  if (thaw)
+    gtk_cmclist_thaw (clist);
+}
+
+void
+gtk_cmctree_collapse (GtkCMCTree     *ctree,
+                   GtkCMCTreeNode *node)
+{
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+  
+  if (GTK_CMCTREE_ROW (node)->is_leaf)
+    return;
+
+  g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_COLLAPSE], 0, node);
+}
+
+void 
+gtk_cmctree_collapse_recursive (GtkCMCTree     *ctree,
+                             GtkCMCTreeNode *node)
+{
+  GtkCMCList *clist;
+  gboolean thaw = FALSE;
+  gint i;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  if (node && GTK_CMCTREE_ROW (node)->is_leaf)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (CLIST_UNFROZEN (clist) && (!node || gtk_cmctree_is_viewable (ctree, node)))
+    {
+      gtk_cmclist_freeze (clist);
+      thaw = TRUE;
+    }
+
+  GTK_CMCLIST_SET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+  gtk_cmctree_post_recursive (ctree, node, GTK_CMCTREE_FUNC (tree_collapse), NULL);
+  GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].auto_resize)
+      gtk_cmclist_set_column_width (clist, i,
+                                 gtk_cmclist_optimal_column_width (clist, i));
+
+  if (thaw)
+    gtk_cmclist_thaw (clist);
+}
+
+void 
+gtk_cmctree_collapse_to_depth (GtkCMCTree     *ctree,
+                            GtkCMCTreeNode *node,
+                            gint          depth)
+{
+  GtkCMCList *clist;
+  gboolean thaw = FALSE;
+  gint i;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  if (node && GTK_CMCTREE_ROW (node)->is_leaf)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (CLIST_UNFROZEN (clist) && (!node || gtk_cmctree_is_viewable (ctree, node)))
+    {
+      gtk_cmclist_freeze (clist);
+      thaw = TRUE;
+    }
+
+  GTK_CMCLIST_SET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+  gtk_cmctree_post_recursive_to_depth (ctree, node, depth,
+                                    GTK_CMCTREE_FUNC (tree_collapse_to_depth),
+                                    GINT_TO_POINTER (depth));
+  GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_AUTO_RESIZE_BLOCKED);
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].auto_resize)
+      gtk_cmclist_set_column_width (clist, i,
+                                 gtk_cmclist_optimal_column_width (clist, i));
+
+  if (thaw)
+    gtk_cmclist_thaw (clist);
+}
+
+void
+gtk_cmctree_toggle_expansion (GtkCMCTree     *ctree,
+                           GtkCMCTreeNode *node)
+{
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+  
+  if (GTK_CMCTREE_ROW (node)->is_leaf)
+    return;
+
+  tree_toggle_expansion (ctree, node, NULL);
+}
+
+void 
+gtk_cmctree_toggle_expansion_recursive (GtkCMCTree     *ctree,
+                                     GtkCMCTreeNode *node)
+{
+  GtkCMCList *clist;
+  gboolean thaw = FALSE;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  
+  if (node && GTK_CMCTREE_ROW (node)->is_leaf)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (CLIST_UNFROZEN (clist) && (!node || gtk_cmctree_is_viewable (ctree, node)))
+    {
+      gtk_cmclist_freeze (clist);
+      thaw = TRUE;
+    }
+  
+  gtk_cmctree_post_recursive (ctree, node,
+                           GTK_CMCTREE_FUNC (tree_toggle_expansion), NULL);
+
+  if (thaw)
+    gtk_cmclist_thaw (clist);
+}
+
+void
+gtk_cmctree_select (GtkCMCTree     *ctree, 
+                 GtkCMCTreeNode *node)
+{
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+
+  if (GTK_CMCTREE_ROW (node)->row.selectable)
+    g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_SELECT_ROW], 0,
+                    node, -1);
+}
+
+void
+gtk_cmctree_unselect (GtkCMCTree     *ctree, 
+                   GtkCMCTreeNode *node)
+{
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+
+  g_signal_emit (GTK_OBJECT (ctree), ctree_signals[TREE_UNSELECT_ROW], 0,
+                  node, -1);
+}
+
+void
+gtk_cmctree_select_recursive (GtkCMCTree     *ctree, 
+                           GtkCMCTreeNode *node)
+{
+  gtk_cmctree_real_select_recursive (ctree, node, TRUE);
+}
+
+void
+gtk_cmctree_unselect_recursive (GtkCMCTree     *ctree, 
+                             GtkCMCTreeNode *node)
+{
+  gtk_cmctree_real_select_recursive (ctree, node, FALSE);
+}
+
+void
+gtk_cmctree_real_select_recursive (GtkCMCTree     *ctree, 
+                                GtkCMCTreeNode *node, 
+                                gint          state)
+{
+  GtkCMCList *clist;
+  gboolean thaw = FALSE;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  clist = GTK_CMCLIST (ctree);
+
+  if ((state && 
+       (clist->selection_mode ==  GTK_SELECTION_BROWSE ||
+       clist->selection_mode == GTK_SELECTION_SINGLE)) ||
+      (!state && clist->selection_mode ==  GTK_SELECTION_BROWSE))
+    return;
+
+  if (CLIST_UNFROZEN (clist) && (!node || gtk_cmctree_is_viewable (ctree, node)))
+    {
+      gtk_cmclist_freeze (clist);
+      thaw = TRUE;
+    }
+
+  if (clist->selection_mode == GTK_SELECTION_MULTIPLE)
+    {
+      GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+      
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+    }
+
+  if (state)
+    gtk_cmctree_post_recursive (ctree, node,
+                             GTK_CMCTREE_FUNC (tree_select), NULL);
+  else 
+    gtk_cmctree_post_recursive (ctree, node,
+                             GTK_CMCTREE_FUNC (tree_unselect), NULL);
+  
+  if (thaw)
+    gtk_cmclist_thaw (clist);
+}
+
+
+/***********************************************************
+ *           Analogons of GtkCMCList functions               *
+ ***********************************************************/
+
+
+void 
+gtk_cmctree_node_set_text (GtkCMCTree     *ctree,
+                        GtkCMCTreeNode *node,
+                        gint          column,
+                        const gchar  *text)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+
+  if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+    return;
+  
+  clist = GTK_CMCLIST (ctree);
+
+  GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+    (clist, &(GTK_CMCTREE_ROW (node)->row), column, GTK_CMCELL_TEXT,
+     text, 0, NULL, NULL);
+
+  tree_draw_node (ctree, node);
+}
+
+void 
+gtk_cmctree_node_set_pixmap (GtkCMCTree     *ctree,
+                          GtkCMCTreeNode *node,
+                          gint          column,
+                          GdkPixmap    *pixmap,
+                          GdkBitmap    *mask)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+  g_return_if_fail (pixmap != NULL);
+
+  if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+    return;
+
+  g_object_ref (pixmap);
+  if (mask) 
+    g_object_ref (mask);
+
+  clist = GTK_CMCLIST (ctree);
+
+  GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+    (clist, &(GTK_CMCTREE_ROW (node)->row), column, GTK_CMCELL_PIXMAP,
+     NULL, 0, pixmap, mask);
+
+  tree_draw_node (ctree, node);
+}
+
+void 
+gtk_cmctree_node_set_pixtext (GtkCMCTree     *ctree,
+                           GtkCMCTreeNode *node,
+                           gint          column,
+                           const gchar  *text,
+                           guint8        spacing,
+                           GdkPixmap    *pixmap,
+                           GdkBitmap    *mask)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+  if (column != ctree->tree_column)
+    g_return_if_fail (pixmap != NULL);
+  if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (pixmap)
+    {
+      g_object_ref (pixmap);
+      if (mask) 
+       g_object_ref (mask);
+    }
+
+  GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+    (clist, &(GTK_CMCTREE_ROW (node)->row), column, GTK_CMCELL_PIXTEXT,
+     text, spacing, pixmap, mask);
+
+  tree_draw_node (ctree, node);
+}
+
+void 
+gtk_cmctree_set_node_info (GtkCMCTree     *ctree,
+                        GtkCMCTreeNode *node,
+                        const gchar  *text,
+                        guint8        spacing,
+                        GdkPixmap    *pixmap_closed,
+                        GdkBitmap    *mask_closed,
+                        GdkPixmap    *pixmap_opened,
+                        GdkBitmap    *mask_opened,
+                        gboolean      is_leaf,
+                        gboolean      expanded)
+{
+  gboolean old_leaf;
+  gboolean old_expanded;
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+
+  old_leaf = GTK_CMCTREE_ROW (node)->is_leaf;
+  old_expanded = GTK_CMCTREE_ROW (node)->expanded;
+
+  if (is_leaf && GTK_CMCTREE_ROW (node)->children)
+    {
+      GtkCMCTreeNode *work;
+      GtkCMCTreeNode *ptr;
+      
+      work = GTK_CMCTREE_ROW (node)->children;
+      while (work)
+       {
+         ptr = work;
+         work = GTK_CMCTREE_ROW (work)->sibling;
+         gtk_cmctree_remove_node (ctree, ptr);
+       }
+    }
+
+  set_node_info (ctree, node, text, spacing, pixmap_closed, mask_closed,
+                pixmap_opened, mask_opened, is_leaf, expanded);
+
+  if (!is_leaf && !old_leaf)
+    {
+      GTK_CMCTREE_ROW (node)->expanded = old_expanded;
+      if (expanded && !old_expanded)
+       gtk_cmctree_expand (ctree, node);
+      else if (!expanded && old_expanded)
+       gtk_cmctree_collapse (ctree, node);
+    }
+
+  GTK_CMCTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
+  
+  tree_draw_node (ctree, node);
+}
+
+void
+gtk_cmctree_node_set_shift (GtkCMCTree     *ctree,
+                         GtkCMCTreeNode *node,
+                         gint          column,
+                         gint          vertical,
+                         gint          horizontal)
+{
+  GtkCMCList *clist;
+  GtkRequisition requisition;
+  gboolean visible = FALSE;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+
+  if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (clist->column[column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      visible = gtk_cmctree_is_viewable (ctree, node);
+      if (visible)
+       GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+         (clist, &GTK_CMCTREE_ROW (node)->row, column, &requisition);
+    }
+
+  GTK_CMCTREE_ROW (node)->row.cell[column].vertical   = vertical;
+  GTK_CMCTREE_ROW (node)->row.cell[column].horizontal = horizontal;
+
+  if (visible)
+    column_auto_resize (clist, &GTK_CMCTREE_ROW (node)->row,
+                       column, requisition.width);
+
+  tree_draw_node (ctree, node);
+}
+
+static void
+remove_grab (GtkCMCList *clist)
+{
+  if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))) && 
+      GTK_WIDGET_HAS_GRAB (clist))
+    {
+      gtk_grab_remove (GTK_WIDGET (clist));
+      gdk_display_pointer_ungrab (gtk_widget_get_display (GTK_WIDGET (clist)),
+                                 GDK_CURRENT_TIME);
+    }
+
+  if (clist->htimer)
+    {
+      g_source_remove (clist->htimer);
+      clist->htimer = 0;
+    }
+
+  if (clist->vtimer)
+    {
+      g_source_remove (clist->vtimer);
+      clist->vtimer = 0;
+    }
+}
+
+void
+gtk_cmctree_node_set_selectable (GtkCMCTree     *ctree,
+                              GtkCMCTreeNode *node,
+                              gboolean      selectable)
+{
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+
+  if (selectable == GTK_CMCTREE_ROW (node)->row.selectable)
+    return;
+
+  GTK_CMCTREE_ROW (node)->row.selectable = selectable;
+
+  if (!selectable && GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
+    {
+      GtkCMCList *clist;
+
+      clist = GTK_CMCLIST (ctree);
+
+      if (clist->anchor >= 0 &&
+         clist->selection_mode == GTK_SELECTION_MULTIPLE)
+       {
+         clist->drag_button = 0;
+         remove_grab (clist);
+
+         GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+       }
+      gtk_cmctree_unselect (ctree, node);
+    }      
+}
+
+gboolean
+gtk_cmctree_node_get_selectable (GtkCMCTree     *ctree,
+                              GtkCMCTreeNode *node)
+{
+  g_return_val_if_fail (node != NULL, FALSE);
+
+  return GTK_CMCTREE_ROW (node)->row.selectable;
+}
+
+GtkCMCellType 
+gtk_cmctree_node_get_cell_type (GtkCMCTree     *ctree,
+                             GtkCMCTreeNode *node,
+                             gint          column)
+{
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), -1);
+  g_return_val_if_fail (node != NULL, -1);
+
+  if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+    return -1;
+
+  return GTK_CMCTREE_ROW (node)->row.cell[column].type;
+}
+
+gboolean
+gtk_cmctree_node_get_text (GtkCMCTree      *ctree,
+                        GtkCMCTreeNode  *node,
+                        gint           column,
+                        gchar        **text)
+{
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+  g_return_val_if_fail (node != NULL, FALSE);
+
+  if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+    return FALSE;
+
+  if (GTK_CMCTREE_ROW (node)->row.cell[column].type != GTK_CMCELL_TEXT)
+    return FALSE;
+
+  if (text)
+    *text = GTK_CMCELL_TEXT (GTK_CMCTREE_ROW (node)->row.cell[column])->text;
+
+  return TRUE;
+}
+
+gboolean
+gtk_cmctree_node_get_pixmap (GtkCMCTree     *ctree,
+                          GtkCMCTreeNode *node,
+                          gint          column,
+                          GdkPixmap   **pixmap,
+                          GdkBitmap   **mask)
+{
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+  g_return_val_if_fail (node != NULL, FALSE);
+
+  if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+    return FALSE;
+
+  if (GTK_CMCTREE_ROW (node)->row.cell[column].type != GTK_CMCELL_PIXMAP)
+    return FALSE;
+
+  if (pixmap)
+    *pixmap = GTK_CMCELL_PIXMAP (GTK_CMCTREE_ROW (node)->row.cell[column])->pixmap;
+  if (mask)
+    *mask = GTK_CMCELL_PIXMAP (GTK_CMCTREE_ROW (node)->row.cell[column])->mask;
+
+  return TRUE;
+}
+
+gboolean
+gtk_cmctree_node_get_pixtext (GtkCMCTree      *ctree,
+                           GtkCMCTreeNode  *node,
+                           gint           column,
+                           gchar        **text,
+                           guint8        *spacing,
+                           GdkPixmap    **pixmap,
+                           GdkBitmap    **mask)
+{
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+  g_return_val_if_fail (node != NULL, FALSE);
+  
+  if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+    return FALSE;
+  
+  if (GTK_CMCTREE_ROW (node)->row.cell[column].type != GTK_CMCELL_PIXTEXT)
+    return FALSE;
+  
+  if (text)
+    *text = GTK_CMCELL_PIXTEXT (GTK_CMCTREE_ROW (node)->row.cell[column])->text;
+  if (spacing)
+    *spacing = GTK_CMCELL_PIXTEXT (GTK_CMCTREE_ROW 
+                                (node)->row.cell[column])->spacing;
+  if (pixmap)
+    *pixmap = GTK_CMCELL_PIXTEXT (GTK_CMCTREE_ROW 
+                               (node)->row.cell[column])->pixmap;
+  if (mask)
+    *mask = GTK_CMCELL_PIXTEXT (GTK_CMCTREE_ROW (node)->row.cell[column])->mask;
+  
+  return TRUE;
+}
+
+gboolean
+gtk_cmctree_get_node_info (GtkCMCTree      *ctree,
+                        GtkCMCTreeNode  *node,
+                        gchar        **text,
+                        guint8        *spacing,
+                        GdkPixmap    **pixmap_closed,
+                        GdkBitmap    **mask_closed,
+                        GdkPixmap    **pixmap_opened,
+                        GdkBitmap    **mask_opened,
+                        gboolean      *is_leaf,
+                        gboolean      *expanded)
+{
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+  g_return_val_if_fail (node != NULL, FALSE);
+  
+  if (text)
+    *text = GTK_CMCELL_PIXTEXT 
+      (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->text;
+  if (spacing)
+    *spacing = GTK_CMCELL_PIXTEXT 
+      (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->spacing;
+  if (pixmap_closed)
+    *pixmap_closed = GTK_CMCTREE_ROW (node)->pixmap_closed;
+  if (mask_closed)
+    *mask_closed = GTK_CMCTREE_ROW (node)->mask_closed;
+  if (pixmap_opened)
+    *pixmap_opened = GTK_CMCTREE_ROW (node)->pixmap_opened;
+  if (mask_opened)
+    *mask_opened = GTK_CMCTREE_ROW (node)->mask_opened;
+  if (is_leaf)
+    *is_leaf = GTK_CMCTREE_ROW (node)->is_leaf;
+  if (expanded)
+    *expanded = GTK_CMCTREE_ROW (node)->expanded;
+  
+  return TRUE;
+}
+
+void
+gtk_cmctree_node_set_cell_style (GtkCMCTree     *ctree,
+                              GtkCMCTreeNode *node,
+                              gint          column,
+                              GtkStyle     *style)
+{
+  GtkCMCList *clist;
+  GtkRequisition requisition;
+  gboolean visible = FALSE;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  if (GTK_CMCTREE_ROW (node)->row.cell[column].style == style)
+    return;
+
+  if (clist->column[column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      visible = gtk_cmctree_is_viewable (ctree, node);
+      if (visible)
+       GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+         (clist, &GTK_CMCTREE_ROW (node)->row, column, &requisition);
+    }
+
+  if (GTK_CMCTREE_ROW (node)->row.cell[column].style)
+    {
+      if (GTK_WIDGET_REALIZED (ctree))
+        gtk_style_detach (GTK_CMCTREE_ROW (node)->row.cell[column].style);
+      g_object_unref (GTK_CMCTREE_ROW (node)->row.cell[column].style);
+    }
+
+  GTK_CMCTREE_ROW (node)->row.cell[column].style = style;
+
+  if (GTK_CMCTREE_ROW (node)->row.cell[column].style)
+    {
+      g_object_ref (GTK_CMCTREE_ROW (node)->row.cell[column].style);
+      
+      if (GTK_WIDGET_REALIZED (ctree))
+        GTK_CMCTREE_ROW (node)->row.cell[column].style =
+         gtk_style_attach (GTK_CMCTREE_ROW (node)->row.cell[column].style,
+                           clist->clist_window);
+    }
+
+  if (visible)
+    column_auto_resize (clist, &GTK_CMCTREE_ROW (node)->row, column,
+                       requisition.width);
+
+  tree_draw_node (ctree, node);
+}
+
+GtkStyle *
+gtk_cmctree_node_get_cell_style (GtkCMCTree     *ctree,
+                              GtkCMCTreeNode *node,
+                              gint          column)
+{
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+  g_return_val_if_fail (node != NULL, NULL);
+
+  if (column < 0 || column >= GTK_CMCLIST (ctree)->columns)
+    return NULL;
+
+  return GTK_CMCTREE_ROW (node)->row.cell[column].style;
+}
+
+void
+gtk_cmctree_node_set_row_style (GtkCMCTree     *ctree,
+                             GtkCMCTreeNode *node,
+                             GtkStyle     *style)
+{
+  GtkCMCList *clist;
+  GtkRequisition requisition;
+  gboolean visible;
+  gint *old_width = NULL;
+  gint i;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (GTK_CMCTREE_ROW (node)->row.style == style)
+    return;
+  
+  visible = gtk_cmctree_is_viewable (ctree, node);
+  if (visible && !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      old_width = g_new (gint, clist->columns);
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].auto_resize)
+         {
+           GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+             (clist, &GTK_CMCTREE_ROW (node)->row, i, &requisition);
+           old_width[i] = requisition.width;
+         }
+    }
+
+  if (GTK_CMCTREE_ROW (node)->row.style)
+    {
+      if (GTK_WIDGET_REALIZED (ctree))
+        gtk_style_detach (GTK_CMCTREE_ROW (node)->row.style);
+      g_object_unref (GTK_CMCTREE_ROW (node)->row.style);
+    }
+
+  GTK_CMCTREE_ROW (node)->row.style = style;
+
+  if (GTK_CMCTREE_ROW (node)->row.style)
+    {
+      g_object_ref (GTK_CMCTREE_ROW (node)->row.style);
+      
+      if (GTK_WIDGET_REALIZED (ctree))
+        GTK_CMCTREE_ROW (node)->row.style =
+         gtk_style_attach (GTK_CMCTREE_ROW (node)->row.style,
+                           clist->clist_window);
+    }
+
+  if (visible && !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].auto_resize)
+         column_auto_resize (clist, &GTK_CMCTREE_ROW (node)->row, i,
+                             old_width[i]);
+      g_free (old_width);
+    }
+  tree_draw_node (ctree, node);
+}
+
+GtkStyle *
+gtk_cmctree_node_get_row_style (GtkCMCTree     *ctree,
+                             GtkCMCTreeNode *node)
+{
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+  g_return_val_if_fail (node != NULL, NULL);
+
+  return GTK_CMCTREE_ROW (node)->row.style;
+}
+
+void
+gtk_cmctree_node_set_foreground (GtkCMCTree       *ctree,
+                              GtkCMCTreeNode   *node,
+                              const GdkColor *color)
+{
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+
+  if (color)
+    {
+      GTK_CMCTREE_ROW (node)->row.foreground = *color;
+      GTK_CMCTREE_ROW (node)->row.fg_set = TRUE;
+      if (GTK_WIDGET_REALIZED (ctree))
+       gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (ctree)),
+                        &GTK_CMCTREE_ROW (node)->row.foreground, TRUE, TRUE);
+    }
+  else
+    GTK_CMCTREE_ROW (node)->row.fg_set = FALSE;
+
+  tree_draw_node (ctree, node);
+}
+
+void
+gtk_cmctree_node_set_background (GtkCMCTree       *ctree,
+                              GtkCMCTreeNode   *node,
+                              const GdkColor *color)
+{
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+
+  if (color)
+    {
+      GTK_CMCTREE_ROW (node)->row.background = *color;
+      GTK_CMCTREE_ROW (node)->row.bg_set = TRUE;
+      if (GTK_WIDGET_REALIZED (ctree))
+       gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (ctree)),
+                        &GTK_CMCTREE_ROW (node)->row.background, TRUE, TRUE);
+    }
+  else
+    GTK_CMCTREE_ROW (node)->row.bg_set = FALSE;
+
+  tree_draw_node (ctree, node);
+}
+
+void
+gtk_cmctree_node_set_row_data (GtkCMCTree     *ctree,
+                            GtkCMCTreeNode *node,
+                            gpointer      data)
+{
+  gtk_cmctree_node_set_row_data_full (ctree, node, data, NULL);
+}
+
+void
+gtk_cmctree_node_set_row_data_full (GtkCMCTree         *ctree,
+                                 GtkCMCTreeNode     *node,
+                                 gpointer          data,
+                                 GtkDestroyNotify  destroy)
+{
+  GtkDestroyNotify dnotify;
+  gpointer ddata;
+  
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (node != NULL);
+
+  dnotify = GTK_CMCTREE_ROW (node)->row.destroy;
+  ddata = GTK_CMCTREE_ROW (node)->row.data;
+  
+  GTK_CMCTREE_ROW (node)->row.data = data;
+  GTK_CMCTREE_ROW (node)->row.destroy = destroy;
+
+  if (dnotify)
+    dnotify (ddata);
+}
+
+gpointer
+gtk_cmctree_node_get_row_data (GtkCMCTree     *ctree,
+                            GtkCMCTreeNode *node)
+{
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
+
+  return node ? GTK_CMCTREE_ROW (node)->row.data : NULL;
+}
+
+void
+gtk_cmctree_node_moveto (GtkCMCTree     *ctree,
+                      GtkCMCTreeNode *node,
+                      gint          column,
+                      gfloat        row_align,
+                      gfloat        col_align)
+{
+  gint row = -1;
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  clist = GTK_CMCLIST (ctree);
+
+  while (node && !gtk_cmctree_is_viewable (ctree, node))
+    node = GTK_CMCTREE_ROW (node)->parent;
+
+  if (node)
+    row = g_list_position (clist->row_list, (GList *)node);
+  
+  gtk_cmclist_moveto (clist, row, column, row_align, col_align);
+}
+
+GtkVisibility 
+gtk_cmctree_node_is_visible (GtkCMCTree     *ctree,
+                           GtkCMCTreeNode *node)
+{
+  gint row;
+  
+  g_return_val_if_fail (ctree != NULL, 0);
+  g_return_val_if_fail (node != NULL, 0);
+  
+  row = g_list_position (GTK_CMCLIST (ctree)->row_list, (GList*) node);
+  return gtk_cmclist_row_is_visible (GTK_CMCLIST (ctree), row);
+}
+
+
+/***********************************************************
+ *             GtkCMCTree specific functions                 *
+ ***********************************************************/
+
+void
+gtk_cmctree_set_indent (GtkCMCTree *ctree, 
+                      gint      indent)
+{
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (indent >= 0);
+
+  if (indent == ctree->tree_indent)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+  ctree->tree_indent = indent;
+
+  if (clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    gtk_cmclist_set_column_width
+      (clist, ctree->tree_column,
+       gtk_cmclist_optimal_column_width (clist, ctree->tree_column));
+  else
+    CLIST_REFRESH (ctree);
+}
+
+void
+gtk_cmctree_set_spacing (GtkCMCTree *ctree, 
+                      gint      spacing)
+{
+  GtkCMCList *clist;
+  gint old_spacing;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+  g_return_if_fail (spacing >= 0);
+
+  if (spacing == ctree->tree_spacing)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+
+  old_spacing = ctree->tree_spacing;
+  ctree->tree_spacing = spacing;
+
+  if (clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    gtk_cmclist_set_column_width (clist, ctree->tree_column,
+                               clist->column[ctree->tree_column].width +
+                               spacing - old_spacing);
+  else
+    CLIST_REFRESH (ctree);
+}
+
+void
+gtk_cmctree_set_show_stub (GtkCMCTree *ctree, 
+                        gboolean  show_stub)
+{
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  show_stub = show_stub != FALSE;
+
+  if (show_stub != ctree->show_stub)
+    {
+      GtkCMCList *clist;
+
+      clist = GTK_CMCLIST (ctree);
+      ctree->show_stub = show_stub;
+
+      if (CLIST_UNFROZEN (clist) && clist->rows &&
+         gtk_cmclist_row_is_visible (clist, 0) != GTK_VISIBILITY_NONE)
+       GTK_CMCLIST_GET_CLASS (clist)->draw_row
+         (clist, NULL, 0, GTK_CMCLIST_ROW (clist->row_list));
+    }
+}
+
+void 
+gtk_cmctree_set_line_style (GtkCMCTree          *ctree, 
+                         GtkCMCTreeLineStyle  line_style)
+{
+  GtkCMCList *clist;
+  GtkCMCTreeLineStyle old_style;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  if (line_style == ctree->line_style)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+
+  old_style = ctree->line_style;
+  ctree->line_style = line_style;
+
+  if (clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      if (old_style == GTK_CMCTREE_LINES_TABBED)
+       gtk_cmclist_set_column_width
+         (clist, ctree->tree_column,
+          clist->column[ctree->tree_column].width - 3);
+      else if (line_style == GTK_CMCTREE_LINES_TABBED)
+       gtk_cmclist_set_column_width
+         (clist, ctree->tree_column,
+          clist->column[ctree->tree_column].width + 3);
+    }
+
+  if (GTK_WIDGET_REALIZED (ctree))
+    {
+      switch (line_style)
+       {
+       case GTK_CMCTREE_LINES_SOLID:
+         if (GTK_WIDGET_REALIZED (ctree))
+           gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID, 
+                                       GDK_CAP_BUTT, GDK_JOIN_MITER);
+         break;
+       case GTK_CMCTREE_LINES_DOTTED:
+         if (GTK_WIDGET_REALIZED (ctree))
+           gdk_gc_set_line_attributes (ctree->lines_gc, 1, 
+                                       GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_MITER);
+         gdk_gc_set_dashes (ctree->lines_gc, 0, "\1\1", 2);
+         break;
+       case GTK_CMCTREE_LINES_TABBED:
+         if (GTK_WIDGET_REALIZED (ctree))
+           gdk_gc_set_line_attributes (ctree->lines_gc, 1, GDK_LINE_SOLID, 
+                                       GDK_CAP_BUTT, GDK_JOIN_MITER);
+         break;
+       case GTK_CMCTREE_LINES_NONE:
+         break;
+       default:
+         return;
+       }
+      CLIST_REFRESH (ctree);
+    }
+}
+
+void 
+gtk_cmctree_set_expander_style (GtkCMCTree              *ctree, 
+                             GtkCMCTreeExpanderStyle  expander_style)
+{
+  GtkCMCList *clist;
+  GtkCMCTreeExpanderStyle old_style;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  if (expander_style == ctree->expander_style)
+    return;
+
+  clist = GTK_CMCLIST (ctree);
+
+  old_style = ctree->expander_style;
+  ctree->expander_style = expander_style;
+
+  if (clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      gint new_width;
+
+      new_width = clist->column[ctree->tree_column].width;
+      switch (old_style)
+       {
+       case GTK_CMCTREE_EXPANDER_NONE:
+         break;
+       case GTK_CMCTREE_EXPANDER_TRIANGLE:
+         new_width -= PM_SIZE + 3;
+         break;
+       case GTK_CMCTREE_EXPANDER_SQUARE:
+       case GTK_CMCTREE_EXPANDER_CIRCULAR:
+         new_width -= PM_SIZE + 1;
+         break;
+       }
+
+      switch (expander_style)
+       {
+       case GTK_CMCTREE_EXPANDER_NONE:
+         break;
+       case GTK_CMCTREE_EXPANDER_TRIANGLE:
+         new_width += PM_SIZE + 3;
+         break;
+       case GTK_CMCTREE_EXPANDER_SQUARE:
+       case GTK_CMCTREE_EXPANDER_CIRCULAR:
+         new_width += PM_SIZE + 1;
+         break;
+       }
+
+      gtk_cmclist_set_column_width (clist, ctree->tree_column, new_width);
+    }
+
+  if (GTK_WIDGET_DRAWABLE (clist))
+    CLIST_REFRESH (clist);
+}
+
+
+/***********************************************************
+ *             Tree sorting functions                      *
+ ***********************************************************/
+
+
+static void
+tree_sort (GtkCMCTree     *ctree,
+          GtkCMCTreeNode *node,
+          gpointer      data)
+{
+  GtkCMCTreeNode *list_start;
+  GtkCMCTreeNode *cmp;
+  GtkCMCTreeNode *work;
+  GtkCMCList *clist;
+
+  clist = GTK_CMCLIST (ctree);
+
+  if (node)
+    list_start = GTK_CMCTREE_ROW (node)->children;
+  else
+    list_start = GTK_CMCTREE_NODE (clist->row_list);
+
+  while (list_start)
+    {
+      cmp = list_start;
+      work = GTK_CMCTREE_ROW (cmp)->sibling;
+      while (work)
+       {
+         if (clist->sort_type == GTK_SORT_ASCENDING)
+           {
+             if (clist->compare 
+                 (clist, GTK_CMCTREE_ROW (work), GTK_CMCTREE_ROW (cmp)) < 0)
+               cmp = work;
+           }
+         else
+           {
+             if (clist->compare 
+                 (clist, GTK_CMCTREE_ROW (work), GTK_CMCTREE_ROW (cmp)) > 0)
+               cmp = work;
+           }
+         work = GTK_CMCTREE_ROW (work)->sibling;
+       }
+      if (cmp == list_start)
+       list_start = GTK_CMCTREE_ROW (cmp)->sibling;
+      else
+       {
+         gtk_cmctree_unlink (ctree, cmp, FALSE);
+         gtk_cmctree_link (ctree, cmp, node, list_start, FALSE);
+       }
+    }
+}
+
+void
+gtk_cmctree_sort_recursive (GtkCMCTree     *ctree, 
+                         GtkCMCTreeNode *node)
+{
+  GtkCMCList *clist;
+  GtkCMCTreeNode *focus_node = NULL;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  clist = GTK_CMCLIST (ctree);
+
+  gtk_cmclist_freeze (clist);
+
+  if (clist->selection_mode == GTK_SELECTION_MULTIPLE)
+    {
+      GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+      
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+    }
+
+  if (!node || (node && gtk_cmctree_is_viewable (ctree, node)))
+    focus_node =
+      GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
+      
+  gtk_cmctree_post_recursive (ctree, node, GTK_CMCTREE_FUNC (tree_sort), NULL);
+
+  if (!node)
+    tree_sort (ctree, NULL, NULL);
+
+  if (focus_node)
+    {
+      clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
+      clist->undo_anchor = clist->focus_row;
+    }
+
+  gtk_cmclist_thaw (clist);
+}
+
+static void
+real_sort_list (GtkCMCList *clist)
+{
+  gtk_cmctree_sort_recursive (GTK_CMCTREE (clist), NULL);
+}
+
+void
+gtk_cmctree_sort_node (GtkCMCTree     *ctree, 
+                    GtkCMCTreeNode *node)
+{
+  GtkCMCList *clist;
+  GtkCMCTreeNode *focus_node = NULL;
+
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  clist = GTK_CMCLIST (ctree);
+
+  gtk_cmclist_freeze (clist);
+
+  if (clist->selection_mode == GTK_SELECTION_MULTIPLE)
+    {
+      GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+      
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+    }
+
+  if (!node || (node && gtk_cmctree_is_viewable (ctree, node)))
+    focus_node = GTK_CMCTREE_NODE
+      (g_list_nth (clist->row_list, clist->focus_row));
+
+  tree_sort (ctree, node, NULL);
+
+  if (focus_node)
+    {
+      clist->focus_row = g_list_position (clist->row_list,(GList *)focus_node);
+      clist->undo_anchor = clist->focus_row;
+    }
+
+  gtk_cmclist_thaw (clist);
+}
+
+/************************************************************************/
+
+static void
+fake_unselect_all (GtkCMCList *clist,
+                  gint      row)
+{
+  GList *list;
+  GList *focus_node = NULL;
+
+  if (row >= 0 && (focus_node = g_list_nth (clist->row_list, row)))
+    {
+      if (GTK_CMCTREE_ROW (focus_node)->row.state == GTK_STATE_NORMAL &&
+         GTK_CMCTREE_ROW (focus_node)->row.selectable)
+       {
+         GTK_CMCTREE_ROW (focus_node)->row.state = GTK_STATE_SELECTED;
+         
+         if (CLIST_UNFROZEN (clist) &&
+             gtk_cmclist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+           GTK_CMCLIST_GET_CLASS (clist)->draw_row (clist, NULL, row,
+                                                 GTK_CMCLIST_ROW (focus_node));
+       }  
+    }
+
+  clist->undo_selection = clist->selection;
+  clist->selection = NULL;
+  clist->selection_end = NULL;
+  
+  for (list = clist->undo_selection; list; list = list->next)
+    {
+      if (list->data == focus_node)
+       continue;
+
+      GTK_CMCTREE_ROW ((GList *)(list->data))->row.state = GTK_STATE_NORMAL;
+      tree_draw_node (GTK_CMCTREE (clist), GTK_CMCTREE_NODE (list->data));
+    }
+}
+
+static GList *
+selection_find (GtkCMCList *clist,
+               gint      row_number,
+               GList    *row_list_element)
+{
+  return g_list_find (clist->selection, row_list_element);
+}
+
+static void
+resync_selection (GtkCMCList *clist, GdkEvent *event)
+{
+  GtkCMCTree *ctree;
+  GList *list;
+  GtkCMCTreeNode *node;
+  gint i;
+  gint e;
+  gint row;
+  gboolean unselect;
+
+  g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+  if (clist->selection_mode != GTK_SELECTION_MULTIPLE)
+    return;
+
+  if (clist->anchor < 0 || clist->drag_pos < 0)
+    return;
+
+  ctree = GTK_CMCTREE (clist);
+  
+  clist->freeze_count++;
+
+  i = MIN (clist->anchor, clist->drag_pos);
+  e = MAX (clist->anchor, clist->drag_pos);
+
+  if (clist->undo_selection)
+    {
+      list = clist->selection;
+      clist->selection = clist->undo_selection;
+      clist->selection_end = g_list_last (clist->selection);
+      clist->undo_selection = list;
+      list = clist->selection;
+
+      while (list)
+       {
+         node = list->data;
+         list = list->next;
+         
+         unselect = TRUE;
+
+         if (gtk_cmctree_is_viewable (ctree, node))
+           {
+             row = g_list_position (clist->row_list, (GList *)node);
+             if (row >= i && row <= e)
+               unselect = FALSE;
+           }
+         if (unselect && GTK_CMCTREE_ROW (node)->row.selectable)
+           {
+             GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
+             gtk_cmctree_unselect (ctree, node);
+             clist->undo_selection = g_list_prepend (clist->undo_selection,
+                                                     node);
+           }
+       }
+    }    
+
+  if (clist->anchor < clist->drag_pos)
+    {
+      for (node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, i)); i <= e;
+          i++, node = GTK_CMCTREE_NODE_NEXT (node))
+       if (GTK_CMCTREE_ROW (node)->row.selectable)
+         {
+           if (g_list_find (clist->selection, node))
+             {
+               if (GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
+                 {
+                   GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
+                   gtk_cmctree_unselect (ctree, node);
+                   clist->undo_selection =
+                     g_list_prepend (clist->undo_selection, node);
+                 }
+             }
+           else if (GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
+             {
+               GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
+               clist->undo_unselection =
+                 g_list_prepend (clist->undo_unselection, node);
+             }
+         }
+    }
+  else
+    {
+      for (node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, e)); i <= e;
+          e--, node = GTK_CMCTREE_NODE_PREV (node))
+       if (GTK_CMCTREE_ROW (node)->row.selectable)
+         {
+           if (g_list_find (clist->selection, node))
+             {
+               if (GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_NORMAL)
+                 {
+                   GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_SELECTED;
+                   gtk_cmctree_unselect (ctree, node);
+                   clist->undo_selection =
+                     g_list_prepend (clist->undo_selection, node);
+                 }
+             }
+           else if (GTK_CMCTREE_ROW (node)->row.state == GTK_STATE_SELECTED)
+             {
+               GTK_CMCTREE_ROW (node)->row.state = GTK_STATE_NORMAL;
+               clist->undo_unselection =
+                 g_list_prepend (clist->undo_unselection, node);
+             }
+         }
+    }
+
+  clist->undo_unselection = g_list_reverse (clist->undo_unselection);
+  for (list = clist->undo_unselection; list; list = list->next)
+    gtk_cmctree_select (ctree, list->data);
+
+  clist->anchor = -1;
+  clist->drag_pos = -1;
+
+  if (!CLIST_UNFROZEN (clist))
+    clist->freeze_count--;
+}
+
+static void
+real_undo_selection (GtkCMCList *clist)
+{
+  GtkCMCTree *ctree;
+  GList *work;
+
+  g_return_if_fail (GTK_IS_CMCTREE (clist));
+
+  if (clist->selection_mode != GTK_SELECTION_MULTIPLE)
+    return;
+
+  if (!(clist->undo_selection || clist->undo_unselection))
+    {
+      gtk_cmclist_unselect_all (clist);
+      return;
+    }
+
+  ctree = GTK_CMCTREE (clist);
+
+  for (work = clist->undo_selection; work; work = work->next)
+    if (GTK_CMCTREE_ROW (work->data)->row.selectable)
+      gtk_cmctree_select (ctree, GTK_CMCTREE_NODE (work->data));
+
+  for (work = clist->undo_unselection; work; work = work->next)
+    if (GTK_CMCTREE_ROW (work->data)->row.selectable)
+      gtk_cmctree_unselect (ctree, GTK_CMCTREE_NODE (work->data));
+
+  if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
+    {
+      clist->focus_row = clist->undo_anchor;
+      gtk_widget_queue_draw (GTK_WIDGET (clist));
+    }
+  else
+    clist->focus_row = clist->undo_anchor;
+  
+  clist->undo_anchor = -1;
+  g_list_free (clist->undo_selection);
+  g_list_free (clist->undo_unselection);
+  clist->undo_selection = NULL;
+  clist->undo_unselection = NULL;
+
+  if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
+      clist->clist_window_height)
+    gtk_cmclist_moveto (clist, clist->focus_row, -1, 1, 0);
+  else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+    gtk_cmclist_moveto (clist, clist->focus_row, -1, 0, 0);
+
+}
+
+void
+gtk_cmctree_set_drag_compare_func (GtkCMCTree                *ctree,
+                                GtkCMCTreeCompareDragFunc  cmp_func)
+{
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
+
+  ctree->drag_compare = cmp_func;
+}
+
+static gboolean
+check_drag (GtkCMCTree        *ctree,
+           GtkCMCTreeNode    *drag_source,
+           GtkCMCTreeNode    *drag_target,
+           GtkCMCListDragPos  insert_pos)
+{
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), FALSE);
+
+  if (drag_source && drag_source != drag_target &&
+      (!GTK_CMCTREE_ROW (drag_source)->children ||
+       !gtk_cmctree_is_ancestor (ctree, drag_source, drag_target)))
+    {
+      switch (insert_pos)
+       {
+       case GTK_CMCLIST_DRAG_NONE:
+         return FALSE;
+       case GTK_CMCLIST_DRAG_AFTER:
+         if (GTK_CMCTREE_ROW (drag_target)->sibling != drag_source)
+           return (!ctree->drag_compare ||
+                   ctree->drag_compare (ctree,
+                                        drag_source,
+                                        GTK_CMCTREE_ROW (drag_target)->parent,
+                                        GTK_CMCTREE_ROW (drag_target)->sibling));
+         break;
+       case GTK_CMCLIST_DRAG_BEFORE:
+         if (GTK_CMCTREE_ROW (drag_source)->sibling != drag_target)
+           return (!ctree->drag_compare ||
+                   ctree->drag_compare (ctree,
+                                        drag_source,
+                                        GTK_CMCTREE_ROW (drag_target)->parent,
+                                        drag_target));
+         break;
+       case GTK_CMCLIST_DRAG_INTO:
+         if (!GTK_CMCTREE_ROW (drag_target)->is_leaf &&
+             GTK_CMCTREE_ROW (drag_target)->children != drag_source)
+           return (!ctree->drag_compare ||
+                   ctree->drag_compare (ctree,
+                                        drag_source,
+                                        drag_target,
+                                        GTK_CMCTREE_ROW (drag_target)->children));
+         break;
+       }
+    }
+  return FALSE;
+}
+
+
+
+/************************************/
+static void
+drag_dest_info_destroy (gpointer data)
+{
+  GtkCMCListDestInfo *info = data;
+
+  g_free (info);
+}
+
+static void
+drag_dest_cell (GtkCMCList         *clist,
+               gint              x,
+               gint              y,
+               GtkCMCListDestInfo *dest_info)
+{
+  GtkWidget *widget;
+
+  widget = GTK_WIDGET (clist);
+
+  dest_info->insert_pos = GTK_CMCLIST_DRAG_NONE;
+
+  y -= (GTK_CONTAINER (widget)->border_width +
+       widget->style->ythickness + clist->column_title_area.height);
+  dest_info->cell.row = ROW_FROM_YPIXEL (clist, y);
+
+  if (dest_info->cell.row >= clist->rows)
+    {
+      dest_info->cell.row = clist->rows - 1;
+      y = ROW_TOP_YPIXEL (clist, dest_info->cell.row) + clist->row_height;
+    }
+  if (dest_info->cell.row < -1)
+    dest_info->cell.row = -1;
+  
+  x -= GTK_CONTAINER (widget)->border_width + widget->style->xthickness;
+
+  dest_info->cell.column = COLUMN_FROM_XPIXEL (clist, x);
+
+  if (dest_info->cell.row >= 0)
+    {
+      gint y_delta;
+      gint h = 0;
+
+      y_delta = y - ROW_TOP_YPIXEL (clist, dest_info->cell.row);
+      
+      if (GTK_CMCLIST_DRAW_DRAG_RECT(clist) &&
+         !GTK_CMCTREE_ROW (g_list_nth (clist->row_list,
+                                     dest_info->cell.row))->is_leaf)
+       {
+         dest_info->insert_pos = GTK_CMCLIST_DRAG_INTO;
+         h = clist->row_height / 4;
+       }
+      else if (GTK_CMCLIST_DRAW_DRAG_LINE(clist))
+       {
+         dest_info->insert_pos = GTK_CMCLIST_DRAG_BEFORE;
+         h = clist->row_height / 2;
+       }
+
+      if (GTK_CMCLIST_DRAW_DRAG_LINE(clist))
+       {
+         if (y_delta < h)
+           dest_info->insert_pos = GTK_CMCLIST_DRAG_BEFORE;
+         else if (clist->row_height - y_delta < h)
+           dest_info->insert_pos = GTK_CMCLIST_DRAG_AFTER;
+       }
+    }
+}
+
+static void
+gtk_cmctree_drag_begin (GtkWidget           *widget,
+                     GdkDragContext *context)
+{
+  GtkCMCList *clist;
+  GtkCMCTree *ctree;
+  gboolean use_icons;
+
+  g_return_if_fail (GTK_IS_CMCTREE (widget));
+  g_return_if_fail (context != NULL);
+
+  clist = GTK_CMCLIST (widget);
+  ctree = GTK_CMCTREE (widget);
+
+  use_icons = GTK_CMCLIST_USE_DRAG_ICONS (clist);
+  GTK_CMCLIST_UNSET_FLAG (clist, CMCLIST_USE_DRAG_ICONS);
+  GTK_WIDGET_CLASS (parent_class)->drag_begin (widget, context);
+
+  if (use_icons)
+    {
+      GtkCMCTreeNode *node;
+
+      GTK_CMCLIST_SET_FLAG (clist, CMCLIST_USE_DRAG_ICONS);
+      node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list,
+                                        clist->click_cell.row));
+      if (node)
+       {
+         if (GTK_CMCELL_PIXTEXT
+             (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
+           {
+             gtk_drag_set_icon_pixmap
+               (context,
+                gtk_widget_get_colormap (widget),
+                GTK_CMCELL_PIXTEXT
+                (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap,
+                GTK_CMCELL_PIXTEXT
+                (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask,
+                -2, -2);
+             return;
+           }
+       }
+      gtk_drag_set_icon_default (context);
+    }
+}
+
+static gint
+gtk_cmctree_drag_motion (GtkWidget      *widget,
+                      GdkDragContext *context,
+                      gint            x,
+                      gint            y,
+                      guint           time)
+{
+  GtkCMCList *clist;
+  GtkCMCTree *ctree;
+  GtkCMCListDestInfo new_info;
+  GtkCMCListDestInfo *dest_info;
+
+  g_return_val_if_fail (GTK_IS_CMCTREE (widget), FALSE);
+
+  clist = GTK_CMCLIST (widget);
+  ctree = GTK_CMCTREE (widget);
+
+  dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
+
+  if (!dest_info)
+    {
+      dest_info = g_new (GtkCMCListDestInfo, 1);
+         
+      dest_info->cell.row    = -1;
+      dest_info->cell.column = -1;
+      dest_info->insert_pos  = GTK_CMCLIST_DRAG_NONE;
+
+      g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info,
+                              drag_dest_info_destroy);
+    }
+
+  drag_dest_cell (clist, x, y, &new_info);
+
+  if (GTK_CMCLIST_REORDERABLE (clist))
+    {
+      GList *list;
+      GdkAtom atom = gdk_atom_intern_static_string ("gtk-clist-drag-reorder");
+
+      list = context->targets;
+      while (list)
+       {
+         if (atom == GDK_POINTER_TO_ATOM (list->data))
+           break;
+         list = list->next;
+       }
+
+      if (list)
+       {
+         GtkCMCTreeNode *drag_source;
+         GtkCMCTreeNode *drag_target;
+
+         drag_source = GTK_CMCTREE_NODE (g_list_nth (clist->row_list,
+                                                   clist->click_cell.row));
+         drag_target = GTK_CMCTREE_NODE (g_list_nth (clist->row_list,
+                                                   new_info.cell.row));
+
+         if (gtk_drag_get_source_widget (context) != widget ||
+             !check_drag (ctree, drag_source, drag_target,
+                          new_info.insert_pos))
+           {
+             if (dest_info->cell.row < 0)
+               {
+                 gdk_drag_status (context, GDK_ACTION_DEFAULT, time);
+                 return FALSE;
+               }
+             return TRUE;
+           }
+
+         if (new_info.cell.row != dest_info->cell.row ||
+             (new_info.cell.row == dest_info->cell.row &&
+              dest_info->insert_pos != new_info.insert_pos))
+           {
+             if (dest_info->cell.row >= 0)
+               GTK_CMCLIST_GET_CLASS (clist)->draw_drag_highlight
+                 (clist,
+                  g_list_nth (clist->row_list, dest_info->cell.row)->data,
+                  dest_info->cell.row, dest_info->insert_pos);
+
+             dest_info->insert_pos  = new_info.insert_pos;
+             dest_info->cell.row    = new_info.cell.row;
+             dest_info->cell.column = new_info.cell.column;
+
+             GTK_CMCLIST_GET_CLASS (clist)->draw_drag_highlight
+               (clist,
+                g_list_nth (clist->row_list, dest_info->cell.row)->data,
+                dest_info->cell.row, dest_info->insert_pos);
+
+             clist->drag_highlight_row = dest_info->cell.row;
+             clist->drag_highlight_pos = dest_info->insert_pos;
+
+             gdk_drag_status (context, context->suggested_action, time);
+           }
+         return TRUE;
+       }
+    }
+
+  dest_info->insert_pos  = new_info.insert_pos;
+  dest_info->cell.row    = new_info.cell.row;
+  dest_info->cell.column = new_info.cell.column;
+  return TRUE;
+}
+
+static void
+gtk_cmctree_drag_data_received (GtkWidget        *widget,
+                             GdkDragContext   *context,
+                             gint              x,
+                             gint              y,
+                             GtkSelectionData *selection_data,
+                             guint             info,
+                             guint32           time)
+{
+  GtkCMCTree *ctree;
+  GtkCMCList *clist;
+
+  g_return_if_fail (GTK_IS_CMCTREE (widget));
+  g_return_if_fail (context != NULL);
+  g_return_if_fail (selection_data != NULL);
+
+  ctree = GTK_CMCTREE (widget);
+  clist = GTK_CMCLIST (widget);
+
+  if (GTK_CMCLIST_REORDERABLE (clist) &&
+      gtk_drag_get_source_widget (context) == widget &&
+      selection_data->target ==
+      gdk_atom_intern_static_string ("gtk-clist-drag-reorder") &&
+      selection_data->format == 8 &&
+      selection_data->length == sizeof (GtkCMCListCellInfo))
+    {
+      GtkCMCListCellInfo *source_info;
+
+      source_info = (GtkCMCListCellInfo *)(selection_data->data);
+      if (source_info)
+       {
+         GtkCMCListDestInfo dest_info;
+         GtkCMCTreeNode *source_node;
+         GtkCMCTreeNode *dest_node;
+
+         drag_dest_cell (clist, x, y, &dest_info);
+         
+         source_node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list,
+                                                   source_info->row));
+         dest_node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list,
+                                                 dest_info.cell.row));
+
+         if (!source_node || !dest_node)
+           return;
+
+         switch (dest_info.insert_pos)
+           {
+           case GTK_CMCLIST_DRAG_NONE:
+             break;
+           case GTK_CMCLIST_DRAG_INTO:
+             if (check_drag (ctree, source_node, dest_node,
+                             dest_info.insert_pos))
+               gtk_cmctree_move (ctree, source_node, dest_node,
+                               GTK_CMCTREE_ROW (dest_node)->children);
+             g_dataset_remove_data (context, "gtk-clist-drag-dest");
+             break;
+           case GTK_CMCLIST_DRAG_BEFORE:
+             if (check_drag (ctree, source_node, dest_node,
+                             dest_info.insert_pos))
+               gtk_cmctree_move (ctree, source_node,
+                               GTK_CMCTREE_ROW (dest_node)->parent, dest_node);
+             g_dataset_remove_data (context, "gtk-clist-drag-dest");
+             break;
+           case GTK_CMCLIST_DRAG_AFTER:
+             if (check_drag (ctree, source_node, dest_node,
+                             dest_info.insert_pos))
+               gtk_cmctree_move (ctree, source_node,
+                               GTK_CMCTREE_ROW (dest_node)->parent, 
+                               GTK_CMCTREE_ROW (dest_node)->sibling);
+             g_dataset_remove_data (context, "gtk-clist-drag-dest");
+             break;
+           }
+       }
+    }
+}
+
+GType
+gtk_cmctree_node_get_type (void)
+{
+  static GType our_type = 0;
+  
+  if (our_type == 0)
+    our_type = g_pointer_type_register_static ("GtkCMCTreeNode");
+
+  return our_type;
+}
diff --git a/src/gtk/gtkcmctree.h b/src/gtk/gtkcmctree.h
new file mode 100644 (file)
index 0000000..9f4a21a
--- /dev/null
@@ -0,0 +1,450 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald
+ * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>
+ *
+ * GtkCMCTree widget for GTK+
+ * Copyright (C) 1998 Lars Hamann and Stefan Jeske
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GTK_CMCTREE_H__
+#define __GTK_CMCTREE_H__
+
+#include "gtkcmclist.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CMCTREE            (gtk_cmctree_get_type ())
+#define GTK_CMCTREE(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_CMCTREE, GtkCMCTree))
+#define GTK_CMCTREE_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CMCTREE, GtkCMCTreeClass))
+#define GTK_IS_CMCTREE(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_CMCTREE))
+#define GTK_IS_CMCTREE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CMCTREE))
+#define GTK_CMCTREE_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_CMCTREE, GtkCMCTreeClass))
+
+#define GTK_CMCTREE_ROW(_node_) ((GtkCMCTreeRow *)(((GList *)(_node_))->data))
+#define GTK_CMCTREE_NODE(_node_) ((GtkCMCTreeNode *)((_node_)))
+#define GTK_CMCTREE_NODE_NEXT(_nnode_) ((GtkCMCTreeNode *)(((GList *)(_nnode_))->next))
+#define GTK_CMCTREE_NODE_PREV(_pnode_) ((GtkCMCTreeNode *)(((GList *)(_pnode_))->prev))
+#define GTK_CMCTREE_FUNC(_func_) ((GtkCMCTreeFunc)(_func_))
+
+#define GTK_TYPE_CMCTREE_NODE (gtk_cmctree_node_get_type ())
+
+GType gtk_cmctree_pos_get_type (void) G_GNUC_CONST;
+#define GTK_TYPE_CMCTREE_POS (gtk_cmctree_pos_get_type())
+GType gtk_cmctree_line_style_get_type (void) G_GNUC_CONST;
+#define GTK_TYPE_CMCTREE_LINE_STYLE (gtk_cmctree_line_style_get_type())
+GType gtk_cmctree_expander_style_get_type (void) G_GNUC_CONST;
+#define GTK_TYPE_CMCTREE_EXPANDER_STYLE (gtk_cmctree_expander_style_get_type())
+GType gtk_cmctree_expansion_type_get_type (void) G_GNUC_CONST;
+#define GTK_TYPE_CMCTREE_EXPANSION_TYPE (gtk_cmctree_expansion_type_get_type())
+
+typedef enum
+{
+  GTK_CMCTREE_POS_BEFORE,
+  GTK_CMCTREE_POS_AS_CHILD,
+  GTK_CMCTREE_POS_AFTER
+} GtkCMCTreePos;
+
+typedef enum
+{
+  GTK_CMCTREE_LINES_NONE,
+  GTK_CMCTREE_LINES_SOLID,
+  GTK_CMCTREE_LINES_DOTTED,
+  GTK_CMCTREE_LINES_TABBED
+} GtkCMCTreeLineStyle;
+
+typedef enum
+{
+  GTK_CMCTREE_EXPANDER_NONE,
+  GTK_CMCTREE_EXPANDER_SQUARE,
+  GTK_CMCTREE_EXPANDER_TRIANGLE,
+  GTK_CMCTREE_EXPANDER_CIRCULAR
+} GtkCMCTreeExpanderStyle;
+
+typedef enum
+{
+  GTK_CMCTREE_EXPANSION_EXPAND,
+  GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE,
+  GTK_CMCTREE_EXPANSION_COLLAPSE,
+  GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE,
+  GTK_CMCTREE_EXPANSION_TOGGLE,
+  GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE
+} GtkCMCTreeExpansionType;
+
+typedef struct _GtkCMCTree      GtkCMCTree;
+typedef struct _GtkCMCTreeClass GtkCMCTreeClass;
+typedef struct _GtkCMCTreeRow   GtkCMCTreeRow;
+typedef struct _GtkCMCTreeNode  GtkCMCTreeNode;
+
+typedef void (*GtkCMCTreeFunc) (GtkCMCTree     *ctree,
+                             GtkCMCTreeNode *node,
+                             gpointer      data);
+
+typedef gboolean (*GtkCMCTreeGNodeFunc) (GtkCMCTree     *ctree,
+                                       guint         depth,
+                                       GNode        *gnode,
+                                      GtkCMCTreeNode *cnode,
+                                       gpointer      data);
+
+typedef gboolean (*GtkCMCTreeCompareDragFunc) (GtkCMCTree     *ctree,
+                                             GtkCMCTreeNode *source_node,
+                                             GtkCMCTreeNode *new_parent,
+                                             GtkCMCTreeNode *new_sibling);
+
+struct _GtkCMCTree
+{
+  GtkCMCList clist;
+  
+  GdkGC *lines_gc;
+  
+  gint tree_indent;
+  gint tree_spacing;
+  gint tree_column;
+
+  guint line_style     : 2;
+  guint expander_style : 2;
+  guint show_stub      : 1;
+
+  GtkCMCTreeCompareDragFunc drag_compare;
+};
+
+struct _GtkCMCTreeClass
+{
+  GtkCMCListClass parent_class;
+  
+  void (*tree_select_row)   (GtkCMCTree     *ctree,
+                            GtkCMCTreeNode *row,
+                            gint          column);
+  void (*tree_unselect_row) (GtkCMCTree     *ctree,
+                            GtkCMCTreeNode *row,
+                            gint          column);
+  void (*tree_expand)       (GtkCMCTree     *ctree,
+                            GtkCMCTreeNode *node);
+  void (*tree_collapse)     (GtkCMCTree     *ctree,
+                            GtkCMCTreeNode *node);
+  void (*tree_move)         (GtkCMCTree     *ctree,
+                            GtkCMCTreeNode *node,
+                            GtkCMCTreeNode *new_parent,
+                            GtkCMCTreeNode *new_sibling);
+  void (*change_focus_row_expansion) (GtkCMCTree *ctree,
+                                     GtkCMCTreeExpansionType action);
+};
+
+struct _GtkCMCTreeRow
+{
+  GtkCMCListRow row;
+  
+  GtkCMCTreeNode *parent;
+  GtkCMCTreeNode *sibling;
+  GtkCMCTreeNode *children;
+  
+  GdkPixmap *pixmap_closed;
+  GdkBitmap *mask_closed;
+  GdkPixmap *pixmap_opened;
+  GdkBitmap *mask_opened;
+  
+  guint16 level;
+  
+  guint is_leaf  : 1;
+  guint expanded : 1;
+};
+
+struct _GtkCMCTreeNode {
+  GList list;
+};
+
+
+/***********************************************************
+ *           Creation, insertion, deletion                 *
+ ***********************************************************/
+
+GType gtk_cmctree_get_type                       (void);
+GtkWidget * gtk_cmctree_new_with_titles            (gint          columns, 
+                                                 gint          tree_column,
+                                                 gchar        *titles[]);
+GtkWidget * gtk_cmctree_new                        (gint          columns, 
+                                                 gint          tree_column);
+GtkCMCTreeNode * gtk_cmctree_insert_node             (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *parent, 
+                                                 GtkCMCTreeNode *sibling,
+                                                 gchar        *text[],
+                                                 guint8        spacing,
+                                                 GdkPixmap    *pixmap_closed,
+                                                 GdkBitmap    *mask_closed,
+                                                 GdkPixmap    *pixmap_opened,
+                                                 GdkBitmap    *mask_opened,
+                                                 gboolean      is_leaf,
+                                                 gboolean      expanded);
+void gtk_cmctree_remove_node                       (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node);
+GtkCMCTreeNode * gtk_cmctree_insert_gnode            (GtkCMCTree          *ctree,
+                                                 GtkCMCTreeNode      *parent,
+                                                 GtkCMCTreeNode      *sibling,
+                                                 GNode             *gnode,
+                                                 GtkCMCTreeGNodeFunc  func,
+                                                 gpointer           data);
+GNode * gtk_cmctree_export_to_gnode                (GtkCMCTree          *ctree,
+                                                 GNode             *parent,
+                                                 GNode             *sibling,
+                                                 GtkCMCTreeNode      *node,
+                                                 GtkCMCTreeGNodeFunc  func,
+                                                 gpointer           data);
+
+/***********************************************************
+ *  Generic recursive functions, querying / finding tree   *
+ *  information                                            *
+ ***********************************************************/
+
+void gtk_cmctree_post_recursive                    (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node,
+                                                 GtkCMCTreeFunc  func,
+                                                 gpointer      data);
+void gtk_cmctree_post_recursive_to_depth           (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node,
+                                                 gint          depth,
+                                                 GtkCMCTreeFunc  func,
+                                                 gpointer      data);
+void gtk_cmctree_pre_recursive                     (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node,
+                                                 GtkCMCTreeFunc  func,
+                                                 gpointer      data);
+void gtk_cmctree_pre_recursive_to_depth            (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node,
+                                                 gint          depth,
+                                                 GtkCMCTreeFunc  func,
+                                                 gpointer      data);
+gboolean gtk_cmctree_is_viewable                   (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node);
+GtkCMCTreeNode * gtk_cmctree_last                    (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node);
+GtkCMCTreeNode * gtk_cmctree_find_node_ptr           (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeRow  *ctree_row);
+GtkCMCTreeNode * gtk_cmctree_node_nth                (GtkCMCTree     *ctree,
+                                                 guint         row);
+gboolean gtk_cmctree_find                          (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 GtkCMCTreeNode *child);
+gboolean gtk_cmctree_is_ancestor                   (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 GtkCMCTreeNode *child);
+GtkCMCTreeNode * gtk_cmctree_find_by_row_data        (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gpointer      data);
+/* returns a GList of all GtkCMCTreeNodes with row->data == data. */
+GList * gtk_cmctree_find_all_by_row_data           (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gpointer      data);
+GtkCMCTreeNode * gtk_cmctree_find_by_row_data_custom (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gpointer      data,
+                                                 GCompareFunc  func);
+/* returns a GList of all GtkCMCTreeNodes with row->data == data. */
+GList * gtk_cmctree_find_all_by_row_data_custom    (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gpointer      data,
+                                                 GCompareFunc  func);
+gboolean gtk_cmctree_is_hot_spot                   (GtkCMCTree     *ctree,
+                                                 gint          x,
+                                                 gint          y);
+
+/***********************************************************
+ *   Tree signals : move, expand, collapse, (un)select     *
+ ***********************************************************/
+
+void gtk_cmctree_move                              (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 GtkCMCTreeNode *new_parent, 
+                                                 GtkCMCTreeNode *new_sibling);
+void gtk_cmctree_expand                            (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_expand_recursive                  (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_expand_to_depth                   (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          depth);
+void gtk_cmctree_collapse                          (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_collapse_recursive                (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_collapse_to_depth                 (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          depth);
+void gtk_cmctree_toggle_expansion                  (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_toggle_expansion_recursive        (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_select                            (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_select_recursive                  (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_unselect                          (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_unselect_recursive                (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_real_select_recursive             (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node, 
+                                                 gint          state);
+
+/***********************************************************
+ *           Analogons of GtkCMCList functions               *
+ ***********************************************************/
+
+void gtk_cmctree_node_set_text                     (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          column,
+                                                 const gchar  *text);
+void gtk_cmctree_node_set_pixmap                   (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          column,
+                                                 GdkPixmap    *pixmap,
+                                                 GdkBitmap    *mask);
+void gtk_cmctree_node_set_pixtext                  (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          column,
+                                                 const gchar  *text,
+                                                 guint8        spacing,
+                                                 GdkPixmap    *pixmap,
+                                                 GdkBitmap    *mask);
+void gtk_cmctree_set_node_info                     (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 const gchar  *text,
+                                                 guint8        spacing,
+                                                 GdkPixmap    *pixmap_closed,
+                                                 GdkBitmap    *mask_closed,
+                                                 GdkPixmap    *pixmap_opened,
+                                                 GdkBitmap    *mask_opened,
+                                                 gboolean      is_leaf,
+                                                 gboolean      expanded);
+void gtk_cmctree_node_set_shift                    (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          column,
+                                                 gint          vertical,
+                                                 gint          horizontal);
+void gtk_cmctree_node_set_selectable               (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gboolean      selectable);
+gboolean gtk_cmctree_node_get_selectable           (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node);
+GtkCMCellType gtk_cmctree_node_get_cell_type         (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          column);
+gboolean gtk_cmctree_node_get_text                 (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          column,
+                                                 gchar       **text);
+gboolean gtk_cmctree_node_get_pixmap               (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          column,
+                                                 GdkPixmap   **pixmap,
+                                                 GdkBitmap   **mask);
+gboolean gtk_cmctree_node_get_pixtext              (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          column,
+                                                 gchar       **text,
+                                                 guint8       *spacing,
+                                                 GdkPixmap   **pixmap,
+                                                 GdkBitmap   **mask);
+gboolean gtk_cmctree_get_node_info                 (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gchar       **text,
+                                                 guint8       *spacing,
+                                                 GdkPixmap   **pixmap_closed,
+                                                 GdkBitmap   **mask_closed,
+                                                 GdkPixmap   **pixmap_opened,
+                                                 GdkBitmap   **mask_opened,
+                                                 gboolean     *is_leaf,
+                                                 gboolean     *expanded);
+void gtk_cmctree_node_set_row_style                (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 GtkStyle     *style);
+GtkStyle * gtk_cmctree_node_get_row_style          (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_node_set_cell_style               (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          column,
+                                                 GtkStyle     *style);
+GtkStyle * gtk_cmctree_node_get_cell_style         (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          column);
+void gtk_cmctree_node_set_foreground               (GtkCMCTree       *ctree,
+                                                 GtkCMCTreeNode   *node,
+                                                 const GdkColor *color);
+void gtk_cmctree_node_set_background               (GtkCMCTree       *ctree,
+                                                 GtkCMCTreeNode   *node,
+                                                 const GdkColor *color);
+void gtk_cmctree_node_set_row_data                 (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gpointer      data);
+void gtk_cmctree_node_set_row_data_full            (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gpointer      data,
+                                                 GtkDestroyNotify destroy);
+gpointer gtk_cmctree_node_get_row_data             (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_node_moveto                       (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node,
+                                                 gint          column,
+                                                 gfloat        row_align,
+                                                 gfloat        col_align);
+GtkVisibility gtk_cmctree_node_is_visible          (GtkCMCTree     *ctree,
+                                                 GtkCMCTreeNode *node);
+
+/***********************************************************
+ *             GtkCMCTree specific functions                 *
+ ***********************************************************/
+
+void gtk_cmctree_set_indent            (GtkCMCTree                *ctree, 
+                                     gint                     indent);
+void gtk_cmctree_set_spacing           (GtkCMCTree                *ctree, 
+                                     gint                     spacing);
+void gtk_cmctree_set_show_stub         (GtkCMCTree                *ctree, 
+                                     gboolean                 show_stub);
+void gtk_cmctree_set_line_style        (GtkCMCTree                *ctree, 
+                                     GtkCMCTreeLineStyle        line_style);
+void gtk_cmctree_set_expander_style    (GtkCMCTree                *ctree, 
+                                     GtkCMCTreeExpanderStyle    expander_style);
+void gtk_cmctree_set_drag_compare_func (GtkCMCTree                   *ctree,
+                                     GtkCMCTreeCompareDragFunc  cmp_func);
+
+/***********************************************************
+ *             Tree sorting functions                      *
+ ***********************************************************/
+
+void gtk_cmctree_sort_node                         (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node);
+void gtk_cmctree_sort_recursive                    (GtkCMCTree     *ctree, 
+                                                 GtkCMCTreeNode *node);
+
+
+#define gtk_cmctree_set_reorderable(t,r)                    gtk_cmclist_set_reorderable((GtkCMCList*) (t),(r))
+
+/* GType for the GtkCMCTreeNode.  This is a boxed type, although it uses
+ * no-op's for the copy and free routines.  It is defined in order to
+ * provide type information for the signal arguments
+ */
+GType   gtk_cmctree_node_get_type                  (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif                         /* __GTK_CMCTREE_H__ */
diff --git a/src/gtk/gtkcmoptionmenu.c b/src/gtk/gtkcmoptionmenu.c
new file mode 100644 (file)
index 0000000..dcfab16
--- /dev/null
@@ -0,0 +1,1025 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Jsh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "claws-marshal.h"
+#include "gtkcmoptionmenu.h"
+
+#define CHILD_LEFT_SPACING        4
+#define CHILD_RIGHT_SPACING       1
+#define CHILD_TOP_SPACING         1
+#define CHILD_BOTTOM_SPACING      1
+
+typedef struct _GtkCMOptionMenuProps GtkCMOptionMenuProps;
+
+struct _GtkCMOptionMenuProps
+{
+  gboolean interior_focus;
+  GtkRequisition indicator_size;
+  GtkBorder indicator_spacing;
+  gint focus_width;
+  gint focus_pad;
+};
+
+static const GtkCMOptionMenuProps default_props = {
+  TRUE,
+  { 7, 13 },
+  { 7, 5, 2, 2 },              /* Left, right, top, bottom */
+  1,
+  0
+};
+
+static void gtk_cmoption_menu_destroy         (GtkObject          *object);
+static void gtk_cmoption_menu_set_property    (GObject            *object,
+                                            guint               prop_id,
+                                            const GValue       *value,
+                                            GParamSpec         *pspec);
+static void gtk_cmoption_menu_get_property    (GObject            *object,
+                                            guint               prop_id,
+                                            GValue             *value,
+                                            GParamSpec         *pspec);
+static void gtk_cmoption_menu_size_request    (GtkWidget          *widget,
+                                            GtkRequisition     *requisition);
+static void gtk_cmoption_menu_size_allocate   (GtkWidget          *widget,
+                                            GtkAllocation      *allocation);
+static void gtk_cmoption_menu_paint           (GtkWidget          *widget,
+                                            GdkRectangle       *area);
+static gint gtk_cmoption_menu_expose          (GtkWidget          *widget,
+                                            GdkEventExpose     *event);
+static gint gtk_cmoption_menu_button_press    (GtkWidget          *widget,
+                                            GdkEventButton     *event);
+static gint gtk_cmoption_menu_key_press            (GtkWidget          *widget,
+                                            GdkEventKey        *event);
+static void gtk_cmoption_menu_selection_done  (GtkMenuShell       *menu_shell,
+                                            GtkCMOptionMenu      *option_menu);
+static void gtk_cmoption_menu_update_contents (GtkCMOptionMenu      *option_menu);
+static void gtk_cmoption_menu_remove_contents (GtkCMOptionMenu      *option_menu);
+static void gtk_cmoption_menu_calc_size       (GtkCMOptionMenu      *option_menu);
+static void gtk_cmoption_menu_position        (GtkMenu            *menu,
+                                            gint               *x,
+                                            gint               *y,
+                                            gint               *scroll_offet,
+                                            gpointer            user_data);
+static void gtk_cmoption_menu_show_all        (GtkWidget          *widget);
+static void gtk_cmoption_menu_hide_all        (GtkWidget          *widget);
+static gboolean gtk_cmoption_menu_mnemonic_activate (GtkWidget    *widget,
+                                                  gboolean      group_cycling);
+static GType gtk_cmoption_menu_child_type   (GtkContainer       *container);
+static gint gtk_cmoption_menu_scroll_event    (GtkWidget          *widget,
+                                            GdkEventScroll     *event);
+
+enum
+{
+  CHANGED,
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_MENU,
+  LAST_PROP
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GtkCMOptionMenu, gtk_cmoption_menu, GTK_TYPE_BUTTON)
+
+static void
+gtk_cmoption_menu_class_init (GtkCMOptionMenuClass *class)
+{
+  GObjectClass *gobject_class;
+  GtkObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+  GtkContainerClass *container_class;
+
+  gobject_class = (GObjectClass*) class;
+  object_class = (GtkObjectClass*) class;
+  widget_class = (GtkWidgetClass*) class;
+  container_class = (GtkContainerClass*) class;
+
+  signals[CHANGED] =
+    g_signal_new (("changed"),
+                  G_OBJECT_CLASS_TYPE (class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GtkCMOptionMenuClass, changed),
+                  NULL, NULL,
+                  claws_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
+  gobject_class->set_property = gtk_cmoption_menu_set_property;
+  gobject_class->get_property = gtk_cmoption_menu_get_property;
+  object_class->destroy = gtk_cmoption_menu_destroy;
+  
+  widget_class->size_request = gtk_cmoption_menu_size_request;
+  widget_class->size_allocate = gtk_cmoption_menu_size_allocate;
+  widget_class->expose_event = gtk_cmoption_menu_expose;
+  widget_class->button_press_event = gtk_cmoption_menu_button_press;
+  widget_class->key_press_event = gtk_cmoption_menu_key_press;
+  widget_class->scroll_event = gtk_cmoption_menu_scroll_event;
+  widget_class->show_all = gtk_cmoption_menu_show_all;
+  widget_class->hide_all = gtk_cmoption_menu_hide_all;
+  widget_class->mnemonic_activate = gtk_cmoption_menu_mnemonic_activate;
+
+  container_class->child_type = gtk_cmoption_menu_child_type;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_MENU,
+                                   g_param_spec_object ("menu",
+                                                        ("Menu"),
+                                                        ("The menu of options"),
+                                                        GTK_TYPE_MENU,
+                                                        G_PARAM_READWRITE));
+  
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_boxed ("indicator-size",
+                                                              ("Indicator Size"),
+                                                              ("Size of dropdown indicator"),
+                                                              GTK_TYPE_REQUISITION,
+                                                              G_PARAM_READABLE));
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_boxed ("indicator-spacing",
+                                                              ("Indicator Spacing"),
+                                                              ("Spacing around indicator"),
+                                                              GTK_TYPE_BORDER,
+                                                              G_PARAM_READABLE));
+}
+
+static GType
+gtk_cmoption_menu_child_type (GtkContainer       *container)
+{
+  return G_TYPE_NONE;
+}
+
+static void
+gtk_cmoption_menu_init (GtkCMOptionMenu *option_menu)
+{
+  GTK_WIDGET_SET_FLAGS (option_menu, GTK_CAN_FOCUS);
+  GTK_WIDGET_UNSET_FLAGS (option_menu, GTK_CAN_DEFAULT | GTK_RECEIVES_DEFAULT);
+
+  option_menu->menu = NULL;
+  option_menu->menu_item = NULL;
+  option_menu->width = 0;
+  option_menu->height = 0;
+}
+
+GtkWidget*
+gtk_cmoption_menu_new (void)
+{
+  return g_object_new (GTK_TYPE_CMOPTION_MENU, NULL);
+}
+
+GtkWidget*
+gtk_cmoption_menu_get_menu (GtkCMOptionMenu *option_menu)
+{
+  g_return_val_if_fail (GTK_IS_CMOPTION_MENU (option_menu), NULL);
+
+  return option_menu->menu;
+}
+
+static void
+gtk_cmoption_menu_detacher (GtkWidget     *widget,
+                         GtkMenu       *menu)
+{
+  GtkCMOptionMenu *option_menu;
+
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (widget));
+
+  option_menu = GTK_CMOPTION_MENU (widget);
+  g_return_if_fail (option_menu->menu == (GtkWidget*) menu);
+
+  gtk_cmoption_menu_remove_contents (option_menu);
+  g_signal_handlers_disconnect_by_func (option_menu->menu,
+                                       gtk_cmoption_menu_selection_done,
+                                       option_menu);
+  g_signal_handlers_disconnect_by_func (option_menu->menu,
+                                       gtk_cmoption_menu_calc_size,
+                                       option_menu);
+  
+  option_menu->menu = NULL;
+  g_object_notify (G_OBJECT (option_menu), "menu");
+}
+
+void
+gtk_cmoption_menu_set_menu (GtkCMOptionMenu *option_menu,
+                         GtkWidget     *menu)
+{
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+  g_return_if_fail (GTK_IS_MENU (menu));
+
+  if (option_menu->menu != menu)
+    {
+      gtk_cmoption_menu_remove_menu (option_menu);
+
+      option_menu->menu = menu;
+      gtk_menu_attach_to_widget (GTK_MENU (menu),
+                                GTK_WIDGET (option_menu),
+                                gtk_cmoption_menu_detacher);
+
+      gtk_cmoption_menu_calc_size (option_menu);
+
+      g_signal_connect_after (option_menu->menu, "selection-done",
+                             G_CALLBACK (gtk_cmoption_menu_selection_done),
+                             option_menu);
+      g_signal_connect_swapped (option_menu->menu, "size_request",
+                               G_CALLBACK (gtk_cmoption_menu_calc_size),
+                               option_menu);
+
+      if (GTK_WIDGET (option_menu)->parent)
+       gtk_widget_queue_resize (GTK_WIDGET (option_menu));
+
+      gtk_cmoption_menu_update_contents (option_menu);
+      
+      g_object_notify (G_OBJECT (option_menu), "menu");
+    }
+}
+
+void
+gtk_cmoption_menu_remove_menu (GtkCMOptionMenu *option_menu)
+{
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+  if (option_menu->menu)
+    {
+      if (GTK_MENU_SHELL (option_menu->menu)->active)
+       gtk_menu_shell_cancel (GTK_MENU_SHELL (option_menu->menu));
+      
+      gtk_menu_detach (GTK_MENU (option_menu->menu));
+    }
+}
+
+void
+gtk_cmoption_menu_set_history (GtkCMOptionMenu *option_menu,
+                            guint          index)
+{
+  GtkWidget *menu_item;
+
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+  if (option_menu->menu)
+    {
+      gtk_menu_set_active (GTK_MENU (option_menu->menu), index);
+      menu_item = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+
+      if (menu_item != option_menu->menu_item)
+        gtk_cmoption_menu_update_contents (option_menu);
+    }
+}
+
+/**
+ * gtk_cmoption_menu_get_history:
+ * @option_menu: a #GtkCMOptionMenu
+ * 
+ * Retrieves the index of the currently selected menu item. The menu
+ * items are numbered from top to bottom, starting with 0. 
+ * 
+ * Return value: index of the selected menu item, or -1 if there are no menu items
+ * Deprecated: 2.4: Use #GtkComboBox instead.
+ **/
+gint
+gtk_cmoption_menu_get_history (GtkCMOptionMenu *option_menu)
+{
+  GtkWidget *active_widget;
+  
+  g_return_val_if_fail (GTK_IS_CMOPTION_MENU (option_menu), -1);
+
+  if (option_menu->menu)
+    {
+      active_widget = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+
+      if (active_widget)
+       return g_list_index (GTK_MENU_SHELL (option_menu->menu)->children,
+                             active_widget);
+      else
+       return -1;
+    }
+  else
+    return -1;
+}
+
+static void
+gtk_cmoption_menu_set_property (GObject            *object,
+                             guint               prop_id,
+                             const GValue       *value,
+                             GParamSpec         *pspec)
+{
+  GtkCMOptionMenu *option_menu = GTK_CMOPTION_MENU (object);
+
+  switch (prop_id)
+    {
+    case PROP_MENU:
+      gtk_cmoption_menu_set_menu (option_menu, g_value_get_object (value));
+      break;
+      
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_cmoption_menu_get_property (GObject            *object,
+                             guint               prop_id,
+                             GValue             *value,
+                             GParamSpec         *pspec)
+{
+  GtkCMOptionMenu *option_menu = GTK_CMOPTION_MENU (object);
+
+  switch (prop_id)
+    {
+    case PROP_MENU:
+      g_value_set_object (value, option_menu->menu);
+      break;
+      
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_cmoption_menu_destroy (GtkObject *object)
+{
+  GtkCMOptionMenu *option_menu;
+
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (object));
+
+  option_menu = GTK_CMOPTION_MENU (object);
+
+  if (option_menu->menu)
+    gtk_widget_destroy (option_menu->menu);
+
+  if (GTK_OBJECT_CLASS (gtk_cmoption_menu_parent_class)->destroy)
+    (* GTK_OBJECT_CLASS (gtk_cmoption_menu_parent_class)->destroy) (object);
+}
+
+static void
+gtk_cmoption_menu_get_props (GtkCMOptionMenu       *option_menu,
+                          GtkCMOptionMenuProps  *props)
+{
+  GtkRequisition *indicator_size;
+  GtkBorder *indicator_spacing;
+  
+  gtk_widget_style_get (GTK_WIDGET (option_menu),
+                       "indicator-size", &indicator_size,
+                       "indicator-spacing", &indicator_spacing,
+                       "interior-focus", &props->interior_focus,
+                       "focus-line-width", &props->focus_width,
+                       "focus-padding", &props->focus_pad,
+                       NULL);
+
+  if (indicator_size)
+    props->indicator_size = *indicator_size;
+  else
+    props->indicator_size = default_props.indicator_size;
+
+  if (indicator_spacing)
+    props->indicator_spacing = *indicator_spacing;
+  else
+    props->indicator_spacing = default_props.indicator_spacing;
+
+  gtk_requisition_free (indicator_size);
+  gtk_border_free (indicator_spacing);
+}
+
+static void
+gtk_cmoption_menu_size_request (GtkWidget      *widget,
+                             GtkRequisition *requisition)
+{
+  GtkCMOptionMenu *option_menu = GTK_CMOPTION_MENU (widget);
+  GtkCMOptionMenuProps props;
+  gint tmp;
+  GtkRequisition child_requisition = { 0, 0 };
+      
+  gtk_cmoption_menu_get_props (option_menu, &props);
+  if (GTK_BIN (option_menu)->child && GTK_WIDGET_VISIBLE (GTK_BIN (option_menu)->child))
+    {
+      gtk_widget_size_request (GTK_BIN (option_menu)->child, &child_requisition);
+
+      requisition->width += child_requisition.width;
+      requisition->height += child_requisition.height;
+    }
+  
+  requisition->width = ((GTK_CONTAINER (widget)->border_width +
+                        GTK_WIDGET (widget)->style->xthickness + props.focus_pad) * 2 +
+                       MAX (child_requisition.width, option_menu->width) +
+                       props.indicator_size.width +
+                       props.indicator_spacing.left + props.indicator_spacing.right +
+                       CHILD_LEFT_SPACING + CHILD_RIGHT_SPACING + props.focus_width * 2);
+  requisition->height = ((GTK_CONTAINER (widget)->border_width +
+                         GTK_WIDGET (widget)->style->ythickness + props.focus_pad) * 2 +
+                        MAX (child_requisition.height, option_menu->height) +
+                        CHILD_TOP_SPACING + CHILD_BOTTOM_SPACING + props.focus_width * 2);
+
+  tmp = (requisition->height - MAX (child_requisition.height, option_menu->height) +
+        props.indicator_size.height + props.indicator_spacing.top + props.indicator_spacing.bottom);
+  requisition->height = MAX (requisition->height, tmp);
+}
+
+static void
+gtk_cmoption_menu_size_allocate (GtkWidget     *widget,
+                              GtkAllocation *allocation)
+{
+  GtkWidget *child;
+  GtkButton *button = GTK_BUTTON (widget);
+  GtkAllocation child_allocation;
+  GtkCMOptionMenuProps props;
+  gint border_width;
+    
+  gtk_cmoption_menu_get_props (GTK_CMOPTION_MENU (widget), &props);
+  border_width = GTK_CONTAINER (widget)->border_width;
+
+  widget->allocation = *allocation;
+  if (GTK_WIDGET_REALIZED (widget))
+    gdk_window_move_resize (button->event_window,
+                           allocation->x + border_width, allocation->y + border_width,
+                           allocation->width - border_width * 2, allocation->height - border_width * 2);
+
+  child = GTK_BIN (widget)->child;
+  if (child && GTK_WIDGET_VISIBLE (child))
+    {
+      gint xthickness = GTK_WIDGET (widget)->style->xthickness;
+      gint ythickness = GTK_WIDGET (widget)->style->ythickness;
+      
+      child_allocation.x = widget->allocation.x + border_width + xthickness + props.focus_width + props.focus_pad + CHILD_LEFT_SPACING;
+      child_allocation.y = widget->allocation.y + border_width + ythickness + props.focus_width + props.focus_pad + CHILD_TOP_SPACING;
+      child_allocation.width = MAX (1, allocation->width - (border_width + xthickness + props.focus_width + props.focus_pad) * 2 -
+                                   props.indicator_size.width - props.indicator_spacing.left - props.indicator_spacing.right -
+                                   CHILD_LEFT_SPACING - CHILD_RIGHT_SPACING);
+      child_allocation.height = MAX (1, allocation->height - (border_width + ythickness + props.focus_width + props.focus_pad) * 2 -
+                                    CHILD_TOP_SPACING - CHILD_BOTTOM_SPACING);
+
+      if (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL) 
+       child_allocation.x += props.indicator_size.width + props.indicator_spacing.left + props.indicator_spacing.right;
+
+      gtk_widget_size_allocate (child, &child_allocation);
+    }
+}
+
+static void
+gtk_cmoption_menu_paint (GtkWidget    *widget,
+                      GdkRectangle *area)
+{
+  GdkRectangle button_area;
+  GtkCMOptionMenuProps props;
+  gint border_width;
+  gint tab_x;
+
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (widget));
+  g_return_if_fail (area != NULL);
+
+  if (GTK_WIDGET_DRAWABLE (widget))
+    {
+      border_width = GTK_CONTAINER (widget)->border_width;
+      gtk_cmoption_menu_get_props (GTK_CMOPTION_MENU (widget), &props);
+
+      button_area.x = widget->allocation.x + border_width;
+      button_area.y = widget->allocation.y + border_width;
+      button_area.width = widget->allocation.width - 2 * border_width;
+      button_area.height = widget->allocation.height - 2 * border_width;
+
+      if (!props.interior_focus && GTK_WIDGET_HAS_FOCUS (widget))
+       {
+         button_area.x += props.focus_width + props.focus_pad;
+         button_area.y += props.focus_width + props.focus_pad;
+         button_area.width -= 2 * (props.focus_width + props.focus_pad);
+         button_area.height -= 2 * (props.focus_width + props.focus_pad);
+       }
+      
+      gtk_paint_box (widget->style, widget->window,
+                    GTK_WIDGET_STATE (widget), GTK_SHADOW_OUT,
+                    area, widget, "optionmenu",
+                    button_area.x, button_area.y,
+                    button_area.width, button_area.height);
+      
+      if (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL) 
+       tab_x = button_area.x + props.indicator_spacing.right + 
+         widget->style->xthickness;
+      else
+       tab_x = button_area.x + button_area.width - 
+         props.indicator_size.width - props.indicator_spacing.right -
+         widget->style->xthickness;
+
+      gtk_paint_tab (widget->style, widget->window,
+                    GTK_WIDGET_STATE (widget), GTK_SHADOW_OUT,
+                    area, widget, "optionmenutab",
+                    tab_x,
+                    button_area.y + (button_area.height - props.indicator_size.height) / 2,
+                    props.indicator_size.width, props.indicator_size.height);
+      
+      if (GTK_WIDGET_HAS_FOCUS (widget))
+       {
+         if (props.interior_focus)
+           {
+             button_area.x += widget->style->xthickness + props.focus_pad;
+             button_area.y += widget->style->ythickness + props.focus_pad;
+             button_area.width -= 2 * (widget->style->xthickness + props.focus_pad) +
+                     props.indicator_spacing.left +
+                     props.indicator_spacing.right +
+                     props.indicator_size.width;
+             button_area.height -= 2 * (widget->style->ythickness + props.focus_pad);
+             if (gtk_widget_get_direction (GTK_WIDGET (widget)) == GTK_TEXT_DIR_RTL) 
+               button_area.x += props.indicator_spacing.left +
+                 props.indicator_spacing.right +
+                 props.indicator_size.width;
+           }
+         else
+           {
+             button_area.x -= props.focus_width + props.focus_pad;
+             button_area.y -= props.focus_width + props.focus_pad;
+             button_area.width += 2 * (props.focus_width + props.focus_pad);
+             button_area.height += 2 * (props.focus_width + props.focus_pad);
+           }
+           
+         gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget),
+                          area, widget, "button",
+                          button_area.x, 
+                          button_area.y, 
+                          button_area.width,
+                          button_area.height);
+       }
+    }
+}
+
+static gint
+gtk_cmoption_menu_expose (GtkWidget      *widget,
+                       GdkEventExpose *event)
+{
+  g_return_val_if_fail (GTK_IS_CMOPTION_MENU (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  if (GTK_WIDGET_DRAWABLE (widget))
+    {
+      gtk_cmoption_menu_paint (widget, &event->area);
+
+
+      /* The following code tries to draw the child in two places at
+       * once. It fails miserably for several reasons
+       *
+       * - If the child is not no-window, removing generates
+       *   more expose events. Bad, bad, bad.
+       * 
+       * - Even if the child is no-window, removing it now (properly)
+       *   clears the space where it was, so it does no good
+       */
+      
+#if 0
+      remove_child = FALSE;
+      child = GTK_BUTTON (widget)->child;
+
+      if (!child)
+       {
+         if (!GTK_CMOPTION_MENU (widget)->menu)
+           return FALSE;
+         gtk_cmoption_menu_update_contents (GTK_CMOPTION_MENU (widget));
+         child = GTK_BUTTON (widget)->child;
+         if (!child)
+           return FALSE;
+         remove_child = TRUE;
+       }
+
+      child_event = *event;
+
+      if (GTK_WIDGET_NO_WINDOW (child) &&
+         gtk_widget_intersect (child, &event->area, &child_event.area))
+       gtk_widget_event (child, (GdkEvent*) &child_event);
+
+      if (remove_child)
+       gtk_cmoption_menu_remove_contents (GTK_CMOPTION_MENU (widget));
+#else
+      if (GTK_BIN (widget)->child)
+       gtk_container_propagate_expose (GTK_CONTAINER (widget),
+                                       GTK_BIN (widget)->child,
+                                       event);
+#endif /* 0 */
+    }
+
+  return FALSE;
+}
+
+static gint
+gtk_cmoption_menu_button_press (GtkWidget      *widget,
+                             GdkEventButton *event)
+{
+  GtkCMOptionMenu *option_menu;
+  GtkWidget *menu_item;
+
+  g_return_val_if_fail (GTK_IS_CMOPTION_MENU (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  option_menu = GTK_CMOPTION_MENU (widget);
+
+  if ((event->type == GDK_BUTTON_PRESS) &&
+      (event->button == 1))
+    {
+      gtk_cmoption_menu_remove_contents (option_menu);
+      gtk_menu_popup (GTK_MENU (option_menu->menu), NULL, NULL,
+                     gtk_cmoption_menu_position, option_menu,
+                     event->button, event->time);
+      menu_item = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+      if (menu_item)
+       gtk_menu_shell_select_item (GTK_MENU_SHELL (option_menu->menu), menu_item);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gint
+gtk_cmoption_menu_key_press (GtkWidget   *widget,
+                          GdkEventKey *event)
+{
+  GtkCMOptionMenu *option_menu;
+  GtkWidget *menu_item;
+
+  g_return_val_if_fail (GTK_IS_CMOPTION_MENU (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  option_menu = GTK_CMOPTION_MENU (widget);
+
+  switch (event->keyval)
+    {
+    case GDK_KP_Space:
+    case GDK_space:
+      gtk_cmoption_menu_remove_contents (option_menu);
+      gtk_menu_popup (GTK_MENU (option_menu->menu), NULL, NULL,
+                     gtk_cmoption_menu_position, option_menu,
+                     0, event->time);
+      menu_item = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+      if (menu_item)
+       gtk_menu_shell_select_item (GTK_MENU_SHELL (option_menu->menu), menu_item);
+      return TRUE;
+    }
+  
+  return FALSE;
+}
+
+static void
+gtk_cmoption_menu_selection_done (GtkMenuShell  *menu_shell,
+                               GtkCMOptionMenu *option_menu)
+{
+  g_return_if_fail (menu_shell != NULL);
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+  gtk_cmoption_menu_update_contents (option_menu);
+}
+
+static void
+gtk_cmoption_menu_changed (GtkCMOptionMenu *option_menu)
+{
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+  g_signal_emit (option_menu, signals[CHANGED], 0);
+}
+
+static void
+gtk_cmoption_menu_select_first_sensitive (GtkCMOptionMenu *option_menu)
+{
+  if (option_menu->menu)
+    {
+      GList *children = GTK_MENU_SHELL (option_menu->menu)->children;
+      gint index = 0;
+
+      while (children)
+       {
+         if (GTK_WIDGET_SENSITIVE (children->data))
+           {
+             gtk_cmoption_menu_set_history (option_menu, index);
+             return;
+           }
+         
+         children = children->next;
+         index++;
+       }
+    }
+}
+
+static void
+gtk_cmoption_menu_item_state_changed_cb (GtkWidget      *widget,
+                                      GtkStateType    previous_state,
+                                      GtkCMOptionMenu  *option_menu)
+{
+  GtkWidget *child = GTK_BIN (option_menu)->child;
+
+  if (child && GTK_WIDGET_SENSITIVE (child) != GTK_WIDGET_IS_SENSITIVE (widget))
+    gtk_widget_set_sensitive (child, GTK_WIDGET_IS_SENSITIVE (widget));
+}
+
+static void
+gtk_cmoption_menu_item_destroy_cb (GtkWidget     *widget,
+                                GtkCMOptionMenu *option_menu)
+{
+  GtkWidget *child = GTK_BIN (option_menu)->child;
+
+  if (child)
+    {
+      g_object_ref (child);
+      gtk_cmoption_menu_remove_contents (option_menu);
+      gtk_widget_destroy (child);
+      g_object_unref (child);
+
+      gtk_cmoption_menu_select_first_sensitive (option_menu);
+    }
+}
+
+static void
+gtk_cmoption_menu_update_contents (GtkCMOptionMenu *option_menu)
+{
+  GtkWidget *child;
+  GtkRequisition child_requisition;
+
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+  if (option_menu->menu)
+    {
+      GtkWidget *old_item = option_menu->menu_item;
+      
+      gtk_cmoption_menu_remove_contents (option_menu);
+
+      option_menu->menu_item = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+      if (option_menu->menu_item)
+       {
+         g_object_ref (option_menu->menu_item);
+         child = GTK_BIN (option_menu->menu_item)->child;
+         if (child)
+           {
+             if (!GTK_WIDGET_IS_SENSITIVE (option_menu->menu_item))
+               gtk_widget_set_sensitive (child, FALSE);
+             gtk_widget_reparent (child, GTK_WIDGET (option_menu));
+           }
+
+         g_signal_connect (option_menu->menu_item, "state_changed",
+                           G_CALLBACK (gtk_cmoption_menu_item_state_changed_cb), option_menu);
+         g_signal_connect (option_menu->menu_item, "destroy",
+                           G_CALLBACK (gtk_cmoption_menu_item_destroy_cb), option_menu);
+
+         gtk_widget_size_request (child, &child_requisition);
+         gtk_widget_size_allocate (GTK_WIDGET (option_menu),
+                                   &(GTK_WIDGET (option_menu)->allocation));
+
+         if (GTK_WIDGET_DRAWABLE (option_menu))
+           gtk_widget_queue_draw (GTK_WIDGET (option_menu));
+       }
+
+      if (old_item != option_menu->menu_item)
+        gtk_cmoption_menu_changed (option_menu);
+    }
+}
+
+static void
+gtk_cmoption_menu_remove_contents (GtkCMOptionMenu *option_menu)
+{
+  GtkWidget *child;
+  
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+  if (option_menu->menu_item)
+    {
+      child = GTK_BIN (option_menu)->child;
+  
+      if (child)
+       {
+         gtk_widget_set_sensitive (child, TRUE);
+         gtk_widget_set_state (child, GTK_STATE_NORMAL);
+         gtk_widget_reparent (child, option_menu->menu_item);
+       }
+
+      g_signal_handlers_disconnect_by_func (option_menu->menu_item,
+                                           gtk_cmoption_menu_item_state_changed_cb,
+                                           option_menu);                                    
+      g_signal_handlers_disconnect_by_func (option_menu->menu_item,
+                                           gtk_cmoption_menu_item_destroy_cb,
+                                           option_menu);   
+      
+      g_object_unref (option_menu->menu_item);
+      option_menu->menu_item = NULL;
+    }
+}
+
+static void
+gtk_cmoption_menu_calc_size (GtkCMOptionMenu *option_menu)
+{
+  GtkWidget *child;
+  GList *children;
+  GtkRequisition child_requisition;
+  gint old_width = option_menu->width;
+  gint old_height = option_menu->height;
+
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (option_menu));
+
+  option_menu->width = 0;
+  option_menu->height = 0;
+
+  if (option_menu->menu)
+    {
+      children = GTK_MENU_SHELL (option_menu->menu)->children;
+      while (children)
+       {
+         child = children->data;
+         children = children->next;
+
+         if (GTK_WIDGET_VISIBLE (child))
+           {
+             GtkWidget *inner = GTK_BIN (child)->child;
+
+             if (inner)
+               {
+                 gtk_widget_size_request (inner, &child_requisition);
+
+                 option_menu->width = MAX (option_menu->width, child_requisition.width);
+                 option_menu->height = MAX (option_menu->height, child_requisition.height);
+               }
+           }
+       }
+    }
+
+  if (old_width != option_menu->width || old_height != option_menu->height)
+    gtk_widget_queue_resize (GTK_WIDGET (option_menu));
+}
+
+static void
+gtk_cmoption_menu_position (GtkMenu  *menu,
+                         gint     *x,
+                         gint     *y,
+                         gboolean *push_in,
+                         gpointer  user_data)
+{
+  GtkCMOptionMenu *option_menu;
+  GtkWidget *active;
+  GtkWidget *child;
+  GtkWidget *widget;
+  GtkRequisition requisition;
+  GList *children;
+  gint screen_width;
+  gint menu_xpos;
+  gint menu_ypos;
+  gint menu_width;
+
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (user_data));
+
+  option_menu = GTK_CMOPTION_MENU (user_data);
+  widget = GTK_WIDGET (option_menu);
+
+  gtk_widget_get_child_requisition (GTK_WIDGET (menu), &requisition);
+  menu_width = requisition.width;
+
+  active = gtk_menu_get_active (GTK_MENU (option_menu->menu));
+  gdk_window_get_origin (widget->window, &menu_xpos, &menu_ypos);
+
+  menu_xpos += widget->allocation.x;
+  menu_ypos += widget->allocation.y + widget->allocation.height / 2 - 2;
+
+  if (active != NULL)
+    {
+      gtk_widget_get_child_requisition (active, &requisition);
+      menu_ypos -= requisition.height / 2;
+    }
+
+  children = GTK_MENU_SHELL (option_menu->menu)->children;
+  while (children)
+    {
+      child = children->data;
+
+      if (active == child)
+       break;
+
+      if (GTK_WIDGET_VISIBLE (child))
+       {
+         gtk_widget_get_child_requisition (child, &requisition);
+         menu_ypos -= requisition.height;
+       }
+
+      children = children->next;
+    }
+
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+    menu_xpos = menu_xpos + widget->allocation.width - menu_width;
+
+  /* Clamp the position on screen */
+  screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget));
+  
+  if (menu_xpos < 0)
+    menu_xpos = 0;
+  else if ((menu_xpos + menu_width) > screen_width)
+    menu_xpos -= ((menu_xpos + menu_width) - screen_width);
+
+  *x = menu_xpos;
+  *y = menu_ypos;
+  *push_in = TRUE;
+}
+
+
+static void
+gtk_cmoption_menu_show_all (GtkWidget *widget)
+{
+  GtkContainer *container;
+  GtkCMOptionMenu *option_menu;
+  
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (widget));
+  container = GTK_CONTAINER (widget);
+  option_menu = GTK_CMOPTION_MENU (widget);
+
+  gtk_widget_show (widget);
+  gtk_container_foreach (container, (GtkCallback) gtk_widget_show_all, NULL);
+  if (option_menu->menu)
+    gtk_widget_show_all (option_menu->menu);
+  if (option_menu->menu_item)
+    gtk_widget_show_all (option_menu->menu_item);
+}
+
+
+static void
+gtk_cmoption_menu_hide_all (GtkWidget *widget)
+{
+  GtkContainer *container;
+
+  g_return_if_fail (GTK_IS_CMOPTION_MENU (widget));
+  container = GTK_CONTAINER (widget);
+
+  gtk_widget_hide (widget);
+  gtk_container_foreach (container, (GtkCallback) gtk_widget_hide_all, NULL);
+}
+
+static gboolean
+gtk_cmoption_menu_mnemonic_activate (GtkWidget *widget,
+                                  gboolean   group_cycling)
+{
+  gtk_widget_grab_focus (widget);
+  return TRUE;
+}
+
+static gint
+gtk_cmoption_menu_scroll_event (GtkWidget          *widget,
+                             GdkEventScroll     *event)
+{
+  GtkCMOptionMenu *option_menu = GTK_CMOPTION_MENU (widget);
+  gint index;
+  gint n_children;
+  gint index_dir;
+  GList *l;
+  GtkMenuItem *item;
+    
+  index = gtk_cmoption_menu_get_history (option_menu);
+
+  if (index != -1)
+    {
+      n_children = g_list_length (GTK_MENU_SHELL (option_menu->menu)->children);
+      
+      if (event->direction == GDK_SCROLL_UP)
+       index_dir = -1;
+      else
+       index_dir = 1;
+
+
+      while (TRUE)
+       {
+         index += index_dir;
+
+         if (index < 0)
+           break;
+         if (index >= n_children)
+           break;
+
+         l = g_list_nth (GTK_MENU_SHELL (option_menu->menu)->children, index);
+         item = GTK_MENU_ITEM (l->data);
+         if (GTK_WIDGET_VISIBLE (item) && GTK_WIDGET_IS_SENSITIVE (item))
+           {
+             gtk_cmoption_menu_set_history (option_menu, index);
+             gtk_menu_item_activate (GTK_MENU_ITEM (item));
+             break;
+           }
+             
+       }
+    }
+
+  return TRUE;
+}
+
diff --git a/src/gtk/gtkcmoptionmenu.h b/src/gtk/gtkcmoptionmenu.h
new file mode 100644 (file)
index 0000000..6824fcb
--- /dev/null
@@ -0,0 +1,86 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GTK_CMOPTION_MENU_H__
+#define __GTK_CMOPTION_MENU_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkbutton.h>
+
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_CMOPTION_MENU              (gtk_cmoption_menu_get_type ())
+#define GTK_CMOPTION_MENU(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CMOPTION_MENU, GtkCMOptionMenu))
+#define GTK_CMOPTION_MENU_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CMOPTION_MENU, GtkCMOptionMenuClass))
+#define GTK_IS_CMOPTION_MENU(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CMOPTION_MENU))
+#define GTK_IS_CMOPTION_MENU_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CMOPTION_MENU))
+#define GTK_CMOPTION_MENU_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CMOPTION_MENU, GtkCMOptionMenuClass))
+
+
+typedef struct _GtkCMOptionMenu       GtkCMOptionMenu;
+typedef struct _GtkCMOptionMenuClass  GtkCMOptionMenuClass;
+
+struct _GtkCMOptionMenu
+{
+  GtkButton button;
+  
+  GtkWidget *menu;
+  GtkWidget *menu_item;
+  
+  guint16 width;
+  guint16 height;
+};
+
+struct _GtkCMOptionMenuClass
+{
+  GtkButtonClass parent_class;
+
+  void (*changed) (GtkCMOptionMenu *option_menu);
+
+  /* Padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+};
+
+
+GType      gtk_cmoption_menu_get_type    (void) G_GNUC_CONST;
+GtkWidget* gtk_cmoption_menu_new         (void);
+GtkWidget* gtk_cmoption_menu_get_menu    (GtkCMOptionMenu *option_menu);
+void       gtk_cmoption_menu_set_menu    (GtkCMOptionMenu *option_menu,
+                                       GtkWidget     *menu);
+void       gtk_cmoption_menu_remove_menu (GtkCMOptionMenu *option_menu);
+gint       gtk_cmoption_menu_get_history (GtkCMOptionMenu *option_menu);
+void       gtk_cmoption_menu_set_history (GtkCMOptionMenu *option_menu,
+                                       guint          index_);
+
+
+G_END_DECLS
+
+#endif /* __GTK_CMOPTION_MENU_H__ */
index 9d2da930d061feef8d3c32712444e0a8b70482d8..ed82d63dc60361e5d78eb465e0dfb0f0a7e7d538 100644 (file)
 #include "prefs_common.h"
 #include "utils.h"
 
-#define CLIST_UNFROZEN(clist)     (((GtkCList*) (clist))->freeze_count == 0)
+#define CLIST_UNFROZEN(clist)     (((GtkCMCList*) (clist))->freeze_count == 0)
 #define CLIST_REFRESH(clist)    G_STMT_START { \
   if (CLIST_UNFROZEN (clist)) \
-    GTK_CLIST_GET_CLASS (clist)->refresh ((GtkCList*) (clist)); \
+    GTK_CMCLIST_GET_CLASS (clist)->refresh ((GtkCMCList*) (clist)); \
 } G_STMT_END
 #define CELL_SPACING               1
 #define CLIST_OPTIMUM_SIZE         64
@@ -83,39 +83,39 @@ static void gtk_sctree_drag_data_received (GtkWidget *widget, GdkDragContext *co
                                          gint x, gint y, GtkSelectionData *data,
                                          guint info, guint time);
 
-static void gtk_sctree_clear (GtkCList *clist);
-static void gtk_sctree_real_unselect_all (GtkCList *clist);
-static void gtk_sctree_collapse (GtkCTree *ctree, GtkCTreeNode *node);
+static void gtk_sctree_clear (GtkCMCList *clist);
+static void gtk_sctree_real_unselect_all (GtkCMCList *clist);
+static void gtk_sctree_collapse (GtkCMCTree *ctree, GtkCMCTreeNode *node);
        
-static void stree_sort (GtkCTree *ctree, GtkCTreeNode  *node, gpointer data);
-void gtk_sctree_sort_node (GtkCTree *ctree, GtkCTreeNode *node);
-void gtk_sctree_sort_recursive (GtkCTree *ctree, GtkCTreeNode *node);
-
-static void gtk_sctree_link (GtkCTree *ctree,
-                       GtkCTreeNode  *node,
-                       GtkCTreeNode  *parent,
-                       GtkCTreeNode  *sibling,
+static void stree_sort (GtkCMCTree *ctree, GtkCMCTreeNode  *node, gpointer data);
+void gtk_sctree_sort_node (GtkCMCTree *ctree, GtkCMCTreeNode *node);
+void gtk_sctree_sort_recursive (GtkCMCTree *ctree, GtkCMCTreeNode *node);
+
+static void gtk_sctree_link (GtkCMCTree *ctree,
+                       GtkCMCTreeNode  *node,
+                       GtkCMCTreeNode  *parent,
+                       GtkCMCTreeNode  *sibling,
                        gboolean       update_focus_row);
 
-static void gtk_sctree_unlink (GtkCTree      *ctree, 
-                       GtkCTreeNode  *node,
+static void gtk_sctree_unlink (GtkCMCTree      *ctree, 
+                       GtkCMCTreeNode  *node,
                        gboolean       update_focus_row);
 
-static void stree_update_level (GtkCTree      *ctree, 
-                       GtkCTreeNode  *node, 
+static void stree_update_level (GtkCMCTree      *ctree, 
+                       GtkCMCTreeNode  *node, 
                        gpointer       data);
 
-static GtkCTreeNode * gtk_sctree_last_visible (GtkCTree     *ctree,
-                                             GtkCTreeNode *node);
-static void gtk_sctree_real_tree_expand            (GtkCTree      *ctree,
-                                                GtkCTreeNode  *node);
+static GtkCMCTreeNode * gtk_sctree_last_visible (GtkCMCTree     *ctree,
+                                             GtkCMCTreeNode *node);
+static void gtk_sctree_real_tree_expand            (GtkCMCTree      *ctree,
+                                                GtkCMCTreeNode  *node);
 static void
-sreal_tree_move (GtkCTree     *ctree,
-               GtkCTreeNode *node,
-               GtkCTreeNode *new_parent, 
-               GtkCTreeNode *new_sibling);
+sreal_tree_move (GtkCMCTree     *ctree,
+               GtkCMCTreeNode *node,
+               GtkCMCTreeNode *new_parent, 
+               GtkCMCTreeNode *new_sibling);
 
-static GtkCTreeClass *parent_class;
+static GtkCMCTreeClass *parent_class;
 
 static guint sctree_signals[LAST_SIGNAL];
 
@@ -148,7 +148,7 @@ gtk_sctree_get_type (void)
                        (GInstanceInitFunc) gtk_sctree_init,
                };
 
-               sctree_type = g_type_register_static (GTK_TYPE_CTREE, "GtkSCTree", &sctree_info, (GTypeFlags)0);
+               sctree_type = g_type_register_static (GTK_TYPE_CMCTREE, "GtkSCTree", &sctree_info, (GTypeFlags)0);
        }
 
        return sctree_type;
@@ -192,7 +192,7 @@ gtk_sctree_draw_cell_pixmap (GdkWindow    *window,
     height = clip_rectangle->y + clip_rectangle->height - y;
 
   if (width > 0 && height > 0)
-    gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
+    gdk_draw_drawable (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
 
   if (mask)
     {
@@ -204,8 +204,8 @@ gtk_sctree_draw_cell_pixmap (GdkWindow    *window,
 }
 
 static void
-gtk_sctree_get_cell_style (GtkCList     *clist,
-               GtkCListRow  *clist_row,
+gtk_sctree_get_cell_style (GtkCMCList     *clist,
+               GtkCMCListRow  *clist_row,
                gint          state,
                gint          row,
                gint          column,
@@ -270,26 +270,26 @@ gtk_sctree_get_cell_style (GtkCList     *clist,
 }
 
 static gint
-gtk_sctree_draw_expander (GtkCTree     *ctree,
-                        GtkCTreeRow  *ctree_row,
+gtk_sctree_draw_expander (GtkCMCTree     *ctree,
+                        GtkCMCTreeRow  *ctree_row,
                         GtkStyle     *style,
                         GdkRectangle *clip_rectangle,
                         gint          x)
 {
-  GtkCList *clist;
+  GtkCMCList *clist;
   GdkPoint points[3];
   gint justification_factor;
   gint y;
 
- if (ctree->expander_style == GTK_CTREE_EXPANDER_NONE)
+ if (ctree->expander_style == GTK_CMCTREE_EXPANDER_NONE)
    return x;
 
-  clist = GTK_CLIST (ctree);
+  clist = GTK_CMCLIST (ctree);
   if (clist->column[ctree->tree_column].justification == GTK_JUSTIFY_RIGHT)
     justification_factor = -1;
   else
     justification_factor = 1;
-  if (!GTK_CLIST_ROW_HEIGHT_SET(GTK_CLIST(clist)))
+  if (!GTK_CMCLIST_ROW_HEIGHT_SET(GTK_CMCLIST(clist)))
       y = (clip_rectangle->y + (clip_rectangle->height - PM_SIZE) / 2 -
           (clip_rectangle->height + 1) % 2);
   else
@@ -300,12 +300,12 @@ gtk_sctree_draw_expander (GtkCTree     *ctree,
     {
       switch (ctree->expander_style)
        {
-       case GTK_CTREE_EXPANDER_NONE:
+       case GTK_CMCTREE_EXPANDER_NONE:
          return x;
-       case GTK_CTREE_EXPANDER_TRIANGLE:
+       case GTK_CMCTREE_EXPANDER_TRIANGLE:
          return x + justification_factor * (PM_SIZE + 3);
-       case GTK_CTREE_EXPANDER_SQUARE:
-       case GTK_CTREE_EXPANDER_CIRCULAR:
+       case GTK_CMCTREE_EXPANDER_SQUARE:
+       case GTK_CMCTREE_EXPANDER_CIRCULAR:
          return x + justification_factor * (PM_SIZE + 1);
        }
     }
@@ -315,9 +315,9 @@ gtk_sctree_draw_expander (GtkCTree     *ctree,
 
   switch (ctree->expander_style)
     {
-    case GTK_CTREE_EXPANDER_NONE:
+    case GTK_CMCTREE_EXPANDER_NONE:
       break;
-    case GTK_CTREE_EXPANDER_TRIANGLE:
+    case GTK_CMCTREE_EXPANDER_TRIANGLE:
       if (ctree_row->expanded)
        {
          points[0].x = x;
@@ -346,12 +346,12 @@ gtk_sctree_draw_expander (GtkCTree     *ctree,
 
       x += justification_factor * (PM_SIZE + 3);
       break;
-    case GTK_CTREE_EXPANDER_SQUARE:
-    case GTK_CTREE_EXPANDER_CIRCULAR:
+    case GTK_CMCTREE_EXPANDER_SQUARE:
+    case GTK_CMCTREE_EXPANDER_CIRCULAR:
       if (justification_factor == -1)
        x += justification_factor * (PM_SIZE + 1);
 
-      if (ctree->expander_style == GTK_CTREE_EXPANDER_CIRCULAR)
+      if (ctree->expander_style == GTK_CMCTREE_EXPANDER_CIRCULAR)
        {
          gdk_draw_arc (clist->clist_window, style->base_gc[GTK_STATE_NORMAL],
                        TRUE, x, y, PM_SIZE, PM_SIZE, 0, 360 * 64);
@@ -388,8 +388,8 @@ gtk_sctree_draw_expander (GtkCTree     *ctree,
 }
 
 static gint
-gtk_sctree_draw_lines (GtkCTree     *ctree,
-                     GtkCTreeRow  *ctree_row,
+gtk_sctree_draw_lines (GtkCMCTree     *ctree,
+                     GtkCMCTreeRow  *ctree_row,
                      gint          row,
                      gint          column,
                      gint          state,
@@ -399,9 +399,9 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
                      GdkRectangle *area,
                      GtkStyle     *style)
 {
-  GtkCList *clist;
-  GtkCTreeNode *node;
-  GtkCTreeNode *parent;
+  GtkCMCList *clist;
+  GtkCMCTreeNode *node;
+  GtkCMCTreeNode *parent;
   GdkRectangle tree_rectangle;
   GdkRectangle tc_rectangle;
   GdkGC *bg_gc;
@@ -416,7 +416,7 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
   gint justify_right;
   gint justification_factor;
   
-  clist = GTK_CLIST (ctree);
+  clist = GTK_CMCLIST (ctree);
   ycenter = clip_rectangle->y + (clip_rectangle->height / 2);
   justify_right = (clist->column[column].justification == GTK_JUSTIFY_RIGHT);
 
@@ -434,9 +434,9 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
 
   switch (ctree->line_style)
     {
-    case GTK_CTREE_LINES_NONE:
+    case GTK_CMCTREE_LINES_NONE:
       break;
-    case GTK_CTREE_LINES_TABBED:
+    case GTK_CMCTREE_LINES_TABBED:
       xcenter = offset + justification_factor * TAB_SIZE;
 
       column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
@@ -474,9 +474,9 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
 
       if (!ctree_row->sibling || (ctree_row->children && ctree_row->expanded))
        {
-         node = gtk_ctree_find_node_ptr (ctree, ctree_row);
-         if (GTK_CTREE_NODE_NEXT (node))
-           next_level = GTK_CTREE_ROW (GTK_CTREE_NODE_NEXT (node))->level;
+         node = gtk_cmctree_find_node_ptr (ctree, ctree_row);
+         if (GTK_CMCTREE_NODE_NEXT (node))
+           next_level = GTK_CMCTREE_ROW (GTK_CMCTREE_NODE_NEXT (node))->level;
          else
            next_level = 0;
        }
@@ -491,7 +491,7 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
              if ((justify_right && xcenter < column_left) ||
                  (!justify_right && xcenter > column_right))
                {
-                 node = GTK_CTREE_ROW (node)->parent;
+                 node = GTK_CMCTREE_ROW (node)->parent;
                  continue;
                }
 
@@ -514,12 +514,12 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
              if (!area || gdk_rectangle_intersect (area, &tree_rectangle,
                                                    &tc_rectangle))
                {
-                 gtk_sctree_get_cell_style (clist, &GTK_CTREE_ROW (node)->row,
+                 gtk_sctree_get_cell_style (clist, &GTK_CMCTREE_ROW (node)->row,
                                  state, row, column, NULL, NULL, &bg_gc);
 
                  if (bg_gc == clist->bg_gc)
                    gdk_gc_set_foreground
-                     (clist->bg_gc, &GTK_CTREE_ROW (node)->row.background);
+                     (clist->bg_gc, &GTK_CMCTREE_ROW (node)->row.background);
 
                  if (!area)
                    gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
@@ -534,7 +534,7 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
                                        tc_rectangle.width,
                                        tc_rectangle.height);
                }
-             if (next_level > GTK_CTREE_ROW (node)->level)
+             if (next_level > GTK_CMCTREE_ROW (node)->level)
                gdk_draw_line (clist->clist_window, ctree->lines_gc,
                               xcenter, crect->y,
                               xcenter, crect->y + crect->height);
@@ -545,7 +545,7 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
                  offset_x = MIN (ctree->tree_indent, 2 * TAB_SIZE);
                  width = offset_x / 2 + offset_x % 2;
 
-                 parent = GTK_CTREE_ROW (node)->parent;
+                 parent = GTK_CMCTREE_ROW (node)->parent;
 
                  tree_rectangle.y = ycenter;
                  tree_rectangle.height = (cell_rectangle->y - ycenter +
@@ -570,12 +570,12 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
                    {
                      if (parent)
                        {
-                         gtk_sctree_get_cell_style (clist, &GTK_CTREE_ROW (parent)->row,
+                         gtk_sctree_get_cell_style (clist, &GTK_CMCTREE_ROW (parent)->row,
                                          state, row, column, NULL, NULL, &bg_gc);
                          if (bg_gc == clist->bg_gc)
                            gdk_gc_set_foreground
                              (clist->bg_gc,
-                              &GTK_CTREE_ROW (parent)->row.background);
+                              &GTK_CMCTREE_ROW (parent)->row.background);
                        }
                      else if (state == GTK_STATE_SELECTED)
                        bg_gc = style->base_gc[state];
@@ -597,11 +597,11 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
                                            tc_rectangle.height);
                    }
 
-                 gtk_sctree_get_cell_style (clist, &GTK_CTREE_ROW (node)->row,
+                 gtk_sctree_get_cell_style (clist, &GTK_CMCTREE_ROW (node)->row,
                                  state, row, column, NULL, NULL, &bg_gc);
                  if (bg_gc == clist->bg_gc)
                    gdk_gc_set_foreground
-                     (clist->bg_gc, &GTK_CTREE_ROW (node)->row.background);
+                     (clist->bg_gc, &GTK_CMCTREE_ROW (node)->row.background);
 
                  gdk_gc_set_clip_rectangle (bg_gc, crect);
                  gdk_draw_arc (clist->clist_window, bg_gc, TRUE,
@@ -625,7 +625,7 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
                                  offset_x, clist->row_height,
                                  180 * 64, 90 * 64);
                }
-             node = GTK_CTREE_ROW (node)->parent;
+             node = GTK_CMCTREE_ROW (node)->parent;
            }
        }
 
@@ -741,7 +741,7 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
 
       offset_x = 1;
       offset_y = 0;
-      if (ctree->line_style == GTK_CTREE_LINES_DOTTED)
+      if (ctree->line_style == GTK_CMCTREE_LINES_DOTTED)
        {
          offset_x += abs((clip_rectangle->x + clist->hoffset) % 2);
          offset_y  = abs((cell_rectangle->y + clist->voffset) % 2);
@@ -767,11 +767,11 @@ gtk_sctree_draw_lines (GtkCTree     *ctree,
        {
          xcenter -= (justification_factor * ctree->tree_indent);
 
-         if (GTK_CTREE_ROW (node)->sibling)
+         if (GTK_CMCTREE_ROW (node)->sibling)
            gdk_draw_line (clist->clist_window, ctree->lines_gc, 
                           xcenter, cell_rectangle->y + offset_y,
                           xcenter, crect->y + crect->height);
-         node = GTK_CTREE_ROW (node)->parent;
+         node = GTK_CMCTREE_ROW (node)->parent;
        }
       gdk_gc_set_clip_rectangle (ctree->lines_gc, NULL);
       clip_rectangle->y++;
@@ -791,13 +791,13 @@ static gboolean filter_fg (PangoAttribute *attribute, gpointer data)
 }
 
 static PangoLayout *
-sc_gtk_clist_create_cell_layout (GtkCList       *clist,
-                              GtkCListRow    *clist_row,
+sc_gtk_cmclist_create_cell_layout (GtkCMCList       *clist,
+                              GtkCMCListRow    *clist_row,
                               gint            column)
 {
   PangoLayout *layout;
   GtkStyle *style;
-  GtkCell *cell;
+  GtkCMCell *cell;
   gchar *text;
   
   gtk_sctree_get_cell_style (clist, clist_row, GTK_STATE_NORMAL, 0, column, &style,
@@ -807,20 +807,20 @@ sc_gtk_clist_create_cell_layout (GtkCList       *clist,
   cell = &clist_row->cell[column];
   switch (cell->type)
     {
-    case GTK_CELL_TEXT:
-    case GTK_CELL_PIXTEXT:
-      text = ((cell->type == GTK_CELL_PIXTEXT) ?
-             GTK_CELL_PIXTEXT (*cell)->text :
-             GTK_CELL_TEXT (*cell)->text);
+    case GTK_CMCELL_TEXT:
+    case GTK_CMCELL_PIXTEXT:
+      text = ((cell->type == GTK_CMCELL_PIXTEXT) ?
+             GTK_CMCELL_PIXTEXT (*cell)->text :
+             GTK_CMCELL_TEXT (*cell)->text);
 
       if (!text)
        return NULL;
       
       if (!GTK_SCTREE(clist)->use_markup[column]) {
              layout = gtk_widget_create_pango_layout (GTK_WIDGET (clist),
-                                                      ((cell->type == GTK_CELL_PIXTEXT) ?
-                                                       GTK_CELL_PIXTEXT (*cell)->text :
-                                                       GTK_CELL_TEXT (*cell)->text));
+                                                      ((cell->type == GTK_CMCELL_PIXTEXT) ?
+                                                       GTK_CMCELL_PIXTEXT (*cell)->text :
+                                                       GTK_CMCELL_TEXT (*cell)->text));
              pango_layout_set_font_description (layout, style->font_desc);
       } else {
              PangoContext *context = gtk_widget_get_pango_context (GTK_WIDGET(clist));
@@ -845,13 +845,13 @@ sc_gtk_clist_create_cell_layout (GtkCList       *clist,
 }
 
 static void
-gtk_sctree_draw_row (GtkCList     *clist,
+gtk_sctree_draw_row (GtkCMCList     *clist,
          GdkRectangle *area,
          gint          row,
-         GtkCListRow  *clist_row)
+         GtkCMCListRow  *clist_row)
 {
   GtkWidget *widget;
-  GtkCTree  *ctree;
+  GtkCMCTree  *ctree;
   GdkRectangle *rect;
   GdkRectangle *crect;
   GdkRectangle row_rectangle;
@@ -897,7 +897,7 @@ gtk_sctree_draw_row (GtkCList     *clist,
     return;
 
   widget = GTK_WIDGET (clist);
-  ctree  = GTK_CTREE  (clist);
+  ctree  = GTK_CMCTREE  (clist);
 
   /* if the function is passed the pointer to the row instead of null,
    * it avoids this expensive lookup */
@@ -965,7 +965,7 @@ gtk_sctree_draw_row (GtkCList     *clist,
     }
 
   /* horizontal black lines */
-  if (ctree->line_style == GTK_CTREE_LINES_TABBED)
+  if (ctree->line_style == GTK_CMCTREE_LINES_TABBED)
     { 
 
       column_right = (COLUMN_LEFT_XPIXEL (clist, ctree->tree_column) +
@@ -980,7 +980,7 @@ gtk_sctree_draw_row (GtkCList     *clist,
        case GTK_JUSTIFY_FILL:
        case GTK_JUSTIFY_LEFT:
          offset = (column_left + ctree->tree_indent *
-                   (((GtkCTreeRow *)clist_row)->level - 1));
+                   (((GtkCMCTreeRow *)clist_row)->level - 1));
 
          gdk_draw_line (clist->clist_window, ctree->lines_gc, 
                         MIN (offset + TAB_SIZE, column_right),
@@ -989,7 +989,7 @@ gtk_sctree_draw_row (GtkCList     *clist,
          break;
        case GTK_JUSTIFY_RIGHT:
          offset = (column_right - 1 - ctree->tree_indent *
-                   (((GtkCTreeRow *)clist_row)->level - 1));
+                   (((GtkCMCTreeRow *)clist_row)->level - 1));
 
          gdk_draw_line (clist->clist_window, ctree->lines_gc,
                         -1, cell_rectangle.y,
@@ -1011,7 +1011,7 @@ gtk_sctree_draw_row (GtkCList     *clist,
                              crect->x, crect->y, crect->width, crect->height);
 
          /* horizontal black lines */
-         if (ctree->line_style == GTK_CTREE_LINES_TABBED)
+         if (ctree->line_style == GTK_CMCTREE_LINES_TABBED)
            { 
              switch (clist->column[ctree->tree_column].justification)
                {
@@ -1020,7 +1020,7 @@ gtk_sctree_draw_row (GtkCList     *clist,
                case GTK_JUSTIFY_LEFT:
                  gdk_draw_line (clist->clist_window, ctree->lines_gc, 
                                 MIN (column_left + TAB_SIZE + COLUMN_INSET +
-                                     (((GtkCTreeRow *)clist_row)->level > 1) *
+                                     (((GtkCMCTreeRow *)clist_row)->level > 1) *
                                      MIN (ctree->tree_indent / 2, TAB_SIZE),
                                      column_right),
                                 cell_rectangle.y,
@@ -1031,7 +1031,7 @@ gtk_sctree_draw_row (GtkCList     *clist,
                                 -1, cell_rectangle.y,
                                 MAX (column_right - TAB_SIZE - 1 -
                                      COLUMN_INSET -
-                                     (((GtkCTreeRow *)clist_row)->level > 1) *
+                                     (((GtkCMCTreeRow *)clist_row)->level > 1) *
                                      MIN (ctree->tree_indent / 2, TAB_SIZE),
                                      column_left - 1), cell_rectangle.y);
                  break;
@@ -1089,7 +1089,7 @@ gtk_sctree_draw_row (GtkCList     *clist,
                              crect->x, crect->y, crect->width, crect->height);
 
 
-         layout = sc_gtk_clist_create_cell_layout (clist, clist_row, i);
+         layout = sc_gtk_cmclist_create_cell_layout (clist, clist_row, i);
          if (layout)
            {
              pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
@@ -1100,28 +1100,28 @@ gtk_sctree_draw_row (GtkCList     *clist,
 
          switch (clist_row->cell[i].type)
            {
-           case GTK_CELL_PIXMAP:
-             gdk_window_get_size
-               (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap, &pixmap_width,
+           case GTK_CMCELL_PIXMAP:
+             gdk_drawable_get_size
+               (GTK_CMCELL_PIXMAP (clist_row->cell[i])->pixmap, &pixmap_width,
                 &height);
              width += pixmap_width;
              break;
-           case GTK_CELL_PIXTEXT:
-             if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
+           case GTK_CMCELL_PIXTEXT:
+             if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
                {
-                 gdk_window_get_size 
-                   (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
+                 gdk_drawable_get_size 
+                   (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
                     &pixmap_width, &height);
                  width += pixmap_width;
                }
 
-             if (GTK_CELL_PIXTEXT (clist_row->cell[i])->text &&
-                 GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
-               width +=  GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
+             if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->text &&
+                 GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+               width +=  GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
 
              if (i == ctree->tree_column)
                width += (ctree->tree_indent *
-                         ((GtkCTreeRow *)clist_row)->level);
+                         ((GtkCMCTreeRow *)clist_row)->level);
              break;
            default:
              break;
@@ -1146,35 +1146,35 @@ gtk_sctree_draw_row (GtkCList     *clist,
          if (i != ctree->tree_column)
            {
              int start_y = (clip_rectangle.height - height) / 2;
-             if (GTK_CLIST_ROW_HEIGHT_SET(GTK_CLIST(clist)))
+             if (GTK_CMCLIST_ROW_HEIGHT_SET(GTK_CMCLIST(clist)))
                      start_y = (clip_rectangle.height/2 - height) / 2;
 
              offset += clist_row->cell[i].horizontal;
              switch (clist_row->cell[i].type)
                {
-               case GTK_CELL_PIXMAP:
+               case GTK_CMCELL_PIXMAP:
                  gtk_sctree_draw_cell_pixmap
                    (clist->clist_window, &clip_rectangle, fg_gc,
-                    GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
-                    GTK_CELL_PIXMAP (clist_row->cell[i])->mask,
+                    GTK_CMCELL_PIXMAP (clist_row->cell[i])->pixmap,
+                    GTK_CMCELL_PIXMAP (clist_row->cell[i])->mask,
                     offset,
                     clip_rectangle.y + clist_row->cell[i].vertical +
                     start_y,
                     pixmap_width, height);
                  break;
-               case GTK_CELL_PIXTEXT:
+               case GTK_CMCELL_PIXTEXT:
                  offset = gtk_sctree_draw_cell_pixmap
                    (clist->clist_window, &clip_rectangle, fg_gc,
-                    GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
-                    GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
+                    GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+                    GTK_CMCELL_PIXTEXT (clist_row->cell[i])->mask,
                     offset,
                     clip_rectangle.y + clist_row->cell[i].vertical +
                     start_y,
                     pixmap_width, height);
-                 offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
+                 offset += GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
 
                  /* Fall through */
-               case GTK_CELL_TEXT:
+               case GTK_CMCELL_TEXT:
                  if (layout)
                    {
                      gint row_center_offset = (clist->row_height - logical_rect.height) / 2;
@@ -1211,12 +1211,12 @@ gtk_sctree_draw_row (GtkCList     *clist,
        }
 
       /* draw lines */
-      offset = gtk_sctree_draw_lines (ctree, (GtkCTreeRow *)clist_row, row, i,
+      offset = gtk_sctree_draw_lines (ctree, (GtkCMCTreeRow *)clist_row, row, i,
                                     state, &clip_rectangle, &cell_rectangle,
                                     crect, area, style);
 
       /* draw expander */
-      offset = gtk_sctree_draw_expander (ctree, (GtkCTreeRow *)clist_row,
+      offset = gtk_sctree_draw_expander (ctree, (GtkCMCTreeRow *)clist_row,
                                        style, &clip_rectangle, offset);
 
       if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
@@ -1231,8 +1231,8 @@ gtk_sctree_draw_row (GtkCList     *clist,
 
       old_offset = offset;
       offset = gtk_sctree_draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
-                                GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
-                                GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
+                                GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap,
+                                GTK_CMCELL_PIXTEXT (clist_row->cell[i])->mask,
                                 offset, 
                                 clip_rectangle.y + clist_row->cell[i].vertical
                                 + (clip_rectangle.height - height) / 2,
@@ -1245,13 +1245,13 @@ gtk_sctree_draw_row (GtkCList     *clist,
          if (clist->column[i].justification == GTK_JUSTIFY_RIGHT)
            {
              offset = (old_offset - string_width);
-             if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
-               offset -= GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
+             if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+               offset -= GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
            }
          else
            {
-             if (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap)
-               offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
+             if (GTK_CMCELL_PIXTEXT (clist_row->cell[i])->pixmap)
+               offset += GTK_CMCELL_PIXTEXT (clist_row->cell[i])->spacing;
            }
          
          gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
@@ -1287,51 +1287,51 @@ gtk_sctree_draw_row (GtkCList     *clist,
 }
 
 static void
-gtk_sctree_change_focus_row_expansion (GtkCTree          *ctree,
-                           GtkCTreeExpansionType action)
+gtk_sctree_change_focus_row_expansion (GtkCMCTree          *ctree,
+                           GtkCMCTreeExpansionType action)
 {
-  GtkCList *clist;
-  GtkCTreeNode *node;
+  GtkCMCList *clist;
+  GtkCMCTreeNode *node;
 
-  g_return_if_fail (GTK_IS_CTREE (ctree));
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
 
-  clist = GTK_CLIST (ctree);
+  clist = GTK_CMCLIST (ctree);
 
   if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (ctree))) && 
       GTK_WIDGET_HAS_GRAB (ctree))
     return;
   
   if (!(node =
-       GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row))) ||
-      GTK_CTREE_ROW (node)->is_leaf || !(GTK_CTREE_ROW (node)->children))
+       GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row))) ||
+      GTK_CMCTREE_ROW (node)->is_leaf || !(GTK_CMCTREE_ROW (node)->children))
     return;
 
   switch (action)
     {
-    case GTK_CTREE_EXPANSION_EXPAND:
+    case GTK_CMCTREE_EXPANSION_EXPAND:
       if (GTK_SCTREE(ctree)->always_expand_recursively)
-             gtk_ctree_expand_recursive (ctree, node);
+             gtk_cmctree_expand_recursive (ctree, node);
       else
-             gtk_ctree_expand (ctree, node);
+             gtk_cmctree_expand (ctree, node);
 
       break;
-    case GTK_CTREE_EXPANSION_EXPAND_RECURSIVE:
-      gtk_ctree_expand_recursive (ctree, node);
+    case GTK_CMCTREE_EXPANSION_EXPAND_RECURSIVE:
+      gtk_cmctree_expand_recursive (ctree, node);
       break;
-    case GTK_CTREE_EXPANSION_COLLAPSE:
-      gtk_ctree_collapse (ctree, node);
+    case GTK_CMCTREE_EXPANSION_COLLAPSE:
+      gtk_cmctree_collapse (ctree, node);
       break;
-    case GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE:
-      gtk_ctree_collapse_recursive (ctree, node);
+    case GTK_CMCTREE_EXPANSION_COLLAPSE_RECURSIVE:
+      gtk_cmctree_collapse_recursive (ctree, node);
       break;
-    case GTK_CTREE_EXPANSION_TOGGLE:
+    case GTK_CMCTREE_EXPANSION_TOGGLE:
       if (GTK_SCTREE(ctree)->always_expand_recursively)
-             gtk_ctree_toggle_expansion_recursive (ctree, node);
+             gtk_cmctree_toggle_expansion_recursive (ctree, node);
       else
-             gtk_ctree_toggle_expansion (ctree, node);
+             gtk_cmctree_toggle_expansion (ctree, node);
       break;
-    case GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE:
-      gtk_ctree_toggle_expansion_recursive (ctree, node);
+    case GTK_CMCTREE_EXPANSION_TOGGLE_RECURSIVE:
+      gtk_cmctree_toggle_expansion_recursive (ctree, node);
       break;
     }
 }
@@ -1351,15 +1351,15 @@ gtk_sctree_class_init (GtkSCTreeClass *klass)
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
        GtkObjectClass *object_class;
        GtkWidgetClass *widget_class;
-       GtkCListClass *clist_class;
-       GtkCTreeClass *ctree_class;
+       GtkCMCListClass *clist_class;
+       GtkCMCTreeClass *ctree_class;
 
        object_class = (GtkObjectClass *) klass;
        widget_class = (GtkWidgetClass *) klass;
-       clist_class = (GtkCListClass *) klass;
-       ctree_class = (GtkCTreeClass *) klass;
+       clist_class = (GtkCMCListClass *) klass;
+       ctree_class = (GtkCMCTreeClass *) klass;
 
-       parent_class = gtk_type_class (gtk_ctree_get_type ());
+       parent_class = gtk_type_class (gtk_cmctree_get_type ());
 
        sctree_signals[ROW_POPUP_MENU] =
                g_signal_new ("row_popup_menu",
@@ -1428,7 +1428,7 @@ gtk_sctree_init (GtkSCTree *sctree)
 {
        sctree->anchor_row = NULL;
 
-       /* GtkCTree does not specify pointer motion by default */
+       /* GtkCMCTree does not specify pointer motion by default */
        gtk_widget_add_events (GTK_WIDGET (sctree), GDK_POINTER_MOTION_MASK);
        gtk_widget_add_events (GTK_WIDGET (sctree), GDK_POINTER_MOTION_MASK);
 }
@@ -1438,8 +1438,8 @@ gtk_sctree_init (GtkSCTree *sctree)
 static gboolean
 row_is_selected(GtkSCTree *sctree, gint row)
 {
-       GtkCListRow *clist_row;
-       clist_row =  g_list_nth (GTK_CLIST(sctree)->row_list, row)->data;
+       GtkCMCListRow *clist_row;
+       clist_row =  g_list_nth (GTK_CMCLIST(sctree)->row_list, row)->data;
        return clist_row ? clist_row->state == GTK_STATE_SELECTED : FALSE;
 }
 
@@ -1453,15 +1453,15 @@ select_range (GtkSCTree *sctree, gint row)
        GList *node;
        if (sctree->anchor_row == NULL) {
                prev_row = row;
-               sctree->anchor_row = gtk_ctree_node_nth(GTK_CTREE(sctree), row);
+               sctree->anchor_row = gtk_cmctree_node_nth(GTK_CMCTREE(sctree), row);
        } else
-               prev_row = g_list_position(GTK_CLIST(sctree)->row_list,
+               prev_row = g_list_position(GTK_CMCLIST(sctree)->row_list,
                                           (GList *)sctree->anchor_row);
 
        if (row < prev_row) {
                min = row;
                max = prev_row;
-               GTK_CLIST(sctree)->focus_row = max;
+               GTK_CMCLIST(sctree)->focus_row = max;
        } else {
                min = prev_row;
                max = row;
@@ -1475,60 +1475,60 @@ select_range (GtkSCTree *sctree, gint row)
        }
        
        if (max - min > 10)
-               gtk_clist_freeze(GTK_CLIST(sctree));
+               gtk_cmclist_freeze(GTK_CMCLIST(sctree));
 
-       node = g_list_nth((GTK_CLIST(sctree))->row_list, min);
+       node = g_list_nth((GTK_CMCLIST(sctree))->row_list, min);
        for (i = min; i < max; i++) {
-               if (node && GTK_CTREE_ROW (node)->row.selectable) {
+               if (node && GTK_CMCTREE_ROW (node)->row.selectable) {
                        g_signal_emit_by_name(G_OBJECT(sctree), "tree_select_row",
                                node, -1);
                }
                node = node->next;
        }
        if (max - min > 10)
-               gtk_clist_thaw(GTK_CLIST(sctree));
+               gtk_cmclist_thaw(GTK_CMCLIST(sctree));
 
 
        sctree->selecting_range--;
-       gtk_clist_select_row (GTK_CLIST (sctree), max, -1);
+       gtk_cmclist_select_row (GTK_CMCLIST (sctree), max, -1);
 }
 
 /* Handles row selection according to the specified modifier state */
-/* in certain cases, we arrive here from a function knowing the GtkCTreeNode, and having
+/* in certain cases, we arrive here from a function knowing the GtkCMCTreeNode, and having
  * already slowly found row using g_list_position. In which case, _node will be non-NULL
  * to avoid this function having to slowly find it with g_list_nth. */
 static void
-select_row (GtkSCTree *sctree, gint row, gint col, guint state, GtkCTreeNode *_node)
+select_row (GtkSCTree *sctree, gint row, gint col, guint state, GtkCMCTreeNode *_node)
 {
        gboolean range, additive;
        g_return_if_fail (sctree != NULL);
        g_return_if_fail (GTK_IS_SCTREE (sctree));
     
        range = ((state & GDK_SHIFT_MASK) != 0) &&
-               (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_SINGLE) &&
-               (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_BROWSE);
+               (GTK_CMCLIST(sctree)->selection_mode != GTK_SELECTION_SINGLE) &&
+               (GTK_CMCLIST(sctree)->selection_mode != GTK_SELECTION_BROWSE);
        additive = ((state & GDK_CONTROL_MASK) != 0) &&
-                  (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_SINGLE) &&
-                  (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_BROWSE);
+                  (GTK_CMCLIST(sctree)->selection_mode != GTK_SELECTION_SINGLE) &&
+                  (GTK_CMCLIST(sctree)->selection_mode != GTK_SELECTION_BROWSE);
 
        if (!range && !additive && sctree->force_additive_sel)
                additive = TRUE;
 
-       GTK_CLIST(sctree)->focus_row = row;
+       GTK_CMCLIST(sctree)->focus_row = row;
 
        if (!additive) {
-               gtk_clist_unselect_all (GTK_CLIST (sctree));
+               gtk_cmclist_unselect_all (GTK_CMCLIST (sctree));
        }
 
        if (!range) {
-               GtkCTreeNode *node;
+               GtkCMCTreeNode *node;
 
-               node = _node ? _node : gtk_ctree_node_nth (GTK_CTREE(sctree), row);
+               node = _node ? _node : gtk_cmctree_node_nth (GTK_CMCTREE(sctree), row);
 
                /*No need to manage overlapped list*/
                if (additive) {
                        if (row_is_selected(sctree, row))
-                               gtk_clist_unselect_row (GTK_CLIST (sctree), row, col);
+                               gtk_cmclist_unselect_row (GTK_CMCLIST (sctree), row, col);
                        else
                                g_signal_emit_by_name
                                        (G_OBJECT (sctree),
@@ -1545,33 +1545,33 @@ select_row (GtkSCTree *sctree, gint row, gint col, guint state, GtkCTreeNode *_n
 
 static gboolean
 sctree_is_hot_spot (GtkSCTree     *sctree, 
-                  GtkCTreeNode *node,
+                  GtkCMCTreeNode *node,
                   gint          row, 
                   gint          x, 
                   gint          y)
 {
-  GtkCTreeRow *tree_row;
-  GtkCList *clist;
-  GtkCTree *ctree;
-  GtkCellPixText *cell;
+  GtkCMCTreeRow *tree_row;
+  GtkCMCList *clist;
+  GtkCMCTree *ctree;
+  GtkCMCellPixText *cell;
   gint xl, xmax;
   gint yu;
   
   g_return_val_if_fail (GTK_IS_SCTREE (sctree), FALSE);
   g_return_val_if_fail (node != NULL, FALSE);
 
-  clist = GTK_CLIST (sctree);
-  ctree = GTK_CTREE (sctree);
+  clist = GTK_CMCLIST (sctree);
+  ctree = GTK_CMCTREE (sctree);
 
   if (!clist->column[ctree->tree_column].visible ||
-      ctree->expander_style == GTK_CTREE_EXPANDER_NONE)
+      ctree->expander_style == GTK_CMCTREE_EXPANDER_NONE)
     return FALSE;
 
-  tree_row = GTK_CTREE_ROW (node);
+  tree_row = GTK_CMCTREE_ROW (node);
 
-  cell = GTK_CELL_PIXTEXT (tree_row->row.cell[ctree->tree_column]);
+  cell = GTK_CMCELL_PIXTEXT (tree_row->row.cell[ctree->tree_column]);
 
-  if (!GTK_CLIST_ROW_HEIGHT_SET(GTK_CLIST(clist)))
+  if (!GTK_CMCLIST_ROW_HEIGHT_SET(GTK_CMCLIST(clist)))
      yu = (ROW_TOP_YPIXEL (clist, row) + (clist->row_height - PM_SIZE) / 2 -
        (clist->row_height - 1) % 2);
   else
@@ -1583,11 +1583,11 @@ sctree_is_hot_spot (GtkSCTree     *sctree,
     xl = (clist->column[ctree->tree_column].area.x + 
          clist->column[ctree->tree_column].area.width - 1 + clist->hoffset -
          (tree_row->level - 1) * ctree->tree_indent - PM_SIZE -
-         (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
+         (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
   else
     xl = (clist->column[ctree->tree_column].area.x + clist->hoffset +
          (tree_row->level - 1) * ctree->tree_indent +
-         (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
+         (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
 
   xmax = xl + PM_SIZE;
 #else
@@ -1595,19 +1595,19 @@ sctree_is_hot_spot (GtkSCTree     *sctree,
     xl = (clist->column[ctree->tree_column].area.x + 
          clist->column[ctree->tree_column].area.width - 1 + clist->hoffset -
          (tree_row->level - 1) * ctree->tree_indent - PM_SIZE -
-         (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
+         (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
     xmax = xl + PM_SIZE;
   } else if (ctree->tree_column == 0) {
     xl = (clist->column[ctree->tree_column].area.x + clist->hoffset +
-         (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
+         (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
     xmax = (clist->column[ctree->tree_column].area.x + clist->hoffset +
           (tree_row->level - 1) * ctree->tree_indent +
-          (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3) +
+          (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3) +
           PM_SIZE;
   } else {
     xl = (clist->column[ctree->tree_column].area.x + clist->hoffset +
          (tree_row->level - 1) * ctree->tree_indent +
-         (ctree->line_style == GTK_CTREE_LINES_TABBED) * 3);
+         (ctree->line_style == GTK_CMCTREE_LINES_TABBED) * 3);
     xmax = xl + PM_SIZE;
   }
 #endif
@@ -1619,27 +1619,27 @@ gtk_sctree_is_hot_spot (GtkSCTree *ctree,
                       gint      x, 
                       gint      y)
 {
-  GtkCTreeNode *node;
+  GtkCMCTreeNode *node;
   gint column;
   gint row;
   
   g_return_val_if_fail (GTK_IS_SCTREE (ctree), FALSE);
 
-  if (gtk_clist_get_selection_info (GTK_CLIST (ctree), x, y, &row, &column))
-    if ((node = GTK_CTREE_NODE(g_list_nth (GTK_CLIST (ctree)->row_list, row))))
+  if (gtk_cmclist_get_selection_info (GTK_CMCLIST (ctree), x, y, &row, &column))
+    if ((node = GTK_CMCTREE_NODE(g_list_nth (GTK_CMCLIST (ctree)->row_list, row))))
       return sctree_is_hot_spot (ctree, node, row, x, y);
 
   return FALSE;
 }
 
-/* Our handler for button_press events.  We override all of GtkCList's broken
+/* Our handler for button_press events.  We override all of GtkCMCList's broken
  * behavior.
  */
 static gint
 gtk_sctree_button_press (GtkWidget *widget, GdkEventButton *event)
 {
        GtkSCTree *sctree;
-       GtkCList *clist;
+       GtkCMCList *clist;
        gboolean on_row;
        gint row;
        gint col;
@@ -1650,25 +1650,25 @@ gtk_sctree_button_press (GtkWidget *widget, GdkEventButton *event)
        g_return_val_if_fail (event != NULL, FALSE);
 
        sctree = GTK_SCTREE (widget);
-       clist = GTK_CLIST (widget);
+       clist = GTK_CMCLIST (widget);
        retval = FALSE;
 
        if (event->window != clist->clist_window)
                return (* GTK_WIDGET_CLASS (parent_class)->button_press_event) (widget, event);
 
-       on_row = gtk_clist_get_selection_info (clist, event->x, event->y, &row, &col);
+       on_row = gtk_cmclist_get_selection_info (clist, event->x, event->y, &row, &col);
 
        if (on_row && !GTK_WIDGET_HAS_FOCUS(widget))
                gtk_widget_grab_focus (widget);
 
        if (gtk_sctree_is_hot_spot (GTK_SCTREE(sctree), event->x, event->y)) {
-               GtkCTreeNode *node = gtk_ctree_node_nth(GTK_CTREE(sctree), row);
-               if (GTK_CTREE_ROW (node)->expanded)
-                       gtk_ctree_collapse(GTK_CTREE(sctree), node);
+               GtkCMCTreeNode *node = gtk_cmctree_node_nth(GTK_CMCTREE(sctree), row);
+               if (GTK_CMCTREE_ROW (node)->expanded)
+                       gtk_cmctree_collapse(GTK_CMCTREE(sctree), node);
                else if (GTK_SCTREE(sctree)->always_expand_recursively)
-                       gtk_ctree_expand_recursive (GTK_CTREE(sctree), node);
+                       gtk_cmctree_expand_recursive (GTK_CMCTREE(sctree), node);
                else
-                       gtk_ctree_expand(GTK_CTREE(sctree), node);
+                       gtk_cmctree_expand(GTK_CMCTREE(sctree), node);
                return TRUE;
        }
 
@@ -1695,7 +1695,7 @@ gtk_sctree_button_press (GtkWidget *widget, GdkEventButton *event)
                                        select_row (sctree, row, col, event->state, NULL);
                                }
                        } else {
-                               gtk_clist_unselect_all (clist);
+                               gtk_cmclist_unselect_all (clist);
                        }
 
                        retval = TRUE;
@@ -1708,7 +1708,7 @@ gtk_sctree_button_press (GtkWidget *widget, GdkEventButton *event)
                                                 sctree_signals[ROW_POPUP_MENU],
                                                 0, event);
                        } else {
-                               gtk_clist_unselect_all(clist);
+                               gtk_cmclist_unselect_all(clist);
                                g_signal_emit (G_OBJECT (sctree),
                                                 sctree_signals[EMPTY_POPUP_MENU],
                                                 0, event);
@@ -1739,14 +1739,14 @@ gtk_sctree_button_press (GtkWidget *widget, GdkEventButton *event)
        return retval;
 }
 
-/* Our handler for button_release events.  We override all of GtkCList's broken
+/* Our handler for button_release events.  We override all of GtkCMCList's broken
  * behavior.
  */
 static gint
 gtk_sctree_button_release (GtkWidget *widget, GdkEventButton *event)
 {
        GtkSCTree *sctree;
-       GtkCList *clist;
+       GtkCMCList *clist;
        gint on_row;
        gint row, col;
        gint retval;
@@ -1756,13 +1756,13 @@ gtk_sctree_button_release (GtkWidget *widget, GdkEventButton *event)
        g_return_val_if_fail (event != NULL, FALSE);
 
        sctree = GTK_SCTREE (widget);
-       clist = GTK_CLIST (widget);
+       clist = GTK_CMCLIST (widget);
        retval = FALSE;
 
        if (event->window != clist->clist_window)
                return (* GTK_WIDGET_CLASS (parent_class)->button_release_event) (widget, event);
 
-       on_row = gtk_clist_get_selection_info (clist, event->x, event->y, &row, &col);
+       on_row = gtk_cmclist_get_selection_info (clist, event->x, event->y, &row, &col);
 
        if (!(event->button == 1 || event->button == 2))
                return FALSE;
@@ -1784,21 +1784,21 @@ gtk_sctree_button_release (GtkWidget *widget, GdkEventButton *event)
        return retval;
 }
 
-/* Our handler for motion_notify events.  We override all of GtkCList's broken
+/* Our handler for motion_notify events.  We override all of GtkCMCList's broken
  * behavior.
  */
 static gint
 gtk_sctree_motion (GtkWidget *widget, GdkEventMotion *event)
 {
        GtkSCTree *sctree;
-       GtkCList *clist;
+       GtkCMCList *clist;
 
        g_return_val_if_fail (widget != NULL, FALSE);
        g_return_val_if_fail (GTK_IS_SCTREE (widget), FALSE);
        g_return_val_if_fail (event != NULL, FALSE);
 
        sctree = GTK_SCTREE (widget);
-       clist = GTK_CLIST (widget);
+       clist = GTK_CMCLIST (widget);
 
        if (event->window != clist->clist_window)
                return (* GTK_WIDGET_CLASS (parent_class)->motion_notify_event) (widget, event);
@@ -1898,7 +1898,7 @@ gtk_sctree_drag_data_received (GtkWidget *widget, GdkDragContext *context,
  * to null.
  */
 static void
-gtk_sctree_clear (GtkCList *clist)
+gtk_sctree_clear (GtkCMCList *clist)
 {
        GtkSCTree *sctree;
 
@@ -1908,12 +1908,12 @@ gtk_sctree_clear (GtkCList *clist)
        sctree = GTK_SCTREE (clist);
        sctree->anchor_row = NULL;
 
-       if (((GtkCListClass *)parent_class)->clear)
-               (* ((GtkCListClass *)parent_class)->clear) (clist);
+       if (((GtkCMCListClass *)parent_class)->clear)
+               (* ((GtkCMCListClass *)parent_class)->clear) (clist);
 }
 
 static void
-gtk_sctree_real_unselect_all (GtkCList *clist)
+gtk_sctree_real_unselect_all (GtkCMCList *clist)
 {
        GtkSCTree *sctree;
        gboolean should_freeze = FALSE;
@@ -1923,17 +1923,17 @@ gtk_sctree_real_unselect_all (GtkCList *clist)
 
        sctree = GTK_SCTREE (clist);
 
-       if (sc_g_list_bigger(GTK_CLIST(sctree)->selection, 10)) {
+       if (sc_g_list_bigger(GTK_CMCLIST(sctree)->selection, 10)) {
                should_freeze = TRUE;
                sctree->selecting_range++;
-               gtk_clist_freeze (GTK_CLIST (sctree));
+               gtk_cmclist_freeze (GTK_CMCLIST (sctree));
        }
 
-       if (((GtkCListClass *)parent_class)->unselect_all)
-               (* ((GtkCListClass *)parent_class)->unselect_all) (clist);
+       if (((GtkCMCListClass *)parent_class)->unselect_all)
+               (* ((GtkCMCListClass *)parent_class)->unselect_all) (clist);
 
        if (should_freeze) {
-               gtk_clist_thaw (GTK_CLIST (sctree));
+               gtk_cmclist_thaw (GTK_CMCLIST (sctree));
                sctree->selecting_range--;
        }
 }
@@ -1942,14 +1942,14 @@ gtk_sctree_real_unselect_all (GtkCList *clist)
  We have to set the anchor to parent visible node.
  */
 static void 
-gtk_sctree_collapse (GtkCTree *ctree, GtkCTreeNode *node)
+gtk_sctree_collapse (GtkCMCTree *ctree, GtkCMCTreeNode *node)
 {
        g_return_if_fail (ctree != NULL);
        g_return_if_fail (GTK_IS_SCTREE (ctree));
 
         (* parent_class->tree_collapse) (ctree, node);
        GTK_SCTREE(ctree)->anchor_row =
-               gtk_ctree_node_nth(ctree, GTK_CLIST(ctree)->focus_row);
+               gtk_cmctree_node_nth(ctree, GTK_CMCLIST(ctree)->focus_row);
 }
 
 GtkWidget *gtk_sctree_new_with_titles (gint columns, gint tree_column, 
@@ -1965,12 +1965,12 @@ GtkWidget *gtk_sctree_new_with_titles (gint columns, gint tree_column,
                                 "tree_column", tree_column,
                                 NULL);
        if (titles) {
-               GtkCList *clist = GTK_CLIST (widget);
+               GtkCMCList *clist = GTK_CMCLIST (widget);
                guint i;
 
                for (i = 0; i < columns; i++)
-                       gtk_clist_set_column_title (clist, i, titles[i]);
-               gtk_clist_column_titles_show (clist);
+                       gtk_cmclist_set_column_title (clist, i, titles[i]);
+               gtk_cmclist_column_titles_show (clist);
        }
 
        GTK_SCTREE(widget)->show_stripes = TRUE;
@@ -2001,36 +2001,36 @@ void gtk_sctree_set_use_markup              (GtkSCTree          *sctree,
        sctree->use_markup[column] = markup;
 }
 
-void gtk_sctree_select (GtkSCTree *sctree, GtkCTreeNode *node)
+void gtk_sctree_select (GtkSCTree *sctree, GtkCMCTreeNode *node)
 {
        select_row(sctree, 
-                  g_list_position(GTK_CLIST(sctree)->row_list, (GList *)node),
+                  g_list_position(GTK_CMCLIST(sctree)->row_list, (GList *)node),
                   -1, 0, node);
 }
 
-void gtk_sctree_select_with_state (GtkSCTree *sctree, GtkCTreeNode *node, int state)
+void gtk_sctree_select_with_state (GtkSCTree *sctree, GtkCMCTreeNode *node, int state)
 {
        select_row(sctree, 
-                  g_list_position(GTK_CLIST(sctree)->row_list, (GList *)node),
+                  g_list_position(GTK_CMCLIST(sctree)->row_list, (GList *)node),
                   -1, state, node);
 }
 
 void gtk_sctree_unselect_all (GtkSCTree *sctree)
 {
-       gtk_clist_unselect_all(GTK_CLIST(sctree));
+       gtk_cmclist_unselect_all(GTK_CMCLIST(sctree));
        sctree->anchor_row = NULL;
 }
 
-void gtk_sctree_set_anchor_row (GtkSCTree *sctree, GtkCTreeNode *node)
+void gtk_sctree_set_anchor_row (GtkSCTree *sctree, GtkCMCTreeNode *node)
 {
        sctree->anchor_row = node;
 }
 
-void gtk_sctree_remove_node (GtkSCTree *sctree, GtkCTreeNode *node)
+void gtk_sctree_remove_node (GtkSCTree *sctree, GtkCMCTreeNode *node)
 {
        if (sctree->anchor_row == node)
                sctree->anchor_row = NULL;
-       gtk_ctree_remove_node(GTK_CTREE(sctree), node);
+       gtk_cmctree_remove_node(GTK_CMCTREE(sctree), node);
 }
 
 void gtk_sctree_set_stripes(GtkSCTree  *sctree, gboolean show_stripes)
@@ -2047,10 +2047,10 @@ void gtk_sctree_set_recursive_expand(GtkSCTree  *sctree, gboolean rec_exp)
  *             Tree sorting functions                      *
  ***********************************************************/
 
-static void sink(GtkCList *clist, GPtrArray *numbers, gint root, gint bottom)
+static void sink(GtkCMCList *clist, GPtrArray *numbers, gint root, gint bottom)
 {
        gint j, k ;
-       GtkCTreeNode *temp;
+       GtkCMCTreeNode *temp;
 
        j = 2 * root;
        k = j + 1;
@@ -2058,12 +2058,12 @@ static void sink(GtkCList *clist, GPtrArray *numbers, gint root, gint bottom)
        /* find the maximum element of numbers[root],
           numbers[2*root] and numbers[2*root+1] */
        if (j <= bottom) {
-               if (clist->compare( clist, GTK_CTREE_ROW (g_ptr_array_index(numbers, root)),
-                                   GTK_CTREE_ROW(g_ptr_array_index( numbers, j))) >= 0)
+               if (clist->compare( clist, GTK_CMCTREE_ROW (g_ptr_array_index(numbers, root)),
+                                   GTK_CMCTREE_ROW(g_ptr_array_index( numbers, j))) >= 0)
                        j = root;
                if (k <= bottom)
-                       if (clist->compare( clist, GTK_CTREE_ROW (g_ptr_array_index(numbers, k)),
-                                           GTK_CTREE_ROW (g_ptr_array_index( numbers, j))) > 0)
+                       if (clist->compare( clist, GTK_CMCTREE_ROW (g_ptr_array_index(numbers, k)),
+                                           GTK_CMCTREE_ROW (g_ptr_array_index( numbers, j))) > 0)
                                j = k;
                /* if numbers[root] wasn't the maximum element then
                   sink again */
@@ -2076,10 +2076,10 @@ static void sink(GtkCList *clist, GPtrArray *numbers, gint root, gint bottom)
        }
 }
 
-static void heap_sort(GtkCList *clist, GPtrArray *numbers, gint array_size)
+static void heap_sort(GtkCMCList *clist, GPtrArray *numbers, gint array_size)
 {
        gint i;
-       GtkCTreeNode *temp;
+       GtkCMCTreeNode *temp;
        
        /* build the Heap */
        for (i = (array_size / 2); i >= 1; i--)
@@ -2094,21 +2094,21 @@ static void heap_sort(GtkCList *clist, GPtrArray *numbers, gint array_size)
 }
 
 static void
-stree_sort (GtkCTree    *ctree,
-          GtkCTreeNode *node,
+stree_sort (GtkCMCTree    *ctree,
+          GtkCMCTreeNode *node,
           gpointer      data)
 {
-       GtkCTreeNode *list_start, *work, *next;
+       GtkCMCTreeNode *list_start, *work, *next;
        GPtrArray *row_array, *viewable_array;
-       GtkCList *clist;
+       GtkCMCList *clist;
        gint i;
 
-       clist = GTK_CLIST (ctree);
+       clist = GTK_CMCLIST (ctree);
 
        if (node)
-               work = GTK_CTREE_ROW (node)->children;
+               work = GTK_CMCTREE_ROW (node)->children;
        else
-               work = GTK_CTREE_NODE (clist->row_list);
+               work = GTK_CMCTREE_NODE (clist->row_list);
 
        row_array = g_ptr_array_new();
        viewable_array = g_ptr_array_new();
@@ -2118,9 +2118,9 @@ stree_sort (GtkCTree    *ctree,
                while (work) {
                        /* add all rows to row_array */
                        g_ptr_array_add( row_array, work);
-                       if (GTK_CTREE_ROW (work)->parent && gtk_ctree_is_viewable( ctree, work))
-                               g_ptr_array_add( viewable_array, GTK_CTREE_ROW (work)->parent);
-                       next = GTK_CTREE_ROW (work)->sibling;
+                       if (GTK_CMCTREE_ROW (work)->parent && gtk_cmctree_is_viewable( ctree, work))
+                               g_ptr_array_add( viewable_array, GTK_CMCTREE_ROW (work)->parent);
+                       next = GTK_CMCTREE_ROW (work)->sibling;
                        gtk_sctree_unlink( ctree, work, FALSE);
                        work = next;
                }
@@ -2128,9 +2128,9 @@ stree_sort (GtkCTree    *ctree,
                heap_sort( clist, row_array, (row_array->len)-1);
 
                if (node)
-                       list_start = GTK_CTREE_ROW (node)->children;
+                       list_start = GTK_CMCTREE_ROW (node)->children;
                else
-                       list_start = GTK_CTREE_NODE (clist->row_list);
+                       list_start = GTK_CMCTREE_NODE (clist->row_list);
 
                if (clist->sort_type == GTK_SORT_ASCENDING) {
                        for (i=(row_array->len)-1; i>=1; i--) {
@@ -2149,7 +2149,7 @@ stree_sort (GtkCTree    *ctree,
                }
 
                for (i=0; i<viewable_array->len; i++) {
-                       gtk_ctree_expand( ctree, g_ptr_array_index( viewable_array, i));
+                       gtk_cmctree_expand( ctree, g_ptr_array_index( viewable_array, i));
                }
                
        }
@@ -2158,21 +2158,21 @@ stree_sort (GtkCTree    *ctree,
 }
 
 void
-gtk_sctree_sort_recursive (GtkCTree     *ctree, 
-                         GtkCTreeNode *node)
+gtk_sctree_sort_recursive (GtkCMCTree     *ctree, 
+                         GtkCMCTreeNode *node)
 {
-       GtkCList *clist;
-       GtkCTreeNode *focus_node = NULL;
+       GtkCMCList *clist;
+       GtkCMCTreeNode *focus_node = NULL;
 
        g_return_if_fail (ctree != NULL);
-       g_return_if_fail (GTK_IS_CTREE (ctree));
+       g_return_if_fail (GTK_IS_CMCTREE (ctree));
 
-       clist = GTK_CLIST (ctree);
+       clist = GTK_CMCLIST (ctree);
 
-       gtk_clist_freeze (clist);
+       gtk_cmclist_freeze (clist);
 
        if (clist->selection_mode == GTK_SELECTION_EXTENDED) {
-               GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+               GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
       
                g_list_free (clist->undo_selection);
                g_list_free (clist->undo_unselection);
@@ -2180,12 +2180,12 @@ gtk_sctree_sort_recursive (GtkCTree     *ctree,
                clist->undo_unselection = NULL;
        }
 
-       if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
-               focus_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
+       if (!node || (node && gtk_cmctree_is_viewable (ctree, node)))
+               focus_node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
       
        GTK_SCTREE(ctree)->sorting = TRUE;
 
-       gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (stree_sort), NULL);
+       gtk_cmctree_post_recursive (ctree, node, GTK_CMCTREE_FUNC (stree_sort), NULL);
 
        if (!node)
                stree_sort (ctree, NULL, NULL);
@@ -2197,25 +2197,25 @@ gtk_sctree_sort_recursive (GtkCTree     *ctree,
                clist->undo_anchor = clist->focus_row;
        }
 
-       gtk_clist_thaw (clist);
+       gtk_cmclist_thaw (clist);
 }
 
 void
-gtk_sctree_sort_node (GtkCTree     *ctree, 
-                    GtkCTreeNode *node)
+gtk_sctree_sort_node (GtkCMCTree     *ctree, 
+                    GtkCMCTreeNode *node)
 {
-       GtkCList *clist;
-       GtkCTreeNode *focus_node = NULL;
+       GtkCMCList *clist;
+       GtkCMCTreeNode *focus_node = NULL;
 
        g_return_if_fail (ctree != NULL);
-       g_return_if_fail (GTK_IS_CTREE (ctree));
+       g_return_if_fail (GTK_IS_CMCTREE (ctree));
 
-       clist = GTK_CLIST (ctree);
+       clist = GTK_CMCLIST (ctree);
 
-       gtk_clist_freeze (clist);
+       gtk_cmclist_freeze (clist);
 
        if (clist->selection_mode == GTK_SELECTION_EXTENDED) {
-               GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+               GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
                g_list_free (clist->undo_selection);
                g_list_free (clist->undo_unselection);
@@ -2223,8 +2223,8 @@ gtk_sctree_sort_node (GtkCTree     *ctree,
                clist->undo_unselection = NULL;
        }
 
-       if (!node || (node && gtk_ctree_is_viewable (ctree, node)))
-               focus_node = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
+       if (!node || (node && gtk_cmctree_is_viewable (ctree, node)))
+               focus_node = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
 
        GTK_SCTREE(ctree)->sorting = TRUE;
 
@@ -2237,32 +2237,32 @@ gtk_sctree_sort_node (GtkCTree     *ctree,
                clist->undo_anchor = clist->focus_row;
        }
 
-       gtk_clist_thaw (clist);
+       gtk_cmclist_thaw (clist);
 }
 
 /************************************************************************/
 
 static void
-gtk_sctree_unlink (GtkCTree     *ctree, 
-                 GtkCTreeNode *node,
+gtk_sctree_unlink (GtkCMCTree     *ctree, 
+                 GtkCMCTreeNode *node,
                   gboolean      update_focus_row)
 {
-       GtkCList *clist;
+       GtkCMCList *clist;
        gint rows;
        gint level;
        gint visible;
-       GtkCTreeNode *work;
-       GtkCTreeNode *parent;
+       GtkCMCTreeNode *work;
+       GtkCMCTreeNode *parent;
        GList *list;
 
        g_return_if_fail (ctree != NULL);
-       g_return_if_fail (GTK_IS_CTREE (ctree));
+       g_return_if_fail (GTK_IS_CMCTREE (ctree));
        g_return_if_fail (node != NULL);
 
-       clist = GTK_CLIST (ctree);
+       clist = GTK_CMCLIST (ctree);
   
        if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED) {
-               GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+               GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
                g_list_free (clist->undo_selection);
                g_list_free (clist->undo_unselection);
@@ -2270,20 +2270,20 @@ gtk_sctree_unlink (GtkCTree     *ctree,
                clist->undo_unselection = NULL;
        }
 
-       visible = gtk_ctree_is_viewable (ctree, node);
+       visible = gtk_cmctree_is_viewable (ctree, node);
 
        /* clist->row_list_end unlinked ? */
-       if (visible && (GTK_CTREE_NODE_NEXT (node) == NULL ||
-          (GTK_CTREE_ROW (node)->children && gtk_ctree_is_ancestor (ctree, node,
-           GTK_CTREE_NODE (clist->row_list_end)))))
-               clist->row_list_end = (GList *) (GTK_CTREE_NODE_PREV (node));
+       if (visible && (GTK_CMCTREE_NODE_NEXT (node) == NULL ||
+          (GTK_CMCTREE_ROW (node)->children && gtk_cmctree_is_ancestor (ctree, node,
+           GTK_CMCTREE_NODE (clist->row_list_end)))))
+               clist->row_list_end = (GList *) (GTK_CMCTREE_NODE_PREV (node));
 
        /* update list */
        rows = 0;
-       level = GTK_CTREE_ROW (node)->level;
-       work = GTK_CTREE_NODE_NEXT (node);
-       while (work && GTK_CTREE_ROW (work)->level > level) {
-               work = GTK_CTREE_NODE_NEXT (work);
+       level = GTK_CMCTREE_ROW (node)->level;
+       work = GTK_CMCTREE_NODE_NEXT (node);
+       while (work && GTK_CMCTREE_ROW (work)->level > level) {
+               work = GTK_CMCTREE_NODE_NEXT (work);
                rows++;
        }
 
@@ -2296,7 +2296,7 @@ gtk_sctree_unlink (GtkCTree     *ctree,
                        if (pos + rows < clist->focus_row)
                                clist->focus_row -= (rows + 1);
                        else if (pos <= clist->focus_row) {
-                               if (!GTK_CTREE_ROW (node)->sibling)
+                               if (!GTK_CMCTREE_ROW (node)->sibling)
                                        clist->focus_row = MAX (pos - 1, 0);
                                else
                                        clist->focus_row = pos;
@@ -2308,55 +2308,55 @@ gtk_sctree_unlink (GtkCTree     *ctree,
        }
 
        if (work) {
-               list = (GList *)GTK_CTREE_NODE_PREV (work);
+               list = (GList *)GTK_CMCTREE_NODE_PREV (work);
                list->next = NULL;
                list = (GList *)work;
-               list->prev = (GList *)GTK_CTREE_NODE_PREV (node);
+               list->prev = (GList *)GTK_CMCTREE_NODE_PREV (node);
        }
 
-       if (GTK_CTREE_NODE_PREV (node) &&
-           GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (node)) == node) {
-               list = (GList *)GTK_CTREE_NODE_PREV (node);
+       if (GTK_CMCTREE_NODE_PREV (node) &&
+           GTK_CMCTREE_NODE_NEXT (GTK_CMCTREE_NODE_PREV (node)) == node) {
+               list = (GList *)GTK_CMCTREE_NODE_PREV (node);
                list->next = (GList *)work;
        }
 
        /* update tree */
-       parent = GTK_CTREE_ROW (node)->parent;
+       parent = GTK_CMCTREE_ROW (node)->parent;
        if (parent) {
-               if (GTK_CTREE_ROW (parent)->children == node) {
-                       GTK_CTREE_ROW (parent)->children = GTK_CTREE_ROW (node)->sibling;
+               if (GTK_CMCTREE_ROW (parent)->children == node) {
+                       GTK_CMCTREE_ROW (parent)->children = GTK_CMCTREE_ROW (node)->sibling;
                }
                else {
-                       GtkCTreeNode *sibling;
+                       GtkCMCTreeNode *sibling;
 
-                       sibling = GTK_CTREE_ROW (parent)->children;
-                       while (GTK_CTREE_ROW (sibling)->sibling != node)
-                               sibling = GTK_CTREE_ROW (sibling)->sibling;
-                       GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
+                       sibling = GTK_CMCTREE_ROW (parent)->children;
+                       while (GTK_CMCTREE_ROW (sibling)->sibling != node)
+                               sibling = GTK_CMCTREE_ROW (sibling)->sibling;
+                       GTK_CMCTREE_ROW (sibling)->sibling = GTK_CMCTREE_ROW (node)->sibling;
                }
        }
        else {
                if (clist->row_list == (GList *)node)
-                       clist->row_list = (GList *) (GTK_CTREE_ROW (node)->sibling);
+                       clist->row_list = (GList *) (GTK_CMCTREE_ROW (node)->sibling);
                else {
-                       GtkCTreeNode *sibling;
+                       GtkCMCTreeNode *sibling;
 
-                       sibling = GTK_CTREE_NODE (clist->row_list);
-                       while (GTK_CTREE_ROW (sibling)->sibling != node)
-                               sibling = GTK_CTREE_ROW (sibling)->sibling;
-                       GTK_CTREE_ROW (sibling)->sibling = GTK_CTREE_ROW (node)->sibling;
+                       sibling = GTK_CMCTREE_NODE (clist->row_list);
+                       while (GTK_CMCTREE_ROW (sibling)->sibling != node)
+                               sibling = GTK_CMCTREE_ROW (sibling)->sibling;
+                       GTK_CMCTREE_ROW (sibling)->sibling = GTK_CMCTREE_ROW (node)->sibling;
                }
        }
 }
 
 static void
-gtk_sctree_link (GtkCTree     *ctree,
-               GtkCTreeNode *node,
-               GtkCTreeNode *parent,
-               GtkCTreeNode *sibling,
+gtk_sctree_link (GtkCMCTree     *ctree,
+               GtkCMCTreeNode *node,
+               GtkCMCTreeNode *parent,
+               GtkCMCTreeNode *sibling,
                gboolean      update_focus_row)
 {
-       GtkCList *clist;
+       GtkCMCList *clist;
        GList *list_end;
        GList *list;
        GList *work;
@@ -2364,15 +2364,15 @@ gtk_sctree_link (GtkCTree     *ctree,
        gint rows = 0;
   
        if (sibling)
-               g_return_if_fail (GTK_CTREE_ROW (sibling)->parent == parent);
+               g_return_if_fail (GTK_CMCTREE_ROW (sibling)->parent == parent);
        g_return_if_fail (node != NULL);
        g_return_if_fail (node != sibling);
        g_return_if_fail (node != parent);
 
-       clist = GTK_CLIST (ctree);
+       clist = GTK_CMCLIST (ctree);
 
        if (update_focus_row && clist->selection_mode == GTK_SELECTION_EXTENDED) {
-               GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+               GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
                g_list_free (clist->undo_selection);
                g_list_free (clist->undo_unselection);
@@ -2384,53 +2384,53 @@ gtk_sctree_link (GtkCTree     *ctree,
             list_end = list_end->next)
                rows++;
 
-       GTK_CTREE_ROW (node)->parent = parent;
-       GTK_CTREE_ROW (node)->sibling = sibling;
+       GTK_CMCTREE_ROW (node)->parent = parent;
+       GTK_CMCTREE_ROW (node)->sibling = sibling;
 
-       if (!parent || (parent && (gtk_ctree_is_viewable (ctree, parent) &&
-           GTK_CTREE_ROW (parent)->expanded))) {
+       if (!parent || (parent && (gtk_cmctree_is_viewable (ctree, parent) &&
+           GTK_CMCTREE_ROW (parent)->expanded))) {
                visible = TRUE;
                clist->rows += rows;
        }
 
        if (parent)
-               work = (GList *)(GTK_CTREE_ROW (parent)->children);
+               work = (GList *)(GTK_CMCTREE_ROW (parent)->children);
        else
                work = clist->row_list;
 
        if (sibling) {
                if (work != (GList *)sibling) {
-                       while (GTK_CTREE_ROW (work)->sibling != sibling)
-                               work = (GList *)(GTK_CTREE_ROW (work)->sibling);
-                       GTK_CTREE_ROW (work)->sibling = node;
+                       while (GTK_CMCTREE_ROW (work)->sibling != sibling)
+                               work = (GList *)(GTK_CMCTREE_ROW (work)->sibling);
+                       GTK_CMCTREE_ROW (work)->sibling = node;
                }
 
-               if (sibling == GTK_CTREE_NODE (clist->row_list))
+               if (sibling == GTK_CMCTREE_NODE (clist->row_list))
                clist->row_list = (GList *) node;
-               if (GTK_CTREE_NODE_PREV (sibling) &&
-                   GTK_CTREE_NODE_NEXT (GTK_CTREE_NODE_PREV (sibling)) == sibling) {
-                       list = (GList *)GTK_CTREE_NODE_PREV (sibling);
+               if (GTK_CMCTREE_NODE_PREV (sibling) &&
+                   GTK_CMCTREE_NODE_NEXT (GTK_CMCTREE_NODE_PREV (sibling)) == sibling) {
+                       list = (GList *)GTK_CMCTREE_NODE_PREV (sibling);
                        list->next = (GList *)node;
                }
 
                list = (GList *)node;
-               list->prev = (GList *)GTK_CTREE_NODE_PREV (sibling);
+               list->prev = (GList *)GTK_CMCTREE_NODE_PREV (sibling);
                list_end->next = (GList *)sibling;
                list = (GList *)sibling;
                list->prev = list_end;
-               if (parent && GTK_CTREE_ROW (parent)->children == sibling)
-                       GTK_CTREE_ROW (parent)->children = node;
+               if (parent && GTK_CMCTREE_ROW (parent)->children == sibling)
+                       GTK_CMCTREE_ROW (parent)->children = node;
        }
        else {
                if (work) {
                        /* find sibling */
-                       while (GTK_CTREE_ROW (work)->sibling)
-                       work = (GList *)(GTK_CTREE_ROW (work)->sibling);
-                       GTK_CTREE_ROW (work)->sibling = node;
+                       while (GTK_CMCTREE_ROW (work)->sibling)
+                       work = (GList *)(GTK_CMCTREE_ROW (work)->sibling);
+                       GTK_CMCTREE_ROW (work)->sibling = node;
 
                        /* find last visible child of sibling */
                        work = (GList *) gtk_sctree_last_visible (ctree,
-                              GTK_CTREE_NODE (work));
+                              GTK_CMCTREE_NODE (work));
 
                        list_end->next = work->next;
                        if (work->next)
@@ -2441,13 +2441,13 @@ gtk_sctree_link (GtkCTree     *ctree,
                }
                else {
                        if (parent) {
-                               GTK_CTREE_ROW (parent)->children = node;
+                               GTK_CMCTREE_ROW (parent)->children = node;
                                list = (GList *)node;
                                list->prev = (GList *)parent;
-                               if (GTK_CTREE_ROW (parent)->expanded) {
-                                       list_end->next = (GList *)GTK_CTREE_NODE_NEXT (parent);
-                                       if (GTK_CTREE_NODE_NEXT(parent)) {
-                                               list = (GList *)GTK_CTREE_NODE_NEXT (parent);
+                               if (GTK_CMCTREE_ROW (parent)->expanded) {
+                                       list_end->next = (GList *)GTK_CMCTREE_NODE_NEXT (parent);
+                                       if (GTK_CMCTREE_NODE_NEXT(parent)) {
+                                               list = (GList *)GTK_CMCTREE_NODE_NEXT (parent);
                                                list->prev = list_end;
                                        }
                                        list = (GList *)parent;
@@ -2465,7 +2465,7 @@ gtk_sctree_link (GtkCTree     *ctree,
                }
        }
 
-       gtk_ctree_pre_recursive (ctree, node, stree_update_level, NULL); 
+       gtk_cmctree_pre_recursive (ctree, node, stree_update_level, NULL); 
 
        if (clist->row_list_end == NULL ||
            clist->row_list_end->next == (GList *)node)
@@ -2483,36 +2483,36 @@ gtk_sctree_link (GtkCTree     *ctree,
 }
 
 static void
-stree_update_level (GtkCTree     *ctree, 
-                  GtkCTreeNode *node, 
+stree_update_level (GtkCMCTree     *ctree, 
+                  GtkCMCTreeNode *node, 
                   gpointer      data)
 {
        if (!node)
                return;
 
-       if (GTK_CTREE_ROW (node)->parent)
-               GTK_CTREE_ROW (node)->level = 
-               GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->level + 1;
+       if (GTK_CMCTREE_ROW (node)->parent)
+               GTK_CMCTREE_ROW (node)->level = 
+               GTK_CMCTREE_ROW (GTK_CMCTREE_ROW (node)->parent)->level + 1;
        else
-               GTK_CTREE_ROW (node)->level = 1;
+               GTK_CMCTREE_ROW (node)->level = 1;
 }
 
-static GtkCTreeNode *
-gtk_sctree_last_visible (GtkCTree     *ctree,
-                       GtkCTreeNode *node)
+static GtkCMCTreeNode *
+gtk_sctree_last_visible (GtkCMCTree     *ctree,
+                       GtkCMCTreeNode *node)
 {
-       GtkCTreeNode *work;
+       GtkCMCTreeNode *work;
   
        if (!node)
                return NULL;
 
-       work = GTK_CTREE_ROW (node)->children;
+       work = GTK_CMCTREE_ROW (node)->children;
 
-       if (!work || !GTK_CTREE_ROW (node)->expanded)
+       if (!work || !GTK_CMCTREE_ROW (node)->expanded)
                return node;
 
-       while (GTK_CTREE_ROW (work)->sibling)
-               work = GTK_CTREE_ROW (work)->sibling;
+       while (GTK_CMCTREE_ROW (work)->sibling)
+               work = GTK_CMCTREE_ROW (work)->sibling;
 
        return gtk_sctree_last_visible (ctree, work);
 }
@@ -2522,9 +2522,9 @@ gtk_sctree_last_visible (GtkCTree     *ctree,
  * around a memory problem deep inside gtk, 
  * revealed by valgrind. 
  */
-/*GtkCTreeNode* gtk_sctree_insert_node        (GtkCTree *ctree,
-                                             GtkCTreeNode *parent,
-                                             GtkCTreeNode *sibling,
+/*GtkCMCTreeNode* gtk_sctree_insert_node        (GtkCMCTree *ctree,
+                                             GtkCMCTreeNode *parent,
+                                             GtkCMCTreeNode *sibling,
                                              gchar *text[],
                                              guint8 spacing,
                                              GdkPixmap *pixmap_closed,
@@ -2546,14 +2546,14 @@ gtk_sctree_last_visible (GtkCTree     *ctree,
                pixmap_opened = emptyxpm;
                mask_opened = emptyxpmmask;
        }
-       return gtk_ctree_insert_node(ctree, parent, sibling, text,spacing,
+       return gtk_cmctree_insert_node(ctree, parent, sibling, text,spacing,
                pixmap_closed, mask_closed, pixmap_opened, mask_opened,
                is_leaf, expanded);
 }*/
 
 static void 
-sset_node_info (GtkCTree     *ctree,
-              GtkCTreeNode *node,
+sset_node_info (GtkCMCTree     *ctree,
+              GtkCMCTreeNode *node,
               const gchar  *text,
               guint8        spacing,
               GdkPixmap    *pixmap_closed,
@@ -2563,70 +2563,70 @@ sset_node_info (GtkCTree     *ctree,
               gboolean      is_leaf,
               gboolean      expanded)
 {
-  if (GTK_CTREE_ROW (node)->pixmap_opened)
+  if (GTK_CMCTREE_ROW (node)->pixmap_opened)
     {
-      gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_opened);
-      if (GTK_CTREE_ROW (node)->mask_opened) 
-       gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_opened);
+      g_object_unref (GTK_CMCTREE_ROW (node)->pixmap_opened);
+      if (GTK_CMCTREE_ROW (node)->mask_opened) 
+       g_object_unref (GTK_CMCTREE_ROW (node)->mask_opened);
     }
-  if (GTK_CTREE_ROW (node)->pixmap_closed)
+  if (GTK_CMCTREE_ROW (node)->pixmap_closed)
     {
-      gdk_pixmap_unref (GTK_CTREE_ROW (node)->pixmap_closed);
-      if (GTK_CTREE_ROW (node)->mask_closed) 
-       gdk_bitmap_unref (GTK_CTREE_ROW (node)->mask_closed);
+      g_object_unref (GTK_CMCTREE_ROW (node)->pixmap_closed);
+      if (GTK_CMCTREE_ROW (node)->mask_closed) 
+       g_object_unref (GTK_CMCTREE_ROW (node)->mask_closed);
     }
 
-  GTK_CTREE_ROW (node)->pixmap_opened = NULL;
-  GTK_CTREE_ROW (node)->mask_opened   = NULL;
-  GTK_CTREE_ROW (node)->pixmap_closed = NULL;
-  GTK_CTREE_ROW (node)->mask_closed   = NULL;
+  GTK_CMCTREE_ROW (node)->pixmap_opened = NULL;
+  GTK_CMCTREE_ROW (node)->mask_opened   = NULL;
+  GTK_CMCTREE_ROW (node)->pixmap_closed = NULL;
+  GTK_CMCTREE_ROW (node)->mask_closed   = NULL;
 
   if (pixmap_closed)
     {
-      GTK_CTREE_ROW (node)->pixmap_closed = gdk_pixmap_ref (pixmap_closed);
+      GTK_CMCTREE_ROW (node)->pixmap_closed = g_object_ref (pixmap_closed);
       if (mask_closed) 
-       GTK_CTREE_ROW (node)->mask_closed = gdk_bitmap_ref (mask_closed);
+       GTK_CMCTREE_ROW (node)->mask_closed = g_object_ref (mask_closed);
     }
   if (pixmap_opened)
     {
-      GTK_CTREE_ROW (node)->pixmap_opened = gdk_pixmap_ref (pixmap_opened);
+      GTK_CMCTREE_ROW (node)->pixmap_opened = g_object_ref (pixmap_opened);
       if (mask_opened) 
-       GTK_CTREE_ROW (node)->mask_opened = gdk_bitmap_ref (mask_opened);
+       GTK_CMCTREE_ROW (node)->mask_opened = g_object_ref (mask_opened);
     }
 
-  GTK_CTREE_ROW (node)->is_leaf  = is_leaf;
-  GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
+  GTK_CMCTREE_ROW (node)->is_leaf  = is_leaf;
+  GTK_CMCTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
 
-  if (GTK_CTREE_ROW (node)->expanded)
-    gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
+  if (GTK_CMCTREE_ROW (node)->expanded)
+    gtk_cmctree_node_set_pixtext (ctree, node, ctree->tree_column,
                                text, spacing, pixmap_opened, mask_opened);
   else 
-    gtk_ctree_node_set_pixtext (ctree, node, ctree->tree_column,
+    gtk_cmctree_node_set_pixtext (ctree, node, ctree->tree_column,
                                text, spacing, pixmap_closed, mask_closed);
 }
 
 static void
-stree_draw_node (GtkCTree     *ctree, 
-               GtkCTreeNode *node)
+stree_draw_node (GtkCMCTree     *ctree, 
+               GtkCMCTreeNode *node)
 {
-  GtkCList *clist;
+  GtkCMCList *clist;
   
-  clist = GTK_CLIST (ctree);
+  clist = GTK_CMCLIST (ctree);
 
-  if (CLIST_UNFROZEN (clist) && gtk_ctree_is_viewable (ctree, node))
+  if (CLIST_UNFROZEN (clist) && gtk_cmctree_is_viewable (ctree, node))
     {
-      GtkCTreeNode *work;
+      GtkCMCTreeNode *work;
       gint num = 0;
       
-      work = GTK_CTREE_NODE (clist->row_list);
+      work = GTK_CMCTREE_NODE (clist->row_list);
       while (work && work != node)
        {
-         work = GTK_CTREE_NODE_NEXT (work);
+         work = GTK_CMCTREE_NODE_NEXT (work);
          num++;
        }
-      if (work && gtk_clist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE)
-       GTK_CLIST_GET_CLASS (clist)->draw_row
-         (clist, NULL, num, GTK_CLIST_ROW ((GList *) node));
+      if (work && gtk_cmclist_row_is_visible (clist, num) != GTK_VISIBILITY_NONE)
+       GTK_CMCLIST_GET_CLASS (clist)->draw_row
+         (clist, NULL, num, GTK_CMCLIST_ROW ((GList *) node));
     }
 }
 
@@ -2635,8 +2635,8 @@ stree_draw_node (GtkCTree     *ctree,
  * around a memory problem deep inside gtk, 
  * revealed by valgrind. 
  */
-void        gtk_sctree_set_node_info        (GtkCTree *ctree,
-                                             GtkCTreeNode *node,
+void        gtk_sctree_set_node_info        (GtkCMCTree *ctree,
+                                             GtkCMCTreeNode *node,
                                              const gchar *text,
                                              guint8 spacing,
                                              GdkPixmap *pixmap_closed,
@@ -2648,7 +2648,7 @@ void        gtk_sctree_set_node_info        (GtkCTree *ctree,
 {
   gboolean old_leaf;
   gboolean old_expanded;
-  GtkCTreeNode *work;
+  GtkCMCTreeNode *work;
  
   if (!emptyxpm) {
          stock_pixmap_gdk(GTK_WIDGET(ctree), STOCK_PIXMAP_EMPTY,
@@ -2663,20 +2663,20 @@ void        gtk_sctree_set_node_info        (GtkCTree *ctree,
          mask_opened = emptyxpmmask;
   }
 
-  if (!GTK_IS_CTREE (ctree) || !node) return;
+  if (!GTK_IS_CMCTREE (ctree) || !node) return;
 
-  old_leaf = GTK_CTREE_ROW (node)->is_leaf;
-  old_expanded = GTK_CTREE_ROW (node)->expanded;
+  old_leaf = GTK_CMCTREE_ROW (node)->is_leaf;
+  old_expanded = GTK_CMCTREE_ROW (node)->expanded;
 
-  if (is_leaf && (work = GTK_CTREE_ROW (node)->children) != NULL)
+  if (is_leaf && (work = GTK_CMCTREE_ROW (node)->children) != NULL)
     {
-      GtkCTreeNode *ptr;
+      GtkCMCTreeNode *ptr;
       
       while (work)
        {
          ptr = work;
-         work = GTK_CTREE_ROW (work)->sibling;
-         gtk_ctree_remove_node (ctree, ptr);
+         work = GTK_CMCTREE_ROW (work)->sibling;
+         gtk_cmctree_remove_node (ctree, ptr);
        }
     }
 
@@ -2685,42 +2685,42 @@ void        gtk_sctree_set_node_info        (GtkCTree *ctree,
 
   if (!is_leaf && !old_leaf)
     {
-      GTK_CTREE_ROW (node)->expanded = old_expanded;
+      GTK_CMCTREE_ROW (node)->expanded = old_expanded;
       if (expanded && !old_expanded)
-       gtk_ctree_expand (ctree, node);
+       gtk_cmctree_expand (ctree, node);
       else if (!expanded && old_expanded)
-       gtk_ctree_collapse (ctree, node);
+       gtk_cmctree_collapse (ctree, node);
     }
 
-  GTK_CTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
+  GTK_CMCTREE_ROW (node)->expanded = (is_leaf) ? FALSE : expanded;
   
   stree_draw_node (ctree, node);
 }
 
-static GtkCTreeRow *
-srow_new (GtkCTree *ctree)
+static GtkCMCTreeRow *
+srow_new (GtkCMCTree *ctree)
 {
-  GtkCList *clist;
-  GtkCTreeRow *ctree_row;
+  GtkCMCList *clist;
+  GtkCMCTreeRow *ctree_row;
   int i;
 
-  clist = GTK_CLIST (ctree);
+  clist = GTK_CMCLIST (ctree);
 #if GTK_CHECK_VERSION(2,9,0)
-  ctree_row = g_slice_new (GtkCTreeRow);
-  ctree_row->row.cell = g_slice_alloc (sizeof (GtkCell) * clist->columns);
+  ctree_row = g_slice_new (GtkCMCTreeRow);
+  ctree_row->row.cell = g_slice_alloc (sizeof (GtkCMCell) * clist->columns);
 #else
-  ctree_row = g_chunk_new (GtkCTreeRow, (GMemChunk *)clist->row_mem_chunk);
-  ctree_row->row.cell = g_chunk_new (GtkCell, (GMemChunk *)clist->cell_mem_chunk);
+  ctree_row = g_chunk_new (GtkCMCTreeRow, (GMemChunk *)clist->row_mem_chunk);
+  ctree_row->row.cell = g_chunk_new (GtkCMCell, (GMemChunk *)clist->cell_mem_chunk);
 #endif
   for (i = 0; i < clist->columns; i++)
     {
-      ctree_row->row.cell[i].type = GTK_CELL_EMPTY;
+      ctree_row->row.cell[i].type = GTK_CMCELL_EMPTY;
       ctree_row->row.cell[i].vertical = 0;
       ctree_row->row.cell[i].horizontal = 0;
       ctree_row->row.cell[i].style = NULL;
     }
 
-  GTK_CELL_PIXTEXT (ctree_row->row.cell[ctree->tree_column])->text = NULL;
+  GTK_CMCELL_PIXTEXT (ctree_row->row.cell[ctree->tree_column])->text = NULL;
 
   ctree_row->row.fg_set     = FALSE;
   ctree_row->row.bg_set     = FALSE;
@@ -2744,18 +2744,18 @@ srow_new (GtkCTree *ctree)
 }
 
 static void
-srow_delete (GtkCTree    *ctree,
-           GtkCTreeRow *ctree_row)
+srow_delete (GtkCMCTree    *ctree,
+           GtkCMCTreeRow *ctree_row)
 {
-  GtkCList *clist;
+  GtkCMCList *clist;
   gint i;
 
-  clist = GTK_CLIST (ctree);
+  clist = GTK_CMCLIST (ctree);
 
   for (i = 0; i < clist->columns; i++)
     {
-      GTK_CLIST_GET_CLASS (clist)->set_cell_contents
-       (clist, &(ctree_row->row), i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
+      GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+       (clist, &(ctree_row->row), i, GTK_CMCELL_EMPTY, NULL, 0, NULL, NULL);
       if (ctree_row->row.cell[i].style)
        {
          if (GTK_WIDGET_REALIZED (ctree))
@@ -2773,16 +2773,16 @@ srow_delete (GtkCTree    *ctree,
 
   if (ctree_row->pixmap_closed)
     {
-      gdk_pixmap_unref (ctree_row->pixmap_closed);
+      g_object_unref (ctree_row->pixmap_closed);
       if (ctree_row->mask_closed)
-       gdk_bitmap_unref (ctree_row->mask_closed);
+       g_object_unref (ctree_row->mask_closed);
     }
 
   if (ctree_row->pixmap_opened)
     {
-      gdk_pixmap_unref (ctree_row->pixmap_opened);
+      g_object_unref (ctree_row->pixmap_opened);
       if (ctree_row->mask_opened)
-       gdk_bitmap_unref (ctree_row->mask_opened);
+       g_object_unref (ctree_row->mask_opened);
     }
 
   if (ctree_row->row.destroy)
@@ -2797,8 +2797,8 @@ srow_delete (GtkCTree    *ctree,
     }
 
 #if GTK_CHECK_VERSION(2,9,0)  
-  g_slice_free1 (sizeof (GtkCell) * clist->columns, ctree_row->row.cell);
-  g_slice_free (GtkCTreeRow, ctree_row);
+  g_slice_free1 (sizeof (GtkCMCell) * clist->columns, ctree_row->row.cell);
+  g_slice_free (GtkCMCTreeRow, ctree_row);
 #else
   g_mem_chunk_free ((GMemChunk *)clist->cell_mem_chunk, ctree_row->row.cell);
   g_mem_chunk_free ((GMemChunk *)clist->row_mem_chunk, ctree_row);
@@ -2806,17 +2806,17 @@ srow_delete (GtkCTree    *ctree,
 }
 
 static void
-stree_delete_row (GtkCTree     *ctree, 
-                GtkCTreeNode *node, 
+stree_delete_row (GtkCMCTree     *ctree, 
+                GtkCMCTreeNode *node, 
                 gpointer      data)
 {
-  srow_delete (ctree, GTK_CTREE_ROW (node));
+  srow_delete (ctree, GTK_CMCTREE_ROW (node));
   g_list_free_1 ((GList *)node);
 }
 
 static void
-gtk_sctree_column_auto_resize (GtkCList    *clist,
-                   GtkCListRow *clist_row,
+gtk_sctree_column_auto_resize (GtkCMCList    *clist,
+                   GtkCMCListRow *clist_row,
                    gint         column,
                    gint         old_width)
 {
@@ -2824,26 +2824,26 @@ gtk_sctree_column_auto_resize (GtkCList    *clist,
   GtkRequisition requisition;
 
   if (!clist->column[column].auto_resize ||
-      GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
     return;
 
   if (clist_row)
-    GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
+    GTK_CMCLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
                                                   column, &requisition);
   else
     requisition.width = 0;
 
   if (requisition.width > clist->column[column].width)
-    gtk_clist_set_column_width (clist, column, requisition.width);
+    gtk_cmclist_set_column_width (clist, column, requisition.width);
   else if (requisition.width < old_width &&
           old_width == clist->column[column].width)
     {
       GList *list;
       gint new_width;
 
-      /* run a "gtk_clist_optimal_column_width" but break, if
+      /* run a "gtk_cmclist_optimal_column_width" but break, if
        * the column doesn't shrink */
-      if (GTK_CLIST_SHOW_TITLES (clist) && clist->column[column].button)
+      if (GTK_CMCLIST_SHOW_TITLES (clist) && clist->column[column].button)
        new_width = (clist->column[column].button->requisition.width -
                     (CELL_SPACING + (2 * COLUMN_INSET)));
       else
@@ -2851,84 +2851,84 @@ gtk_sctree_column_auto_resize (GtkCList    *clist,
 
       for (list = clist->row_list; list; list = list->next)
        {
-         GTK_CLIST_GET_CLASS (clist)->cell_size_request
-           (clist, GTK_CLIST_ROW (list), column, &requisition);
+         GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+           (clist, GTK_CMCLIST_ROW (list), column, &requisition);
          new_width = MAX (new_width, requisition.width);
          if (new_width == clist->column[column].width)
            break;
        }
       if (new_width < clist->column[column].width)
-       gtk_clist_set_column_width (clist, column, new_width);
+       gtk_cmclist_set_column_width (clist, column, new_width);
     }
 }
 
 
 static void 
-gtk_sctree_real_tree_expand (GtkCTree     *ctree,
-                 GtkCTreeNode *node)
+gtk_sctree_real_tree_expand (GtkCMCTree     *ctree,
+                 GtkCMCTreeNode *node)
 {
-  GtkCList *clist;
-  GtkCTreeNode *work;
+  GtkCMCList *clist;
+  GtkCMCTreeNode *work;
   GtkRequisition requisition;
   gboolean visible;
   gint level;
 
-  g_return_if_fail (GTK_IS_CTREE (ctree));
+  g_return_if_fail (GTK_IS_CMCTREE (ctree));
 
-  if (!node || GTK_CTREE_ROW (node)->expanded || GTK_CTREE_ROW (node)->is_leaf)
+  if (!node || GTK_CMCTREE_ROW (node)->expanded || GTK_CMCTREE_ROW (node)->is_leaf)
     return;
 
-  clist = GTK_CLIST (ctree);
+  clist = GTK_CMCLIST (ctree);
   
-  GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+  GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
-  GTK_CTREE_ROW (node)->expanded = TRUE;
-  level = GTK_CTREE_ROW (node)->level;
+  GTK_CMCTREE_ROW (node)->expanded = TRUE;
+  level = GTK_CMCTREE_ROW (node)->level;
 
-  visible = gtk_ctree_is_viewable (ctree, node);
+  visible = gtk_cmctree_is_viewable (ctree, node);
   /* get cell width if tree_column is auto resized */
   if (visible && clist->column[ctree->tree_column].auto_resize &&
-      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
-    GTK_CLIST_GET_CLASS (clist)->cell_size_request
-      (clist, &GTK_CTREE_ROW (node)->row, ctree->tree_column, &requisition);
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
+    GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+      (clist, &GTK_CMCTREE_ROW (node)->row, ctree->tree_column, &requisition);
 
   /* unref/unset closed pixmap */
-  if (GTK_CELL_PIXTEXT 
-      (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
+  if (GTK_CMCELL_PIXTEXT 
+      (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
     {
-      gdk_pixmap_unref
-       (GTK_CELL_PIXTEXT
-        (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
+      g_object_unref
+       (GTK_CMCELL_PIXTEXT
+        (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap);
       
-      GTK_CELL_PIXTEXT
-       (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
+      GTK_CMCELL_PIXTEXT
+       (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = NULL;
       
-      if (GTK_CELL_PIXTEXT 
-         (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
+      if (GTK_CMCELL_PIXTEXT 
+         (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask)
        {
-         gdk_pixmap_unref
-           (GTK_CELL_PIXTEXT 
-            (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
-         GTK_CELL_PIXTEXT 
-           (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
+         g_object_unref
+           (GTK_CMCELL_PIXTEXT 
+            (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask);
+         GTK_CMCELL_PIXTEXT 
+           (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask = NULL;
        }
     }
 
   /* set/ref opened pixmap */
-  if (GTK_CTREE_ROW (node)->pixmap_opened)
+  if (GTK_CMCTREE_ROW (node)->pixmap_opened)
     {
-      GTK_CELL_PIXTEXT 
-       (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = 
-       gdk_pixmap_ref (GTK_CTREE_ROW (node)->pixmap_opened);
-
-      if (GTK_CTREE_ROW (node)->mask_opened) 
-       GTK_CELL_PIXTEXT 
-         (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->mask = 
-         gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_opened);
+      GTK_CMCELL_PIXTEXT 
+       (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap = 
+       g_object_ref (GTK_CMCTREE_ROW (node)->pixmap_opened);
+
+      if (GTK_CMCTREE_ROW (node)->mask_opened) 
+       GTK_CMCELL_PIXTEXT 
+         (GTK_CMCTREE_ROW (node)->row.cell[ctree->tree_column])->mask = 
+         g_object_ref (GTK_CMCTREE_ROW (node)->mask_opened);
     }
 
 
-  work = GTK_CTREE_ROW (node)->children;
+  work = GTK_CMCTREE_ROW (node)->children;
   if (work)
     {
       GList *list = (GList *)work;
@@ -2937,7 +2937,7 @@ gtk_sctree_real_tree_expand (GtkCTree     *ctree,
       gint row;
       gint i;
       
-      if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+      if (visible && !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist))
        {
          cell_width = g_new0 (gint, clist->columns);
          if (clist->column[ctree->tree_column].auto_resize)
@@ -2949,13 +2949,13 @@ gtk_sctree_real_tree_expand (GtkCTree     *ctree,
              for (i = 0; i < clist->columns; i++)
                if (clist->column[i].auto_resize)
                  {
-                   GTK_CLIST_GET_CLASS (clist)->cell_size_request
-                     (clist, &GTK_CTREE_ROW (work)->row, i, &requisition);
+                   GTK_CMCLIST_GET_CLASS (clist)->cell_size_request
+                     (clist, &GTK_CMCTREE_ROW (work)->row, i, &requisition);
                    cell_width[i] = MAX (requisition.width, cell_width[i]);
                  }
 
              list = (GList *)work;
-             work = GTK_CTREE_NODE_NEXT (work);
+             work = GTK_CMCTREE_NODE_NEXT (work);
              tmp++;
            }
        }
@@ -2963,27 +2963,27 @@ gtk_sctree_real_tree_expand (GtkCTree     *ctree,
        while (work)
          {
            list = (GList *)work;
-           work = GTK_CTREE_NODE_NEXT (work);
+           work = GTK_CMCTREE_NODE_NEXT (work);
            tmp++;
          }
 
-      list->next = (GList *)GTK_CTREE_NODE_NEXT (node);
+      list->next = (GList *)GTK_CMCTREE_NODE_NEXT (node);
 
-      if (GTK_CTREE_NODE_NEXT (node))
+      if (GTK_CMCTREE_NODE_NEXT (node))
        {
          GList *tmp_list;
 
          if (clist->row_list_end == list)
              clist->row_list_end = g_list_last(list);
 
-         tmp_list = (GList *)GTK_CTREE_NODE_NEXT (node);
+         tmp_list = (GList *)GTK_CMCTREE_NODE_NEXT (node);
          tmp_list->prev = list;
        }
       else
        clist->row_list_end = list;
 
       list = (GList *)node;
-      list->next = (GList *)(GTK_CTREE_ROW (node)->children);
+      list->next = (GList *)(GTK_CMCTREE_ROW (node)->children);
 
       if (visible)
        {
@@ -2991,7 +2991,7 @@ gtk_sctree_real_tree_expand (GtkCTree     *ctree,
          for (i = 0; i < clist->columns; i++)
            if (clist->column[i].auto_resize &&
                cell_width[i] > clist->column[i].width)
-             gtk_clist_set_column_width (clist, i, cell_width[i]);
+             gtk_cmclist_set_column_width (clist, i, cell_width[i]);
          g_free (cell_width);
        
          if (!GTK_SCTREE(ctree)->sorting) {
@@ -3006,15 +3006,15 @@ gtk_sctree_real_tree_expand (GtkCTree     *ctree,
     }
   else if (visible && clist->column[ctree->tree_column].auto_resize)
     /* resize tree_column if needed */
-    gtk_sctree_column_auto_resize (clist, &GTK_CTREE_ROW (node)->row, ctree->tree_column,
+    gtk_sctree_column_auto_resize (clist, &GTK_CMCTREE_ROW (node)->row, ctree->tree_column,
                        requisition.width);
 
 }
 
-GtkCTreeNode * 
-gtk_sctree_insert_node (GtkCTree     *ctree,
-                      GtkCTreeNode *parent, 
-                      GtkCTreeNode *sibling,
+GtkCMCTreeNode * 
+gtk_sctree_insert_node (GtkCMCTree     *ctree,
+                      GtkCMCTreeNode *parent, 
+                      GtkCMCTreeNode *sibling,
                       gchar        *text[],
                       guint8        spacing,
                       GdkPixmap    *pixmap_closed,
@@ -3024,9 +3024,9 @@ gtk_sctree_insert_node (GtkCTree     *ctree,
                       gboolean      is_leaf,
                       gboolean      expanded)
 {
-  GtkCList *clist;
-  GtkCTreeRow *new_row;
-  GtkCTreeNode *node;
+  GtkCMCList *clist;
+  GtkCMCTreeRow *new_row;
+  GtkCMCTreeNode *node;
   GList *list;
   gint i;
 
@@ -3042,48 +3042,48 @@ gtk_sctree_insert_node (GtkCTree     *ctree,
          pixmap_opened = emptyxpm;
          mask_opened = emptyxpmmask;
   }
-  g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
   if (sibling)
-    g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
+    g_return_val_if_fail (GTK_CMCTREE_ROW (sibling)->parent == parent, NULL);
 
-  if (parent && GTK_CTREE_ROW (parent)->is_leaf)
+  if (parent && GTK_CMCTREE_ROW (parent)->is_leaf)
     return NULL;
 
-  clist = GTK_CLIST (ctree);
+  clist = GTK_CMCLIST (ctree);
 
   /* create the row */
   new_row = srow_new (ctree);
   list = g_list_alloc ();
   list->data = new_row;
-  node = GTK_CTREE_NODE (list);
+  node = GTK_CMCTREE_NODE (list);
 
   if (text)
     for (i = 0; i < clist->columns; i++)
       if (text[i] && i != ctree->tree_column)
-       GTK_CLIST_GET_CLASS (clist)->set_cell_contents
-         (clist, &(new_row->row), i, GTK_CELL_TEXT, text[i], 0, NULL, NULL);
+       GTK_CMCLIST_GET_CLASS (clist)->set_cell_contents
+         (clist, &(new_row->row), i, GTK_CMCELL_TEXT, text[i], 0, NULL, NULL);
 
   sset_node_info (ctree, node, text ?
                 text[ctree->tree_column] : NULL, spacing, pixmap_closed,
                 mask_closed, pixmap_opened, mask_opened, is_leaf, expanded);
 
   /* sorted insertion */
-  if (GTK_CLIST_AUTO_SORT (clist))
+  if (GTK_CMCLIST_AUTO_SORT (clist))
     {
       if (parent)
-       sibling = GTK_CTREE_ROW (parent)->children;
+       sibling = GTK_CMCTREE_ROW (parent)->children;
       else
-       sibling = GTK_CTREE_NODE (clist->row_list);
+       sibling = GTK_CMCTREE_NODE (clist->row_list);
 
       while (sibling && clist->compare
-            (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (sibling)) > 0)
-       sibling = GTK_CTREE_ROW (sibling)->sibling;
+            (clist, GTK_CMCTREE_ROW (node), GTK_CMCTREE_ROW (sibling)) > 0)
+       sibling = GTK_CMCTREE_ROW (sibling)->sibling;
     }
 
   gtk_sctree_link (ctree, node, parent, sibling, FALSE);
 
-  if (text && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
-      gtk_ctree_is_viewable (ctree, node))
+  if (text && !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist) &&
+      gtk_cmctree_is_viewable (ctree, node))
     {
       for (i = 0; i < clist->columns; i++)
        if (clist->column[i].auto_resize)
@@ -3103,58 +3103,58 @@ gtk_sctree_insert_node (GtkCTree     *ctree,
   return node;
 }
 
-GtkCTreeNode *
-gtk_sctree_insert_gnode (GtkCTree          *ctree,
-                       GtkCTreeNode      *parent,
-                       GtkCTreeNode      *sibling,
+GtkCMCTreeNode *
+gtk_sctree_insert_gnode (GtkCMCTree          *ctree,
+                       GtkCMCTreeNode      *parent,
+                       GtkCMCTreeNode      *sibling,
                        GNode             *gnode,
-                       GtkCTreeGNodeFunc  func,
+                       GtkCMCTreeGNodeFunc  func,
                        gpointer           data)
 {
-  GtkCList *clist;
-  GtkCTreeNode *cnode = NULL;
-  GtkCTreeNode *child = NULL;
-  GtkCTreeNode *new_child;
+  GtkCMCList *clist;
+  GtkCMCTreeNode *cnode = NULL;
+  GtkCMCTreeNode *child = NULL;
+  GtkCMCTreeNode *new_child;
   GList *list;
   GNode *work;
   guint depth = 1;
 
-  g_return_val_if_fail (GTK_IS_CTREE (ctree), NULL);
+  g_return_val_if_fail (GTK_IS_CMCTREE (ctree), NULL);
   g_return_val_if_fail (gnode != NULL, NULL);
   g_return_val_if_fail (func != NULL, NULL);
   if (sibling)
-    g_return_val_if_fail (GTK_CTREE_ROW (sibling)->parent == parent, NULL);
+    g_return_val_if_fail (GTK_CMCTREE_ROW (sibling)->parent == parent, NULL);
   
-  clist = GTK_CLIST (ctree);
+  clist = GTK_CMCLIST (ctree);
 
   if (parent)
-    depth = GTK_CTREE_ROW (parent)->level + 1;
+    depth = GTK_CMCTREE_ROW (parent)->level + 1;
 
   list = g_list_alloc ();
   list->data = srow_new (ctree);
-  cnode = GTK_CTREE_NODE (list);
+  cnode = GTK_CMCTREE_NODE (list);
 
-  gtk_clist_freeze (clist);
+  gtk_cmclist_freeze (clist);
 
   sset_node_info (ctree, cnode, "", 0, NULL, NULL, NULL, NULL, TRUE, FALSE);
 
   if (!func (ctree, depth, gnode, cnode, data))
     {
       stree_delete_row (ctree, cnode, NULL);
-      gtk_clist_thaw (clist);
+      gtk_cmclist_thaw (clist);
       return NULL;
     }
 
-  if (GTK_CLIST_AUTO_SORT (clist))
+  if (GTK_CMCLIST_AUTO_SORT (clist))
     {
       if (parent)
-       sibling = GTK_CTREE_ROW (parent)->children;
+       sibling = GTK_CMCTREE_ROW (parent)->children;
       else
-       sibling = GTK_CTREE_NODE (clist->row_list);
+       sibling = GTK_CMCTREE_NODE (clist->row_list);
 
       while (sibling && clist->compare
-            (clist, GTK_CTREE_ROW (cnode), GTK_CTREE_ROW (sibling)) > 0)
-       sibling = GTK_CTREE_ROW (sibling)->sibling;
+            (clist, GTK_CMCTREE_ROW (cnode), GTK_CMCTREE_ROW (sibling)) > 0)
+       sibling = GTK_CMCTREE_ROW (sibling)->sibling;
     }
 
   gtk_sctree_link (ctree, cnode, parent, sibling, FALSE);
@@ -3167,41 +3167,41 @@ gtk_sctree_insert_gnode (GtkCTree          *ctree,
        child = new_child;
     }  
   
-  gtk_clist_thaw (clist);
+  gtk_cmclist_thaw (clist);
 
   return cnode;
 }
 
 static void
-sreal_tree_move (GtkCTree     *ctree,
-               GtkCTreeNode *node,
-               GtkCTreeNode *new_parent, 
-               GtkCTreeNode *new_sibling)
+sreal_tree_move (GtkCMCTree     *ctree,
+               GtkCMCTreeNode *node,
+               GtkCMCTreeNode *new_parent, 
+               GtkCMCTreeNode *new_sibling)
 {
-  GtkCList *clist;
-  GtkCTreeNode *work;
+  GtkCMCList *clist;
+  GtkCMCTreeNode *work;
   gboolean visible = FALSE;
 
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (node != NULL);
   g_return_if_fail (!new_sibling || 
-                   GTK_CTREE_ROW (new_sibling)->parent == new_parent);
+                   GTK_CMCTREE_ROW (new_sibling)->parent == new_parent);
 
-  if (new_parent && GTK_CTREE_ROW (new_parent)->is_leaf)
+  if (new_parent && GTK_CMCTREE_ROW (new_parent)->is_leaf)
     return;
 
   /* new_parent != child of child */
-  for (work = new_parent; work; work = GTK_CTREE_ROW (work)->parent)
+  for (work = new_parent; work; work = GTK_CMCTREE_ROW (work)->parent)
     if (work == node)
       return;
 
-  clist = GTK_CLIST (ctree);
+  clist = GTK_CMCLIST (ctree);
 
-  visible = gtk_ctree_is_viewable (ctree, node);
+  visible = gtk_cmctree_is_viewable (ctree, node);
 
   if (clist->selection_mode == GTK_SELECTION_MULTIPLE)
     {
-      GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
+      GTK_CMCLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
       
       g_list_free (clist->undo_selection);
       g_list_free (clist->undo_unselection);
@@ -3209,51 +3209,51 @@ sreal_tree_move (GtkCTree     *ctree,
       clist->undo_unselection = NULL;
     }
 
-  if (GTK_CLIST_AUTO_SORT (clist))
+  if (GTK_CMCLIST_AUTO_SORT (clist))
     {
-      if (new_parent == GTK_CTREE_ROW (node)->parent)
+      if (new_parent == GTK_CMCTREE_ROW (node)->parent)
        return;
       
       if (new_parent)
-       new_sibling = GTK_CTREE_ROW (new_parent)->children;
+       new_sibling = GTK_CMCTREE_ROW (new_parent)->children;
       else
-       new_sibling = GTK_CTREE_NODE (clist->row_list);
+       new_sibling = GTK_CMCTREE_NODE (clist->row_list);
 
       while (new_sibling && clist->compare
-            (clist, GTK_CTREE_ROW (node), GTK_CTREE_ROW (new_sibling)) > 0)
-       new_sibling = GTK_CTREE_ROW (new_sibling)->sibling;
+            (clist, GTK_CMCTREE_ROW (node), GTK_CMCTREE_ROW (new_sibling)) > 0)
+       new_sibling = GTK_CMCTREE_ROW (new_sibling)->sibling;
     }
 
-  if (new_parent == GTK_CTREE_ROW (node)->parent && 
-      new_sibling == GTK_CTREE_ROW (node)->sibling)
+  if (new_parent == GTK_CMCTREE_ROW (node)->parent && 
+      new_sibling == GTK_CMCTREE_ROW (node)->sibling)
     return;
 
-  gtk_clist_freeze (clist);
+  gtk_cmclist_freeze (clist);
 
   work = NULL;
 
-  if (!GTK_SCTREE(ctree)->sorting && gtk_ctree_is_viewable (ctree, node))
-    work = GTK_CTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
+  if (!GTK_SCTREE(ctree)->sorting && gtk_cmctree_is_viewable (ctree, node))
+    work = GTK_CMCTREE_NODE (g_list_nth (clist->row_list, clist->focus_row));
       
   gtk_sctree_unlink (ctree, node, FALSE);
   gtk_sctree_link (ctree, node, new_parent, new_sibling, FALSE);
   
   if (!GTK_SCTREE(ctree)->sorting && work)
     {
-      while (work &&  !gtk_ctree_is_viewable (ctree, work))
-       work = GTK_CTREE_ROW (work)->parent;
+      while (work &&  !gtk_cmctree_is_viewable (ctree, work))
+       work = GTK_CMCTREE_ROW (work)->parent;
       clist->focus_row = g_list_position (clist->row_list, (GList *)work);
       clist->undo_anchor = clist->focus_row;
     }
 
   if (clist->column[ctree->tree_column].auto_resize &&
-      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
-      (visible || gtk_ctree_is_viewable (ctree, node)))
-    gtk_clist_set_column_width
+      !GTK_CMCLIST_AUTO_RESIZE_BLOCKED (clist) &&
+      (visible || gtk_cmctree_is_viewable (ctree, node)))
+    gtk_cmclist_set_column_width
       (clist, ctree->tree_column,
-       gtk_clist_optimal_column_width (clist, ctree->tree_column));
+       gtk_cmclist_optimal_column_width (clist, ctree->tree_column));
 
-  gtk_clist_thaw (clist);
+  gtk_cmclist_thaw (clist);
 }
 
 void gtk_sctree_set_column_tooltip         (GtkSCTree          *sctree,
@@ -3267,7 +3267,7 @@ void gtk_sctree_set_column_tooltip            (GtkSCTree          *sctree,
        tips = sctree->tips;
 #endif
 
-       CLAWS_SET_TIP(GTK_CLIST(sctree)->column[column].button,
+       CLAWS_SET_TIP(GTK_CMCLIST(sctree)->column[column].button,
                        tip);
 }
 
index cab79b75ceccab7c15caa17e61bd483f6e1166ea..73e52b1ae879e19fe3bb79e82e80454e18f3a752 100644 (file)
@@ -4,8 +4,7 @@
 #define __GTK_SCTREE_H__
 
 #include <gtk/gtk.h>
-#include <gtk/gtkclist.h>
-#include <gtk/gtkctree.h>
+#include "gtk/gtkcmctree.h"
 
 /* This code is based on "gtkflist.{h,c}" from mc-4.5.42 .*/
 
@@ -20,10 +19,10 @@ typedef struct _GtkSCTree GtkSCTree;
 typedef struct _GtkSCTreeClass GtkSCTreeClass;
 
 struct _GtkSCTree {
-       GtkCTree ctree;
+       GtkCMCTree ctree;
 
        /* The anchor row for range selections */
-       GtkCTreeNode *anchor_row;
+       GtkCMCTreeNode *anchor_row;
 
        /* Mouse button and position saved on button press */
        gint dnd_press_button;
@@ -38,14 +37,16 @@ struct _GtkSCTree {
 
        /* (dis)allow fancy color stripes */
        gboolean show_stripes;
-       GtkTooltips *tips;
+#if !GTK_CHECK_VERSION(2,12,0)
+       GtkTooltips *tooltips;
+#endif
        gboolean always_expand_recursively;
        gboolean force_additive_sel;
        gboolean *use_markup;
 };
 
 struct _GtkSCTreeClass {
-       GtkCTreeClass parent_class;
+       GtkCMCTreeClass parent_class;
     
        /* Signal: invoke the popup menu for rows */
        void (* row_popup_menu) (GtkSCTree *sctree, GdkEventButton *event);
@@ -67,17 +68,17 @@ GtkWidget *gtk_sctree_new_with_titles       (gint            columns,
                                         gint            tree_column, 
                                         gchar          *titles[]);
 void gtk_sctree_select                 (GtkSCTree      *sctree,
-                                        GtkCTreeNode   *node);
+                                        GtkCMCTreeNode *node);
 void gtk_sctree_select_with_state      (GtkSCTree      *sctree,
-                                        GtkCTreeNode   *node,
+                                        GtkCMCTreeNode *node,
                                         int             state);
 void gtk_sctree_unselect_all           (GtkSCTree      *sctree);
 
 void gtk_sctree_set_anchor_row         (GtkSCTree      *sctree,
-                                        GtkCTreeNode   *node);
+                                        GtkCMCTreeNode *node);
 
 void gtk_sctree_remove_node            (GtkSCTree      *sctree,
-                                        GtkCTreeNode   *node);
+                                        GtkCMCTreeNode *node);
 
 void gtk_sctree_set_stripes(GtkSCTree  *sctree, gboolean show_stripes);
 void gtk_sctree_set_recursive_expand(GtkSCTree  *sctree, gboolean rec_exp);
@@ -86,13 +87,13 @@ void gtk_sctree_set_recursive_expand(GtkSCTree  *sctree, gboolean rec_exp);
  *             Tree sorting functions                      *
  ***********************************************************/
 
-void gtk_sctree_sort_node (GtkCTree *ctree, GtkCTreeNode *node);
+void gtk_sctree_sort_node (GtkCMCTree *ctree, GtkCMCTreeNode *node);
 
-void gtk_sctree_sort_recursive (GtkCTree *ctree, GtkCTreeNode *node);
+void gtk_sctree_sort_recursive (GtkCMCTree *ctree, GtkCMCTreeNode *node);
 
-GtkCTreeNode* gtk_sctree_insert_node        (GtkCTree *ctree,
-                                             GtkCTreeNode *parent,
-                                             GtkCTreeNode *sibling,
+GtkCMCTreeNode* gtk_sctree_insert_node        (GtkCMCTree *ctree,
+                                             GtkCMCTreeNode *parent,
+                                             GtkCMCTreeNode *sibling,
                                              gchar *text[],
                                              guint8 spacing,
                                              GdkPixmap *pixmap_closed,
@@ -101,8 +102,8 @@ GtkCTreeNode* gtk_sctree_insert_node        (GtkCTree *ctree,
                                              GdkBitmap *mask_opened,
                                              gboolean is_leaf,
                                              gboolean expanded);
-void        gtk_sctree_set_node_info        (GtkCTree *ctree,
-                                             GtkCTreeNode *node,
+void        gtk_sctree_set_node_info        (GtkCMCTree *ctree,
+                                             GtkCMCTreeNode *node,
                                              const gchar *text,
                                              guint8 spacing,
                                              GdkPixmap *pixmap_closed,
@@ -111,12 +112,12 @@ void        gtk_sctree_set_node_info        (GtkCTree *ctree,
                                              GdkBitmap *mask_opened,
                                              gboolean is_leaf,
                                              gboolean expanded);
-GtkCTreeNode *
-gtk_sctree_insert_gnode                    (GtkCTree          *ctree,
-                                            GtkCTreeNode      *parent,
-                                            GtkCTreeNode      *sibling,
+GtkCMCTreeNode *
+gtk_sctree_insert_gnode                    (GtkCMCTree          *ctree,
+                                            GtkCMCTreeNode      *parent,
+                                            GtkCMCTreeNode      *sibling,
                                             GNode             *gnode,
-                                            GtkCTreeGNodeFunc  func,
+                                            GtkCMCTreeGNodeFunc  func,
                                             gpointer           data);
 
 void gtk_sctree_set_column_tooltip         (GtkSCTree          *sctree,
index f88aefdba63edbdac636c86618dcaeda35c375c9..e390fa184220f1a8e5a538981eafb30995c4a4fc 100644 (file)
 #include <glib/gi18n.h>
 #include <gdk/gdkkeysyms.h>
 #include <gdk/gdk.h>
-#include <gtk/gtkwidget.h>
-#include <gtk/gtkhbbox.h>
-#include <gtk/gtkbutton.h>
-#include <gtk/gtkctree.h>
-#include <gtk/gtkcombo.h>
-#include <gtk/gtkbindings.h>
-#include <gtk/gtkitemfactory.h>
+#include <gtk/gtk.h>
+#include "gtk/gtksctree.h"
 #include <stdlib.h>
 #include <stdarg.h>
 #include <sys/stat.h>
@@ -221,9 +216,9 @@ void gtkut_stock_with_text_button_set_create(GtkWidget **bbox,
 #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \
                                   ((clist)->row_height + CELL_SPACING))
 
-void gtkut_ctree_node_move_if_on_the_edge(GtkCTree *ctree, GtkCTreeNode *node, gint _row)
+void gtkut_ctree_node_move_if_on_the_edge(GtkCMCTree *ctree, GtkCMCTreeNode *node, gint _row)
 {
-       GtkCList *clist = GTK_CLIST(ctree);
+       GtkCMCList *clist = GTK_CMCLIST(ctree);
        gint row;
        GtkVisibility row_visibility, prev_row_visibility, next_row_visibility;
 
@@ -233,12 +228,12 @@ void gtkut_ctree_node_move_if_on_the_edge(GtkCTree *ctree, GtkCTreeNode *node, g
        row = (_row != -1 ? _row : g_list_position(clist->row_list, (GList *)node));
 
        if (row < 0 || row >= clist->rows || clist->row_height == 0) return;
-       row_visibility = gtk_clist_row_is_visible(clist, row);
-       prev_row_visibility = gtk_clist_row_is_visible(clist, row - 1);
-       next_row_visibility = gtk_clist_row_is_visible(clist, row + 1);
+       row_visibility = gtk_cmclist_row_is_visible(clist, row);
+       prev_row_visibility = gtk_cmclist_row_is_visible(clist, row - 1);
+       next_row_visibility = gtk_cmclist_row_is_visible(clist, row + 1);
 
        if (row_visibility == GTK_VISIBILITY_NONE) {
-               gtk_clist_moveto(clist, row, -1, 0.5, 0);
+               gtk_cmclist_moveto(clist, row, -1, 0.5, 0);
                return;
        }
        if (row_visibility == GTK_VISIBILITY_FULL &&
@@ -250,11 +245,11 @@ void gtkut_ctree_node_move_if_on_the_edge(GtkCTree *ctree, GtkCTreeNode *node, g
                return;
 
        if (prev_row_visibility != GTK_VISIBILITY_FULL) {
-               gtk_clist_moveto(clist, row, -1, 0.2, 0);
+               gtk_cmclist_moveto(clist, row, -1, 0.2, 0);
                return;
        }
        if (next_row_visibility != GTK_VISIBILITY_FULL) {
-               gtk_clist_moveto(clist, row, -1, 0.8, 0);
+               gtk_cmclist_moveto(clist, row, -1, 0.8, 0);
                return;
        }
 }
@@ -263,115 +258,115 @@ void gtkut_ctree_node_move_if_on_the_edge(GtkCTree *ctree, GtkCTreeNode *node, g
 #undef ROW_TOP_YPIXEL
 #undef ROW_FROM_YPIXEL
 
-gint gtkut_ctree_get_nth_from_node(GtkCTree *ctree, GtkCTreeNode *node)
+gint gtkut_ctree_get_nth_from_node(GtkCMCTree *ctree, GtkCMCTreeNode *node)
 {
        g_return_val_if_fail(ctree != NULL, -1);
        g_return_val_if_fail(node != NULL, -1);
 
-       return g_list_position(GTK_CLIST(ctree)->row_list, (GList *)node);
+       return g_list_position(GTK_CMCLIST(ctree)->row_list, (GList *)node);
 }
 
 /* get the next node, including the invisible one */
-GtkCTreeNode *gtkut_ctree_node_next(GtkCTree *ctree, GtkCTreeNode *node)
+GtkCMCTreeNode *gtkut_ctree_node_next(GtkCMCTree *ctree, GtkCMCTreeNode *node)
 {
-       GtkCTreeNode *parent;
+       GtkCMCTreeNode *parent;
 
        if (!node) return NULL;
 
-       if (GTK_CTREE_ROW(node)->children)
-               return GTK_CTREE_ROW(node)->children;
+       if (GTK_CMCTREE_ROW(node)->children)
+               return GTK_CMCTREE_ROW(node)->children;
 
-       if (GTK_CTREE_ROW(node)->sibling)
-               return GTK_CTREE_ROW(node)->sibling;
+       if (GTK_CMCTREE_ROW(node)->sibling)
+               return GTK_CMCTREE_ROW(node)->sibling;
 
-       for (parent = GTK_CTREE_ROW(node)->parent; parent != NULL;
-            parent = GTK_CTREE_ROW(parent)->parent) {
-               if (GTK_CTREE_ROW(parent)->sibling)
-                       return GTK_CTREE_ROW(parent)->sibling;
+       for (parent = GTK_CMCTREE_ROW(node)->parent; parent != NULL;
+            parent = GTK_CMCTREE_ROW(parent)->parent) {
+               if (GTK_CMCTREE_ROW(parent)->sibling)
+                       return GTK_CMCTREE_ROW(parent)->sibling;
        }
 
        return NULL;
 }
 
 /* get the previous node, including the invisible one */
-GtkCTreeNode *gtkut_ctree_node_prev(GtkCTree *ctree, GtkCTreeNode *node)
+GtkCMCTreeNode *gtkut_ctree_node_prev(GtkCMCTree *ctree, GtkCMCTreeNode *node)
 {
-       GtkCTreeNode *prev;
-       GtkCTreeNode *child;
+       GtkCMCTreeNode *prev;
+       GtkCMCTreeNode *child;
 
        if (!node) return NULL;
 
-       prev = GTK_CTREE_NODE_PREV(node);
-       if (prev == GTK_CTREE_ROW(node)->parent)
+       prev = GTK_CMCTREE_NODE_PREV(node);
+       if (prev == GTK_CMCTREE_ROW(node)->parent)
                return prev;
 
        child = prev;
-       while (GTK_CTREE_ROW(child)->children != NULL) {
-               child = GTK_CTREE_ROW(child)->children;
-               while (GTK_CTREE_ROW(child)->sibling != NULL)
-                       child = GTK_CTREE_ROW(child)->sibling;
+       while (GTK_CMCTREE_ROW(child)->children != NULL) {
+               child = GTK_CMCTREE_ROW(child)->children;
+               while (GTK_CMCTREE_ROW(child)->sibling != NULL)
+                       child = GTK_CMCTREE_ROW(child)->sibling;
        }
 
        return child;
 }
 
-gboolean gtkut_ctree_node_is_selected(GtkCTree *ctree, GtkCTreeNode *node)
+gboolean gtkut_ctree_node_is_selected(GtkCMCTree *ctree, GtkCMCTreeNode *node)
 {
-       GtkCList *clist = GTK_CLIST(ctree);
+       GtkCMCList *clist = GTK_CMCLIST(ctree);
        GList *cur;
 
        for (cur = clist->selection; cur != NULL; cur = cur->next) {
-               if (node == GTK_CTREE_NODE(cur->data))
+               if (node == GTK_CMCTREE_NODE(cur->data))
                        return TRUE;
        }
 
        return FALSE;
 }
 
-GtkCTreeNode *gtkut_ctree_find_collapsed_parent(GtkCTree *ctree,
-                                               GtkCTreeNode *node)
+GtkCMCTreeNode *gtkut_ctree_find_collapsed_parent(GtkCMCTree *ctree,
+                                               GtkCMCTreeNode *node)
 {
        if (!node) return NULL;
 
-       while ((node = GTK_CTREE_ROW(node)->parent) != NULL) {
-               if (!GTK_CTREE_ROW(node)->expanded)
+       while ((node = GTK_CMCTREE_ROW(node)->parent) != NULL) {
+               if (!GTK_CMCTREE_ROW(node)->expanded)
                        return node;
        }
 
        return NULL;
 }
 
-void gtkut_ctree_expand_parent_all(GtkCTree *ctree, GtkCTreeNode *node)
+void gtkut_ctree_expand_parent_all(GtkCMCTree *ctree, GtkCMCTreeNode *node)
 {
        while ((node = gtkut_ctree_find_collapsed_parent(ctree, node)) != NULL)
-               gtk_ctree_expand(ctree, node);
+               gtk_cmctree_expand(ctree, node);
 }
 
-gboolean gtkut_ctree_node_is_parent(GtkCTreeNode *parent, GtkCTreeNode *node)
+gboolean gtkut_ctree_node_is_parent(GtkCMCTreeNode *parent, GtkCMCTreeNode *node)
 {
-       GtkCTreeNode *tmp;
+       GtkCMCTreeNode *tmp;
        g_return_val_if_fail(node != NULL, FALSE);
        g_return_val_if_fail(parent != NULL, FALSE);
        tmp = node;
        
        while (tmp) {
-               if(GTK_CTREE_ROW(tmp)->parent && GTK_CTREE_ROW(tmp)->parent == parent)
+               if(GTK_CMCTREE_ROW(tmp)->parent && GTK_CMCTREE_ROW(tmp)->parent == parent)
                        return TRUE;
-               tmp = GTK_CTREE_ROW(tmp)->parent;
+               tmp = GTK_CMCTREE_ROW(tmp)->parent;
        }
        
        return FALSE;
 }
 
-void gtkut_ctree_set_focus_row(GtkCTree *ctree, GtkCTreeNode *node)
+void gtkut_ctree_set_focus_row(GtkCMCTree *ctree, GtkCMCTreeNode *node)
 {
        if (node == NULL)
                return;
-       gtkut_clist_set_focus_row(GTK_CLIST(ctree),
+       gtkut_clist_set_focus_row(GTK_CMCLIST(ctree),
                                  gtkut_ctree_get_nth_from_node(ctree, node));
 }
 
-void gtkut_clist_set_focus_row(GtkCList *clist, gint row)
+void gtkut_clist_set_focus_row(GtkCMCList *clist, gint row)
 {
        clist->focus_row = row;
        GTKUT_CTREE_REFRESH(clist);
@@ -652,7 +647,7 @@ static void gtkut_clist_bindings_add(GtkWidget *clist)
        GtkBindingSet *binding_set;
 
        binding_set = gtk_binding_set_by_class
-               (GTK_CLIST_GET_CLASS(clist));
+               (GTK_CMCLIST_GET_CLASS(clist));
 
        gtk_binding_entry_add_signal(binding_set, GDK_n, GDK_CONTROL_MASK,
                                     "scroll_vertical", 2,
@@ -668,13 +663,13 @@ void gtkut_widget_init(void)
 {
        GtkWidget *clist;
 
-       clist = gtk_clist_new(1);
+       clist = gtk_cmclist_new(1);
        g_object_ref(GTK_OBJECT(clist));
        g_object_ref_sink(GTK_OBJECT(clist));
        gtkut_clist_bindings_add(clist);
        g_object_unref(GTK_OBJECT(clist));
 
-       clist = gtk_ctree_new(1, 0);
+       clist = gtk_cmctree_new(1, 0);
        g_object_ref(GTK_OBJECT(clist));
        g_object_ref_sink(GTK_OBJECT(clist));
        gtkut_clist_bindings_add(clist);
index 312a81f2193f2f488d0991b1319c56c9a784622a..f3aa73262b576d701b2eaff876105d8397df37e5 100644 (file)
 #include <gtk/gtkmain.h>
 #endif
 
-typedef struct _ComboButton    ComboButton;
-
-struct _ComboButton
-{
-       GtkWidget *arrow;
-       GtkWidget *button;
-       GtkWidget *menu;
-       GtkItemFactory *factory;
-       gpointer data;
-};
+#include "gtkcmctree.h"
 
 #define GTK_EVENTS_FLUSH() \
 { \
@@ -84,14 +75,14 @@ struct _ComboButton
 
 #define GTKUT_CTREE_NODE_SET_ROW_DATA(node, d) \
 { \
-       GTK_CTREE_ROW(node)->row.data = d; \
+       GTK_CMCTREE_ROW(node)->row.data = d; \
 }
 
 #define GTKUT_CTREE_NODE_GET_ROW_DATA(node) \
-       (GTK_CTREE_ROW(node)->row.data)
+       (GTK_CMCTREE_ROW(node)->row.data)
 
 #define GTKUT_CTREE_REFRESH(clist) \
-       GTK_CLIST_GET_CLASS(clist)->refresh(clist)
+       GTK_CMCLIST_GET_CLASS(clist)->refresh(clist)
 
 gboolean gtkut_get_font_size           (GtkWidget      *widget,
                                         gint           *width,
@@ -122,28 +113,28 @@ void gtkut_stock_with_text_button_set_create(GtkWidget **bbox,
                                   GtkWidget **button3, const gchar *label3, const gchar *text3);
 
 void gtkut_ctree_node_move_if_on_the_edge
-                                       (GtkCTree       *ctree,
-                                        GtkCTreeNode   *node,
+                                       (GtkCMCTree     *ctree,
+                                        GtkCMCTreeNode *node,
                                         gint            _row);
-gint gtkut_ctree_get_nth_from_node     (GtkCTree       *ctree,
-                                        GtkCTreeNode   *node);
-GtkCTreeNode *gtkut_ctree_node_next    (GtkCTree       *ctree,
-                                        GtkCTreeNode   *node);
-GtkCTreeNode *gtkut_ctree_node_prev    (GtkCTree       *ctree,
-                                        GtkCTreeNode   *node);
-gboolean gtkut_ctree_node_is_selected  (GtkCTree       *ctree,
-                                        GtkCTreeNode   *node);
-GtkCTreeNode *gtkut_ctree_find_collapsed_parent
-                                       (GtkCTree       *ctree,
-                                        GtkCTreeNode   *node);
-void gtkut_ctree_expand_parent_all     (GtkCTree       *ctree,
-                                        GtkCTreeNode   *node);
-gboolean gtkut_ctree_node_is_parent    (GtkCTreeNode   *parent, 
-                                        GtkCTreeNode   *node);
-void gtkut_ctree_set_focus_row         (GtkCTree       *ctree,
-                                        GtkCTreeNode   *node);
-
-void gtkut_clist_set_focus_row         (GtkCList       *clist,
+gint gtkut_ctree_get_nth_from_node     (GtkCMCTree     *ctree,
+                                        GtkCMCTreeNode *node);
+GtkCMCTreeNode *gtkut_ctree_node_next  (GtkCMCTree     *ctree,
+                                        GtkCMCTreeNode *node);
+GtkCMCTreeNode *gtkut_ctree_node_prev  (GtkCMCTree     *ctree,
+                                        GtkCMCTreeNode *node);
+gboolean gtkut_ctree_node_is_selected  (GtkCMCTree     *ctree,
+                                        GtkCMCTreeNode *node);
+GtkCMCTreeNode *gtkut_ctree_find_collapsed_parent
+                                       (GtkCMCTree     *ctree,
+                                        GtkCMCTreeNode *node);
+void gtkut_ctree_expand_parent_all     (GtkCMCTree     *ctree,
+                                        GtkCMCTreeNode *node);
+gboolean gtkut_ctree_node_is_parent    (GtkCMCTreeNode         *parent, 
+                                        GtkCMCTreeNode         *node);
+void gtkut_ctree_set_focus_row         (GtkCMCTree     *ctree,
+                                        GtkCMCTreeNode *node);
+
+void gtkut_clist_set_focus_row         (GtkCMCList     *clist,
                                         gint            row);
 
 void gtkut_container_remove            (GtkContainer   *container,
index 8aca2a9231cfb643acb67fca9e40512fe4c6c745..a7e89a87ba39f03f60d9ce04e44fcc170042a768 100644 (file)
@@ -87,24 +87,27 @@ static gint gtk_real_vscrollbutton_timer    (GtkVScrollbutton *scrollbutton);
 static void gtk_vscrollbutton_set_sensitivity   (GtkAdjustment    *adjustment,
                                                 GtkVScrollbutton *scrollbutton);
 
-GtkType gtk_vscrollbutton_get_type(void)
+GType gtk_vscrollbutton_get_type(void)
 {
-    static GtkType vscrollbutton_type = 0;
+    static GType vscrollbutton_type = 0;
 
     if (!vscrollbutton_type) {
-       static const GtkTypeInfo vscrollbutton_info = {
-           "GtkVScrollbutton",
-           sizeof(GtkVScrollbutton),
-           sizeof(GtkVScrollbuttonClass),
-           (GtkClassInitFunc) gtk_vscrollbutton_class_init,
-           (GtkObjectInitFunc) gtk_vscrollbutton_init,
-           /* reserved_1 */ NULL,
-           /* reserved_2 */ NULL,
-           (GtkClassInitFunc) NULL,
+       static const GTypeInfo vscrollbutton_info = {
+                       sizeof (GtkVScrollbuttonClass),
+
+                       (GBaseInitFunc) NULL,
+                       (GBaseFinalizeFunc) NULL,
+
+                       (GClassInitFunc) gtk_vscrollbutton_class_init,
+                       (GClassFinalizeFunc) NULL,
+                       NULL,   /* class_data */
+
+                       sizeof (GtkVScrollbutton),
+                       0,      /* n_preallocs */
+                       (GInstanceInitFunc) gtk_vscrollbutton_init,
        };
 
-       vscrollbutton_type =
-           gtk_type_unique(GTK_TYPE_VBOX, &vscrollbutton_info);
+       vscrollbutton_type = g_type_register_static (GTK_TYPE_VBOX, "GtkVScrollbutton", &vscrollbutton_info, (GTypeFlags)0);
     }
 
     return vscrollbutton_type;
@@ -206,7 +209,8 @@ static void gtk_vscrollbutton_init(GtkVScrollbutton *scrollbutton)
 GtkWidget *gtk_vscrollbutton_new(GtkAdjustment *adjustment)
 {
     GtkWidget *vscrollbutton;
-    vscrollbutton = GTK_WIDGET(gtk_type_new(gtk_vscrollbutton_get_type()));
+    vscrollbutton = g_object_new (gtk_vscrollbutton_get_type(),
+                       NULL);
     gtk_vscrollbutton_set_adjustment(GTK_VSCROLLBUTTON(vscrollbutton),
                                     adjustment);
     g_signal_connect(G_OBJECT(GTK_VSCROLLBUTTON(vscrollbutton)->adjustment),
index dda22b8130f9d8a009419bf271949c86e86d2a07..eb2411d44cf34c83605170d232509dd555c14a4b 100644 (file)
@@ -25,6 +25,7 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
+#include "gtkcmoptionmenu.h"
 #include "menu.h"
 #include "utils.h"
 #include "gtkutils.h"
@@ -166,7 +167,7 @@ void menu_button_position(GtkMenu *menu, gint *x, gint *y, gboolean *push_in,
                *y -= mreq.height;
 }
 
-gint menu_find_option_menu_index(GtkOptionMenu *optmenu, gpointer data,
+gint menu_find_option_menu_index(GtkCMOptionMenu *optmenu, gpointer data,
                                 GCompareFunc func)
 {
        GtkWidget *menu;
@@ -175,7 +176,7 @@ gint menu_find_option_menu_index(GtkOptionMenu *optmenu, gpointer data,
        GList *cur;
        gint n;
 
-       menu = gtk_option_menu_get_menu(optmenu);
+       menu = gtk_cmoption_menu_get_menu(optmenu);
 
        for (cur = GTK_MENU_SHELL(menu)->children, n = 0;
             cur != NULL; cur = cur->next, n++) {
@@ -204,6 +205,7 @@ static void connect_accel_change_signals(GtkWidget* widget, GtkWidget *wid2)
 
 void menu_connect_identical_items(void)
 {
+#if 0 /* DEPRECATED */
        gint n;
        GtkWidget *item1;
        GtkWidget *item2;
@@ -273,4 +275,5 @@ void menu_connect_identical_items(void)
                        if (!item2) debug_print(" ** Menu item not found: %s\n",pairs[n].path2);
                }                               
        }
+#endif
 }
index 74d1d38d99ef9d6b57ddae84a1a0e4e6bcdaaca8..00546e9b7178351fc51deefa75fda7ad54232344 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <glib.h>
 #include <gtk/gtk.h>
+#include "gtkcmoptionmenu.h"
 
 #define MENU_VAL_ID "Claws::Menu::ValueID"
 #define MENU_VAL_DATA "Claws::Menu::ValueDATA"
@@ -91,15 +92,15 @@ void cm_toggle_menu_set_active(gchar *menu, gboolean active);
 void cm_menu_set_sensitive_full(GtkUIManager *gui_manager, gchar *menu, gboolean sensitive);
 void cm_toggle_menu_set_active_full(GtkUIManager *gui_manager, gchar *menu, gboolean active);
 
+gint menu_find_option_menu_index(GtkCMOptionMenu *optmenu, gpointer data,
+                                GCompareFunc func);
+
 void menu_button_position      (GtkMenu                *menu,
                                 gint                   *x,
                                 gint                   *y,
                                 gboolean               *push_in,
                                 gpointer                user_data);
 
-gint menu_find_option_menu_index(GtkOptionMenu         *optmenu,
-                                gpointer                data,
-                                GCompareFunc            func);
 void menu_set_sensitive_all(GtkMenuShell *menu_shell, gboolean sensitive);
 void menu_connect_identical_items(void);
 
index 6a0599c98081093d05e2524b7fb98000bc5776f6..0ea51faa95b55f39fc853921d95291bcc43bba94 100644 (file)
@@ -29,6 +29,7 @@
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
 
+#include "gtkcmoptionmenu.h"
 #include "utils.h"
 #include "combobox.h"
 #include "menu.h"
@@ -87,10 +88,10 @@ gboolean quicksearch_is_fast(QuickSearch *quicksearch)
 static void quicksearch_set_type(QuickSearch *quicksearch, gint type)
 {
        gint index;
-       index = menu_find_option_menu_index(GTK_OPTION_MENU(quicksearch->search_type_opt), 
+       index = menu_find_option_menu_index(GTK_CMOPTION_MENU(quicksearch->search_type_opt), 
                                        GINT_TO_POINTER(type),
                                        NULL);
-       gtk_option_menu_set_history(GTK_OPTION_MENU(quicksearch->search_type_opt), index);      
+       gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(quicksearch->search_type_opt), index);  
 }
 
 static gchar *quicksearch_get_text(QuickSearch * quicksearch)
@@ -557,7 +558,7 @@ QuickSearch *quicksearch_new()
        /* quick search */
        hbox_search = gtk_hbox_new(FALSE, 0);
 
-       search_type_opt = gtk_option_menu_new();
+       search_type_opt = gtk_cmoption_menu_new();
        gtk_widget_show(search_type_opt);
        gtk_box_pack_start(GTK_BOX(hbox_search), search_type_opt, FALSE, FALSE, 0);
 
@@ -638,7 +639,7 @@ QuickSearch *quicksearch_new()
                         G_CALLBACK(searchtype_autorun_changed),
                         quicksearch);
 
-       gtk_option_menu_set_menu(GTK_OPTION_MENU(search_type_opt), search_type);
+       gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(search_type_opt), search_type);
 
        quicksearch->search_type_opt = search_type_opt;
        quicksearch_set_type(quicksearch, prefs_common.summary_quicksearch_type);
@@ -800,7 +801,7 @@ void quicksearch_show(QuickSearch *quicksearch)
        ctree = summary_get_main_widget(mainwin->summaryview);
        
        if (ctree && mainwin->summaryview->selected)
-               gtk_ctree_node_moveto(GTK_CTREE(ctree), 
+               gtk_cmctree_node_moveto(GTK_CMCTREE(ctree), 
                                mainwin->summaryview->selected, 
                                0, 0.5, 0);
 }
index 1399a3ed5a9f6b2385d85524d757c6aa0e07ce23..e100a760261d0a1706945294970bdec871936a91 100644 (file)
@@ -197,7 +197,7 @@ static void dillo_destroy_viewer(MimeViewer *_viewer)
                gtk_widget_destroy(viewer->socket);
        }
 
-       gtk_widget_unref(GTK_WIDGET(viewer->widget));
+       g_object_unref(GTK_WIDGET(viewer->widget));
        claws_unlink(viewer->filename);
        g_free(viewer->filename);
        g_free(viewer);
@@ -219,7 +219,7 @@ static MimeViewer *dillo_viewer_create(void)
        viewer->widget = gtk_event_box_new();
 
        gtk_widget_show(viewer->widget);
-       gtk_widget_ref(viewer->widget);
+       g_object_ref(viewer->widget);
 
        viewer->filename = NULL;
 
index 8335aa4869b2f8b8868610f8bd3452045e42d981..803af2f8b2ca3f6c88ada3a9c847e9768560106b 100644 (file)
@@ -53,7 +53,7 @@ struct select_keys_s {
     int okay;
     GtkWidget *window;
     GtkLabel *toplabel;
-    GtkCList *clist;
+    GtkCMCList *clist;
     const char *pattern;
     unsigned int num_keys;
     gpgme_key_t *kset;
@@ -65,7 +65,7 @@ struct select_keys_s {
 };
 
 
-static void set_row (GtkCList *clist, gpgme_key_t key, gpgme_protocol_t proto);
+static void set_row (GtkCMCList *clist, gpgme_key_t key, gpgme_protocol_t proto);
 static gpgme_key_t fill_clist (struct select_keys_s *sk, const char *pattern,
                        gpgme_protocol_t proto);
 static void create_dialog (struct select_keys_s *sk);
@@ -126,7 +126,7 @@ gpgmegtk_recipient_selection (GSList *recp_names, SelectionResult *result,
     do {
         sk.pattern = recp_names? recp_names->data:NULL;
        sk.proto = proto;
-        gtk_clist_clear (sk.clist);
+        gtk_cmclist_clear (sk.clist);
         key = fill_clist (&sk, sk.pattern, proto);
         update_progress (&sk, 0, sk.pattern);
        if (!key) {
@@ -172,7 +172,7 @@ destroy_key (gpointer data)
 }
 
 static void
-set_row (GtkCList *clist, gpgme_key_t key, gpgme_protocol_t proto)
+set_row (GtkCMCList *clist, gpgme_key_t key, gpgme_protocol_t proto)
 {
     const char *s;
     const char *text[N_COL_TITLES];
@@ -256,16 +256,16 @@ set_row (GtkCList *clist, gpgme_key_t key, gpgme_protocol_t proto)
       }
     text[COL_VALIDITY] = s;
 
-    row = gtk_clist_append (clist, (gchar**)text);
+    row = gtk_cmclist_append (clist, (gchar**)text);
     g_free (algo_buf);
 
-    gtk_clist_set_row_data_full (clist, row, key, destroy_key);
+    gtk_cmclist_set_row_data_full (clist, row, key, destroy_key);
 }
 
 static gpgme_key_t 
 fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t proto)
 {
-    GtkCList *clist;
+    GtkCMCList *clist;
     gpgme_ctx_t ctx;
     gpgme_error_t err;
     gpgme_key_t key;
@@ -279,7 +279,7 @@ fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t prot
 
     debug_print ("select_keys:fill_clist:  pattern '%s' proto %d\n", pattern, proto);
 
-    /*gtk_clist_freeze (select_keys.clist);*/
+    /*gtk_cmclist_freeze (select_keys.clist);*/
     err = gpgme_new (&ctx);
     g_assert (!err);
 
@@ -343,7 +343,7 @@ fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t prot
            sk->select_ctx = NULL;
            gpgme_release (ctx);
     }
-    /*gtk_clist_thaw (select_keys.clist);*/
+    /*gtk_cmclist_thaw (select_keys.clist);*/
     return (exact_match == TRUE && num_results == 1 ? last_key:NULL);
 }
 
@@ -396,18 +396,18 @@ create_dialog (struct select_keys_s *sk)
     titles[COL_EMAIL]    = _("Address");
     titles[COL_VALIDITY] = _("Val");
 
-    clist = gtk_clist_new_with_titles (N_COL_TITLES, (char**)titles);
+    clist = gtk_cmclist_new_with_titles (N_COL_TITLES, (char**)titles);
     gtk_container_add (GTK_CONTAINER (scrolledwin), clist);
-    gtk_clist_set_column_width (GTK_CLIST(clist), COL_ALGO,      72);
-    gtk_clist_set_column_width (GTK_CLIST(clist), COL_KEYID,     76);
-    gtk_clist_set_column_width (GTK_CLIST(clist), COL_NAME,     130);
-    gtk_clist_set_column_width (GTK_CLIST(clist), COL_EMAIL,    130);
-    gtk_clist_set_column_width (GTK_CLIST(clist), COL_VALIDITY,  20);
-    gtk_clist_set_selection_mode (GTK_CLIST(clist), GTK_SELECTION_BROWSE);
-    g_signal_connect (G_OBJECT(GTK_CLIST(clist)->column[COL_NAME].button),
+    gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_ALGO,      72);
+    gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_KEYID,     76);
+    gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_NAME,     130);
+    gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_EMAIL,    130);
+    gtk_cmclist_set_column_width (GTK_CMCLIST(clist), COL_VALIDITY,  20);
+    gtk_cmclist_set_selection_mode (GTK_CMCLIST(clist), GTK_SELECTION_BROWSE);
+    g_signal_connect (G_OBJECT(GTK_CMCLIST(clist)->column[COL_NAME].button),
                      "clicked",
                       G_CALLBACK(sort_keys_name), sk);
-    g_signal_connect (G_OBJECT(GTK_CLIST(clist)->column[COL_EMAIL].button),
+    g_signal_connect (G_OBJECT(GTK_CMCLIST(clist)->column[COL_EMAIL].button),
                      "clicked",
                       G_CALLBACK(sort_keys_email), sk);
 
@@ -440,7 +440,7 @@ create_dialog (struct select_keys_s *sk)
 
     sk->window = window;
     sk->toplabel = GTK_LABEL (label);
-    sk->clist  = GTK_CLIST (clist);
+    sk->clist  = GTK_CMCLIST (clist);
 }
 
 
@@ -505,7 +505,7 @@ select_btn_cb (GtkWidget *widget, gpointer data)
         return;
     }
     row = GPOINTER_TO_INT(sk->clist->selection->data);
-    key = gtk_clist_get_row_data(sk->clist, row);
+    key = gtk_cmclist_get_row_data(sk->clist, row);
     if (key) {
         if ( key->uids->validity < GPGME_VALIDITY_FULL ) {
             use_key = use_untrusted(key, sk->proto);
@@ -599,10 +599,10 @@ use_untrusted (gpgme_key_t key, gpgme_protocol_t proto)
 
 
 static gint 
-cmp_name (GtkCList *clist, gconstpointer pa, gconstpointer pb)
+cmp_name (GtkCMCList *clist, gconstpointer pa, gconstpointer pb)
 {
-    gpgme_key_t a = ((GtkCListRow *)pa)->data;
-    gpgme_key_t b = ((GtkCListRow *)pb)->data;
+    gpgme_key_t a = ((GtkCMCListRow *)pa)->data;
+    gpgme_key_t b = ((GtkCMCListRow *)pb)->data;
     const char *sa, *sb;
     
     sa = a? a->uids->name : NULL;
@@ -615,10 +615,10 @@ cmp_name (GtkCList *clist, gconstpointer pa, gconstpointer pb)
 }
 
 static gint 
-cmp_email (GtkCList *clist, gconstpointer pa, gconstpointer pb)
+cmp_email (GtkCMCList *clist, gconstpointer pa, gconstpointer pb)
 {
-    gpgme_key_t a = ((GtkCListRow *)pa)->data;
-    gpgme_key_t b = ((GtkCListRow *)pb)->data;
+    gpgme_key_t a = ((GtkCMCListRow *)pa)->data;
+    gpgme_key_t b = ((GtkCMCListRow *)pb)->data;
     const char *sa, *sb;
     
     sa = a? a->uids->email : NULL;
@@ -633,14 +633,14 @@ cmp_email (GtkCList *clist, gconstpointer pa, gconstpointer pb)
 static void
 sort_keys ( struct select_keys_s *sk, enum col_titles column)
 {
-    GtkCList *clist = sk->clist;
+    GtkCMCList *clist = sk->clist;
 
     switch (column) {
       case COL_NAME:
-        gtk_clist_set_compare_func (clist, cmp_name);
+        gtk_cmclist_set_compare_func (clist, cmp_name);
         break;
       case COL_EMAIL:
-        gtk_clist_set_compare_func (clist, cmp_email);
+        gtk_cmclist_set_compare_func (clist, cmp_email);
         break;
       default:
         return;
@@ -655,8 +655,8 @@ sort_keys ( struct select_keys_s *sk, enum col_titles column)
         sk->sort_type = GTK_SORT_ASCENDING;
 
     sk->sort_column = column;
-    gtk_clist_set_sort_type (clist, sk->sort_type);
-    gtk_clist_sort (clist);
+    gtk_cmclist_set_sort_type (clist, sk->sort_type);
+    gtk_cmclist_sort (clist);
 }
 
 static void
index 1189f6319a7e71ffe32a3b16f7af7a93d14e72ab..0941ca5d70daa474a1e6d747b89d7ffd8a57b073 100644 (file)
@@ -35,7 +35,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
-
+#include "gtkcmoptionmenu.h"
 #include "main.h"
 #include "prefs_gtk.h"
 #include "prefs_account.h"
@@ -2601,12 +2601,12 @@ static void advanced_create_widget_func(PrefsPage * _page,
                          G_CALLBACK (crosspost_color_toggled),
                          NULL);
 
-       colormenu_crosspost = gtk_option_menu_new();
+       colormenu_crosspost = gtk_cmoption_menu_new();
        gtk_widget_show (colormenu_crosspost);
        gtk_box_pack_start (GTK_BOX (hbox1), colormenu_crosspost, FALSE, FALSE, 0);
 
        menu = colorlabel_create_color_menu();
-       gtk_option_menu_set_menu (GTK_OPTION_MENU(colormenu_crosspost), menu);
+       gtk_cmoption_menu_set_menu (GTK_CMOPTION_MENU(colormenu_crosspost), menu);
        SET_TOGGLE_SENSITIVITY(checkbtn_crosspost, colormenu_crosspost);
 
        PACK_HBOX (hbox1);
@@ -3591,7 +3591,7 @@ static void prefs_account_crosspost_set_data_from_colormenu(PrefParam *pparam)
        GtkWidget *menu;
        GtkWidget *menuitem;
 
-       menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(advanced_page.crosspost_colormenu));
+       menu = gtk_cmoption_menu_get_menu(GTK_CMOPTION_MENU(advanced_page.crosspost_colormenu));
        menuitem = gtk_menu_get_active(GTK_MENU(menu));
        *((gint *)pparam->data) = GPOINTER_TO_INT
                (g_object_get_data(G_OBJECT(menuitem), "color"));
@@ -3600,12 +3600,12 @@ static void prefs_account_crosspost_set_data_from_colormenu(PrefParam *pparam)
 static void prefs_account_crosspost_set_colormenu(PrefParam *pparam)
 {
        gint colorlabel = *((gint *)pparam->data);
-       GtkOptionMenu *colormenu = GTK_OPTION_MENU(*pparam->widget);
+       GtkCMOptionMenu *colormenu = GTK_CMOPTION_MENU(*pparam->widget);
        GtkWidget *menu;
        GtkWidget *menuitem;
 
-       gtk_option_menu_set_history(colormenu, colorlabel);
-       menu = gtk_option_menu_get_menu(colormenu);
+       gtk_cmoption_menu_set_history(colormenu, colorlabel);
+       menu = gtk_cmoption_menu_get_menu(colormenu);
        menuitem = gtk_menu_get_active(GTK_MENU(menu));
        gtk_menu_item_activate(GTK_MENU_ITEM(menuitem));
 }
index 1cb26fe7980e211a1b852753b60c9ebee79b1c09..9d8b5f47f5c991e3a892835deba58023cf274d73 100644 (file)
@@ -33,6 +33,7 @@
 #include <string.h>
 #include <errno.h>
 
+#include "gtkcmoptionmenu.h"
 #include "main.h"
 #include "prefs_gtk.h"
 #include "prefs_filtering_action.h"
@@ -271,7 +272,7 @@ void prefs_filtering_action_open(GSList *action_list,
                prefs_filtering_action_create();
        } else {
                /* update color label menu */
-               gtk_option_menu_set_menu(GTK_OPTION_MENU(filtering_action.color_optmenu),
+               gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(filtering_action.color_optmenu),
                                colorlabel_create_color_menu());
        }
 
@@ -503,9 +504,9 @@ static void prefs_filtering_action_create(void)
        score_entry = gtk_spin_button_new_with_range(-1000, 1000, 1);
        gtk_box_pack_start(GTK_BOX(hbox1), score_entry, FALSE, FALSE, 0);
        
-       color_optmenu = gtk_option_menu_new();
+       color_optmenu = gtk_cmoption_menu_new();
        gtk_size_group_add_widget(size_action, color_optmenu);
-       gtk_option_menu_set_menu(GTK_OPTION_MENU(color_optmenu),
+       gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(color_optmenu),
                                 colorlabel_create_color_menu());
        prefs_filtering_action_check_widget_width(color_optmenu);
        gtk_box_pack_start(GTK_BOX(hbox1), color_optmenu, FALSE, FALSE, 0);
@@ -904,7 +905,7 @@ static FilteringAction * prefs_filtering_action_dialog_to_action(gboolean alert)
                break;
        case ACTION_COLOR:
                labelcolor = colorlabel_get_color_menu_active_item(
-                       gtk_option_menu_get_menu(GTK_OPTION_MENU(filtering_action.color_optmenu)));
+                       gtk_cmoption_menu_get_menu(GTK_CMOPTION_MENU(filtering_action.color_optmenu)));
                destination = NULL;     
                break;
         case ACTION_CHANGE_SCORE:
@@ -1273,8 +1274,8 @@ static void prefs_filtering_action_enable_widget(GtkWidget* widget, const gboole
                        gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), 0);
                else if(GTK_IS_ENTRY(widget)) {
                        gtk_entry_set_text(GTK_ENTRY(widget), "");
-               } else if(GTK_IS_OPTION_MENU(widget))
-                       gtk_option_menu_set_history(GTK_OPTION_MENU(widget), 0);
+               } else if(GTK_IS_CMOPTION_MENU(widget))
+                       gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(widget), 0);
                
                gtk_widget_set_sensitive(widget, TRUE);
                gtk_widget_show(widget);
@@ -1572,7 +1573,7 @@ static gboolean prefs_filtering_actions_selected
        case MATCHACTION_COLOR:
                combobox_select_by_data(GTK_COMBO_BOX(filtering_action.action_combo),
                                     ACTION_COLOR);
-               gtk_option_menu_set_history(GTK_OPTION_MENU(filtering_action.color_optmenu),
+               gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(filtering_action.color_optmenu),
                                            action->labelcolor);     
                break;
        case MATCHACTION_CHANGE_SCORE:
index 1ee23c1940531bc0433ab418475a4a8c4cc9ec0a..45182177477f538acb5ed15cfffac65c8d439d7e 100644 (file)
@@ -33,6 +33,7 @@
 #include <string.h>
 #include <errno.h>
 
+#include "gtkcmoptionmenu.h"
 #include "main.h"
 #include "prefs_gtk.h"
 #include "prefs_matcher.h"
@@ -422,7 +423,7 @@ void prefs_matcher_open(MatcherList *matchers, PrefsMatcherSignal *cb)
                prefs_matcher_create();
        } else {
                /* update color label menu */
-               gtk_option_menu_set_menu(GTK_OPTION_MENU(matcher.color_optmenu),
+               gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(matcher.color_optmenu),
                                colorlabel_create_color_menu());
        }
 
@@ -656,8 +657,8 @@ static void prefs_matcher_create(void)
        gtk_box_pack_start(GTK_BOX(match_hbox), match_combo, TRUE, TRUE, 0);
        
        /* color labels combo */
-       color_optmenu = gtk_option_menu_new();
-       gtk_option_menu_set_menu(GTK_OPTION_MENU(color_optmenu),
+       color_optmenu = gtk_cmoption_menu_new();
+       gtk_cmoption_menu_set_menu(GTK_CMOPTION_MENU(color_optmenu),
                                 colorlabel_create_color_menu());
        gtk_box_pack_start(GTK_BOX(match_hbox), color_optmenu, FALSE, FALSE, 0);
        
@@ -868,7 +869,7 @@ static void prefs_matcher_reset_condition(void)
        gtk_combo_box_set_active(GTK_COMBO_BOX(matcher.criteria_combo2), 0);
        gtk_combo_box_set_active(GTK_COMBO_BOX(matcher.match_combo), 0);
        gtk_combo_box_set_active(GTK_COMBO_BOX(matcher.match_combo2), 0);
-       gtk_option_menu_set_history(GTK_OPTION_MENU(matcher.color_optmenu), 0);
+       gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(matcher.color_optmenu), 0);
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(matcher.numeric_entry), 0);
        gtk_entry_set_text(GTK_ENTRY(matcher.header_entry), "");
        gtk_entry_set_text(GTK_ENTRY(matcher.header_addr_entry), "");
@@ -1440,7 +1441,7 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
                
        case CRITERIA_COLORLABEL:
                value = colorlabel_get_color_menu_active_item
-                       (gtk_option_menu_get_menu(GTK_OPTION_MENU
+                       (gtk_cmoption_menu_get_menu(GTK_CMOPTION_MENU
                                (matcher.color_optmenu))); 
                break;
 
@@ -1836,7 +1837,7 @@ static void prefs_matcher_criteria_select(GtkWidget *widget,
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.case_checkbtn), FALSE);
                break;
        case MATCH_LABEL:
-               gtk_option_menu_set_history(GTK_OPTION_MENU(matcher.color_optmenu), 0);
+               gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(matcher.color_optmenu), 0);
                prefs_matcher_set_model(matcher.match_combo2, matcher.model_set);
                gtk_label_set_text(GTK_LABEL(matcher.match_label), _("Label"));
                gtk_label_set_text(GTK_LABEL(matcher.match_label2), _("is"));
@@ -2394,9 +2395,9 @@ static gboolean prefs_matcher_selected(GtkTreeSelection *selector,
 
        case MATCHCRITERIA_NOT_COLORLABEL:
        case MATCHCRITERIA_COLORLABEL:
-               gtk_option_menu_set_history(GTK_OPTION_MENU(matcher.color_optmenu),
+               gtk_cmoption_menu_set_history(GTK_CMOPTION_MENU(matcher.color_optmenu),
                                            prop->value);
-               menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(matcher.color_optmenu));
+               menu = gtk_cmoption_menu_get_menu(GTK_CMOPTION_MENU(matcher.color_optmenu));
                g_signal_emit_by_name(G_OBJECT(menu), "selection-done", menu);
                break;