Merge remote-tracking branch 'origin/master' into sheet
authorJohn Darrington <john@darrington.wattle.id.au>
Sat, 6 Aug 2016 17:40:31 +0000 (19:40 +0200)
committerJohn Darrington <john@darrington.wattle.id.au>
Sat, 6 Aug 2016 17:40:31 +0000 (19:40 +0200)
Conflicts:
src/ui/gui/automake.mk
src/ui/gui/psppire-data-editor.c
src/ui/gui/psppire-data-sheet.c
src/ui/gui/psppire-var-sheet.c

23 files changed:
1  2 
configure.ac
src/ui/gui/automake.mk
src/ui/gui/pspp-sheet-private.h
src/ui/gui/pspp-sheet-selection.c
src/ui/gui/pspp-sheet-selection.h
src/ui/gui/pspp-sheet-view-column.c
src/ui/gui/pspp-sheet-view-column.h
src/ui/gui/pspp-sheet-view.c
src/ui/gui/pspp-sheet-view.h
src/ui/gui/pspp-widget-facade.c
src/ui/gui/pspp-widget-facade.h
src/ui/gui/psppire-button-editable.c
src/ui/gui/psppire-button-editable.h
src/ui/gui/psppire-cell-renderer-button.c
src/ui/gui/psppire-cell-renderer-button.h
src/ui/gui/psppire-data-editor.c
src/ui/gui/psppire-data-editor.h
src/ui/gui/psppire-data-sheet.c
src/ui/gui/psppire-data-sheet.h
src/ui/gui/psppire-data-window.c
src/ui/gui/psppire-import-assistant.c
src/ui/gui/psppire-var-sheet.h
src/ui/gui/widgets.c

diff --cc configure.ac
Simple merge
index 1155cf70db779a1b41dd91f9f030b1e9bdc3bd91,e991eb2e47532e125c5151467f4ade270cc5249e..f4791522a487fbfce5d001d727d0978be915ade6
@@@ -126,19 -121,19 +122,6 @@@ dist_src_ui_gui_psppire_DATA = 
        $(top_srcdir)/src/ui/gui/psppire.gtkrc
  
  src_ui_gui_psppire_SOURCES = \
--      src/ui/gui/pspp-sheet-private.h \
--      src/ui/gui/pspp-sheet-selection.c \
--      src/ui/gui/pspp-sheet-selection.h \
--      src/ui/gui/pspp-sheet-view-column.c \
--      src/ui/gui/pspp-sheet-view-column.h \
--      src/ui/gui/pspp-sheet-view.c \
--      src/ui/gui/pspp-sheet-view.h \
--      src/ui/gui/pspp-widget-facade.c \
--      src/ui/gui/pspp-widget-facade.h \
--      src/ui/gui/psppire-button-editable.c \
--      src/ui/gui/psppire-button-editable.h \
--      src/ui/gui/psppire-cell-renderer-button.c \
--      src/ui/gui/psppire-cell-renderer-button.h \
        src/ui/gui/psppire-dialog.c \
        src/ui/gui/psppire-keypad.c \
        src/ui/gui/psppire-selector.c \
        src/ui/gui/psppire-value-entry.h \
        src/ui/gui/psppire-var-ptr.c \
        src/ui/gui/psppire-var-ptr.h \
 -      src/ui/gui/psppire-var-sheet.c \
--      src/ui/gui/psppire-var-sheet.h \
 +      src/ui/gui/psppire-var-sheet-header.h \
 +      src/ui/gui/psppire-var-sheet-header.c \
-       src/ui/gui/psppire-vbuttonbox.h \
        src/ui/gui/psppire-window.c \
        src/ui/gui/psppire-window.h \
        src/ui/gui/psppire-window-base.c \
@@@ -386,10 -384,10 +372,12 @@@ desktop_DATA = src/ui/gui/pspp.deskto
  appdatadir = $(datadir)/appdata
  dist_appdata_DATA = src/ui/gui/pspp.appdata.xml
  
- BUILT_SOURCES += src/ui/gui/psppire-marshal.c src/ui/gui/psppire-marshal.h
+ BUILT_SOURCES += src/ui/gui/psppire-marshal.c src/ui/gui/psppire-marshal.h src/ui/gui/resources.c
  CLEANFILES += src/ui/gui/psppire-marshal.c src/ui/gui/psppire-marshal.h \
-       $(nodist_src_ui_gui_psppire_DATA)
 -      src/ui/gui/resources.c $(nodist_src_ui_gui_psppire_DATA)
++      src/ui/gui/resources.c $(nodist_src_ui_gui_psppire_DATA) 
++
 +include $(top_srcdir)/src/ui/gui/efficient-sheet.mk
  endif HAVE_GUI
  
  #ensure the installcheck passes even if there is no X server available
diff --cc src/ui/gui/pspp-sheet-private.h
index a19c7c5b783bf60bef8916a8616be49a091e86c8,a19c7c5b783bf60bef8916a8616be49a091e86c8..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,455 -1,455 +1,0 @@@
-- /* PSPPIRE - a graphical user interface for PSPP.
--    Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc.
--
--    This program is free software: you can redistribute it and/or modify
--    it under the terms of the GNU General Public License as published by
--    the Free Software Foundation, either version 3 of the License, or
--    (at your option) any later version.
--
--    This program 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 General Public License for more details.
--
--    You should have received a copy of the GNU General Public License
--    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--/* gtktreeprivate.h
-- * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Library 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
-- * Library General Public License for more details.
-- *
-- * You should have received a copy of the GNU Library 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.
-- */
--
--#ifndef __GTK_TREE_PRIVATE_H__
--#define __GTK_TREE_PRIVATE_H__
--
--
--#include <gtk/gtk.h>
--#include "libpspp/range-tower.h"
--#include "ui/gui/pspp-sheet-view.h"
--#include "ui/gui/pspp-sheet-view-column.h"
--
--#define TREE_VIEW_DRAG_WIDTH 6
--
--typedef enum
--{
--  PSPP_SHEET_VIEW_IN_COLUMN_RESIZE = 1 << 2,
--  PSPP_SHEET_VIEW_HEADERS_VISIBLE = 1 << 4,
--  PSPP_SHEET_VIEW_DRAW_KEYFOCUS = 1 << 5,
--  PSPP_SHEET_VIEW_MODEL_SETUP = 1 << 6,
--  PSPP_SHEET_VIEW_IN_COLUMN_DRAG = 1 << 7
--} PsppSheetViewFlags;
--
--enum
--{
--  DRAG_COLUMN_WINDOW_STATE_UNSET = 0,
--  DRAG_COLUMN_WINDOW_STATE_ORIGINAL = 1,
--  DRAG_COLUMN_WINDOW_STATE_ARROW = 2,
--  DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT = 3,
--  DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT = 4
--};
--
--enum
--{
--  RUBBER_BAND_OFF = 0,
--  RUBBER_BAND_MAYBE_START = 1,
--  RUBBER_BAND_ACTIVE = 2
--};
--
--#define PSPP_SHEET_VIEW_SET_FLAG(tree_view, flag)   G_STMT_START{ (tree_view->priv->flags|=flag); }G_STMT_END
--#define PSPP_SHEET_VIEW_UNSET_FLAG(tree_view, flag) G_STMT_START{ (tree_view->priv->flags&=~(flag)); }G_STMT_END
--#define PSPP_SHEET_VIEW_FLAG_SET(tree_view, flag)   ((tree_view->priv->flags&flag)==flag)
--#define TREE_VIEW_HEADER_HEIGHT(tree_view)        (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE)?tree_view->priv->header_height:0)
--#define TREE_VIEW_COLUMN_REQUESTED_WIDTH(column)  (CLAMP (column->requested_width, (column->min_width!=-1)?column->min_width:column->requested_width, (column->max_width!=-1)?column->max_width:column->requested_width))
--
-- /* This lovely little value is used to determine how far away from the title bar
--  * you can move the mouse and still have a column drag work.
--  */
--#define TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER(tree_view) (10*TREE_VIEW_HEADER_HEIGHT(tree_view))
--
--typedef struct _PsppSheetViewColumnReorder PsppSheetViewColumnReorder;
--struct _PsppSheetViewColumnReorder
--{
--  gint left_align;
--  gint right_align;
--  PsppSheetViewColumn *left_column;
--  PsppSheetViewColumn *right_column;
--};
--
--struct _PsppSheetViewPrivate
--{
--  GtkTreeModel *model;
--
--  guint flags;
--  /* tree information */
--  gint row_count;
--  struct range_tower *selected;
--
--  /* Container info */
--  GList *children;
--  gint width;
--  gint height;
--
--  /* Adjustments */
--  GtkAdjustment *hadjustment;
--  GtkAdjustment *vadjustment;
--
--  /* Sub windows */
--  GdkWindow *bin_window;
--  GdkWindow *header_window;
--
--  /* Scroll position state keeping */
--  GtkTreeRowReference *top_row;
--  gint top_row_dy;
--  /* dy == y pos of top_row + top_row_dy */
--  /* we cache it for simplicity of the code */
--  gint dy;
--
--  guint presize_handler_timer;
--  guint validate_rows_timer;
--  guint scroll_sync_timer;
--
--  /* Indentation and expander layout */
--  gint expander_size;
--
--  /* Key navigation (focus), selection */
--  gint cursor_offset;
--
--  GtkTreeRowReference *anchor;
--  GtkTreeRowReference *cursor;
--
--  PsppSheetViewColumn *focus_column;
--
--  /* Current pressed node, previously pressed, prelight */
--  gint pressed_button;
--  gint press_start_x;
--  gint press_start_y;
--  gint press_start_node;
--
--  gint event_last_x;
--  gint event_last_y;
--
--  guint last_button_time;
--  gint last_button_x;
--  gint last_button_y;
--
--  int prelight_node;
--
--  /* Cell Editing */
--  PsppSheetViewColumn *edited_column;
--  gint edited_row;
--
--  /* Selection information */
--  PsppSheetSelection *selection;
--
--  /* Header information */
--  gint n_columns;
--  GList *columns;
--  gint header_height;
--  gint n_selected_columns;
--
--  PsppSheetViewColumnDropFunc column_drop_func;
--  gpointer column_drop_func_data;
--  GDestroyNotify column_drop_func_data_destroy;
--  GList *column_drag_info;
--  PsppSheetViewColumnReorder *cur_reorder;
--
--  /* Interactive Header reordering */
--  GdkWindow *drag_window;
--  GdkWindow *drag_highlight_window;
--  PsppSheetViewColumn *drag_column;
--  gint drag_column_x;
--
--  /* Interactive Header Resizing */
--  gint drag_pos;
--  gint x_drag;
--
--  /* Non-interactive Header Resizing, expand flag support */
--  gint prev_width;
--
--  /* ATK Hack */
--  PsppSheetDestroyCountFunc destroy_count_func;
--  gpointer destroy_count_data;
--  GDestroyNotify destroy_count_destroy;
--
--  /* Scroll timeout (e.g. during dnd, rubber banding) */
--  guint scroll_timeout;
--
--  /* Row drag-and-drop */
--  GtkTreeRowReference *drag_dest_row;
--  PsppSheetViewDropPosition drag_dest_pos;
--  guint open_dest_timeout;
--
--  /* Rubber banding */
--  gint rubber_band_status;
--  gint rubber_band_x;
--  gint rubber_band_y;
--  gint rubber_band_shift;
--  gint rubber_band_ctrl;
--
--  int rubber_band_start_node;
--
--  int rubber_band_end_node;
--
--  /* Rectangular selection. */
--  PsppSheetViewColumn *anchor_column; /* XXX needs to be a weak pointer? */
--
--  /* fixed height */
--  gint fixed_height;
--  gboolean fixed_height_set;
--
--  /* Scroll-to functionality when unrealized */
--  GtkTreeRowReference *scroll_to_path;
--  PsppSheetViewColumn *scroll_to_column;
--  gfloat scroll_to_row_align;
--  gfloat scroll_to_col_align;
--
--  /* Interactive search */
--  gint selected_iter;
--  gint search_column;
--  PsppSheetViewSearchPositionFunc search_position_func;
--  PsppSheetViewSearchEqualFunc search_equal_func;
--  gpointer search_user_data;
--  GDestroyNotify search_destroy;
--  gpointer search_position_user_data;
--  GDestroyNotify search_position_destroy;
--  GtkWidget *search_window;
--  GtkWidget *search_entry;
--  guint search_entry_changed_id;
--  guint typeselect_flush_timeout;
--
--  /* Grid and tree lines */
--  PsppSheetViewGridLines grid_lines;
--
--  /* Special cells. */
--  PsppSheetViewSpecialCells special_cells;
--
--  /* Tooltip support */
--  gint tooltip_column;
--
--  /* Cached style for button facades in columns. */
--  GtkStyle *button_style;
--
--  /* Here comes the bitfield */
--  guint scroll_to_use_align : 1;
--
--  guint reorderable : 1;
--  guint header_has_focus : 1;
--  guint drag_column_window_state : 3;
--  /* hint to display rows in alternating colors */
--  guint has_rules : 1;
--
--  /* for DnD */
--  guint empty_view_drop : 1;
--
--  guint init_hadjust_value : 1;
--
--  guint in_top_row_to_dy : 1;
--
--  /* interactive search */
--  guint enable_search : 1;
--  guint disable_popdown : 1;
--  guint search_custom_entry_set : 1;
--  
--  guint hover_selection : 1;
--  guint imcontext_changed : 1;
--
--  guint rubber_banding_enable : 1;
--
--  guint in_grab : 1;
--
--  guint post_validation_flag : 1;
--
--  /* Whether our key press handler is to avoid sending an unhandled binding to the search entry */
--
--  guint search_entry_avoid_unhandled_binding : 1;
--  /* GtkScrollablePolicy needs to be checked when
--   * driving the scrollable adjustment values */
--  guint hscroll_policy : 1;
--  guint vscroll_policy : 1;
--
--  /* For optimisation of size allocate requests */
--  guint resized : 1;
-- };
--
--#ifdef __GNUC__
--
--#define TREE_VIEW_INTERNAL_ASSERT(expr, ret)     G_STMT_START{          \
--     if (!(expr))                                                       \
--       {                                                                \
--         g_log (G_LOG_DOMAIN,                                           \
--                G_LOG_LEVEL_CRITICAL,                                   \
--              "%s (%s): assertion `%s' failed.\n"                     \
--              "There is a disparity between the internal view of the PsppSheetView,\n"    \
--              "and the GtkTreeModel.  This generally means that the model has changed\n"\
--              "without letting the view know.  Any display from now on is likely to\n"  \
--              "be incorrect.\n",                                                        \
--                G_STRLOC,                                               \
--                G_STRFUNC,                                              \
--                #expr);                                                 \
--         return ret;                                                    \
--       };                               }G_STMT_END
--
--#define TREE_VIEW_INTERNAL_ASSERT_VOID(expr)     G_STMT_START{          \
--     if (!(expr))                                                       \
--       {                                                                \
--         g_log (G_LOG_DOMAIN,                                           \
--                G_LOG_LEVEL_CRITICAL,                                   \
--              "%s (%s): assertion `%s' failed.\n"                     \
--              "There is a disparity between the internal view of the PsppSheetView,\n"    \
--              "and the GtkTreeModel.  This generally means that the model has changed\n"\
--              "without letting the view know.  Any display from now on is likely to\n"  \
--              "be incorrect.\n",                                                        \
--                G_STRLOC,                                               \
--                G_STRFUNC,                                              \
--                #expr);                                                 \
--         return;                                                        \
--       };                               }G_STMT_END
--
--#else
--
--#define TREE_VIEW_INTERNAL_ASSERT(expr, ret)     G_STMT_START{          \
--     if (!(expr))                                                       \
--       {                                                                \
--         g_log (G_LOG_DOMAIN,                                           \
--                G_LOG_LEVEL_CRITICAL,                                   \
--              "file %s: line %d: assertion `%s' failed.\n"       \
--              "There is a disparity between the internal view of the PsppSheetView,\n"    \
--              "and the GtkTreeModel.  This generally means that the model has changed\n"\
--              "without letting the view know.  Any display from now on is likely to\n"  \
--              "be incorrect.\n",                                                        \
--                __FILE__,                                               \
--                __LINE__,                                               \
--                #expr);                                                 \
--         return ret;                                                    \
--       };                               }G_STMT_END
--
--#define TREE_VIEW_INTERNAL_ASSERT_VOID(expr)     G_STMT_START{          \
--     if (!(expr))                                                       \
--       {                                                                \
--         g_log (G_LOG_DOMAIN,                                           \
--                G_LOG_LEVEL_CRITICAL,                                   \
--              "file %s: line %d: assertion '%s' failed.\n"            \
--              "There is a disparity between the internal view of the PsppSheetView,\n"    \
--              "and the GtkTreeModel.  This generally means that the model has changed\n"\
--              "without letting the view know.  Any display from now on is likely to\n"  \
--              "be incorrect.\n",                                                        \
--                __FILE__,                                               \
--                __LINE__,                                               \
--                #expr);                                                 \
--         return;                                                        \
--       };                               }G_STMT_END
--#endif
--
--
--/* functions that shouldn't be exported */
--void         _pspp_sheet_selection_internal_select_node (PsppSheetSelection  *selection,
--                                                     int                node,
--                                                     GtkTreePath       *path,
--                                                       PsppSheetSelectMode  mode,
--                                                     gboolean           override_browse_mode);
--void         _pspp_sheet_selection_emit_changed         (PsppSheetSelection  *selection);
--void         _pspp_sheet_view_find_node                 (PsppSheetView       *tree_view,
--                                                     GtkTreePath       *path,
--                                                     int              *node);
--GtkTreePath *_pspp_sheet_view_find_path                 (PsppSheetView       *tree_view,
--                                                     int                    node);
--void         _pspp_sheet_view_child_move_resize         (PsppSheetView       *tree_view,
--                                                     GtkWidget         *widget,
--                                                     gint               x,
--                                                     gint               y,
--                                                     gint               width,
--                                                     gint               height);
--void         _pspp_sheet_view_queue_draw_node           (PsppSheetView       *tree_view,
--                                                     int                    node,
--                                                     const GdkRectangle *clip_rect);
--
--void _pspp_sheet_view_column_realize_button   (PsppSheetViewColumn *column);
--void _pspp_sheet_view_column_unrealize_button (PsppSheetViewColumn *column);
--void _pspp_sheet_view_column_set_tree_view    (PsppSheetViewColumn *column,
--                                           PsppSheetView       *tree_view);
--void _pspp_sheet_view_column_unset_model      (PsppSheetViewColumn *column,
--                                           GtkTreeModel      *old_model);
--void _pspp_sheet_view_column_unset_tree_view  (PsppSheetViewColumn *column);
--void _pspp_sheet_view_column_set_width        (PsppSheetViewColumn *column,
--                                           gint               width);
--void _pspp_sheet_view_column_start_drag       (PsppSheetView       *tree_view,
--                                           PsppSheetViewColumn *column);
--gboolean _pspp_sheet_view_column_cell_event   (PsppSheetViewColumn  *tree_column,
--                                           GtkCellEditable   **editable_widget,
--                                           GdkEvent           *event,
--                                           gchar              *path_string,
--                                           const GdkRectangle *background_area,
--                                           const GdkRectangle *cell_area,
--                                           guint               flags);
--void _pspp_sheet_view_column_start_editing (PsppSheetViewColumn *tree_column,
--                                        GtkCellEditable   *editable_widget);
--void _pspp_sheet_view_column_stop_editing  (PsppSheetViewColumn *tree_column);
--void _pspp_sheet_view_install_mark_rows_col_dirty (PsppSheetView *tree_view);
--void             _pspp_sheet_view_column_autosize          (PsppSheetView       *tree_view,
--                                                        PsppSheetViewColumn *column);
--
--gboolean         _pspp_sheet_view_column_has_editable_cell (PsppSheetViewColumn *column);
--GtkCellRenderer *_pspp_sheet_view_column_get_edited_cell   (PsppSheetViewColumn *column);
--gint             _pspp_sheet_view_column_count_special_cells (PsppSheetViewColumn *column);
--GtkCellRenderer *_pspp_sheet_view_column_get_cell_at_pos   (PsppSheetViewColumn *column,
--                                                        gint               x);
--
--PsppSheetSelection* _pspp_sheet_selection_new                (void);
--PsppSheetSelection* _pspp_sheet_selection_new_with_tree_view (PsppSheetView      *tree_view);
--void              _pspp_sheet_selection_set_tree_view      (PsppSheetSelection *selection,
--                                                          PsppSheetView      *tree_view);
--
--void            _pspp_sheet_view_column_cell_render      (PsppSheetViewColumn  *tree_column,
--                                                          cairo_t *cr,
--                                                        const GdkRectangle *background_area,
--                                                        const GdkRectangle *cell_area,
--                                                        guint               flags);
--void            _pspp_sheet_view_column_get_focus_area   (PsppSheetViewColumn  *tree_column,
--                                                        const GdkRectangle *background_area,
--                                                        const GdkRectangle *cell_area,
--                                                        GdkRectangle       *focus_area);
--gboolean        _pspp_sheet_view_column_cell_focus       (PsppSheetViewColumn  *tree_column,
--                                                        gint                direction,
--                                                        gboolean            left,
--                                                        gboolean            right);
--void            _pspp_sheet_view_column_cell_draw_focus  (PsppSheetViewColumn  *tree_column,
--                                                          cairo_t *cr,
--                                                        const GdkRectangle *background_area,
--                                                        const GdkRectangle *cell_area,
--                                                        guint               flags);
--void            _pspp_sheet_view_column_cell_set_dirty         (PsppSheetViewColumn  *tree_column);
--void              _pspp_sheet_view_column_get_neighbor_sizes (PsppSheetViewColumn *column,
--                                                          GtkCellRenderer   *cell,
--                                                          gint              *left,
--                                                          gint              *right);
--
--gboolean pspp_sheet_view_node_is_selected (PsppSheetView *tree_view,
--                                           int node);
--void pspp_sheet_view_node_select (PsppSheetView *tree_view,
--                                  int node);
--void pspp_sheet_view_node_unselect (PsppSheetView *tree_view,
--                                    int node);
--
--gint
--pspp_sheet_view_node_next (PsppSheetView *tree_view,
--                           gint node);
--gint
--pspp_sheet_view_node_prev (PsppSheetView *tree_view,
--                           gint node);
--
--#endif /* __GTK_TREE_PRIVATE_H__ */
--
diff --cc src/ui/gui/pspp-sheet-selection.c
index 13c69c0ed6ed59dbc05493cdf1b7c5299a0bbea4,13c69c0ed6ed59dbc05493cdf1b7c5299a0bbea4..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,1303 -1,1303 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--/* gtktreeselection.h
-- * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Library 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
-- * Library General Public License for more details.
-- *
-- * You should have received a copy of the GNU Library 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.
-- */
--
--#include <config.h>
--
--#include "ui/gui/pspp-sheet-private.h"
--
--#include <gtk/gtk.h>
--#include <string.h>
--
--#include "ui/gui/pspp-sheet-selection.h"
--
--#include "libpspp/range-set.h"
--
--static void pspp_sheet_selection_finalize          (GObject               *object);
--static gint pspp_sheet_selection_real_select_all   (PsppSheetSelection      *selection);
--static gint pspp_sheet_selection_real_unselect_all (PsppSheetSelection      *selection);
--static gint pspp_sheet_selection_real_select_node  (PsppSheetSelection      *selection,
--                                                int node,
--                                                gboolean               select);
--
--enum
--{
--  CHANGED,
--  LAST_SIGNAL
--};
--
--static guint tree_selection_signals [LAST_SIGNAL] = { 0 };
--
--G_DEFINE_TYPE (PsppSheetSelection, pspp_sheet_selection, G_TYPE_OBJECT)
--
--static void
--pspp_sheet_selection_class_init (PsppSheetSelectionClass *class)
--{
--  GObjectClass *object_class;
--
--  object_class = (GObjectClass*) class;
--
--  object_class->finalize = pspp_sheet_selection_finalize;
--  class->changed = NULL;
--
--  tree_selection_signals[CHANGED] =
--    g_signal_new ("changed",
--                G_OBJECT_CLASS_TYPE (object_class),
--                G_SIGNAL_RUN_FIRST,
--                G_STRUCT_OFFSET (PsppSheetSelectionClass, changed),
--                NULL, NULL,
--                  g_cclosure_marshal_VOID__VOID,
--                G_TYPE_NONE, 0);
--}
--
--static void
--pspp_sheet_selection_init (PsppSheetSelection *selection)
--{
--  selection->type = PSPP_SHEET_SELECTION_SINGLE;
--}
--
--static void
--pspp_sheet_selection_finalize (GObject *object)
--{
--  G_OBJECT_CLASS (pspp_sheet_selection_parent_class)->finalize (object);
--}
--
--/**
-- * _pspp_sheet_selection_new:
-- *
-- * Creates a new #PsppSheetSelection object.  This function should not be invoked,
-- * as each #PsppSheetView will create its own #PsppSheetSelection.
-- *
-- * Return value: A newly created #PsppSheetSelection object.
-- **/
--PsppSheetSelection*
--_pspp_sheet_selection_new (void)
--{
--  PsppSheetSelection *selection;
--
--  selection = g_object_new (PSPP_TYPE_SHEET_SELECTION, NULL);
--
--  return selection;
--}
--
--/**
-- * _pspp_sheet_selection_new_with_tree_view:
-- * @tree_view: The #PsppSheetView.
-- *
-- * Creates a new #PsppSheetSelection object.  This function should not be invoked,
-- * as each #PsppSheetView will create its own #PsppSheetSelection.
-- *
-- * Return value: A newly created #PsppSheetSelection object.
-- **/
--PsppSheetSelection*
--_pspp_sheet_selection_new_with_tree_view (PsppSheetView *tree_view)
--{
--  PsppSheetSelection *selection;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
--
--  selection = _pspp_sheet_selection_new ();
--  _pspp_sheet_selection_set_tree_view (selection, tree_view);
--
--  return selection;
--}
--
--/**
-- * _pspp_sheet_selection_set_tree_view:
-- * @selection: A #PsppSheetSelection.
-- * @tree_view: The #PsppSheetView.
-- *
-- * Sets the #PsppSheetView of @selection.  This function should not be invoked, as
-- * it is used internally by #PsppSheetView.
-- **/
--void
--_pspp_sheet_selection_set_tree_view (PsppSheetSelection *selection,
--                                   PsppSheetView      *tree_view)
--{
--  g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
--  if (tree_view != NULL)
--    g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  selection->tree_view = tree_view;
--}
--
--/**
-- * pspp_sheet_selection_set_mode:
-- * @selection: A #PsppSheetSelection.
-- * @type: The selection mode
-- *
-- * Sets the selection mode of the @selection.  If the previous type was
-- * #PSPP_SHEET_SELECTION_MULTIPLE or #PSPP_SHEET_SELECTION_RECTANGLE, then the
-- * anchor is kept selected, if it was previously selected.
-- **/
--void
--pspp_sheet_selection_set_mode (PsppSheetSelection *selection,
--                           PsppSheetSelectionMode  type)
--{
--  g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
--
--  if (selection->type == type)
--    return;
--
--  if (type == PSPP_SHEET_SELECTION_NONE)
--    {
--      pspp_sheet_selection_unselect_all (selection);
--
--      gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
--      selection->tree_view->priv->anchor = NULL;
--    }
--  else if (type == PSPP_SHEET_SELECTION_SINGLE ||
--         type == PSPP_SHEET_SELECTION_BROWSE)
--    {
--      int node = -1;
--      gint selected = FALSE;
--      GtkTreePath *anchor_path = NULL;
--
--      if (selection->tree_view->priv->anchor)
--      {
--          anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
--
--          if (anchor_path)
--            {
--              _pspp_sheet_view_find_node (selection->tree_view,
--                                        anchor_path,
--                                        &node);
--
--              if (node >= 0 && pspp_sheet_view_node_is_selected (selection->tree_view, node))
--                selected = TRUE;
--            }
--      }
--
--      /* We do this so that we unconditionally unset all rows
--       */
--      pspp_sheet_selection_unselect_all (selection);
--
--      if (node >= 0 && selected)
--      _pspp_sheet_selection_internal_select_node (selection,
--                                                node,
--                                                anchor_path,
--                                                  0,
--                                                FALSE);
--      if (anchor_path)
--      gtk_tree_path_free (anchor_path);
--    }
--
--  /* XXX unselect all columns when switching to/from rectangular selection? */
--
--  selection->type = type;
--}
--
--/**
-- * pspp_sheet_selection_get_mode:
-- * @selection: a #PsppSheetSelection
-- *
-- * Gets the selection mode for @selection. See
-- * pspp_sheet_selection_set_mode().
-- *
-- * Return value: the current selection mode
-- **/
--PsppSheetSelectionMode
--pspp_sheet_selection_get_mode (PsppSheetSelection *selection)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), PSPP_SHEET_SELECTION_SINGLE);
--
--  return selection->type;
--}
--
--/**
-- * pspp_sheet_selection_get_tree_view:
-- * @selection: A #PsppSheetSelection
-- * 
-- * Returns the tree view associated with @selection.
-- * 
-- * Return value: A #PsppSheetView
-- **/
--PsppSheetView *
--pspp_sheet_selection_get_tree_view (PsppSheetSelection *selection)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), NULL);
--
--  return selection->tree_view;
--}
--
--/**
-- * pspp_sheet_selection_get_selected:
-- * @selection: A #PsppSheetSelection.
-- * @model: (out) (allow-none): A pointer to set to the #GtkTreeModel, or NULL.
-- * @iter: (allow-none): The #GtkTreeIter, or NULL.
-- *
-- * Sets @iter to the currently selected node if @selection is set to
-- * #PSPP_SHEET_SELECTION_SINGLE or #PSPP_SHEET_SELECTION_BROWSE.  @iter may be
-- * NULL if you just want to test if @selection has any selected nodes.  @model
-- * is filled with the current model as a convenience.  This function will not
-- * work if @selection's mode is #PSPP_SHEET_SELECTION_MULTIPLE or
-- * #PSPP_SHEET_SELECTION_RECTANGLE.
-- *
-- * Return value: TRUE, if there is a selected node.
-- **/
--gboolean
--pspp_sheet_selection_get_selected (PsppSheetSelection  *selection,
--                               GtkTreeModel     **model,
--                               GtkTreeIter       *iter)
--{
--  int node;
--  GtkTreePath *anchor_path;
--  gboolean retval;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), FALSE);
--  g_return_val_if_fail (selection->type != PSPP_SHEET_SELECTION_MULTIPLE &&
--                        selection->type != PSPP_SHEET_SELECTION_RECTANGLE,
--                        FALSE);
--  g_return_val_if_fail (selection->tree_view != NULL, FALSE);
--
--  /* Clear the iter */
--  if (iter)
--    memset (iter, 0, sizeof (GtkTreeIter));
--
--  if (model)
--    *model = selection->tree_view->priv->model;
--
--  if (selection->tree_view->priv->anchor == NULL)
--    return FALSE;
--
--  anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
--
--  if (anchor_path == NULL)
--    return FALSE;
--
--  retval = FALSE;
--
--  _pspp_sheet_view_find_node (selection->tree_view,
--                              anchor_path,
--                              &node);
--
--  if (pspp_sheet_view_node_is_selected (selection->tree_view, node))
--    {
--      /* we only want to return the anchor if it exists in the rbtree and
--       * is selected.
--       */
--      if (iter == NULL)
--      retval = TRUE;
--      else
--        retval = gtk_tree_model_get_iter (selection->tree_view->priv->model,
--                                          iter,
--                                          anchor_path);
--    }
--  else
--    {
--      /* We don't want to return the anchor if it isn't actually selected.
--       */
--      retval = FALSE;
--    }
--
--  gtk_tree_path_free (anchor_path);
--
--  return retval;
--}
--
--/**
-- * pspp_sheet_selection_get_selected_rows:
-- * @selection: A #PsppSheetSelection.
-- * @model: (allow-none): A pointer to set to the #GtkTreeModel, or NULL.
-- *
-- * Creates a list of path of all selected rows. Additionally, if you are
-- * planning on modifying the model after calling this function, you may
-- * want to convert the returned list into a list of #GtkTreeRowReference<!-- -->s.
-- * To do this, you can use gtk_tree_row_reference_new().
-- *
-- * To free the return value, use:
-- * |[
-- * g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
-- * g_list_free (list);
-- * ]|
-- *
-- * Return value: (element-type GtkTreePath) (transfer full): A #GList containing a #GtkTreePath for each selected row.
-- *
-- * Since: 2.2
-- **/
--GList *
--pspp_sheet_selection_get_selected_rows (PsppSheetSelection   *selection,
--                                      GtkTreeModel      **model)
--{
--  const struct range_tower_node *node;
--  unsigned long int start;
--  GList *list = NULL;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), NULL);
--  g_return_val_if_fail (selection->tree_view != NULL, NULL);
--
--  if (model)
--    *model = selection->tree_view->priv->model;
--
--  if (selection->tree_view->priv->row_count == 0)
--    return NULL;
--
--  if (selection->type == PSPP_SHEET_SELECTION_NONE)
--    return NULL;
--  else if (selection->type != PSPP_SHEET_SELECTION_MULTIPLE &&
--           selection->type != PSPP_SHEET_SELECTION_RECTANGLE)
--    {
--      GtkTreeIter iter;
--
--      if (pspp_sheet_selection_get_selected (selection, NULL, &iter))
--        {
--        GtkTreePath *path;
--
--        path = gtk_tree_model_get_path (selection->tree_view->priv->model, &iter);
--        list = g_list_append (list, path);
--
--        return list;
--      }
--
--      return NULL;
--    }
--
--  RANGE_TOWER_FOR_EACH (node, start, selection->tree_view->priv->selected)
--    {
--      unsigned long int width = range_tower_node_get_width (node);
--      unsigned long int index;
--
--      for (index = start; index < start + width; index++)
--        list = g_list_prepend (list, gtk_tree_path_new_from_indices (index, -1));
--    }
--
--  return g_list_reverse (list);
--}
--
--/**
-- * pspp_sheet_selection_count_selected_rows:
-- * @selection: A #PsppSheetSelection.
-- *
-- * Returns the number of rows that have been selected in @tree.
-- *
-- * Return value: The number of rows selected.
-- * 
-- * Since: 2.2
-- **/
--gint
--pspp_sheet_selection_count_selected_rows (PsppSheetSelection *selection)
--{
--  const struct range_tower_node *node;
--  unsigned long int start;
--  gint count = 0;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), 0);
--  g_return_val_if_fail (selection->tree_view != NULL, 0);
--
--  if (selection->tree_view->priv->row_count == 0)
--    return 0;
--
--  if (selection->type == PSPP_SHEET_SELECTION_SINGLE ||
--      selection->type == PSPP_SHEET_SELECTION_BROWSE)
--    {
--      if (pspp_sheet_selection_get_selected (selection, NULL, NULL))
--      return 1;
--      else
--      return 0;
--    }
--
--  count = 0;
--  RANGE_TOWER_FOR_EACH (node, start, selection->tree_view->priv->selected)
--    count += range_tower_node_get_width (node);
--
--  return count;
--}
--
--/* pspp_sheet_selection_selected_foreach helper */
--static void
--model_changed (gpointer data)
--{
--  gboolean *stop = (gboolean *)data;
--
--  *stop = TRUE;
--}
--
--/**
-- * pspp_sheet_selection_selected_foreach:
-- * @selection: A #PsppSheetSelection.
-- * @func: The function to call for each selected node.
-- * @data: user data to pass to the function.
-- *
-- * Calls a function for each selected node. Note that you cannot modify
-- * the tree or selection from within this function. As a result,
-- * pspp_sheet_selection_get_selected_rows() might be more useful.
-- **/
--void
--pspp_sheet_selection_selected_foreach (PsppSheetSelection            *selection,
--                                   PsppSheetSelectionForeachFunc  func,
--                                   gpointer                     data)
--{
--  const struct range_tower_node *node;
--  unsigned long int start;
--  GtkTreePath *path;
--  GtkTreeIter iter;
--  GtkTreeModel *model;
--
--  gulong inserted_id, deleted_id, reordered_id, changed_id;
--  gboolean stop = FALSE;
--
--  g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
--  g_return_if_fail (selection->tree_view != NULL);
--
--  if (func == NULL ||
--      selection->tree_view->priv->row_count == 0)
--    return;
--
--  if (selection->type == PSPP_SHEET_SELECTION_SINGLE ||
--      selection->type == PSPP_SHEET_SELECTION_BROWSE)
--    {
--      if (gtk_tree_row_reference_valid (selection->tree_view->priv->anchor))
--      {
--        path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
--        gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path);
--        (* func) (selection->tree_view->priv->model, path, &iter, data);
--        gtk_tree_path_free (path);
--      }
--      return;
--    }
--
--  model = selection->tree_view->priv->model;
--  g_object_ref (model);
--
--  /* connect to signals to monitor changes in treemodel */
--  inserted_id = g_signal_connect_swapped (model, "row-inserted",
--                                        G_CALLBACK (model_changed),
--                                        &stop);
--  deleted_id = g_signal_connect_swapped (model, "row-deleted",
--                                       G_CALLBACK (model_changed),
--                                       &stop);
--  reordered_id = g_signal_connect_swapped (model, "rows-reordered",
--                                         G_CALLBACK (model_changed),
--                                         &stop);
--  changed_id = g_signal_connect_swapped (selection->tree_view, "notify::model",
--                                       G_CALLBACK (model_changed), 
--                                       &stop);
--
--  RANGE_TOWER_FOR_EACH (node, start, selection->tree_view->priv->selected)
--    {
--      unsigned long int width = range_tower_node_get_width (node);
--      unsigned long int index;
--
--      for (index = start; index < start + width; index++)
--        {
--          GtkTreePath *path;
--          GtkTreeIter iter;
--
--          path = gtk_tree_path_new_from_indices (index, -1);
--          gtk_tree_model_get_iter (model, &iter, path);
--        (* func) (model, path, &iter, data);
--          gtk_tree_path_free (path);
--        }
--    }
--
--  g_signal_handler_disconnect (model, inserted_id);
--  g_signal_handler_disconnect (model, deleted_id);
--  g_signal_handler_disconnect (model, reordered_id);
--  g_signal_handler_disconnect (selection->tree_view, changed_id);
--  g_object_unref (model);
--
--  /* check if we have to spew a scary message */
--  if (stop)
--    g_warning ("The model has been modified from within pspp_sheet_selection_selected_foreach.\n"
--             "This function is for observing the selections of the tree only.  If\n"
--             "you are trying to get all selected items from the tree, try using\n"
--             "pspp_sheet_selection_get_selected_rows instead.\n");
--}
--
--/**
-- * pspp_sheet_selection_select_path:
-- * @selection: A #PsppSheetSelection.
-- * @path: The #GtkTreePath to be selected.
-- *
-- * Select the row at @path.
-- **/
--void
--pspp_sheet_selection_select_path (PsppSheetSelection *selection,
--                              GtkTreePath      *path)
--{
--  int node;
--  PsppSheetSelectMode mode = 0;
--
--  g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
--  g_return_if_fail (selection->tree_view != NULL);
--  g_return_if_fail (path != NULL);
--
--   _pspp_sheet_view_find_node (selection->tree_view,
--                               path,
--                               &node);
--
--  if (node < 0 || pspp_sheet_view_node_is_selected (selection->tree_view, node)) 
--    return;
--
--  if (selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
--      selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
--    mode = PSPP_SHEET_SELECT_MODE_TOGGLE;
--
--  _pspp_sheet_selection_internal_select_node (selection,
--                                          node,
--                                          path,
--                                            mode,
--                                          FALSE);
--}
--
--/**
-- * pspp_sheet_selection_unselect_path:
-- * @selection: A #PsppSheetSelection.
-- * @path: The #GtkTreePath to be unselected.
-- *
-- * Unselects the row at @path.
-- **/
--void
--pspp_sheet_selection_unselect_path (PsppSheetSelection *selection,
--                                GtkTreePath      *path)
--{
--  int node;
--
--  g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
--  g_return_if_fail (selection->tree_view != NULL);
--  g_return_if_fail (path != NULL);
--
--  _pspp_sheet_view_find_node (selection->tree_view,
--                              path,
--                              &node);
--
--  if (node < 0 || !pspp_sheet_view_node_is_selected (selection->tree_view, node)) 
--    return;
--
--  _pspp_sheet_selection_internal_select_node (selection,
--                                          node,
--                                          path,
--                                            PSPP_SHEET_SELECT_MODE_TOGGLE,
--                                          TRUE);
--}
--
--/**
-- * pspp_sheet_selection_select_iter:
-- * @selection: A #PsppSheetSelection.
-- * @iter: The #GtkTreeIter to be selected.
-- *
-- * Selects the specified iterator.
-- **/
--void
--pspp_sheet_selection_select_iter (PsppSheetSelection *selection,
--                              GtkTreeIter      *iter)
--{
--  GtkTreePath *path;
--
--  g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
--  g_return_if_fail (selection->tree_view != NULL);
--  g_return_if_fail (selection->tree_view->priv->model != NULL);
--  g_return_if_fail (iter != NULL);
--
--  path = gtk_tree_model_get_path (selection->tree_view->priv->model,
--                                iter);
--
--  if (path == NULL)
--    return;
--
--  pspp_sheet_selection_select_path (selection, path);
--  gtk_tree_path_free (path);
--}
--
--
--/**
-- * pspp_sheet_selection_unselect_iter:
-- * @selection: A #PsppSheetSelection.
-- * @iter: The #GtkTreeIter to be unselected.
-- *
-- * Unselects the specified iterator.
-- **/
--void
--pspp_sheet_selection_unselect_iter (PsppSheetSelection *selection,
--                                GtkTreeIter      *iter)
--{
--  GtkTreePath *path;
--
--  g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
--  g_return_if_fail (selection->tree_view != NULL);
--  g_return_if_fail (selection->tree_view->priv->model != NULL);
--  g_return_if_fail (iter != NULL);
--
--  path = gtk_tree_model_get_path (selection->tree_view->priv->model,
--                                iter);
--
--  if (path == NULL)
--    return;
--
--  pspp_sheet_selection_unselect_path (selection, path);
--  gtk_tree_path_free (path);
--}
--
--/**
-- * pspp_sheet_selection_path_is_selected:
-- * @selection: A #PsppSheetSelection.
-- * @path: A #GtkTreePath to check selection on.
-- * 
-- * Returns %TRUE if the row pointed to by @path is currently selected.  If @path
-- * does not point to a valid location, %FALSE is returned
-- * 
-- * Return value: %TRUE if @path is selected.
-- **/
--gboolean
--pspp_sheet_selection_path_is_selected (PsppSheetSelection *selection,
--                                   GtkTreePath      *path)
--{
--  int node;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), FALSE);
--  g_return_val_if_fail (path != NULL, FALSE);
--  g_return_val_if_fail (selection->tree_view != NULL, FALSE);
--
--  if (selection->tree_view->priv->model == NULL)
--    return FALSE;
--
--  _pspp_sheet_view_find_node (selection->tree_view,
--                                path,
--                                &node);
--
--  if (node < 0 || !pspp_sheet_view_node_is_selected (selection->tree_view, node)) 
--    return FALSE;
--
--  return TRUE;
--}
--
--/**
-- * pspp_sheet_selection_iter_is_selected:
-- * @selection: A #PsppSheetSelection
-- * @iter: A valid #GtkTreeIter
-- * 
-- * Returns %TRUE if the row at @iter is currently selected.
-- * 
-- * Return value: %TRUE, if @iter is selected
-- **/
--gboolean
--pspp_sheet_selection_iter_is_selected (PsppSheetSelection *selection,
--                                   GtkTreeIter      *iter)
--{
--  GtkTreePath *path;
--  gboolean retval;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), FALSE);
--  g_return_val_if_fail (iter != NULL, FALSE);
--  g_return_val_if_fail (selection->tree_view != NULL, FALSE);
--  g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
--
--  path = gtk_tree_model_get_path (selection->tree_view->priv->model, iter);
--  if (path == NULL)
--    return FALSE;
--
--  retval = pspp_sheet_selection_path_is_selected (selection, path);
--  gtk_tree_path_free (path);
--
--  return retval;
--}
--
--
--/* We have a real_{un,}select_all function that doesn't emit the signal, so we
-- * can use it in other places without fear of the signal being emitted.
-- */
--static gint
--pspp_sheet_selection_real_select_all (PsppSheetSelection *selection)
--{
--  const struct range_tower_node *node;
--  int row_count = selection->tree_view->priv->row_count;
--
--  if (row_count == 0)
--    return FALSE;
--
--  node = range_tower_first (selection->tree_view->priv->selected);
--  if (node
--      && range_tower_node_get_start (node) == 0
--      && range_tower_node_get_width (node) >= row_count)
--    return FALSE;
--
--  range_tower_set1 (selection->tree_view->priv->selected, 0, row_count);
--  pspp_sheet_selection_select_all_columns (selection);
--
--  /* XXX we could invalidate individual visible rows instead */
--  gdk_window_invalidate_rect (selection->tree_view->priv->bin_window, NULL, TRUE);
--
--  return TRUE;
--}
--
--/**
-- * pspp_sheet_selection_select_all:
-- * @selection: A #PsppSheetSelection.
-- *
-- * Selects all the nodes and column. @selection must be set to
-- * #PSPP_SHEET_SELECTION_MULTIPLE or  #PSPP_SHEET_SELECTION_RECTANGLE mode.
-- **/
--void
--pspp_sheet_selection_select_all (PsppSheetSelection *selection)
--{
--  g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
--  g_return_if_fail (selection->tree_view != NULL);
--
--  if (selection->tree_view->priv->row_count == 0 || selection->tree_view->priv->model == NULL)
--    return;
--
--  g_return_if_fail (selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
--                    selection->type == PSPP_SHEET_SELECTION_RECTANGLE);
--
--  if (pspp_sheet_selection_real_select_all (selection))
--    g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
--}
--
--static gint
--pspp_sheet_selection_real_unselect_all (PsppSheetSelection *selection)
--{
--  if (selection->type == PSPP_SHEET_SELECTION_SINGLE ||
--      selection->type == PSPP_SHEET_SELECTION_BROWSE)
--    {
--      int node = -1;
--      GtkTreePath *anchor_path;
--
--      if (selection->tree_view->priv->anchor == NULL)
--      return FALSE;
--
--      anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
--
--      if (anchor_path == NULL)
--        return FALSE;
--
--      _pspp_sheet_view_find_node (selection->tree_view,
--                                anchor_path,
--                              &node);
--
--      gtk_tree_path_free (anchor_path);
--
--      if (node < 0)
--        return FALSE;
--
--      if (pspp_sheet_view_node_is_selected (selection->tree_view, node))
--      {
--        if (pspp_sheet_selection_real_select_node (selection, node, FALSE))
--          {
--            gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
--            selection->tree_view->priv->anchor = NULL;
--            return TRUE;
--          }
--      }
--      return FALSE;
--    }
--  else if (range_tower_is_empty (selection->tree_view->priv->selected))
--    return FALSE;
--  else
--    {
--      range_tower_set0 (selection->tree_view->priv->selected, 0, ULONG_MAX);
--      pspp_sheet_selection_unselect_all_columns (selection);
--
--      /* XXX we could invalidate individual visible rows instead */
--      gdk_window_invalidate_rect (selection->tree_view->priv->bin_window, NULL, TRUE);
--
--      return TRUE;
--    }
--}
--
--/**
-- * pspp_sheet_selection_unselect_all:
-- * @selection: A #PsppSheetSelection.
-- *
-- * Unselects all the nodes and columns.
-- **/
--void
--pspp_sheet_selection_unselect_all (PsppSheetSelection *selection)
--{
--  g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
--  g_return_if_fail (selection->tree_view != NULL);
--
--  if (selection->tree_view->priv->row_count == 0 || selection->tree_view->priv->model == NULL)
--    return;
--  
--  if (pspp_sheet_selection_real_unselect_all (selection))
--    g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
--}
--
--enum
--{
--  RANGE_SELECT,
--  RANGE_UNSELECT
--};
--
--static gint
--pspp_sheet_selection_real_modify_range (PsppSheetSelection *selection,
--                                      gint              mode,
--                                    GtkTreePath      *start_path,
--                                    GtkTreePath      *end_path)
--{
--  int start_node, end_node;
--  GtkTreePath *anchor_path = NULL;
--  gboolean dirty = FALSE;
--
--  switch (gtk_tree_path_compare (start_path, end_path))
--    {
--    case 1:
--      _pspp_sheet_view_find_node (selection->tree_view,
--                              end_path,
--                              &start_node);
--      _pspp_sheet_view_find_node (selection->tree_view,
--                              start_path,
--                              &end_node);
--      anchor_path = start_path;
--      break;
--    case 0:
--      _pspp_sheet_view_find_node (selection->tree_view,
--                              start_path,
--                              &start_node);
--      end_node = start_node;
--      anchor_path = start_path;
--      break;
--    case -1:
--      _pspp_sheet_view_find_node (selection->tree_view,
--                              start_path,
--                              &start_node);
--      _pspp_sheet_view_find_node (selection->tree_view,
--                              end_path,
--                              &end_node);
--      anchor_path = start_path;
--      break;
--    }
--
--  g_return_val_if_fail (start_node >= 0, FALSE);
--  g_return_val_if_fail (end_node >= 0, FALSE);
--
--  if (anchor_path)
--    {
--      if (selection->tree_view->priv->anchor)
--      gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
--
--      selection->tree_view->priv->anchor =
--      gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view),
--                                        selection->tree_view->priv->model,
--                                        anchor_path);
--    }
--
--  do
--    {
--      dirty |= pspp_sheet_selection_real_select_node (selection, start_node, (mode == RANGE_SELECT)?TRUE:FALSE);
--
--      if (start_node == end_node)
--      break;
--
--      start_node = pspp_sheet_view_node_next (selection->tree_view, start_node);
--      if (start_node < 0)
--        {
--          /* we just ran out of tree.  That means someone passed in bogus values.
--           */
--          return dirty;
--        }
--    }
--  while (TRUE);
--
--  return dirty;
--}
--
--/**
-- * pspp_sheet_selection_select_range:
-- * @selection: A #PsppSheetSelection.
-- * @start_path: The initial node of the range.
-- * @end_path: The final node of the range.
-- *
-- * Selects a range of nodes, determined by @start_path and @end_path inclusive.
-- * @selection must be set to #PSPP_SHEET_SELECTION_MULTIPLE or
-- * #PSPP_SHEET_SELECTION_RECTANGLE mode.
-- **/
--void
--pspp_sheet_selection_select_range (PsppSheetSelection *selection,
--                               GtkTreePath      *start_path,
--                               GtkTreePath      *end_path)
--{
--  g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
--  g_return_if_fail (selection->tree_view != NULL);
--  g_return_if_fail (selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
--                    selection->type == PSPP_SHEET_SELECTION_RECTANGLE);
--  g_return_if_fail (selection->tree_view->priv->model != NULL);
--
--  if (pspp_sheet_selection_real_modify_range (selection, RANGE_SELECT, start_path, end_path))
--    g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
--}
--
--/**
-- * pspp_sheet_selection_unselect_range:
-- * @selection: A #PsppSheetSelection.
-- * @start_path: The initial node of the range.
-- * @end_path: The initial node of the range.
-- *
-- * Unselects a range of nodes, determined by @start_path and @end_path
-- * inclusive.
-- *
-- * Since: 2.2
-- **/
--void
--pspp_sheet_selection_unselect_range (PsppSheetSelection *selection,
--                                   GtkTreePath      *start_path,
--                                 GtkTreePath      *end_path)
--{
--  g_return_if_fail (PSPP_IS_SHEET_SELECTION (selection));
--  g_return_if_fail (selection->tree_view != NULL);
--  g_return_if_fail (selection->tree_view->priv->model != NULL);
--
--  if (pspp_sheet_selection_real_modify_range (selection, RANGE_UNSELECT, start_path, end_path))
--    g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
--}
--
--struct range_set *
--pspp_sheet_selection_get_range_set (PsppSheetSelection *selection)
--{
--  const struct range_tower_node *node;
--  unsigned long int start;
--  struct range_set *set;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection),
--                        range_set_create ());
--  g_return_val_if_fail (selection->tree_view != NULL, range_set_create ());
--
--  set = range_set_create ();
--  RANGE_TOWER_FOR_EACH (node, start, selection->tree_view->priv->selected)
--    range_set_set1 (set, start, range_tower_node_get_width (node));
--  return set;
--}
--
--/* Called internally by gtktreeview.c It handles actually selecting the tree.
-- */
--
--/*
-- * docs about the 'override_browse_mode', we set this flag when we want to
-- * unset select the node and override the select browse mode behaviour (that is
-- * 'one node should *always* be selected').
-- */
--void
--_pspp_sheet_selection_internal_select_node (PsppSheetSelection *selection,
--                                        int               node,
--                                        GtkTreePath      *path,
--                                          PsppSheetSelectMode mode,
--                                        gboolean          override_browse_mode)
--{
--  gint dirty = FALSE;
--  GtkTreePath *anchor_path = NULL;
--
--  if (selection->type == PSPP_SHEET_SELECTION_NONE)
--    return;
--
--  if (selection->tree_view->priv->anchor)
--    anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
--
--  if (selection->type == PSPP_SHEET_SELECTION_SINGLE ||
--      selection->type == PSPP_SHEET_SELECTION_BROWSE)
--    {
--      /* just unselect */
--      if (selection->type == PSPP_SHEET_SELECTION_BROWSE && override_browse_mode)
--        {
--        dirty = pspp_sheet_selection_real_unselect_all (selection);
--      }
--      /* Did we try to select the same node again? */
--      else if (selection->type == PSPP_SHEET_SELECTION_SINGLE &&
--             anchor_path && gtk_tree_path_compare (path, anchor_path) == 0)
--      {
--        if ((mode & PSPP_SHEET_SELECT_MODE_TOGGLE) == PSPP_SHEET_SELECT_MODE_TOGGLE)
--          {
--            dirty = pspp_sheet_selection_real_unselect_all (selection);
--          }
--      }
--      else
--      {
--        if (anchor_path)
--          {
--              dirty = pspp_sheet_selection_real_unselect_all (selection);
--
--            /* if dirty is TRUE at this point, we successfully unselected the
--             * old one, and can then select the new one */
--            if (dirty)
--              {
--                if (selection->tree_view->priv->anchor)
--                    {
--                      gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
--                      selection->tree_view->priv->anchor = NULL;
--                    }
--
--                if (pspp_sheet_selection_real_select_node (selection, node, TRUE))
--                  {
--                    selection->tree_view->priv->anchor =
--                      gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
--                  }
--              }
--          }
--        else
--          {
--            if (pspp_sheet_selection_real_select_node (selection, node, TRUE))
--              {
--                dirty = TRUE;
--                if (selection->tree_view->priv->anchor)
--                  gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
--
--                selection->tree_view->priv->anchor =
--                  gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
--              }
--          }
--      }
--    }
--  else if (selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
--           selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
--    {
--      if ((mode & PSPP_SHEET_SELECT_MODE_EXTEND) == PSPP_SHEET_SELECT_MODE_EXTEND
--          && (anchor_path == NULL))
--      {
--        if (selection->tree_view->priv->anchor)
--          gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
--
--        selection->tree_view->priv->anchor =
--          gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
--        dirty = pspp_sheet_selection_real_select_node (selection, node, TRUE);
--      }
--      else if ((mode & (PSPP_SHEET_SELECT_MODE_EXTEND | PSPP_SHEET_SELECT_MODE_TOGGLE)) == (PSPP_SHEET_SELECT_MODE_EXTEND | PSPP_SHEET_SELECT_MODE_TOGGLE))
--      {
--        pspp_sheet_selection_select_range (selection,
--                                         anchor_path,
--                                         path);
--      }
--      else if ((mode & PSPP_SHEET_SELECT_MODE_TOGGLE) == PSPP_SHEET_SELECT_MODE_TOGGLE)
--      {
--          bool selected = pspp_sheet_view_node_is_selected (selection->tree_view, node);
--        if (selection->tree_view->priv->anchor)
--          gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
--
--        selection->tree_view->priv->anchor =
--          gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
--
--        if (selected)
--          dirty |= pspp_sheet_selection_real_select_node (selection, node, FALSE);
--        else
--          dirty |= pspp_sheet_selection_real_select_node (selection, node, TRUE);
--      }
--      else if ((mode & PSPP_SHEET_SELECT_MODE_EXTEND) == PSPP_SHEET_SELECT_MODE_EXTEND)
--      {
--        dirty = pspp_sheet_selection_real_unselect_all (selection);
--        dirty |= pspp_sheet_selection_real_modify_range (selection,
--                                                         RANGE_SELECT,
--                                                       anchor_path,
--                                                       path);
--      }
--      else
--      {
--        dirty = pspp_sheet_selection_real_unselect_all (selection);
--
--        if (selection->tree_view->priv->anchor)
--          gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
--
--        selection->tree_view->priv->anchor =
--          gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
--
--        dirty |= pspp_sheet_selection_real_select_node (selection, node, TRUE);
--      }
--    }
--
--  if (anchor_path)
--    gtk_tree_path_free (anchor_path);
--
--  if (dirty)
--    g_signal_emit (selection, tree_selection_signals[CHANGED], 0);  
--}
--
--
--void 
--_pspp_sheet_selection_emit_changed (PsppSheetSelection *selection)
--{
--  g_signal_emit (selection, tree_selection_signals[CHANGED], 0);  
--}
--
--/* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
-- */
--
--static gint
--pspp_sheet_selection_real_select_node (PsppSheetSelection *selection,
--                                   int               node,
--                                   gboolean          select)
--{
--  select = !! select;
--  if (pspp_sheet_view_node_is_selected (selection->tree_view, node) != select)
--    {
--      if (select)
--        pspp_sheet_view_node_select (selection->tree_view, node);
--      else
--        pspp_sheet_view_node_unselect (selection->tree_view, node);
--
--      _pspp_sheet_view_queue_draw_node (selection->tree_view, node, NULL);
--      
--      return TRUE;
--    }
--
--  return FALSE;
--}
--
--void
--pspp_sheet_selection_unselect_all_columns (PsppSheetSelection *selection)
--{
--  PsppSheetView *sheet_view = selection->tree_view;
--  gboolean changed;
--  GList *list;
--
--  changed = FALSE;
--  for (list = sheet_view->priv->columns; list; list = list->next)
--    {
--      PsppSheetViewColumn *column = list->data;
--      if (column->selected)
--        {
--          column->selected = FALSE;
--          changed = TRUE;
--        }
--    }
--  if (changed && selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
--    {
--      gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
--      _pspp_sheet_selection_emit_changed (selection);
--    }
--}
--
--GList *
--pspp_sheet_selection_get_selected_columns (PsppSheetSelection *selection)
--{
--  PsppSheetView *sheet_view = selection->tree_view;
--  GList *selected_columns = NULL;
--  GList *iter;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_SELECTION (selection), NULL);
--  g_return_val_if_fail (selection->tree_view != NULL, NULL);
--
--  if (selection->type != PSPP_SHEET_SELECTION_RECTANGLE)
--    return NULL;
--
--  for (iter = sheet_view->priv->columns; iter; iter = iter->next)
--    {
--      PsppSheetViewColumn *column = iter->data;
--      if (column->selected)
--        selected_columns = g_list_prepend (selected_columns, column);
--    }
--  return g_list_reverse (selected_columns);
--}
--
--gint
--pspp_sheet_selection_count_selected_columns (PsppSheetSelection *selection)
--{
--  PsppSheetView *sheet_view = selection->tree_view;
--  GList *list;
--  gint n;
--
--  n = 0;
--  for (list = sheet_view->priv->columns; list; list = list->next)
--    {
--      PsppSheetViewColumn *column = list->data;
--      if (column->selected)
--        n++;
--    }
--  return n;
--}
--
--void
--pspp_sheet_selection_select_all_columns (PsppSheetSelection *selection)
--{
--  PsppSheetView *sheet_view = selection->tree_view;
--  gboolean changed;
--  GList *list;
--
--  changed = FALSE;
--  for (list = sheet_view->priv->columns; list; list = list->next)
--    {
--      PsppSheetViewColumn *column = list->data;
--      if (!column->selected && column->selectable)
--        {
--          /* XXX should use pspp_sheet_view_column_set_selected() here (and
--             elsewhere) but we want to call
--             _pspp_sheet_selection_emit_changed() only once for all the
--             columns. */
--          column->selected = TRUE;
--          changed = TRUE;
--        }
--    }
--  if (changed && selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
--    {
--      _pspp_sheet_selection_emit_changed (selection);
--      gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
--    }
--}
--
--void
--pspp_sheet_selection_select_column (PsppSheetSelection        *selection,
--                                    PsppSheetViewColumn       *column)
--{
--  if (!column->selected && column->selectable)
--    {
--      column->selected = TRUE;
--      if (selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
--        {
--          _pspp_sheet_selection_emit_changed (selection);
--          gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
--        }
--    }
--}
--
--void
--pspp_sheet_selection_select_column_range  (PsppSheetSelection        *selection,
--                                           PsppSheetViewColumn       *first,
--                                           PsppSheetViewColumn       *last)
--{
--  PsppSheetView *sheet_view = selection->tree_view;
--  gboolean in_range;
--  gboolean changed;
--  GList *list;
--
--  in_range = FALSE;
--  changed = FALSE;
--  for (list = sheet_view->priv->columns; list; list = list->next)
--    {
--      PsppSheetViewColumn *column = list->data;
--      gboolean c0 = column == first;
--      gboolean c1 = column == last;
--
--      if (in_range || c0 || c1)
--        {
--          if (!column->selected && column->selectable)
--            {
--              column->selected = TRUE;
--              changed = TRUE;
--            }
--        }
--
--      in_range = in_range ^ c0 ^ c1;
--    }
--  if (changed && selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
--    {
--      _pspp_sheet_selection_emit_changed (selection);
--      gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
--    }
--}
diff --cc src/ui/gui/pspp-sheet-selection.h
index ded218c8c5ff1c856149d8790afc9444e0a9c3e0,ded218c8c5ff1c856149d8790afc9444e0a9c3e0..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,159 -1,159 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2011 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--/* gtktreeselection.h
-- * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Library 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
-- * Library General Public License for more details.
-- *
-- * You should have received a copy of the GNU Library 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.
-- */
--
--#ifndef __PSPP_SHEET_SELECTION_H__
--#define __PSPP_SHEET_SELECTION_H__
--
--#include <gtk/gtk.h>
--
--G_BEGIN_DECLS
--
--
--#define PSPP_TYPE_SHEET_SELECTION                     (pspp_sheet_selection_get_type ())
--#define PSPP_SHEET_SELECTION(obj)                     (G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPP_TYPE_SHEET_SELECTION, PsppSheetSelection))
--#define PSPP_SHEET_SELECTION_CLASS(klass)             (G_TYPE_CHECK_CLASS_CAST ((klass), PSPP_TYPE_SHEET_SELECTION, PsppSheetSelectionClass))
--#define PSPP_IS_SHEET_SELECTION(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPP_TYPE_SHEET_SELECTION))
--#define PSPP_IS_SHEET_SELECTION_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPP_TYPE_SHEET_SELECTION))
--#define PSPP_SHEET_SELECTION_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), PSPP_TYPE_SHEET_SELECTION, PsppSheetSelectionClass))
--
--typedef enum
--  {
--    /* Same as GtkSelectionMode. */
--    PSPP_SHEET_SELECTION_NONE = GTK_SELECTION_NONE,
--    PSPP_SHEET_SELECTION_SINGLE = GTK_SELECTION_SINGLE,
--    PSPP_SHEET_SELECTION_BROWSE = GTK_SELECTION_BROWSE,
--    PSPP_SHEET_SELECTION_MULTIPLE = GTK_SELECTION_MULTIPLE,
--
--    /* PsppSheetView extension. */
--    PSPP_SHEET_SELECTION_RECTANGLE = 10
--  }
--PsppSheetSelectionMode;
--
--typedef gboolean (* PsppSheetSelectionFunc)    (PsppSheetSelection  *selection,
--                                            GtkTreeModel      *model,
--                                            GtkTreePath       *path,
--                                              gboolean           path_currently_selected,
--                                            gpointer           data);
--typedef void (* PsppSheetSelectionForeachFunc) (GtkTreeModel      *model,
--                                            GtkTreePath       *path,
--                                            GtkTreeIter       *iter,
--                                            gpointer           data);
--
--struct _PsppSheetSelection
--{
--  GObject parent;
--
--  /*< private >*/
--
--  PsppSheetView *PSEAL (tree_view);
--  PsppSheetSelectionMode PSEAL (type);
--};
--
--struct _PsppSheetSelectionClass
--{
--  GObjectClass parent_class;
--
--  void (* changed) (PsppSheetSelection *selection);
--
--  /* Padding for future expansion */
--  void (*_gtk_reserved1) (void);
--  void (*_gtk_reserved2) (void);
--  void (*_gtk_reserved3) (void);
--  void (*_gtk_reserved4) (void);
--};
--
--
--GType            pspp_sheet_selection_get_type            (void) G_GNUC_CONST;
--
--void             pspp_sheet_selection_set_mode            (PsppSheetSelection            *selection,
--                                                       PsppSheetSelectionMode             type);
--PsppSheetSelectionMode pspp_sheet_selection_get_mode        (PsppSheetSelection            *selection);
--void             pspp_sheet_selection_set_select_function (PsppSheetSelection            *selection,
--                                                       PsppSheetSelectionFunc         func,
--                                                       gpointer                     data,
--                                                       GDestroyNotify               destroy);
--gpointer         pspp_sheet_selection_get_user_data       (PsppSheetSelection            *selection);
--PsppSheetView*     pspp_sheet_selection_get_tree_view       (PsppSheetSelection            *selection);
--
--PsppSheetSelectionFunc pspp_sheet_selection_get_select_function (PsppSheetSelection        *selection);
--
--/* Only meaningful if PSPP_SHEET_SELECTION_SINGLE or PSPP_SHEET_SELECTION_BROWSE is set */
--/* Use selected_foreach or get_selected_rows for
--   PSPP_SHEET_SELECTION_MULTIPLE */
--gboolean         pspp_sheet_selection_get_selected        (PsppSheetSelection            *selection,
--                                                       GtkTreeModel               **model,
--                                                       GtkTreeIter                 *iter);
--GList *          pspp_sheet_selection_get_selected_rows   (PsppSheetSelection            *selection,
--                                                         GtkTreeModel               **model);
--gint             pspp_sheet_selection_count_selected_rows (PsppSheetSelection            *selection);
--void             pspp_sheet_selection_selected_foreach    (PsppSheetSelection            *selection,
--                                                       PsppSheetSelectionForeachFunc  func,
--                                                       gpointer                     data);
--void             pspp_sheet_selection_select_path         (PsppSheetSelection            *selection,
--                                                       GtkTreePath                 *path);
--void             pspp_sheet_selection_unselect_path       (PsppSheetSelection            *selection,
--                                                       GtkTreePath                 *path);
--void             pspp_sheet_selection_select_iter         (PsppSheetSelection            *selection,
--                                                       GtkTreeIter                 *iter);
--void             pspp_sheet_selection_unselect_iter       (PsppSheetSelection            *selection,
--                                                       GtkTreeIter                 *iter);
--gboolean         pspp_sheet_selection_path_is_selected    (PsppSheetSelection            *selection,
--                                                       GtkTreePath                 *path);
--gboolean         pspp_sheet_selection_iter_is_selected    (PsppSheetSelection            *selection,
--                                                       GtkTreeIter                 *iter);
--void             pspp_sheet_selection_select_all          (PsppSheetSelection            *selection);
--void             pspp_sheet_selection_unselect_all        (PsppSheetSelection            *selection);
--void             pspp_sheet_selection_select_range        (PsppSheetSelection            *selection,
--                                                       GtkTreePath                 *start_path,
--                                                       GtkTreePath                 *end_path);
--void             pspp_sheet_selection_unselect_range      (PsppSheetSelection            *selection,
--                                                         GtkTreePath                 *start_path,
--                                                       GtkTreePath                 *end_path);
--struct range_set *pspp_sheet_selection_get_range_set (PsppSheetSelection *selection);
--
--
--GList *          pspp_sheet_selection_get_selected_columns (PsppSheetSelection            *selection);
--gint             pspp_sheet_selection_count_selected_columns (PsppSheetSelection            *selection);
--void             pspp_sheet_selection_select_all_columns (PsppSheetSelection        *selection);
--void             pspp_sheet_selection_unselect_all_columns (PsppSheetSelection        *selection);
--void             pspp_sheet_selection_select_column        (PsppSheetSelection        *selection,
--                                                            PsppSheetViewColumn       *column);
--void             pspp_sheet_selection_select_column_range  (PsppSheetSelection        *selection,
--                                                            PsppSheetViewColumn       *first,
--                                                            PsppSheetViewColumn       *last);
--
--G_END_DECLS
--
--#endif /* __PSPP_SHEET_SELECTION_H__ */
diff --cc src/ui/gui/pspp-sheet-view-column.c
index 92b0b0e4c5fae116787fa0576b45e468eba49c9f,92b0b0e4c5fae116787fa0576b45e468eba49c9f..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,4343 -1,4343 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2011, 2012, 2015 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--/* gtktreeviewcolumn.c
-- * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Library 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
-- * Library General Public License for more details.
-- *
-- * You should have received a copy of the GNU Library 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.
-- */
--
--#include <config.h>
--
--#include "ui/gui/pspp-sheet-private.h"
--
--#include <errno.h>
--#include <gtk/gtk.h>
--#include <stdlib.h>
--#include <string.h>
--
--#include "ui/gui/psppire-marshal.h"
--#include "ui/gui/pspp-sheet-selection.h"
--#include "ui/gui/pspp-widget-facade.h"
--
--#define P_(STRING) STRING
--#define GTK_PARAM_READABLE G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
--#define GTK_PARAM_READWRITE G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
--
--enum
--{
--  PROP_0,
--  PROP_VISIBLE,
--  PROP_RESIZABLE,
--  PROP_WIDTH,
--  PROP_SPACING,
--  PROP_FIXED_WIDTH,
--  PROP_MIN_WIDTH,
--  PROP_MAX_WIDTH,
--  PROP_TITLE,
--  PROP_EXPAND,
--  PROP_CLICKABLE,
--  PROP_WIDGET,
--  PROP_ALIGNMENT,
--  PROP_REORDERABLE,
--  PROP_SORT_INDICATOR,
--  PROP_SORT_ORDER,
--  PROP_SORT_COLUMN_ID,
--  PROP_QUICK_EDIT,
--  PROP_SELECTED,
--  PROP_SELECTABLE,
--  PROP_ROW_HEAD,
--  PROP_TABBABLE
--};
--
--enum
--{
--  CLICKED,
--  QUERY_TOOLTIP,
--  POPUP_MENU,
--  BUTTON_PRESS_EVENT,
--  LAST_SIGNAL
--};
--
--typedef struct _PsppSheetViewColumnCellInfo PsppSheetViewColumnCellInfo;
--struct _PsppSheetViewColumnCellInfo
--{
--  GtkCellRenderer *cell;
--  GSList *attributes;
--  PsppSheetCellDataFunc func;
--  gpointer func_data;
--  GDestroyNotify destroy;
--  gint requested_width;
--  gint real_width;
--  guint expand : 1;
--  guint pack : 1;
--  guint has_focus : 1;
--  guint in_editing_mode : 1;
--};
--
--/* Type methods */
--static void pspp_sheet_view_column_cell_layout_init              (GtkCellLayoutIface      *iface);
--
--/* GObject methods */
--static void pspp_sheet_view_column_set_property                  (GObject                 *object,
--                                                              guint                    prop_id,
--                                                              const GValue            *value,
--                                                              GParamSpec              *pspec);
--static void pspp_sheet_view_column_get_property                  (GObject                 *object,
--                                                              guint                    prop_id,
--                                                              GValue                  *value,
--                                                              GParamSpec              *pspec);
--static void pspp_sheet_view_column_finalize                      (GObject                 *object);
--
--/* GtkCellLayout implementation */
--static void pspp_sheet_view_column_cell_layout_pack_start         (GtkCellLayout         *cell_layout,
--                                                                 GtkCellRenderer       *cell,
--                                                                 gboolean               expand);
--static void pspp_sheet_view_column_cell_layout_pack_end           (GtkCellLayout         *cell_layout,
--                                                                 GtkCellRenderer       *cell,
--                                                                 gboolean               expand);
--static void pspp_sheet_view_column_cell_layout_clear              (GtkCellLayout         *cell_layout);
--static void pspp_sheet_view_column_cell_layout_add_attribute      (GtkCellLayout         *cell_layout,
--                                                                 GtkCellRenderer       *cell,
--                                                                 const gchar           *attribute,
--                                                                 gint                   column);
--static void pspp_sheet_view_column_cell_layout_set_cell_data_func (GtkCellLayout         *cell_layout,
--                                                                 GtkCellRenderer       *cell,
--                                                                 GtkCellLayoutDataFunc  func,
--                                                                 gpointer               func_data,
--                                                                 GDestroyNotify         destroy);
--static void pspp_sheet_view_column_cell_layout_clear_attributes   (GtkCellLayout         *cell_layout,
--                                                                 GtkCellRenderer       *cell);
--static void pspp_sheet_view_column_cell_layout_reorder            (GtkCellLayout         *cell_layout,
--                                                                 GtkCellRenderer       *cell,
--                                                                 gint                   position);
--static GList *pspp_sheet_view_column_cell_layout_get_cells        (GtkCellLayout         *cell_layout);
--
--/* Button handling code */
--static void pspp_sheet_view_column_create_button                 (PsppSheetViewColumn       *tree_column);
--void pspp_sheet_view_column_update_button                 (PsppSheetViewColumn       *tree_column);
--
--/* Button signal handlers */
--static gint pspp_sheet_view_column_button_event                  (GtkWidget               *widget,
--                                                              GdkEventButton             *event,
--                                                              gpointer                 data);
--static void pspp_sheet_view_column_button_clicked                (GtkWidget               *widget,
--                                                              gpointer                 data);
--static void pspp_sheet_view_column_button_popup_menu (GtkWidget *widget,
--                                                      gpointer data);
--static gboolean pspp_sheet_view_column_mnemonic_activate         (GtkWidget *widget,
--                                                              gboolean   group_cycling,
--                                                              gpointer   data);
--static gboolean on_pspp_sheet_view_column_button_clicked (PsppSheetViewColumn *);
--static gboolean on_pspp_sheet_view_column_button_press_event (PsppSheetViewColumn *,
--                                                              GdkEventButton *);
--
--/* Property handlers */
--static void pspp_sheet_view_model_sort_column_changed            (GtkTreeSortable         *sortable,
--                                                              PsppSheetViewColumn       *tree_column);
--
--/* Internal functions */
--static void pspp_sheet_view_column_sort                          (PsppSheetViewColumn       *tree_column,
--                                                              gpointer                 data);
--static void pspp_sheet_view_column_setup_sort_column_id_callback (PsppSheetViewColumn       *tree_column);
--static void pspp_sheet_view_column_set_attributesv               (PsppSheetViewColumn       *tree_column,
--                                                              GtkCellRenderer         *cell_renderer,
--                                                              va_list                  args);
--static PsppSheetViewColumnCellInfo *pspp_sheet_view_column_get_cell_info (PsppSheetViewColumn *tree_column,
--                                                                    GtkCellRenderer   *cell_renderer);
--
--/* cell list manipulation */
--static GList *pspp_sheet_view_column_cell_first                  (PsppSheetViewColumn      *tree_column);
--static GList *pspp_sheet_view_column_cell_last                   (PsppSheetViewColumn      *tree_column);
--static GList *pspp_sheet_view_column_cell_next                   (PsppSheetViewColumn      *tree_column,
--                                                              GList                  *current);
--static GList *pspp_sheet_view_column_cell_prev                   (PsppSheetViewColumn      *tree_column,
--                                                              GList                  *current);
--static void pspp_sheet_view_column_clear_attributes_by_info      (PsppSheetViewColumn      *tree_column,
--                                                              PsppSheetViewColumnCellInfo *info);
--/* GtkBuildable implementation */
--static void pspp_sheet_view_column_buildable_init                 (GtkBuildableIface     *iface);
--
--static guint tree_column_signals[LAST_SIGNAL] = { 0 };
--
--G_DEFINE_TYPE_WITH_CODE (PsppSheetViewColumn, pspp_sheet_view_column, G_TYPE_OBJECT,
--                       G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
--                                              pspp_sheet_view_column_cell_layout_init)
--                       G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
--                                              pspp_sheet_view_column_buildable_init))
--
--
--static void
--pspp_sheet_view_column_class_init (PsppSheetViewColumnClass *class)
--{
--  GObjectClass *object_class;
--
--  object_class = (GObjectClass*) class;
--
--  class->clicked = on_pspp_sheet_view_column_button_clicked;
--  class->button_press_event = on_pspp_sheet_view_column_button_press_event;
--
--  object_class->finalize = pspp_sheet_view_column_finalize;
--  object_class->set_property = pspp_sheet_view_column_set_property;
--  object_class->get_property = pspp_sheet_view_column_get_property;
--  
--  tree_column_signals[CLICKED] =
--    g_signal_new ("clicked",
--                  G_OBJECT_CLASS_TYPE (object_class),
--                  G_SIGNAL_RUN_LAST,
--                  G_STRUCT_OFFSET (PsppSheetViewColumnClass, clicked),
--                  g_signal_accumulator_true_handled, NULL,
--                  psppire_marshal_BOOLEAN__VOID,
--                  G_TYPE_BOOLEAN, 0);
--
--  tree_column_signals[POPUP_MENU] =
--    g_signal_new ("popup-menu",
--                  G_OBJECT_CLASS_TYPE (object_class),
--                  G_SIGNAL_RUN_LAST,
--                  0,
--                  NULL, NULL,
--                  g_cclosure_marshal_VOID__VOID,
--                  G_TYPE_NONE, 0);
--
--  tree_column_signals[QUERY_TOOLTIP] =
--    g_signal_new ("query-tooltip",
--                  G_OBJECT_CLASS_TYPE (object_class),
--                  G_SIGNAL_RUN_LAST,
--                  0,
--                  g_signal_accumulator_true_handled, NULL,
--                  psppire_marshal_BOOLEAN__OBJECT,
--                  G_TYPE_BOOLEAN, 1,
--                  GTK_TYPE_TOOLTIP);
--
--  tree_column_signals[BUTTON_PRESS_EVENT] =
--    g_signal_new ("button-press-event",
--                  G_OBJECT_CLASS_TYPE (object_class),
--                  G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST,
--                  G_STRUCT_OFFSET (PsppSheetViewColumnClass, button_press_event),
--                  g_signal_accumulator_true_handled, NULL,
--                  psppire_marshal_BOOLEAN__BOXED,
--                  G_TYPE_BOOLEAN, 1,
--                  GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
--
--  g_object_class_install_property (object_class,
--                                   PROP_VISIBLE,
--                                   g_param_spec_boolean ("visible",
--                                                        P_("Visible"),
--                                                        P_("Whether to display the column"),
--                                                         TRUE,
--                                                         GTK_PARAM_READWRITE));
--  
--  g_object_class_install_property (object_class,
--                                   PROP_RESIZABLE,
--                                   g_param_spec_boolean ("resizable",
--                                                       P_("Resizable"),
--                                                       P_("Column is user-resizable"),
--                                                         FALSE,
--                                                         GTK_PARAM_READWRITE));
--  
--  g_object_class_install_property (object_class,
--                                   PROP_WIDTH,
--                                   g_param_spec_int ("width",
--                                                   P_("Width"),
--                                                   P_("Current width of the column"),
--                                                   0,
--                                                   G_MAXINT,
--                                                   0,
--                                                   GTK_PARAM_READABLE));
--  g_object_class_install_property (object_class,
--                                   PROP_SPACING,
--                                   g_param_spec_int ("spacing",
--                                                   P_("Spacing"),
--                                                   P_("Space which is inserted between cells"),
--                                                   0,
--                                                   G_MAXINT,
--                                                   0,
--                                                   GTK_PARAM_READWRITE));
--  
--  g_object_class_install_property (object_class,
--                                   PROP_FIXED_WIDTH,
--                                   g_param_spec_int ("fixed-width",
--                                                     P_("Fixed Width"),
--                                                     P_("Current fixed width of the column"),
--                                                     1,
--                                                     G_MAXINT,
--                                                     100,
--                                                     GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (object_class,
--                                   PROP_MIN_WIDTH,
--                                   g_param_spec_int ("min-width",
--                                                     P_("Minimum Width"),
--                                                     P_("Minimum allowed width of the column"),
--                                                     -1,
--                                                     G_MAXINT,
--                                                     -1,
--                                                     GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (object_class,
--                                   PROP_MAX_WIDTH,
--                                   g_param_spec_int ("max-width",
--                                                     P_("Maximum Width"),
--                                                     P_("Maximum allowed width of the column"),
--                                                     -1,
--                                                     G_MAXINT,
--                                                     -1,
--                                                     GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (object_class,
--                                   PROP_TITLE,
--                                   g_param_spec_string ("title",
--                                                        P_("Title"),
--                                                        P_("Title to appear in column header"),
--                                                        "",
--                                                        GTK_PARAM_READWRITE));
--  
--  g_object_class_install_property (object_class,
--                                   PROP_EXPAND,
--                                   g_param_spec_boolean ("expand",
--                                                       P_("Expand"),
--                                                       P_("Column gets share of extra width allocated to the widget"),
--                                                       FALSE,
--                                                       GTK_PARAM_READWRITE));
--  
--  g_object_class_install_property (object_class,
--                                   PROP_CLICKABLE,
--                                   g_param_spec_boolean ("clickable",
--                                                        P_("Clickable"),
--                                                        P_("Whether the header can be clicked"),
--                                                         FALSE,
--                                                         GTK_PARAM_READWRITE));
--  
--
--  g_object_class_install_property (object_class,
--                                   PROP_WIDGET,
--                                   g_param_spec_object ("widget",
--                                                        P_("Widget"),
--                                                        P_("Widget to put in column header button instead of column title"),
--                                                        GTK_TYPE_WIDGET,
--                                                        GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (object_class,
--                                   PROP_ALIGNMENT,
--                                   g_param_spec_float ("alignment",
--                                                       P_("Alignment"),
--                                                       P_("X Alignment of the column header text or widget"),
--                                                       0.0,
--                                                       1.0,
--                                                       0.0,
--                                                       GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (object_class,
--                                   PROP_REORDERABLE,
--                                   g_param_spec_boolean ("reorderable",
--                                                       P_("Reorderable"),
--                                                       P_("Whether the column can be reordered around the headers"),
--                                                       FALSE,
--                                                       GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (object_class,
--                                   PROP_SORT_INDICATOR,
--                                   g_param_spec_boolean ("sort-indicator",
--                                                        P_("Sort indicator"),
--                                                        P_("Whether to show a sort indicator"),
--                                                         FALSE,
--                                                         GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (object_class,
--                                   PROP_SORT_ORDER,
--                                   g_param_spec_enum ("sort-order",
--                                                      P_("Sort order"),
--                                                      P_("Sort direction the sort indicator should indicate"),
--                                                      GTK_TYPE_SORT_TYPE,
--                                                      GTK_SORT_ASCENDING,
--                                                      GTK_PARAM_READWRITE));
--
--  /**
--   * PsppSheetViewColumn:sort-column-id:
--   *
--   * Logical sort column ID this column sorts on when selected for sorting. Setting the sort column ID makes the column header
--   * clickable. Set to %-1 to make the column unsortable.
--   *
--   * Since: 2.18
--   **/
--  g_object_class_install_property (object_class,
--                                   PROP_SORT_COLUMN_ID,
--                                   g_param_spec_int ("sort-column-id",
--                                                     P_("Sort column ID"),
--                                                     P_("Logical sort column ID this column sorts on when selected for sorting"),
--                                                     -1,
--                                                     G_MAXINT,
--                                                     -1,
--                                                     GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (object_class,
--                                   PROP_QUICK_EDIT,
--                                   g_param_spec_boolean ("quick-edit",
--                                                         P_("Quick edit"),
--                                                         P_("If true, editing starts upon the first click in the column.  If false, the first click selects the column and a second click is needed to begin editing.  This has no effect on cells that are not editable."),
--                                                         TRUE,
--                                                         GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (object_class,
--                                   PROP_SELECTED,
--                                   g_param_spec_boolean ("selected",
--                                                         P_("Selected"),
--                                                         P_("If true, this column is selected as part of a rectangular selection."),
--                                                         FALSE,
--                                                         GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (object_class,
--                                   PROP_SELECTABLE,
--                                   g_param_spec_boolean ("selectable",
--                                                         P_("Selectable"),
--                                                         P_("If true, this column may be selected as part of a rectangular selection."),
--                                                         TRUE,
--                                                         GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (object_class,
--                                   PROP_ROW_HEAD,
--                                   g_param_spec_boolean ("row-head",
--                                                         P_("Row head"),
--                                                         P_("If true, this column is a \"row head\", equivalent to a column head.  If rectangular selection is enabled, then shift+click and control+click in the column select row ranges and toggle row selection, respectively.  The column should ordinarily include a button cell; clicking on the button will select the row (and deselect all other rows)."),
--                                                         FALSE,
--                                                         GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (object_class,
--                                   PROP_TABBABLE,
--                                   g_param_spec_boolean ("tabbable",
--                                                         P_("Tabbable"),
--                                                         P_("If true, Tab and Shift+Tab visit this column.  If false, Tab and Shift+Tab skip this column."),
--                                                         TRUE,
--                                                         GTK_PARAM_READWRITE));
--}
--
--
--static void _cell_layout_buildable_custom_tag_end (GtkBuildable *buildable,
--                                                 GtkBuilder   *builder,
--                                                 GObject      *child,
--                                                 const gchar  *tagname,
--                                                 gpointer     *data);
--
--
--static void _cell_layout_buildable_add_child (GtkBuildable      *buildable,
--                                                GtkBuilder        *builder,
--                                                GObject           *child,
--                                                const gchar       *type);
--
--
--static gboolean _cell_layout_buildable_custom_tag_start (GtkBuildable  *buildable,
--                                             GtkBuilder    *builder,
--                                             GObject       *child,
--                                             const gchar   *tagname,
--                                             GMarkupParser *parser,
--                                       gpointer      *data);
--
--
--static void
--pspp_sheet_view_column_buildable_init (GtkBuildableIface *iface)
--{
--  iface->add_child = _cell_layout_buildable_add_child;
--  iface->custom_tag_start = _cell_layout_buildable_custom_tag_start;
--  iface->custom_tag_end = _cell_layout_buildable_custom_tag_end;
--}
--
--static void
--pspp_sheet_view_column_cell_layout_init (GtkCellLayoutIface *iface)
--{
--  iface->pack_start = pspp_sheet_view_column_cell_layout_pack_start;
--  iface->pack_end = pspp_sheet_view_column_cell_layout_pack_end;
--  iface->clear = pspp_sheet_view_column_cell_layout_clear;
--  iface->add_attribute = pspp_sheet_view_column_cell_layout_add_attribute;
--  iface->set_cell_data_func = pspp_sheet_view_column_cell_layout_set_cell_data_func;
--  iface->clear_attributes = pspp_sheet_view_column_cell_layout_clear_attributes;
--  iface->reorder = pspp_sheet_view_column_cell_layout_reorder;
--  iface->get_cells = pspp_sheet_view_column_cell_layout_get_cells;
--}
--
--static void
--pspp_sheet_view_column_init (PsppSheetViewColumn *tree_column)
--{
--  tree_column->button = NULL;
--  tree_column->halign = GTK_ALIGN_START;
--  tree_column->width = 0;
--  tree_column->spacing = 0;
--  tree_column->requested_width = -1;
--  tree_column->min_width = -1;
--  tree_column->max_width = -1;
--  tree_column->resized_width = 0;
--  tree_column->visible = TRUE;
--  tree_column->resizable = FALSE;
--  tree_column->expand = FALSE;
--  tree_column->clickable = FALSE;
--  tree_column->dirty = TRUE;
--  tree_column->selected = FALSE;
--  tree_column->selectable = TRUE;
--  tree_column->row_head = FALSE;
--  tree_column->tabbable = TRUE;
--  tree_column->sort_order = GTK_SORT_ASCENDING;
--  tree_column->show_sort_indicator = FALSE;
--  tree_column->property_changed_signal = 0;
--  tree_column->sort_clicked_signal = 0;
--  tree_column->sort_column_changed_signal = 0;
--  tree_column->sort_column_id = -1;
--  tree_column->reorderable = FALSE;
--  tree_column->maybe_reordered = FALSE;
--  tree_column->fixed_width = 1;
--  tree_column->use_resized_width = FALSE;
--  tree_column->title = g_strdup ("");
--  tree_column->quick_edit = TRUE;
--}
--
--static void
--pspp_sheet_view_column_finalize (GObject *object)
--{
--  PsppSheetViewColumn *tree_column = (PsppSheetViewColumn *) object;
--  GList *list;
--
--  for (list = tree_column->cell_list; list; list = list->next)
--    {
--      PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) list->data;
--
--      if (info->destroy)
--      {
--        GDestroyNotify d = info->destroy;
--
--        info->destroy = NULL;
--        d (info->func_data);
--      }
--      pspp_sheet_view_column_clear_attributes_by_info (tree_column, info);
--      g_object_unref (info->cell);
--      g_free (info);
--    }
--
--  g_free (tree_column->title);
--  g_list_free (tree_column->cell_list);
--
--  if (tree_column->child)
--    g_object_unref (tree_column->child);
--
--  G_OBJECT_CLASS (pspp_sheet_view_column_parent_class)->finalize (object);
--}
--
--static void
--pspp_sheet_view_column_set_property (GObject         *object,
--                                   guint            prop_id,
--                                   const GValue    *value,
--                                   GParamSpec      *pspec)
--{
--  PsppSheetViewColumn *tree_column;
--
--  tree_column = PSPP_SHEET_VIEW_COLUMN (object);
--
--  switch (prop_id)
--    {
--    case PROP_VISIBLE:
--      pspp_sheet_view_column_set_visible (tree_column,
--                                        g_value_get_boolean (value));
--      break;
--
--    case PROP_RESIZABLE:
--      pspp_sheet_view_column_set_resizable (tree_column,
--                                        g_value_get_boolean (value));
--      break;
--
--    case PROP_FIXED_WIDTH:
--      pspp_sheet_view_column_set_fixed_width (tree_column,
--                                          g_value_get_int (value));
--      break;
--
--    case PROP_MIN_WIDTH:
--      pspp_sheet_view_column_set_min_width (tree_column,
--                                          g_value_get_int (value));
--      break;
--
--    case PROP_MAX_WIDTH:
--      pspp_sheet_view_column_set_max_width (tree_column,
--                                          g_value_get_int (value));
--      break;
--
--    case PROP_SPACING:
--      pspp_sheet_view_column_set_spacing (tree_column,
--                                      g_value_get_int (value));
--      break;
--
--    case PROP_TITLE:
--      pspp_sheet_view_column_set_title (tree_column,
--                                      g_value_get_string (value));
--      break;
--
--    case PROP_EXPAND:
--      pspp_sheet_view_column_set_expand (tree_column,
--                                     g_value_get_boolean (value));
--      break;
--
--    case PROP_CLICKABLE:
--      pspp_sheet_view_column_set_clickable (tree_column,
--                                          g_value_get_boolean (value));
--      break;
--
--    case PROP_WIDGET:
--      pspp_sheet_view_column_set_widget (tree_column,
--                                       (GtkWidget*) g_value_get_object (value));
--      break;
--
--    case PROP_ALIGNMENT:
--      pspp_sheet_view_column_set_alignment (tree_column,
--                                          g_value_get_float (value));
--      break;
--
--    case PROP_REORDERABLE:
--      pspp_sheet_view_column_set_reorderable (tree_column,
--                                          g_value_get_boolean (value));
--      break;
--
--    case PROP_SORT_INDICATOR:
--      pspp_sheet_view_column_set_sort_indicator (tree_column,
--                                               g_value_get_boolean (value));
--      break;
--
--    case PROP_SORT_ORDER:
--      pspp_sheet_view_column_set_sort_order (tree_column,
--                                           g_value_get_enum (value));
--      break;
--      
--    case PROP_SORT_COLUMN_ID:
--      pspp_sheet_view_column_set_sort_column_id (tree_column,
--                                               g_value_get_int (value));
--      break;
--
--    case PROP_QUICK_EDIT:
--      pspp_sheet_view_column_set_quick_edit (tree_column,
--                                             g_value_get_boolean (value));
--      break;
--
--    case PROP_SELECTED:
--      pspp_sheet_view_column_set_selected (tree_column,
--                                             g_value_get_boolean (value));
--      break;
--
--    case PROP_SELECTABLE:
--      pspp_sheet_view_column_set_selectable (tree_column,
--                                             g_value_get_boolean (value));
--      break;
--
--    case PROP_ROW_HEAD:
--      pspp_sheet_view_column_set_row_head (tree_column,
--                                             g_value_get_boolean (value));
--      break;
--
--    case PROP_TABBABLE:
--      pspp_sheet_view_column_set_tabbable (tree_column,
--                                           g_value_get_boolean (value));
--      break;
--
--    default:
--      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
--      break;
--    }
--}
--
--static void
--pspp_sheet_view_column_get_property (GObject         *object,
--                                   guint            prop_id,
--                                   GValue          *value,
--                                   GParamSpec      *pspec)
--{
--  PsppSheetViewColumn *tree_column;
--
--  tree_column = PSPP_SHEET_VIEW_COLUMN (object);
--
--  switch (prop_id)
--    {
--    case PROP_VISIBLE:
--      g_value_set_boolean (value,
--                           pspp_sheet_view_column_get_visible (tree_column));
--      break;
--
--    case PROP_RESIZABLE:
--      g_value_set_boolean (value,
--                           pspp_sheet_view_column_get_resizable (tree_column));
--      break;
--
--    case PROP_WIDTH:
--      g_value_set_int (value,
--                       pspp_sheet_view_column_get_width (tree_column));
--      break;
--
--    case PROP_SPACING:
--      g_value_set_int (value,
--                       pspp_sheet_view_column_get_spacing (tree_column));
--      break;
--
--    case PROP_FIXED_WIDTH:
--      g_value_set_int (value,
--                       pspp_sheet_view_column_get_fixed_width (tree_column));
--      break;
--
--    case PROP_MIN_WIDTH:
--      g_value_set_int (value,
--                       pspp_sheet_view_column_get_min_width (tree_column));
--      break;
--
--    case PROP_MAX_WIDTH:
--      g_value_set_int (value,
--                       pspp_sheet_view_column_get_max_width (tree_column));
--      break;
--
--    case PROP_TITLE:
--      g_value_set_string (value,
--                          pspp_sheet_view_column_get_title (tree_column));
--      break;
--
--    case PROP_EXPAND:
--      g_value_set_boolean (value,
--                          pspp_sheet_view_column_get_expand (tree_column));
--      break;
--
--    case PROP_CLICKABLE:
--      g_value_set_boolean (value,
--                           pspp_sheet_view_column_get_clickable (tree_column));
--      break;
--
--    case PROP_WIDGET:
--      g_value_set_object (value,
--                          (GObject*) pspp_sheet_view_column_get_widget (tree_column));
--      break;
--
--    case PROP_ALIGNMENT:
--      g_value_set_float (value,
--                         pspp_sheet_view_column_get_alignment (tree_column));
--      break;
--
--    case PROP_REORDERABLE:
--      g_value_set_boolean (value,
--                         pspp_sheet_view_column_get_reorderable (tree_column));
--      break;
--
--    case PROP_SORT_INDICATOR:
--      g_value_set_boolean (value,
--                           pspp_sheet_view_column_get_sort_indicator (tree_column));
--      break;
--
--    case PROP_SORT_ORDER:
--      g_value_set_enum (value,
--                        pspp_sheet_view_column_get_sort_order (tree_column));
--      break;
--      
--    case PROP_SORT_COLUMN_ID:
--      g_value_set_int (value,
--                       pspp_sheet_view_column_get_sort_column_id (tree_column));
--      break;
--
--    case PROP_QUICK_EDIT:
--      g_value_set_boolean (value,
--                           pspp_sheet_view_column_get_quick_edit (tree_column));
--      break;
--
--    case PROP_SELECTED:
--      g_value_set_boolean (value,
--                           pspp_sheet_view_column_get_selected (tree_column));
--      break;
--
--    case PROP_SELECTABLE:
--      g_value_set_boolean (value,
--                           pspp_sheet_view_column_get_selectable (tree_column));
--      break;
--
--    case PROP_ROW_HEAD:
--      g_value_set_boolean (value,
--                           pspp_sheet_view_column_get_row_head (tree_column));
--      break;
--
--    case PROP_TABBABLE:
--      g_value_set_boolean (value,
--                           pspp_sheet_view_column_get_tabbable (tree_column));
--      break;
--
--    default:
--      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
--      break;
--    }
--}
--
--/* Implementation of GtkCellLayout interface
-- */
--
--static void
--pspp_sheet_view_column_cell_layout_pack_start (GtkCellLayout   *cell_layout,
--                                             GtkCellRenderer *cell,
--                                             gboolean         expand)
--{
--  PsppSheetViewColumn *column;
--  PsppSheetViewColumnCellInfo *cell_info;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
--  column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
--  g_return_if_fail (! pspp_sheet_view_column_get_cell_info (column, cell));
--
--  g_object_ref_sink (cell);
--
--  cell_info = g_new0 (PsppSheetViewColumnCellInfo, 1);
--  cell_info->cell = cell;
--  cell_info->expand = expand ? TRUE : FALSE;
--  cell_info->pack = GTK_PACK_START;
--  cell_info->has_focus = 0;
--  cell_info->attributes = NULL;
--
--  column->cell_list = g_list_append (column->cell_list, cell_info);
--}
--
--static void
--pspp_sheet_view_column_cell_layout_pack_end (GtkCellLayout   *cell_layout,
--                                           GtkCellRenderer *cell,
--                                           gboolean         expand)
--{
--  PsppSheetViewColumn *column;
--  PsppSheetViewColumnCellInfo *cell_info;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
--  column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
--  g_return_if_fail (! pspp_sheet_view_column_get_cell_info (column, cell));
--
--  g_object_ref_sink (cell);
--
--  cell_info = g_new0 (PsppSheetViewColumnCellInfo, 1);
--  cell_info->cell = cell;
--  cell_info->expand = expand ? TRUE : FALSE;
--  cell_info->pack = GTK_PACK_END;
--  cell_info->has_focus = 0;
--  cell_info->attributes = NULL;
--
--  column->cell_list = g_list_append (column->cell_list, cell_info);
--}
--
--static void
--pspp_sheet_view_column_cell_layout_clear (GtkCellLayout *cell_layout)
--{
--  PsppSheetViewColumn *column;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
--  column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
--
--  while (column->cell_list)
--    {
--      PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *)column->cell_list->data;
--
--      pspp_sheet_view_column_cell_layout_clear_attributes (cell_layout, info->cell);
--      g_object_unref (info->cell);
--      g_free (info);
--      column->cell_list = g_list_delete_link (column->cell_list, 
--                                            column->cell_list);
--    }
--}
--
--static void
--pspp_sheet_view_column_cell_layout_add_attribute (GtkCellLayout   *cell_layout,
--                                                GtkCellRenderer *cell,
--                                                const gchar     *attribute,
--                                                gint             column)
--{
--  PsppSheetViewColumn *tree_column;
--  PsppSheetViewColumnCellInfo *info;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
--  tree_column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
--
--  info = pspp_sheet_view_column_get_cell_info (tree_column, cell);
--  g_return_if_fail (info != NULL);
--
--  info->attributes = g_slist_prepend (info->attributes, GINT_TO_POINTER (column));
--  info->attributes = g_slist_prepend (info->attributes, g_strdup (attribute));
--
--  if (tree_column->tree_view)
--    _pspp_sheet_view_column_cell_set_dirty (tree_column);
--}
--
--static void
--pspp_sheet_view_column_cell_layout_set_cell_data_func (GtkCellLayout         *cell_layout,
--                                                     GtkCellRenderer       *cell,
--                                                     GtkCellLayoutDataFunc  func,
--                                                     gpointer               func_data,
--                                                     GDestroyNotify         destroy)
--{
--  PsppSheetViewColumn *column;
--  PsppSheetViewColumnCellInfo *info;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
--  column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
--
--  info = pspp_sheet_view_column_get_cell_info (column, cell);
--  g_return_if_fail (info != NULL);
--
--  if (info->destroy)
--    {
--      GDestroyNotify d = info->destroy;
--
--      info->destroy = NULL;
--      d (info->func_data);
--    }
--
--  info->func = (PsppSheetCellDataFunc)func;
--  info->func_data = func_data;
--  info->destroy = destroy;
--
--  if (column->tree_view)
--    _pspp_sheet_view_column_cell_set_dirty (column);
--}
--
--static void
--pspp_sheet_view_column_cell_layout_clear_attributes (GtkCellLayout    *cell_layout,
--                                                   GtkCellRenderer  *cell_renderer)
--{
--  PsppSheetViewColumn *column;
--  PsppSheetViewColumnCellInfo *info;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
--  column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
--
--  info = pspp_sheet_view_column_get_cell_info (column, cell_renderer);
--  if (info)
--    pspp_sheet_view_column_clear_attributes_by_info (column, info);
--}
--
--static void
--pspp_sheet_view_column_cell_layout_reorder (GtkCellLayout   *cell_layout,
--                                          GtkCellRenderer *cell,
--                                          gint             position)
--{
--  GList *link;
--  PsppSheetViewColumn *column;
--  PsppSheetViewColumnCellInfo *info;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (cell_layout));
--  column = PSPP_SHEET_VIEW_COLUMN (cell_layout);
--
--  info = pspp_sheet_view_column_get_cell_info (column, cell);
--
--  g_return_if_fail (info != NULL);
--  g_return_if_fail (position >= 0);
--
--  link = g_list_find (column->cell_list, info);
--
--  g_return_if_fail (link != NULL);
--
--  column->cell_list = g_list_delete_link (column->cell_list, link);
--  column->cell_list = g_list_insert (column->cell_list, info, position);
--
--  if (column->tree_view)
--    gtk_widget_queue_draw (column->tree_view);
--}
--
--static void
--pspp_sheet_view_column_clear_attributes_by_info (PsppSheetViewColumn *tree_column,
--                                             PsppSheetViewColumnCellInfo *info)
--{
--  GSList *list;
--
--  list = info->attributes;
--
--  while (list && list->next)
--    {
--      g_free (list->data);
--      list = list->next->next;
--    }
--  g_slist_free (info->attributes);
--  info->attributes = NULL;
--
--  if (tree_column->tree_view)
--    _pspp_sheet_view_column_cell_set_dirty (tree_column);
--}
--
--static gboolean
--on_query_tooltip (GtkWidget  *widget,
--                  gint        x,
--                  gint        y,
--                  gboolean    keyboard_mode,
--                  GtkTooltip *tooltip,
--                  gpointer    user_data)
--{
--  PsppSheetViewColumn *tree_column = user_data;
--  gboolean handled;
--
--  g_signal_emit (tree_column, tree_column_signals[QUERY_TOOLTIP], 0,
--                 tooltip, &handled);
--  return handled;
--}
--
--static gboolean
--on_button_pressed (GtkWidget *widget, GdkEventButton *event,
--                   gpointer user_data)
--{
--  PsppSheetViewColumn *tree_column = user_data;
--  gboolean handled;
--
--  /* XXX See "Implement GtkWidget::popup_menu" in GTK+ reference manual. */
--  g_signal_emit (tree_column, tree_column_signals[BUTTON_PRESS_EVENT],
--                 0, event, &handled);
--  return handled;
--}
--
--/* Helper functions
-- */
--
--/* Button handling code
-- */
--static void
--pspp_sheet_view_column_create_button (PsppSheetViewColumn *tree_column)
--{
--  PsppSheetView *tree_view;
--  GtkWidget *child;
--  GtkWidget *hbox;
--
--  tree_view = (PsppSheetView *) tree_column->tree_view;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (tree_column->button == NULL);
--
--  tree_column->button = gtk_button_new ();
--  gtk_widget_add_events (tree_column->button, GDK_POINTER_MOTION_MASK);
--
--  /* make sure we own a reference to it as well. */
--  if (tree_view->priv->header_window)
--    gtk_widget_set_parent_window (tree_column->button, tree_view->priv->header_window);
--  gtk_widget_set_parent (tree_column->button, GTK_WIDGET (tree_view));
--
--  g_signal_connect (tree_column->button, "event",
--                  G_CALLBACK (pspp_sheet_view_column_button_event),
--                  tree_column);
--  g_signal_connect (tree_column->button, "clicked",
--                  G_CALLBACK (pspp_sheet_view_column_button_clicked),
--                  tree_column);
--  g_signal_connect (tree_column->button, "popup-menu",
--                  G_CALLBACK (pspp_sheet_view_column_button_popup_menu),
--                  tree_column);
--  g_signal_connect (tree_column->button, "button-press-event",
--                    G_CALLBACK (on_button_pressed), tree_column);
--
--  g_signal_connect (tree_column->button, "query-tooltip",
--                    G_CALLBACK (on_query_tooltip), tree_column);
--  g_object_set (tree_column->button, "has-tooltip", TRUE, NULL);
--
--  tree_column->bin = gtk_event_box_new ();
--  g_object_set (tree_column->bin, "halign", GTK_ALIGN_CENTER, NULL);
--
--  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
--
--  if (tree_column->child)
--    child = tree_column->child;
--  else
--    {
--      child = gtk_label_new (tree_column->title);
--      gtk_widget_show (child);
--    }
--
--  g_signal_connect (child, "mnemonic-activate",
--                  G_CALLBACK (pspp_sheet_view_column_mnemonic_activate),
--                  tree_column);
--
--
--  gtk_box_pack_start (GTK_BOX (hbox), tree_column->bin, TRUE, TRUE, 0);
--        
--  gtk_container_add (GTK_CONTAINER (tree_column->bin), child);
--  gtk_container_add (GTK_CONTAINER (tree_column->button), hbox);
--
--  gtk_widget_show (hbox);
--  gtk_widget_show (tree_column->bin);
--  pspp_sheet_view_column_update_button (tree_column);
--}
--
--void 
--pspp_sheet_view_column_update_button (PsppSheetViewColumn *tree_column)
--{
--  gint sort_column_id = -1;
--  GtkWidget *alignment;
--  GtkWidget *current_child;
--  GtkTreeModel *model;
--  gboolean can_focus;
--
--  if (tree_column->tree_view)
--    model = pspp_sheet_view_get_model (PSPP_SHEET_VIEW (tree_column->tree_view));
--  else
--    model = NULL;
--
--  /* Create a button if necessary */
--  if (tree_column->visible &&
--      tree_column->button == NULL &&
--      tree_column->tree_view &&
--      gtk_widget_get_realized (tree_column->tree_view))
--    pspp_sheet_view_column_create_button (tree_column);
--  
--  if (! tree_column->button)
--    return;
--
--  alignment = tree_column->bin;
--  current_child = gtk_bin_get_child (GTK_BIN (alignment));
--
--  /* Set up the actual button */
--  g_object_set (alignment,
--              "halign", tree_column->halign,
--              "valign", GTK_ALIGN_CENTER, NULL);
--      
--  if (tree_column->child)
--    {
--      if (current_child != tree_column->child)
--      {
--        gtk_container_remove (GTK_CONTAINER (alignment),
--                              current_child);
--        gtk_container_add (GTK_CONTAINER (alignment),
--                           tree_column->child);
--      }
--    }
--  else 
--    {
--      if (current_child == NULL)
--      {
--        current_child = gtk_label_new (NULL);
--        gtk_widget_show (current_child);
--        gtk_container_add (GTK_CONTAINER (alignment),
--                           current_child);
--      }
--
--      g_return_if_fail (GTK_IS_LABEL (current_child));
--
--      if (tree_column->title)
--      gtk_label_set_text_with_mnemonic (GTK_LABEL (current_child),
--                                        tree_column->title);
--      else
--      gtk_label_set_text_with_mnemonic (GTK_LABEL (current_child),
--                                        "");
--    }
--
--  if (GTK_IS_TREE_SORTABLE (model))
--    gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
--                                        &sort_column_id,
--                                        NULL);
--
--
--  /* It's always safe to hide the button.  It isn't always safe to show it, as
--   * if you show it before it's realized, it'll get the wrong window. */
--  if (tree_column->button &&
--      tree_column->tree_view != NULL &&
--      gtk_widget_get_realized (tree_column->tree_view))
--    {
--      if (tree_column->visible)
--      {
--        gtk_widget_show (tree_column->button);
--        if (tree_column->window)
--          {
--            if (tree_column->resizable)
--              {
--                gdk_window_show (tree_column->window);
--                gdk_window_raise (tree_column->window);
--              }
--            else
--              {
--                gdk_window_hide (tree_column->window);
--              }
--          }
--      }
--      else
--      {
--        gtk_widget_hide (tree_column->button);
--        if (tree_column->window)
--          gdk_window_hide (tree_column->window);
--      }
--    }
--
--  can_focus = pspp_sheet_view_column_can_focus (tree_column);
--  gtk_widget_set_can_focus (tree_column->button, can_focus);
--  if (!can_focus && gtk_widget_has_focus (tree_column->button))
--    {
--      GtkWidget *toplevel = gtk_widget_get_toplevel (tree_column->tree_view);
--      if (gtk_widget_is_toplevel (toplevel))
--        {
--          gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
--        }
--    }
--
--  /* Queue a resize on the assumption that we always want to catch all changes
--   * and columns don't change all that often.
--   */
--  if (gtk_widget_get_realized (tree_column->tree_view))
--     gtk_widget_queue_resize (tree_column->tree_view);
--
--}
--
--/* Button signal handlers
-- */
--
--static gint
--pspp_sheet_view_column_button_event (GtkWidget *widget,
--                                 GdkEventButton  *event,
--                                 gpointer   data)
--{
--  PsppSheetViewColumn *column = (PsppSheetViewColumn *) data;
--
--  g_return_val_if_fail (event != NULL, FALSE);
--
--  if (event->type == GDK_BUTTON_PRESS &&
--      column->reorderable &&
--      ((GdkEventButton *)event)->button == 1)
--    {
--      column->maybe_reordered = TRUE;
--      gdk_window_get_device_position (gtk_button_get_event_window (GTK_BUTTON (widget)),
--                                    event->device,
--                            &column->drag_x,
--                            &column->drag_y,
--                            NULL);
--      gtk_widget_grab_focus (widget);
--    }
--
--  if (event->type == GDK_BUTTON_RELEASE ||
--      event->type == GDK_LEAVE_NOTIFY)
--    column->maybe_reordered = FALSE;
--  
--  if (event->type == GDK_MOTION_NOTIFY &&
--      column->maybe_reordered &&
--      (gtk_drag_check_threshold (widget,
--                               column->drag_x,
--                               column->drag_y,
--                               (gint) ((GdkEventMotion *)event)->x,
--                               (gint) ((GdkEventMotion *)event)->y)))
--    {
--      column->maybe_reordered = FALSE;
--      _pspp_sheet_view_column_start_drag (PSPP_SHEET_VIEW (column->tree_view), column);
--      return TRUE;
--    }
--  if (column->clickable == FALSE)
--    {
--      switch (event->type)
--      {
--      case GDK_MOTION_NOTIFY:
--      case GDK_BUTTON_RELEASE:
--      case GDK_ENTER_NOTIFY:
--      case GDK_LEAVE_NOTIFY:
--        return TRUE;
--      default:
--        return FALSE;
--      }
--    }
--  return FALSE;
--}
--
--static gboolean
--all_rows_selected (PsppSheetView *sheet_view)
--{
--  PsppSheetSelection *selection = sheet_view->priv->selection;
--  gint n_rows, n_selected_rows;
--
--  n_rows = sheet_view->priv->row_count;
--  n_selected_rows = pspp_sheet_selection_count_selected_rows (selection);
--
--  return n_rows > 0 && n_selected_rows >= n_rows;
--}
--
--static gboolean
--on_pspp_sheet_view_column_button_press_event (PsppSheetViewColumn *column,
--                                              GdkEventButton *event)
--{
--  PsppSheetView *sheet_view = PSPP_SHEET_VIEW (column->tree_view);
--  PsppSheetSelection *selection;
--  GSignalInvocationHint *hint;
--  guint modifiers;
--
--  /* We only want to run first, not last, but combining that with return type
--     `gboolean' makes GObject warn, so just ignore the run_last call. */
--  hint = g_signal_get_invocation_hint (column);
--  g_return_val_if_fail (hint != NULL, FALSE);
--  if (hint->run_type != G_SIGNAL_RUN_FIRST)
--    return FALSE;
--
--  g_return_val_if_fail (sheet_view != NULL, FALSE);
--
--  selection = sheet_view->priv->selection;
--  g_return_val_if_fail (selection != NULL, FALSE);
--
--  if (pspp_sheet_selection_get_mode (selection) != PSPP_SHEET_SELECTION_RECTANGLE)
--    return FALSE;
--
--  modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
--  if (event->type == GDK_BUTTON_PRESS && event->button == 3)
--    {
--      if (pspp_sheet_selection_count_selected_columns (selection) <= 1
--          || !all_rows_selected (sheet_view))
--        {
--          pspp_sheet_selection_select_all (selection);
--          pspp_sheet_selection_unselect_all_columns (selection);
--          pspp_sheet_selection_select_column (selection, column);
--          sheet_view->priv->anchor_column = column;
--        }
--      return FALSE;
--    }
--  else if (event->type == GDK_BUTTON_PRESS && event->button == 1
--           && modifiers == GDK_CONTROL_MASK)
--    {
--      gboolean is_selected;
--
--      if (!all_rows_selected (sheet_view))
--        {
--          pspp_sheet_selection_select_all (selection);
--          pspp_sheet_selection_unselect_all_columns (selection);
--        }
--      sheet_view->priv->anchor_column = column;
--
--      is_selected = pspp_sheet_view_column_get_selected (column);
--      pspp_sheet_view_column_set_selected (column, !is_selected);
--
--      return TRUE;
--    }
--  else if (event->type == GDK_BUTTON_PRESS && event->button == 1
--           && modifiers == GDK_SHIFT_MASK)
--    {
--      if (!all_rows_selected (sheet_view))
--        {
--          pspp_sheet_selection_select_all (selection);
--          pspp_sheet_selection_unselect_all_columns (selection);
--          sheet_view->priv->anchor_column = column;
--        }
--      else if (sheet_view->priv->anchor_column == NULL)
--        sheet_view->priv->anchor_column = column;
--
--      pspp_sheet_selection_unselect_all_columns (selection);
--      pspp_sheet_selection_select_column_range (selection,
--                                                sheet_view->priv->anchor_column,
--                                                column);
--      return TRUE;
--    }
--
--  return FALSE;
--}
--
--static gboolean
--on_pspp_sheet_view_column_button_clicked (PsppSheetViewColumn *column)
--{
--  PsppSheetSelection *selection;
--  PsppSheetView *sheet_view;
--
--  sheet_view = PSPP_SHEET_VIEW (pspp_sheet_view_column_get_tree_view (column));
--  selection = pspp_sheet_view_get_selection (sheet_view);
--  if (pspp_sheet_selection_get_mode (selection) == PSPP_SHEET_SELECTION_RECTANGLE)
--    {
--      pspp_sheet_selection_select_all (selection);
--      if (pspp_sheet_view_column_get_row_head (column))
--        pspp_sheet_selection_select_all_columns (selection);
--      else
--        {
--          pspp_sheet_selection_unselect_all_columns (selection);
--          pspp_sheet_selection_select_column (selection, column);
--        }
--      sheet_view->priv->anchor_column = column;
--      return TRUE;
--    }
--  return FALSE;
--}
--
--static void
--pspp_sheet_view_column_button_clicked (GtkWidget *widget, gpointer data)
--{
--  PsppSheetViewColumn *column = data;
--  gboolean handled;
--
--  g_signal_emit (column, tree_column_signals[CLICKED], 0, &handled);
--}
--
--static void
--pspp_sheet_view_column_button_popup_menu (GtkWidget *widget, gpointer data)
--{
--  g_signal_emit_by_name (data, "popup-menu");
--}
--
--static gboolean
--pspp_sheet_view_column_mnemonic_activate (GtkWidget *widget,
--                                      gboolean   group_cycling,
--                                      gpointer   data)
--{
--  PsppSheetViewColumn *column = (PsppSheetViewColumn *)data;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (column), FALSE);
--
--  PSPP_SHEET_VIEW (column->tree_view)->priv->focus_column = column;
--  if (column->clickable)
--    gtk_button_clicked (GTK_BUTTON (column->button));
--  else if (gtk_widget_get_can_focus (column->button))
--    gtk_widget_grab_focus (column->button);
--  else
--    gtk_widget_grab_focus (column->tree_view);
--
--  return TRUE;
--}
--
--static void
--pspp_sheet_view_model_sort_column_changed (GtkTreeSortable   *sortable,
--                                       PsppSheetViewColumn *column)
--{
--  gint sort_column_id;
--  GtkSortType order;
--
--  if (gtk_tree_sortable_get_sort_column_id (sortable,
--                                          &sort_column_id,
--                                          &order))
--    {
--      if (sort_column_id == column->sort_column_id)
--      {
--        pspp_sheet_view_column_set_sort_indicator (column, TRUE);
--        pspp_sheet_view_column_set_sort_order (column, order);
--      }
--      else
--      {
--        pspp_sheet_view_column_set_sort_indicator (column, FALSE);
--      }
--    }
--  else
--    {
--      pspp_sheet_view_column_set_sort_indicator (column, FALSE);
--    }
--}
--
--static void
--pspp_sheet_view_column_sort (PsppSheetViewColumn *tree_column,
--                         gpointer           data)
--{
--  gint sort_column_id;
--  GtkSortType order;
--  gboolean has_sort_column;
--  gboolean has_default_sort_func;
--
--  g_return_if_fail (tree_column->tree_view != NULL);
--
--  has_sort_column =
--    gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->model),
--                                        &sort_column_id,
--                                        &order);
--  has_default_sort_func =
--    gtk_tree_sortable_has_default_sort_func (GTK_TREE_SORTABLE (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->model));
--
--  if (has_sort_column &&
--      sort_column_id == tree_column->sort_column_id)
--    {
--      if (order == GTK_SORT_ASCENDING)
--      gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->model),
--                                            tree_column->sort_column_id,
--                                            GTK_SORT_DESCENDING);
--      else if (order == GTK_SORT_DESCENDING && has_default_sort_func)
--      gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->model),
--                                            GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
--                                            GTK_SORT_ASCENDING);
--      else
--      gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->model),
--                                            tree_column->sort_column_id,
--                                            GTK_SORT_ASCENDING);
--    }
--  else
--    {
--      gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->model),
--                                          tree_column->sort_column_id,
--                                          GTK_SORT_ASCENDING);
--    }
--}
--
--
--static void
--pspp_sheet_view_column_setup_sort_column_id_callback (PsppSheetViewColumn *tree_column)
--{
--  GtkTreeModel *model;
--
--  if (tree_column->tree_view == NULL)
--    return;
--
--  model = pspp_sheet_view_get_model (PSPP_SHEET_VIEW (tree_column->tree_view));
--
--  if (model == NULL)
--    return;
--
--  if (GTK_IS_TREE_SORTABLE (model) &&
--      tree_column->sort_column_id != -1)
--    {
--      gint real_sort_column_id;
--      GtkSortType real_order;
--
--      if (tree_column->sort_column_changed_signal == 0)
--        tree_column->sort_column_changed_signal =
--        g_signal_connect (model, "sort-column-changed",
--                          G_CALLBACK (pspp_sheet_view_model_sort_column_changed),
--                          tree_column);
--      
--      if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
--                                              &real_sort_column_id,
--                                              &real_order) &&
--        (real_sort_column_id == tree_column->sort_column_id))
--      {
--        pspp_sheet_view_column_set_sort_indicator (tree_column, TRUE);
--        pspp_sheet_view_column_set_sort_order (tree_column, real_order);
--      }
--      else 
--      {
--        pspp_sheet_view_column_set_sort_indicator (tree_column, FALSE);
--      }
--   }
--}
--
--
--/* Exported Private Functions.
-- * These should only be called by gtktreeview.c or gtktreeviewcolumn.c
-- */
--
--void
--_pspp_sheet_view_column_realize_button (PsppSheetViewColumn *column)
--{
--  GtkAllocation allocation;
--  PsppSheetView *tree_view;
--  GdkWindowAttr attr;
--  guint attributes_mask;
--  gboolean rtl;
--
--  tree_view = (PsppSheetView *)column->tree_view;
--  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (tree_view)));
--  g_return_if_fail (tree_view->priv->header_window != NULL);
--  if (!column->button)
--    return;
--
--  g_return_if_fail (column->button != NULL);
--
--  gtk_widget_set_parent_window (column->button, tree_view->priv->header_window);
--
--  if (column->visible)
--    gtk_widget_show (column->button);
--
--  attr.window_type = GDK_WINDOW_CHILD;
--  attr.wclass = GDK_INPUT_ONLY;
--  attr.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
--  attr.event_mask = gtk_widget_get_events (GTK_WIDGET (tree_view)) |
--                    (GDK_BUTTON_PRESS_MASK |
--                   GDK_BUTTON_RELEASE_MASK |
--                   GDK_POINTER_MOTION_MASK |
--                   GDK_POINTER_MOTION_HINT_MASK |
--                   GDK_KEY_PRESS_MASK);
--  attributes_mask = GDK_WA_CURSOR | GDK_WA_X | GDK_WA_Y;
--  attr.cursor = gdk_cursor_new_for_display (gdk_window_get_display (tree_view->priv->header_window),
--                                          GDK_SB_H_DOUBLE_ARROW);
--  attr.y = 0;
--  attr.width = TREE_VIEW_DRAG_WIDTH;
--  attr.height = tree_view->priv->header_height;
--  gtk_widget_get_allocation (column->button, &allocation);
--  attr.x = (allocation.x + (rtl ? 0 : allocation.width)) - TREE_VIEW_DRAG_WIDTH / 2;
--  column->window = gdk_window_new (tree_view->priv->header_window,
--                                 &attr, attributes_mask);
--  gdk_window_set_user_data (column->window, tree_view);
--
--  pspp_sheet_view_column_update_button (column);
--
--  g_object_unref (attr.cursor);
--}
--
--void
--_pspp_sheet_view_column_unrealize_button (PsppSheetViewColumn *column)
--{
--  g_return_if_fail (column != NULL);
--  if (column->window != NULL)
--    {
--      gdk_window_set_user_data (column->window, NULL);
--      gdk_window_destroy (column->window);
--      column->window = NULL;
--    }
--}
--
--void
--_pspp_sheet_view_column_unset_model (PsppSheetViewColumn *column,
--                                 GtkTreeModel      *old_model)
--{
--  if (column->sort_column_changed_signal)
--    {
--      g_signal_handler_disconnect (old_model,
--                                 column->sort_column_changed_signal);
--      column->sort_column_changed_signal = 0;
--    }
--  pspp_sheet_view_column_set_sort_indicator (column, FALSE);
--}
--
--void
--_pspp_sheet_view_column_set_tree_view (PsppSheetViewColumn *column,
--                                   PsppSheetView       *tree_view)
--{
--  g_assert (column->tree_view == NULL);
--
--  column->tree_view = GTK_WIDGET (tree_view);
--  pspp_sheet_view_column_create_button (column);
--
--  column->property_changed_signal =
--        g_signal_connect_swapped (tree_view,
--                                  "notify::model",
--                                  G_CALLBACK (pspp_sheet_view_column_setup_sort_column_id_callback),
--                                  column);
--
--  pspp_sheet_view_column_setup_sort_column_id_callback (column);
--}
--
--void
--_pspp_sheet_view_column_unset_tree_view (PsppSheetViewColumn *column)
--{
--  if (column->tree_view && column->button)
--    {
--      gtk_container_remove (GTK_CONTAINER (column->tree_view), column->button);
--    }
--  if (column->property_changed_signal)
--    {
--      g_signal_handler_disconnect (column->tree_view, column->property_changed_signal);
--      column->property_changed_signal = 0;
--    }
--
--  if (column->sort_column_changed_signal)
--    {
--      g_signal_handler_disconnect (pspp_sheet_view_get_model (PSPP_SHEET_VIEW (column->tree_view)),
--                                 column->sort_column_changed_signal);
--      column->sort_column_changed_signal = 0;
--    }
--
--  column->tree_view = NULL;
--  column->button = NULL;
--}
--
--gboolean
--_pspp_sheet_view_column_has_editable_cell (PsppSheetViewColumn *column)
--{
--  GList *list;
--
--  for (list = column->cell_list; list; list = list->next)
--    {
--      GtkCellRendererMode mode;
--      g_object_get (((PsppSheetViewColumnCellInfo *)list->data)->cell, "mode", &mode, NULL);
--      if (mode == GTK_CELL_RENDERER_MODE_EDITABLE)
--      return TRUE;
--    }
--
--  return FALSE;
--}
--
--/* gets cell being edited */
--GtkCellRenderer *
--_pspp_sheet_view_column_get_edited_cell (PsppSheetViewColumn *column)
--{
--  GList *list;
--
--  for (list = column->cell_list; list; list = list->next)
--    if (((PsppSheetViewColumnCellInfo *)list->data)->in_editing_mode)
--      return ((PsppSheetViewColumnCellInfo *)list->data)->cell;
--
--  return NULL;
--}
--
--gint
--_pspp_sheet_view_column_count_special_cells (PsppSheetViewColumn *column)
--{
--  gint i = 0;
--  GList *list;
--
--  for (list = column->cell_list; list; list = list->next)
--    {
--      PsppSheetViewColumnCellInfo *cellinfo = list->data;
--
--      GtkCellRendererMode mode;
--      g_object_get (cellinfo->cell, "mode", &mode, NULL);
--
--      if ((mode == GTK_CELL_RENDERER_MODE_EDITABLE ||
--        mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE) &&
--        gtk_cell_renderer_get_visible (cellinfo->cell))
--      i++;
--    }
--
--  return i;
--}
--
--GtkCellRenderer *
--_pspp_sheet_view_column_get_cell_at_pos (PsppSheetViewColumn *column,
--                                     gint               x)
--{
--  GList *list;
--  gint current_x = 0;
--
--  list = pspp_sheet_view_column_cell_first (column);
--  for (; list; list = pspp_sheet_view_column_cell_next (column, list))
--   {
--     PsppSheetViewColumnCellInfo *cellinfo = list->data;
--     if (current_x <= x && x <= current_x + cellinfo->real_width)
--       return cellinfo->cell;
--     current_x += cellinfo->real_width;
--   }
--
--  return NULL;
--}
--
--/* Public Functions */
--
--
--/**
-- * pspp_sheet_view_column_new:
-- * 
-- * Creates a new #PsppSheetViewColumn.
-- * 
-- * Return value: A newly created #PsppSheetViewColumn.
-- **/
--PsppSheetViewColumn *
--pspp_sheet_view_column_new (void)
--{
--  PsppSheetViewColumn *tree_column;
--
--  tree_column = g_object_new (PSPP_TYPE_SHEET_VIEW_COLUMN, NULL);
--
--  return tree_column;
--}
--
--/**
-- * pspp_sheet_view_column_new_with_attributes:
-- * @title: The title to set the header to.
-- * @cell: The #GtkCellRenderer.
-- * @Varargs: A %NULL-terminated list of attributes.
-- * 
-- * Creates a new #PsppSheetViewColumn with a number of default values.  This is
-- * equivalent to calling pspp_sheet_view_column_set_title(),
-- * pspp_sheet_view_column_pack_start(), and
-- * pspp_sheet_view_column_set_attributes() on the newly created #PsppSheetViewColumn.
-- *
-- * Here's a simple example:
-- * |[
-- *  enum { TEXT_COLUMN, COLOR_COLUMN, N_COLUMNS };
-- *  ...
-- *  {
-- *    PsppSheetViewColumn *column;
-- *    GtkCellRenderer   *renderer = gtk_cell_renderer_text_new ();
-- *  
-- *    column = pspp_sheet_view_column_new_with_attributes ("Title",
-- *                                                       renderer,
-- *                                                       "text", TEXT_COLUMN,
-- *                                                       "foreground", COLOR_COLUMN,
-- *                                                       NULL);
-- *  }
-- * ]|
-- * 
-- * Return value: A newly created #PsppSheetViewColumn.
-- **/
--PsppSheetViewColumn *
--pspp_sheet_view_column_new_with_attributes (const gchar     *title,
--                                        GtkCellRenderer *cell,
--                                        ...)
--{
--  PsppSheetViewColumn *retval;
--  va_list args;
--
--  retval = pspp_sheet_view_column_new ();
--
--  pspp_sheet_view_column_set_title (retval, title);
--  pspp_sheet_view_column_pack_start (retval, cell, TRUE);
--
--  va_start (args, cell);
--  pspp_sheet_view_column_set_attributesv (retval, cell, args);
--  va_end (args);
--
--  return retval;
--}
--
--static PsppSheetViewColumnCellInfo *
--pspp_sheet_view_column_get_cell_info (PsppSheetViewColumn *tree_column,
--                                  GtkCellRenderer   *cell_renderer)
--{
--  GList *list;
--  for (list = tree_column->cell_list; list; list = list->next)
--    if (((PsppSheetViewColumnCellInfo *)list->data)->cell == cell_renderer)
--      return (PsppSheetViewColumnCellInfo *) list->data;
--  return NULL;
--}
--
--
--/**
-- * pspp_sheet_view_column_pack_start:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @cell: The #GtkCellRenderer. 
-- * @expand: %TRUE if @cell is to be given extra space allocated to @tree_column.
-- *
-- * Packs the @cell into the beginning of the column. If @expand is %FALSE, then
-- * the @cell is allocated no more space than it needs. Any unused space is divided
-- * evenly between cells for which @expand is %TRUE.
-- **/
--void
--pspp_sheet_view_column_pack_start (PsppSheetViewColumn *tree_column,
--                               GtkCellRenderer   *cell,
--                               gboolean           expand)
--{
--  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (tree_column), cell, expand);
--}
--
--/**
-- * pspp_sheet_view_column_pack_end:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @cell: The #GtkCellRenderer. 
-- * @expand: %TRUE if @cell is to be given extra space allocated to @tree_column.
-- *
-- * Adds the @cell to end of the column. If @expand is %FALSE, then the @cell
-- * is allocated no more space than it needs. Any unused space is divided
-- * evenly between cells for which @expand is %TRUE.
-- **/
--void
--pspp_sheet_view_column_pack_end (PsppSheetViewColumn  *tree_column,
--                             GtkCellRenderer    *cell,
--                             gboolean            expand)
--{
--  gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (tree_column), cell, expand);
--}
--
--/**
-- * pspp_sheet_view_column_clear:
-- * @tree_column: A #PsppSheetViewColumn
-- * 
-- * Unsets all the mappings on all renderers on the @tree_column.
-- **/
--void
--pspp_sheet_view_column_clear (PsppSheetViewColumn *tree_column)
--{
--  gtk_cell_layout_clear (GTK_CELL_LAYOUT (tree_column));
--}
--
--static GList *
--pspp_sheet_view_column_cell_layout_get_cells (GtkCellLayout *layout)
--{
--  PsppSheetViewColumn *tree_column = PSPP_SHEET_VIEW_COLUMN (layout);
--  GList *retval = NULL, *list;
--
--  g_return_val_if_fail (tree_column != NULL, NULL);
--
--  for (list = tree_column->cell_list; list; list = list->next)
--    {
--      PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *)list->data;
--
--      retval = g_list_append (retval, info->cell);
--    }
--
--  return retval;
--}
--
--/**
-- * pspp_sheet_view_column_get_cell_renderers:
-- * @tree_column: A #PsppSheetViewColumn
-- *
-- * Returns a newly-allocated #GList of all the cell renderers in the column,
-- * in no particular order.  The list must be freed with g_list_free().
-- *
-- * Return value: A list of #GtkCellRenderers
-- *
-- * Deprecated: 2.18: use gtk_cell_layout_get_cells() instead.
-- **/
--GList *
--pspp_sheet_view_column_get_cell_renderers (PsppSheetViewColumn *tree_column)
--{
--  return pspp_sheet_view_column_cell_layout_get_cells (GTK_CELL_LAYOUT (tree_column));
--}
--
--/**
-- * pspp_sheet_view_column_add_attribute:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @cell_renderer: the #GtkCellRenderer to set attributes on
-- * @attribute: An attribute on the renderer
-- * @column: The column position on the model to get the attribute from.
-- * 
-- * Adds an attribute mapping to the list in @tree_column.  The @column is the
-- * column of the model to get a value from, and the @attribute is the
-- * parameter on @cell_renderer to be set from the value. So for example
-- * if column 2 of the model contains strings, you could have the
-- * "text" attribute of a #GtkCellRendererText get its values from
-- * column 2.
-- **/
--void
--pspp_sheet_view_column_add_attribute (PsppSheetViewColumn *tree_column,
--                                  GtkCellRenderer   *cell_renderer,
--                                  const gchar       *attribute,
--                                  gint               column)
--{
--  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (tree_column),
--                                 cell_renderer, attribute, column);
--}
--
--static void
--pspp_sheet_view_column_set_attributesv (PsppSheetViewColumn *tree_column,
--                                    GtkCellRenderer   *cell_renderer,
--                                    va_list            args)
--{
--  gchar *attribute;
--  gint column;
--
--  attribute = va_arg (args, gchar *);
--
--  pspp_sheet_view_column_clear_attributes (tree_column, cell_renderer);
--  
--  while (attribute != NULL)
--    {
--      column = va_arg (args, gint);
--      pspp_sheet_view_column_add_attribute (tree_column, cell_renderer, attribute, column);
--      attribute = va_arg (args, gchar *);
--    }
--}
--
--/**
-- * pspp_sheet_view_column_set_attributes:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @cell_renderer: the #GtkCellRenderer we're setting the attributes of
-- * @Varargs: A %NULL-terminated list of attributes.
-- * 
-- * Sets the attributes in the list as the attributes of @tree_column.
-- * The attributes should be in attribute/column order, as in
-- * pspp_sheet_view_column_add_attribute(). All existing attributes
-- * are removed, and replaced with the new attributes.
-- **/
--void
--pspp_sheet_view_column_set_attributes (PsppSheetViewColumn *tree_column,
--                                   GtkCellRenderer   *cell_renderer,
--                                   ...)
--{
--  va_list args;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--  g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
--  g_return_if_fail (pspp_sheet_view_column_get_cell_info (tree_column, cell_renderer));
--
--  va_start (args, cell_renderer);
--  pspp_sheet_view_column_set_attributesv (tree_column, cell_renderer, args);
--  va_end (args);
--}
--
--
--/**
-- * pspp_sheet_view_column_set_cell_data_func:
-- * @tree_column: A #PsppSheetViewColumn
-- * @cell_renderer: A #GtkCellRenderer
-- * @func: The #PsppSheetViewColumnFunc to use. 
-- * @func_data: The user data for @func.
-- * @destroy: The destroy notification for @func_data
-- * 
-- * Sets the #PsppSheetViewColumnFunc to use for the column.  This
-- * function is used instead of the standard attributes mapping for
-- * setting the column value, and should set the value of @tree_column's
-- * cell renderer as appropriate.  @func may be %NULL to remove an
-- * older one.
-- **/
--void
--pspp_sheet_view_column_set_cell_data_func (PsppSheetViewColumn   *tree_column,
--                                       GtkCellRenderer     *cell_renderer,
--                                       PsppSheetCellDataFunc  func,
--                                       gpointer             func_data,
--                                       GDestroyNotify       destroy)
--{
--  gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (tree_column),
--                                      cell_renderer,
--                                      (GtkCellLayoutDataFunc)func,
--                                      func_data, destroy);
--}
--
--
--/**
-- * pspp_sheet_view_column_clear_attributes:
-- * @tree_column: a #PsppSheetViewColumn
-- * @cell_renderer: a #GtkCellRenderer to clear the attribute mapping on.
-- * 
-- * Clears all existing attributes previously set with
-- * pspp_sheet_view_column_set_attributes().
-- **/
--void
--pspp_sheet_view_column_clear_attributes (PsppSheetViewColumn *tree_column,
--                                     GtkCellRenderer   *cell_renderer)
--{
--  gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (tree_column),
--                                    cell_renderer);
--}
--
--/**
-- * pspp_sheet_view_column_set_spacing:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @spacing: distance between cell renderers in pixels.
-- * 
-- * Sets the spacing field of @tree_column, which is the number of pixels to
-- * place between cell renderers packed into it.
-- **/
--void
--pspp_sheet_view_column_set_spacing (PsppSheetViewColumn *tree_column,
--                                gint               spacing)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--  g_return_if_fail (spacing >= 0);
--
--  if (tree_column->spacing == spacing)
--    return;
--
--  tree_column->spacing = spacing;
--  if (tree_column->tree_view)
--    _pspp_sheet_view_column_cell_set_dirty (tree_column);
--}
--
--/**
-- * pspp_sheet_view_column_get_spacing:
-- * @tree_column: A #PsppSheetViewColumn.
-- * 
-- * Returns the spacing of @tree_column.
-- * 
-- * Return value: the spacing of @tree_column.
-- **/
--gint
--pspp_sheet_view_column_get_spacing (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), 0);
--
--  return tree_column->spacing;
--}
--
--/* Options for manipulating the columns */
--
--/**
-- * pspp_sheet_view_column_set_visible:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @visible: %TRUE if the @tree_column is visible.
-- * 
-- * Sets the visibility of @tree_column.
-- **/
--void
--pspp_sheet_view_column_set_visible (PsppSheetViewColumn *tree_column,
--                                gboolean           visible)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  visible = !! visible;
--  
--  if (tree_column->visible == visible)
--    return;
--
--  tree_column->visible = visible;
--
--  if (tree_column->visible)
--    _pspp_sheet_view_column_cell_set_dirty (tree_column);
--
--  pspp_sheet_view_column_update_button (tree_column);
--  g_object_notify (G_OBJECT (tree_column), "visible");
--}
--
--/**
-- * pspp_sheet_view_column_get_visible:
-- * @tree_column: A #PsppSheetViewColumn.
-- * 
-- * Returns %TRUE if @tree_column is visible.
-- * 
-- * Return value: whether the column is visible or not.  If it is visible, then
-- * the tree will show the column.
-- **/
--gboolean
--pspp_sheet_view_column_get_visible (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  return tree_column->visible;
--}
--
--/**
-- * pspp_sheet_view_column_set_resizable:
-- * @tree_column: A #PsppSheetViewColumn
-- * @resizable: %TRUE, if the column can be resized
-- * 
-- * If @resizable is %TRUE, then the user can explicitly resize the column by
-- * grabbing the outer edge of the column button.
-- **/
--void
--pspp_sheet_view_column_set_resizable (PsppSheetViewColumn *tree_column,
--                                  gboolean           resizable)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  resizable = !! resizable;
--
--  if (tree_column->resizable == resizable)
--    return;
--
--  tree_column->resizable = resizable;
--
--  pspp_sheet_view_column_update_button (tree_column);
--
--  g_object_notify (G_OBJECT (tree_column), "resizable");
--}
--
--/**
-- * pspp_sheet_view_column_get_resizable:
-- * @tree_column: A #PsppSheetViewColumn
-- * 
-- * Returns %TRUE if the @tree_column can be resized by the end user.
-- * 
-- * Return value: %TRUE, if the @tree_column can be resized.
-- **/
--gboolean
--pspp_sheet_view_column_get_resizable (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  return tree_column->resizable;
--}
--
--
--/**
-- * pspp_sheet_view_column_get_width:
-- * @tree_column: A #PsppSheetViewColumn.
-- * 
-- * Returns the current size of @tree_column in pixels.
-- * 
-- * Return value: The current width of @tree_column.
-- **/
--gint
--pspp_sheet_view_column_get_width (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), 0);
--
--  return tree_column->width;
--}
--
--/**
-- * pspp_sheet_view_column_set_fixed_width:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @fixed_width: The size to set @tree_column to. Must be greater than 0.
-- * 
-- * Sets the size of the column in pixels.  The size of the column is clamped to
-- * the min/max width for the column.  Please note that the min/max width of the
-- * column doesn't actually affect the "fixed_width" property of the widget, just
-- * the actual size when displayed.
-- **/
--void
--pspp_sheet_view_column_set_fixed_width (PsppSheetViewColumn *tree_column,
--                                    gint               fixed_width)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--  g_return_if_fail (fixed_width > 0);
--
--  tree_column->fixed_width = fixed_width;
--  tree_column->use_resized_width = FALSE;
--
--  if (tree_column->tree_view &&
--      gtk_widget_get_realized (tree_column->tree_view))
--    {
--      gtk_widget_queue_resize (tree_column->tree_view);
--    }
--
--  g_object_notify (G_OBJECT (tree_column), "fixed-width");
--}
--
--/**
-- * pspp_sheet_view_column_get_fixed_width:
-- * @tree_column: a #PsppSheetViewColumn
-- * 
-- * Gets the fixed width of the column.  This value is only meaning may not be
-- * the actual width of the column on the screen, just what is requested.
-- * 
-- * Return value: the fixed width of the column
-- **/
--gint
--pspp_sheet_view_column_get_fixed_width (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), 0);
--
--  return tree_column->fixed_width;
--}
--
--/**
-- * pspp_sheet_view_column_set_min_width:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @min_width: The minimum width of the column in pixels, or -1.
-- * 
-- * Sets the minimum width of the @tree_column.  If @min_width is -1, then the
-- * minimum width is unset.
-- **/
--void
--pspp_sheet_view_column_set_min_width (PsppSheetViewColumn *tree_column,
--                                  gint               min_width)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--  g_return_if_fail (min_width >= -1);
--
--  if (min_width == tree_column->min_width)
--    return;
--
--  if (tree_column->visible &&
--      tree_column->tree_view != NULL &&
--      gtk_widget_get_realized (tree_column->tree_view))
--    {
--      if (min_width > tree_column->width)
--      gtk_widget_queue_resize (tree_column->tree_view);
--    }
--
--  tree_column->min_width = min_width;
--  g_object_freeze_notify (G_OBJECT (tree_column));
--  if (tree_column->max_width != -1 && tree_column->max_width < min_width)
--    {
--      tree_column->max_width = min_width;
--      g_object_notify (G_OBJECT (tree_column), "max-width");
--    }
--  g_object_notify (G_OBJECT (tree_column), "min-width");
--  g_object_thaw_notify (G_OBJECT (tree_column));
--}
--
--/**
-- * pspp_sheet_view_column_get_min_width:
-- * @tree_column: A #PsppSheetViewColumn.
-- * 
-- * Returns the minimum width in pixels of the @tree_column, or -1 if no minimum
-- * width is set.
-- * 
-- * Return value: The minimum width of the @tree_column.
-- **/
--gint
--pspp_sheet_view_column_get_min_width (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), -1);
--
--  return tree_column->min_width;
--}
--
--/**
-- * pspp_sheet_view_column_set_max_width:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @max_width: The maximum width of the column in pixels, or -1.
-- * 
-- * Sets the maximum width of the @tree_column.  If @max_width is -1, then the
-- * maximum width is unset.  Note, the column can actually be wider than max
-- * width if it's the last column in a view.  In this case, the column expands to
-- * fill any extra space.
-- **/
--void
--pspp_sheet_view_column_set_max_width (PsppSheetViewColumn *tree_column,
--                                  gint               max_width)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--  g_return_if_fail (max_width >= -1);
--
--  if (max_width == tree_column->max_width)
--    return;
--
--  if (tree_column->visible &&
--      tree_column->tree_view != NULL &&
--      gtk_widget_get_realized (tree_column->tree_view))
--    {
--      if (max_width != -1 && max_width < tree_column->width)
--      gtk_widget_queue_resize (tree_column->tree_view);
--    }
--
--  tree_column->max_width = max_width;
--  g_object_freeze_notify (G_OBJECT (tree_column));
--  if (max_width != -1 && max_width < tree_column->min_width)
--    {
--      tree_column->min_width = max_width;
--      g_object_notify (G_OBJECT (tree_column), "min-width");
--    }
--  g_object_notify (G_OBJECT (tree_column), "max-width");
--  g_object_thaw_notify (G_OBJECT (tree_column));
--}
--
--/**
-- * pspp_sheet_view_column_get_max_width:
-- * @tree_column: A #PsppSheetViewColumn.
-- * 
-- * Returns the maximum width in pixels of the @tree_column, or -1 if no maximum
-- * width is set.
-- * 
-- * Return value: The maximum width of the @tree_column.
-- **/
--gint
--pspp_sheet_view_column_get_max_width (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), -1);
--
--  return tree_column->max_width;
--}
--
--/**
-- * pspp_sheet_view_column_clicked:
-- * @tree_column: a #PsppSheetViewColumn
-- * 
-- * Emits the "clicked" signal on the column.  This function will only work if
-- * @tree_column is clickable.
-- **/
--void
--pspp_sheet_view_column_clicked (PsppSheetViewColumn *tree_column)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  if (tree_column->visible &&
--      tree_column->button &&
--      tree_column->clickable)
--    gtk_button_clicked (GTK_BUTTON (tree_column->button));
--}
--
--/**
-- * pspp_sheet_view_column_set_title:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @title: The title of the @tree_column.
-- * 
-- * Sets the title of the @tree_column.  If a custom widget has been set, then
-- * this value is ignored.
-- **/
--void
--pspp_sheet_view_column_set_title (PsppSheetViewColumn *tree_column,
--                              const gchar       *title)
--{
--  gchar *new_title;
--  
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  new_title = g_strdup (title);
--  g_free (tree_column->title);
--  tree_column->title = new_title;
--
--  pspp_sheet_view_column_update_button (tree_column);
--  g_object_notify (G_OBJECT (tree_column), "title");
--}
--
--/**
-- * pspp_sheet_view_column_get_title:
-- * @tree_column: A #PsppSheetViewColumn.
-- * 
-- * Returns the title of the widget.
-- * 
-- * Return value: the title of the column. This string should not be
-- * modified or freed.
-- **/
--const gchar *
--pspp_sheet_view_column_get_title (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), NULL);
--
--  return tree_column->title;
--}
--
--/**
-- * pspp_sheet_view_column_set_expand:
-- * @tree_column: A #PsppSheetViewColumn
-- * @expand: %TRUE if the column should take available extra space, %FALSE if not
-- * 
-- * Sets the column to take available extra space.  This space is shared equally
-- * amongst all columns that have the expand set to %TRUE.  If no column has this
-- * option set, then the last column gets all extra space.  By default, every
-- * column is created with this %FALSE.
-- *
-- * Since: 2.4
-- **/
--void
--pspp_sheet_view_column_set_expand (PsppSheetViewColumn *tree_column,
--                               gboolean           expand)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  expand = !!expand;
--  if (tree_column->expand == expand)
--    return;
--  tree_column->expand = expand;
--
--  if (tree_column->visible &&
--      tree_column->tree_view != NULL &&
--      gtk_widget_get_realized (tree_column->tree_view))
--    {
--      /* We want to continue using the original width of the
--       * column that includes additional space added by the user
--       * resizing the columns and possibly extra (expanded) space, which
--       * are not included in the resized width.
--       */
--      tree_column->use_resized_width = FALSE;
--
--      gtk_widget_queue_resize (tree_column->tree_view);
--    }
--
--  g_object_notify (G_OBJECT (tree_column), "expand");
--}
--
--/**
-- * pspp_sheet_view_column_get_expand:
-- * @tree_column: a #PsppSheetViewColumn
-- * 
-- * Return %TRUE if the column expands to take any available space.
-- * 
-- * Return value: %TRUE, if the column expands
-- *
-- * Since: 2.4
-- **/
--gboolean
--pspp_sheet_view_column_get_expand (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  return tree_column->expand;
--}
--
--/**
-- * pspp_sheet_view_column_set_clickable:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @clickable: %TRUE if the header is active.
-- * 
-- * Sets the header to be active if @active is %TRUE.  When the header is active,
-- * then it can take keyboard focus, and can be clicked.
-- **/
--void
--pspp_sheet_view_column_set_clickable (PsppSheetViewColumn *tree_column,
--                                    gboolean           clickable)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  clickable = !! clickable;
--  if (tree_column->clickable == clickable)
--    return;
--
--  tree_column->clickable = clickable;
--  pspp_sheet_view_column_update_button (tree_column);
--  g_object_notify (G_OBJECT (tree_column), "clickable");
--}
--
--/**
-- * pspp_sheet_view_column_get_clickable:
-- * @tree_column: a #PsppSheetViewColumn
-- * 
-- * Returns %TRUE if the user can click on the header for the column.
-- * 
-- * Return value: %TRUE if user can click the column header.
-- **/
--gboolean
--pspp_sheet_view_column_get_clickable (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  return tree_column->clickable;
--}
--
--/**
-- * pspp_sheet_view_column_set_widget:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @widget: (allow-none): A child #GtkWidget, or %NULL.
-- *
-- * Sets the widget in the header to be @widget.  If widget is %NULL, then the
-- * header button is set with a #GtkLabel set to the title of @tree_column.
-- **/
--void
--pspp_sheet_view_column_set_widget (PsppSheetViewColumn *tree_column,
--                               GtkWidget         *widget)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--  g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
--
--  if (widget)
--    g_object_ref_sink (widget);
--
--  if (tree_column->child)      
--    g_object_unref (tree_column->child);
--
--  tree_column->child = widget;
--  pspp_sheet_view_column_update_button (tree_column);
--  g_object_notify (G_OBJECT (tree_column), "widget");
--}
--
--/**
-- * pspp_sheet_view_column_get_widget:
-- * @tree_column: A #PsppSheetViewColumn.
-- * 
-- * Returns the #GtkWidget in the button on the column header.  If a custom
-- * widget has not been set then %NULL is returned.
-- * 
-- * Return value: The #GtkWidget in the column header, or %NULL
-- **/
--GtkWidget *
--pspp_sheet_view_column_get_widget (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), NULL);
--
--  return tree_column->child;
--}
--
--/**
-- * pspp_sheet_view_column_set_alignment:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @xalign: The alignment, which is between [0.0 and 1.0] inclusive.
-- * 
-- * Sets the alignment of the title or custom widget inside the column header.
-- * The alignment determines its location inside the button.
-- **/
--void
--pspp_sheet_view_column_set_alignment (PsppSheetViewColumn *tree_column,
--                                    GtkAlign  xalign)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--
--  if (tree_column->halign == xalign)
--    return;
--
--  tree_column->halign = xalign;
--  pspp_sheet_view_column_update_button (tree_column);
--  g_object_notify (G_OBJECT (tree_column), "alignment");
--}
--
--/**
-- * pspp_sheet_view_column_get_alignment:
-- * @tree_column: A #PsppSheetViewColumn.
-- * 
-- * Returns the current x alignment of @tree_column.
-- * 
-- * Return value: The current alignent of @tree_column.
-- **/
--GtkAlign
--pspp_sheet_view_column_get_alignment (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), GTK_ALIGN_CENTER);
--
--  return tree_column->halign;
--}
--
--
--/**
-- * pspp_sheet_view_column_set_reorderable:
-- * @tree_column: A #PsppSheetViewColumn
-- * @reorderable: %TRUE, if the column can be reordered.
-- * 
-- * If @reorderable is %TRUE, then the column can be reordered by the end user
-- * dragging the header.
-- **/
--void
--pspp_sheet_view_column_set_reorderable (PsppSheetViewColumn *tree_column,
--                                    gboolean           reorderable)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  /*  if (reorderable)
--      pspp_sheet_view_column_set_clickable (tree_column, TRUE);*/
--
--  reorderable = !!reorderable;
--  if (tree_column->reorderable == reorderable)
--    return;
--
--  tree_column->reorderable = reorderable;
--  pspp_sheet_view_column_update_button (tree_column);
--  g_object_notify (G_OBJECT (tree_column), "reorderable");
--}
--
--/**
-- * pspp_sheet_view_column_get_reorderable:
-- * @tree_column: A #PsppSheetViewColumn
-- * 
-- * Returns %TRUE if the @tree_column can be reordered by the user.
-- * 
-- * Return value: %TRUE if the @tree_column can be reordered by the user.
-- **/
--gboolean
--pspp_sheet_view_column_get_reorderable (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  return tree_column->reorderable;
--}
--
--/**
-- * pspp_sheet_view_column_set_quick_edit:
-- * @tree_column: A #PsppSheetViewColumn
-- * @quick_edit: If true, editing starts upon the first click in the column.  If
-- * false, the first click selects the column and a second click is needed to
-- * begin editing.  This has no effect on cells that are not editable.
-- **/
--void
--pspp_sheet_view_column_set_quick_edit (PsppSheetViewColumn *tree_column,
--                                    gboolean           quick_edit)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  quick_edit = !!quick_edit;
--  if (tree_column->quick_edit != quick_edit)
--    {
--      tree_column->quick_edit = quick_edit;
--      g_object_notify (G_OBJECT (tree_column), "quick-edit");
--    }
--}
--
--/**
-- * pspp_sheet_view_column_get_quick_edit:
-- * @tree_column: A #PsppSheetViewColumn
-- *
-- * Returns %TRUE if editing starts upon the first click in the column.  Returns
-- * %FALSE, the first click selects the column and a second click is needed to
-- * begin editing.  This is not meaningful for cells that are not editable.
-- *
-- * Return value: %TRUE if editing starts upon the first click.
-- **/
--gboolean
--pspp_sheet_view_column_get_quick_edit (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  return tree_column->quick_edit;
--}
--
--
--/**
-- * pspp_sheet_view_column_set_selected:
-- * @tree_column: A #PsppSheetViewColumn
-- * @selected: If true, the column is selected as part of a rectangular
-- * selection.
-- **/
--void
--pspp_sheet_view_column_set_selected (PsppSheetViewColumn *tree_column,
--                                    gboolean           selected)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  selected = !!selected;
--  if (tree_column->selected != selected)
--    {
--      PsppSheetSelection *selection;
--      PsppSheetView *sheet_view;
--
--      if (tree_column->tree_view != NULL)
--        gtk_widget_queue_draw (GTK_WIDGET (tree_column->tree_view));
--      tree_column->selected = selected;
--      g_object_notify (G_OBJECT (tree_column), "selected");
--
--      sheet_view = PSPP_SHEET_VIEW (pspp_sheet_view_column_get_tree_view (
--                                      tree_column));
--      selection = pspp_sheet_view_get_selection (sheet_view);
--      _pspp_sheet_selection_emit_changed (selection);
--    }
--}
--
--/**
-- * pspp_sheet_view_column_get_selected:
-- * @tree_column: A #PsppSheetViewColumn
-- *
-- * Returns %TRUE if the column is selected as part of a rectangular
-- * selection.
-- *
-- * Return value: %TRUE if the column is selected as part of a rectangular
-- * selection.
-- **/
--gboolean
--pspp_sheet_view_column_get_selected (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  return tree_column->selected;
--}
--
--/**
-- * pspp_sheet_view_column_set_selectable:
-- * @tree_column: A #PsppSheetViewColumn
-- * @selectable: If true, the column may be selected as part of a rectangular
-- * selection.
-- **/
--void
--pspp_sheet_view_column_set_selectable (PsppSheetViewColumn *tree_column,
--                                    gboolean           selectable)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  selectable = !!selectable;
--  if (tree_column->selectable != selectable)
--    {
--      if (tree_column->tree_view != NULL)
--        gtk_widget_queue_draw (GTK_WIDGET (tree_column->tree_view));
--      tree_column->selectable = selectable;
--      g_object_notify (G_OBJECT (tree_column), "selectable");
--    }
--}
--
--/**
-- * pspp_sheet_view_column_get_selectable:
-- * @tree_column: A #PsppSheetViewColumn
-- *
-- * Returns %TRUE if the column may be selected as part of a rectangular
-- * selection.
-- *
-- * Return value: %TRUE if the column may be selected as part of a rectangular
-- * selection.
-- **/
--gboolean
--pspp_sheet_view_column_get_selectable (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  return tree_column->selectable;
--}
--
--
--/**
-- * pspp_sheet_view_column_set_row_head:
-- * @tree_column: A #PsppSheetViewColumn
-- * @row_head: If true, the column is a "row head", analogous to a column head.
-- * See the description of the row-head property for more information.
-- **/
--void
--pspp_sheet_view_column_set_row_head (PsppSheetViewColumn *tree_column,
--                                    gboolean           row_head)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  row_head = !!row_head;
--  if (tree_column->row_head != row_head)
--    {
--      tree_column->row_head = row_head;
--      g_object_notify (G_OBJECT (tree_column), "row_head");
--    }
--}
--
--/**
-- * pspp_sheet_view_column_get_row_head:
-- * @tree_column: A #PsppSheetViewColumn
-- *
-- * Returns %TRUE if the column is a row head.
-- *
-- * Return value: %TRUE if the column is a row head.
-- **/
--gboolean
--pspp_sheet_view_column_get_row_head (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  return tree_column->row_head;
--}
--
--
--/**
-- * pspp_sheet_view_column_set_tabbable:
-- * @tree_column: A #PsppSheetViewColumn
-- * @tabbable: If true, the column is "tabbable", meaning that Tab and Shift+Tab
-- * in the sheet visit this column.  If false, Tab and Shift+Tab skip this
-- * column.
-- **/
--void
--pspp_sheet_view_column_set_tabbable (PsppSheetViewColumn *tree_column,
--                                     gboolean           tabbable)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  tabbable = !!tabbable;
--  if (tree_column->tabbable != tabbable)
--    {
--      tree_column->tabbable = tabbable;
--      g_object_notify (G_OBJECT (tree_column), "tabbable");
--    }
--}
--
--/**
-- * pspp_sheet_view_column_get_tabbable:
-- * @tree_column: A #PsppSheetViewColumn
-- *
-- * Returns %TRUE if the column is tabbable.
-- *
-- * Return value: %TRUE if the column is tabbable.
-- **/
--gboolean
--pspp_sheet_view_column_get_tabbable (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  return tree_column->tabbable;
--}
--
--
--/**
-- * pspp_sheet_view_column_set_sort_column_id:
-- * @tree_column: a #PsppSheetViewColumn
-- * @sort_column_id: The @sort_column_id of the model to sort on.
-- *
-- * Sets the logical @sort_column_id that this column sorts on when this column 
-- * is selected for sorting.  Doing so makes the column header clickable.
-- **/
--void
--pspp_sheet_view_column_set_sort_column_id (PsppSheetViewColumn *tree_column,
--                                       gint               sort_column_id)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--  g_return_if_fail (sort_column_id >= -1);
--
--  if (tree_column->sort_column_id == sort_column_id)
--    return;
--
--  tree_column->sort_column_id = sort_column_id;
--
--  /* Handle unsetting the id */
--  if (sort_column_id == -1)
--    {
--      GtkTreeModel *model = pspp_sheet_view_get_model (PSPP_SHEET_VIEW (tree_column->tree_view));
--
--      if (tree_column->sort_clicked_signal)
--      {
--        g_signal_handler_disconnect (tree_column, tree_column->sort_clicked_signal);
--        tree_column->sort_clicked_signal = 0;
--      }
--
--      if (tree_column->sort_column_changed_signal)
--      {
--        g_signal_handler_disconnect (model, tree_column->sort_column_changed_signal);
--        tree_column->sort_column_changed_signal = 0;
--      }
--
--      pspp_sheet_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
--      pspp_sheet_view_column_set_sort_indicator (tree_column, FALSE);
--      pspp_sheet_view_column_set_clickable (tree_column, FALSE);
--      g_object_notify (G_OBJECT (tree_column), "sort-column-id");
--      return;
--    }
--
--  pspp_sheet_view_column_set_clickable (tree_column, TRUE);
--
--  if (! tree_column->sort_clicked_signal)
--    tree_column->sort_clicked_signal = g_signal_connect (tree_column,
--                                                         "clicked",
--                                                         G_CALLBACK (pspp_sheet_view_column_sort),
--                                                         NULL);
--
--  pspp_sheet_view_column_setup_sort_column_id_callback (tree_column);
--  g_object_notify (G_OBJECT (tree_column), "sort-column-id");
--}
--
--/**
-- * pspp_sheet_view_column_get_sort_column_id:
-- * @tree_column: a #PsppSheetViewColumn
-- *
-- * Gets the logical @sort_column_id that the model sorts on when this
-- * column is selected for sorting.
-- * See pspp_sheet_view_column_set_sort_column_id().
-- *
-- * Return value: the current @sort_column_id for this column, or -1 if
-- *               this column can't be used for sorting.
-- **/
--gint
--pspp_sheet_view_column_get_sort_column_id (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), 0);
--
--  return tree_column->sort_column_id;
--}
--
--/**
-- * pspp_sheet_view_column_set_sort_indicator:
-- * @tree_column: a #PsppSheetViewColumn
-- * @setting: %TRUE to display an indicator that the column is sorted
-- *
-- * Call this function with a @setting of %TRUE to display an arrow in
-- * the header button indicating the column is sorted. Call
-- * pspp_sheet_view_column_set_sort_order() to change the direction of
-- * the arrow.
-- * 
-- **/
--void
--pspp_sheet_view_column_set_sort_indicator (PsppSheetViewColumn     *tree_column,
--                                         gboolean               setting)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  setting = setting != FALSE;
--
--  if (setting == tree_column->show_sort_indicator)
--    return;
--
--  tree_column->show_sort_indicator = setting;
--  pspp_sheet_view_column_update_button (tree_column);
--  g_object_notify (G_OBJECT (tree_column), "sort-indicator");
--}
--
--/**
-- * pspp_sheet_view_column_get_sort_indicator:
-- * @tree_column: a #PsppSheetViewColumn
-- * 
-- * Gets the value set by pspp_sheet_view_column_set_sort_indicator().
-- * 
-- * Return value: whether the sort indicator arrow is displayed
-- **/
--gboolean
--pspp_sheet_view_column_get_sort_indicator  (PsppSheetViewColumn     *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  return tree_column->show_sort_indicator;
--}
--
--/**
-- * pspp_sheet_view_column_set_sort_order:
-- * @tree_column: a #PsppSheetViewColumn
-- * @order: sort order that the sort indicator should indicate
-- *
-- * Changes the appearance of the sort indicator. 
-- * 
-- * This <emphasis>does not</emphasis> actually sort the model.  Use
-- * pspp_sheet_view_column_set_sort_column_id() if you want automatic sorting
-- * support.  This function is primarily for custom sorting behavior, and should
-- * be used in conjunction with gtk_tree_sortable_set_sort_column() to do
-- * that. For custom models, the mechanism will vary. 
-- * 
-- * The sort indicator changes direction to indicate normal sort or reverse sort.
-- * Note that you must have the sort indicator enabled to see anything when 
-- * calling this function; see pspp_sheet_view_column_set_sort_indicator().
-- **/
--void
--pspp_sheet_view_column_set_sort_order      (PsppSheetViewColumn     *tree_column,
--                                          GtkSortType            order)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  if (order == tree_column->sort_order)
--    return;
--
--  tree_column->sort_order = order;
--  pspp_sheet_view_column_update_button (tree_column);
--  g_object_notify (G_OBJECT (tree_column), "sort-order");
--}
--
--/**
-- * pspp_sheet_view_column_get_sort_order:
-- * @tree_column: a #PsppSheetViewColumn
-- * 
-- * Gets the value set by pspp_sheet_view_column_set_sort_order().
-- * 
-- * Return value: the sort order the sort indicator is indicating
-- **/
--GtkSortType
--pspp_sheet_view_column_get_sort_order      (PsppSheetViewColumn     *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), 0);
--
--  return tree_column->sort_order;
--}
--
--/**
-- * pspp_sheet_view_column_cell_set_cell_data:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
-- * @iter: The #GtkTreeIter to to get the cell renderer's attributes from.
-- * 
-- * Sets the cell renderer based on the @tree_model and @iter.  That is, for
-- * every attribute mapping in @tree_column, it will get a value from the set
-- * column on the @iter, and use that value to set the attribute on the cell
-- * renderer.  This is used primarily by the #PsppSheetView.
-- **/
--void
--pspp_sheet_view_column_cell_set_cell_data (PsppSheetViewColumn *tree_column,
--                                       GtkTreeModel      *tree_model,
--                                       GtkTreeIter       *iter)
--{
--  GSList *list;
--  GValue value = { 0, };
--  GList *cell_list;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  if (tree_model == NULL)
--    return;
--
--  for (cell_list = tree_column->cell_list; cell_list; cell_list = cell_list->next)
--    {
--      PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) cell_list->data;
--      GObject *cell = (GObject *) info->cell;
--
--      list = info->attributes;
--
--      g_object_freeze_notify (cell);
--
--      while (list && list->next)
--      {
--        gtk_tree_model_get_value (tree_model, iter,
--                                  GPOINTER_TO_INT (list->next->data),
--                                  &value);
--        g_object_set_property (cell, (gchar *) list->data, &value);
--        g_value_unset (&value);
--        list = list->next->next;
--      }
--
--      if (info->func)
--      (* info->func) (tree_column, info->cell, tree_model, iter, info->func_data);
--      g_object_thaw_notify (G_OBJECT (info->cell));
--    }
--
--}
--
--/**
-- * pspp_sheet_view_column_cell_get_size:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @cell_area: (allow-none): The area a cell in the column will be allocated, or %NULL
-- * @x_offset: (allow-none): location to return x offset of a cell relative to @cell_area, or %NULL
-- * @y_offset: (allow-none): location to return y offset of a cell relative to @cell_area, or %NULL
-- * @width: (allow-none): location to return width needed to render a cell, or %NULL
-- * @height: (allow-none): location to return height needed to render a cell, or %NULL
-- * 
-- * Obtains the width and height needed to render the column.  This is used
-- * primarily by the #PsppSheetView.
-- **/
--void
--pspp_sheet_view_column_cell_get_size (PsppSheetViewColumn  *tree_column,
--                                  const GdkRectangle *cell_area,
--                                  gint               *x_offset,
--                                  gint               *y_offset,
--                                  gint               *width,
--                                  gint               *height)
--{
--  GList *list;
--  gboolean first_cell = TRUE;
--  gint focus_line_width;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  if (height)
--    * height = 0;
--  if (width)
--    * width = 0;
--
--  gtk_widget_style_get (tree_column->tree_view, "focus-line-width", &focus_line_width, NULL);
--  
--  for (list = tree_column->cell_list; list; list = list->next)
--    {
--      PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) list->data;
--      gboolean visible;
--      gint new_height = 0;
--      gint new_width = 0;
--      g_object_get (info->cell, "visible", &visible, NULL);
--
--      if (visible == FALSE)
--      continue;
--
--      if (first_cell == FALSE && width)
--      *width += tree_column->spacing;
--
--      gtk_cell_renderer_get_padding (info->cell, x_offset, y_offset);
--      gtk_cell_renderer_get_preferred_width (info->cell, tree_column->tree_view,
--                                           NULL, &new_width);
--
--      gtk_cell_renderer_get_preferred_height (info->cell, tree_column->tree_view,
--                                            NULL, &new_height);
--
--
--      if (height)
--      * height = MAX (*height, new_height + focus_line_width * 2);
--      info->requested_width = MAX (info->requested_width, new_width + focus_line_width * 2);
--      if (width)
--      * width += info->requested_width;
--      first_cell = FALSE;
--    }
--}
--
--/* rendering, event handling and rendering focus are somewhat complicated, and
-- * quite a bit of code.  Rather than duplicate them, we put them together to
-- * keep the code in one place.
-- *
-- * To better understand what's going on, check out
-- * docs/tree-column-sizing.png
-- */
--enum {
--  CELL_ACTION_RENDER,
--  CELL_ACTION_FOCUS,
--  CELL_ACTION_EVENT
--};
--
--static gboolean
--pspp_sheet_view_column_cell_process_action (PsppSheetViewColumn  *tree_column,
--                                          cairo_t *cr,
--                                        const GdkRectangle *background_area,
--                                        const GdkRectangle *cell_area,
--                                        guint               flags,
--                                        gint                action,
--                                        GdkRectangle       *focus_rectangle, /* FOCUS  */
--                                        GtkCellEditable   **editable_widget, /* EVENT  */
--                                        GdkEvent           *event,           /* EVENT  */
--                                        gchar              *path_string)     /* EVENT  */
--{
--  GList *list;
--  GdkRectangle real_cell_area;
--  GdkRectangle real_background_area;
--  gint depth = 0;
--  gint expand_cell_count = 0;
--  gint full_requested_width = 0;
--  gint extra_space;
--  gint min_x, min_y, max_x, max_y;
--  gint focus_line_width;
--  gint special_cells;
--  gint horizontal_separator;
--  gboolean cursor_row = FALSE;
--  gboolean first_cell = TRUE;
--  gboolean rtl;
--  /* If we have rtl text, we need to transform our areas */
--  GdkRectangle rtl_cell_area;
--  GdkRectangle rtl_background_area;
--
--  min_x = G_MAXINT;
--  min_y = G_MAXINT;
--  max_x = 0;
--  max_y = 0;
--
--  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_column->tree_view)) == GTK_TEXT_DIR_RTL);
--  special_cells = _pspp_sheet_view_column_count_special_cells (tree_column);
--
--  if (special_cells > 1 && action == CELL_ACTION_FOCUS)
--    {
--      PsppSheetViewColumnCellInfo *info = NULL;
--      gboolean found_has_focus = FALSE;
--
--      /* one should have focus */
--      for (list = tree_column->cell_list; list; list = list->next)
--        {
--        info = list->data;
--        if (info && info->has_focus)
--          {
--            found_has_focus = TRUE;
--            break;
--          }
--      }
--
--      if (!found_has_focus)
--        {
--        /* give the first one focus */
--        info = pspp_sheet_view_column_cell_first (tree_column)->data;
--        info->has_focus = TRUE;
--      }
--    }
--
--  cursor_row = flags & GTK_CELL_RENDERER_FOCUSED;
--
--  gtk_widget_style_get (GTK_WIDGET (tree_column->tree_view),
--                      "focus-line-width", &focus_line_width,
--                      "horizontal-separator", &horizontal_separator,
--                      NULL);
--
--  real_cell_area = *cell_area;
--  real_background_area = *background_area;
--
--
--  real_cell_area.x += focus_line_width;
--  real_cell_area.y += focus_line_width;
--  real_cell_area.height -= 2 * focus_line_width;
--
--  if (rtl)
--    depth = real_background_area.width - real_cell_area.width;
--  else
--    depth = real_cell_area.x - real_background_area.x;
--
--  /* Find out how much extra space we have to allocate */
--  for (list = tree_column->cell_list; list; list = list->next)
--    {
--      PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *)list->data;
--
--      if (! gtk_cell_renderer_get_visible (info->cell))
--      continue;
--
--      if (info->expand == TRUE)
--      expand_cell_count ++;
--      full_requested_width += info->requested_width;
--
--      if (!first_cell)
--      full_requested_width += tree_column->spacing;
--
--      first_cell = FALSE;
--    }
--
--  extra_space = cell_area->width - full_requested_width;
--  if (extra_space < 0)
--    extra_space = 0;
--  else if (extra_space > 0 && expand_cell_count > 0)
--    extra_space /= expand_cell_count;
--
--  /* iterate list for GTK_PACK_START cells */
--  for (list = tree_column->cell_list; list; list = list->next)
--    {
--      PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) list->data;
--
--      if (info->pack == GTK_PACK_END)
--      continue;
--
--      if (! gtk_cell_renderer_get_visible (info->cell))
--      continue;
--
--      if ((info->has_focus || special_cells == 1) && cursor_row)
--      flags |= GTK_CELL_RENDERER_FOCUSED;
--      else
--        flags &= ~GTK_CELL_RENDERER_FOCUSED;
--
--      info->real_width = info->requested_width + (info->expand?extra_space:0);
--
--      /* We constrain ourselves to only the width available */
--      if (real_cell_area.x - focus_line_width + info->real_width > cell_area->x + cell_area->width)
--      {
--        info->real_width = cell_area->x + cell_area->width - real_cell_area.x;
--      }   
--
--      if (real_cell_area.x > cell_area->x + cell_area->width)
--      break;
--
--      real_cell_area.width = info->real_width;
--      real_cell_area.width -= 2 * focus_line_width;
--
--      if (list->next)
--      {
--        real_background_area.width = info->real_width + depth;
--      }
--      else
--      {
--          /* fill the rest of background for the last cell */
--        real_background_area.width = background_area->x + background_area->width - real_background_area.x;
--      }
--
--      rtl_cell_area = real_cell_area;
--      rtl_background_area = real_background_area;
--      
--      if (rtl)
--      {
--        rtl_cell_area.x = cell_area->x + cell_area->width - (real_cell_area.x - cell_area->x) - real_cell_area.width;
--        rtl_background_area.x = background_area->x + background_area->width - (real_background_area.x - background_area->x) - real_background_area.width;
--      }
--
--      /* RENDER */
--      if (action == CELL_ACTION_RENDER)
--      {
--        gtk_cell_renderer_render (info->cell,
--                                  cr,
--                                  tree_column->tree_view,
--                                  &rtl_background_area,
--                                  &rtl_cell_area,
--                                  flags);
--      }
--      /* FOCUS */
--      else if (action == CELL_ACTION_FOCUS)
--      {
--        gint x_offset, y_offset, width, height;
--
--        gtk_cell_renderer_get_preferred_height (info->cell, tree_column->tree_view,
--                                                NULL, &height);
--
--        gtk_cell_renderer_get_preferred_width (info->cell, tree_column->tree_view,
--                                                NULL, &width);
--
--
--        gtk_cell_renderer_get_padding (info->cell,
--                                       &x_offset, &y_offset);
--
--        if (special_cells > 1)
--          {
--            if (info->has_focus)
--              {
--                min_x = rtl_cell_area.x + x_offset;
--                max_x = min_x + width;
--                min_y = rtl_cell_area.y + y_offset;
--                max_y = min_y + height;
--              }
--          }
--        else
--          {
--            if (min_x > (rtl_cell_area.x + x_offset))
--              min_x = rtl_cell_area.x + x_offset;
--            if (max_x < rtl_cell_area.x + x_offset + width)
--              max_x = rtl_cell_area.x + x_offset + width;
--            if (min_y > (rtl_cell_area.y + y_offset))
--              min_y = rtl_cell_area.y + y_offset;
--            if (max_y < rtl_cell_area.y + y_offset + height)
--              max_y = rtl_cell_area.y + y_offset + height;
--          }
--      }
--      /* EVENT */
--      else if (action == CELL_ACTION_EVENT)
--      {
--        gboolean try_event = FALSE;
--
--        if (event)
--          {
--            if (special_cells == 1)
--              {
--                /* only 1 activatable cell -> whole column can activate */
--                if (cell_area->x <= ((GdkEventButton *)event)->x &&
--                    cell_area->x + cell_area->width > ((GdkEventButton *)event)->x)
--                  try_event = TRUE;
--              }
--            else if (rtl_cell_area.x <= ((GdkEventButton *)event)->x &&
--                rtl_cell_area.x + rtl_cell_area.width > ((GdkEventButton *)event)->x)
--                /* only activate cell if the user clicked on an individual
--                 * cell
--                 */
--              try_event = TRUE;
--          }
--        else if (special_cells > 1 && info->has_focus)
--          try_event = TRUE;
--        else if (special_cells == 1)
--          try_event = TRUE;
--
--        if (try_event)
--          {
--            gboolean visible, mode;
--
--            g_object_get (info->cell,
--                          "visible", &visible,
--                          "mode", &mode,
--                          NULL);
--            if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
--              {
--                if (gtk_cell_renderer_activate (info->cell,
--                                                event,
--                                                tree_column->tree_view,
--                                                path_string,
--                                                &rtl_background_area,
--                                                &rtl_cell_area,
--                                                flags))
--                  {
--                      flags &= ~GTK_CELL_RENDERER_FOCUSED;
--                    return TRUE;
--                  }
--              }
--            else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
--              {
--                *editable_widget =
--                  gtk_cell_renderer_start_editing (info->cell,
--                                                   event,
--                                                   tree_column->tree_view,
--                                                   path_string,
--                                                   &rtl_background_area,
--                                                   &rtl_cell_area,
--                                                   flags);
--
--                if (*editable_widget != NULL)
--                  {
--                    g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
--                    info->in_editing_mode = TRUE;
--                    pspp_sheet_view_column_focus_cell (tree_column, info->cell);
--                    
--                      flags &= ~GTK_CELL_RENDERER_FOCUSED;
--
--                    return TRUE;
--                  }
--              }
--          }
--      }
--
--      flags &= ~GTK_CELL_RENDERER_FOCUSED;
--
--      real_cell_area.x += (real_cell_area.width + 2 * focus_line_width + tree_column->spacing);
--      real_background_area.x += real_background_area.width + tree_column->spacing;
--
--      /* Only needed for first cell */
--      depth = 0;
--    }
--
--  /* iterate list for PACK_END cells */
--  for (list = g_list_last (tree_column->cell_list); list; list = list->prev)
--    {
--      PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) list->data;
--
--      if (info->pack == GTK_PACK_START)
--      continue;
--
--      if (! gtk_cell_renderer_get_visible (info->cell))
--      continue;
--
--      if ((info->has_focus || special_cells == 1) && cursor_row)
--      flags |= GTK_CELL_RENDERER_FOCUSED;
--      else
--        flags &= ~GTK_CELL_RENDERER_FOCUSED;
--
--      info->real_width = info->requested_width + (info->expand?extra_space:0);
--
--      /* We constrain ourselves to only the width available */
--      if (real_cell_area.x - focus_line_width + info->real_width > cell_area->x + cell_area->width)
--      {
--        info->real_width = cell_area->x + cell_area->width - real_cell_area.x;
--      }   
--
--      if (real_cell_area.x > cell_area->x + cell_area->width)
--      break;
--
--      real_cell_area.width = info->real_width;
--      real_cell_area.width -= 2 * focus_line_width;
--      real_background_area.width = info->real_width + depth;
--
--      rtl_cell_area = real_cell_area;
--      rtl_background_area = real_background_area;
--      if (rtl)
--      {
--        rtl_cell_area.x = cell_area->x + cell_area->width - (real_cell_area.x - cell_area->x) - real_cell_area.width;
--        rtl_background_area.x = background_area->x + background_area->width - (real_background_area.x - background_area->x) - real_background_area.width;
--      }
--
--      /* RENDER */
--      if (action == CELL_ACTION_RENDER)
--      {
--        gtk_cell_renderer_render (info->cell,
--                                  cr,
--                                  tree_column->tree_view,
--                                  &rtl_background_area,
--                                  &rtl_cell_area,
--                                  flags);
--      }
--      /* FOCUS */
--      else if (action == CELL_ACTION_FOCUS)
--      {
--        gint x_offset, y_offset, width, height;
--
--        gtk_cell_renderer_get_preferred_height (info->cell, tree_column->tree_view,
--                                                NULL, &height);
--
--        gtk_cell_renderer_get_preferred_width (info->cell, tree_column->tree_view,
--                                                NULL, &width);
--
--
--        gtk_cell_renderer_get_padding (info->cell,
--                                       &x_offset, &y_offset);
--
--        if (special_cells > 1)
--          {
--            if (info->has_focus)
--              {
--                min_x = rtl_cell_area.x + x_offset;
--                max_x = min_x + width;
--                min_y = rtl_cell_area.y + y_offset;
--                max_y = min_y + height;
--              }
--          }
--        else
--          {
--            if (min_x > (rtl_cell_area.x + x_offset))
--              min_x = rtl_cell_area.x + x_offset;
--            if (max_x < rtl_cell_area.x + x_offset + width)
--              max_x = rtl_cell_area.x + x_offset + width;
--            if (min_y > (rtl_cell_area.y + y_offset))
--              min_y = rtl_cell_area.y + y_offset;
--            if (max_y < rtl_cell_area.y + y_offset + height)
--              max_y = rtl_cell_area.y + y_offset + height;
--          }
--      }
--      /* EVENT */
--      else if (action == CELL_ACTION_EVENT)
--        {
--        gboolean try_event = FALSE;
--
--        if (event)
--          {
--            if (special_cells == 1)
--              {
--                /* only 1 activatable cell -> whole column can activate */
--                if (cell_area->x <= ((GdkEventButton *)event)->x &&
--                    cell_area->x + cell_area->width > ((GdkEventButton *)event)->x)
--                  try_event = TRUE;
--              }
--            else if (rtl_cell_area.x <= ((GdkEventButton *)event)->x &&
--                rtl_cell_area.x + rtl_cell_area.width > ((GdkEventButton *)event)->x)
--              /* only activate cell if the user clicked on an individual
--               * cell
--               */
--              try_event = TRUE;
--          }
--        else if (special_cells > 1 && info->has_focus)
--          try_event = TRUE;
--        else if (special_cells == 1)
--          try_event = TRUE;
--
--        if (try_event)
--          {
--            gboolean visible, mode;
--
--            g_object_get (info->cell,
--                          "visible", &visible,
--                          "mode", &mode,
--                          NULL);
--            if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
--              {
--                if (gtk_cell_renderer_activate (info->cell,
--                                                event,
--                                                tree_column->tree_view,
--                                                path_string,
--                                                &rtl_background_area,
--                                                &rtl_cell_area,
--                                                flags))
--                  {
--                    flags &= ~GTK_CELL_RENDERER_FOCUSED;
--                    return TRUE;
--                  }
--              }
--            else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
--              {
--                *editable_widget =
--                  gtk_cell_renderer_start_editing (info->cell,
--                                                   event,
--                                                   tree_column->tree_view,
--                                                   path_string,
--                                                   &rtl_background_area,
--                                                   &rtl_cell_area,
--                                                   flags);
--
--                if (*editable_widget != NULL)
--                  {
--                    g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
--                    info->in_editing_mode = TRUE;
--                    pspp_sheet_view_column_focus_cell (tree_column, info->cell);
--
--                    flags &= ~GTK_CELL_RENDERER_FOCUSED;
--                    return TRUE;
--                  }
--              }
--          }
--      }
--
--      flags &= ~GTK_CELL_RENDERER_FOCUSED;
--
--      real_cell_area.x += (real_cell_area.width + 2 * focus_line_width + tree_column->spacing);
--      real_background_area.x += (real_background_area.width + tree_column->spacing);
--
--      /* Only needed for first cell */
--      depth = 0;
--    }
--
--  /* fill focus_rectangle when required */
--  if (action == CELL_ACTION_FOCUS)
--    {
--      if (min_x >= max_x || min_y >= max_y)
--      {
--        *focus_rectangle = *cell_area;
--        /* don't change the focus_rectangle, just draw it nicely inside
--         * the cell area */
--      }
--      else
--      {
--        focus_rectangle->x = min_x - focus_line_width;
--        focus_rectangle->y = min_y - focus_line_width;
--        focus_rectangle->width = (max_x - min_x) + 2 * focus_line_width;
--        focus_rectangle->height = (max_y - min_y) + 2 * focus_line_width;
--      }
--    }
--
--  return FALSE;
--}
--
--/**
-- * pspp_sheet_view_column_cell_render:
-- * @tree_column: A #PsppSheetViewColumn.
-- * @window: a #GdkDrawable to draw to
-- * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
-- * @cell_area: area normally rendered by a cell renderer
-- * @flags: flags that affect rendering
-- * 
-- * Renders the cell contained by #tree_column. This is used primarily by the
-- * #PsppSheetView.
-- **/
--void
--_pspp_sheet_view_column_cell_render (PsppSheetViewColumn  *tree_column,
--                                   cairo_t *cr,
--                                 const GdkRectangle *background_area,
--                                 const GdkRectangle *cell_area,
--                                 guint               flags)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--  g_return_if_fail (background_area != NULL);
--  g_return_if_fail (cell_area != NULL);
--
--  pspp_sheet_view_column_cell_process_action (tree_column,
--                                            cr,
--                                          background_area,
--                                          cell_area,
--                                          flags,
--                                          CELL_ACTION_RENDER,
--                                          NULL, NULL, NULL, NULL);
--}
--
--gboolean
--_pspp_sheet_view_column_cell_event (PsppSheetViewColumn  *tree_column,
--                                GtkCellEditable   **editable_widget,
--                                GdkEvent           *event,
--                                gchar              *path_string,
--                                const GdkRectangle *background_area,
--                                const GdkRectangle *cell_area,
--                                guint               flags)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  return pspp_sheet_view_column_cell_process_action (tree_column,
--                                                 NULL,
--                                                 background_area,
--                                                 cell_area,
--                                                 flags,
--                                                 CELL_ACTION_EVENT,
--                                                 NULL,
--                                                 editable_widget,
--                                                 event,
--                                                 path_string);
--}
--
--void
--_pspp_sheet_view_column_get_focus_area (PsppSheetViewColumn  *tree_column,
--                                    const GdkRectangle *background_area,
--                                    const GdkRectangle *cell_area,
--                                    GdkRectangle       *focus_area)
--{
--  pspp_sheet_view_column_cell_process_action (tree_column,
--                                          NULL,
--                                          background_area,
--                                          cell_area,
--                                          0,
--                                          CELL_ACTION_FOCUS,
--                                          focus_area,
--                                          NULL, NULL, NULL);
--}
--
--
--/* cell list manipulation */
--static GList *
--pspp_sheet_view_column_cell_first (PsppSheetViewColumn *tree_column)
--{
--  GList *list = tree_column->cell_list;
--
--  /* first GTK_PACK_START cell we find */
--  for ( ; list; list = list->next)
--    {
--      PsppSheetViewColumnCellInfo *info = list->data;
--      if (info->pack == GTK_PACK_START)
--      return list;
--    }
--
--  /* hmm, else the *last* GTK_PACK_END cell */
--  list = g_list_last (tree_column->cell_list);
--
--  for ( ; list; list = list->prev)
--    {
--      PsppSheetViewColumnCellInfo *info = list->data;
--      if (info->pack == GTK_PACK_END)
--      return list;
--    }
--
--  return NULL;
--}
--
--static GList *
--pspp_sheet_view_column_cell_last (PsppSheetViewColumn *tree_column)
--{
--  GList *list = tree_column->cell_list;
--
--  /* *first* GTK_PACK_END cell we find */
--  for ( ; list ; list = list->next)
--    {
--      PsppSheetViewColumnCellInfo *info = list->data;
--      if (info->pack == GTK_PACK_END)
--      return list;
--    }
--
--  /* hmm, else the last GTK_PACK_START cell */
--  list = g_list_last (tree_column->cell_list);
--
--  for ( ; list; list = list->prev)
--    {
--      PsppSheetViewColumnCellInfo *info = list->data;
--      if (info->pack == GTK_PACK_START)
--      return list;
--    }
--
--  return NULL;
--}
--
--
--static GList *
--pspp_sheet_view_column_cell_next (PsppSheetViewColumn *tree_column,
--                              GList             *current)
--{
--  GList *list;
--  PsppSheetViewColumnCellInfo *info = current->data;
--
--  if (info->pack == GTK_PACK_START)
--    {
--      for (list = current->next; list; list = list->next)
--        {
--        PsppSheetViewColumnCellInfo *inf = list->data;
--        if (inf->pack == GTK_PACK_START)
--          return list;
--      }
--
--      /* out of GTK_PACK_START cells, get *last* GTK_PACK_END one */
--      list = g_list_last (tree_column->cell_list);
--      for (; list; list = list->prev)
--        {
--        PsppSheetViewColumnCellInfo *inf = list->data;
--        if (inf->pack == GTK_PACK_END)
--          return list;
--      }
--    }
--
--  for (list = current->prev; list; list = list->prev)
--    {
--      PsppSheetViewColumnCellInfo *inf = list->data;
--      if (inf->pack == GTK_PACK_END)
--      return list;
--    }
--
--  return NULL;
--}
--
--static GList *
--pspp_sheet_view_column_cell_prev (PsppSheetViewColumn *tree_column,
--                              GList             *current)
--{
--  GList *list;
--  PsppSheetViewColumnCellInfo *info = current->data;
--
--  if (info->pack == GTK_PACK_END)
--    {
--      for (list = current->next; list; list = list->next)
--        {
--        PsppSheetViewColumnCellInfo *inf = list->data;
--        if (inf->pack == GTK_PACK_END)
--          return list;
--      }
--
--      /* out of GTK_PACK_END, get last GTK_PACK_START one */
--      list = g_list_last (tree_column->cell_list);
--      for ( ; list; list = list->prev)
--        {
--        PsppSheetViewColumnCellInfo *inf = list->data;
--        if (inf->pack == GTK_PACK_START)
--          return list;
--      }
--    }
--
--  for (list = current->prev; list; list = list->prev)
--    {
--      PsppSheetViewColumnCellInfo *inf = list->data;
--      if (inf->pack == GTK_PACK_START)
--      return list;
--    }
--
--  return NULL;
--}
--
--gboolean
--_pspp_sheet_view_column_cell_focus (PsppSheetViewColumn *tree_column,
--                                gint               direction,
--                                gboolean           left,
--                                gboolean           right)
--{
--  gint count;
--  gboolean rtl;
--
--  count = _pspp_sheet_view_column_count_special_cells (tree_column);
--  rtl = gtk_widget_get_direction (GTK_WIDGET (tree_column->tree_view)) == GTK_TEXT_DIR_RTL;
--
--  /* if we are the current focus column and have multiple editable cells,
--   * try to select the next one, else move the focus to the next column
--   */
--  if (PSPP_SHEET_VIEW (tree_column->tree_view)->priv->focus_column == tree_column)
--    {
--      if (count > 1)
--        {
--          GList *next, *prev;
--        GList *list = tree_column->cell_list;
--        PsppSheetViewColumnCellInfo *info = NULL;
--
--        /* find current focussed cell */
--        for ( ; list; list = list->next)
--          {
--            info = list->data;
--            if (info->has_focus)
--              break;
--          }
--
--        /* not a focussed cell in the focus column? */
--        if (!list || !info || !info->has_focus)
--          return FALSE;
--
--        if (rtl)
--          {
--            prev = pspp_sheet_view_column_cell_next (tree_column, list);
--            next = pspp_sheet_view_column_cell_prev (tree_column, list);
--          }
--        else
--          {
--            next = pspp_sheet_view_column_cell_next (tree_column, list);
--            prev = pspp_sheet_view_column_cell_prev (tree_column, list);
--          }
--
--        info->has_focus = FALSE;
--        if (direction > 0 && next)
--          {
--            info = next->data;
--            info->has_focus = TRUE;
--            return TRUE;
--          }
--        else if (direction > 0 && !next && !right)
--          {
--            /* keep focus on last cell */
--            if (rtl)
--              info = pspp_sheet_view_column_cell_first (tree_column)->data;
--            else
--              info = pspp_sheet_view_column_cell_last (tree_column)->data;
--
--            info->has_focus = TRUE;
--            return TRUE;
--          }
--        else if (direction < 0 && prev)
--          {
--            info = prev->data;
--            info->has_focus = TRUE;
--            return TRUE;
--          }
--        else if (direction < 0 && !prev && !left)
--          {
--            /* keep focus on first cell */
--            if (rtl)
--              info = pspp_sheet_view_column_cell_last (tree_column)->data;
--            else
--              info = pspp_sheet_view_column_cell_first (tree_column)->data;
--
--            info->has_focus = TRUE;
--            return TRUE;
--          }
--      }
--      return FALSE;
--    }
--
--  /* we get focus, if we have multiple editable cells, give the correct one
--   * focus
--   */
--  if (count > 1)
--    {
--      GList *list = tree_column->cell_list;
--
--      /* clear focus first */
--      for ( ; list ; list = list->next)
--        {
--        PsppSheetViewColumnCellInfo *info = list->data;
--        if (info->has_focus)
--          info->has_focus = FALSE;
--      }
--
--      list = NULL;
--      if (rtl)
--        {
--        if (direction > 0)
--          list = pspp_sheet_view_column_cell_last (tree_column);
--        else if (direction < 0)
--          list = pspp_sheet_view_column_cell_first (tree_column);
--      }
--      else
--        {
--        if (direction > 0)
--          list = pspp_sheet_view_column_cell_first (tree_column);
--        else if (direction < 0)
--          list = pspp_sheet_view_column_cell_last (tree_column);
--      }
--
--      if (list)
--      ((PsppSheetViewColumnCellInfo *) list->data)->has_focus = TRUE;
--    }
--
--  return TRUE;
--}
--
--void
--_pspp_sheet_view_column_cell_draw_focus (PsppSheetViewColumn  *tree_column,
--                                       cairo_t *cr,
--                                     const GdkRectangle *background_area,
--                                     const GdkRectangle *cell_area,
--                                     guint               flags)
--{
--  gint focus_line_width;
--  GtkStateType cell_state;
--  
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--  gtk_widget_style_get (GTK_WIDGET (tree_column->tree_view),
--                      "focus-line-width", &focus_line_width, NULL);
--  if (tree_column->editable_widget)
--    {
--      /* This function is only called on the editable row when editing.
--       */
--#if 0
--      gtk_paint_focus (tree_column->tree_view->style,
--                     window,
--                     gtk_widget_get_state (tree_column->tree_view),
--                     NULL,
--                     tree_column->tree_view,
--                     "treeview",
--                     cell_area->x - focus_line_width,
--                     cell_area->y - focus_line_width,
--                     cell_area->width + 2 * focus_line_width,
--                     cell_area->height + 2 * focus_line_width);
--#endif      
--    }
--  else
--    {
--      GdkRectangle focus_rectangle;
--      pspp_sheet_view_column_cell_process_action (tree_column,
--                                                cr,
--                                              background_area,
--                                              cell_area,
--                                              flags,
--                                              CELL_ACTION_FOCUS,
--                                              &focus_rectangle,
--                                              NULL, NULL, NULL);
--
--      cell_state = flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
--            (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
--            (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL));
--
--      gtk_paint_focus (gtk_widget_get_style (GTK_WIDGET (tree_column->tree_view)),
--                     cr,
--                     cell_state,
--                     tree_column->tree_view,
--                     "treeview",
--                     focus_rectangle.x,
--                     focus_rectangle.y,
--                     focus_rectangle.width,
--                     focus_rectangle.height);
--    }
--}
--
--/**
-- * pspp_sheet_view_column_cell_is_visible:
-- * @tree_column: A #PsppSheetViewColumn
-- * 
-- * Returns %TRUE if any of the cells packed into the @tree_column are visible.
-- * For this to be meaningful, you must first initialize the cells with
-- * pspp_sheet_view_column_cell_set_cell_data()
-- * 
-- * Return value: %TRUE, if any of the cells packed into the @tree_column are currently visible
-- **/
--gboolean
--pspp_sheet_view_column_cell_is_visible (PsppSheetViewColumn *tree_column)
--{
--  GList *list;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), FALSE);
--
--  for (list = tree_column->cell_list; list; list = list->next)
--    {
--      PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) list->data;
--
--      if (gtk_cell_renderer_get_visible (info->cell))
--      return TRUE;
--    }
--
--  return FALSE;
--}
--
--/**
-- * pspp_sheet_view_column_focus_cell:
-- * @tree_column: A #PsppSheetViewColumn
-- * @cell: A #GtkCellRenderer
-- *
-- * Sets the current keyboard focus to be at @cell, if the column contains
-- * 2 or more editable and activatable cells.
-- *
-- * Since: 2.2
-- **/
--void
--pspp_sheet_view_column_focus_cell (PsppSheetViewColumn *tree_column,
--                               GtkCellRenderer   *cell)
--{
--  GList *list;
--  gboolean found_cell = FALSE;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--  g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
--
--  if (_pspp_sheet_view_column_count_special_cells (tree_column) < 2)
--    return;
--
--  for (list = tree_column->cell_list; list; list = list->next)
--    {
--      PsppSheetViewColumnCellInfo *info = list->data;
--
--      if (info->cell == cell)
--        {
--        info->has_focus = TRUE;
--        found_cell = TRUE;
--        break;
--      }
--    }
--
--  if (found_cell)
--    {
--      for (list = tree_column->cell_list; list; list = list->next)
--        {
--        PsppSheetViewColumnCellInfo *info = list->data;
--
--        if (info->cell != cell)
--          info->has_focus = FALSE;
--        }
--
--      /* FIXME: redraw? */
--    }
--}
--
--void
--_pspp_sheet_view_column_cell_set_dirty (PsppSheetViewColumn *tree_column)
--{
--  GList *list;
--
--  for (list = tree_column->cell_list; list; list = list->next)
--    {
--      PsppSheetViewColumnCellInfo *info = (PsppSheetViewColumnCellInfo *) list->data;
--
--      info->requested_width = 0;
--    }
--  tree_column->dirty = TRUE;
--  tree_column->requested_width = -1;
--  tree_column->width = 0;
--
--  if (tree_column->tree_view &&
--      PSPP_SHEET_VIEW (tree_column->tree_view)->priv->resized &&
--      gtk_widget_get_realized (tree_column->tree_view))
--    {
--      PSPP_SHEET_VIEW (tree_column->tree_view)->priv->resized = FALSE;
--      _pspp_sheet_view_install_mark_rows_col_dirty (PSPP_SHEET_VIEW (tree_column->tree_view));
--      gtk_widget_queue_resize (tree_column->tree_view);
--    }
--}
--
--void
--_pspp_sheet_view_column_start_editing (PsppSheetViewColumn *tree_column,
--                                   GtkCellEditable   *cell_editable)
--{
--  g_return_if_fail (tree_column->editable_widget == NULL);
--
--  tree_column->editable_widget = cell_editable;
--}
--
--void
--_pspp_sheet_view_column_stop_editing (PsppSheetViewColumn *tree_column)
--{
--  GList *list;
--
--  g_return_if_fail (tree_column->editable_widget != NULL);
--
--  tree_column->editable_widget = NULL;
--  for (list = tree_column->cell_list; list; list = list->next)
--    ((PsppSheetViewColumnCellInfo *)list->data)->in_editing_mode = FALSE;
--}
--
--void
--_pspp_sheet_view_column_get_neighbor_sizes (PsppSheetViewColumn *column,
--                                        GtkCellRenderer   *cell,
--                                        gint              *left,
--                                        gint              *right)
--{
--  GList *list;
--  PsppSheetViewColumnCellInfo *info;
--  gint l, r;
--  gboolean rtl;
--
--  l = r = 0;
--
--  list = pspp_sheet_view_column_cell_first (column);  
--
--  while (list)
--    {
--      info = (PsppSheetViewColumnCellInfo *)list->data;
--      
--      list = pspp_sheet_view_column_cell_next (column, list);
--
--      if (info->cell == cell)
--      break;
--      
--      if (gtk_cell_renderer_get_visible (info->cell))
--      l += info->real_width + column->spacing;
--    }
--
--  while (list)
--    {
--      info = (PsppSheetViewColumnCellInfo *)list->data;
--      
--      list = pspp_sheet_view_column_cell_next (column, list);
--
--      if (gtk_cell_renderer_get_visible (info->cell))
--      r += info->real_width + column->spacing;
--    }
--
--  rtl = (gtk_widget_get_direction (GTK_WIDGET (column->tree_view)) == GTK_TEXT_DIR_RTL);
--  if (left)
--    *left = rtl ? r : l;
--
--  if (right)
--    *right = rtl ? l : r;
--}
--
--/**
-- * pspp_sheet_view_column_cell_get_position:
-- * @tree_column: a #PsppSheetViewColumn
-- * @cell_renderer: a #GtkCellRenderer
-- * @start_pos: return location for the horizontal position of @cell within
-- *            @tree_column, may be %NULL
-- * @width: return location for the width of @cell, may be %NULL
-- *
-- * Obtains the horizontal position and size of a cell in a column. If the
-- * cell is not found in the column, @start_pos and @width are not changed and
-- * %FALSE is returned.
-- * 
-- * Return value: %TRUE if @cell belongs to @tree_column.
-- */
--gboolean
--pspp_sheet_view_column_cell_get_position (PsppSheetViewColumn *tree_column,
--                                      GtkCellRenderer   *cell_renderer,
--                                      gint              *start_pos,
--                                      gint              *width)
--{
--  GList *list;
--  gint current_x = 0;
--  gboolean found_cell = FALSE;
--  PsppSheetViewColumnCellInfo *cellinfo = NULL;
--
--  list = pspp_sheet_view_column_cell_first (tree_column);
--  for (; list; list = pspp_sheet_view_column_cell_next (tree_column, list))
--    {
--      cellinfo = list->data;
--      if (cellinfo->cell == cell_renderer)
--        {
--          found_cell = TRUE;
--          break;
--        }
--
--      if (gtk_cell_renderer_get_visible (cellinfo->cell))
--        current_x += cellinfo->real_width;
--    }
--
--  if (found_cell)
--    {
--      if (start_pos)
--        *start_pos = current_x;
--      if (width)
--        *width = cellinfo->real_width;
--    }
--
--  return found_cell;
--}
--
--/**
-- * pspp_sheet_view_column_queue_resize:
-- * @tree_column: A #PsppSheetViewColumn
-- *
-- * Flags the column, and the cell renderers added to this column, to have
-- * their sizes renegotiated.
-- *
-- * Since: 2.8
-- **/
--void
--pspp_sheet_view_column_queue_resize (PsppSheetViewColumn *tree_column)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column));
--
--  if (tree_column->tree_view)
--    _pspp_sheet_view_column_cell_set_dirty (tree_column);
--}
--
--/**
-- * pspp_sheet_view_column_get_tree_view:
-- * @tree_column: A #PsppSheetViewColumn
-- *
-- * Returns the #PsppSheetView wherein @tree_column has been inserted.  If
-- * @column is currently not inserted in any tree view, %NULL is
-- * returned.
-- *
-- * Return value: The tree view wherein @column has been inserted if any,
-- *               %NULL otherwise.
-- *
-- * Since: 2.12
-- */
--GtkWidget *
--pspp_sheet_view_column_get_tree_view (PsppSheetViewColumn *tree_column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (tree_column), NULL);
--
--  return tree_column->tree_view;
--}
--
--typedef struct {
--  GtkCellLayout   *cell_layout;
--  GtkCellRenderer *renderer;
--  gchar           *attr_name;
--} AttributesSubParserData;
--
--static void
--attributes_start_element (GMarkupParseContext *context,
--                          const gchar         *element_name,
--                          const gchar        **names,
--                          const gchar        **values,
--                          gpointer             user_data,
--                          GError             **error)
--{
--  AttributesSubParserData *parser_data = (AttributesSubParserData*)user_data;
--  guint i;
--
--  if (strcmp (element_name, "attribute") == 0)
--    {
--      for (i = 0; names[i]; i++)
--        if (strcmp (names[i], "name") == 0)
--          parser_data->attr_name = g_strdup (values[i]);
--    }
--  else if (strcmp (element_name, "attributes") == 0)
--    return;
--  else
--    g_warning ("Unsupported tag for GtkCellLayout: %s\n", element_name);
--}
--
--static void
--attributes_text_element (GMarkupParseContext *context,
--                         const gchar         *text,
--                         gsize                text_len,
--                         gpointer             user_data,
--                         GError             **error)
--{
--  AttributesSubParserData *parser_data = (AttributesSubParserData*)user_data;
--  glong l;
--  gchar *endptr;
--  gchar *string;
--  
--  if (!parser_data->attr_name)
--    return;
--
--  errno = 0;
--  string = g_strndup (text, text_len);
--  l = strtol (string, &endptr, 0);
--  if (errno || endptr == string)
--    {
--      g_set_error (error, 
--                   GTK_BUILDER_ERROR,
--                   GTK_BUILDER_ERROR_INVALID_VALUE,
--                   "Could not parse integer `%s'",
--                   string);
--      g_free (string);
--      return;
--    }
--  g_free (string);
--
--  gtk_cell_layout_add_attribute (parser_data->cell_layout,
--                                 parser_data->renderer,
--                                 parser_data->attr_name, l);
--  g_free (parser_data->attr_name);
--  parser_data->attr_name = NULL;
--}
--
--static const GMarkupParser attributes_parser =
--  {
--    attributes_start_element,
--    NULL,
--    attributes_text_element,
--  };
--
--static gboolean
--_cell_layout_buildable_custom_tag_start (GtkBuildable  *buildable,
--                                             GtkBuilder    *builder,
--                                             GObject       *child,
--                                             const gchar   *tagname,
--                                             GMarkupParser *parser,
--                                             gpointer      *data)
--{
--  AttributesSubParserData *parser_data;
--
--  if (!child)
--    return FALSE;
--
--  if (strcmp (tagname, "attributes") == 0)
--    {
--      parser_data = g_slice_new0 (AttributesSubParserData);
--      parser_data->cell_layout = GTK_CELL_LAYOUT (buildable);
--      parser_data->renderer = GTK_CELL_RENDERER (child);
--      parser_data->attr_name = NULL;
--
--      *parser = attributes_parser;
--      *data = parser_data;
--      return TRUE;
--    }
--
--  return FALSE;
--}
--
--static void
--_cell_layout_buildable_custom_tag_end (GtkBuildable *buildable,
--                                           GtkBuilder   *builder,
--                                           GObject      *child,
--                                           const gchar  *tagname,
--                                           gpointer     *data)
--{
--  AttributesSubParserData *parser_data;
--
--  parser_data = (AttributesSubParserData*)data;
--  g_assert (!parser_data->attr_name);
--  g_slice_free (AttributesSubParserData, parser_data);
--}
--
--static void
--_cell_layout_buildable_add_child (GtkBuildable      *buildable,
--                                      GtkBuilder        *builder,
--                                      GObject           *child,
--                                      const gchar       *type)
--{
--  GtkCellLayoutIface *iface;
--  
--  g_return_if_fail (GTK_IS_CELL_LAYOUT (buildable));
--  g_return_if_fail (GTK_IS_CELL_RENDERER (child));
--
--  iface = GTK_CELL_LAYOUT_GET_IFACE (buildable);
--  g_return_if_fail (iface->pack_start != NULL);
--  iface->pack_start (GTK_CELL_LAYOUT (buildable), GTK_CELL_RENDERER (child), FALSE);
--}
--
--void
--pspp_sheet_view_column_size_request (PsppSheetViewColumn       *tree_column,
--                                     GtkRequisition            *request)
--{
--  GtkWidget *base = GTK_WIDGET (tree_column->tree_view);
--  GtkRequisition label_req;
--  GtkRequisition align_req;
--  GtkRequisition arrow_req;
--  GtkRequisition hbox_req;
--  GtkStyle **button_style;
--
--  if (tree_column->button)
--    {
--      gtk_widget_get_preferred_size (tree_column->button, NULL, request);
--      return;
--    }
--
--  facade_label_get_size_request (0, 0, base, tree_column->title, &label_req);
--  facade_alignment_get_size_request (0, 0, 0, 0, 0, &label_req, &align_req);
--  facade_arrow_get_size_request (0, 0, &arrow_req);
--
--  facade_hbox_get_base_size_request (0, 2, 2, &hbox_req);
--  facade_hbox_add_child_size_request (0, &arrow_req, 0, &hbox_req);
--  facade_hbox_add_child_size_request (0, &align_req, 0, &hbox_req);
--
--  button_style = &PSPP_SHEET_VIEW (tree_column->tree_view)->priv->button_style;
--  if (*button_style == NULL)
--    {
--      *button_style = facade_get_style (base, GTK_TYPE_BUTTON, 0);
--      g_object_ref (*button_style);
--    }
--  facade_button_get_size_request (0, base, *button_style, &hbox_req, request);
--}
--
--void
--pspp_sheet_view_column_size_allocate (PsppSheetViewColumn       *tree_column,
--                                      GtkAllocation             *allocation)
--{
--  tree_column->allocation = *allocation;
--  if (tree_column->button)
--    gtk_widget_size_allocate (tree_column->button, allocation);
--}
--
--gboolean
--pspp_sheet_view_column_can_focus (PsppSheetViewColumn       *tree_column)
--{
--  return tree_column->reorderable || tree_column->clickable;
--}
diff --cc src/ui/gui/pspp-sheet-view-column.h
index 65eede214efebe8dee8654968e94d47e6dde371c,65eede214efebe8dee8654968e94d47e6dde371c..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,267 -1,267 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2011, 2012 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--/* gtktreeviewcolumn.h
-- * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Library 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
-- * Library General Public License for more details.
-- *
-- * You should have received a copy of the GNU Library 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.
-- */
--
--#ifndef __PSPP_SHEET_VIEW_COLUMN_H__
--#define __PSPP_SHEET_VIEW_COLUMN_H__
--
--#include <gtk/gtk.h>
--
--G_BEGIN_DECLS
--
--#define PSPP_TYPE_SHEET_VIEW_COLUMN        (pspp_sheet_view_column_get_type ())
--#define PSPP_SHEET_VIEW_COLUMN(obj)        (G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPP_TYPE_SHEET_VIEW_COLUMN, PsppSheetViewColumn))
--#define PSPP_SHEET_VIEW_COLUMN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PSPP_TYPE_SHEET_VIEW_COLUMN, PsppSheetViewColumnClass))
--#define PSPP_IS_SHEET_VIEW_COLUMN(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPP_TYPE_SHEET_VIEW_COLUMN))
--#define PSPP_IS_SHEET_VIEW_COLUMN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPP_TYPE_SHEET_VIEW_COLUMN))
--#define PSPP_SHEET_VIEW_COLUMN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PSPP_TYPE_SHEET_VIEW_COLUMN, PsppSheetViewColumnClass))
--
--typedef struct _PsppSheetViewColumn      PsppSheetViewColumn;
--typedef struct _PsppSheetViewColumnClass PsppSheetViewColumnClass;
--
--typedef void (* PsppSheetCellDataFunc) (PsppSheetViewColumn *tree_column,
--                                        GtkCellRenderer   *cell,
--                                        GtkTreeModel      *tree_model,
--                                        GtkTreeIter       *iter,
--                                        gpointer           data);
--
--
--struct _PsppSheetViewColumn
--{
--  GObject parent;
--
--  GtkWidget *PSEAL (tree_view);
--  GtkWidget *PSEAL (button);
--  GtkWidget *PSEAL (child);
--  GtkWidget *PSEAL (bin);
--  GdkWindow *PSEAL (window);
--  GtkCellEditable *PSEAL (editable_widget);
--  GtkAlign PSEAL (halign);
--  guint PSEAL (property_changed_signal);
--  gint PSEAL (spacing);
--  GtkAllocation PSEAL (allocation);
--
--  /* Sizing fields */
--  /* see gtk+/doc/tree-column-sizing.txt for more information on them */
--  gint PSEAL (requested_width);
--  gint PSEAL (button_request);
--  gint PSEAL (resized_width);
--  gint PSEAL (width);
--  gint PSEAL (fixed_width);
--  gint PSEAL (min_width);
--  gint PSEAL (max_width);
--
--  /* dragging columns */
--  gint PSEAL (drag_x);
--  gint PSEAL (drag_y);
--
--  gchar *PSEAL (title);
--  GList *PSEAL (cell_list);
--
--  /* Sorting */
--  guint PSEAL (sort_clicked_signal);
--  guint PSEAL (sort_column_changed_signal);
--  gint PSEAL (sort_column_id);
--  GtkSortType PSEAL (sort_order);
--
--  /* Flags */
--  guint PSEAL (visible)             : 1;
--  guint PSEAL (resizable)           : 1;
--  guint PSEAL (clickable)           : 1;
--  guint PSEAL (dirty)               : 1;
--  guint PSEAL (show_sort_indicator) : 1;
--  guint PSEAL (maybe_reordered)     : 1;
--  guint PSEAL (reorderable)         : 1;
--  guint PSEAL (use_resized_width)   : 1;
--  guint PSEAL (expand)              : 1;
--  guint PSEAL (quick_edit)          : 1;
--  guint PSEAL (selected)            : 1;
--  guint PSEAL (selectable)          : 1;
--  guint PSEAL (row_head)            : 1;
--  guint PSEAL (tabbable)            : 1;
--};
--
--struct _PsppSheetViewColumnClass
--{
--  GObjectClass parent_class;
--
--  gboolean (*clicked) (PsppSheetViewColumn *tree_column);
--  gboolean (*button_press_event) (PsppSheetViewColumn *,
--                                  GdkEventButton *);
--
--  /* Padding for future expansion */
--  void (*_gtk_reserved1) (void);
--  void (*_gtk_reserved2) (void);
--  void (*_gtk_reserved3) (void);
--  void (*_gtk_reserved4) (void);
--};
--
--GType                   pspp_sheet_view_column_get_type            (void) G_GNUC_CONST;
--PsppSheetViewColumn      *pspp_sheet_view_column_new                 (void);
--PsppSheetViewColumn      *pspp_sheet_view_column_new_with_attributes (const gchar             *title,
--                                                                GtkCellRenderer         *cell,
--                                                                ...) G_GNUC_NULL_TERMINATED;
--void                    pspp_sheet_view_column_pack_start          (PsppSheetViewColumn       *tree_column,
--                                                                GtkCellRenderer         *cell,
--                                                                gboolean                 expand);
--void                    pspp_sheet_view_column_pack_end            (PsppSheetViewColumn       *tree_column,
--                                                                GtkCellRenderer         *cell,
--                                                                gboolean                 expand);
--void                    pspp_sheet_view_column_clear               (PsppSheetViewColumn       *tree_column);
--
--GList                  *pspp_sheet_view_column_get_cell_renderers  (PsppSheetViewColumn       *tree_column);
--
--void                    pspp_sheet_view_column_add_attribute       (PsppSheetViewColumn       *tree_column,
--                                                                GtkCellRenderer         *cell_renderer,
--                                                                const gchar             *attribute,
--                                                                gint                     column);
--void                    pspp_sheet_view_column_set_attributes      (PsppSheetViewColumn       *tree_column,
--                                                                GtkCellRenderer         *cell_renderer,
--                                                                ...) G_GNUC_NULL_TERMINATED;
--void                    pspp_sheet_view_column_set_cell_data_func  (PsppSheetViewColumn       *tree_column,
--                                                                GtkCellRenderer         *cell_renderer,
--                                                                PsppSheetCellDataFunc      func,
--                                                                gpointer                 func_data,
--                                                                GDestroyNotify           destroy);
--void                    pspp_sheet_view_column_clear_attributes    (PsppSheetViewColumn       *tree_column,
--                                                                GtkCellRenderer         *cell_renderer);
--void                    pspp_sheet_view_column_set_spacing         (PsppSheetViewColumn       *tree_column,
--                                                                gint                     spacing);
--gint                    pspp_sheet_view_column_get_spacing         (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_visible         (PsppSheetViewColumn       *tree_column,
--                                                                gboolean                 visible);
--gboolean                pspp_sheet_view_column_get_visible         (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_resizable       (PsppSheetViewColumn       *tree_column,
--                                                                gboolean                 resizable);
--gboolean                pspp_sheet_view_column_get_resizable       (PsppSheetViewColumn       *tree_column);
--gint                    pspp_sheet_view_column_get_width           (PsppSheetViewColumn       *tree_column);
--gint                    pspp_sheet_view_column_get_fixed_width     (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_fixed_width     (PsppSheetViewColumn       *tree_column,
--                                                                gint                     fixed_width);
--void                    pspp_sheet_view_column_set_min_width       (PsppSheetViewColumn       *tree_column,
--                                                                gint                     min_width);
--gint                    pspp_sheet_view_column_get_min_width       (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_max_width       (PsppSheetViewColumn       *tree_column,
--                                                                gint                     max_width);
--gint                    pspp_sheet_view_column_get_max_width       (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_clicked             (PsppSheetViewColumn       *tree_column);
--
--
--
--/* Options for manipulating the column headers
-- */
--void                    pspp_sheet_view_column_set_title           (PsppSheetViewColumn       *tree_column,
--                                                                const gchar             *title);
--const gchar   *         pspp_sheet_view_column_get_title           (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_expand          (PsppSheetViewColumn       *tree_column,
--                                                                gboolean                 expand);
--gboolean                pspp_sheet_view_column_get_expand          (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_clickable       (PsppSheetViewColumn       *tree_column,
--                                                                gboolean                 clickable);
--gboolean                pspp_sheet_view_column_get_clickable       (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_widget          (PsppSheetViewColumn       *tree_column,
--                                                                GtkWidget               *widget);
--GtkWidget              *pspp_sheet_view_column_get_widget          (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_alignment       (PsppSheetViewColumn       *tree_columna,
--                                                                GtkAlign                   xalign);
--GtkAlign                  pspp_sheet_view_column_get_alignment       (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_reorderable     (PsppSheetViewColumn       *tree_column,
--                                                                gboolean                 reorderable);
--gboolean                pspp_sheet_view_column_get_reorderable     (PsppSheetViewColumn       *tree_column);
--
--void                    pspp_sheet_view_column_set_quick_edit     (PsppSheetViewColumn       *tree_column,
--                                                                gboolean                 quick_edit);
--gboolean                pspp_sheet_view_column_get_quick_edit     (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_selected     (PsppSheetViewColumn       *tree_column,
--                                                                gboolean                 selected);
--gboolean                pspp_sheet_view_column_get_selected     (PsppSheetViewColumn       *tree_column);
--
--void                    pspp_sheet_view_column_set_selectable     (PsppSheetViewColumn       *tree_column,
--                                                                gboolean                 selectable);
--gboolean                pspp_sheet_view_column_get_selectable     (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_row_head     (PsppSheetViewColumn       *tree_column,
--                                                                gboolean                 row_head);
--gboolean                pspp_sheet_view_column_get_row_head     (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_tabbable     (PsppSheetViewColumn       *tree_column,
--                                                                 gboolean                 tabbable);
--gboolean                pspp_sheet_view_column_get_tabbable     (PsppSheetViewColumn       *tree_column);
--
--
--
--/* You probably only want to use pspp_sheet_view_column_set_sort_column_id.  The
-- * other sorting functions exist primarily to let others do their own custom sorting.
-- */
--void                    pspp_sheet_view_column_set_sort_column_id  (PsppSheetViewColumn       *tree_column,
--                                                                gint                     sort_column_id);
--gint                    pspp_sheet_view_column_get_sort_column_id  (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_sort_indicator  (PsppSheetViewColumn       *tree_column,
--                                                                gboolean                 setting);
--gboolean                pspp_sheet_view_column_get_sort_indicator  (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_set_sort_order      (PsppSheetViewColumn       *tree_column,
--                                                                GtkSortType              order);
--GtkSortType             pspp_sheet_view_column_get_sort_order      (PsppSheetViewColumn       *tree_column);
--
--
--/* These functions are meant primarily for interaction between the PsppSheetView and the column.
-- */
--void                    pspp_sheet_view_column_cell_set_cell_data  (PsppSheetViewColumn       *tree_column,
--                                                                GtkTreeModel            *tree_model,
--                                                                GtkTreeIter             *iter);
--void                    pspp_sheet_view_column_cell_get_size       (PsppSheetViewColumn       *tree_column,
--                                                                const GdkRectangle      *cell_area,
--                                                                gint                    *x_offset,
--                                                                gint                    *y_offset,
--                                                                gint                    *width,
--                                                                gint                    *height);
--gboolean                pspp_sheet_view_column_cell_is_visible     (PsppSheetViewColumn       *tree_column);
--void                    pspp_sheet_view_column_focus_cell          (PsppSheetViewColumn       *tree_column,
--                                                                GtkCellRenderer         *cell);
--gboolean                pspp_sheet_view_column_cell_get_position   (PsppSheetViewColumn       *tree_column,
--                                                                GtkCellRenderer         *cell_renderer,
--                                                                gint                    *start_pos,
--                                                                gint                    *width);
--void                    pspp_sheet_view_column_queue_resize        (PsppSheetViewColumn       *tree_column);
--GtkWidget              *pspp_sheet_view_column_get_tree_view       (PsppSheetViewColumn       *tree_column);
--
--void                    pspp_sheet_view_column_size_request       (PsppSheetViewColumn       *tree_column,
--                                                                    GtkRequisition             *requisition);
--
--void                    pspp_sheet_view_column_size_allocate       (PsppSheetViewColumn       *tree_column,
--                                                                    GtkAllocation             *allocation);
--gboolean                pspp_sheet_view_column_can_focus           (PsppSheetViewColumn       *tree_column);
--
--G_END_DECLS
--
--
--#endif /* __PSPP_SHEET_VIEW_COLUMN_H__ */
diff --cc src/ui/gui/pspp-sheet-view.c
index 13f05ebf4f1e31ce0f58db41bd7192ea6c0908ae,13f05ebf4f1e31ce0f58db41bd7192ea6c0908ae..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,12530 -1,12530 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2011, 2012, 2013, 2015 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--/* gtktreeview.c
-- * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Library 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
-- * Library General Public License for more details.
-- *
-- * You should have received a copy of the GNU Library 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.
-- */
--
--#include <config.h>
--
--#include "ui/gui/pspp-sheet-private.h"
--
--#include <gtk/gtk.h>
--#include <gdk/gdk.h>
--#include <gdk/gdkkeysyms.h>
--#include <gdk/gdkkeysyms-compat.h>
--#include <string.h>
--
--#include "ui/gui/psppire-marshal.h"
--#include "ui/gui/pspp-sheet-selection.h"
--
--#define P_(STRING) STRING
--#define GTK_PARAM_READABLE G_PARAM_READABLE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
--#define GTK_PARAM_READWRITE G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB
--
--/* Many keyboard shortcuts for Mac are the same as for X
-- * except they use Command key instead of Control (e.g. Cut,
-- * Copy, Paste). This symbol is for those simple cases. */
--#ifndef GDK_WINDOWING_QUARTZ
--#define GTK_DEFAULT_ACCEL_MOD_MASK GDK_CONTROL_MASK
--#else
--#define GTK_DEFAULT_ACCEL_MOD_MASK GDK_META_MASK
--#endif
--
--#define PSPP_SHEET_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
--#define PSPP_SHEET_VIEW_PRIORITY_SCROLL_SYNC (PSPP_SHEET_VIEW_PRIORITY_VALIDATE + 2)
--#define PSPP_SHEET_VIEW_TIME_MS_PER_IDLE 30
--#define SCROLL_EDGE_SIZE 15
--#define EXPANDER_EXTRA_PADDING 4
--#define PSPP_SHEET_VIEW_SEARCH_DIALOG_TIMEOUT 5000
--
--/* The "background" areas of all rows/cells add up to cover the entire tree.
-- * The background includes all inter-row and inter-cell spacing.
-- * The "cell" areas are the cell_area passed in to gtk_cell_renderer_render(),
-- * i.e. just the cells, no spacing.
-- */
--
--#define BACKGROUND_HEIGHT(tree_view) (tree_view->priv->fixed_height)
--#define CELL_HEIGHT(tree_view, separator) ((BACKGROUND_HEIGHT (tree_view)) - (separator))
--
--/* Translate from bin_window coordinates to rbtree (tree coordinates) and
-- * vice versa.
-- */
--#define TREE_WINDOW_Y_TO_RBTREE_Y(tree_view,y) ((y) + tree_view->priv->dy)
--#define RBTREE_Y_TO_TREE_WINDOW_Y(tree_view,y) ((y) - tree_view->priv->dy)
--
--/* This is in bin_window coordinates */
--#define BACKGROUND_FIRST_PIXEL(tree_view,node) (RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, pspp_sheet_view_node_find_offset (tree_view, (node))))
--#define CELL_FIRST_PIXEL(tree_view,node,separator) (BACKGROUND_FIRST_PIXEL (tree_view,node) + separator/2)
--
--#define ROW_HEIGHT(tree_view) \
--  ((tree_view->priv->fixed_height > 0) ? (tree_view->priv->fixed_height) : (tree_view)->priv->expander_size)
--
--
--typedef struct _PsppSheetViewChild PsppSheetViewChild;
--struct _PsppSheetViewChild
--{
--  GtkWidget *widget;
--  PsppSheetViewColumn *column;
--  int node;
--};
--
--
--typedef struct _TreeViewDragInfo TreeViewDragInfo;
--struct _TreeViewDragInfo
--{
--  GdkModifierType start_button_mask;
--  GtkTargetList *_unused_source_target_list;
--  GdkDragAction source_actions;
--
--  GtkTargetList *_unused_dest_target_list;
--
--  guint source_set : 1;
--  guint dest_set : 1;
--};
--
--
--/* Signals */
--enum
--{
--  ROW_ACTIVATED,
--  COLUMNS_CHANGED,
--  CURSOR_CHANGED,
--  MOVE_CURSOR,
--  SELECT_ALL,
--  UNSELECT_ALL,
--  SELECT_CURSOR_ROW,
--  TOGGLE_CURSOR_ROW,
--  START_INTERACTIVE_SEARCH,
--  LAST_SIGNAL
--};
--
--/* Properties */
--enum {
--  PROP_0,
--  PROP_MODEL,
--  PROP_HADJUSTMENT,
--  PROP_VADJUSTMENT,
--  PROP_HSCROLL_POLICY,
--  PROP_VSCROLL_POLICY,
--  PROP_HEADERS_VISIBLE,
--  PROP_HEADERS_CLICKABLE,
--  PROP_REORDERABLE,
--  PROP_RULES_HINT,
--  PROP_ENABLE_SEARCH,
--  PROP_SEARCH_COLUMN,
--  PROP_HOVER_SELECTION,
--  PROP_RUBBER_BANDING,
--  PROP_ENABLE_GRID_LINES,
--  PROP_TOOLTIP_COLUMN,
--  PROP_SPECIAL_CELLS,
--  PROP_FIXED_HEIGHT,
--  PROP_FIXED_HEIGHT_SET
--};
--
--/* object signals */
--static void     pspp_sheet_view_finalize             (GObject          *object);
--static void     pspp_sheet_view_set_property         (GObject         *object,
--                                                  guint            prop_id,
--                                                  const GValue    *value,
--                                                  GParamSpec      *pspec);
--static void     pspp_sheet_view_get_property         (GObject         *object,
--                                                  guint            prop_id,
--                                                  GValue          *value,
--                                                  GParamSpec      *pspec);
--
--static void     pspp_sheet_view_dispose              (GObject        *object);
--
--/* gtkwidget signals */
--static void     pspp_sheet_view_realize              (GtkWidget        *widget);
--static void     pspp_sheet_view_unrealize            (GtkWidget        *widget);
--static void     pspp_sheet_view_map                  (GtkWidget        *widget);
--static void     pspp_sheet_view_size_request         (GtkWidget        *widget,
--                                                  GtkRequisition   *requisition);
--static void     pspp_sheet_view_size_allocate        (GtkWidget        *widget,
--                                                  GtkAllocation    *allocation);
--static gboolean pspp_sheet_view_draw               (GtkWidget        *widget,
--                                                  cairo_t *cr);
--static gboolean pspp_sheet_view_key_press            (GtkWidget        *widget,
--                                                  GdkEventKey      *event);
--static gboolean pspp_sheet_view_key_release          (GtkWidget        *widget,
--                                                  GdkEventKey      *event);
--static gboolean pspp_sheet_view_motion               (GtkWidget        *widget,
--                                                  GdkEventMotion   *event);
--static gboolean pspp_sheet_view_enter_notify         (GtkWidget        *widget,
--                                                  GdkEventCrossing *event);
--static gboolean pspp_sheet_view_leave_notify         (GtkWidget        *widget,
--                                                  GdkEventCrossing *event);
--static gboolean pspp_sheet_view_button_press         (GtkWidget        *widget,
--                                                  GdkEventButton   *event);
--static gboolean pspp_sheet_view_button_release       (GtkWidget        *widget,
--                                                  GdkEventButton   *event);
--static gboolean pspp_sheet_view_grab_broken          (GtkWidget          *widget,
--                                                  GdkEventGrabBroken *event);
--
--static void     pspp_sheet_view_set_focus_child      (GtkContainer     *container,
--                                                  GtkWidget        *child);
--static gint     pspp_sheet_view_focus_out            (GtkWidget        *widget,
--                                                  GdkEventFocus    *event);
--static gint     pspp_sheet_view_focus                (GtkWidget        *widget,
--                                                  GtkDirectionType  direction);
--static void     pspp_sheet_view_grab_focus           (GtkWidget        *widget);
--static void     pspp_sheet_view_style_updated        (GtkWidget        *widget);
--static void     pspp_sheet_view_grab_notify          (GtkWidget        *widget,
--                                                  gboolean          was_grabbed);
--static void     pspp_sheet_view_state_changed        (GtkWidget        *widget,
--                                                  GtkStateType      previous_state);
--
--/* container signals */
--static void     pspp_sheet_view_remove               (GtkContainer     *container,
--                                                  GtkWidget        *widget);
--static void     pspp_sheet_view_forall               (GtkContainer     *container,
--                                                  gboolean          include_internals,
--                                                  GtkCallback       callback,
--                                                  gpointer          callback_data);
--
--/* Source side drag signals */
--static void pspp_sheet_view_drag_begin       (GtkWidget        *widget,
--                                            GdkDragContext   *context);
--static void pspp_sheet_view_drag_end         (GtkWidget        *widget,
--                                            GdkDragContext   *context);
--static void pspp_sheet_view_drag_data_get    (GtkWidget        *widget,
--                                            GdkDragContext   *context,
--                                            GtkSelectionData *selection_data,
--                                            guint             info,
--                                            guint             time);
--static void pspp_sheet_view_drag_data_delete (GtkWidget        *widget,
--                                            GdkDragContext   *context);
--
--/* Target side drag signals */
--static void     pspp_sheet_view_drag_leave         (GtkWidget        *widget,
--                                                  GdkDragContext   *context,
--                                                  guint             time);
--static gboolean pspp_sheet_view_drag_motion        (GtkWidget        *widget,
--                                                  GdkDragContext   *context,
--                                                  gint              x,
--                                                  gint              y,
--                                                  guint             time);
--static gboolean pspp_sheet_view_drag_drop          (GtkWidget        *widget,
--                                                  GdkDragContext   *context,
--                                                  gint              x,
--                                                  gint              y,
--                                                  guint             time);
--static void     pspp_sheet_view_drag_data_received (GtkWidget        *widget,
--                                                  GdkDragContext   *context,
--                                                  gint              x,
--                                                  gint              y,
--                                                  GtkSelectionData *selection_data,
--                                                  guint             info,
--                                                  guint             time);
--
--/* tree_model signals */
--static void pspp_sheet_view_set_adjustments                 (PsppSheetView     *tree_view,
--                                                         GtkAdjustment   *hadj,
--                                                         GtkAdjustment   *vadj);
--static gboolean pspp_sheet_view_real_move_cursor            (PsppSheetView     *tree_view,
--                                                         GtkMovementStep  step,
--                                                         gint             count);
--static gboolean pspp_sheet_view_real_select_all             (PsppSheetView     *tree_view);
--static gboolean pspp_sheet_view_real_unselect_all           (PsppSheetView     *tree_view);
--static gboolean pspp_sheet_view_real_select_cursor_row      (PsppSheetView     *tree_view,
--                                                             gboolean         start_editing,
--                                                             PsppSheetSelectMode mode);
--static gboolean pspp_sheet_view_real_toggle_cursor_row      (PsppSheetView     *tree_view);
--static void pspp_sheet_view_row_changed                     (GtkTreeModel    *model,
--                                                         GtkTreePath     *path,
--                                                         GtkTreeIter     *iter,
--                                                         gpointer         data);
--static void pspp_sheet_view_row_inserted                    (GtkTreeModel    *model,
--                                                         GtkTreePath     *path,
--                                                         GtkTreeIter     *iter,
--                                                         gpointer         data);
--static void pspp_sheet_view_row_deleted                     (GtkTreeModel    *model,
--                                                         GtkTreePath     *path,
--                                                         gpointer         data);
--static void pspp_sheet_view_rows_reordered                  (GtkTreeModel    *model,
--                                                         GtkTreePath     *parent,
--                                                         GtkTreeIter     *iter,
--                                                         gint            *new_order,
--                                                         gpointer         data);
--
--/* Incremental reflow */
--static gint validate_row             (PsppSheetView *tree_view,
--                                        int node,
--                                        GtkTreeIter *iter,
--                                        GtkTreePath *path);
--static void     validate_visible_area    (PsppSheetView *tree_view);
--static gboolean validate_rows_handler    (PsppSheetView *tree_view);
--static gboolean presize_handler_callback (gpointer     data);
--static void     install_presize_handler  (PsppSheetView *tree_view);
--static void     install_scroll_sync_handler (PsppSheetView *tree_view);
--static void     pspp_sheet_view_set_top_row   (PsppSheetView *tree_view,
--                                           GtkTreePath *path,
--                                           gint         offset);
--static void   pspp_sheet_view_dy_to_top_row (PsppSheetView *tree_view);
--static void     pspp_sheet_view_top_row_to_dy (PsppSheetView *tree_view);
--static void     invalidate_empty_focus      (PsppSheetView *tree_view);
--
--/* Internal functions */
--static GtkAdjustment *pspp_sheet_view_do_get_hadjustment (PsppSheetView *);
--static GtkAdjustment *pspp_sheet_view_do_get_vadjustment (PsppSheetView *);
--static void pspp_sheet_view_do_set_hadjustment (PsppSheetView   *tree_view,
--                                              GtkAdjustment *adjustment);
--static void pspp_sheet_view_do_set_vadjustment (PsppSheetView   *tree_view,
--                                              GtkAdjustment *adjustment);
--static void     pspp_sheet_view_add_move_binding               (GtkBindingSet      *binding_set,
--                                                            guint               keyval,
--                                                            guint               modmask,
--                                                            gboolean            add_shifted_binding,
--                                                            GtkMovementStep     step,
--                                                            gint                count);
--static void     pspp_sheet_view_queue_draw_path                (PsppSheetView        *tree_view,
--                                                            GtkTreePath        *path,
--                                                            const GdkRectangle *clip_rect);
--static gint     pspp_sheet_view_new_column_width               (PsppSheetView        *tree_view,
--                                                            gint                i,
--                                                            gint               *x);
--static void     pspp_sheet_view_adjustment_changed             (GtkAdjustment      *adjustment,
--                                                            PsppSheetView        *tree_view);
--static void     pspp_sheet_view_clamp_node_visible             (PsppSheetView        *tree_view,
--                                                            int node);
--static void     pspp_sheet_view_clamp_column_visible           (PsppSheetView        *tree_view,
--                                                            PsppSheetViewColumn  *column,
--                                                            gboolean            focus_to_cell);
--static gboolean pspp_sheet_view_maybe_begin_dragging_row       (PsppSheetView        *tree_view,
--                                                            GdkEventMotion     *event);
--static void     pspp_sheet_view_focus_to_cursor                (PsppSheetView        *tree_view);
--static gboolean pspp_sheet_view_move_cursor_up_down            (PsppSheetView        *tree_view,
--                                                            gint                count,
--                                                                PsppSheetSelectMode mode);
--static void     pspp_sheet_view_move_cursor_page_up_down       (PsppSheetView        *tree_view,
--                                                            gint                count,
--                                                                PsppSheetSelectMode mode);
--static void     pspp_sheet_view_move_cursor_left_right         (PsppSheetView        *tree_view,
--                                                                gint                count,
--                                                                PsppSheetSelectMode mode);
--static void     pspp_sheet_view_move_cursor_line_start_end     (PsppSheetView        *tree_view,
--                                                              gint                count,
--                                                                PsppSheetSelectMode mode);
--static void     pspp_sheet_view_move_cursor_tab                (PsppSheetView        *tree_view,
--                                                            gint                count);
--static void     pspp_sheet_view_move_cursor_start_end          (PsppSheetView        *tree_view,
--                                                            gint                count,
--                                                                PsppSheetSelectMode mode);
--static void     pspp_sheet_view_real_set_cursor                (PsppSheetView        *tree_view,
--                                                            GtkTreePath        *path,
--                                                            gboolean            clear_and_select,
--                                                              gboolean            clamp_node,
--                                                              PsppSheetSelectMode mode);
--static gboolean pspp_sheet_view_has_special_cell               (PsppSheetView        *tree_view);
--static void     pspp_sheet_view_stop_rubber_band               (PsppSheetView        *tree_view);
--static void     update_prelight                              (PsppSheetView        *tree_view,
--                                                              int                 x,
--                                                              int                 y);
--static void initialize_fixed_height_mode (PsppSheetView *tree_view);
--
--/* interactive search */
--static void     pspp_sheet_view_ensure_interactive_directory (PsppSheetView *tree_view);
--static void     pspp_sheet_view_search_dialog_hide     (GtkWidget        *search_dialog,
--                                                       PsppSheetView      *tree_view);
--static void     pspp_sheet_view_search_position_func      (PsppSheetView      *tree_view,
--                                                       GtkWidget        *search_dialog,
--                                                       gpointer          user_data);
--static void     pspp_sheet_view_search_disable_popdown    (GtkEntry         *entry,
--                                                       GtkMenu          *menu,
--                                                       gpointer          data);
--static void     pspp_sheet_view_search_activate           (GtkEntry         *entry,
--                                                       PsppSheetView      *tree_view);
--static gboolean pspp_sheet_view_real_search_enable_popdown(gpointer          data);
--static void     pspp_sheet_view_search_enable_popdown     (GtkWidget        *widget,
--                                                       gpointer          data);
--static gboolean pspp_sheet_view_search_delete_event       (GtkWidget        *widget,
--                                                       GdkEventAny      *event,
--                                                       PsppSheetView      *tree_view);
--static gboolean pspp_sheet_view_search_button_press_event (GtkWidget        *widget,
--                                                       GdkEventButton   *event,
--                                                       PsppSheetView      *tree_view);
--static gboolean pspp_sheet_view_search_scroll_event       (GtkWidget        *entry,
--                                                       GdkEventScroll   *event,
--                                                       PsppSheetView      *tree_view);
--static gboolean pspp_sheet_view_search_key_press_event    (GtkWidget        *entry,
--                                                       GdkEventKey      *event,
--                                                       PsppSheetView      *tree_view);
--static gboolean pspp_sheet_view_search_move               (GtkWidget        *window,
--                                                       PsppSheetView      *tree_view,
--                                                       gboolean          up);
--static gboolean pspp_sheet_view_search_equal_func         (GtkTreeModel     *model,
--                                                       gint              column,
--                                                       const gchar      *key,
--                                                       GtkTreeIter      *iter,
--                                                       gpointer          search_data);
--static gboolean pspp_sheet_view_search_iter               (GtkTreeModel     *model,
--                                                       PsppSheetSelection *selection,
--                                                       GtkTreeIter      *iter,
--                                                       const gchar      *text,
--                                                       gint             *count,
--                                                       gint              n);
--static void     pspp_sheet_view_search_init               (GtkWidget        *entry,
--                                                       PsppSheetView      *tree_view);
--static void     pspp_sheet_view_put                       (PsppSheetView      *tree_view,
--                                                       GtkWidget        *child_widget,
--                                                       GtkTreePath *path,
--                                                       PsppSheetViewColumn *column);
--static gboolean pspp_sheet_view_start_editing             (PsppSheetView      *tree_view,
--                                                       GtkTreePath      *cursor_path);
--static gboolean pspp_sheet_view_editable_button_press_event (GtkWidget *,
--                                                             GdkEventButton *,
--                                                             PsppSheetView *);
--static void pspp_sheet_view_editable_clicked (GtkButton *, PsppSheetView *);
--static void pspp_sheet_view_real_start_editing (PsppSheetView       *tree_view,
--                                            PsppSheetViewColumn *column,
--                                            GtkTreePath       *path,
--                                            GtkCellEditable   *cell_editable,
--                                            GdkRectangle      *cell_area,
--                                            GdkEvent          *event,
--                                            guint              flags);
--static gboolean pspp_sheet_view_real_start_interactive_search (PsppSheetView *tree_view,
--                                                           gboolean     keybinding);
--static gboolean pspp_sheet_view_start_interactive_search      (PsppSheetView *tree_view);
--static PsppSheetViewColumn *pspp_sheet_view_get_drop_column (PsppSheetView       *tree_view,
--                                                       PsppSheetViewColumn *column,
--                                                       gint               drop_position);
--static void
--pspp_sheet_view_adjust_cell_area (PsppSheetView        *tree_view,
--                                  PsppSheetViewColumn  *column,
--                                  const GdkRectangle   *background_area,
--                                  gboolean              subtract_focus_rect,
--                                  GdkRectangle         *cell_area);
--static gint pspp_sheet_view_find_offset (PsppSheetView *tree_view,
--                                         gint height,
--                                         int *new_node);
--
--/* GtkBuildable */
--static void pspp_sheet_view_buildable_add_child (GtkBuildable *tree_view,
--                                             GtkBuilder  *builder,
--                                             GObject     *child,
--                                             const gchar *type);
--static void pspp_sheet_view_buildable_init      (GtkBuildableIface *iface);
--
--
--static gboolean scroll_row_timeout                   (gpointer     data);
--static void     add_scroll_timeout                   (PsppSheetView *tree_view);
--static void     remove_scroll_timeout                (PsppSheetView *tree_view);
--
--static guint tree_view_signals [LAST_SIGNAL] = { 0 };
--
--static GtkBindingSet *edit_bindings;
--
--\f
--
--/* GType Methods
-- */
--
--G_DEFINE_TYPE_WITH_CODE (PsppSheetView, pspp_sheet_view, GTK_TYPE_CONTAINER,
--                       G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
--                                              pspp_sheet_view_buildable_init)
--                         G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
--
--static void
--pspp_sheet_view_get_preferred_width (GtkWidget *widget,
--                               gint      *minimal_width,
--                               gint      *natural_width)
--{
--  GtkRequisition requisition;
--
--  pspp_sheet_view_size_request (widget, &requisition);
--
--  *minimal_width = *natural_width = requisition.width;
--}
--
--static void
--pspp_sheet_view_get_preferred_height (GtkWidget *widget,
--                                gint      *minimal_height,
--                                gint      *natural_height)
--{
--  GtkRequisition requisition;
--
--  pspp_sheet_view_size_request (widget, &requisition);
--
--  *minimal_height = *natural_height = requisition.height;
--}
--
--static void
--pspp_sheet_view_class_init (PsppSheetViewClass *class)
--{
--  GObjectClass *o_class;
--  GtkWidgetClass *widget_class;
--  GtkContainerClass *container_class;
--  GtkBindingSet *binding_set[2];
--  int i;
--
--  binding_set[0] = gtk_binding_set_by_class (class);
--
--  binding_set[1] = gtk_binding_set_new ("PsppSheetViewEditing");
--  edit_bindings = binding_set[1];
--
--  o_class = (GObjectClass *) class;
--  widget_class = (GtkWidgetClass *) class;
--  container_class = (GtkContainerClass *) class;
--
--  /* GObject signals */
--  o_class->set_property = pspp_sheet_view_set_property;
--  o_class->get_property = pspp_sheet_view_get_property;
--  o_class->finalize = pspp_sheet_view_finalize;
--  o_class->dispose = pspp_sheet_view_dispose;
--
--  /* GtkWidget signals */
--  widget_class->map = pspp_sheet_view_map;
--  widget_class->realize = pspp_sheet_view_realize;
--  widget_class->unrealize = pspp_sheet_view_unrealize;
--  widget_class->get_preferred_width = pspp_sheet_view_get_preferred_width;
--  widget_class->get_preferred_height = pspp_sheet_view_get_preferred_height;
--  widget_class->size_allocate = pspp_sheet_view_size_allocate;
--  widget_class->button_press_event = pspp_sheet_view_button_press;
--  widget_class->button_release_event = pspp_sheet_view_button_release;
--  widget_class->grab_broken_event = pspp_sheet_view_grab_broken;
--  /*widget_class->configure_event = pspp_sheet_view_configure;*/
--  widget_class->motion_notify_event = pspp_sheet_view_motion;
--  widget_class->draw = pspp_sheet_view_draw;
--  widget_class->key_press_event = pspp_sheet_view_key_press;
--  widget_class->key_release_event = pspp_sheet_view_key_release;
--  widget_class->enter_notify_event = pspp_sheet_view_enter_notify;
--  widget_class->leave_notify_event = pspp_sheet_view_leave_notify;
--  widget_class->focus_out_event = pspp_sheet_view_focus_out;
--  widget_class->drag_begin = pspp_sheet_view_drag_begin;
--  widget_class->drag_end = pspp_sheet_view_drag_end;
--  widget_class->drag_data_get = pspp_sheet_view_drag_data_get;
--  widget_class->drag_data_delete = pspp_sheet_view_drag_data_delete;
--  widget_class->drag_leave = pspp_sheet_view_drag_leave;
--  widget_class->drag_motion = pspp_sheet_view_drag_motion;
--  widget_class->drag_drop = pspp_sheet_view_drag_drop;
--  widget_class->drag_data_received = pspp_sheet_view_drag_data_received;
--  widget_class->focus = pspp_sheet_view_focus;
--  widget_class->grab_focus = pspp_sheet_view_grab_focus;
--  widget_class->style_updated = pspp_sheet_view_style_updated;
--  widget_class->grab_notify = pspp_sheet_view_grab_notify;
--  widget_class->state_changed = pspp_sheet_view_state_changed;
--
--  /* GtkContainer signals */
--  container_class->remove = pspp_sheet_view_remove;
--  container_class->forall = pspp_sheet_view_forall;
--  container_class->set_focus_child = pspp_sheet_view_set_focus_child;
--
--  class->set_scroll_adjustments = pspp_sheet_view_set_adjustments;
--  class->move_cursor = pspp_sheet_view_real_move_cursor;
--  class->select_all = pspp_sheet_view_real_select_all;
--  class->unselect_all = pspp_sheet_view_real_unselect_all;
--  class->select_cursor_row = pspp_sheet_view_real_select_cursor_row;
--  class->toggle_cursor_row = pspp_sheet_view_real_toggle_cursor_row;
--  class->start_interactive_search = pspp_sheet_view_start_interactive_search;
--
--  /* Properties */
--
--  g_object_class_install_property (o_class,
--                                   PROP_MODEL,
--                                   g_param_spec_object ("model",
--                                                      P_("TreeView Model"),
--                                                      P_("The model for the tree view"),
--                                                      GTK_TYPE_TREE_MODEL,
--                                                      GTK_PARAM_READWRITE));
--
--  g_object_class_override_property (o_class, PROP_HADJUSTMENT,    "hadjustment");
--  g_object_class_override_property (o_class, PROP_VADJUSTMENT,    "vadjustment");
--  g_object_class_override_property (o_class, PROP_HSCROLL_POLICY, "hscroll-policy");
--  g_object_class_override_property (o_class, PROP_VSCROLL_POLICY, "vscroll-policy");
--
--  g_object_class_install_property (o_class,
--                                   PROP_HEADERS_VISIBLE,
--                                   g_param_spec_boolean ("headers-visible",
--                                                       P_("Headers Visible"),
--                                                       P_("Show the column header buttons"),
--                                                       TRUE,
--                                                       GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (o_class,
--                                   PROP_HEADERS_CLICKABLE,
--                                   g_param_spec_boolean ("headers-clickable",
--                                                       P_("Headers Clickable"),
--                                                       P_("Column headers respond to click events"),
--                                                       TRUE,
--                                                       GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (o_class,
--                                   PROP_REORDERABLE,
--                                   g_param_spec_boolean ("reorderable",
--                                                       P_("Reorderable"),
--                                                       P_("View is reorderable"),
--                                                       FALSE,
--                                                       GTK_PARAM_READWRITE));
--
--  g_object_class_install_property (o_class,
--                                   PROP_RULES_HINT,
--                                   g_param_spec_boolean ("rules-hint",
--                                                       P_("Rules Hint"),
--                                                       P_("Set a hint to the theme engine to draw rows in alternating colors"),
--                                                       FALSE,
--                                                       GTK_PARAM_READWRITE));
--
--    g_object_class_install_property (o_class,
--                                   PROP_ENABLE_SEARCH,
--                                   g_param_spec_boolean ("enable-search",
--                                                         P_("Enable Search"),
--                                                         P_("View allows user to search through columns interactively"),
--                                                         TRUE,
--                                                         GTK_PARAM_READWRITE));
--
--    g_object_class_install_property (o_class,
--                                   PROP_SEARCH_COLUMN,
--                                   g_param_spec_int ("search-column",
--                                                     P_("Search Column"),
--                                                     P_("Model column to search through during interactive search"),
--                                                     -1,
--                                                     G_MAXINT,
--                                                     -1,
--                                                     GTK_PARAM_READWRITE));
--
--    /**
--     * PsppSheetView:hover-selection:
--     * 
--     * Enables of disables the hover selection mode of @tree_view.
--     * Hover selection makes the selected row follow the pointer.
--     * Currently, this works only for the selection modes 
--     * %PSPP_SHEET_SELECTION_SINGLE and %PSPP_SHEET_SELECTION_BROWSE.
--     *
--     * This mode is primarily intended for treeviews in popups, e.g.
--     * in #GtkComboBox or #GtkEntryCompletion.
--     *
--     * Since: 2.6
--     */
--    g_object_class_install_property (o_class,
--                                     PROP_HOVER_SELECTION,
--                                     g_param_spec_boolean ("hover-selection",
--                                                           P_("Hover Selection"),
--                                                           P_("Whether the selection should follow the pointer"),
--                                                           FALSE,
--                                                           GTK_PARAM_READWRITE));
--
--    g_object_class_install_property (o_class,
--                                     PROP_RUBBER_BANDING,
--                                     g_param_spec_boolean ("rubber-banding",
--                                                           P_("Rubber Banding"),
--                                                           P_("Whether to enable selection of multiple items by dragging the mouse pointer"),
--                                                           FALSE,
--                                                           GTK_PARAM_READWRITE));
--
--    g_object_class_install_property (o_class,
--                                     PROP_ENABLE_GRID_LINES,
--                                     g_param_spec_enum ("enable-grid-lines",
--                                                      P_("Enable Grid Lines"),
--                                                      P_("Whether grid lines should be drawn in the tree view"),
--                                                      PSPP_TYPE_SHEET_VIEW_GRID_LINES,
--                                                      PSPP_SHEET_VIEW_GRID_LINES_NONE,
--                                                      GTK_PARAM_READWRITE));
--
--    g_object_class_install_property (o_class,
--                                   PROP_TOOLTIP_COLUMN,
--                                   g_param_spec_int ("tooltip-column",
--                                                     P_("Tooltip Column"),
--                                                     P_("The column in the model containing the tooltip texts for the rows"),
--                                                     -1,
--                                                     G_MAXINT,
--                                                     -1,
--                                                     GTK_PARAM_READWRITE));
--
--    g_object_class_install_property (o_class,
--                                     PROP_SPECIAL_CELLS,
--                                     g_param_spec_enum ("special-cells",
--                                                      P_("Special Cells"),
--                                                      P_("Whether rows have special cells."),
--                                                      PSPP_TYPE_SHEET_VIEW_SPECIAL_CELLS,
--                                                      PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT,
--                                                      GTK_PARAM_READWRITE));
--
--    g_object_class_install_property (o_class,
--                                   PROP_FIXED_HEIGHT,
--                                   g_param_spec_int ("fixed-height",
--                                                     P_("Fixed Height"),
--                                                     P_("Height of a single row.  Normally the height of a row is determined automatically.  Writing this property sets fixed-height-set to true, preventing this property's value from changing."),
--                                                     -1,
--                                                     G_MAXINT,
--                                                     -1,
--                                                     GTK_PARAM_READWRITE));
--
--    g_object_class_install_property (o_class,
--                                     PROP_FIXED_HEIGHT_SET,
--                                     g_param_spec_boolean ("fixed-height-set",
--                                                           P_("Fixed Height Set"),
--                                                           P_("Whether fixed-height was set externally."),
--                                                           FALSE,
--                                                           GTK_PARAM_READWRITE));
--
--  /* Style properties */
--#define _TREE_VIEW_EXPANDER_SIZE 12
--#define _TREE_VIEW_VERTICAL_SEPARATOR 2
--#define _TREE_VIEW_HORIZONTAL_SEPARATOR 2
--
--  gtk_widget_class_install_style_property (widget_class,
--                                         g_param_spec_int ("expander-size",
--                                                           P_("Expander Size"),
--                                                           P_("Size of the expander arrow"),
--                                                           0,
--                                                           G_MAXINT,
--                                                           _TREE_VIEW_EXPANDER_SIZE,
--                                                           GTK_PARAM_READABLE));
--
--  gtk_widget_class_install_style_property (widget_class,
--                                         g_param_spec_int ("vertical-separator",
--                                                           P_("Vertical Separator Width"),
--                                                           P_("Vertical space between cells.  Must be an even number"),
--                                                           0,
--                                                           G_MAXINT,
--                                                           _TREE_VIEW_VERTICAL_SEPARATOR,
--                                                           GTK_PARAM_READABLE));
--
--  gtk_widget_class_install_style_property (widget_class,
--                                         g_param_spec_int ("horizontal-separator",
--                                                           P_("Horizontal Separator Width"),
--                                                           P_("Horizontal space between cells.  Must be an even number"),
--                                                           0,
--                                                           G_MAXINT,
--                                                           _TREE_VIEW_HORIZONTAL_SEPARATOR,
--                                                           GTK_PARAM_READABLE));
--
--  gtk_widget_class_install_style_property (widget_class,
--                                         g_param_spec_boolean ("allow-rules",
--                                                               P_("Allow Rules"),
--                                                               P_("Allow drawing of alternating color rows"),
--                                                               TRUE,
--                                                               GTK_PARAM_READABLE));
--
--  gtk_widget_class_install_style_property (widget_class,
--                                           g_param_spec_boxed ("even-row-color",
--                                                               P_("Even Row Color"),
--                                                               P_("Color to use for even rows"),
--                                                             GDK_TYPE_COLOR,
--                                                             GTK_PARAM_READABLE));
--
--  gtk_widget_class_install_style_property (widget_class,
--                                           g_param_spec_boxed ("odd-row-color",
--                                                               P_("Odd Row Color"),
--                                                               P_("Color to use for odd rows"),
--                                                             GDK_TYPE_COLOR,
--                                                             GTK_PARAM_READABLE));
--
--  gtk_widget_class_install_style_property (widget_class,
--                                         g_param_spec_boolean ("row-ending-details",
--                                                               P_("Row Ending details"),
--                                                               P_("Enable extended row background theming"),
--                                                               FALSE,
--                                                               GTK_PARAM_READABLE));
--
--  gtk_widget_class_install_style_property (widget_class,
--                                         g_param_spec_int ("grid-line-width",
--                                                           P_("Grid line width"),
--                                                           P_("Width, in pixels, of the tree view grid lines"),
--                                                           0, G_MAXINT, 1,
--                                                           GTK_PARAM_READABLE));
--
--  gtk_widget_class_install_style_property (widget_class,
--                                         g_param_spec_int ("tree-line-width",
--                                                           P_("Tree line width"),
--                                                           P_("Width, in pixels, of the tree view lines"),
--                                                           0, G_MAXINT, 1,
--                                                           GTK_PARAM_READABLE));
--
--  gtk_widget_class_install_style_property (widget_class,
--                                         g_param_spec_string ("tree-line-pattern",
--                                                              P_("Tree line pattern"),
--                                                              P_("Dash pattern used to draw the tree view lines"),
--                                                              "\1\1",
--                                                              GTK_PARAM_READABLE));
--
--  /* Signals */
--
--  /**
--   * PsppSheetView::row-activated:
--   * @tree_view: the object on which the signal is emitted
--   * @path: the #GtkTreePath for the activated row
--   * @column: the #PsppSheetViewColumn in which the activation occurred
--   *
--   * The "row-activated" signal is emitted when the method
--   * pspp_sheet_view_row_activated() is called or the user double clicks 
--   * a treeview row. It is also emitted when a non-editable row is 
--   * selected and one of the keys: Space, Shift+Space, Return or 
--   * Enter is pressed.
--   * 
--   * For selection handling refer to the <link linkend="TreeWidget">tree 
--   * widget conceptual overview</link> as well as #PsppSheetSelection.
--   */
--  tree_view_signals[ROW_ACTIVATED] =
--    g_signal_new ("row-activated",
--                G_TYPE_FROM_CLASS (o_class),
--                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
--                G_STRUCT_OFFSET (PsppSheetViewClass, row_activated),
--                NULL, NULL,
--                  psppire_marshal_VOID__BOXED_OBJECT,
--                G_TYPE_NONE, 2,
--                GTK_TYPE_TREE_PATH,
--                PSPP_TYPE_SHEET_VIEW_COLUMN);
--
--  /**
--   * PsppSheetView::columns-changed:
--   * @tree_view: the object on which the signal is emitted 
--   * 
--   * The number of columns of the treeview has changed.
--   */
--  tree_view_signals[COLUMNS_CHANGED] =
--    g_signal_new ("columns-changed",
--                G_TYPE_FROM_CLASS (o_class),
--                G_SIGNAL_RUN_LAST,
--                G_STRUCT_OFFSET (PsppSheetViewClass, columns_changed),
--                NULL, NULL,
--                g_cclosure_marshal_VOID__VOID,
--                G_TYPE_NONE, 0);
--
--  /**
--   * PsppSheetView::cursor-changed:
--   * @tree_view: the object on which the signal is emitted
--   * 
--   * The position of the cursor (focused cell) has changed.
--   */
--  tree_view_signals[CURSOR_CHANGED] =
--    g_signal_new ("cursor-changed",
--                G_TYPE_FROM_CLASS (o_class),
--                G_SIGNAL_RUN_LAST,
--                G_STRUCT_OFFSET (PsppSheetViewClass, cursor_changed),
--                NULL, NULL,
--                g_cclosure_marshal_VOID__VOID,
--                G_TYPE_NONE, 0);
--
--  tree_view_signals[MOVE_CURSOR] =
--    g_signal_new ("move-cursor",
--                G_TYPE_FROM_CLASS (o_class),
--                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
--                G_STRUCT_OFFSET (PsppSheetViewClass, move_cursor),
--                NULL, NULL,
--                psppire_marshal_BOOLEAN__ENUM_INT,
--                G_TYPE_BOOLEAN, 2,
--                GTK_TYPE_MOVEMENT_STEP,
--                G_TYPE_INT);
--
--  tree_view_signals[SELECT_ALL] =
--    g_signal_new ("select-all",
--                G_TYPE_FROM_CLASS (o_class),
--                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
--                G_STRUCT_OFFSET (PsppSheetViewClass, select_all),
--                NULL, NULL,
--                psppire_marshal_BOOLEAN__VOID,
--                G_TYPE_BOOLEAN, 0);
--
--  tree_view_signals[UNSELECT_ALL] =
--    g_signal_new ("unselect-all",
--                G_TYPE_FROM_CLASS (o_class),
--                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
--                G_STRUCT_OFFSET (PsppSheetViewClass, unselect_all),
--                NULL, NULL,
--                psppire_marshal_BOOLEAN__VOID,
--                G_TYPE_BOOLEAN, 0);
--
--  tree_view_signals[SELECT_CURSOR_ROW] =
--    g_signal_new ("select-cursor-row",
--                G_TYPE_FROM_CLASS (o_class),
--                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
--                G_STRUCT_OFFSET (PsppSheetViewClass, select_cursor_row),
--                NULL, NULL,
--                psppire_marshal_BOOLEAN__BOOLEAN,
--                G_TYPE_BOOLEAN, 2,
--                G_TYPE_BOOLEAN, G_TYPE_INT);
--
--  tree_view_signals[TOGGLE_CURSOR_ROW] =
--    g_signal_new ("toggle-cursor-row",
--                G_TYPE_FROM_CLASS (o_class),
--                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
--                G_STRUCT_OFFSET (PsppSheetViewClass, toggle_cursor_row),
--                NULL, NULL,
--                psppire_marshal_BOOLEAN__VOID,
--                G_TYPE_BOOLEAN, 0);
--
--  tree_view_signals[START_INTERACTIVE_SEARCH] =
--    g_signal_new ("start-interactive-search",
--                G_TYPE_FROM_CLASS (o_class),
--                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
--                G_STRUCT_OFFSET (PsppSheetViewClass, start_interactive_search),
--                NULL, NULL,
--                psppire_marshal_BOOLEAN__VOID,
--                G_TYPE_BOOLEAN, 0);
--
--  /* Key bindings */
--  for (i = 0; i < 2; i++)
--    {
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_Up, 0, TRUE,
--                                        GTK_MOVEMENT_DISPLAY_LINES, -1);
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_KP_Up, 0, TRUE,
--                                        GTK_MOVEMENT_DISPLAY_LINES, -1);
--
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_Down, 0, TRUE,
--                                        GTK_MOVEMENT_DISPLAY_LINES, 1);
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_KP_Down, 0, TRUE,
--                                        GTK_MOVEMENT_DISPLAY_LINES, 1);
--
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_p, GDK_CONTROL_MASK, FALSE,
--                                        GTK_MOVEMENT_DISPLAY_LINES, -1);
--
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_n, GDK_CONTROL_MASK, FALSE,
--                                        GTK_MOVEMENT_DISPLAY_LINES, 1);
--
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_Home, 0, TRUE,
--                                        GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_KP_Home, 0, TRUE,
--                                        GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
--
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_End, 0, TRUE,
--                                        GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_KP_End, 0, TRUE,
--                                        GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
--
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_Page_Up, 0, TRUE,
--                                        GTK_MOVEMENT_PAGES, -1);
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_KP_Page_Up, 0, TRUE,
--                                        GTK_MOVEMENT_PAGES, -1);
--
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_Page_Down, 0, TRUE,
--                                        GTK_MOVEMENT_PAGES, 1);
--      pspp_sheet_view_add_move_binding (binding_set[i], GDK_KP_Page_Down, 0, TRUE,
--                                        GTK_MOVEMENT_PAGES, 1);
--
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_Up, GDK_CONTROL_MASK, "move-cursor", 2,
--                                    G_TYPE_ENUM, GTK_MOVEMENT_BUFFER_ENDS,
--                                    G_TYPE_INT, -1);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_Down, GDK_CONTROL_MASK, "move-cursor", 2,
--                                    G_TYPE_ENUM, GTK_MOVEMENT_BUFFER_ENDS,
--                                    G_TYPE_INT, 1);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_Right, 0, "move-cursor", 2,
--                                    G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
--                                    G_TYPE_INT, 1);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_Left, 0, "move-cursor", 2,
--                                    G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
--                                    G_TYPE_INT, -1);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_Tab, 0, "move-cursor", 2,
--                                    G_TYPE_ENUM, GTK_MOVEMENT_LOGICAL_POSITIONS,
--                                    G_TYPE_INT, 1);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_Tab, GDK_SHIFT_MASK, "move-cursor", 2,
--                                    G_TYPE_ENUM, GTK_MOVEMENT_LOGICAL_POSITIONS,
--                                    G_TYPE_INT, -1);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_KP_Right, 0, "move-cursor", 2,
--                                    G_TYPE_ENUM, GTK_MOVEMENT_DISPLAY_LINE_ENDS,
--                                    G_TYPE_INT, 1);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_KP_Left, 0, "move-cursor", 2,
--                                    G_TYPE_ENUM, GTK_MOVEMENT_DISPLAY_LINE_ENDS,
--                                    G_TYPE_INT, -1);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_Right, GDK_CONTROL_MASK,
--                                    "move-cursor", 2,
--                                    G_TYPE_ENUM, GTK_MOVEMENT_DISPLAY_LINE_ENDS,
--                                    G_TYPE_INT, 1);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_Left, GDK_CONTROL_MASK,
--                                    "move-cursor", 2,
--                                    G_TYPE_ENUM, GTK_MOVEMENT_DISPLAY_LINE_ENDS,
--                                    G_TYPE_INT, -1);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_KP_Right, GDK_CONTROL_MASK,
--                                    "move-cursor", 2,
--                                    G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
--                                    G_TYPE_INT, 1);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_KP_Left, GDK_CONTROL_MASK,
--                                    "move-cursor", 2,
--                                    G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
--                                    G_TYPE_INT, -1);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_f, GDK_CONTROL_MASK, "start-interactive-search", 0);
--
--      gtk_binding_entry_add_signal (binding_set[i], GDK_F, GDK_CONTROL_MASK, "start-interactive-search", 0);
--    }
--
--  gtk_binding_entry_add_signal (binding_set[0], GDK_space, GDK_CONTROL_MASK, "toggle-cursor-row", 0);
--  gtk_binding_entry_add_signal (binding_set[0], GDK_KP_Space, GDK_CONTROL_MASK, "toggle-cursor-row", 0);
--
--  gtk_binding_entry_add_signal (binding_set[0], GDK_a, GDK_CONTROL_MASK, "select-all", 0);
--  gtk_binding_entry_add_signal (binding_set[0], GDK_slash, GDK_CONTROL_MASK, "select-all", 0);
--
--  gtk_binding_entry_add_signal (binding_set[0], GDK_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect-all", 0);
--  gtk_binding_entry_add_signal (binding_set[0], GDK_backslash, GDK_CONTROL_MASK, "unselect-all", 0);
--
--  gtk_binding_entry_add_signal (binding_set[0], GDK_space, GDK_SHIFT_MASK, "select-cursor-row", 1,
--                              G_TYPE_BOOLEAN, TRUE,
--                                G_TYPE_INT, PSPP_SHEET_SELECT_MODE_EXTEND);
--  gtk_binding_entry_add_signal (binding_set[0], GDK_KP_Space, GDK_SHIFT_MASK, "select-cursor-row", 1,
--                              G_TYPE_BOOLEAN, TRUE,
--                                G_TYPE_INT, PSPP_SHEET_SELECT_MODE_EXTEND);
--
--  gtk_binding_entry_add_signal (binding_set[0], GDK_space, 0, "select-cursor-row", 1,
--                              G_TYPE_BOOLEAN, TRUE,
--                                G_TYPE_INT, 0);
--  gtk_binding_entry_add_signal (binding_set[0], GDK_KP_Space, 0, "select-cursor-row", 1,
--                              G_TYPE_BOOLEAN, TRUE,
--                                G_TYPE_INT, 0);
--  gtk_binding_entry_add_signal (binding_set[0], GDK_Return, 0, "select-cursor-row", 1,
--                              G_TYPE_BOOLEAN, TRUE,
--                                G_TYPE_INT, 0);
--  gtk_binding_entry_add_signal (binding_set[0], GDK_ISO_Enter, 0, "select-cursor-row", 1,
--                              G_TYPE_BOOLEAN, TRUE,
--                                G_TYPE_INT, 0);
--  gtk_binding_entry_add_signal (binding_set[0], GDK_KP_Enter, 0, "select-cursor-row", 1,
--                              G_TYPE_BOOLEAN, TRUE,
--                                G_TYPE_INT, 0);
--
--  gtk_binding_entry_add_signal (binding_set[0], GDK_BackSpace, 0, "select-cursor-parent", 0);
--  gtk_binding_entry_add_signal (binding_set[0], GDK_BackSpace, GDK_CONTROL_MASK, "select-cursor-parent", 0);
--
--  g_type_class_add_private (o_class, sizeof (PsppSheetViewPrivate));
--}
--
--static void
--pspp_sheet_view_buildable_init (GtkBuildableIface *iface)
--{
--  iface->add_child = pspp_sheet_view_buildable_add_child;
--}
--
--static void
--pspp_sheet_view_init (PsppSheetView *tree_view)
--{
--  tree_view->priv = G_TYPE_INSTANCE_GET_PRIVATE (tree_view, PSPP_TYPE_SHEET_VIEW, PsppSheetViewPrivate);
--
--  gtk_widget_set_can_focus (GTK_WIDGET (tree_view), TRUE);
--  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (tree_view), FALSE);
--
--  tree_view->priv->flags =  PSPP_SHEET_VIEW_DRAW_KEYFOCUS
--                            | PSPP_SHEET_VIEW_HEADERS_VISIBLE;
--
--  /* We need some padding */
--  tree_view->priv->selected = range_tower_create ();
--  tree_view->priv->dy = 0;
--  tree_view->priv->cursor_offset = 0;
--  tree_view->priv->n_columns = 0;
--  tree_view->priv->header_height = 1;
--  tree_view->priv->x_drag = 0;
--  tree_view->priv->drag_pos = -1;
--  tree_view->priv->header_has_focus = FALSE;
--  tree_view->priv->pressed_button = -1;
--  tree_view->priv->press_start_x = -1;
--  tree_view->priv->press_start_y = -1;
--  tree_view->priv->reorderable = FALSE;
--  tree_view->priv->presize_handler_timer = 0;
--  tree_view->priv->scroll_sync_timer = 0;
--  tree_view->priv->fixed_height = -1;
--  tree_view->priv->fixed_height_set = FALSE;
--  pspp_sheet_view_set_adjustments (tree_view, NULL, NULL);
--  tree_view->priv->selection = _pspp_sheet_selection_new_with_tree_view (tree_view);
--  tree_view->priv->enable_search = TRUE;
--  tree_view->priv->search_column = -1;
--  tree_view->priv->search_position_func = pspp_sheet_view_search_position_func;
--  tree_view->priv->search_equal_func = pspp_sheet_view_search_equal_func;
--  tree_view->priv->search_custom_entry_set = FALSE;
--  tree_view->priv->typeselect_flush_timeout = 0;
--  tree_view->priv->init_hadjust_value = TRUE;    
--  tree_view->priv->width = 0;
--          
--  tree_view->priv->hover_selection = FALSE;
--
--  tree_view->priv->rubber_banding_enable = FALSE;
--
--  tree_view->priv->grid_lines = PSPP_SHEET_VIEW_GRID_LINES_NONE;
--
--  tree_view->priv->tooltip_column = -1;
--
--  tree_view->priv->special_cells = PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT;
--
--  tree_view->priv->post_validation_flag = FALSE;
--
--  tree_view->priv->last_button_x = -1;
--  tree_view->priv->last_button_y = -1;
--
--  tree_view->priv->event_last_x = -10000;
--  tree_view->priv->event_last_y = -10000;
--
--  tree_view->priv->prelight_node = -1;
--  tree_view->priv->rubber_band_start_node = -1;
--  tree_view->priv->rubber_band_end_node = -1;
--
--  tree_view->priv->anchor_column = NULL;
--
--  tree_view->priv->button_style = NULL;
--
--  tree_view->dispose_has_run = FALSE;
--
--  pspp_sheet_view_do_set_vadjustment (tree_view, NULL);
--  pspp_sheet_view_do_set_hadjustment (tree_view, NULL);
--  gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (tree_view)),
--                               GTK_STYLE_CLASS_VIEW);
--}
--
--\f
--
--/* GObject Methods
-- */
--
--static void
--pspp_sheet_view_set_property (GObject         *object,
--                          guint            prop_id,
--                          const GValue    *value,
--                          GParamSpec      *pspec)
--{
--  PsppSheetView *tree_view;
--
--  tree_view = PSPP_SHEET_VIEW (object);
--
--  switch (prop_id)
--    {
--    case PROP_MODEL:
--      pspp_sheet_view_set_model (tree_view, g_value_get_object (value));
--      break;
--    case PROP_HADJUSTMENT:
--      pspp_sheet_view_do_set_hadjustment (tree_view, g_value_get_object (value));
--      break;
--    case PROP_VADJUSTMENT:
--      pspp_sheet_view_do_set_vadjustment (tree_view, g_value_get_object (value));
--      break;
--    case PROP_HSCROLL_POLICY:
--      tree_view->priv->hscroll_policy = g_value_get_enum (value);
--      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
--      break;
--    case PROP_VSCROLL_POLICY:
--      tree_view->priv->vscroll_policy = g_value_get_enum (value);
--      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
--      break;
--     case PROP_HEADERS_VISIBLE:
--      pspp_sheet_view_set_headers_visible (tree_view, g_value_get_boolean (value));
--      break;
--    case PROP_HEADERS_CLICKABLE:
--      pspp_sheet_view_set_headers_clickable (tree_view, g_value_get_boolean (value));
--      break;
--    case PROP_REORDERABLE:
--      pspp_sheet_view_set_reorderable (tree_view, g_value_get_boolean (value));
--      break;
--    case PROP_RULES_HINT:
--      pspp_sheet_view_set_rules_hint (tree_view, g_value_get_boolean (value));
--      break;
--    case PROP_ENABLE_SEARCH:
--      pspp_sheet_view_set_enable_search (tree_view, g_value_get_boolean (value));
--      break;
--    case PROP_SEARCH_COLUMN:
--      pspp_sheet_view_set_search_column (tree_view, g_value_get_int (value));
--      break;
--    case PROP_HOVER_SELECTION:
--      tree_view->priv->hover_selection = g_value_get_boolean (value);
--      break;
--    case PROP_RUBBER_BANDING:
--      tree_view->priv->rubber_banding_enable = g_value_get_boolean (value);
--      break;
--    case PROP_ENABLE_GRID_LINES:
--      pspp_sheet_view_set_grid_lines (tree_view, g_value_get_enum (value));
--      break;
--    case PROP_TOOLTIP_COLUMN:
--      pspp_sheet_view_set_tooltip_column (tree_view, g_value_get_int (value));
--      break;
--    case PROP_SPECIAL_CELLS:
--      pspp_sheet_view_set_special_cells (tree_view, g_value_get_enum (value));
--      break;
--    case PROP_FIXED_HEIGHT:
--      pspp_sheet_view_set_fixed_height (tree_view, g_value_get_int (value));
--      break;
--    case PROP_FIXED_HEIGHT_SET:
--      if (g_value_get_boolean (value))
--        {
--          if (!tree_view->priv->fixed_height_set
--              && tree_view->priv->fixed_height >= 0)
--            {
--              tree_view->priv->fixed_height_set = true;
--              g_object_notify (G_OBJECT (tree_view), "fixed-height-set");
--            }
--        }
--      else
--        {
--          if (tree_view->priv->fixed_height_set)
--            {
--              tree_view->priv->fixed_height_set = false;
--              g_object_notify (G_OBJECT (tree_view), "fixed-height-set");
--              install_presize_handler (tree_view);
--            }
--        }
--      break;
--    default:
--      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
--      break;
--    }
--}
--
--static void
--pspp_sheet_view_get_property (GObject    *object,
--                          guint       prop_id,
--                          GValue     *value,
--                          GParamSpec *pspec)
--{
--  PsppSheetView *tree_view;
--
--  tree_view = PSPP_SHEET_VIEW (object);
--
--  switch (prop_id)
--    {
--    case PROP_MODEL:
--      g_value_set_object (value, tree_view->priv->model);
--      break;
--    case PROP_HADJUSTMENT:
--      g_value_set_object (value, tree_view->priv->hadjustment);
--      break;
--    case PROP_VADJUSTMENT:
--      g_value_set_object (value, tree_view->priv->vadjustment);
--      break;
--    case PROP_HSCROLL_POLICY:
--      g_value_set_enum (value, tree_view->priv->hscroll_policy);
--      break;
--    case PROP_VSCROLL_POLICY:
--      g_value_set_enum (value, tree_view->priv->vscroll_policy);
--      break;
--    case PROP_HEADERS_VISIBLE:
--      g_value_set_boolean (value, pspp_sheet_view_get_headers_visible (tree_view));
--      break;
--    case PROP_HEADERS_CLICKABLE:
--      g_value_set_boolean (value, pspp_sheet_view_get_headers_clickable (tree_view));
--      break;
--    case PROP_REORDERABLE:
--      g_value_set_boolean (value, tree_view->priv->reorderable);
--      break;
--    case PROP_RULES_HINT:
--      g_value_set_boolean (value, tree_view->priv->has_rules);
--      break;
--    case PROP_ENABLE_SEARCH:
--      g_value_set_boolean (value, tree_view->priv->enable_search);
--      break;
--    case PROP_SEARCH_COLUMN:
--      g_value_set_int (value, tree_view->priv->search_column);
--      break;
--    case PROP_HOVER_SELECTION:
--      g_value_set_boolean (value, tree_view->priv->hover_selection);
--      break;
--    case PROP_RUBBER_BANDING:
--      g_value_set_boolean (value, tree_view->priv->rubber_banding_enable);
--      break;
--    case PROP_ENABLE_GRID_LINES:
--      g_value_set_enum (value, tree_view->priv->grid_lines);
--      break;
--    case PROP_TOOLTIP_COLUMN:
--      g_value_set_int (value, tree_view->priv->tooltip_column);
--      break;
--    case PROP_SPECIAL_CELLS:
--      g_value_set_enum (value, tree_view->priv->special_cells);
--      break;
--    case PROP_FIXED_HEIGHT:
--      g_value_set_int (value, pspp_sheet_view_get_fixed_height (tree_view));
--      break;
--    case PROP_FIXED_HEIGHT_SET:
--      g_value_set_boolean (value, tree_view->priv->fixed_height_set);
--      break;
--    default:
--      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
--      break;
--    }
--}
--
--static void
--pspp_sheet_view_dispose (GObject *object)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (object);
--
--  if (tree_view->dispose_has_run)
--    return;
--
--  tree_view->dispose_has_run = TRUE;
--
--  if (tree_view->priv->selection != NULL)
--    {
--      _pspp_sheet_selection_set_tree_view (tree_view->priv->selection, NULL);
--      g_object_unref (tree_view->priv->selection);
--      tree_view->priv->selection = NULL;
--    }
--
--  if (tree_view->priv->hadjustment)
--    {
--      g_object_unref (tree_view->priv->hadjustment);
--      tree_view->priv->hadjustment = NULL;
--    }
--  if (tree_view->priv->vadjustment)
--    {
--      g_object_unref (tree_view->priv->vadjustment);
--      tree_view->priv->vadjustment = NULL;
--    }
--
--  if (tree_view->priv->button_style)
--    {
--      g_object_unref (tree_view->priv->button_style);
--      tree_view->priv->button_style = NULL;
--    }
--
--
--  G_OBJECT_CLASS (pspp_sheet_view_parent_class)->dispose (object);
--}
--
--\f
--
--static void
--pspp_sheet_view_buildable_add_child (GtkBuildable *tree_view,
--                                 GtkBuilder  *builder,
--                                 GObject     *child,
--                                 const gchar *type)
--{
--  pspp_sheet_view_append_column (PSPP_SHEET_VIEW (tree_view), PSPP_SHEET_VIEW_COLUMN (child));
--}
--
--static void
--pspp_sheet_view_finalize (GObject *object)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (object);
--
--  pspp_sheet_view_stop_editing (tree_view, TRUE);
--
--  if (tree_view->priv->selected != NULL)
--    {
--      range_tower_destroy (tree_view->priv->selected);
--      tree_view->priv->selected = NULL;
--    }
--
--
--  tree_view->priv->prelight_node = -1;
--
--
--  if (tree_view->priv->scroll_to_path != NULL)
--    {
--      gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
--      tree_view->priv->scroll_to_path = NULL;
--    }
--
--  if (tree_view->priv->drag_dest_row != NULL)
--    {
--      gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
--      tree_view->priv->drag_dest_row = NULL;
--    }
--
--  if (tree_view->priv->top_row != NULL)
--    {
--      gtk_tree_row_reference_free (tree_view->priv->top_row);
--      tree_view->priv->top_row = NULL;
--    }
--
--  if (tree_view->priv->column_drop_func_data &&
--      tree_view->priv->column_drop_func_data_destroy)
--    {
--      tree_view->priv->column_drop_func_data_destroy (tree_view->priv->column_drop_func_data);
--      tree_view->priv->column_drop_func_data = NULL;
--    }
--
--  if (tree_view->priv->destroy_count_destroy &&
--      tree_view->priv->destroy_count_data)
--    {
--      tree_view->priv->destroy_count_destroy (tree_view->priv->destroy_count_data);
--      tree_view->priv->destroy_count_data = NULL;
--    }
--
--  gtk_tree_row_reference_free (tree_view->priv->cursor);
--  tree_view->priv->cursor = NULL;
--
--  gtk_tree_row_reference_free (tree_view->priv->anchor);
--  tree_view->priv->anchor = NULL;
--
--  /* destroy interactive search dialog */
--  if (tree_view->priv->search_window)
--    {
--      gtk_widget_destroy (tree_view->priv->search_window);
--      tree_view->priv->search_window = NULL;
--      tree_view->priv->search_entry = NULL;
--      if (tree_view->priv->typeselect_flush_timeout)
--      {
--        g_source_remove (tree_view->priv->typeselect_flush_timeout);
--        tree_view->priv->typeselect_flush_timeout = 0;
--      }
--    }
--
--  if (tree_view->priv->search_destroy && tree_view->priv->search_user_data)
--    {
--      tree_view->priv->search_destroy (tree_view->priv->search_user_data);
--      tree_view->priv->search_user_data = NULL;
--    }
--
--  if (tree_view->priv->search_position_destroy && tree_view->priv->search_position_user_data)
--    {
--      tree_view->priv->search_position_destroy (tree_view->priv->search_position_user_data);
--      tree_view->priv->search_position_user_data = NULL;
--    }
--
--  pspp_sheet_view_set_model (tree_view, NULL);
--
--
--  G_OBJECT_CLASS (pspp_sheet_view_parent_class)->finalize (object);
--}
--
--\f
--
--/* GtkWidget Methods
-- */
--
--/* GtkWidget::map helper */
--static void
--pspp_sheet_view_map_buttons (PsppSheetView *tree_view)
--{
--  GList *list;
--
--  g_return_if_fail (gtk_widget_get_mapped (GTK_WIDGET (tree_view)));
--
--  if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE))
--    {
--      PsppSheetViewColumn *column;
--
--      for (list = tree_view->priv->columns; list; list = list->next)
--      {
--        column = list->data;
--          if (column->button != NULL &&
--              gtk_widget_get_visible (column->button) &&
--              !gtk_widget_get_mapped (column->button))
--            gtk_widget_map (column->button);
--      }
--      for (list = tree_view->priv->columns; list; list = list->next)
--      {
--        column = list->data;
--        if (column->visible == FALSE || column->window == NULL)
--          continue;
--        if (column->resizable)
--          {
--            gdk_window_raise (column->window);
--            gdk_window_show (column->window);
--          }
--        else
--          gdk_window_hide (column->window);
--      }
--      gdk_window_show (tree_view->priv->header_window);
--    }
--}
--
--static void
--pspp_sheet_view_map (GtkWidget *widget)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--  GList *tmp_list;
--
--  gtk_widget_set_mapped (widget, TRUE);
--
--  tmp_list = tree_view->priv->children;
--  while (tmp_list)
--    {
--      PsppSheetViewChild *child = tmp_list->data;
--      tmp_list = tmp_list->next;
--
--      if (gtk_widget_get_visible (child->widget))
--      {
--        if (!gtk_widget_get_mapped (child->widget))
--          gtk_widget_map (child->widget);
--      }
--    }
--  gdk_window_show (tree_view->priv->bin_window);
--
--  pspp_sheet_view_map_buttons (tree_view);
--
--  gdk_window_show (gtk_widget_get_window (widget));
--}
--
--static void
--pspp_sheet_view_realize (GtkWidget *widget)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--  GList *tmp_list;
--  GdkWindow *window;
--  GdkWindowAttr attributes;
--  gint attributes_mask;
--  GtkAllocation allocation;
--
--  gtk_widget_set_realized (widget, TRUE);
--
--  gtk_widget_get_allocation (widget, &allocation);
--
--  /* Make the main, clipping window */
--  attributes.window_type = GDK_WINDOW_CHILD;
--  attributes.x =      allocation.x;
--  attributes.y =      allocation.y;
--  attributes.width =  allocation.width;
--  attributes.height = allocation.height;
--  attributes.wclass = GDK_INPUT_OUTPUT;
--  attributes.visual = gtk_widget_get_visual (widget);
--  attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
--
--  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
--
--  window = gdk_window_new (gtk_widget_get_parent_window (widget),
--                           &attributes, attributes_mask);
--  gtk_widget_set_window (widget, window);
--
--  gtk_widget_register_window (widget, window);
--  gtk_widget_get_allocation (widget, &allocation);
--
--  /* Make the window for the tree */
--  attributes.x = 0;
--  attributes.y = TREE_VIEW_HEADER_HEIGHT (tree_view);
--  attributes.width = MAX (tree_view->priv->width, allocation.width);
--  attributes.height = allocation.height;
--  attributes.event_mask = (GDK_EXPOSURE_MASK |
--                           GDK_SCROLL_MASK |
--                           GDK_POINTER_MOTION_MASK |
--                           GDK_ENTER_NOTIFY_MASK |
--                           GDK_LEAVE_NOTIFY_MASK |
--                           GDK_BUTTON_PRESS_MASK |
--                           GDK_BUTTON_RELEASE_MASK |
--                           gtk_widget_get_events (widget));
--
--  tree_view->priv->bin_window = gdk_window_new (window,
--                                              &attributes, attributes_mask);
--  gtk_widget_register_window (widget, tree_view->priv->bin_window);
--  gtk_widget_get_allocation (widget, &allocation);
--
--  /* Make the column header window */
--  attributes.x = 0;
--  attributes.y = 0;
--  attributes.width = MAX (tree_view->priv->width, allocation.width);
--  attributes.height = tree_view->priv->header_height;
--  attributes.event_mask = (GDK_EXPOSURE_MASK |
--                           GDK_SCROLL_MASK |
--                           GDK_BUTTON_PRESS_MASK |
--                           GDK_BUTTON_RELEASE_MASK |
--                           GDK_KEY_PRESS_MASK |
--                           GDK_KEY_RELEASE_MASK |
--                           gtk_widget_get_events (widget));
--
--  tree_view->priv->header_window = gdk_window_new (window,
--                                                 &attributes, attributes_mask);
--  gtk_widget_register_window (widget, tree_view->priv->header_window);
--
--  { /* Ensure Background */
--    GtkStyleContext *context;
--
--    context = gtk_widget_get_style_context (GTK_WIDGET (tree_view));
--
--    gtk_style_context_set_background (context, gtk_widget_get_window (GTK_WIDGET (tree_view)));
--    gtk_style_context_set_background (context, tree_view->priv->header_window);
--  }
--
--  tmp_list = tree_view->priv->children;
--  while (tmp_list)
--    {
--      PsppSheetViewChild *child = tmp_list->data;
--      tmp_list = tmp_list->next;
--
--      gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
--    }
--
--  for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
--    _pspp_sheet_view_column_realize_button (PSPP_SHEET_VIEW_COLUMN (tmp_list->data));
--
--  /* Need to call those here, since they create GCs */
--  pspp_sheet_view_set_grid_lines (tree_view, tree_view->priv->grid_lines);
--
--  install_presize_handler (tree_view); 
--}
--
--static void
--pspp_sheet_view_unrealize (GtkWidget *widget)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--  PsppSheetViewPrivate *priv = tree_view->priv;
--  GList *list;
--
--  GTK_WIDGET_CLASS (pspp_sheet_view_parent_class)->unrealize (widget);
--
--  if (priv->scroll_timeout != 0)
--    {
--      g_source_remove (priv->scroll_timeout);
--      priv->scroll_timeout = 0;
--    }
--
--  if (priv->open_dest_timeout != 0)
--    {
--      g_source_remove (priv->open_dest_timeout);
--      priv->open_dest_timeout = 0;
--    }
--
--  if (priv->presize_handler_timer != 0)
--    {
--      g_source_remove (priv->presize_handler_timer);
--      priv->presize_handler_timer = 0;
--    }
--
--  if (priv->validate_rows_timer != 0)
--    {
--      g_source_remove (priv->validate_rows_timer);
--      priv->validate_rows_timer = 0;
--    }
--
--  if (priv->scroll_sync_timer != 0)
--    {
--      g_source_remove (priv->scroll_sync_timer);
--      priv->scroll_sync_timer = 0;
--    }
--
--  if (priv->typeselect_flush_timeout)
--    {
--      g_source_remove (priv->typeselect_flush_timeout);
--      priv->typeselect_flush_timeout = 0;
--    }
--  
--  for (list = priv->columns; list; list = list->next)
--    _pspp_sheet_view_column_unrealize_button (PSPP_SHEET_VIEW_COLUMN (list->data));
--
--  gdk_window_set_user_data (priv->bin_window, NULL);
--  gdk_window_destroy (priv->bin_window);
--  priv->bin_window = NULL;
--
--  gdk_window_set_user_data (priv->header_window, NULL);
--  gdk_window_destroy (priv->header_window);
--  priv->header_window = NULL;
--
--  if (priv->drag_window)
--    {
--      gdk_window_set_user_data (priv->drag_window, NULL);
--      gdk_window_destroy (priv->drag_window);
--      priv->drag_window = NULL;
--    }
--
--  if (priv->drag_highlight_window)
--    {
--      gdk_window_set_user_data (priv->drag_highlight_window, NULL);
--      gdk_window_destroy (priv->drag_highlight_window);
--      priv->drag_highlight_window = NULL;
--    }
--
--  if (tree_view->priv->columns != NULL)
--    {
--      list = tree_view->priv->columns;
--      while (list)
--      {
--        PsppSheetViewColumn *column;
--        column = PSPP_SHEET_VIEW_COLUMN (list->data);
--        list = list->next;
--        pspp_sheet_view_remove_column (tree_view, column);
--      }
--      tree_view->priv->columns = NULL;
--    }
--}
--
--/* GtkWidget::size_request helper */
--static void
--pspp_sheet_view_size_request_columns (PsppSheetView *tree_view)
--{
--  GList *list;
--
--  tree_view->priv->header_height = 0;
--
--  if (tree_view->priv->model)
--    {
--      for (list = tree_view->priv->columns; list; list = list->next)
--        {
--          GtkRequisition requisition;
--          PsppSheetViewColumn *column = list->data;
--
--          pspp_sheet_view_column_size_request (column, &requisition);
--        column->button_request = requisition.width;
--          tree_view->priv->header_height = MAX (tree_view->priv->header_height, requisition.height);
--        }
--    }
--}
--
--
--/* Called only by ::size_request */
--static void
--pspp_sheet_view_update_size (PsppSheetView *tree_view)
--{
--  GList *list;
--  PsppSheetViewColumn *column;
--  gint i;
--
--  if (tree_view->priv->model == NULL)
--    {
--      tree_view->priv->width = 0;
--      tree_view->priv->prev_width = 0;                   
--      tree_view->priv->height = 0;
--      return;
--    }
--
--  tree_view->priv->prev_width = tree_view->priv->width;  
--  tree_view->priv->width = 0;
--
--  /* keep this in sync with size_allocate below */
--  for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
--    {
--      gint real_requested_width = 0;
--      column = list->data;
--      if (!column->visible)
--      continue;
--
--      if (column->use_resized_width)
--      {
--        real_requested_width = column->resized_width;
--      }
--      else
--      {
--        real_requested_width = column->fixed_width;
--      }
--
--      if (column->min_width != -1)
--      real_requested_width = MAX (real_requested_width, column->min_width);
--      if (column->max_width != -1)
--      real_requested_width = MIN (real_requested_width, column->max_width);
--
--      tree_view->priv->width += real_requested_width;
--    }
--
--  tree_view->priv->height = tree_view->priv->fixed_height * tree_view->priv->row_count;
--}
--
--static void
--pspp_sheet_view_size_request (GtkWidget      *widget,
--                          GtkRequisition *requisition)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--  GList *tmp_list;
--
--  /* we validate some rows initially just to make sure we have some size. 
--   * In practice, with a lot of static lists, this should get a good width.
--   */
--  initialize_fixed_height_mode (tree_view);
--  pspp_sheet_view_size_request_columns (tree_view);
--  pspp_sheet_view_update_size (PSPP_SHEET_VIEW (widget));
--
--  requisition->width = tree_view->priv->width;
--  requisition->height = tree_view->priv->height + TREE_VIEW_HEADER_HEIGHT (tree_view);
--
--  tmp_list = tree_view->priv->children;
--
--  while (tmp_list)
--    {
--      PsppSheetViewChild *child = tmp_list->data;
--      GtkRequisition child_requisition;
--
--      tmp_list = tmp_list->next;
--
--      if (gtk_widget_get_visible (child->widget))
--      {
--        gtk_widget_get_preferred_size (child->widget, NULL, &child_requisition);
--      }
--    }
--}
--
--static void
--invalidate_column (PsppSheetView       *tree_view,
--                   PsppSheetViewColumn *column)
--{
--  gint column_offset = 0;
--  GList *list;
--  GtkWidget *widget = GTK_WIDGET (tree_view);
--  gboolean rtl;
--
--  if (!gtk_widget_get_realized (widget))
--    return;
--
--  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--  for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
--       list;
--       list = (rtl ? list->prev : list->next))
--    {
--      PsppSheetViewColumn *tmpcolumn = list->data;
--      if (tmpcolumn == column)
--      {
--        GdkRectangle invalid_rect;
--        GtkAllocation allocation;
--
--        gtk_widget_get_allocation (widget, &allocation);
--        invalid_rect.x = column_offset;
--        invalid_rect.y = 0;
--        invalid_rect.width = column->width;
--        invalid_rect.height = allocation.height;
--        
--        gdk_window_invalidate_rect (gtk_widget_get_window (widget), &invalid_rect, TRUE);
--        break;
--      }
--      
--      column_offset += tmpcolumn->width;
--    }
--}
--
--static void
--invalidate_last_column (PsppSheetView *tree_view)
--{
--  GList *last_column;
--  gboolean rtl;
--
--  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--
--  for (last_column = (rtl ? g_list_first (tree_view->priv->columns) : g_list_last (tree_view->priv->columns));
--       last_column;
--       last_column = (rtl ? last_column->next : last_column->prev))
--    {
--      if (PSPP_SHEET_VIEW_COLUMN (last_column->data)->visible)
--        {
--          invalidate_column (tree_view, last_column->data);
--          return;
--        }
--    }
--}
--
--static gint
--pspp_sheet_view_get_real_requested_width_from_column (PsppSheetView       *tree_view,
--                                                    PsppSheetViewColumn *column)
--{
--  gint real_requested_width;
--
--  if (column->use_resized_width)
--    {
--      real_requested_width = column->resized_width;
--    }
--  else
--    {
--      real_requested_width = column->fixed_width;
--    }
--
--  if (column->min_width != -1)
--    real_requested_width = MAX (real_requested_width, column->min_width);
--  if (column->max_width != -1)
--    real_requested_width = MIN (real_requested_width, column->max_width);
--
--  return real_requested_width;
--}
--
--static gboolean
--span_intersects (int a0, int a_width,
--                 int b0, int b_width)
--{
--  int a1 = a0 + a_width;
--  int b1 = b0 + b_width;
--  return (a0 >= b0 && a0 < b1) || (b0 >= a0 && b0 < a1);
--}
--
--/* GtkWidget::size_allocate helper */
--static void
--pspp_sheet_view_size_allocate_columns (GtkWidget *widget,
--                                   gboolean  *width_changed)
--{
--  PsppSheetView *tree_view;
--  GList *list, *first_column, *last_column;
--  PsppSheetViewColumn *column;
--  GtkAllocation col_allocation;
--  GtkAllocation allocation;
--  gint width = 0;
--  gint extra, extra_per_column;
--  gint full_requested_width = 0;
--  gint number_of_expand_columns = 0;
--  gboolean column_changed = FALSE;
--  gboolean rtl;
--
--  tree_view = PSPP_SHEET_VIEW (widget);
--
--  for (last_column = g_list_last (tree_view->priv->columns);
--       last_column && !(PSPP_SHEET_VIEW_COLUMN (last_column->data)->visible);
--       last_column = last_column->prev)
--    ;
--
--  if (last_column == NULL)
--    return;
--
--  for (first_column = g_list_first (tree_view->priv->columns);
--       first_column && !(PSPP_SHEET_VIEW_COLUMN (first_column->data)->visible);
--       first_column = first_column->next)
--    ;
--
--  col_allocation.y = 0;
--  col_allocation.height = tree_view->priv->header_height;
--
--  rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
--
--  /* find out how many extra space and expandable columns we have */
--  for (list = tree_view->priv->columns; list != last_column->next; list = list->next)
--    {
--      column = (PsppSheetViewColumn *)list->data;
--
--      if (!column->visible)
--      continue;
--
--      full_requested_width += pspp_sheet_view_get_real_requested_width_from_column (tree_view, column);
--
--      if (column->expand)
--      number_of_expand_columns++;
--    }
--
--  gtk_widget_get_allocation (widget, &allocation);
--  extra = MAX (allocation.width - full_requested_width, 0);
--  if (number_of_expand_columns > 0)
--    extra_per_column = extra/number_of_expand_columns;
--  else
--    extra_per_column = 0;
--
--  for (list = (rtl ? last_column : first_column); 
--       list != (rtl ? first_column->prev : last_column->next);
--       list = (rtl ? list->prev : list->next)) 
--    {
--      gint real_requested_width = 0;
--      gint old_width;
--
--      column = list->data;
--      old_width = column->width;
--
--      if (!column->visible)
--      continue;
--
--      /* We need to handle the dragged button specially.
--       */
--      if (column == tree_view->priv->drag_column)
--      {
--        GtkAllocation drag_allocation;
--        drag_allocation.width =  gdk_window_get_width (tree_view->priv->drag_window);
--        drag_allocation.height = gdk_window_get_height (tree_view->priv->drag_window);
--        drag_allocation.x = 0;
--        drag_allocation.y = 0;
--          pspp_sheet_view_column_size_allocate (tree_view->priv->drag_column,
--                                                &drag_allocation);
--        width += drag_allocation.width;
--        continue;
--      }
--
--      real_requested_width = pspp_sheet_view_get_real_requested_width_from_column (tree_view, column);
--
--      col_allocation.x = width;
--      column->width = real_requested_width;
--
--      if (column->expand)
--      {
--        if (number_of_expand_columns == 1)
--          {
--            /* We add the remander to the last column as
--             * */
--            column->width += extra;
--          }
--        else
--          {
--            column->width += extra_per_column;
--            extra -= extra_per_column;
--            number_of_expand_columns --;
--          }
--      }
--
--      if (column->width != old_width)
--        g_object_notify (G_OBJECT (column), "width");
--
--      col_allocation.width = column->width;
--      width += column->width;
--
--      if (column->width > old_width)
--        column_changed = TRUE;
--
--      pspp_sheet_view_column_size_allocate (column, &col_allocation);
--
--      if (column->window)
--      gdk_window_move_resize (column->window,
--                                col_allocation.x + (rtl ? 0 : col_allocation.width) - TREE_VIEW_DRAG_WIDTH/2,
--                              col_allocation.y,
--                                TREE_VIEW_DRAG_WIDTH, col_allocation.height);
--    }
--
--  /* We change the width here.  The user might have been resizing columns,
--   * so the total width of the tree view changes.
--   */
--  tree_view->priv->width = width;
--  if (width_changed)
--    *width_changed = TRUE;
--
--  if (column_changed)
--    gtk_widget_queue_draw (GTK_WIDGET (tree_view));
--}
--
--static void
--update_childrens_allocation (PsppSheetView *tree_view)
--{
--  GList *tmp_list;
--  for (tmp_list = tree_view->priv->children; tmp_list; tmp_list = tmp_list->next)
--    {
--      PsppSheetViewChild *child = tmp_list->data;
--      GtkAllocation allocation;
--      GtkTreePath *path;
--
--      /* totally ignore our child's requisition */
--      path = _pspp_sheet_view_find_path (tree_view, child->node);
--      pspp_sheet_view_get_cell_area (tree_view, path, child->column, &allocation);
--      gtk_tree_path_free (path);
--      gtk_widget_size_allocate (child->widget, &allocation);
--    }
--}
--
--static void
--pspp_sheet_view_size_allocate (GtkWidget     *widget,
--                           GtkAllocation *allocation)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--  GList *tmp_list;
--  gboolean width_changed = FALSE;
--  GtkAllocation old_allocation;
--  gtk_widget_get_allocation (widget, &old_allocation);
--
--  if (allocation->width != old_allocation.width)
--    width_changed = TRUE;
--
--  if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL)   
--    allocation->x += allocation->width - tree_view->priv->width ;
--
--  gtk_widget_set_allocation (widget, allocation);
--
--  /* We size-allocate the columns first because the width of the
--   * tree view (used in updating the adjustments below) might change.
--   */
--  pspp_sheet_view_size_allocate_columns (widget, &width_changed);
--
--  gtk_adjustment_set_page_size (tree_view->priv->hadjustment, allocation->width);
--  gtk_adjustment_set_page_increment (tree_view->priv->hadjustment, allocation->width * 0.9);
--  gtk_adjustment_set_step_increment (tree_view->priv->hadjustment, allocation->width * 0.1);
--  gtk_adjustment_set_lower (tree_view->priv->hadjustment, 0);
--  gtk_adjustment_set_upper (tree_view->priv->hadjustment, MAX (gtk_adjustment_get_page_size (tree_view->priv->hadjustment), tree_view->priv->width));
--
--  if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL)   
--    {
--      if (allocation->width < tree_view->priv->width)
--        {
--        if (tree_view->priv->init_hadjust_value)
--          {
--            gtk_adjustment_set_value (tree_view->priv->hadjustment, MAX (tree_view->priv->width - allocation->width, 0));
--            tree_view->priv->init_hadjust_value = FALSE;
--          }
--        else if (allocation->width != old_allocation.width)
--          {
--            gtk_adjustment_set_value (tree_view->priv->hadjustment, CLAMP (gtk_adjustment_get_value (tree_view->priv->hadjustment) - allocation->width + old_allocation.width, 0, tree_view->priv->width - allocation->width));
--          }
--        else
--          gtk_adjustment_set_value (tree_view->priv->hadjustment, CLAMP (tree_view->priv->width - (tree_view->priv->prev_width - gtk_adjustment_get_value (tree_view->priv->hadjustment)), 0, tree_view->priv->width - allocation->width));
--      }
--      else
--        {
--        gtk_adjustment_set_value (tree_view->priv->hadjustment, 0);
--        tree_view->priv->init_hadjust_value = TRUE;
--      }
--    }
--  else
--    if (gtk_adjustment_get_value (tree_view->priv->hadjustment) + allocation->width > tree_view->priv->width)
--      gtk_adjustment_set_value (tree_view->priv->hadjustment, MAX (tree_view->priv->width - allocation->width, 0));
--
--  gtk_adjustment_changed (tree_view->priv->hadjustment);
--
--  gtk_adjustment_set_page_size (tree_view->priv->vadjustment, allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view));
--  gtk_adjustment_set_step_increment (tree_view->priv->vadjustment, gtk_adjustment_get_page_size (tree_view->priv->vadjustment) * 0.1);
--  gtk_adjustment_set_page_increment (tree_view->priv->vadjustment, gtk_adjustment_get_page_size (tree_view->priv->vadjustment) * 0.9);
--  gtk_adjustment_set_lower (tree_view->priv->vadjustment, 0);
--  gtk_adjustment_set_upper (tree_view->priv->vadjustment, MAX (gtk_adjustment_get_page_size (tree_view->priv->vadjustment), tree_view->priv->height));
--
--  gtk_adjustment_changed (tree_view->priv->vadjustment);
--
--  /* now the adjustments and window sizes are in sync, we can sync toprow/dy again */
--  if (tree_view->priv->height <= gtk_adjustment_get_page_size (tree_view->priv->vadjustment))
--    gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
--  else if (gtk_adjustment_get_value (tree_view->priv->vadjustment) + gtk_adjustment_get_page_size (tree_view->priv->vadjustment) > tree_view->priv->height)
--    gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
--                              tree_view->priv->height - gtk_adjustment_get_page_size (tree_view->priv->vadjustment));
--  else if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
--    pspp_sheet_view_top_row_to_dy (tree_view);
--  else
--    pspp_sheet_view_dy_to_top_row (tree_view);
--  
--  if (gtk_widget_get_realized (widget))
--    {
--      gdk_window_move_resize (gtk_widget_get_window (widget),
--                            allocation->x, allocation->y,
--                            allocation->width, allocation->height);
--      gdk_window_move_resize (tree_view->priv->header_window,
--                            - (gint) gtk_adjustment_get_value (tree_view->priv->hadjustment),
--                            0,
--                            MAX (tree_view->priv->width, allocation->width),
--                            tree_view->priv->header_height);
--      gdk_window_move_resize (tree_view->priv->bin_window,
--                            - (gint) gtk_adjustment_get_value (tree_view->priv->hadjustment),
--                            TREE_VIEW_HEADER_HEIGHT (tree_view),
--                            MAX (tree_view->priv->width, allocation->width),
--                            allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view));
--    }
--
--  if (tree_view->priv->row_count == 0)
--    invalidate_empty_focus (tree_view);
--
--  if (gtk_widget_get_realized (widget))
--    {
--      gboolean has_expand_column = FALSE;
--      for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
--      {
--        if (pspp_sheet_view_column_get_expand (PSPP_SHEET_VIEW_COLUMN (tmp_list->data)))
--          {
--            has_expand_column = TRUE;
--            break;
--          }
--      }
--
--      /* This little hack only works if we have an LTR locale, and no column has the  */
--      if (width_changed)
--      {
--        if (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_LTR &&
--            ! has_expand_column)
--          invalidate_last_column (tree_view);
--        else
--          gtk_widget_queue_draw (widget);
--      }
--      update_childrens_allocation(tree_view);
--    }
--
--  tree_view->priv->resized = TRUE;
--}
--
--/* Grabs the focus and unsets the PSPP_SHEET_VIEW_DRAW_KEYFOCUS flag */
--static void
--grab_focus_and_unset_draw_keyfocus (PsppSheetView *tree_view)
--{
--  GtkWidget *widget = GTK_WIDGET (tree_view);
--
--  if (gtk_widget_get_can_focus (widget) && !gtk_widget_has_focus (widget))
--    gtk_widget_grab_focus (widget);
--  PSPP_SHEET_VIEW_UNSET_FLAG (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS);
--}
--
--gboolean
--pspp_sheet_view_node_is_selected (PsppSheetView *tree_view,
--                                  int node)
--{
--  return node >= 0 && range_tower_contains (tree_view->priv->selected, node);
--}
--
--void
--pspp_sheet_view_node_select (PsppSheetView *tree_view,
--                             int node)
--{
--  range_tower_set1 (tree_view->priv->selected, node, 1);
--}
--
--void
--pspp_sheet_view_node_unselect (PsppSheetView *tree_view,
--                               int node)
--{
--  range_tower_set0 (tree_view->priv->selected, node, 1);
--}
--
--gint
--pspp_sheet_view_node_next (PsppSheetView *tree_view,
--                           gint node)
--{
--  return node + 1 < tree_view->priv->row_count ? node + 1 : -1;
--}
--
--gint
--pspp_sheet_view_node_prev (PsppSheetView *tree_view,
--                           gint node)
--{
--  return node > 0 ? node - 1 : -1;
--}
--
--static gboolean
--all_columns_selected (PsppSheetView *tree_view)
--{
--  GList *list;
--
--  for (list = tree_view->priv->columns; list; list = list->next)
--    {
--      PsppSheetViewColumn *column = list->data;
--      if (column->selectable && !column->selected)
--        return FALSE;
--    }
--
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_row_head_clicked (PsppSheetView *tree_view,
--                                  gint node,
--                                  PsppSheetViewColumn *column,
--                                  GdkEventButton *event)
--{
--  PsppSheetSelection *selection;
--  PsppSheetSelectionMode mode;
--  GtkTreePath *path;
--  gboolean update_anchor;
--  gboolean handled;
--  guint modifiers;
--
--  g_return_val_if_fail (tree_view != NULL, FALSE);
--  g_return_val_if_fail (column != NULL, FALSE);
--
--  selection = tree_view->priv->selection;
--  mode = pspp_sheet_selection_get_mode (selection);
--  if (mode != PSPP_SHEET_SELECTION_RECTANGLE)
--    return FALSE;
--
--  if (!column->row_head)
--    return FALSE;
--
--  if (event)
--    {
--      modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
--      if (event->type != GDK_BUTTON_PRESS
--          || (modifiers != GDK_CONTROL_MASK && modifiers != GDK_SHIFT_MASK))
--        return FALSE;
--    }
--  else
--    modifiers = 0;
--
--  path = gtk_tree_path_new_from_indices (node, -1);
--  if (event == NULL)
--    {
--      pspp_sheet_selection_unselect_all (selection);
--      pspp_sheet_selection_select_path (selection, path);
--      pspp_sheet_selection_select_all_columns (selection);
--      update_anchor = TRUE;
--      handled = TRUE;
--    }
--  else if (event->type == GDK_BUTTON_PRESS && event->button == 3)
--    {
--      if (pspp_sheet_selection_count_selected_rows (selection) <= 1
--          || !all_columns_selected (tree_view))
--        {
--          pspp_sheet_selection_unselect_all (selection);
--          pspp_sheet_selection_select_path (selection, path);
--          pspp_sheet_selection_select_all_columns (selection);
--          update_anchor = TRUE;
--          handled = FALSE;
--        }
--      else
--        update_anchor = handled = FALSE;
--    }
--  else if (event->type == GDK_BUTTON_PRESS && event->button == 1
--           && modifiers == GDK_CONTROL_MASK)
--    {
--      if (!all_columns_selected (tree_view))
--        {
--          pspp_sheet_selection_unselect_all (selection);
--          pspp_sheet_selection_select_all_columns (selection);
--        }
--
--      if (pspp_sheet_selection_path_is_selected (selection, path))
--        pspp_sheet_selection_unselect_path (selection, path);
--      else
--        pspp_sheet_selection_select_path (selection, path);
--      update_anchor = TRUE;
--      handled = TRUE;
--    }
--  else if (event->type == GDK_BUTTON_PRESS && event->button == 1
--           && modifiers == GDK_SHIFT_MASK)
--    {
--      GtkTreeRowReference *anchor = tree_view->priv->anchor;
--      GtkTreePath *anchor_path;
--
--      if (all_columns_selected (tree_view)
--          && gtk_tree_row_reference_valid (anchor))
--        {
--          update_anchor = FALSE;
--          anchor_path = gtk_tree_row_reference_get_path (anchor);
--        }
--      else
--        {
--          update_anchor = TRUE;
--          anchor_path = gtk_tree_path_copy (path);
--        }
--
--      pspp_sheet_selection_unselect_all (selection);
--      pspp_sheet_selection_select_range (selection, anchor_path, path);
--      pspp_sheet_selection_select_all_columns (selection);
--
--      gtk_tree_path_free (anchor_path);
--
--      handled = TRUE;
--    }
--  else
--    update_anchor = handled = FALSE;
--
--  if (update_anchor)
--    {
--      if (tree_view->priv->anchor)
--        gtk_tree_row_reference_free (tree_view->priv->anchor);
--      tree_view->priv->anchor =
--        gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
--                                          tree_view->priv->model,
--                                          path);
--    }
--
--  gtk_tree_path_free (path);
--  return handled;
--}
--
--static gboolean
--find_click (PsppSheetView *tree_view,
--            gint x, gint y,
--            gint *node,
--            PsppSheetViewColumn **column,
--            GdkRectangle *background_area,
--            GdkRectangle *cell_area)
--{
--  gint y_offset;
--  gboolean rtl;
--  GList *list;
--  gint new_y;
--
--  /* find the node that was clicked */
--  new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, y);
--  if (new_y < 0)
--    new_y = 0;
--  y_offset = -pspp_sheet_view_find_offset (tree_view, new_y, node);
--
--  if (*node < 0)
--    return FALSE;
--
--  background_area->y = y_offset + y;
--  background_area->height = ROW_HEIGHT (tree_view);
--  background_area->x = 0;
--
--  /* Let the column have a chance at selecting it. */
--  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--  for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
--       list; list = (rtl ? list->prev : list->next))
--    {
--      PsppSheetViewColumn *candidate = list->data;
--
--      if (!candidate->visible)
--        continue;
--
--      background_area->width = candidate->width;
--      if ((background_area->x > x) ||
--          (background_area->x + background_area->width <= x))
--        {
--          background_area->x += background_area->width;
--          continue;
--        }
--
--      /* we found the focus column */
--
--      pspp_sheet_view_adjust_cell_area (tree_view, candidate, background_area,
--                                        TRUE, cell_area);
--      *column = candidate;
--      return TRUE;
--    }
--
--  return FALSE;
--}
--
--static gboolean
--pspp_sheet_view_button_press (GtkWidget      *widget,
--                          GdkEventButton *event)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--  GList *list;
--  PsppSheetViewColumn *column = NULL;
--  gint i;
--  GdkRectangle background_area;
--  GdkRectangle cell_area;
--  gboolean rtl;
--
--  rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
--  pspp_sheet_view_stop_editing (tree_view, FALSE);
--
--
--  /* Because grab_focus can cause reentrancy, we delay grab_focus until after
--   * we're done handling the button press.
--   */
--
--  if (event->window == tree_view->priv->bin_window)
--    {
--      int node;
--      GtkTreePath *path;
--      gint dval;
--      gint pre_val, aft_val;
--      PsppSheetViewColumn *column = NULL;
--      GtkCellRenderer *focus_cell = NULL;
--      gboolean row_double_click = FALSE;
--
--      /* Empty tree? */
--      if (tree_view->priv->row_count == 0)
--      {
--        grab_focus_and_unset_draw_keyfocus (tree_view);
--        return TRUE;
--      }
--
--      if (!find_click (tree_view, event->x, event->y, &node, &column,
--                       &background_area, &cell_area))
--        {
--        grab_focus_and_unset_draw_keyfocus (tree_view);
--          return FALSE;
--        }
--
--      tree_view->priv->focus_column = column;
--
--      if (pspp_sheet_view_row_head_clicked (tree_view, node, column, event))
--        return TRUE;
--
--      /* select */
--      pre_val = gtk_adjustment_get_value (tree_view->priv->vadjustment);
--
--      path = _pspp_sheet_view_find_path (tree_view, node);
--
--      /* we only handle selection modifications on the first button press
--       */
--      if (event->type == GDK_BUTTON_PRESS)
--        {
--          PsppSheetSelectionMode mode = 0;
--
--          if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
--            mode |= PSPP_SHEET_SELECT_MODE_TOGGLE;
--          if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
--            mode |= PSPP_SHEET_SELECT_MODE_EXTEND;
--
--          focus_cell = _pspp_sheet_view_column_get_cell_at_pos (column, event->x - background_area.x);
--          if (focus_cell)
--            pspp_sheet_view_column_focus_cell (column, focus_cell);
--
--          if (event->state & GDK_CONTROL_MASK)
--            {
--              pspp_sheet_view_real_set_cursor (tree_view, path, FALSE, TRUE, mode);
--              pspp_sheet_view_real_toggle_cursor_row (tree_view);
--            }
--          else if (event->state & GDK_SHIFT_MASK)
--            {
--              pspp_sheet_view_real_set_cursor (tree_view, path, TRUE, TRUE, mode);
--              pspp_sheet_view_real_select_cursor_row (tree_view, FALSE, mode);
--            }
--          else
--            {
--              pspp_sheet_view_real_set_cursor (tree_view, path, TRUE, TRUE, 0);
--            }
--
--          if (tree_view->priv->anchor_column == NULL ||
--              !(event->state & GDK_SHIFT_MASK))
--            tree_view->priv->anchor_column = column;
--          pspp_sheet_selection_unselect_all_columns (tree_view->priv->selection);
--          pspp_sheet_selection_select_column_range (tree_view->priv->selection,
--                                                    tree_view->priv->anchor_column,
--                                                    column);
--        }
--
--      /* the treeview may have been scrolled because of _set_cursor,
--       * correct here
--       */
--
--      aft_val = gtk_adjustment_get_value (tree_view->priv->vadjustment);
--      dval = pre_val - aft_val;
--
--      cell_area.y += dval;
--      background_area.y += dval;
--
--      /* Save press to possibly begin a drag
--       */
--      if (!tree_view->priv->in_grab &&
--        tree_view->priv->pressed_button < 0)
--        {
--          tree_view->priv->pressed_button = event->button;
--          tree_view->priv->press_start_x = event->x;
--          tree_view->priv->press_start_y = event->y;
--          tree_view->priv->press_start_node = node;
--
--        if (tree_view->priv->rubber_banding_enable
--            && (tree_view->priv->selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
--                  tree_view->priv->selection->type == PSPP_SHEET_SELECTION_RECTANGLE))
--          {
--            tree_view->priv->press_start_y += tree_view->priv->dy;
--            tree_view->priv->rubber_band_x = event->x;
--            tree_view->priv->rubber_band_y = event->y + tree_view->priv->dy;
--            tree_view->priv->rubber_band_status = RUBBER_BAND_MAYBE_START;
--
--            if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
--              tree_view->priv->rubber_band_ctrl = TRUE;
--            if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
--              tree_view->priv->rubber_band_shift = TRUE;
--
--          }
--        }
--
--      /* Test if a double click happened on the same row. */
--      if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
--        {
--          int double_click_time, double_click_distance;
--
--          g_object_get (gtk_settings_get_for_screen (
--                          gtk_widget_get_screen (widget)),
--                        "gtk-double-click-time", &double_click_time,
--                        "gtk-double-click-distance", &double_click_distance,
--                        NULL);
--
--          /* Same conditions as _gdk_event_button_generate */
--          if (tree_view->priv->last_button_x != -1 &&
--              (event->time < tree_view->priv->last_button_time + double_click_time) &&
--              (ABS (event->x - tree_view->priv->last_button_x) <= double_click_distance) &&
--              (ABS (event->y - tree_view->priv->last_button_y) <= double_click_distance))
--            {
--              /* We do no longer compare paths of this row and the
--               * row clicked previously.  We use the double click
--               * distance to decide whether this is a valid click,
--               * allowing the mouse to slightly move over another row.
--               */
--              row_double_click = TRUE;
--
--              tree_view->priv->last_button_time = 0;
--              tree_view->priv->last_button_x = -1;
--              tree_view->priv->last_button_y = -1;
--            }
--          else
--            {
--              tree_view->priv->last_button_time = event->time;
--              tree_view->priv->last_button_x = event->x;
--              tree_view->priv->last_button_y = event->y;
--            }
--        }
--
--      if (row_double_click)
--      {
--        gtk_grab_remove (widget);
--        pspp_sheet_view_row_activated (tree_view, path, column);
--
--          if (tree_view->priv->pressed_button == event->button)
--            tree_view->priv->pressed_button = -1;
--      }
--
--      gtk_tree_path_free (path);
--
--      /* If we activated the row through a double click we don't want to grab
--       * focus back, as moving focus to another widget is pretty common.
--       */
--      if (!row_double_click)
--      grab_focus_and_unset_draw_keyfocus (tree_view);
--
--      return TRUE;
--    }
--
--  /* We didn't click in the window.  Let's check to see if we clicked on a column resize window.
--   */
--  for (i = 0, list = tree_view->priv->columns; list; list = list->next, i++)
--    {
--      column = list->data;
--      if (event->window == column->window &&
--        column->resizable &&
--        column->window)
--      {
--        gpointer drag_data;
--
--        if (GDK_GRAB_SUCCESS != gdk_device_grab (event->device,
--                                                 column->window,
--                                                 GDK_OWNERSHIP_NONE,
--                                                 FALSE,
--                                                 GDK_POINTER_MOTION_HINT_MASK |
--                                                 GDK_BUTTON1_MOTION_MASK |
--                                                 GDK_BUTTON_RELEASE_MASK,
--                                                 NULL, event->time))
--          return FALSE;
--
--        gtk_grab_add (widget);
--        PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_RESIZE);
--        column->resized_width = column->width;
--
--        /* block attached dnd signal handler */
--        drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
--        if (drag_data)
--          g_signal_handlers_block_matched (widget,
--                                           G_SIGNAL_MATCH_DATA,
--                                           0, 0, NULL, NULL,
--                                           drag_data);
--
--        tree_view->priv->drag_pos = i;
--        tree_view->priv->x_drag = column->allocation.x + (rtl ? 0 : column->allocation.width);
--
--        if (!gtk_widget_has_focus (widget))
--          gtk_widget_grab_focus (widget);
--
--        return TRUE;
--      }
--    }
--  return FALSE;
--}
--
--/* GtkWidget::button_release_event helper */
--static gboolean
--pspp_sheet_view_button_release_drag_column (GtkWidget      *widget,
--                                        GdkEventButton *event)
--{
--  PsppSheetView *tree_view;
--  GList *l;
--  gboolean rtl;
--
--  tree_view = PSPP_SHEET_VIEW (widget);
--
--  rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
--  gdk_display_pointer_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME);
--  gdk_display_keyboard_ungrab (gtk_widget_get_display (widget), GDK_CURRENT_TIME);
--
--  /* Move the button back */
--  g_return_val_if_fail (tree_view->priv->drag_column->button, FALSE);
--
--  g_object_ref (tree_view->priv->drag_column->button);
--  gtk_container_remove (GTK_CONTAINER (tree_view), tree_view->priv->drag_column->button);
--  gtk_widget_set_parent_window (tree_view->priv->drag_column->button, tree_view->priv->header_window);
--  gtk_widget_set_parent (tree_view->priv->drag_column->button, GTK_WIDGET (tree_view));
--  g_object_unref (tree_view->priv->drag_column->button);
--  gtk_widget_queue_resize (widget);
--  if (tree_view->priv->drag_column->resizable)
--    {
--      gdk_window_raise (tree_view->priv->drag_column->window);
--      gdk_window_show (tree_view->priv->drag_column->window);
--    }
--  else
--    gdk_window_hide (tree_view->priv->drag_column->window);
--
--  gtk_widget_grab_focus (tree_view->priv->drag_column->button);
--
--  if (rtl)
--    {
--      if (tree_view->priv->cur_reorder &&
--        tree_view->priv->cur_reorder->right_column != tree_view->priv->drag_column)
--      pspp_sheet_view_move_column_after (tree_view, tree_view->priv->drag_column,
--                                       tree_view->priv->cur_reorder->right_column);
--    }
--  else
--    {
--      if (tree_view->priv->cur_reorder &&
--        tree_view->priv->cur_reorder->left_column != tree_view->priv->drag_column)
--      pspp_sheet_view_move_column_after (tree_view, tree_view->priv->drag_column,
--                                       tree_view->priv->cur_reorder->left_column);
--    }
--  tree_view->priv->drag_column = NULL;
--  gdk_window_hide (tree_view->priv->drag_window);
--
--  for (l = tree_view->priv->column_drag_info; l != NULL; l = l->next)
--    g_slice_free (PsppSheetViewColumnReorder, l->data);
--  g_list_free (tree_view->priv->column_drag_info);
--  tree_view->priv->column_drag_info = NULL;
--  tree_view->priv->cur_reorder = NULL;
--
--  if (tree_view->priv->drag_highlight_window)
--    gdk_window_hide (tree_view->priv->drag_highlight_window);
--
--  /* Reset our flags */
--  tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_UNSET;
--  PSPP_SHEET_VIEW_UNSET_FLAG (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_DRAG);
--
--  return TRUE;
--}
--
--/* GtkWidget::button_release_event helper */
--static gboolean
--pspp_sheet_view_button_release_column_resize (GtkWidget      *widget,
--                                          GdkEventButton *event)
--{
--  PsppSheetView *tree_view;
--  gpointer drag_data;
--
--  tree_view = PSPP_SHEET_VIEW (widget);
--
--  tree_view->priv->drag_pos = -1;
--
--  /* unblock attached dnd signal handler */
--  drag_data = g_object_get_data (G_OBJECT (widget), "gtk-site-data");
--  if (drag_data)
--    g_signal_handlers_unblock_matched (widget,
--                                     G_SIGNAL_MATCH_DATA,
--                                     0, 0, NULL, NULL,
--                                     drag_data);
--
--  PSPP_SHEET_VIEW_UNSET_FLAG (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_RESIZE);
--  gtk_grab_remove (widget);
--  gdk_device_ungrab (event->device, event->time);
--
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_button_release_edit (PsppSheetView *tree_view,
--                                     GdkEventButton *event)
--{
--  GtkCellEditable *cell_editable;
--  gchar *path_string;
--  GtkTreePath *path;
--  gint left, right;
--  GtkTreeIter iter;
--  PsppSheetViewColumn *column;
--  GdkRectangle background_area;
--  GdkRectangle cell_area;
--  GdkRectangle area;
--  guint modifiers;
--  guint flags;
--  int node;
--
--  if (event->window != tree_view->priv->bin_window)
--    return FALSE;
--
--  /* Ignore a released button, if that button wasn't depressed */
--  if (tree_view->priv->pressed_button != event->button)
--    return FALSE;
--
--  if (!find_click (tree_view, event->x, event->y, &node, &column, &background_area,
--                   &cell_area))
--    return FALSE;
--
--  /* decide if we edit */
--  path = _pspp_sheet_view_find_path (tree_view, node);
--  modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
--  if (event->button != 1 || modifiers)
--    return FALSE;
--
--  gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
--  pspp_sheet_view_column_cell_set_cell_data (column,
--                                             tree_view->priv->model,
--                                             &iter);
--
--  if (!pspp_sheet_view_column_get_quick_edit (column)
--      && _pspp_sheet_view_column_has_editable_cell (column))
--    return FALSE;
--
--  flags = 0;                    /* FIXME: get the right flags */
--  path_string = gtk_tree_path_to_string (path);
--
--  if (!_pspp_sheet_view_column_cell_event (column,
--                                           &cell_editable,
--                                           (GdkEvent *)event,
--                                           path_string,
--                                           &background_area,
--                                           &cell_area, flags))
--    return FALSE;
--
--  if (cell_editable == NULL)
--    return FALSE;
--
--  pspp_sheet_view_real_set_cursor (tree_view, path,
--                                   TRUE, TRUE, 0); /* XXX mode? */
--  gtk_widget_queue_draw (GTK_WIDGET (tree_view));
--
--  area = cell_area;
--  _pspp_sheet_view_column_get_neighbor_sizes (
--    column, _pspp_sheet_view_column_get_edited_cell (column), &left, &right);
--
--  area.x += left;
--  area.width -= right + left;
--
--  pspp_sheet_view_real_start_editing (tree_view,
--                                      column,
--                                      path,
--                                      cell_editable,
--                                      &area,
--                                      (GdkEvent *)event,
--                                      flags);
--  g_free (path_string);
--  gtk_tree_path_free (path);
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_button_release (GtkWidget      *widget,
--                            GdkEventButton *event)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--
--  pspp_sheet_view_stop_editing (tree_view, FALSE);
--  if (tree_view->priv->rubber_band_status != RUBBER_BAND_ACTIVE
--      && pspp_sheet_view_button_release_edit (tree_view, event))
--    {
--      if (tree_view->priv->pressed_button == event->button)
--        tree_view->priv->pressed_button = -1;
--
--      tree_view->priv->rubber_band_status = RUBBER_BAND_OFF;
--      return TRUE;
--    }
--
--  if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_DRAG))
--    return pspp_sheet_view_button_release_drag_column (widget, event);
--
--  if (tree_view->priv->rubber_band_status)
--    pspp_sheet_view_stop_rubber_band (tree_view);
--
--  if (tree_view->priv->pressed_button == event->button)
--    tree_view->priv->pressed_button = -1;
--
--  if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_RESIZE))
--    return pspp_sheet_view_button_release_column_resize (widget, event);
--
--  return FALSE;
--}
--
--static gboolean
--pspp_sheet_view_grab_broken (GtkWidget          *widget,
--                         GdkEventGrabBroken *event)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--
--  if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_DRAG))
--    pspp_sheet_view_button_release_drag_column (widget, (GdkEventButton *)event);
--
--  if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_RESIZE))
--    pspp_sheet_view_button_release_column_resize (widget, (GdkEventButton *)event);
--
--  return TRUE;
--}
--
--/* GtkWidget::motion_event function set.
-- */
--
--static void
--do_prelight (PsppSheetView *tree_view,
--             int node,
--           /* these are in bin_window coords */
--             gint         x,
--             gint         y)
--{
--  int prev_node = tree_view->priv->prelight_node;
--
--  if (prev_node != node)
--    {
--      tree_view->priv->prelight_node = node;
--
--      if (prev_node >= 0)
--        _pspp_sheet_view_queue_draw_node (tree_view, prev_node, NULL);
--
--      if (node >= 0)
--        _pspp_sheet_view_queue_draw_node (tree_view, node, NULL);
--    }
--}
--
--
--static void
--prelight_or_select (PsppSheetView *tree_view,
--                  int node,
--                  /* these are in bin_window coords */
--                  gint         x,
--                  gint         y)
--{
--  PsppSheetSelectionMode mode = pspp_sheet_selection_get_mode (tree_view->priv->selection);
--  
--  if (tree_view->priv->hover_selection &&
--      (mode == PSPP_SHEET_SELECTION_SINGLE || mode == PSPP_SHEET_SELECTION_BROWSE) &&
--      !(tree_view->priv->edited_column &&
--      tree_view->priv->edited_column->editable_widget))
--    {
--      if (node >= 0)
--      {
--          if (!pspp_sheet_view_node_is_selected (tree_view, node))
--          {
--            GtkTreePath *path;
--            
--            path = _pspp_sheet_view_find_path (tree_view, node);
--            pspp_sheet_selection_select_path (tree_view->priv->selection, path);
--              if (pspp_sheet_view_node_is_selected (tree_view, node))
--              {
--                PSPP_SHEET_VIEW_UNSET_FLAG (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS);
--                pspp_sheet_view_real_set_cursor (tree_view, path, FALSE, FALSE, 0); /* XXX mode? */
--              }
--            gtk_tree_path_free (path);
--          }
--      }
--
--      else if (mode == PSPP_SHEET_SELECTION_SINGLE)
--      pspp_sheet_selection_unselect_all (tree_view->priv->selection);
--    }
--
--    do_prelight (tree_view, node, x, y);
--}
--
--static void
--ensure_unprelighted (PsppSheetView *tree_view)
--{
--  do_prelight (tree_view,
--             -1,
--             -1000, -1000); /* coords not possibly over an arrow */
--
--  g_assert (tree_view->priv->prelight_node < 0);
--}
--
--static void
--update_prelight (PsppSheetView *tree_view,
--                 gint         x,
--                 gint         y)
--{
--  int new_y;
--  int node;
--
--  if (tree_view->priv->row_count == 0)
--    return;
--
--  if (x == -10000)
--    {
--      ensure_unprelighted (tree_view);
--      return;
--    }
--
--  new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y);
--  if (new_y < 0)
--    new_y = 0;
--
--  pspp_sheet_view_find_offset (tree_view, new_y, &node);
--
--  if (node >= 0)
--    prelight_or_select (tree_view, node, x, y);
--}
--
--
--
--
--/* Our motion arrow is either a box (in the case of the original spot)
-- * or an arrow.  It is expander_size wide.
-- */
--/*
-- * 11111111111111
-- * 01111111111110
-- * 00111111111100
-- * 00011111111000
-- * 00001111110000
-- * 00000111100000
-- * 00000111100000
-- * 00000111100000
-- * ~ ~ ~ ~ ~ ~ ~
-- * 00000111100000
-- * 00000111100000
-- * 00000111100000
-- * 00001111110000
-- * 00011111111000
-- * 00111111111100
-- * 01111111111110
-- * 11111111111111
-- */
--
--static void
--pspp_sheet_view_motion_draw_column_motion_arrow (PsppSheetView *tree_view)
--{
--}
--
--static gboolean
--pspp_sheet_view_motion_resize_column (GtkWidget      *widget,
--                                  GdkEventMotion *event)
--{
--  gint x;
--  gint new_width;
--  PsppSheetViewColumn *column;
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--
--  column = pspp_sheet_view_get_column (tree_view, tree_view->priv->drag_pos);
--
--  if (event->is_hint || event->window != gtk_widget_get_window (widget))
--    gtk_widget_get_pointer (widget, &x, NULL);
--  else
--    x = event->x;
--
--  if (tree_view->priv->hadjustment)
--    x += gtk_adjustment_get_value (tree_view->priv->hadjustment);
--
--  new_width = pspp_sheet_view_new_column_width (tree_view,
--                                            tree_view->priv->drag_pos, &x);
--  if (x != tree_view->priv->x_drag &&
--      (new_width != column->fixed_width))
--    {
--      column->use_resized_width = TRUE;
--      column->resized_width = new_width;
--#if 0
--      if (column->expand)
--      column->resized_width -= tree_view->priv->last_extra_space_per_column;
--#endif
--      gtk_widget_queue_resize (widget);
--    }
--
--  return FALSE;
--}
--
--
--static void
--pspp_sheet_view_update_current_reorder (PsppSheetView *tree_view)
--{
--  PsppSheetViewColumnReorder *reorder = NULL;
--  GList *list;
--  gint mouse_x;
--
--  gdk_window_get_pointer (tree_view->priv->header_window, &mouse_x, NULL, NULL);
--  for (list = tree_view->priv->column_drag_info; list; list = list->next)
--    {
--      reorder = (PsppSheetViewColumnReorder *) list->data;
--      if (mouse_x >= reorder->left_align && mouse_x < reorder->right_align)
--      break;
--      reorder = NULL;
--    }
--
--  /*  if (reorder && reorder == tree_view->priv->cur_reorder)
--      return;*/
--
--  tree_view->priv->cur_reorder = reorder;
--  pspp_sheet_view_motion_draw_column_motion_arrow (tree_view);
--}
--
--static void
--pspp_sheet_view_vertical_autoscroll (PsppSheetView *tree_view)
--{
--  GdkRectangle visible_rect;
--  gint y;
--  gint offset;
--  gfloat value;
--
--  gdk_window_get_pointer (tree_view->priv->bin_window, NULL, &y, NULL);
--  y += tree_view->priv->dy;
--
--  pspp_sheet_view_get_visible_rect (tree_view, &visible_rect);
--
--  /* see if we are near the edge. */
--  offset = y - (visible_rect.y + 2 * SCROLL_EDGE_SIZE);
--  if (offset > 0)
--    {
--      offset = y - (visible_rect.y + visible_rect.height - 2 * SCROLL_EDGE_SIZE);
--      if (offset < 0)
--      return;
--    }
--
--  value = CLAMP (gtk_adjustment_get_value (tree_view->priv->vadjustment) + offset, 0.0,
--               gtk_adjustment_get_upper (tree_view->priv->vadjustment) - gtk_adjustment_get_page_size (tree_view->priv->vadjustment));
--  gtk_adjustment_set_value (tree_view->priv->vadjustment, value);
--}
--
--static gboolean
--pspp_sheet_view_horizontal_autoscroll (PsppSheetView *tree_view)
--{
--  GdkRectangle visible_rect;
--  gint x;
--  gint offset;
--  gfloat value;
--
--  gdk_window_get_pointer (tree_view->priv->bin_window, &x, NULL, NULL);
--
--  pspp_sheet_view_get_visible_rect (tree_view, &visible_rect);
--
--  /* See if we are near the edge. */
--  offset = x - (visible_rect.x + SCROLL_EDGE_SIZE);
--  if (offset > 0)
--    {
--      offset = x - (visible_rect.x + visible_rect.width - SCROLL_EDGE_SIZE);
--      if (offset < 0)
--      return TRUE;
--    }
--  offset = offset/3;
--
--  value = CLAMP (gtk_adjustment_get_value (tree_view->priv->hadjustment) + offset,
--               0.0, gtk_adjustment_get_upper (tree_view->priv->hadjustment) - gtk_adjustment_get_page_size (tree_view->priv->hadjustment));
--  gtk_adjustment_set_value (tree_view->priv->hadjustment, value);
--
--  return TRUE;
--
--}
--
--static gboolean
--pspp_sheet_view_motion_drag_column (GtkWidget      *widget,
--                                GdkEventMotion *event)
--{
--  PsppSheetView *tree_view = (PsppSheetView *) widget;
--  PsppSheetViewColumn *column = tree_view->priv->drag_column;
--  gint x, y;
--  GtkAllocation allocation;
--
--  /* Sanity Check */
--  if ((column == NULL) ||
--      (event->window != tree_view->priv->drag_window))
--    return FALSE;
--
--  /* Handle moving the header */
--  gdk_window_get_position (tree_view->priv->drag_window, &x, &y);
--  gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
--  x = CLAMP (x + (gint)event->x - column->drag_x, 0,
--           MAX (tree_view->priv->width, allocation.width) - column->allocation.width);
--  gdk_window_move (tree_view->priv->drag_window, x, y);
--  
--  /* autoscroll, if needed */
--  pspp_sheet_view_horizontal_autoscroll (tree_view);
--  /* Update the current reorder position and arrow; */
--  pspp_sheet_view_update_current_reorder (tree_view);
--
--  return TRUE;
--}
--
--static void
--pspp_sheet_view_stop_rubber_band (PsppSheetView *tree_view)
--{
--  remove_scroll_timeout (tree_view);
--  gtk_grab_remove (GTK_WIDGET (tree_view));
--
--  if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
--    {
--      GtkTreePath *tmp_path;
--
--      gtk_widget_queue_draw (GTK_WIDGET (tree_view));
--
--      /* The anchor path should be set to the start path */
--      tmp_path = _pspp_sheet_view_find_path (tree_view,
--                                         tree_view->priv->rubber_band_start_node);
--
--      if (tree_view->priv->anchor)
--      gtk_tree_row_reference_free (tree_view->priv->anchor);
--
--      tree_view->priv->anchor =
--      gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
--                                        tree_view->priv->model,
--                                        tmp_path);
--
--      gtk_tree_path_free (tmp_path);
--
--      /* ... and the cursor to the end path */
--      tmp_path = _pspp_sheet_view_find_path (tree_view,
--                                         tree_view->priv->rubber_band_end_node);
--      pspp_sheet_view_real_set_cursor (PSPP_SHEET_VIEW (tree_view), tmp_path, FALSE, FALSE, 0); /* XXX mode? */
--      gtk_tree_path_free (tmp_path);
--
--      _pspp_sheet_selection_emit_changed (tree_view->priv->selection);
--    }
--
--  /* Clear status variables */
--  tree_view->priv->rubber_band_status = RUBBER_BAND_OFF;
--  tree_view->priv->rubber_band_shift = 0;
--  tree_view->priv->rubber_band_ctrl = 0;
--
--  tree_view->priv->rubber_band_start_node = -1;
--  tree_view->priv->rubber_band_end_node = -1;
--}
--
--static void
--pspp_sheet_view_update_rubber_band_selection_range (PsppSheetView *tree_view,
--                                               int start_node,
--                                               int end_node,
--                                               gboolean     select,
--                                               gboolean     skip_start,
--                                               gboolean     skip_end)
--{
--  if (start_node == end_node)
--    return;
--
--  /* We skip the first node and jump inside the loop */
--  if (skip_start)
--    goto skip_first;
--
--  do
--    {
--      /* Small optimization by assuming insensitive nodes are never
--       * selected.
--       */
--      if (select)
--        {
--        if (tree_view->priv->rubber_band_shift)
--            pspp_sheet_view_node_select (tree_view, start_node);
--        else if (tree_view->priv->rubber_band_ctrl)
--          {
--            /* Toggle the selection state */
--              if (pspp_sheet_view_node_is_selected (tree_view, start_node))
--                pspp_sheet_view_node_unselect (tree_view, start_node);
--            else
--                pspp_sheet_view_node_select (tree_view, start_node);
--          }
--        else
--            pspp_sheet_view_node_select (tree_view, start_node);
--      }
--      else
--        {
--        /* Mirror the above */
--        if (tree_view->priv->rubber_band_shift)
--                pspp_sheet_view_node_unselect (tree_view, start_node);
--        else if (tree_view->priv->rubber_band_ctrl)
--          {
--            /* Toggle the selection state */
--              if (pspp_sheet_view_node_is_selected (tree_view, start_node))
--                pspp_sheet_view_node_unselect (tree_view, start_node);
--            else
--                pspp_sheet_view_node_select (tree_view, start_node);
--          }
--        else
--            pspp_sheet_view_node_unselect (tree_view, start_node);
--      }
--
--      _pspp_sheet_view_queue_draw_node (tree_view, start_node, NULL);
--
--      if (start_node == end_node)
--      break;
--
--skip_first:
--
--      start_node = pspp_sheet_view_node_next (tree_view, start_node);
--
--      if (start_node < 0)
--        /* Ran out of tree */
--        break;
--
--      if (skip_end && start_node == end_node)
--      break;
--    }
--  while (TRUE);
--}
--
--static gint
--pspp_sheet_view_node_find_offset (PsppSheetView *tree_view,
--                                  int node)
--{
--  return node * tree_view->priv->fixed_height;
--}
--
--static gint
--pspp_sheet_view_find_offset (PsppSheetView *tree_view,
--                             gint height,
--                             int *new_node)
--{
--  int fixed_height = tree_view->priv->fixed_height;
--  if (fixed_height <= 0
--      || height < 0
--      || height >= tree_view->priv->row_count * fixed_height)
--    {
--      *new_node = -1;
--      return 0;
--    }
--  else
--    {
--      *new_node = height / fixed_height;
--      return height % fixed_height;
--    }
--}
--
--static void
--pspp_sheet_view_update_rubber_band_selection (PsppSheetView *tree_view)
--{
--  int start_node;
--  int end_node;
--
--  pspp_sheet_view_find_offset (tree_view, MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y), &start_node);
--  pspp_sheet_view_find_offset (tree_view, MAX (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y), &end_node);
--
--  /* Handle the start area first */
--  if (tree_view->priv->rubber_band_start_node < 0)
--    {
--      pspp_sheet_view_update_rubber_band_selection_range (tree_view,
--                                                     start_node,
--                                                     end_node,
--                                                     TRUE,
--                                                     FALSE,
--                                                     FALSE);
--    }
--  else if (start_node < tree_view->priv->rubber_band_start_node)
--    {
--      /* New node is above the old one; selection became bigger */
--      pspp_sheet_view_update_rubber_band_selection_range (tree_view,
--                                                     start_node,
--                                                     tree_view->priv->rubber_band_start_node,
--                                                     TRUE,
--                                                     FALSE,
--                                                     TRUE);
--    }
--  else if (start_node > tree_view->priv->rubber_band_start_node)
--    {
--      /* New node is below the old one; selection became smaller */
--      pspp_sheet_view_update_rubber_band_selection_range (tree_view,
--                                                     tree_view->priv->rubber_band_start_node,
--                                                     start_node,
--                                                     FALSE,
--                                                     FALSE,
--                                                     TRUE);
--    }
--
--  tree_view->priv->rubber_band_start_node = start_node;
--
--  /* Next, handle the end area */
--  if (tree_view->priv->rubber_band_end_node < 0)
--    {
--      /* In the event this happens, start_node was also -1; this case is
--       * handled above.
--       */
--    }
--  else if (end_node < 0)
--    {
--      /* Find the last node in the tree */
--      pspp_sheet_view_find_offset (tree_view, tree_view->priv->height - 1,
--                             &end_node);
--
--      /* Selection reached end of the tree */
--      pspp_sheet_view_update_rubber_band_selection_range (tree_view,
--                                                     tree_view->priv->rubber_band_end_node,
--                                                     end_node,
--                                                     TRUE,
--                                                     TRUE,
--                                                     FALSE);
--    }
--  else if (end_node > tree_view->priv->rubber_band_end_node)
--    {
--      /* New node is below the old one; selection became bigger */
--      pspp_sheet_view_update_rubber_band_selection_range (tree_view,
--                                                     tree_view->priv->rubber_band_end_node,
--                                                     end_node,
--                                                     TRUE,
--                                                     TRUE,
--                                                     FALSE);
--    }
--  else if (end_node < tree_view->priv->rubber_band_end_node)
--    {
--      /* New node is above the old one; selection became smaller */
--      pspp_sheet_view_update_rubber_band_selection_range (tree_view,
--                                                     end_node,
--                                                     tree_view->priv->rubber_band_end_node,
--                                                     FALSE,
--                                                     TRUE,
--                                                     FALSE);
--    }
--
--  tree_view->priv->rubber_band_end_node = end_node;
--}
--
--#define GDK_RECTANGLE_PTR(X) ((GdkRectangle *)(X))
--
--static void
--pspp_sheet_view_update_rubber_band (PsppSheetView *tree_view)
--{
--  gint x, y;
--  cairo_rectangle_int_t old_area;
--  cairo_rectangle_int_t new_area;
--  cairo_rectangle_int_t common;
--  cairo_region_t *invalid_region;
--  PsppSheetViewColumn *column;
--
--  old_area.x = MIN (tree_view->priv->press_start_x, tree_view->priv->rubber_band_x);
--  old_area.y = MIN (tree_view->priv->press_start_y, tree_view->priv->rubber_band_y) - tree_view->priv->dy;
--  old_area.width = ABS (tree_view->priv->rubber_band_x - tree_view->priv->press_start_x) + 1;
--  old_area.height = ABS (tree_view->priv->rubber_band_y - tree_view->priv->press_start_y) + 1;
--
--  gdk_window_get_pointer (tree_view->priv->bin_window, &x, &y, NULL);
--
--  x = MAX (x, 0);
--  y = MAX (y, 0) + tree_view->priv->dy;
--
--  new_area.x = MIN (tree_view->priv->press_start_x, x);
--  new_area.y = MIN (tree_view->priv->press_start_y, y) - tree_view->priv->dy;
--  new_area.width = ABS (x - tree_view->priv->press_start_x) + 1;
--  new_area.height = ABS (y - tree_view->priv->press_start_y) + 1;
--
--  invalid_region = cairo_region_create_rectangle (&old_area);
--  cairo_region_union_rectangle (invalid_region, &new_area);
--
--  gdk_rectangle_intersect (GDK_RECTANGLE_PTR (&old_area), 
--                         GDK_RECTANGLE_PTR (&new_area), GDK_RECTANGLE_PTR (&common));
--  if (common.width > 2 && common.height > 2)
--    {
--      cairo_region_t *common_region;
--
--      /* make sure the border is invalidated */
--      common.x += 1;
--      common.y += 1;
--      common.width -= 2;
--      common.height -= 2;
--
--      common_region = cairo_region_create_rectangle (&common);
--
--      cairo_region_subtract (invalid_region, common_region);
--      cairo_region_destroy (common_region);
--    }
--
--#if GTK_MAJOR_VERSION == 3
--  gdk_window_invalidate_region (tree_view->priv->bin_window, invalid_region, TRUE);  
--#else
--  {
--    cairo_rectangle_int_t extents;
--    GdkRegion *ereg;
--    cairo_region_get_extents (invalid_region, &extents);
--    ereg = gdk_region_rectangle (GDK_RECTANGLE_PTR (&extents));
--    gdk_window_invalidate_region (tree_view->priv->bin_window, ereg, TRUE);
--    gdk_region_destroy (ereg);
--  }
--#endif
--
--  cairo_region_destroy (invalid_region);
--
--  tree_view->priv->rubber_band_x = x;
--  tree_view->priv->rubber_band_y = y;
--  pspp_sheet_view_get_path_at_pos (tree_view, x, y, NULL, &column, NULL, NULL);
--
--  pspp_sheet_selection_unselect_all_columns (tree_view->priv->selection);
--  pspp_sheet_selection_select_column_range (tree_view->priv->selection,
--                                            tree_view->priv->anchor_column,
--                                            column);
--
--  gtk_widget_queue_draw (GTK_WIDGET (tree_view));
--
--  pspp_sheet_view_update_rubber_band_selection (tree_view);
--}
--
--
--
--static gboolean
--pspp_sheet_view_motion_bin_window (GtkWidget      *widget,
--                               GdkEventMotion *event)
--{
--  PsppSheetView *tree_view;
--  int node;
--  gint new_y;
--
--  tree_view = (PsppSheetView *) widget;
--
--  if (tree_view->priv->row_count == 0)
--    return FALSE;
--
--  if (tree_view->priv->rubber_band_status == RUBBER_BAND_MAYBE_START)
--    {
--      GdkRectangle background_area, cell_area;
--      PsppSheetViewColumn *column;
--
--      if (find_click (tree_view, event->x, event->y, &node, &column,
--                      &background_area, &cell_area)
--          && tree_view->priv->focus_column == column
--          && tree_view->priv->press_start_node == node)
--        return FALSE;
--
--      gtk_grab_add (GTK_WIDGET (tree_view));
--      pspp_sheet_view_update_rubber_band (tree_view);
--
--      tree_view->priv->rubber_band_status = RUBBER_BAND_ACTIVE;
--    }
--  else if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
--    {
--      pspp_sheet_view_update_rubber_band (tree_view);
--
--      add_scroll_timeout (tree_view);
--    }
--
--  /* only check for an initiated drag when a button is pressed */
--  if (tree_view->priv->pressed_button >= 0
--      && !tree_view->priv->rubber_band_status)
--    pspp_sheet_view_maybe_begin_dragging_row (tree_view, event);
--
--  new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
--  if (new_y < 0)
--    new_y = 0;
--
--  pspp_sheet_view_find_offset (tree_view, new_y, &node);
--
--  tree_view->priv->event_last_x = event->x;
--  tree_view->priv->event_last_y = event->y;
--
--  prelight_or_select (tree_view, node, event->x, event->y);
--
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_motion (GtkWidget      *widget,
--                    GdkEventMotion *event)
--{
--  PsppSheetView *tree_view;
--
--  tree_view = (PsppSheetView *) widget;
--
--  /* Resizing a column */
--  if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_RESIZE))
--    return pspp_sheet_view_motion_resize_column (widget, event);
--
--  /* Drag column */
--  if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_DRAG))
--    return pspp_sheet_view_motion_drag_column (widget, event);
--
--  /* Sanity check it */
--  if (event->window == tree_view->priv->bin_window)
--    return pspp_sheet_view_motion_bin_window (widget, event);
--
--  return FALSE;
--}
--
--/* Invalidate the focus rectangle near the edge of the bin_window; used when
-- * the tree is empty.
-- */
--static void
--invalidate_empty_focus (PsppSheetView *tree_view)
--{
--  GdkRectangle area;
--
--  if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    return;
--
--  area.x = 0;
--  area.y = 0;
--  area.width = gdk_window_get_width (tree_view->priv->bin_window);
--  area.height = gdk_window_get_height (tree_view->priv->bin_window);
--  gdk_window_invalidate_rect (tree_view->priv->bin_window, &area, FALSE);
--}
--
--/* Draws a focus rectangle near the edge of the bin_window; used when the tree
-- * is empty.
-- */
--static void
--draw_empty_focus (PsppSheetView *tree_view)
--{
--  GtkWidget *widget = GTK_WIDGET (tree_view);
--  gint w, h;
--  cairo_t *cr = gdk_cairo_create (tree_view->priv->bin_window);
--
--  if (!gtk_widget_has_focus (widget))
--    return;
--
--  w = gdk_window_get_width (tree_view->priv->bin_window);
--  h = gdk_window_get_height (tree_view->priv->bin_window);
--
--  w -= 2;
--  h -= 2;
--
--  if (w > 0 && h > 0)
--    gtk_paint_focus (gtk_widget_get_style (widget),
--                   cr,
--                   gtk_widget_get_state (widget),
--                   widget,
--                   NULL,
--                   1, 1, w, h);
--  cairo_destroy (cr);
--}
--
--static void
--pspp_sheet_view_draw_vertical_grid_lines (PsppSheetView    *tree_view,
--                                        cairo_t *cr,
--                                        gint n_visible_columns,
--                                        gint min_y,
--                                        gint max_y)
--{
--  GList *list = tree_view->priv->columns;
--  gint x = 0;
--
--  if (tree_view->priv->grid_lines != PSPP_SHEET_VIEW_GRID_LINES_VERTICAL
--      && tree_view->priv->grid_lines != PSPP_SHEET_VIEW_GRID_LINES_BOTH)
--    return;
--
--  /* Only draw the lines for visible rows and columns */
--  gboolean rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--
--  for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
--       list;
--       list = (rtl ? list->prev : list->next))
--    {
--      PsppSheetViewColumn *column = list->data;
--
--      if (! column->visible)
--      continue;
--
--      if (!rtl)
--      x += column->width;
--
--      cairo_set_line_width (cr, 1.0);
--      cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
--      cairo_move_to (cr, x + 0.5, min_y);
--      cairo_line_to (cr, x + 0.5, max_y - min_y - 0.5);
--      cairo_stroke (cr);
--
--      if (rtl)
--      x += column->width;
--    }
--}
--
--/* Warning: Very scary function.
-- * Modify at your own risk
-- *
-- * KEEP IN SYNC WITH pspp_sheet_view_create_row_drag_icon()!
-- * FIXME: It's not...
-- */
--static void
--pspp_sheet_view_draw_bin (GtkWidget      *widget,
--                        cairo_t *cr)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--  GtkTreePath *path;
--  GList *list;
--  int node;
--  int cursor = -1;
--  int drag_highlight = -1;
--  GtkTreeIter iter;
--  gint new_y;
--  gint y_offset, cell_offset;
--  gint max_height;
--  GdkRectangle background_area;
--  GdkRectangle cell_area;
--  guint flags;
--  gint bin_window_width;
--  gint bin_window_height;
--  GtkTreePath *cursor_path;
--  GtkTreePath *drag_dest_path;
--  GList *first_column, *last_column;
--  gint vertical_separator;
--  gint horizontal_separator;
--  gint focus_line_width;
--  gboolean allow_rules;
--  gboolean rtl;
--  gint n_visible_columns;
--  gint grid_line_width;
--  gboolean row_ending_details;
--  gboolean draw_vgrid_lines, draw_hgrid_lines;
--  gint min_y, max_y;
--  GtkStyleContext *context;
--  context = gtk_widget_get_style_context (widget);
--
--  GdkRectangle Zarea;
--  GtkAllocation allocation;
--  gtk_widget_get_allocation (widget, &allocation);
--
--  GdkRectangle exposed_rect;
--  gdk_cairo_get_clip_rectangle (cr, &exposed_rect);
--  
--  Zarea.x =      0;
--  Zarea.y =      0;
--  Zarea.height = allocation.height;
--
--  rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
--
--  gtk_widget_style_get (widget,
--                      "horizontal-separator", &horizontal_separator,
--                      "vertical-separator", &vertical_separator,
--                      "allow-rules", &allow_rules,
--                      "focus-line-width", &focus_line_width,
--                      "row-ending-details", &row_ending_details,
--                      NULL);
--
--  if (tree_view->priv->row_count == 0)
--    {
--      draw_empty_focus (tree_view);
--      return;
--    }
--
--  validate_visible_area (tree_view);
--
--  new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, Zarea.y);
--
--  if (new_y < 0)
--    new_y = 0;
--  y_offset = -pspp_sheet_view_find_offset (tree_view, new_y, &node);
--  bin_window_width = 
--    gdk_window_get_width (tree_view->priv->bin_window);
--
--  bin_window_height = 
--    gdk_window_get_height (tree_view->priv->bin_window);
--
--
--  if (tree_view->priv->height < bin_window_height)
--    {
--      gtk_paint_flat_box (gtk_widget_get_style (widget),
--                          cr,
--                          gtk_widget_get_state (widget),
--                          GTK_SHADOW_NONE,
--                          widget,
--                          "cell_even",
--                          0, tree_view->priv->height,
--                          bin_window_width,
--                          bin_window_height - tree_view->priv->height);
--    }
--
--  if (node < 0)
--    return;
--
--  /* find the path for the node */
--  path = _pspp_sheet_view_find_path ((PsppSheetView *)widget, node);
--  gtk_tree_model_get_iter (tree_view->priv->model,
--                         &iter,
--                         path);
--  gtk_tree_path_free (path);
--  
--  cursor_path = NULL;
--  drag_dest_path = NULL;
--
--  if (tree_view->priv->cursor)
--    cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--
--  if (cursor_path)
--    _pspp_sheet_view_find_node (tree_view, cursor_path, &cursor);
--
--  if (tree_view->priv->drag_dest_row)
--    drag_dest_path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
--
--  if (drag_dest_path)
--    _pspp_sheet_view_find_node (tree_view, drag_dest_path,
--                                &drag_highlight);
--
--  draw_vgrid_lines =
--    tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_VERTICAL
--    || tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_BOTH;
--  draw_hgrid_lines =
--    tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_HORIZONTAL
--    || tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_BOTH;
--
--  if (draw_vgrid_lines || draw_hgrid_lines)
--    gtk_widget_style_get (widget, "grid-line-width", &grid_line_width, NULL);
--  
--  n_visible_columns = 0;
--  for (list = tree_view->priv->columns; list; list = list->next)
--    {
--      if (! PSPP_SHEET_VIEW_COLUMN (list->data)->visible)
--      continue;
--      n_visible_columns ++;
--    }
--
--  /* Find the last column */
--  for (last_column = g_list_last (tree_view->priv->columns);
--       last_column && !(PSPP_SHEET_VIEW_COLUMN (last_column->data)->visible);
--       last_column = last_column->prev)
--    ;
--
--  /* and the first */
--  for (first_column = g_list_first (tree_view->priv->columns);
--       first_column && !(PSPP_SHEET_VIEW_COLUMN (first_column->data)->visible);
--       first_column = first_column->next)
--    ;
--
--  /* Actually process the expose event.  To do this, we want to
--   * start at the first node of the event, and walk the tree in
--   * order, drawing each successive node.
--   */
--
--  min_y = y_offset;
--  do
--    {
--      gboolean parity;
--      gboolean is_first = FALSE;
--      gboolean is_last = FALSE;
--      gboolean done = FALSE;
--      gboolean selected;
--
--      max_height = ROW_HEIGHT (tree_view);
--
--      cell_offset = 0;
--
--      background_area.y = y_offset + Zarea.y;
--      background_area.height = max_height;
--      max_y = background_area.y + max_height;
--
--      flags = 0;
--
--      if (node == tree_view->priv->prelight_node)
--      flags |= GTK_CELL_RENDERER_PRELIT;
--
--      selected = pspp_sheet_view_node_is_selected (tree_view, node);
--
--      parity = node % 2;
--
--      for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
--         list;
--         list = (rtl ? list->prev : list->next))
--      {
--        PsppSheetViewColumn *column = list->data;
--        const gchar *detail = NULL;
--          gboolean selected_column;
--        GtkStateType state;
--
--        if (!column->visible)
--            continue;
--
--          if (tree_view->priv->selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
--            selected_column = column->selected && column->selectable;
--          else
--            selected_column = TRUE;
--
--          if (selected && selected_column)
--            flags |= GTK_CELL_RENDERER_SELECTED;
--          else
--            flags &= ~GTK_CELL_RENDERER_SELECTED;
--
--          if (column->show_sort_indicator)
--          flags |= GTK_CELL_RENDERER_SORTED;
--          else
--            flags &= ~GTK_CELL_RENDERER_SORTED;
--
--        if (cursor == node)
--            flags |= GTK_CELL_RENDERER_FOCUSED;
--          else
--            flags &= ~GTK_CELL_RENDERER_FOCUSED;
--
--        background_area.x = cell_offset;
--        background_area.width = column->width;
--
--          cell_area = background_area;
--          cell_area.y += vertical_separator / 2;
--          cell_area.x += horizontal_separator / 2;
--          cell_area.height -= vertical_separator;
--        cell_area.width -= horizontal_separator;
--
--        if (draw_vgrid_lines)
--          {
--            if (list == first_column)
--              {
--                cell_area.width -= grid_line_width / 2;
--              }
--            else if (list == last_column)
--              {
--                cell_area.x += grid_line_width / 2;
--                cell_area.width -= grid_line_width / 2;
--              }
--            else
--              {
--                cell_area.x += grid_line_width / 2;
--                cell_area.width -= grid_line_width;
--              }
--          }
--
--        if (draw_hgrid_lines)
--          {
--            cell_area.y += grid_line_width / 2;
--            cell_area.height -= grid_line_width;
--          }
--
--        if (!gdk_rectangle_intersect (&background_area, &exposed_rect, NULL))
--          {
--            cell_offset += column->width;
--            continue;
--          }
--
--
--        pspp_sheet_view_column_cell_set_cell_data (column,
--                                                     tree_view->priv->model,
--                                                     &iter);
--
--          /* Select the detail for drawing the cell.  relevant
--           * factors are parity, sortedness, and whether to
--           * display rules.
--           */
--          if (allow_rules && tree_view->priv->has_rules)
--            {
--              if ((flags & GTK_CELL_RENDERER_SORTED) &&
--                n_visible_columns >= 3)
--                {
--                  if (parity)
--                    detail = "cell_odd_ruled_sorted";
--                  else
--                    detail = "cell_even_ruled_sorted";
--                }
--              else
--                {
--                  if (parity)
--                    detail = "cell_odd_ruled";
--                  else
--                    detail = "cell_even_ruled";
--                }
--            }
--          else
--            {
--              if ((flags & GTK_CELL_RENDERER_SORTED) &&
--                n_visible_columns >= 3)
--                {
--                  if (parity)
--                    detail = "cell_odd_sorted";
--                  else
--                    detail = "cell_even_sorted";
--                }
--              else
--                {
--                  if (parity)
--                    detail = "cell_odd";
--                  else
--                    detail = "cell_even";
--                }
--            }
--
--          g_assert (detail);
--
--        gtk_style_context_save (context);
--        state = gtk_cell_renderer_get_state (NULL, widget, flags);
--          gtk_style_context_set_state (context, state);
--          gtk_style_context_add_class (context, GTK_STYLE_CLASS_CELL);
--
--        /* Draw background */
--          gtk_render_background (context, cr,
--                                 background_area.x,
--                                 background_area.y,
--                                 background_area.width,
--                                 background_area.height);
--
--          /* Draw frame */
--          gtk_render_frame (context, cr,
--                            background_area.x,
--                            background_area.y,
--                            background_area.width,
--                            background_area.height);
--
--        if (draw_hgrid_lines)
--          {
--            cairo_set_line_width (cr, 1.0);
--            cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
--
--            if (background_area.y >= 0)
--              {
--                cairo_move_to (cr, background_area.x, background_area.y - 0.5);
--                cairo_line_to (cr, background_area.x + background_area.width,
--                               background_area.y - 0.5);
--              }
--
--            if (y_offset + max_height <= Zarea.height - 0.5)
--              {
--                cairo_move_to (cr, background_area.x, background_area.y + max_height - 0.5);
--                cairo_line_to (cr, background_area.x + background_area.width,
--                               background_area.y + max_height - 0.5);
--              }
--            cairo_stroke (cr);
--          }
--
--          _pspp_sheet_view_column_cell_render (column,
--                                               cr,
--                                               &background_area,
--                                               &cell_area,
--                                               flags);
--
--
--        cell_offset += column->width;
--        gtk_style_context_restore (context);
--      }
--
--      if (node == drag_highlight)
--        {
--          /* Draw indicator for the drop
--           */
--          gint highlight_y = -1;
--        int node = -1;
--        gint width;
--
--          switch (tree_view->priv->drag_dest_pos)
--            {
--            case PSPP_SHEET_VIEW_DROP_BEFORE:
--              highlight_y = background_area.y - 1;
--            if (highlight_y < 0)
--                    highlight_y = 0;
--              break;
--
--            case PSPP_SHEET_VIEW_DROP_AFTER:
--              highlight_y = background_area.y + background_area.height - 1;
--              break;
--
--            case PSPP_SHEET_VIEW_DROP_INTO_OR_BEFORE:
--            case PSPP_SHEET_VIEW_DROP_INTO_OR_AFTER:
--            _pspp_sheet_view_find_node (tree_view, drag_dest_path, &node);
--
--            if (node < 0)
--              break;
--            width = gdk_window_get_width (tree_view->priv->bin_window);
--
--            if (row_ending_details)
--              gtk_paint_focus (gtk_widget_get_style (widget),
--                               cr,
--                               gtk_widget_get_state (widget),
--                               widget,
--                               (is_first
--                                ? (is_last ? "treeview-drop-indicator" : "treeview-drop-indicator-left" )
--                                : (is_last ? "treeview-drop-indicator-right" : "tree-view-drop-indicator-middle" )),
--                               0, BACKGROUND_FIRST_PIXEL (tree_view, node)
--                               - focus_line_width / 2,
--                               width, ROW_HEIGHT (tree_view)
--                             - focus_line_width + 1);
--            else
--              gtk_paint_focus (gtk_widget_get_style (widget),
--                               cr,
--                               gtk_widget_get_state (widget),
--                               widget,
--                               "treeview-drop-indicator",
--                               0, BACKGROUND_FIRST_PIXEL (tree_view, node)
--                               - focus_line_width / 2,
--                               width, ROW_HEIGHT (tree_view)
--                               - focus_line_width + 1);
--              break;
--            }
--
--        }
--
--      y_offset += max_height;
--
--      do
--        {
--          node = pspp_sheet_view_node_next (tree_view, node);
--          if (node >= 0)
--            {
--              gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
--              done = TRUE;
--
--              /* Sanity Check! */
--              TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
--            }
--          else
--            goto done;
--        }
--      while (!done);
--    }
--  while (y_offset < Zarea.height);
--
--done:
--  pspp_sheet_view_draw_vertical_grid_lines (tree_view, cr, n_visible_columns,
--                                   min_y, max_y);
--
--  if (cursor_path)
--    gtk_tree_path_free (cursor_path);
--
--  if (drag_dest_path)
--    gtk_tree_path_free (drag_dest_path);
--
--  return;
--}
--
--
--static gboolean
--pspp_sheet_view_draw (GtkWidget      *widget,
--                    cairo_t *cr)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--  GtkStyleContext *context;
--
--  context = gtk_widget_get_style_context (widget);
--
--  if (gtk_cairo_should_draw_window (cr, tree_view->priv->bin_window))
--    {
--      GList *tmp_list;
--
--      cairo_save (cr);
--      gtk_cairo_transform_to_window(cr,widget,tree_view->priv->bin_window);
--      pspp_sheet_view_draw_bin (widget, cr);
--      cairo_restore (cr);
--
--      /* We can't just chain up to Container::expose as it will try to send the
--       * event to the headers, so we handle propagating it to our children
--       * (eg. widgets being edited) ourselves.
--       */
--      tmp_list = tree_view->priv->children;
--      while (tmp_list)
--      {
--        PsppSheetViewChild *child = tmp_list->data;
--        tmp_list = tmp_list->next;
--
--        gtk_container_propagate_draw (GTK_CONTAINER (tree_view), child->widget, cr);
--        }
--    }
--  else
--    {
--      gtk_render_background (context, cr,
--                             0, 0,
--                             gtk_widget_get_allocated_width (widget),
--                             gtk_widget_get_allocated_height (widget));
--    }
--
--  gtk_style_context_save (context);
--  gtk_style_context_remove_class (context, GTK_STYLE_CLASS_VIEW);
--
--  if (gtk_cairo_should_draw_window (cr, tree_view->priv->header_window))
--    {
--      gint n_visible_columns;
--      GList *list;
--
--      for (list = tree_view->priv->columns; list != NULL; list = list->next)
--      {
--        PsppSheetViewColumn *column = list->data;
--
--        if (column == tree_view->priv->drag_column || !column->visible)
--          continue;
--
--          if (span_intersects (column->allocation.x, column->allocation.width,
--                               (int) gtk_adjustment_get_value (tree_view->priv->hadjustment),
--                               (int) gtk_widget_get_allocated_width (widget))
--              && column->button != NULL)
--            gtk_container_propagate_draw (GTK_CONTAINER (tree_view),
--                                        column->button, cr);
--      }
--
--      n_visible_columns = 0;
--      for (list = tree_view->priv->columns; list; list = list->next)
--        {
--          if (! PSPP_SHEET_VIEW_COLUMN (list->data)->visible)
--            continue;
--          n_visible_columns ++;
--        }
--      cairo_save (cr);
--      gtk_cairo_transform_to_window(cr,widget,tree_view->priv->header_window);
--      pspp_sheet_view_draw_vertical_grid_lines (tree_view,
--                                              cr,
--                                              n_visible_columns,
--                                              0,
--                                              TREE_VIEW_HEADER_HEIGHT (tree_view));
--      cairo_restore (cr);
--    }
--  if (tree_view->priv->drag_window &&
--      gtk_cairo_should_draw_window (cr, tree_view->priv->drag_window))
--    {
--      gtk_container_propagate_draw (GTK_CONTAINER (tree_view),
--                                  tree_view->priv->drag_column->button,
--                                  cr);
--    }
--
--  gtk_style_context_restore (context);
--  return FALSE;
--}
--
--enum
--{
--  DROP_HOME,
--  DROP_RIGHT,
--  DROP_LEFT,
--  DROP_END
--};
--
--/* returns 0x1 when no column has been found -- yes it's hackish */
--static PsppSheetViewColumn *
--pspp_sheet_view_get_drop_column (PsppSheetView       *tree_view,
--                             PsppSheetViewColumn *column,
--                             gint               drop_position)
--{
--  PsppSheetViewColumn *left_column = NULL;
--  PsppSheetViewColumn *cur_column = NULL;
--  GList *tmp_list;
--
--  if (!column->reorderable)
--    return (PsppSheetViewColumn *)0x1;
--
--  switch (drop_position)
--    {
--      case DROP_HOME:
--      /* find first column where we can drop */
--      tmp_list = tree_view->priv->columns;
--      if (column == PSPP_SHEET_VIEW_COLUMN (tmp_list->data))
--        return (PsppSheetViewColumn *)0x1;
--
--      while (tmp_list)
--        {
--          g_assert (tmp_list);
--
--          cur_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
--          tmp_list = tmp_list->next;
--
--          if (left_column && left_column->visible == FALSE)
--            continue;
--
--          if (!tree_view->priv->column_drop_func)
--            return left_column;
--
--          if (!tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
--            {
--              left_column = cur_column;
--              continue;
--            }
--
--          return left_column;
--        }
--
--      if (!tree_view->priv->column_drop_func)
--        return left_column;
--
--      if (tree_view->priv->column_drop_func (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
--        return left_column;
--      else
--        return (PsppSheetViewColumn *)0x1;
--      break;
--
--      case DROP_RIGHT:
--      /* find first column after column where we can drop */
--      tmp_list = tree_view->priv->columns;
--
--      for (; tmp_list; tmp_list = tmp_list->next)
--        if (PSPP_SHEET_VIEW_COLUMN (tmp_list->data) == column)
--          break;
--
--      if (!tmp_list || !tmp_list->next)
--        return (PsppSheetViewColumn *)0x1;
--
--      tmp_list = tmp_list->next;
--      left_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
--      tmp_list = tmp_list->next;
--
--      while (tmp_list)
--        {
--          g_assert (tmp_list);
--
--          cur_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
--          tmp_list = tmp_list->next;
--
--          if (left_column && left_column->visible == FALSE)
--            {
--              left_column = cur_column;
--              if (tmp_list)
--                tmp_list = tmp_list->next;
--              continue;
--            }
--
--          if (!tree_view->priv->column_drop_func)
--            return left_column;
--
--          if (!tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
--            {
--              left_column = cur_column;
--              continue;
--            }
--
--          return left_column;
--        }
--
--      if (!tree_view->priv->column_drop_func)
--        return left_column;
--
--      if (tree_view->priv->column_drop_func (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data))
--        return left_column;
--      else
--        return (PsppSheetViewColumn *)0x1;
--      break;
--
--      case DROP_LEFT:
--      /* find first column before column where we can drop */
--      tmp_list = tree_view->priv->columns;
--
--      for (; tmp_list; tmp_list = tmp_list->next)
--        if (PSPP_SHEET_VIEW_COLUMN (tmp_list->data) == column)
--          break;
--
--      if (!tmp_list || !tmp_list->prev)
--        return (PsppSheetViewColumn *)0x1;
--
--      tmp_list = tmp_list->prev;
--      cur_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
--      tmp_list = tmp_list->prev;
--
--      while (tmp_list)
--        {
--          g_assert (tmp_list);
--
--          left_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
--
--          if (left_column && !left_column->visible)
--            {
--              /*if (!tmp_list->prev)
--                return (PsppSheetViewColumn *)0x1;
--                */
--/*
--              cur_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->prev->data);
--              tmp_list = tmp_list->prev->prev;
--              continue;*/
--
--              cur_column = left_column;
--              if (tmp_list)
--                tmp_list = tmp_list->prev;
--              continue;
--            }
--
--          if (!tree_view->priv->column_drop_func)
--            return left_column;
--
--          if (tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
--            return left_column;
--
--          cur_column = left_column;
--          tmp_list = tmp_list->prev;
--        }
--
--      if (!tree_view->priv->column_drop_func)
--        return NULL;
--
--      if (tree_view->priv->column_drop_func (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
--        return NULL;
--      else
--        return (PsppSheetViewColumn *)0x1;
--      break;
--
--      case DROP_END:
--      /* same as DROP_HOME case, but doing it backwards */
--      tmp_list = g_list_last (tree_view->priv->columns);
--      cur_column = NULL;
--
--      if (column == PSPP_SHEET_VIEW_COLUMN (tmp_list->data))
--        return (PsppSheetViewColumn *)0x1;
--
--      while (tmp_list)
--        {
--          g_assert (tmp_list);
--
--          left_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
--
--          if (left_column && !left_column->visible)
--            {
--              cur_column = left_column;
--              tmp_list = tmp_list->prev;
--            }
--
--          if (!tree_view->priv->column_drop_func)
--            return left_column;
--
--          if (tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
--            return left_column;
--
--          cur_column = left_column;
--          tmp_list = tmp_list->prev;
--        }
--
--      if (!tree_view->priv->column_drop_func)
--        return NULL;
--
--      if (tree_view->priv->column_drop_func (tree_view, column, NULL, cur_column, tree_view->priv->column_drop_func_data))
--        return NULL;
--      else
--        return (PsppSheetViewColumn *)0x1;
--      break;
--    }
--
--  return (PsppSheetViewColumn *)0x1;
--}
--
--static gboolean
--pspp_sheet_view_key_press (GtkWidget   *widget,
--                       GdkEventKey *event)
--{
--  PsppSheetView *tree_view = (PsppSheetView *) widget;
--
--  if (tree_view->priv->rubber_band_status)
--    {
--      if (event->keyval == GDK_Escape)
--      pspp_sheet_view_stop_rubber_band (tree_view);
--
--      return TRUE;
--    }
--
--  if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_DRAG))
--    {
--      if (event->keyval == GDK_Escape)
--      {
--        tree_view->priv->cur_reorder = NULL;
--        pspp_sheet_view_button_release_drag_column (widget, NULL);
--      }
--      return TRUE;
--    }
--
--  if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE))
--    {
--      GList *focus_column;
--      gboolean rtl;
--
--      rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--
--      for (focus_column = tree_view->priv->columns;
--           focus_column;
--           focus_column = focus_column->next)
--        {
--          PsppSheetViewColumn *column = PSPP_SHEET_VIEW_COLUMN (focus_column->data);
--
--          if (column->button && gtk_widget_has_focus (column->button))
--            break;
--        }
--
--      if (focus_column &&
--          (event->state & GDK_SHIFT_MASK) && (event->state & GDK_MOD1_MASK) &&
--          (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
--           || event->keyval == GDK_Right || event->keyval == GDK_KP_Right))
--        {
--          PsppSheetViewColumn *column = PSPP_SHEET_VIEW_COLUMN (focus_column->data);
--
--          if (!column->resizable)
--            {
--              gtk_widget_error_bell (widget);
--              return TRUE;
--            }
--
--          if (event->keyval == (rtl ? GDK_Right : GDK_Left)
--              || event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))
--            {
--              gint old_width = column->resized_width;
--
--              column->resized_width = MAX (column->resized_width,
--                                           column->width);
--              column->resized_width -= 2;
--              if (column->resized_width < 0)
--                column->resized_width = 0;
--
--              if (column->min_width == -1)
--                column->resized_width = MAX (column->button_request,
--                                             column->resized_width);
--              else
--                column->resized_width = MAX (column->min_width,
--                                             column->resized_width);
--
--              if (column->max_width != -1)
--                column->resized_width = MIN (column->resized_width,
--                                             column->max_width);
--
--              column->use_resized_width = TRUE;
--
--              if (column->resized_width != old_width)
--                gtk_widget_queue_resize (widget);
--              else
--                gtk_widget_error_bell (widget);
--            }
--          else if (event->keyval == (rtl ? GDK_Left : GDK_Right)
--                   || event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
--            {
--              gint old_width = column->resized_width;
--
--              column->resized_width = MAX (column->resized_width,
--                                           column->width);
--              column->resized_width += 2;
--
--              if (column->max_width != -1)
--                column->resized_width = MIN (column->resized_width,
--                                             column->max_width);
--
--              column->use_resized_width = TRUE;
--
--              if (column->resized_width != old_width)
--                gtk_widget_queue_resize (widget);
--              else
--                gtk_widget_error_bell (widget);
--            }
--
--          return TRUE;
--        }
--
--      if (focus_column &&
--          (event->state & GDK_MOD1_MASK) &&
--          (event->keyval == GDK_Left || event->keyval == GDK_KP_Left
--           || event->keyval == GDK_Right || event->keyval == GDK_KP_Right
--           || event->keyval == GDK_Home || event->keyval == GDK_KP_Home
--           || event->keyval == GDK_End || event->keyval == GDK_KP_End))
--        {
--          PsppSheetViewColumn *column = PSPP_SHEET_VIEW_COLUMN (focus_column->data);
--
--          if (event->keyval == (rtl ? GDK_Right : GDK_Left)
--              || event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))
--            {
--              PsppSheetViewColumn *col;
--              col = pspp_sheet_view_get_drop_column (tree_view, column, DROP_LEFT);
--              if (col != (PsppSheetViewColumn *)0x1)
--                pspp_sheet_view_move_column_after (tree_view, column, col);
--              else
--                gtk_widget_error_bell (widget);
--            }
--          else if (event->keyval == (rtl ? GDK_Left : GDK_Right)
--                   || event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
--            {
--              PsppSheetViewColumn *col;
--              col = pspp_sheet_view_get_drop_column (tree_view, column, DROP_RIGHT);
--              if (col != (PsppSheetViewColumn *)0x1)
--                pspp_sheet_view_move_column_after (tree_view, column, col);
--              else
--                gtk_widget_error_bell (widget);
--            }
--          else if (event->keyval == GDK_Home || event->keyval == GDK_KP_Home)
--            {
--              PsppSheetViewColumn *col;
--              col = pspp_sheet_view_get_drop_column (tree_view, column, DROP_HOME);
--              if (col != (PsppSheetViewColumn *)0x1)
--                pspp_sheet_view_move_column_after (tree_view, column, col);
--              else
--                gtk_widget_error_bell (widget);
--            }
--          else if (event->keyval == GDK_End || event->keyval == GDK_KP_End)
--            {
--              PsppSheetViewColumn *col;
--              col = pspp_sheet_view_get_drop_column (tree_view, column, DROP_END);
--              if (col != (PsppSheetViewColumn *)0x1)
--                pspp_sheet_view_move_column_after (tree_view, column, col);
--              else
--                gtk_widget_error_bell (widget);
--            }
--
--          return TRUE;
--        }
--    }
--
--  /* Chain up to the parent class.  It handles the keybindings. */
--  if (GTK_WIDGET_CLASS (pspp_sheet_view_parent_class)->key_press_event (widget, event))
--    return TRUE;
--
--  if (tree_view->priv->search_entry_avoid_unhandled_binding)
--    {
--      tree_view->priv->search_entry_avoid_unhandled_binding = FALSE;
--      return FALSE;
--    }
--
--  /* We pass the event to the search_entry.  If its text changes, then we start
--   * the typeahead find capabilities. */
--  if (gtk_widget_has_focus (GTK_WIDGET (tree_view))
--      && tree_view->priv->enable_search
--      && !tree_view->priv->search_custom_entry_set)
--    {
--      GdkEvent *new_event;
--      char *old_text;
--      const char *new_text;
--      gboolean retval;
--      GdkScreen *screen;
--      gboolean text_modified;
--      gulong popup_menu_id;
--
--      pspp_sheet_view_ensure_interactive_directory (tree_view);
--
--      /* Make a copy of the current text */
--      old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry)));
--      new_event = gdk_event_copy ((GdkEvent *) event);
--      g_object_unref (((GdkEventKey *) new_event)->window);
--      ((GdkEventKey *) new_event)->window = g_object_ref (gtk_widget_get_window (tree_view->priv->search_window));
--      gtk_widget_realize (tree_view->priv->search_window);
--
--      popup_menu_id = g_signal_connect (tree_view->priv->search_entry, 
--                                      "popup-menu", G_CALLBACK (gtk_true),
--                                        NULL);
--
--      /* Move the entry off screen */
--      screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
--      gtk_window_move (GTK_WINDOW (tree_view->priv->search_window),
--                     gdk_screen_get_width (screen) + 1,
--                     gdk_screen_get_height (screen) + 1);
--      gtk_widget_show (tree_view->priv->search_window);
--
--      /* Send the event to the window.  If the preedit_changed signal is emitted
--       * during this event, we will set priv->imcontext_changed  */
--      tree_view->priv->imcontext_changed = FALSE;
--      retval = gtk_widget_event (tree_view->priv->search_window, new_event);
--      gdk_event_free (new_event);
--      gtk_widget_hide (tree_view->priv->search_window);
--
--      g_signal_handler_disconnect (tree_view->priv->search_entry, 
--                                 popup_menu_id);
--
--      /* We check to make sure that the entry tried to handle the text, and that
--       * the text has changed.
--       */
--      new_text = gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry));
--      text_modified = strcmp (old_text, new_text) != 0;
--      g_free (old_text);
--      if (tree_view->priv->imcontext_changed ||    /* we're in a preedit */
--        (retval && text_modified))               /* ...or the text was modified */
--      {
--        if (pspp_sheet_view_real_start_interactive_search (tree_view, FALSE))
--          {
--            gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--            return TRUE;
--          }
--        else
--          {
--            gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
--            return FALSE;
--          }
--      }
--    }
--
--  return FALSE;
--}
--
--static gboolean
--pspp_sheet_view_key_release (GtkWidget   *widget,
--                         GdkEventKey *event)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--
--  if (tree_view->priv->rubber_band_status)
--    return TRUE;
--
--  return GTK_WIDGET_CLASS (pspp_sheet_view_parent_class)->key_release_event (widget, event);
--}
--
--/* FIXME Is this function necessary? Can I get an enter_notify event
-- * w/o either an expose event or a mouse motion event?
-- */
--static gboolean
--pspp_sheet_view_enter_notify (GtkWidget        *widget,
--                          GdkEventCrossing *event)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--  int node;
--  gint new_y;
--
--  /* Sanity check it */
--  if (event->window != tree_view->priv->bin_window)
--    return FALSE;
--
--  if (tree_view->priv->row_count == 0)
--    return FALSE;
--
--  if (event->mode == GDK_CROSSING_GRAB ||
--      event->mode == GDK_CROSSING_GTK_GRAB ||
--      event->mode == GDK_CROSSING_GTK_UNGRAB ||
--      event->mode == GDK_CROSSING_STATE_CHANGED)
--    return TRUE;
--
--  /* find the node internally */
--  new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, event->y);
--  if (new_y < 0)
--    new_y = 0;
--  pspp_sheet_view_find_offset (tree_view, new_y, &node);
--
--  tree_view->priv->event_last_x = event->x;
--  tree_view->priv->event_last_y = event->y;
--
--  prelight_or_select (tree_view, node, event->x, event->y);
--
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_leave_notify (GtkWidget        *widget,
--                          GdkEventCrossing *event)
--{
--  PsppSheetView *tree_view;
--
--  if (event->mode == GDK_CROSSING_GRAB)
--    return TRUE;
--
--  tree_view = PSPP_SHEET_VIEW (widget);
--
--  if (tree_view->priv->prelight_node >= 0)
--    _pspp_sheet_view_queue_draw_node (tree_view,
--                                   tree_view->priv->prelight_node,
--                                   NULL);
--
--  tree_view->priv->event_last_x = -10000;
--  tree_view->priv->event_last_y = -10000;
--
--  prelight_or_select (tree_view,
--                    -1,
--                    -1000, -1000); /* coords not possibly over an arrow */
--
--  return TRUE;
--}
--
--
--static gint
--pspp_sheet_view_focus_out (GtkWidget     *widget,
--                       GdkEventFocus *event)
--{
--  PsppSheetView *tree_view;
--
--  tree_view = PSPP_SHEET_VIEW (widget);
--
--  gtk_widget_queue_draw (widget);
--
--  /* destroy interactive search dialog */
--  if (tree_view->priv->search_window)
--    pspp_sheet_view_search_dialog_hide (tree_view->priv->search_window, tree_view);
--
--  return FALSE;
--}
--
--
--/* Incremental Reflow
-- */
--
--static void
--pspp_sheet_view_node_queue_redraw (PsppSheetView *tree_view,
--                               int node)
--{
--  GtkAllocation allocation;
--  gint y = pspp_sheet_view_node_find_offset (tree_view, node)
--    - gtk_adjustment_get_value (tree_view->priv->vadjustment)
--    + TREE_VIEW_HEADER_HEIGHT (tree_view);
--
--  gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
--
--  gtk_widget_queue_draw_area (GTK_WIDGET (tree_view),
--                            0, y,
--                            allocation.width,
--                              tree_view->priv->fixed_height);
--}
--
--static gboolean
--node_is_visible (PsppSheetView *tree_view,
--               int node)
--{
--  int y;
--  int height;
--
--  y = pspp_sheet_view_node_find_offset (tree_view, node);
--  height = ROW_HEIGHT (tree_view);
--
--  if (y >= gtk_adjustment_get_value (tree_view->priv->vadjustment) &&
--      y + height <= (gtk_adjustment_get_value (tree_view->priv->vadjustment)
--                   + gtk_adjustment_get_page_size (tree_view->priv->vadjustment)))
--    return TRUE;
--
--  return FALSE;
--}
--
--/* Returns the row height. */
--static gint
--validate_row (PsppSheetView *tree_view,
--            int node,
--            GtkTreeIter *iter,
--            GtkTreePath *path)
--{
--  PsppSheetViewColumn *column;
--  GList *list, *first_column, *last_column;
--  gint height = 0;
--  gint horizontal_separator;
--  gint vertical_separator;
--  gint focus_line_width;
--  gboolean draw_vgrid_lines, draw_hgrid_lines;
--  gint focus_pad;
--  gint grid_line_width;
--  gboolean wide_separators;
--  gint separator_height;
--
--  gtk_widget_style_get (GTK_WIDGET (tree_view),
--                      "focus-padding", &focus_pad,
--                      "focus-line-width", &focus_line_width,
--                      "horizontal-separator", &horizontal_separator,
--                      "vertical-separator", &vertical_separator,
--                      "grid-line-width", &grid_line_width,
--                        "wide-separators",  &wide_separators,
--                        "separator-height", &separator_height,
--                      NULL);
--  
--  draw_vgrid_lines =
--    tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_VERTICAL
--    || tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_BOTH;
--  draw_hgrid_lines =
--    tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_HORIZONTAL
--    || tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_BOTH;
--
--  for (last_column = g_list_last (tree_view->priv->columns);
--       last_column && !(PSPP_SHEET_VIEW_COLUMN (last_column->data)->visible);
--       last_column = last_column->prev)
--    ;
--
--  for (first_column = g_list_first (tree_view->priv->columns);
--       first_column && !(PSPP_SHEET_VIEW_COLUMN (first_column->data)->visible);
--       first_column = first_column->next)
--    ;
--
--  for (list = tree_view->priv->columns; list; list = list->next)
--    {
--      gint tmp_width;
--      gint tmp_height;
--
--      column = list->data;
--
--      if (! column->visible)
--      continue;
--
--      pspp_sheet_view_column_cell_set_cell_data (column, tree_view->priv->model, iter);
--      pspp_sheet_view_column_cell_get_size (column,
--                                        NULL, NULL, NULL,
--                                        &tmp_width, &tmp_height);
--
--      tmp_height += vertical_separator;
--      height = MAX (height, tmp_height);
--
--      tmp_width = tmp_width + horizontal_separator;
--
--      if (draw_vgrid_lines)
--        {
--        if (list->data == first_column || list->data == last_column)
--          tmp_width += grid_line_width / 2.0;
--        else
--          tmp_width += grid_line_width;
--      }
--
--      if (tmp_width > column->requested_width)
--        column->requested_width = tmp_width;
--    }
--
--  if (draw_hgrid_lines)
--    height += grid_line_width;
--
--  tree_view->priv->post_validation_flag = TRUE;
--  return height;
--}
--
--
--static void
--validate_visible_area (PsppSheetView *tree_view)
--{
--  GtkTreePath *path = NULL;
--  GtkTreePath *above_path = NULL;
--  GtkTreeIter iter;
--  int node = -1;
--  gint total_height;
--  gint area_above = 0;
--  gint area_below = 0;
--  GtkAllocation allocation;
--
--  if (tree_view->priv->row_count == 0)
--    return;
--
--  if (tree_view->priv->scroll_to_path == NULL)
--    return;
--
--  gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
--
--  total_height = allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
--
--  if (total_height == 0)
--    return;
--
--  path = gtk_tree_row_reference_get_path (tree_view->priv->scroll_to_path);
--  if (path)
--    {
--      /* we are going to scroll, and will update dy */
--      _pspp_sheet_view_find_node (tree_view, path, &node);
--      gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
--
--      if (tree_view->priv->scroll_to_use_align)
--        {
--          gint height = ROW_HEIGHT (tree_view);
--          area_above = (total_height - height) *
--            tree_view->priv->scroll_to_row_align;
--          area_below = total_height - area_above - height;
--          area_above = MAX (area_above, 0);
--          area_below = MAX (area_below, 0);
--        }
--      else
--        {
--          /* two cases:
--           * 1) row not visible
--           * 2) row visible
--           */
--          gint dy;
--          gint height = ROW_HEIGHT (tree_view);
--
--          dy = pspp_sheet_view_node_find_offset (tree_view, node);
--
--          if (dy >= gtk_adjustment_get_value (tree_view->priv->vadjustment) &&
--              dy + height <= (gtk_adjustment_get_value (tree_view->priv->vadjustment)
--                              + gtk_adjustment_get_page_size (tree_view->priv->vadjustment)))
--            {
--              /* row visible: keep the row at the same position */
--              area_above = dy - gtk_adjustment_get_value (tree_view->priv->vadjustment);
--              area_below = (gtk_adjustment_get_value (tree_view->priv->vadjustment) +
--                            gtk_adjustment_get_page_size (tree_view->priv->vadjustment))
--                - dy - height;
--            }
--          else
--            {
--              /* row not visible */
--              if (dy >= 0
--                  && dy + height <= gtk_adjustment_get_page_size (tree_view->priv->vadjustment))
--                {
--                  /* row at the beginning -- fixed */
--                  area_above = dy;
--                  area_below = gtk_adjustment_get_page_size (tree_view->priv->vadjustment)
--                    - area_above - height;
--                }
--              else if (dy >= (gtk_adjustment_get_upper (tree_view->priv->vadjustment) -
--                              gtk_adjustment_get_page_size (tree_view->priv->vadjustment)))
--                {
--                  /* row at the end -- fixed */
--                  area_above = dy - (gtk_adjustment_get_upper (tree_view->priv->vadjustment) -
--                                     gtk_adjustment_get_page_size (tree_view->priv->vadjustment));
--                  area_below = gtk_adjustment_get_page_size (tree_view->priv->vadjustment) -
--                    area_above - height;
--
--                  if (area_below < 0)
--                    {
--                      area_above = gtk_adjustment_get_page_size (tree_view->priv->vadjustment) - height;
--                      area_below = 0;
--                    }
--                }
--              else
--                {
--                  /* row somewhere in the middle, bring it to the top
--                   * of the view
--                   */
--                  area_above = 0;
--                  area_below = total_height - height;
--                }
--            }
--        }
--    }
--  else
--    /* the scroll to isn't valid; ignore it.
--     */
--    {
--      gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
--      tree_view->priv->scroll_to_path = NULL;
--      return;
--    }
--
--  above_path = gtk_tree_path_copy (path);
--
--  /* Now, we walk forwards and backwards, measuring rows. Unfortunately,
--   * backwards is much slower then forward, as there is no iter_prev function.
--   * We go forwards first in case we run out of tree.  Then we go backwards to
--   * fill out the top.
--   */
--  while (node >= 0 && area_below > 0)
--    {
--      gboolean done = FALSE;
--      do
--        {
--          node = pspp_sheet_view_node_next (tree_view, node);
--          if (node >= 0)
--            {
--              gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
--              done = TRUE;
--              gtk_tree_path_next (path);
--
--              /* Sanity Check! */
--              TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
--            }
--          else
--            break;
--        }
--      while (!done);
--
--      if (node < 0)
--        break;
--
--      area_below -= ROW_HEIGHT (tree_view);
--    }
--  gtk_tree_path_free (path);
--
--  /* If we ran out of tree, and have extra area_below left, we need to add it
--   * to area_above */
--  if (area_below > 0)
--    area_above += area_below;
--
--  _pspp_sheet_view_find_node (tree_view, above_path, &node);
--
--  /* We walk backwards */
--  while (area_above > 0)
--    {
--      node = pspp_sheet_view_node_prev (tree_view, node);
--
--      /* Always find the new path in the tree.  We cannot just assume
--       * a gtk_tree_path_prev() is enough here, as there might be children
--       * in between this node and the previous sibling node.  If this
--       * appears to be a performance hotspot in profiles, we can look into
--       * intrigate logic for keeping path, node and iter in sync like
--       * we do for forward walks.  (Which will be hard because of the lacking
--       * iter_prev).
--       */
--
--      if (node < 0)
--      break;
--
--      gtk_tree_path_free (above_path);
--      above_path = _pspp_sheet_view_find_path (tree_view, node);
--
--      gtk_tree_model_get_iter (tree_view->priv->model, &iter, above_path);
--
--      area_above -= ROW_HEIGHT (tree_view);
--    }
--
--  /* set the dy here to scroll to the path,
--   * and sync the top row accordingly
--   */
--  pspp_sheet_view_set_top_row (tree_view, above_path, -area_above);
--  pspp_sheet_view_top_row_to_dy (tree_view);
--
--  gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
--  tree_view->priv->scroll_to_path = NULL;
--
--  if (above_path)
--    gtk_tree_path_free (above_path);
--
--  if (tree_view->priv->scroll_to_column)
--    {
--      tree_view->priv->scroll_to_column = NULL;
--    }
--  gtk_widget_queue_draw (GTK_WIDGET (tree_view));
--}
--
--static void
--initialize_fixed_height_mode (PsppSheetView *tree_view)
--{
--  if (!tree_view->priv->row_count)
--    return;
--
--  if (tree_view->priv->fixed_height_set)
--    return;
--
--  if (tree_view->priv->fixed_height < 0)
--    {
--      GtkTreeIter iter;
--      GtkTreePath *path;
--
--      int node = 0;
--
--      path = _pspp_sheet_view_find_path (tree_view, node);
--      gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
--
--      tree_view->priv->fixed_height = validate_row (tree_view, node, &iter, path);
--
--      gtk_tree_path_free (path);
--
--      g_object_notify (G_OBJECT (tree_view), "fixed-height");
--    }
--}
--
--/* Our strategy for finding nodes to validate is a little convoluted.  We find
-- * the left-most uninvalidated node.  We then try walking right, validating
-- * nodes.  Once we find a valid node, we repeat the previous process of finding
-- * the first invalid node.
-- */
--
--static gboolean
--validate_rows_handler (PsppSheetView *tree_view)
--{
--  initialize_fixed_height_mode (tree_view);
--  if (tree_view->priv->validate_rows_timer)
--    {
--      g_source_remove (tree_view->priv->validate_rows_timer);
--      tree_view->priv->validate_rows_timer = 0;
--    }
--
--  return FALSE;
--}
--
--static gboolean
--do_presize_handler (PsppSheetView *tree_view)
--{
--  GtkRequisition requisition;
--
--  validate_visible_area (tree_view);
--  tree_view->priv->presize_handler_timer = 0;
--
--  if (! gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    return FALSE;
--
--  gtk_widget_get_preferred_size (GTK_WIDGET (tree_view), NULL, &requisition);
--
--  gtk_adjustment_set_upper (tree_view->priv->hadjustment, MAX (gtk_adjustment_get_upper (tree_view->priv->hadjustment), (gfloat)requisition.width));
--  gtk_adjustment_set_upper (tree_view->priv->vadjustment, MAX (gtk_adjustment_get_upper (tree_view->priv->vadjustment), (gfloat)requisition.height));
--  gtk_adjustment_changed (tree_view->priv->hadjustment);
--  gtk_adjustment_changed (tree_view->priv->vadjustment);
--  gtk_widget_queue_resize (GTK_WIDGET (tree_view));
--                 
--  return FALSE;
--}
--
--static gboolean
--presize_handler_callback (gpointer data)
--{
--  do_presize_handler (PSPP_SHEET_VIEW (data));
--                 
--  return FALSE;
--}
--
--static void
--install_presize_handler (PsppSheetView *tree_view)
--{
--  if (! gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    return;
--
--  if (! tree_view->priv->presize_handler_timer)
--    {
--      tree_view->priv->presize_handler_timer =
--      gdk_threads_add_idle_full (GTK_PRIORITY_RESIZE - 2, presize_handler_callback, tree_view, NULL);
--    }
--  if (! tree_view->priv->validate_rows_timer)
--    {
--      tree_view->priv->validate_rows_timer =
--      gdk_threads_add_idle_full (PSPP_SHEET_VIEW_PRIORITY_VALIDATE, (GSourceFunc) validate_rows_handler, tree_view, NULL);
--    }
--}
--
--static gboolean
--scroll_sync_handler (PsppSheetView *tree_view)
--{
--  if (tree_view->priv->height <= gtk_adjustment_get_page_size (tree_view->priv->vadjustment))
--    gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment), 0);
--  else if (gtk_tree_row_reference_valid (tree_view->priv->top_row))
--    pspp_sheet_view_top_row_to_dy (tree_view);
--  else
--    pspp_sheet_view_dy_to_top_row (tree_view);
--
--  tree_view->priv->scroll_sync_timer = 0;
--
--  return FALSE;
--}
--
--static void
--install_scroll_sync_handler (PsppSheetView *tree_view)
--{
--  if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    return;
--
--  if (!tree_view->priv->scroll_sync_timer)
--    {
--      tree_view->priv->scroll_sync_timer =
--      gdk_threads_add_idle_full (PSPP_SHEET_VIEW_PRIORITY_SCROLL_SYNC, (GSourceFunc) scroll_sync_handler, tree_view, NULL);
--    }
--}
--
--static void
--pspp_sheet_view_set_top_row (PsppSheetView *tree_view,
--                         GtkTreePath *path,
--                         gint         offset)
--{
--  gtk_tree_row_reference_free (tree_view->priv->top_row);
--
--  if (!path)
--    {
--      tree_view->priv->top_row = NULL;
--      tree_view->priv->top_row_dy = 0;
--    }
--  else
--    {
--      tree_view->priv->top_row = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
--      tree_view->priv->top_row_dy = offset;
--    }
--}
--
--/* Always call this iff dy is in the visible range.  If the tree is empty, then
-- * it's set to be NULL, and top_row_dy is 0;
-- */
--static void
--pspp_sheet_view_dy_to_top_row (PsppSheetView *tree_view)
--{
--  gint offset;
--  GtkTreePath *path;
--  int node;
--
--  if (tree_view->priv->row_count == 0)
--    {
--      pspp_sheet_view_set_top_row (tree_view, NULL, 0);
--    }
--  else
--    {
--      offset = pspp_sheet_view_find_offset (tree_view,
--                                            tree_view->priv->dy,
--                                            &node);
--
--      if (node < 0)
--        {
--        pspp_sheet_view_set_top_row (tree_view, NULL, 0);
--      }
--      else
--        {
--        path = _pspp_sheet_view_find_path (tree_view, node);
--        pspp_sheet_view_set_top_row (tree_view, path, offset);
--        gtk_tree_path_free (path);
--      }
--    }
--}
--
--static void
--pspp_sheet_view_top_row_to_dy (PsppSheetView *tree_view)
--{
--  GtkTreePath *path;
--  int node;
--  int new_dy;
--
--  /* Avoid recursive calls */
--  if (tree_view->priv->in_top_row_to_dy)
--    return;
--
--  if (tree_view->priv->top_row)
--    path = gtk_tree_row_reference_get_path (tree_view->priv->top_row);
--  else
--    path = NULL;
--
--  if (!path)
--    node = -1;
--  else
--    _pspp_sheet_view_find_node (tree_view, path, &node);
--
--  if (path)
--    gtk_tree_path_free (path);
--
--  if (node < 0)
--    {
--      /* keep dy and set new toprow */
--      gtk_tree_row_reference_free (tree_view->priv->top_row);
--      tree_view->priv->top_row = NULL;
--      tree_view->priv->top_row_dy = 0;
--      /* DO NOT install the idle handler */
--      pspp_sheet_view_dy_to_top_row (tree_view);
--      return;
--    }
--
--  if (ROW_HEIGHT (tree_view) < tree_view->priv->top_row_dy)
--    {
--      /* new top row -- do NOT install the idle handler */
--      pspp_sheet_view_dy_to_top_row (tree_view);
--      return;
--    }
--
--  new_dy = pspp_sheet_view_node_find_offset (tree_view, node);
--  new_dy += tree_view->priv->top_row_dy;
--
--  if (new_dy + gtk_adjustment_get_page_size (tree_view->priv->vadjustment) > tree_view->priv->height)
--    new_dy = tree_view->priv->height - gtk_adjustment_get_page_size (tree_view->priv->vadjustment);
--
--  new_dy = MAX (0, new_dy);
--
--  tree_view->priv->in_top_row_to_dy = TRUE;
--  gtk_adjustment_set_value (tree_view->priv->vadjustment, (gdouble)new_dy);
--  tree_view->priv->in_top_row_to_dy = FALSE;
--}
--
--
--void
--_pspp_sheet_view_install_mark_rows_col_dirty (PsppSheetView *tree_view)
--{
--  install_presize_handler (tree_view);
--}
--
--/* Drag-and-drop */
--
--static void
--set_source_row (GdkDragContext *context,
--                GtkTreeModel   *model,
--                GtkTreePath    *source_row)
--{
--  g_object_set_data_full (G_OBJECT (context),
--                          "gtk-tree-view-source-row",
--                          source_row ? gtk_tree_row_reference_new (model, source_row) : NULL,
--                          (GDestroyNotify) (source_row ? gtk_tree_row_reference_free : NULL));
--}
--
--static GtkTreePath*
--get_source_row (GdkDragContext *context)
--{
--  GtkTreeRowReference *ref =
--    g_object_get_data (G_OBJECT (context), "gtk-tree-view-source-row");
--
--  if (ref)
--    return gtk_tree_row_reference_get_path (ref);
--  else
--    return NULL;
--}
--
--typedef struct
--{
--  GtkTreeRowReference *dest_row;
--  guint                path_down_mode   : 1;
--  guint                empty_view_drop  : 1;
--  guint                drop_append_mode : 1;
--}
--DestRow;
--
--static void
--dest_row_free (gpointer data)
--{
--  DestRow *dr = (DestRow *)data;
--
--  gtk_tree_row_reference_free (dr->dest_row);
--  g_slice_free (DestRow, dr);
--}
--
--static void
--set_dest_row (GdkDragContext *context,
--              GtkTreeModel   *model,
--              GtkTreePath    *dest_row,
--              gboolean        path_down_mode,
--              gboolean        empty_view_drop,
--              gboolean        drop_append_mode)
--{
--  DestRow *dr;
--
--  if (!dest_row)
--    {
--      g_object_set_data_full (G_OBJECT (context), "gtk-tree-view-dest-row",
--                              NULL, NULL);
--      return;
--    }
--
--  dr = g_slice_new (DestRow);
--
--  dr->dest_row = gtk_tree_row_reference_new (model, dest_row);
--  dr->path_down_mode = path_down_mode != FALSE;
--  dr->empty_view_drop = empty_view_drop != FALSE;
--  dr->drop_append_mode = drop_append_mode != FALSE;
--
--  g_object_set_data_full (G_OBJECT (context), "gtk-tree-view-dest-row",
--                          dr, (GDestroyNotify) dest_row_free);
--}
--
--static GtkTreePath*
--get_dest_row (GdkDragContext *context,
--              gboolean       *path_down_mode)
--{
--  DestRow *dr =
--    g_object_get_data (G_OBJECT (context), "gtk-tree-view-dest-row");
--
--  if (dr)
--    {
--      GtkTreePath *path = NULL;
--
--      if (path_down_mode)
--        *path_down_mode = dr->path_down_mode;
--
--      if (dr->dest_row)
--        path = gtk_tree_row_reference_get_path (dr->dest_row);
--      else if (dr->empty_view_drop)
--        path = gtk_tree_path_new_from_indices (0, -1);
--      else
--        path = NULL;
--
--      if (path && dr->drop_append_mode)
--        gtk_tree_path_next (path);
--
--      return path;
--    }
--  else
--    return NULL;
--}
--
--/* Get/set whether drag_motion requested the drag data and
-- * drag_data_received should thus not actually insert the data,
-- * since the data doesn't result from a drop.
-- */
--static void
--set_status_pending (GdkDragContext *context,
--                    GdkDragAction   suggested_action)
--{
--  g_object_set_data (G_OBJECT (context),
--                     "gtk-tree-view-status-pending",
--                     GINT_TO_POINTER (suggested_action));
--}
--
--static GdkDragAction
--get_status_pending (GdkDragContext *context)
--{
--  return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
--                                             "gtk-tree-view-status-pending"));
--}
--
--static TreeViewDragInfo*
--get_info (PsppSheetView *tree_view)
--{
--  return g_object_get_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info");
--}
--
--static void
--destroy_info (TreeViewDragInfo *di)
--{
--  g_slice_free (TreeViewDragInfo, di);
--}
--
--static TreeViewDragInfo*
--ensure_info (PsppSheetView *tree_view)
--{
--  TreeViewDragInfo *di;
--
--  di = get_info (tree_view);
--
--  if (di == NULL)
--    {
--      di = g_slice_new0 (TreeViewDragInfo);
--
--      g_object_set_data_full (G_OBJECT (tree_view),
--                              "gtk-tree-view-drag-info",
--                              di,
--                              (GDestroyNotify) destroy_info);
--    }
--
--  return di;
--}
--
--static void
--remove_info (PsppSheetView *tree_view)
--{
--  g_object_set_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info", NULL);
--}
--
--#if 0
--static gint
--drag_scan_timeout (gpointer data)
--{
--  PsppSheetView *tree_view;
--  gint x, y;
--  GdkModifierType state;
--  GtkTreePath *path = NULL;
--  PsppSheetViewColumn *column = NULL;
--  GdkRectangle visible_rect;
--
--  GDK_THREADS_ENTER ();
--
--  tree_view = PSPP_SHEET_VIEW (data);
--
--  gdk_window_get_pointer (tree_view->priv->bin_window,
--                          &x, &y, &state);
--
--  pspp_sheet_view_get_visible_rect (tree_view, &visible_rect);
--
--  /* See if we are near the edge. */
--  if ((x - visible_rect.x) < SCROLL_EDGE_SIZE ||
--      (visible_rect.x + visible_rect.width - x) < SCROLL_EDGE_SIZE ||
--      (y - visible_rect.y) < SCROLL_EDGE_SIZE ||
--      (visible_rect.y + visible_rect.height - y) < SCROLL_EDGE_SIZE)
--    {
--      pspp_sheet_view_get_path_at_pos (tree_view,
--                                     tree_view->priv->bin_window,
--                                     x, y,
--                                     &path,
--                                     &column,
--                                     NULL,
--                                     NULL);
--
--      if (path != NULL)
--        {
--          pspp_sheet_view_scroll_to_cell (tree_view,
--                                        path,
--                                        column,
--                                      TRUE,
--                                        0.5, 0.5);
--
--          gtk_tree_path_free (path);
--        }
--    }
--
--  GDK_THREADS_LEAVE ();
--
--  return TRUE;
--}
--#endif /* 0 */
--
--static void
--add_scroll_timeout (PsppSheetView *tree_view)
--{
--  if (tree_view->priv->scroll_timeout == 0)
--    {
--      tree_view->priv->scroll_timeout =
--      gdk_threads_add_timeout (150, scroll_row_timeout, tree_view);
--    }
--}
--
--static void
--remove_scroll_timeout (PsppSheetView *tree_view)
--{
--  if (tree_view->priv->scroll_timeout != 0)
--    {
--      g_source_remove (tree_view->priv->scroll_timeout);
--      tree_view->priv->scroll_timeout = 0;
--    }
--}
--
--static gboolean
--check_model_dnd (GtkTreeModel *model,
--                 GType         required_iface,
--                 const gchar  *signal)
--{
--  if (model == NULL || !G_TYPE_CHECK_INSTANCE_TYPE ((model), required_iface))
--    {
--      g_warning ("You must override the default '%s' handler "
--                 "on PsppSheetView when using models that don't support "
--                 "the %s interface and enabling drag-and-drop. The simplest way to do this "
--                 "is to connect to '%s' and call "
--                 "g_signal_stop_emission_by_name() in your signal handler to prevent "
--                 "the default handler from running. Look at the source code "
--                 "for the default handler in gtktreeview.c to get an idea what "
--                 "your handler should do. (gtktreeview.c is in the GTK source "
--                 "code.) If you're using GTK from a language other than C, "
--                 "there may be a more natural way to override default handlers, e.g. via derivation.",
--                 signal, g_type_name (required_iface), signal);
--      return FALSE;
--    }
--  else
--    return TRUE;
--}
--
--static gboolean
--scroll_row_timeout (gpointer data)
--{
--  PsppSheetView *tree_view = data;
--
--  pspp_sheet_view_horizontal_autoscroll (tree_view);
--  pspp_sheet_view_vertical_autoscroll (tree_view);
--
--  if (tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
--    pspp_sheet_view_update_rubber_band (tree_view);
--
--  return TRUE;
--}
--
--/* Returns TRUE if event should not be propagated to parent widgets */
--static gboolean
--set_destination_row (PsppSheetView    *tree_view,
--                     GdkDragContext *context,
--                     /* coordinates relative to the widget */
--                     gint            x,
--                     gint            y,
--                     GdkDragAction  *suggested_action,
--                     GdkAtom        *target)
--{
--  GtkTreePath *path = NULL;
--  PsppSheetViewDropPosition pos;
--  PsppSheetViewDropPosition old_pos;
--  TreeViewDragInfo *di;
--  GtkWidget *widget;
--  GtkTreePath *old_dest_path = NULL;
--  gboolean can_drop = FALSE;
--
--  *suggested_action = 0;
--  *target = GDK_NONE;
--
--  widget = GTK_WIDGET (tree_view);
--
--  di = get_info (tree_view);
--
--  if (di == NULL || y - TREE_VIEW_HEADER_HEIGHT (tree_view) < 0)
--    {
--      /* someone unset us as a drag dest, note that if
--       * we return FALSE drag_leave isn't called
--       */
--
--      pspp_sheet_view_set_drag_dest_row (tree_view,
--                                       NULL,
--                                       PSPP_SHEET_VIEW_DROP_BEFORE);
--
--      remove_scroll_timeout (PSPP_SHEET_VIEW (widget));
--
--      return FALSE; /* no longer a drop site */
--    }
--
--  *target = gtk_drag_dest_find_target (widget, context,
--                                       gtk_drag_dest_get_target_list (widget));
--  if (*target == GDK_NONE)
--    {
--      return FALSE;
--    }
--
--  if (!pspp_sheet_view_get_dest_row_at_pos (tree_view,
--                                          x, y,
--                                          &path,
--                                          &pos))
--    {
--      gint n_children;
--      GtkTreeModel *model;
--
--      /* the row got dropped on empty space, let's setup a special case
--       */
--
--      if (path)
--      gtk_tree_path_free (path);
--
--      model = pspp_sheet_view_get_model (tree_view);
--
--      n_children = gtk_tree_model_iter_n_children (model, NULL);
--      if (n_children)
--        {
--          pos = PSPP_SHEET_VIEW_DROP_AFTER;
--          path = gtk_tree_path_new_from_indices (n_children - 1, -1);
--        }
--      else
--        {
--          pos = PSPP_SHEET_VIEW_DROP_BEFORE;
--          path = gtk_tree_path_new_from_indices (0, -1);
--        }
--
--      can_drop = TRUE;
--
--      goto out;
--    }
--
--  g_assert (path);
--
--  /* If we left the current row's "open" zone, unset the timeout for
--   * opening the row
--   */
--  pspp_sheet_view_get_drag_dest_row (tree_view,
--                                   &old_dest_path,
--                                   &old_pos);
--
--  if (old_dest_path)
--    gtk_tree_path_free (old_dest_path);
--
--  if (TRUE /* FIXME if the location droppable predicate */)
--    {
--      can_drop = TRUE;
--    }
--
--out:
--  if (can_drop)
--    {
--      GtkWidget *source_widget;
--
--      *suggested_action = gdk_drag_context_get_suggested_action (context);
--      source_widget = gtk_drag_get_source_widget (context);
--
--      if (source_widget == widget)
--        {
--          /* Default to MOVE, unless the user has
--           * pressed ctrl or shift to affect available actions
--           */
--          if ((gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE) != 0)
--            *suggested_action = GDK_ACTION_MOVE;
--        }
--
--      pspp_sheet_view_set_drag_dest_row (PSPP_SHEET_VIEW (widget),
--                                       path, pos);
--    }
--  else
--    {
--      /* can't drop here */
--      pspp_sheet_view_set_drag_dest_row (PSPP_SHEET_VIEW (widget),
--                                       NULL,
--                                       PSPP_SHEET_VIEW_DROP_BEFORE);
--    }
--
--  if (path)
--    gtk_tree_path_free (path);
--
--  return TRUE;
--}
--
--static GtkTreePath*
--get_logical_dest_row (PsppSheetView *tree_view,
--                      gboolean    *path_down_mode,
--                      gboolean    *drop_append_mode)
--{
--  /* adjust path to point to the row the drop goes in front of */
--  GtkTreePath *path = NULL;
--  PsppSheetViewDropPosition pos;
--
--  g_return_val_if_fail (path_down_mode != NULL, NULL);
--  g_return_val_if_fail (drop_append_mode != NULL, NULL);
--
--  *path_down_mode = FALSE;
--  *drop_append_mode = 0;
--
--  pspp_sheet_view_get_drag_dest_row (tree_view, &path, &pos);
--
--  if (path == NULL)
--    return NULL;
--
--  if (pos == PSPP_SHEET_VIEW_DROP_BEFORE)
--    ; /* do nothing */
--  else if (pos == PSPP_SHEET_VIEW_DROP_INTO_OR_BEFORE ||
--           pos == PSPP_SHEET_VIEW_DROP_INTO_OR_AFTER)
--    *path_down_mode = TRUE;
--  else
--    {
--      GtkTreeIter iter;
--      GtkTreeModel *model = pspp_sheet_view_get_model (tree_view);
--
--      g_assert (pos == PSPP_SHEET_VIEW_DROP_AFTER);
--
--      if (!gtk_tree_model_get_iter (model, &iter, path) ||
--          !gtk_tree_model_iter_next (model, &iter))
--        *drop_append_mode = 1;
--      else
--        {
--          *drop_append_mode = 0;
--          gtk_tree_path_next (path);
--        }
--    }
--
--  return path;
--}
--
--static gboolean
--pspp_sheet_view_maybe_begin_dragging_row (PsppSheetView      *tree_view,
--                                        GdkEventMotion   *event)
--{
--  GtkWidget *widget = GTK_WIDGET (tree_view);
--  GdkDragContext *context;
--  TreeViewDragInfo *di;
--  GtkTreePath *path = NULL;
--  gint button;
--  gint cell_x, cell_y;
--  GtkTreeModel *model;
--  gboolean retval = FALSE;
--
--  di = get_info (tree_view);
--
--  if (di == NULL || !di->source_set)
--    goto out;
--
--  if (tree_view->priv->pressed_button < 0)
--    goto out;
--
--  if (!gtk_drag_check_threshold (widget,
--                                 tree_view->priv->press_start_x,
--                                 tree_view->priv->press_start_y,
--                                 event->x, event->y))
--    goto out;
--
--  model = pspp_sheet_view_get_model (tree_view);
--
--  if (model == NULL)
--    goto out;
--
--  button = tree_view->priv->pressed_button;
--  tree_view->priv->pressed_button = -1;
--
--  pspp_sheet_view_get_path_at_pos (tree_view,
--                                 tree_view->priv->press_start_x,
--                                 tree_view->priv->press_start_y,
--                                 &path,
--                                 NULL,
--                                 &cell_x,
--                                 &cell_y);
--
--  if (path == NULL)
--    goto out;
--
--  if (!GTK_IS_TREE_DRAG_SOURCE (model) ||
--      !gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model),
--                                         path))
--    goto out;
--
--  if (!(GDK_BUTTON1_MASK << (button - 1) & di->start_button_mask))
--    goto out;
--
--  /* Now we can begin the drag */
--
--  retval = TRUE;
--
--  context = gtk_drag_begin (widget,
--                            gtk_drag_source_get_target_list (widget),
--                            di->source_actions,
--                            button,
--                            (GdkEvent*)event);
--
--  set_source_row (context, model, path);
--
-- out:
--  if (path)
--    gtk_tree_path_free (path);
--
--  return retval;
--}
--
--
--
--static void
--pspp_sheet_view_drag_begin (GtkWidget      *widget,
--                          GdkDragContext *context)
--{
--}
--
--
--static void
--pspp_sheet_view_drag_end (GtkWidget      *widget,
--                        GdkDragContext *context)
--{
--  /* do nothing */
--}
--
--/* Default signal implementations for the drag signals */
--static void
--pspp_sheet_view_drag_data_get (GtkWidget        *widget,
--                             GdkDragContext   *context,
--                             GtkSelectionData *selection_data,
--                             guint             info,
--                             guint             time)
--{
--  PsppSheetView *tree_view;
--  GtkTreeModel *model;
--  TreeViewDragInfo *di;
--  GtkTreePath *source_row;
--
--  tree_view = PSPP_SHEET_VIEW (widget);
--
--  model = pspp_sheet_view_get_model (tree_view);
--
--  if (model == NULL)
--    return;
--
--  di = get_info (PSPP_SHEET_VIEW (widget));
--
--  if (di == NULL)
--    return;
--
--  source_row = get_source_row (context);
--
--  if (source_row == NULL)
--    return;
--
--  /* We can implement the GTK_TREE_MODEL_ROW target generically for
--   * any model; for DragSource models there are some other targets
--   * we also support.
--   */
--
--  if (GTK_IS_TREE_DRAG_SOURCE (model) &&
--      gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model),
--                                          source_row,
--                                          selection_data))
--    goto done;
--
--  /* If drag_data_get does nothing, try providing row data. */
--  if (gtk_selection_data_get_target (selection_data) == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
--    {
--      gtk_tree_set_row_drag_data (selection_data,
--                                model,
--                                source_row);
--    }
--
-- done:
--  gtk_tree_path_free (source_row);
--}
--
--
--static void
--pspp_sheet_view_drag_data_delete (GtkWidget      *widget,
--                                GdkDragContext *context)
--{
--  TreeViewDragInfo *di;
--  GtkTreeModel *model;
--  PsppSheetView *tree_view;
--  GtkTreePath *source_row;
--
--  tree_view = PSPP_SHEET_VIEW (widget);
--  model = pspp_sheet_view_get_model (tree_view);
--
--  if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_SOURCE, "drag_data_delete"))
--    return;
--
--  di = get_info (tree_view);
--
--  if (di == NULL)
--    return;
--
--  source_row = get_source_row (context);
--
--  if (source_row == NULL)
--    return;
--
--  gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model),
--                                         source_row);
--
--  gtk_tree_path_free (source_row);
--
--  set_source_row (context, NULL, NULL);
--}
--
--static void
--pspp_sheet_view_drag_leave (GtkWidget      *widget,
--                          GdkDragContext *context,
--                          guint             time)
--{
--  /* unset any highlight row */
--  pspp_sheet_view_set_drag_dest_row (PSPP_SHEET_VIEW (widget),
--                                   NULL,
--                                   PSPP_SHEET_VIEW_DROP_BEFORE);
--
--  remove_scroll_timeout (PSPP_SHEET_VIEW (widget));
--}
--
--
--static gboolean
--pspp_sheet_view_drag_motion (GtkWidget        *widget,
--                           GdkDragContext   *context,
--                         /* coordinates relative to the widget */
--                           gint              x,
--                           gint              y,
--                           guint             time)
--{
--  gboolean empty;
--  GtkTreePath *path = NULL;
--  PsppSheetViewDropPosition pos;
--  PsppSheetView *tree_view;
--  GdkDragAction suggested_action = 0;
--  GdkAtom target;
--
--  tree_view = PSPP_SHEET_VIEW (widget);
--
--  if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
--    return FALSE;
--
--  pspp_sheet_view_get_drag_dest_row (tree_view, &path, &pos);
--
--  /* we only know this *after* set_desination_row */
--  empty = tree_view->priv->empty_view_drop;
--
--  if (path == NULL && !empty)
--    {
--      /* Can't drop here. */
--      gdk_drag_status (context, 0, time);
--    }
--  else
--    {
--      if (tree_view->priv->open_dest_timeout == 0 &&
--          (pos == PSPP_SHEET_VIEW_DROP_INTO_OR_AFTER ||
--           pos == PSPP_SHEET_VIEW_DROP_INTO_OR_BEFORE))
--        {
--          /* Nothing. */
--        }
--      else
--        {
--        add_scroll_timeout (tree_view);
--      }
--
--      if (target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
--        {
--          /* Request data so we can use the source row when
--           * determining whether to accept the drop
--           */
--          set_status_pending (context, suggested_action);
--          gtk_drag_get_data (widget, context, target, time);
--        }
--      else
--        {
--          set_status_pending (context, 0);
--          gdk_drag_status (context, suggested_action, time);
--        }
--    }
--
--  if (path)
--    gtk_tree_path_free (path);
--
--  return TRUE;
--}
--
--
--static gboolean
--pspp_sheet_view_drag_drop (GtkWidget        *widget,
--                         GdkDragContext   *context,
--                       /* coordinates relative to the widget */
--                         gint              x,
--                         gint              y,
--                         guint             time)
--{
--  PsppSheetView *tree_view;
--  GtkTreePath *path;
--  GdkDragAction suggested_action = 0;
--  GdkAtom target = GDK_NONE;
--  TreeViewDragInfo *di;
--  GtkTreeModel *model;
--  gboolean path_down_mode;
--  gboolean drop_append_mode;
--
--  tree_view = PSPP_SHEET_VIEW (widget);
--
--  model = pspp_sheet_view_get_model (tree_view);
--
--  remove_scroll_timeout (PSPP_SHEET_VIEW (widget));
--
--  di = get_info (tree_view);
--
--  if (di == NULL)
--    return FALSE;
--
--  if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_drop"))
--    return FALSE;
--
--  if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
--    return FALSE;
--
--  path = get_logical_dest_row (tree_view, &path_down_mode, &drop_append_mode);
--
--  if (target != GDK_NONE && path != NULL)
--    {
--      /* in case a motion had requested drag data, change things so we
--       * treat drag data receives as a drop.
--       */
--      set_status_pending (context, 0);
--      set_dest_row (context, model, path,
--                    path_down_mode, tree_view->priv->empty_view_drop,
--                    drop_append_mode);
--    }
--
--  if (path)
--    gtk_tree_path_free (path);
--
--  /* Unset this thing */
--  pspp_sheet_view_set_drag_dest_row (PSPP_SHEET_VIEW (widget),
--                                   NULL,
--                                   PSPP_SHEET_VIEW_DROP_BEFORE);
--
--  if (target != GDK_NONE)
--    {
--      gtk_drag_get_data (widget, context, target, time);
--      return TRUE;
--    }
--  else
--    return FALSE;
--}
--
--static void
--pspp_sheet_view_drag_data_received (GtkWidget        *widget,
--                                  GdkDragContext   *context,
--                                /* coordinates relative to the widget */
--                                  gint              x,
--                                  gint              y,
--                                  GtkSelectionData *selection_data,
--                                  guint             info,
--                                  guint             time)
--{
--  GtkTreePath *path;
--  TreeViewDragInfo *di;
--  gboolean accepted = FALSE;
--  GtkTreeModel *model;
--  PsppSheetView *tree_view;
--  GtkTreePath *dest_row;
--  GdkDragAction suggested_action;
--  gboolean path_down_mode;
--  gboolean drop_append_mode;
--
--  tree_view = PSPP_SHEET_VIEW (widget);
--
--  model = pspp_sheet_view_get_model (tree_view);
--
--  if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_data_received"))
--    return;
--
--  di = get_info (tree_view);
--
--  if (di == NULL)
--    return;
--
--  suggested_action = get_status_pending (context);
--
--  if (suggested_action)
--    {
--      /* We are getting this data due to a request in drag_motion,
--       * rather than due to a request in drag_drop, so we are just
--       * supposed to call drag_status, not actually paste in the
--       * data.
--       */
--      path = get_logical_dest_row (tree_view, &path_down_mode,
--                                   &drop_append_mode);
--
--      if (path == NULL)
--        suggested_action = 0;
--      else if (path_down_mode)
--        gtk_tree_path_down (path);
--
--      if (suggested_action)
--        {
--        if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
--                                                   path,
--                                                   selection_data))
--            {
--              if (path_down_mode)
--                {
--                  path_down_mode = FALSE;
--                  gtk_tree_path_up (path);
--
--                  if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
--                                                             path,
--                                                             selection_data))
--                    suggested_action = 0;
--                }
--              else
--              suggested_action = 0;
--            }
--        }
--
--      gdk_drag_status (context, suggested_action, time);
--
--      if (path)
--        gtk_tree_path_free (path);
--
--      /* If you can't drop, remove user drop indicator until the next motion */
--      if (suggested_action == 0)
--        pspp_sheet_view_set_drag_dest_row (PSPP_SHEET_VIEW (widget),
--                                         NULL,
--                                         PSPP_SHEET_VIEW_DROP_BEFORE);
--
--      return;
--    }
--
--  dest_row = get_dest_row (context, &path_down_mode);
--
--  if (dest_row == NULL)
--    return;
--
--  if (gtk_selection_data_get_length (selection_data) >= 0)
--    {
--      if (path_down_mode)
--        {
--          gtk_tree_path_down (dest_row);
--          if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
--                                                     dest_row, selection_data))
--            gtk_tree_path_up (dest_row);
--        }
--    }
--
--  if (gtk_selection_data_get_length (selection_data) >= 0)
--    {
--      if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
--                                                 dest_row,
--                                                 selection_data))
--        accepted = TRUE;
--    }
--
--  gtk_drag_finish (context,
--                   accepted,
--                   (gdk_drag_context_get_actions (context) == GDK_ACTION_MOVE),
--                   time);
--
--  if (gtk_tree_path_get_depth (dest_row) == 1
--      && gtk_tree_path_get_indices (dest_row)[0] == 0)
--    {
--      /* special special case drag to "0", scroll to first item */
--      if (!tree_view->priv->scroll_to_path)
--        pspp_sheet_view_scroll_to_cell (tree_view, dest_row, NULL, FALSE, 0.0, 0.0);
--    }
--
--  gtk_tree_path_free (dest_row);
--
--  /* drop dest_row */
--  set_dest_row (context, NULL, NULL, FALSE, FALSE, FALSE);
--}
--
--
--
--/* GtkContainer Methods
-- */
--
--
--static void
--pspp_sheet_view_remove (GtkContainer *container,
--                    GtkWidget    *widget)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (container);
--  PsppSheetViewChild *child = NULL;
--  GList *tmp_list;
--
--  tmp_list = tree_view->priv->children;
--  while (tmp_list)
--    {
--      child = tmp_list->data;
--      if (child->widget == widget)
--      {
--        gtk_widget_unparent (widget);
--
--        tree_view->priv->children = g_list_remove_link (tree_view->priv->children, tmp_list);
--        g_list_free_1 (tmp_list);
--        g_slice_free (PsppSheetViewChild, child);
--        return;
--      }
--
--      tmp_list = tmp_list->next;
--    }
--
--  tmp_list = tree_view->priv->columns;
--
--  while (tmp_list)
--    {
--      PsppSheetViewColumn *column;
--      column = tmp_list->data;
--      if (column->button == widget)
--      {
--        gtk_widget_unparent (widget);
--        return;
--      }
--      tmp_list = tmp_list->next;
--    }
--}
--
--static void
--pspp_sheet_view_forall (GtkContainer *container,
--                    gboolean      include_internals,
--                    GtkCallback   callback,
--                    gpointer      callback_data)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (container);
--  PsppSheetViewChild *child = NULL;
--  PsppSheetViewColumn *column;
--  GList *tmp_list;
--
--  tmp_list = tree_view->priv->children;
--  while (tmp_list)
--    {
--      child = tmp_list->data;
--      tmp_list = tmp_list->next;
--
--      (* callback) (child->widget, callback_data);
--    }
--  if (include_internals == FALSE)
--    return;
--
--  for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
--    {
--      column = tmp_list->data;
--
--      if (column->button)
--      (* callback) (column->button, callback_data);
--    }
--}
--
--/* Returns TRUE if the treeview contains no "special" (editable or activatable)
-- * cells. If so we draw one big row-spanning focus rectangle.
-- */
--static gboolean
--pspp_sheet_view_has_special_cell (PsppSheetView *tree_view)
--{
--  GList *list;
--
--  if (tree_view->priv->special_cells != PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT)
--    return tree_view->priv->special_cells = PSPP_SHEET_VIEW_SPECIAL_CELLS_YES;
--
--  for (list = tree_view->priv->columns; list; list = list->next)
--    {
--      if (!((PsppSheetViewColumn *)list->data)->visible)
--      continue;
--      if (_pspp_sheet_view_column_count_special_cells (list->data))
--      return TRUE;
--    }
--
--  return FALSE;
--}
--
--static void
--pspp_sheet_view_focus_column (PsppSheetView *tree_view,
--                              PsppSheetViewColumn *focus_column,
--                              gboolean clamp_column_visible)
--{
--  g_return_if_fail (focus_column != NULL);
--
--  tree_view->priv->focus_column = focus_column;
--
--  if (gtk_container_get_focus_child (GTK_CONTAINER (tree_view)) != focus_column->button)
--    gtk_widget_grab_focus (focus_column->button);
--
--  if (clamp_column_visible)
--    pspp_sheet_view_clamp_column_visible (tree_view, focus_column, FALSE);
--}
--
--/* Returns TRUE if the focus is within the headers, after the focus operation is
-- * done
-- */
--static gboolean
--pspp_sheet_view_header_focus (PsppSheetView      *tree_view,
--                          GtkDirectionType  dir,
--                          gboolean          clamp_column_visible)
--{
--  GtkWidget *focus_child;
--  PsppSheetViewColumn *focus_column;
--  GList *last_column, *first_column;
--  GList *tmp_list;
--  gboolean rtl;
--
--  if (! PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE))
--    return FALSE;
--
--  focus_child = gtk_container_get_focus_child (GTK_CONTAINER (tree_view));
--
--  first_column = tree_view->priv->columns;
--  while (first_column)
--    {
--      PsppSheetViewColumn *c = PSPP_SHEET_VIEW_COLUMN (first_column->data);
--
--      if (pspp_sheet_view_column_can_focus (c) && c->visible)
--      break;
--      first_column = first_column->next;
--    }
--
--  /* No headers are visible, or are focusable.  We can't focus in or out.
--   */
--  if (first_column == NULL)
--    return FALSE;
--
--  last_column = g_list_last (tree_view->priv->columns);
--  while (last_column)
--    {
--      PsppSheetViewColumn *c = PSPP_SHEET_VIEW_COLUMN (last_column->data);
--
--      if (pspp_sheet_view_column_can_focus (c) && c->visible)
--      break;
--      last_column = last_column->prev;
--    }
--
--
--  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--
--  switch (dir)
--    {
--    case GTK_DIR_TAB_BACKWARD:
--    case GTK_DIR_TAB_FORWARD:
--    case GTK_DIR_UP:
--    case GTK_DIR_DOWN:
--      if (focus_child == NULL)
--      {
--        if (tree_view->priv->focus_column != NULL &&
--              pspp_sheet_view_column_can_focus (tree_view->priv->focus_column))
--          focus_column = tree_view->priv->focus_column;
--        else
--            focus_column = first_column->data;
--          pspp_sheet_view_focus_column (tree_view, focus_column,
--                                        clamp_column_visible);
--        return TRUE;
--      }
--      return FALSE;
--
--    case GTK_DIR_LEFT:
--    case GTK_DIR_RIGHT:
--      if (focus_child == NULL)
--      {
--        if (tree_view->priv->focus_column != NULL)
--          focus_column = tree_view->priv->focus_column;
--        else if (dir == GTK_DIR_LEFT)
--          focus_column = last_column->data;
--        else
--          focus_column = first_column->data;
--          pspp_sheet_view_focus_column (tree_view, focus_column,
--                                        clamp_column_visible);
--        return TRUE;
--      }
--
--      if (gtk_widget_child_focus (focus_child, dir))
--      {
--        /* The focus moves inside the button. */
--        /* This is probably a great example of bad UI */
--          if (clamp_column_visible)
--            pspp_sheet_view_clamp_column_visible (tree_view,
--                                                  tree_view->priv->focus_column,
--                                                  FALSE);
--        return TRUE;
--      }
--
--      /* We need to move the focus among the row of buttons. */
--      for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
--      if (PSPP_SHEET_VIEW_COLUMN (tmp_list->data)->button == focus_child)
--        break;
--
--      if ((tmp_list == first_column && dir == (rtl ? GTK_DIR_RIGHT : GTK_DIR_LEFT))
--        || (tmp_list == last_column && dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT)))
--        {
--        gtk_widget_error_bell (GTK_WIDGET (tree_view));
--        return TRUE;
--      }
--
--      while (tmp_list)
--      {
--        PsppSheetViewColumn *column;
--
--        if (dir == (rtl ? GTK_DIR_LEFT : GTK_DIR_RIGHT))
--          tmp_list = tmp_list->next;
--        else
--          tmp_list = tmp_list->prev;
--
--        if (tmp_list == NULL)
--          {
--            g_warning ("Internal button not found");
--            break;
--          }
--        column = tmp_list->data;
--          if (column->visible &&
--            pspp_sheet_view_column_can_focus (column))
--            {
--              if (column->button)
--                {
--                  pspp_sheet_view_focus_column (tree_view, column,
--                                                clamp_column_visible);
--                  return TRUE;
--                }
--          }
--      }
--      return FALSE;
--
--    default:
--      g_assert_not_reached ();
--      break;
--    }
--
--  return FALSE;
--}
--
--/* This function returns in 'path' the first focusable path, if the given path
-- * is already focusable, it's the returned one.
-- *
-- */
--static gboolean
--search_first_focusable_path (PsppSheetView  *tree_view,
--                           GtkTreePath **path,
--                           gboolean      search_forward,
--                           int *new_node)
--{
--  /* XXX this function is trivial given that the sheetview doesn't support
--     separator rows */
--  int node = -1;
--
--  if (!path || !*path)
--    return FALSE;
--
--  _pspp_sheet_view_find_node (tree_view, *path, &node);
--
--  if (node < 0)
--    return FALSE;
--
--  if (new_node)
--    *new_node = node;
--
--  return (*path != NULL);
--}
--
--static gint
--pspp_sheet_view_focus (GtkWidget        *widget,
--                   GtkDirectionType  direction)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--  GtkContainer *container = GTK_CONTAINER (widget);
--  GtkWidget *focus_child;
--
--  if (!gtk_widget_is_sensitive (widget) || !gtk_widget_get_can_focus (widget))
--    return FALSE;
--
--  focus_child = gtk_container_get_focus_child (container);
--
--  pspp_sheet_view_stop_editing (PSPP_SHEET_VIEW (widget), FALSE);
--  /* Case 1.  Headers currently have focus. */
--  if (focus_child)
--    {
--      switch (direction)
--      {
--      case GTK_DIR_LEFT:
--      case GTK_DIR_RIGHT:
--        pspp_sheet_view_header_focus (tree_view, direction, TRUE);
--        return TRUE;
--      case GTK_DIR_TAB_BACKWARD:
--      case GTK_DIR_UP:
--        return FALSE;
--      case GTK_DIR_TAB_FORWARD:
--      case GTK_DIR_DOWN:
--        gtk_widget_grab_focus (widget);
--        return TRUE;
--      default:
--        g_assert_not_reached ();
--        return FALSE;
--      }
--    }
--
--  /* Case 2. We don't have focus at all. */
--  if (!gtk_widget_has_focus (widget))
--    {
--      if (!pspp_sheet_view_header_focus (tree_view, direction, FALSE))
--      gtk_widget_grab_focus (widget);
--      return TRUE;
--    }
--
--  /* Case 3. We have focus already. */
--  if (direction == GTK_DIR_TAB_BACKWARD)
--    return (pspp_sheet_view_header_focus (tree_view, direction, FALSE));
--  else if (direction == GTK_DIR_TAB_FORWARD)
--    return FALSE;
--
--  /* Other directions caught by the keybindings */
--  gtk_widget_grab_focus (widget);
--  return TRUE;
--}
--
--static void
--pspp_sheet_view_grab_focus (GtkWidget *widget)
--{
--  GTK_WIDGET_CLASS (pspp_sheet_view_parent_class)->grab_focus (widget);
--
--  pspp_sheet_view_focus_to_cursor (PSPP_SHEET_VIEW (widget));
--}
--
--static void
--pspp_sheet_view_style_updated (GtkWidget *widget)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--  GList *list;
--  PsppSheetViewColumn *column;
--  GtkStyleContext *context;
--
--  GTK_WIDGET_CLASS (pspp_sheet_view_parent_class)->style_updated (widget);
--
--  if (gtk_widget_get_realized (widget))
--    {
--      context = gtk_widget_get_style_context (GTK_WIDGET (tree_view));
--      gtk_style_context_set_background (context, gtk_widget_get_window (GTK_WIDGET (tree_view)));
--      gtk_style_context_set_background (context, tree_view->priv->header_window);
--      pspp_sheet_view_set_grid_lines (tree_view, tree_view->priv->grid_lines);
--    }
--
--  gtk_widget_style_get (widget,
--                      "expander-size", &tree_view->priv->expander_size,
--                      NULL);
--  tree_view->priv->expander_size += EXPANDER_EXTRA_PADDING;
--
--  for (list = tree_view->priv->columns; list; list = list->next)
--    {
--      column = list->data;
--      _pspp_sheet_view_column_cell_set_dirty (column);
--    }
--
--  tree_view->priv->fixed_height = -1;
--
--  /* Invalidate cached button style. */
--  if (tree_view->priv->button_style)
--    {
--      g_object_unref (tree_view->priv->button_style);
--      tree_view->priv->button_style = NULL;
--    }
--
--  gtk_widget_queue_resize (widget);
--}
--
--
--static void
--pspp_sheet_view_set_focus_child (GtkContainer *container,
--                             GtkWidget    *child)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (container);
--  GList *list;
--
--  for (list = tree_view->priv->columns; list; list = list->next)
--    {
--      if (PSPP_SHEET_VIEW_COLUMN (list->data)->button == child)
--      {
--        tree_view->priv->focus_column = PSPP_SHEET_VIEW_COLUMN (list->data);
--        break;
--      }
--    }
--
--  GTK_CONTAINER_CLASS (pspp_sheet_view_parent_class)->set_focus_child (container, child);
--}
--
--static void
--pspp_sheet_view_set_adjustments (PsppSheetView   *tree_view,
--                             GtkAdjustment *hadj,
--                             GtkAdjustment *vadj)
--{
--  gboolean need_adjust = FALSE;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (hadj)
--    g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
--  else
--    hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
--  if (vadj)
--    g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
--  else
--    vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
--
--  if (tree_view->priv->hadjustment && (tree_view->priv->hadjustment != hadj))
--    {
--      g_signal_handlers_disconnect_by_func (tree_view->priv->hadjustment,
--                                          pspp_sheet_view_adjustment_changed,
--                                          tree_view);
--      g_object_unref (tree_view->priv->hadjustment);
--    }
--
--  if (tree_view->priv->vadjustment && (tree_view->priv->vadjustment != vadj))
--    {
--      g_signal_handlers_disconnect_by_func (tree_view->priv->vadjustment,
--                                          pspp_sheet_view_adjustment_changed,
--                                          tree_view);
--      g_object_unref (tree_view->priv->vadjustment);
--    }
--
--  if (tree_view->priv->hadjustment != hadj)
--    {
--      tree_view->priv->hadjustment = hadj;
--      g_object_ref_sink (tree_view->priv->hadjustment);
--
--      g_signal_connect (tree_view->priv->hadjustment, "value-changed",
--                      G_CALLBACK (pspp_sheet_view_adjustment_changed),
--                      tree_view);
--      need_adjust = TRUE;
--    }
--
--  if (tree_view->priv->vadjustment != vadj)
--    {
--      tree_view->priv->vadjustment = vadj;
--      g_object_ref_sink (tree_view->priv->vadjustment);
--
--      g_signal_connect (tree_view->priv->vadjustment, "value-changed",
--                      G_CALLBACK (pspp_sheet_view_adjustment_changed),
--                      tree_view);
--      need_adjust = TRUE;
--    }
--
--  if (need_adjust)
--    pspp_sheet_view_adjustment_changed (NULL, tree_view);
--}
--
--
--static gboolean
--pspp_sheet_view_real_move_cursor (PsppSheetView       *tree_view,
--                              GtkMovementStep    step,
--                              gint               count)
--{
--  PsppSheetSelectMode mode;
--  GdkModifierType state;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
--  g_return_val_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
--                      step == GTK_MOVEMENT_VISUAL_POSITIONS ||
--                      step == GTK_MOVEMENT_DISPLAY_LINES ||
--                      step == GTK_MOVEMENT_PAGES ||
--                      step == GTK_MOVEMENT_BUFFER_ENDS ||
--                      step == GTK_MOVEMENT_DISPLAY_LINE_ENDS, FALSE);
--
--  if (tree_view->priv->row_count == 0)
--    return FALSE;
--  if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    return FALSE;
--
--  pspp_sheet_view_stop_editing (tree_view, FALSE);
--  PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS);
--  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--
--  mode = 0;
--  if (gtk_get_current_event_state (&state))
--    {
--      if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
--        mode |= PSPP_SHEET_SELECT_MODE_TOGGLE;
--      if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
--        mode |= PSPP_SHEET_SELECT_MODE_EXTEND;
--    }
--  /* else we assume not pressed */
--
--  switch (step)
--    {
--    case GTK_MOVEMENT_LOGICAL_POSITIONS:
--      pspp_sheet_view_move_cursor_tab (tree_view, count);
--      break;
--    case GTK_MOVEMENT_VISUAL_POSITIONS:
--      pspp_sheet_view_move_cursor_left_right (tree_view, count, mode);
--      break;
--    case GTK_MOVEMENT_DISPLAY_LINES:
--      pspp_sheet_view_move_cursor_up_down (tree_view, count, mode);
--      break;
--    case GTK_MOVEMENT_PAGES:
--      pspp_sheet_view_move_cursor_page_up_down (tree_view, count, mode);
--      break;
--    case GTK_MOVEMENT_BUFFER_ENDS:
--      pspp_sheet_view_move_cursor_start_end (tree_view, count, mode);
--      break;
--    case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
--      pspp_sheet_view_move_cursor_line_start_end (tree_view, count, mode);
--      break;
--    default:
--      g_assert_not_reached ();
--    }
--
--  return TRUE;
--}
--
--static void
--pspp_sheet_view_put (PsppSheetView *tree_view,
--                   GtkWidget   *child_widget,
--                   GtkTreePath *path,
--                   PsppSheetViewColumn *column)
--{
--  PsppSheetViewChild *child;
--  
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (GTK_IS_WIDGET (child_widget));
--
--  child = g_slice_new (PsppSheetViewChild);
--
--  child->widget = child_widget;
--  _pspp_sheet_view_find_node (tree_view, path, &child->node);
--  if (child->node < 0)
--    {
--      g_assert_not_reached ();
--    }
--  child->column = column;
--
--  tree_view->priv->children = g_list_append (tree_view->priv->children, child);
--
--  if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
--  
--  gtk_widget_set_parent (child_widget, GTK_WIDGET (tree_view));
--}
--
--/* TreeModel Callbacks
-- */
--
--static void
--pspp_sheet_view_row_changed (GtkTreeModel *model,
--                         GtkTreePath  *path,
--                         GtkTreeIter  *iter,
--                         gpointer      data)
--{
--  PsppSheetView *tree_view = (PsppSheetView *)data;
--  int node;
--  gboolean free_path = FALSE;
--  GtkTreePath *cursor_path;
--
--  g_return_if_fail (path != NULL || iter != NULL);
--
--  if (tree_view->priv->cursor != NULL)
--    cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--  else
--    cursor_path = NULL;
--
--  if (tree_view->priv->edited_column &&
--      (cursor_path == NULL || gtk_tree_path_compare (cursor_path, path) == 0))
--    pspp_sheet_view_stop_editing (tree_view, TRUE);
--
--  if (cursor_path != NULL)
--    gtk_tree_path_free (cursor_path);
--
--  if (path == NULL)
--    {
--      path = gtk_tree_model_get_path (model, iter);
--      free_path = TRUE;
--    }
--  else if (iter == NULL)
--    gtk_tree_model_get_iter (model, iter, path);
--
--  _pspp_sheet_view_find_node (tree_view,
--                              path,
--                              &node);
--
--  if (node >= 0)
--    {
--      if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--        pspp_sheet_view_node_queue_redraw (tree_view, node);
--    }
--  
--  if (free_path)
--    gtk_tree_path_free (path);
--}
--
--static void
--pspp_sheet_view_row_inserted (GtkTreeModel *model,
--                          GtkTreePath  *path,
--                          GtkTreeIter  *iter,
--                          gpointer      data)
--{
--  PsppSheetView *tree_view = (PsppSheetView *) data;
--  gint *indices;
--  int tmpnode = -1;
--  gint height = tree_view->priv->fixed_height;
--  gboolean free_path = FALSE;
--  gboolean node_visible = TRUE;
--
--  g_return_if_fail (path != NULL || iter != NULL);
--
--  if (path == NULL)
--    {
--      path = gtk_tree_model_get_path (model, iter);
--      free_path = TRUE;
--    }
--  else if (iter == NULL)
--    gtk_tree_model_get_iter (model, iter, path);
--
--  tree_view->priv->row_count = gtk_tree_model_iter_n_children (model, NULL);
--
--  /* Update all row-references */
--  gtk_tree_row_reference_inserted (G_OBJECT (data), path);
--  indices = gtk_tree_path_get_indices (path);
--  tmpnode = indices[0];
--
--  range_tower_insert0 (tree_view->priv->selected, tmpnode, 1);
--
--  if (height > 0)
--    {
--      if (node_visible && node_is_visible (tree_view, tmpnode))
--      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
--      else
--      gtk_widget_queue_resize_no_redraw (GTK_WIDGET (tree_view));
--    }
--  else
--    install_presize_handler (tree_view);
--  if (free_path)
--    gtk_tree_path_free (path);
--}
--
--static void
--pspp_sheet_view_row_deleted (GtkTreeModel *model,
--                         GtkTreePath  *path,
--                         gpointer      data)
--{
--  PsppSheetView *tree_view = (PsppSheetView *)data;
--  int node;
--
--  g_return_if_fail (path != NULL);
--
--  gtk_tree_row_reference_deleted (G_OBJECT (data), path);
--
--  _pspp_sheet_view_find_node (tree_view, path, &node);
--
--  if (node < 0)
--    return;
--
--  range_tower_delete (tree_view->priv->selected, node, 1);
--
--  /* Ensure we don't have a dangling pointer to a dead node */
--  ensure_unprelighted (tree_view);
--
--  /* Cancel editting if we've started */
--  pspp_sheet_view_stop_editing (tree_view, TRUE);
--
--  if (tree_view->priv->destroy_count_func)
--    {
--      gint child_count = 0;
--      tree_view->priv->destroy_count_func (tree_view, path, child_count, tree_view->priv->destroy_count_data);
--    }
--
--  tree_view->priv->row_count = gtk_tree_model_iter_n_children (model, NULL);
--
--  if (! gtk_tree_row_reference_valid (tree_view->priv->top_row))
--    {
--      gtk_tree_row_reference_free (tree_view->priv->top_row);
--      tree_view->priv->top_row = NULL;
--    }
--
--  install_scroll_sync_handler (tree_view);
--
--  gtk_widget_queue_resize (GTK_WIDGET (tree_view));
--
--#if 0
--  if (helper_data.changed)
--    g_signal_emit_by_name (tree_view->priv->selection, "changed");
--#endif
--}
--
--static void
--pspp_sheet_view_rows_reordered (GtkTreeModel *model,
--                            GtkTreePath  *parent,
--                            GtkTreeIter  *iter,
--                            gint         *new_order,
--                            gpointer      data)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (data);
--  gint len;
--
--  /* XXX need to adjust selection */
--  len = gtk_tree_model_iter_n_children (model, iter);
--
--  if (len < 2)
--    return;
--
--  gtk_tree_row_reference_reordered (G_OBJECT (data),
--                                  parent,
--                                  iter,
--                                  new_order);
--
--  if (gtk_tree_path_get_depth (parent) != 0)
--    return;
--
--  if (tree_view->priv->edited_column)
--    pspp_sheet_view_stop_editing (tree_view, TRUE);
--
--  /* we need to be unprelighted */
--  ensure_unprelighted (tree_view);
--
--  gtk_widget_queue_draw (GTK_WIDGET (tree_view));
--
--  pspp_sheet_view_dy_to_top_row (tree_view);
--}
--
--
--/* Internal tree functions
-- */
--
--
--static void
--pspp_sheet_view_get_background_xrange (PsppSheetView       *tree_view,
--                                     PsppSheetViewColumn *column,
--                                     gint              *x1,
--                                     gint              *x2)
--{
--  PsppSheetViewColumn *tmp_column = NULL;
--  gint total_width;
--  GList *list;
--  gboolean rtl;
--
--  if (x1)
--    *x1 = 0;
--
--  if (x2)
--    *x2 = 0;
--
--  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--
--  total_width = 0;
--  for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
--       list;
--       list = (rtl ? list->prev : list->next))
--    {
--      tmp_column = list->data;
--
--      if (tmp_column == column)
--        break;
--
--      if (tmp_column->visible)
--        total_width += tmp_column->width;
--    }
--
--  if (tmp_column != column)
--    {
--      g_warning (G_STRLOC": passed-in column isn't in the tree");
--      return;
--    }
--
--  if (x1)
--    *x1 = total_width;
--
--  if (x2)
--    {
--      if (column->visible)
--        *x2 = total_width + column->width;
--      else
--        *x2 = total_width; /* width of 0 */
--    }
--}
--
--/* Make sure the node is visible vertically */
--static void
--pspp_sheet_view_clamp_node_visible (PsppSheetView *tree_view,
--                                    int node)
--{
--  gint node_dy, height;
--  GtkTreePath *path = NULL;
--
--  if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    return;
--
--  /* just return if the node is visible, avoiding a costly expose */
--  node_dy = pspp_sheet_view_node_find_offset (tree_view, node);
--  height = ROW_HEIGHT (tree_view);
--  if (node_dy >= gtk_adjustment_get_value (tree_view->priv->vadjustment)
--      && node_dy + height <= (gtk_adjustment_get_value (tree_view->priv->vadjustment)
--                              + gtk_adjustment_get_page_size (tree_view->priv->vadjustment)))
--    return;
--
--  path = _pspp_sheet_view_find_path (tree_view, node);
--  if (path)
--    {
--      /* We process updates because we want to clear old selected items when we scroll.
--       * if this is removed, we get a "selection streak" at the bottom. */
--      gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
--      pspp_sheet_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0.0, 0.0);
--      gtk_tree_path_free (path);
--    }
--}
--
--static void
--pspp_sheet_view_clamp_column_visible (PsppSheetView       *tree_view,
--                                  PsppSheetViewColumn *column,
--                                  gboolean           focus_to_cell)
--{
--  gint x, width;
--
--  if (column == NULL)
--    return;
--
--  x = column->allocation.x;
--  width = column->allocation.width;
--
--  if (width > gtk_adjustment_get_page_size (tree_view->priv->hadjustment))
--    {
--      /* The column is larger than the horizontal page size.  If the
--       * column has cells which can be focussed individually, then we make
--       * sure the cell which gets focus is fully visible (if even the
--       * focus cell is bigger than the page size, we make sure the
--       * left-hand side of the cell is visible).
--       *
--       * If the column does not have those so-called special cells, we
--       * make sure the left-hand side of the column is visible.
--       */
--
--      if (focus_to_cell && pspp_sheet_view_has_special_cell (tree_view))
--        {
--        GtkTreePath *cursor_path;
--        GdkRectangle background_area, cell_area, focus_area;
--
--        cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--
--        pspp_sheet_view_get_cell_area (tree_view,
--                                     cursor_path, column, &cell_area);
--        pspp_sheet_view_get_background_area (tree_view,
--                                           cursor_path, column,
--                                           &background_area);
--
--        gtk_tree_path_free (cursor_path);
--
--        _pspp_sheet_view_column_get_focus_area (column,
--                                              &background_area,
--                                              &cell_area,
--                                              &focus_area);
--
--        x = focus_area.x;
--        width = focus_area.width;
--
--        if (width < gtk_adjustment_get_page_size (tree_view->priv->hadjustment))
--          {
--            if ((gtk_adjustment_get_value (tree_view->priv->hadjustment) + gtk_adjustment_get_page_size (tree_view->priv->hadjustment)) < (x + width))
--              gtk_adjustment_set_value (tree_view->priv->hadjustment,
--                                        x + width - gtk_adjustment_get_page_size (tree_view->priv->hadjustment));
--            else if (gtk_adjustment_get_value (tree_view->priv->hadjustment) > x)
--              gtk_adjustment_set_value (tree_view->priv->hadjustment, x);
--          }
--      }
--
--      gtk_adjustment_set_value (tree_view->priv->hadjustment,
--                              CLAMP (x,
--                                     gtk_adjustment_get_lower (tree_view->priv->hadjustment),
--                                     gtk_adjustment_get_upper (tree_view->priv->hadjustment)
--                                     - gtk_adjustment_get_page_size (tree_view->priv->hadjustment)));
--    }
--  else
--    {
--      if ((gtk_adjustment_get_value (tree_view->priv->hadjustment) + gtk_adjustment_get_page_size (tree_view->priv->hadjustment)) < (x + width))
--        gtk_adjustment_set_value (tree_view->priv->hadjustment,
--                                  x + width - gtk_adjustment_get_page_size (tree_view->priv->hadjustment));
--      else if (gtk_adjustment_get_value (tree_view->priv->hadjustment) > x)
--      gtk_adjustment_set_value (tree_view->priv->hadjustment, x);
--  }
--}
--
--GtkTreePath *
--_pspp_sheet_view_find_path (PsppSheetView *tree_view,
--                            int node)
--{
--  GtkTreePath *path;
--
--  path = gtk_tree_path_new ();
--  if (node >= 0)
--    gtk_tree_path_append_index (path, node);
--  return path;
--}
--
--void
--_pspp_sheet_view_find_node (PsppSheetView  *tree_view,
--                        GtkTreePath  *path,
--                        int *node)
--{
--  gint *indices = gtk_tree_path_get_indices (path);
--  gint depth = gtk_tree_path_get_depth (path);
--
--  *node = -1;
--  if (depth == 0 || indices[0] < 0 || indices[0] >= tree_view->priv->row_count)
--    return;
--  *node = indices[0];
--}
--
--static void
--pspp_sheet_view_add_move_binding (GtkBindingSet  *binding_set,
--                              guint           keyval,
--                              guint           modmask,
--                              gboolean        add_shifted_binding,
--                              GtkMovementStep step,
--                              gint            count)
--{
--  
--  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
--                                "move-cursor", 2,
--                                G_TYPE_ENUM, step,
--                                G_TYPE_INT, count);
--
--  if (add_shifted_binding)
--    gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
--                                "move-cursor", 2,
--                                G_TYPE_ENUM, step,
--                                G_TYPE_INT, count);
--
--  if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
--   return;
--
--  gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
--                                "move-cursor", 2,
--                                G_TYPE_ENUM, step,
--                                G_TYPE_INT, count);
--
--  gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
--                                "move-cursor", 2,
--                                G_TYPE_ENUM, step,
--                                G_TYPE_INT, count);
--}
--
--static void
--pspp_sheet_view_set_column_drag_info (PsppSheetView       *tree_view,
--                                  PsppSheetViewColumn *column)
--{
--  PsppSheetViewColumn *left_column;
--  PsppSheetViewColumn *cur_column = NULL;
--  PsppSheetViewColumnReorder *reorder;
--  gboolean rtl;
--  GList *tmp_list;
--  gint left;
--
--  /* We want to precalculate the motion list such that we know what column slots
--   * are available.
--   */
--  left_column = NULL;
--  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--
--  /* First, identify all possible drop spots */
--  if (rtl)
--    tmp_list = g_list_last (tree_view->priv->columns);
--  else
--    tmp_list = g_list_first (tree_view->priv->columns);
--
--  while (tmp_list)
--    {
--      cur_column = PSPP_SHEET_VIEW_COLUMN (tmp_list->data);
--      tmp_list = rtl?g_list_previous (tmp_list):g_list_next (tmp_list);
--
--      if (cur_column->visible == FALSE)
--      continue;
--
--      /* If it's not the column moving and func tells us to skip over the column, we continue. */
--      if (left_column != column && cur_column != column &&
--        tree_view->priv->column_drop_func &&
--        ! tree_view->priv->column_drop_func (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
--      {
--        left_column = cur_column;
--        continue;
--      }
--      reorder = g_slice_new0 (PsppSheetViewColumnReorder);
--      reorder->left_column = left_column;
--      left_column = reorder->right_column = cur_column;
--
--      tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
--    }
--
--  /* Add the last one */
--  if (tree_view->priv->column_drop_func == NULL ||
--      ((left_column != column) &&
--       tree_view->priv->column_drop_func (tree_view, column, left_column, NULL, tree_view->priv->column_drop_func_data)))
--    {
--      reorder = g_slice_new0 (PsppSheetViewColumnReorder);
--      reorder->left_column = left_column;
--      reorder->right_column = NULL;
--      tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
--    }
--
--  /* We quickly check to see if it even makes sense to reorder columns. */
--  /* If there is nothing that can be moved, then we return */
--
--  if (tree_view->priv->column_drag_info == NULL)
--    return;
--
--  /* We know there are always 2 slots possbile, as you can always return column. */
--  /* If that's all there is, return */
--  if (tree_view->priv->column_drag_info->next == NULL || 
--      (tree_view->priv->column_drag_info->next->next == NULL &&
--       ((PsppSheetViewColumnReorder *)tree_view->priv->column_drag_info->data)->right_column == column &&
--       ((PsppSheetViewColumnReorder *)tree_view->priv->column_drag_info->next->data)->left_column == column))
--    {
--      for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
--      g_slice_free (PsppSheetViewColumnReorder, tmp_list->data);
--      g_list_free (tree_view->priv->column_drag_info);
--      tree_view->priv->column_drag_info = NULL;
--      return;
--    }
--  /* We fill in the ranges for the columns, now that we've isolated them */
--  left = - TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
--
--  for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
--    {
--      reorder = (PsppSheetViewColumnReorder *) tmp_list->data;
--
--      reorder->left_align = left;
--      if (tmp_list->next != NULL)
--      {
--        g_assert (tmp_list->next->data);
--        left = reorder->right_align = (reorder->right_column->allocation.x +
--                                       reorder->right_column->allocation.width +
--                                       ((PsppSheetViewColumnReorder *)tmp_list->next->data)->left_column->allocation.x)/2;
--      }
--      else
--      {
--        gint width = gdk_window_get_width (tree_view->priv->header_window);
--        reorder->right_align = width + TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
--      }
--    }
--}
--
--void
--_pspp_sheet_view_column_start_drag (PsppSheetView       *tree_view,
--                                PsppSheetViewColumn *column)
--{
--  GdkEvent *send_event;
--  GtkAllocation allocation;
--  gint x, y;
--  GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
--  GdkDisplay *display = gdk_screen_get_display (screen);
--
--  g_return_if_fail (tree_view->priv->column_drag_info == NULL);
--  g_return_if_fail (tree_view->priv->cur_reorder == NULL);
--  g_return_if_fail (column->button);
--
--  pspp_sheet_view_set_column_drag_info (tree_view, column);
--
--  if (tree_view->priv->column_drag_info == NULL)
--    return;
--
--  if (tree_view->priv->drag_window == NULL)
--    {
--      GdkWindowAttr attributes;
--      guint attributes_mask;
--
--      attributes.window_type = GDK_WINDOW_CHILD;
--      attributes.wclass = GDK_INPUT_OUTPUT;
--      attributes.x = column->allocation.x;
--      attributes.y = 0;
--      attributes.width = column->allocation.width;
--      attributes.height = column->allocation.height;
--      attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
--      attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
--      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL ;
--
--      tree_view->priv->drag_window = gdk_window_new (tree_view->priv->bin_window,
--                                                   &attributes,
--                                                   attributes_mask);
--      gdk_window_set_user_data (tree_view->priv->drag_window, GTK_WIDGET (tree_view));
--    }
--
--  gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
--  gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
--
--  gtk_grab_remove (column->button);
--
--  send_event = gdk_event_new (GDK_LEAVE_NOTIFY);
--  send_event->crossing.send_event = TRUE;
--  send_event->crossing.window = g_object_ref (gtk_button_get_event_window (GTK_BUTTON (column->button)));
--  send_event->crossing.subwindow = NULL;
--  send_event->crossing.detail = GDK_NOTIFY_ANCESTOR;
--  send_event->crossing.time = GDK_CURRENT_TIME;
--
--  gtk_propagate_event (column->button, send_event);
--  gdk_event_free (send_event);
--
--  send_event = gdk_event_new (GDK_BUTTON_RELEASE);
--  send_event->button.window = g_object_ref (gdk_screen_get_root_window (screen));
--  send_event->button.send_event = TRUE;
--  send_event->button.time = GDK_CURRENT_TIME;
--  send_event->button.x = -1;
--  send_event->button.y = -1;
--  send_event->button.axes = NULL;
--  send_event->button.state = 0;
--  send_event->button.button = 1;
--  send_event->button.device = 
--    gdk_device_manager_get_client_pointer (gdk_display_get_device_manager (display));
--
--  send_event->button.x_root = 0;
--  send_event->button.y_root = 0;
--
--  gtk_propagate_event (column->button, send_event);
--  gdk_event_free (send_event);
--
--  /* Kids, don't try this at home */
--  g_object_ref (column->button);
--  gtk_container_remove (GTK_CONTAINER (tree_view), column->button);
--  gtk_widget_set_parent_window (column->button, tree_view->priv->drag_window);
--  gtk_widget_set_parent (column->button, GTK_WIDGET (tree_view));
--  g_object_unref (column->button);
--
--  tree_view->priv->drag_column_x = column->allocation.x;
--  allocation = column->allocation;
--  allocation.x = 0;
--  gtk_widget_size_allocate (column->button, &allocation);
--  gtk_widget_set_parent_window (column->button, tree_view->priv->drag_window);
--
--  tree_view->priv->drag_column = column;
--  gdk_window_show (tree_view->priv->drag_window);
--
--  gdk_window_get_origin (tree_view->priv->header_window, &x, &y);
--
--  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--  while (gtk_events_pending ())
--    gtk_main_iteration ();
--
--  PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_IN_COLUMN_DRAG);
--  gdk_pointer_grab (tree_view->priv->drag_window,
--                  FALSE,
--                  GDK_POINTER_MOTION_MASK|GDK_BUTTON_RELEASE_MASK,
--                  NULL, NULL, GDK_CURRENT_TIME);
--  gdk_keyboard_grab (tree_view->priv->drag_window,
--                   FALSE,
--                   GDK_CURRENT_TIME);
--}
--
--void
--_pspp_sheet_view_queue_draw_node (PsppSheetView        *tree_view,
--                              int node,
--                              const GdkRectangle *clip_rect)
--{
--  GdkRectangle rect;
--  GtkAllocation allocation;
--
--  if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    return;
--
--  gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
--  rect.x = 0;
--  rect.width = MAX (tree_view->priv->width, allocation.width);
--
--  rect.y = BACKGROUND_FIRST_PIXEL (tree_view, node);
--  rect.height = ROW_HEIGHT (tree_view);
--
--  if (clip_rect)
--    {
--      GdkRectangle new_rect;
--
--      gdk_rectangle_intersect (clip_rect, &rect, &new_rect);
--
--      gdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE);
--    }
--  else
--    {
--      gdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE);
--    }
--}
--
--static void
--pspp_sheet_view_queue_draw_path (PsppSheetView        *tree_view,
--                               GtkTreePath        *path,
--                               const GdkRectangle *clip_rect)
--{
--  int node = -1;
--
--  _pspp_sheet_view_find_node (tree_view, path, &node);
--
--  if (node)
--    _pspp_sheet_view_queue_draw_node (tree_view, node, clip_rect);
--}
--
--static void
--pspp_sheet_view_focus_to_cursor (PsppSheetView *tree_view)
--
--{
--  GtkTreePath *cursor_path;
--
--  if ((tree_view->priv->row_count == 0) ||
--      (! gtk_widget_get_realized (GTK_WIDGET (tree_view))))
--    return;
--
--  cursor_path = NULL;
--  if (tree_view->priv->cursor)
--    cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--
--  if (cursor_path == NULL)
--    {
--      /* There's no cursor.  Move the cursor to the first selected row, if any
--       * are selected, otherwise to the first row in the sheetview.
--       */
--      GList *selected_rows;
--      GtkTreeModel *model;
--      PsppSheetSelection *selection;
--
--      selection = pspp_sheet_view_get_selection (tree_view);
--      selected_rows = pspp_sheet_selection_get_selected_rows (selection, &model);
--
--      if (selected_rows)
--      {
--          /* XXX we could avoid doing O(n) work to get this result */
--          cursor_path = gtk_tree_path_copy((const GtkTreePath *)(selected_rows->data));
--        g_list_foreach (selected_rows, (GFunc)gtk_tree_path_free, NULL);
--        g_list_free (selected_rows);
--        }
--      else
--      {
--        cursor_path = gtk_tree_path_new_first ();
--        search_first_focusable_path (tree_view, &cursor_path,
--                                     TRUE, NULL);
--      }
--
--      gtk_tree_row_reference_free (tree_view->priv->cursor);
--      tree_view->priv->cursor = NULL;
--
--      if (cursor_path)
--      {
--        if (tree_view->priv->selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
--              tree_view->priv->selection->type == PSPP_SHEET_SELECTION_RECTANGLE)
--          pspp_sheet_view_real_set_cursor (tree_view, cursor_path, FALSE, FALSE, 0);
--        else
--          pspp_sheet_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE, 0);
--      }
--    }
--
--  if (cursor_path)
--    {
--      /* Now find a column for the cursor. */
--      PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS);
--
--      pspp_sheet_view_queue_draw_path (tree_view, cursor_path, NULL);
--      gtk_tree_path_free (cursor_path);
--
--      if (tree_view->priv->focus_column == NULL)
--      {
--        GList *list;
--        for (list = tree_view->priv->columns; list; list = list->next)
--          {
--            if (PSPP_SHEET_VIEW_COLUMN (list->data)->visible)
--              {
--                tree_view->priv->focus_column = PSPP_SHEET_VIEW_COLUMN (list->data);
--                  pspp_sheet_selection_unselect_all_columns (tree_view->priv->selection);
--                  pspp_sheet_selection_select_column (tree_view->priv->selection, tree_view->priv->focus_column);
--                break;
--              }
--          }
--
--      }
--    }
--}
--
--static gboolean
--pspp_sheet_view_move_cursor_up_down (PsppSheetView *tree_view,
--                                 gint         count,
--                                   PsppSheetSelectMode mode)
--{
--  gint selection_count;
--  int cursor_node = -1;
--  int new_cursor_node = -1;
--  GtkTreePath *cursor_path = NULL;
--  gboolean grab_focus = TRUE;
--
--  if (! gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    return FALSE;
--
--  cursor_path = NULL;
--  if (!gtk_tree_row_reference_valid (tree_view->priv->cursor))
--    /* FIXME: we lost the cursor; should we get the first? */
--    return FALSE;
--
--  cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--  _pspp_sheet_view_find_node (tree_view, cursor_path, &cursor_node);
--
--  if (cursor_node < 0)
--    /* FIXME: we lost the cursor; should we get the first? */
--    return FALSE;
--
--  selection_count = pspp_sheet_selection_count_selected_rows (tree_view->priv->selection);
--
--  if (selection_count == 0
--      && tree_view->priv->selection->type != PSPP_SHEET_SELECTION_NONE
--      && !(mode & PSPP_SHEET_SELECT_MODE_TOGGLE))
--    {
--      /* Don't move the cursor, but just select the current node */
--      new_cursor_node = cursor_node;
--    }
--  else
--    {
--      if (count == -1)
--      new_cursor_node = pspp_sheet_view_node_prev (tree_view, cursor_node);
--      else
--      new_cursor_node = pspp_sheet_view_node_next (tree_view, cursor_node);
--    }
--
--  gtk_tree_path_free (cursor_path);
--
--  if (new_cursor_node)
--    {
--      cursor_path = _pspp_sheet_view_find_path (tree_view, new_cursor_node);
--
--      search_first_focusable_path (tree_view, &cursor_path,
--                                 (count != -1),
--                                 &new_cursor_node);
--
--      if (cursor_path)
--      gtk_tree_path_free (cursor_path);
--    }
--
--  /*
--   * If the list has only one item and multi-selection is set then select
--   * the row (if not yet selected).
--   */
--  if ((tree_view->priv->selection->type == PSPP_SHEET_SELECTION_MULTIPLE ||
--       tree_view->priv->selection->type == PSPP_SHEET_SELECTION_RECTANGLE) &&
--      new_cursor_node < 0)
--    {
--      if (count == -1)
--        new_cursor_node = pspp_sheet_view_node_next (tree_view, cursor_node);
--      else
--        new_cursor_node = pspp_sheet_view_node_prev (tree_view, cursor_node);
--
--      if (new_cursor_node < 0
--        && !pspp_sheet_view_node_is_selected (tree_view, cursor_node))
--        {
--          new_cursor_node = cursor_node;
--        }
--      else
--        {
--          new_cursor_node = -1;
--        }
--    }
--
--  if (new_cursor_node >= 0)
--    {
--      cursor_path = _pspp_sheet_view_find_path (tree_view, new_cursor_node);
--      pspp_sheet_view_real_set_cursor (tree_view, cursor_path, TRUE, TRUE, mode);
--      gtk_tree_path_free (cursor_path);
--    }
--  else
--    {
--      pspp_sheet_view_clamp_node_visible (tree_view, cursor_node);
--
--      if (!(mode & PSPP_SHEET_SELECT_MODE_EXTEND))
--        {
--          if (! gtk_widget_keynav_failed (GTK_WIDGET (tree_view),
--                                          count < 0 ?
--                                          GTK_DIR_UP : GTK_DIR_DOWN))
--            {
--              GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
--
--              if (toplevel)
--                gtk_widget_child_focus (toplevel,
--                                        count < 0 ?
--                                        GTK_DIR_TAB_BACKWARD :
--                                        GTK_DIR_TAB_FORWARD);
--
--              grab_focus = FALSE;
--            }
--        }
--      else
--        {
--          gtk_widget_error_bell (GTK_WIDGET (tree_view));
--        }
--    }
--
--  if (grab_focus)
--    gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--
--  return new_cursor_node >= 0;
--}
--
--static void
--pspp_sheet_view_move_cursor_page_up_down (PsppSheetView *tree_view,
--                                          gint         count,
--                                          PsppSheetSelectMode mode)
--{
--  int cursor_node = -1;
--  GtkTreePath *old_cursor_path = NULL;
--  GtkTreePath *cursor_path = NULL;
--  int start_cursor_node = -1;
--  gint y;
--  gint window_y;
--  gint vertical_separator;
--
--  if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    return;
--
--  if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
--    old_cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--  else
--    /* This is sorta weird.  Focus in should give us a cursor */
--    return;
--
--  gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical-separator", &vertical_separator, NULL);
--  _pspp_sheet_view_find_node (tree_view, old_cursor_path, &cursor_node);
--
--  if (cursor_node < 0)
--    {
--      /* FIXME: we lost the cursor.  Should we try to get one? */
--      gtk_tree_path_free (old_cursor_path);
--      return;
--    }
--
--  y = pspp_sheet_view_node_find_offset (tree_view, cursor_node);
--  window_y = RBTREE_Y_TO_TREE_WINDOW_Y (tree_view, y);
--  y += tree_view->priv->cursor_offset;
--  y += count * (int)gtk_adjustment_get_page_increment (tree_view->priv->vadjustment);
--  y = CLAMP (y, (gint)gtk_adjustment_get_lower (tree_view->priv->vadjustment),  (gint)gtk_adjustment_get_upper (tree_view->priv->vadjustment) - vertical_separator);
--
--  if (y >= tree_view->priv->height)
--    y = tree_view->priv->height - 1;
--
--  tree_view->priv->cursor_offset =
--    pspp_sheet_view_find_offset (tree_view, y, &cursor_node);
--
--  if (tree_view->priv->cursor_offset > BACKGROUND_HEIGHT (tree_view))
--    {
--      cursor_node = pspp_sheet_view_node_next (tree_view, cursor_node);
--      tree_view->priv->cursor_offset -= BACKGROUND_HEIGHT (tree_view);
--    }
--
--  y -= tree_view->priv->cursor_offset;
--  cursor_path = _pspp_sheet_view_find_path (tree_view, cursor_node);
--
--  start_cursor_node = cursor_node;
--
--  if (! search_first_focusable_path (tree_view, &cursor_path,
--                                   (count != -1),
--                                   &cursor_node))
--    {
--      /* It looks like we reached the end of the view without finding
--       * a focusable row.  We will step backwards to find the last
--       * focusable row.
--       */
--      cursor_node = start_cursor_node;
--      cursor_path = _pspp_sheet_view_find_path (tree_view, cursor_node);
--
--      search_first_focusable_path (tree_view, &cursor_path,
--                                 (count == -1),
--                                 &cursor_node);
--    }
--
--  if (!cursor_path)
--    goto cleanup;
--
--  /* update y */
--  y = pspp_sheet_view_node_find_offset (tree_view, cursor_node);
--
--  pspp_sheet_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE, mode);
--
--  y -= window_y;
--  pspp_sheet_view_scroll_to_point (tree_view, -1, y);
--  pspp_sheet_view_clamp_node_visible (tree_view, cursor_node);
--  _pspp_sheet_view_queue_draw_node (tree_view, cursor_node, NULL);
--
--  if (!gtk_tree_path_compare (old_cursor_path, cursor_path))
--    gtk_widget_error_bell (GTK_WIDGET (tree_view));
--
--  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--
--cleanup:
--  gtk_tree_path_free (old_cursor_path);
--  gtk_tree_path_free (cursor_path);
--}
--
--static void
--pspp_sheet_view_move_cursor_left_right (PsppSheetView *tree_view,
--                                        gint         count,
--                                        PsppSheetSelectMode mode)
--{
--  int cursor_node = -1;
--  GtkTreePath *cursor_path = NULL;
--  PsppSheetViewColumn *column;
--  GtkTreeIter iter;
--  GList *list;
--  gboolean found_column = FALSE;
--  gboolean rtl;
--
--  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--
--  if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    return;
--
--  if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
--    cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--  else
--    return;
--
--  _pspp_sheet_view_find_node (tree_view, cursor_path, &cursor_node);
--  if (cursor_node < 0)
--    return;
--  if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path) == FALSE)
--    {
--      gtk_tree_path_free (cursor_path);
--      return;
--    }
--  gtk_tree_path_free (cursor_path);
--
--  list = rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns);
--  if (tree_view->priv->focus_column)
--    {
--      for (; list; list = (rtl ? list->prev : list->next))
--      {
--        if (list->data == tree_view->priv->focus_column)
--          break;
--      }
--    }
--
--  while (list)
--    {
--      gboolean left, right;
--
--      column = list->data;
--      if (column->visible == FALSE || column->row_head)
--      goto loop_end;
--
--      pspp_sheet_view_column_cell_set_cell_data (column,
--                                             tree_view->priv->model,
--                                             &iter);
--
--      if (rtl)
--        {
--        right = list->prev ? TRUE : FALSE;
--        left = list->next ? TRUE : FALSE;
--      }
--      else
--        {
--        left = list->prev ? TRUE : FALSE;
--        right = list->next ? TRUE : FALSE;
--        }
--
--      if (_pspp_sheet_view_column_cell_focus (column, count, left, right))
--      {
--        tree_view->priv->focus_column = column;
--        found_column = TRUE;
--        break;
--      }
--    loop_end:
--      if (count == 1)
--      list = rtl ? list->prev : list->next;
--      else
--      list = rtl ? list->next : list->prev;
--    }
--
--  if (found_column)
--    {
--      _pspp_sheet_view_queue_draw_node (tree_view, cursor_node, NULL);
--      g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
--      gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--    }
--  else
--    {
--      gtk_widget_error_bell (GTK_WIDGET (tree_view));
--    }
--
--  pspp_sheet_view_clamp_column_visible (tree_view,
--                                    tree_view->priv->focus_column, TRUE);
--}
--
--static void
--pspp_sheet_view_move_cursor_line_start_end (PsppSheetView *tree_view,
--                                            gint         count,
--                                            PsppSheetSelectMode mode)
--{
--  int cursor_node = -1;
--  GtkTreePath *cursor_path = NULL;
--  PsppSheetViewColumn *column;
--  PsppSheetViewColumn *found_column;
--  GtkTreeIter iter;
--  GList *list;
--  gboolean rtl;
--
--  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--
--  if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    return;
--
--  if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
--    cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--  else
--    return;
--
--  _pspp_sheet_view_find_node (tree_view, cursor_path, &cursor_node);
--  if (cursor_node < 0)
--    return;
--  if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path) == FALSE)
--    {
--      gtk_tree_path_free (cursor_path);
--      return;
--    }
--  gtk_tree_path_free (cursor_path);
--
--  list = rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns);
--  if (tree_view->priv->focus_column)
--    {
--      for (; list; list = (rtl ? list->prev : list->next))
--      {
--        if (list->data == tree_view->priv->focus_column)
--          break;
--      }
--    }
--
--  found_column = NULL;
--  while (list)
--    {
--      gboolean left, right;
--
--      column = list->data;
--      if (column->visible == FALSE || column->row_head)
--      goto loop_end;
--
--      pspp_sheet_view_column_cell_set_cell_data (column,
--                                             tree_view->priv->model,
--                                             &iter);
--
--      if (rtl)
--        {
--        right = list->prev ? TRUE : FALSE;
--        left = list->next ? TRUE : FALSE;
--      }
--      else
--        {
--        left = list->prev ? TRUE : FALSE;
--        right = list->next ? TRUE : FALSE;
--        }
--
--      if (column->tabbable
--          && _pspp_sheet_view_column_cell_focus (column, count, left, right))
--        found_column = column;
--
--    loop_end:
--      if (count == 1)
--      list = rtl ? list->prev : list->next;
--      else
--      list = rtl ? list->next : list->prev;
--    }
--
--  if (found_column)
--    {
--      tree_view->priv->focus_column = found_column;
--      _pspp_sheet_view_queue_draw_node (tree_view, cursor_node, NULL);
--      g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
--      gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--    }
--
--  pspp_sheet_view_clamp_column_visible (tree_view,
--                                    tree_view->priv->focus_column, TRUE);
--}
--
--static gboolean
--try_move_cursor_tab (PsppSheetView *tree_view,
--                     gboolean start_at_focus_column,
--                     gint count)
--{
--  PsppSheetViewColumn *column;
--  GtkTreeIter iter;
--  int cursor_node = -1;
--  GtkTreePath *cursor_path = NULL;
--  gboolean rtl;
--  GList *list;
--
--  if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
--    cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--  else
--    return TRUE;
--
--  _pspp_sheet_view_find_node (tree_view, cursor_path, &cursor_node);
--  if (cursor_node < 0)
--    return TRUE;
--  if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path) == FALSE)
--    {
--      gtk_tree_path_free (cursor_path);
--      return TRUE;
--    }
--  gtk_tree_path_free (cursor_path);
--
--  rtl = gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL;
--  if (start_at_focus_column)
--    {
--      list = (rtl
--              ? g_list_last (tree_view->priv->columns)
--              : g_list_first (tree_view->priv->columns));
--      if (tree_view->priv->focus_column)
--        {
--          for (; list; list = (rtl ? list->prev : list->next))
--            {
--              if (list->data == tree_view->priv->focus_column)
--                break;
--            }
--        }
--    }
--  else
--    {
--      list = (rtl ^ (count == 1)
--              ? g_list_first (tree_view->priv->columns)
--              : g_list_last (tree_view->priv->columns));
--    }
--
--  while (list)
--    {
--      gboolean left, right;
--
--      column = list->data;
--      if (column->visible == FALSE || !column->tabbable)
--      goto loop_end;
--
--      pspp_sheet_view_column_cell_set_cell_data (column,
--                                                 tree_view->priv->model,
--                                                 &iter);
--
--      if (rtl)
--        {
--        right = list->prev ? TRUE : FALSE;
--        left = list->next ? TRUE : FALSE;
--      }
--      else
--        {
--        left = list->prev ? TRUE : FALSE;
--        right = list->next ? TRUE : FALSE;
--        }
--
--      if (column->tabbable
--          && _pspp_sheet_view_column_cell_focus (column, count, left, right))
--      {
--        tree_view->priv->focus_column = column;
--          _pspp_sheet_view_queue_draw_node (tree_view, cursor_node, NULL);
--          g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
--          gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--          return TRUE;
--      }
--    loop_end:
--      if (count == 1)
--      list = rtl ? list->prev : list->next;
--      else
--      list = rtl ? list->next : list->prev;
--    }
--
--  return FALSE;
--}
--
--static void
--pspp_sheet_view_move_cursor_tab (PsppSheetView *tree_view,
--                                 gint         count)
--{
--  if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    return;
--
--  if (!try_move_cursor_tab (tree_view, TRUE, count))
--    {
--      if (pspp_sheet_view_move_cursor_up_down (tree_view, count, 0)
--          && !try_move_cursor_tab (tree_view, FALSE, count))
--        gtk_widget_error_bell (GTK_WIDGET (tree_view));
--    }
--
--  pspp_sheet_view_clamp_column_visible (tree_view,
--                                        tree_view->priv->focus_column, TRUE);
--}
--
--static void
--pspp_sheet_view_move_cursor_start_end (PsppSheetView *tree_view,
--                                       gint         count,
--                                       PsppSheetSelectMode mode)
--{
--  int cursor_node;
--  GtkTreePath *path;
--  GtkTreePath *old_path;
--
--  if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    return;
--
--  g_return_if_fail (tree_view->priv->row_count > 0);
--
--  pspp_sheet_view_get_cursor (tree_view, &old_path, NULL);
--
--  if (count == -1)
--    {
--      /* Now go forward to find the first focusable row. */
--      path = _pspp_sheet_view_find_path (tree_view, 0);
--      search_first_focusable_path (tree_view, &path,
--                                 TRUE, &cursor_node);
--    }
--  else
--    {
--      /* Now go backwards to find last focusable row. */
--      path = _pspp_sheet_view_find_path (tree_view, tree_view->priv->row_count - 1);
--      search_first_focusable_path (tree_view, &path,
--                                 FALSE, &cursor_node);
--    }
--
--  if (!path)
--    goto cleanup;
--
--  if (gtk_tree_path_compare (old_path, path))
--    {
--      pspp_sheet_view_real_set_cursor (tree_view, path, TRUE, TRUE, mode);
--      gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--    }
--  else
--    {
--      gtk_widget_error_bell (GTK_WIDGET (tree_view));
--    }
--
--cleanup:
--  gtk_tree_path_free (old_path);
--  gtk_tree_path_free (path);
--}
--
--static gboolean
--pspp_sheet_view_real_select_all (PsppSheetView *tree_view)
--{
--  if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    return FALSE;
--
--  if (tree_view->priv->selection->type != PSPP_SHEET_SELECTION_MULTIPLE &&
--      tree_view->priv->selection->type != PSPP_SHEET_SELECTION_RECTANGLE)
--    return FALSE;
--
--  pspp_sheet_selection_select_all (tree_view->priv->selection);
--
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_real_unselect_all (PsppSheetView *tree_view)
--{
--  if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    return FALSE;
--
--  if (tree_view->priv->selection->type != PSPP_SHEET_SELECTION_MULTIPLE &&
--      tree_view->priv->selection->type != PSPP_SHEET_SELECTION_RECTANGLE)
--    return FALSE;
--
--  pspp_sheet_selection_unselect_all (tree_view->priv->selection);
--
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_real_select_cursor_row (PsppSheetView *tree_view,
--                                        gboolean     start_editing,
--                                        PsppSheetSelectMode mode)
--{
--  int new_node = -1;
--  int cursor_node = -1;
--  GtkTreePath *cursor_path = NULL;
--
--  if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    return FALSE;
--
--  if (tree_view->priv->cursor)
--    cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--
--  if (cursor_path == NULL)
--    return FALSE;
--
--  _pspp_sheet_view_find_node (tree_view, cursor_path,
--                              &cursor_node);
--
--  if (cursor_node < 0)
--    {
--      gtk_tree_path_free (cursor_path);
--      return FALSE;
--    }
--
--  if (!(mode & PSPP_SHEET_SELECT_MODE_EXTEND) && start_editing &&
--      tree_view->priv->focus_column)
--    {
--      if (pspp_sheet_view_start_editing (tree_view, cursor_path))
--      {
--        gtk_tree_path_free (cursor_path);
--        return TRUE;
--      }
--    }
--
--  _pspp_sheet_selection_internal_select_node (tree_view->priv->selection,
--                                          cursor_node,
--                                          cursor_path,
--                                            mode,
--                                          FALSE);
--
--  /* We bail out if the original (tree, node) don't exist anymore after
--   * handling the selection-changed callback.  We do return TRUE because
--   * the key press has been handled at this point.
--   */
--  _pspp_sheet_view_find_node (tree_view, cursor_path, &new_node);
--
--  if (cursor_node != new_node)
--    return FALSE;
--
--  pspp_sheet_view_clamp_node_visible (tree_view, cursor_node);
--
--  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--  _pspp_sheet_view_queue_draw_node (tree_view, cursor_node, NULL);
--
--  if (!(mode & PSPP_SHEET_SELECT_MODE_EXTEND))
--    pspp_sheet_view_row_activated (tree_view, cursor_path,
--                                 tree_view->priv->focus_column);
--    
--  gtk_tree_path_free (cursor_path);
--
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_real_toggle_cursor_row (PsppSheetView *tree_view)
--{
--  int new_node = -1;
--  int cursor_node = -1;
--  GtkTreePath *cursor_path = NULL;
--
--  if (!gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    return FALSE;
--
--  cursor_path = NULL;
--  if (tree_view->priv->cursor)
--    cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--
--  if (cursor_path == NULL)
--    return FALSE;
--
--  _pspp_sheet_view_find_node (tree_view, cursor_path, &cursor_node);
--  if (cursor_node < 0)
--    {
--      gtk_tree_path_free (cursor_path);
--      return FALSE;
--    }
--
--  _pspp_sheet_selection_internal_select_node (tree_view->priv->selection,
--                                          cursor_node,
--                                          cursor_path,
--                                            PSPP_SHEET_SELECT_MODE_TOGGLE,
--                                          FALSE);
--
--  /* We bail out if the original (tree, node) don't exist anymore after
--   * handling the selection-changed callback.  We do return TRUE because
--   * the key press has been handled at this point.
--   */
--  _pspp_sheet_view_find_node (tree_view, cursor_path, &new_node);
--
--  if (cursor_node != new_node)
--    return FALSE;
--
--  pspp_sheet_view_clamp_node_visible (tree_view, cursor_node);
--
--  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--  pspp_sheet_view_queue_draw_path (tree_view, cursor_path, NULL);
--  gtk_tree_path_free (cursor_path);
--
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_search_entry_flush_timeout (PsppSheetView *tree_view)
--{
--  pspp_sheet_view_search_dialog_hide (tree_view->priv->search_window, tree_view);
--  tree_view->priv->typeselect_flush_timeout = 0;
--
--  return FALSE;
--}
--
--/* Cut and paste from gtkwindow.c */
--static void
--send_focus_change (GtkWidget *widget,
--                 gboolean   in)
--{
--  GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
--
--  fevent->focus_change.type = GDK_FOCUS_CHANGE;
--  fevent->focus_change.window = g_object_ref (gtk_widget_get_window (widget));
--  fevent->focus_change.in = in;
--  
--  gtk_widget_send_focus_change (widget, fevent);
--  gdk_event_free (fevent);
--}
--
--static void
--pspp_sheet_view_ensure_interactive_directory (PsppSheetView *tree_view)
--{
--  GtkWidget *frame, *vbox, *toplevel;
--  GdkScreen *screen;
--
--  if (tree_view->priv->search_custom_entry_set)
--    return;
--
--  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tree_view));
--  screen = gtk_widget_get_screen (GTK_WIDGET (tree_view));
--
--   if (tree_view->priv->search_window != NULL)
--     {
--       if (gtk_window_get_group (GTK_WINDOW (toplevel)))
--       gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
--                                    GTK_WINDOW (tree_view->priv->search_window));
--       else if (gtk_window_get_group (GTK_WINDOW (tree_view->priv->search_window)))
--       gtk_window_group_remove_window (gtk_window_get_group (GTK_WINDOW (tree_view->priv->search_window)),
--                                       GTK_WINDOW (tree_view->priv->search_window));
--       gtk_window_set_screen (GTK_WINDOW (tree_view->priv->search_window), screen);
--       return;
--     }
--   
--  tree_view->priv->search_window = gtk_window_new (GTK_WINDOW_POPUP);
--  gtk_window_set_screen (GTK_WINDOW (tree_view->priv->search_window), screen);
--
--  if (gtk_window_get_group (GTK_WINDOW (toplevel)))
--    gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)),
--                               GTK_WINDOW (tree_view->priv->search_window));
--
--  gtk_window_set_type_hint (GTK_WINDOW (tree_view->priv->search_window),
--                          GDK_WINDOW_TYPE_HINT_UTILITY);
--  gtk_window_set_modal (GTK_WINDOW (tree_view->priv->search_window), TRUE);
--  g_signal_connect (tree_view->priv->search_window, "delete-event",
--                  G_CALLBACK (pspp_sheet_view_search_delete_event),
--                  tree_view);
--  g_signal_connect (tree_view->priv->search_window, "key-press-event",
--                  G_CALLBACK (pspp_sheet_view_search_key_press_event),
--                  tree_view);
--  g_signal_connect (tree_view->priv->search_window, "button-press-event",
--                  G_CALLBACK (pspp_sheet_view_search_button_press_event),
--                  tree_view);
--  g_signal_connect (tree_view->priv->search_window, "scroll-event",
--                  G_CALLBACK (pspp_sheet_view_search_scroll_event),
--                  tree_view);
--
--  frame = gtk_frame_new (NULL);
--  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
--  gtk_widget_show (frame);
--  gtk_container_add (GTK_CONTAINER (tree_view->priv->search_window), frame);
--
--  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
--  gtk_widget_show (vbox);
--  gtk_container_add (GTK_CONTAINER (frame), vbox);
--  gtk_container_set_border_width (GTK_CONTAINER (vbox), 3);
--
--  /* add entry */
--  tree_view->priv->search_entry = gtk_entry_new ();
--  gtk_widget_show (tree_view->priv->search_entry);
--  g_signal_connect (tree_view->priv->search_entry, "populate-popup",
--                  G_CALLBACK (pspp_sheet_view_search_disable_popdown),
--                  tree_view);
--  g_signal_connect (tree_view->priv->search_entry,
--                  "activate", G_CALLBACK (pspp_sheet_view_search_activate),
--                  tree_view);
--
--  gtk_container_add (GTK_CONTAINER (vbox),
--                   tree_view->priv->search_entry);
--
--  gtk_widget_realize (tree_view->priv->search_entry);
--}
--
--/* Pops up the interactive search entry.  If keybinding is TRUE then the user
-- * started this by typing the start_interactive_search keybinding.  Otherwise, it came from 
-- */
--static gboolean
--pspp_sheet_view_real_start_interactive_search (PsppSheetView *tree_view,
--                                           gboolean     keybinding)
--{
--  /* We only start interactive search if we have focus or the columns
--   * have focus.  If one of our children have focus, we don't want to
--   * start the search.
--   */
--  GList *list;
--  gboolean found_focus = FALSE;
--  GtkWidgetClass *entry_parent_class;
--  
--  if (!tree_view->priv->enable_search && !keybinding)
--    return FALSE;
--
--  if (tree_view->priv->search_custom_entry_set)
--    return FALSE;
--
--  if (tree_view->priv->search_window != NULL &&
--      gtk_widget_get_visible (tree_view->priv->search_window))
--    return TRUE;
--
--  for (list = tree_view->priv->columns; list; list = list->next)
--    {
--      PsppSheetViewColumn *column;
--
--      column = list->data;
--      if (! column->visible)
--      continue;
--
--      if (column->button && gtk_widget_has_focus (column->button))
--      {
--        found_focus = TRUE;
--        break;
--      }
--    }
--  
--  if (gtk_widget_has_focus (GTK_WIDGET (tree_view)))
--    found_focus = TRUE;
--
--  if (!found_focus)
--    return FALSE;
--
--  if (tree_view->priv->search_column < 0)
--    return FALSE;
--
--  pspp_sheet_view_ensure_interactive_directory (tree_view);
--
--  if (keybinding)
--    gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
--
--  /* done, show it */
--  tree_view->priv->search_position_func (tree_view, tree_view->priv->search_window, tree_view->priv->search_position_user_data);
--  gtk_widget_show (tree_view->priv->search_window);
--  if (tree_view->priv->search_entry_changed_id == 0)
--    {
--      tree_view->priv->search_entry_changed_id =
--      g_signal_connect (tree_view->priv->search_entry, "changed",
--                        G_CALLBACK (pspp_sheet_view_search_init),
--                        tree_view);
--    }
--
--  tree_view->priv->typeselect_flush_timeout =
--    gdk_threads_add_timeout (PSPP_SHEET_VIEW_SEARCH_DIALOG_TIMEOUT,
--                 (GSourceFunc) pspp_sheet_view_search_entry_flush_timeout,
--                 tree_view);
--
--  /* Grab focus will select all the text.  We don't want that to happen, so we
--   * call the parent instance and bypass the selection change.  This is probably
--   * really non-kosher. */
--  entry_parent_class = g_type_class_peek_parent (GTK_ENTRY_GET_CLASS (tree_view->priv->search_entry));
--  (entry_parent_class->grab_focus) (tree_view->priv->search_entry);
--
--  /* send focus-in event */
--  send_focus_change (tree_view->priv->search_entry, TRUE);
--
--  /* search first matching iter */
--  pspp_sheet_view_search_init (tree_view->priv->search_entry, tree_view);
--
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_start_interactive_search (PsppSheetView *tree_view)
--{
--  return pspp_sheet_view_real_start_interactive_search (tree_view, TRUE);
--}
--
--/* 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
--pspp_sheet_view_new_column_width (PsppSheetView *tree_view,
--                              gint       i,
--                              gint      *x)
--{
--  PsppSheetViewColumn *column;
--  gint width;
--  gboolean rtl;
--
--  /* first translate the x position from gtk_widget_get_window (widget)
--   * to clist->clist_window
--   */
--  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--  column = g_list_nth (tree_view->priv->columns, i)->data;
--  width = rtl ? (column->allocation.x + column->allocation.width - *x) : (*x - column->allocation.x);
-- 
--  /* Clamp down the value */
--  if (column->min_width == -1)
--    width = MAX (column->button_request, width);
--  else
--    width = MAX (column->min_width, width);
--  if (column->max_width != -1)
--    width = MIN (width, column->max_width);
--
--  *x = rtl ? (column->allocation.x + column->allocation.width - width) : (column->allocation.x + width);
-- 
--  return width;
--}
--
--void 
--pspp_sheet_view_column_update_button (PsppSheetViewColumn *tree_column);
--
--/* Callbacks */
--static void
--pspp_sheet_view_adjustment_changed (GtkAdjustment *adjustment,
--                                PsppSheetView   *tree_view)
--{
--  if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    {
--      gint dy;
--
--      gdk_window_move (tree_view->priv->bin_window,
--                     - gtk_adjustment_get_value (tree_view->priv->hadjustment),
--                     TREE_VIEW_HEADER_HEIGHT (tree_view));
--      gdk_window_move (tree_view->priv->header_window,
--                     - gtk_adjustment_get_value (tree_view->priv->hadjustment),
--                     0);
--      dy = tree_view->priv->dy - (int) gtk_adjustment_get_value (tree_view->priv->vadjustment);
--
--      gdk_window_scroll (tree_view->priv->bin_window, 0, dy);
--
--      if (dy != 0)
--        {
--          /* update our dy and top_row */
--          tree_view->priv->dy = (int) gtk_adjustment_get_value (tree_view->priv->vadjustment);
--
--        update_prelight (tree_view,
--                           tree_view->priv->event_last_x,
--                           tree_view->priv->event_last_y);
--
--          if (!tree_view->priv->in_top_row_to_dy)
--            pspp_sheet_view_dy_to_top_row (tree_view);
--      }
--
--      update_childrens_allocation(tree_view);
--    }
--}
--
--/* Public methods
-- */
--
--/**
-- * pspp_sheet_view_new:
-- *
-- * Creates a new #PsppSheetView widget.
-- *
-- * Return value: A newly created #PsppSheetView widget.
-- **/
--GtkWidget *
--pspp_sheet_view_new (void)
--{
--  return g_object_new (PSPP_TYPE_SHEET_VIEW, NULL);
--}
--
--/**
-- * pspp_sheet_view_new_with_model:
-- * @model: the model.
-- *
-- * Creates a new #PsppSheetView widget with the model initialized to @model.
-- *
-- * Return value: A newly created #PsppSheetView widget.
-- **/
--GtkWidget *
--pspp_sheet_view_new_with_model (GtkTreeModel *model)
--{
--  return g_object_new (PSPP_TYPE_SHEET_VIEW, "model", model, NULL);
--}
--
--/* Public Accessors
-- */
--
--/**
-- * pspp_sheet_view_get_model:
-- * @tree_view: a #PsppSheetView
-- *
-- * Returns the model the #PsppSheetView is based on.  Returns %NULL if the
-- * model is unset.
-- *
-- * Return value: A #GtkTreeModel, or %NULL if none is currently being used.
-- **/
--GtkTreeModel *
--pspp_sheet_view_get_model (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
--
--  return tree_view->priv->model;
--}
--
--/**
-- * pspp_sheet_view_set_model:
-- * @tree_view: A #GtkTreeNode.
-- * @model: (allow-none): The model.
-- *
-- * Sets the model for a #PsppSheetView.  If the @tree_view already has a model
-- * set, it will remove it before setting the new model.  If @model is %NULL,
-- * then it will unset the old model.
-- **/
--void
--pspp_sheet_view_set_model (PsppSheetView  *tree_view,
--                       GtkTreeModel *model)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
--
--  if (model == tree_view->priv->model)
--    return;
--
--  if (tree_view->priv->scroll_to_path)
--    {
--      gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
--      tree_view->priv->scroll_to_path = NULL;
--    }
--
--  if (tree_view->priv->model)
--    {
--      GList *tmplist = tree_view->priv->columns;
--
--      if (tree_view->priv->selected)
--        range_tower_set0 (tree_view->priv->selected, 0, ULONG_MAX);
--      pspp_sheet_view_stop_editing (tree_view, TRUE);
--
--      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
--                                          pspp_sheet_view_row_changed,
--                                          tree_view);
--      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
--                                          pspp_sheet_view_row_inserted,
--                                          tree_view);
--      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
--                                          pspp_sheet_view_row_deleted,
--                                          tree_view);
--      g_signal_handlers_disconnect_by_func (tree_view->priv->model,
--                                          pspp_sheet_view_rows_reordered,
--                                          tree_view);
--
--      for (; tmplist; tmplist = tmplist->next)
--      _pspp_sheet_view_column_unset_model (tmplist->data,
--                                         tree_view->priv->model);
--
--      tree_view->priv->prelight_node = -1;
--
--      gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
--      tree_view->priv->drag_dest_row = NULL;
--      gtk_tree_row_reference_free (tree_view->priv->cursor);
--      tree_view->priv->cursor = NULL;
--      gtk_tree_row_reference_free (tree_view->priv->anchor);
--      tree_view->priv->anchor = NULL;
--      gtk_tree_row_reference_free (tree_view->priv->top_row);
--      tree_view->priv->top_row = NULL;
--      gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
--      tree_view->priv->scroll_to_path = NULL;
--
--      tree_view->priv->scroll_to_column = NULL;
--
--      g_object_unref (tree_view->priv->model);
--
--      tree_view->priv->search_column = -1;
--      tree_view->priv->fixed_height = -1;
--      tree_view->priv->dy = tree_view->priv->top_row_dy = 0;
--      tree_view->priv->last_button_x = -1;
--      tree_view->priv->last_button_y = -1;
--    }
--
--  tree_view->priv->model = model;
--
--  if (tree_view->priv->model)
--    {
--      gint i;
--
--      if (tree_view->priv->search_column == -1)
--      {
--        for (i = 0; i < gtk_tree_model_get_n_columns (model); i++)
--          {
--            GType type = gtk_tree_model_get_column_type (model, i);
--
--            if (g_value_type_transformable (type, G_TYPE_STRING))
--              {
--                tree_view->priv->search_column = i;
--                break;
--              }
--          }
--      }
--
--      g_object_ref (tree_view->priv->model);
--      g_signal_connect (tree_view->priv->model,
--                      "row-changed",
--                      G_CALLBACK (pspp_sheet_view_row_changed),
--                      tree_view);
--      g_signal_connect (tree_view->priv->model,
--                      "row-inserted",
--                      G_CALLBACK (pspp_sheet_view_row_inserted),
--                      tree_view);
--      g_signal_connect (tree_view->priv->model,
--                      "row-deleted",
--                      G_CALLBACK (pspp_sheet_view_row_deleted),
--                      tree_view);
--      g_signal_connect (tree_view->priv->model,
--                      "rows-reordered",
--                      G_CALLBACK (pspp_sheet_view_rows_reordered),
--                      tree_view);
--
--      tree_view->priv->row_count = gtk_tree_model_iter_n_children (tree_view->priv->model, NULL);
--
--      /*  FIXME: do I need to do this? pspp_sheet_view_create_buttons (tree_view); */
--      install_presize_handler (tree_view);
--    }
--
--  g_object_notify (G_OBJECT (tree_view), "model");
--
--  if (tree_view->priv->selection)
--    _pspp_sheet_selection_emit_changed (tree_view->priv->selection);
--
--  if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    gtk_widget_queue_resize (GTK_WIDGET (tree_view));
--}
--
--/**
-- * pspp_sheet_view_get_selection:
-- * @tree_view: A #PsppSheetView.
-- *
-- * Gets the #PsppSheetSelection associated with @tree_view.
-- *
-- * Return value: A #PsppSheetSelection object.
-- **/
--PsppSheetSelection *
--pspp_sheet_view_get_selection (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
--
--  return tree_view->priv->selection;
--}
--
--/**
-- * pspp_sheet_view_get_hadjustment:
-- * @tree_view: A #PsppSheetView
-- *
-- * Gets the #GtkAdjustment currently being used for the horizontal aspect.
-- *
-- * Return value: A #GtkAdjustment object, or %NULL if none is currently being
-- * used.
-- **/
--GtkAdjustment *
--pspp_sheet_view_get_hadjustment (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
--
--  return pspp_sheet_view_do_get_hadjustment (tree_view);
--}
--
--static GtkAdjustment *
--pspp_sheet_view_do_get_hadjustment (PsppSheetView *tree_view)
--{
--  return tree_view->priv->hadjustment;
--}
--
--/**
-- * pspp_sheet_view_set_hadjustment:
-- * @tree_view: A #PsppSheetView
-- * @adjustment: (allow-none): The #GtkAdjustment to set, or %NULL
-- *
-- * Sets the #GtkAdjustment for the current horizontal aspect.
-- **/
--void
--pspp_sheet_view_set_hadjustment (PsppSheetView   *tree_view,
--                             GtkAdjustment *adjustment)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  pspp_sheet_view_set_adjustments (tree_view,
--                               adjustment,
--                               tree_view->priv->vadjustment);
--
--  g_object_notify (G_OBJECT (tree_view), "hadjustment");
--}
--
--static void
--pspp_sheet_view_do_set_hadjustment (PsppSheetView   *tree_view,
--                                  GtkAdjustment *adjustment)
--{
--  PsppSheetViewPrivate *priv = tree_view->priv;
--
--  if (adjustment && priv->hadjustment == adjustment)
--    return;
--
--  if (priv->hadjustment != NULL)
--    {
--      g_signal_handlers_disconnect_by_func (priv->hadjustment,
--                                            pspp_sheet_view_adjustment_changed,
--                                            tree_view);
--      g_object_unref (priv->hadjustment);
--    }
--
--  if (adjustment == NULL)
--    adjustment = gtk_adjustment_new (0.0, 0.0, 0.0,
--                                     0.0, 0.0, 0.0);
--
--  g_signal_connect (adjustment, "value-changed",
--                    G_CALLBACK (pspp_sheet_view_adjustment_changed), tree_view);
--  priv->hadjustment = g_object_ref_sink (adjustment);
--  /* FIXME: Adjustment should probably be populated here with fresh values, but
--   * internal details are too complicated for me to decipher right now.
--   */
--  pspp_sheet_view_adjustment_changed (NULL, tree_view);
--
--  g_object_notify (G_OBJECT (tree_view), "hadjustment");
--}
--
--/**
-- * pspp_sheet_view_get_vadjustment:
-- * @tree_view: A #PsppSheetView
-- *
-- * Gets the #GtkAdjustment currently being used for the vertical aspect.
-- *
-- * Return value: (transfer none): A #GtkAdjustment object, or %NULL
-- *     if none is currently being used.
-- *
-- * Deprecated: 3.0: Use gtk_scrollable_get_vadjustment()
-- **/
--GtkAdjustment *
--pspp_sheet_view_get_vadjustment (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
--
--  return pspp_sheet_view_do_get_vadjustment (tree_view);
--}
--
--static GtkAdjustment *
--pspp_sheet_view_do_get_vadjustment (PsppSheetView *tree_view)
--{
--  return tree_view->priv->vadjustment;
--}
--
--/**
-- * pspp_sheet_view_set_vadjustment:
-- * @tree_view: A #PsppSheetView
-- * @adjustment: (allow-none): The #GtkAdjustment to set, or %NULL
-- *
-- * Sets the #GtkAdjustment for the current vertical aspect.
-- *
-- * Deprecated: 3.0: Use gtk_scrollable_set_vadjustment()
-- **/
--void
--pspp_sheet_view_set_vadjustment (PsppSheetView   *tree_view,
--                               GtkAdjustment *adjustment)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (adjustment == NULL || GTK_IS_ADJUSTMENT (adjustment));
--
--  pspp_sheet_view_do_set_vadjustment (tree_view, adjustment);
--}
--
--static void
--pspp_sheet_view_do_set_vadjustment (PsppSheetView   *tree_view,
--                                  GtkAdjustment *adjustment)
--{
--  PsppSheetViewPrivate *priv = tree_view->priv;
--
--  if (adjustment && priv->vadjustment == adjustment)
--    return;
--
--  if (priv->vadjustment != NULL)
--    {
--      g_signal_handlers_disconnect_by_func (priv->vadjustment,
--                                            pspp_sheet_view_adjustment_changed,
--                                            tree_view);
--      g_object_unref (priv->vadjustment);
--    }
--
--  if (adjustment == NULL)
--    adjustment = gtk_adjustment_new (0.0, 0.0, 0.0,
--                                     0.0, 0.0, 0.0);
--
--  g_signal_connect (adjustment, "value-changed",
--                    G_CALLBACK (pspp_sheet_view_adjustment_changed), tree_view);
--  priv->vadjustment = g_object_ref_sink (adjustment);
--  /* FIXME: Adjustment should probably be populated here with fresh values, but
--   * internal details are too complicated for me to decipher right now.
--   */
--  pspp_sheet_view_adjustment_changed (NULL, tree_view);
--  g_object_notify (G_OBJECT (tree_view), "vadjustment");
--}
--
--/* Column and header operations */
--
--/**
-- * pspp_sheet_view_get_headers_visible:
-- * @tree_view: A #PsppSheetView.
-- *
-- * Returns %TRUE if the headers on the @tree_view are visible.
-- *
-- * Return value: Whether the headers are visible or not.
-- **/
--gboolean
--pspp_sheet_view_get_headers_visible (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
--
--  return PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE);
--}
--
--/**
-- * pspp_sheet_view_set_headers_visible:
-- * @tree_view: A #PsppSheetView.
-- * @headers_visible: %TRUE if the headers are visible
-- *
-- * Sets the visibility state of the headers.
-- **/
--void
--pspp_sheet_view_set_headers_visible (PsppSheetView *tree_view,
--                                 gboolean     headers_visible)
--{
--  gint x, y;
--  GList *list;
--  PsppSheetViewColumn *column;
--  GtkAllocation allocation;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
--
--  headers_visible = !! headers_visible;
--
--  if (PSPP_SHEET_VIEW_FLAG_SET (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE) == headers_visible)
--    return;
--
--  if (headers_visible)
--    PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE);
--  else
--    PSPP_SHEET_VIEW_UNSET_FLAG (tree_view, PSPP_SHEET_VIEW_HEADERS_VISIBLE);
--
--  if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    {
--      gdk_window_get_position (tree_view->priv->bin_window, &x, &y);
--      if (headers_visible)
--      {
--        gdk_window_move_resize (tree_view->priv->bin_window, x, y  + TREE_VIEW_HEADER_HEIGHT (tree_view), 
--                                tree_view->priv->width, allocation.height -  + TREE_VIEW_HEADER_HEIGHT (tree_view));
--
--          if (gtk_widget_get_mapped (GTK_WIDGET (tree_view)))
--            pspp_sheet_view_map_buttons (tree_view);
--      }
--      else
--      {
--        gdk_window_move_resize (tree_view->priv->bin_window, x, y, tree_view->priv->width, tree_view->priv->height);
--
--        for (list = tree_view->priv->columns; list; list = list->next)
--          {
--            column = list->data;
--              if (column->button)
--                gtk_widget_unmap (column->button);
--          }
--        gdk_window_hide (tree_view->priv->header_window);
--      }
--    }
--
--  gtk_adjustment_set_page_size (tree_view->priv->vadjustment, allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view));
--  gtk_adjustment_set_page_increment (tree_view->priv->vadjustment, (allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2);
--  gtk_adjustment_set_lower (tree_view->priv->vadjustment, 0);
--  gtk_adjustment_set_upper (tree_view->priv->vadjustment, tree_view->priv->height);
--  gtk_adjustment_changed (tree_view->priv->vadjustment);
--
--  gtk_widget_queue_resize (GTK_WIDGET (tree_view));
--
--  g_object_notify (G_OBJECT (tree_view), "headers-visible");
--}
--
--/**
-- * pspp_sheet_view_columns_autosize:
-- * @tree_view: A #PsppSheetView.
-- *
-- * Resizes all columns to their optimal width. Only works after the
-- * treeview has been realized.
-- **/
--void
--pspp_sheet_view_columns_autosize (PsppSheetView *tree_view)
--{
--  gboolean dirty = FALSE;
--  GList *list;
--  PsppSheetViewColumn *column;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  for (list = tree_view->priv->columns; list; list = list->next)
--    {
--      column = list->data;
--      _pspp_sheet_view_column_cell_set_dirty (column);
--      dirty = TRUE;
--    }
--
--  if (dirty)
--    gtk_widget_queue_resize (GTK_WIDGET (tree_view));
--}
--
--/**
-- * pspp_sheet_view_set_headers_clickable:
-- * @tree_view: A #PsppSheetView.
-- * @setting: %TRUE if the columns are clickable.
-- *
-- * Allow the column title buttons to be clicked.
-- **/
--void
--pspp_sheet_view_set_headers_clickable (PsppSheetView *tree_view,
--                                   gboolean   setting)
--{
--  GList *list;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  for (list = tree_view->priv->columns; list; list = list->next)
--    pspp_sheet_view_column_set_clickable (PSPP_SHEET_VIEW_COLUMN (list->data), setting);
--
--  g_object_notify (G_OBJECT (tree_view), "headers-clickable");
--}
--
--
--/**
-- * pspp_sheet_view_get_headers_clickable:
-- * @tree_view: A #PsppSheetView.
-- *
-- * Returns whether all header columns are clickable.
-- *
-- * Return value: %TRUE if all header columns are clickable, otherwise %FALSE
-- *
-- * Since: 2.10
-- **/
--gboolean 
--pspp_sheet_view_get_headers_clickable (PsppSheetView *tree_view)
--{
--  GList *list;
--  
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
--
--  for (list = tree_view->priv->columns; list; list = list->next)
--    if (!PSPP_SHEET_VIEW_COLUMN (list->data)->clickable)
--      return FALSE;
--
--  return TRUE;
--}
--
--/**
-- * pspp_sheet_view_set_rules_hint
-- * @tree_view: a #PsppSheetView
-- * @setting: %TRUE if the tree requires reading across rows
-- *
-- * This function tells GTK+ that the user interface for your
-- * application requires users to read across tree rows and associate
-- * cells with one another. By default, GTK+ will then render the tree
-- * with alternating row colors. Do <emphasis>not</emphasis> use it
-- * just because you prefer the appearance of the ruled tree; that's a
-- * question for the theme. Some themes will draw tree rows in
-- * alternating colors even when rules are turned off, and users who
-- * prefer that appearance all the time can choose those themes. You
-- * should call this function only as a <emphasis>semantic</emphasis>
-- * hint to the theme engine that your tree makes alternating colors
-- * useful from a functional standpoint (since it has lots of columns,
-- * generally).
-- *
-- **/
--void
--pspp_sheet_view_set_rules_hint (PsppSheetView  *tree_view,
--                              gboolean      setting)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  setting = setting != FALSE;
--
--  if (tree_view->priv->has_rules != setting)
--    {
--      tree_view->priv->has_rules = setting;
--      gtk_widget_queue_draw (GTK_WIDGET (tree_view));
--    }
--
--  g_object_notify (G_OBJECT (tree_view), "rules-hint");
--}
--
--/**
-- * pspp_sheet_view_get_rules_hint
-- * @tree_view: a #PsppSheetView
-- *
-- * Gets the setting set by pspp_sheet_view_set_rules_hint().
-- *
-- * Return value: %TRUE if rules are useful for the user of this tree
-- **/
--gboolean
--pspp_sheet_view_get_rules_hint (PsppSheetView  *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
--
--  return tree_view->priv->has_rules;
--}
--
--/* Public Column functions
-- */
--
--/**
-- * pspp_sheet_view_append_column:
-- * @tree_view: A #PsppSheetView.
-- * @column: The #PsppSheetViewColumn to add.
-- *
-- * Appends @column to the list of columns.
-- *
-- * Return value: The number of columns in @tree_view after appending.
-- **/
--gint
--pspp_sheet_view_append_column (PsppSheetView       *tree_view,
--                           PsppSheetViewColumn *column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), -1);
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (column), -1);
--  g_return_val_if_fail (column->tree_view == NULL, -1);
--
--  return pspp_sheet_view_insert_column (tree_view, column, -1);
--}
--
--
--/**
-- * pspp_sheet_view_remove_column:
-- * @tree_view: A #PsppSheetView.
-- * @column: The #PsppSheetViewColumn to remove.
-- *
-- * Removes @column from @tree_view.
-- *
-- * Return value: The number of columns in @tree_view after removing.
-- **/
--gint
--pspp_sheet_view_remove_column (PsppSheetView       *tree_view,
--                             PsppSheetViewColumn *column)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), -1);
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (column), -1);
--  g_return_val_if_fail (column->tree_view == GTK_WIDGET (tree_view), -1);
--
--  if (tree_view->priv->focus_column == column)
--    tree_view->priv->focus_column = NULL;
--
--  if (tree_view->priv->edited_column == column)
--    {
--      pspp_sheet_view_stop_editing (tree_view, TRUE);
--
--      /* no need to, but just to be sure ... */
--      tree_view->priv->edited_column = NULL;
--    }
--
--  _pspp_sheet_view_column_unset_tree_view (column);
--
--  tree_view->priv->columns = g_list_remove (tree_view->priv->columns, column);
--  tree_view->priv->n_columns--;
--
--  if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    {
--      GList *list;
--
--      _pspp_sheet_view_column_unrealize_button (column);
--      for (list = tree_view->priv->columns; list; list = list->next)
--      {
--        PsppSheetViewColumn *tmp_column;
--
--        tmp_column = PSPP_SHEET_VIEW_COLUMN (list->data);
--        if (tmp_column->visible)
--          _pspp_sheet_view_column_cell_set_dirty (tmp_column);
--      }
--
--      if (tree_view->priv->n_columns == 0 &&
--        pspp_sheet_view_get_headers_visible (tree_view) && 
--        tree_view->priv->header_window)
--      gdk_window_hide (tree_view->priv->header_window);
--
--      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
--    }
--
--  g_object_unref (column);
--  g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
--
--  return tree_view->priv->n_columns;
--}
--
--/**
-- * pspp_sheet_view_insert_column:
-- * @tree_view: A #PsppSheetView.
-- * @column: The #PsppSheetViewColumn to be inserted.
-- * @position: The position to insert @column in.
-- *
-- * This inserts the @column into the @tree_view at @position.  If @position is
-- * -1, then the column is inserted at the end.
-- *
-- * Return value: The number of columns in @tree_view after insertion.
-- **/
--gint
--pspp_sheet_view_insert_column (PsppSheetView       *tree_view,
--                             PsppSheetViewColumn *column,
--                             gint               position)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), -1);
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW_COLUMN (column), -1);
--  g_return_val_if_fail (column->tree_view == NULL, -1);
--
--  g_object_ref_sink (column);
--
--  if (tree_view->priv->n_columns == 0 &&
--      gtk_widget_get_realized (GTK_WIDGET (tree_view)) &&
--      pspp_sheet_view_get_headers_visible (tree_view))
--    {
--      gdk_window_show (tree_view->priv->header_window);
--    }
--
--  tree_view->priv->columns = g_list_insert (tree_view->priv->columns,
--                                          column, position);
--  tree_view->priv->n_columns++;
--
--  _pspp_sheet_view_column_set_tree_view (column, tree_view);
--
--  if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    {
--      GList *list;
--
--      _pspp_sheet_view_column_realize_button (column);
--
--      for (list = tree_view->priv->columns; list; list = list->next)
--      {
--        column = PSPP_SHEET_VIEW_COLUMN (list->data);
--        if (column->visible)
--          _pspp_sheet_view_column_cell_set_dirty (column);
--      }
--      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
--    }
--
--  g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
--
--  return tree_view->priv->n_columns;
--}
--
--/**
-- * pspp_sheet_view_insert_column_with_attributes:
-- * @tree_view: A #PsppSheetView
-- * @position: The position to insert the new column in.
-- * @title: The title to set the header to.
-- * @cell: The #GtkCellRenderer.
-- * @Varargs: A %NULL-terminated list of attributes.
-- *
-- * Creates a new #PsppSheetViewColumn and inserts it into the @tree_view at
-- * @position.  If @position is -1, then the newly created column is inserted at
-- * the end.  The column is initialized with the attributes given.
-- *
-- * Return value: The number of columns in @tree_view after insertion.
-- **/
--gint
--pspp_sheet_view_insert_column_with_attributes (PsppSheetView     *tree_view,
--                                           gint             position,
--                                           const gchar     *title,
--                                           GtkCellRenderer *cell,
--                                           ...)
--{
--  PsppSheetViewColumn *column;
--  gchar *attribute;
--  va_list args;
--  gint column_id;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), -1);
--
--  column = pspp_sheet_view_column_new ();
--  pspp_sheet_view_column_set_title (column, title);
--  pspp_sheet_view_column_pack_start (column, cell, TRUE);
--
--  va_start (args, cell);
--
--  attribute = va_arg (args, gchar *);
--
--  while (attribute != NULL)
--    {
--      column_id = va_arg (args, gint);
--      pspp_sheet_view_column_add_attribute (column, cell, attribute, column_id);
--      attribute = va_arg (args, gchar *);
--    }
--
--  va_end (args);
--
--  pspp_sheet_view_insert_column (tree_view, column, position);
--
--  return tree_view->priv->n_columns;
--}
--
--/**
-- * pspp_sheet_view_insert_column_with_data_func:
-- * @tree_view: a #PsppSheetView
-- * @position: Position to insert, -1 for append
-- * @title: column title
-- * @cell: cell renderer for column
-- * @func: function to set attributes of cell renderer
-- * @data: data for @func
-- * @dnotify: destroy notifier for @data
-- *
-- * Convenience function that inserts a new column into the #PsppSheetView
-- * with the given cell renderer and a #GtkCellDataFunc to set cell renderer
-- * attributes (normally using data from the model). See also
-- * pspp_sheet_view_column_set_cell_data_func(), pspp_sheet_view_column_pack_start().
-- *
-- * Return value: number of columns in the tree view post-insert
-- **/
--gint
--pspp_sheet_view_insert_column_with_data_func  (PsppSheetView               *tree_view,
--                                             gint                       position,
--                                             const gchar               *title,
--                                             GtkCellRenderer           *cell,
--                                             PsppSheetCellDataFunc        func,
--                                             gpointer                   data,
--                                             GDestroyNotify             dnotify)
--{
--  PsppSheetViewColumn *column;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), -1);
--
--  column = pspp_sheet_view_column_new ();
--  pspp_sheet_view_column_set_title (column, title);
--  pspp_sheet_view_column_pack_start (column, cell, TRUE);
--  pspp_sheet_view_column_set_cell_data_func (column, cell, func, data, dnotify);
--
--  pspp_sheet_view_insert_column (tree_view, column, position);
--
--  return tree_view->priv->n_columns;
--}
--
--/**
-- * pspp_sheet_view_get_column:
-- * @tree_view: A #PsppSheetView.
-- * @n: The position of the column, counting from 0.
-- *
-- * Gets the #PsppSheetViewColumn at the given position in the #tree_view.
-- *
-- * Return value: The #PsppSheetViewColumn, or %NULL if the position is outside the
-- * range of columns.
-- **/
--PsppSheetViewColumn *
--pspp_sheet_view_get_column (PsppSheetView *tree_view,
--                        gint         n)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
--
--  if (n < 0 || n >= tree_view->priv->n_columns)
--    return NULL;
--
--  if (tree_view->priv->columns == NULL)
--    return NULL;
--
--  return PSPP_SHEET_VIEW_COLUMN (g_list_nth (tree_view->priv->columns, n)->data);
--}
--
--/**
-- * pspp_sheet_view_get_columns:
-- * @tree_view: A #PsppSheetView
-- *
-- * Returns a #GList of all the #PsppSheetViewColumn s currently in @tree_view.
-- * The returned list must be freed with g_list_free ().
-- *
-- * Return value: (element-type PsppSheetViewColumn) (transfer container): A list of #PsppSheetViewColumn s
-- **/
--GList *
--pspp_sheet_view_get_columns (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
--
--  return g_list_copy (tree_view->priv->columns);
--}
--
--/**
-- * pspp_sheet_view_move_column_after:
-- * @tree_view: A #PsppSheetView
-- * @column: The #PsppSheetViewColumn to be moved.
-- * @base_column: (allow-none): The #PsppSheetViewColumn to be moved relative to, or %NULL.
-- *
-- * Moves @column to be after to @base_column.  If @base_column is %NULL, then
-- * @column is placed in the first position.
-- **/
--void
--pspp_sheet_view_move_column_after (PsppSheetView       *tree_view,
--                               PsppSheetViewColumn *column,
--                               PsppSheetViewColumn *base_column)
--{
--  GList *column_list_el, *base_el = NULL;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  column_list_el = g_list_find (tree_view->priv->columns, column);
--  g_return_if_fail (column_list_el != NULL);
--
--  if (base_column)
--    {
--      base_el = g_list_find (tree_view->priv->columns, base_column);
--      g_return_if_fail (base_el != NULL);
--    }
--
--  if (column_list_el->prev == base_el)
--    return;
--
--  tree_view->priv->columns = g_list_remove_link (tree_view->priv->columns, column_list_el);
--  if (base_el == NULL)
--    {
--      column_list_el->prev = NULL;
--      column_list_el->next = tree_view->priv->columns;
--      if (column_list_el->next)
--      column_list_el->next->prev = column_list_el;
--      tree_view->priv->columns = column_list_el;
--    }
--  else
--    {
--      column_list_el->prev = base_el;
--      column_list_el->next = base_el->next;
--      if (column_list_el->next)
--      column_list_el->next->prev = column_list_el;
--      base_el->next = column_list_el;
--    }
--
--  if (gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    {
--      gtk_widget_queue_resize (GTK_WIDGET (tree_view));
--      pspp_sheet_view_size_allocate_columns (GTK_WIDGET (tree_view), NULL);
--    }
--
--  g_signal_emit (tree_view, tree_view_signals[COLUMNS_CHANGED], 0);
--}
--
--/**
-- * pspp_sheet_view_set_column_drag_function:
-- * @tree_view: A #PsppSheetView.
-- * @func: (allow-none): A function to determine which columns are reorderable, or %NULL.
-- * @user_data: (allow-none): User data to be passed to @func, or %NULL
-- * @destroy: (allow-none): Destroy notifier for @user_data, or %NULL
-- *
-- * Sets a user function for determining where a column may be dropped when
-- * dragged.  This function is called on every column pair in turn at the
-- * beginning of a column drag to determine where a drop can take place.  The
-- * arguments passed to @func are: the @tree_view, the #PsppSheetViewColumn being
-- * dragged, the two #PsppSheetViewColumn s determining the drop spot, and
-- * @user_data.  If either of the #PsppSheetViewColumn arguments for the drop spot
-- * are %NULL, then they indicate an edge.  If @func is set to be %NULL, then
-- * @tree_view reverts to the default behavior of allowing all columns to be
-- * dropped everywhere.
-- **/
--void
--pspp_sheet_view_set_column_drag_function (PsppSheetView               *tree_view,
--                                      PsppSheetViewColumnDropFunc  func,
--                                      gpointer                   user_data,
--                                      GDestroyNotify             destroy)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (tree_view->priv->column_drop_func_data_destroy)
--    tree_view->priv->column_drop_func_data_destroy (tree_view->priv->column_drop_func_data);
--
--  tree_view->priv->column_drop_func = func;
--  tree_view->priv->column_drop_func_data = user_data;
--  tree_view->priv->column_drop_func_data_destroy = destroy;
--}
--
--/**
-- * pspp_sheet_view_scroll_to_point:
-- * @tree_view: a #PsppSheetView
-- * @tree_x: X coordinate of new top-left pixel of visible area, or -1
-- * @tree_y: Y coordinate of new top-left pixel of visible area, or -1
-- *
-- * Scrolls the tree view such that the top-left corner of the visible
-- * area is @tree_x, @tree_y, where @tree_x and @tree_y are specified
-- * in tree coordinates.  The @tree_view must be realized before
-- * this function is called.  If it isn't, you probably want to be
-- * using pspp_sheet_view_scroll_to_cell().
-- *
-- * If either @tree_x or @tree_y are -1, then that direction isn't scrolled.
-- **/
--void
--pspp_sheet_view_scroll_to_point (PsppSheetView *tree_view,
--                               gint         tree_x,
--                               gint         tree_y)
--{
--  GtkAdjustment *hadj;
--  GtkAdjustment *vadj;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (tree_view)));
--
--  hadj = tree_view->priv->hadjustment;
--  vadj = tree_view->priv->vadjustment;
--
--  if (tree_x != -1)
--    gtk_adjustment_set_value (hadj, CLAMP (tree_x, gtk_adjustment_get_lower (hadj), gtk_adjustment_get_upper (hadj) - gtk_adjustment_get_page_size (hadj)));
--  if (tree_y != -1)
--    gtk_adjustment_set_value (vadj, CLAMP (tree_y, gtk_adjustment_get_lower (vadj), gtk_adjustment_get_upper (vadj) - gtk_adjustment_get_page_size (vadj)));
--}
--
--/**
-- * pspp_sheet_view_scroll_to_cell:
-- * @tree_view: A #PsppSheetView.
-- * @path: (allow-none): The path of the row to move to, or %NULL.
-- * @column: (allow-none): The #PsppSheetViewColumn to move horizontally to, or %NULL.
-- * @use_align: whether to use alignment arguments, or %FALSE.
-- * @row_align: The vertical alignment of the row specified by @path.
-- * @col_align: The horizontal alignment of the column specified by @column.
-- *
-- * Moves the alignments of @tree_view to the position specified by @column and
-- * @path.  If @column is %NULL, then no horizontal scrolling occurs.  Likewise,
-- * if @path is %NULL no vertical scrolling occurs.  At a minimum, one of @column
-- * or @path need to be non-%NULL.  @row_align determines where the row is
-- * placed, and @col_align determines where @column is placed.  Both are expected
-- * to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0 means
-- * right/bottom alignment, 0.5 means center.
-- *
-- * If @use_align is %FALSE, then the alignment arguments are ignored, and the
-- * tree does the minimum amount of work to scroll the cell onto the screen.
-- * This means that the cell will be scrolled to the edge closest to its current
-- * position.  If the cell is currently visible on the screen, nothing is done.
-- *
-- * This function only works if the model is set, and @path is a valid row on the
-- * model.  If the model changes before the @tree_view is realized, the centered
-- * path will be modified to reflect this change.
-- **/
--void
--pspp_sheet_view_scroll_to_cell (PsppSheetView       *tree_view,
--                              GtkTreePath       *path,
--                              PsppSheetViewColumn *column,
--                            gboolean           use_align,
--                              gfloat             row_align,
--                              gfloat             col_align)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (tree_view->priv->model != NULL);
--  g_return_if_fail (row_align >= 0.0 && row_align <= 1.0);
--  g_return_if_fail (col_align >= 0.0 && col_align <= 1.0);
--  g_return_if_fail (path != NULL || column != NULL);
--
--#if 0
--  g_print ("pspp_sheet_view_scroll_to_cell:\npath: %s\ncolumn: %s\nuse_align: %d\nrow_align: %f\ncol_align: %f\n",
--         gtk_tree_path_to_string (path), column?"non-null":"null", use_align, row_align, col_align);
--#endif
--  row_align = CLAMP (row_align, 0.0, 1.0);
--  col_align = CLAMP (col_align, 0.0, 1.0);
--
--
--  /* Note: Despite the benefits that come from having one code path for the
--   * scrolling code, we short-circuit validate_visible_area's immplementation as
--   * it is much slower than just going to the point.
--   */
--  if (!gtk_widget_get_visible (GTK_WIDGET (tree_view)) ||
--      !gtk_widget_get_realized (GTK_WIDGET (tree_view))
--      /* XXX || GTK_WIDGET_ALLOC_NEEDED (tree_view) */)
--    {
--      if (tree_view->priv->scroll_to_path)
--      gtk_tree_row_reference_free (tree_view->priv->scroll_to_path);
--
--      tree_view->priv->scroll_to_path = NULL;
--      tree_view->priv->scroll_to_column = NULL;
--
--      if (path)
--      tree_view->priv->scroll_to_path = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
--      if (column)
--      tree_view->priv->scroll_to_column = column;
--      tree_view->priv->scroll_to_use_align = use_align;
--      tree_view->priv->scroll_to_row_align = row_align;
--      tree_view->priv->scroll_to_col_align = col_align;
--
--      install_presize_handler (tree_view);
--    }
--  else
--    {
--      GdkRectangle cell_rect;
--      GdkRectangle vis_rect;
--      gint dest_x, dest_y;
--
--      pspp_sheet_view_get_background_area (tree_view, path, column, &cell_rect);
--      pspp_sheet_view_get_visible_rect (tree_view, &vis_rect);
--
--      cell_rect.y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, cell_rect.y);
--
--      dest_x = vis_rect.x;
--      dest_y = vis_rect.y;
--
--      if (column)
--      {
--        if (use_align)
--          {
--            dest_x = cell_rect.x - ((vis_rect.width - cell_rect.width) * col_align);
--          }
--        else
--          {
--            if (cell_rect.x < vis_rect.x)
--              dest_x = cell_rect.x;
--            if (cell_rect.x + cell_rect.width > vis_rect.x + vis_rect.width)
--              dest_x = cell_rect.x + cell_rect.width - vis_rect.width;
--          }
--      }
--
--      if (path)
--      {
--        if (use_align)
--          {
--            dest_y = cell_rect.y - ((vis_rect.height - cell_rect.height) * row_align);
--            dest_y = MAX (dest_y, 0);
--          }
--        else
--          {
--            if (cell_rect.y < vis_rect.y)
--              dest_y = cell_rect.y;
--            if (cell_rect.y + cell_rect.height > vis_rect.y + vis_rect.height)
--              dest_y = cell_rect.y + cell_rect.height - vis_rect.height;
--          }
--      }
--
--      pspp_sheet_view_scroll_to_point (tree_view, dest_x, dest_y);
--    }
--}
--
--/**
-- * pspp_sheet_view_row_activated:
-- * @tree_view: A #PsppSheetView
-- * @path: The #GtkTreePath to be activated.
-- * @column: The #PsppSheetViewColumn to be activated.
-- *
-- * Activates the cell determined by @path and @column.
-- **/
--void
--pspp_sheet_view_row_activated (PsppSheetView       *tree_view,
--                           GtkTreePath       *path,
--                           PsppSheetViewColumn *column)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  g_signal_emit (tree_view, tree_view_signals[ROW_ACTIVATED], 0, path, column);
--}
--
--
--/**
-- * pspp_sheet_view_get_reorderable:
-- * @tree_view: a #PsppSheetView
-- *
-- * Retrieves whether the user can reorder the tree via drag-and-drop. See
-- * pspp_sheet_view_set_reorderable().
-- *
-- * Return value: %TRUE if the tree can be reordered.
-- **/
--gboolean
--pspp_sheet_view_get_reorderable (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
--
--  return tree_view->priv->reorderable;
--}
--
--/**
-- * pspp_sheet_view_set_reorderable:
-- * @tree_view: A #PsppSheetView.
-- * @reorderable: %TRUE, if the tree can be reordered.
-- *
-- * This function is a convenience function to allow you to reorder
-- * models that support the #GtkDragSourceIface and the
-- * #GtkDragDestIface.  Both #GtkTreeStore and #GtkListStore support
-- * these.  If @reorderable is %TRUE, then the user can reorder the
-- * model by dragging and dropping rows. The developer can listen to
-- * these changes by connecting to the model's row_inserted and
-- * row_deleted signals. The reordering is implemented by setting up
-- * the tree view as a drag source and destination. Therefore, drag and
-- * drop can not be used in a reorderable view for any other purpose.
-- *
-- * This function does not give you any degree of control over the order -- any
-- * reordering is allowed.  If more control is needed, you should probably
-- * handle drag and drop manually.
-- **/
--void
--pspp_sheet_view_set_reorderable (PsppSheetView *tree_view,
--                             gboolean     reorderable)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  reorderable = reorderable != FALSE;
--
--  if (tree_view->priv->reorderable == reorderable)
--    return;
--
--  if (reorderable)
--    {
--      const GtkTargetEntry row_targets[] = {
--        { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
--      };
--
--      pspp_sheet_view_enable_model_drag_source (tree_view,
--                                            GDK_BUTTON1_MASK,
--                                            row_targets,
--                                            G_N_ELEMENTS (row_targets),
--                                            GDK_ACTION_MOVE);
--      pspp_sheet_view_enable_model_drag_dest (tree_view,
--                                          row_targets,
--                                          G_N_ELEMENTS (row_targets),
--                                          GDK_ACTION_MOVE);
--    }
--  else
--    {
--      pspp_sheet_view_unset_rows_drag_source (tree_view);
--      pspp_sheet_view_unset_rows_drag_dest (tree_view);
--    }
--
--  tree_view->priv->reorderable = reorderable;
--
--  g_object_notify (G_OBJECT (tree_view), "reorderable");
--}
--
--/* If CLEAR_AND_SELECT is true, then the row will be selected and, unless Shift
--   is pressed, other rows will be unselected.
--
--   If CLAMP_NODE is true, then the sheetview will scroll to make the row
--   visible. */
--static void
--pspp_sheet_view_real_set_cursor (PsppSheetView     *tree_view,
--                             GtkTreePath     *path,
--                             gboolean         clear_and_select,
--                               gboolean         clamp_node,
--                               PsppSheetSelectMode mode)
--{
--  int node = -1;
--
--  if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
--    {
--      GtkTreePath *cursor_path;
--      cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--      pspp_sheet_view_queue_draw_path (tree_view, cursor_path, NULL);
--      gtk_tree_path_free (cursor_path);
--    }
--
--  gtk_tree_row_reference_free (tree_view->priv->cursor);
--  tree_view->priv->cursor = NULL;
--
--  _pspp_sheet_view_find_node (tree_view, path, &node);
--  tree_view->priv->cursor =
--    gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
--                                      tree_view->priv->model,
--                                      path);
--
--  if (tree_view->priv->row_count > 0)
--    {
--      int new_node = -1;
--
--      if (clear_and_select && !(mode & PSPP_SHEET_SELECT_MODE_TOGGLE))
--        _pspp_sheet_selection_internal_select_node (tree_view->priv->selection,
--                                                    node, path, mode,
--                                                    FALSE);
--
--      /* We have to re-find tree and node here again, somebody might have
--       * cleared the node or the whole tree in the PsppSheetSelection::changed
--       * callback. If the nodes differ we bail out here.
--       */
--      _pspp_sheet_view_find_node (tree_view, path, &new_node);
--
--      if (node != new_node)
--        return;
--
--      if (clamp_node)
--        {
--        pspp_sheet_view_clamp_node_visible (tree_view, node);
--        _pspp_sheet_view_queue_draw_node (tree_view, node, NULL);
--      }
--    }
--
--  g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
--}
--
--/**
-- * pspp_sheet_view_get_cursor:
-- * @tree_view: A #PsppSheetView
-- * @path: (allow-none): A pointer to be filled with the current cursor path, or %NULL
-- * @focus_column: (allow-none): A pointer to be filled with the current focus column, or %NULL
-- *
-- * Fills in @path and @focus_column with the current path and focus column.  If
-- * the cursor isn't currently set, then *@path will be %NULL.  If no column
-- * currently has focus, then *@focus_column will be %NULL.
-- *
-- * The returned #GtkTreePath must be freed with gtk_tree_path_free() when
-- * you are done with it.
-- **/
--void
--pspp_sheet_view_get_cursor (PsppSheetView        *tree_view,
--                        GtkTreePath       **path,
--                        PsppSheetViewColumn **focus_column)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (path)
--    {
--      if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
--      *path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--      else
--      *path = NULL;
--    }
--
--  if (focus_column)
--    {
--      *focus_column = tree_view->priv->focus_column;
--    }
--}
--
--/**
-- * pspp_sheet_view_set_cursor:
-- * @tree_view: A #PsppSheetView
-- * @path: A #GtkTreePath
-- * @focus_column: (allow-none): A #PsppSheetViewColumn, or %NULL
-- * @start_editing: %TRUE if the specified cell should start being edited.
-- *
-- * Sets the current keyboard focus to be at @path, and selects it.  This is
-- * useful when you want to focus the user's attention on a particular row.  If
-- * @focus_column is not %NULL, then focus is given to the column specified by 
-- * it. Additionally, if @focus_column is specified, and @start_editing is 
-- * %TRUE, then editing should be started in the specified cell.  
-- * This function is often followed by @gtk_widget_grab_focus (@tree_view) 
-- * in order to give keyboard focus to the widget.  Please note that editing 
-- * can only happen when the widget is realized.
-- *
-- * If @path is invalid for @model, the current cursor (if any) will be unset
-- * and the function will return without failing.
-- **/
--void
--pspp_sheet_view_set_cursor (PsppSheetView       *tree_view,
--                        GtkTreePath       *path,
--                        PsppSheetViewColumn *focus_column,
--                        gboolean           start_editing)
--{
--  pspp_sheet_view_set_cursor_on_cell (tree_view, path, focus_column,
--                                  NULL, start_editing);
--}
--
--/**
-- * pspp_sheet_view_set_cursor_on_cell:
-- * @tree_view: A #PsppSheetView
-- * @path: A #GtkTreePath
-- * @focus_column: (allow-none): A #PsppSheetViewColumn, or %NULL
-- * @focus_cell: (allow-none): A #GtkCellRenderer, or %NULL
-- * @start_editing: %TRUE if the specified cell should start being edited.
-- *
-- * Sets the current keyboard focus to be at @path, and selects it.  This is
-- * useful when you want to focus the user's attention on a particular row.  If
-- * @focus_column is not %NULL, then focus is given to the column specified by
-- * it. If @focus_column and @focus_cell are not %NULL, and @focus_column
-- * contains 2 or more editable or activatable cells, then focus is given to
-- * the cell specified by @focus_cell. Additionally, if @focus_column is
-- * specified, and @start_editing is %TRUE, then editing should be started in
-- * the specified cell.  This function is often followed by
-- * @gtk_widget_grab_focus (@tree_view) in order to give keyboard focus to the
-- * widget.  Please note that editing can only happen when the widget is
-- * realized.
-- *
-- * If @path is invalid for @model, the current cursor (if any) will be unset
-- * and the function will return without failing.
-- *
-- * Since: 2.2
-- **/
--void
--pspp_sheet_view_set_cursor_on_cell (PsppSheetView       *tree_view,
--                                GtkTreePath       *path,
--                                PsppSheetViewColumn *focus_column,
--                                GtkCellRenderer   *focus_cell,
--                                gboolean           start_editing)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (path != NULL);
--  g_return_if_fail (focus_column == NULL || PSPP_IS_SHEET_VIEW_COLUMN (focus_column));
--
--  if (!tree_view->priv->model)
--    return;
--
--  if (focus_cell)
--    {
--      g_return_if_fail (focus_column);
--      g_return_if_fail (GTK_IS_CELL_RENDERER (focus_cell));
--    }
--
--  /* cancel the current editing, if it exists */
--  if (tree_view->priv->edited_column &&
--      tree_view->priv->edited_column->editable_widget)
--    pspp_sheet_view_stop_editing (tree_view, TRUE);
--
--  pspp_sheet_view_real_set_cursor (tree_view, path, TRUE, TRUE, 0);
--
--  if (focus_column && focus_column->visible)
--    {
--      GList *list;
--      gboolean column_in_tree = FALSE;
--
--      for (list = tree_view->priv->columns; list; list = list->next)
--      if (list->data == focus_column)
--        {
--          column_in_tree = TRUE;
--          break;
--        }
--      g_return_if_fail (column_in_tree);
--      tree_view->priv->focus_column = focus_column;
--      if (focus_cell)
--      pspp_sheet_view_column_focus_cell (focus_column, focus_cell);
--      if (start_editing)
--      pspp_sheet_view_start_editing (tree_view, path);
--
--      pspp_sheet_selection_unselect_all_columns (tree_view->priv->selection);
--      pspp_sheet_selection_select_column (tree_view->priv->selection, focus_column);
--
--    }
--}
--
--/**
-- * pspp_sheet_view_get_bin_window:
-- * @tree_view: A #PsppSheetView
-- * 
-- * Returns the window that @tree_view renders to.  This is used primarily to
-- * compare to <literal>event->window</literal> to confirm that the event on
-- * @tree_view is on the right window.
-- * 
-- * Return value: A #GdkWindow, or %NULL when @tree_view hasn't been realized yet
-- **/
--GdkWindow *
--pspp_sheet_view_get_bin_window (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
--
--  return tree_view->priv->bin_window;
--}
--
--/**
-- * pspp_sheet_view_get_path_at_pos:
-- * @tree_view: A #PsppSheetView.
-- * @x: The x position to be identified (relative to bin_window).
-- * @y: The y position to be identified (relative to bin_window).
-- * @path: (out) (allow-none): A pointer to a #GtkTreePath pointer to be filled in, or %NULL
-- * @column: (out) (allow-none): A pointer to a #PsppSheetViewColumn pointer to be filled in, or %NULL
-- * @cell_x: (out) (allow-none): A pointer where the X coordinate relative to the cell can be placed, or %NULL
-- * @cell_y: (out) (allow-none): A pointer where the Y coordinate relative to the cell can be placed, or %NULL
-- *
-- * Finds the path at the point (@x, @y), relative to bin_window coordinates
-- * (please see pspp_sheet_view_get_bin_window()).
-- * That is, @x and @y are relative to an events coordinates. @x and @y must
-- * come from an event on the @tree_view only where <literal>event->window ==
-- * pspp_sheet_view_get_bin_window (<!-- -->)</literal>. It is primarily for
-- * things like popup menus. If @path is non-%NULL, then it will be filled
-- * with the #GtkTreePath at that point.  This path should be freed with
-- * gtk_tree_path_free().  If @column is non-%NULL, then it will be filled
-- * with the column at that point.  @cell_x and @cell_y return the coordinates
-- * relative to the cell background (i.e. the @background_area passed to
-- * gtk_cell_renderer_render()).  This function is only meaningful if
-- * @tree_view is realized.  Therefore this function will always return %FALSE
-- * if @tree_view is not realized or does not have a model.
-- *
-- * For converting widget coordinates (eg. the ones you get from
-- * GtkWidget::query-tooltip), please see
-- * pspp_sheet_view_convert_widget_to_bin_window_coords().
-- *
-- * Return value: %TRUE if a row exists at that coordinate.
-- **/
--gboolean
--pspp_sheet_view_get_path_at_pos (PsppSheetView        *tree_view,
--                             gint                x,
--                             gint                y,
--                             GtkTreePath       **path,
--                             PsppSheetViewColumn **column,
--                               gint               *cell_x,
--                               gint               *cell_y)
--{
--  int node;
--  gint y_offset;
--
--  g_return_val_if_fail (tree_view != NULL, FALSE);
--
--  if (path)
--    *path = NULL;
--  if (column)
--    *column = NULL;
--
--  if (tree_view->priv->bin_window == NULL)
--    return FALSE;
--
--  if (tree_view->priv->row_count == 0)
--    return FALSE;
--
--  if (x > gtk_adjustment_get_upper (tree_view->priv->hadjustment))
--    return FALSE;
--
--  if (x < 0 || y < 0)
--    return FALSE;
--
--  if (column || cell_x)
--    {
--      PsppSheetViewColumn *tmp_column;
--      PsppSheetViewColumn *last_column = NULL;
--      GList *list;
--      gint remaining_x = x;
--      gboolean found = FALSE;
--      gboolean rtl;
--
--      rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
--      for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
--         list;
--         list = (rtl ? list->prev : list->next))
--      {
--        tmp_column = list->data;
--
--        if (tmp_column->visible == FALSE)
--          continue;
--
--        last_column = tmp_column;
--        if (remaining_x <= tmp_column->width)
--          {
--              found = TRUE;
--
--              if (column)
--                *column = tmp_column;
--
--              if (cell_x)
--                *cell_x = remaining_x;
--
--            break;
--          }
--        remaining_x -= tmp_column->width;
--      }
--
--      /* If found is FALSE and there is a last_column, then it the remainder
--       * space is in that area
--       */
--      if (!found)
--        {
--        if (last_column)
--          {
--            if (column)
--              *column = last_column;
--            
--            if (cell_x)
--              *cell_x = last_column->width + remaining_x;
--          }
--        else
--          {
--            return FALSE;
--          }
--      }
--    }
--
--  y_offset = pspp_sheet_view_find_offset (tree_view,
--                                          TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y),
--                                          &node);
--
--  if (node < 0)
--    return FALSE;
--
--  if (cell_y)
--    *cell_y = y_offset;
--
--  if (path)
--    *path = _pspp_sheet_view_find_path (tree_view, node);
--
--  return TRUE;
--}
--
--/* Computes 'cell_area' from 'background_area', which must be the background
--   area for a cell.  Set 'subtract_focus_rect' to TRUE to compute the cell area
--   as passed to a GtkCellRenderer's "render" function, or to FALSE to compute
--   the cell area as passed to _pspp_sheet_view_column_cell_render().
--
--   'column' is required to properly adjust 'cell_area->x' and
--   'cell_area->width'.  It may be set to NULL if these values are not of
--   interest.  In this case 'cell_area->x' and 'cell_area->width' will be
--   returned as 0. */
--static void
--pspp_sheet_view_adjust_cell_area (PsppSheetView        *tree_view,
--                                  PsppSheetViewColumn  *column,
--                                  const GdkRectangle   *background_area,
--                                  gboolean              subtract_focus_rect,
--                                  GdkRectangle         *cell_area)
--{
--  gint vertical_separator;
--  gint horizontal_separator;
--
--  *cell_area = *background_area;
--
--  gtk_widget_style_get (GTK_WIDGET (tree_view),
--                      "vertical-separator", &vertical_separator,
--                      "horizontal-separator", &horizontal_separator,
--                      NULL);
--  cell_area->x += horizontal_separator / 2;
--  cell_area->y += vertical_separator / 2;
--  cell_area->width -= horizontal_separator;
--  cell_area->height -= vertical_separator;
--
--  if (subtract_focus_rect)
--    {
--      int focus_line_width;
--
--      gtk_widget_style_get (GTK_WIDGET (tree_view),
--                            "focus-line-width", &focus_line_width,
--                            NULL);
--      cell_area->x += focus_line_width;
--      cell_area->y += focus_line_width;
--      cell_area->width -= 2 * focus_line_width;
--      cell_area->height -= 2 * focus_line_width;
--    }
--
--  if (tree_view->priv->grid_lines != PSPP_SHEET_VIEW_GRID_LINES_NONE)
--    {
--      gint grid_line_width;
--      gtk_widget_style_get (GTK_WIDGET (tree_view),
--                            "grid-line-width", &grid_line_width,
--                            NULL);
--
--      if ((tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_VERTICAL
--           || tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_BOTH)
--          && column != NULL)
--        {
--          PsppSheetViewColumn *first_column, *last_column;
--          GList *list;
--
--          /* Find the last visible column. */
--          last_column = NULL;
--          for (list = g_list_last (tree_view->priv->columns);
--               list;
--               list = list->prev)
--            {
--              PsppSheetViewColumn *c = list->data;
--              if (c->visible)
--                {
--                  last_column = c;
--                  break;
--                }
--            }
--
--          /* Find the first visible column. */
--          first_column = NULL;
--          for (list = g_list_first (tree_view->priv->columns);
--               list;
--               list = list->next)
--            {
--              PsppSheetViewColumn *c = list->data;
--              if (c->visible)
--                {
--                  first_column = c;
--                  break;
--                }
--            }
--
--          if (column == first_column)
--            {
--              cell_area->width -= grid_line_width / 2;
--            }
--          else if (column == last_column)
--            {
--              cell_area->x += grid_line_width / 2;
--              cell_area->width -= grid_line_width / 2;
--            }
--          else
--            {
--              cell_area->x += grid_line_width / 2;
--              cell_area->width -= grid_line_width;
--            }
--        }
--
--      if (tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_HORIZONTAL
--          || tree_view->priv->grid_lines == PSPP_SHEET_VIEW_GRID_LINES_BOTH)
--        {
--          cell_area->y += grid_line_width / 2;
--          cell_area->height -= grid_line_width;
--        }
--    }
--
--  if (column == NULL)
--    {
--      cell_area->x = 0;
--      cell_area->width = 0;
--    }
--}
--
--/**
-- * pspp_sheet_view_get_cell_area:
-- * @tree_view: a #PsppSheetView
-- * @path: (allow-none): a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
-- * @column: (allow-none): a #PsppSheetViewColumn for the column, or %NULL to get only vertical coordinates
-- * @rect: rectangle to fill with cell rect
-- *
-- * Fills the bounding rectangle in bin_window coordinates for the cell at the
-- * row specified by @path and the column specified by @column.  If @path is
-- * %NULL, or points to a path not currently displayed, the @y and @height fields
-- * of the rectangle will be filled with 0. If @column is %NULL, the @x and @width
-- * fields will be filled with 0.  The sum of all cell rects does not cover the
-- * entire tree; there are extra pixels in between rows, for example. The
-- * returned rectangle is equivalent to the @cell_area passed to
-- * gtk_cell_renderer_render().  This function is only valid if @tree_view is
-- * realized.
-- **/
--void
--pspp_sheet_view_get_cell_area (PsppSheetView        *tree_view,
--                             GtkTreePath        *path,
--                             PsppSheetViewColumn  *column,
--                             GdkRectangle       *rect)
--{
--  GdkRectangle background_area;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (column == NULL || PSPP_IS_SHEET_VIEW_COLUMN (column));
--  g_return_if_fail (rect != NULL);
--  g_return_if_fail (!column || column->tree_view == (GtkWidget *) tree_view);
--  g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (tree_view)));
--
--  pspp_sheet_view_get_background_area (tree_view, path, column,
--                                       &background_area);
--  pspp_sheet_view_adjust_cell_area (tree_view, column, &background_area,
--                                    FALSE, rect);
--}
--
--/**
-- * pspp_sheet_view_get_background_area:
-- * @tree_view: a #PsppSheetView
-- * @path: (allow-none): a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
-- * @column: (allow-none): a #PsppSheetViewColumn for the column, or %NULL to get only vertical coordiantes
-- * @rect: rectangle to fill with cell background rect
-- *
-- * Fills the bounding rectangle in bin_window coordinates for the cell at the
-- * row specified by @path and the column specified by @column.  If @path is
-- * %NULL, or points to a node not found in the tree, the @y and @height fields of
-- * the rectangle will be filled with 0. If @column is %NULL, the @x and @width
-- * fields will be filled with 0.  The returned rectangle is equivalent to the
-- * @background_area passed to gtk_cell_renderer_render().  These background
-- * areas tile to cover the entire bin window.  Contrast with the @cell_area,
-- * returned by pspp_sheet_view_get_cell_area(), which returns only the cell
-- * itself, excluding surrounding borders.
-- *
-- **/
--void
--pspp_sheet_view_get_background_area (PsppSheetView        *tree_view,
--                                   GtkTreePath        *path,
--                                   PsppSheetViewColumn  *column,
--                                   GdkRectangle       *rect)
--{
--  int node = -1;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (column == NULL || PSPP_IS_SHEET_VIEW_COLUMN (column));
--  g_return_if_fail (rect != NULL);
--
--  rect->x = 0;
--  rect->y = 0;
--  rect->width = 0;
--  rect->height = 0;
--
--  if (path)
--    {
--      /* Get vertical coords */
--
--      _pspp_sheet_view_find_node (tree_view, path, &node);
--      if (node < 0)
--      return;
--
--      rect->y = BACKGROUND_FIRST_PIXEL (tree_view, node);
--
--      rect->height = ROW_HEIGHT (tree_view);
--    }
--
--  if (column)
--    {
--      gint x2 = 0;
--
--      pspp_sheet_view_get_background_xrange (tree_view, column, &rect->x, &x2);
--      rect->width = x2 - rect->x;
--    }
--}
--
--/**
-- * pspp_sheet_view_get_visible_rect:
-- * @tree_view: a #PsppSheetView
-- * @visible_rect: rectangle to fill
-- *
-- * Fills @visible_rect with the currently-visible region of the
-- * buffer, in tree coordinates. Convert to bin_window coordinates with
-- * pspp_sheet_view_convert_tree_to_bin_window_coords().
-- * Tree coordinates start at 0,0 for row 0 of the tree, and cover the entire
-- * scrollable area of the tree.
-- **/
--void
--pspp_sheet_view_get_visible_rect (PsppSheetView  *tree_view,
--                                GdkRectangle *visible_rect)
--{
--  GtkWidget *widget;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  widget = GTK_WIDGET (tree_view);
--
--  if (visible_rect)
--    {
--      GtkAllocation allocation;
--      gtk_widget_get_allocation (widget, &allocation);
--      visible_rect->x = gtk_adjustment_get_value (tree_view->priv->hadjustment);
--      visible_rect->y = gtk_adjustment_get_value (tree_view->priv->vadjustment);
--      visible_rect->width  = allocation.width;
--      visible_rect->height = allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
--    }
--}
--
--/**
-- * pspp_sheet_view_widget_to_tree_coords:
-- * @tree_view: a #PsppSheetView
-- * @wx: X coordinate relative to bin_window
-- * @wy: Y coordinate relative to bin_window
-- * @tx: return location for tree X coordinate
-- * @ty: return location for tree Y coordinate
-- *
-- * Converts bin_window coordinates to coordinates for the
-- * tree (the full scrollable area of the tree).
-- *
-- * Deprecated: 2.12: Due to historial reasons the name of this function is
-- * incorrect.  For converting coordinates relative to the widget to
-- * bin_window coordinates, please see
-- * pspp_sheet_view_convert_widget_to_bin_window_coords().
-- *
-- **/
--void
--pspp_sheet_view_widget_to_tree_coords (PsppSheetView *tree_view,
--                                    gint         wx,
--                                    gint         wy,
--                                    gint        *tx,
--                                    gint        *ty)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (tx)
--    *tx = wx + gtk_adjustment_get_value (tree_view->priv->hadjustment);
--  if (ty)
--    *ty = wy + tree_view->priv->dy;
--}
--
--/**
-- * pspp_sheet_view_tree_to_widget_coords:
-- * @tree_view: a #PsppSheetView
-- * @tx: tree X coordinate
-- * @ty: tree Y coordinate
-- * @wx: return location for X coordinate relative to bin_window
-- * @wy: return location for Y coordinate relative to bin_window
-- *
-- * Converts tree coordinates (coordinates in full scrollable area of the tree)
-- * to bin_window coordinates.
-- *
-- * Deprecated: 2.12: Due to historial reasons the name of this function is
-- * incorrect.  For converting bin_window coordinates to coordinates relative
-- * to bin_window, please see
-- * pspp_sheet_view_convert_bin_window_to_widget_coords().
-- *
-- **/
--void
--pspp_sheet_view_tree_to_widget_coords (PsppSheetView *tree_view,
--                                     gint         tx,
--                                     gint         ty,
--                                     gint        *wx,
--                                     gint        *wy)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (wx)
--    *wx = tx - gtk_adjustment_get_value (tree_view->priv->hadjustment);
--  if (wy)
--    *wy = ty - tree_view->priv->dy;
--}
--
--
--/**
-- * pspp_sheet_view_convert_widget_to_tree_coords:
-- * @tree_view: a #PsppSheetView
-- * @wx: X coordinate relative to the widget
-- * @wy: Y coordinate relative to the widget
-- * @tx: return location for tree X coordinate
-- * @ty: return location for tree Y coordinate
-- *
-- * Converts widget coordinates to coordinates for the
-- * tree (the full scrollable area of the tree).
-- *
-- * Since: 2.12
-- **/
--void
--pspp_sheet_view_convert_widget_to_tree_coords (PsppSheetView *tree_view,
--                                             gint         wx,
--                                             gint         wy,
--                                             gint        *tx,
--                                             gint        *ty)
--{
--  gint x, y;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  pspp_sheet_view_convert_widget_to_bin_window_coords (tree_view,
--                                                   wx, wy,
--                                                   &x, &y);
--  pspp_sheet_view_convert_bin_window_to_tree_coords (tree_view,
--                                                 x, y,
--                                                 tx, ty);
--}
--
--/**
-- * pspp_sheet_view_convert_tree_to_widget_coords:
-- * @tree_view: a #PsppSheetView
-- * @tx: X coordinate relative to the tree
-- * @ty: Y coordinate relative to the tree
-- * @wx: return location for widget X coordinate
-- * @wy: return location for widget Y coordinate
-- *
-- * Converts tree coordinates (coordinates in full scrollable area of the tree)
-- * to widget coordinates.
-- *
-- * Since: 2.12
-- **/
--void
--pspp_sheet_view_convert_tree_to_widget_coords (PsppSheetView *tree_view,
--                                             gint         tx,
--                                             gint         ty,
--                                             gint        *wx,
--                                             gint        *wy)
--{
--  gint x, y;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  pspp_sheet_view_convert_tree_to_bin_window_coords (tree_view,
--                                                 tx, ty,
--                                                 &x, &y);
--  pspp_sheet_view_convert_bin_window_to_widget_coords (tree_view,
--                                                   x, y,
--                                                   wx, wy);
--}
--
--/**
-- * pspp_sheet_view_convert_widget_to_bin_window_coords:
-- * @tree_view: a #PsppSheetView
-- * @wx: X coordinate relative to the widget
-- * @wy: Y coordinate relative to the widget
-- * @bx: return location for bin_window X coordinate
-- * @by: return location for bin_window Y coordinate
-- *
-- * Converts widget coordinates to coordinates for the bin_window
-- * (see pspp_sheet_view_get_bin_window()).
-- *
-- * Since: 2.12
-- **/
--void
--pspp_sheet_view_convert_widget_to_bin_window_coords (PsppSheetView *tree_view,
--                                                   gint         wx,
--                                                   gint         wy,
--                                                   gint        *bx,
--                                                   gint        *by)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (bx)
--    *bx = wx + gtk_adjustment_get_value (tree_view->priv->hadjustment);
--  if (by)
--    *by = wy - TREE_VIEW_HEADER_HEIGHT (tree_view);
--}
--
--/**
-- * pspp_sheet_view_convert_bin_window_to_widget_coords:
-- * @tree_view: a #PsppSheetView
-- * @bx: bin_window X coordinate
-- * @by: bin_window Y coordinate
-- * @wx: return location for widget X coordinate
-- * @wy: return location for widget Y coordinate
-- *
-- * Converts bin_window coordinates (see pspp_sheet_view_get_bin_window())
-- * to widget relative coordinates.
-- *
-- * Since: 2.12
-- **/
--void
--pspp_sheet_view_convert_bin_window_to_widget_coords (PsppSheetView *tree_view,
--                                                   gint         bx,
--                                                   gint         by,
--                                                   gint        *wx,
--                                                   gint        *wy)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (wx)
--    *wx = bx - gtk_adjustment_get_value (tree_view->priv->hadjustment);
--  if (wy)
--    *wy = by + TREE_VIEW_HEADER_HEIGHT (tree_view);
--}
--
--/**
-- * pspp_sheet_view_convert_tree_to_bin_window_coords:
-- * @tree_view: a #PsppSheetView
-- * @tx: tree X coordinate
-- * @ty: tree Y coordinate
-- * @bx: return location for X coordinate relative to bin_window
-- * @by: return location for Y coordinate relative to bin_window
-- *
-- * Converts tree coordinates (coordinates in full scrollable area of the tree)
-- * to bin_window coordinates.
-- *
-- * Since: 2.12
-- **/
--void
--pspp_sheet_view_convert_tree_to_bin_window_coords (PsppSheetView *tree_view,
--                                                 gint         tx,
--                                                 gint         ty,
--                                                 gint        *bx,
--                                                 gint        *by)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (bx)
--    *bx = tx;
--  if (by)
--    *by = ty - tree_view->priv->dy;
--}
--
--/**
-- * pspp_sheet_view_convert_bin_window_to_tree_coords:
-- * @tree_view: a #PsppSheetView
-- * @bx: X coordinate relative to bin_window
-- * @by: Y coordinate relative to bin_window
-- * @tx: return location for tree X coordinate
-- * @ty: return location for tree Y coordinate
-- *
-- * Converts bin_window coordinates to coordinates for the
-- * tree (the full scrollable area of the tree).
-- *
-- * Since: 2.12
-- **/
--void
--pspp_sheet_view_convert_bin_window_to_tree_coords (PsppSheetView *tree_view,
--                                                 gint         bx,
--                                                 gint         by,
--                                                 gint        *tx,
--                                                 gint        *ty)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (tx)
--    *tx = bx;
--  if (ty)
--    *ty = by + tree_view->priv->dy;
--}
--
--
--
--/**
-- * pspp_sheet_view_get_visible_range:
-- * @tree_view: A #PsppSheetView
-- * @start_path: (allow-none): Return location for start of region, or %NULL.
-- * @end_path: (allow-none): Return location for end of region, or %NULL.
-- *
-- * Sets @start_path and @end_path to be the first and last visible path.
-- * Note that there may be invisible paths in between.
-- *
-- * The paths should be freed with gtk_tree_path_free() after use.
-- *
-- * Returns: %TRUE, if valid paths were placed in @start_path and @end_path.
-- *
-- * Since: 2.8
-- **/
--gboolean
--pspp_sheet_view_get_visible_range (PsppSheetView  *tree_view,
--                                 GtkTreePath **start_path,
--                                 GtkTreePath **end_path)
--{
--  int node;
--  gboolean retval;
--  
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
--
--  if (!tree_view->priv->row_count)
--    return FALSE;
--
--  retval = TRUE;
--
--  if (start_path)
--    {
--      pspp_sheet_view_find_offset (tree_view,
--                                   TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, 0),
--                                   &node);
--      if (node >= 0)
--        *start_path = _pspp_sheet_view_find_path (tree_view, node);
--      else
--        retval = FALSE;
--    }
--
--  if (end_path)
--    {
--      gint y;
--
--      if (tree_view->priv->height < gtk_adjustment_get_page_size (tree_view->priv->vadjustment))
--        y = tree_view->priv->height - 1;
--      else
--        y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, gtk_adjustment_get_page_size (tree_view->priv->vadjustment)) - 1;
--
--      pspp_sheet_view_find_offset (tree_view, y, &node);
--      if (node >= 0)
--        *end_path = _pspp_sheet_view_find_path (tree_view, node);
--      else
--        retval = FALSE;
--    }
--
--  return retval;
--}
--
--static void
--unset_reorderable (PsppSheetView *tree_view)
--{
--  if (tree_view->priv->reorderable)
--    {
--      tree_view->priv->reorderable = FALSE;
--      g_object_notify (G_OBJECT (tree_view), "reorderable");
--    }
--}
--
--/**
-- * pspp_sheet_view_enable_model_drag_source:
-- * @tree_view: a #PsppSheetView
-- * @start_button_mask: Mask of allowed buttons to start drag
-- * @targets: the table of targets that the drag will support
-- * @n_targets: the number of items in @targets
-- * @actions: the bitmask of possible actions for a drag from this
-- *    widget
-- *
-- * Turns @tree_view into a drag source for automatic DND. Calling this
-- * method sets #PsppSheetView:reorderable to %FALSE.
-- **/
--void
--pspp_sheet_view_enable_model_drag_source (PsppSheetView              *tree_view,
--                                      GdkModifierType           start_button_mask,
--                                      const GtkTargetEntry     *targets,
--                                      gint                      n_targets,
--                                      GdkDragAction             actions)
--{
--  TreeViewDragInfo *di;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  gtk_drag_source_set (GTK_WIDGET (tree_view),
--                     0,
--                     targets,
--                     n_targets,
--                     actions);
--
--  di = ensure_info (tree_view);
--
--  di->start_button_mask = start_button_mask;
--  di->source_actions = actions;
--  di->source_set = TRUE;
--
--  unset_reorderable (tree_view);
--}
--
--/**
-- * pspp_sheet_view_enable_model_drag_dest:
-- * @tree_view: a #PsppSheetView
-- * @targets: the table of targets that the drag will support
-- * @n_targets: the number of items in @targets
-- * @actions: the bitmask of possible actions for a drag from this
-- *    widget
-- * 
-- * Turns @tree_view into a drop destination for automatic DND. Calling
-- * this method sets #PsppSheetView:reorderable to %FALSE.
-- **/
--void
--pspp_sheet_view_enable_model_drag_dest (PsppSheetView              *tree_view,
--                                    const GtkTargetEntry     *targets,
--                                    gint                      n_targets,
--                                    GdkDragAction             actions)
--{
--  TreeViewDragInfo *di;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  gtk_drag_dest_set (GTK_WIDGET (tree_view),
--                     0,
--                     targets,
--                     n_targets,
--                     actions);
--
--  di = ensure_info (tree_view);
--  di->dest_set = TRUE;
--
--  unset_reorderable (tree_view);
--}
--
--/**
-- * pspp_sheet_view_unset_rows_drag_source:
-- * @tree_view: a #PsppSheetView
-- *
-- * Undoes the effect of
-- * pspp_sheet_view_enable_model_drag_source(). Calling this method sets
-- * #PsppSheetView:reorderable to %FALSE.
-- **/
--void
--pspp_sheet_view_unset_rows_drag_source (PsppSheetView *tree_view)
--{
--  TreeViewDragInfo *di;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  di = get_info (tree_view);
--
--  if (di)
--    {
--      if (di->source_set)
--        {
--          gtk_drag_source_unset (GTK_WIDGET (tree_view));
--          di->source_set = FALSE;
--        }
--
--      if (!di->dest_set && !di->source_set)
--        remove_info (tree_view);
--    }
--  
--  unset_reorderable (tree_view);
--}
--
--/**
-- * pspp_sheet_view_unset_rows_drag_dest:
-- * @tree_view: a #PsppSheetView
-- *
-- * Undoes the effect of
-- * pspp_sheet_view_enable_model_drag_dest(). Calling this method sets
-- * #PsppSheetView:reorderable to %FALSE.
-- **/
--void
--pspp_sheet_view_unset_rows_drag_dest (PsppSheetView *tree_view)
--{
--  TreeViewDragInfo *di;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  di = get_info (tree_view);
--
--  if (di)
--    {
--      if (di->dest_set)
--        {
--          gtk_drag_dest_unset (GTK_WIDGET (tree_view));
--          di->dest_set = FALSE;
--        }
--
--      if (!di->dest_set && !di->source_set)
--        remove_info (tree_view);
--    }
--
--  unset_reorderable (tree_view);
--}
--
--/**
-- * pspp_sheet_view_set_drag_dest_row:
-- * @tree_view: a #PsppSheetView
-- * @path: (allow-none): The path of the row to highlight, or %NULL.
-- * @pos: Specifies whether to drop before, after or into the row
-- * 
-- * Sets the row that is highlighted for feedback.
-- **/
--void
--pspp_sheet_view_set_drag_dest_row (PsppSheetView            *tree_view,
--                                 GtkTreePath            *path,
--                                 PsppSheetViewDropPosition pos)
--{
--  GtkTreePath *current_dest;
--
--  /* Note; this function is exported to allow a custom DND
--   * implementation, so it can't touch TreeViewDragInfo
--   */
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  current_dest = NULL;
--
--  if (tree_view->priv->drag_dest_row)
--    {
--      current_dest = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
--      gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
--    }
--
--  /* special case a drop on an empty model */
--  tree_view->priv->empty_view_drop = 0;
--
--  if (pos == PSPP_SHEET_VIEW_DROP_BEFORE && path
--      && gtk_tree_path_get_depth (path) == 1
--      && gtk_tree_path_get_indices (path)[0] == 0)
--    {
--      gint n_children;
--
--      n_children = gtk_tree_model_iter_n_children (tree_view->priv->model,
--                                                   NULL);
--
--      if (!n_children)
--        tree_view->priv->empty_view_drop = 1;
--    }
--
--  tree_view->priv->drag_dest_pos = pos;
--
--  if (path)
--    {
--      tree_view->priv->drag_dest_row =
--        gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
--      pspp_sheet_view_queue_draw_path (tree_view, path, NULL);
--    }
--  else
--    tree_view->priv->drag_dest_row = NULL;
--
--  if (current_dest)
--    {
--      int node, new_node;
--
--      _pspp_sheet_view_find_node (tree_view, current_dest, &node);
--      _pspp_sheet_view_queue_draw_node (tree_view, node, NULL);
--
--      if (node >= 0)
--      {
--        new_node = pspp_sheet_view_node_next (tree_view, node);
--        if (new_node >= 0)
--          _pspp_sheet_view_queue_draw_node (tree_view, new_node, NULL);
--
--        new_node = pspp_sheet_view_node_prev (tree_view, node);
--        if (new_node >= 0)
--          _pspp_sheet_view_queue_draw_node (tree_view, new_node, NULL);
--      }
--      gtk_tree_path_free (current_dest);
--    }
--}
--
--/**
-- * pspp_sheet_view_get_drag_dest_row:
-- * @tree_view: a #PsppSheetView
-- * @path: (allow-none): Return location for the path of the highlighted row, or %NULL.
-- * @pos: (allow-none): Return location for the drop position, or %NULL
-- * 
-- * Gets information about the row that is highlighted for feedback.
-- **/
--void
--pspp_sheet_view_get_drag_dest_row (PsppSheetView              *tree_view,
--                                 GtkTreePath             **path,
--                                 PsppSheetViewDropPosition  *pos)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (path)
--    {
--      if (tree_view->priv->drag_dest_row)
--        *path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
--      else
--        {
--          if (tree_view->priv->empty_view_drop)
--            *path = gtk_tree_path_new_from_indices (0, -1);
--          else
--            *path = NULL;
--        }
--    }
--
--  if (pos)
--    *pos = tree_view->priv->drag_dest_pos;
--}
--
--/**
-- * pspp_sheet_view_get_dest_row_at_pos:
-- * @tree_view: a #PsppSheetView
-- * @drag_x: the position to determine the destination row for
-- * @drag_y: the position to determine the destination row for
-- * @path: (allow-none): Return location for the path of the highlighted row, or %NULL.
-- * @pos: (allow-none): Return location for the drop position, or %NULL
-- * 
-- * Determines the destination row for a given position.  @drag_x and
-- * @drag_y are expected to be in widget coordinates.  This function is only
-- * meaningful if @tree_view is realized.  Therefore this function will always
-- * return %FALSE if @tree_view is not realized or does not have a model.
-- * 
-- * Return value: whether there is a row at the given position, %TRUE if this
-- * is indeed the case.
-- **/
--gboolean
--pspp_sheet_view_get_dest_row_at_pos (PsppSheetView             *tree_view,
--                                   gint                     drag_x,
--                                   gint                     drag_y,
--                                   GtkTreePath            **path,
--                                   PsppSheetViewDropPosition *pos)
--{
--  gint cell_y;
--  gint bin_x, bin_y;
--  gdouble offset_into_row;
--  gdouble third;
--  GdkRectangle cell;
--  PsppSheetViewColumn *column = NULL;
--  GtkTreePath *tmp_path = NULL;
--
--  /* Note; this function is exported to allow a custom DND
--   * implementation, so it can't touch TreeViewDragInfo
--   */
--
--  g_return_val_if_fail (tree_view != NULL, FALSE);
--  g_return_val_if_fail (drag_x >= 0, FALSE);
--  g_return_val_if_fail (drag_y >= 0, FALSE);
--
--  if (path)
--    *path = NULL;
--
--  if (tree_view->priv->bin_window == NULL)
--    return FALSE;
--
--  if (tree_view->priv->row_count == 0)
--    return FALSE;
--
--  /* If in the top third of a row, we drop before that row; if
--   * in the bottom third, drop after that row; if in the middle,
--   * and the row has children, drop into the row.
--   */
--  pspp_sheet_view_convert_widget_to_bin_window_coords (tree_view, drag_x, drag_y,
--                                                   &bin_x, &bin_y);
--
--  if (!pspp_sheet_view_get_path_at_pos (tree_view,
--                                    bin_x,
--                                    bin_y,
--                                      &tmp_path,
--                                      &column,
--                                      NULL,
--                                      &cell_y))
--    return FALSE;
--
--  pspp_sheet_view_get_background_area (tree_view, tmp_path, column,
--                                     &cell);
--
--  offset_into_row = cell_y;
--
--  if (path)
--    *path = tmp_path;
--  else
--    gtk_tree_path_free (tmp_path);
--
--  tmp_path = NULL;
--
--  third = cell.height / 3.0;
--
--  if (pos)
--    {
--      if (offset_into_row < third)
--        {
--          *pos = PSPP_SHEET_VIEW_DROP_BEFORE;
--        }
--      else if (offset_into_row < (cell.height / 2.0))
--        {
--          *pos = PSPP_SHEET_VIEW_DROP_INTO_OR_BEFORE;
--        }
--      else if (offset_into_row < third * 2.0)
--        {
--          *pos = PSPP_SHEET_VIEW_DROP_INTO_OR_AFTER;
--        }
--      else
--        {
--          *pos = PSPP_SHEET_VIEW_DROP_AFTER;
--        }
--    }
--
--  return TRUE;
--}
--
--
--
--/**
-- * pspp_sheet_view_set_destroy_count_func:
-- * @tree_view: A #PsppSheetView
-- * @func: (allow-none): Function to be called when a view row is destroyed, or %NULL
-- * @data: (allow-none): User data to be passed to @func, or %NULL
-- * @destroy: (allow-none): Destroy notifier for @data, or %NULL
-- *
-- * This function should almost never be used.  It is meant for private use by
-- * ATK for determining the number of visible children that are removed when a row is deleted.
-- **/
--void
--pspp_sheet_view_set_destroy_count_func (PsppSheetView             *tree_view,
--                                    PsppSheetDestroyCountFunc  func,
--                                    gpointer                 data,
--                                    GDestroyNotify           destroy)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (tree_view->priv->destroy_count_destroy)
--    tree_view->priv->destroy_count_destroy (tree_view->priv->destroy_count_data);
--
--  tree_view->priv->destroy_count_func = func;
--  tree_view->priv->destroy_count_data = data;
--  tree_view->priv->destroy_count_destroy = destroy;
--}
--
--
--/*
-- * Interactive search
-- */
--
--/**
-- * pspp_sheet_view_set_enable_search:
-- * @tree_view: A #PsppSheetView
-- * @enable_search: %TRUE, if the user can search interactively
-- *
-- * If @enable_search is set, then the user can type in text to search through
-- * the tree interactively (this is sometimes called "typeahead find").
-- * 
-- * Note that even if this is %FALSE, the user can still initiate a search 
-- * using the "start-interactive-search" key binding.
-- */
--void
--pspp_sheet_view_set_enable_search (PsppSheetView *tree_view,
--                               gboolean     enable_search)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  enable_search = !!enable_search;
--  
--  if (tree_view->priv->enable_search != enable_search)
--    {
--       tree_view->priv->enable_search = enable_search;
--       g_object_notify (G_OBJECT (tree_view), "enable-search");
--    }
--}
--
--/**
-- * pspp_sheet_view_get_enable_search:
-- * @tree_view: A #PsppSheetView
-- *
-- * Returns whether or not the tree allows to start interactive searching 
-- * by typing in text.
-- *
-- * Return value: whether or not to let the user search interactively
-- */
--gboolean
--pspp_sheet_view_get_enable_search (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
--
--  return tree_view->priv->enable_search;
--}
--
--
--/**
-- * pspp_sheet_view_get_search_column:
-- * @tree_view: A #PsppSheetView
-- *
-- * Gets the column searched on by the interactive search code.
-- *
-- * Return value: the column the interactive search code searches in.
-- */
--gint
--pspp_sheet_view_get_search_column (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), -1);
--
--  return (tree_view->priv->search_column);
--}
--
--/**
-- * pspp_sheet_view_set_search_column:
-- * @tree_view: A #PsppSheetView
-- * @column: the column of the model to search in, or -1 to disable searching
-- *
-- * Sets @column as the column where the interactive search code should
-- * search in for the current model. 
-- * 
-- * If the search column is set, users can use the "start-interactive-search"
-- * key binding to bring up search popup. The enable-search property controls
-- * whether simply typing text will also start an interactive search.
-- *
-- * Note that @column refers to a column of the current model. The search 
-- * column is reset to -1 when the model is changed.
-- */
--void
--pspp_sheet_view_set_search_column (PsppSheetView *tree_view,
--                               gint         column)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (column >= -1);
--
--  if (tree_view->priv->search_column == column)
--    return;
--
--  tree_view->priv->search_column = column;
--  g_object_notify (G_OBJECT (tree_view), "search-column");
--}
--
--/**
-- * pspp_sheet_view_get_search_equal_func:
-- * @tree_view: A #PsppSheetView
-- *
-- * Returns the compare function currently in use.
-- *
-- * Return value: the currently used compare function for the search code.
-- */
--
--PsppSheetViewSearchEqualFunc
--pspp_sheet_view_get_search_equal_func (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
--
--  return tree_view->priv->search_equal_func;
--}
--
--/**
-- * pspp_sheet_view_set_search_equal_func:
-- * @tree_view: A #PsppSheetView
-- * @search_equal_func: the compare function to use during the search
-- * @search_user_data: (allow-none): user data to pass to @search_equal_func, or %NULL
-- * @search_destroy: (allow-none): Destroy notifier for @search_user_data, or %NULL
-- *
-- * Sets the compare function for the interactive search capabilities; note
-- * that somewhat like strcmp() returning 0 for equality
-- * #PsppSheetViewSearchEqualFunc returns %FALSE on matches.
-- **/
--void
--pspp_sheet_view_set_search_equal_func (PsppSheetView                *tree_view,
--                                   PsppSheetViewSearchEqualFunc  search_equal_func,
--                                   gpointer                    search_user_data,
--                                   GDestroyNotify              search_destroy)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (search_equal_func != NULL);
--
--  if (tree_view->priv->search_destroy)
--    tree_view->priv->search_destroy (tree_view->priv->search_user_data);
--
--  tree_view->priv->search_equal_func = search_equal_func;
--  tree_view->priv->search_user_data = search_user_data;
--  tree_view->priv->search_destroy = search_destroy;
--  if (tree_view->priv->search_equal_func == NULL)
--    tree_view->priv->search_equal_func = pspp_sheet_view_search_equal_func;
--}
--
--/**
-- * pspp_sheet_view_get_search_entry:
-- * @tree_view: A #PsppSheetView
-- *
-- * Returns the #GtkEntry which is currently in use as interactive search
-- * entry for @tree_view.  In case the built-in entry is being used, %NULL
-- * will be returned.
-- *
-- * Return value: the entry currently in use as search entry.
-- *
-- * Since: 2.10
-- */
--GtkEntry *
--pspp_sheet_view_get_search_entry (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
--
--  if (tree_view->priv->search_custom_entry_set)
--    return GTK_ENTRY (tree_view->priv->search_entry);
--
--  return NULL;
--}
--
--/**
-- * pspp_sheet_view_set_search_entry:
-- * @tree_view: A #PsppSheetView
-- * @entry: (allow-none): the entry the interactive search code of @tree_view should use or %NULL
-- *
-- * Sets the entry which the interactive search code will use for this
-- * @tree_view.  This is useful when you want to provide a search entry
-- * in our interface at all time at a fixed position.  Passing %NULL for
-- * @entry will make the interactive search code use the built-in popup
-- * entry again.
-- *
-- * Since: 2.10
-- */
--void
--pspp_sheet_view_set_search_entry (PsppSheetView *tree_view,
--                              GtkEntry    *entry)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (entry == NULL || GTK_IS_ENTRY (entry));
--
--  if (tree_view->priv->search_custom_entry_set)
--    {
--      if (tree_view->priv->search_entry_changed_id)
--        {
--        g_signal_handler_disconnect (tree_view->priv->search_entry,
--                                     tree_view->priv->search_entry_changed_id);
--        tree_view->priv->search_entry_changed_id = 0;
--      }
--      g_signal_handlers_disconnect_by_func (tree_view->priv->search_entry,
--                                          G_CALLBACK (pspp_sheet_view_search_key_press_event),
--                                          tree_view);
--
--      g_object_unref (tree_view->priv->search_entry);
--    }
--  else if (tree_view->priv->search_window)
--    {
--      gtk_widget_destroy (tree_view->priv->search_window);
--
--      tree_view->priv->search_window = NULL;
--    }
--
--  if (entry)
--    {
--      tree_view->priv->search_entry = g_object_ref (entry);
--      tree_view->priv->search_custom_entry_set = TRUE;
--
--      if (tree_view->priv->search_entry_changed_id == 0)
--        {
--          tree_view->priv->search_entry_changed_id =
--          g_signal_connect (tree_view->priv->search_entry, "changed",
--                            G_CALLBACK (pspp_sheet_view_search_init),
--                            tree_view);
--      }
--      
--        g_signal_connect (tree_view->priv->search_entry, "key-press-event",
--                        G_CALLBACK (pspp_sheet_view_search_key_press_event),
--                        tree_view);
--
--      pspp_sheet_view_search_init (tree_view->priv->search_entry, tree_view);
--    }
--  else
--    {
--      tree_view->priv->search_entry = NULL;
--      tree_view->priv->search_custom_entry_set = FALSE;
--    }
--}
--
--/**
-- * pspp_sheet_view_set_search_position_func:
-- * @tree_view: A #PsppSheetView
-- * @func: (allow-none): the function to use to position the search dialog, or %NULL
-- *    to use the default search position function
-- * @data: (allow-none): user data to pass to @func, or %NULL
-- * @destroy: (allow-none): Destroy notifier for @data, or %NULL
-- *
-- * Sets the function to use when positioning the search dialog.
-- *
-- * Since: 2.10
-- **/
--void
--pspp_sheet_view_set_search_position_func (PsppSheetView                   *tree_view,
--                                      PsppSheetViewSearchPositionFunc  func,
--                                      gpointer                       user_data,
--                                      GDestroyNotify                 destroy)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (tree_view->priv->search_position_destroy)
--    tree_view->priv->search_position_destroy (tree_view->priv->search_position_user_data);
--
--  tree_view->priv->search_position_func = func;
--  tree_view->priv->search_position_user_data = user_data;
--  tree_view->priv->search_position_destroy = destroy;
--  if (tree_view->priv->search_position_func == NULL)
--    tree_view->priv->search_position_func = pspp_sheet_view_search_position_func;
--}
--
--/**
-- * pspp_sheet_view_get_search_position_func:
-- * @tree_view: A #PsppSheetView
-- *
-- * Returns the positioning function currently in use.
-- *
-- * Return value: the currently used function for positioning the search dialog.
-- *
-- * Since: 2.10
-- */
--PsppSheetViewSearchPositionFunc
--pspp_sheet_view_get_search_position_func (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), NULL);
--
--  return tree_view->priv->search_position_func;
--}
--
--
--static void
--pspp_sheet_view_search_dialog_hide (GtkWidget   *search_dialog,
--                                PsppSheetView *tree_view)
--{
--  if (tree_view->priv->disable_popdown)
--    return;
--
--  if (tree_view->priv->search_entry_changed_id)
--    {
--      g_signal_handler_disconnect (tree_view->priv->search_entry,
--                                 tree_view->priv->search_entry_changed_id);
--      tree_view->priv->search_entry_changed_id = 0;
--    }
--  if (tree_view->priv->typeselect_flush_timeout)
--    {
--      g_source_remove (tree_view->priv->typeselect_flush_timeout);
--      tree_view->priv->typeselect_flush_timeout = 0;
--    }
--      
--  if (gtk_widget_get_visible (search_dialog))
--    {
--      /* send focus-in event */
--      send_focus_change (GTK_WIDGET (tree_view->priv->search_entry), FALSE);
--      gtk_widget_hide (search_dialog);
--      gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
--      send_focus_change (GTK_WIDGET (tree_view), TRUE);
--    }
--}
--
--static void
--pspp_sheet_view_search_position_func (PsppSheetView *tree_view,
--                                  GtkWidget   *search_dialog,
--                                  gpointer     user_data)
--{
--  gint x, y;
--  gint tree_x, tree_y;
--  gint tree_width, tree_height;
--  GdkWindow *tree_window = gtk_widget_get_window (GTK_WIDGET (tree_view));
--  GdkScreen *screen = gdk_window_get_screen (tree_window);
--  GtkRequisition requisition;
--  gint monitor_num;
--  GdkRectangle monitor;
--
--  monitor_num = gdk_screen_get_monitor_at_window (screen, tree_window);
--  gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
--
--  gtk_widget_realize (search_dialog);
--
--  gdk_window_get_origin (tree_window, &tree_x, &tree_y);
--  tree_width = gdk_window_get_width (tree_window);
--  tree_height = gdk_window_get_height (tree_window);
--
--  gtk_widget_size_request (search_dialog, &requisition);
--
--  if (tree_x + tree_width > gdk_screen_get_width (screen))
--    x = gdk_screen_get_width (screen) - requisition.width;
--  else if (tree_x + tree_width - requisition.width < 0)
--    x = 0;
--  else
--    x = tree_x + tree_width - requisition.width;
--
--  if (tree_y + tree_height + requisition.height > gdk_screen_get_height (screen))
--    y = gdk_screen_get_height (screen) - requisition.height;
--  else if (tree_y + tree_height < 0) /* isn't really possible ... */
--    y = 0;
--  else
--    y = tree_y + tree_height;
--
--  gtk_window_move (GTK_WINDOW (search_dialog), x, y);
--}
--
--static void
--pspp_sheet_view_search_disable_popdown (GtkEntry *entry,
--                                    GtkMenu  *menu,
--                                    gpointer  data)
--{
--  PsppSheetView *tree_view = (PsppSheetView *)data;
--
--  tree_view->priv->disable_popdown = 1;
--  g_signal_connect (menu, "hide",
--                  G_CALLBACK (pspp_sheet_view_search_enable_popdown), data);
--}
--
--
--static void
--pspp_sheet_view_search_activate (GtkEntry    *entry,
--                             PsppSheetView *tree_view)
--{
--  GtkTreePath *path;
--  int node;
--
--  pspp_sheet_view_search_dialog_hide (tree_view->priv->search_window,
--                                  tree_view);
--
--  /* If we have a row selected and it's the cursor row, we activate
--   * the row XXX */
--  if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
--    {
--      path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
--      
--      _pspp_sheet_view_find_node (tree_view, path, &node);
--      
--      if (node >= 0 && pspp_sheet_view_node_is_selected (tree_view, node))
--      pspp_sheet_view_row_activated (tree_view, path, tree_view->priv->focus_column);
--      
--      gtk_tree_path_free (path);
--    }
--}
--
--static gboolean
--pspp_sheet_view_real_search_enable_popdown (gpointer data)
--{
--  PsppSheetView *tree_view = (PsppSheetView *)data;
--
--  tree_view->priv->disable_popdown = 0;
--
--  return FALSE;
--}
--
--static void
--pspp_sheet_view_search_enable_popdown (GtkWidget *widget,
--                                   gpointer   data)
--{
--  gdk_threads_add_timeout_full (G_PRIORITY_HIGH, 200, pspp_sheet_view_real_search_enable_popdown, g_object_ref (data), g_object_unref);
--}
--
--static gboolean
--pspp_sheet_view_search_delete_event (GtkWidget *widget,
--                                 GdkEventAny *event,
--                                 PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
--
--  pspp_sheet_view_search_dialog_hide (widget, tree_view);
--
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_search_button_press_event (GtkWidget *widget,
--                                       GdkEventButton *event,
--                                       PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
--
--  pspp_sheet_view_search_dialog_hide (widget, tree_view);
--
--  if (event->window == tree_view->priv->bin_window)
--    pspp_sheet_view_button_press (GTK_WIDGET (tree_view), event);
--
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_search_scroll_event (GtkWidget *widget,
--                                 GdkEventScroll *event,
--                                 PsppSheetView *tree_view)
--{
--  gboolean retval = FALSE;
--
--  if (event->direction == GDK_SCROLL_UP)
--    {
--      pspp_sheet_view_search_move (widget, tree_view, TRUE);
--      retval = TRUE;
--    }
--  else if (event->direction == GDK_SCROLL_DOWN)
--    {
--      pspp_sheet_view_search_move (widget, tree_view, FALSE);
--      retval = TRUE;
--    }
--
--  /* renew the flush timeout */
--  if (retval && tree_view->priv->typeselect_flush_timeout
--      && !tree_view->priv->search_custom_entry_set)
--    {
--      g_source_remove (tree_view->priv->typeselect_flush_timeout);
--      tree_view->priv->typeselect_flush_timeout =
--      gdk_threads_add_timeout (PSPP_SHEET_VIEW_SEARCH_DIALOG_TIMEOUT,
--                     (GSourceFunc) pspp_sheet_view_search_entry_flush_timeout,
--                     tree_view);
--    }
--
--  return retval;
--}
--
--static gboolean
--pspp_sheet_view_search_key_press_event (GtkWidget *widget,
--                                    GdkEventKey *event,
--                                    PsppSheetView *tree_view)
--{
--  gboolean retval = FALSE;
--
--  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
--
--  /* close window and cancel the search */
--  if (!tree_view->priv->search_custom_entry_set
--      && (event->keyval == GDK_Escape ||
--          event->keyval == GDK_Tab ||
--          event->keyval == GDK_KP_Tab ||
--          event->keyval == GDK_ISO_Left_Tab))
--    {
--      pspp_sheet_view_search_dialog_hide (widget, tree_view);
--      return TRUE;
--    }
--
--  /* select previous matching iter */
--  if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up)
--    {
--      if (!pspp_sheet_view_search_move (widget, tree_view, TRUE))
--        gtk_widget_error_bell (widget);
--
--      retval = TRUE;
--    }
--
--  if (((event->state & (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK)) == (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK))
--      && (event->keyval == GDK_g || event->keyval == GDK_G))
--    {
--      if (!pspp_sheet_view_search_move (widget, tree_view, TRUE))
--        gtk_widget_error_bell (widget);
--
--      retval = TRUE;
--    }
--
--  /* select next matching iter */
--  if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
--    {
--      if (!pspp_sheet_view_search_move (widget, tree_view, FALSE))
--        gtk_widget_error_bell (widget);
--
--      retval = TRUE;
--    }
--
--  if (((event->state & (GTK_DEFAULT_ACCEL_MOD_MASK | GDK_SHIFT_MASK)) == GTK_DEFAULT_ACCEL_MOD_MASK)
--      && (event->keyval == GDK_g || event->keyval == GDK_G))
--    {
--      if (!pspp_sheet_view_search_move (widget, tree_view, FALSE))
--        gtk_widget_error_bell (widget);
--
--      retval = TRUE;
--    }
--
--  /* renew the flush timeout */
--  if (retval && tree_view->priv->typeselect_flush_timeout
--      && !tree_view->priv->search_custom_entry_set)
--    {
--      g_source_remove (tree_view->priv->typeselect_flush_timeout);
--      tree_view->priv->typeselect_flush_timeout =
--      gdk_threads_add_timeout (PSPP_SHEET_VIEW_SEARCH_DIALOG_TIMEOUT,
--                     (GSourceFunc) pspp_sheet_view_search_entry_flush_timeout,
--                     tree_view);
--    }
--
--  return retval;
--}
--
--/*  this function returns FALSE if there is a search string but
-- *  nothing was found, and TRUE otherwise.
-- */
--static gboolean
--pspp_sheet_view_search_move (GtkWidget   *window,
--                         PsppSheetView *tree_view,
--                         gboolean     up)
--{
--  gboolean ret;
--  gint len;
--  gint count = 0;
--  const gchar *text;
--  GtkTreeIter iter;
--  GtkTreeModel *model;
--  PsppSheetSelection *selection;
--
--  text = gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry));
--
--  g_return_val_if_fail (text != NULL, FALSE);
--
--  len = strlen (text);
--
--  if (up && tree_view->priv->selected_iter == 1)
--    return strlen (text) < 1;
--
--  len = strlen (text);
--
--  if (len < 1)
--    return TRUE;
--
--  model = pspp_sheet_view_get_model (tree_view);
--  selection = pspp_sheet_view_get_selection (tree_view);
--
--  /* search */
--  pspp_sheet_selection_unselect_all (selection);
--  if (!gtk_tree_model_get_iter_first (model, &iter))
--    return TRUE;
--
--  ret = pspp_sheet_view_search_iter (model, selection, &iter, text,
--                                 &count, up?((tree_view->priv->selected_iter) - 1):((tree_view->priv->selected_iter + 1)));
--
--  if (ret)
--    {
--      /* found */
--      tree_view->priv->selected_iter += up?(-1):(1);
--      return TRUE;
--    }
--  else
--    {
--      /* return to old iter */
--      count = 0;
--      gtk_tree_model_get_iter_first (model, &iter);
--      pspp_sheet_view_search_iter (model, selection,
--                               &iter, text,
--                               &count, tree_view->priv->selected_iter);
--      return FALSE;
--    }
--}
--
--static gboolean
--pspp_sheet_view_search_equal_func (GtkTreeModel *model,
--                               gint          column,
--                               const gchar  *key,
--                               GtkTreeIter  *iter,
--                               gpointer      search_data)
--{
--  gboolean retval = TRUE;
--  const gchar *str;
--  gchar *normalized_string;
--  gchar *normalized_key;
--  gchar *case_normalized_string = NULL;
--  gchar *case_normalized_key = NULL;
--  GValue value = {0,};
--  GValue transformed = {0,};
--
--  gtk_tree_model_get_value (model, iter, column, &value);
--
--  g_value_init (&transformed, G_TYPE_STRING);
--
--  if (!g_value_transform (&value, &transformed))
--    {
--      g_value_unset (&value);
--      return TRUE;
--    }
--
--  g_value_unset (&value);
--
--  str = g_value_get_string (&transformed);
--  if (!str)
--    {
--      g_value_unset (&transformed);
--      return TRUE;
--    }
--
--  normalized_string = g_utf8_normalize (str, -1, G_NORMALIZE_ALL);
--  normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
--
--  if (normalized_string && normalized_key)
--    {
--      case_normalized_string = g_utf8_casefold (normalized_string, -1);
--      case_normalized_key = g_utf8_casefold (normalized_key, -1);
--
--      if (strncmp (case_normalized_key, case_normalized_string, strlen (case_normalized_key)) == 0)
--        retval = FALSE;
--    }
--
--  g_value_unset (&transformed);
--  g_free (normalized_key);
--  g_free (normalized_string);
--  g_free (case_normalized_key);
--  g_free (case_normalized_string);
--
--  return retval;
--}
--
--static gboolean
--pspp_sheet_view_search_iter (GtkTreeModel     *model,
--                             PsppSheetSelection *selection,
--                             GtkTreeIter      *iter,
--                             const gchar      *text,
--                             gint             *count,
--                             gint              n)
--{
--  int node = -1;
--  GtkTreePath *path;
--
--  PsppSheetView *tree_view = pspp_sheet_selection_get_tree_view (selection);
--
--  path = gtk_tree_model_get_path (model, iter);
--  _pspp_sheet_view_find_node (tree_view, path, &node);
--
--  do
--    {
--      gboolean done = FALSE;
--
--      if (! tree_view->priv->search_equal_func (model, tree_view->priv->search_column, text, iter, tree_view->priv->search_user_data))
--        {
--          (*count)++;
--          if (*count == n)
--            {
--              pspp_sheet_view_scroll_to_cell (tree_view, path, NULL,
--                                              TRUE, 0.5, 0.0);
--              pspp_sheet_selection_select_iter (selection, iter);
--              pspp_sheet_view_real_set_cursor (tree_view, path, FALSE, TRUE, 0);
--
--            if (path)
--              gtk_tree_path_free (path);
--
--              return TRUE;
--            }
--        }
--
--
--      do
--        {
--          node = pspp_sheet_view_node_next (tree_view, node);
--
--          if (node >= 0)
--            {
--              gboolean has_next;
--
--              has_next = gtk_tree_model_iter_next (model, iter);
--
--              done = TRUE;
--              gtk_tree_path_next (path);
--
--              /* sanity check */
--              TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
--            }
--          else
--            {
--              if (path)
--                gtk_tree_path_free (path);
--
--              /* we've run out of tree, done with this func */
--              return FALSE;
--            }
--        }
--      while (!done);
--    }
--  while (1);
--
--  return FALSE;
--}
--
--static void
--pspp_sheet_view_search_init (GtkWidget   *entry,
--                         PsppSheetView *tree_view)
--{
--  gint ret;
--  gint count = 0;
--  const gchar *text;
--  GtkTreeIter iter;
--  GtkTreeModel *model;
--  PsppSheetSelection *selection;
--
--  g_return_if_fail (GTK_IS_ENTRY (entry));
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  text = gtk_entry_get_text (GTK_ENTRY (entry));
--
--  model = pspp_sheet_view_get_model (tree_view);
--  selection = pspp_sheet_view_get_selection (tree_view);
--
--  /* search */
--  pspp_sheet_selection_unselect_all (selection);
--  if (tree_view->priv->typeselect_flush_timeout
--      && !tree_view->priv->search_custom_entry_set)
--    {
--      g_source_remove (tree_view->priv->typeselect_flush_timeout);
--      tree_view->priv->typeselect_flush_timeout =
--      gdk_threads_add_timeout (PSPP_SHEET_VIEW_SEARCH_DIALOG_TIMEOUT,
--                     (GSourceFunc) pspp_sheet_view_search_entry_flush_timeout,
--                     tree_view);
--    }
--
--  if (*text == '\0')
--    return;
--
--  if (!gtk_tree_model_get_iter_first (model, &iter))
--    return;
--
--  ret = pspp_sheet_view_search_iter (model, selection,
--                                 &iter, text,
--                                 &count, 1);
--
--  if (ret)
--    tree_view->priv->selected_iter = 1;
--}
--
--static void
--pspp_sheet_view_remove_widget (GtkCellEditable *cell_editable,
--                           PsppSheetView     *tree_view)
--{
--  if (tree_view->priv->edited_column == NULL)
--    return;
--
--  _pspp_sheet_view_column_stop_editing (tree_view->priv->edited_column);
--  tree_view->priv->edited_column = NULL;
--
--  if (gtk_widget_has_focus (GTK_WIDGET (cell_editable)))
--    gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--
--  g_signal_handlers_disconnect_by_func (cell_editable,
--                                      pspp_sheet_view_remove_widget,
--                                      tree_view);
--  g_signal_handlers_disconnect_by_func (cell_editable,
--                                      pspp_sheet_view_editable_button_press_event,
--                                      tree_view);
--  g_signal_handlers_disconnect_by_func (cell_editable,
--                                      pspp_sheet_view_editable_clicked,
--                                      tree_view);
--
--  gtk_container_remove (GTK_CONTAINER (tree_view),
--                      GTK_WIDGET (cell_editable));  
--
--  /* FIXME should only redraw a single node */
--  gtk_widget_queue_draw (GTK_WIDGET (tree_view));
--}
--
--static gboolean
--pspp_sheet_view_start_editing (PsppSheetView *tree_view,
--                           GtkTreePath *cursor_path)
--{
--  GtkTreeIter iter;
--  GdkRectangle background_area;
--  GdkRectangle cell_area;
--  GtkCellEditable *editable_widget = NULL;
--  gchar *path_string;
--  guint flags = 0; /* can be 0, as the flags are primarily for rendering */
--  gint retval = FALSE;
--  int cursor_node;
--
--  g_assert (tree_view->priv->focus_column);
--
--  if (!gtk_widget_get_realized (GTK_WIDGET (tree_view)))
--    return FALSE;
--
--  _pspp_sheet_view_find_node (tree_view, cursor_path, &cursor_node);
--  if (cursor_node < 0)
--    return FALSE;
--
--  path_string = gtk_tree_path_to_string (cursor_path);
--  gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path);
--
--  pspp_sheet_view_column_cell_set_cell_data (tree_view->priv->focus_column,
--                                         tree_view->priv->model,
--                                         &iter);
--  pspp_sheet_view_get_background_area (tree_view,
--                                   cursor_path,
--                                   tree_view->priv->focus_column,
--                                   &background_area);
--  pspp_sheet_view_get_cell_area (tree_view,
--                             cursor_path,
--                             tree_view->priv->focus_column,
--                             &cell_area);
--
--  if (_pspp_sheet_view_column_cell_event (tree_view->priv->focus_column,
--                                      &editable_widget,
--                                      NULL,
--                                      path_string,
--                                      &background_area,
--                                      &cell_area,
--                                      flags))
--    {
--      retval = TRUE;
--      if (editable_widget != NULL)
--      {
--        gint left, right;
--        GdkRectangle area;
--        GtkCellRenderer *cell;
--
--        area = cell_area;
--        cell = _pspp_sheet_view_column_get_edited_cell (tree_view->priv->focus_column);
--
--        _pspp_sheet_view_column_get_neighbor_sizes (tree_view->priv->focus_column, cell, &left, &right);
--
--        area.x += left;
--        area.width -= right + left;
--
--        pspp_sheet_view_real_start_editing (tree_view,
--                                          tree_view->priv->focus_column,
--                                          cursor_path,
--                                          editable_widget,
--                                          &area,
--                                          NULL,
--                                          flags);
--      }
--
--    }
--  g_free (path_string);
--  return retval;
--}
--
--static gboolean
--pspp_sheet_view_editable_button_press_event (GtkWidget *widget,
--                                             GdkEventButton *event,
--                                             PsppSheetView *sheet_view)
--{
--  gint node;
--
--  node = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
--                                             "pspp-sheet-view-node"));
--  return pspp_sheet_view_row_head_clicked (sheet_view,
--                                           node,
--                                           sheet_view->priv->edited_column,
--                                           event);
--}
--
--static void
--pspp_sheet_view_editable_clicked (GtkButton *button,
--                                  PsppSheetView *sheet_view)
--{
--  pspp_sheet_view_editable_button_press_event (GTK_WIDGET (button), NULL,
--                                               sheet_view);
--}
--
--static gboolean
--is_all_selected (GtkWidget *widget)
--{
--  GtkEntryBuffer *buffer;
--  gint start_pos, end_pos;
--
--  if (!GTK_IS_ENTRY (widget))
--    return FALSE;
--
--  buffer = gtk_entry_get_buffer (GTK_ENTRY (widget));
--  return (gtk_editable_get_selection_bounds (GTK_EDITABLE (widget),
--                                             &start_pos, &end_pos)
--          && start_pos == 0
--          && end_pos == gtk_entry_buffer_get_length (buffer));
--}
--
--static gboolean
--is_at_left (GtkWidget *widget)
--{
--  return (GTK_IS_ENTRY (widget)
--          && gtk_editable_get_position (GTK_EDITABLE (widget)) == 0);
--}
--
--static gboolean
--is_at_right (GtkWidget *widget)
--{
--  GtkEntryBuffer *buffer;
--  gint length;
--
--  if (!GTK_IS_ENTRY (widget))
--    return FALSE;
--
--  buffer = gtk_entry_get_buffer (GTK_ENTRY (widget));
--  length = gtk_entry_buffer_get_length (buffer);
--  return gtk_editable_get_position (GTK_EDITABLE (widget)) == length;
--}
--
--static gboolean
--pspp_sheet_view_event (GtkWidget *widget,
--                       GdkEventKey *event,
--                       PsppSheetView *tree_view)
--{
--  PsppSheetViewColumn *column;
--  GtkTreePath *path;
--  gboolean handled;
--  gboolean cancel;
--  guint keyval;
--  gint row;
--
--  /* Intercept only key press events.
--     It would make sense to use "key-press-event" instead of "event", but
--     GtkEntry attaches its own signal handler to "key-press-event" that runs
--     before ours and overrides our desired behavior for GDK_Up and GDK_Down.
--  */
--  if (event->type != GDK_KEY_PRESS)
--    return FALSE;
--
--  keyval = event->keyval;
--  cancel = FALSE;
--  switch (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK))
--    {
--    case 0:
--      switch (event->keyval)
--        {
--        case GDK_Left:      case GDK_KP_Left:
--        case GDK_Home:      case GDK_KP_Home:
--          if (!is_all_selected (widget) && !is_at_left (widget))
--            return FALSE;
--          break;
--
--        case GDK_Right:     case GDK_KP_Right:
--        case GDK_End:       case GDK_KP_End:
--          if (!is_all_selected (widget) && !is_at_right (widget))
--            return FALSE;
--          break;
--
--        case GDK_Up:        case GDK_KP_Up:
--        case GDK_Down:      case GDK_KP_Down:
--          break;
--
--        case GDK_Page_Up:   case GDK_KP_Page_Up:
--        case GDK_Page_Down: case GDK_KP_Page_Down:
--          break;
--
--        case GDK_Escape:
--          cancel = TRUE;
--          break;
--
--        case GDK_Return:
--          keyval = GDK_Down;
--          break;
--
--        case GDK_Tab:       case GDK_KP_Tab:
--        case GDK_ISO_Left_Tab:
--          keyval = GDK_Tab;
--          break;
--
--        default:
--          return FALSE;
--        }
--      break;
--
--    case GDK_SHIFT_MASK:
--      switch (event->keyval)
--        {
--        case GDK_Tab:
--        case GDK_ISO_Left_Tab:
--          keyval = GDK_Tab;
--          break;
--
--        default:
--          return FALSE;
--        }
--      break;
--
--    case GDK_CONTROL_MASK:
--      switch (event->keyval)
--        {
--        case GDK_Left:      case GDK_KP_Left:
--          if (!is_all_selected (widget) && !is_at_left (widget))
--            return FALSE;
--          break;
--
--        case GDK_Right:     case GDK_KP_Right:
--          if (!is_all_selected (widget) && !is_at_right (widget))
--            return FALSE;
--          break;
--
--        case GDK_Up:        case GDK_KP_Up:
--        case GDK_Down:      case GDK_KP_Down:
--          break;
--
--        default:
--          return FALSE;
--        }
--      break;
--
--    default:
--      return FALSE;
--    }
--
--  row = tree_view->priv->edited_row;
--  column = tree_view->priv->edited_column;
--  path = gtk_tree_path_new_from_indices (row, -1);
--
--  pspp_sheet_view_stop_editing (tree_view, cancel);
--  gtk_widget_grab_focus (GTK_WIDGET (tree_view));
--
--  pspp_sheet_view_set_cursor (tree_view, path, column, FALSE);
--  gtk_tree_path_free (path);
--
--  handled = gtk_binding_set_activate (edit_bindings, keyval, event->state,
--                                      G_OBJECT (tree_view));
--  if (handled)
--    g_signal_stop_emission_by_name (widget, "event");
--
--  pspp_sheet_view_get_cursor (tree_view, &path, NULL);
--  pspp_sheet_view_start_editing (tree_view, path);
--  gtk_tree_path_free (path);
--
--  return handled;
--}
--
--static void
--pspp_sheet_view_override_cell_keypresses (GtkWidget *widget,
--                                          gpointer data)
--{
--  PsppSheetView *sheet_view = data;
--
--  g_signal_connect (widget, "event",
--                    G_CALLBACK (pspp_sheet_view_event),
--                    sheet_view);
--
--  if (GTK_IS_CONTAINER (widget))
--    gtk_container_foreach (GTK_CONTAINER (widget),
--                           pspp_sheet_view_override_cell_keypresses,
--                           data);
--}
--
--static void
--pspp_sheet_view_real_start_editing (PsppSheetView       *tree_view,
--                                PsppSheetViewColumn *column,
--                                GtkTreePath       *path,
--                                GtkCellEditable   *cell_editable,
--                                GdkRectangle      *cell_area,
--                                GdkEvent          *event,
--                                guint              flags)
--{
--  PsppSheetSelectionMode mode = pspp_sheet_selection_get_mode (tree_view->priv->selection);
--  gint pre_val = gtk_adjustment_get_value (tree_view->priv->vadjustment);
--  gint row;
--
--  g_return_if_fail (gtk_tree_path_get_depth (path) == 1);
--
--  tree_view->priv->edited_column = column;
--  _pspp_sheet_view_column_start_editing (column, GTK_CELL_EDITABLE (cell_editable));
--
--  row = gtk_tree_path_get_indices (path)[0];
--  tree_view->priv->edited_row = row;
--  pspp_sheet_view_real_set_cursor (tree_view, path, FALSE, TRUE, 0);
--  cell_area->y += pre_val - (int)gtk_adjustment_get_value (tree_view->priv->vadjustment);
--
--  pspp_sheet_selection_unselect_all_columns (tree_view->priv->selection);
--  pspp_sheet_selection_select_column (tree_view->priv->selection, column);
--  tree_view->priv->anchor_column = column;
--
--  PSPP_SHEET_VIEW_SET_FLAG (tree_view, PSPP_SHEET_VIEW_DRAW_KEYFOCUS);
--
--  pspp_sheet_view_put (tree_view,
--                     GTK_WIDGET (cell_editable),
--                     path,
--                     column);
--
--  gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (cell_editable),
--                                 (GdkEvent *)event);
--
--  gtk_widget_grab_focus (GTK_WIDGET (cell_editable));
--  g_signal_connect (cell_editable, "remove-widget",
--                  G_CALLBACK (pspp_sheet_view_remove_widget), tree_view);
--  if (mode == PSPP_SHEET_SELECTION_RECTANGLE && column->row_head &&
--      GTK_IS_BUTTON (cell_editable))
--    {
--      g_signal_connect (cell_editable, "button-press-event",
--                        G_CALLBACK (pspp_sheet_view_editable_button_press_event),
--                        tree_view);
--      g_object_set_data (G_OBJECT (cell_editable), "pspp-sheet-view-node",
--                         GINT_TO_POINTER (row));
--      g_signal_connect (cell_editable, "clicked",
--                        G_CALLBACK (pspp_sheet_view_editable_clicked),
--                        tree_view);
--    }
--
--  pspp_sheet_view_override_cell_keypresses (GTK_WIDGET (cell_editable),
--                                            tree_view);
--}
--
--void
--pspp_sheet_view_stop_editing (PsppSheetView *tree_view,
--                              gboolean     cancel_editing)
--{
--  PsppSheetViewColumn *column;
--  GtkCellRenderer *cell;
--
--  if (tree_view->priv->edited_column == NULL)
--    return;
--
--  /*
--   * This is very evil. We need to do this, because
--   * gtk_cell_editable_editing_done may trigger pspp_sheet_view_row_changed
--   * later on. If pspp_sheet_view_row_changed notices
--   * tree_view->priv->edited_column != NULL, it'll call
--   * pspp_sheet_view_stop_editing again. Bad things will happen then.
--   *
--   * Please read that again if you intend to modify anything here.
--   */
--
--  column = tree_view->priv->edited_column;
--  tree_view->priv->edited_column = NULL;
--
--  cell = _pspp_sheet_view_column_get_edited_cell (column);
--  gtk_cell_renderer_stop_editing (cell, cancel_editing);
--
--  if (!cancel_editing)
--    gtk_cell_editable_editing_done (column->editable_widget);
--
--  tree_view->priv->edited_column = column;
--
--  gtk_cell_editable_remove_widget (column->editable_widget);
--}
--
--
--/**
-- * pspp_sheet_view_set_hover_selection:
-- * @tree_view: a #PsppSheetView
-- * @hover: %TRUE to enable hover selection mode
-- *
-- * Enables of disables the hover selection mode of @tree_view.
-- * Hover selection makes the selected row follow the pointer.
-- * Currently, this works only for the selection modes 
-- * %PSPP_SHEET_SELECTION_SINGLE and %PSPP_SHEET_SELECTION_BROWSE.
-- * 
-- * Since: 2.6
-- **/
--void     
--pspp_sheet_view_set_hover_selection (PsppSheetView *tree_view,
--                                 gboolean     hover)
--{
--  hover = hover != FALSE;
--
--  if (hover != tree_view->priv->hover_selection)
--    {
--      tree_view->priv->hover_selection = hover;
--
--      g_object_notify (G_OBJECT (tree_view), "hover-selection");
--    }
--}
--
--/**
-- * pspp_sheet_view_get_hover_selection:
-- * @tree_view: a #PsppSheetView
-- * 
-- * Returns whether hover selection mode is turned on for @tree_view.
-- * 
-- * Return value: %TRUE if @tree_view is in hover selection mode
-- *
-- * Since: 2.6 
-- **/
--gboolean 
--pspp_sheet_view_get_hover_selection (PsppSheetView *tree_view)
--{
--  return tree_view->priv->hover_selection;
--}
--
--/**
-- * pspp_sheet_view_set_rubber_banding:
-- * @tree_view: a #PsppSheetView
-- * @enable: %TRUE to enable rubber banding
-- *
-- * Enables or disables rubber banding in @tree_view.  If the selection mode is
-- * #PSPP_SHEET_SELECTION_MULTIPLE or #PSPP_SHEET_SELECTION_RECTANGLE, rubber
-- * banding will allow the user to select multiple rows by dragging the mouse.
-- * 
-- * Since: 2.10
-- **/
--void
--pspp_sheet_view_set_rubber_banding (PsppSheetView *tree_view,
--                                gboolean     enable)
--{
--  enable = enable != FALSE;
--
--  if (enable != tree_view->priv->rubber_banding_enable)
--    {
--      tree_view->priv->rubber_banding_enable = enable;
--
--      g_object_notify (G_OBJECT (tree_view), "rubber-banding");
--    }
--}
--
--/**
-- * pspp_sheet_view_get_rubber_banding:
-- * @tree_view: a #PsppSheetView
-- * 
-- * Returns whether rubber banding is turned on for @tree_view.  If the
-- * selection mode is #PSPP_SHEET_SELECTION_MULTIPLE or
-- * #PSPP_SHEET_SELECTION_RECTANGLE, rubber banding will allow the user to
-- * select multiple rows by dragging the mouse.
-- * 
-- * Return value: %TRUE if rubber banding in @tree_view is enabled.
-- *
-- * Since: 2.10
-- **/
--gboolean
--pspp_sheet_view_get_rubber_banding (PsppSheetView *tree_view)
--{
--  return tree_view->priv->rubber_banding_enable;
--}
--
--/**
-- * pspp_sheet_view_is_rubber_banding_active:
-- * @tree_view: a #PsppSheetView
-- * 
-- * Returns whether a rubber banding operation is currently being done
-- * in @tree_view.
-- *
-- * Return value: %TRUE if a rubber banding operation is currently being
-- * done in @tree_view.
-- *
-- * Since: 2.12
-- **/
--gboolean
--pspp_sheet_view_is_rubber_banding_active (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
--
--  if (tree_view->priv->rubber_banding_enable
--      && tree_view->priv->rubber_band_status == RUBBER_BAND_ACTIVE)
--    return TRUE;
--
--  return FALSE;
--}
--
--static void
--pspp_sheet_view_grab_notify (GtkWidget *widget,
--                         gboolean   was_grabbed)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--
--  tree_view->priv->in_grab = !was_grabbed;
--
--  if (!was_grabbed)
--    {
--      tree_view->priv->pressed_button = -1;
--
--      if (tree_view->priv->rubber_band_status)
--      pspp_sheet_view_stop_rubber_band (tree_view);
--    }
--}
--
--static void
--pspp_sheet_view_state_changed (GtkWidget      *widget,
--                           GtkStateType    previous_state)
--{
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--
--  if (gtk_widget_get_realized (widget))
--    {
--      GtkStyle *style = gtk_widget_get_style (widget);
--      gdk_window_set_background (tree_view->priv->bin_window, &style->base[gtk_widget_get_state (widget)]);
--    }
--
--  gtk_widget_queue_draw (widget);
--}
--
--/**
-- * pspp_sheet_view_get_grid_lines:
-- * @tree_view: a #PsppSheetView
-- *
-- * Returns which grid lines are enabled in @tree_view.
-- *
-- * Return value: a #PsppSheetViewGridLines value indicating which grid lines
-- * are enabled.
-- *
-- * Since: 2.10
-- */
--PsppSheetViewGridLines
--pspp_sheet_view_get_grid_lines (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), 0);
--
--  return tree_view->priv->grid_lines;
--}
--
--/**
-- * pspp_sheet_view_set_grid_lines:
-- * @tree_view: a #PsppSheetView
-- * @grid_lines: a #PsppSheetViewGridLines value indicating which grid lines to
-- * enable.
-- *
-- * Sets which grid lines to draw in @tree_view.
-- *
-- * Since: 2.10
-- */
--void
--pspp_sheet_view_set_grid_lines (PsppSheetView           *tree_view,
--                            PsppSheetViewGridLines   grid_lines)
--{
--  PsppSheetViewPrivate *priv;
--  PsppSheetViewGridLines old_grid_lines;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  priv = tree_view->priv;
--
--  old_grid_lines = priv->grid_lines;
--  priv->grid_lines = grid_lines;
--  
--  if (old_grid_lines != grid_lines)
--    {
--      gtk_widget_queue_draw (GTK_WIDGET (tree_view));
--      
--      g_object_notify (G_OBJECT (tree_view), "enable-grid-lines");
--    }
--}
--
--/**
-- * pspp_sheet_view_get_special_cells:
-- * @tree_view: a #PsppSheetView
-- *
-- * Returns which grid lines are enabled in @tree_view.
-- *
-- * Return value: a #PsppSheetViewSpecialCells value indicating whether rows in
-- * the sheet view contain special cells.
-- */
--PsppSheetViewSpecialCells
--pspp_sheet_view_get_special_cells (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), 0);
--
--  return tree_view->priv->special_cells;
--}
--
--/**
-- * pspp_sheet_view_set_special_cells:
-- * @tree_view: a #PsppSheetView
-- * @special_cells: a #PsppSheetViewSpecialCells value indicating whether rows in
-- * the sheet view contain special cells.
-- *
-- * Sets whether rows in the sheet view contain special cells, controlling the
-- * rendering of row selections.
-- */
--void
--pspp_sheet_view_set_special_cells (PsppSheetView           *tree_view,
--                            PsppSheetViewSpecialCells   special_cells)
--{
--  PsppSheetViewPrivate *priv;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  priv = tree_view->priv;
--
--  if (priv->special_cells != special_cells)
--    {
--      priv->special_cells = special_cells;
--      gtk_widget_queue_draw (GTK_WIDGET (tree_view));
--      g_object_notify (G_OBJECT (tree_view), "special-cells");
--    }
--}
--
--int
--pspp_sheet_view_get_fixed_height (const PsppSheetView *tree_view)
--{
--  /* XXX (re)calculate fixed_height if necessary */
--  return tree_view->priv->fixed_height;
--}
--
--void
--pspp_sheet_view_set_fixed_height (PsppSheetView *tree_view,
--                                  int fixed_height)
--{
--  g_return_if_fail (fixed_height > 0);
--
--  if (tree_view->priv->fixed_height != fixed_height)
--    {
--      tree_view->priv->fixed_height = fixed_height;
--      g_object_notify (G_OBJECT (tree_view), "fixed-height");
--    }
--  if (!tree_view->priv->fixed_height_set)
--    {
--      tree_view->priv->fixed_height_set = TRUE;
--      g_object_notify (G_OBJECT (tree_view), "fixed-height-set");
--    }
--}
--
--/**
-- * pspp_sheet_view_set_tooltip_row:
-- * @tree_view: a #PsppSheetView
-- * @tooltip: a #GtkTooltip
-- * @path: a #GtkTreePath
-- *
-- * Sets the tip area of @tooltip to be the area covered by the row at @path.
-- * See also pspp_sheet_view_set_tooltip_column() for a simpler alternative.
-- * See also gtk_tooltip_set_tip_area().
-- *
-- * Since: 2.12
-- */
--void
--pspp_sheet_view_set_tooltip_row (PsppSheetView *tree_view,
--                             GtkTooltip  *tooltip,
--                             GtkTreePath *path)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
--
--  pspp_sheet_view_set_tooltip_cell (tree_view, tooltip, path, NULL, NULL);
--}
--
--/**
-- * pspp_sheet_view_set_tooltip_cell:
-- * @tree_view: a #PsppSheetView
-- * @tooltip: a #GtkTooltip
-- * @path: (allow-none): a #GtkTreePath or %NULL
-- * @column: (allow-none): a #PsppSheetViewColumn or %NULL
-- * @cell: (allow-none): a #GtkCellRenderer or %NULL
-- *
-- * Sets the tip area of @tooltip to the area @path, @column and @cell have
-- * in common.  For example if @path is %NULL and @column is set, the tip
-- * area will be set to the full area covered by @column.  See also
-- * gtk_tooltip_set_tip_area().
-- *
-- * See also pspp_sheet_view_set_tooltip_column() for a simpler alternative.
-- *
-- * Since: 2.12
-- */
--void
--pspp_sheet_view_set_tooltip_cell (PsppSheetView       *tree_view,
--                              GtkTooltip        *tooltip,
--                              GtkTreePath       *path,
--                              PsppSheetViewColumn *column,
--                              GtkCellRenderer   *cell)
--{
--  GdkRectangle rect;
--
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--  g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
--  g_return_if_fail (column == NULL || PSPP_IS_SHEET_VIEW_COLUMN (column));
--  g_return_if_fail (cell == NULL || GTK_IS_CELL_RENDERER (cell));
--
--  /* Determine x values. */
--  if (column && cell)
--    {
--      GdkRectangle tmp;
--      gint start, width;
--
--      pspp_sheet_view_get_cell_area (tree_view, path, column, &tmp);
--      pspp_sheet_view_column_cell_get_position (column, cell, &start, &width);
--
--      pspp_sheet_view_convert_bin_window_to_widget_coords (tree_view,
--                                                       tmp.x + start, 0,
--                                                       &rect.x, NULL);
--      rect.width = width;
--    }
--  else if (column)
--    {
--      GdkRectangle tmp;
--
--      pspp_sheet_view_get_background_area (tree_view, NULL, column, &tmp);
--      pspp_sheet_view_convert_bin_window_to_widget_coords (tree_view,
--                                                       tmp.x, 0,
--                                                       &rect.x, NULL);
--      rect.width = tmp.width;
--    }
--  else
--    {
--      GtkAllocation allocation;
--      gtk_widget_get_allocation (GTK_WIDGET (tree_view), &allocation);
--      rect.x = 0;
--      rect.width = allocation.width;
--    }
--
--  /* Determine y values. */
--  if (path)
--    {
--      GdkRectangle tmp;
--
--      pspp_sheet_view_get_background_area (tree_view, path, NULL, &tmp);
--      pspp_sheet_view_convert_bin_window_to_widget_coords (tree_view,
--                                                       0, tmp.y,
--                                                       NULL, &rect.y);
--      rect.height = tmp.height;
--    }
--  else
--    {
--      rect.y = 0;
--      rect.height = gtk_adjustment_get_page_size (tree_view->priv->vadjustment);
--    }
--
--  gtk_tooltip_set_tip_area (tooltip, &rect);
--}
--
--/**
-- * pspp_sheet_view_get_tooltip_context:
-- * @tree_view: a #PsppSheetView
-- * @x: the x coordinate (relative to widget coordinates)
-- * @y: the y coordinate (relative to widget coordinates)
-- * @keyboard_tip: whether this is a keyboard tooltip or not
-- * @model: (allow-none): a pointer to receive a #GtkTreeModel or %NULL
-- * @path: (allow-none): a pointer to receive a #GtkTreePath or %NULL
-- * @iter: (allow-none): a pointer to receive a #GtkTreeIter or %NULL
-- *
-- * This function is supposed to be used in a #GtkWidget::query-tooltip
-- * signal handler for #PsppSheetView.  The @x, @y and @keyboard_tip values
-- * which are received in the signal handler, should be passed to this
-- * function without modification.
-- *
-- * The return value indicates whether there is a tree view row at the given
-- * coordinates (%TRUE) or not (%FALSE) for mouse tooltips.  For keyboard
-- * tooltips the row returned will be the cursor row.  When %TRUE, then any of
-- * @model, @path and @iter which have been provided will be set to point to
-- * that row and the corresponding model.  @x and @y will always be converted
-- * to be relative to @tree_view's bin_window if @keyboard_tooltip is %FALSE.
-- *
-- * Return value: whether or not the given tooltip context points to a row.
-- *
-- * Since: 2.12
-- */
--gboolean
--pspp_sheet_view_get_tooltip_context (PsppSheetView   *tree_view,
--                                 gint          *x,
--                                 gint          *y,
--                                 gboolean       keyboard_tip,
--                                 GtkTreeModel **model,
--                                 GtkTreePath  **path,
--                                 GtkTreeIter   *iter)
--{
--  GtkTreePath *tmppath = NULL;
--
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), FALSE);
--  g_return_val_if_fail (x != NULL, FALSE);
--  g_return_val_if_fail (y != NULL, FALSE);
--
--  if (keyboard_tip)
--    {
--      pspp_sheet_view_get_cursor (tree_view, &tmppath, NULL);
--
--      if (!tmppath)
--      return FALSE;
--    }
--  else
--    {
--      pspp_sheet_view_convert_widget_to_bin_window_coords (tree_view, *x, *y,
--                                                       x, y);
--
--      if (!pspp_sheet_view_get_path_at_pos (tree_view, *x, *y,
--                                        &tmppath, NULL, NULL, NULL))
--      return FALSE;
--    }
--
--  if (model)
--    *model = pspp_sheet_view_get_model (tree_view);
--
--  if (iter)
--    gtk_tree_model_get_iter (pspp_sheet_view_get_model (tree_view),
--                           iter, tmppath);
--
--  if (path)
--    *path = tmppath;
--  else
--    gtk_tree_path_free (tmppath);
--
--  return TRUE;
--}
--
--static gboolean
--pspp_sheet_view_set_tooltip_query_cb (GtkWidget  *widget,
--                                  gint        x,
--                                  gint        y,
--                                  gboolean    keyboard_tip,
--                                  GtkTooltip *tooltip,
--                                  gpointer    data)
--{
--  GValue value = { 0, };
--  GValue transformed = { 0, };
--  GtkTreeIter iter;
--  GtkTreePath *path;
--  GtkTreeModel *model;
--  PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
--
--  if (!pspp_sheet_view_get_tooltip_context (PSPP_SHEET_VIEW (widget),
--                                        &x, &y,
--                                        keyboard_tip,
--                                        &model, &path, &iter))
--    return FALSE;
--
--  gtk_tree_model_get_value (model, &iter,
--                            tree_view->priv->tooltip_column, &value);
--
--  g_value_init (&transformed, G_TYPE_STRING);
--
--  if (!g_value_transform (&value, &transformed))
--    {
--      g_value_unset (&value);
--      gtk_tree_path_free (path);
--
--      return FALSE;
--    }
--
--  g_value_unset (&value);
--
--  if (!g_value_get_string (&transformed))
--    {
--      g_value_unset (&transformed);
--      gtk_tree_path_free (path);
--
--      return FALSE;
--    }
--
--  gtk_tooltip_set_markup (tooltip, g_value_get_string (&transformed));
--  pspp_sheet_view_set_tooltip_row (tree_view, tooltip, path);
--
--  gtk_tree_path_free (path);
--  g_value_unset (&transformed);
--
--  return TRUE;
--}
--
--/**
-- * pspp_sheet_view_set_tooltip_column:
-- * @tree_view: a #PsppSheetView
-- * @column: an integer, which is a valid column number for @tree_view's model
-- *
-- * If you only plan to have simple (text-only) tooltips on full rows, you
-- * can use this function to have #PsppSheetView handle these automatically
-- * for you. @column should be set to the column in @tree_view's model
-- * containing the tooltip texts, or -1 to disable this feature.
-- *
-- * When enabled, #GtkWidget::has-tooltip will be set to %TRUE and
-- * @tree_view will connect a #GtkWidget::query-tooltip signal handler.
-- *
-- * Note that the signal handler sets the text with gtk_tooltip_set_markup(),
-- * so &amp;, &lt;, etc have to be escaped in the text.
-- *
-- * Since: 2.12
-- */
--void
--pspp_sheet_view_set_tooltip_column (PsppSheetView *tree_view,
--                                gint         column)
--{
--  g_return_if_fail (PSPP_IS_SHEET_VIEW (tree_view));
--
--  if (column == tree_view->priv->tooltip_column)
--    return;
--
--  if (column == -1)
--    {
--      g_signal_handlers_disconnect_by_func (tree_view,
--                                          pspp_sheet_view_set_tooltip_query_cb,
--                                          NULL);
--      gtk_widget_set_has_tooltip (GTK_WIDGET (tree_view), FALSE);
--    }
--  else
--    {
--      if (tree_view->priv->tooltip_column == -1)
--        {
--          g_signal_connect (tree_view, "query-tooltip",
--                          G_CALLBACK (pspp_sheet_view_set_tooltip_query_cb), NULL);
--          gtk_widget_set_has_tooltip (GTK_WIDGET (tree_view), TRUE);
--        }
--    }
--
--  tree_view->priv->tooltip_column = column;
--  g_object_notify (G_OBJECT (tree_view), "tooltip-column");
--}
--
--/**
-- * pspp_sheet_view_get_tooltip_column:
-- * @tree_view: a #PsppSheetView
-- *
-- * Returns the column of @tree_view's model which is being used for
-- * displaying tooltips on @tree_view's rows.
-- *
-- * Return value: the index of the tooltip column that is currently being
-- * used, or -1 if this is disabled.
-- *
-- * Since: 2.12
-- */
--gint
--pspp_sheet_view_get_tooltip_column (PsppSheetView *tree_view)
--{
--  g_return_val_if_fail (PSPP_IS_SHEET_VIEW (tree_view), 0);
--
--  return tree_view->priv->tooltip_column;
--}
--
--gboolean
--_gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
--                                  GValue                *return_accu,
--                                  const GValue          *handler_return,
--                                  gpointer               dummy)
--{
--  gboolean continue_emission;
--  gboolean signal_handled;
--  
--  signal_handled = g_value_get_boolean (handler_return);
--  g_value_set_boolean (return_accu, signal_handled);
--  continue_emission = !signal_handled;
--  
--  return continue_emission;
--}
--
--
--GType
--pspp_sheet_view_grid_lines_get_type (void)
--{
--    static GType etype = 0;
--    if (G_UNLIKELY(etype == 0)) {
--        static const GEnumValue values[] = {
--            { PSPP_SHEET_VIEW_GRID_LINES_NONE, "PSPP_SHEET_VIEW_GRID_LINES_NONE", "none" },
--            { PSPP_SHEET_VIEW_GRID_LINES_HORIZONTAL, "PSPP_SHEET_VIEW_GRID_LINES_HORIZONTAL", "horizontal" },
--            { PSPP_SHEET_VIEW_GRID_LINES_VERTICAL, "PSPP_SHEET_VIEW_GRID_LINES_VERTICAL", "vertical" },
--            { PSPP_SHEET_VIEW_GRID_LINES_BOTH, "PSPP_SHEET_VIEW_GRID_LINES_BOTH", "both" },
--            { 0, NULL, NULL }
--        };
--        etype = g_enum_register_static (g_intern_static_string ("PsppSheetViewGridLines"), values);
--    }
--    return etype;
--}
--
--GType
--pspp_sheet_view_special_cells_get_type (void)
--{
--    static GType etype = 0;
--    if (G_UNLIKELY(etype == 0)) {
--        static const GEnumValue values[] = {
--            { PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT, "PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT", "detect" },
--            { PSPP_SHEET_VIEW_SPECIAL_CELLS_YES, "PSPP_SHEET_VIEW_SPECIAL_CELLS_YES", "yes" },
--            { PSPP_SHEET_VIEW_SPECIAL_CELLS_NO, "PSPP_SHEET_VIEW_SPECIAL_CELLS_NO", "no" },
--            { 0, NULL, NULL }
--        };
--        etype = g_enum_register_static (g_intern_static_string ("PsppSheetViewSpecialCells"), values);
--    }
--    return etype;
--}
diff --cc src/ui/gui/pspp-sheet-view.h
index 8941b8946bd8245d0f7055cf16d0af6f6714ae98,8941b8946bd8245d0f7055cf16d0af6f6714ae98..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,432 -1,432 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--/* gtktreeview.h
-- * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
-- *
-- * This library is free software; you can redistribute it and/or
-- * modify it under the terms of the GNU Library 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
-- * Library General Public License for more details.
-- *
-- * You should have received a copy of the GNU Library 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.
-- */
--
--#ifndef __PSPP_SHEET_VIEW_H__
--#define __PSPP_SHEET_VIEW_H__
--
--#include <gtk/gtk.h>
--#include "ui/gui/pspp-sheet-view-column.h"
--
--G_BEGIN_DECLS
--
--
--typedef enum
--{
--  PSPP_SHEET_VIEW_GRID_LINES_NONE,
--  PSPP_SHEET_VIEW_GRID_LINES_HORIZONTAL,
--  PSPP_SHEET_VIEW_GRID_LINES_VERTICAL,
--  PSPP_SHEET_VIEW_GRID_LINES_BOTH
--} PsppSheetViewGridLines;
--
--GType pspp_sheet_view_grid_lines_get_type (void) G_GNUC_CONST;
--#define PSPP_TYPE_SHEET_VIEW_GRID_LINES (pspp_sheet_view_grid_lines_get_type ())
--
--/* A "special cell" is a cell that is editable or activatable.  When a row that
-- * contains a special cell is selected, the cursor is drawn around a single
-- * cell; when other rows are selected, the cursor is drawn around the entire
-- * row.
-- *
-- * With the default of "detect", whether a given row contains a special cell is
-- * detected automatically.  This is the best choice most of the time.  For
-- * sheet views that contain more than 100 columns, an explicit "yes" or "no"
-- * improves performance. */
--typedef enum
--{
--  PSPP_SHEET_VIEW_SPECIAL_CELLS_DETECT,
--  PSPP_SHEET_VIEW_SPECIAL_CELLS_YES,
--  PSPP_SHEET_VIEW_SPECIAL_CELLS_NO,
--} PsppSheetViewSpecialCells;
--
--GType pspp_sheet_view_special_cells_get_type (void) G_GNUC_CONST;
--#define PSPP_TYPE_SHEET_VIEW_SPECIAL_CELLS (pspp_sheet_view_special_cells_get_type ())
--
--typedef enum
--{
--  /* drop before/after this row */
--  PSPP_SHEET_VIEW_DROP_BEFORE,
--  PSPP_SHEET_VIEW_DROP_AFTER,
--  /* drop as a child of this row (with fallback to before or after
--   * if into is not possible)
--   */
--  PSPP_SHEET_VIEW_DROP_INTO_OR_BEFORE,
--  PSPP_SHEET_VIEW_DROP_INTO_OR_AFTER
--} PsppSheetViewDropPosition;
--
--typedef enum
--{
--  PSPP_SHEET_SELECT_MODE_TOGGLE = 1 << 0,
--  PSPP_SHEET_SELECT_MODE_EXTEND = 1 << 1
--}
--PsppSheetSelectMode;
--
--#define PSPP_TYPE_SHEET_VIEW          (pspp_sheet_view_get_type ())
--#define PSPP_SHEET_VIEW(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPP_TYPE_SHEET_VIEW, PsppSheetView))
--#define PSPP_SHEET_VIEW_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass), PSPP_TYPE_SHEET_VIEW, PsppSheetViewClass))
--#define PSPP_IS_SHEET_VIEW(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPP_TYPE_SHEET_VIEW))
--#define PSPP_IS_SHEET_VIEW_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPP_TYPE_SHEET_VIEW))
--#define PSPP_SHEET_VIEW_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PSPP_TYPE_SHEET_VIEW, PsppSheetViewClass))
--
--typedef struct _PsppSheetView           PsppSheetView;
--typedef struct _PsppSheetViewClass      PsppSheetViewClass;
--typedef struct _PsppSheetViewPrivate    PsppSheetViewPrivate;
--typedef struct _PsppSheetSelection      PsppSheetSelection;
--typedef struct _PsppSheetSelectionClass PsppSheetSelectionClass;
--
--struct _PsppSheetView
--{
--  GtkContainer parent;
--
--  PsppSheetViewPrivate *PSEAL (priv);
--
--  gboolean dispose_has_run ;
--};
--
--struct _PsppSheetViewClass
--{
--  GtkContainerClass parent_class;
--
--  void     (* set_scroll_adjustments)     (PsppSheetView       *tree_view,
--                                         GtkAdjustment     *hadjustment,
--                                         GtkAdjustment     *vadjustment);
--  void     (* row_activated)              (PsppSheetView       *tree_view,
--                                         GtkTreePath       *path,
--                                         PsppSheetViewColumn *column);
--  void     (* columns_changed)            (PsppSheetView       *tree_view);
--  void     (* cursor_changed)             (PsppSheetView       *tree_view);
--
--  /* Key Binding signals */
--  gboolean (* move_cursor)                (PsppSheetView       *tree_view,
--                                         GtkMovementStep    step,
--                                         gint               count);
--  gboolean (* select_all)                 (PsppSheetView       *tree_view);
--  gboolean (* unselect_all)               (PsppSheetView       *tree_view);
--  gboolean (* select_cursor_row)          (PsppSheetView       *tree_view,
--                                         gboolean           start_editing,
--                                           PsppSheetSelectMode mode);
--  gboolean (* toggle_cursor_row)          (PsppSheetView       *tree_view);
--  gboolean (* select_cursor_parent)       (PsppSheetView       *tree_view);
--  gboolean (* start_interactive_search)   (PsppSheetView       *tree_view);
--
--  /* Padding for future expansion */
--  void (*_gtk_reserved0) (void);
--  void (*_gtk_reserved1) (void);
--  void (*_gtk_reserved2) (void);
--  void (*_gtk_reserved3) (void);
--  void (*_gtk_reserved4) (void);
--};
--
--
--typedef gboolean (* PsppSheetViewColumnDropFunc) (PsppSheetView             *tree_view,
--                                              PsppSheetViewColumn       *column,
--                                              PsppSheetViewColumn       *prev_column,
--                                              PsppSheetViewColumn       *next_column,
--                                              gpointer                 data);
--typedef void     (* PsppSheetViewMappingFunc)    (PsppSheetView             *tree_view,
--                                              GtkTreePath             *path,
--                                              gpointer                 user_data);
--typedef gboolean (*PsppSheetViewSearchEqualFunc) (GtkTreeModel            *model,
--                                              gint                     column,
--                                              const gchar             *key,
--                                              GtkTreeIter             *iter,
--                                              gpointer                 search_data);
--typedef void     (*PsppSheetViewSearchPositionFunc) (PsppSheetView  *tree_view,
--                                                 GtkWidget    *search_dialog,
--                                                 gpointer      user_data);
--
--
--/* Creators */
--GType                  pspp_sheet_view_get_type                      (void) G_GNUC_CONST;
--GtkWidget             *pspp_sheet_view_new                           (void);
--GtkWidget             *pspp_sheet_view_new_with_model                (GtkTreeModel              *model);
--
--/* Accessors */
--GtkTreeModel          *pspp_sheet_view_get_model                     (PsppSheetView               *tree_view);
--void                   pspp_sheet_view_set_model                     (PsppSheetView               *tree_view,
--                                                                  GtkTreeModel              *model);
--PsppSheetSelection      *pspp_sheet_view_get_selection                 (PsppSheetView               *tree_view);
--GtkAdjustment         *pspp_sheet_view_get_hadjustment               (PsppSheetView               *tree_view);
--void                   pspp_sheet_view_set_hadjustment               (PsppSheetView               *tree_view,
--                                                                  GtkAdjustment             *adjustment);
--GtkAdjustment         *pspp_sheet_view_get_vadjustment               (PsppSheetView               *tree_view);
--void                   pspp_sheet_view_set_vadjustment               (PsppSheetView               *tree_view,
--                                                                  GtkAdjustment             *adjustment);
--gboolean               pspp_sheet_view_get_headers_visible           (PsppSheetView               *tree_view);
--void                   pspp_sheet_view_set_headers_visible           (PsppSheetView               *tree_view,
--                                                                  gboolean                   headers_visible);
--void                   pspp_sheet_view_columns_autosize              (PsppSheetView               *tree_view);
--gboolean               pspp_sheet_view_get_headers_clickable         (PsppSheetView *tree_view);
--void                   pspp_sheet_view_set_headers_clickable         (PsppSheetView               *tree_view,
--                                                                  gboolean                   setting);
--void                   pspp_sheet_view_set_rules_hint                (PsppSheetView               *tree_view,
--                                                                  gboolean                   setting);
--gboolean               pspp_sheet_view_get_rules_hint                (PsppSheetView               *tree_view);
--
--/* Column funtions */
--gint                   pspp_sheet_view_append_column                 (PsppSheetView               *tree_view,
--                                                                  PsppSheetViewColumn         *column);
--gint                   pspp_sheet_view_remove_column                 (PsppSheetView               *tree_view,
--                                                                  PsppSheetViewColumn         *column);
--gint                   pspp_sheet_view_insert_column                 (PsppSheetView               *tree_view,
--                                                                  PsppSheetViewColumn         *column,
--                                                                  gint                       position);
--gint                   pspp_sheet_view_insert_column_with_attributes (PsppSheetView               *tree_view,
--                                                                  gint                       position,
--                                                                  const gchar               *title,
--                                                                  GtkCellRenderer           *cell,
--                                                                  ...) G_GNUC_NULL_TERMINATED;
--gint                   pspp_sheet_view_insert_column_with_data_func  (PsppSheetView               *tree_view,
--                                                                  gint                       position,
--                                                                  const gchar               *title,
--                                                                  GtkCellRenderer           *cell,
--                                                                    PsppSheetCellDataFunc        func,
--                                                                    gpointer                   data,
--                                                                    GDestroyNotify             dnotify);
--PsppSheetViewColumn     *pspp_sheet_view_get_column                    (PsppSheetView               *tree_view,
--                                                                  gint                       n);
--GList                 *pspp_sheet_view_get_columns                   (PsppSheetView               *tree_view);
--void                   pspp_sheet_view_move_column_after             (PsppSheetView               *tree_view,
--                                                                  PsppSheetViewColumn         *column,
--                                                                  PsppSheetViewColumn         *base_column);
--void                   pspp_sheet_view_set_column_drag_function      (PsppSheetView               *tree_view,
--                                                                  PsppSheetViewColumnDropFunc  func,
--                                                                  gpointer                   user_data,
--                                                                  GDestroyNotify             destroy);
--
--/* Actions */
--void                   pspp_sheet_view_scroll_to_point               (PsppSheetView               *tree_view,
--                                                                  gint                       tree_x,
--                                                                  gint                       tree_y);
--void                   pspp_sheet_view_scroll_to_cell                (PsppSheetView               *tree_view,
--                                                                  GtkTreePath               *path,
--                                                                  PsppSheetViewColumn         *column,
--                                                                  gboolean                   use_align,
--                                                                  gfloat                     row_align,
--                                                                  gfloat                     col_align);
--void                   pspp_sheet_view_row_activated                 (PsppSheetView               *tree_view,
--                                                                  GtkTreePath               *path,
--                                                                  PsppSheetViewColumn         *column);
--void                   pspp_sheet_view_set_reorderable               (PsppSheetView               *tree_view,
--                                                                  gboolean                   reorderable);
--gboolean               pspp_sheet_view_get_reorderable               (PsppSheetView               *tree_view);
--void                   pspp_sheet_view_set_cursor                    (PsppSheetView               *tree_view,
--                                                                  GtkTreePath               *path,
--                                                                  PsppSheetViewColumn         *focus_column,
--                                                                  gboolean                   start_editing);
--void                   pspp_sheet_view_set_cursor_on_cell            (PsppSheetView               *tree_view,
--                                                                  GtkTreePath               *path,
--                                                                  PsppSheetViewColumn         *focus_column,
--                                                                  GtkCellRenderer           *focus_cell,
--                                                                  gboolean                   start_editing);
--void                   pspp_sheet_view_get_cursor                    (PsppSheetView               *tree_view,
--                                                                  GtkTreePath              **path,
--                                                                  PsppSheetViewColumn        **focus_column);
--
--
--/* Layout information */
--GdkWindow             *pspp_sheet_view_get_bin_window                (PsppSheetView               *tree_view);
--gboolean               pspp_sheet_view_get_path_at_pos               (PsppSheetView               *tree_view,
--                                                                  gint                       x,
--                                                                  gint                       y,
--                                                                  GtkTreePath              **path,
--                                                                  PsppSheetViewColumn        **column,
--                                                                  gint                      *cell_x,
--                                                                  gint                      *cell_y);
--void                   pspp_sheet_view_get_cell_area                 (PsppSheetView               *tree_view,
--                                                                  GtkTreePath               *path,
--                                                                  PsppSheetViewColumn         *column,
--                                                                  GdkRectangle              *rect);
--void                   pspp_sheet_view_get_background_area           (PsppSheetView               *tree_view,
--                                                                  GtkTreePath               *path,
--                                                                  PsppSheetViewColumn         *column,
--                                                                  GdkRectangle              *rect);
--void                   pspp_sheet_view_get_visible_rect              (PsppSheetView               *tree_view,
--                                                                  GdkRectangle              *visible_rect);
--
--#ifndef GTK_DISABLE_DEPRECATED
--void                   pspp_sheet_view_widget_to_tree_coords         (PsppSheetView               *tree_view,
--                                                                  gint                       wx,
--                                                                  gint                       wy,
--                                                                  gint                      *tx,
--                                                                  gint                      *ty);
--void                   pspp_sheet_view_tree_to_widget_coords         (PsppSheetView               *tree_view,
--                                                                  gint                       tx,
--                                                                  gint                       ty,
--                                                                  gint                      *wx,
--                                                                  gint                      *wy);
--#endif /* !GTK_DISABLE_DEPRECATED */
--gboolean               pspp_sheet_view_get_visible_range             (PsppSheetView               *tree_view,
--                                                                  GtkTreePath              **start_path,
--                                                                  GtkTreePath              **end_path);
--
--/* Drag-and-Drop support */
--void                   pspp_sheet_view_enable_model_drag_source      (PsppSheetView               *tree_view,
--                                                                  GdkModifierType            start_button_mask,
--                                                                  const GtkTargetEntry      *targets,
--                                                                  gint                       n_targets,
--                                                                  GdkDragAction              actions);
--void                   pspp_sheet_view_enable_model_drag_dest        (PsppSheetView               *tree_view,
--                                                                  const GtkTargetEntry      *targets,
--                                                                  gint                       n_targets,
--                                                                  GdkDragAction              actions);
--void                   pspp_sheet_view_unset_rows_drag_source        (PsppSheetView               *tree_view);
--void                   pspp_sheet_view_unset_rows_drag_dest          (PsppSheetView               *tree_view);
--
--
--/* These are useful to implement your own custom stuff. */
--void                   pspp_sheet_view_set_drag_dest_row             (PsppSheetView               *tree_view,
--                                                                  GtkTreePath               *path,
--                                                                  PsppSheetViewDropPosition    pos);
--void                   pspp_sheet_view_get_drag_dest_row             (PsppSheetView               *tree_view,
--                                                                  GtkTreePath              **path,
--                                                                  PsppSheetViewDropPosition   *pos);
--gboolean               pspp_sheet_view_get_dest_row_at_pos           (PsppSheetView               *tree_view,
--                                                                  gint                       drag_x,
--                                                                  gint                       drag_y,
--                                                                  GtkTreePath              **path,
--                                                                  PsppSheetViewDropPosition   *pos);
--
--/* Interactive search */
--void                       pspp_sheet_view_set_enable_search     (PsppSheetView                *tree_view,
--                                                              gboolean                    enable_search);
--gboolean                   pspp_sheet_view_get_enable_search     (PsppSheetView                *tree_view);
--gint                       pspp_sheet_view_get_search_column     (PsppSheetView                *tree_view);
--void                       pspp_sheet_view_set_search_column     (PsppSheetView                *tree_view,
--                                                              gint                        column);
--PsppSheetViewSearchEqualFunc pspp_sheet_view_get_search_equal_func (PsppSheetView                *tree_view);
--void                       pspp_sheet_view_set_search_equal_func (PsppSheetView                *tree_view,
--                                                              PsppSheetViewSearchEqualFunc  search_equal_func,
--                                                              gpointer                    search_user_data,
--                                                              GDestroyNotify              search_destroy);
--
--GtkEntry                     *pspp_sheet_view_get_search_entry         (PsppSheetView                   *tree_view);
--void                          pspp_sheet_view_set_search_entry         (PsppSheetView                   *tree_view,
--                                                                    GtkEntry                      *entry);
--PsppSheetViewSearchPositionFunc pspp_sheet_view_get_search_position_func (PsppSheetView                   *tree_view);
--void                          pspp_sheet_view_set_search_position_func (PsppSheetView                   *tree_view,
--                                                                    PsppSheetViewSearchPositionFunc  func,
--                                                                    gpointer                       data,
--                                                                    GDestroyNotify                 destroy);
--
--/* Convert between the different coordinate systems */
--void pspp_sheet_view_convert_widget_to_tree_coords       (PsppSheetView *tree_view,
--                                                      gint         wx,
--                                                      gint         wy,
--                                                      gint        *tx,
--                                                      gint        *ty);
--void pspp_sheet_view_convert_tree_to_widget_coords       (PsppSheetView *tree_view,
--                                                      gint         tx,
--                                                      gint         ty,
--                                                      gint        *wx,
--                                                      gint        *wy);
--void pspp_sheet_view_convert_widget_to_bin_window_coords (PsppSheetView *tree_view,
--                                                      gint         wx,
--                                                      gint         wy,
--                                                      gint        *bx,
--                                                      gint        *by);
--void pspp_sheet_view_convert_bin_window_to_widget_coords (PsppSheetView *tree_view,
--                                                      gint         bx,
--                                                      gint         by,
--                                                      gint        *wx,
--                                                      gint        *wy);
--void pspp_sheet_view_convert_tree_to_bin_window_coords   (PsppSheetView *tree_view,
--                                                      gint         tx,
--                                                      gint         ty,
--                                                      gint        *bx,
--                                                      gint        *by);
--void pspp_sheet_view_convert_bin_window_to_tree_coords   (PsppSheetView *tree_view,
--                                                      gint         bx,
--                                                      gint         by,
--                                                      gint        *tx,
--                                                      gint        *ty);
--
--/* This function should really never be used.  It is just for use by ATK.
-- */
--typedef void (* PsppSheetDestroyCountFunc)  (PsppSheetView             *tree_view,
--                                         GtkTreePath             *path,
--                                         gint                     children,
--                                         gpointer                 user_data);
--void pspp_sheet_view_set_destroy_count_func (PsppSheetView             *tree_view,
--                                         PsppSheetDestroyCountFunc  func,
--                                         gpointer                 data,
--                                         GDestroyNotify           destroy);
--
--void     pspp_sheet_view_set_hover_selection   (PsppSheetView          *tree_view,
--                                            gboolean              hover);
--gboolean pspp_sheet_view_get_hover_selection   (PsppSheetView          *tree_view);
--void     pspp_sheet_view_set_rubber_banding    (PsppSheetView          *tree_view,
--                                            gboolean              enable);
--gboolean pspp_sheet_view_get_rubber_banding    (PsppSheetView          *tree_view);
--
--gboolean pspp_sheet_view_is_rubber_banding_active (PsppSheetView       *tree_view);
--
--PsppSheetViewGridLines        pspp_sheet_view_get_grid_lines         (PsppSheetView                *tree_view);
--void                        pspp_sheet_view_set_grid_lines         (PsppSheetView                *tree_view,
--                                                                PsppSheetViewGridLines        grid_lines);
--
--PsppSheetViewSpecialCells pspp_sheet_view_get_special_cells (PsppSheetView                *tree_view);
--void                        pspp_sheet_view_set_special_cells (PsppSheetView                *tree_view,
--                                                               PsppSheetViewSpecialCells);
--
--int           pspp_sheet_view_get_fixed_height (const PsppSheetView *);
--void          pspp_sheet_view_set_fixed_height (PsppSheetView *,
--                                                int fixed_height);
--
--/* Convenience functions for setting tooltips */
--void          pspp_sheet_view_set_tooltip_row    (PsppSheetView       *tree_view,
--                                              GtkTooltip        *tooltip,
--                                              GtkTreePath       *path);
--void          pspp_sheet_view_set_tooltip_cell   (PsppSheetView       *tree_view,
--                                              GtkTooltip        *tooltip,
--                                              GtkTreePath       *path,
--                                              PsppSheetViewColumn *column,
--                                              GtkCellRenderer   *cell);
--gboolean      pspp_sheet_view_get_tooltip_context(PsppSheetView       *tree_view,
--                                              gint              *x,
--                                              gint              *y,
--                                              gboolean           keyboard_tip,
--                                              GtkTreeModel     **model,
--                                              GtkTreePath      **path,
--                                              GtkTreeIter       *iter);
--void          pspp_sheet_view_set_tooltip_column (PsppSheetView       *tree_view,
--                                              gint               column);
--gint          pspp_sheet_view_get_tooltip_column (PsppSheetView       *tree_view);
--
--void pspp_sheet_view_stop_editing (PsppSheetView *tree_view,
--                                   gboolean     cancel_editing);
--
--G_END_DECLS
--
--
--#endif /* __PSPP_SHEET_VIEW_H__ */
diff --cc src/ui/gui/pspp-widget-facade.c
index be785dc133c4ca69aa0134a95975b398ff0df5a5,be785dc133c4ca69aa0134a95975b398ff0df5a5..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,355 -1,355 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2011, 2012, 2014 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--#include <config.h>
--
--#include "pspp-widget-facade.h"
--
--#include <math.h>
--#include <stdarg.h>
--#include <stdlib.h>
--#include <string.h>
--
--static void
--inset_rectangle (const GdkRectangle *src,
--                 const GtkBorder *inset,
--                 GdkRectangle *dst)
--{
--  dst->x = src->x + inset->left;
--  dst->y = src->y + inset->top;
--  dst->width = MAX (1, src->width - inset->left - inset->right);
--  dst->height = MAX (1, src->height - inset->top - inset->bottom);
--}
--
--static void
--thicken_border (gint x, gint y, GtkBorder *border)
--{
--  border->left += x;
--  border->right += x;
--  border->top += y;
--  border->bottom += y;
--}
--
--GtkStyle *
--facade_get_style (GtkWidget *base,
--                  GType type1,
--                  ...)
--{
--  GString path, class_path;
--  GType final_type;
--  GtkStyle *style;
--  va_list args;
--  GType type;
--
--  gtk_widget_path (base, NULL, &path.str, NULL);
--  path.len = path.allocated_len = strlen (path.str);
--
--  gtk_widget_class_path (base, NULL, &class_path.str, NULL);
--  class_path.len = class_path.allocated_len = strlen (class_path.str);
--
--  va_start (args, type1);
--  for (type = final_type = type1; type != 0; type = va_arg (args, GType))
--    {
--      const gchar *type_name = g_type_name (type);
--      g_string_append_printf (&path, ".%s", type_name);
--      g_string_append_printf (&class_path, ".%s", type_name);
--      final_type = type;
--    }
--  va_end (args);
--
--  style = gtk_rc_get_style_by_paths (gtk_widget_get_settings (base),
--                                     path.str, class_path.str, final_type);
--
--  free (path.str);
--  free (class_path.str);
--
--  return style;
--}
--
--void
--facade_hbox_get_base_size_request (gint border_width,
--                                   gint spacing,
--                                   gint n_children,
--                                   GtkRequisition *request)
--{
--  request->width = border_width * 2;
--  if (n_children > 1)
--    request->width += spacing * (n_children - 1);
--
--  request->height = border_width * 2;
--}
--
--void
--facade_hbox_add_child_size_request (gint hbox_border_width,
--                                    const GtkRequisition *child_request,
--                                    gint child_padding,
--                                    GtkRequisition *request)
--{
--  request->width += child_request->width + child_padding * 2;
--  request->height = MAX (request->height,
--                         hbox_border_width * 2 + child_request->height);
--}
--
--void
--facade_arrow_get_size_request (gint xpad,
--                               gint ypad,
--                               GtkRequisition *request)
--{
--#define MIN_ARROW_SIZE 15
--  request->width = MIN_ARROW_SIZE + xpad * 2;
--  request->height = MIN_ARROW_SIZE + ypad * 2;
--}
--
--void
--facade_alignment_get_size_request (gint border_width,
--                                   gint padding_left,
--                                   gint padding_right,
--                                   gint padding_top,
--                                   gint padding_bottom,
--                                   const GtkRequisition *child_request,
--                                   GtkRequisition *request)
--{
--  request->width = (border_width * 2 + padding_left + padding_right
--                    + child_request->width);
--  request->height = (border_width * 2 + padding_top + padding_bottom
--                     + child_request->height);
--}
--
--void
--facade_label_get_size_request (gint xpad,
--                               gint ypad,
--                               GtkWidget *base,
--                               const char *text,
--                               GtkRequisition *request)
--{
--  PangoLayout *layout;
--
--  layout = facade_label_get_layout (base, text);
--  facade_label_get_size_request_from_layout (xpad, ypad, layout, request);
--  g_object_unref (layout);
--}
--
--void
--facade_label_get_size_request_from_layout (gint xpad,
--                                           gint ypad,
--                                           PangoLayout *layout,
--                                           GtkRequisition *request)
--{
--  PangoRectangle logical_rect;
--
--  pango_layout_get_extents (layout, NULL, &logical_rect);
--  request->width = xpad * 2 + PANGO_PIXELS (logical_rect.width);
--  request->height = ypad * 2 + PANGO_PIXELS (logical_rect.height);
--}
--
--PangoLayout *
--facade_label_get_layout (GtkWidget *base,
--                         const char *text)
--{
--  PangoAlignment alignment;
--  PangoLayout *layout;
--  gboolean rtl;
--
--  rtl = gtk_widget_get_direction (base) == GTK_TEXT_DIR_RTL;
--  alignment = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
--
--  layout = gtk_widget_create_pango_layout (base, text);
--  pango_layout_set_alignment (layout, alignment);
--
--  return layout;
--}
--
--static void
--facade_button_get_inner_border (GtkStyle *button_style,
--                                GtkBorder *inner_border)
--{
--  GtkBorder *tmp_border;
--
--  gtk_style_get (button_style, GTK_TYPE_BUTTON,
--                 "inner-border", &tmp_border,
--                 NULL);
--
--  if (tmp_border)
--    {
--      *inner_border = *tmp_border;
--      gtk_border_free (tmp_border);
--    }
--  else
--    {
--      static const GtkBorder default_inner_border = { 1, 1, 1, 1 };
--      *inner_border = default_inner_border;
--    }
--}
--
--void
--facade_button_get_size_request (gint border_width,
--                                GtkWidget *base,
--                                GtkStyle *button_style,
--                                const GtkRequisition *child_request,
--                                GtkRequisition *request)
--{
--  GtkBorder inner_border;
--  gint common_width;
--  gint focus_width;
--  gint focus_pad;
--
--  gtk_style_get (button_style, GTK_TYPE_BUTTON,
--                 "focus-line-width", &focus_width,
--                 "focus-padding", &focus_pad,
--                 NULL);
--  facade_button_get_inner_border (button_style, &inner_border);
--
--  common_width = 2 * (border_width + focus_width + focus_pad);
--  request->width = (common_width
--                    + 2 * button_style->xthickness
--                    + inner_border.left + inner_border.right
--                    + child_request->width);
--  request->height = (common_width
--                     + 2 * button_style->ythickness
--                     + inner_border.top + inner_border.bottom
--                     + child_request->height);
--}
--
--void
--facade_button_get_focus_inset (gint border_width,
--                               GtkWidget *base,
--                               GtkStyle *button_style,
--                               GtkBorder *focus_inset)
--{
--  facade_button_get_inner_border (button_style, focus_inset);
--  thicken_border (border_width + button_style->xthickness,
--                  border_width + button_style->ythickness,
--                  focus_inset);
--}
--
--static void
--facade_button_get_label_inset (gint border_width,
--                               GtkWidget *base,
--                               GtkStyle *button_style,
--                               GtkBorder *label_inset)
--{
--  gint focus_width;
--  gint focus_pad;
--
--  facade_button_get_focus_inset (border_width, base, button_style,
--                                 label_inset);
--
--  gtk_style_get (button_style, GTK_TYPE_BUTTON,
--                 "focus-line-width", &focus_width,
--                 "focus-padding", &focus_pad,
--                 NULL);
--  thicken_border (focus_width + focus_pad,
--                  focus_width + focus_pad,
--                  label_inset);
--}
--
--static void
--get_layout_location (GtkWidget *base,
--                     const GdkRectangle *label_area,
--                     PangoLayout *layout,
--                     gint xpad,
--                     gint ypad,
--                     gfloat xalign,
--                     gfloat yalign,
--                     gint *x,
--                     gint *y)
--{
--  PangoRectangle logical;
--  GtkRequisition req;
--
--  if (gtk_widget_get_direction (base) == GTK_TEXT_DIR_RTL)
--    xalign = 1.0 - xalign;
--
--  pango_layout_get_pixel_extents (layout, NULL, &logical);
--
--  facade_label_get_size_request_from_layout (xpad, ypad, layout, &req);
--
--  *x = floor (label_area->x + xpad + xalign * (label_area->width - req.width));
--
--  if (gtk_widget_get_direction (base) == GTK_TEXT_DIR_LTR)
--    *x = MAX (*x, label_area->x + xpad);
--  else
--    *x = MIN (*x, label_area->x + label_area->width - xpad);
--  *x -= logical.x;
--
--  /* bgo#315462 - For single-line labels, *do* align the requisition with
--   * respect to the allocation, even if we are under-allocated.  For multi-line
--   * labels, always show the top of the text when they are under-allocated.
--   * The rationale is this:
--   *
--   * - Single-line labels appear in GtkButtons, and it is very easy to get them
--   *   to be smaller than their requisition.  The button may clip the label,
--   *   but the label will still be able to show most of itself and the focus
--   *   rectangle.  Also, it is fairly easy to read a single line of clipped
--   *   text.
--   *
--   * - Multi-line labels should not be clipped to showing "something in the
--   *   middle".  You want to read the first line, at least, to get some
--   *   context.
--   */
--  if (pango_layout_get_line_count (layout) == 1)
--    *y = floor (label_area->y + ypad
--                + (label_area->height - req.height) * yalign);
--  else
--    *y = floor (label_area->y + ypad
--                + MAX (((label_area->height - req.height) * yalign),
--                       0));
--}
--
--void
--facade_button_render (GtkWidget *base,
--                      cairo_t *cr,
--                      const GdkRectangle *button_area,
--                      gint border_width,
--                      GtkStyle *button_style,
--                      GtkStateType state_type,
--
--                      GtkStyle *label_style,
--                      const gchar *label,
--                      gint xpad,
--                      gint ypad,
--                      gfloat xalign,
--                      gfloat yalign)
--{
--  GdkRectangle label_area;
--  PangoLayout *layout;
--  GtkBorder inset;
--  gint x, y;
--
--  /* Paint the button. */
--  gtk_paint_box (button_style, cr,
--                 state_type,
--                 GTK_SHADOW_OUT, base, "button",
--                 button_area->x + border_width,
--                 button_area->y + border_width,
--                 button_area->width - border_width * 2,
--                 button_area->height - border_width * 2);
--
--  /* Figure out where the label should go. */
--  facade_button_get_label_inset (border_width, base, button_style, &inset);
--  inset_rectangle (button_area, &inset, &label_area);
--
--  /* Paint the label. */
--  layout = facade_label_get_layout (base, label);
--  get_layout_location (base, &label_area, layout, xpad, ypad, xalign, yalign,
--                       &x, &y);
--
--  gtk_paint_layout (label_style, cr, state_type, FALSE, 
--                    base, "label", x, y, layout);
--
--  g_object_unref (layout);
--}
--
diff --cc src/ui/gui/pspp-widget-facade.h
index 6705185f7fcdc3f2524243ca6658b5dcbf6701b6,6705185f7fcdc3f2524243ca6658b5dcbf6701b6..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,85 -1,85 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2011, 2012 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--#ifndef FACADE_WIDGET_FACADE_H
--#define FACADE_WIDGET_FACADE_H 1
--
--#include <gtk/gtk.h>
--
--G_BEGIN_DECLS
--
--GtkStyle *facade_get_style (GtkWidget *base, GType, ...);
--
--void facade_hbox_get_base_size_request (gint border_width,
--                                        gint spacing,
--                                        gint n_children,
--                                        GtkRequisition *);
--void facade_hbox_add_child_size_request (gint hbox_border_width,
--                                         const GtkRequisition *child_request,
--                                         gint child_padding,
--                                         GtkRequisition *);
--
--void facade_arrow_get_size_request (gint xpad,
--                                    gint ypad,
--                                    GtkRequisition *);
--
--
--void facade_alignment_get_size_request (gint border_width,
--                                        gint padding_left,
--                                        gint padding_right,
--                                        gint padding_top,
--                                        gint padding_bottom,
--                                        const GtkRequisition *child_request,
--                                        GtkRequisition *);
--
--void facade_label_get_size_request (gint xpad,
--                                    gint ypad,
--                                    GtkWidget *base,
--                                    const char *text,
--                                    GtkRequisition *);
--void facade_label_get_size_request_from_layout (gint xpad,
--                                                gint ypad,
--                                                PangoLayout *,
--                                                GtkRequisition *);
--PangoLayout *facade_label_get_layout (GtkWidget *base,
--                                      const char *text);
--
--void facade_button_get_size_request (gint border_width,
--                                     GtkWidget *base,
--                                     GtkStyle *button_style,
--                                     const GtkRequisition *child_request,
--                                     GtkRequisition *);
--void facade_button_render (GtkWidget *base,
--                           cairo_t *cr,
--                           const GdkRectangle *button_area,
--                           gint border_width,
--                           GtkStyle *button_style,
--                           GtkStateType state_type,
--
--                           GtkStyle *label_style,
--                           const gchar *label,
--                           gint xpad,
--                           gint ypad,
--                           gfloat xalign,
--                           gfloat yalign);
--void facade_button_get_focus_inset (gint border_width,
--                                    GtkWidget *base,
--                                    GtkStyle *button_style,
--                                    GtkBorder *focus_inset);
--
--G_END_DECLS
--
--#endif /* FACADE_WIDGET_FACADE_H */
diff --cc src/ui/gui/psppire-button-editable.c
index f77e3ce21711263f8eff489e28dd756b6bae2986,f77e3ce21711263f8eff489e28dd756b6bae2986..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,185 -1,185 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2011, 2012, 2016 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--#include <config.h>
--
--#include "ui/gui/psppire-button-editable.h"
--
--#include <gettext.h>
--#define _(msgid) gettext (msgid)
--#define N_(msgid) msgid
--#define P_(STRING) STRING
--
--/* GtkCellEditable interface. */
--static void gtk_cell_editable_interface_init (GtkCellEditableIface *iface);
--static void button_editable_editing_done (GtkCellEditable *cell_editable);
--static void button_editable_remove_widget (GtkCellEditable *cell_editable);
--static void button_editable_start_editing (GtkCellEditable *cell_editable,
--                                           GdkEvent        *event);
--
--G_DEFINE_TYPE_EXTENDED (PsppireButtonEditable,
--                        psppire_button_editable,
--                        GTK_TYPE_BUTTON,
--                        0,
--                        G_IMPLEMENT_INTERFACE (
--                          GTK_TYPE_CELL_EDITABLE,
--                          gtk_cell_editable_interface_init));
--
--enum
--  {
--    PROP_0,
--    PROP_PATH,
--    PROP_EDITING_CANCELED
--  };
--
--static void
--psppire_button_editable_set_property (GObject      *object,
--                                      guint         prop_id,
--                                      const GValue *value,
--                                      GParamSpec   *pspec)
--{
--  PsppireButtonEditable *obj = PSPPIRE_BUTTON_EDITABLE (object);
--
--  switch (prop_id)
--    {
--    case PROP_PATH:
--      g_free (obj->path);
--      obj->path = g_value_dup_string (value);
--      break;
--
--    case PROP_EDITING_CANCELED:
--      break;
--
--    default:
--      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
--      break;
--    }
--}
--
--static void
--psppire_button_editable_get_property (GObject      *object,
--                                      guint         prop_id,
--                                      GValue       *value,
--                                      GParamSpec   *pspec)
--{
--  PsppireButtonEditable *obj = PSPPIRE_BUTTON_EDITABLE (object);
--
--  switch (prop_id)
--    {
--    case PROP_PATH:
--      g_value_set_string (value, obj->path);
--      break;
--
--    case PROP_EDITING_CANCELED:
--      g_value_set_boolean (value, FALSE);
--      break;
--
--    default:
--      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
--      break;
--    }
--}
--
--static void
--psppire_button_editable_finalize (GObject *gobject)
--{
--  PsppireButtonEditable *obj = PSPPIRE_BUTTON_EDITABLE (gobject);
--
--  g_free (obj->path);
--
--  G_OBJECT_CLASS (psppire_button_editable_parent_class)->finalize (gobject);
--}
--
--static gboolean
--psppire_button_editable_button_release (GtkWidget      *widget,
--                                        GdkEventButton *event)
--{
--  if (event->button == 1)
--    {
--      g_signal_emit_by_name (widget, "released", event, NULL);
--    }
--
--  return TRUE;
--}
--
--static void
--psppire_button_editable_class_init (PsppireButtonEditableClass *class)
--{
--  GObjectClass *gobject_class;
--  GtkWidgetClass *widget_class;
--
--  gobject_class = G_OBJECT_CLASS (class);
--  widget_class = GTK_WIDGET_CLASS (class);
--
--  gobject_class->set_property = psppire_button_editable_set_property;
--  gobject_class->get_property = psppire_button_editable_get_property;
--  gobject_class->finalize = psppire_button_editable_finalize;
--
--  widget_class->button_release_event = psppire_button_editable_button_release;
--
--  g_object_class_install_property (gobject_class,
--                                   PROP_PATH,
--                                   g_param_spec_string ("path",
--                                                      P_("TreeView path"),
--                                                      P_("The path to the row in the GtkTreeView, as a string"),
--                                                      "",
--                                                      G_PARAM_READWRITE));
--
--  g_object_class_override_property (gobject_class,
--                                   PROP_EDITING_CANCELED,
--                                    "editing-canceled");
--}
--
--static void
--psppire_button_editable_init (PsppireButtonEditable *obj)
--{
--  obj->path = g_strdup ("");
--}
--
--PsppireButtonEditable *
--psppire_button_editable_new (void)
--{
--  return PSPPIRE_BUTTON_EDITABLE (g_object_new (PSPPIRE_TYPE_BUTTON_EDITABLE, NULL));
--}
--
--\f
--/* GtkCellEditable interface. */
--
--static void
--gtk_cell_editable_interface_init (GtkCellEditableIface *iface)
--{
--  g_return_if_fail (iface != NULL);
--
--  iface->editing_done = button_editable_editing_done;
--  iface->remove_widget = button_editable_remove_widget;
--  iface->start_editing = button_editable_start_editing;
--}
--
--static void
--button_editable_editing_done (GtkCellEditable *cell_editable)
--{
--}
--
--static void
--button_editable_remove_widget (GtkCellEditable *cell_editable)
--{
--}
--
--static void
--button_editable_start_editing (GtkCellEditable *cell_editable,
--                               GdkEvent        *event)
--{
--}
diff --cc src/ui/gui/psppire-button-editable.h
index 80b6180d79ea8761f2efe2b88d84a12b9528377c,80b6180d79ea8761f2efe2b88d84a12b9528377c..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,48 -1,48 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2011, 2012 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--#ifndef PSPPIRE_BUTTON_EDITABLE_H
--#define PSPPIRE_BUTTON_EDITABLE_H 1
--
--#include <gtk/gtk.h>
--
--G_BEGIN_DECLS
--
--#define PSPPIRE_TYPE_BUTTON_EDITABLE             (psppire_button_editable_get_type())
--#define PSPPIRE_BUTTON_EDITABLE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj),PSPPIRE_TYPE_BUTTON_EDITABLE,PsppireButtonEditable))
--#define PSPPIRE_BUTTON_EDITABLE_CLASS(class)     (G_TYPE_CHECK_CLASS_CAST ((class),PSPPIRE_TYPE_BUTTON_EDITABLE,PsppireButtonEditableClass))
--#define PSPPIRE_IS_BUTTON_EDITABLE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj),PSPPIRE_TYPE_BUTTON_EDITABLE))
--#define PSPPIRE_IS_BUTTON_EDITABLE_CLASS(class)  (G_TYPE_CHECK_CLASS_TYPE ((class),PSPPIRE_TYPE_BUTTON_EDITABLE))
--#define PSPPIRE_BUTTON_EDITABLE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),PSPPIRE_TYPE_BUTTON_EDITABLE,PsppireButtonEditableClass))
--
--typedef struct _PsppireButtonEditable      PsppireButtonEditable;
--typedef struct _PsppireButtonEditableClass PsppireButtonEditableClass;
--
--struct _PsppireButtonEditable {
--  GtkButton parent;
--  gchar *path;
--};
--
--struct _PsppireButtonEditableClass {
--  GtkButtonClass parent_class;
--};
--
--GType psppire_button_editable_get_type (void) G_GNUC_CONST;
--PsppireButtonEditable* psppire_button_editable_new (void);
--
--G_END_DECLS
--
--#endif /* PSPPIRE_BUTTON_EDITABLE_H */
diff --cc src/ui/gui/psppire-cell-renderer-button.c
index c31a73fce23113fc0d0ef5c04fec45602cc4d4db,c31a73fce23113fc0d0ef5c04fec45602cc4d4db..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,578 -1,578 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2011, 2012 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--#include <config.h>
--
--#include "ui/gui/psppire-cell-renderer-button.h"
--
--#include <math.h>
--#include <string.h>
--
--#include "ui/gui/psppire-button-editable.h"
--#include "ui/gui/pspp-widget-facade.h"
--
--#include "gl/configmake.h"
--#include "gl/relocatable.h"
--
--#define P_(msgid) (msgid)
--
--static void psppire_cell_renderer_button_dispose (GObject *);
--static void psppire_cell_renderer_button_finalize (GObject *);
--
--static void update_style_cache (PsppireCellRendererButton *button,
--                                GtkWidget                 *widget);
--
--static void psppire_cell_renderer_button_load_gtkrc (void);
--
--
--G_DEFINE_TYPE_EXTENDED (PsppireCellRendererButton,
--                        psppire_cell_renderer_button,
--                        GTK_TYPE_CELL_RENDERER,
--                        0,
--                        psppire_cell_renderer_button_load_gtkrc ());
--
--static void
--psppire_cell_renderer_button_load_gtkrc (void)
--{
--  const char *gtkrc_file;
--
--  gtkrc_file = relocate (PKGDATADIR "/psppire.gtkrc");
--  gtk_rc_add_default_file (gtkrc_file);
--  gtk_rc_parse (gtkrc_file);
--}
--
--enum
--  {
--    PROP_0,
--    PROP_EDITABLE,
--    PROP_LABEL,
--    PROP_SLASH
--  };
--
--static void
--psppire_cell_renderer_button_set_property (GObject      *object,
--                                           guint         prop_id,
--                                           const GValue *value,
--                                           GParamSpec   *pspec)
--{
--  PsppireCellRendererButton *obj = PSPPIRE_CELL_RENDERER_BUTTON (object);
--  switch (prop_id)
--    {
--    case PROP_EDITABLE:
--      obj->editable = g_value_get_boolean (value);
--      if (obj->editable)
--      g_object_set (obj, "mode", GTK_CELL_RENDERER_MODE_EDITABLE, NULL);
--      else
--      g_object_set (obj, "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
--      break;
--
--    case PROP_LABEL:
--      g_free (obj->label);
--      obj->label = g_value_dup_string (value);
--      break;
--
--    case PROP_SLASH:
--      psppire_cell_renderer_button_set_slash (obj,
--                                              g_value_get_boolean (value));
--      break;
--
--    default:
--      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
--      break;
--    }
--}
--
--static void
--psppire_cell_renderer_button_get_property (GObject      *object,
--                                           guint         prop_id,
--                                           GValue       *value,
--                                           GParamSpec   *pspec)
--{
--  PsppireCellRendererButton *obj = PSPPIRE_CELL_RENDERER_BUTTON (object);
--
--  switch (prop_id)
--    {
--    case PROP_EDITABLE:
--      g_value_set_boolean (value, obj->editable);
--      break;
--
--    case PROP_LABEL:
--      g_value_set_string (value, obj->label);
--      break;
--
--    case PROP_SLASH:
--      g_value_set_boolean (value,
--                           psppire_cell_renderer_button_get_slash (obj));
--      break;
--
--    default:
--      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
--      break;
--    }
--}
--
--static void
--on_style_set (GtkWidget                 *base,
--              GtkStyle                  *previous_style,
--              PsppireCellRendererButton *button)
--{
--  update_style_cache (button, NULL);
--}
--
--static void
--update_style_cache (PsppireCellRendererButton *button,
--                    GtkWidget                 *widget)
--{
--  if (button->base == widget)
--    return;
--
--  /* Clear old cache. */
--  if (button->button_style)
--    {
--      g_object_unref (button->button_style);
--      button->button_style = NULL;
--    }
--  if (button->label_style)
--    {
--      g_object_unref (button->label_style);
--      button->label_style = NULL;
--    }
--  if (button->base != NULL)
--    {
--      if (button->style_set_handler)
--        {
--          g_signal_handler_disconnect (button->base,
--                                       button->style_set_handler);
--          button->style_set_handler = 0;
--        }
--      g_object_unref (button->base);
--      button->base = NULL;
--    }
--
--  /* Populate cache. */
--  if (widget)
--    {
--      button->button_style = facade_get_style (widget, GTK_TYPE_BUTTON, 0);
--      button->label_style = facade_get_style (widget, GTK_TYPE_BUTTON,
--                                              GTK_TYPE_LABEL, 0);
--      button->base = widget;
--      button->style_set_handler = g_signal_connect (widget, "style-set",
--                                                    G_CALLBACK (on_style_set),
--                                                    button);
--      g_object_ref (widget);
--      g_object_ref (button->button_style);
--      g_object_ref (button->label_style);
--    }
--}
--
--static void
--psppire_cell_renderer_button_render (GtkCellRenderer      *cell,
--                                     cairo_t              *cr,
--                                     GtkWidget            *widget,
--                                     const GdkRectangle         *background_area,
--                                     const GdkRectangle         *cell_area,
--                                     GtkCellRendererState  flags)
--{
--  GtkStateType state_type;
--  PsppireCellRendererButton *button = PSPPIRE_CELL_RENDERER_BUTTON (cell);
--  gfloat xalign, yalign;
--  
--  if (!button->editable || ! gtk_cell_renderer_get_sensitive (cell))
--    state_type = GTK_STATE_INSENSITIVE;
--  else if (flags & GTK_CELL_RENDERER_SELECTED)
--    {
--      if (gtk_widget_has_focus (widget))
--        state_type = GTK_STATE_SELECTED;
--      else
--        state_type = GTK_STATE_ACTIVE;
--    }
--  else if (flags & GTK_CELL_RENDERER_PRELIT)
--    state_type = GTK_STATE_PRELIGHT;
--  else
--    {
--      if (gtk_widget_get_state_flags (widget) == GTK_STATE_FLAG_INSENSITIVE)
--        state_type = GTK_STATE_INSENSITIVE;
--      else
--        state_type = GTK_STATE_NORMAL;
--    }
--
--  gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
--
--
--  update_style_cache (button, widget);
--
--  facade_button_render (widget, cr,
--                        cell_area, button->border_width, button->button_style,
--                        state_type,
--                        button->label_style, button->label, button->xpad,
--                        button->ypad, xalign, yalign);
--
--  if (button->slash)
--    {
--      cairo_set_line_width (cr, 1.0);
--      cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
--      cairo_move_to (cr, 
--                   cell_area->x,
--                   cell_area->y + cell_area->height);
--
--      cairo_line_to (cr,
--                   cell_area->x + cell_area->width,
--                   cell_area->y);
--      cairo_stroke (cr);
--    }
--}
--
--static void
--psppire_cell_renderer_button_get_size (GtkCellRenderer      *cell,
--                                       GtkWidget            *widget,
--                                       const GdkRectangle   *cell_area,
--                                       gint                 *x_offset,
--                                       gint                 *y_offset,
--                                       gint                 *width,
--                                       gint                 *height)
--{
--  PsppireCellRendererButton *button = PSPPIRE_CELL_RENDERER_BUTTON (cell);
--
--  update_style_cache (button, widget);
--  if (cell_area != NULL)
--    {
--      /* The caller is really asking for the placement of the focus rectangle.
--         The focus rectangle should surround the whole label area, so calculate
--         that area. */
--      GtkBorder inset;
--
--      facade_button_get_focus_inset (button->border_width, widget,
--                                     button->button_style, &inset);
--
--      if (x_offset)
--        *x_offset = inset.left;
--      if (y_offset)
--        *y_offset = inset.top;
--      if (width)
--        *width = MAX (1, cell_area->width - inset.left - inset.right);
--      if (height)
--        *height = MAX (1, cell_area->height - inset.top - inset.bottom);
--    }
--  else
--    {
--      /* The caller is asking for the preferred size of the cell. */
--      GtkRequisition label_req;
--      GtkRequisition request;
--
--      facade_label_get_size_request (button->xpad, button->ypad,
--                                     widget, button->label, &label_req);
--      facade_button_get_size_request (button->border_width, widget,
--                                      button->button_style, &label_req,
--                                      &request);
--
--      if (x_offset)
--        *x_offset = 0;
--      if (y_offset)
--        *y_offset = 0;
--      if (width)
--        *width = request.width;
--      if (height)
--        *height = request.height;
--    }
--}
--
--static void
--psppire_cell_renderer_button_clicked (GtkButton *button,
--                                      gpointer   data)
--{
--  PsppireCellRendererButton *cell_button = data;
--  gchar *path;
--
--  g_object_get (button, "path", &path, NULL);
--  g_signal_emit_by_name (cell_button, "clicked", path);
--  g_free (path);
--}
--
--#define IDLE_ID_STRING "psppire-cell-renderer-button-idle-id"
--
--static gboolean
--psppire_cell_renderer_button_initial_click (gpointer data)
--{
--  GtkButton *button = data;
--
--  g_object_steal_data (G_OBJECT (button), IDLE_ID_STRING);
--  gtk_button_clicked (button);
--  return FALSE;
--}
--
--static void
--psppire_cell_renderer_button_on_destroy (GObject *object, gpointer user_data)
--{
--  guint idle_id;
--
--  idle_id = GPOINTER_TO_INT (g_object_steal_data (object, IDLE_ID_STRING));
--  if (idle_id != 0)
--    g_source_remove (idle_id);
--}
--
--static void
--psppire_cell_renderer_button_double_click (GtkButton *button,
--                                           PsppireCellRendererButton *cell_button)
--{
--  gchar *path;
--
--  if (g_object_get_data (G_OBJECT (button), IDLE_ID_STRING))
--    psppire_cell_renderer_button_initial_click (button);
--
--  g_object_get (button, "path", &path, NULL);
--  g_signal_emit_by_name (cell_button, "double-clicked", path);
--  g_free (path);
--}
--
--static gboolean
--psppire_cell_renderer_button_press_event (GtkButton      *button,
--                                          GdkEventButton *event,
--                                          gpointer        data)
--{
--  PsppireCellRendererButton *cell_button = data;
--
--  if (event->button == 3)
--    {
--      /* Allow right-click events to propagate upward in the widget hierarchy.
--         Otherwise right-click menus, that trigger on a button-press-event on
--         the containing PsppSheetView, will pop up if the button is rendered as
--         a facade but not if the button widget exists.
--
--         We have to translate the event's data by hand to be relative to the
--         parent window, because the normal GObject signal propagation mechanism
--         won't do it for us.  (This might be a hint that we're doing this
--         wrong.) */
--      gint x, y;
--
--      gdk_window_get_position (event->window, &x, &y);
--      event->x += x;
--      event->y += y;
--      g_signal_stop_emission_by_name (button, "button-press-event");
--      return FALSE;
--    }
--
--  if (cell_button->click_time != 0)
--    {
--      GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button));
--      GtkSettings *settings = gtk_settings_get_for_screen (screen);
--      gint double_click_distance;
--      gint double_click_time;
--
--      g_object_get (settings,
--                    "gtk-double-click-time", &double_click_time,
--                    "gtk-double-click-distance", &double_click_distance,
--                    NULL);
--
--      if (event->type == GDK_BUTTON_PRESS
--          && event->button == 1
--          && event->time <= cell_button->click_time + double_click_time
--          && ABS (event->x_root - cell_button->click_x) <= double_click_distance
--          && ABS (event->y_root - cell_button->click_y) <= double_click_distance)
--        {
--          psppire_cell_renderer_button_double_click (button, cell_button);
--          return TRUE;
--        }
--
--      cell_button->click_time = 0;
--    }
--
--  if (event->type == GDK_2BUTTON_PRESS)
--    {
--      psppire_cell_renderer_button_double_click (button, cell_button);
--      return TRUE;
--    }
--
--  return FALSE;
--}
--
--static GtkCellEditable *
--psppire_cell_renderer_button_start_editing (GtkCellRenderer      *cell,
--                                            GdkEvent             *event,
--                                            GtkWidget            *widget,
--                                            const gchar          *path,
--                                            const GdkRectangle   *background_area,
--                                            const GdkRectangle   *cell_area,
--                                            GtkCellRendererState  flags)
--{
--  PsppireCellRendererButton *cell_button = PSPPIRE_CELL_RENDERER_BUTTON (cell);
--  gfloat xalign, yalign;
--
--  gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
--  cell_button->button = g_object_new (PSPPIRE_TYPE_BUTTON_EDITABLE,
--                                      "label", cell_button->label,
--                                      "xalign", xalign,
--                                      "yalign", yalign,
--                                      "path", path,
--                                      NULL);
--
--  g_signal_connect (G_OBJECT (cell_button->button), "clicked",
--                    G_CALLBACK (psppire_cell_renderer_button_clicked),
--                    cell);
--  g_signal_connect (G_OBJECT (cell_button->button), "button-press-event",
--                    G_CALLBACK (psppire_cell_renderer_button_press_event),
--                    cell);
--
--  gtk_widget_show (cell_button->button);
--
--  if (event != NULL && event->any.type == GDK_BUTTON_RELEASE)
--    {
--      guint idle_id;
--
--      cell_button->click_time = event->button.time;
--      cell_button->click_x = event->button.x_root;
--      cell_button->click_y = event->button.y_root;
--      idle_id = g_idle_add (psppire_cell_renderer_button_initial_click,
--                            cell_button->button);
--      g_object_set_data (G_OBJECT (cell_button->button), IDLE_ID_STRING,
--                         GINT_TO_POINTER (idle_id));
--      g_signal_connect (G_OBJECT (cell_button->button), "destroy",
--                        G_CALLBACK (psppire_cell_renderer_button_on_destroy),
--                        NULL);
--    }
--  else
--    {
--      cell_button->click_time = 0;
--      cell_button->click_x = 0;
--      cell_button->click_y = 0;
--    }
--
--  return GTK_CELL_EDITABLE (cell_button->button);
--}
--
--static void
--psppire_cell_renderer_button_class_init (PsppireCellRendererButtonClass *class)
--{
--  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
--  GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
--
--  gobject_class->set_property = psppire_cell_renderer_button_set_property;
--  gobject_class->get_property = psppire_cell_renderer_button_get_property;
--  gobject_class->finalize = psppire_cell_renderer_button_finalize;
--  gobject_class->dispose = psppire_cell_renderer_button_dispose;
--
--  cell_class->get_size = psppire_cell_renderer_button_get_size;
--  cell_class->render = psppire_cell_renderer_button_render;
--  cell_class->start_editing = psppire_cell_renderer_button_start_editing;
--
--  g_signal_new ("clicked",
--                G_TYPE_FROM_CLASS (gobject_class),
--                G_SIGNAL_RUN_LAST,
--                0,
--                NULL, NULL,
--                g_cclosure_marshal_VOID__STRING,
--                G_TYPE_NONE,
--                1, G_TYPE_STRING);
--
--  g_signal_new ("double-clicked",
--                G_TYPE_FROM_CLASS (gobject_class),
--                G_SIGNAL_RUN_LAST,
--                0,
--                NULL, NULL,
--                g_cclosure_marshal_VOID__STRING,
--                G_TYPE_NONE,
--                1, G_TYPE_STRING);
--
--  g_object_class_install_property (gobject_class,
--                                   PROP_EDITABLE,
--                                   g_param_spec_boolean ("editable",
--                                                         P_("Editable"),
--                                                         P_("Whether the button may be clicked."),
--                                                         FALSE,
--                                                         G_PARAM_READWRITE));
--
--  g_object_class_install_property (gobject_class,
--                                   PROP_LABEL,
--                                   g_param_spec_string ("label",
--                                                        P_("Label"),
--                                                        P_("Text to appear in button."),
--                                                        "",
--                                                        G_PARAM_READWRITE));
--
--  g_object_class_install_property (gobject_class,
--                                   PROP_SLASH,
--                                   g_param_spec_boolean ("slash",
--                                                         P_("Diagonal slash"),
--                                                         P_("Whether to draw a diagonal slash across the button."),
--                                                         FALSE,
--                                                         G_PARAM_READWRITE));
--
--}
--
--static void
--psppire_cell_renderer_button_init (PsppireCellRendererButton *obj)
--{
--  obj->editable = FALSE;
--  obj->label = g_strdup ("");
--  obj->border_width = 0;
--  obj->xpad = 0;
--  obj->ypad = 0;
--
--  obj->slash = FALSE;
--
--  obj->button = NULL;
--
--  obj->button_style = NULL;
--  obj->label_style = NULL;
--  obj->base = NULL;
--  obj->style_set_handler = 0;
--  obj->dispose_has_run = FALSE;
--}
--
--static void
--psppire_cell_renderer_button_finalize (GObject *obj)
--{
--  PsppireCellRendererButton *button = PSPPIRE_CELL_RENDERER_BUTTON (obj);
--
--  g_free (button->label);
--}
--
--static void
--psppire_cell_renderer_button_dispose (GObject *obj)
--{
--  PsppireCellRendererButton *button = PSPPIRE_CELL_RENDERER_BUTTON (obj);
--
--  if (button->dispose_has_run)
--    return;
--  
--  button->dispose_has_run = TRUE;
--
--  /* When called with NULL, as we are doing here, update_style_cache
--     does nothing more than to drop references */
--  update_style_cache (button, NULL);
--
--  G_OBJECT_CLASS (psppire_cell_renderer_button_parent_class)->dispose (obj);
--}
--
--GtkCellRenderer *
--psppire_cell_renderer_button_new (void)
--{
--  return GTK_CELL_RENDERER (g_object_new (PSPPIRE_TYPE_CELL_RENDERER_BUTTON, NULL));
--}
--
--void
--psppire_cell_renderer_button_set_slash (PsppireCellRendererButton *button,
--                                        gboolean slash)
--{
--  g_return_if_fail (button != NULL);
--  button->slash = slash;
--}
--
--gboolean
--psppire_cell_renderer_button_get_slash (const PsppireCellRendererButton *button)
--{
--  g_return_val_if_fail (button != NULL, FALSE);
--  return button->slash;
--}
diff --cc src/ui/gui/psppire-cell-renderer-button.h
index 28d5dd14e5062ff8807ac4172eedec3895a26517,28d5dd14e5062ff8807ac4172eedec3895a26517..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,72 -1,72 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2011, 2012 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--#ifndef PSPPIRE_CELL_RENDERER_BUTTON_H
--#define PSPPIRE_CELL_RENDERER_BUTTON_H 1
--
--#include <gtk/gtk.h>
--
--G_BEGIN_DECLS
--
--#define PSPPIRE_TYPE_CELL_RENDERER_BUTTON             (psppire_cell_renderer_button_get_type())
--#define PSPPIRE_CELL_RENDERER_BUTTON(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj),PSPPIRE_TYPE_CELL_RENDERER_BUTTON,PsppireCellRendererButton))
--#define PSPPIRE_CELL_RENDERER_BUTTON_CLASS(class)     (G_TYPE_CHECK_CLASS_CAST ((class),PSPPIRE_TYPE_CELL_RENDERER_BUTTON,PsppireCellRendererButtonClass))
--#define PSPPIRE_IS_CELL_RENDERER_BUTTON(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj),PSPPIRE_TYPE_CELL_RENDERER_BUTTON))
--#define PSPPIRE_IS_CELL_RENDERER_BUTTON_CLASS(class)  (G_TYPE_CHECK_CLASS_TYPE ((class),PSPPIRE_TYPE_CELL_RENDERER_BUTTON))
--#define PSPPIRE_CELL_RENDERER_BUTTON_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),PSPPIRE_TYPE_CELL_RENDERER_BUTTON,PsppireCellRendererButtonClass))
--
--typedef struct _PsppireCellRendererButton      PsppireCellRendererButton;
--typedef struct _PsppireCellRendererButtonClass PsppireCellRendererButtonClass;
--
--struct _PsppireCellRendererButton
--{
--  GtkCellRenderer parent;
--
--  gboolean editable;
--  gchar *label;
--  gint border_width;
--  gint xpad;
--  gint ypad;
--
--  gboolean slash;
--
--  GtkWidget *button;
--  guint32 click_time;
--  gdouble click_x;
--  gdouble click_y;
--
--  /* Style caching. */
--  GtkStyle *button_style;
--  GtkStyle *label_style;
--  GtkWidget *base;
--  gulong style_set_handler;
--  gboolean dispose_has_run;
--};
--
--struct _PsppireCellRendererButtonClass {
--  GtkCellRendererClass parent_class;
--};
--
--GType psppire_cell_renderer_button_get_type (void) G_GNUC_CONST;
--GtkCellRenderer* psppire_cell_renderer_button_new (void);
--
--void psppire_cell_renderer_button_set_slash (PsppireCellRendererButton *,
--                                             gboolean slash);
--gboolean psppire_cell_renderer_button_get_slash (const PsppireCellRendererButton *);
--
--G_END_DECLS
--
--#endif /* PSPPIRE_CELL_RENDERER_BUTTON_H */
index b643acf0462a6ee59d29cd16c67f8c3e05ecfc1c,1c6143aaf4df167310b2d517915f09b4e43bd247..147ffcd4c3b50ec4f0ea479d27a2278cd69d241d
  #include "libpspp/range-set.h"
  #include "libpspp/str.h"
  #include "ui/gui/helper.h"
--#include "ui/gui/pspp-sheet-selection.h"
 -#include "ui/gui/psppire-data-sheet.h"
  #include "ui/gui/psppire-data-store.h"
  #include "ui/gui/psppire-value-entry.h"
--#include "ui/gui/psppire-var-sheet.h"
  #include "ui/gui/psppire-conf.h"
 +#include "ui/gui/psppire-var-sheet-header.h"
 +
 +#include "ui/gui/efficient-sheet/jmd-sheet.h"
  
  #include <gettext.h>
  #define _(msgid) gettext (msgid)
@@@ -303,15 -166,15 +293,15 @@@ psppire_data_editor_set_property (GObje
        de->dict = g_value_get_pointer (value);
        g_object_ref (de->dict);
  
 -      psppire_var_sheet_set_dictionary (PSPPIRE_VAR_SHEET (de->var_sheet),
 -                                        de->dict);
 +      g_object_set (de->data_sheet, "hmodel", de->dict, NULL);
 +      g_object_set (de->var_sheet, "data-model", de->dict, NULL);
 +      g_signal_connect_swapped (de->var_sheet, "value-changed",
 +                              G_CALLBACK (change_var_property), de->dict);
 +
        break;
      case PROP_VALUE_LABELS:
 -      FOR_EACH_DATA_SHEET (data_sheet, i, de)
 -        psppire_data_sheet_set_value_labels (data_sheet,
 -                                          g_value_get_boolean (value));
        break;
-     case PROP_UI_MANAGER:
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
@@@ -338,10 -201,10 +328,7 @@@ psppire_data_editor_get_property (GObje
        g_value_set_pointer (value, de->dict);
        break;
      case PROP_VALUE_LABELS:
 -      g_value_set_boolean (value,
 -                           psppire_data_sheet_get_value_labels (
 -                             PSPPIRE_DATA_SHEET (de->data_sheets[0])));
        break;
-     case PROP_UI_MANAGER:
-       g_value_set_object (value, psppire_data_editor_get_ui_manager (de));
-       break;
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
@@@ -430,39 -293,37 +417,33 @@@ psppire_data_editor_class_init (Psppire
                                     PROP_SPLIT_WINDOW,
                                     split_window_spec);
  
-   ui_manager_spec =
-     g_param_spec_object ("ui-manager",
-                          "UI Manager",
-                          "UI manager for the active notebook tab.  The client should merge this UI manager with the active UI manager to obtain menu items and tool bar items specific to the active notebook tab.",
-                          GTK_TYPE_UI_MANAGER,
-                          G_PARAM_READABLE);
-   g_object_class_install_property (object_class,
-                                    PROP_UI_MANAGER,
-                                    ui_manager_spec);
  }
  
 -static gboolean
 -on_data_sheet_var_double_clicked (PsppireDataSheet *data_sheet,
 -                                  gint dict_index,
 -                                  PsppireDataEditor *de)
 +
 +static void
- on_var_sheet_var_double_clicked (PsppireVarSheet *var_sheet, gint dict_index,
++on_var_sheet_var_double_clicked (void *var_sheet, gint dict_index,
 +                                 PsppireDataEditor *de)
  {
    gtk_notebook_set_current_page (GTK_NOTEBOOK (de),
 -                                 PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
 -
 -  psppire_var_sheet_goto_variable (PSPPIRE_VAR_SHEET (de->var_sheet),
 -                                   dict_index);
 +                                 PSPPIRE_DATA_EDITOR_DATA_VIEW);
  
 -  return TRUE;
 +  jmd_sheet_scroll_to (JMD_SHEET (de->data_sheet), dict_index, -1);
  }
  
 -static gboolean
 -on_var_sheet_var_double_clicked (PsppireVarSheet *var_sheet, gint dict_index,
++
 +static void
 +on_data_sheet_var_double_clicked (JmdSheet *data_sheet, gint dict_index,
                                   PsppireDataEditor *de)
  {
 -  PsppireDataSheet *data_sheet;
 -
++  
    gtk_notebook_set_current_page (GTK_NOTEBOOK (de),
 -                                 PSPPIRE_DATA_EDITOR_DATA_VIEW);
 -
 -  data_sheet = psppire_data_editor_get_active_data_sheet (de);
 -  psppire_data_sheet_goto_variable (data_sheet, dict_index);
 +                                 PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
  
 -  return TRUE;
 +  jmd_sheet_scroll_to (JMD_SHEET (de->var_sheet), -1, dict_index);
  }
  
 +
++
  /* Refreshes 'de->cell_ref_label' and 'de->datum_entry' from the currently
     active cell or cells. */
  static void
@@@ -621,13 -755,17 +600,15 @@@ psppire_data_editor_new (PsppireDict *d
  void
  psppire_data_editor_show_grid (PsppireDataEditor *de, gboolean grid_visible)
  {
++#if 0
    GtkTreeViewGridLines grid;
 -  PsppireDataSheet *data_sheet;
 -  int i;
  
    grid = (grid_visible
            ? GTK_TREE_VIEW_GRID_LINES_BOTH
            : GTK_TREE_VIEW_GRID_LINES_NONE);
  
 -  FOR_EACH_DATA_SHEET (data_sheet, i, de)
 -    pspp_sheet_view_set_grid_lines (PSPP_SHEET_VIEW (data_sheet), grid);
    pspp_sheet_view_set_grid_lines (PSPP_SHEET_VIEW (de->var_sheet), grid);
++#endif  
  }
  
  
@@@ -687,50 -848,54 +667,42 @@@ psppire_data_editor_split_window (Psppi
  void
  psppire_data_editor_goto_variable (PsppireDataEditor *de, gint dict_index)
  {
 -  PsppireDataSheet *data_sheet;
 -
 -  switch (gtk_notebook_get_current_page (GTK_NOTEBOOK (de)))
 -    {
 -    case PSPPIRE_DATA_EDITOR_DATA_VIEW:
 -      data_sheet = psppire_data_editor_get_active_data_sheet (de);
 -      psppire_data_sheet_goto_variable (data_sheet, dict_index);
 -      break;
 -
 -    case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
 -      psppire_var_sheet_goto_variable (PSPPIRE_VAR_SHEET (de->var_sheet),
 -                                       dict_index);
 -      break;
 -    }
  }
  
- /* Returns the UI manager that should be merged into DE's toplevel widget's UI
-    manager to display menu items and toolbar items specific to DE's current
-    page and data sheet.
-    DE's toplevel widget can watch for changes by connecting to DE's
-    notify::ui-manager signal. */
- GtkUIManager *
- psppire_data_editor_get_ui_manager (PsppireDataEditor *de)
- {
-   psppire_data_editor_update_ui_manager (de);
-   return de->ui_manager;
- }
- static void
- psppire_data_editor_update_ui_manager (PsppireDataEditor *de)
++#if 0
+ /* Returns the "active" data sheet in DE.  If DE is in single-paned mode, this
+    is the only data sheet.  If DE is in split mode (showing four data sheets),
+    this is the focused data sheet or, if none is focused, the data sheet with
+    selected cells or, if none has selected cells, the upper-left data sheet. */
+ PsppireDataSheet *
+ psppire_data_editor_get_active_data_sheet (PsppireDataEditor *de)
  {
-   GtkUIManager *ui_manager;
-   ui_manager = NULL;
-   switch (gtk_notebook_get_current_page (GTK_NOTEBOOK (de)))
+   if (de->split)
      {
-     case PSPPIRE_DATA_EDITOR_DATA_VIEW:
-       break;
-     case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
-       break;
+       PsppireDataSheet *data_sheet;
+       GtkWidget *scroller;
+       int i;
+       /* If one of the datasheet's scrollers is focused, choose that one. */
+       scroller = gtk_container_get_focus_child (
+         GTK_CONTAINER (de->datasheet_vbox_widget));
+       if (scroller != NULL)
+         return PSPPIRE_DATA_SHEET (gtk_bin_get_child (GTK_BIN (scroller)));
+       /* Otherwise if there's a nonempty selection in some data sheet, choose
+          that one. */
+       FOR_EACH_DATA_SHEET (data_sheet, i, de)
+         {
+           PsppSheetSelection *selection;
  
-     default:
-       /* This happens transiently in psppire_data_editor_init(). */
-       break;
+           selection = pspp_sheet_view_get_selection (
+             PSPP_SHEET_VIEW (data_sheet));
+           if (pspp_sheet_selection_count_selected_rows (selection)
+               && pspp_sheet_selection_count_selected_columns (selection))
+             return data_sheet;
+         }
      }
  
-   if (ui_manager != de->ui_manager)
-     {
-       if (de->ui_manager)
-         g_object_unref (de->ui_manager);
-       if (ui_manager)
-         g_object_ref (ui_manager);
-       de->ui_manager = ui_manager;
-       g_object_notify (G_OBJECT (de), "ui-manager");
-     }
+   return PSPPIRE_DATA_SHEET (de->data_sheets[0]);
  }
++#endif
index e75ccd781989a49c92280d59ab2140f94ba78f31,28ae214a68953bee4ea405cc01057dac79e9b85b..d31b32c380f7031853fc7cebdfac69976c890d67
@@@ -33,7 -33,7 +33,6 @@@
  #include <gtk/gtk.h>
  
  #include "psppire-data-store.h"
--#include "ui/gui/pspp-sheet-view.h"
  
  G_BEGIN_DECLS
  
index cce71873b9bceccf4377396d1f331f75436a59a6,b4e3d5f3d6cd8304b0764de216e10e7e575cc008..a0f4ad916944effeea72ed9b626411d042cdcbbb
     along with this program.  If not, see <http://www.gnu.org/licenses/>. */
  
  #include <config.h>
 -#include "ui/gui/psppire-data-sheet.h"
 -#include "ui/gui/pspp-sheet-selection.h"
 -#include "ui/gui/psppire-cell-renderer-button.h"
++// #include "ui/gui/psppire-data-sheet.h"
+ #include "data/case-map.h"
+ #include "data/casereader.h"
+ #include "data/casewriter.h"
+ #include "data/data-out.h"
+ #include "data/datasheet.h"
+ #include "data/format.h"
+ #include "data/value-labels.h"
+ #include "libpspp/intern.h"
+ #include "libpspp/range-set.h"
+ #include "ui/gui/executor.h"
+ #include "ui/gui/find-dialog.h"
+ #include "ui/gui/goto-case-dialog.h"
+ #include "ui/gui/builder-wrapper.h"
+ #include "ui/gui/helper.h"
+ #include "ui/gui/psppire-data-store.h"
+ #include "ui/gui/psppire-data-window.h"
+ #include "ui/gui/psppire-dialog-action-var-info.h"
+ #include "ui/gui/psppire-empty-list-store.h"
+ #include "ui/gui/psppire-marshal.h"
+ #include "gl/intprops.h"
+ #include "gl/xalloc.h"
+ #include <gettext.h>
+ #define _(msgid) gettext (msgid)
+ #define N_(msgid) msgid
++#if 0
++
+ static void psppire_data_sheet_dispose (GObject *);
+ static void psppire_data_sheet_unset_data_store (PsppireDataSheet *);
+ static void psppire_data_sheet_update_clip_actions (PsppireDataSheet *);
+ static void psppire_data_sheet_update_primary_selection (PsppireDataSheet *,
+                                                          gboolean should_own);
+ static void psppire_data_sheet_set_clip (PsppireDataSheet *, gboolean cut);
+ static void on_selection_changed (PsppSheetSelection *, gpointer);
+ static void on_owner_change (GtkClipboard *, GdkEventOwnerChange *, gpointer);
+ static void psppire_data_sheet_clip_received_cb (GtkClipboard *,
+                                                  GtkSelectionData *, gpointer);
+ G_DEFINE_TYPE (PsppireDataSheet, psppire_data_sheet, PSPP_TYPE_SHEET_VIEW);
+ static gboolean
+ get_tooltip_location (GtkWidget *widget, GtkTooltip *tooltip,
+                       gint wx, gint wy,
+                       size_t *row, PsppSheetViewColumn **columnp)
+ {
+   PsppSheetView *tree_view = PSPP_SHEET_VIEW (widget);
+   gint bx, by;
+   GtkTreePath *path;
+   GtkTreeIter iter;
+   PsppSheetViewColumn *tree_column;
+   GtkTreeModel *tree_model;
+   bool ok;
+   /* Check that WIDGET is really visible on the screen before we
+      do anything else.  This is a bug fix for a sticky situation:
+      when text_data_import_assistant() returns, it frees the data
+      necessary to compose the tool tip message, but there may be
+      a tool tip under preparation at that point (even if there is
+      no visible tool tip) that will call back into us a little
+      bit later.  Perhaps the correct solution to this problem is
+      to make the data related to the tool tips part of a GObject
+      that only gets destroyed when all references are released,
+      but this solution appears to be effective too. */
+   if (!gtk_widget_get_mapped (widget))
+     return FALSE;
+   pspp_sheet_view_convert_widget_to_bin_window_coords (tree_view,
+                                                      wx, wy, &bx, &by);
+   if (!pspp_sheet_view_get_path_at_pos (tree_view, bx, by,
+                                       &path, &tree_column, NULL, NULL))
+     return FALSE;
+   *columnp = tree_column;
+   pspp_sheet_view_set_tooltip_cell (tree_view, tooltip, path, tree_column,
+                                     NULL);
+   tree_model = pspp_sheet_view_get_model (tree_view);
+   ok = gtk_tree_model_get_iter (tree_model, &iter, path);
+   gtk_tree_path_free (path);
+   if (!ok)
+     return FALSE;
+   *row = GPOINTER_TO_INT (iter.user_data);
+   return TRUE;
+ }
+ static gboolean
+ on_query_tooltip (GtkWidget *widget, gint wx, gint wy,
+                   gboolean keyboard_mode UNUSED,
+                   GtkTooltip *tooltip, gpointer data UNUSED)
+ {
+   PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (widget);
+   PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet);
+   PsppSheetViewColumn *column;
+   struct variable *var;
+   const char *label;
+   union value v;
+   size_t row;
+   int width;
+   g_return_val_if_fail (data_store != NULL, FALSE);
+   g_return_val_if_fail (data_store->datasheet != NULL, FALSE);
+   if (!get_tooltip_location (widget, tooltip, wx, wy, &row, &column))
+     return FALSE;
+   var = g_object_get_data (G_OBJECT (column), "variable");
+   if (var == NULL)
+     {
+       if (g_object_get_data (G_OBJECT (column), "new-var-column") == NULL)
+         return FALSE;
+       gtk_tooltip_set_text (tooltip,
+                             _("Enter a number to add a new variable."));
+       return TRUE;
+     }
+   else if (row >= datasheet_get_n_rows (data_store->datasheet))
+     {
+       gtk_tooltip_set_text (tooltip, _("Enter a number to add a new case."));
+       return TRUE;
+     }
+   width = var_get_width (var);
+   value_init (&v, width);
+   datasheet_get_value (data_store->datasheet, row, var_get_case_index (var),
+                        &v);
+   label = var_lookup_value_label (var, &v);
+   if (label != NULL)
+     {
+       if (data_sheet->show_value_labels)
+         {
+           char *s = value_to_text (v, var);
+           gtk_tooltip_set_text (tooltip, s);
+           free (s);
+         }
+       else
+         gtk_tooltip_set_text (tooltip, label);
+     }
+   value_destroy (&v, width);
+   return label != NULL;
+ }
+ static void
+ render_row_number_cell (PsppSheetViewColumn *tree_column,
+                         GtkCellRenderer *cell,
+                         GtkTreeModel *model,
+                         GtkTreeIter *iter,
+                         gpointer store_)
+ {
+   PsppireDataStore *store = store_;
+   GValue gvalue = { 0, };
+   gint row = GPOINTER_TO_INT (iter->user_data);
+   g_return_if_fail (store->datasheet);
+   g_value_init (&gvalue, G_TYPE_INT);
+   g_value_set_int (&gvalue, row + 1);
+   g_object_set_property (G_OBJECT (cell), "label", &gvalue);
+   g_value_unset (&gvalue);
+   if (row < datasheet_get_n_rows (store->datasheet))
+     g_object_set (cell, "editable", TRUE, NULL);
+   else
+     g_object_set (cell, "editable", FALSE, NULL);
+   g_object_set (cell,
+                 "slash", psppire_data_store_filtered (store, row),
+                 NULL);
+ }
+ static void
+ on_row_number_clicked (PsppireCellRendererButton *button,
+                        gchar *path_string,
+                        PsppSheetView *sheet_view)
+ {
+   PsppSheetSelection *selection;
+   GtkTreePath *path;
+   path = gtk_tree_path_new_from_string (path_string);
+   selection = pspp_sheet_view_get_selection (sheet_view);
+   pspp_sheet_selection_unselect_all (selection);
+   pspp_sheet_selection_select_path (selection, path);
+   pspp_sheet_selection_select_all_columns (selection);
+   gtk_tree_path_free (path);
+ }
+ static void
+ make_row_number_column (PsppireDataSheet *data_sheet,
+                         PsppireDataStore *ds)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppSheetViewColumn *column;
+   GtkCellRenderer *renderer;
+   renderer = psppire_cell_renderer_button_new ();
+   g_object_set (renderer, "xalign", 1.0, NULL);
+   g_signal_connect (renderer, "clicked", G_CALLBACK (on_row_number_clicked),
+                     sheet_view);
+   column = pspp_sheet_view_column_new_with_attributes (_("Case"),
+                                                        renderer, NULL);
+   pspp_sheet_view_column_set_selectable (column, TRUE);
+   pspp_sheet_view_column_set_row_head (column, TRUE);
+   pspp_sheet_view_column_set_tabbable (column, FALSE);
+   pspp_sheet_view_column_set_clickable (column, TRUE);
+   pspp_sheet_view_column_set_cell_data_func (
+     column, renderer, render_row_number_cell, ds, NULL);
+   pspp_sheet_view_column_set_fixed_width (column, 50);
+   pspp_sheet_view_column_set_visible (column, data_sheet->show_case_numbers);
+   pspp_sheet_view_append_column (sheet_view, column);
+ }
+ static void
+ render_data_cell (PsppSheetViewColumn *tree_column,
+                   GtkCellRenderer *cell,
+                   GtkTreeModel *model,
+                   GtkTreeIter *iter,
+                   gpointer data_sheet_)
+ {
+   PsppireDataSheet *data_sheet = data_sheet_;
+   PsppireDataStore *store = psppire_data_sheet_get_data_store (data_sheet);
+   struct variable *var;
+   gchar *string;
+   gint row;
+   double xalign;
+   row = GPOINTER_TO_INT (iter->user_data);
+   var = g_object_get_data (G_OBJECT (tree_column), "variable");
+   string = psppire_data_store_get_string (store, row, var,
+                                           data_sheet->show_value_labels);
+   if (string != NULL)
+     {
+       GValue gvalue = { 0 };
+       g_value_init (&gvalue, G_TYPE_STRING);
+       g_value_take_string (&gvalue, string);
+       g_object_set_property (G_OBJECT (cell), "text", &gvalue);
+       g_value_unset (&gvalue);
+     }
+   else
+     g_object_set (G_OBJECT (cell), "text", "", NULL);
+   switch (var_get_alignment (var))
+     {
+     case ALIGN_LEFT: xalign = 0.0; break;
+     case ALIGN_RIGHT: xalign = 1.0; break;
+     case ALIGN_CENTRE: xalign = 0.5; break;
+     default: xalign = 0.0; break;
+     }
+   g_object_set (cell,
+                 "xalign", xalign,
+                 "editable", TRUE,
+                 NULL);
+ }
+ static gint
+ get_string_width (PsppSheetView *treeview, GtkCellRenderer *renderer,
+                   const char *string)
+ {
+   gint width;
+   g_object_set (G_OBJECT (renderer), "text", string, (void *) NULL);
+   gtk_cell_renderer_get_preferred_width (renderer, GTK_WIDGET (treeview),
+                                        NULL, &width);
+   return width;
+ }
+ static gint
+ get_monospace_width (PsppSheetView *treeview, GtkCellRenderer *renderer,
+                      size_t char_cnt)
+ {
+   struct string s;
+   gint width;
+   ds_init_empty (&s);
+   ds_put_byte_multiple (&s, '0', char_cnt);
+   ds_put_byte (&s, ' ');
+   width = get_string_width (treeview, renderer, ds_cstr (&s));
+   ds_destroy (&s);
+   return width;
+ }
+ static void
+ on_data_column_editing_started (GtkCellRenderer *cell,
+                                 GtkCellEditable *editable,
+                                 const gchar     *path,
+                                 gpointer         user_data)
+ {
+   PsppSheetViewColumn *column = g_object_get_data (G_OBJECT (cell), "column");
+   PsppireDataSheet *data_sheet = g_object_get_data (G_OBJECT (cell), "data-sheet");
+   PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet);
+   struct variable *var;
+   g_return_if_fail (column);
+   g_return_if_fail (data_sheet);
+   g_return_if_fail (data_store);
+   g_object_ref (editable);
+   g_object_set_data_full (G_OBJECT (cell), "data-sheet-editable",
+                           editable, g_object_unref);
+   var = g_object_get_data (G_OBJECT (column), "variable");
+   g_return_if_fail (var);
+   if (var_has_value_labels (var) && GTK_IS_COMBO_BOX (editable))
+     {
+       const struct val_labs *labels = var_get_value_labels (var);
+       const struct val_lab **vls = val_labs_sorted (labels);
+       size_t n_vls = val_labs_count (labels);
+       GtkListStore *list_store;
+       int i;
+       list_store = gtk_list_store_new (1, G_TYPE_STRING);
+       for (i = 0; i < n_vls; ++i)
+         {
+           const struct val_lab *vl = vls[i];
+           GtkTreeIter iter;
+           gtk_list_store_append (list_store, &iter);
+           gtk_list_store_set (list_store, &iter,
+                               0, val_lab_get_label (vl),
+                               -1);
+         }
+       free (vls);
+       gtk_combo_box_set_model (GTK_COMBO_BOX (editable),
+                                GTK_TREE_MODEL (list_store));
+       g_object_unref (list_store);
+     }
+ }
+ static void
+ scroll_to_bottom (GtkWidget      *widget,
+                   GtkRequisition *requisition,
+                   gpointer        unused UNUSED)
+ {
+   PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (widget);
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (widget);
+   GtkAdjustment *vadjust;
+   vadjust = pspp_sheet_view_get_vadjustment (sheet_view);
+   gtk_adjustment_set_value (vadjust, gtk_adjustment_get_upper (vadjust));
+   if (data_sheet->scroll_to_bottom_signal)
+     {
+       g_signal_handler_disconnect (data_sheet,
+                                    data_sheet->scroll_to_bottom_signal);
+       data_sheet->scroll_to_bottom_signal = 0;
+     }
+ }
+ static void
+ on_data_column_edited (GtkCellRendererText *cell,
+                        gchar               *path_string,
+                        gchar               *new_text,
+                        gpointer             user_data)
+ {
+   PsppSheetViewColumn *column = g_object_get_data (G_OBJECT (cell), "column");
+   PsppireDataSheet *data_sheet = g_object_get_data (G_OBJECT (cell), "data-sheet");
+   PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet);
+   GtkEditable *editable;
+   struct variable *var;
+   GtkTreePath *path;
+   gboolean is_val_lab;
+   gboolean new_row;
+   gint row;
+   path = gtk_tree_path_new_from_string (path_string);
+   row = gtk_tree_path_get_indices (path)[0];
+   gtk_tree_path_free (path);
+   var = g_object_get_data (G_OBJECT (column), "variable");
+   new_row = row == psppire_data_store_get_case_count (data_store);
+   if (new_row && new_text[0] == '\0')
+     return;
+   editable = g_object_steal_data (G_OBJECT (cell), "data-sheet-editable");
+   g_return_if_fail (editable != NULL);
+   is_val_lab = (GTK_IS_COMBO_BOX (editable)
+                 && gtk_combo_box_get_active (GTK_COMBO_BOX (editable)) >= 0);
+   g_object_unref (editable);
+   psppire_data_store_set_string (data_store, new_text, row, var, is_val_lab);
+   if (new_row && !data_sheet->scroll_to_bottom_signal)
+     {
+       gtk_widget_queue_resize (GTK_WIDGET (data_sheet));
+       data_sheet->scroll_to_bottom_signal =
+         g_signal_connect (data_sheet, "size-allocate",
+                           G_CALLBACK (scroll_to_bottom), NULL);
+     }
+   else
+     {
+       /* We could be more specific about what to redraw, if it seems
+          important for performance. */
+       gtk_widget_queue_draw (GTK_WIDGET (data_sheet));
+     }
+ }
+ static void
+ scroll_to_right (GtkWidget      *widget,
+                  PsppireDataSheet  *data_sheet)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppSheetViewColumn *column, *prev;
+   GList *columns, *iter;
+   column = NULL;
+   prev = NULL;
+   columns = pspp_sheet_view_get_columns (sheet_view);
+   for (iter = columns; iter; iter = iter->next)
+     {
+       PsppSheetViewColumn *c = iter->data;
+       if (g_object_get_data (G_OBJECT (c), "new-var-column"))
+         {
+           column = c;
+           break;
+         }
+       prev = c;
+     }
+   g_list_free (columns);
+   if (column == NULL)
+     return;
+   pspp_sheet_view_scroll_to_cell (sheet_view, NULL, column, FALSE, 0, 0);
+   if (prev)
+     {
+       GtkTreePath *path;
+       pspp_sheet_view_get_cursor (sheet_view, &path, NULL);
+       if (path)
+         {
+           pspp_sheet_view_set_cursor (sheet_view, path, prev, TRUE);
+           gtk_tree_path_free (path);
+         }
+     }
+   if (data_sheet->scroll_to_right_signal)
+     {
+       g_signal_handler_disconnect (widget, data_sheet->scroll_to_right_signal);
+       data_sheet->scroll_to_right_signal = 0;
+     }
+ }
+ static void
+ on_new_variable_column_edited (GtkCellRendererText *cell,
+                                gchar               *path_string,
+                                gchar               *new_text,
+                                gpointer             user_data)
+ {
+   PsppireDataSheet *data_sheet = g_object_get_data (G_OBJECT (cell), "data-sheet");
+   PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet);
+   PsppireDict *dict = data_store->dict;
+   struct variable *var;
+   GtkTreePath *path;
+   char name[64];
+   gint row;
+   if (new_text[0] == '\0')
+     {
+       /* User didn't enter anything so don't create a variable. */
+       return;
+     }
+   path = gtk_tree_path_new_from_string (path_string);
+   row = gtk_tree_path_get_indices (path)[0];
+   gtk_tree_path_free (path);
+   if (!psppire_dict_generate_name (dict, name, sizeof name))
+     return;
+   var = psppire_dict_insert_variable (dict, psppire_dict_get_var_cnt (dict),
+                                       name);
+   g_return_if_fail (var != NULL);
+   psppire_data_store_set_string (data_store, new_text, row, var, FALSE);
+   if (!data_sheet->scroll_to_right_signal)
+     {
+       gtk_widget_queue_resize (GTK_WIDGET (data_sheet));
+       data_sheet->scroll_to_right_signal =
+         g_signal_connect_after (gtk_widget_get_toplevel (GTK_WIDGET (data_sheet)), "check-resize",
+                                 G_CALLBACK (scroll_to_right), data_sheet);
+     }
+   else
+     {
+       /* We could be more specific about what to redraw, if it seems
+          important for performance. */
+       gtk_widget_queue_draw (GTK_WIDGET (data_sheet));
+     }
+ }
+ static void
+ calc_width_conversion (PsppireDataSheet *data_sheet,
+                        gint *base_width, gint *incr_width)
+ {
+   GtkCellRenderer *cell;
+   gint w1, w10;
+   cell = gtk_cell_renderer_text_new ();
+   w1 = get_monospace_width (PSPP_SHEET_VIEW (data_sheet), cell, 1);
+   w10 = get_monospace_width (PSPP_SHEET_VIEW (data_sheet), cell, 10);
+   *incr_width = MAX (1, (w10 - w1) / 9);
+   *base_width = MAX (0, w10 - *incr_width * 10);
+   g_object_ref_sink (cell);
+   g_object_unref (cell);
+ }
+ static gint
+ display_width_from_pixel_width (PsppireDataSheet *data_sheet,
+                                 gint pixel_width)
+ {
+   gint base_width, incr_width;
+   calc_width_conversion (data_sheet, &base_width, &incr_width);
+   return MAX ((pixel_width - base_width + incr_width / 2) / incr_width, 1);
+ }
+ static gint
+ display_width_to_pixel_width (PsppireDataSheet *data_sheet,
+                               gint display_width,
+                               gint base_width,
+                               gint incr_width)
+ {
+   return base_width + incr_width * display_width;
+ }
+ static void
+ on_data_column_resized (GObject    *gobject,
+                         GParamSpec *pspec,
+                         gpointer    user_data)
+ {
+   PsppireDataSheet *data_sheet = user_data;
+   PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet);
+   PsppSheetViewColumn *column = PSPP_SHEET_VIEW_COLUMN (gobject);
+   struct variable *var;
+   gint pixel_width;
+   int display_width;
+   if (data_store == NULL)
+     return;
+   pixel_width = pspp_sheet_view_column_get_width (column);
+   if (pixel_width == pspp_sheet_view_column_get_fixed_width (column))
+     {
+       /* Short-circuit the expensive display_width_from_pixel_width()
+          calculation, to make loading .sav files with 2000 columns visibly
+          faster. */
+       return;
+     }
+   var = g_object_get_data (G_OBJECT (column), "variable");
+   display_width = display_width_from_pixel_width (data_sheet, pixel_width);
+   var_set_display_width (var, display_width);
+ }
+ enum sort_order
+   {
+     SORT_ASCEND,
+     SORT_DESCEND
+   };
+ static void
+ do_sort (PsppireDataSheet *data_sheet, enum sort_order order)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view);
+   PsppireDataWindow *pdw;
+   GList *list, *iter;
+   GString *syntax;
+   int n_vars;
+   pdw = psppire_data_window_for_data_store (data_sheet->data_store);
+   g_return_if_fail (pdw != NULL);
+   list = pspp_sheet_selection_get_selected_columns (selection);
+   syntax = g_string_new ("SORT CASES BY");
+   n_vars = 0;
+   for (iter = list; iter; iter = iter->next)
+     {
+       PsppSheetViewColumn *column = iter->data;
+       struct variable *var;
+       var = g_object_get_data (G_OBJECT (column), "variable");
+       if (var != NULL)
+         {
+           g_string_append_printf (syntax, " %s", var_get_name (var));
+           n_vars++;
+         }
+     }
+   if (n_vars > 0)
+     {
+       if (order == SORT_DESCEND)
+         g_string_append (syntax, " (DOWN)");
+       g_string_append_c (syntax, '.');
+       execute_const_syntax_string (pdw, syntax->str);
+     }
+   g_string_free (syntax, TRUE);
+ }
+ static void
+ on_sort_up (PsppireDataSheet *data_sheet)
+ {
+   do_sort (data_sheet, SORT_ASCEND);
+ }
+ static void
+ on_sort_down (PsppireDataSheet *data_sheet)
+ {
+   do_sort (data_sheet, SORT_DESCEND);
+ }
+ static void
+ do_data_column_popup_menu (PsppSheetViewColumn *column,
+                            guint button, guint32 time)
+ {
+   GtkWidget *sheet_view = pspp_sheet_view_column_get_tree_view (column);
+   PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (sheet_view);
+   gtk_menu_popup (GTK_MENU (data_sheet->column_popup_menu), NULL, NULL, NULL, NULL, button, time);
+ }
+ static void
+ on_data_column_popup_menu (PsppSheetViewColumn *column,
+                            gpointer user_data UNUSED)
+ {
+   do_data_column_popup_menu (column, 0, gtk_get_current_event_time ());
+ }
+ static gboolean
+ on_column_button_press_event (PsppSheetViewColumn *column,
+                               GdkEventButton *event,
+                               gpointer user_data UNUSED)
+ {
+   PsppSheetSelection *selection;
+   PsppSheetView *sheet_view;
+   sheet_view = PSPP_SHEET_VIEW (pspp_sheet_view_column_get_tree_view (
+                                   column));
+   g_return_val_if_fail (sheet_view != NULL, FALSE);
+   selection = pspp_sheet_view_get_selection (sheet_view);
+   g_return_val_if_fail (selection != NULL, FALSE);
+   if (event->type == GDK_BUTTON_PRESS && event->button == 3)
+     {
+       do_data_column_popup_menu (column, event->button, event->time);
+       return TRUE;
+     }
+   else if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
+     {
+       PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (sheet_view);
+       struct variable *var;
+       var = g_object_get_data (G_OBJECT (column), "variable");
+       if (var != NULL)
+         {
+           gboolean handled;
+           g_signal_emit_by_name (data_sheet, "var-double-clicked",
+                                  var_get_dict_index (var), &handled);
+           return handled;
+         }
+     }
+   return FALSE;
+ }
+ static gboolean
+ on_data_column_query_tooltip (PsppSheetViewColumn *column,
+                               GtkTooltip *tooltip,
+                               gpointer user_data UNUSED)
+ {
+   struct variable *var;
+   const char *text;
+   var = g_object_get_data (G_OBJECT (column), "variable");
+   g_return_val_if_fail (var != NULL, FALSE);
+   text = var_has_label (var) ? var_get_label (var) : var_get_name (var);
+   gtk_tooltip_set_text (tooltip, text);
+   return TRUE;
+ }
+ static void
+ add_data_column_cell_renderer (PsppireDataSheet *data_sheet,
+                                PsppSheetViewColumn *column)
+ {
+   GtkCellRenderer *cell;
+   struct variable *var;
+   var = g_object_get_data (G_OBJECT (column), "variable");
+   g_return_if_fail (var != NULL);
+   if (data_sheet->show_value_labels && var_has_value_labels (var))
+     {
+       cell = gtk_cell_renderer_combo_new ();
+       g_object_set (G_OBJECT (cell),
+                     "has-entry", TRUE,
+                     "text-column", 0,
+                     NULL);
+     }
+   else
+     cell = gtk_cell_renderer_text_new ();
+   g_signal_connect (cell, "editing-started",
+                     G_CALLBACK (on_data_column_editing_started), NULL);
+   g_signal_connect (cell, "edited", G_CALLBACK (on_data_column_edited), NULL);
+   g_object_set_data (G_OBJECT (cell), "column", column);
+   g_object_set_data (G_OBJECT (cell), "data-sheet", data_sheet);
+   pspp_sheet_view_column_clear (column);
+   pspp_sheet_view_column_pack_start (column, cell, TRUE);
+   pspp_sheet_view_column_set_cell_data_func (
+     column, cell, render_data_cell, data_sheet, NULL);
+ }
+ static PsppSheetViewColumn *
+ make_data_column (PsppireDataSheet *data_sheet, gint dict_idx,
+                   gint base_width, gint incr_width)
+ {
+   PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet);
+   struct variable *var;
+   PsppSheetViewColumn *column;
+   char *name;
+   int width;
+   var = psppire_dict_get_variable (data_store->dict, dict_idx);
+   column = pspp_sheet_view_column_new ();
+   name = escape_underscores (var_get_name (var));
+   pspp_sheet_view_column_set_title (column, name);
+   free (name);
+   g_object_set_data (G_OBJECT (column), "variable", var);
+   width = display_width_to_pixel_width (data_sheet,
+                                         var_get_display_width (var),
+                                         base_width, incr_width);
+   pspp_sheet_view_column_set_min_width (column, 10);
+   pspp_sheet_view_column_set_fixed_width (column, width);
+   pspp_sheet_view_column_set_resizable (column, TRUE);
+   pspp_sheet_view_column_set_clickable (column, TRUE);
+   g_signal_connect (column, "notify::width",
+                     G_CALLBACK (on_data_column_resized), data_sheet);
+   g_signal_connect (column, "button-press-event",
+                     G_CALLBACK (on_column_button_press_event),
+                     data_sheet);
+   g_signal_connect (column, "query-tooltip",
+                     G_CALLBACK (on_data_column_query_tooltip), NULL);
+   g_signal_connect (column, "popup-menu",
+                     G_CALLBACK (on_data_column_popup_menu), data_sheet);
+   add_data_column_cell_renderer (data_sheet, column);
+   return column;
+ }
+ static void
+ make_new_variable_column (PsppireDataSheet *data_sheet,
+                           gint base_width, gint incr_width)
+ {
+   PsppSheetViewColumn *column;
+   GtkCellRenderer *cell;
+   int width;
+   cell = gtk_cell_renderer_text_new ();
+   g_object_set (cell, "editable", TRUE, NULL);
+   g_signal_connect (cell, "edited", G_CALLBACK (on_new_variable_column_edited),
+                     NULL);
+   column = pspp_sheet_view_column_new_with_attributes ("", cell, NULL);
+   g_object_set_data (G_OBJECT (column), "new-var-column", column);
+   width = display_width_to_pixel_width (data_sheet, 8, base_width, incr_width);
+   pspp_sheet_view_column_set_min_width (column, 10);
+   pspp_sheet_view_column_set_fixed_width (column, width);
+   pspp_sheet_view_column_set_tabbable (column, FALSE);
+   g_object_set_data (G_OBJECT (cell), "data-sheet", data_sheet);
+   g_signal_connect (column, "button-press-event",
+                     G_CALLBACK (on_column_button_press_event),
+                     data_sheet);
+   g_signal_connect (column, "popup-menu",
+                     G_CALLBACK (on_data_column_popup_menu), data_sheet);
+   pspp_sheet_view_column_set_visible (column, data_sheet->may_create_vars);
+   pspp_sheet_view_append_column (PSPP_SHEET_VIEW (data_sheet), column);
+   data_sheet->new_variable_column = column;
+ }
+ static void
+ psppire_data_sheet_model_changed (GObject    *gobject,
+                                   GParamSpec *pspec,
+                                   gpointer    user_data)
+ {
+   PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (gobject);
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppireDataStore *data_store;
+   /* Remove old columns. */
+   for (;;)
+     {
+       PsppSheetViewColumn *column = pspp_sheet_view_get_column (sheet_view, 0);
+       if (column == NULL)
+         break;
+       pspp_sheet_view_remove_column (sheet_view, column);
+     }
+   data_sheet->new_variable_column = NULL;
+   if (pspp_sheet_view_get_model (sheet_view) == NULL)
+     {
+       /* Don't create any columns at all if there's no model.  Otherwise we'll
+          create some columns as part of the "dispose" callback for the sheet
+          view, which sets the model to NULL.  That causes warnings to be
+          logged and is obviously undesirable in any case. */
+       return;
+     }
+   /* Add new columns. */
+   data_store = psppire_data_sheet_get_data_store (data_sheet);
+   if (data_store != NULL)
+     {
+       gint base_width, incr_width;
+       int i;
+       calc_width_conversion (data_sheet, &base_width, &incr_width);
+       make_row_number_column (data_sheet, data_store);
+       for (i = 0; i < psppire_dict_get_var_cnt (data_store->dict); i++)
+         {
+           PsppSheetViewColumn *column;
+           column = make_data_column (data_sheet, i, base_width, incr_width);
+           pspp_sheet_view_append_column (sheet_view, column);
+         }
+       make_new_variable_column (data_sheet, base_width, incr_width);
+     }
+ }
+ enum
+   {
+     PROP_0,
+     PROP_DATA_STORE,
+     PROP_VALUE_LABELS,
+     PROP_CASE_NUMBERS,
+     PROP_CURRENT_CASE,
+     PROP_MAY_CREATE_VARS,
+     PROP_MAY_DELETE_VARS
+   };
+ static void
+ psppire_data_sheet_set_property (GObject      *object,
+                                  guint         prop_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+ {
+   PsppireDataSheet *obj = PSPPIRE_DATA_SHEET (object);
+   switch (prop_id)
+     {
+     case PROP_DATA_STORE:
+       psppire_data_sheet_set_data_store (
+         obj, PSPPIRE_DATA_STORE (g_value_get_object (value)));
+       break;
+     case PROP_VALUE_LABELS:
+       psppire_data_sheet_set_value_labels (obj, g_value_get_boolean (value));
+       break;
+     case PROP_CASE_NUMBERS:
+       psppire_data_sheet_set_case_numbers (obj, g_value_get_boolean (value));
+       break;
+     case PROP_CURRENT_CASE:
+       psppire_data_sheet_goto_case (obj, g_value_get_long (value));
+       break;
+     case PROP_MAY_CREATE_VARS:
+       psppire_data_sheet_set_may_create_vars (obj,
+                                               g_value_get_boolean (value));
+       break;
+     case PROP_MAY_DELETE_VARS:
+       psppire_data_sheet_set_may_delete_vars (obj,
+                                               g_value_get_boolean (value));
+       break;
+     default:
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       break;
+     }
+ }
+ static void
+ psppire_data_sheet_get_property (GObject      *object,
+                                  guint         prop_id,
+                                  GValue       *value,
+                                  GParamSpec   *pspec)
+ {
+   PsppireDataSheet *obj = PSPPIRE_DATA_SHEET (object);
+   switch (prop_id)
+     {
+     case PROP_DATA_STORE:
+       g_value_set_object (value, psppire_data_sheet_get_data_store (obj));
+       break;
+     case PROP_VALUE_LABELS:
+       g_value_set_boolean (value, psppire_data_sheet_get_value_labels (obj));
+       break;
+     case PROP_CASE_NUMBERS:
+       g_value_set_boolean (value, psppire_data_sheet_get_case_numbers (obj));
+       break;
+     case PROP_CURRENT_CASE:
+       g_value_set_long (value, psppire_data_sheet_get_selected_case (obj));
+       break;
+     case PROP_MAY_CREATE_VARS:
+       g_value_set_boolean (value, obj->may_create_vars);
+       break;
+     case PROP_MAY_DELETE_VARS:
+       g_value_set_boolean (value, obj->may_delete_vars);
+       break;
+     default:
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       break;
+     }
+ }
+ gboolean
+ psppire_data_sheet_get_value_labels (const PsppireDataSheet *ds)
+ {
+   return ds->show_value_labels;
+ }
+ void
+ psppire_data_sheet_set_value_labels (PsppireDataSheet *ds,
+                                   gboolean show_value_labels)
+ {
+   show_value_labels = !!show_value_labels;
+   if (show_value_labels != ds->show_value_labels)
+     {
+       ds->show_value_labels = show_value_labels;
+       g_object_notify (G_OBJECT (ds), "value-labels");
+       /* Pretend the model changed, to force the columns to be rebuilt.
+          Otherwise cell renderers won't get changed from combo boxes to text
+          entries or vice versa. */
+       g_object_notify (G_OBJECT (ds), "model");
+     }
+ }
+ gboolean
+ psppire_data_sheet_get_case_numbers (const PsppireDataSheet *ds)
+ {
+   return ds->show_case_numbers;
+ }
+ void
+ psppire_data_sheet_set_case_numbers (PsppireDataSheet *ds,
+                                      gboolean show_case_numbers)
+ {
+   show_case_numbers = !!show_case_numbers;
+   if (show_case_numbers != ds->show_case_numbers)
+     {
+       PsppSheetViewColumn *column;
+       ds->show_case_numbers = show_case_numbers;
+       column = pspp_sheet_view_get_column (PSPP_SHEET_VIEW (ds), 0);
+       if (column)
+         pspp_sheet_view_column_set_visible (column, show_case_numbers);
+       g_object_notify (G_OBJECT (ds), "case-numbers");
+       gtk_widget_queue_draw (GTK_WIDGET (ds));
+     }
+ }
+ gboolean
+ psppire_data_sheet_get_may_create_vars (PsppireDataSheet *data_sheet)
+ {
+   return data_sheet->may_create_vars;
+ }
+ void
+ psppire_data_sheet_set_may_create_vars (PsppireDataSheet *data_sheet,
+                                        gboolean may_create_vars)
+ {
+   if (data_sheet->may_create_vars != may_create_vars)
+     {
+       data_sheet->may_create_vars = may_create_vars;
+       if (data_sheet->new_variable_column)
+         pspp_sheet_view_column_set_visible (data_sheet->new_variable_column,
+                                             may_create_vars);
+       on_selection_changed (pspp_sheet_view_get_selection (
+                               PSPP_SHEET_VIEW (data_sheet)), NULL);
+     }
+ }
+ gboolean
+ psppire_data_sheet_get_may_delete_vars (PsppireDataSheet *data_sheet)
+ {
+   return data_sheet->may_delete_vars;
+ }
+ void
+ psppire_data_sheet_set_may_delete_vars (PsppireDataSheet *data_sheet,
+                                        gboolean may_delete_vars)
+ {
+   if (data_sheet->may_delete_vars != may_delete_vars)
+     {
+       data_sheet->may_delete_vars = may_delete_vars;
+       on_selection_changed (pspp_sheet_view_get_selection (
+                               PSPP_SHEET_VIEW (data_sheet)), NULL);
+     }
+ }
+ static PsppSheetViewColumn *
+ psppire_data_sheet_find_column_for_variable (PsppireDataSheet *data_sheet,
+                                              gint dict_index)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppireDataStore *data_store;
+   PsppSheetViewColumn *column;
+   struct variable *var;
+   GList *list, *iter;
+   data_store = psppire_data_sheet_get_data_store (data_sheet);
+   g_return_val_if_fail (data_store != NULL, NULL);
+   g_return_val_if_fail (data_store->dict != NULL, NULL);
+   var = psppire_dict_get_variable (data_store->dict, dict_index);
+   g_return_val_if_fail (var != NULL, NULL);
+   column = NULL;
+   list = pspp_sheet_view_get_columns (sheet_view);
+   for (iter = list; iter != NULL; iter = iter->next)
+     {
+       PsppSheetViewColumn *c = iter->data;
+       struct variable *v;
+       v = g_object_get_data (G_OBJECT (c), "variable");
+       if (v == var)
+         {
+           column = c;
+           break;
+         }
+     }
+   g_list_free (list);
+   return column;
+ }
+ void
+ psppire_data_sheet_goto_variable (PsppireDataSheet *data_sheet,
+                                   gint dict_index)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppSheetViewColumn *column;
+   column = psppire_data_sheet_find_column_for_variable (data_sheet,
+                                                         dict_index);
+   if (column != NULL)
+     {
+       GtkTreePath *path;
+       gint row = psppire_data_sheet_get_current_case (data_sheet);
+       path = gtk_tree_path_new_from_indices (row >= 0 ? row : 0, -1);
+       pspp_sheet_view_scroll_to_cell (sheet_view, path, column,
+                                       FALSE, 0.0, 0.0);
+       pspp_sheet_view_set_cursor (sheet_view, path, column, FALSE);
+       gtk_tree_path_free (path);
+     }
+ }
+ struct variable *
+ psppire_data_sheet_get_current_variable (const PsppireDataSheet *data_sheet)
+ {
+   PsppSheetSelection *selection;
+   struct variable *var;
+   GList *selected_columns;
+   GList *iter;
+   selection = pspp_sheet_view_get_selection (PSPP_SHEET_VIEW (data_sheet));
+   selected_columns = pspp_sheet_selection_get_selected_columns (selection);
+   var = NULL;
+   for (iter = selected_columns; iter != NULL; iter = iter->next)
+     {
+       PsppSheetViewColumn *column = iter->data;
+       struct variable *v = g_object_get_data (G_OBJECT (column), "variable");
+       if (v != NULL)
+         {
+           if (var)
+             {
+               var = NULL;
+               break;
+             }
+           else
+             var = v;
+         }
+     }
+   g_list_free (selected_columns);
+   return var;
+ }
+ void
+ psppire_data_sheet_goto_case (PsppireDataSheet *data_sheet, gint case_index)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppireDataStore *store = data_sheet->data_store;
+   PsppSheetSelection *selection;
+   GtkTreePath *path;
+   g_return_if_fail (case_index >= 0);
+   g_return_if_fail (case_index < psppire_data_store_get_case_count (store));
+   path = gtk_tree_path_new_from_indices (case_index, -1);
+   /* Select the case. */
+   selection = pspp_sheet_view_get_selection (sheet_view);
+   pspp_sheet_selection_unselect_all (selection);
+   pspp_sheet_selection_select_path (selection, path);
+   pspp_sheet_selection_select_all_columns (selection);
+   /* Scroll so that the case is visible. */
+   pspp_sheet_view_scroll_to_cell (sheet_view, path, NULL, FALSE, 0.0, 0.0);
+   gtk_tree_path_free (path);
+ }
+ /* Returns the 0-based index of a selected case, if there is at least one, and
+    -1 otherwise.
+    If more than one case is selected, returns the one with the smallest index,
+    that is, the index of the case closest to the beginning of the file.  The
+    row that can be used to insert a new case is not considered a case. */
+ gint
+ psppire_data_sheet_get_selected_case (const PsppireDataSheet *data_sheet)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppireDataStore *store = data_sheet->data_store;
+   const struct range_set_node *node;
+   PsppSheetSelection *selection;
+   struct range_set *rows;
+   gint row;
+   selection = pspp_sheet_view_get_selection (sheet_view);
+   rows = pspp_sheet_selection_get_range_set (selection);
+   node = range_set_first (rows);
+   row = (node && node->start < psppire_data_store_get_case_count (store)
+          ? node->start
+          : -1);
+   range_set_destroy (rows);
+   return row;
+ }
+ /* Returns the 0-based index of a selected case, if exactly one case is
+    selected, and -1 otherwise.  Returns -1 if the row that can be used to
+    insert a new case is selected. */
+ gint
+ psppire_data_sheet_get_current_case (const PsppireDataSheet *data_sheet)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppireDataStore *store = data_sheet->data_store;
+   const struct range_set_node *node;
+   PsppSheetSelection *selection;
+   struct range_set *rows;
+   gint row;
+   selection = pspp_sheet_view_get_selection (sheet_view);
+   if (pspp_sheet_selection_count_selected_rows (selection) != 1)
+     return -1;
+   rows = pspp_sheet_selection_get_range_set (selection);
+   node = range_set_first (rows);
+   row = (node && node->start < psppire_data_store_get_case_count (store)
+          ? node->start
+          : -1);
+   range_set_destroy (rows);
+   return row;
+ }
+ static void
+ psppire_data_sheet_dispose (GObject *object)
+ {
+   PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (object);
+   if (data_sheet->clip != NULL && data_sheet->on_owner_change_signal != 0)
+     {
+       g_signal_handler_disconnect (data_sheet->clip,
+                                    data_sheet->on_owner_change_signal);
+       data_sheet->on_owner_change_signal = 0;
+     }
+   if (data_sheet->dispose_has_run)
+     return;
+   data_sheet->dispose_has_run = TRUE;
+   psppire_data_sheet_unset_data_store (data_sheet);
+   G_OBJECT_CLASS (psppire_data_sheet_parent_class)->dispose (object);
+ }
+ static void
+ psppire_data_sheet_map (GtkWidget *widget)
+ {
+   PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (widget);
+   GTK_WIDGET_CLASS (psppire_data_sheet_parent_class)->map (widget);
+   data_sheet->clip = gtk_widget_get_clipboard (widget,
+                                                GDK_SELECTION_CLIPBOARD);
+   if (data_sheet->on_owner_change_signal)
+     g_signal_handler_disconnect (data_sheet->clip,
+                                  data_sheet->on_owner_change_signal);
+   data_sheet->on_owner_change_signal
+     = g_signal_connect (data_sheet->clip, "owner-change",
+                         G_CALLBACK (on_owner_change), widget);
+   on_owner_change (data_sheet->clip, NULL, widget);
+ }
+ static void
+ psppire_data_sheet_class_init (PsppireDataSheetClass *class)
+ {
+   GObjectClass *gobject_class;
+   GtkWidgetClass *widget_class;
+   gobject_class = G_OBJECT_CLASS (class);
+   gobject_class->set_property = psppire_data_sheet_set_property;
+   gobject_class->get_property = psppire_data_sheet_get_property;
+   gobject_class->dispose = psppire_data_sheet_dispose;
+   widget_class = GTK_WIDGET_CLASS (class);
+   widget_class->map = psppire_data_sheet_map;
+   g_signal_new ("var-double-clicked",
+                 G_OBJECT_CLASS_TYPE (gobject_class),
+                 G_SIGNAL_RUN_LAST,
+                 0,
+                 g_signal_accumulator_true_handled, NULL,
+                 psppire_marshal_BOOLEAN__INT,
+                 G_TYPE_BOOLEAN, 1, G_TYPE_INT);
+   g_object_class_install_property (
+     gobject_class, PROP_DATA_STORE,
+     g_param_spec_object ("data-store",
+                          "Data Store",
+                          "The data store for the data sheet to display.",
+                          PSPPIRE_TYPE_DATA_STORE,
+                          G_PARAM_WRITABLE | G_PARAM_READABLE));
+   g_object_class_install_property (
+     gobject_class, PROP_VALUE_LABELS,
+     g_param_spec_boolean ("value-labels",
+                           "Value Labels",
+                           "Whether or not the data sheet should display labels instead of values",
+                         FALSE,
+                           G_PARAM_WRITABLE | G_PARAM_READABLE));
+   g_object_class_install_property (
+     gobject_class, PROP_CASE_NUMBERS,
+     g_param_spec_boolean ("case-numbers",
+                           "Case Numbers",
+                           "Whether or not the data sheet should display case numbers",
+                         FALSE,
+                           G_PARAM_WRITABLE | G_PARAM_READABLE));
+   g_object_class_install_property (
+     gobject_class,
+     PROP_CURRENT_CASE,
+     g_param_spec_long ("current-case",
+                      "Current Case",
+                      "Zero based number of the selected case",
+                      0, CASENUMBER_MAX,
+                      0,
+                      G_PARAM_WRITABLE | G_PARAM_READABLE));
+   g_object_class_install_property (
+     gobject_class,
+     PROP_MAY_CREATE_VARS,
+     g_param_spec_boolean ("may-create-vars",
+                           "May create variables",
+                           "Whether the user may create more variables",
+                           TRUE,
+                           G_PARAM_READWRITE));
+   
+   g_object_class_install_property (
+     gobject_class,
+     PROP_MAY_DELETE_VARS,
+     g_param_spec_boolean ("may-delete-vars",
+                           "May delete variables",
+                           "Whether the user may delete variables",
+                           TRUE,
+                           G_PARAM_READWRITE));
+ }
+ static void
+ do_row_popup_menu (GtkWidget *widget, guint button, guint32 time)
+ {
+   PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (widget);
+   
+   gtk_menu_popup (GTK_MENU (data_sheet->row_popup_menu), NULL, NULL, NULL, NULL, button, time);
+ }
+ static void
+ on_popup_menu (GtkWidget *widget, gpointer user_data UNUSED)
+ {
+   do_row_popup_menu (widget, 0, gtk_get_current_event_time ());
+ }
+ static gboolean
+ on_button_pressed (GtkWidget *widget, GdkEventButton *event,
+                    gpointer user_data UNUSED)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (widget);
+   if (event->type == GDK_BUTTON_PRESS && event->button == 3)
+     {
+       PsppSheetSelection *selection;
+       selection = pspp_sheet_view_get_selection (sheet_view);
+       if (pspp_sheet_selection_count_selected_rows (selection) <= 1)
+         {
+           GtkTreePath *path;
+           if (pspp_sheet_view_get_path_at_pos (sheet_view, event->x, event->y,
+                                                &path, NULL, NULL, NULL))
+             {
+               pspp_sheet_selection_unselect_all (selection);
+               pspp_sheet_selection_select_path (selection, path);
+               pspp_sheet_selection_select_all_columns (selection);
+               gtk_tree_path_free (path);
+             }
+         }
+       do_row_popup_menu (widget, event->button, event->time);
+       return TRUE;
+     }
+   return FALSE;
+ }
+ void
+ psppire_data_sheet_edit_clear_cases (PsppireDataSheet *data_sheet)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view);
+   const struct range_set_node *node;
+   struct range_set *selected;
+   selected = pspp_sheet_selection_get_range_set (selection);
+   for (node = range_set_last (selected); node != NULL;
+        node = range_set_prev (selected, node))
+     {
+       unsigned long int start = range_set_node_get_start (node);
+       unsigned long int count = range_set_node_get_width (node);
+       psppire_data_store_delete_cases (data_sheet->data_store, start, count);
+     }
+   range_set_destroy (selected);
+ }
+ static void
+ on_selection_changed (PsppSheetSelection *selection,
+                       gpointer user_data UNUSED)
+ {
+   PsppSheetView *sheet_view = pspp_sheet_selection_get_tree_view (selection);
+   PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (sheet_view);
+   gboolean any_variables_selected;
+   gboolean may_delete_cases, may_delete_vars, may_insert_vars;
+   GList *list, *iter;
+   GtkTreePath *path;
+   GtkWidget *top = gtk_widget_get_toplevel (GTK_WIDGET (data_sheet));
+   if (! PSPPIRE_IS_DATA_WINDOW (top))
+     return;
+   
+   PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (top);
+   gint n_selected_rows = pspp_sheet_selection_count_selected_rows (selection);
+   gtk_widget_set_sensitive (dw->mi_insert_case, n_selected_rows > 0);
+   switch (n_selected_rows)
+     {
+     case 0:
+       may_delete_cases = FALSE;
+       break;
+     case 1:
+       /* The row used for inserting new cases cannot be deleted. */
+       path = gtk_tree_path_new_from_indices (
+         psppire_data_store_get_case_count (data_sheet->data_store), -1);
+       may_delete_cases = !pspp_sheet_selection_path_is_selected (selection,
+                                                                  path);
+       gtk_tree_path_free (path);
+       break;
+     default:
+       may_delete_cases = TRUE;
+       break;
+     }
+   gtk_widget_set_sensitive (dw->mi_clear_cases, may_delete_cases);
+   any_variables_selected = FALSE;
+   may_delete_vars = may_insert_vars = FALSE;
+   list = pspp_sheet_selection_get_selected_columns (selection);
+   for (iter = list; iter != NULL; iter = iter->next)
+     {
+       PsppSheetViewColumn *column = iter->data;
+       struct variable *var = g_object_get_data (G_OBJECT (column), "variable");
+       if (var != NULL)
+         {
+           may_delete_vars = may_insert_vars = TRUE;
+           any_variables_selected = TRUE;
+           break;
+         }
+       if (g_object_get_data (G_OBJECT (column), "new-var-column") != NULL)
+         may_insert_vars = TRUE;
+     }
+   g_list_free (list);
+   may_insert_vars = may_insert_vars && data_sheet->may_create_vars;
+   may_delete_vars = may_delete_vars && data_sheet->may_delete_vars;
+   gtk_widget_set_sensitive (dw->mi_insert_var, may_insert_vars);
+   gtk_widget_set_sensitive (dw->mi_clear_variables, may_delete_vars);
+   gtk_widget_set_sensitive (data_sheet->pu_sort_up, may_delete_vars);
+   gtk_widget_set_sensitive (data_sheet->pu_sort_down, may_delete_vars);
+   psppire_data_sheet_update_clip_actions (data_sheet);
+   psppire_data_sheet_update_primary_selection (data_sheet,
+                                                (n_selected_rows > 0
+                                                 && any_variables_selected));
+ }
+ static gboolean
+ psppire_data_sheet_get_selected_range (PsppireDataSheet *data_sheet,
+                                     struct range_set **rowsp,
+                                     struct range_set **colsp)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppireDataStore *data_store = data_sheet->data_store;
+   PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view);
+   unsigned long n_cases;
+   struct range_set *rows, *cols;
+   GList *list, *iter;
+   if (data_store == NULL)
+     return FALSE;
+   n_cases = psppire_data_store_get_case_count (data_store);
+   rows = pspp_sheet_selection_get_range_set (selection);
+   range_set_set0 (rows, n_cases, ULONG_MAX - n_cases);
+   if (range_set_is_empty (rows))
+     {
+       range_set_destroy (rows);
+       return FALSE;
+     }
+   cols = range_set_create ();
+   list = pspp_sheet_selection_get_selected_columns (selection);
+   for (iter = list; iter != NULL; iter = iter->next)
+     {
+       PsppSheetViewColumn *column = iter->data;
+       struct variable *var = g_object_get_data (G_OBJECT (column), "variable");
+       if (var != NULL)
+         range_set_set1 (cols, var_get_dict_index (var), 1);
+     }
+   g_list_free (list);
+   if (range_set_is_empty (cols))
+     {
+       range_set_destroy (rows);
+       range_set_destroy (cols);
+       return FALSE;
+     }
+   *rowsp = rows;
+   *colsp = cols;
+   return TRUE;
+ }
+ /* Insert a case at the selected row */
+ void
+ psppire_data_sheet_insert_case (PsppireDataSheet *data_sheet)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view);
+   PsppireDataStore *data_store = data_sheet->data_store;
+   struct range_set *selected = pspp_sheet_selection_get_range_set (selection);
+   unsigned long row = range_set_scan (selected, 0);
+   range_set_destroy (selected);
+   if (row <= psppire_data_store_get_case_count (data_store))
+     psppire_data_store_insert_new_case (data_store, row);
+ }
+ void
+ psppire_data_sheet_insert_variable (PsppireDataSheet *data_sheet)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view);
+   PsppireDict *dict = data_sheet->data_store->dict;
+   PsppSheetViewColumn *column;
+   struct variable *var;
+   gchar name[64];
+   GList *list;
+   gint index;
+   list = pspp_sheet_selection_get_selected_columns (selection);
+   if (list == NULL)
+     return;
+   column = list->data;
+   g_list_free (list);
+   var = g_object_get_data (G_OBJECT (column), "variable");
+   index = var ? var_get_dict_index (var) : psppire_dict_get_var_cnt (dict);
+   if (psppire_dict_generate_name (dict, name, sizeof name))
+     psppire_dict_insert_variable (dict, index, name);
+ }
+ void
+ psppire_data_sheet_edit_clear_variables (PsppireDataSheet *data_sheet)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   PsppSheetSelection *selection = pspp_sheet_view_get_selection (sheet_view);
+   PsppireDict *dict = data_sheet->data_store->dict;
+   GList *iter;
+   GList *list = pspp_sheet_selection_get_selected_columns (selection);
+   
+   if (list == NULL)
+     return;
+   list = g_list_reverse (list);
+   for (iter = list; iter; iter = iter->next)
+     {
+       PsppSheetViewColumn *column = iter->data;
+       struct variable *var = g_object_get_data (G_OBJECT (column), "variable");
+       if (var != NULL)
+         psppire_dict_delete_variables (dict, var_get_dict_index (var), 1);
+     }
+   g_list_free (list);
+ }
+ void
+ psppire_data_sheet_edit_copy (PsppireDataSheet *data_sheet)
+ {
+   psppire_data_sheet_set_clip (data_sheet, FALSE);
+ }
+ void
+ psppire_data_sheet_edit_cut (PsppireDataSheet *data_sheet)
+ {
+   psppire_data_sheet_set_clip (data_sheet, TRUE);
+ }
+ void
+ psppire_data_sheet_edit_paste (PsppireDataSheet *data_sheet)
+ {
+   GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (data_sheet));
+   GtkClipboard *clipboard =
+     gtk_clipboard_get_for_display (display, GDK_SELECTION_CLIPBOARD);
+   gtk_clipboard_request_contents (clipboard,
+                                   gdk_atom_intern ("UTF8_STRING", TRUE),
+                                   psppire_data_sheet_clip_received_cb,
+                                   data_sheet);
+ }
+ static void
+ psppire_data_sheet_init (PsppireDataSheet *obj)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (obj);
+   obj->show_value_labels = FALSE;
+   obj->show_case_numbers = TRUE;
+   obj->may_create_vars = TRUE;
+   obj->may_delete_vars = TRUE;
+   obj->owns_primary_selection = FALSE;
+   obj->scroll_to_bottom_signal = 0;
+   obj->scroll_to_right_signal = 0;
+   obj->on_owner_change_signal = 0;
+   obj->new_variable_column = NULL;
+   obj->container = NULL;
+   obj->dispose_has_run = FALSE;
+   pspp_sheet_view_set_special_cells (sheet_view, PSPP_SHEET_VIEW_SPECIAL_CELLS_YES);
+   {
+     obj->row_popup_menu = gtk_menu_new ();
+     int i = 0;
+     GtkWidget *insert_case = gtk_menu_item_new_with_mnemonic (_("_Insert Case"));
+     GtkWidget *clear_cases = gtk_menu_item_new_with_mnemonic (_("Cl_ear Cases"));
+     gtk_menu_attach (GTK_MENU (obj->row_popup_menu), insert_case,     0, 1, i, i + 1); ++i;
+     gtk_menu_attach (GTK_MENU (obj->row_popup_menu), clear_cases,     0, 1, i, i + 1); ++i;
+     g_signal_connect_swapped (clear_cases, "activate", G_CALLBACK (psppire_data_sheet_edit_clear_cases), obj);
+     g_signal_connect_swapped (insert_case, "activate", G_CALLBACK (psppire_data_sheet_insert_case), obj);
+   
+     gtk_widget_show_all (obj->row_popup_menu);
+   }
+   
+   {
+     obj->column_popup_menu = gtk_menu_new ();
+     int i = 0;
+     GtkWidget *insert_variable = gtk_menu_item_new_with_mnemonic (_("_Insert Variable"));
+     GtkWidget *clear_variables = gtk_menu_item_new_with_mnemonic (_("Cl_ear Variables"));
+     obj->pu_sort_up = gtk_menu_item_new_with_mnemonic (_("Sort _Ascending"));
+     obj->pu_sort_down = gtk_menu_item_new_with_mnemonic (_("Sort _Descending"));
+     g_signal_connect_swapped (clear_variables, "activate", G_CALLBACK (psppire_data_sheet_edit_clear_variables), obj);
+     g_signal_connect_swapped (insert_variable, "activate", G_CALLBACK (psppire_data_sheet_insert_variable), obj);
+     g_signal_connect_swapped (obj->pu_sort_up, "activate", G_CALLBACK (on_sort_up), obj);
+     g_signal_connect_swapped (obj->pu_sort_down, "activate", G_CALLBACK (on_sort_down), obj);
+   
+     gtk_menu_attach (GTK_MENU (obj->column_popup_menu), insert_variable,     0, 1, i, i + 1); ++i;
+     gtk_menu_attach (GTK_MENU (obj->column_popup_menu), clear_variables,     0, 1, i, i + 1); ++i;
+     gtk_menu_attach (GTK_MENU (obj->column_popup_menu), gtk_separator_menu_item_new (),     0, 1, i, i + 1); ++i;
+   
+     gtk_menu_attach (GTK_MENU (obj->column_popup_menu), obj->pu_sort_up,             0, 1, i, i + 1); ++i;
+     gtk_menu_attach (GTK_MENU (obj->column_popup_menu), obj->pu_sort_down,           0, 1, i, i + 1); ++i;
+     gtk_widget_show_all (obj->column_popup_menu);
+   }
+   
+   g_signal_connect (obj, "notify::model",
+                     G_CALLBACK (psppire_data_sheet_model_changed), NULL);
+   pspp_sheet_view_set_rubber_banding (sheet_view, TRUE);
+   pspp_sheet_selection_set_mode (pspp_sheet_view_get_selection (sheet_view),
+                                  PSPP_SHEET_SELECTION_RECTANGLE);
+   g_object_set (G_OBJECT (obj), "has-tooltip", TRUE, (void *) NULL);
+   g_signal_connect (obj, "query-tooltip",
+                     G_CALLBACK (on_query_tooltip), NULL);
+   g_signal_connect (obj, "button-press-event",
+                     G_CALLBACK (on_button_pressed), NULL);
+   
+   g_signal_connect (obj, "popup-menu", G_CALLBACK (on_popup_menu), NULL);
+   g_signal_connect (pspp_sheet_view_get_selection (sheet_view),
+                     "changed", G_CALLBACK (on_selection_changed), NULL);
+ }
+ GtkWidget *
+ psppire_data_sheet_new (void)
+ {
+   return g_object_new (PSPP_TYPE_DATA_SHEET, NULL);
+ }
+ PsppireDataStore *
+ psppire_data_sheet_get_data_store (PsppireDataSheet *data_sheet)
+ {
+   return data_sheet->data_store;
+ }
+ static void
+ refresh_model (PsppireDataSheet *data_sheet)
+ {
+   pspp_sheet_view_set_model (PSPP_SHEET_VIEW (data_sheet), NULL);
+   if (data_sheet->data_store != NULL)
+     {
+       int n_rows = psppire_data_store_get_case_count (data_sheet->data_store) + 1;
+       PsppireEmptyListStore *model = psppire_empty_list_store_new (n_rows);
+       pspp_sheet_view_set_model (PSPP_SHEET_VIEW (data_sheet),
+                                  GTK_TREE_MODEL (model));
+       g_object_unref (model);
+     }
+ }
+ static void
+ on_case_inserted (PsppireDataStore *data_store, gint row,
+                   PsppireDataSheet *data_sheet)
+ {
+   PsppireEmptyListStore *empty_list_store;
+   GtkTreeModel *tree_model;
+   gint n_rows;
+   g_return_if_fail (data_store == data_sheet->data_store);
+   n_rows = psppire_data_store_get_case_count (data_store) + 1;
+   if (row == n_rows - 1)
+     row++;
+   tree_model = pspp_sheet_view_get_model (PSPP_SHEET_VIEW (data_sheet));
+   empty_list_store = PSPPIRE_EMPTY_LIST_STORE (tree_model);
+   psppire_empty_list_store_set_n_rows (empty_list_store, n_rows);
+   psppire_empty_list_store_row_inserted (empty_list_store, row);
+ }
+ static void
+ on_cases_deleted (PsppireDataStore *data_store, gint first, gint n_cases,
+                   PsppireDataSheet *data_sheet)
+ {
+   g_return_if_fail (data_store == data_sheet->data_store);
+   if (n_cases > 1)
+     {
+       /* This is a bit of a cop-out.  We could do better, if it ever turns out
+          that this performs too poorly. */
+       refresh_model (data_sheet);
+     }
+   else
+     {
+       PsppireEmptyListStore *empty_list_store;
+       GtkTreeModel *tree_model;
+       gint n_rows = psppire_data_store_get_case_count (data_store) + 1;
+       tree_model = pspp_sheet_view_get_model (PSPP_SHEET_VIEW (data_sheet));
+       empty_list_store = PSPPIRE_EMPTY_LIST_STORE (tree_model);
+       psppire_empty_list_store_set_n_rows (empty_list_store, n_rows);
+       psppire_empty_list_store_row_deleted (empty_list_store, first);
+     }
+ }
+ static void
+ on_case_change (PsppireDataStore *data_store, gint row,
+                 PsppireDataSheet *data_sheet)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   pspp_sheet_view_stop_editing (sheet_view, TRUE);
+   gtk_widget_queue_draw (GTK_WIDGET (data_sheet));
+ }
+ static void
+ on_backend_changed (PsppireDataStore *data_store,
+                     PsppireDataSheet *data_sheet)
+ {
+   g_return_if_fail (data_store == data_sheet->data_store);
+   refresh_model (data_sheet);
+ }
+ static void
+ on_variable_display_width_changed (PsppireDict *dict, int dict_index,
+                                    PsppireDataSheet *data_sheet)
+ {
+   PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet);
+   PsppSheetViewColumn *column;
+   struct variable *var;
+   int display_width;
+   gint pixel_width;
+   g_return_if_fail (data_sheet->data_store != NULL);
+   g_return_if_fail (dict == data_sheet->data_store->dict);
+   column = psppire_data_sheet_find_column_for_variable (data_sheet,
+                                                         dict_index);
+   if (column == NULL)
+     return;
+   var = psppire_dict_get_variable (data_store->dict, dict_index);
+   g_return_if_fail (var != NULL);
+   pixel_width = pspp_sheet_view_column_get_fixed_width (column);
+   display_width = display_width_from_pixel_width (data_sheet, pixel_width);
+   if (display_width != var_get_display_width (var))
+     {
+       gint base_width, incr_width;
+       display_width = var_get_display_width (var);
+       calc_width_conversion (data_sheet, &base_width, &incr_width);
+       pixel_width = display_width_to_pixel_width (data_sheet, display_width,
+                                                   base_width, incr_width);
+       pspp_sheet_view_column_set_fixed_width (column, pixel_width);
+     }
+ }
+ static void
+ on_variable_changed (PsppireDict *dict, int dict_index,
+                    guint what, const struct variable *oldvar,
+                      PsppireDataSheet *data_sheet)
+ {
+   PsppireDataStore *data_store = psppire_data_sheet_get_data_store (data_sheet);
+   PsppSheetViewColumn *column;
+   GtkCellRenderer *cell;
+   struct variable *var;
+   GList *cells;
+   char *name;
+   g_return_if_fail (data_sheet->data_store != NULL);
+   g_return_if_fail (dict == data_sheet->data_store->dict);
+   if (what & VAR_TRAIT_DISPLAY_WIDTH)
+     on_variable_display_width_changed (dict, dict_index, data_sheet);
+   column = psppire_data_sheet_find_column_for_variable (data_sheet,
+                                                         dict_index);
+   if (column == NULL)
+     return;
+   var = psppire_dict_get_variable (data_store->dict, dict_index);
+   g_return_if_fail (var != NULL);
+   name = escape_underscores (var_get_name (var));
+   if (strcmp (name, pspp_sheet_view_column_get_title (column)))
+     pspp_sheet_view_column_set_title (column, name);
+   free (name);
+   cells = pspp_sheet_view_column_get_cell_renderers (column);
+   g_return_if_fail (cells);
+   cell = cells->data;
+   g_list_free (cells);
+   if (var_has_value_labels (var) != GTK_IS_CELL_RENDERER_COMBO (cell))
+     {
+       /* Stop editing before we delete and replace the cell renderers.
+          Otherwise if this column is currently being edited, an eventual call
+          to pspp_sheet_view_stop_editing() will obtain a NULL cell and pass
+          that to gtk_cell_renderer_stop_editing(), which causes a critical.
+          It's possible that this is a bug in PsppSheetView, and it's possible
+          that PsppSheetView inherits that from GtkTreeView, but I haven't
+          investigated yet. */
+       pspp_sheet_view_stop_editing (PSPP_SHEET_VIEW (data_sheet), TRUE);
+       add_data_column_cell_renderer (data_sheet, column);
+     }
+ }
+ static void
+ on_variable_inserted (PsppireDict *dict, int var_index,
+                       PsppireDataSheet *data_sheet)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   gint base_width, incr_width;
+   PsppSheetViewColumn *column;
+   calc_width_conversion (data_sheet, &base_width, &incr_width);
+   column = make_data_column (data_sheet, var_index, base_width, incr_width);
+   pspp_sheet_view_insert_column (sheet_view, column, var_index + 1);
+ }
+ static void
+ on_variable_deleted (PsppireDict *dict,
+                      const struct variable *var, int case_idx, int width,
+                      PsppireDataSheet *data_sheet)
+ {
+   PsppSheetView *sheet_view = PSPP_SHEET_VIEW (data_sheet);
+   GList *columns, *iter;
+   columns = pspp_sheet_view_get_columns (sheet_view);
+   for (iter = columns; iter != NULL; iter = iter->next)
+     {
+       PsppSheetViewColumn *column = iter->data;
+       const struct variable *column_var;
+       column_var = g_object_get_data (G_OBJECT (column), "variable");
+       if (column_var == var)
+         pspp_sheet_view_remove_column (sheet_view, column);
+     }
+   g_list_free (columns);
+ }
+ static void
+ psppire_data_sheet_unset_data_store (PsppireDataSheet *data_sheet)
+ {
+   PsppireDataStore *store = data_sheet->data_store;
+   if (store == NULL)
+     return;
+   data_sheet->data_store = NULL;
+   g_signal_handlers_disconnect_by_func (
+     store, G_CALLBACK (on_backend_changed), data_sheet);
+   g_signal_handlers_disconnect_by_func (
+     store, G_CALLBACK (on_case_inserted), data_sheet);
+   g_signal_handlers_disconnect_by_func (
+     store, G_CALLBACK (on_cases_deleted), data_sheet);
+   g_signal_handlers_disconnect_by_func (
+     store, G_CALLBACK (on_case_change), data_sheet);
+   g_signal_handlers_disconnect_by_func (
+     store->dict, G_CALLBACK (on_variable_changed), data_sheet);
+   g_signal_handlers_disconnect_by_func (
+     store->dict, G_CALLBACK (on_variable_display_width_changed), data_sheet);
+   g_signal_handlers_disconnect_by_func (
+     store->dict, G_CALLBACK (on_variable_inserted), data_sheet);
+   g_signal_handlers_disconnect_by_func (
+     store->dict, G_CALLBACK (on_variable_deleted), data_sheet);
+   g_object_unref (store);
+ }
+ void
+ psppire_data_sheet_set_data_store (PsppireDataSheet *data_sheet,
+                                 PsppireDataStore *data_store)
+ {
+   psppire_data_sheet_unset_data_store (data_sheet);
+   data_sheet->data_store = data_store;
+   if (data_store != NULL)
+     {
+       g_object_ref (data_store);
+       g_signal_connect (data_store, "backend-changed",
+                         G_CALLBACK (on_backend_changed), data_sheet);
+       g_signal_connect (data_store, "case-inserted",
+                         G_CALLBACK (on_case_inserted), data_sheet);
+       g_signal_connect (data_store, "cases-deleted",
+                         G_CALLBACK (on_cases_deleted), data_sheet);
+       g_signal_connect (data_store, "case-changed",
+                         G_CALLBACK (on_case_change), data_sheet);
+       /* XXX it's unclean to hook into the dict this way--what if the dict
+          changes?  As of this writing, though, nothing ever changes the
+          data_store's dict. */
+       g_signal_connect (data_store->dict, "variable-changed",
+                         G_CALLBACK (on_variable_changed),
+                         data_sheet);
+       g_signal_connect (data_store->dict, "variable-inserted",
+                         G_CALLBACK (on_variable_inserted), data_sheet);
+       g_signal_connect (data_store->dict, "variable-deleted",
+                         G_CALLBACK (on_variable_deleted), data_sheet);
+     }
+   refresh_model (data_sheet);
+ }
\f
+ /* Clipboard stuff */
+ /* A casereader and dictionary holding the data currently in the clip */
+ static struct casereader *clip_datasheet = NULL;
+ static struct dictionary *clip_dict = NULL;
+ static void psppire_data_sheet_update_clipboard (PsppireDataSheet *);
+ static gboolean
+ psppire_data_sheet_fetch_clip (PsppireDataSheet *data_sheet, gboolean cut,
+                                struct casereader **readerp,
+                                struct dictionary **dictp)
+ {
+   struct casewriter *writer ;
+   PsppireDataStore *ds = psppire_data_sheet_get_data_store (data_sheet);
+   struct case_map *map = NULL;
+   struct range_set *rows, *cols;
+   const struct range_set_node *node;
+   struct dictionary *dict;
+   if (!psppire_data_sheet_get_selected_range (data_sheet, &rows, &cols))
+     {
+       *readerp = NULL;
+       *dictp = NULL;
+       return FALSE;
+     }
+   /* Construct clip dictionary. */
+   *dictp = dict = dict_create (dict_get_encoding (ds->dict->dict));
+   RANGE_SET_FOR_EACH (node, cols)
+     {
+       int dict_index;
+       for (dict_index = node->start; dict_index < node->end; dict_index++)
+         {
+           struct variable *var = dict_get_var (ds->dict->dict, dict_index);
+           dict_clone_var_assert (dict, var);
+         }
+     }
+   /* Construct clip data. */
+   map = case_map_by_name (ds->dict->dict, dict);
+   writer = autopaging_writer_create (dict_get_proto (dict));
+   RANGE_SET_FOR_EACH (node, rows)
+     {
+       unsigned long int row;
+       for (row = node->start; row < node->end; row++)
+         {
+           struct ccase *old = psppire_data_store_get_case (ds, row);
+           if (old != NULL)
+             casewriter_write (writer, case_map_execute (map, old));
+           else
+             casewriter_force_error (writer);
+         }
+     }
+   case_map_destroy (map);
+   /* Clear data that we copied out, if we're doing a "cut". */
+   if (cut && !casewriter_error (writer))
+     {
+       RANGE_SET_FOR_EACH (node, rows)
+         {
+           unsigned long int row;
+           for (row = node->start; row < node->end; row++)
+             {
+               const struct range_set_node *node2;
+               RANGE_SET_FOR_EACH (node2, cols)
+                 {
+                   int dict_index;
+                   for (dict_index = node2->start; dict_index < node2->end;
+                        dict_index++)
+                     {
+                       struct variable *var;
+                       var = dict_get_var (ds->dict->dict, dict_index);
+                       psppire_data_store_set_string (ds, "", row,
+                                                      var, false);
+                     }
+                 }
+             }
+         }
+     }
+   range_set_destroy (rows);
+   range_set_destroy (cols);
+   *readerp = casewriter_make_reader (writer);
+   return TRUE;
+ }
+ /* Set the clip from the currently selected range in DATA_SHEET.  If CUT is
+    true, clears the original data from DATA_SHEET, otherwise leaves the
+    original data in-place. */
+ static void
+ psppire_data_sheet_set_clip (PsppireDataSheet *data_sheet,
+                              gboolean cut)
+ {
+   struct casereader *reader;
+   struct dictionary *dict;
+   if (psppire_data_sheet_fetch_clip (data_sheet, cut, &reader, &dict))
+     {
+       casereader_destroy (clip_datasheet);
+       dict_destroy (clip_dict);
+       clip_datasheet = reader;
+       clip_dict = dict;
+       psppire_data_sheet_update_clipboard (data_sheet);
+     }
+ }
+ enum {
+   SELECT_FMT_NULL,
+   SELECT_FMT_TEXT,
+   SELECT_FMT_HTML
+ };
+ /* Perform data_out for case CC, variable V, appending to STRING */
+ static void
+ data_out_g_string (GString *string, const struct variable *v,
+                  const struct ccase *cc)
+ {
+   const struct fmt_spec *fs = var_get_print_format (v);
+   const union value *val = case_data (cc, v);
+   char *s = data_out (val, var_get_encoding (v), fs);
+   g_string_append (string, s);
+   g_free (s);
+ }
+ static GString *
+ clip_to_text (struct casereader *datasheet, struct dictionary *dict)
+ {
+   casenumber r;
+   GString *string;
+   const size_t val_cnt = caseproto_get_n_widths (casereader_get_proto (datasheet));
+   const casenumber case_cnt = casereader_get_case_cnt (datasheet);
+   const size_t var_cnt = dict_get_var_cnt (dict);
+   string = g_string_sized_new (10 * val_cnt * case_cnt);
+   for (r = 0 ; r < case_cnt ; ++r )
+     {
+       int c;
+       struct ccase *cc;
+       cc = casereader_peek (datasheet, r);
+       if (cc == NULL)
+       {
+         g_warning ("Clipboard seems to have inexplicably shrunk");
+         break;
+       }
+       for (c = 0 ; c < var_cnt ; ++c)
+       {
+         const struct variable *v = dict_get_var (dict, c);
+         data_out_g_string (string, v, cc);
+         if ( c < val_cnt - 1 )
+           g_string_append (string, "\t");
+       }
+       if ( r < case_cnt)
+       g_string_append (string, "\n");
+       case_unref (cc);
+     }
+   return string;
+ }
+ static GString *
+ clip_to_html (struct casereader *datasheet, struct dictionary *dict)
+ {
+   casenumber r;
+   GString *string;
+   const size_t val_cnt = caseproto_get_n_widths (casereader_get_proto (datasheet));
+   const casenumber case_cnt = casereader_get_case_cnt (datasheet);
+   const size_t var_cnt = dict_get_var_cnt (dict);
+   /* Guestimate the size needed */
+   string = g_string_sized_new (80 + 20 * val_cnt * case_cnt);
+   g_string_append (string,
+                  "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
+   g_string_append (string, "<table>\n");
+   for (r = 0 ; r < case_cnt ; ++r )
+     {
+       int c;
+       struct ccase *cc = casereader_peek (datasheet, r);
+       if (cc == NULL)
+       {
+         g_warning ("Clipboard seems to have inexplicably shrunk");
+         break;
+       }
+       g_string_append (string, "<tr>\n");
+       for (c = 0 ; c < var_cnt ; ++c)
+       {
+         const struct variable *v = dict_get_var (dict, c);
+         g_string_append (string, "<td>");
+         data_out_g_string (string, v, cc);
+         g_string_append (string, "</td>\n");
+       }
+       g_string_append (string, "</tr>\n");
+       case_unref (cc);
+     }
+   g_string_append (string, "</table>\n");
+   return string;
+ }
+ static void
+ psppire_data_sheet_clipboard_set (GtkSelectionData *selection_data,
+                                   guint             info,
+                                   struct casereader *reader,
+                                   struct dictionary *dict)
+ {
+   GString *string = NULL;
+   switch (info)
+     {
+     case SELECT_FMT_TEXT:
+       string = clip_to_text (reader, dict);
+       break;
+     case SELECT_FMT_HTML:
+       string = clip_to_html (reader, dict);
+       break;
+     default:
+       g_assert_not_reached ();
+     }
+   gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data),
+                         8,
+                         (const guchar *) string->str, string->len);
+   g_string_free (string, TRUE);
+ }
+ static void
+ psppire_data_sheet_clipboard_get_cb (GtkClipboard     *clipboard,
+                                      GtkSelectionData *selection_data,
+                                      guint             info,
+                                      gpointer          data)
+ {
+   psppire_data_sheet_clipboard_set (selection_data, info,
+                                     clip_datasheet, clip_dict);
+ }
+ static void
+ psppire_data_sheet_clipboard_clear_cb (GtkClipboard *clipboard,
+                                        gpointer data)
+ {
+   dict_destroy (clip_dict);
+   clip_dict = NULL;
+   casereader_destroy (clip_datasheet);
+   clip_datasheet = NULL;
+ }
+ static const GtkTargetEntry targets[] = {
+   { "UTF8_STRING",   0, SELECT_FMT_TEXT },
+   { "STRING",        0, SELECT_FMT_TEXT },
+   { "TEXT",          0, SELECT_FMT_TEXT },
+   { "COMPOUND_TEXT", 0, SELECT_FMT_TEXT },
+   { "text/plain;charset=utf-8", 0, SELECT_FMT_TEXT },
+   { "text/plain",    0, SELECT_FMT_TEXT },
+   { "text/html",     0, SELECT_FMT_HTML }
+ };
+ static void
+ psppire_data_sheet_update_clipboard (PsppireDataSheet *sheet)
+ {
+   GtkClipboard *clipboard =
+     gtk_widget_get_clipboard (GTK_WIDGET (sheet),
+                             GDK_SELECTION_CLIPBOARD);
+   if (!gtk_clipboard_set_with_owner (clipboard, targets,
+                                    G_N_ELEMENTS (targets),
+                                    psppire_data_sheet_clipboard_get_cb,
+                                      psppire_data_sheet_clipboard_clear_cb,
+                                    G_OBJECT (sheet)))
+     psppire_data_sheet_clipboard_clear_cb (clipboard, sheet);
+ }
+ static void
+ psppire_data_sheet_update_clip_actions (PsppireDataSheet *data_sheet)
+ {
+   struct range_set *rows, *cols;
+   GtkWidget *top = gtk_widget_get_toplevel (GTK_WIDGET (data_sheet));
+   if (! PSPPIRE_IS_DATA_WINDOW (top))
+     return;
+   
+   PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (top);
+   gboolean enable =
+     psppire_data_sheet_get_selected_range (data_sheet, &rows, &cols);
+   if (enable)
+     {
+       range_set_destroy (rows);
+       range_set_destroy (cols);
+     }
+   gtk_widget_set_sensitive (dw->mi_copy, enable);
+   gtk_widget_set_sensitive (dw->mi_cut, enable);
+ }
+ static void
+ psppire_data_sheet_primary_get_cb (GtkClipboard     *clipboard,
+                                    GtkSelectionData *selection_data,
+                                    guint             info,
+                                    gpointer          data)
+ {
+   PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (data);
+   struct casereader *reader;
+   struct dictionary *dict;
+   if (psppire_data_sheet_fetch_clip (data_sheet, FALSE, &reader, &dict))
+     {
+       psppire_data_sheet_clipboard_set (selection_data, info,
+                                         reader, dict);
+       casereader_destroy (reader);
+       dict_destroy (dict);
+     }
+ }
+ static void
+ psppire_data_sheet_update_primary_selection (PsppireDataSheet *data_sheet,
+                                              gboolean should_own)
+ {
+   GtkClipboard *clipboard;
+   GdkDisplay *display;
+   display = gtk_widget_get_display (GTK_WIDGET (data_sheet));
+   clipboard = gtk_clipboard_get_for_display (display, GDK_SELECTION_PRIMARY);
+   g_return_if_fail (clipboard != NULL);
+   if (data_sheet->owns_primary_selection && !should_own)
+     {
+       data_sheet->owns_primary_selection = FALSE;
+       gtk_clipboard_clear (clipboard);
+     }
+   else if (should_own)
+     data_sheet->owns_primary_selection =
+       gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets),
+                                     psppire_data_sheet_primary_get_cb,
+                                     NULL, G_OBJECT (data_sheet));
+ }
\f
+ /* A callback for when the clipboard contents have been received. */
+ static void
+ psppire_data_sheet_clip_received_cb (GtkClipboard *clipboard,
+                                      GtkSelectionData *sd,
+                                      gpointer data)
+ {
+   PsppireDataSheet *data_sheet = data;
+   PsppireDataStore *store = data_sheet->data_store;
+   struct range_set *rows, *cols;
+   gint count = 0;
+   gint next_row, next_column;
+   gint first_column;
+   char *c;
+   if ( gtk_selection_data_get_length (sd) < 0 )
+     return;
+   if ( gtk_selection_data_get_data_type (sd) != gdk_atom_intern ("UTF8_STRING", FALSE))
+     return;
+   c = (char *) gtk_selection_data_get_data (sd);
+   /* Get the starting selected position in the data sheet.  (Possibly we should
+      only paste into the selected range if it's larger than one cell?) */
+   if (!psppire_data_sheet_get_selected_range (data_sheet, &rows, &cols))
+     return;
+   next_row = range_set_first (rows)->start;
+   first_column = next_column = range_set_first (cols)->start;
+   range_set_destroy (rows);
+   range_set_destroy (cols);
+   g_return_if_fail (next_row >= 0);
+   g_return_if_fail (next_column >= 0);
+   while (count < gtk_selection_data_get_length (sd))
+     {
+       gint row = next_row;
+       gint column = next_column;
+       struct variable *var;
+       char *s = c;
+       while (*c != '\t' && *c != '\n' && count < gtk_selection_data_get_length (sd))
+         {
+           c++;
+           count++;
+         }
+       if ( *c == '\t')
+         {
+           next_row = row ;
+           next_column = column + 1;
+         }
+       else if ( *c == '\n')
+         {
+           next_row = row + 1;
+           next_column = first_column;
+         }
+       *c++ = '\0';
+       count++;
+       var = psppire_dict_get_variable (store->dict, column);
+       if (var != NULL)
+         psppire_data_store_set_string (store, s, row, var, FALSE);
+     }
+ }
+ static void
+ psppire_data_sheet_targets_received_cb (GtkClipboard *clipboard,
+                                         GdkAtom *atoms,
+                                         gint n_atoms,
+                                         gpointer data)
+ {
+   GtkWidget *mi = GTK_WIDGET (data);
+   gboolean compatible_target = FALSE;
+   gint i;
+   for (i = 0; i < G_N_ELEMENTS (targets); i++)
+     {
+       GdkAtom target = gdk_atom_intern (targets[i].target, TRUE);
+       gint j;
+       for (j = 0; j < n_atoms; j++)
+         if (target == atoms[j])
+           {
+             compatible_target = TRUE;
+             break;
+           }
+     }
+   gtk_widget_set_sensitive (mi, compatible_target);
+ }
+ static void
+ on_owner_change (GtkClipboard *clip, GdkEventOwnerChange *event, gpointer data)
+ {
+   PsppireDataSheet *data_sheet = PSPPIRE_DATA_SHEET (data);
+   GtkWidget *top = gtk_widget_get_toplevel (GTK_WIDGET (data_sheet));
+   if (! PSPPIRE_IS_DATA_WINDOW (top))
+     return;
+   
+   PsppireDataWindow *dw = PSPPIRE_DATA_WINDOW (top);
+   gtk_clipboard_request_targets (clip,
+                                psppire_data_sheet_targets_received_cb,
+                                dw->mi_paste);
+ }
++
++#endif
Simple merge
index c2a27c04f4f53c974d0ebf8bc43d27a26e2f2abe,b2f61c60a30d45acc1608b6bc33c47c7dda60866..ec4d1bb745c2206326270f7869052c30983af5e3
  #include "ui/gui/psppire-encoding-selector.h"
  #include "ui/gui/psppire-syntax-window.h"
  #include "ui/gui/psppire-window.h"
 -#include "ui/gui/psppire-data-sheet.h"
 -#include "ui/gui/psppire-var-sheet.h"
  #include "ui/gui/windows-menu.h"
+ #include "ui/gui/goto-case-dialog.h"
  #include "ui/gui/psppire.h"
  #include "ui/syntax-gen.h"
  
@@@ -944,6 -992,380 +990,401 @@@ file_import (PsppireDataWindow *dw
    gtk_widget_destroy (GTK_WIDGET (asst));
  }
  
 -
+ static void
+ connect_dialog_action (GType type, PsppireDataWindow *de)
+ {
+   GAction *act = g_object_new (type,
+                              "top-level", de,
+                              NULL);
+   
+   g_action_map_add_action (G_ACTION_MAP (de), act);
+ }
+ static void
+ g_action_activate_null (GAction *a)
+ {
+   g_action_activate (a, NULL);
+ }
+ static void
+ connect_action_to_menuitem (GActionMap *map, const gchar *action_name, GtkWidget *w, const gchar *accel)
+ {
+   GAction *a = g_action_map_lookup_action (map, action_name);
+   
+   if (NULL == a)
+     g_error ("Action \"%s\" not found in map", action_name);
+   if (accel)
+     {
+       GtkApplication *app = GTK_APPLICATION (g_application_get_default());
+       /* First set the label for the accellerator so that it appears
+        on the menuitem */
+       GtkWidget *child = gtk_bin_get_child (GTK_BIN (w));
+       guint key;
+       GdkModifierType modifier;
+       gtk_accelerator_parse (accel, &key, &modifier);
+       gtk_accel_label_set_accel (GTK_ACCEL_LABEL (child), key, modifier);
+       /* Now tell the application that it must do something when that
+        key combination is pressed */
+       const gchar *accels[2];
+       accels[0] = accel;
+       accels[1] = NULL;
+       gchar *detailed_action_name = NULL;
+       if (GTK_IS_WINDOW (map))
+       detailed_action_name = g_strdup_printf ("win.%s", action_name);
+       else if (GTK_IS_APPLICATION (map))
+       detailed_action_name = g_strdup_printf ("app.%s", action_name);
+       
+       gtk_application_set_accels_for_action (app,
+                                            detailed_action_name,
+                                            accels);
+       free (detailed_action_name);
+     }
+   
+   g_signal_connect_swapped (w, "activate", G_CALLBACK (g_action_activate_null), a);
+  }
+ static void
+ set_data_page (PsppireDataWindow *dw)
+ {
+   gtk_notebook_set_current_page (GTK_NOTEBOOK (dw->data_editor), 1);
+   gtk_notebook_set_current_page (GTK_NOTEBOOK (dw->data_editor), 0);
+ }
+ static void
+ on_cut (PsppireDataWindow *dw)
+ {
++  #if 0
+   int p = gtk_notebook_get_current_page (GTK_NOTEBOOK (dw->data_editor));
+   if (p == 0)
+     {
+       PsppireDataSheet *ds = psppire_data_editor_get_active_data_sheet (dw->data_editor);
+       psppire_data_sheet_edit_cut (ds);
+     }
++  #endif
+ }
++
++
+ static void
+ on_copy (PsppireDataWindow *dw)
+ {
++  #if 0
+   int p = gtk_notebook_get_current_page (GTK_NOTEBOOK (dw->data_editor));
+   if (p == 0)
+     {
+       PsppireDataSheet *ds = psppire_data_editor_get_active_data_sheet (dw->data_editor);
+       psppire_data_sheet_edit_copy (ds);
+     }
++  #endif
+ }
+ static void
+ on_paste (PsppireDataWindow *dw)
+ {
++  #if 0
+   int p = gtk_notebook_get_current_page (GTK_NOTEBOOK (dw->data_editor));
+   if (p == 0)
+     {
+       PsppireDataSheet *ds = psppire_data_editor_get_active_data_sheet (dw->data_editor);
+       psppire_data_sheet_edit_paste (ds);
+     }
++  #endif
+ }
+ static void
+ on_clear_cases (PsppireDataWindow *dw)
+ {
++  #if 0
+   int p = gtk_notebook_get_current_page (GTK_NOTEBOOK (dw->data_editor));
+   if (p == 0)
+     {
+       PsppireDataSheet *ds = psppire_data_editor_get_active_data_sheet (dw->data_editor);
+       psppire_data_sheet_edit_clear_cases (ds);
+     }
++  #endif
+ }
+ static void
+ on_clear_variables (PsppireDataWindow *dw)
+ {
++  #if 0
+   int p = gtk_notebook_get_current_page (GTK_NOTEBOOK (dw->data_editor));
+   if (p == 0)
+     {
+       PsppireDataSheet *ds = psppire_data_editor_get_active_data_sheet (dw->data_editor);
+       psppire_data_sheet_edit_clear_variables (ds);
+     }
+   else
+     {
+       psppire_var_sheet_clear_variables (PSPPIRE_VAR_SHEET (dw->data_editor->var_sheet));
+     }
++  #endif
+ }
++
+ static void
+ insert_variable (PsppireDataWindow *dw)
+ {
++#if 0  
+   int p = gtk_notebook_get_current_page (GTK_NOTEBOOK (dw->data_editor));
+   if (p == 0)
+     {
+       PsppireDataSheet *ds = psppire_data_editor_get_active_data_sheet (dw->data_editor);
+       psppire_data_sheet_insert_variable (ds);
+     }
+   else
+     {
+       psppire_var_sheet_insert_variable (PSPPIRE_VAR_SHEET (dw->data_editor->var_sheet));
+     }
++#endif
+ }
++
+ static void
+ insert_case_at_row (PsppireDataWindow *dw)
+ {
++#if 0
+   PsppireDataSheet *ds = psppire_data_editor_get_active_data_sheet (dw->data_editor);
+   psppire_data_sheet_insert_case (ds);
++#endif
+ }
++
++
+ static void
+ goto_case (PsppireDataWindow *dw)
+ {
++  #if 0
+   PsppireDataSheet *ds = psppire_data_editor_get_active_data_sheet (dw->data_editor);
+   goto_case_dialog (ds);
++  #endif
+ }
 -
+ static GtkWidget *
+ create_file_menu (PsppireDataWindow *dw)
+ {
+   GtkWidget *menuitem = gtk_menu_item_new_with_mnemonic (_("_File"));
+   GtkWidget *menu = gtk_menu_new ();
+   {
+     GtkWidget *new = gtk_menu_item_new_with_mnemonic (_("_New"));
+     gtk_menu_attach (GTK_MENU (menu), new,        0, 1, 0, 1);
+     GtkWidget *new_menu = gtk_menu_new ();
+     g_object_set (new, "submenu", new_menu, NULL);
+       
+     GtkWidget *syntax  = gtk_menu_item_new_with_mnemonic (_("_Syntax"));
+     connect_action_to_menuitem (G_ACTION_MAP (g_application_get_default ()), "new-syntax", syntax, 0);
+     
+     GtkWidget *data = gtk_menu_item_new_with_mnemonic (_("_Data"));
+     connect_action_to_menuitem (G_ACTION_MAP (g_application_get_default ()), "new-data", data, 0);
+     gtk_menu_attach (GTK_MENU (new_menu), syntax,    0, 1, 0, 1);
+     gtk_menu_attach (GTK_MENU (new_menu), data,      0, 1, 1, 2);
+   }
+   
+   GtkWidget *open = gtk_menu_item_new_with_mnemonic (_("_Open"));
+   connect_action_to_menuitem (G_ACTION_MAP (dw), "open", open, "<Ctrl>O");
+   
+   GtkWidget *import = gtk_menu_item_new_with_mnemonic (_("_Import Data..."));
+   connect_action_to_menuitem (G_ACTION_MAP (dw), "file-import", import, 0);
+   
+   gtk_menu_attach (GTK_MENU (menu), open,       0, 1, 1, 2);
+   gtk_menu_attach (GTK_MENU (menu), import,     0, 1, 2, 3);
+   gtk_menu_attach (GTK_MENU (menu), gtk_separator_menu_item_new (), 0, 1, 3, 4);
+   GtkWidget *save = gtk_menu_item_new_with_mnemonic (_("_Save..."));
+   connect_action_to_menuitem (G_ACTION_MAP (dw), "save", save, "<Ctrl>S");
+   
+   GtkWidget *save_as = gtk_menu_item_new_with_mnemonic (_("Save _As..."));
+   connect_action_to_menuitem (G_ACTION_MAP (dw), "save-as", save_as, "<Shift><Ctrl>S");
+   
+   GtkWidget *rename_dataset = gtk_menu_item_new_with_mnemonic (_("_Rename Dataset..."));
+   connect_action_to_menuitem (G_ACTION_MAP (dw), "rename-dataset", rename_dataset, 0);
+   
+   gtk_menu_attach (GTK_MENU (menu), save,        0, 1, 4, 5);
+   gtk_menu_attach (GTK_MENU (menu), save_as,     0, 1, 5, 6);
+   gtk_menu_attach (GTK_MENU (menu), rename_dataset,     0, 1, 6, 7);
+   gtk_menu_attach (GTK_MENU (menu), gtk_separator_menu_item_new (), 0, 1, 7, 8);
+   {
+     GtkWidget *display_data = gtk_menu_item_new_with_mnemonic (_("_Display Data File Information"));
+     gtk_menu_attach (GTK_MENU (menu), display_data,     0, 1, 8, 9);
+     GtkWidget *dd_menu = gtk_menu_new ();
+     g_object_set (display_data, "submenu", dd_menu, NULL);
+     
+     GtkWidget *working_file  = gtk_menu_item_new_with_mnemonic (_("Working File"));
+     connect_action_to_menuitem (G_ACTION_MAP (dw), "info-working", working_file, 0);
+     GtkWidget *external_file = gtk_menu_item_new_with_mnemonic (_("_External File..."));
+     connect_action_to_menuitem (G_ACTION_MAP (dw), "info-external", external_file, 0);
+     gtk_menu_attach (GTK_MENU (dd_menu), working_file,    0, 1, 0, 1);
+     gtk_menu_attach (GTK_MENU (dd_menu), external_file,   0, 1, 1, 2);
+   }
+   
+   gtk_menu_attach (GTK_MENU (menu), gtk_separator_menu_item_new (), 0, 1, 9, 10);
+   {
+     GtkWidget *mi_data = gtk_menu_item_new_with_mnemonic (_("_Recently Used Data"));
+     GtkWidget *mi_files = gtk_menu_item_new_with_mnemonic (_("Recently Used _Files"));
+     GtkWidget *menu_data = gtk_recent_chooser_menu_new_for_manager (
+       gtk_recent_manager_get_default ());
+     GtkWidget *menu_files = gtk_recent_chooser_menu_new_for_manager (
+       gtk_recent_manager_get_default ());
+     gtk_menu_attach (GTK_MENU (menu), mi_data,       0, 1, 10, 11);
+     gtk_menu_attach (GTK_MENU (menu), mi_files,      0, 1, 11, 12);
+     
+     g_object_set (menu_data, "show-tips",  TRUE, NULL);
+     g_object_set (menu_files, "show-tips",  TRUE, NULL);
+     g_object_set (mi_data, "submenu",  menu_data, NULL);
+     g_object_set (mi_files, "submenu", menu_files, NULL);
+     
+     {
+       GtkRecentFilter *filter = gtk_recent_filter_new ();
+       gtk_recent_filter_add_mime_type (filter, "application/x-spss-sav");
+       gtk_recent_filter_add_mime_type (filter, "application/x-spss-por");
+       gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_data), GTK_RECENT_SORT_MRU);
+       gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_data), filter);
+     }
+     g_signal_connect (menu_data, "selection-done", G_CALLBACK (on_recent_data_select), dw);
+     {
+       GtkRecentFilter *filter = gtk_recent_filter_new ();
+       gtk_recent_filter_add_pattern (filter, "*.sps");
+       gtk_recent_filter_add_pattern (filter, "*.SPS");
+       gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (menu_files), GTK_RECENT_SORT_MRU);
+       gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu_files), filter);
+     }
+     g_signal_connect (menu_files, "selection-done", G_CALLBACK (on_recent_files_select), dw);
+   }
+   gtk_menu_attach (GTK_MENU (menu), gtk_separator_menu_item_new (), 0, 1, 12, 13);
+   {
+     GtkWidget *quit = gtk_menu_item_new_with_mnemonic (_("_Quit"));
+     gtk_menu_attach (GTK_MENU (menu), quit,     0, 1, 13, 14);
+     connect_action_to_menuitem (G_ACTION_MAP (g_application_get_default ()),
+                               "quit", quit, "<Ctrl>Q");
+   }
+   
+   g_object_set (menuitem, "submenu", menu, NULL);
+   gtk_widget_show_all (menuitem);
+   
+   return menuitem;
+ }
++
+ static GtkWidget *
+ create_edit_menu (PsppireDataWindow *dw)
+ {
+   int i = 0;
+   GtkWidget *menuitem = gtk_menu_item_new_with_mnemonic (_("_Edit"));
+   GtkWidget *menu = gtk_menu_new ();
+   dw->mi_insert_var = gtk_menu_item_new_with_mnemonic (_("_Insert Variable"));
+   dw->mi_insert_case = gtk_menu_item_new_with_mnemonic (_("_Insert Case"));
+   GtkWidget *go_to_variable = gtk_menu_item_new_with_mnemonic (_("_Go To Variable..."));
+   dw->mi_go_to_case = gtk_menu_item_new_with_mnemonic (_("_Go To Case..."));
+   gtk_menu_attach (GTK_MENU (menu), dw->mi_insert_var,        0, 1, i, i + 1); ++i;
+   gtk_menu_attach (GTK_MENU (menu), dw->mi_insert_case,     0, 1, i, i + 1); ++i;
+   g_signal_connect_swapped (dw->mi_insert_case, "activate", G_CALLBACK (insert_case_at_row), dw);
+   g_signal_connect_swapped (dw->mi_go_to_case, "activate", G_CALLBACK (goto_case), dw);
+   g_signal_connect_swapped (dw->mi_insert_var, "activate", G_CALLBACK (insert_variable), dw);
+   GAction *a = g_action_map_lookup_action (G_ACTION_MAP (dw),  "PsppireDialogActionVarInfo");
+   g_assert (a);
+   g_signal_connect_swapped (go_to_variable, "activate", G_CALLBACK (psppire_dialog_action_activate_null), a);
+   
+   gtk_menu_attach (GTK_MENU (menu), go_to_variable,         0, 1, i, i + 1); ++i;
+   gtk_menu_attach (GTK_MENU (menu), dw->mi_go_to_case,      0, 1, i, i + 1); ++i;
+   {
+     GtkAccelGroup *ag = gtk_accel_group_new ();
+     
+     dw->mi_edit_separator = gtk_separator_menu_item_new ();
+     gtk_menu_attach (GTK_MENU (menu), dw->mi_edit_separator, 0, 1, i, i + 1); ++i;
+     dw->mi_cut = gtk_menu_item_new_with_mnemonic (_("Cu_t"));
+     gtk_menu_attach (GTK_MENU (menu), dw->mi_cut,     0, 1, i, i + 1); ++i;
+     g_signal_connect_swapped (dw->mi_cut, "activate", G_CALLBACK (on_cut), dw);
+     gtk_window_add_accel_group (GTK_WINDOW (dw), ag);
+     gtk_widget_add_accelerator (dw->mi_cut, "activate", ag,
+                               'X', GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+     
+     dw->mi_copy = gtk_menu_item_new_with_mnemonic (_("_Copy"));
+     gtk_menu_attach (GTK_MENU (menu), dw->mi_copy,     0, 1, i, i + 1); ++i;
+     g_signal_connect_swapped (dw->mi_copy, "activate", G_CALLBACK (on_copy), dw);
+     gtk_widget_add_accelerator (dw->mi_copy, "activate", ag,
+                               'C', GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+       
+     dw->mi_paste = gtk_menu_item_new_with_mnemonic (_("_Paste"));
+     gtk_menu_attach (GTK_MENU (menu), dw->mi_paste,     0, 1, i, i + 1); ++i;
+     g_signal_connect_swapped (dw->mi_paste, "activate", G_CALLBACK (on_paste), dw);
+     gtk_widget_add_accelerator (dw->mi_paste, "activate", ag,
+                               'V', GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
+     dw->mi_clear_variables = gtk_menu_item_new_with_mnemonic (_("Clear _Variables"));
+     gtk_menu_attach (GTK_MENU (menu), dw->mi_clear_variables,     0, 1, i, i + 1); ++i;
+     g_signal_connect_swapped (dw->mi_clear_variables, "activate", G_CALLBACK (on_clear_variables), dw);
+     
+     dw->mi_clear_cases = gtk_menu_item_new_with_mnemonic (_("Cl_ear Cases"));
+     gtk_menu_attach (GTK_MENU (menu), dw->mi_clear_cases,     0, 1, i, i + 1); ++i;
+     g_signal_connect_swapped (dw->mi_clear_cases, "activate", G_CALLBACK (on_clear_cases), dw);
+   }
+   
+   {
+     dw->mi_find_separator = gtk_separator_menu_item_new ();
+     gtk_menu_attach (GTK_MENU (menu), dw->mi_find_separator, 0, 1, i, i + 1); ++i;
+   
+     dw->mi_find = gtk_menu_item_new_with_mnemonic (_("_Find..."));
+     g_signal_connect_swapped (dw->mi_find, "activate", G_CALLBACK (find_dialog), dw);
+     gtk_menu_attach (GTK_MENU (menu), dw->mi_find,      0, 1,  i, i + 1); ++i;
+   }
+   
+   g_object_set (menuitem, "submenu", menu, NULL);
+   
+   gtk_widget_show_all (menuitem);
+   
+   return menuitem;
+ }
  static void
  psppire_data_window_finish_init (PsppireDataWindow *de,
                                   struct dataset *ds)
    ll_push_head (&all_data_windows, &de->ll);
  }
  
++
  static void
  psppire_data_window_dispose (GObject *object)
  {
@@@ -1220,65 -1840,7 +1860,8 @@@ psppire_data_window_get_property (GObje
      };
  }
  
- static guint
- psppire_data_window_add_ui (PsppireDataWindow *pdw, GtkUIManager *uim)
- {
-   gchar *ui_string;
-   guint merge_id;
-   GList *list;
-   ui_string = gtk_ui_manager_get_ui (uim);
-   merge_id = gtk_ui_manager_add_ui_from_string (pdw->ui_manager, ui_string,
-                                                 -1, NULL);
-   g_free (ui_string);
-   g_return_val_if_fail (merge_id != 0, 0);
-   list = gtk_ui_manager_get_action_groups (uim);
-   for (; list != NULL; list = list->next)
-     {
-       GtkActionGroup *action_group = list->data;
-       GList *actions = gtk_action_group_list_actions (action_group);
-       GList *action;
-       for (action = actions; action != NULL; action = action->next)
-         {
-           GtkAction *a = action->data;
-           if (PSPPIRE_IS_DIALOG_ACTION (a))
-             g_object_set (a, "manager", pdw->ui_manager, NULL);
-         }
  
-       gtk_ui_manager_insert_action_group (pdw->ui_manager, action_group, 0);
-     }
-   gtk_window_add_accel_group (GTK_WINDOW (pdw),
-                               gtk_ui_manager_get_accel_group (uim));
-   return merge_id;
- }
- static void
- psppire_data_window_remove_ui (PsppireDataWindow *pdw,
-                                GtkUIManager *uim, guint merge_id)
- {
-   GList *list;
-   g_return_if_fail (merge_id != 0);
-   gtk_ui_manager_remove_ui (pdw->ui_manager, merge_id);
-   list = gtk_ui_manager_get_action_groups (uim);
-   for (; list != NULL; list = list->next)
-     {
-       GtkActionGroup *action_group = list->data;
-       gtk_ui_manager_remove_action_group (pdw->ui_manager, action_group);
-     }
-   gtk_window_remove_accel_group (GTK_WINDOW (pdw),
-                                  gtk_ui_manager_get_accel_group (uim));
- }
 +
  GtkWidget*
  psppire_data_window_new (struct dataset *ds)
  {
    return dw;
  }
  
++
++
  bool
  psppire_data_window_is_empty (PsppireDataWindow *dw)
  {
    return psppire_dict_get_var_cnt (dw->dict) == 0;
  }
  
++
  static void
  psppire_data_window_iface_init (PsppireWindowIface *iface)
  {
    iface->pick_filename = data_pick_filename;
    iface->load = load_file;
  }
  \f
++
  PsppireDataWindow *
  psppire_default_data_window (void)
  {
    return ll_data (ll_head (&all_data_windows), PsppireDataWindow, ll);
  }
  
++
++
  void
  psppire_data_window_set_default (PsppireDataWindow *pdw)
  {
@@@ -1344,6 -1912,6 +1939,8 @@@ psppire_data_window_undefault (PsppireD
    ll_push_tail (&all_data_windows, &pdw->ll);
  }
  
++
++
  PsppireDataWindow *
  psppire_data_window_for_dataset (struct dataset *ds)
  {
    return NULL;
  }
  
++#if 0
++
  PsppireDataWindow *
  psppire_data_window_for_data_store (PsppireDataStore *data_store)
  {
    return NULL;
  }
  
- void
++#endif
++
+ GtkWindow *
  create_data_window (void)
  {
-   gtk_widget_show (psppire_data_window_new (NULL));
+   GtkWidget *w = psppire_data_window_new (NULL);
+   gtk_widget_show (w);
+   
+   return GTK_WINDOW (w);
  }
  
++
++
  void
  open_data_window (PsppireWindow *victim, const char *file_name,
                    const char *encoding, gpointer hint)
index d3131a3a2ca795b6dc38965e1d87606988587931,bb29d04993cd288425dfb0215a3b83f6705e850d..2a44bda3600b6fe481e68c718be74eaff7140de2
  
  #include "builder-wrapper.h"
  #include "helper.h"
--#include "pspp-sheet-view.h"
--#include "pspp-sheet-selection.h"
  #include "psppire-import-assistant.h"
  #include "psppire-scanf.h"
  #include "psppire-dialog.h"
  #include "psppire-empty-list-store.h"
  #include "psppire-encoding-selector.h"
  #include "psppire-spreadsheet-model.h"
--#include "psppire-var-sheet.h"
  #include "ui/syntax-gen.h"
  
  #include <gettext.h>
  #define _(msgid) gettext (msgid)
  #define N_(msgid) msgid
  
++GType psppire_import_assistant_get_type (void)
++{
++  return 0;
++}
++
++#if 0
  enum { MAX_LINE_LEN = 16384 }; /* Max length of an acceptable line. */
  
  
@@@ -1254,6 -1254,6 +1257,7 @@@ intro_page_create (PsppireImportAssista
    g_object_set_data (G_OBJECT (w), "on-reset", reset_intro_page);
  }
  
++#endif
  
  GtkWidget *
  psppire_import_assistant_new (GtkWindow *toplevel)
                                   NULL));
  }
  
++#if 0
++
  \f
  
  struct column
@@@ -2165,11 -2359,11 +2171,14 @@@ sheet_spec_gen_syntax (PsppireImportAss
    return ds_cstr (&s);
  }
  
++#endif
++
  gchar *
  psppire_import_assistant_generate_syntax (PsppireImportAssistant *ia)
  {
    struct string s = DS_EMPTY_INITIALIZER;
  
++#if 0
    if (!ia->spreadsheet)
      {
        if (ia->file_name == NULL)
      {
        return sheet_spec_gen_syntax (ia);
      }
++
++#endif
    
    return ds_cstr (&s);
  }
diff --cc src/ui/gui/psppire-var-sheet.h
index 3d10dd0d53950599b89696baec0e513ff86010e7,6a57cc6de9cd38c5c64f730d030e1dfbc3658a91..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,102 -1,100 +1,0 @@@
--/* PSPPIRE - a graphical user interface for PSPP.
--   Copyright (C) 2008, 2011, 2012 Free Software Foundation, Inc.
--
--   This program is free software: you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation, either version 3 of the License, or
--   (at your option) any later version.
--
--   This program 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
--
--#ifndef __PSPPIRE_VAR_SHEET_H__
--#define __PSPPIRE_VAR_SHEET_H__
--
--/* PsppireVarSheet is a PsppSheetView that displays the variables in a
--   dictionary, one variable per row.
--
--   PsppireDataSheet is usually a child of PsppireDataEditor in the widget
--   hierarchy.  Other widgets can also use it. */
--
--#include <gtk/gtk.h>
--#include "data/format.h"
--#include "ui/gui/pspp-sheet-view.h"
--
--
--G_BEGIN_DECLS
--
--#define PSPPIRE_TYPE_FMT_USE (psppire_fmt_use_get_type ())
--
--GType psppire_fmt_use_get_type (void) G_GNUC_CONST;
--\f
--#define PSPPIRE_VAR_SHEET_TYPE            (psppire_var_sheet_get_type ())
--#define PSPPIRE_VAR_SHEET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), PSPPIRE_VAR_SHEET_TYPE, PsppireVarSheet))
--#define PSPPIRE_VAR_SHEET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PSPPIRE_VAR_SHEET_TYPE, PsppireVarSheetClass))
--#define PSPPIRE_IS_VAR_SHEET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PSPPIRE_VAR_SHEET_TYPE))
--#define PSPPIRE_IS_VAR_SHEET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PSPPIRE_VAR_SHEET_TYPE))
--
--
--typedef struct _PsppireVarSheet       PsppireVarSheet;
--typedef struct _PsppireVarSheetClass  PsppireVarSheetClass;
--
--enum
--{
 -    PSPPIRE_VAR_SHEET_BACKEND_CHANGED,
--    PSPPIRE_VAR_SHEET_VARIABLE_CHANGED,
--    PSPPIRE_VAR_SHEET_VARIABLE_INSERTED,
--    PSPPIRE_VAR_SHEET_VARIABLE_DELETED,
--    PSPPIRE_VAR_SHEET_N_SIGNALS
-- };
--
--struct _PsppireVarSheet
--{
--  PsppSheetView parent;
--
--  gboolean may_create_vars;
--  gboolean may_delete_vars;
--  enum fmt_use format_use;
--
--  struct _PsppireDict *dict;
--
--  gulong scroll_to_bottom_signal;
--  gulong dict_signals[PSPPIRE_VAR_SHEET_N_SIGNALS];
-   GtkBuilder *builder;
--
--  GtkWidget *container;
--  gulong on_switch_page_handler;
-   GtkUIManager *uim;
--
--  gboolean dispose_has_run;
--};
--
--struct _PsppireVarSheetClass
--{
--  PsppSheetViewClass parent_class;
--};
--
--GType          psppire_var_sheet_get_type        (void);
--GtkWidget*     psppire_var_sheet_new             (void);
--
--struct _PsppireDict *psppire_var_sheet_get_dictionary (PsppireVarSheet *);
--void psppire_var_sheet_set_dictionary (PsppireVarSheet *,
--                                       struct _PsppireDict *);
--
--gboolean psppire_var_sheet_get_may_create_vars (PsppireVarSheet *);
--void psppire_var_sheet_set_may_create_vars (PsppireVarSheet *, gboolean);
--
--gboolean psppire_var_sheet_get_may_delete_vars (PsppireVarSheet *);
--void psppire_var_sheet_set_may_delete_vars (PsppireVarSheet *, gboolean);
--
--void psppire_var_sheet_goto_variable (PsppireVarSheet *, int dict_index);
 -void psppire_var_sheet_insert_variable (PsppireVarSheet *var_sheet);
 -void psppire_var_sheet_clear_variables (PsppireVarSheet *var_sheet);
--
- GtkUIManager *psppire_var_sheet_get_ui_manager (PsppireVarSheet *);
--
--G_END_DECLS
--
--#endif /* __PSPPIRE_VAR_SHEET_H__ */
Simple merge