Merge branch 'master' into rewrite-sheet
authorJohn Darrington <john@darrington.wattle.id.au>
Thu, 4 Dec 2008 00:14:35 +0000 (09:14 +0900)
committerJohn Darrington <john@darrington.wattle.id.au>
Thu, 4 Dec 2008 00:14:35 +0000 (09:14 +0900)
Conflicts:

src/ui/gui/psppire-case-file.c
src/ui/gui/psppire-case-file.h

62 files changed:
.gitignore
examples/grid.sps [new file with mode: 0644]
lib/gtksheet/automake.mk
lib/gtksheet/gsheet-column-iface.c [deleted file]
lib/gtksheet/gsheet-column-iface.h [deleted file]
lib/gtksheet/gsheet-hetero-column.c [deleted file]
lib/gtksheet/gsheet-hetero-column.h [deleted file]
lib/gtksheet/gsheet-row-iface.c [deleted file]
lib/gtksheet/gsheet-row-iface.h [deleted file]
lib/gtksheet/gsheet-uniform-column.c [deleted file]
lib/gtksheet/gsheet-uniform-column.h [deleted file]
lib/gtksheet/gsheet-uniform-row.c [deleted file]
lib/gtksheet/gsheet-uniform-row.h [deleted file]
lib/gtksheet/gsheetmodel.c
lib/gtksheet/gsheetmodel.h
lib/gtksheet/gtkextra-marshal.c [deleted file]
lib/gtksheet/gtkextra-marshal.h [deleted file]
lib/gtksheet/gtkextra-sheet.h
lib/gtksheet/gtkextra.c [deleted file]
lib/gtksheet/gtkextrafeatures.h [deleted file]
lib/gtksheet/gtkitementry.c [deleted file]
lib/gtksheet/gtkitementry.h [deleted file]
lib/gtksheet/gtksheet.c
lib/gtksheet/gtksheet.h
lib/gtksheet/gtkxpaned.c [new file with mode: 0644]
lib/gtksheet/gtkxpaned.h [new file with mode: 0644]
lib/gtksheet/marshaller-list [new file with mode: 0644]
lib/gtksheet/psppire-axis-hetero.c [new file with mode: 0644]
lib/gtksheet/psppire-axis-hetero.h [new file with mode: 0644]
lib/gtksheet/psppire-axis-uniform.c [new file with mode: 0644]
lib/gtksheet/psppire-axis-uniform.h [new file with mode: 0644]
lib/gtksheet/psppire-axis.c [new file with mode: 0644]
lib/gtksheet/psppire-axis.h [new file with mode: 0644]
po/en_GB.po
src/data/datasheet.c
src/data/dictionary.c
src/data/dictionary.h
src/data/vardict.h
src/data/variable.c
src/libpspp/misc.h
src/libpspp/tower.c
src/libpspp/tower.h
src/ui/gui/automake.mk
src/ui/gui/data-editor.c
src/ui/gui/data-editor.glade
src/ui/gui/data-editor.h
src/ui/gui/find-dialog.c
src/ui/gui/helper.c
src/ui/gui/psppire-case-file.c [deleted file]
src/ui/gui/psppire-case-file.h [deleted file]
src/ui/gui/psppire-data-editor.c
src/ui/gui/psppire-data-editor.h
src/ui/gui/psppire-data-store.c
src/ui/gui/psppire-data-store.h
src/ui/gui/psppire-dict.c
src/ui/gui/psppire-dict.h
src/ui/gui/psppire-var-sheet.c
src/ui/gui/psppire-var-store.c
src/ui/gui/psppire-var-store.h
src/ui/gui/psppire.c
src/ui/gui/text-data-import-dialog.c
tests/libpspp/tower-test.c

index 1d69e1696363c481df809fff20fbafe821dfce85..b50c6a377a2ab182f2ebaddd06e8abfc12ac5ca3 100644 (file)
@@ -39,3 +39,4 @@ gitlog-to-changelog
 *.dirstamp
 *.deps
 *.la
+*.libs
diff --git a/examples/grid.sps b/examples/grid.sps
new file mode 100644 (file)
index 0000000..ea7f9d7
--- /dev/null
@@ -0,0 +1,20 @@
+COMMENT  -*-pspp-*- .
+
+COMMENT This program is useful for testing the behaviour of the Data and Variable Sheets.
+
+input program.
+vector var(500 F8.3).
+  loop #c = 1 to 1000.
+    loop #v = 1 to 500.
+      compute var(#v) = #v + #c / 1000.
+    end loop.
+    end case.
+  end loop.
+  end file.
+end input program.
+
+variable label  var1 'First variable' var2 'Second variable' var3 'Third variable'.
+
+save outfile='grid.sav'.
+
+execute.
index b28382602d437c7f646872a6502dbb0724c17e96..1ad14a7f63ef360bd223a88cf0b6533434b4c9e8 100644 (file)
@@ -2,31 +2,39 @@
 
 noinst_LIBRARIES += lib/gtksheet/libgtksheet.a
 
-lib_gtksheet_libgtksheet_a_CFLAGS = $(GTK_CFLAGS) -Wall
+AM_CPPFLAGS += -Ilib
 
+lib_gtksheet_libgtksheet_a_CFLAGS = $(GTK_CFLAGS) -Wall -DGDK_MULTIHEAD_SAFE=1
+
+nodist_lib_gtksheet_libgtksheet_a_SOURCES = \
+       lib/gtksheet/psppire-marshal.c \
+       lib/gtksheet/psppire-marshal.h
 
 lib_gtksheet_libgtksheet_a_SOURCES = \
-       lib/gtksheet/gsheet-column-iface.c \
-       lib/gtksheet/gsheet-column-iface.h \
-       lib/gtksheet/gsheet-hetero-column.c \
-       lib/gtksheet/gsheet-hetero-column.h \
        lib/gtksheet/gsheetmodel.c \
        lib/gtksheet/gsheetmodel.h \
-       lib/gtksheet/gsheet-row-iface.c \
-       lib/gtksheet/gsheet-row-iface.h \
-       lib/gtksheet/gsheet-uniform-column.c \
-       lib/gtksheet/gsheet-uniform-column.h \
-       lib/gtksheet/gsheet-uniform-row.c \
-       lib/gtksheet/gsheet-uniform-row.h \
-       lib/gtksheet/gtkextra.c \
-       lib/gtksheet/gtkextrafeatures.h \
-       lib/gtksheet/gtkextra-marshal.c \
-       lib/gtksheet/gtkextra-marshal.h \
        lib/gtksheet/gtkextra-sheet.h \
-       lib/gtksheet/gtkitementry.h \
-       lib/gtksheet/gtkitementry.c \
        lib/gtksheet/gtksheet.c \
-       lib/gtksheet/gtksheet.h 
+       lib/gtksheet/gtksheet.h \
+       lib/gtksheet/gtkxpaned.c \
+       lib/gtksheet/gtkxpaned.h \
+       lib/gtksheet/psppire-axis.c \
+       lib/gtksheet/psppire-axis.h \
+       lib/gtksheet/psppire-axis-hetero.c \
+       lib/gtksheet/psppire-axis-hetero.h \
+       lib/gtksheet/psppire-axis-uniform.c \
+       lib/gtksheet/psppire-axis-uniform.h 
+
 
 EXTRA_DIST += lib/gtksheet/OChangeLog \
+       lib/gtksheet/marshaller-list \
        lib/gtksheet/README
+
+lib/gtksheet/psppire-marshal.c: lib/gtksheet/marshaller-list
+       glib-genmarshal --body --prefix=psppire_marshal $< > $@
+
+lib/gtksheet/psppire-marshal.h: lib/gtksheet/marshaller-list
+       glib-genmarshal --header --prefix=psppire_marshal $< > $@
+
+BUILT_SOURCES += $(nodist_lib_gtksheet_libgtksheet_a_SOURCES)
+CLEANFILES += $(nodist_lib_gtksheet_libgtksheet_a_SOURCES)
diff --git a/lib/gtksheet/gsheet-column-iface.c b/lib/gtksheet/gsheet-column-iface.c
deleted file mode 100644 (file)
index 1cd7996..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-/* GSheetColumn --- an abstract model of the column geometry of a
-   GSheet widget.
-
- * Copyright (C) 2006 Free Software Foundation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <config.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include <glib/gprintf.h>
-#include <gobject/gvaluecollector.h>
-#include "gsheet-column-iface.h"
-#include "gtkextra-marshal.h"
-#include "gtkextra-sheet.h"
-
-enum {
-  COLUMNS_CHANGED,
-  LAST_SIGNAL
-};
-
-static guint sheet_column_signals[LAST_SIGNAL];
-
-
-
-static void      g_sheet_column_base_init   (gpointer g_class);
-
-
-GType
-g_sheet_column_get_type (void)
-{
-  static GType sheet_column_type = 0;
-
-  if (! sheet_column_type)
-    {
-      static const GTypeInfo sheet_column_info =
-
-      {
-        sizeof (GSheetColumnIface), /* class_size */
-       g_sheet_column_base_init,   /* base_init */
-       NULL,           /* base_finalize */
-       NULL,
-       NULL,           /* class_finalize */
-       NULL,           /* class_data */
-       0,
-       0,              /* n_preallocs */
-       NULL
-      };
-
-      sheet_column_type =
-       g_type_register_static (G_TYPE_INTERFACE, "GSheetColumn",
-                               &sheet_column_info, 0);
-
-      g_assert(sheet_column_type);
-
-      g_type_interface_add_prerequisite (sheet_column_type, G_TYPE_OBJECT);
-    }
-
-  return sheet_column_type;
-}
-
-
-static void
-g_sheet_column_base_init (gpointer g_class)
-{
-  static gboolean initialized = FALSE;
-
-  if (! initialized)
-    {
-
-      sheet_column_signals[COLUMNS_CHANGED] =
-       g_signal_new ("columns_changed",
-                     G_TYPE_SHEET_COLUMN,
-                     G_SIGNAL_RUN_LAST,
-                     G_STRUCT_OFFSET (GSheetColumnIface, columns_changed),
-                     NULL, NULL,
-                     gtkextra_VOID__INT_INT,
-                     G_TYPE_NONE, 2,
-                     G_TYPE_INT,
-                     G_TYPE_INT);
-
-
-      initialized = TRUE;
-    }
-}
-
-
-void
-g_sheet_column_set_width (GSheetColumn *column, glong col, gint size)
-{
-  g_return_if_fail (G_IS_SHEET_COLUMN (column));
-
-  if ((G_SHEET_COLUMN_GET_IFACE (column)->set_width) )
-    (G_SHEET_COLUMN_GET_IFACE (column)->set_width) (column, col, size);
-}
-
-
-gint
-g_sheet_column_get_width (const GSheetColumn *column, glong col)
-{
-  g_return_val_if_fail (G_IS_SHEET_COLUMN (column), -1);
-
-  g_assert (G_SHEET_COLUMN_GET_IFACE (column)->get_width);
-
-  return (G_SHEET_COLUMN_GET_IFACE (column)->get_width) (column, col);
-}
-
-
-
-gboolean
-g_sheet_column_get_visibility(const GSheetColumn *column,
-                                           glong col)
-{
-  g_return_val_if_fail (G_IS_SHEET_COLUMN (column), FALSE);
-
-  g_assert (G_SHEET_COLUMN_GET_IFACE (column)->get_visibility);
-
-  return (G_SHEET_COLUMN_GET_IFACE (column)->get_visibility) (column,
-                                                                 col);
-
-}
-
-gboolean
-g_sheet_column_get_sensitivity(const GSheetColumn *column,
-                                            glong col)
-{
-  g_return_val_if_fail (G_IS_SHEET_COLUMN (column), FALSE);
-
-  g_assert (G_SHEET_COLUMN_GET_IFACE (column)->get_sensitivity);
-
-  return (G_SHEET_COLUMN_GET_IFACE (column)->get_sensitivity) (column,
-                                                                  col);
-
-}
-
-
-GtkSheetButton *
-g_sheet_column_get_button(const GSheetColumn *column,
-                             glong col)
-{
-  GtkSheetButton *button = gtk_sheet_button_new();
-
-  GSheetColumnIface *iface = G_SHEET_COLUMN_GET_IFACE (column);
-
-  g_return_val_if_fail (G_IS_SHEET_COLUMN (column), FALSE);
-
-  if ( iface->get_button_label)
-    button->label = iface->get_button_label(column, col);
-
-  return button;
-}
-
-GtkJustification
-g_sheet_column_get_justification(const GSheetColumn *column,
-                                    glong col)
-{
-  g_return_val_if_fail (G_IS_SHEET_COLUMN (column), FALSE);
-
-  g_assert (G_SHEET_COLUMN_GET_IFACE (column)->get_justification);
-
-  return (G_SHEET_COLUMN_GET_IFACE (column)->get_justification) (column, col);
-}
-
-gchar *
-g_sheet_column_get_subtitle (const GSheetColumn *column, glong col)
-{
-  g_return_val_if_fail (G_IS_SHEET_COLUMN (column), NULL);
-
-  if  ( ! G_SHEET_COLUMN_GET_IFACE (column)->get_subtitle)
-    return NULL;
-
-  return (G_SHEET_COLUMN_GET_IFACE (column)->get_subtitle) (column, col);
-}
-
-
-
-gint
-g_sheet_column_get_left_text_column (const GSheetColumn *column,
-                                        glong col)
-{
-  g_return_val_if_fail (G_IS_SHEET_COLUMN (column), -1);
-
-  if  ( ! G_SHEET_COLUMN_GET_IFACE (column)->get_left_text_column)
-    return col;
-
-  return (G_SHEET_COLUMN_GET_IFACE (column)->get_left_text_column) (column, col);
-
-}
-
-gint
-g_sheet_column_get_right_text_column (const GSheetColumn *column,
-                                         glong col)
-{
-  g_return_val_if_fail (G_IS_SHEET_COLUMN (column), -1);
-
-  if  ( ! G_SHEET_COLUMN_GET_IFACE (column)->get_right_text_column)
-    return col;
-
-  return (G_SHEET_COLUMN_GET_IFACE (column)->get_right_text_column) (column, col);
-
-}
-
-void
-g_sheet_column_set_left_text_column (const GSheetColumn *column,
-                                        glong col, gint i)
-{
-  g_return_if_fail (G_IS_SHEET_COLUMN (column));
-
-  if  ( G_SHEET_COLUMN_GET_IFACE (column)->set_left_text_column)
-    (G_SHEET_COLUMN_GET_IFACE (column)->set_left_text_column) (column, col, i);
-
-}
-
-
-void
-g_sheet_column_set_right_text_column (const GSheetColumn *column,
-                                         glong col, gint i)
-{
-  g_return_if_fail (G_IS_SHEET_COLUMN (column));
-
-  if  ( G_SHEET_COLUMN_GET_IFACE (column)->set_right_text_column)
-    (G_SHEET_COLUMN_GET_IFACE (column)->set_right_text_column) (column, col, i);
-}
-
-glong
-g_sheet_column_get_column_count(const GSheetColumn *geo)
-{
-  g_return_val_if_fail (G_IS_SHEET_COLUMN (geo), -1);
-
-  g_assert  ( G_SHEET_COLUMN_GET_IFACE (geo)->get_column_count);
-
-  return (G_SHEET_COLUMN_GET_IFACE (geo)->get_column_count) (geo);
-}
-
-gint
-g_sheet_column_start_pixel(const GSheetColumn *geo, glong col)
-{
-  gint i;
-  gint start_pixel = 0;
-
-  g_return_val_if_fail (G_IS_SHEET_COLUMN (geo), -1);
-  g_return_val_if_fail (col <
-                       g_sheet_column_get_column_count(geo),-1);
-
-  for ( i = 0 ; i < col ; ++i )
-    {
-      if ( g_sheet_column_get_visibility(geo, i))
-       start_pixel += g_sheet_column_get_width(geo, i);
-    }
-
-  return start_pixel;
-
-}
-
-
-
-void
-g_sheet_column_columns_changed(GSheetColumn *geo,
-                                glong first, glong n_columns)
-{
-  g_return_if_fail (G_IS_SHEET_COLUMN (geo));
-
-  g_signal_emit (geo, sheet_column_signals[COLUMNS_CHANGED], 0,
-                first, n_columns);
-}
-
-
-
-
diff --git a/lib/gtksheet/gsheet-column-iface.h b/lib/gtksheet/gsheet-column-iface.h
deleted file mode 100644 (file)
index 5503393..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/* GSheetColumn --- an abstract model of the column geometry of a
- * GSheet widget.
- * Copyright (C) 2006 Free Software Foundation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef __GSHEET_COLUMN_IFACE_H
-#define __GSHEET_COLUMN_IFACE_H
-
-#include <glib-object.h>
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-#include "gtkextra-sheet.h"
-
-
-G_BEGIN_DECLS
-
-#define G_TYPE_SHEET_COLUMN            (g_sheet_column_get_type ())
-#define G_SHEET_COLUMN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_SHEET_COLUMN, GSheetColumn))
-#define G_IS_SHEET_COLUMN(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_SHEET_COLUMN))
-#define G_SHEET_COLUMN_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_SHEET_COLUMN, GSheetColumnIface))
-
-
-typedef struct _GSheetColumn        GSheetColumn;
-typedef struct _GSheetColumnIface   GSheetColumnIface;
-struct _GSheetColumnIface
-{
-  GTypeInterface g_iface;
-
-
-  /* Signals */
-  void         (* columns_changed)     (GSheetColumn *geo,
-                                     glong col, glong n_columns);
-
-  /* Virtual Table */
-  gint (* get_width) (const GSheetColumn *gcolumn, glong col);
-  void (* set_width) (GSheetColumn *gcolumn, glong col, gint width);
-
-  gboolean (* get_visibility) (const GSheetColumn *gcolumn, glong col);
-  gboolean (* get_sensitivity) (const GSheetColumn *gcolumn, glong col);
-  const GtkSheetButton * (* get_button) (const GSheetColumn *gcolumn, glong col);
-  GtkJustification (* get_justification) (const GSheetColumn *gcolumn, glong col);
-
-  gint  (*get_left_text_column) (const GSheetColumn *gcolumn,
-                                glong col);
-
-  gint  (*get_right_text_column) (const GSheetColumn *gcolumn,
-                                 glong col);
-
-  void (* set_left_text_column) (const GSheetColumn *gcolumn,
-                                glong col, gint i);
-
-  void (* set_right_text_column) (const GSheetColumn *gcolumn,
-                                 glong col, gint i);
-
-  glong  (* get_column_count) (const GSheetColumn *geo);
-
-
-  GtkStateType  (*get_button_state)(const GSheetColumn *geo, glong col);
-  gchar * (*get_button_label)(const GSheetColumn *geo, glong col);
-  gchar * (*get_subtitle)(const GSheetColumn *geo, glong col);
-
-  gboolean      (*get_button_visibility)(const GSheetColumn *geo,
-                                       glong col);
-  const GtkSheetChild * (*get_button_child)(const GSheetColumn *geo,
-                                          glong col);
-  GtkJustification * (*get_button_justification)(const GSheetColumn *geo,
-                                               glong col);
-};
-
-
-inline GType g_sheet_column_get_type   (void) G_GNUC_CONST;
-
-
-inline gint  g_sheet_column_get_width (const GSheetColumn *gcolumn,
-                                      glong col);
-
-
-inline void  g_sheet_column_set_width (GSheetColumn *gcolumn,
-                                      glong col, gint size);
-
-
-inline gboolean  g_sheet_column_get_visibility (const GSheetColumn *gcolumn,
-                                           glong col);
-
-inline gboolean  g_sheet_column_get_sensitivity (const GSheetColumn *gcolumn,
-                                            glong col);
-
-
-inline GtkSheetButton *g_sheet_column_get_button (const GSheetColumn *gcolumn,
-                                            glong col);
-
-gchar *g_sheet_column_get_subtitle (const GSheetColumn *, glong);
-
-inline GtkJustification g_sheet_column_get_justification (const GSheetColumn *gcolumn, glong col);
-
-
-inline gint  g_sheet_column_get_left_text_column (const GSheetColumn *gcolumn,
-                                       glong col);
-
-inline gint  g_sheet_column_get_right_text_column (const GSheetColumn *gcolumn,
-                                       glong col);
-
-inline void g_sheet_column_set_left_text_column (const GSheetColumn *gcolumn,
-                                       glong col, gint i);
-
-
-inline void g_sheet_column_set_right_text_column (const GSheetColumn *gcolumn,
-                                       glong col, gint i);
-
-
-inline glong  g_sheet_column_get_column_count (const GSheetColumn *geo);
-
-inline gint  g_sheet_column_start_pixel (const GSheetColumn *geo, glong col);
-
-inline void g_sheet_column_columns_changed (GSheetColumn *geo,
-                                          glong first, glong n_columns);
-
-G_END_DECLS
-
-#endif /* __G_SHEET_COLUMN_IFACE_H__ */
diff --git a/lib/gtksheet/gsheet-hetero-column.c b/lib/gtksheet/gsheet-hetero-column.c
deleted file mode 100644 (file)
index ecc06cc..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-/* gsheet-hetero-column.c
- * PSPPIRE --- A Graphical User Interface for PSPP
- * Copyright (C) 2006  Free Software Foundation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <config.h>
-
-#include "gsheet-column-iface.h"
-#include "gsheet-hetero-column.h"
-#include <string.h>
-
-
-static void  g_sheet_hetero_column_init       (GSheetHeteroColumn      *hg);
-static void  g_sheet_hetero_column_class_init (GSheetHeteroColumnClass *class);
-static void  g_sheet_hetero_column_finalize   (GObject           *object);
-
-static void g_sheet_column_init (GSheetColumnIface *iface);
-
-
-static GObjectClass *parent_class = NULL;
-
-GType
-g_sheet_hetero_column_get_type (void)
-{
-  static GType hetero_column_type = 0;
-
-  if (!hetero_column_type)
-    {
-      static const GTypeInfo hetero_column_info =
-      {
-       sizeof (GSheetHeteroColumnClass),
-       NULL,           /* base_init */
-       NULL,           /* base_finalize */
-        (GClassInitFunc) g_sheet_hetero_column_class_init,
-       NULL,           /* class_finalize */
-       NULL,           /* class_data */
-        sizeof (GSheetHeteroColumn),
-       0,
-        (GInstanceInitFunc) g_sheet_hetero_column_init,
-      };
-
-      static const GInterfaceInfo column_info =
-      {
-       (GInterfaceInitFunc) g_sheet_column_init,
-       NULL,
-       NULL
-      };
-
-      hetero_column_type =
-       g_type_register_static (G_TYPE_OBJECT, "g_sheet_hetero_column",
-                               &hetero_column_info, 0);
-
-      g_type_add_interface_static (hetero_column_type,
-                                  G_TYPE_SHEET_COLUMN,
-                                  &column_info);
-    }
-
-  return hetero_column_type;
-}
-
-
-static GtkSheetButton default_button;
-
-
-
-/**
- * g_sheet_hetero_column_new:
- * @width: The size of columns in this hetero column
- *
- * Return value: a new #g_sheet_hetero_column
- **/
-GObject *
-g_sheet_hetero_column_new (gint default_width, gint n_columns)
-{
-  gint i;
-  GSheetHeteroColumn *hg;
-  GObject *retval;
-
-  retval = g_object_new (G_TYPE_SHEET_HETERO_COLUMN, NULL);
-
-  hg = G_SHEET_HETERO_COLUMN (retval);
-  hg->n_columns = n_columns;
-  hg->default_width = default_width;
-  hg->col = g_new0 (struct GSheetHeteroColumnUnit, n_columns);
-
-  for (i = 0 ; i < hg->n_columns; ++i )
-    {
-      hg->col[i].button = default_button;
-    }
-
-  return retval;
-}
-
-static gint
-g_sheet_hetero_column_get_width (const GSheetColumn *geom, glong i)
-{
-  GSheetHeteroColumn *hg = G_SHEET_HETERO_COLUMN (geom);
-
-  g_return_val_if_fail (i < hg->n_columns, -1);
-
-  return hg->col[i].width;
-}
-
-static gboolean
-g_sheet_hetero_column_get_sensitivity (const GSheetColumn *geom, glong u)
-{
-  return TRUE;
-}
-
-
-static gboolean
-g_sheet_hetero_column_get_visibility (const GSheetColumn *geom, glong u)
-{
-  return TRUE;
-}
-
-
-
-static gchar *
-g_sheet_hetero_column_get_button_label (const GSheetColumn *geom, glong u)
-{
-  GSheetHeteroColumn *hg = G_SHEET_HETERO_COLUMN (geom);
-
-  return g_locale_to_utf8 (hg->col[u].button.label, -1, 0, 0, 0);
-}
-
-
-static GtkJustification
-g_sheet_hetero_column_get_justification (const GSheetColumn *geom, glong u)
-{
-  return GTK_JUSTIFY_FILL;
-}
-
-
-
-static glong
-g_sheet_hetero_column_get_column_count (const GSheetColumn *geom)
-{
-  GSheetHeteroColumn *hg = G_SHEET_HETERO_COLUMN (geom);
-
-  return hg->n_columns;
-}
-
-static void
-g_sheet_hetero_column_class_init (GSheetHeteroColumnClass *class)
-{
-  GObjectClass *object_class;
-
-  parent_class = g_type_class_peek_parent (class);
-  object_class = (GObjectClass*) class;
-
-  object_class->finalize = g_sheet_hetero_column_finalize;
-
-  default_button.label=NULL;
-  default_button.child=NULL;
-  default_button.state=GTK_STATE_NORMAL;
-  default_button.justification=GTK_JUSTIFY_CENTER;
-  default_button.label_visible = TRUE;
-}
-
-
-static void
-g_sheet_hetero_column_init (GSheetHeteroColumn *o)
-{
-}
-
-static void
-g_sheet_hetero_column_finalize (GObject           *object)
-{
-  GSheetHeteroColumn *hg = G_SHEET_HETERO_COLUMN (object);
-
-  g_free (hg->col);
-}
-
-static void
-hetero_column_set_width (GSheetColumn *geo, glong i, gint size)
-{
-  GSheetHeteroColumn *hg = G_SHEET_HETERO_COLUMN (geo);
-
-  g_return_if_fail (i < hg->n_columns);
-
-  hg->col[i].width = size;
-}
-
-
-
-static void
-g_sheet_column_init (GSheetColumnIface *iface)
-{
-  iface->get_width = g_sheet_hetero_column_get_width ;
-  iface->set_width = hetero_column_set_width ;
-  iface->get_sensitivity = g_sheet_hetero_column_get_sensitivity ;
-  iface->get_visibility = g_sheet_hetero_column_get_visibility ;
-  iface->get_justification = g_sheet_hetero_column_get_justification;
-  iface->get_column_count = g_sheet_hetero_column_get_column_count;
-
-  iface->get_button_label = g_sheet_hetero_column_get_button_label;
-}
-
-
-void
-g_sheet_hetero_column_set_button_label (GSheetHeteroColumn *geo,
-                                             glong i, const gchar *label)
-{
-  g_return_if_fail (i < geo->n_columns);
-
-  g_free (geo->col[i].button.label);
-  geo->col[i].button.label = g_malloc (strlen (label) + 1);
-
-  g_stpcpy (geo->col[i].button.label, label);
-}
-
-
-
-
-void
-g_sheet_hetero_column_set_width (GSheetHeteroColumn *geo, glong i, gint size)
-{
-  GSheetColumn *iface = G_SHEET_COLUMN (geo);
-
-  hetero_column_set_width (iface, i, size);
-}
-
-
-
diff --git a/lib/gtksheet/gsheet-hetero-column.h b/lib/gtksheet/gsheet-hetero-column.h
deleted file mode 100644 (file)
index 507bc20..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/* GtkSheet widget for Gtk+.
- * Copyright (C) 2006 Free Software Foundation
-
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef __G_SHEET_HETERO_COLUMN_H__
-#define __G_SHEET_HETERO_COLUMN_H__
-
-#include <glib-object.h>
-#include <glib.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-#define G_TYPE_SHEET_HETERO_COLUMN (g_sheet_hetero_column_get_type ())
-
-#define G_SHEET_HETERO_COLUMN(obj)    G_TYPE_CHECK_INSTANCE_CAST (obj, G_TYPE_SHEET_HETERO_COLUMN, GSheetHeteroColumn )
-#define G_SHEET_HETERO_COLUMN_CLASS(klass)  G_TYPE_CHECK_CLASS_CAST (klass, g_sheet_hetero_column_get_type (), GSheetHeteroColumnClass)
-#define G_IS_SHEET_HETERO_COLUMN(obj)  G_TYPE_CHECK_INSTANCE_TYPE (obj, G_TYPE_SHEET_HETERO_COLUMN)
-
-
-  struct GSheetHeteroColumnUnit
-  {
-    GtkSheetButton button;
-
-    gint width;
-    gboolean is_sensitive;
-    gboolean is_visible;
-  };
-
-
-  struct _GSheetHeteroColumn{
-    GObject parent;
-
-    gint n_columns;
-    gint default_width;
-
-    struct GSheetHeteroColumnUnit *col;
-
-  };
-
-  struct _GSheetHeteroColumnClass
-  {
-    GObjectClass parent_class;
-  };
-
-
-
-
-  /* create a new column */
-  GObject * g_sheet_hetero_column_new (gint default_width, gint n_columns);
-
-  GType g_sheet_hetero_column_get_type (void);
-
-
-  typedef struct _GSheetHeteroColumn GSheetHeteroColumn;
-  typedef struct _GSheetHeteroColumnClass GSheetHeteroColumnClass;
-
-
-  void g_sheet_hetero_column_set_button_label (GSheetHeteroColumn *geo,
-                                               glong i, const gchar *label);
-
-  void g_sheet_hetero_column_set_width (GSheetHeteroColumn *geo,
-                                            glong i, gint size);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __G_SHEET_HETERO_COLUMN_H__ */
-
-
diff --git a/lib/gtksheet/gsheet-row-iface.c b/lib/gtksheet/gsheet-row-iface.c
deleted file mode 100644 (file)
index 1512737..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/* GSheetRow --- an abstract model of the row geometry of a
- * GSheet widget.
- * Copyright (C) 2006 Free Software Foundation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <config.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-#include <glib/gprintf.h>
-#include <gobject/gvaluecollector.h>
-#include "gsheet-row-iface.h"
-#include "gtkextra-marshal.h"
-
-
-enum {
-  ROWS_CHANGED,
-  LAST_SIGNAL
-};
-
-static guint sheet_row_signals[LAST_SIGNAL];
-
-
-
-static void      g_sheet_row_base_init   (gpointer g_class);
-
-
-GType
-g_sheet_row_get_type (void)
-{
-  static GType sheet_row_type = 0;
-
-  if (! sheet_row_type)
-    {
-      static const GTypeInfo sheet_row_info =
-
-      {
-        sizeof (GSheetRowIface), /* class_size */
-       g_sheet_row_base_init,   /* base_init */
-       NULL,           /* base_finalize */
-       NULL,
-       NULL,           /* class_finalize */
-       NULL,           /* class_data */
-       0,
-       0,              /* n_preallocs */
-       NULL
-      };
-
-      sheet_row_type =
-       g_type_register_static (G_TYPE_INTERFACE, "GSheetRow",
-                               &sheet_row_info, 0);
-
-      g_type_interface_add_prerequisite (sheet_row_type, G_TYPE_OBJECT);
-    }
-
-  return sheet_row_type;
-}
-
-
-static GtkSheetButton default_button;
-
-static void
-g_sheet_row_base_init (gpointer g_class)
-{
-  static gboolean initialized = FALSE;
-
-  if (! initialized)
-    {
-
-      sheet_row_signals[ROWS_CHANGED] =
-       g_signal_new ("rows_changed",
-                     G_TYPE_SHEET_ROW,
-                     G_SIGNAL_RUN_LAST,
-                     G_STRUCT_OFFSET (GSheetRowIface, rows_changed),
-                     NULL, NULL,
-                     gtkextra_VOID__INT_INT,
-                     G_TYPE_NONE, 2,
-                     G_TYPE_INT,
-                     G_TYPE_INT);
-
-
-      default_button.state = GTK_STATE_NORMAL;
-      default_button.label = NULL;
-      default_button.label_visible = TRUE;
-      default_button.child = NULL;
-      default_button.justification = GTK_JUSTIFY_FILL;
-
-      initialized = TRUE;
-    }
-}
-
-void
-g_sheet_row_set_height (GSheetRow *row_geo,
-                       glong row, gint size)
-{
-  g_return_if_fail (G_IS_SHEET_ROW (row_geo));
-
-  if ((G_SHEET_ROW_GET_IFACE (row_geo)->set_height) )
-    (G_SHEET_ROW_GET_IFACE (row_geo)->set_height) (row_geo, row,
-                                                       size);
-}
-
-
-gint
-g_sheet_row_get_height     (const GSheetRow *row_geo,
-                           glong row)
-{
-  g_return_val_if_fail (G_IS_SHEET_ROW (row_geo), -1);
-
-  g_assert (G_SHEET_ROW_GET_IFACE (row_geo)->get_height);
-
-  return (G_SHEET_ROW_GET_IFACE (row_geo)->get_height) (row_geo, row);
-}
-
-
-
-gboolean
-g_sheet_row_get_visibility(const GSheetRow *row_geo,
-                          glong row)
-{
-  g_return_val_if_fail (G_IS_SHEET_ROW (row_geo), FALSE);
-
-  g_assert (G_SHEET_ROW_GET_IFACE (row_geo)->get_visibility);
-
-  return (G_SHEET_ROW_GET_IFACE (row_geo)->get_visibility) (row_geo,
-                                                                 row);
-
-}
-
-gboolean
-g_sheet_row_get_sensitivity(const GSheetRow *row_geo,
-                           glong row)
-{
-  g_return_val_if_fail (G_IS_SHEET_ROW (row_geo), FALSE);
-
-  g_assert (G_SHEET_ROW_GET_IFACE (row_geo)->get_sensitivity);
-
-  return (G_SHEET_ROW_GET_IFACE (row_geo)->get_sensitivity) (row_geo,
-                                                            row);
-
-}
-
-
-GtkSheetButton *
-g_sheet_row_get_button(const GSheetRow *row_geo,
-                      glong row)
-{
-  GtkSheetButton *button  = gtk_sheet_button_new();
-
-  GSheetRowIface *iface = G_SHEET_ROW_GET_IFACE (row_geo);
-
-  g_return_val_if_fail (G_IS_SHEET_ROW (row_geo), FALSE);
-
-  if ( iface->get_button_label)
-    button->label = iface->get_button_label(row_geo, row);
-
-  return button;
-}
-
-gchar *
-g_sheet_row_get_subtitle (const GSheetRow *row_geo, glong row)
-{
-  g_return_val_if_fail (G_IS_SHEET_ROW (row_geo), NULL);
-
-  if ( ! G_SHEET_ROW_GET_IFACE (row_geo)->get_subtitle )
-    return NULL;
-
-  return (G_SHEET_ROW_GET_IFACE (row_geo)->get_subtitle) (row_geo, row);
-}
-
-
-
-
-glong
-g_sheet_row_get_row_count (const GSheetRow *geo)
-{
-  g_return_val_if_fail (G_IS_SHEET_ROW (geo), -1);
-
-  g_assert  ( G_SHEET_ROW_GET_IFACE (geo)->get_row_count);
-
-  return (G_SHEET_ROW_GET_IFACE (geo)->get_row_count) (geo);
-}
-
-/**
- * g_sheet_row_start_pixel:
- * @geo: the row model
- * @row: the row number
- * @sheet: pointer to the sheet
- *
- * Returns the top y pixel for ROW.
- * Instances may override this method in order to achieve time and/or memory
- * optmisation.
- *
- * Returns: the y coordinate of the top of the row.
- */
-
-gint
-g_sheet_row_start_pixel(const GSheetRow *geo, glong row)
-{
-  gint i;
-  gint start_pixel = 0;
-
-  g_return_val_if_fail (G_IS_SHEET_ROW (geo), -1);
-  g_return_val_if_fail (row >= 0, -1);
-  g_return_val_if_fail (row <
-                       g_sheet_row_get_row_count(geo),-1);
-
-  if ( G_SHEET_ROW_GET_IFACE(geo)->top_ypixel)
-    return (G_SHEET_ROW_GET_IFACE(geo)->top_ypixel)(geo, row);
-
-  for ( i = 0 ; i < row ; ++i )
-    {
-      if ( g_sheet_row_get_visibility(geo, i))
-       start_pixel += g_sheet_row_get_height(geo, i);
-    }
-
-  return start_pixel;
-}
-
-
-glong
-g_sheet_row_pixel_to_row (const GSheetRow *geo, gint pixel)
-{
-  gint i, cy;
-  g_return_val_if_fail (G_IS_SHEET_ROW (geo), -1);
-  g_return_val_if_fail (pixel >= 0, -1) ;
-
-  if ( G_SHEET_ROW_GET_IFACE(geo)->pixel_to_row)
-    return (G_SHEET_ROW_GET_IFACE(geo)->pixel_to_row)(geo, pixel);
-
-  cy = 0;
-  for (i = 0; i < g_sheet_row_get_row_count (geo); ++i )
-    {
-      if (pixel >= cy  &&
-         pixel <= (cy + g_sheet_row_get_height (geo, i)) &&
-         g_sheet_row_get_visibility (geo, i))
-       return i;
-
-      if(g_sheet_row_get_visibility (geo, i))
-       cy += g_sheet_row_get_height (geo, i);
-    }
-
-  /* no match */
-  return g_sheet_row_get_row_count (geo) - 1;
-}
-
-
-
-void
-g_sheet_row_rows_deleted (GSheetRow *geo,
-                                glong first, glong n_rows)
-{
-  g_return_if_fail (G_IS_SHEET_ROW (geo));
-
-  g_signal_emit (geo, sheet_row_signals[ROWS_CHANGED], 0,
-                first, n_rows);
-}
diff --git a/lib/gtksheet/gsheet-row-iface.h b/lib/gtksheet/gsheet-row-iface.h
deleted file mode 100644 (file)
index 921f369..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/* GSheetRow --- an abstract model of the row geometry of a
- * GSheet widget.
- * Copyright (C) 2006 Free Software Foundation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef __G_SHEET_ROW_IFACE_H__
-#define __G_SHEET_ROW_IFACE_H__
-
-#include <glib-object.h>
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-#include "gtkextra-sheet.h"
-
-
-G_BEGIN_DECLS
-
-#define G_TYPE_SHEET_ROW            (g_sheet_row_get_type ())
-#define G_SHEET_ROW(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_SHEET_ROW, GSheetRow))
-#define G_IS_SHEET_ROW(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_SHEET_ROW))
-#define G_SHEET_ROW_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_SHEET_ROW, GSheetRowIface))
-
-
-
-
-typedef struct _GSheetRow        GSheetRow;
-typedef struct _GSheetRowIface   GSheetRowIface;
-
-struct _GSheetRowIface
-{
-  GTypeInterface g_iface;
-
-
-  /* Signals */
-  void         (* rows_changed)     (GSheetRow *geo,
-                                     glong row, glong n_rows);
-
-  /* Virtual Table */
-  gint (* get_height) (const GSheetRow *grow, glong row);
-  void (* set_height) (GSheetRow *grow, glong row, gint height);
-
-  gboolean (* get_visibility) (const GSheetRow *grow, glong row);
-
-  gboolean (* get_sensitivity) (const GSheetRow *grow, glong row);
-
-  const GtkSheetButton * (* get_button) (const GSheetRow *grow, glong row);
-
-  glong  (* get_row_count) (const GSheetRow *geo);
-
-  GtkStateType  (*get_button_state) (const GSheetRow *geo, glong row);
-
-  gchar * (*get_button_label) (const GSheetRow *geo, glong row);
-
-  gchar * (*get_subtitle) (const GSheetRow *geo, glong row);
-
-  gboolean  (*get_button_visibility) (const GSheetRow *geo,
-                                         glong row);
-
-  const GtkSheetChild * (*get_button_child) (const GSheetRow *geo,
-                                            glong row);
-
-  guint (*top_ypixel) (const GSheetRow *geo, glong row);
-  glong (*pixel_to_row) (const GSheetRow *geo, guint pixel);
-};
-
-
-GType g_sheet_row_get_type   (void) G_GNUC_CONST;
-
-
-gint  g_sheet_row_get_height (const GSheetRow *grow,
-                             glong row);
-
-
-void  g_sheet_row_set_height (GSheetRow *grow,
-                             glong row, gint size);
-
-
-gboolean  g_sheet_row_get_visibility (const GSheetRow *grow,
-                                     glong row);
-
-gboolean  g_sheet_row_get_sensitivity (const GSheetRow *grow,
-                                      glong row);
-
-
-GtkSheetButton *g_sheet_row_get_button (const GSheetRow *grow,
-                                       glong row);
-
-
-glong  g_sheet_row_get_row_count (const GSheetRow *geo);
-
-/* Return the top pixel of row ROW */
-gint  g_sheet_row_start_pixel (const GSheetRow *geo, glong row);
-
-
-/* Return the row contained by pixel PIXEL */
-glong  g_sheet_row_pixel_to_row (const GSheetRow *geo, gint pixel);
-
-
-void g_sheet_row_rows_deleted (GSheetRow *geo,
-                                     glong first, glong n_rows);
-
-
-gchar *g_sheet_row_get_subtitle (const GSheetRow *row_geo, glong row);
-
-
-G_END_DECLS
-
-#endif /* __G_SHEET_ROW_IFACE_H__ */
diff --git a/lib/gtksheet/gsheet-uniform-column.c b/lib/gtksheet/gsheet-uniform-column.c
deleted file mode 100644 (file)
index 5093da2..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/* gsheet-uniform-column.c
- *
- * PSPPIRE --- A Graphical User Interface for PSPP
- * Copyright (C) 2006  Free Software Foundation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <config.h>
-
-#include "gsheet-column-iface.h"
-#include "gsheet-uniform-column.h"
-
-
-static void  g_sheet_uniform_column_init       (GSheetUniformColumn      *ug);
-static void  g_sheet_uniform_column_class_init (GSheetUniformColumnClass *class);
-static void  g_sheet_uniform_column_finalize   (GObject           *object);
-
-static void g_sheet_column_init (GSheetColumnIface *iface);
-
-
-static GObjectClass *parent_class = NULL;
-
-GType
-g_sheet_uniform_column_get_type (void)
-{
-  static GType uniform_column_type = 0;
-
-  if (!uniform_column_type)
-    {
-      static const GTypeInfo uniform_column_info =
-      {
-       sizeof (GSheetUniformColumnClass),
-       NULL,           /* base_init */
-       NULL,           /* base_finalize */
-        (GClassInitFunc) g_sheet_uniform_column_class_init,
-       NULL,           /* class_finalize */
-       NULL,           /* class_data */
-        sizeof (GSheetUniformColumn),
-       0,
-        (GInstanceInitFunc) g_sheet_uniform_column_init,
-      };
-
-      static const GInterfaceInfo column_info =
-      {
-       (GInterfaceInitFunc) g_sheet_column_init,
-       NULL,
-       NULL
-      };
-
-      uniform_column_type =
-       g_type_register_static (G_TYPE_OBJECT, "g_sheet_uniform_column",
-                               &uniform_column_info, 0);
-
-      g_type_add_interface_static (uniform_column_type,
-                                  G_TYPE_SHEET_COLUMN,
-                                  &column_info);
-    }
-
-  return uniform_column_type;
-}
-
-
-/**
- * g_sheet_uniform_column_new:
- * @width: The size of columns in this uniform column
- *
- * Return value: a new #g_sheet_uniform_column
- **/
-GObject *
-g_sheet_uniform_column_new (gint width, gint n_columns)
-{
-  GSheetUniformColumn *ug;
-  GObject *retval;
-
-  retval = g_object_new (G_TYPE_SHEET_UNIFORM_COLUMN, NULL);
-
-  ug = G_SHEET_UNIFORM_COLUMN(retval);
-  ug->n_columns = n_columns;
-  ug->width = width;
-  ug->is_visible = TRUE;
-  ug->is_sensitive = FALSE;
-
-  return retval;
-}
-
-static gint
-g_sheet_uniform_column_get_width (const GSheetColumn *geom, glong u)
-{
-  GSheetUniformColumn *ug = G_SHEET_UNIFORM_COLUMN (geom);
-
-  return ug->width;
-}
-
-static gboolean
-g_sheet_uniform_column_get_sensitivity (const GSheetColumn *geom, glong u)
-{
-  GSheetUniformColumn *ug = G_SHEET_UNIFORM_COLUMN (geom);
-
-  return ug->is_sensitive;
-}
-
-
-static gboolean
-g_sheet_uniform_column_get_visibility (const GSheetColumn *geom, glong u)
-{
-  GSheetUniformColumn *ug = G_SHEET_UNIFORM_COLUMN (geom);
-
-  return ug->is_visible;
-}
-
-
-static gchar *
-g_sheet_uniform_column_get_button_label (const GSheetColumn *geom, glong u)
-{
-  gchar *label = g_strdup_printf ("%ld", u);
-
-  return label;
-}
-
-
-static GtkJustification
-g_sheet_uniform_column_get_justification (const GSheetColumn *geom, glong u)
-{
-  return GTK_JUSTIFY_FILL;
-}
-
-
-
-static glong
-g_sheet_uniform_column_get_column_count (const GSheetColumn *geom)
-{
-  GSheetUniformColumn *ug = G_SHEET_UNIFORM_COLUMN (geom);
-
-  return ug->n_columns;
-}
-
-static void
-g_sheet_uniform_column_class_init (GSheetUniformColumnClass *class)
-{
-  GObjectClass *object_class;
-
-  parent_class = g_type_class_peek_parent (class);
-  object_class = (GObjectClass*) class;
-
-  object_class->finalize = g_sheet_uniform_column_finalize;
-
-}
-
-
-static void
-g_sheet_uniform_column_init (GSheetUniformColumn *o)
-{
-}
-
-static void
-g_sheet_uniform_column_finalize (GObject *object)
-{
-}
-
-
-static void
-g_sheet_column_init (GSheetColumnIface *iface)
-{
-  iface->get_width = g_sheet_uniform_column_get_width ;
-  iface->get_sensitivity = g_sheet_uniform_column_get_sensitivity ;
-  iface->get_visibility = g_sheet_uniform_column_get_visibility ;
-  iface->get_justification = g_sheet_uniform_column_get_justification;
-  iface->get_column_count = g_sheet_uniform_column_get_column_count;
-  iface->get_button_label = g_sheet_uniform_column_get_button_label;
-}
-
diff --git a/lib/gtksheet/gsheet-uniform-column.h b/lib/gtksheet/gsheet-uniform-column.h
deleted file mode 100644 (file)
index e56037b..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* GtkSheet widget for Gtk+.
- * Copyright (C) 2006 Free Software Foundation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef  __G_SHEET_UNIFORM_COLUMN_H__
-#define  __G_SHEET_UNIFORM_COLUMN_H__
-
-
-#include <glib-object.h>
-#include <glib.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-#define G_TYPE_SHEET_UNIFORM_COLUMN (g_sheet_uniform_column_get_type ())
-
-#define G_SHEET_UNIFORM_COLUMN(obj)    G_TYPE_CHECK_INSTANCE_CAST (obj, G_TYPE_SHEET_UNIFORM_COLUMN, GSheetUniformColumn )
-#define G_SHEET_UNIFORM_COLUMN_CLASS(klass)  G_TYPE_CHECK_CLASS_CAST (klass, g_sheet_uniform_column_get_type (), GSheetUniformColumnClass)
-#define G_IS_SHEET_UNIFORM_COLUMN(obj)  G_TYPE_CHECK_INSTANCE_TYPE (obj, G_TYPE_SHEET_UNIFORM_COLUMN)
-
-
-  struct _GSheetUniformColumn{
-    GObject parent;
-
-    gint n_columns;
-    gint width;
-    gboolean is_sensitive;
-    gboolean is_visible;
-  };
-
-  struct _GSheetUniformColumnClass
-  {
-    GObjectClass parent_class;
-  };
-
-  /* create a new column */
-  GObject * g_sheet_uniform_column_new (gint width, gint n_columns);
-
-  GType g_sheet_uniform_column_get_type (void);
-
-
-  typedef struct _GSheetUniformColumn GSheetUniformColumn;
-  typedef struct _GSheetUniformColumnClass GSheetUniformColumnClass;
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __G_SHEET_UNIFORM_COLUMN_H__ */
-
-
diff --git a/lib/gtksheet/gsheet-uniform-row.c b/lib/gtksheet/gsheet-uniform-row.c
deleted file mode 100644 (file)
index 7ab9b60..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/* gsheet-uniform-row.c
- *
- *  PSPPIRE --- A Graphical User Interface for PSPP
- * Copyright (C) 2006  Free Software Foundation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <config.h>
-
-#include "gsheet-row-iface.h"
-#include "gsheet-uniform-row.h"
-
-
-static void  g_sheet_uniform_row_init       (GSheetUniformRow      *ug);
-static void  g_sheet_uniform_row_class_init (GSheetUniformRowClass *class);
-static void  g_sheet_uniform_row_finalize   (GObject           *object);
-
-static void g_sheet_row_init (GSheetRowIface *iface);
-
-
-static GObjectClass *parent_class = NULL;
-
-GType
-g_sheet_uniform_row_get_type (void)
-{
-  static GType uniform_row_type = 0;
-
-  if (!uniform_row_type)
-    {
-      static const GTypeInfo uniform_row_info =
-      {
-       sizeof (GSheetUniformRowClass),
-       NULL,           /* base_init */
-       NULL,           /* base_finalize */
-        (GClassInitFunc) g_sheet_uniform_row_class_init,
-       NULL,           /* class_finalize */
-       NULL,           /* class_data */
-        sizeof (GSheetUniformRow),
-       0,
-        (GInstanceInitFunc) g_sheet_uniform_row_init,
-      };
-
-      static const GInterfaceInfo row_info =
-      {
-       (GInterfaceInitFunc) g_sheet_row_init,
-       NULL,
-       NULL
-      };
-
-      uniform_row_type =
-       g_type_register_static (G_TYPE_OBJECT, "g_sheet_uniform_row",
-                               &uniform_row_info, 0);
-
-      g_type_add_interface_static (uniform_row_type,
-                                  G_TYPE_SHEET_ROW,
-                                  &row_info);
-    }
-
-  return uniform_row_type;
-}
-
-
-/**
- * g_sheet_uniform_row_new:
- * @height: The size of rows in this uniform row
- *
- * Return value: a new #g_sheet_uniform_row
- **/
-GObject *
-g_sheet_uniform_row_new (gint height, gint n_rows)
-{
-  GSheetUniformRow *ug;
-  GObject *retval;
-
-  retval = g_object_new (G_TYPE_SHEET_UNIFORM_ROW, NULL);
-
-  ug = G_SHEET_UNIFORM_ROW(retval);
-  ug->n_rows = n_rows;
-  ug->height = height;
-  ug->is_visible = TRUE;
-
-  return retval;
-}
-
-static gint
-g_sheet_uniform_row_get_height (const GSheetRow *geom, glong u)
-{
-  GSheetUniformRow *ug = G_SHEET_UNIFORM_ROW(geom);
-
-  return ug->height;
-}
-
-static gboolean
-g_sheet_uniform_row_get_sensitivity (const GSheetRow *geom, glong u)
-{
-  GSheetUniformRow *ug = G_SHEET_UNIFORM_ROW(geom);
-
-  return (u < ug->n_rows);
-}
-
-
-static gboolean
-g_sheet_uniform_row_get_visibility (const GSheetRow *geom, glong u)
-{
-  GSheetUniformRow *ug = G_SHEET_UNIFORM_ROW (geom);
-
-  return ug->is_visible;
-}
-
-
-static gchar *
-g_sheet_uniform_row_get_button_label (const GSheetRow *geom, glong u)
-{
-  gchar *label = g_strdup_printf("%ld", u);
-
-  return label;
-}
-
-
-
-static glong
-g_sheet_uniform_row_get_row_count (const GSheetRow *geom)
-{
-  GSheetUniformRow *ug = G_SHEET_UNIFORM_ROW(geom);
-
-  return ug->n_rows;
-}
-
-
-static void
-g_sheet_uniform_row_class_init (GSheetUniformRowClass *class)
-{
-  GObjectClass *object_class;
-
-  parent_class = g_type_class_peek_parent (class);
-  object_class = (GObjectClass*) class;
-
-  object_class->finalize = g_sheet_uniform_row_finalize;
-
-}
-
-
-static void
-g_sheet_uniform_row_init (GSheetUniformRow *o)
-{
-}
-
-static void
-g_sheet_uniform_row_finalize (GObject *object)
-{
-}
-
-
-static guint
-g_sheet_uniform_row_top_ypixel (const GSheetRow *geo, glong row)
-{
-  GSheetUniformRow *ug = G_SHEET_UNIFORM_ROW(geo);
-
-  return row * ug->height;
-}
-
-static glong
-g_sheet_uniform_row_pixel_to_row (const GSheetRow *geo, guint pixel)
-{
-  GSheetUniformRow *ug = G_SHEET_UNIFORM_ROW(geo);
-
-  gint row = pixel / ug->height;
-
-  if (row >= g_sheet_uniform_row_get_row_count(geo))
-    row = g_sheet_uniform_row_get_row_count(geo) - 1;
-
-  return row;
-}
-
-
-
-static void
-g_sheet_row_init (GSheetRowIface *iface)
-{
-  iface->get_height = g_sheet_uniform_row_get_height;
-  iface->get_sensitivity = g_sheet_uniform_row_get_sensitivity ;
-  iface->get_visibility = g_sheet_uniform_row_get_visibility;
-  iface->get_row_count = g_sheet_uniform_row_get_row_count;
-  iface->get_button_label = g_sheet_uniform_row_get_button_label;
-  iface->top_ypixel = g_sheet_uniform_row_top_ypixel;
-  iface->pixel_to_row = g_sheet_uniform_row_pixel_to_row;
-}
-
diff --git a/lib/gtksheet/gsheet-uniform-row.h b/lib/gtksheet/gsheet-uniform-row.h
deleted file mode 100644 (file)
index 845dbf6..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/* GtkSheet widget for Gtk+.
- * Copyright (C) 2006 Free Software Foundation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef __G_SHEET_UNIFORM_ROW_H__
-#define __G_SHEET_UNIFORM_ROW_H__
-
-#include <glib-object.h>
-#include <glib.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-#define G_TYPE_SHEET_UNIFORM_ROW (g_sheet_uniform_row_get_type ())
-
-#define G_SHEET_UNIFORM_ROW(obj)    G_TYPE_CHECK_INSTANCE_CAST (obj, G_TYPE_SHEET_UNIFORM_ROW, GSheetUniformRow )
-#define G_SHEET_UNIFORM_ROW_CLASS(klass)  G_TYPE_CHECK_CLASS_CAST (klass, g_sheet_uniform_row_get_type (), GSheetUniformRowClass)
-#define G_IS_SHEET_UNIFORM_ROW(obj)  G_TYPE_CHECK_INSTANCE_TYPE (obj, G_TYPE_SHEET_UNIFORM_ROW)
-
-
-  struct _GSheetUniformRow{
-    GObject parent;
-
-    gint n_rows;
-    gint height;
-    gboolean is_visible;
-  };
-
-  struct _GSheetUniformRowClass
-  {
-    GObjectClass parent_class;
-  };
-
-  /* create a new row */
-  GObject * g_sheet_uniform_row_new (gint height, gint n_rows);
-
-  GType g_sheet_uniform_row_get_type (void);
-
-
-  typedef struct _GSheetUniformRow GSheetUniformRow;
-  typedef struct _GSheetUniformRowClass GSheetUniformRowClass;
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __G_SHEET_UNIFORM_ROW_H__ */
-
-
index 0d1a3f560a60c8edee89d9e7f8d0ff0553aa660a..e200b300fa3f38adb60599f4cc840cc97dc22d43 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <glib.h>
 #include "gsheetmodel.h"
-#include "gtkextra-marshal.h"
+#include <gtksheet/psppire-marshal.h>
 
 enum {
   RANGE_CHANGED,
@@ -80,7 +80,7 @@ g_sheet_model_base_init (gpointer g_class)
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (GSheetModelIface, range_changed),
                      NULL, NULL,
-                     gtkextra_VOID__INT_INT_INT_INT,
+                     psppire_marshal_VOID__INT_INT_INT_INT,
                      G_TYPE_NONE, 4,
                      G_TYPE_INT,
                      G_TYPE_INT,
@@ -95,7 +95,7 @@ g_sheet_model_base_init (gpointer g_class)
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (GSheetModelIface, rows_inserted),
                      NULL, NULL,
-                     gtkextra_VOID__INT_INT,
+                     psppire_marshal_VOID__INT_INT,
                      G_TYPE_NONE, 2,
                      G_TYPE_INT,
                      G_TYPE_INT);
@@ -107,7 +107,7 @@ g_sheet_model_base_init (gpointer g_class)
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (GSheetModelIface, rows_deleted),
                      NULL, NULL,
-                     gtkextra_VOID__INT_INT,
+                     psppire_marshal_VOID__INT_INT,
                      G_TYPE_NONE, 2,
                      G_TYPE_INT,
                      G_TYPE_INT);
@@ -118,7 +118,7 @@ g_sheet_model_base_init (gpointer g_class)
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (GSheetModelIface, columns_inserted),
                      NULL, NULL,
-                     gtkextra_VOID__INT_INT,
+                     psppire_marshal_VOID__INT_INT,
                      G_TYPE_NONE, 2,
                      G_TYPE_INT,
                      G_TYPE_INT);
@@ -130,7 +130,7 @@ g_sheet_model_base_init (gpointer g_class)
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (GSheetModelIface, columns_deleted),
                      NULL, NULL,
-                     gtkextra_VOID__INT_INT,
+                     psppire_marshal_VOID__INT_INT,
                      G_TYPE_NONE, 2,
                      G_TYPE_INT,
                      G_TYPE_INT);
@@ -348,27 +348,6 @@ g_sheet_model_is_editable (const GSheetModel *model,
                                                          row, column);
 }
 
-/**
- * g_sheet_model_is_visible:
- * @sheet_model: A #GSheetModel
- * @row: The row
- * @column: The column
- *
- * Returns: TRUE if the cell is visible, FALSE otherwise
- **/
-gboolean
-g_sheet_model_is_visible (const GSheetModel *model,
-                         glong row, glong column)
-{
-  g_return_val_if_fail (G_IS_SHEET_MODEL (model), TRUE);
-
-  if ( ! G_SHEET_MODEL_GET_IFACE (model)->is_visible )
-    return TRUE;
-
-  return G_SHEET_MODEL_GET_IFACE (model)->is_visible (model,
-                                                       row, column);
-}
-
 
 /**
  * g_sheet_model_get_foreground:
@@ -377,9 +356,9 @@ g_sheet_model_is_visible (const GSheetModel *model,
  * @column: The column
  *
  * Returns the foreground colour of the cell at @row, @column
- * Returns: the foreground colour, or NULL on error.
+ * The color is unallocated.  It will be allocated by the viewing object.
  **/
-const GdkColor *
+GdkColor *
 g_sheet_model_get_foreground (const GSheetModel *model,
                                glong row, glong column)
 {
@@ -399,9 +378,9 @@ g_sheet_model_get_foreground (const GSheetModel *model,
  * @column: The column
  *
  * Returns the background colour of the cell at @row, @column
- * Returns: the background colour, or NULL on error.
+ * The color is unallocated.  It will be allocated by the viewing object.
  **/
-const GdkColor *
+GdkColor *
 g_sheet_model_get_background (const GSheetModel *model,
                                glong row, glong column)
 {
@@ -436,49 +415,6 @@ g_sheet_model_get_justification (const GSheetModel *model,
                                                               row, column);
 }
 
-/**
- * g_sheet_model_get_font_desc:
- * @sheet_model: A #GSheetModel
- * @row: The row
- * @column: The column
- *
- * Returns the font description of the cell at @row, @column
- * Returns: the font description, or NULL on error.
- **/
-const PangoFontDescription *
-g_sheet_model_get_font_desc(const GSheetModel *model,
-                             glong row, glong column)
-{
-  g_return_val_if_fail (G_IS_SHEET_MODEL (model), NULL);
-  if ( ! G_SHEET_MODEL_GET_IFACE (model)->get_font_desc)
-    return NULL;
-
-  return G_SHEET_MODEL_GET_IFACE (model)->get_font_desc (model,
-                                                          row, column);
-}
-
-/**
- * g_sheet_model_get_cell_border:
- * @sheet_model: A #GSheetModel
- * @row: The row
- * @column: The column
- *
- * Returns the cell border of the cell at @row, @column
- * Returns: the cell border, or NULL on error.
- **/
-const GtkSheetCellBorder *
-g_sheet_model_get_cell_border (const GSheetModel *model,
-                                glong row, glong column)
-{
-  g_return_val_if_fail (G_IS_SHEET_MODEL (model), NULL);
-  if ( ! G_SHEET_MODEL_GET_IFACE (model)->get_cell_border)
-    return NULL;
-
-  return G_SHEET_MODEL_GET_IFACE (model)->get_cell_border (model,
-                                                          row, column);
-}
-
-
 
 /**
  * g_sheet_model_get_column_count:
@@ -505,6 +441,102 @@ g_sheet_model_get_row_count(const GSheetModel *model)
 {
   g_return_val_if_fail (G_IS_SHEET_MODEL (model), -1);
 
-
   return G_SHEET_MODEL_GET_IFACE (model)->get_row_count (model);
 }
+
+\f
+
+/* Column related functions  */
+gboolean
+g_sheet_model_get_column_sensitivity (const GSheetModel *model, gint col)
+{
+  g_return_val_if_fail (G_IS_SHEET_MODEL (model), FALSE);
+
+  if ( NULL == G_SHEET_MODEL_GET_IFACE (model)->get_column_sensitivity)
+    return TRUE;
+
+  return G_SHEET_MODEL_GET_IFACE (model)->get_column_sensitivity (model, col);
+}
+
+
+gchar *
+g_sheet_model_get_column_subtitle (const GSheetModel *model,
+                                  gint col)
+{
+  g_return_val_if_fail (G_IS_SHEET_MODEL (model), NULL);
+
+  if ( NULL == G_SHEET_MODEL_GET_IFACE (model)->get_column_subtitle)
+    return NULL;
+
+  return G_SHEET_MODEL_GET_IFACE (model)->get_column_subtitle (model, col);
+}
+
+
+GtkSheetButton *
+g_sheet_model_get_column_button (const GSheetModel *model,
+                                gint col)
+{
+  GtkSheetButton *button = gtk_sheet_button_new ();
+
+  g_return_val_if_fail (G_IS_SHEET_MODEL (model), NULL);
+
+  if ( G_SHEET_MODEL_GET_IFACE (model)->get_column_title)
+    button->label = G_SHEET_MODEL_GET_IFACE (model)->get_column_title (model, col);
+
+  return button;
+}
+
+GtkJustification
+g_sheet_model_get_column_justification (const GSheetModel *model,
+                                       gint col)
+{
+  g_return_val_if_fail (G_IS_SHEET_MODEL (model), GTK_JUSTIFY_LEFT);
+
+  if ( G_SHEET_MODEL_GET_IFACE (model)->get_column_justification)
+    return G_SHEET_MODEL_GET_IFACE (model)->get_column_justification (model, col);
+
+  return GTK_JUSTIFY_LEFT;
+}
+
+\f
+
+gboolean
+g_sheet_model_get_row_sensitivity (const GSheetModel *model, gint row)
+{
+  g_return_val_if_fail (G_IS_SHEET_MODEL (model), FALSE);
+
+  if ( NULL == G_SHEET_MODEL_GET_IFACE (model)->get_row_sensitivity)
+    return TRUE;
+
+  return G_SHEET_MODEL_GET_IFACE (model)->get_row_sensitivity (model, row);
+}
+
+
+
+gchar *
+g_sheet_model_get_row_subtitle (const GSheetModel *model,
+                               gint row)
+{
+  g_return_val_if_fail (G_IS_SHEET_MODEL (model), NULL);
+
+  if ( NULL == G_SHEET_MODEL_GET_IFACE (model)->get_row_subtitle)
+    return NULL;
+
+  return G_SHEET_MODEL_GET_IFACE (model)->get_row_subtitle (model, row);
+}
+
+
+GtkSheetButton *
+g_sheet_model_get_row_button (const GSheetModel *model,
+                                gint row)
+{
+  GtkSheetButton *button = gtk_sheet_button_new ();
+
+  g_return_val_if_fail (G_IS_SHEET_MODEL (model), NULL);
+
+  if ( G_SHEET_MODEL_GET_IFACE (model)->get_row_title)
+    button->label = G_SHEET_MODEL_GET_IFACE (model)->get_row_title (model, row);
+
+  return button;
+}
+
index 6d60e032f9fb741b97d389b1ae1f50781b5ff298..6a54d7e85ab25a72abf8815548e5bec4c9bb910b 100644 (file)
@@ -26,7 +26,7 @@
 #include <glib-object.h>
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
-
+#include "gtkextra-sheet.h"
 
 G_BEGIN_DECLS
 
@@ -51,8 +51,8 @@ typedef struct _GtkSheetCellBorder     GtkSheetCellBorder;
 
 struct _GtkSheetRange
 {
-  glong row0,col0; /* upper-left cell */
-  glong rowi,coli; /* lower-right cell */
+  gint row0, col0; /* upper-left cell */
+  gint rowi, coli; /* lower-right cell */
 };
 
 struct _GtkSheetCellBorder
@@ -85,10 +85,12 @@ struct _GSheetModelIface
                                     glong row, glong n_rows);
 
   void         (* columns_inserted)    (GSheetModel *sheet_model,
-                                    glong column, glong n_columns);
+                                       glong column, glong n_columns);
 
   void         (* columns_deleted)     (GSheetModel *sheet_model,
-                                    glong column, glong n_columns);
+                                       glong column, glong n_columns);
+
+
 
 
 
@@ -96,7 +98,7 @@ struct _GSheetModelIface
   /* Virtual Table */
 
   gchar *      (* get_string)      (const GSheetModel *sheet_model,
-                                              glong row, glong column);
+                                   glong row, glong column);
 
   gboolean  (* set_string) (GSheetModel *sheet_model,
                            const gchar *s, glong row, glong column);
@@ -104,29 +106,33 @@ struct _GSheetModelIface
   gboolean  (* clear_datum) (GSheetModel *sheet_model,
                             glong row, glong column);
 
-  gboolean (* is_visible) (const GSheetModel *sheet_model, glong row, glong column);
   gboolean (* is_editable) (const GSheetModel *sheet_model, glong row, glong column);
 
-  const GdkColor *  (* get_foreground) (const GSheetModel *sheet_model,
-                                   glong row, glong column);
+  GdkColor *  (* get_foreground) (const GSheetModel *sheet_model,
+                                 glong row, glong column);
 
-  const GdkColor *  (* get_background) (const GSheetModel *sheet_model,
-                                   glong row, glong column);
+  GdkColor *  (* get_background) (const GSheetModel *sheet_model,
+                                 glong row, glong column);
 
   const GtkJustification *  (* get_justification) (const GSheetModel *sheet_model,
                                                   glong row, glong column);
 
-  const PangoFontDescription *  (* get_font_desc) (const GSheetModel *sheet_model,
-                                                  glong row, glong column);
-
-  const GtkSheetCellBorder *  (* get_cell_border) (const GSheetModel *sheet_model,
-                                                  glong row, glong column);
+  /* column related metadata */
 
+  gchar * (*get_column_title) (const GSheetModel *, gint col);
+  gchar * (*get_column_subtitle) (const GSheetModel *, gint col);
+  gboolean (*get_column_sensitivity) (const GSheetModel *, gint col);
+  GtkJustification (*get_column_justification) (const GSheetModel *mode, gint col);
+  const GtkSheetButton * (* get_button) (const GSheetModel *model, gint col);
 
   glong (*get_column_count) (const GSheetModel *model);
 
-  glong (*get_row_count) (const GSheetModel *model);
 
+  /* row related metadata */
+  gchar * (*get_row_title) (const GSheetModel *, gint row);
+  gchar * (*get_row_subtitle) (const GSheetModel *, gint row);
+  glong (*get_row_count) (const GSheetModel *model);
+  gboolean (*get_row_sensitivity) (const GSheetModel *, gint row);
 };
 
 
@@ -134,63 +140,86 @@ struct _GSheetModelIface
 GType              g_sheet_model_get_type   (void) G_GNUC_CONST;
 
 
-inline  gchar * g_sheet_model_get_string (const GSheetModel *sheet_model,
-                                              glong row, glong column);
+gchar * g_sheet_model_get_string (const GSheetModel *sheet_model,
+                                 glong row, glong column);
+
+gboolean  g_sheet_model_set_string (GSheetModel *sheet_model,
+                                   const gchar *s,
+                                   glong row, glong column);
+
+gboolean g_sheet_model_datum_clear    (GSheetModel *sheet_model,
+                                      glong row, glong column);
+
+
+void g_sheet_model_range_changed (GSheetModel *sheet_model,
+                                 glong row0, glong col0,
+                                 glong rowi, glong coli);
+
+void g_sheet_model_rows_deleted (GSheetModel *sheet_model,
+                                glong row, glong n_rows);
+
+void g_sheet_model_rows_inserted (GSheetModel *sheet_model,
+                                 glong row, glong n_rows);
+
+void g_sheet_model_columns_inserted (GSheetModel *sheet_model,
+                                    glong column, glong n_columns);
+
+void g_sheet_model_columns_deleted (GSheetModel *sheet_model,
+                                   glong column, glong n_columns);
+
+
+gboolean g_sheet_model_is_editable (const GSheetModel *model,
+                                   glong row, glong column);
+
+gboolean g_sheet_model_is_visible
+ (const GSheetModel *model, glong row, glong column);
 
-inline gboolean  g_sheet_model_set_string (GSheetModel *sheet_model,
-                                     const gchar *s,
-                                     glong row, glong column);
 
-inline gboolean g_sheet_model_datum_clear    (GSheetModel *sheet_model,
                                       glong row, glong column);
+GdkColor *g_sheet_model_get_foreground
(const GSheetModel *model, glong row, glong column);
 
+GdkColor *g_sheet_model_get_background
+ (const GSheetModel *model, glong row, glong column);
 
-inline void g_sheet_model_range_changed (GSheetModel *sheet_model,
-                                   glong row0, glong col0,
-                                   glong rowi, glong coli);
+const GtkJustification *g_sheet_model_get_justification
+ (const GSheetModel *model, glong row, glong column);
 
-inline void g_sheet_model_rows_deleted (GSheetModel *sheet_model,
                                 glong row, glong n_rows);
+const GtkSheetCellBorder * g_sheet_model_get_cell_border
(const GSheetModel *model, glong row, glong column);
 
-inline void g_sheet_model_rows_inserted (GSheetModel *sheet_model,
-                                   glong row, glong n_rows);
+gboolean g_sheet_model_free_strings (const GSheetModel *sheet_model);
 
-inline void g_sheet_model_columns_inserted (GSheetModel *sheet_model,
-                                           glong column, glong n_columns);
+glong g_sheet_model_get_column_count (const GSheetModel *sheet_model);
 
-inline void g_sheet_model_columns_deleted (GSheetModel *sheet_model,
-                                          glong column, glong n_columns);
+gint g_sheet_model_get_row_count (const GSheetModel *sheet_model);
 
+\f
 
-inline gboolean g_sheet_model_is_editable (const GSheetModel *model,
-                                     glong row, glong column);
+gboolean g_sheet_model_get_column_sensitivity (const GSheetModel *model,
+                                              gint col);
 
-inline gboolean g_sheet_model_is_visible
-                   (const GSheetModel *model, glong row, glong column);
+gchar * g_sheet_model_get_column_subtitle (const GSheetModel *model,
+                                           gint col);
 
+GtkSheetButton * g_sheet_model_get_column_button (const GSheetModel *, gint);
 
-inline const GdkColor *g_sheet_model_get_foreground
-                   (const GSheetModel *model, glong row, glong column);
+GtkJustification g_sheet_model_get_column_justification (const GSheetModel *,
+                                                        gint);
 
-inline const GdkColor *g_sheet_model_get_background
-                   (const GSheetModel *model, glong row, glong column);
+\f
 
+gboolean g_sheet_model_get_row_sensitivity (const GSheetModel *model,
+                                           gint row);
 
-inline const GtkJustification *g_sheet_model_get_justification
-                   (const GSheetModel *model, glong row, glong column);
 
+gchar * g_sheet_model_get_row_subtitle (const GSheetModel *model,
+                                           gint row);
 
-inline const PangoFontDescription *g_sheet_model_get_font_desc
-                   (const GSheetModel *model, glong row, glong column);
 
-inline const GtkSheetCellBorder * g_sheet_model_get_cell_border
-                   (const GSheetModel *model, glong row, glong column);
+GtkSheetButton * g_sheet_model_get_row_button (const GSheetModel *, gint);
 
-inline  gboolean g_sheet_model_free_strings (const GSheetModel *sheet_model);
 
-inline glong g_sheet_model_get_column_count (const GSheetModel *sheet_model);
 
-inline  gint g_sheet_model_get_row_count (const GSheetModel *sheet_model);
 
 G_END_DECLS
 
diff --git a/lib/gtksheet/gtkextra-marshal.c b/lib/gtksheet/gtkextra-marshal.c
deleted file mode 100644 (file)
index f8c8448..0000000
+++ /dev/null
@@ -1,893 +0,0 @@
-#include <config.h>
-
-#include       <glib-object.h>
-
-
-#ifdef G_ENABLE_DEBUG
-#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
-#define g_marshal_value_peek_char(v)     g_value_get_char (v)
-#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
-#define g_marshal_value_peek_int(v)      g_value_get_int (v)
-#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
-#define g_marshal_value_peek_long(v)     g_value_get_long (v)
-#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
-#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
-#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
-#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
-#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
-#define g_marshal_value_peek_float(v)    g_value_get_float (v)
-#define g_marshal_value_peek_double(v)   g_value_get_double (v)
-#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
-#define g_marshal_value_peek_param(v)    g_value_get_param (v)
-#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
-#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
-#define g_marshal_value_peek_object(v)   g_value_get_object (v)
-#else /* !G_ENABLE_DEBUG */
-/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
- *          Do not access GValues directly in your code. Instead, use the
- *          g_value_get_*() functions
- */
-#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
-#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
-#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
-#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
-#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
-#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
-#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
-#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
-#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
-#define g_marshal_value_peek_enum(v)     (v)->data[0].v_int
-#define g_marshal_value_peek_flags(v)    (v)->data[0].v_uint
-#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
-#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
-#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
-#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
-#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
-#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
-#endif /* !G_ENABLE_DEBUG */
-
-
-/* BOOL:INT,INT,POINTER,POINTER (gtkextra-marshal.list:1) */
-void
-gtkextra_BOOLEAN__INT_INT_POINTER_POINTER (GClosure     *closure,
-                                           GValue       *return_value,
-                                           guint         n_param_values,
-                                           const GValue *param_values,
-                                           gpointer      invocation_hint,
-                                           gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__INT_INT_POINTER_POINTER) (gpointer     data1,
-                                                                     gint         arg_1,
-                                                                     gint         arg_2,
-                                                                     gpointer     arg_3,
-                                                                     gpointer     arg_4,
-                                                                     gpointer     data2);
-  register GMarshalFunc_BOOLEAN__INT_INT_POINTER_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 5);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__INT_INT_POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_int (param_values + 1),
-                       g_marshal_value_peek_int (param_values + 2),
-                       g_marshal_value_peek_pointer (param_values + 3),
-                       g_marshal_value_peek_pointer (param_values + 4),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* BOOL:BOXED,POINTER (gtkextra-marshal.list:2) */
-void
-gtkextra_BOOLEAN__BOXED_POINTER (GClosure     *closure,
-                                 GValue       *return_value,
-                                 guint         n_param_values,
-                                 const GValue *param_values,
-                                 gpointer      invocation_hint,
-                                 gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__BOXED_POINTER) (gpointer     data1,
-                                                           gpointer     arg_1,
-                                                           gpointer     arg_2,
-                                                           gpointer     data2);
-  register GMarshalFunc_BOOLEAN__BOXED_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__BOXED_POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_boxed (param_values + 1),
-                       g_marshal_value_peek_pointer (param_values + 2),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* BOOL:BOXED,STRING (gtkextra-marshal.list:3) */
-void
-gtkextra_BOOLEAN__BOXED_STRING (GClosure     *closure,
-                                GValue       *return_value,
-                                guint         n_param_values,
-                                const GValue *param_values,
-                                gpointer      invocation_hint,
-                                gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__BOXED_STRING) (gpointer     data1,
-                                                          gpointer     arg_1,
-                                                          gpointer     arg_2,
-                                                          gpointer     data2);
-  register GMarshalFunc_BOOLEAN__BOXED_STRING callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__BOXED_STRING) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_boxed (param_values + 1),
-                       g_marshal_value_peek_string (param_values + 2),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* BOOL:BOXED,BOXED (gtkextra-marshal.list:4) */
-void
-gtkextra_BOOLEAN__BOXED_BOXED (GClosure     *closure,
-                               GValue       *return_value,
-                               guint         n_param_values,
-                               const GValue *param_values,
-                               gpointer      invocation_hint,
-                               gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__BOXED_BOXED) (gpointer     data1,
-                                                         gpointer     arg_1,
-                                                         gpointer     arg_2,
-                                                         gpointer     data2);
-  register GMarshalFunc_BOOLEAN__BOXED_BOXED callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__BOXED_BOXED) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_boxed (param_values + 1),
-                       g_marshal_value_peek_boxed (param_values + 2),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* BOOL:BOXED,DOUBLE,DOUBLE (gtkextra-marshal.list:5) */
-void
-gtkextra_BOOLEAN__BOXED_DOUBLE_DOUBLE (GClosure     *closure,
-                                       GValue       *return_value,
-                                       guint         n_param_values,
-                                       const GValue *param_values,
-                                       gpointer      invocation_hint,
-                                       gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__BOXED_DOUBLE_DOUBLE) (gpointer     data1,
-                                                                 gpointer     arg_1,
-                                                                 gdouble      arg_2,
-                                                                 gdouble      arg_3,
-                                                                 gpointer     data2);
-  register GMarshalFunc_BOOLEAN__BOXED_DOUBLE_DOUBLE callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 4);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__BOXED_DOUBLE_DOUBLE) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_boxed (param_values + 1),
-                       g_marshal_value_peek_double (param_values + 2),
-                       g_marshal_value_peek_double (param_values + 3),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* BOOL:POINTER,POINTER (gtkextra-marshal.list:6) */
-void
-gtkextra_BOOLEAN__POINTER_POINTER (GClosure     *closure,
-                                   GValue       *return_value,
-                                   guint         n_param_values,
-                                   const GValue *param_values,
-                                   gpointer      invocation_hint,
-                                   gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER) (gpointer     data1,
-                                                             gpointer     arg_1,
-                                                             gpointer     arg_2,
-                                                             gpointer     data2);
-  register GMarshalFunc_BOOLEAN__POINTER_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_pointer (param_values + 1),
-                       g_marshal_value_peek_pointer (param_values + 2),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* BOOL:POINTER,BOXED (gtkextra-marshal.list:7) */
-void
-gtkextra_BOOLEAN__POINTER_BOXED (GClosure     *closure,
-                                 GValue       *return_value,
-                                 guint         n_param_values,
-                                 const GValue *param_values,
-                                 gpointer      invocation_hint,
-                                 gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_BOXED) (gpointer     data1,
-                                                           gpointer     arg_1,
-                                                           gpointer     arg_2,
-                                                           gpointer     data2);
-  register GMarshalFunc_BOOLEAN__POINTER_BOXED callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__POINTER_BOXED) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_pointer (param_values + 1),
-                       g_marshal_value_peek_boxed (param_values + 2),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* BOOL:POINTER,STRING (gtkextra-marshal.list:8) */
-void
-gtkextra_BOOLEAN__POINTER_STRING (GClosure     *closure,
-                                  GValue       *return_value,
-                                  guint         n_param_values,
-                                  const GValue *param_values,
-                                  gpointer      invocation_hint,
-                                  gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_STRING) (gpointer     data1,
-                                                            gpointer     arg_1,
-                                                            gpointer     arg_2,
-                                                            gpointer     data2);
-  register GMarshalFunc_BOOLEAN__POINTER_STRING callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__POINTER_STRING) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_pointer (param_values + 1),
-                       g_marshal_value_peek_string (param_values + 2),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* BOOL:POINTER (gtkextra-marshal.list:9) */
-void
-gtkextra_BOOLEAN__POINTER (GClosure     *closure,
-                           GValue       *return_value,
-                           guint         n_param_values,
-                           const GValue *param_values,
-                           gpointer      invocation_hint,
-                           gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER) (gpointer     data1,
-                                                     gpointer     arg_1,
-                                                     gpointer     data2);
-  register GMarshalFunc_BOOLEAN__POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 2);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_pointer (param_values + 1),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* BOOL:BOXED (gtkextra-marshal.list:10) */
-void
-gtkextra_BOOLEAN__BOXED (GClosure     *closure,
-                         GValue       *return_value,
-                         guint         n_param_values,
-                         const GValue *param_values,
-                         gpointer      invocation_hint,
-                         gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__BOXED) (gpointer     data1,
-                                                   gpointer     arg_1,
-                                                   gpointer     data2);
-  register GMarshalFunc_BOOLEAN__BOXED callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 2);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__BOXED) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_boxed (param_values + 1),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* BOOL:INT,INT (gtkextra-marshal.list:11) */
-void
-gtkextra_BOOLEAN__INT_INT (GClosure     *closure,
-                           GValue       *return_value,
-                           guint         n_param_values,
-                           const GValue *param_values,
-                           gpointer      invocation_hint,
-                           gpointer      marshal_data)
-{
-  typedef gboolean (*GMarshalFunc_BOOLEAN__INT_INT) (gpointer     data1,
-                                                     gint         arg_1,
-                                                     gint         arg_2,
-                                                     gpointer     data2);
-  register GMarshalFunc_BOOLEAN__INT_INT callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-  gboolean v_return;
-
-  g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_BOOLEAN__INT_INT) (marshal_data ? marshal_data : cc->callback);
-
-  v_return = callback (data1,
-                       g_marshal_value_peek_int (param_values + 1),
-                       g_marshal_value_peek_int (param_values + 2),
-                       data2);
-
-  g_value_set_boolean (return_value, v_return);
-}
-
-/* VOID:INT (gtkextra-marshal.list:12) */
-
-/* VOID:INT,STRING (gtkextra-marshal.list:13) */
-void
-gtkextra_VOID__INT_STRING (GClosure     *closure,
-                           GValue       *return_value,
-                           guint         n_param_values,
-                           const GValue *param_values,
-                           gpointer      invocation_hint,
-                           gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__INT_STRING) (gpointer     data1,
-                                                 gint         arg_1,
-                                                 gpointer     arg_2,
-                                                 gpointer     data2);
-  register GMarshalFunc_VOID__INT_STRING callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__INT_STRING) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_int (param_values + 1),
-            g_marshal_value_peek_string (param_values + 2),
-            data2);
-}
-
-/* VOID:BOXED (gtkextra-marshal.list:14) */
-
-/* VOID:VOID (gtkextra-marshal.list:15) */
-
-/* VOID:BOOL (gtkextra-marshal.list:16) */
-
-/* VOID:POINTER (gtkextra-marshal.list:17) */
-
-/* VOID:INT,INT (gtkextra-marshal.list:18) */
-void
-gtkextra_VOID__INT_INT (GClosure     *closure,
-                        GValue       *return_value,
-                        guint         n_param_values,
-                        const GValue *param_values,
-                        gpointer      invocation_hint,
-                        gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__INT_INT) (gpointer     data1,
-                                              gint         arg_1,
-                                              gint         arg_2,
-                                              gpointer     data2);
-  register GMarshalFunc_VOID__INT_INT callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__INT_INT) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_int (param_values + 1),
-            g_marshal_value_peek_int (param_values + 2),
-            data2);
-}
-
-
-/* VOID:INT,INT,INT,INT (Added by JMD 1/1/2006) */
-void
-gtkextra_VOID__INT_INT_INT_INT (GClosure     *closure,
-                        GValue       *return_value,
-                        guint         n_param_values,
-                        const GValue *param_values,
-                        gpointer      invocation_hint,
-                        gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__INT_INT_INT_INT) (gpointer     data1,
-                                              gint         arg_1,
-                                              gint         arg_2,
-                                              gint         arg_3,
-                                              gint         arg_4,
-                                              gpointer     data2);
-  register GMarshalFunc_VOID__INT_INT_INT_INT callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 5);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__INT_INT_INT_INT) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_int (param_values + 1),
-            g_marshal_value_peek_int (param_values + 2),
-            g_marshal_value_peek_int (param_values + 3),
-            g_marshal_value_peek_int (param_values + 4),
-            data2);
-}
-
-
-/* VOID:INT,POINTER (gtkextra-marshal.list:19) */
-void
-gtkextra_VOID__INT_POINTER (GClosure     *closure,
-                            GValue       *return_value,
-                            guint         n_param_values,
-                            const GValue *param_values,
-                            gpointer      invocation_hint,
-                            gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__INT_POINTER) (gpointer     data1,
-                                                  gint         arg_1,
-                                                  gpointer     arg_2,
-                                                  gpointer     data2);
-  register GMarshalFunc_VOID__INT_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__INT_POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_int (param_values + 1),
-            g_marshal_value_peek_pointer (param_values + 2),
-            data2);
-}
-
-/* VOID:INT,BOXED (gtkextra-marshal.list:20) */
-void
-gtkextra_VOID__INT_BOXED (GClosure     *closure,
-                          GValue       *return_value,
-                          guint         n_param_values,
-                          const GValue *param_values,
-                          gpointer      invocation_hint,
-                          gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__INT_BOXED) (gpointer     data1,
-                                                gint         arg_1,
-                                                gpointer     arg_2,
-                                                gpointer     data2);
-  register GMarshalFunc_VOID__INT_BOXED callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__INT_BOXED) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_int (param_values + 1),
-            g_marshal_value_peek_boxed (param_values + 2),
-            data2);
-}
-
-/* VOID:POINTER,POINTER (gtkextra-marshal.list:21) */
-void
-gtkextra_VOID__POINTER_POINTER (GClosure     *closure,
-                                GValue       *return_value,
-                                guint         n_param_values,
-                                const GValue *param_values,
-                                gpointer      invocation_hint,
-                                gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__POINTER_POINTER) (gpointer     data1,
-                                                      gpointer     arg_1,
-                                                      gpointer     arg_2,
-                                                      gpointer     data2);
-  register GMarshalFunc_VOID__POINTER_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_pointer (param_values + 1),
-            g_marshal_value_peek_pointer (param_values + 2),
-            data2);
-}
-
-/* VOID:BOXED,POINTER (gtkextra-marshal.list:22) */
-void
-gtkextra_VOID__BOXED_POINTER (GClosure     *closure,
-                              GValue       *return_value,
-                              guint         n_param_values,
-                              const GValue *param_values,
-                              gpointer      invocation_hint,
-                              gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__BOXED_POINTER) (gpointer     data1,
-                                                    gpointer     arg_1,
-                                                    gpointer     arg_2,
-                                                    gpointer     data2);
-  register GMarshalFunc_VOID__BOXED_POINTER callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__BOXED_POINTER) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_boxed (param_values + 1),
-            g_marshal_value_peek_pointer (param_values + 2),
-            data2);
-}
-
-/* VOID:BOXED,BOXED (gtkextra-marshal.list:23) */
-void
-gtkextra_VOID__BOXED_BOXED (GClosure     *closure,
-                            GValue       *return_value,
-                            guint         n_param_values,
-                            const GValue *param_values,
-                            gpointer      invocation_hint,
-                            gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__BOXED_BOXED) (gpointer     data1,
-                                                  gpointer     arg_1,
-                                                  gpointer     arg_2,
-                                                  gpointer     data2);
-  register GMarshalFunc_VOID__BOXED_BOXED callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__BOXED_BOXED) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_boxed (param_values + 1),
-            g_marshal_value_peek_boxed (param_values + 2),
-            data2);
-}
-
-/* VOID:OBJECT,OBJECT (gtkextra-marshal.list:24) */
-void
-gtkextra_VOID__OBJECT_OBJECT (GClosure     *closure,
-                              GValue       *return_value,
-                              guint         n_param_values,
-                              const GValue *param_values,
-                              gpointer      invocation_hint,
-                              gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer     data1,
-                                                    gpointer     arg_1,
-                                                    gpointer     arg_2,
-                                                    gpointer     data2);
-  register GMarshalFunc_VOID__OBJECT_OBJECT callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 3);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_object (param_values + 1),
-            g_marshal_value_peek_object (param_values + 2),
-            data2);
-}
-
-/* VOID:DOUBLE,DOUBLE,DOUBLE,DOUBLE (gtkextra-marshal.list:25) */
-void
-gtkextra_VOID__DOUBLE_DOUBLE_DOUBLE_DOUBLE (GClosure     *closure,
-                                            GValue       *return_value,
-                                            guint         n_param_values,
-                                            const GValue *param_values,
-                                            gpointer      invocation_hint,
-                                            gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__DOUBLE_DOUBLE_DOUBLE_DOUBLE) (gpointer     data1,
-                                                                  gdouble      arg_1,
-                                                                  gdouble      arg_2,
-                                                                  gdouble      arg_3,
-                                                                  gdouble      arg_4,
-                                                                  gpointer     data2);
-  register GMarshalFunc_VOID__DOUBLE_DOUBLE_DOUBLE_DOUBLE callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 5);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__DOUBLE_DOUBLE_DOUBLE_DOUBLE) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_double (param_values + 1),
-            g_marshal_value_peek_double (param_values + 2),
-            g_marshal_value_peek_double (param_values + 3),
-            g_marshal_value_peek_double (param_values + 4),
-            data2);
-}
-
diff --git a/lib/gtksheet/gtkextra-marshal.h b/lib/gtksheet/gtkextra-marshal.h
deleted file mode 100644 (file)
index ea9ed5e..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-
-#ifndef __gtkextra_MARSHAL_H__
-#define __gtkextra_MARSHAL_H__
-
-#include       <glib-object.h>
-
-G_BEGIN_DECLS
-
-/* BOOL:INT,INT,POINTER,POINTER (gtkextra-marshal.list:1) */
-extern void gtkextra_BOOLEAN__INT_INT_POINTER_POINTER (GClosure     *closure,
-                                                       GValue       *return_value,
-                                                       guint         n_param_values,
-                                                       const GValue *param_values,
-                                                       gpointer      invocation_hint,
-                                                       gpointer      marshal_data);
-#define gtkextra_BOOL__INT_INT_POINTER_POINTER gtkextra_BOOLEAN__INT_INT_POINTER_POINTER
-
-/* BOOL:BOXED,POINTER (gtkextra-marshal.list:2) */
-extern void gtkextra_BOOLEAN__BOXED_POINTER (GClosure     *closure,
-                                             GValue       *return_value,
-                                             guint         n_param_values,
-                                             const GValue *param_values,
-                                             gpointer      invocation_hint,
-                                             gpointer      marshal_data);
-#define gtkextra_BOOL__BOXED_POINTER   gtkextra_BOOLEAN__BOXED_POINTER
-
-/* BOOL:BOXED,STRING (gtkextra-marshal.list:3) */
-extern void gtkextra_BOOLEAN__BOXED_STRING (GClosure     *closure,
-                                            GValue       *return_value,
-                                            guint         n_param_values,
-                                            const GValue *param_values,
-                                            gpointer      invocation_hint,
-                                            gpointer      marshal_data);
-#define gtkextra_BOOL__BOXED_STRING    gtkextra_BOOLEAN__BOXED_STRING
-
-/* BOOL:BOXED,BOXED (gtkextra-marshal.list:4) */
-extern void gtkextra_BOOLEAN__BOXED_BOXED (GClosure     *closure,
-                                           GValue       *return_value,
-                                           guint         n_param_values,
-                                           const GValue *param_values,
-                                           gpointer      invocation_hint,
-                                           gpointer      marshal_data);
-#define gtkextra_BOOL__BOXED_BOXED     gtkextra_BOOLEAN__BOXED_BOXED
-
-/* BOOL:BOXED,DOUBLE,DOUBLE (gtkextra-marshal.list:5) */
-extern void gtkextra_BOOLEAN__BOXED_DOUBLE_DOUBLE (GClosure     *closure,
-                                                   GValue       *return_value,
-                                                   guint         n_param_values,
-                                                   const GValue *param_values,
-                                                   gpointer      invocation_hint,
-                                                   gpointer      marshal_data);
-#define gtkextra_BOOL__BOXED_DOUBLE_DOUBLE     gtkextra_BOOLEAN__BOXED_DOUBLE_DOUBLE
-
-/* BOOL:POINTER,POINTER (gtkextra-marshal.list:6) */
-extern void gtkextra_BOOLEAN__POINTER_POINTER (GClosure     *closure,
-                                               GValue       *return_value,
-                                               guint         n_param_values,
-                                               const GValue *param_values,
-                                               gpointer      invocation_hint,
-                                               gpointer      marshal_data);
-#define gtkextra_BOOL__POINTER_POINTER gtkextra_BOOLEAN__POINTER_POINTER
-
-/* BOOL:POINTER,BOXED (gtkextra-marshal.list:7) */
-extern void gtkextra_BOOLEAN__POINTER_BOXED (GClosure     *closure,
-                                             GValue       *return_value,
-                                             guint         n_param_values,
-                                             const GValue *param_values,
-                                             gpointer      invocation_hint,
-                                             gpointer      marshal_data);
-#define gtkextra_BOOL__POINTER_BOXED   gtkextra_BOOLEAN__POINTER_BOXED
-
-/* BOOL:POINTER,STRING (gtkextra-marshal.list:8) */
-extern void gtkextra_BOOLEAN__POINTER_STRING (GClosure     *closure,
-                                              GValue       *return_value,
-                                              guint         n_param_values,
-                                              const GValue *param_values,
-                                              gpointer      invocation_hint,
-                                              gpointer      marshal_data);
-#define gtkextra_BOOL__POINTER_STRING  gtkextra_BOOLEAN__POINTER_STRING
-
-/* BOOL:POINTER (gtkextra-marshal.list:9) */
-extern void gtkextra_BOOLEAN__POINTER (GClosure     *closure,
-                                       GValue       *return_value,
-                                       guint         n_param_values,
-                                       const GValue *param_values,
-                                       gpointer      invocation_hint,
-                                       gpointer      marshal_data);
-#define gtkextra_BOOL__POINTER gtkextra_BOOLEAN__POINTER
-
-/* BOOL:BOXED (gtkextra-marshal.list:10) */
-extern void gtkextra_BOOLEAN__BOXED (GClosure     *closure,
-                                     GValue       *return_value,
-                                     guint         n_param_values,
-                                     const GValue *param_values,
-                                     gpointer      invocation_hint,
-                                     gpointer      marshal_data);
-#define gtkextra_BOOL__BOXED   gtkextra_BOOLEAN__BOXED
-
-/* BOOL:INT,INT (gtkextra-marshal.list:11) */
-extern void gtkextra_BOOLEAN__INT_INT (GClosure     *closure,
-                                       GValue       *return_value,
-                                       guint         n_param_values,
-                                       const GValue *param_values,
-                                       gpointer      invocation_hint,
-                                       gpointer      marshal_data);
-#define gtkextra_BOOL__INT_INT gtkextra_BOOLEAN__INT_INT
-
-/* VOID:INT (gtkextra-marshal.list:12) */
-#define gtkextra_VOID__INT     g_cclosure_marshal_VOID__INT
-
-/* VOID:INT,STRING (gtkextra-marshal.list:13) */
-extern void gtkextra_VOID__INT_STRING (GClosure     *closure,
-                                       GValue       *return_value,
-                                       guint         n_param_values,
-                                       const GValue *param_values,
-                                       gpointer      invocation_hint,
-                                       gpointer      marshal_data);
-
-/* VOID:BOXED (gtkextra-marshal.list:14) */
-#define gtkextra_VOID__BOXED   g_cclosure_marshal_VOID__BOXED
-
-/* VOID:VOID (gtkextra-marshal.list:15) */
-#define gtkextra_VOID__VOID    g_cclosure_marshal_VOID__VOID
-
-/* VOID:BOOL (gtkextra-marshal.list:16) */
-#define gtkextra_VOID__BOOLEAN g_cclosure_marshal_VOID__BOOLEAN
-#define gtkextra_VOID__BOOL    gtkextra_VOID__BOOLEAN
-
-/* VOID:POINTER (gtkextra-marshal.list:17) */
-#define gtkextra_VOID__POINTER g_cclosure_marshal_VOID__POINTER
-
-/* VOID:INT,INT (gtkextra-marshal.list:18) */
-extern void gtkextra_VOID__INT_INT (GClosure     *closure,
-                                    GValue       *return_value,
-                                    guint         n_param_values,
-                                    const GValue *param_values,
-                                    gpointer      invocation_hint,
-                                    gpointer      marshal_data);
-
-/* VOID:INT,INT,INT,INT (Added by JMD 1/1/26) */
-extern void gtkextra_VOID__INT_INT_INT_INT (GClosure     *closure,
-                                           GValue       *return_value,
-                                           guint         n_param_values,
-                                           const GValue *param_values,
-                                           gpointer      invocation_hint,
-                                           gpointer      marshal_data);
-
-
-/* VOID:INT,POINTER (gtkextra-marshal.list:19) */
-extern void gtkextra_VOID__INT_POINTER (GClosure     *closure,
-                                        GValue       *return_value,
-                                        guint         n_param_values,
-                                        const GValue *param_values,
-                                        gpointer      invocation_hint,
-                                        gpointer      marshal_data);
-
-/* VOID:INT,BOXED (gtkextra-marshal.list:20) */
-extern void gtkextra_VOID__INT_BOXED (GClosure     *closure,
-                                      GValue       *return_value,
-                                      guint         n_param_values,
-                                      const GValue *param_values,
-                                      gpointer      invocation_hint,
-                                      gpointer      marshal_data);
-
-/* VOID:POINTER,POINTER (gtkextra-marshal.list:21) */
-extern void gtkextra_VOID__POINTER_POINTER (GClosure     *closure,
-                                            GValue       *return_value,
-                                            guint         n_param_values,
-                                            const GValue *param_values,
-                                            gpointer      invocation_hint,
-                                            gpointer      marshal_data);
-
-/* VOID:BOXED,POINTER (gtkextra-marshal.list:22) */
-extern void gtkextra_VOID__BOXED_POINTER (GClosure     *closure,
-                                          GValue       *return_value,
-                                          guint         n_param_values,
-                                          const GValue *param_values,
-                                          gpointer      invocation_hint,
-                                          gpointer      marshal_data);
-
-/* VOID:BOXED,BOXED (gtkextra-marshal.list:23) */
-extern void gtkextra_VOID__BOXED_BOXED (GClosure     *closure,
-                                        GValue       *return_value,
-                                        guint         n_param_values,
-                                        const GValue *param_values,
-                                        gpointer      invocation_hint,
-                                        gpointer      marshal_data);
-
-/* VOID:OBJECT,OBJECT (gtkextra-marshal.list:24) */
-extern void gtkextra_VOID__OBJECT_OBJECT (GClosure     *closure,
-                                          GValue       *return_value,
-                                          guint         n_param_values,
-                                          const GValue *param_values,
-                                          gpointer      invocation_hint,
-                                          gpointer      marshal_data);
-
-/* VOID:DOUBLE,DOUBLE,DOUBLE,DOUBLE (gtkextra-marshal.list:25) */
-extern void gtkextra_VOID__DOUBLE_DOUBLE_DOUBLE_DOUBLE (GClosure     *closure,
-                                                        GValue       *return_value,
-                                                        guint         n_param_values,
-                                                        const GValue *param_values,
-                                                        gpointer      invocation_hint,
-                                                        gpointer      marshal_data);
-
-G_END_DECLS
-
-#endif /* __gtkextra_MARSHAL_H__ */
-
index 0a5fb70fa1bd93897d8eefdc6f23db8bf2788c5f..7ea9b1714cc732cbec011571752a3c432d703093 100644 (file)
@@ -23,8 +23,8 @@
  */
 
 
-#ifndef __GTK_EXTRA_SHEET_H__
-#define __GTK_EXTRA_SHEET_H__
+#ifndef GTK_EXTRA_SHEET_H__
+#define GTK_EXTRA_SHEET_H__
 
 
 struct _GtkSheet ;
@@ -32,47 +32,30 @@ struct _GtkSheet ;
 typedef struct _GtkSheet GtkSheet;
 
 
-struct _GtkSheetChild
-{
-  GtkWidget *widget;
-  gint x,y ;
-  gboolean attached_to_cell;
-  gboolean floating;
-  gint row, col;
-  guint16 xpadding;
-  guint16 ypadding;
-  gboolean xexpand;
-  gboolean yexpand;
-  gboolean xshrink;
-  gboolean yshrink;
-  gboolean xfill;
-  gboolean yfill;
-};
-
-typedef struct _GtkSheetChild GtkSheetChild;
-
-
-
 struct _GtkSheetButton
 {
   GtkStateType state;
   gchar *label;
 
   gboolean label_visible;
-  GtkSheetChild *child;
 
   GtkJustification justification;
 };
 
-typedef struct _GtkSheetButton GtkSheetButton;
-
+struct _GtkSheetCell
+{
+  gint row;
+  gint col;
+};
 
+typedef struct _GtkSheetButton GtkSheetButton;
+typedef struct _GtkSheetCell GtkSheetCell;
 
-GtkSheetButton * gtk_sheet_button_new(void);
+GtkSheetButton * gtk_sheet_button_new (void);
 
-inline void gtk_sheet_button_free(GtkSheetButton *button);
+void gtk_sheet_button_free (GtkSheetButton *button);
 
 
-#endif /* __GTK_EXTRA_SHEET_H__ */
+#endif /* GTK_EXTRA_SHEET_H__ */
 
 
diff --git a/lib/gtksheet/gtkextra.c b/lib/gtksheet/gtkextra.c
deleted file mode 100644 (file)
index 4d79268..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/* gtkextra
- * Copyright 1999-2001 Adrian E. Feiguin <feiguin@ifir.edu.ar>
- *
- * 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 <string.h>
-#include <gtk/gtk.h>
-#include "gtkextrafeatures.h"
-#include <gobject/gvaluecollector.h>
-
-const guint gtkextra_major_version = GTKEXTRA_MAJOR_VERSION;
-const guint gtkextra_minor_version = GTKEXTRA_MINOR_VERSION;
-const guint gtkextra_micro_version = GTKEXTRA_MICRO_VERSION;
-const guint gtkextra_binary_age = GTKEXTRA_BINARY_AGE;
-const guint gtkextra_interface_age = GTKEXTRA_INTERFACE_AGE;
-
-gchar *
-gtkextra_check_version (guint required_major,
-                        guint required_minor,
-                        guint required_micro)
-{
-  if (required_major > GTKEXTRA_MAJOR_VERSION)
-    return "GtkExtra version too old (major mismatch)";
-  if (required_major < GTKEXTRA_MAJOR_VERSION)
-    return "GtkExtra version too new (major mismatch)";
-  if (required_minor > GTKEXTRA_MINOR_VERSION)
-    return "GtkExtra version too old (minor mismatch)";
-  if (required_minor < GTKEXTRA_MINOR_VERSION)
-    return "GtkExtra version too new (minor mismatch)";
-  if (required_micro < GTKEXTRA_MICRO_VERSION - GTKEXTRA_BINARY_AGE)
-    return "GtkExtra version too new (micro mismatch)";
-  if (required_micro > GTKEXTRA_MICRO_VERSION)
-    return "GtkExtra version too old (micro mismatch)";
-  return NULL;
-}
-
-/*
-void
-_gtkextra_signal_test(GtkObject *object, guint signal_id, gint arg1, gint arg2, gboolean *default_ret)
-{
-  gboolean result;
-  GValue ret = { 0, };
-  GValue instance_and_param[3] = { { 0, }, {0, }, {0, } };
-
-  g_value_init(instance_and_param + 0, GTK_OBJECT_TYPE(object));
-  g_value_set_instance(instance_and_param + 0, G_OBJECT(object));
-
-  g_value_init(instance_and_param + 1, G_TYPE_INT);
-  g_value_set_int(instance_and_param + 1, arg1);
-
-  g_value_init(instance_and_param + 2, G_TYPE_INT);
-  g_value_set_int(instance_and_param + 2, arg2);
-
-  g_value_init(&ret, G_TYPE_BOOLEAN);
-  g_value_set_boolean(&ret, *default_ret);
-
-  g_signal_emitv(instance_and_param, signal_id, 0, &ret);
-  *default_ret = g_value_get_boolean(&ret);
-
-  g_value_unset(instance_and_param + 0);
-  g_value_unset(instance_and_param + 1);
-  g_value_unset(instance_and_param + 2);
-}
-*/
-
-void
-_gtkextra_signal_emit(GtkObject *object, guint signal_id, ...)
-{
-  gboolean *result;
-  GValue ret = { 0, };
-  GValue instance_and_params [10] = { {0, }, };
-  va_list var_args;
-  GSignalQuery query;
-  gchar *error;
-  int i;
-
-  va_start (var_args, signal_id);
-
-  g_value_init(instance_and_params + 0, GTK_OBJECT_TYPE(object));
-  g_value_set_instance (instance_and_params + 0, G_OBJECT(object));
-
-  g_signal_query(signal_id, &query);
-
-  for (i = 0; i < query.n_params; i++)
-    {
-      gboolean static_scope = query.param_types[i]&~G_SIGNAL_TYPE_STATIC_SCOPE;
-      g_value_init(instance_and_params + i + 1, query.param_types[i]);
-
-
-      G_VALUE_COLLECT (instance_and_params + i + 1,
-                       var_args,
-                       static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
-                       &error);
-
-      if (error)
-        {
-          g_warning ("%s: %s", G_STRLOC, error);
-          g_free (error);
-          while (i-- > 0)
-            g_value_unset (instance_and_params + i);
-
-          va_end (var_args);
-          return;
-        }
-
-
-    }
-
-  g_value_init(&ret, query.return_type);
-  result = va_arg(var_args,gboolean *);
-  g_value_set_boolean(&ret, *result);
-  g_signal_emitv(instance_and_params, signal_id, 0, &ret);
-  *result = g_value_get_boolean(&ret);
-  g_value_unset (&ret);
-
-  for (i = 0; i < query.n_params; i++)
-    g_value_unset (instance_and_params + 1 + i);
-  g_value_unset (instance_and_params + 0);
-
-  va_end (var_args);
-}
diff --git a/lib/gtksheet/gtkextrafeatures.h b/lib/gtksheet/gtkextrafeatures.h
deleted file mode 100644 (file)
index 8b526a8..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* gtkextra - set of widgets for gtk+
- * Copyright 1999-2001  Adrian E. Feiguin <feiguin@ifir.edu.ar>
- *
- * 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_EXTRA_FEATURES_H
-#define GTK_EXTRA_FEATURES_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-/* GtkExtra version.
- */
-
-#define GTKEXTRA_MAJOR_VERSION                 (2)
-#define GTKEXTRA_MINOR_VERSION                 (1)
-#define GTKEXTRA_MICRO_VERSION                 (1)
-#define GTKEXTRA_BINARY_AGE                    (0)
-#define GTKEXTRA_INTERFACE_AGE                 (0)
-#define GTKEXTRA_CHECK_VERSION(major,minor,micro)    \
-   (GTKEXTRA_MAJOR_VERSION > (major) || \
-    (GTKEXTRA_MAJOR_VERSION == (major) && GTKEXTRA_MINOR_VERSION > (minor)) || \
-    (GTKEXTRA_MAJOR_VERSION == (major) && GTKEXTRA_MINOR_VERSION == (minor) && \
-     GTKEXTRA_MICRO_VERSION >= (micro)))
-
-
-extern const guint gtkextra_major_version;
-extern const guint gtkextra_minor_version;
-extern const guint gtkextra_micro_version;
-extern const guint gtkextra_binary_age;
-extern const guint gtkextra_interface_age;
-gchar* gtkextra_check_version (guint required_major,
-                               guint required_minor,
-                               guint required_micro);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
-#endif /* GTK_EXTRA_FEATURES_H */
diff --git a/lib/gtksheet/gtkitementry.c b/lib/gtksheet/gtkitementry.c
deleted file mode 100644 (file)
index efc22e2..0000000
+++ /dev/null
@@ -1,2406 +0,0 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-#include <config.h>
-
-#include <string.h>
-
-#include <pango/pango.h>
-
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-#include "gtkitementry.h"
-
-#define MIN_ENTRY_WIDTH  150
-#define DRAW_TIMEOUT     20
-#define INNER_BORDER     0
-
-/* Initial size of buffer, in bytes */
-#define MIN_SIZE 16
-
-/* Maximum size of text buffer, in bytes */
-#define MAX_SIZE G_MAXUSHORT
-
-typedef enum {
-  CURSOR_STANDARD,
-  CURSOR_DND
-} CursorType;
-
-/* GObject, GtkObject methods
- */
-static void   gtk_item_entry_class_init           (GtkItemEntryClass        *klass);
-static void   gtk_item_entry_init                 (GtkItemEntry         *entry);
-static void   gtk_item_entry_editable_init (GtkEditableClass *iface);
-
-/* GtkWidget methods
- */
-static void   gtk_entry_realize              (GtkWidget        *widget);
-static void   gtk_entry_size_request         (GtkWidget        *widget,
-                                             GtkRequisition   *requisition);
-static void   gtk_entry_size_allocate        (GtkWidget        *widget,
-                                             GtkAllocation    *allocation);
-static void   gtk_entry_draw_frame           (GtkWidget        *widget);
-static gint   gtk_entry_expose               (GtkWidget        *widget,
-                                             GdkEventExpose   *event);
-static void   gtk_entry_grab_focus           (GtkWidget        *widget);
-static void   gtk_entry_style_set            (GtkWidget        *widget,
-                                             GtkStyle         *previous_style);
-static void   gtk_entry_direction_changed    (GtkWidget        *widget,
-                                             GtkTextDirection  previous_dir);
-static void   gtk_entry_state_changed        (GtkWidget        *widget,
-                                             GtkStateType      previous_state);
-
-/* GtkEditable method implementations
- */
-static void     gtk_entry_insert_text          (GtkEditable *editable,
-                                               const gchar *new_text,
-                                               gint         new_text_length,
-                                               gint        *position);
-static void     gtk_entry_delete_text          (GtkEditable *editable,
-                                               gint         start_pos,
-                                               gint         end_pos);
-
-static void     gtk_entry_real_set_position    (GtkEditable *editable,
-                                                gint         position);
-static gint     gtk_entry_get_position         (GtkEditable *editable);
-
-/* Default signal handlers
- */
-static void gtk_entry_real_insert_text   (GtkEditable     *editable,
-                                         const gchar     *new_text,
-                                         gint             new_text_length,
-                                         gint            *position);
-static void gtk_entry_real_delete_text   (GtkEditable     *editable,
-                                         gint             start_pos,
-                                         gint             end_pos);
-static void gtk_entry_move_cursor        (GtkEntry        *entry,
-                                         GtkMovementStep  step,
-                                         gint             count,
-                                         gboolean         extend_selection);
-static void gtk_entry_insert_at_cursor   (GtkEntry        *entry,
-                                         const gchar     *str);
-static void gtk_entry_delete_from_cursor (GtkEntry        *entry,
-                                         GtkDeleteType    type,
-                                         gint             count);
-
-/* IM Context Callbacks
- */
-static void     gtk_entry_commit_cb               (GtkIMContext *context,
-                                                   const gchar  *str,
-                                                   GtkEntry     *entry);
-static void     gtk_entry_preedit_changed_cb      (GtkIMContext *context,
-                                                   GtkEntry     *entry);
-static gboolean gtk_entry_retrieve_surrounding_cb (GtkIMContext *context,
-                                                   GtkEntry     *entry);
-static gboolean gtk_entry_delete_surrounding_cb   (GtkIMContext *context,
-                                                   gint          offset,
-                                                   gint          n_chars,
-                                                   GtkEntry     *entry);
-
-/* Internal routines
- */
-static void         gtk_entry_enter_text               (GtkEntry       *entry,
-                                                        const gchar    *str);
-static void         gtk_entry_set_positions            (GtkEntry       *entry,
-                                                        gint            current_pos,
-                                                        gint            selection_bound);
-static void         gtk_entry_draw_text                (GtkEntry       *entry);
-static void         gtk_entry_draw_cursor              (GtkEntry       *entry,
-                                                       CursorType      type);
-static PangoLayout *gtk_entry_ensure_layout            (GtkEntry       *entry,
-                                                        gboolean        include_preedit);
-static void         gtk_entry_queue_draw               (GtkEntry       *entry);
-static void         gtk_entry_reset_im_context         (GtkEntry       *entry);
-static void         gtk_entry_recompute                (GtkEntry       *entry);
-static void         gtk_entry_get_cursor_locations     (GtkEntry       *entry,
-                                                       CursorType      type,
-                                                       gint           *strong_x,
-                                                       gint           *weak_x);
-static void         gtk_entry_adjust_scroll            (GtkEntry       *entry);
-static gint         gtk_entry_move_visually            (GtkEntry       *editable,
-                                                       gint            start,
-                                                       gint            count);
-static gint         gtk_entry_move_logically           (GtkEntry       *entry,
-                                                       gint            start,
-                                                       gint            count);
-static gint         gtk_entry_move_forward_word        (GtkEntry       *entry,
-                                                       gint            start);
-static gint         gtk_entry_move_backward_word       (GtkEntry       *entry,
-                                                       gint            start);
-static void         gtk_entry_delete_whitespace        (GtkEntry       *entry);
-static char *       gtk_entry_get_public_chars         (GtkEntry       *entry,
-                                                       gint            start,
-                                                       gint            end);
-static void         gtk_entry_update_primary_selection (GtkEntry       *entry);
-static void         gtk_entry_state_changed            (GtkWidget      *widget,
-                                                       GtkStateType    previous_state);
-static void         gtk_entry_check_cursor_blink       (GtkEntry       *entry);
-static void         gtk_entry_pend_cursor_blink        (GtkEntry       *entry);
-static void         get_text_area_size                 (GtkEntry       *entry,
-                                                       gint           *x,
-                                                       gint           *y,
-                                                       gint           *width,
-                                                       gint           *height);
-static void         get_widget_window_size             (GtkEntry       *entry,
-                                                       gint           *x,
-                                                       gint           *y,
-                                                       gint           *width,
-                                                       gint           *height);
-
-static GtkEntryClass *parent_class = NULL;
-
-GtkType
-gtk_item_entry_get_type (void)
-{
-  static GtkType item_entry_type = 0;
-
-  if (!item_entry_type)
-    {
-      static const GtkTypeInfo item_entry_info =
-      {
-       "GtkItemEntry",
-       sizeof (GtkItemEntry),
-       sizeof (GtkItemEntryClass),
-       (GtkClassInitFunc) gtk_item_entry_class_init,
-       (GtkObjectInitFunc) gtk_item_entry_init,
-       /* reserved_1 */ NULL,
-       /* reserved_2 */ NULL,
-        (GtkClassInitFunc) NULL,
-      };
-
-      static const GInterfaceInfo item_editable_info =
-      {
-        (GInterfaceInitFunc) gtk_item_entry_editable_init,    /* interface_init */
-        NULL,                                            /* interface_finalize */
-        NULL                                             /* interface_data */
-      };
-
-
-      item_entry_type = gtk_type_unique (GTK_TYPE_ENTRY, &item_entry_info);
-
-      g_type_add_interface_static (item_entry_type,
-                                   GTK_TYPE_EDITABLE,
-                                   &item_editable_info);
-
-    }
-
-  return item_entry_type;
-}
-
-static void
-gtk_item_entry_class_init (GtkItemEntryClass *class)
-{
-  GtkObjectClass *object_class;
-  GtkWidgetClass *widget_class;
-  GtkEntryClass *entry_class;
-
-  object_class = (GtkObjectClass*) class;
-  widget_class = (GtkWidgetClass*) class;
-  parent_class = gtk_type_class (GTK_TYPE_ENTRY);
-  entry_class = (GtkEntryClass *) class;
-
-  widget_class->realize = gtk_entry_realize;
-  widget_class->size_request = gtk_entry_size_request;
-  widget_class->size_allocate = gtk_entry_size_allocate;
-  widget_class->expose_event = gtk_entry_expose;
-  widget_class->grab_focus = gtk_entry_grab_focus;
-  widget_class->style_set = gtk_entry_style_set;
-  widget_class->direction_changed = gtk_entry_direction_changed;
-  widget_class->state_changed = gtk_entry_state_changed;
-
-  entry_class->move_cursor = gtk_entry_move_cursor;
-  entry_class->insert_at_cursor = gtk_entry_insert_at_cursor;
-  entry_class->delete_from_cursor = gtk_entry_delete_from_cursor;
-
-}
-
-static void
-gtk_item_entry_editable_init (GtkEditableClass *iface)
-{
-  iface->do_insert_text = gtk_entry_insert_text;
-  iface->do_delete_text = gtk_entry_delete_text;
-  iface->insert_text = gtk_entry_real_insert_text;
-  iface->delete_text = gtk_entry_real_delete_text;
-  iface->set_position = gtk_entry_real_set_position;
-  iface->get_position = gtk_entry_get_position;
-}
-
-static void
-gtk_item_entry_init (GtkItemEntry *entry)
-{
-  entry->justification = GTK_JUSTIFY_LEFT;
-  entry->text_max_size = 0;
-  GTK_ENTRY(entry)->has_frame = FALSE;
-
-  g_object_unref(G_OBJECT(GTK_ENTRY(entry)->im_context));
-
-  GTK_ENTRY(entry)->im_context = gtk_im_multicontext_new ();
-
-  g_signal_connect (G_OBJECT (GTK_ENTRY(entry)->im_context), "commit",
-                    G_CALLBACK (gtk_entry_commit_cb), entry);
-  g_signal_connect (G_OBJECT (GTK_ENTRY(entry)->im_context), "preedit_changed",
-                    G_CALLBACK (gtk_entry_preedit_changed_cb), entry);
-  g_signal_connect (G_OBJECT (GTK_ENTRY(entry)->im_context), "retrieve_surrounding",
-                    G_CALLBACK (gtk_entry_retrieve_surrounding_cb), entry);
-  g_signal_connect (G_OBJECT (GTK_ENTRY(entry)->im_context), "delete_surrounding",
-                    G_CALLBACK (gtk_entry_delete_surrounding_cb), entry);
-
-}
-
-static void
-gtk_entry_realize (GtkWidget *widget)
-{
-  GtkEntry *entry;
-  GtkEditable *editable;
-  GdkWindowAttr attributes;
-  gint attributes_mask;
-
-  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-  entry = GTK_ENTRY (widget);
-  editable = GTK_EDITABLE (widget);
-
-  attributes.window_type = GDK_WINDOW_CHILD;
-
-  get_widget_window_size (entry, &attributes.x, &attributes.y, &attributes.width, &attributes.height);
-
-  attributes.wclass = GDK_INPUT_OUTPUT;
-  attributes.visual = gtk_widget_get_visual (widget);
-  attributes.colormap = gtk_widget_get_colormap (widget);
-  attributes.event_mask = gtk_widget_get_events (widget);
-  attributes.event_mask |= (GDK_EXPOSURE_MASK |
-                            GDK_BUTTON_PRESS_MASK |
-                            GDK_BUTTON_RELEASE_MASK |
-                            GDK_BUTTON1_MOTION_MASK |
-                            GDK_BUTTON3_MOTION_MASK |
-                            GDK_POINTER_MOTION_HINT_MASK |
-                            GDK_POINTER_MOTION_MASK |
-                            GDK_ENTER_NOTIFY_MASK |
-                            GDK_LEAVE_NOTIFY_MASK);
-  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
-
-  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
-  gdk_window_set_user_data (widget->window, entry);
-
-  get_text_area_size (entry, &attributes.x, &attributes.y, &attributes.width, &attributes.height);
-
-  attributes.cursor = gdk_cursor_new (GDK_XTERM);
-  attributes_mask |= GDK_WA_CURSOR;
-
-  entry->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
-  gdk_window_set_user_data (entry->text_area, entry);
-
-  gdk_cursor_unref (attributes.cursor);
-
-  widget->style = gtk_style_attach (widget->style, widget->window);
-
-  gdk_window_set_background (widget->window, &widget->style->bg[GTK_WIDGET_STATE(widget)]);
-  gdk_window_set_background (entry->text_area, &widget->style->bg[GTK_WIDGET_STATE (widget)]);
-
-  gdk_window_show (entry->text_area);
-
-  gtk_im_context_set_client_window (entry->im_context, entry->text_area);
-
-  gtk_entry_adjust_scroll (entry);
-}
-
-static void
-get_borders (GtkEntry *entry,
-             gint     *xborder,
-             gint     *yborder)
-{
-  GtkWidget *widget = GTK_WIDGET (entry);
-  gint focus_width;
-  gboolean interior_focus;
-
-  gtk_widget_style_get (widget,
-                       "interior-focus", &interior_focus,
-                       "focus-line-width", &focus_width,
-                       NULL);
-
-  if (entry->has_frame)
-    {
-      *xborder = widget->style->xthickness;
-      *yborder = widget->style->ythickness;
-    }
-  else
-    {
-      *xborder = 0;
-      *yborder = 0;
-    }
-
-  if (!interior_focus)
-    {
-      *xborder += focus_width;
-      *yborder += focus_width;
-    }
-
-}
-
-static void
-gtk_entry_size_request (GtkWidget      *widget,
-                       GtkRequisition *requisition)
-{
-  GtkEntry *entry = GTK_ENTRY (widget);
-  PangoFontMetrics *metrics;
-  gint xborder, yborder;
-  PangoContext *context;
-
-  context = gtk_widget_get_pango_context (widget);
-  metrics = pango_context_get_metrics (context,
-                                      widget->style->font_desc,
-                                      pango_context_get_language (context));
-
-  entry->ascent = pango_font_metrics_get_ascent (metrics);
-  entry->descent = pango_font_metrics_get_descent (metrics);
-
-  get_borders (entry, &xborder, &yborder);
-
-  xborder += INNER_BORDER;
-  yborder += INNER_BORDER;
-
-  if (entry->width_chars < 0)
-    requisition->width = MIN_ENTRY_WIDTH + xborder * 2;
-  else
-    {
-      gint char_width = pango_font_metrics_get_approximate_char_width (metrics);
-      requisition->width = PANGO_PIXELS (char_width) * entry->width_chars + xborder * 2;
-    }
-
-  requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder * 2;
-
-  pango_font_metrics_unref (metrics);
-}
-
-static void
-get_text_area_size (GtkEntry *entry,
-                    gint     *x,
-                    gint     *y,
-                    gint     *width,
-                    gint     *height)
-{
-  gint xborder, yborder;
-  GtkRequisition requisition;
-  GtkWidget *widget = GTK_WIDGET (entry);
-
-  gtk_widget_get_child_requisition (widget, &requisition);
-
-  get_borders (entry, &xborder, &yborder);
-
-  if (x)
-    *x = xborder;
-
-  if (y)
-    *y = yborder;
-
-  if (width)
-    *width = GTK_WIDGET (entry)->allocation.width - xborder * 2;
-
-  if (height)
-    *height = requisition.height - yborder * 2;
-}
-
-static void
-get_widget_window_size (GtkEntry *entry,
-                        gint     *x,
-                        gint     *y,
-                        gint     *width,
-                        gint     *height)
-{
-  GtkRequisition requisition;
-  GtkWidget *widget = GTK_WIDGET (entry);
-
-  gtk_widget_get_child_requisition (widget, &requisition);
-
-  if (x)
-    *x = widget->allocation.x;
-
-  if (y)
-    {
-      if (entry->is_cell_renderer)
-       *y = widget->allocation.y;
-      else
-       *y = widget->allocation.y + (widget->allocation.height - requisition.height) / 2;
-    }
-
-  if (width)
-    *width = widget->allocation.width;
-
-  if (height)
-    {
-      if (entry->is_cell_renderer)
-       *height = widget->allocation.height;
-      else
-       *height = requisition.height;
-    }
-}
-
-static void
-gtk_entry_size_allocate (GtkWidget     *widget,
-                        GtkAllocation *allocation)
-{
-  GtkEntry *entry = GTK_ENTRY (widget);
-  GtkItemEntry *ientry = GTK_ITEM_ENTRY (widget);
-
-  if(ientry->text_max_size > 0)
-    allocation->width = MIN(ientry->text_max_size, allocation->width);
-
-  widget->allocation = *allocation;
-
-  if (GTK_WIDGET_REALIZED (widget))
-    {
-      /* We call gtk_widget_get_child_requisition, since we want (for
-       * backwards compatibility reasons) the realization here to
-       * be affected by the usize of the entry, if set
-       */
-      gint x, y, width, height;
-
-      get_widget_window_size (entry, &x, &y, &width, &height);
-
-      gdk_window_move_resize (widget->window,
-                              allocation->x, allocation->y, allocation->width, allocation->height);
-
-      get_text_area_size (entry, &x, &y, &width, &height);
-
-      gdk_window_move_resize (entry->text_area,
-                              0, allocation->height - height, allocation->width, height);
-
-      gtk_entry_recompute (entry);
-    }
-}
-
-static void
-gtk_entry_draw_frame (GtkWidget *widget)
-{
-}
-
-static gint
-gtk_entry_expose (GtkWidget      *widget,
-                 GdkEventExpose *event)
-{
-  GtkEntry *entry = GTK_ENTRY (widget);
-
-  if (widget->window == event->window)
-    gtk_entry_draw_frame (widget);
-  else if (entry->text_area == event->window)
-    {
-      gint area_width, area_height;
-
-      get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
-
-      gdk_draw_rectangle (entry->text_area,
-                          widget->style->bg_gc[GTK_WIDGET_STATE(widget)],
-                          TRUE,
-                          0, 0, area_width, area_height);
-
-      if ((entry->visible || entry->invisible_char != 0) &&
-         GTK_WIDGET_HAS_FOCUS (widget) &&
-         entry->selection_bound == entry->current_pos && entry->cursor_visible)
-       gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_STANDARD);
-
-      if (entry->dnd_position != -1)
-       gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_DND);
-
-      gtk_entry_draw_text (GTK_ENTRY (widget));
-    }
-
-  return FALSE;
-}
-
-static void
-gtk_entry_grab_focus (GtkWidget        *widget)
-{
-  GtkEntry *entry = GTK_ENTRY (widget);
-  gboolean select_on_focus;
-
-  GTK_WIDGET_CLASS (parent_class)->grab_focus (widget);
-
-  g_object_get (G_OBJECT (gtk_settings_get_default ()),
-               "gtk-entry-select-on-focus",
-               &select_on_focus,
-               NULL);
-
-  if (select_on_focus && entry->editable && !entry->in_click)
-    gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
-}
-
-static void
-gtk_entry_direction_changed (GtkWidget        *widget,
-                            GtkTextDirection  previous_dir)
-{
-  GtkEntry *entry = GTK_ENTRY (widget);
-
-  gtk_entry_recompute (entry);
-
-  GTK_WIDGET_CLASS (parent_class)->direction_changed (widget, previous_dir);
-}
-
-static void
-gtk_entry_state_changed (GtkWidget      *widget,
-                        GtkStateType    previous_state)
-{
-  GtkEntry *entry = GTK_ENTRY (widget);
-
-  if (GTK_WIDGET_REALIZED (widget))
-    {
-      gdk_window_set_background (widget->window, &widget->style->bg[GTK_WIDGET_STATE (widget)]);
-      gdk_window_set_background (entry->text_area, &widget->style->bg[GTK_WIDGET_STATE (widget)]);
-    }
-
-  if (!GTK_WIDGET_IS_SENSITIVE (widget))
-    {
-      /* Clear any selection */
-      gtk_editable_select_region (GTK_EDITABLE (entry), entry->current_pos, entry->current_pos);
-    }
-
-  gtk_widget_queue_clear (widget);
-}
-
-/* GtkEditable method implementations
- */
-static void
-gtk_entry_insert_text (GtkEditable *editable,
-                      const gchar *new_text,
-                      gint         new_text_length,
-                      gint        *position)
-{
-  GtkEntry *entry = GTK_ENTRY (editable);
-  gchar buf[64];
-  gchar *text;
-
-  if (*position < 0 || *position > entry->text_length)
-    *position = entry->text_length;
-
-  g_object_ref (G_OBJECT (editable));
-
-  if (new_text_length <= 63)
-    text = buf;
-  else
-    text = g_new (gchar, new_text_length + 1);
-
-  text[new_text_length] = '\0';
-  strncpy (text, new_text, new_text_length);
-
-  g_signal_emit_by_name (editable, "insert_text", text, new_text_length, position);
-
-  if (new_text_length > 63)
-    g_free (text);
-
-  g_object_unref (G_OBJECT (editable));
-}
-
-static void
-gtk_entry_delete_text (GtkEditable *editable,
-                      gint         start_pos,
-                      gint         end_pos)
-{
-  GtkEntry *entry = GTK_ENTRY (editable);
-
-  if (end_pos < 0 || end_pos > entry->text_length)
-    end_pos = entry->text_length;
-  if (start_pos < 0)
-    start_pos = 0;
-  if (start_pos > end_pos)
-    start_pos = end_pos;
-
-  g_object_ref (G_OBJECT (editable));
-
-  g_signal_emit_by_name (editable, "delete_text", start_pos, end_pos);
-
-  g_object_unref (G_OBJECT (editable));
-}
-
-static void
-gtk_entry_style_set    (GtkWidget      *widget,
-                        GtkStyle       *previous_style)
-{
-  GtkEntry *entry = GTK_ENTRY (widget);
-
-  if (previous_style && GTK_WIDGET_REALIZED (widget))
-    {
-      gtk_entry_recompute (entry);
-
-      gdk_window_set_background (widget->window, &widget->style->bg[GTK_WIDGET_STATE(widget)]);
-      gdk_window_set_background (entry->text_area, &widget->style->bg[GTK_WIDGET_STATE (widget)]);
-    }
-}
-
-static void
-gtk_entry_real_set_position (GtkEditable *editable,
-                             gint         position)
-{
-  GtkEntry *entry = GTK_ENTRY (editable);
-
-  if (position < 0 || position > entry->text_length)
-    position = entry->text_length;
-
-  if (position != entry->current_pos ||
-      position != entry->selection_bound)
-    {
-      gtk_entry_reset_im_context (entry);
-      gtk_entry_set_positions (entry, position, position);
-    }
-}
-
-static gint
-gtk_entry_get_position (GtkEditable *editable)
-{
-  return GTK_ENTRY (editable)->current_pos;
-}
-
-
-/* Default signal handlers
- */
-static void
-gtk_entry_real_insert_text (GtkEditable *editable,
-                           const gchar *new_text,
-                           gint         new_text_length,
-                           gint        *position)
-{
-  gint index;
-  gint n_chars;
-
-  GtkEntry *entry = GTK_ENTRY (editable);
-
-  if (new_text_length < 0)
-    new_text_length = strlen (new_text);
-
-  n_chars = g_utf8_strlen (new_text, new_text_length);
-  if (entry->text_max_length > 0 && n_chars + entry->text_length > entry->text_max_length)
-    {
-      gdk_beep ();
-      n_chars = entry->text_max_length - entry->text_length;
-      new_text_length = g_utf8_offset_to_pointer (new_text, n_chars) - new_text;
-    }
-
-  if (new_text_length + entry->n_bytes + 1 > entry->text_size)
-    {
-      while (new_text_length + entry->n_bytes + 1 > entry->text_size)
-       {
-         if (entry->text_size == 0)
-           entry->text_size = MIN_SIZE;
-         else
-           {
-             if (2 * (guint)entry->text_size < MAX_SIZE &&
-                 2 * (guint)entry->text_size > entry->text_size)
-               entry->text_size *= 2;
-             else
-               {
-                 entry->text_size = MAX_SIZE;
-                 if (new_text_length > (gint)entry->text_size - (gint)entry->n_bytes - 1)
-                   {
-                     new_text_length = (gint)entry->text_size - (gint)entry->n_bytes - 1;
-                     new_text_length = g_utf8_find_prev_char (new_text, new_text + new_text_length + 1) - new_text;
-                     n_chars = g_utf8_strlen (new_text, new_text_length);
-                   }
-                 break;
-               }
-           }
-       }
-
-      entry->text = g_realloc (entry->text, entry->text_size);
-    }
-
-  index = g_utf8_offset_to_pointer (entry->text, *position) - entry->text;
-
-  g_memmove (entry->text + index + new_text_length, entry->text + index, entry->n_bytes - index);
-  memcpy (entry->text + index, new_text, new_text_length);
-
-  entry->n_bytes += new_text_length;
-  entry->text_length += n_chars;
-
-  /* NUL terminate for safety and convenience */
-  entry->text[entry->n_bytes] = '\0';
-
-  if (entry->current_pos > *position)
-    entry->current_pos += n_chars;
-
-  if (entry->selection_bound > *position)
-    entry->selection_bound += n_chars;
-
-  *position += n_chars;
-
-  gtk_entry_recompute (entry);
-
-  g_signal_emit_by_name (editable, "changed");
-  g_object_notify (G_OBJECT (editable), "text");
-}
-
-static void
-gtk_entry_real_delete_text (GtkEditable *editable,
-                           gint         start_pos,
-                           gint         end_pos)
-{
-  GtkEntry *entry = GTK_ENTRY (editable);
-
-  if (start_pos < 0)
-    start_pos = 0;
-  if (end_pos < 0 || end_pos > entry->text_length)
-    end_pos = entry->text_length;
-
-  if (start_pos < end_pos)
-    {
-      gint start_index = g_utf8_offset_to_pointer (entry->text, start_pos) - entry->text;
-      gint end_index = g_utf8_offset_to_pointer (entry->text, end_pos) - entry->text;
-
-      g_memmove (entry->text + start_index, entry->text + end_index, entry->n_bytes + 1 - end_index);
-      entry->text_length -= (end_pos - start_pos);
-      entry->n_bytes -= (end_index - start_index);
-
-      if (entry->current_pos > start_pos)
-       entry->current_pos -= MIN (entry->current_pos, end_pos) - start_pos;
-
-      if (entry->selection_bound > start_pos)
-       entry->selection_bound -= MIN (entry->selection_bound, end_pos) - start_pos;
-      /* We might have deleted the selection
-       */
-      gtk_entry_update_primary_selection (entry);
-
-      gtk_entry_recompute (entry);
-
-      g_signal_emit_by_name (editable, "changed");
-      g_object_notify (G_OBJECT (editable), "text");
-    }
-}
-
-/* Compute the X position for an offset that corresponds to the "more important
- * cursor position for that offset. We use this when trying to guess to which
- * end of the selection we should go to when the user hits the left or
- * right arrow key.
- */
-static gint
-get_better_cursor_x (GtkEntry *entry,
-                    gint      offset)
-{
-  GtkTextDirection keymap_direction =
-    (gdk_keymap_get_direction (gdk_keymap_get_default ()) == PANGO_DIRECTION_LTR) ?
-    GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
-  GtkTextDirection widget_direction = gtk_widget_get_direction (GTK_WIDGET (entry));
-  gboolean split_cursor;
-
-  PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
-  gint index = g_utf8_offset_to_pointer (entry->text, offset) - entry->text;
-
-  PangoRectangle strong_pos, weak_pos;
-
-  g_object_get (gtk_widget_get_settings (GTK_WIDGET (entry)),
-               "gtk-split-cursor", &split_cursor,
-               NULL);
-
-  pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
-
-  if (split_cursor)
-    return strong_pos.x / PANGO_SCALE;
-  else
-    return (keymap_direction == widget_direction) ? strong_pos.x / PANGO_SCALE : weak_pos.x / PANGO_SCALE;
-}
-
-static void
-gtk_entry_move_cursor (GtkEntry       *entry,
-                      GtkMovementStep step,
-                      gint            count,
-                      gboolean        extend_selection)
-{
-  gint new_pos = entry->current_pos;
-
-  gtk_entry_reset_im_context (entry);
-
-  if (entry->current_pos != entry->selection_bound && !extend_selection)
-    {
-      /* If we have a current selection and aren't extending it, move to the
-       * start/or end of the selection as appropriate
-       */
-      switch (step)
-       {
-       case GTK_MOVEMENT_VISUAL_POSITIONS:
-         {
-           gint current_x = get_better_cursor_x (entry, entry->current_pos);
-           gint bound_x = get_better_cursor_x (entry, entry->selection_bound);
-
-           if (count < 0)
-             new_pos = current_x < bound_x ? entry->current_pos : entry->selection_bound;
-           else
-             new_pos = current_x > bound_x ? entry->current_pos : entry->selection_bound;
-
-           break;
-         }
-       case GTK_MOVEMENT_LOGICAL_POSITIONS:
-       case GTK_MOVEMENT_WORDS:
-         if (count < 0)
-           new_pos = MIN (entry->current_pos, entry->selection_bound);
-         else
-           new_pos = MAX (entry->current_pos, entry->selection_bound);
-         break;
-       case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
-       case GTK_MOVEMENT_PARAGRAPH_ENDS:
-       case GTK_MOVEMENT_BUFFER_ENDS:
-         new_pos = count < 0 ? 0 : entry->text_length;
-         break;
-       case GTK_MOVEMENT_DISPLAY_LINES:
-       case GTK_MOVEMENT_PARAGRAPHS:
-       case GTK_MOVEMENT_PAGES:
-         break;
-       default:
-         break;
-       }
-    }
-  else
-    {
-      switch (step)
-       {
-       case GTK_MOVEMENT_LOGICAL_POSITIONS:
-         new_pos = gtk_entry_move_logically (entry, new_pos, count);
-         break;
-       case GTK_MOVEMENT_VISUAL_POSITIONS:
-         new_pos = gtk_entry_move_visually (entry, new_pos, count);
-         break;
-       case GTK_MOVEMENT_WORDS:
-         while (count > 0)
-           {
-             new_pos = gtk_entry_move_forward_word (entry, new_pos);
-             count--;
-           }
-         while (count < 0)
-           {
-             new_pos = gtk_entry_move_backward_word (entry, new_pos);
-             count++;
-           }
-         break;
-       case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
-       case GTK_MOVEMENT_PARAGRAPH_ENDS:
-       case GTK_MOVEMENT_BUFFER_ENDS:
-         new_pos = count < 0 ? 0 : entry->text_length;
-         break;
-       case GTK_MOVEMENT_DISPLAY_LINES:
-       case GTK_MOVEMENT_PARAGRAPHS:
-       case GTK_MOVEMENT_PAGES:
-         break;
-       default:
-         break;
-       }
-    }
-
-  if (extend_selection)
-    gtk_editable_select_region (GTK_EDITABLE (entry), entry->selection_bound, new_pos);
-  else
-    gtk_editable_set_position (GTK_EDITABLE (entry), new_pos);
-
-  gtk_entry_pend_cursor_blink (entry);
-}
-
-static void
-gtk_entry_insert_at_cursor (GtkEntry    *entry,
-                           const gchar *str)
-{
-  GtkEditable *editable = GTK_EDITABLE (entry);
-  gint pos = entry->current_pos;
-
-  if (entry->editable)
-    {
-      gtk_entry_reset_im_context (entry);
-
-      gtk_editable_insert_text (editable, str, -1, &pos);
-      gtk_editable_set_position (editable, pos);
-    }
-}
-
-static void
-gtk_entry_delete_from_cursor (GtkEntry       *entry,
-                             GtkDeleteType   type,
-                             gint            count)
-{
-  GtkEditable *editable = GTK_EDITABLE (entry);
-  gint start_pos = entry->current_pos;
-  gint end_pos = entry->current_pos;
-
-  gtk_entry_reset_im_context (entry);
-
-  if (!entry->editable)
-    return;
-
-  if (entry->selection_bound != entry->current_pos)
-    {
-      gtk_editable_delete_selection (editable);
-      return;
-    }
-
-  switch (type)
-    {
-    case GTK_DELETE_CHARS:
-      end_pos = gtk_entry_move_logically (entry, entry->current_pos, count);
-      gtk_editable_delete_text (editable, MIN (start_pos, end_pos), MAX (start_pos, end_pos));
-      break;
-    case GTK_DELETE_WORDS:
-      if (count < 0)
-       {
-         /* Move to end of current word, or if not on a word, end of previous word */
-         end_pos = gtk_entry_move_backward_word (entry, end_pos);
-         end_pos = gtk_entry_move_forward_word (entry, end_pos);
-       }
-      else if (count > 0)
-       {
-         /* Move to beginning of current word, or if not on a word, begining of next word */
-         start_pos = gtk_entry_move_forward_word (entry, start_pos);
-         start_pos = gtk_entry_move_backward_word (entry, start_pos);
-       }
-
-      /* Fall through */
-    case GTK_DELETE_WORD_ENDS:
-      while (count < 0)
-       {
-         start_pos = gtk_entry_move_backward_word (entry, start_pos);
-         count++;
-       }
-      while (count > 0)
-       {
-         end_pos = gtk_entry_move_forward_word (entry, end_pos);
-         count--;
-       }
-      gtk_editable_delete_text (editable, start_pos, end_pos);
-      break;
-    case GTK_DELETE_DISPLAY_LINE_ENDS:
-    case GTK_DELETE_PARAGRAPH_ENDS:
-      if (count < 0)
-       gtk_editable_delete_text (editable, 0, entry->current_pos);
-      else
-       gtk_editable_delete_text (editable, entry->current_pos, -1);
-      break;
-    case GTK_DELETE_DISPLAY_LINES:
-    case GTK_DELETE_PARAGRAPHS:
-      gtk_editable_delete_text (editable, 0, -1);
-      break;
-    case GTK_DELETE_WHITESPACE:
-      gtk_entry_delete_whitespace (entry);
-      break;
-    }
-
-  gtk_entry_pend_cursor_blink (entry);
-}
-
-/* IM Context Callbacks
- */
-
-static void
-gtk_entry_commit_cb (GtkIMContext *context,
-                     const gchar  *str,
-                     GtkEntry     *entry)
-{
-  gtk_entry_enter_text (entry, str);
-}
-
-static void
-gtk_entry_preedit_changed_cb (GtkIMContext *context,
-                              GtkEntry     *entry)
-{
-  gchar *preedit_string;
-  gint cursor_pos;
-
-  gtk_im_context_get_preedit_string (entry->im_context,
-                                     &preedit_string, NULL,
-                                     &cursor_pos);
-  entry->preedit_length = strlen (preedit_string);
-  cursor_pos = CLAMP (cursor_pos, 0, g_utf8_strlen (preedit_string, -1));
-  entry->preedit_cursor = cursor_pos;
-  g_free (preedit_string);
-
-  gtk_entry_recompute (entry);
-}
-
-static gboolean
-gtk_entry_retrieve_surrounding_cb (GtkIMContext *context,
-                               GtkEntry     *entry)
-{
-  gtk_im_context_set_surrounding (context,
-                                  entry->text,
-                                  entry->n_bytes,
-                                  g_utf8_offset_to_pointer (entry->text, entry->current_pos) - entry->text);
-
-  return TRUE;
-}
-
-static gboolean
-gtk_entry_delete_surrounding_cb (GtkIMContext *slave,
-                                 gint          offset,
-                                 gint          n_chars,
-                                 GtkEntry     *entry)
-{
-  gtk_editable_delete_text (GTK_EDITABLE (entry),
-                            entry->current_pos + offset,
-                            entry->current_pos + offset + n_chars);
-
-  return TRUE;
-}
-
-
-/* Internal functions
- */
-
-/* Used for im_commit_cb and inserting Unicode chars */
-static void
-gtk_entry_enter_text (GtkEntry       *entry,
-                      const gchar    *str)
-{
-  GtkEditable *editable = GTK_EDITABLE (entry);
-  gint tmp_pos;
-
-  if (gtk_editable_get_selection_bounds (editable, NULL, NULL))
-    gtk_editable_delete_selection (editable);
-  else
-    {
-      if (entry->overwrite_mode)
-        gtk_entry_delete_from_cursor (entry, GTK_DELETE_CHARS, 1);
-    }
-
-  tmp_pos = entry->current_pos;
-  gtk_editable_insert_text (editable, str, strlen (str), &tmp_pos);
-  gtk_editable_set_position (editable, tmp_pos);
-}
-
-/* All changes to entry->current_pos and entry->selection_bound
- * should go through this function.
- */
-static void
-gtk_entry_set_positions (GtkEntry *entry,
-                         gint      current_pos,
-                         gint      selection_bound)
-{
-  gboolean changed = FALSE;
-
-  g_object_freeze_notify (G_OBJECT (entry));
-
-  if (current_pos != -1 &&
-      entry->current_pos != current_pos)
-    {
-      entry->current_pos = current_pos;
-      changed = TRUE;
-
-      g_object_notify (G_OBJECT (entry), "cursor_position");
-    }
-
-  if (selection_bound != -1 &&
-      entry->selection_bound != selection_bound)
-    {
-      entry->selection_bound = selection_bound;
-      changed = TRUE;
-
-      g_object_notify (G_OBJECT (entry), "selection_bound");
-    }
-
-  g_object_thaw_notify (G_OBJECT (entry));
-
-  if (changed)
-    gtk_entry_recompute (entry);
-}
-
-static void
-gtk_entry_reset_layout (GtkEntry *entry)
-{
-  if (entry->cached_layout)
-    {
-      g_object_unref (G_OBJECT (entry->cached_layout));
-      entry->cached_layout = NULL;
-    }
-}
-
-static void
-update_im_cursor_location (GtkEntry *entry)
-{
-  GdkRectangle area;
-  gint strong_x;
-  gint strong_xoffset;
-  gint x, y, area_width, area_height;
-
-  gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &strong_x, NULL)
-;
-  get_text_area_size (entry, &x, &y, &area_width, &area_height);
-
-  strong_xoffset = strong_x - entry->scroll_offset;
-  if (strong_xoffset < 0)
-    {
-      strong_xoffset = 0;
-    }
-  else if (strong_xoffset > area_width)
-    {
-      strong_xoffset = area_width;
-    }
-  area.x = x + strong_xoffset;
-  area.y = y + area_height;
-  area.width = area_width;
-  area.height = area_height;
-
-  gtk_im_context_set_cursor_location (entry->im_context, &area);
-}
-
-static gboolean
-recompute_idle_func (gpointer data)
-{
-  GtkEntry *entry;
-
-  GDK_THREADS_ENTER ();
-
-  entry = GTK_ENTRY (data);
-
-  gtk_entry_adjust_scroll (entry);
-  gtk_entry_queue_draw (entry);
-
-  entry->recompute_idle = FALSE;
-
-  update_im_cursor_location (entry);
-
-  GDK_THREADS_LEAVE ();
-
-  return FALSE;
-}
-
-static void
-gtk_entry_recompute (GtkEntry *entry)
-{
-  gtk_entry_reset_layout (entry);
-  gtk_entry_check_cursor_blink (entry);
-
-
-  if (!entry->recompute_idle)
-    {
-      entry->recompute_idle = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 15, /* between resize and redraw */
-                                              recompute_idle_func, entry, NULL);
-    }
-}
-
-static void
-append_char (GString *str,
-             gunichar ch,
-             gint     count)
-{
-  gint i;
-  gint char_len;
-  gchar buf[7];
-
-  char_len = g_unichar_to_utf8 (ch, buf);
-
-  i = 0;
-  while (i < count)
-    {
-      g_string_append_len (str, buf, char_len);
-      ++i;
-    }
-}
-
-static PangoLayout *
-gtk_entry_create_layout (GtkEntry *entry,
-                        gboolean  include_preedit)
-{
-  PangoLayout *layout = gtk_widget_create_pango_layout (GTK_WIDGET (entry), NULL);
-  PangoAttrList *tmp_attrs = pango_attr_list_new ();
-
-  gchar *preedit_string = NULL;
-  gint preedit_length = 0;
-  PangoAttrList *preedit_attrs = NULL;
-
-  pango_layout_set_single_paragraph_mode (layout, TRUE);
-
-  if (include_preedit)
-    {
-      gtk_im_context_get_preedit_string (entry->im_context,
-                                        &preedit_string, &preedit_attrs, NULL);
-      preedit_length = entry->preedit_length;
-    }
-
-  if (preedit_length)
-    {
-      GString *tmp_string = g_string_new (NULL);
-
-      gint cursor_index = g_utf8_offset_to_pointer (entry->text, entry->current_pos) - entry->text;
-
-      if (entry->visible)
-        {
-          g_string_prepend_len (tmp_string, entry->text, entry->n_bytes);
-          g_string_insert (tmp_string, cursor_index, preedit_string);
-        }
-      else
-        {
-          gint ch_len;
-          gint preedit_len_chars;
-          gunichar invisible_char;
-
-          ch_len = g_utf8_strlen (entry->text, entry->n_bytes);
-          preedit_len_chars = g_utf8_strlen (preedit_string, -1);
-          ch_len += preedit_len_chars;
-
-          if (entry->invisible_char != 0)
-            invisible_char = entry->invisible_char;
-          else
-            invisible_char = ' '; /* just pick a char */
-
-          append_char (tmp_string, invisible_char, ch_len);
-
-          /* Fix cursor index to point to invisible char corresponding
-           * to the preedit, fix preedit_length to be the length of
-           * the invisible chars representing the preedit
-           */
-          cursor_index =
-            g_utf8_offset_to_pointer (tmp_string->str, entry->current_pos) -
-            tmp_string->str;
-          preedit_length =
-            preedit_len_chars *
-            g_unichar_to_utf8 (invisible_char, NULL);
-        }
-
-      pango_layout_set_text (layout, tmp_string->str, tmp_string->len);
-
-      pango_attr_list_splice (tmp_attrs, preedit_attrs,
-                             cursor_index, preedit_length);
-
-      g_string_free (tmp_string, TRUE);
-    }
-  else
-    {
-      if (entry->visible)
-        {
-          pango_layout_set_text (layout, entry->text, entry->n_bytes);
-        }
-      else
-        {
-          GString *str = g_string_new (NULL);
-          gunichar invisible_char;
-
-          if (entry->invisible_char != 0)
-            invisible_char = entry->invisible_char;
-          else
-            invisible_char = ' '; /* just pick a char */
-
-          append_char (str, invisible_char, entry->text_length);
-          pango_layout_set_text (layout, str->str, str->len);
-          g_string_free (str, TRUE);
-        }
-    }
-
-  pango_layout_set_attributes (layout, tmp_attrs);
-
-  if (preedit_string)
-    g_free (preedit_string);
-  if (preedit_attrs)
-    pango_attr_list_unref (preedit_attrs);
-
-  pango_attr_list_unref (tmp_attrs);
-
-  return layout;
-}
-
-static PangoLayout *
-gtk_entry_ensure_layout (GtkEntry *entry,
-                         gboolean  include_preedit)
-{
-  if (entry->preedit_length > 0 &&
-      !include_preedit != !entry->cache_includes_preedit)
-    gtk_entry_reset_layout (entry);
-
-  if (!entry->cached_layout)
-    {
-      entry->cached_layout = gtk_entry_create_layout (entry, include_preedit);
-      entry->cache_includes_preedit = include_preedit;
-    }
-
-  return entry->cached_layout;
-}
-
-static void
-get_layout_position (GtkEntry *entry,
-                     gint     *x,
-                     gint     *y)
-{
-  PangoLayout *layout;
-  PangoRectangle logical_rect;
-  gint area_width, area_height;
-  gint y_pos;
-  PangoLayoutLine *line;
-
-  layout = gtk_entry_ensure_layout (entry, TRUE);
-
-  get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
-
-  area_height = PANGO_SCALE * (area_height);
-
-  line = pango_layout_get_lines (layout)->data;
-  pango_layout_line_get_extents (line, NULL, &logical_rect);
-
-  /* Align primarily for locale's ascent/descent */
-
-  y_pos = ((area_height - entry->ascent - entry->descent) / 2 +
-           entry->ascent + logical_rect.y);
-
-
-  /* Now see if we need to adjust to fit in actual drawn string */
-
-  if (logical_rect.height > area_height)
-    y_pos = (area_height - logical_rect.height) / 2;
-  else if (y_pos < 0)
-    y_pos = 0;
-  else if (y_pos + logical_rect.height > area_height)
-    y_pos = area_height - logical_rect.height;
-
-  y_pos = y_pos / PANGO_SCALE;
-
-  if (x)
-    *x = - entry->scroll_offset;
-
-  if (y)
-    *y = y_pos;
-}
-
-static void
-gtk_entry_draw_text (GtkEntry *entry)
-{
-  GtkWidget *widget;
-  PangoLayoutLine *line;
-
-  if (!entry->visible && entry->invisible_char == 0)
-    return;
-
-  if (GTK_WIDGET_DRAWABLE (entry))
-    {
-      PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
-      gint area_width, area_height;
-
-      gint x, y;
-      gint start_pos, end_pos;
-
-      widget = GTK_WIDGET (entry);
-
-      get_layout_position (entry, &x, &y);
-
-      get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
-
-
-      gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state],
-                       x, y,
-                      layout);
-
-
-      if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos))
-       {
-         gint *ranges;
-         gint n_ranges, i;
-          PangoRectangle logical_rect;
-         const gchar *text = pango_layout_get_text (layout);
-         gint start_index = g_utf8_offset_to_pointer (text, start_pos) - text;
-         gint end_index = g_utf8_offset_to_pointer (text, end_pos) - text;
-         GdkRegion *clip_region = gdk_region_new ();
-         GdkGC *text_gc;
-         GdkGC *selection_gc;
-
-          line = pango_layout_get_lines (layout)->data;
-
-         pango_layout_line_get_x_ranges (line, start_index, end_index, &ranges, &n_ranges);
-
-          pango_layout_get_extents (layout, NULL, &logical_rect);
-
-         if (GTK_WIDGET_HAS_FOCUS (entry))
-           {
-             selection_gc = widget->style->base_gc [GTK_STATE_SELECTED];
-             text_gc = widget->style->text_gc [GTK_STATE_SELECTED];
-           }
-         else
-           {
-             selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE];
-             text_gc = widget->style->text_gc [GTK_STATE_ACTIVE];
-           }
-
-         for (i=0; i < n_ranges; i++)
-           {
-             GdkRectangle rect;
-
-             rect.x = INNER_BORDER - entry->scroll_offset + ranges[2*i] / PANGO_SCALE;
-             rect.y = y;
-             rect.width = (ranges[2*i + 1] - ranges[2*i]) / PANGO_SCALE;
-             rect.height = logical_rect.height / PANGO_SCALE;
-
-             gdk_draw_rectangle (entry->text_area, selection_gc, TRUE,
-                                 rect.x, rect.y, rect.width, rect.height);
-
-             gdk_region_union_with_rect (clip_region, &rect);
-           }
-
-         gdk_gc_set_clip_region (text_gc, clip_region);
-         gdk_draw_layout (entry->text_area, text_gc,
-                          x, y,
-                          layout);
-         gdk_gc_set_clip_region (text_gc, NULL);
-
-         gdk_region_destroy (clip_region);
-         g_free (ranges);
-       }
-    }
-}
-
-/*
- * From _gtk_get_insertion_cursor_gc
- */
-
-typedef struct _CursorInfo CursorInfo;
-
-struct _CursorInfo
-{
-  GType for_type;
-  GdkGC *primary_gc;
-  GdkGC *secondary_gc;
-};
-
-static GdkGC *
-make_cursor_gc (GtkWidget *widget,
-               const gchar *property_name,
-               GdkColor *fallback)
-{
-  GdkGCValues gc_values;
-  GdkGCValuesMask gc_values_mask;
-  GdkColor *cursor_color;
-
-  gtk_widget_style_get (widget, property_name, &cursor_color, NULL);
-
-  gc_values_mask = GDK_GC_FOREGROUND;
-  if (cursor_color)
-    {
-      gc_values.foreground = *cursor_color;
-      gdk_color_free (cursor_color);
-    }
-  else
-    gc_values.foreground = *fallback;
-
-  gdk_rgb_find_color (widget->style->colormap, &gc_values.foreground);
-  return gtk_gc_get (widget->style->depth, widget->style->colormap,
-    &gc_values, gc_values_mask);
-}
-
-static GdkGC *
-_gtkextra_get_insertion_cursor_gc (GtkWidget *widget,
-                                  gboolean   is_primary)
-{
-  CursorInfo *cursor_info;
-
-  cursor_info = g_object_get_data (G_OBJECT (widget->style), "gtk-style-cursor-info");
-  if (!cursor_info)
-    {
-      cursor_info = g_new (CursorInfo, 1);
-      g_object_set_data (G_OBJECT (widget->style), "gtk-style-cursor-info", cursor_info);
-      cursor_info->primary_gc = NULL;
-      cursor_info->secondary_gc = NULL;
-      cursor_info->for_type = G_TYPE_INVALID;
-    }
-
-  /* We have to keep track of the type because gtk_widget_style_get()
-   * can return different results when called on the same property and
-   * same style but for different widgets. :-(. That is,
-   * GtkEntry::cursor-color = "red" in a style will modify the cursor
-   * color for entries but not for text view.
-   */
-  if (cursor_info->for_type != G_OBJECT_TYPE (widget))
-    {
-      cursor_info->for_type = G_OBJECT_TYPE (widget);
-      if (cursor_info->primary_gc)
-       {
-         gtk_gc_release (cursor_info->primary_gc);
-         cursor_info->primary_gc = NULL;
-       }
-      if (cursor_info->secondary_gc)
-       {
-         gtk_gc_release (cursor_info->secondary_gc);
-         cursor_info->secondary_gc = NULL;
-       }
-    }
-
-  if (is_primary)
-    {
-      if (!cursor_info->primary_gc)
-       cursor_info->primary_gc = make_cursor_gc (widget,
-                                                 "cursor-color",
-                                                 &widget->style->black);
-
-      return g_object_ref (cursor_info->primary_gc);
-    }
-  else
-    {
-      static GdkColor gray = { 0, 0x8888, 0x8888, 0x8888 };
-
-      if (!cursor_info->secondary_gc)
-       cursor_info->secondary_gc = make_cursor_gc (widget,
-                                                   "secondary-cursor-color",
-                                                   &gray);
-
-      return g_object_ref (cursor_info->secondary_gc);
-    }
-}
-
-/*
- * From _gtk_draw_insertion_cursor
- */
-static void
-_gtkextra_draw_insertion_cursor (GtkWidget *widget,
-                                GdkDrawable *drawable,
-                                GdkGC *gc,
-                                GdkRectangle *location,
-                                GtkTextDirection direction,
-                                gboolean draw_arrow)
-{
-  gint stem_width;
-  gint arrow_width;
-  gint x, y;
-  gint i;
-  gfloat cursor_aspect_ratio;
-  gint offset;
-
-  g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
-
-  gtk_widget_style_get (widget, "cursor-aspect-ratio", &cursor_aspect_ratio, NULL);
-
-  stem_width = location->height * cursor_aspect_ratio + 1;
-  arrow_width = stem_width + 1;
-
-  /* put (stem_width % 2) on the proper side of the cursor */
-  if (direction == GTK_TEXT_DIR_LTR)
-    offset = stem_width / 2;
-  else
-    offset = stem_width - stem_width / 2;
-
-  for (i = 0; i < stem_width; i++)
-    gdk_draw_line (drawable, gc,
-                  location->x + i - offset, location->y,
-                  location->x + i - offset, location->y + location->height - 1);
-
-  if (draw_arrow)
-    {
-      if (direction == GTK_TEXT_DIR_RTL)
-        {
-          x = location->x - offset - 1;
-          y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
-
-          for (i = 0; i < arrow_width; i++)
-            {
-              gdk_draw_line (drawable, gc,
-                             x, y + i + 1,
-                             x, y + 2 * arrow_width - i - 1);
-              x --;
-            }
-        }
-      else if (direction == GTK_TEXT_DIR_LTR)
-        {
-          x = location->x + stem_width - offset;
-          y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
-
-          for (i = 0; i < arrow_width; i++)
-            {
-              gdk_draw_line (drawable, gc,
-                             x, y + i + 1,
-                             x, y + 2 * arrow_width - i - 1);
-              x++;
-            }
-        }
-    }
-}
-
-static void
-gtk_entry_draw_cursor (GtkEntry  *entry,
-                      CursorType type)
-{
-  GtkTextDirection keymap_direction =
-    (gdk_keymap_get_direction (gdk_keymap_get_default ()) == PANGO_DIRECTION_LTR) ?
-    GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
-  GtkTextDirection widget_direction = gtk_widget_get_direction (GTK_WIDGET (entry));
-
-  if (GTK_WIDGET_DRAWABLE (entry) && GTK_ENTRY(entry)->cursor_visible)
-    {
-      GtkWidget *widget = GTK_WIDGET (entry);
-      GdkRectangle cursor_location;
-      gboolean split_cursor;
-
-      gint xoffset = INNER_BORDER - entry->scroll_offset;
-      gint strong_x, weak_x;
-      gint text_area_height;
-      GtkTextDirection dir1 = GTK_TEXT_DIR_NONE;
-      GtkTextDirection dir2 = GTK_TEXT_DIR_NONE;
-      gint x1 = 0;
-      gint x2 = 0;
-      GdkGC *gc;
-
-      gdk_window_get_size (entry->text_area, NULL, &text_area_height);
-
-      gtk_entry_get_cursor_locations (entry, type, &strong_x, &weak_x);
-
-      g_object_get (gtk_widget_get_settings (widget),
-                   "gtk-split-cursor", &split_cursor,
-                   NULL);
-
-      dir1 = widget_direction;
-
-      if (split_cursor)
-       {
-         x1 = strong_x;
-
-         if (weak_x != strong_x)
-           {
-             dir2 = (widget_direction == GTK_TEXT_DIR_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
-             x2 = weak_x;
-           }
-       }
-      else
-       {
-         if (keymap_direction == widget_direction)
-           x1 = strong_x;
-         else
-           x1 = weak_x;
-       }
-
-      cursor_location.x = xoffset + x1;
-      cursor_location.y = INNER_BORDER;
-      cursor_location.width = 0;
-      cursor_location.height = text_area_height - 2 * INNER_BORDER ;
-
-      gc = _gtkextra_get_insertion_cursor_gc (widget, TRUE);
-      _gtkextra_draw_insertion_cursor (widget, entry->text_area, gc,
-                                 &cursor_location, dir1,
-                                  dir2 != GTK_TEXT_DIR_NONE);
-      g_object_unref (gc);
-
-      if (dir2 != GTK_TEXT_DIR_NONE)
-       {
-         cursor_location.x = xoffset + x2;
-         gc = _gtkextra_get_insertion_cursor_gc (widget, FALSE);
-         _gtkextra_draw_insertion_cursor (widget, entry->text_area, gc,
-                                     &cursor_location, dir2,
-                                      TRUE);
-         g_object_unref (gc);
-       }
-    }
-}
-
-static void
-gtk_entry_queue_draw (GtkEntry *entry)
-{
-  if (GTK_WIDGET_REALIZED (entry))
-    gdk_window_invalidate_rect (entry->text_area, NULL, FALSE);
-}
-
-static void
-gtk_entry_reset_im_context (GtkEntry *entry)
-{
-  if (entry->need_im_reset)
-    {
-      entry->need_im_reset = 0;
-      gtk_im_context_reset (entry->im_context);
-    }
-}
-
-static void
-gtk_entry_get_cursor_locations (GtkEntry   *entry,
-                               CursorType  type,
-                               gint       *strong_x,
-                               gint       *weak_x)
-{
-  PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
-  const gchar *text;
-  PangoRectangle strong_pos, weak_pos;
-  gint index;
-
-  if (type == CURSOR_STANDARD)
-    {
-      text = pango_layout_get_text (layout);
-      index = g_utf8_offset_to_pointer (text, entry->current_pos + entry->preedit_cursor) - text;
-    }
-  else /* type == CURSOR_DND */
-    {
-      index = g_utf8_offset_to_pointer (entry->text, entry->dnd_position) - entry->text;
-      if (entry->dnd_position > entry->current_pos)
-       index += entry->preedit_length;
-    }
-
-  pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
-
-  if (strong_x)
-    *strong_x = strong_pos.x / PANGO_SCALE;
-
-  if (weak_x)
-    *weak_x = weak_pos.x / PANGO_SCALE;
-}
-
-static void
-gtk_entry_adjust_scroll (GtkEntry *entry)
-{
-  gint min_offset, max_offset;
-  gint text_area_width;
-  gint strong_x, weak_x;
-  PangoLayout *layout;
-  PangoLayoutLine *line;
-  PangoRectangle logical_rect;
-  GtkItemEntry *item_entry;
-  gint text_width;
-
-  if (!GTK_WIDGET_REALIZED (entry))
-    return;
-
-  item_entry = GTK_ITEM_ENTRY(entry);
-
-  gdk_window_get_size (entry->text_area, &text_area_width, NULL);
-  text_area_width -= 2 * INNER_BORDER;
-
-  layout = gtk_entry_ensure_layout (entry, TRUE);
-  line = pango_layout_get_lines (layout)->data;
-
-  pango_layout_line_get_extents (line, NULL, &logical_rect);
-  text_width = logical_rect.width / PANGO_SCALE + 2; /* 2 for cursor */
-
-  gtk_entry_get_cursor_locations (entry, CURSOR_STANDARD, &strong_x, &weak_x);
-
-  /* Display as much text as we can */
-
-  if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_LTR)
-    {
-      entry->scroll_offset = 0;
-      switch(item_entry->justification){
-
-        case GTK_JUSTIFY_FILL:
-        case GTK_JUSTIFY_LEFT:
-
-/* LEFT JUSTIFICATION */
-
-          strong_x -= entry->scroll_offset;
-          if (strong_x < 0)
-            entry->scroll_offset += strong_x;
-          else if (strong_x > text_area_width){
-            if(item_entry->text_max_size != 0 &&
-               text_area_width + 2 <= item_entry->text_max_size){
-               GtkAllocation allocation;
-               allocation = GTK_WIDGET(entry)->allocation;
-               allocation.width += text_width - text_area_width;
-               entry->scroll_offset = 0;
-               gtk_entry_size_allocate(GTK_WIDGET(entry), &allocation);
-            }else{
-               entry->scroll_offset += (strong_x - text_area_width) + 1;
-            }
-          }
-
-          break;
-
-        case GTK_JUSTIFY_RIGHT:
-
-    /* RIGHT JUSTIFICATION FOR NUMBERS */
-          if(entry->text){
-
-            entry->scroll_offset=  -(text_area_width - text_width) + 1;
-            if(entry->scroll_offset > 0){
-              if(item_entry->text_max_size != 0 &&
-                text_area_width + 2 <= item_entry->text_max_size){
-                GtkAllocation allocation;
-                allocation = GTK_WIDGET(entry)->allocation;
-                allocation.x -= text_width - text_area_width;
-                allocation.width += text_width - text_area_width;
-                entry->scroll_offset = 0;
-                gtk_entry_size_allocate(GTK_WIDGET(entry), &allocation);
-              }
-              else
-              {
-                entry->scroll_offset= -(text_area_width - strong_x) + 1;
-                if(entry->scroll_offset < 0) entry->scroll_offset = 0;
-              }
-            }
-          }
-          else
-            entry->scroll_offset=0;
-
-          break;
-        case GTK_JUSTIFY_CENTER:
-
-          if(entry->text){
-
-            entry->scroll_offset=  -(text_area_width - text_width)/2;
-            if(entry->scroll_offset > 0){
-              if(item_entry->text_max_size != 0 &&
-                          text_area_width+1<=item_entry->text_max_size){
-                GtkAllocation allocation;
-                allocation = GTK_WIDGET(entry)->allocation;
-                allocation.x += (text_area_width/2 - text_width/2);
-                allocation.width += text_width - text_area_width;
-                entry->scroll_offset = 0;
-                gtk_entry_size_allocate(GTK_WIDGET(entry), &allocation);
-              }
-              else
-              {
-                entry->scroll_offset= -(text_area_width - strong_x) + 1;
-                if(entry->scroll_offset < 0) entry->scroll_offset = 0;
-              }
-            }
-          }
-          else
-            entry->scroll_offset=0;
-
-          break;
-
-      }
-
-    }
-  else
-    {
-      max_offset = text_width - text_area_width;
-      min_offset = MIN (0, max_offset);
-      entry->scroll_offset = CLAMP (entry->scroll_offset, min_offset, max_offset);
-    }
-
-  g_object_notify (G_OBJECT (entry), "scroll_offset");
-}
-
-static gint
-gtk_entry_move_visually (GtkEntry *entry,
-                        gint      start,
-                        gint      count)
-{
-  gint index;
-  PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
-  const gchar *text;
-
-  text = pango_layout_get_text (layout);
-
-  index = g_utf8_offset_to_pointer (text, start) - text;
-
-  while (count != 0)
-    {
-      int new_index, new_trailing;
-      gboolean split_cursor;
-      gboolean strong;
-
-      g_object_get (gtk_widget_get_settings (GTK_WIDGET (entry)),
-                   "gtk-split-cursor", &split_cursor,
-                   NULL);
-
-      if (split_cursor)
-       strong = TRUE;
-      else
-       {
-         GtkTextDirection keymap_direction =
-           (gdk_keymap_get_direction (gdk_keymap_get_default ()) == PANGO_DIRECTION_LTR) ?
-           GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
-
-         strong = keymap_direction == gtk_widget_get_direction (GTK_WIDGET (entry));
-       }
-
-      if (count > 0)
-       {
-         pango_layout_move_cursor_visually (layout, strong, index, 0, 1, &new_index, &new_trailing);
-         count--;
-       }
-      else
-       {
-         pango_layout_move_cursor_visually (layout, strong, index, 0, -1, &new_index, &new_trailing);
-         count++;
-       }
-
-      if (new_index < 0 || new_index == G_MAXINT)
-       break;
-
-      index = new_index;
-
-      while (new_trailing--)
-       index = g_utf8_next_char (entry->text + new_index) - entry->text;
-    }
-
-  return g_utf8_pointer_to_offset (text, text + index);
-}
-
-static gint
-gtk_entry_move_logically (GtkEntry *entry,
-                         gint      start,
-                         gint      count)
-{
-  gint new_pos = start;
-
-  /* Prevent any leak of information */
-  if (!entry->visible)
-    {
-      new_pos = CLAMP (start + count, 0, entry->text_length);
-    }
-  else if (entry->text)
-    {
-      PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
-      PangoLogAttr *log_attrs;
-      gint n_attrs;
-
-      pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
-
-      while (count > 0 && new_pos < entry->text_length)
-       {
-         do
-           new_pos++;
-         while (new_pos < entry->text_length && !log_attrs[new_pos].is_cursor_position);
-
-         count--;
-       }
-      while (count < 0 && new_pos > 0)
-       {
-         do
-           new_pos--;
-         while (new_pos > 0 && !log_attrs[new_pos].is_cursor_position);
-
-         count++;
-       }
-
-      g_free (log_attrs);
-    }
-
-  return new_pos;
-}
-
-static gint
-gtk_entry_move_forward_word (GtkEntry *entry,
-                            gint      start)
-{
-  gint new_pos = start;
-
-  /* Prevent any leak of information */
-  if (!entry->visible)
-    {
-      new_pos = entry->text_length;
-    }
-  else if (entry->text && (new_pos < entry->text_length))
-    {
-      PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
-      PangoLogAttr *log_attrs;
-      gint n_attrs;
-
-      pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
-
-      /* Find the next word end */
-      new_pos++;
-      while (new_pos < n_attrs && !log_attrs[new_pos].is_word_end)
-       new_pos++;
-
-      g_free (log_attrs);
-    }
-
-  return new_pos;
-}
-
-
-static gint
-gtk_entry_move_backward_word (GtkEntry *entry,
-                             gint      start)
-{
-  gint new_pos = start;
-
-  /* Prevent any leak of information */
-  if (!entry->visible)
-    {
-      new_pos = 0;
-    }
-  else if (entry->text && start > 0)
-    {
-      PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
-      PangoLogAttr *log_attrs;
-      gint n_attrs;
-
-      pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
-
-      new_pos = start - 1;
-
-      /* Find the previous word beginning */
-      while (new_pos > 0 && !log_attrs[new_pos].is_word_start)
-       new_pos--;
-
-      g_free (log_attrs);
-    }
-
-  return new_pos;
-}
-
-static void
-gtk_entry_delete_whitespace (GtkEntry *entry)
-{
-  PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
-  PangoLogAttr *log_attrs;
-  gint n_attrs;
-  gint start, end;
-
-  pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
-
-  start = end = entry->current_pos;
-
-  while (start > 0 && log_attrs[start-1].is_white)
-    start--;
-
-  while (end < n_attrs && log_attrs[end].is_white)
-    end++;
-
-  g_free (log_attrs);
-
-  if (start != end)
-    gtk_editable_delete_text (GTK_EDITABLE (entry), start, end);
-}
-
-
-/*
- * Like gtk_editable_get_chars, but if the editable is not
- * visible, return asterisks; also convert result to UTF-8.
- */
-static char *
-gtk_entry_get_public_chars (GtkEntry *entry,
-                           gint      start,
-                           gint      end)
-{
-  if (end < 0)
-    end = entry->text_length;
-
-  if (entry->visible)
-    return gtk_editable_get_chars (GTK_EDITABLE (entry), start, end);
-  else
-    {
-      gchar *str;
-      gint i;
-      gint n_chars = end - start;
-
-      str = g_malloc (n_chars + 1);
-      for (i = 0; i < n_chars; i++)
-       str[i] = '*';
-      str[i] = '\0';
-
-      return str;
-    }
-
-}
-
-static void
-primary_get_cb (GtkClipboard     *clipboard,
-               GtkSelectionData *selection_data,
-               guint             info,
-               gpointer          data)
-{
-  GtkEntry *entry = GTK_ENTRY (data);
-  gint start, end;
-
-  if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
-    {
-      gchar *str = gtk_entry_get_public_chars (entry, start, end);
-      gtk_selection_data_set_text (selection_data, str, -1);
-      g_free (str);
-    }
-}
-
-static void
-primary_clear_cb (GtkClipboard *clipboard,
-                 gpointer      data)
-{
-  GtkEntry *entry = GTK_ENTRY (data);
-
-  gtk_editable_select_region (GTK_EDITABLE (entry), entry->current_pos, entry->current_pos);
-}
-
-static void
-gtk_entry_update_primary_selection (GtkEntry *entry)
-{
-  static const GtkTargetEntry targets[] = {
-    { "UTF8_STRING", 0, 0 },
-    { "STRING", 0, 0 },
-    { "TEXT",   0, 0 },
-    { "COMPOUND_TEXT", 0, 0 }
-  };
-
-  GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
-  gint start, end;
-
-  if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
-    {
-      if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets),
-                                        primary_get_cb, primary_clear_cb, G_OBJECT (entry)))
-       primary_clear_cb (clipboard, entry);
-    }
-  else
-    {
-      if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (entry))
-       gtk_clipboard_clear (clipboard);
-    }
-}
-
-/* Public API
- */
-
-GtkWidget*
-gtk_item_entry_new (void)
-{
-  GtkWidget *widget;
-
-  widget = GTK_WIDGET (gtk_type_new (GTK_TYPE_ITEM_ENTRY));
-  return widget;
-}
-
-GtkWidget*
-gtk_item_entry_new_with_max_length (gint max)
-{
-  GtkItemEntry *entry;
-
-  entry = gtk_type_new (GTK_TYPE_ITEM_ENTRY);
-  gtk_entry_set_max_length(GTK_ENTRY(entry), max);
-
-  return GTK_WIDGET (entry);
-}
-
-void
-gtk_item_entry_set_text (GtkItemEntry    *entry,
-                        const gchar *text,
-                         GtkJustification justification)
-{
-  gint tmp_pos;
-
-  g_return_if_fail (GTK_IS_ITEM_ENTRY (entry));
-  g_return_if_fail (text != NULL);
-
-  entry->justification = justification;
-
-  /* Actually setting the text will affect the cursor and selection;
-   * if the contents don't actually change, this will look odd to the user.
-   */
-  if (strcmp (GTK_ENTRY(entry)->text, text) == 0)
-    return;
-
-  if (GTK_ENTRY(entry)->recompute_idle){
-    g_source_remove (GTK_ENTRY(entry)->recompute_idle);
-    GTK_ENTRY(entry)->recompute_idle = 0;
-  }
-  if (GTK_ENTRY(entry)->blink_timeout){
-    g_source_remove (GTK_ENTRY(entry)->blink_timeout);
-    GTK_ENTRY(entry)->blink_timeout = 0;
-  }
-
-  gtk_editable_delete_text (GTK_EDITABLE (entry), 0, -1);
-
-  tmp_pos = 0;
-  gtk_editable_insert_text (GTK_EDITABLE (entry), text, strlen (text), &tmp_pos);
-}
-
-/**
- * gtk_entry_get_layout_offsets:
- * @entry: a #GtkEntry
- * @x: location to store X offset of layout, or %NULL
- * @y: location to store Y offset of layout, or %NULL
- *
- *
- * Obtains the position of the #PangoLayout used to render text
- * in the entry, in widget coordinates. Useful if you want to line
- * up the text in an entry with some other text, e.g. when using the
- * entry to implement editable cells in a sheet widget.
- *
- * Also useful to convert mouse events into coordinates inside the
- * #PangoLayout, e.g. to take some action if some part of the entry text
- * is clicked.
- *
- * Note that as the user scrolls around in the entry the offsets will
- * change; you'll need to connect to the "notify::scroll_offset"
- * signal to track this. Remember when using the #PangoLayout
- * functions you need to convert to and from pixels using
- * PANGO_PIXELS() or #PANGO_SCALE.
- *
- * Keep in mind that the layout text may contain a preedit string, so
- * gtk_entry_layout_index_to_text_index() and
- * gtk_entry_text_index_to_layout_index() are needed to convert byte
- * indices in the layout to byte indices in the entry contents.
- *
- **/
-void
-gtk_item_entry_get_layout_offsets (GtkItemEntry *entry,
-                                   gint     *x,
-                                   gint     *y)
-{
-  gint text_area_x, text_area_y;
-
-  g_return_if_fail (GTK_IS_ITEM_ENTRY (entry));
-
-  /* this gets coords relative to text area */
-  get_layout_position (GTK_ENTRY(entry), x, y);
-
-  /* convert to widget coords */
-  get_text_area_size (GTK_ENTRY(entry), &text_area_x, &text_area_y, NULL, NULL);
-
-  if (x)
-    *x += text_area_x;
-
-  if (y)
-    *y += text_area_y;
-}
-
-void
-gtk_item_entry_set_justification(GtkItemEntry *entry, GtkJustification just)
-{
-  g_return_if_fail (GTK_IS_ITEM_ENTRY (entry));
-
-  entry->justification = just;
-}
-
-
-/* We display the cursor when
- *
- *  - the selection is empty, AND
- *  - the widget has focus
- */
-
-#define CURSOR_ON_MULTIPLIER 0.66
-#define CURSOR_OFF_MULTIPLIER 0.34
-#define CURSOR_PEND_MULTIPLIER 1.0
-
-static gboolean
-cursor_blinks (GtkEntry *entry)
-{
-  GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (entry));
-  gboolean blink;
-
-  if (GTK_WIDGET_HAS_FOCUS (entry) &&
-      entry->selection_bound == entry->current_pos)
-    {
-      g_object_get (G_OBJECT (settings), "gtk-cursor-blink", &blink, NULL);
-      return blink;
-    }
-  else
-    return FALSE;
-}
-
-static gint
-get_cursor_time (GtkEntry *entry)
-{
-  GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (entry));
-  gint time;
-
-  g_object_get (G_OBJECT (settings), "gtk-cursor-blink-time", &time, NULL);
-
-  return time;
-}
-
-static void
-show_cursor (GtkEntry *entry)
-{
-  if (!entry->cursor_visible)
-    {
-      entry->cursor_visible = TRUE;
-
-      if (GTK_WIDGET_HAS_FOCUS (entry) && entry->selection_bound == entry->current_pos)
-       gtk_widget_queue_draw (GTK_WIDGET (entry));
-    }
-}
-
-static void
-hide_cursor (GtkEntry *entry)
-{
-  if (entry->cursor_visible)
-    {
-      entry->cursor_visible = FALSE;
-
-      if (GTK_WIDGET_HAS_FOCUS (entry) && entry->selection_bound == entry->current_pos)
-       gtk_widget_queue_draw (GTK_WIDGET (entry));
-    }
-}
-
-/*
- * Blink!
- */
-static gint
-blink_cb (gpointer data)
-{
-  GtkEntry *entry;
-
-  GDK_THREADS_ENTER ();
-
-  entry = GTK_ENTRY (data);
-
-  g_assert (GTK_WIDGET_HAS_FOCUS (entry));
-  g_assert (entry->selection_bound == entry->current_pos);
-
-  if (entry->cursor_visible)
-    {
-      hide_cursor (entry);
-      entry->blink_timeout = gtk_timeout_add (get_cursor_time (entry) * CURSOR_OFF_MULTIPLIER,
-                                             blink_cb,
-                                             entry);
-    }
-  else
-    {
-      show_cursor (entry);
-      entry->blink_timeout = gtk_timeout_add (get_cursor_time (entry) * CURSOR_ON_MULTIPLIER,
-                                             blink_cb,
-                                             entry);
-    }
-
-  GDK_THREADS_LEAVE ();
-
-  /* Remove ourselves */
-  return FALSE;
-}
-
-static void
-gtk_entry_check_cursor_blink (GtkEntry *entry)
-{
-  if (cursor_blinks (entry))
-    {
-      if (!entry->blink_timeout)
-       {
-         entry->blink_timeout = gtk_timeout_add (get_cursor_time (entry) * CURSOR_ON_MULTIPLIER,
-                                                 blink_cb,
-                                                 entry);
-         show_cursor (entry);
-       }
-    }
-  else
-    {
-      if (entry->blink_timeout)
-       {
-         gtk_timeout_remove (entry->blink_timeout);
-         entry->blink_timeout = 0;
-       }
-
-      entry->cursor_visible = TRUE;
-    }
-
-}
-
-static void
-gtk_entry_pend_cursor_blink (GtkEntry *entry)
-{
-  if (cursor_blinks (entry))
-    {
-      if (entry->blink_timeout != 0)
-       gtk_timeout_remove (entry->blink_timeout);
-
-      entry->blink_timeout = gtk_timeout_add (get_cursor_time (entry) * CURSOR_PEND_MULTIPLIER,
-                                             blink_cb,
-                                             entry);
-      show_cursor (entry);
-    }
-}
-
-void
-gtk_item_entry_set_cursor_visible(GtkItemEntry *entry, gboolean visible)
-{
-  g_return_if_fail (GTK_IS_ITEM_ENTRY (entry));
-
-  GTK_ENTRY(entry)->cursor_visible = visible;
-}
-
-gboolean
-gtk_item_entry_get_cursor_visible(GtkItemEntry *entry)
-{
-  g_return_val_if_fail (GTK_IS_ITEM_ENTRY (entry), FALSE);
-
-  return(GTK_ENTRY(entry)->cursor_visible);
-}
diff --git a/lib/gtksheet/gtkitementry.h b/lib/gtksheet/gtkitementry.h
deleted file mode 100644 (file)
index 11fab7a..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* GtkItemEntry - widget for gtk+
- * Copyright (C) 1999-2001 Adrian E. Feiguin <adrian@ifir.ifir.edu.ar>
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * GtkItemEntry widget by Adrian E. Feiguin
- * Based on GtkEntry widget
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef __GTK_ITEM_ENTRY_H__
-#define __GTK_ITEM_ENTRY_H__
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-#define GTK_TYPE_ITEM_ENTRY            (gtk_item_entry_get_type ())
-#define GTK_ITEM_ENTRY(obj)            (GTK_CHECK_CAST (obj, gtk_item_entry_get_type (), GtkItemEntry))
-#define GTK_ITEM_ENTRY_CLASS(klass)    (GTK_CHECK_CLASS_CAST (klass, gtk_item_entry_get_type (), GtkItemEntryClass))
-#define GTK_IS_ITEM_ENTRY(obj)         (GTK_CHECK_TYPE (obj, gtk_item_entry_get_type ()))
-#define GTK_IS_ITEM_ENTRY_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ENTRY))
-
-
-typedef struct _GtkItemEntry       GtkItemEntry;
-typedef struct _GtkItemEntryClass  GtkItemEntryClass;
-
-struct _GtkItemEntry
-{
-  GtkEntry parent;
-
-  gint text_max_size;
-
-  GtkJustification justification;
-};
-
-struct _GtkItemEntryClass
-{
-  GtkEntryClass parent_class;
-};
-
-GtkType    gtk_item_entry_get_type       (void);
-GtkWidget* gtk_item_entry_new            (void);
-GtkWidget* gtk_item_entry_new_with_max_length (gint   max);
-void       gtk_item_entry_set_text            (GtkItemEntry *item_entry,
-                                               const gchar *text,
-                                               GtkJustification justification);
-
-void       gtk_item_entry_set_justification (GtkItemEntry        *item_entry,
-                                            GtkJustification   justification);
-
-void       gtk_item_entry_set_cursor_visible   (GtkItemEntry *entry,
-                                                gboolean visible);
-gboolean   gtk_item_entry_get_cursor_visible   (GtkItemEntry *entry);
-
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
-#endif /* __GTK_ITEM_ENTRY_H__ */
index 942b0233117b4641a61b9dadccbec4fed9f51866..c638c9e7d1dbf96c6161c66ebf70bd754d3e6475 100644 (file)
  *
  * GtkSheet is a matrix widget for GTK+. It consists of an scrollable grid of
  * cells where you can allocate text. Cell contents can be edited interactively
- * through a specially designed entry, GtkItemEntry. It is also a container
- * subclass, allowing you to display buttons, curves, pixmaps and any other
- * widgets in it.
+ * through a specially designed entry, GtkItemEntry.
  *
- * You can also set many attributes as: border, foreground and background color,
- * text justification, and more.
- *
- * The testgtksheet program shows how easy is to create a spreadsheet-like GUI
- * using this widget.
  */
 #include <config.h>
 
 #include <gdk/gdk.h>
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtksignal.h>
-#include <gtk/gtklabel.h>
 #include <gtk/gtkbutton.h>
 #include <gtk/gtkadjustment.h>
-#include <gtk/gtktable.h>
-#include <gtk/gtkbox.h>
-#include <gtk/gtkmain.h>
 #include <gtk/gtktypeutils.h>
 #include <gtk/gtkentry.h>
 #include <gtk/gtkcontainer.h>
-#include <gtk/gtkpixmap.h>
 #include <pango/pango.h>
-#include "gtkitementry.h"
 #include "gtksheet.h"
-#include "gtkextra-marshal.h"
+#include <gtksheet/psppire-marshal.h>
 #include "gsheetmodel.h"
+#include <libpspp/misc.h>
+#include <math.h>
 
 /* sheet flags */
 enum
   {
-    GTK_SHEET_IS_FROZEN = 1 << 1,
-    GTK_SHEET_IN_XDRAG = 1 << 2,
-    GTK_SHEET_IN_YDRAG = 1 << 3,
-    GTK_SHEET_IN_DRAG = 1 << 4,
-    GTK_SHEET_IN_SELECTION = 1 << 5,
-    GTK_SHEET_IN_RESIZE = 1 << 6,
-    GTK_SHEET_REDRAW_PENDING = 1 << 7,
+    GTK_SHEET_IN_XDRAG = 1 << 1,
+    GTK_SHEET_IN_YDRAG = 1 << 2,
+    GTK_SHEET_IN_DRAG = 1 << 3,
+    GTK_SHEET_IN_SELECTION = 1 << 4,
+    GTK_SHEET_IN_RESIZE = 1 << 5
   };
 
 #define GTK_SHEET_FLAGS(sheet) (GTK_SHEET (sheet)->flags)
 #define GTK_SHEET_SET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) |= (flag))
 #define GTK_SHEET_UNSET_FLAGS(sheet,flag) (GTK_SHEET_FLAGS (sheet) &= ~ (flag))
 
-#define GTK_SHEET_IS_FROZEN(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_FROZEN)
 #define GTK_SHEET_IN_XDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_XDRAG)
 #define GTK_SHEET_IN_YDRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_YDRAG)
 #define GTK_SHEET_IN_DRAG(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_DRAG)
 #define GTK_SHEET_IN_SELECTION(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_SELECTION)
 #define GTK_SHEET_IN_RESIZE(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_RESIZE)
-#define GTK_SHEET_REDRAW_PENDING(sheet) (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_REDRAW_PENDING)
 
 #define CELL_SPACING 1
-#define DRAG_WIDTH 6
+
 #define TIMEOUT_HOVER 300
 #define COLUMN_MIN_WIDTH 10
-#define CELLOFFSET 4
+#define COLUMN_TITLES_HEIGHT 4
 #define DEFAULT_COLUMN_WIDTH 80
+#define DEFAULT_ROW_HEIGHT 25
+
+static void set_entry_widget_font (GtkSheet *sheet);
 
 static void gtk_sheet_update_primary_selection (GtkSheet *sheet);
-static void gtk_sheet_column_title_button_draw (GtkSheet *sheet, gint column);
+static void draw_column_title_buttons_range (GtkSheet *sheet, gint first, gint n);
+static void draw_row_title_buttons_range (GtkSheet *sheet, gint first, gint n);
 
-static void gtk_sheet_row_title_button_draw (GtkSheet *sheet, gint row);
 
+static void gtk_sheet_set_row_height (GtkSheet *sheet,
+                                     gint row,
+                                     guint height);
+
+static void destroy_hover_window (GtkSheetHoverTitle *);
+static GtkSheetHoverTitle *create_hover_window (void);
+
+static GtkStateType gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col);
 
-static gboolean gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col);
 
 static inline  void
 dispose_string (const GtkSheet *sheet, gchar *text)
@@ -120,402 +115,133 @@ dispose_string (const GtkSheet *sheet, gchar *text)
     g_free (text);
 }
 
-static inline
-guint DEFAULT_ROW_HEIGHT (GtkWidget *widget)
-{
-  if (!widget->style->font_desc) return 24;
-  else
-    {
-      PangoContext *context = gtk_widget_get_pango_context (widget);
-      PangoFontMetrics *metrics =
-       pango_context_get_metrics (context,
-                                  widget->style->font_desc,
-                                  pango_context_get_language (context));
-
-      guint val = pango_font_metrics_get_descent (metrics) +
-       pango_font_metrics_get_ascent (metrics);
-
-      pango_font_metrics_unref (metrics);
-
-      return PANGO_PIXELS (val) + 2 * CELLOFFSET;
-    }
-}
-
-static inline
-guint DEFAULT_FONT_ASCENT (GtkWidget *widget)
-{
-  if (!widget->style->font_desc) return 12;
-  else
-    {
-      PangoContext *context = gtk_widget_get_pango_context (widget);
-      PangoFontMetrics *metrics =
-       pango_context_get_metrics (context,
-                                  widget->style->font_desc,
-                                  pango_context_get_language (context));
-      guint val = pango_font_metrics_get_ascent (metrics);
-      pango_font_metrics_unref (metrics);
-      return PANGO_PIXELS (val);
-    }
-}
-
-static inline
-guint STRING_WIDTH (GtkWidget *widget,
-                   const PangoFontDescription *font, const gchar *text)
-{
-  PangoRectangle rect;
-  PangoLayout *layout;
-
-  layout = gtk_widget_create_pango_layout (widget, text);
-  pango_layout_set_font_description (layout, font);
-
-  pango_layout_get_extents (layout, NULL, &rect);
-
-  g_object_unref (layout);
-  return PANGO_PIXELS (rect.width);
-}
-
-static inline
-guint DEFAULT_FONT_DESCENT (GtkWidget *widget)
-{
-  if (!widget->style->font_desc) return 12;
-  else
-    {
-      PangoContext *context = gtk_widget_get_pango_context (widget);
-      PangoFontMetrics *metrics =
-       pango_context_get_metrics (context,
-                                  widget->style->font_desc,
-                                  pango_context_get_language (context));
-      guint val = pango_font_metrics_get_descent (metrics);
-      pango_font_metrics_unref (metrics);
-      return PANGO_PIXELS (val);
-    }
-}
-
-
-static gint
-yyy_row_is_visible (const GtkSheet *sheet, gint row)
-{
-  GSheetRow *row_geo = sheet->row_geometry;
-
-  return g_sheet_row_get_visibility (row_geo, row);
-}
-
-
-static gint
-yyy_row_is_sensitive (const GtkSheet *sheet, gint row)
-{
-  GSheetRow *row_geo = sheet->row_geometry;
-
-  return g_sheet_row_get_sensitivity (row_geo, row);
-}
-
-
-
-static inline gint
-yyy_row_count (const GtkSheet *sheet)
-{
-  GSheetRow *row_geo = sheet->row_geometry;
-
-  return g_sheet_row_get_row_count (row_geo);
-}
-
-static inline gint
-yyy_row_height (const GtkSheet *sheet, gint row)
-{
-  GSheetRow *row_geo = sheet->row_geometry;
-
-  return g_sheet_row_get_height (row_geo, row);
-}
-
-static gint
-yyy_row_top_ypixel (const GtkSheet *sheet, gint row)
-{
-  GSheetRow *geo = sheet->row_geometry;
-
-  gint y = g_sheet_row_start_pixel (geo, row);
-
-  if ( sheet->column_titles_visible )
-    y += sheet->column_title_area.height;
-
-  return y;
-}
-
-
-/* Return the row containing pixel Y */
-static gint
-yyy_row_ypixel_to_row (const GtkSheet *sheet, gint y)
-{
-  GSheetRow *geo = sheet->row_geometry;
-
-  gint cy = sheet->voffset;
-
-  if (sheet->column_titles_visible)
-    cy += sheet->column_title_area.height;
-
-  if (y < cy) return 0;
-
-  return g_sheet_row_pixel_to_row (geo, y - cy);
-}
 
+/* FIXME: Why bother with these two ? */
 
-/* gives the top pixel of the given row in context of
- * the sheet's voffset */
+/* returns the column index from a pixel location */
 static inline gint
-ROW_TOP_YPIXEL (const GtkSheet *sheet, gint row)
+column_from_xpixel (const GtkSheet *sheet, gint pixel)
 {
-  return (sheet->voffset + yyy_row_top_ypixel (sheet, row));
+  return psppire_axis_get_unit_at_pixel (sheet->haxis, pixel);
 }
 
-
-/* returns the row index from a y pixel location in the
- * context of the sheet's voffset */
 static inline gint
-ROW_FROM_YPIXEL (const GtkSheet *sheet, gint y)
+row_from_ypixel (const GtkSheet *sheet, gint pixel)
 {
-  return (yyy_row_ypixel_to_row (sheet, y));
-}
-
-static inline GtkSheetButton *
-xxx_column_button (const GtkSheet *sheet, gint col)
-{
-  GSheetColumn *col_geo = sheet->column_geometry;
-  if ( col < 0 ) return NULL ;
-
-  return g_sheet_column_get_button (col_geo, col);
+  return psppire_axis_get_unit_at_pixel (sheet->vaxis, pixel);
 }
 
 
-static inline gint
-xxx_column_left_xpixel (const GtkSheet *sheet, gint col)
+/* Return the lowest row number which is wholly or partially on
+   the visible range of the sheet */
+static inline glong
+min_visible_row (const GtkSheet *sheet)
 {
-  GSheetColumn *geo = sheet->column_geometry;
-
-  gint x = g_sheet_column_start_pixel (geo, col);
-
-  if ( sheet->row_titles_visible )
-    x += sheet->row_title_area.width;
-
-  return x;
+  return row_from_ypixel (sheet, sheet->vadjustment->value);
 }
 
-static inline gint
-xxx_column_width (const GtkSheet *sheet, gint col)
+static inline glong
+min_fully_visible_row (const GtkSheet *sheet)
 {
-  GSheetColumn *col_geo = sheet->column_geometry;
-
-  return g_sheet_column_get_width (col_geo, col);
-}
+  glong row = min_visible_row (sheet);
 
+  if ( psppire_axis_pixel_start (sheet->vaxis, row) < sheet->vadjustment->value)
+    row++;
 
-static inline void
-xxx_set_column_width (GtkSheet *sheet, gint col, gint width)
-{
-  if ( sheet->column_geometry )
-    g_sheet_column_set_width (sheet->column_geometry, col, width);
+  return row;
 }
 
-static inline void
-xxx_column_set_left_column (GtkSheet *sheet, gint col, gint i)
+static inline glong
+max_visible_row (const GtkSheet *sheet)
 {
-  GSheetColumn *col_geo = sheet->column_geometry;
-
-  g_sheet_column_set_left_text_column (col_geo, col, i);
+  return row_from_ypixel (sheet, sheet->vadjustment->value + sheet->vadjustment->page_size);
 }
 
-static inline gint
-xxx_column_left_column (const GtkSheet *sheet, gint col)
-{
-  GSheetColumn *col_geo = sheet->column_geometry;
-
-  return g_sheet_column_get_left_text_column (col_geo, col);
-}
 
-static inline void
-xxx_column_set_right_column (GtkSheet *sheet, gint col, gint i)
+static inline glong
+max_fully_visible_row (const GtkSheet *sheet)
 {
-  GSheetColumn *col_geo = sheet->column_geometry;
-
-  g_sheet_column_set_right_text_column (col_geo, col, i);
-}
+  glong row = max_visible_row (sheet);
 
-static inline gint
-xxx_column_right_column (const GtkSheet *sheet, gint col)
-{
-  GSheetColumn *col_geo = sheet->column_geometry;
+  if ( psppire_axis_pixel_start (sheet->vaxis, row)
+       +
+       psppire_axis_unit_size (sheet->vaxis, row)
+       > sheet->vadjustment->value)
+    row--;
 
-  return g_sheet_column_get_right_text_column (col_geo, col);
+  return row;
 }
 
-static inline GtkJustification
-xxx_column_justification (const GtkSheet *sheet, gint col)
-{
-  GSheetColumn *col_geo = sheet->column_geometry;
-
-  return g_sheet_column_get_justification (col_geo, col);
-}
 
-static inline gint
-xxx_column_is_visible (const GtkSheet *sheet, gint col)
+/* Returns the lowest column number which is wholly or partially
+   on the sheet */
+static inline glong
+min_visible_column (const GtkSheet *sheet)
 {
-  GSheetColumn *col_geo = sheet->column_geometry;
-
-  return g_sheet_column_get_visibility (col_geo, col);
+  return column_from_xpixel (sheet, sheet->hadjustment->value);
 }
 
-
-static inline gint
-xxx_column_is_sensitive (const GtkSheet *sheet, gint col)
+static inline glong
+min_fully_visible_column (const GtkSheet *sheet)
 {
-  GSheetColumn *col_geo = sheet->column_geometry;
-
-  return g_sheet_column_get_sensitivity (col_geo, col);
-}
+  glong col = min_visible_column (sheet);
 
+  if ( psppire_axis_pixel_start (sheet->haxis, col) < sheet->hadjustment->value)
+    col++;
 
-/* gives the left pixel of the given column in context of
- * the sheet's hoffset */
-static inline gint
-COLUMN_LEFT_XPIXEL (const GtkSheet *sheet, gint ncol)
-{
-  return (sheet->hoffset + xxx_column_left_xpixel (sheet, ncol));
+  return col;
 }
 
-static inline gint
-xxx_column_count (const GtkSheet *sheet)
-{
-  GSheetColumn *col_geo = sheet->column_geometry;
-
-  return g_sheet_column_get_column_count (col_geo);
-}
 
-/* returns the column index from a x pixel location in the
- * context of the sheet's hoffset */
-static inline gint
-COLUMN_FROM_XPIXEL (const GtkSheet * sheet,
-                   gint x)
+/* Returns the highest column number which is wholly or partially
+   on the sheet */
+static inline glong
+max_visible_column (const GtkSheet *sheet)
 {
-  gint i, cx;
-
-  cx = sheet->hoffset;
-  if ( sheet->row_titles_visible )
-    cx += sheet->row_title_area.width;
-
-  if (x < cx) return 0;
-  for (i = 0; i < xxx_column_count (sheet); i++)
-    {
-      if (x >= cx && x <= (cx + xxx_column_width (sheet, i)) &&
-         xxx_column_is_visible (sheet, i))
-       return i;
-      if ( xxx_column_is_visible (sheet, i))
-       cx += xxx_column_width (sheet, i);
-    }
-
-  /* no match */
-  return xxx_column_count (sheet) - 1;
+  return column_from_xpixel (sheet, sheet->hadjustment->value + sheet->hadjustment->page_size);
 }
 
-/* returns the total height of the sheet */
-static inline gint SHEET_HEIGHT (GtkSheet *sheet)
+static inline glong
+max_fully_visible_column (const GtkSheet *sheet)
 {
-  const gint n_rows = yyy_row_count (sheet);
-
-  return yyy_row_top_ypixel (sheet, n_rows - 1) +
-    yyy_row_height (sheet, n_rows - 1);
-}
+  glong col = max_visible_column (sheet);
 
+  if ( psppire_axis_pixel_start (sheet->haxis, col)
+       + 
+       psppire_axis_unit_size (sheet->haxis, col)
+       > sheet->hadjustment->value)
+    col--;
 
-static inline GtkSheetButton *
-yyy_row_button (GtkSheet *sheet, gint row)
-{
-  GSheetRow *row_geo = sheet->row_geometry;
-
-  return g_sheet_row_get_button (row_geo, row);
+  return col;
 }
 
 
 
+/* The size of the region (in pixels) around the row/column boundaries
+   where the height/width may be grabbed to change size */
+#define DRAG_WIDTH 6
 
-static inline void
-yyy_set_row_height (GtkSheet *sheet, gint row, gint height)
-{
-  if ( sheet->row_geometry )
-    g_sheet_row_set_height (sheet->row_geometry, row, height);
-}
-
-
-
-/* returns the total width of the sheet */
-static inline gint SHEET_WIDTH (GtkSheet *sheet)
+static gboolean
+on_column_boundary (const GtkSheet *sheet, gint x, gint *column)
 {
-  gint i, cx;
-
-  cx = ( sheet->row_titles_visible ? sheet->row_title_area.width : 0);
-
-  for (i = 0; i < xxx_column_count (sheet); i++)
-    if (xxx_column_is_visible (sheet, i))
-      cx += xxx_column_width (sheet, i);
-
-  return cx;
-}
-
-#define MIN_VISIBLE_ROW(sheet) \
-    ROW_FROM_YPIXEL (sheet, sheet->column_title_area.height + 1)
-
-#define MAX_VISIBLE_ROW(sheet) \
-    ROW_FROM_YPIXEL (sheet, sheet->sheet_window_height - 1)
-
-#define MIN_VISIBLE_COLUMN(sheet) \
-    COLUMN_FROM_XPIXEL (sheet, sheet->row_title_area.width + 1)
-
-#define MAX_VISIBLE_COLUMN(sheet) \
-    COLUMN_FROM_XPIXEL (sheet, sheet->sheet_window_width)
-
-
+  gint col;
 
-static inline gboolean
-POSSIBLE_XDRAG (const GtkSheet *sheet, gint x, gint *drag_column)
-{
-  gint column, xdrag;
+  x += sheet->hadjustment->value;
 
-  column = COLUMN_FROM_XPIXEL (sheet, x);
-  *drag_column = column;
+  col = column_from_xpixel (sheet, x);
 
-  xdrag = COLUMN_LEFT_XPIXEL (sheet, column) + CELL_SPACING;
-  if (x <= xdrag + DRAG_WIDTH / 2 && column != 0)
+  if ( column_from_xpixel (sheet, x - DRAG_WIDTH / 2) < col )
     {
-      while (! xxx_column_is_visible (sheet, column - 1) && column > 0) column--;
-      *drag_column = column - 1;
-      return xxx_column_is_sensitive (sheet, column - 1);
+      *column = col - 1;
+      return TRUE;
     }
 
-  xdrag += xxx_column_width (sheet, column);
-  if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2)
-    return xxx_column_is_sensitive (sheet, column);
-
-  return FALSE;
-}
-
-static inline gboolean
-POSSIBLE_YDRAG (const GtkSheet *sheet, gint y, gint *drag_row)
-{
-  gint row, ydrag;
-  row = ROW_FROM_YPIXEL (sheet, y);
-  *drag_row = row;
-
-  ydrag = ROW_TOP_YPIXEL (sheet, row)+CELL_SPACING;
-  if (y <= ydrag + DRAG_WIDTH / 2 && row != 0)
+  if  ( column_from_xpixel (sheet, x + DRAG_WIDTH / 2) > col )
     {
-      while (!yyy_row_is_visible (sheet, row - 1) && row > 0) row--;
-      *drag_row = row - 1;
-      return yyy_row_is_sensitive (sheet, row - 1);
+      *column = col;
+      return TRUE;
     }
 
-  ydrag +=yyy_row_height (sheet, row);
-
-  if (y >= ydrag - DRAG_WIDTH / 2 && y <= ydrag + DRAG_WIDTH / 2)
-    return yyy_row_is_sensitive (sheet, row);
-
-
   return FALSE;
 }
 
@@ -530,21 +256,21 @@ POSSIBLE_DRAG (const GtkSheet *sheet, gint x, gint y,
        sheet->range.col0 < 0 || sheet->range.coli < 0 )
     return FALSE;
 
-  *drag_column = COLUMN_FROM_XPIXEL (sheet, x);
-  *drag_row = ROW_FROM_YPIXEL (sheet, y);
+  *drag_column = column_from_xpixel (sheet, x);
+  *drag_row = row_from_ypixel (sheet, y);
 
-  if (x >= COLUMN_LEFT_XPIXEL (sheet, sheet->range.col0) - DRAG_WIDTH / 2 &&
-      x <= COLUMN_LEFT_XPIXEL (sheet, sheet->range.coli) +
-      xxx_column_width (sheet, sheet->range.coli) + DRAG_WIDTH / 2)
+  if (x >= psppire_axis_pixel_start (sheet->haxis, sheet->range.col0) - DRAG_WIDTH / 2 &&
+      x <= psppire_axis_pixel_start (sheet->haxis, sheet->range.coli) +
+      psppire_axis_unit_size (sheet->haxis, sheet->range.coli) + DRAG_WIDTH / 2)
     {
-      ydrag = ROW_TOP_YPIXEL (sheet, sheet->range.row0);
+      ydrag = psppire_axis_pixel_start (sheet->vaxis, sheet->range.row0);
       if (y >= ydrag - DRAG_WIDTH / 2 && y <= ydrag + DRAG_WIDTH / 2)
        {
          *drag_row = sheet->range.row0;
          return TRUE;
        }
-      ydrag = ROW_TOP_YPIXEL (sheet, sheet->range.rowi) +
-       yyy_row_height (sheet, sheet->range.rowi);
+      ydrag = psppire_axis_pixel_start (sheet->vaxis, sheet->range.rowi) +
+       psppire_axis_unit_size (sheet->vaxis, sheet->range.rowi);
       if (y >= ydrag - DRAG_WIDTH / 2 && y <= ydrag + DRAG_WIDTH / 2)
        {
          *drag_row = sheet->range.rowi;
@@ -552,18 +278,18 @@ POSSIBLE_DRAG (const GtkSheet *sheet, gint x, gint y,
        }
     }
 
-  if (y >= ROW_TOP_YPIXEL (sheet, sheet->range.row0) - DRAG_WIDTH / 2 &&
-      y <= ROW_TOP_YPIXEL (sheet, sheet->range.rowi) +
-      yyy_row_height (sheet, sheet->range.rowi) + DRAG_WIDTH / 2)
+  if (y >= psppire_axis_pixel_start (sheet->vaxis, sheet->range.row0) - DRAG_WIDTH / 2 &&
+      y <= psppire_axis_pixel_start (sheet->vaxis, sheet->range.rowi) +
+      psppire_axis_unit_size (sheet->vaxis, sheet->range.rowi) + DRAG_WIDTH / 2)
     {
-      xdrag = COLUMN_LEFT_XPIXEL (sheet, sheet->range.col0);
+      xdrag = psppire_axis_pixel_start (sheet->haxis, sheet->range.col0);
       if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2)
        {
          *drag_column = sheet->range.col0;
          return TRUE;
        }
-      xdrag = COLUMN_LEFT_XPIXEL (sheet, sheet->range.coli) +
-       xxx_column_width (sheet, sheet->range.coli);
+      xdrag = psppire_axis_pixel_start (sheet->haxis, sheet->range.coli) +
+       psppire_axis_unit_size (sheet->haxis, sheet->range.coli);
       if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2)
        {
          *drag_column = sheet->range.coli;
@@ -585,20 +311,20 @@ POSSIBLE_RESIZE (const GtkSheet *sheet, gint x, gint y,
        sheet->range.col0 < 0 || sheet->range.coli < 0 )
     return FALSE;
 
-  xdrag = COLUMN_LEFT_XPIXEL (sheet, sheet->range.coli)+
-    xxx_column_width (sheet, sheet->range.coli);
+  xdrag = psppire_axis_pixel_start (sheet->haxis, sheet->range.coli)+
+    psppire_axis_unit_size (sheet->haxis, sheet->range.coli);
 
-  ydrag = ROW_TOP_YPIXEL (sheet, sheet->range.rowi)+
-    yyy_row_height (sheet, sheet->range.rowi);
+  ydrag = psppire_axis_pixel_start (sheet->vaxis, sheet->range.rowi) +
+    psppire_axis_unit_size (sheet->vaxis, sheet->range.rowi);
 
   if (sheet->state == GTK_SHEET_COLUMN_SELECTED)
-    ydrag = ROW_TOP_YPIXEL (sheet, MIN_VISIBLE_ROW (sheet));
+    ydrag = psppire_axis_pixel_start (sheet->vaxis, min_visible_row (sheet));
 
   if (sheet->state == GTK_SHEET_ROW_SELECTED)
-    xdrag = COLUMN_LEFT_XPIXEL (sheet, MIN_VISIBLE_COLUMN (sheet));
+    xdrag = psppire_axis_pixel_start (sheet->haxis, min_visible_column (sheet));
 
-  *drag_column = COLUMN_FROM_XPIXEL (sheet, x);
-  *drag_row = ROW_FROM_YPIXEL (sheet, y);
+  *drag_column = column_from_xpixel (sheet, x);
+  *drag_row = row_from_ypixel (sheet, y);
 
   if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2 &&
       y >= ydrag - DRAG_WIDTH / 2 && y <= ydrag + DRAG_WIDTH / 2) return TRUE;
@@ -606,18 +332,65 @@ POSSIBLE_RESIZE (const GtkSheet *sheet, gint x, gint y,
   return FALSE;
 }
 
-static void gtk_sheet_class_init                (GtkSheetClass * klass);
-static void gtk_sheet_init                      (GtkSheet * sheet);
-static void gtk_sheet_dispose                   (GObject * object);
-static void gtk_sheet_finalize                          (GObject * object);
+
+static gboolean
+rectangle_from_range (GtkSheet *sheet, const GtkSheetRange *range,
+                     GdkRectangle *r)
+{
+  g_return_val_if_fail (range, FALSE);
+
+  r->x = psppire_axis_pixel_start (sheet->haxis, range->col0);
+  r->x -= round (sheet->hadjustment->value);
+
+  if ( sheet->row_titles_visible)
+    r->x += sheet->row_title_area.width;
+
+
+  r->y = psppire_axis_pixel_start (sheet->vaxis, range->row0);
+  r->y -= round (sheet->vadjustment->value);
+
+  if ( sheet->column_titles_visible)
+    r->y += sheet->column_title_area.height;
+
+  r->width = psppire_axis_pixel_start (sheet->haxis, range->coli) -
+    psppire_axis_pixel_start (sheet->haxis, range->col0) +
+    psppire_axis_unit_size (sheet->haxis, range->coli);
+
+  r->height = psppire_axis_pixel_start (sheet->vaxis, range->rowi) -
+    psppire_axis_pixel_start (sheet->vaxis, range->row0) +
+    psppire_axis_unit_size (sheet->vaxis, range->rowi);
+
+  return TRUE;
+}
+
+static gboolean
+rectangle_from_cell (GtkSheet *sheet, gint row, gint col,
+                    GdkRectangle *r)
+{
+  GtkSheetRange range;
+  g_return_val_if_fail (row >= 0, FALSE);
+  g_return_val_if_fail (col >= 0, FALSE);
+
+  range.row0 = range.rowi = row;
+  range.col0 = range.coli = col;
+
+  return rectangle_from_range (sheet, &range, r);
+}
+
+
+static void gtk_sheet_class_init                (GtkSheetClass *klass);
+static void gtk_sheet_init                      (GtkSheet *sheet);
+static void gtk_sheet_dispose                   (GObject *object);
+static void gtk_sheet_finalize                          (GObject *object);
 static void gtk_sheet_style_set                 (GtkWidget *widget,
                                                  GtkStyle *previous_style);
-static void gtk_sheet_realize                   (GtkWidget * widget);
-static void gtk_sheet_unrealize                 (GtkWidget * widget);
-static void gtk_sheet_map                       (GtkWidget * widget);
-static void gtk_sheet_unmap                     (GtkWidget * widget);
-static gint gtk_sheet_expose                    (GtkWidget * widget,
-                                                 GdkEventExpose * event);
+static void gtk_sheet_realize                   (GtkWidget *widget);
+static void gtk_sheet_unrealize                 (GtkWidget *widget);
+static void gtk_sheet_map                       (GtkWidget *widget);
+static void gtk_sheet_unmap                     (GtkWidget *widget);
+static gint gtk_sheet_expose                    (GtkWidget *widget,
+                                                 GdkEventExpose *event);
+
 static void gtk_sheet_forall                    (GtkContainer *container,
                                                  gboolean include_internals,
                                                  GtkCallback callback,
@@ -627,40 +400,38 @@ static void gtk_sheet_set_scroll_adjustments       (GtkSheet *sheet,
                                                  GtkAdjustment *hadjustment,
                                                  GtkAdjustment *vadjustment);
 
-static gint gtk_sheet_button_press              (GtkWidget * widget,
-                                                 GdkEventButton * event);
-static gint gtk_sheet_button_release            (GtkWidget * widget,
-                                                 GdkEventButton * event);
-static gint gtk_sheet_motion                    (GtkWidget * widget,
-                                                 GdkEventMotion * event);
+static gint gtk_sheet_button_press              (GtkWidget *widget,
+                                                 GdkEventButton *event);
+static gint gtk_sheet_button_release            (GtkWidget *widget,
+                                                 GdkEventButton *event);
+static gint gtk_sheet_motion                    (GtkWidget *widget,
+                                                 GdkEventMotion *event);
+static gboolean gtk_sheet_crossing_notify           (GtkWidget *widget,
+                                                    GdkEventCrossing *event);
 static gint gtk_sheet_entry_key_press           (GtkWidget *widget,
                                                  GdkEventKey *key);
-static gint gtk_sheet_key_press                         (GtkWidget *widget,
+static gboolean gtk_sheet_key_press             (GtkWidget *widget,
                                                  GdkEventKey *key);
-static void gtk_sheet_size_request              (GtkWidget * widget,
-                                                 GtkRequisition * requisition);
-static void gtk_sheet_size_allocate             (GtkWidget * widget,
-                                                 GtkAllocation * allocation);
+static void gtk_sheet_size_request              (GtkWidget *widget,
+                                                 GtkRequisition *requisition);
+static void gtk_sheet_size_allocate             (GtkWidget *widget,
+                                                 GtkAllocation *allocation);
 
 /* Sheet queries */
 
-static gboolean gtk_sheet_range_isvisible (const GtkSheet * sheet,
-                                          GtkSheetRange range);
-static gboolean gtk_sheet_cell_isvisible  (GtkSheet * sheet,
+static gboolean gtk_sheet_range_isvisible (const GtkSheet *sheet,
+                                          const GtkSheetRange *range);
+static gboolean gtk_sheet_cell_isvisible  (GtkSheet *sheet,
                                           gint row, gint column);
 /* Drawing Routines */
 
-/* draw cell background and frame */
-static void gtk_sheet_cell_draw_default         (GtkSheet *sheet,
-                                                 gint row, gint column);
+/* draw cell */
+static void gtk_sheet_cell_draw (GtkSheet *sheet, gint row, gint column);
 
-/* draw cell contents */
-static void gtk_sheet_cell_draw_label           (GtkSheet *sheet,
-                                                 gint row, gint column);
 
 /* draw visible part of range. If range == NULL then draw the whole screen */
-static void gtk_sheet_range_draw                (GtkSheet *sheet,
-                                                 const GtkSheetRange *range);
+static void gtk_sheet_range_draw (GtkSheet *sheet,
+                                 const GtkSheetRange *range);
 
 /* highlight the visible part of the selected range */
 static void gtk_sheet_range_draw_selection      (GtkSheet *sheet,
@@ -668,63 +439,51 @@ static void gtk_sheet_range_draw_selection         (GtkSheet *sheet,
 
 /* Selection */
 
-static gboolean gtk_sheet_move_query                    (GtkSheet *sheet,
-                                                 gint row, gint column);
-static void gtk_sheet_real_select_range         (GtkSheet * sheet,
-                                                 const GtkSheetRange * range);
-static void gtk_sheet_real_unselect_range       (GtkSheet * sheet,
-                                                 const GtkSheetRange * range);
+static void gtk_sheet_real_select_range         (GtkSheet *sheet,
+                                                 const GtkSheetRange *range);
+static void gtk_sheet_real_unselect_range       (GtkSheet *sheet,
+                                                 const GtkSheetRange *range);
 static void gtk_sheet_extend_selection          (GtkSheet *sheet,
                                                  gint row, gint column);
 static void gtk_sheet_new_selection             (GtkSheet *sheet,
                                                  GtkSheetRange *range);
 static void gtk_sheet_draw_border               (GtkSheet *sheet,
                                                  GtkSheetRange range);
-static void gtk_sheet_draw_corners              (GtkSheet *sheet,
-                                                 GtkSheetRange range);
-
 
 /* Active Cell handling */
 
 static void gtk_sheet_entry_changed             (GtkWidget *widget,
                                                  gpointer data);
-static void gtk_sheet_deactivate_cell   (GtkSheet *sheet);
-static void gtk_sheet_hide_active_cell          (GtkSheet *sheet);
-static gboolean gtk_sheet_activate_cell                 (GtkSheet *sheet,
-                                                 gint row, gint col);
+static void gtk_sheet_hide_entry_widget                 (GtkSheet *sheet);
+static void change_active_cell          (GtkSheet *sheet,
+                                         gint row, gint col);
 static void gtk_sheet_draw_active_cell          (GtkSheet *sheet);
-static void gtk_sheet_show_active_cell          (GtkSheet *sheet);
-static void gtk_sheet_click_cell                (GtkSheet *sheet,
+static void gtk_sheet_show_entry_widget                 (GtkSheet *sheet);
+static gboolean gtk_sheet_click_cell            (GtkSheet *sheet,
                                                  gint row,
-                                                 gint column,
-                                                 gboolean *veto);
+                                                 gint column);
 
-/* Backing Pixmap */
 
-static void gtk_sheet_make_backing_pixmap       (GtkSheet *sheet,
-                                                 guint width, guint height);
-static void gtk_sheet_draw_backing_pixmap       (GtkSheet *sheet,
-                                                 GtkSheetRange range);
 /* Scrollbars */
 
-static void adjust_scrollbars                   (GtkSheet * sheet);
-static void vadjustment_value_changed           (GtkAdjustment * adjustment,
+static void adjust_scrollbars                   (GtkSheet *sheet);
+static void vadjustment_value_changed           (GtkAdjustment *adjustment,
                                                  gpointer data);
-static void hadjustment_value_changed           (GtkAdjustment * adjustment,
+static void hadjustment_value_changed           (GtkAdjustment *adjustment,
                                                  gpointer data);
 
 
-static void draw_xor_vline                      (GtkSheet * sheet);
-static void draw_xor_hline                      (GtkSheet * sheet);
+static void draw_xor_vline                      (GtkSheet *sheet);
+static void draw_xor_hline                      (GtkSheet *sheet);
 static void draw_xor_rectangle                  (GtkSheet *sheet,
                                                  GtkSheetRange range);
 
-static guint new_column_width                   (GtkSheet * sheet,
+static guint new_column_width                   (GtkSheet *sheet,
                                                  gint column,
-                                                 gint * x);
-static guint new_row_height                     (GtkSheet * sheet,
+                                                 gint *x);
+static guint new_row_height                     (GtkSheet *sheet,
                                                  gint row,
-                                                 gint * y);
+                                                 gint *y);
 /* Sheet Button */
 
 static void create_global_button                (GtkSheet *sheet);
@@ -734,12 +493,11 @@ static void global_button_clicked          (GtkWidget *widget,
 
 static void create_sheet_entry                  (GtkSheet *sheet);
 static void gtk_sheet_size_allocate_entry       (GtkSheet *sheet);
-static void gtk_sheet_entry_set_max_size        (GtkSheet *sheet);
 
 /* Sheet button gadgets */
 
-static void size_allocate_column_title_buttons          (GtkSheet * sheet);
-static void size_allocate_row_title_buttons     (GtkSheet * sheet);
+static void draw_column_title_buttons   (GtkSheet *sheet);
+static void draw_row_title_buttons      (GtkSheet *sheet);
 
 
 static void size_allocate_global_button         (GtkSheet *sheet);
@@ -747,30 +505,11 @@ static void gtk_sheet_button_size_request  (GtkSheet *sheet,
                                                  const GtkSheetButton *button,
                                                  GtkRequisition *requisition);
 
-/* Attributes routines */
-static void init_attributes                     (const GtkSheet *sheet, gint col,
-                                                 GtkSheetCellAttr *attributes);
-
-
-/* Memory allocation routines */
-static void gtk_sheet_real_range_clear                  (GtkSheet *sheet,
-                                                 const GtkSheetRange *range);
-
 static void gtk_sheet_real_cell_clear           (GtkSheet *sheet,
                                                  gint row,
                                                  gint column);
 
 
-/* Container Functions */
-static void gtk_sheet_remove                    (GtkContainer *container,
-                                                 GtkWidget *widget);
-static void gtk_sheet_realize_child             (GtkSheet *sheet,
-                                                 GtkSheetChild *child);
-static void gtk_sheet_position_child            (GtkSheet *sheet,
-                                                 GtkSheetChild *child);
-static void gtk_sheet_position_children                 (GtkSheet *sheet);
-static void gtk_sheet_child_show                (GtkSheetChild *child);
-static void gtk_sheet_child_hide                (GtkSheetChild *child);
 static void gtk_sheet_column_size_request (GtkSheet *sheet,
                                           gint col,
                                           guint *requisition);
@@ -780,10 +519,6 @@ static void gtk_sheet_row_size_request (GtkSheet *sheet,
 
 
 /* Signals */
-
-extern void
-_gtkextra_signal_emit (GtkObject *object, guint signal_id, ...);
-
 enum
   {
     SELECT_ROW,
@@ -796,9 +531,7 @@ enum
     RESIZE_RANGE,
     MOVE_RANGE,
     TRAVERSE,
-    DEACTIVATE,
     ACTIVATE,
-    CHANGED,
     LAST_SIGNAL
   };
 
@@ -826,13 +559,16 @@ gtk_sheet_get_type ()
          (GInstanceInitFunc) gtk_sheet_init,
          NULL,
        };
+
       sheet_type =
-       g_type_register_static (GTK_TYPE_CONTAINER, "GtkSheet",
+       g_type_register_static (GTK_TYPE_BIN, "GtkSheet",
                                &sheet_info, 0);
     }
   return sheet_type;
 }
 
+\f
+
 static GtkSheetRange*
 gtk_sheet_range_copy (const GtkSheetRange *range)
 {
@@ -871,36 +607,76 @@ gtk_sheet_range_get_type (void)
   return sheet_range_type;
 }
 
+static GtkSheetCell*
+gtk_sheet_cell_copy (const GtkSheetCell *cell)
+{
+  GtkSheetCell *new_cell;
+
+  g_return_val_if_fail (cell != NULL, NULL);
+
+  new_cell = g_new (GtkSheetCell, 1);
+
+  *new_cell = *cell;
+
+  return new_cell;
+}
+
+static void
+gtk_sheet_cell_free (GtkSheetCell *cell)
+{
+  g_return_if_fail (cell != NULL);
+
+  g_free (cell);
+}
+
+GType
+gtk_sheet_cell_get_type (void)
+{
+  static GType sheet_cell_type = 0;
+
+  if (!sheet_cell_type)
+    {
+      sheet_cell_type =
+       g_boxed_type_register_static ("GtkSheetCell",
+                                     (GBoxedCopyFunc) gtk_sheet_cell_copy,
+                                     (GBoxedFreeFunc) gtk_sheet_cell_free);
+    }
 
-static void column_titles_changed (GtkWidget *w, gint first, gint n_columns, gpointer data);
+  return sheet_cell_type;
+}
+\f
 
 /* Properties */
 enum
   {
     PROP_0,
-    PROP_ROW_GEO,
-    PROP_COL_GEO,
+    PROP_VAXIS,
+    PROP_HAXIS,
     PROP_MODEL
   };
 
 static void
-gtk_sheet_set_row_geometry (GtkSheet *sheet, GSheetRow *geo)
+gtk_sheet_set_horizontal_axis (GtkSheet *sheet, PsppireAxis *a)
 {
-  if ( sheet->row_geometry ) g_object_unref (sheet->row_geometry);
+  if ( sheet->haxis )
+    g_object_unref (sheet->haxis);
 
-  sheet->row_geometry = geo;
+  sheet->haxis = a;
 
-  if ( sheet->row_geometry ) g_object_ref (sheet->row_geometry);
+  if ( sheet->haxis )
+    g_object_ref (sheet->haxis);
 }
 
 static void
-gtk_sheet_set_column_geometry (GtkSheet *sheet, GSheetColumn *geo)
+gtk_sheet_set_vertical_axis (GtkSheet *sheet, PsppireAxis *a)
 {
-  if ( sheet->column_geometry ) g_object_unref (sheet->column_geometry);
+  if ( sheet->vaxis )
+    g_object_unref (sheet->vaxis);
 
-  sheet->column_geometry = geo;
+  sheet->vaxis = a;
 
-  if ( sheet->column_geometry ) g_object_ref (sheet->column_geometry);
+  if ( sheet->vaxis )
+    g_object_ref (sheet->vaxis);
 }
 
 
@@ -915,14 +691,11 @@ gtk_sheet_set_property (GObject         *object,
 
   switch (prop_id)
     {
-    case PROP_ROW_GEO:
-      gtk_sheet_set_row_geometry (sheet, g_value_get_pointer (value));
+    case PROP_VAXIS:
+      gtk_sheet_set_vertical_axis (sheet, g_value_get_pointer (value));
       break;
-    case PROP_COL_GEO:
-      gtk_sheet_set_column_geometry (sheet, g_value_get_pointer (value));
-      if ( sheet->column_geometry)
-       g_signal_connect (sheet->column_geometry, "columns_changed",
-                         G_CALLBACK (column_titles_changed), sheet);
+    case PROP_HAXIS:
+      gtk_sheet_set_horizontal_axis (sheet, g_value_get_pointer (value));
       break;
     case PROP_MODEL:
       gtk_sheet_set_model (sheet, g_value_get_pointer (value));
@@ -943,11 +716,11 @@ gtk_sheet_get_property (GObject         *object,
 
   switch (prop_id)
     {
-    case PROP_ROW_GEO:
-      g_value_set_pointer (value, sheet->row_geometry);
+    case PROP_VAXIS:
+      g_value_set_pointer (value, sheet->vaxis);
       break;
-    case PROP_COL_GEO:
-      g_value_set_pointer (value, sheet->column_geometry);
+    case PROP_HAXIS:
+      g_value_set_pointer (value, sheet->haxis);
       break;
     case PROP_MODEL:
       g_value_set_pointer (value, sheet->model);
@@ -960,16 +733,16 @@ gtk_sheet_get_property (GObject         *object,
 
 
 static void
-gtk_sheet_class_init (GtkSheetClass * klass)
+gtk_sheet_class_init (GtkSheetClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  GParamSpec *row_geo_spec ;
-  GParamSpec *col_geo_spec ;
+  GParamSpec *haxis_spec ;
+  GParamSpec *vaxis_spec ;
   GParamSpec *model_spec ;
 
-  GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
-  GtkContainerClass *container_class = (GtkContainerClass *) klass;
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
 
   parent_class = g_type_class_peek_parent (klass);
 
@@ -1062,7 +835,7 @@ gtk_sheet_class_init (GtkSheetClass * klass)
                  G_SIGNAL_RUN_LAST,
                  0,
                  NULL, NULL,
-                 gtkextra_VOID__INT_POINTER,
+                 psppire_marshal_VOID__INT_POINTER,
                  G_TYPE_NONE,
                  2,
                  G_TYPE_INT,
@@ -1083,7 +856,7 @@ gtk_sheet_class_init (GtkSheetClass * klass)
                  G_SIGNAL_RUN_LAST,
                  0,
                  NULL, NULL,
-                 gtkextra_VOID__INT_POINTER,
+                 psppire_marshal_VOID__INT_POINTER,
                  G_TYPE_NONE,
                  2,
                  G_TYPE_INT,
@@ -1109,7 +882,7 @@ gtk_sheet_class_init (GtkSheetClass * klass)
                  G_SIGNAL_RUN_LAST,
                  offsetof (GtkSheetClass, resize_range),
                  NULL, NULL,
-                 gtkextra_VOID__BOXED_BOXED,
+                 psppire_marshal_VOID__BOXED_BOXED,
                  G_TYPE_NONE,
                  2,
                  GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE
@@ -1121,7 +894,7 @@ gtk_sheet_class_init (GtkSheetClass * klass)
                  G_SIGNAL_RUN_LAST,
                  offsetof (GtkSheetClass, move_range),
                  NULL, NULL,
-                 gtkextra_VOID__BOXED_BOXED,
+                 psppire_marshal_VOID__BOXED_BOXED,
                  G_TYPE_NONE,
                  2,
                  GTK_TYPE_SHEET_RANGE, GTK_TYPE_SHEET_RANGE
@@ -1133,19 +906,11 @@ gtk_sheet_class_init (GtkSheetClass * klass)
                  G_SIGNAL_RUN_LAST,
                  offsetof (GtkSheetClass, traverse),
                  NULL, NULL,
-                 gtkextra_BOOLEAN__INT_INT_POINTER_POINTER,
-                 G_TYPE_BOOLEAN, 4, G_TYPE_INT, G_TYPE_INT,
-                 G_TYPE_POINTER, G_TYPE_POINTER);
-
+                 psppire_marshal_BOOLEAN__BOXED_POINTER,
+                 G_TYPE_BOOLEAN, 2,
+                 GTK_TYPE_SHEET_CELL,
+                 G_TYPE_POINTER);
 
-  sheet_signals[DEACTIVATE] =
-    g_signal_new ("deactivate",
-                 G_TYPE_FROM_CLASS (object_class),
-                 G_SIGNAL_RUN_LAST,
-                 offsetof (GtkSheetClass, deactivate),
-                 NULL, NULL,
-                 gtkextra_VOID__INT_INT,
-                 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
 
   sheet_signals[ACTIVATE] =
     g_signal_new ("activate",
@@ -1153,17 +918,10 @@ gtk_sheet_class_init (GtkSheetClass * klass)
                  G_SIGNAL_RUN_LAST,
                  offsetof (GtkSheetClass, activate),
                  NULL, NULL,
-                 gtkextra_BOOLEAN__INT_INT,
-                 G_TYPE_BOOLEAN, 2, G_TYPE_INT, G_TYPE_INT);
-
-  sheet_signals[CHANGED] =
-    g_signal_new ("changed",
-                 G_TYPE_FROM_CLASS (object_class),
-                 G_SIGNAL_RUN_LAST,
-                 offsetof (GtkSheetClass, changed),
-                 NULL, NULL,
-                 gtkextra_VOID__INT_INT,
-                 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
+                 psppire_marshal_VOID__INT_INT_INT_INT,
+                 G_TYPE_NONE, 4,
+                 G_TYPE_INT, G_TYPE_INT,
+                 G_TYPE_INT, G_TYPE_INT);
 
   widget_class->set_scroll_adjustments_signal =
     g_signal_new ("set-scroll-adjustments",
@@ -1171,28 +929,28 @@ gtk_sheet_class_init (GtkSheetClass * klass)
                  G_SIGNAL_RUN_LAST,
                  offsetof (GtkSheetClass, set_scroll_adjustments),
                  NULL, NULL,
-                 gtkextra_VOID__OBJECT_OBJECT,
+                 psppire_marshal_VOID__OBJECT_OBJECT,
                  G_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
 
 
   container_class->add = NULL;
-  container_class->remove = gtk_sheet_remove;
+  container_class->remove = NULL;
   container_class->forall = gtk_sheet_forall;
 
   object_class->dispose = gtk_sheet_dispose;
   object_class->finalize = gtk_sheet_finalize;
 
 
-  row_geo_spec =
-    g_param_spec_pointer ("row-geometry",
-                         "Row Geometry",
-                         "A pointer to the model of the row geometry",
+  vaxis_spec =
+    g_param_spec_pointer ("vertical-axis",
+                         "Vertical Axis",
+                         "A pointer to the PsppireAxis object for the rows",
                          G_PARAM_READABLE | G_PARAM_WRITABLE );
 
-  col_geo_spec =
-    g_param_spec_pointer ("column-geometry",
-                         "Column Geometry",
-                         "A pointer to the model of the column geometry",
+  haxis_spec =
+    g_param_spec_pointer ("horizontal-axis",
+                         "Horizontal Axis",
+                         "A pointer to the PsppireAxis object for the columns",
                          G_PARAM_READABLE | G_PARAM_WRITABLE );
 
   model_spec =
@@ -1206,12 +964,12 @@ gtk_sheet_class_init (GtkSheetClass * klass)
   object_class->get_property = gtk_sheet_get_property;
 
   g_object_class_install_property (object_class,
-                                   PROP_ROW_GEO,
-                                   row_geo_spec);
+                                   PROP_VAXIS,
+                                   vaxis_spec);
 
   g_object_class_install_property (object_class,
-                                   PROP_COL_GEO,
-                                   col_geo_spec);
+                                   PROP_HAXIS,
+                                   haxis_spec);
 
   g_object_class_install_property (object_class,
                                    PROP_MODEL,
@@ -1226,6 +984,8 @@ gtk_sheet_class_init (GtkSheetClass * klass)
   widget_class->button_press_event = gtk_sheet_button_press;
   widget_class->button_release_event = gtk_sheet_button_release;
   widget_class->motion_notify_event = gtk_sheet_motion;
+  widget_class->enter_notify_event = gtk_sheet_crossing_notify;
+  widget_class->leave_notify_event = gtk_sheet_crossing_notify;
   widget_class->key_press_event = gtk_sheet_key_press;
   widget_class->expose_event = gtk_sheet_expose;
   widget_class->size_request = gtk_sheet_size_request;
@@ -1240,7 +1000,6 @@ gtk_sheet_class_init (GtkSheetClass * klass)
   klass->resize_range = NULL;
   klass->move_range = NULL;
   klass->traverse = NULL;
-  klass->deactivate = NULL;
   klass->activate = NULL;
   klass->changed = NULL;
 }
@@ -1249,14 +1008,11 @@ static void
 gtk_sheet_init (GtkSheet *sheet)
 {
   sheet->model = NULL;
-  sheet->column_geometry = NULL;
-  sheet->row_geometry = NULL;
-
-  sheet->children = NULL;
+  sheet->haxis = NULL;
+  sheet->vaxis = NULL;
 
   sheet->flags = 0;
   sheet->selection_mode = GTK_SELECTION_NONE;
-  sheet->freeze_count = 0;
   sheet->state = GTK_SHEET_NORMAL;
 
   GTK_WIDGET_UNSET_FLAGS (sheet, GTK_NO_WINDOW);
@@ -1266,7 +1022,7 @@ gtk_sheet_init (GtkSheet *sheet)
   sheet->column_title_area.x = 0;
   sheet->column_title_area.y = 0;
   sheet->column_title_area.width = 0;
-  sheet->column_title_area.height = DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet));
+  sheet->column_title_area.height = DEFAULT_ROW_HEIGHT;
 
   sheet->row_title_window = NULL;
   sheet->row_title_area.x = 0;
@@ -1280,8 +1036,6 @@ gtk_sheet_init (GtkSheet *sheet)
   sheet->selection_cell.row = 0;
   sheet->selection_cell.col = 0;
 
-  sheet->pixmap = NULL;
-
   sheet->range.row0 = 0;
   sheet->range.rowi = 0;
   sheet->range.col0 = 0;
@@ -1290,31 +1044,20 @@ gtk_sheet_init (GtkSheet *sheet)
   sheet->state = GTK_SHEET_NORMAL;
 
   sheet->sheet_window = NULL;
-  sheet->sheet_window_width = 0;
-  sheet->sheet_window_height = 0;
   sheet->entry_widget = NULL;
-  sheet->entry_container = NULL;
+  sheet->entry_handler_id = 0;
   sheet->button = NULL;
 
-  sheet->hoffset = 0;
-  sheet->voffset = 0;
-
   sheet->hadjustment = NULL;
   sheet->vadjustment = NULL;
 
-  sheet->cursor_drag = gdk_cursor_new (GDK_PLUS);
+  sheet->cursor_drag = NULL;
+
   sheet->xor_gc = NULL;
   sheet->fg_gc = NULL;
   sheet->bg_gc = NULL;
   sheet->x_drag = 0;
   sheet->y_drag = 0;
-  gdk_color_parse ("white", &sheet->bg_color);
-  gdk_colormap_alloc_color (gdk_colormap_get_system (), &sheet->bg_color, FALSE,
-                            TRUE);
-  gdk_color_parse ("gray", &sheet->grid_color);
-  gdk_colormap_alloc_color (gdk_colormap_get_system (), &sheet->grid_color, FALSE,
-                            TRUE);
-
   sheet->show_grid = TRUE;
 
   sheet->motion_timer = 0;
@@ -1326,12 +1069,10 @@ gtk_sheet_init (GtkSheet *sheet)
   sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
 
   sheet->column_titles_visible = TRUE;
-  sheet->autoscroll = TRUE;
-  sheet->justify_entry = TRUE;
 
 
   /* create sheet entry */
-  sheet->entry_type = 0;
+  sheet->entry_type = GTK_TYPE_ENTRY;
   create_sheet_entry (sheet);
 
   /* create global selection button */
@@ -1345,7 +1086,6 @@ columns_inserted_deleted_callback (GSheetModel *model, gint first_column,
                                   gint n_columns,
                                   gpointer data)
 {
-  gint i;
   GtkSheet *sheet = GTK_SHEET (data);
 
   GtkSheetRange range;
@@ -1357,16 +1097,16 @@ columns_inserted_deleted_callback (GSheetModel *model, gint first_column,
    */
   range.col0 = first_column;
   range.row0 = 0;
-  range.coli = xxx_column_count (sheet) - 1;
-  range.rowi = yyy_row_count (sheet) - 1;
+  range.coli = psppire_axis_unit_count (sheet->haxis) - 1;
+  range.rowi = psppire_axis_unit_count (sheet->vaxis) - 1;
 
   adjust_scrollbars (sheet);
 
   if (sheet->active_cell.col >= model_columns)
-    gtk_sheet_activate_cell (sheet, sheet->active_cell.row, model_columns - 1);
+    change_active_cell (sheet, sheet->active_cell.row, model_columns - 1);
 
-  for (i = first_column; i <= MAX_VISIBLE_COLUMN (sheet); i++)
-    gtk_sheet_column_title_button_draw (sheet, i);
+  draw_column_title_buttons_range (sheet,
+                                  first_column, max_visible_column (sheet));
 
   gtk_sheet_range_draw (sheet, &range);
 }
@@ -1377,7 +1117,6 @@ static void
 rows_inserted_deleted_callback (GSheetModel *model, gint first_row,
                                gint n_rows, gpointer data)
 {
-  gint i;
   GtkSheet *sheet = GTK_SHEET (data);
 
   GtkSheetRange range;
@@ -1389,16 +1128,15 @@ rows_inserted_deleted_callback (GSheetModel *model, gint first_row,
    */
   range.row0 = first_row;
   range.col0 = 0;
-  range.rowi = yyy_row_count (sheet) - 1;
-  range.coli = xxx_column_count (sheet) - 1;
+  range.rowi = psppire_axis_unit_count (sheet->vaxis) - 1;
+  range.coli = psppire_axis_unit_count (sheet->haxis) - 1;
 
   adjust_scrollbars (sheet);
 
   if (sheet->active_cell.row >= model_rows)
-    gtk_sheet_activate_cell (sheet, model_rows - 1, sheet->active_cell.col);
+    change_active_cell (sheet, model_rows - 1, sheet->active_cell.col);
 
-  for (i = first_row; i <= MAX_VISIBLE_ROW (sheet); i++)
-    gtk_sheet_row_title_button_draw (sheet, i);
+  draw_row_title_buttons_range (sheet, first_row, max_visible_row (sheet));
 
   gtk_sheet_range_draw (sheet, &range);
 }
@@ -1420,39 +1158,31 @@ range_update_callback (GSheetModel *m, gint row0, gint col0,
   range.rowi = rowi;
   range.coli = coli;
 
-  if ( MAX_VISIBLE_ROW (sheet) >
-       g_sheet_model_get_row_count (sheet->model)
-       ||
-       MAX_VISIBLE_COLUMN (sheet) >
-       g_sheet_model_get_column_count (sheet->model))
-    {
-      gtk_sheet_move_query (sheet, 0, 0);
-    }
+  if ( !GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
+    return;
 
   if ( ( row0 < 0 && col0 < 0 ) || ( rowi < 0 && coli < 0 ) )
     {
-      gint i;
       gtk_sheet_range_draw (sheet, NULL);
       adjust_scrollbars (sheet);
 
-      for (i = MIN_VISIBLE_ROW (sheet); i <= MAX_VISIBLE_ROW (sheet); i++)
-       gtk_sheet_row_title_button_draw (sheet, i);
+      draw_row_title_buttons_range (sheet, min_visible_row (sheet),
+                                      max_visible_row (sheet));
 
-      for (i = MIN_VISIBLE_COLUMN (sheet);
-          i <= MAX_VISIBLE_COLUMN (sheet); i++)
-       gtk_sheet_column_title_button_draw (sheet, i);
+      draw_column_title_buttons_range (sheet, min_visible_column (sheet),
+                                      max_visible_column (sheet));
 
       return;
     }
   else if ( row0 < 0 || rowi < 0 )
     {
-      range.row0 = MIN_VISIBLE_ROW (sheet);
-      range.rowi = MAX_VISIBLE_ROW (sheet);
+      range.row0 = min_visible_row (sheet);
+      range.rowi = max_visible_row (sheet);
     }
   else if ( col0 < 0 || coli < 0 )
     {
-      range.col0 = MIN_VISIBLE_COLUMN (sheet);
-      range.coli = MAX_VISIBLE_COLUMN (sheet);
+      range.col0 = min_visible_column (sheet);
+      range.coli = max_visible_column (sheet);
     }
 
   gtk_sheet_range_draw (sheet, &range);
@@ -1471,11 +1201,9 @@ range_update_callback (GSheetModel *m, gint row0, gint col0,
  * Returns: the new sheet widget
  */
 GtkWidget *
-gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, GSheetModel *model)
+gtk_sheet_new (GSheetModel *model)
 {
   GtkWidget *widget = g_object_new (GTK_TYPE_SHEET,
-                                   "row-geometry", vgeo,
-                                   "column-geometry", hgeo,
                                    "model", model,
                                    NULL);
   return widget;
@@ -1521,38 +1249,6 @@ gtk_sheet_set_model (GtkSheet *sheet, GSheetModel *model)
 }
 
 
-/* Call back for when the column titles have changed.
-   FIRST is the first column changed.
-   N_COLUMNS is the number of columns which have changed, or - 1, which
-   indicates that the column has changed to its right - most extremity
-*/
-static void
-column_titles_changed (GtkWidget *w, gint first, gint n_columns, gpointer data)
-{
-  GtkSheet *sheet = GTK_SHEET (data);
-  gboolean extremity = FALSE;
-
-  if ( n_columns == -1 )
-    {
-      extremity = TRUE;
-      n_columns = xxx_column_count (sheet) - 1 ;
-    }
-
-  if (!GTK_SHEET_IS_FROZEN (sheet))
-    {
-      gint i;
-      for ( i = first ; i <= first + n_columns ; ++i )
-       {
-         gtk_sheet_column_title_button_draw (sheet, i);
-         g_signal_emit (sheet, sheet_signals[CHANGED], 0, -1, i);
-       }
-    }
-
-  if ( extremity)
-    gtk_sheet_column_title_button_draw (sheet, -1);
-
-}
-
 void
 gtk_sheet_change_entry (GtkSheet *sheet, GtkType entry_type)
 {
@@ -1564,7 +1260,7 @@ gtk_sheet_change_entry (GtkSheet *sheet, GtkType entry_type)
   state = sheet->state;
 
   if (sheet->state == GTK_SHEET_NORMAL)
-    gtk_sheet_hide_active_cell (sheet);
+    gtk_sheet_hide_entry_widget (sheet);
 
   sheet->entry_type = entry_type;
 
@@ -1572,12 +1268,9 @@ gtk_sheet_change_entry (GtkSheet *sheet, GtkType entry_type)
 
   if (state == GTK_SHEET_NORMAL)
     {
-      gtk_sheet_show_active_cell (sheet);
-      g_signal_connect (gtk_sheet_get_entry (sheet),
-                       "changed",
-                       G_CALLBACK (gtk_sheet_entry_changed),
-                       sheet);
+      gtk_sheet_show_entry_widget (sheet);
     }
+
 }
 
 void
@@ -1590,8 +1283,7 @@ gtk_sheet_show_grid (GtkSheet *sheet, gboolean show)
 
   sheet->show_grid = show;
 
-  if (!GTK_SHEET_IS_FROZEN (sheet))
-    gtk_sheet_range_draw (sheet, NULL);
+  gtk_sheet_range_draw (sheet, NULL);
 }
 
 gboolean
@@ -1603,291 +1295,40 @@ gtk_sheet_grid_visible (GtkSheet *sheet)
   return sheet->show_grid;
 }
 
-void
-gtk_sheet_set_background (GtkSheet *sheet, GdkColor *color)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if (!color)
-    {
-      gdk_color_parse ("white", &sheet->bg_color);
-      gdk_colormap_alloc_color (gdk_colormap_get_system (), &sheet->bg_color, FALSE, TRUE);
-    }
-  else
-    sheet->bg_color = *color;
-
-  if (!GTK_SHEET_IS_FROZEN (sheet))
-    gtk_sheet_range_draw (sheet, NULL);
-}
-
-void
-gtk_sheet_set_grid (GtkSheet *sheet, GdkColor *color)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if (!color)
-    {
-      gdk_color_parse ("black", &sheet->grid_color);
-      gdk_colormap_alloc_color (gdk_colormap_get_system (), &sheet->grid_color, FALSE, TRUE);
-    }
-  else
-    sheet->grid_color = *color;
-
-  if (!GTK_SHEET_IS_FROZEN (sheet))
-    gtk_sheet_range_draw (sheet, NULL);
-}
-
-guint
-gtk_sheet_get_columns_count (GtkSheet *sheet)
-{
-  g_return_val_if_fail (sheet != NULL, 0);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
-
-  return xxx_column_count (sheet);
-}
-
-guint
-gtk_sheet_get_rows_count (GtkSheet *sheet)
+guint
+gtk_sheet_get_columns_count (GtkSheet *sheet)
 {
   g_return_val_if_fail (sheet != NULL, 0);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
 
-  return yyy_row_count (sheet);
-}
-
-gint
-gtk_sheet_get_state (GtkSheet *sheet)
-{
-  g_return_val_if_fail (sheet != NULL, 0);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
-
-  return (sheet->state);
-}
-
-void
-gtk_sheet_set_selection_mode (GtkSheet *sheet, gint mode)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if (GTK_WIDGET_REALIZED (sheet))
-    gtk_sheet_real_unselect_range (sheet, NULL);
-
-  sheet->selection_mode = mode;
-}
-
-void
-gtk_sheet_set_autoresize (GtkSheet *sheet, gboolean autoresize)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  sheet->autoresize = autoresize;
-}
-
-gboolean
-gtk_sheet_autoresize (GtkSheet *sheet)
-{
-  g_return_val_if_fail (sheet != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
-
-  return sheet->autoresize;
+  return psppire_axis_unit_count (sheet->haxis);
 }
 
 static void
-gtk_sheet_set_column_width (GtkSheet * sheet,
+gtk_sheet_set_column_width (GtkSheet *sheet,
                            gint column,
                            guint width);
 
 
-static void
-gtk_sheet_autoresize_column (GtkSheet *sheet, gint column)
-{
-  gint text_width = 0;
-  gint row;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-  if (column >= xxx_column_count (sheet) || column < 0) return;
-
-  for (row = 0; row < yyy_row_count (sheet); row++)
-    {
-      gchar *text = gtk_sheet_cell_get_text (sheet, row, column);
-      if (text && strlen (text) > 0)
-       {
-         GtkSheetCellAttr attributes;
-
-         gtk_sheet_get_attributes (sheet, row, column, &attributes);
-         if (attributes.is_visible)
-           {
-             gint width = STRING_WIDTH (GTK_WIDGET (sheet),
-                                        attributes.font_desc,
-                                        text)
-               + 2 * CELLOFFSET + attributes.border.width;
-             text_width = MAX (text_width, width);
-           }
-       }
-      dispose_string (sheet, text);
-    }
-
-  if (text_width > xxx_column_width (sheet, column) )
-    {
-      gtk_sheet_set_column_width (sheet, column, text_width);
-      GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_REDRAW_PENDING);
-    }
-}
-
-
-void
-gtk_sheet_set_autoscroll (GtkSheet *sheet, gboolean autoscroll)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  sheet->autoscroll = autoscroll;
-}
-
-gboolean
-gtk_sheet_autoscroll (GtkSheet *sheet)
-{
-  g_return_val_if_fail (sheet != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
-
-  return sheet->autoscroll;
-}
-
-
-void
-gtk_sheet_set_justify_entry (GtkSheet *sheet, gboolean justify)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  sheet->justify_entry = justify;
-}
-
-gboolean
-gtk_sheet_justify_entry (GtkSheet *sheet)
-{
-  g_return_val_if_fail (sheet != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
-
-  return sheet->justify_entry;
-}
-
-
-
-void
-gtk_sheet_freeze (GtkSheet *sheet)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  sheet->freeze_count++;
-  GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IS_FROZEN);
-}
-
-void
-gtk_sheet_thaw (GtkSheet *sheet)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if (sheet->freeze_count == 0) return;
-
-  sheet->freeze_count--;
-  if (sheet->freeze_count > 0) return;
-
-  adjust_scrollbars (sheet);
-
-  GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IS_FROZEN);
-
-  sheet->old_vadjustment = -1.;
-  sheet->old_hadjustment = -1.;
-
-  if (sheet->hadjustment)
-    g_signal_emit_by_name (sheet->hadjustment,
-                          "value_changed");
-  if (sheet->vadjustment)
-    g_signal_emit_by_name (sheet->vadjustment,
-                          "value_changed");
-
-  if (sheet->state == GTK_STATE_NORMAL)
-    if (sheet->entry_widget && GTK_WIDGET_MAPPED (sheet->entry_widget))
-      {
-       gtk_sheet_activate_cell (sheet, sheet->active_cell.row,
-                                sheet->active_cell.col);
-      }
-
-}
-
-void
-gtk_sheet_set_row_titles_width (GtkSheet *sheet, guint width)
-{
-  if (width < COLUMN_MIN_WIDTH) return;
-
-  sheet->row_title_area.width = width;
-
-  adjust_scrollbars (sheet);
-
-  sheet->old_hadjustment = -1.;
-  if (sheet->hadjustment)
-    g_signal_emit_by_name (sheet->hadjustment,
-                          "value_changed");
-  size_allocate_global_button (sheet);
-}
-
-void
-gtk_sheet_set_column_titles_height (GtkSheet *sheet, guint height)
-{
-  if (height < DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet))) return;
-
-  sheet->column_title_area.height = height;
-
-  adjust_scrollbars (sheet);
-
-  sheet->old_vadjustment = -1.;
-  if (sheet->vadjustment)
-    g_signal_emit_by_name (sheet->vadjustment,
-                          "value_changed");
-  size_allocate_global_button (sheet);
-}
-
 void
 gtk_sheet_show_column_titles (GtkSheet *sheet)
 {
-  gint col;
-
   if (sheet->column_titles_visible) return;
 
   sheet->column_titles_visible = TRUE;
 
+  if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
+    return;
 
-  if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
-    {
-      gdk_window_show (sheet->column_title_window);
-      gdk_window_move_resize (sheet->column_title_window,
-                             sheet->column_title_area.x,
-                             sheet->column_title_area.y,
-                             sheet->column_title_area.width,
-                             sheet->column_title_area.height);
+  gdk_window_show (sheet->column_title_window);
+  gdk_window_move_resize (sheet->column_title_window,
+                         sheet->column_title_area.x,
+                         sheet->column_title_area.y,
+                         sheet->column_title_area.width,
+                         sheet->column_title_area.height);
 
-      for (col = MIN_VISIBLE_COLUMN (sheet);
-          col <= MAX_VISIBLE_COLUMN (sheet);
-          col++)
-       {
-         GtkSheetButton *button = xxx_column_button (sheet, col);
-         GtkSheetChild *child = button->child;
-         if (child)
-           gtk_sheet_child_show (child);
-         gtk_sheet_button_free (button);
-       }
-      adjust_scrollbars (sheet);
-    }
+  adjust_scrollbars (sheet);
 
-  sheet->old_vadjustment = -1.;
   if (sheet->vadjustment)
     g_signal_emit_by_name (sheet->vadjustment,
                           "value_changed");
@@ -1898,8 +1339,6 @@ gtk_sheet_show_column_titles (GtkSheet *sheet)
 void
 gtk_sheet_show_row_titles (GtkSheet *sheet)
 {
-  gint row;
-
   if (sheet->row_titles_visible) return;
 
   sheet->row_titles_visible = TRUE;
@@ -1914,22 +1353,9 @@ gtk_sheet_show_row_titles (GtkSheet *sheet)
                              sheet->row_title_area.width,
                              sheet->row_title_area.height);
 
-      for (row = MIN_VISIBLE_ROW (sheet);
-          row <= MAX_VISIBLE_ROW (sheet);
-          row++)
-       {
-         const GtkSheetButton *button = yyy_row_button (sheet, row);
-         GtkSheetChild *child = button->child;
-
-         if (child)
-           {
-             gtk_sheet_child_show (child);
-           }
-       }
       adjust_scrollbars (sheet);
     }
 
-  sheet->old_hadjustment = -1.;
   if (sheet->hadjustment)
     g_signal_emit_by_name (sheet->hadjustment,
                           "value_changed");
@@ -1939,8 +1365,6 @@ gtk_sheet_show_row_titles (GtkSheet *sheet)
 void
 gtk_sheet_hide_column_titles (GtkSheet *sheet)
 {
-  gint col;
-
   if (!sheet->column_titles_visible) return;
 
   sheet->column_titles_visible = FALSE;
@@ -1952,20 +1376,9 @@ gtk_sheet_hide_column_titles (GtkSheet *sheet)
       if (GTK_WIDGET_VISIBLE (sheet->button))
        gtk_widget_hide (sheet->button);
 
-      for (col = MIN_VISIBLE_COLUMN (sheet);
-          col <= MAX_VISIBLE_COLUMN (sheet);
-          col++)
-       {
-         GtkSheetButton *button = xxx_column_button (sheet, col);
-         GtkSheetChild *child = button->child;
-         if (child)
-           gtk_sheet_child_hide (child);
-         gtk_sheet_button_free (button);
-       }
       adjust_scrollbars (sheet);
     }
 
-  sheet->old_vadjustment = -1.;
   if (sheet->vadjustment)
     g_signal_emit_by_name (sheet->vadjustment,
                           "value_changed");
@@ -1974,171 +1387,75 @@ gtk_sheet_hide_column_titles (GtkSheet *sheet)
 void
 gtk_sheet_hide_row_titles (GtkSheet *sheet)
 {
-  gint row;
-
   if (!sheet->row_titles_visible) return;
 
   sheet->row_titles_visible = FALSE;
 
-
   if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
     {
       if (sheet->row_title_window)
        gdk_window_hide (sheet->row_title_window);
+
       if (GTK_WIDGET_VISIBLE (sheet->button))
        gtk_widget_hide (sheet->button);
-      for (row = MIN_VISIBLE_ROW (sheet);
-          row <= MAX_VISIBLE_ROW (sheet);
-          row++)
-       {
-         const GtkSheetButton *button = yyy_row_button (sheet, row);
-         GtkSheetChild *child = button->child;
 
-         if (child)
-           gtk_sheet_child_hide (child);
-       }
       adjust_scrollbars (sheet);
     }
 
-  sheet->old_hadjustment = -1.;
   if (sheet->hadjustment)
     g_signal_emit_by_name (sheet->hadjustment,
                           "value_changed");
 }
 
-gboolean
-gtk_sheet_column_titles_visible (GtkSheet *sheet)
-{
-  g_return_val_if_fail (sheet != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
-  return sheet->column_titles_visible;
-}
-
-gboolean
-gtk_sheet_row_titles_visible (GtkSheet *sheet)
-{
-  g_return_val_if_fail (sheet != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
-  return sheet->row_titles_visible;
-}
 
+/* Scroll the sheet so that the cell ROW, COLUMN is visible.
+   If {ROW,COL}_ALIGN is zero, then the cell will be placed
+   at the {top,left} of the sheet.  If it's 1, then it'll
+   be placed at the {bottom,right}.
+   ROW or COL may be -1, in which case scrolling in that dimension
+   does not occur.
+ */
 void
 gtk_sheet_moveto (GtkSheet *sheet,
                  gint row,
-                 gint column,
+                 gint col,
                  gfloat row_align,
                  gfloat col_align)
 {
-  gint x, y;
-  guint width, height;
-  gint adjust;
-  gint min_row, min_col;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-  g_return_if_fail (sheet->hadjustment != NULL);
-  g_return_if_fail (sheet->vadjustment != NULL);
+  gint width, height;
 
-  if (row < 0 || row >= yyy_row_count (sheet))
-    return;
-  if (column < 0 || column >= xxx_column_count (sheet))
-    return;
+  g_return_if_fail (row_align >= 0);
+  g_return_if_fail (col_align >= 0);
 
-  height = sheet->sheet_window_height;
-  width = sheet->sheet_window_width;
+  g_return_if_fail (row_align <= 1);
+  g_return_if_fail (col_align <= 1);
 
-  /* adjust vertical scrollbar */
-  if (row >= 0 && row_align >= 0.0)
-    {
-      y = ROW_TOP_YPIXEL (sheet, row) - sheet->voffset
-       - (gint) ( row_align * height + (1.0 - row_align)
-                  * yyy_row_height (sheet, row));
-
-      /* This forces the sheet to scroll when you don't see the entire cell */
-      min_row = row;
-      adjust = 0;
-      if (row_align >= 1.0)
-       {
-         while (min_row >= 0 && min_row > MIN_VISIBLE_ROW (sheet))
-           {
-             if (yyy_row_is_visible (sheet, min_row))
-               adjust += yyy_row_height (sheet, min_row);
+  g_return_if_fail (col <
+                   psppire_axis_unit_count (sheet->haxis));
+  g_return_if_fail (row <
+                   psppire_axis_unit_count (sheet->vaxis));
 
-             if (adjust >= height)
-               {
-                 break;
-               }
-             min_row--;
-           }
-         min_row = MAX (min_row, 0);
+  gdk_drawable_get_size (sheet->sheet_window, &width, &height);
 
-         min_row ++;
 
-         y = ROW_TOP_YPIXEL (sheet, min_row) - sheet->voffset +
-           yyy_row_height (sheet, min_row) - 1;
-       }
-
-      if (y < 0)
-       sheet->vadjustment->value = 0.0;
-      else
-       sheet->vadjustment->value = y;
-
-      sheet->old_vadjustment = -1.;
-      g_signal_emit_by_name (sheet->vadjustment,
-                            "value_changed");
-
-    }
+  if (row >= 0)
+  {
+    gint y =  psppire_axis_pixel_start (sheet->vaxis, row);
 
-  /* adjust horizontal scrollbar */
-  if (column >= 0 && col_align >= 0.0)
-    {
-      x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset
-       - (gint) ( col_align*width + (1.0 - col_align)*
-                  xxx_column_width (sheet, column));
-
-      /* This forces the sheet to scroll when you don't see the entire cell */
-      min_col = column;
-      adjust = 0;
-      if (col_align == 1.0)
-       {
-         while (min_col >= 0 && min_col > MIN_VISIBLE_COLUMN (sheet))
-           {
-             if (xxx_column_is_visible (sheet, min_col))
-               adjust += xxx_column_width (sheet, min_col);
+    gtk_adjustment_set_value (sheet->vadjustment, y - height * row_align);
+  }
 
-             if (adjust >= width)
-               {
-                 break;
-               }
-             min_col--;
-           }
-         min_col = MAX (min_col, 0);
-         x = COLUMN_LEFT_XPIXEL (sheet, min_col) - sheet->hoffset +
-           xxx_column_width (sheet, min_col) - 1;
-       }
 
-      if (x < 0)
-       sheet->hadjustment->value = 0.0;
-      else
-       sheet->hadjustment->value = x;
+  if (col >= 0)
+  {
+    gint x =  psppire_axis_pixel_start (sheet->haxis, col);
 
-      sheet->old_vadjustment = -1.;
-      g_signal_emit_by_name (sheet->hadjustment,
-                            "value_changed");
-    }
+    gtk_adjustment_set_value (sheet->hadjustment, x - width * col_align);
+  }
 }
 
 
-void
-gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  sheet->columns_resizable = resizable;
-}
-
-gboolean
+static gboolean
 gtk_sheet_columns_resizable (GtkSheet *sheet)
 {
   g_return_val_if_fail (sheet != NULL, FALSE);
@@ -2148,16 +1465,7 @@ gtk_sheet_columns_resizable (GtkSheet *sheet)
 }
 
 
-void
-gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  sheet->rows_resizable = resizable;
-}
-
-gboolean
+static gboolean
 gtk_sheet_rows_resizable (GtkSheet *sheet)
 {
   g_return_val_if_fail (sheet != NULL, FALSE);
@@ -2168,25 +1476,22 @@ gtk_sheet_rows_resizable (GtkSheet *sheet)
 
 
 void
-gtk_sheet_select_row (GtkSheet * sheet,
-                     gint row)
+gtk_sheet_select_row (GtkSheet *sheet, gint row)
 {
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  if (row < 0 || row >= yyy_row_count (sheet))
+  if (row < 0 || row >= psppire_axis_unit_count (sheet->vaxis))
     return;
 
   if (sheet->state != GTK_SHEET_NORMAL)
     gtk_sheet_real_unselect_range (sheet, NULL);
-  else
-    gtk_sheet_deactivate_cell (sheet);
 
   sheet->state = GTK_SHEET_ROW_SELECTED;
   sheet->range.row0 = row;
   sheet->range.col0 = 0;
   sheet->range.rowi = row;
-  sheet->range.coli = xxx_column_count (sheet) - 1;
+  sheet->range.coli = psppire_axis_unit_count (sheet->haxis) - 1;
   sheet->active_cell.row = row;
   sheet->active_cell.col = 0;
 
@@ -2196,24 +1501,21 @@ gtk_sheet_select_row (GtkSheet * sheet,
 
 
 void
-gtk_sheet_select_column (GtkSheet * sheet, gint column)
+gtk_sheet_select_column (GtkSheet *sheet, gint column)
 {
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  if (column < 0 || column >= xxx_column_count (sheet))
+  if (column < 0 || column >= psppire_axis_unit_count (sheet->haxis))
     return;
 
   if (sheet->state != GTK_SHEET_NORMAL)
     gtk_sheet_real_unselect_range (sheet, NULL);
-  else
-    gtk_sheet_deactivate_cell (sheet);
-
 
   sheet->state = GTK_SHEET_COLUMN_SELECTED;
   sheet->range.row0 = 0;
   sheet->range.col0 = column;
-  sheet->range.rowi = yyy_row_count (sheet) - 1;
+  sheet->range.rowi = psppire_axis_unit_count (sheet->vaxis) - 1;
   sheet->range.coli = column;
   sheet->active_cell.row = 0;
   sheet->active_cell.col = column;
@@ -2226,40 +1528,40 @@ gtk_sheet_select_column (GtkSheet * sheet, gint column)
 
 
 static gboolean
-gtk_sheet_range_isvisible (const GtkSheet * sheet,
-                          GtkSheetRange range)
+gtk_sheet_range_isvisible (const GtkSheet *sheet,
+                          const GtkSheetRange *range)
 {
   g_return_val_if_fail (sheet != NULL, FALSE);
 
-  if (range.row0 < 0 || range.row0 >= yyy_row_count (sheet))
+  if (range->row0 < 0 || range->row0 >= psppire_axis_unit_count (sheet->vaxis))
     return FALSE;
 
-  if (range.rowi < 0 || range.rowi >= yyy_row_count (sheet))
+  if (range->rowi < 0 || range->rowi >= psppire_axis_unit_count (sheet->vaxis))
     return FALSE;
 
-  if (range.col0 < 0 || range.col0 >= xxx_column_count (sheet))
+  if (range->col0 < 0 || range->col0 >= psppire_axis_unit_count (sheet->haxis))
     return FALSE;
 
-  if (range.coli < 0 || range.coli >= xxx_column_count (sheet))
+  if (range->coli < 0 || range->coli >= psppire_axis_unit_count (sheet->haxis))
     return FALSE;
 
-  if (range.rowi < MIN_VISIBLE_ROW (sheet))
+  if (range->rowi < min_visible_row (sheet))
     return FALSE;
 
-  if (range.row0 > MAX_VISIBLE_ROW (sheet))
+  if (range->row0 > max_visible_row (sheet))
     return FALSE;
 
-  if (range.coli < MIN_VISIBLE_COLUMN (sheet))
+  if (range->coli < min_visible_column (sheet))
     return FALSE;
 
-  if (range.col0 > MAX_VISIBLE_COLUMN (sheet))
+  if (range->col0 > max_visible_column (sheet))
     return FALSE;
 
   return TRUE;
 }
 
 static gboolean
-gtk_sheet_cell_isvisible (GtkSheet * sheet,
+gtk_sheet_cell_isvisible (GtkSheet *sheet,
                          gint row, gint column)
 {
   GtkSheetRange range;
@@ -2269,7 +1571,7 @@ gtk_sheet_cell_isvisible (GtkSheet * sheet,
   range.rowi = row;
   range.coli = column;
 
-  return gtk_sheet_range_isvisible (sheet, range);
+  return gtk_sheet_range_isvisible (sheet, &range);
 }
 
 void
@@ -2279,136 +1581,45 @@ gtk_sheet_get_visible_range (GtkSheet *sheet, GtkSheetRange *range)
   g_return_if_fail (GTK_IS_SHEET (sheet)) ;
   g_return_if_fail (range != NULL);
 
-  range->row0 = MIN_VISIBLE_ROW (sheet);
-  range->col0 = MIN_VISIBLE_COLUMN (sheet);
-  range->rowi = MAX_VISIBLE_ROW (sheet);
-  range->coli = MAX_VISIBLE_COLUMN (sheet);
-}
-
-GtkAdjustment *
-gtk_sheet_get_vadjustment (GtkSheet * sheet)
-{
-  g_return_val_if_fail (sheet != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
-
-  return sheet->vadjustment;
+  range->row0 = min_visible_row (sheet);
+  range->col0 = min_visible_column (sheet);
+  range->rowi = max_visible_row (sheet);
+  range->coli = max_visible_column (sheet);
 }
 
-GtkAdjustment *
-gtk_sheet_get_hadjustment (GtkSheet * sheet)
-{
-  g_return_val_if_fail (sheet != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
-
-  return sheet->hadjustment;
-}
 
-void
-gtk_sheet_set_vadjustment (GtkSheet *sheet,
-                          GtkAdjustment *adjustment)
+static void
+gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
+                                 GtkAdjustment *hadjustment,
+                                 GtkAdjustment *vadjustment)
 {
-  GtkAdjustment *old_adjustment;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-  if (adjustment)
-    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
-
-  if (sheet->vadjustment == adjustment)
-    return;
-
-  old_adjustment = sheet->vadjustment;
-
-  if (sheet->vadjustment)
+  if ( sheet->vadjustment != vadjustment )
     {
-      g_signal_handlers_disconnect_matched (sheet->vadjustment,
-                                           G_SIGNAL_MATCH_DATA,
-                                           0, 0, 0, 0,
-                                           sheet);
-      g_object_unref (sheet->vadjustment);
-    }
-
-  sheet->vadjustment = adjustment;
-
-  if (sheet->vadjustment)
-    {
-      g_object_ref (sheet->vadjustment);
-      g_object_ref_sink (sheet->vadjustment);
+      if (sheet->vadjustment)
+       g_object_unref (sheet->vadjustment);
+      sheet->vadjustment = vadjustment;
+      g_object_ref (vadjustment);
 
       g_signal_connect (sheet->vadjustment, "value_changed",
                        G_CALLBACK (vadjustment_value_changed),
                        sheet);
     }
 
-  if (!sheet->vadjustment || !old_adjustment)
-    {
-      gtk_widget_queue_resize (GTK_WIDGET (sheet));
-      return;
-    }
-
-  sheet->old_vadjustment = sheet->vadjustment->value;
-}
-
-void
-gtk_sheet_set_hadjustment (GtkSheet *sheet,
-                          GtkAdjustment *adjustment)
-{
-  GtkAdjustment *old_adjustment;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-  if (adjustment)
-    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
-
-  if (sheet->hadjustment == adjustment)
-    return;
-
-  old_adjustment = sheet->hadjustment;
-
-  if (sheet->hadjustment)
-    {
-      g_signal_handlers_disconnect_matched (sheet->hadjustment,
-                                           G_SIGNAL_MATCH_DATA,
-                                           0, 0, 0, 0,
-                                           sheet);
-      g_object_unref (sheet->hadjustment);
-    }
-
-  sheet->hadjustment = adjustment;
-
-  if (sheet->hadjustment)
+  if ( sheet->hadjustment != hadjustment )
     {
-      g_object_ref (sheet->hadjustment);
-      g_object_ref_sink (sheet->hadjustment);
+      if (sheet->hadjustment)
+       g_object_unref (sheet->hadjustment);
+      sheet->hadjustment = hadjustment;
+      g_object_ref (hadjustment);
 
       g_signal_connect (sheet->hadjustment, "value_changed",
                        G_CALLBACK (hadjustment_value_changed),
                        sheet);
     }
-
-  if (!sheet->hadjustment || !old_adjustment)
-    {
-      gtk_widget_queue_resize (GTK_WIDGET (sheet));
-      return;
-    }
-
-  sheet->old_hadjustment = sheet->hadjustment->value;
-}
-
-static void
-gtk_sheet_set_scroll_adjustments (GtkSheet *sheet,
-                                 GtkAdjustment *hadjustment,
-                                 GtkAdjustment *vadjustment)
-{
-  if (sheet->hadjustment != hadjustment)
-    gtk_sheet_set_hadjustment (sheet, hadjustment);
-
-  if (sheet->vadjustment != vadjustment)
-    gtk_sheet_set_vadjustment (sheet, vadjustment);
 }
 
 static void
-gtk_sheet_finalize (GObject * object)
+gtk_sheet_finalize (GObject *object)
 {
   GtkSheet *sheet;
 
@@ -2425,7 +1636,6 @@ static void
 gtk_sheet_dispose  (GObject *object)
 {
   GtkSheet *sheet = GTK_SHEET (object);
-  GList *children;
 
   g_return_if_fail (object != NULL);
   g_return_if_fail (GTK_IS_SHEET (object));
@@ -2436,11 +1646,8 @@ gtk_sheet_dispose  (GObject *object)
   sheet->dispose_has_run = TRUE;
 
   if (sheet->model) g_object_unref (sheet->model);
-  if (sheet->row_geometry) g_object_unref (sheet->row_geometry);
-  if (sheet->column_geometry) g_object_unref (sheet->column_geometry);
-
-  g_object_unref (sheet->entry_container);
-  sheet->entry_container = NULL;
+  if (sheet->vaxis) g_object_unref (sheet->vaxis);
+  if (sheet->haxis) g_object_unref (sheet->haxis);
 
   g_object_unref (sheet->button);
   sheet->button = NULL;
@@ -2469,16 +1676,6 @@ gtk_sheet_dispose  (GObject *object)
       sheet->vadjustment = NULL;
     }
 
-  children = sheet->children;
-  while (children)
-    {
-      GtkSheetChild *child = (GtkSheetChild *)children->data;
-      if (child && child->widget)
-       gtk_sheet_remove (GTK_CONTAINER (sheet), child->widget);
-      children = sheet->children;
-    }
-  sheet->children = NULL;
-
   if (G_OBJECT_CLASS (parent_class)->dispose)
     (*G_OBJECT_CLASS (parent_class)->dispose) (object);
 }
@@ -2502,18 +1699,22 @@ gtk_sheet_style_set (GtkWidget *widget,
       gtk_style_set_background (widget->style, widget->window, widget->state);
     }
 
+  set_entry_widget_font (sheet);
 }
 
+#define BORDER_WIDTH 2
+
 static void
-gtk_sheet_realize (GtkWidget * widget)
+gtk_sheet_realize (GtkWidget *widget)
 {
   GtkSheet *sheet;
   GdkWindowAttr attributes;
-  gint attributes_mask;
-  GdkGCValues values, auxvalues;
+  const gint attributes_mask =
+    GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_CURSOR;
+
+  GdkGCValues values;
   GdkColormap *colormap;
-  GtkSheetChild *child;
-  GList *children;
+  GdkDisplay *display;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_SHEET (widget));
@@ -2522,6 +1723,9 @@ gtk_sheet_realize (GtkWidget * widget)
 
   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
 
+  colormap = gtk_widget_get_colormap (widget);
+  display = gtk_widget_get_display (widget);
+
   attributes.window_type = GDK_WINDOW_CHILD;
   attributes.x = widget->allocation.x;
   attributes.y = widget->allocation.y;
@@ -2530,19 +1734,19 @@ gtk_sheet_realize (GtkWidget * widget)
   attributes.wclass = GDK_INPUT_OUTPUT;
 
   attributes.visual = gtk_widget_get_visual (widget);
-  attributes.colormap = gtk_widget_get_colormap (widget);
+  attributes.colormap = colormap;
 
   attributes.event_mask = gtk_widget_get_events (widget);
   attributes.event_mask |= (GDK_EXPOSURE_MASK |
                            GDK_BUTTON_PRESS_MASK |
                            GDK_BUTTON_RELEASE_MASK |
                            GDK_KEY_PRESS_MASK |
+                           GDK_ENTER_NOTIFY_MASK |
+                           GDK_LEAVE_NOTIFY_MASK |
                            GDK_POINTER_MOTION_MASK |
                            GDK_POINTER_MOTION_HINT_MASK);
-  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP |
-    GDK_WA_CURSOR;
 
-  attributes.cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
+  attributes.cursor = gdk_cursor_new_for_display (display, GDK_TOP_LEFT_ARROW);
 
   /* main window */
   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
@@ -2553,39 +1757,47 @@ gtk_sheet_realize (GtkWidget * widget)
 
   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
 
+  gdk_color_parse ("white", &sheet->color[BG_COLOR]);
+  gdk_colormap_alloc_color (colormap, &sheet->color[BG_COLOR], FALSE,
+                           TRUE);
+  gdk_color_parse ("gray", &sheet->color[GRID_COLOR]);
+  gdk_colormap_alloc_color (colormap, &sheet->color[GRID_COLOR], FALSE,
+                           TRUE);
+
   attributes.x = 0;
-  if (sheet->row_titles_visible)
-    attributes.x = sheet->row_title_area.width;
   attributes.y = 0;
   attributes.width = sheet->column_title_area.width;
   attributes.height = sheet->column_title_area.height;
 
+
   /* column - title window */
-  sheet->column_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
+  sheet->column_title_window =
+    gdk_window_new (widget->window, &attributes, attributes_mask);
   gdk_window_set_user_data (sheet->column_title_window, sheet);
-  gtk_style_set_background (widget->style, sheet->column_title_window, GTK_STATE_NORMAL);
+  gtk_style_set_background (widget->style, sheet->column_title_window,
+                           GTK_STATE_NORMAL);
+
 
   attributes.x = 0;
   attributes.y = 0;
-  if (sheet->column_titles_visible)
-    attributes.y = sheet->column_title_area.height;
   attributes.width = sheet->row_title_area.width;
   attributes.height = sheet->row_title_area.height;
 
   /* row - title window */
-  sheet->row_title_window = gdk_window_new (widget->window, &attributes, attributes_mask);
+  sheet->row_title_window = gdk_window_new (widget->window,
+                                           &attributes, attributes_mask);
   gdk_window_set_user_data (sheet->row_title_window, sheet);
-  gtk_style_set_background (widget->style, sheet->row_title_window, GTK_STATE_NORMAL);
+  gtk_style_set_background (widget->style, sheet->row_title_window,
+                           GTK_STATE_NORMAL);
 
   /* sheet - window */
-  attributes.cursor = gdk_cursor_new (GDK_PLUS);
+  attributes.cursor = gdk_cursor_new_for_display (display, GDK_PLUS);
 
   attributes.x = 0;
   attributes.y = 0;
-  attributes.width = sheet->sheet_window_width,
-    attributes.height = sheet->sheet_window_height;
 
-  sheet->sheet_window = gdk_window_new (widget->window, &attributes, attributes_mask);
+  sheet->sheet_window = gdk_window_new (widget->window,
+                                       &attributes, attributes_mask);
   gdk_window_set_user_data (sheet->sheet_window, sheet);
 
   gdk_cursor_unref (attributes.cursor);
@@ -2593,31 +1805,22 @@ gtk_sheet_realize (GtkWidget * widget)
   gdk_window_set_background (sheet->sheet_window, &widget->style->white);
   gdk_window_show (sheet->sheet_window);
 
-  /* backing_pixmap */
-  gtk_sheet_make_backing_pixmap (sheet, 0, 0);
-
   /* GCs */
-  if (sheet->fg_gc)
-    g_object_unref (sheet->fg_gc);
-  if (sheet->bg_gc)
-    g_object_unref (sheet->bg_gc);
   sheet->fg_gc = gdk_gc_new (widget->window);
   sheet->bg_gc = gdk_gc_new (widget->window);
 
-  colormap = gtk_widget_get_colormap (widget);
-
-  gdk_gc_get_values (sheet->fg_gc, &auxvalues);
-
   values.foreground = widget->style->white;
   values.function = GDK_INVERT;
   values.subwindow_mode = GDK_INCLUDE_INFERIORS;
-  if (sheet->xor_gc)
-    g_object_unref (sheet->xor_gc);
+  values.line_width = BORDER_WIDTH;
+
   sheet->xor_gc = gdk_gc_new_with_values (widget->window,
                                          &values,
                                          GDK_GC_FOREGROUND |
                                          GDK_GC_FUNCTION |
-                                         GDK_GC_SUBWINDOW);
+                                         GDK_GC_SUBWINDOW |
+                                         GDK_GC_LINE_WIDTH
+                                         );
 
 
   gtk_widget_set_parent_window (sheet->entry_widget, sheet->sheet_window);
@@ -2627,25 +1830,17 @@ gtk_sheet_realize (GtkWidget * widget)
   gtk_widget_set_parent (sheet->button, GTK_WIDGET (sheet));
 
 
-  gdk_cursor_unref (sheet->cursor_drag);
-  sheet->cursor_drag = gdk_cursor_new (GDK_PLUS);
+  sheet->cursor_drag = gdk_cursor_new_for_display (display, GDK_PLUS);
 
   if (sheet->column_titles_visible)
     gdk_window_show (sheet->column_title_window);
   if (sheet->row_titles_visible)
     gdk_window_show (sheet->row_title_window);
 
-  size_allocate_row_title_buttons (sheet);
-  size_allocate_column_title_buttons (sheet);
-
-  children = sheet->children;
-  while (children)
-    {
-      child = children->data;
-      children = children->next;
+  sheet->hover_window = create_hover_window ();
 
-      gtk_sheet_realize_child (sheet, child);
-    }
+  draw_row_title_buttons (sheet);
+  draw_column_title_buttons (sheet);
 
   gtk_sheet_update_primary_selection (sheet);
 }
@@ -2685,15 +1880,12 @@ size_allocate_global_button (GtkSheet *sheet)
 static void
 global_button_clicked (GtkWidget *widget, gpointer data)
 {
-  gboolean veto;
-
-  gtk_sheet_click_cell (GTK_SHEET (data), - 1, - 1, &veto);
-  gtk_widget_grab_focus (GTK_WIDGET (data));
+  gtk_sheet_click_cell (GTK_SHEET (data), -1, -1);
 }
 
 
 static void
-gtk_sheet_unrealize (GtkWidget * widget)
+gtk_sheet_unrealize (GtkWidget *widget)
 {
   GtkSheet *sheet;
 
@@ -2703,27 +1895,21 @@ gtk_sheet_unrealize (GtkWidget * widget)
   sheet = GTK_SHEET (widget);
 
   gdk_cursor_unref (sheet->cursor_drag);
+  sheet->cursor_drag = NULL;
+
+  gdk_colormap_free_colors (gtk_widget_get_colormap (widget),
+                           sheet->color, n_COLORS);
 
   g_object_unref (sheet->xor_gc);
   g_object_unref (sheet->fg_gc);
   g_object_unref (sheet->bg_gc);
 
+  destroy_hover_window (sheet->hover_window);
+
   gdk_window_destroy (sheet->sheet_window);
   gdk_window_destroy (sheet->column_title_window);
   gdk_window_destroy (sheet->row_title_window);
 
-  if (sheet->pixmap)
-    {
-      g_object_unref (sheet->pixmap);
-      sheet->pixmap = NULL;
-    }
-
-  sheet->column_title_window = NULL;
-  sheet->sheet_window = NULL;
-  sheet->xor_gc = NULL;
-  sheet->fg_gc = NULL;
-  sheet->bg_gc = NULL;
-
   gtk_widget_unparent (sheet->entry_widget);
   if (sheet->button != NULL)
     gtk_widget_unparent (sheet->button);
@@ -2733,11 +1919,9 @@ gtk_sheet_unrealize (GtkWidget * widget)
 }
 
 static void
-gtk_sheet_map (GtkWidget * widget)
+gtk_sheet_map (GtkWidget *widget)
 {
   GtkSheet *sheet = GTK_SHEET (widget);
-  GtkSheetChild *child;
-  GList *children;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_SHEET (widget));
@@ -2751,12 +1935,12 @@ gtk_sheet_map (GtkWidget * widget)
 
       if (sheet->column_titles_visible)
        {
-         size_allocate_column_title_buttons (sheet);
+         draw_column_title_buttons (sheet);
          gdk_window_show (sheet->column_title_window);
        }
       if (sheet->row_titles_visible)
        {
-         size_allocate_row_title_buttons (sheet);
+         draw_row_title_buttons (sheet);
          gdk_window_show (sheet->row_title_window);
        }
 
@@ -2781,92 +1965,62 @@ gtk_sheet_map (GtkWidget * widget)
          gtk_widget_map (GTK_BIN (sheet->button)->child);
 
       gtk_sheet_range_draw (sheet, NULL);
-      gtk_sheet_activate_cell (sheet,
-                              sheet->active_cell.row,
-                              sheet->active_cell.col);
-
-      children = sheet->children;
-      while (children)
-       {
-         child = children->data;
-         children = children->next;
-
-         if (GTK_WIDGET_VISIBLE (child->widget) &&
-             !GTK_WIDGET_MAPPED (child->widget))
-           {
-             gtk_widget_map (child->widget);
-             gtk_sheet_position_child (sheet, child);
-           }
-       }
-
+      change_active_cell (sheet,
+                    sheet->active_cell.row,
+                    sheet->active_cell.col);
     }
 }
 
 static void
-gtk_sheet_unmap (GtkWidget * widget)
+gtk_sheet_unmap (GtkWidget *widget)
 {
-  GtkSheet *sheet;
-  GtkSheetChild *child;
-  GList *children;
-
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_SHEET (widget));
-
-  sheet = GTK_SHEET (widget);
-
-  if (GTK_WIDGET_MAPPED (widget))
-    {
-      GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
-
-      gdk_window_hide (sheet->sheet_window);
-      if (sheet->column_titles_visible)
-       gdk_window_hide (sheet->column_title_window);
-      if (sheet->row_titles_visible)
-       gdk_window_hide (sheet->row_title_window);
-      gdk_window_hide (widget->window);
+  GtkSheet *sheet = GTK_SHEET (widget);
 
-      if (GTK_WIDGET_MAPPED (sheet->entry_widget))
-       gtk_widget_unmap (sheet->entry_widget);
+  if (!GTK_WIDGET_MAPPED (widget))
+    return;
 
-      if (GTK_WIDGET_MAPPED (sheet->button))
-       gtk_widget_unmap (sheet->button);
+  GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
 
-      children = sheet->children;
-      while (children)
-       {
-         child = children->data;
-         children = children->next;
+  gdk_window_hide (sheet->sheet_window);
+  if (sheet->column_titles_visible)
+    gdk_window_hide (sheet->column_title_window);
+  if (sheet->row_titles_visible)
+    gdk_window_hide (sheet->row_title_window);
+  gdk_window_hide (widget->window);
 
-         if (GTK_WIDGET_VISIBLE (child->widget) &&
-             GTK_WIDGET_MAPPED (child->widget))
-           {
-             gtk_widget_unmap (child->widget);
-           }
-       }
+  if (GTK_WIDGET_MAPPED (sheet->entry_widget))
+    gtk_widget_unmap (sheet->entry_widget);
 
-    }
+  if (GTK_WIDGET_MAPPED (sheet->button))
+    gtk_widget_unmap (sheet->button);
 }
 
 
 static void
-gtk_sheet_cell_draw_default (GtkSheet *sheet, gint row, gint col)
+gtk_sheet_cell_draw (GtkSheet *sheet, gint row, gint col)
 {
-  GtkWidget *widget;
-  GdkGC *fg_gc, *bg_gc;
+  PangoLayout *layout;
+  PangoRectangle text;
+  PangoFontDescription *font_desc = GTK_WIDGET (sheet)->style->font_desc;
+  gint font_height;
+
+  gchar *label;
+
   GtkSheetCellAttr attributes;
   GdkRectangle area;
 
   g_return_if_fail (sheet != NULL);
 
-  /* bail now if we arn't drawable yet */
+  /* bail now if we aren't yet drawable */
   if (!GTK_WIDGET_DRAWABLE (sheet)) return;
 
-  if (row < 0 || row >= yyy_row_count (sheet)) return;
-  if (col < 0 || col >= xxx_column_count (sheet)) return;
-  if (! xxx_column_is_visible (sheet, col)) return;
-  if (! yyy_row_is_visible (sheet, row)) return;
+  if (row < 0 ||
+      row >= psppire_axis_unit_count (sheet->vaxis))
+    return;
 
-  widget = GTK_WIDGET (sheet);
+  if (col < 0 ||
+      col >= psppire_axis_unit_count (sheet->haxis))
+    return;
 
   gtk_sheet_get_attributes (sheet, row, col, &attributes);
 
@@ -2874,226 +2028,79 @@ gtk_sheet_cell_draw_default (GtkSheet *sheet, gint row, gint col)
   gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
   gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
 
-  fg_gc = sheet->fg_gc;
-  bg_gc = sheet->bg_gc;
-
-  area.x = COLUMN_LEFT_XPIXEL (sheet, col);
-  area.y = ROW_TOP_YPIXEL (sheet, row);
-  area.width= xxx_column_width (sheet, col);
-  area.height = yyy_row_height (sheet, row);
-
-  gdk_draw_rectangle (sheet->pixmap,
-                     bg_gc,
-                     TRUE,
-                     area.x,
-                     area.y,
-                     area.width,
-                     area.height);
+  rectangle_from_cell (sheet, row, col, &area);
 
   gdk_gc_set_line_attributes (sheet->fg_gc, 1, 0, 0, 0);
 
   if (sheet->show_grid)
     {
-      gdk_gc_set_foreground (sheet->bg_gc, &sheet->grid_color);
+      gdk_gc_set_foreground (sheet->bg_gc, &sheet->color[GRID_COLOR]);
 
-      gdk_draw_rectangle (sheet->pixmap,
+      gdk_draw_rectangle (sheet->sheet_window,
                          sheet->bg_gc,
                          FALSE,
                          area.x, area.y,
                          area.width, area.height);
     }
-}
-
-static void
-gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
-{
-  GtkWidget *widget;
-  GdkRectangle area;
-  gint i;
-  gint text_width, text_height, y;
-  gint xoffset = 0;
-  gint size, sizel, sizer;
-  GdkGC *fg_gc, *bg_gc;
-  GtkSheetCellAttr attributes;
-  PangoLayout *layout;
-  PangoRectangle rect;
-  PangoRectangle logical_rect;
-  PangoLayoutLine *line;
-  PangoFontMetrics *metrics;
-  PangoContext *context = gtk_widget_get_pango_context (GTK_WIDGET (sheet));
-  gint ascent, descent, y_pos;
-
-  gchar *label;
-
-  g_return_if_fail (sheet != NULL);
 
-  /* bail now if we aren't drawable yet */
-  if (!GTK_WIDGET_DRAWABLE (sheet))
-    return;
 
   label = gtk_sheet_cell_get_text (sheet, row, col);
-  if (!label)
+  if (NULL == label)
     return;
 
-  if (row < 0 || row >= yyy_row_count (sheet)) return;
-  if (col < 0 || col >= xxx_column_count (sheet)) return;
-  if (! xxx_column_is_visible (sheet, col)) return;
-  if (!yyy_row_is_visible (sheet, row)) return;
-
-
-  widget = GTK_WIDGET (sheet);
-
-  gtk_sheet_get_attributes (sheet, row, col, &attributes);
-
-  /* select GC for background rectangle */
-  gdk_gc_set_foreground (sheet->fg_gc, &attributes.foreground);
-  gdk_gc_set_foreground (sheet->bg_gc, &attributes.background);
-
-  fg_gc = sheet->fg_gc;
-  bg_gc = sheet->bg_gc;
-
-  area.x = COLUMN_LEFT_XPIXEL (sheet, col);
-  area.y = ROW_TOP_YPIXEL (sheet, row);
-  area.width = xxx_column_width (sheet, col);
-  area.height = yyy_row_height (sheet, row);
-
 
   layout = gtk_widget_create_pango_layout (GTK_WIDGET (sheet), label);
   dispose_string (sheet, label);
-  pango_layout_set_font_description (layout, attributes.font_desc);
-
-  pango_layout_get_pixel_extents (layout, NULL, &rect);
 
-  line = pango_layout_get_lines (layout)->data;
-  pango_layout_line_get_extents (line, NULL, &logical_rect);
 
-  metrics = pango_context_get_metrics (context,
-                                      attributes.font_desc,
-                                      pango_context_get_language (context));
+  pango_layout_set_font_description (layout, font_desc);
 
-  ascent = pango_font_metrics_get_ascent (metrics) / PANGO_SCALE;
-  descent = pango_font_metrics_get_descent (metrics) / PANGO_SCALE;
+  pango_layout_get_pixel_extents (layout, NULL, &text);
 
-  pango_font_metrics_unref (metrics);
+  gdk_gc_set_clip_rectangle (sheet->fg_gc, &area);
 
-  /* Align primarily for locale's ascent / descent */
+  font_height = pango_font_description_get_size (font_desc);
+  if ( !pango_font_description_get_size_is_absolute (font_desc))
+    font_height /= PANGO_SCALE;
 
-  logical_rect.height /= PANGO_SCALE;
-  logical_rect.y /= PANGO_SCALE;
-  y_pos = area.height - logical_rect.height;
-
-  if (logical_rect.height > area.height)
-    y_pos = (logical_rect.height - area.height - 2 * CELLOFFSET) / 2;
-  else if (y_pos < 0)
-    y_pos = 0;
-  else if (y_pos + logical_rect.height > area.height)
-    y_pos = area.height - logical_rect.height;
-
-  text_width = rect.width;
-  text_height = rect.height;
-  y = area.y + y_pos - CELLOFFSET;
+  /* Centre the text vertically */
+  area.y += (area.height - font_height) / 2.0;
 
   switch (attributes.justification)
     {
     case GTK_JUSTIFY_RIGHT:
-      size = area.width;
-      area.x +=area.width;
-      {
-       for (i = col - 1; i >= MIN_VISIBLE_COLUMN (sheet); i--)
-         {
-           if ( !gtk_sheet_cell_empty (sheet, row, i)) break;
-           if (size >= text_width + CELLOFFSET) break;
-           size +=xxx_column_width (sheet, i);
-           xxx_column_set_right_column (sheet, i,
-                                        MAX (col,
-                                             xxx_column_right_column (sheet, i)));
-         }
-       area.width = size;
-      }
-      area.x -= size;
-      xoffset += area.width - text_width - 2 * CELLOFFSET -
-       attributes.border.width / 2;
+      area.x += area.width - text.width;
       break;
     case GTK_JUSTIFY_CENTER:
-      sizel = area.width / 2;
-      sizer = area.width / 2;
-      area.x += area.width / 2;
-      {
-       for (i = col + 1; i <= MAX_VISIBLE_COLUMN (sheet); i++)
-         {
-           if ( ! gtk_sheet_cell_empty (sheet, row, i)) break;
-           if (sizer >= text_width / 2) break;
-           sizer += xxx_column_width (sheet, i);
-           xxx_column_set_left_column (sheet, i,
-                                       MIN (
-                                            col,
-                                            xxx_column_left_column (sheet, i)));
-         }
-       for (i = col - 1; i >= MIN_VISIBLE_COLUMN (sheet); i--)
-         {
-           if ( ! gtk_sheet_cell_empty (sheet, row, i)) break;
-           if (sizel >= text_width / 2) break;
-           sizel +=xxx_column_width (sheet, i);
-           xxx_column_set_right_column (sheet, i,
-                                        MAX (col,
-                                             xxx_column_right_column (sheet, i)));
-         }
-       size = MIN (sizel, sizer);
-      }
-      area.x -= sizel;
-      xoffset += sizel - text_width / 2 - CELLOFFSET;
-      area.width = sizel + sizer;
+      area.x += (area.width - text.width) / 2.0;
       break;
     case GTK_JUSTIFY_LEFT:
+      /* Do nothing */
+      break;
     default:
-      size = area.width;
-      {
-       for (i = col + 1; i <= MAX_VISIBLE_COLUMN (sheet); i++)
-         {
-           if (! gtk_sheet_cell_empty (sheet, row, i)) break;
-           if (size >= text_width + CELLOFFSET) break;
-           size +=xxx_column_width (sheet, i);
-           xxx_column_set_left_column (sheet, i,
-                                       MIN (
-                                            col,
-                                            xxx_column_left_column (sheet, i)));
-
-         }
-       area.width = size;
-      }
-      xoffset += attributes.border.width / 2;
+      g_critical ("Unhandled justification %d in column %d\n",
+                attributes.justification, col);
       break;
     }
 
-  gdk_gc_set_clip_rectangle (fg_gc, &area);
-
-
-  gdk_draw_layout (sheet->pixmap, fg_gc,
-                  area.x + xoffset + CELLOFFSET,
-                  y,
+  gdk_draw_layout (sheet->sheet_window, sheet->fg_gc,
+                  area.x,
+                  area.y,
                   layout);
 
-  gdk_gc_set_clip_rectangle (fg_gc, NULL);
+  gdk_gc_set_clip_rectangle (sheet->fg_gc, NULL);
   g_object_unref (layout);
+}
 
-  gdk_draw_drawable (sheet->sheet_window,
-                  GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
-                  sheet->pixmap,
-                  area.x,
-                  area.y,
-                  area.x,
-                  area.y,
-                  area.width,
-                  area.height);
 
-}
 
 static void
 gtk_sheet_range_draw (GtkSheet *sheet, const GtkSheetRange *range)
 {
   gint i, j;
-  GtkSheetRange drawing_range;
+
   GdkRectangle area;
+  GtkSheetRange drawing_range;
 
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_SHEET (sheet));
@@ -3104,94 +2111,37 @@ gtk_sheet_range_draw (GtkSheet *sheet, const GtkSheetRange *range)
 
   if (range == NULL)
     {
-      drawing_range.row0 = MIN_VISIBLE_ROW (sheet);
-      drawing_range.col0 = MIN_VISIBLE_COLUMN (sheet);
-      drawing_range.rowi = MIN (MAX_VISIBLE_ROW (sheet),
-                               yyy_row_count (sheet) - 1);
-      drawing_range.coli = MAX_VISIBLE_COLUMN (sheet);
-
-
-      gdk_draw_rectangle (sheet->pixmap,
-                         GTK_WIDGET (sheet)->style->white_gc,
-                         TRUE,
-                         0, 0,
-                         sheet->sheet_window_width,
-                         sheet->sheet_window_height);
+      drawing_range.row0 = min_visible_row (sheet);
+      drawing_range.col0 = min_visible_column (sheet);
+      drawing_range.rowi = MIN (max_visible_row (sheet),
+                               psppire_axis_unit_count (sheet->vaxis) - 1);
+      drawing_range.coli = max_visible_column (sheet);
+      gdk_drawable_get_size (sheet->sheet_window, &area.width, &area.height);
+      area.x = area.y = 0;
     }
   else
     {
-      drawing_range.row0 = MAX (range->row0, MIN_VISIBLE_ROW (sheet));
-      drawing_range.col0 = MAX (range->col0, MIN_VISIBLE_COLUMN (sheet));
-      drawing_range.rowi = MIN (range->rowi, MAX_VISIBLE_ROW (sheet));
-      drawing_range.coli = MIN (range->coli, MAX_VISIBLE_COLUMN (sheet));
-    }
-
-  if (drawing_range.coli == xxx_column_count (sheet) - 1)
-    {
-      area.x = COLUMN_LEFT_XPIXEL (sheet,
-                                  xxx_column_count (sheet) - 1) +
-       xxx_column_width (sheet, xxx_column_count (sheet) - 1) + 1;
-
-      area.y = 0;
+      drawing_range.row0 = MAX (range->row0, min_visible_row (sheet));
+      drawing_range.col0 = MAX (range->col0, min_visible_column (sheet));
+      drawing_range.rowi = MIN (range->rowi, max_visible_row (sheet));
+      drawing_range.coli = MIN (range->coli, max_visible_column (sheet));
 
-      gdk_gc_set_foreground (sheet->fg_gc, &sheet->bg_color);
-
-      gdk_draw_rectangle (sheet->pixmap,
-                         sheet->fg_gc,
-                         TRUE,
-                         area.x, area.y,
-                         sheet->sheet_window_width - area.x,
-                         sheet->sheet_window_height);
-
-      gdk_draw_drawable (sheet->sheet_window,
-                      GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
-                      sheet->pixmap,
-                      area.x,
-                      area.y,
-                      area.x,
-                      area.y,
-                      sheet->sheet_window_width - area.x,
-                      sheet->sheet_window_height);
+      rectangle_from_range (sheet, &drawing_range, &area);
     }
 
-  if (drawing_range.rowi == yyy_row_count (sheet) - 1)
-    {
-      area.x = 0;
-      area.y = ROW_TOP_YPIXEL (sheet,
-                              yyy_row_count (sheet) - 1) +
-       yyy_row_height (sheet, yyy_row_count (sheet) - 1) + 1;
-
-      gdk_gc_set_foreground (sheet->fg_gc, &sheet->bg_color);
+  g_return_if_fail (drawing_range.rowi >= drawing_range.row0);
+  g_return_if_fail (drawing_range.coli >= drawing_range.col0);
 
-      gdk_draw_rectangle (sheet->pixmap,
-                         sheet->fg_gc,
-                         TRUE,
-                         area.x, area.y,
-                         sheet->sheet_window_width,
-                         sheet->sheet_window_height - area.y);
-
-      gdk_draw_drawable (sheet->sheet_window,
-                      GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
-                      sheet->pixmap,
-                      area.x,
-                      area.y,
-                      area.x,
-                      area.y,
-                      sheet->sheet_window_width,
-                      sheet->sheet_window_height - area.y);
-    }
+  gdk_window_begin_paint_rect (sheet->sheet_window, &area);
 
   for (i = drawing_range.row0; i <= drawing_range.rowi; i++)
     for (j = drawing_range.col0; j <= drawing_range.coli; j++)
       {
-       gtk_sheet_cell_draw_default (sheet, i, j);
-       gtk_sheet_cell_draw_label (sheet, i, j);
+       gtk_sheet_cell_draw (sheet, i, j);
       }
 
-  gtk_sheet_draw_backing_pixmap (sheet, drawing_range);
-
   if (sheet->state != GTK_SHEET_NORMAL &&
-      gtk_sheet_range_isvisible (sheet, sheet->range))
+      gtk_sheet_range_isvisible (sheet, &sheet->range))
     gtk_sheet_range_draw_selection (sheet, drawing_range);
 
   if (sheet->state == GTK_STATE_NORMAL &&
@@ -3199,7 +2149,9 @@ gtk_sheet_range_draw (GtkSheet *sheet, const GtkSheetRange *range)
       sheet->active_cell.row <= drawing_range.rowi &&
       sheet->active_cell.col >= drawing_range.col0 &&
       sheet->active_cell.col <= drawing_range.coli)
-    gtk_sheet_show_active_cell (sheet);
+    gtk_sheet_show_entry_widget (sheet);
+
+  gdk_window_end_paint (sheet->sheet_window);
 }
 
 static void
@@ -3213,7 +2165,7 @@ gtk_sheet_range_draw_selection (GtkSheet *sheet, GtkSheetRange range)
       range.row0 > sheet->range.rowi || range.rowi < sheet->range.row0)
     return;
 
-  if (!gtk_sheet_range_isvisible (sheet, range)) return;
+  if (!gtk_sheet_range_isvisible (sheet, &range)) return;
   if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
 
   aux = range;
@@ -3223,24 +2175,18 @@ gtk_sheet_range_draw_selection (GtkSheet *sheet, GtkSheetRange range)
   range.row0 = MAX (sheet->range.row0, range.row0);
   range.rowi = MIN (sheet->range.rowi, range.rowi);
 
-  range.col0 = MAX (range.col0, MIN_VISIBLE_COLUMN (sheet));
-  range.coli = MIN (range.coli, MAX_VISIBLE_COLUMN (sheet));
-  range.row0 = MAX (range.row0, MIN_VISIBLE_ROW (sheet));
-  range.rowi = MIN (range.rowi, MAX_VISIBLE_ROW (sheet));
+  range.col0 = MAX (range.col0, min_visible_column (sheet));
+  range.coli = MIN (range.coli, max_visible_column (sheet));
+  range.row0 = MAX (range.row0, min_visible_row (sheet));
+  range.rowi = MIN (range.rowi, max_visible_row (sheet));
 
   for (i = range.row0; i <= range.rowi; i++)
     {
       for (j = range.col0; j <= range.coli; j++)
        {
-
-         if (gtk_sheet_cell_get_state (sheet, i, j) == GTK_STATE_SELECTED &&
-             xxx_column_is_visible (sheet, j) && yyy_row_is_visible (sheet, i))
+         if (gtk_sheet_cell_get_state (sheet, i, j) == GTK_STATE_SELECTED)
            {
-
-             area.x = COLUMN_LEFT_XPIXEL (sheet, j);
-             area.y = ROW_TOP_YPIXEL (sheet, i);
-             area.width= xxx_column_width (sheet, j);
-             area.height = yyy_row_height (sheet, i);
+             rectangle_from_cell (sheet, i, j, &area);
 
              if (i == sheet->range.row0)
                {
@@ -3271,153 +2217,41 @@ gtk_sheet_range_draw_selection (GtkSheet *sheet, GtkSheetRange range)
   gtk_sheet_draw_border (sheet, sheet->range);
 }
 
-static void
-gtk_sheet_draw_backing_pixmap (GtkSheet *sheet, GtkSheetRange range)
-{
-  gint x, y, width, height;
-
-  if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
-
-  x = COLUMN_LEFT_XPIXEL (sheet, range.col0);
-  y = ROW_TOP_YPIXEL (sheet, range.row0);
-  width = COLUMN_LEFT_XPIXEL (sheet, range.coli) - x +
-    xxx_column_width (sheet, range.coli);
-
-  height = ROW_TOP_YPIXEL (sheet, range.rowi)- y + yyy_row_height (sheet, range.rowi);
-
-  if (range.row0 == sheet->range.row0)
-    {
-      y = y - 5;
-      height = height + 5;
-    }
-  if (range.rowi == sheet->range.rowi) height = height + 5;
-  if (range.col0 == sheet->range.col0)
-    {
-      x = x - 5;
-      width = width + 5;
-    }
-  if (range.coli == sheet->range.coli) width = width + 5;
-
-  width = MIN (width, sheet->sheet_window_width - x);
-  height = MIN (height, sheet->sheet_window_height - y);
-
-  x--;
-  y--;
-  width +=2;
-  height +=2;
-
-  x = (sheet->row_titles_visible)
-    ? MAX (x, sheet->row_title_area.width) : MAX (x, 0);
-  y = (sheet->column_titles_visible)
-    ? MAX (y, sheet->column_title_area.height) : MAX (y, 0);
-
-  if (range.coli == xxx_column_count (sheet) - 1)
-    width = sheet->sheet_window_width - x;
-  if (range.rowi == yyy_row_count (sheet) - 1)
-    height = sheet->sheet_window_height - y;
-
-  gdk_draw_drawable (sheet->sheet_window,
-                  GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
-                  sheet->pixmap,
-                  x,
-                  y,
-                  x,
-                  y,
-                  width + 1,
-                  height + 1);
-}
-
-
-void
-gtk_sheet_set_cell_text (GtkSheet *sheet, gint row, gint col, const gchar *text)
-{
-  GtkSheetCellAttr attributes;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-  if (col >= xxx_column_count (sheet) || row >= yyy_row_count (sheet)) return;
-  if (col < 0 || row < 0) return;
-
-  gtk_sheet_get_attributes (sheet, row, col, &attributes);
-  gtk_sheet_set_cell (sheet, row, col, attributes.justification, text);
-}
-
 static inline gint
 safe_strcmp (const gchar *s1, const gchar *s2)
 {
   if ( !s1 && !s2) return 0;
-  if ( !s1) return - 1;
+  if ( !s1) return -1;
   if ( !s2) return +1;
   return strcmp (s1, s2);
 }
 
-void
+static void
 gtk_sheet_set_cell (GtkSheet *sheet, gint row, gint col,
                    GtkJustification justification,
                    const gchar *text)
 {
   GSheetModel *model ;
-  gboolean changed ;
   gchar *old_text ;
 
-  GtkSheetRange range;
-  gint text_width;
-  GtkSheetCellAttr attributes;
-
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
-  if (col >= xxx_column_count (sheet) || row >= yyy_row_count (sheet)) return;
-  if (col < 0 || row < 0) return;
 
-  gtk_sheet_get_attributes (sheet, row, col, &attributes);
+  if (col >= psppire_axis_unit_count (sheet->haxis)
+      || row >= psppire_axis_unit_count (sheet->vaxis))
+    return;
 
-  attributes.justification = justification;
+  if (col < 0 || row < 0) return;
 
   model = gtk_sheet_get_model (sheet);
 
   old_text = g_sheet_model_get_string (model, row, col);
 
-  changed = FALSE;
-
   if (0 != safe_strcmp (old_text, text))
-    changed = g_sheet_model_set_string (model, text, row, col);
+    g_sheet_model_set_string (model, text, row, col);
 
   if ( g_sheet_model_free_strings (model))
     g_free (old_text);
-
-
-  if (changed && attributes.is_visible)
-    {
-      gchar *s = gtk_sheet_cell_get_text (sheet, row, col);
-      text_width = 0;
-      if (s && strlen (s) > 0)
-       {
-         text_width = STRING_WIDTH (GTK_WIDGET (sheet),
-                                    attributes.font_desc, text);
-       }
-      dispose_string (sheet, s);
-
-      range.row0 = row;
-      range.rowi = row;
-      range.col0 = MIN_VISIBLE_COLUMN (sheet);
-      range.coli = MAX_VISIBLE_COLUMN (sheet);
-
-      if (gtk_sheet_autoresize (sheet) &&
-         text_width > xxx_column_width (sheet, col) -
-         2 * CELLOFFSET- attributes.border.width)
-       {
-         gtk_sheet_set_column_width (sheet, col, text_width + 2 * CELLOFFSET
-                                     + attributes.border.width);
-         GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_REDRAW_PENDING);
-       }
-      else
-       if (!GTK_SHEET_IS_FROZEN (sheet))
-         gtk_sheet_range_draw (sheet, &range);
-    }
-
-  if ( changed )
-    g_signal_emit (sheet, sheet_signals[CHANGED], 0, row, col);
-
 }
 
 
@@ -3428,22 +2262,19 @@ gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
 
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
-  if (column >= xxx_column_count (sheet) ||
-      row >= yyy_row_count (sheet)) return;
+  if (column >= psppire_axis_unit_count (sheet->haxis) ||
+      row >= psppire_axis_unit_count (sheet->vaxis)) return;
 
   if (column < 0 || row < 0) return;
 
   range.row0 = row;
   range.rowi = row;
-  range.col0 = MIN_VISIBLE_COLUMN (sheet);
-  range.coli = MAX_VISIBLE_COLUMN (sheet);
+  range.col0 = min_visible_column (sheet);
+  range.coli = max_visible_column (sheet);
 
   gtk_sheet_real_cell_clear (sheet, row, column);
 
-  if (!GTK_SHEET_IS_FROZEN (sheet))
-    {
-      gtk_sheet_range_draw (sheet, &range);
-    }
+  gtk_sheet_range_draw (sheet, &range);
 }
 
 static void
@@ -3461,59 +2292,6 @@ gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column)
   dispose_string (sheet, old_text);
 }
 
-void
-gtk_sheet_range_clear (GtkSheet *sheet, const GtkSheetRange *range)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  gtk_sheet_real_range_clear (sheet, range);
-}
-
-static void
-gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range)
-{
-  gint i, j;
-  GtkSheetRange clear;
-
-  if (!range)
-    {
-      clear.row0 = 0;
-      clear.rowi = yyy_row_count (sheet) - 1;
-      clear.col0 = 0;
-      clear.coli = xxx_column_count (sheet) - 1;
-    }
-  else
-    clear=*range;
-
-  clear.row0 = MAX (clear.row0, 0);
-  clear.col0 = MAX (clear.col0, 0);
-  clear.rowi = MIN (clear.rowi, yyy_row_count (sheet) - 1 );
-  clear.coli = MIN (clear.coli, xxx_column_count (sheet) - 1 );
-
-  for (i = clear.row0; i <= clear.rowi; i++)
-    for (j = clear.col0; j <= clear.coli; j++)
-      {
-       gtk_sheet_real_cell_clear (sheet, i, j);
-      }
-
-  gtk_sheet_range_draw (sheet, NULL);
-}
-
-
-static gboolean
-gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col)
-{
-  gboolean empty;
-  char *text = gtk_sheet_cell_get_text (sheet, row, col);
-  empty = (text == NULL );
-
-  dispose_string (sheet, text);
-
-  return empty;
-}
-
-
 gchar *
 gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col)
 {
@@ -3521,7 +2299,7 @@ gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col)
   g_return_val_if_fail (sheet != NULL, NULL);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
 
-  if (col >= xxx_column_count (sheet) || row >= yyy_row_count (sheet))
+  if (col >= psppire_axis_unit_count (sheet->haxis) || row >= psppire_axis_unit_count (sheet->vaxis))
     return NULL;
   if (col < 0 || row < 0) return NULL;
 
@@ -3534,7 +2312,7 @@ gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col)
 }
 
 
-GtkStateType
+static GtkStateType
 gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
 {
   gint state;
@@ -3542,7 +2320,7 @@ gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
 
   g_return_val_if_fail (sheet != NULL, 0);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
-  if (col >= xxx_column_count (sheet) || row >= yyy_row_count (sheet)) return 0;
+  if (col >= psppire_axis_unit_count (sheet->haxis) || row >= psppire_axis_unit_count (sheet->vaxis)) return 0;
   if (col < 0 || row < 0) return 0;
 
   state = sheet->state;
@@ -3570,11 +2348,10 @@ gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
   return GTK_STATE_NORMAL;
 }
 
-/* Convert X, Y (in pixels) to *ROW, *COLUMN (in cell coords)
-   -1 indicates the title buttons.
+/* Convert X, Y (in pixels) to *ROW, *COLUMN
    If the function returns FALSE, then the results will be unreliable.
 */
-gboolean
+static gboolean
 gtk_sheet_get_pixel_info (GtkSheet *sheet,
                          gint x,
                          gint y,
@@ -3596,34 +2373,47 @@ gtk_sheet_get_pixel_info (GtkSheet *sheet,
   if (x < 0)
     return FALSE;
 
-  if ( y < sheet->column_title_area.height + sheet->column_title_area.y)
-    *row = -1;
+  if ( sheet->column_titles_visible)
+    y -= sheet->column_title_area.height;
+
+  y += sheet->vadjustment->value;
 
+  if ( y < 0 && sheet->column_titles_visible)
+    {
+      trow = -1;
+    }
   else
     {
-      trow = ROW_FROM_YPIXEL (sheet, y);
-      if (trow > yyy_row_count (sheet))
+      trow = row_from_ypixel (sheet, y);
+      if (trow > psppire_axis_unit_count (sheet->vaxis))
        return FALSE;
-
-      *row = trow;
     }
 
-  if ( x < sheet->row_title_area.width + sheet->row_title_area.x)
-    *column = -1;
+  *row = trow;
+
+  if ( sheet->row_titles_visible)
+    x -= sheet->row_title_area.width;
+
+  x += sheet->hadjustment->value;
+
+  if ( x < 0 && sheet->row_titles_visible)
+    {
+      tcol = -1;
+    }
   else
     {
-      tcol = COLUMN_FROM_XPIXEL (sheet, x);
-      if (tcol > xxx_column_count (sheet))
+      tcol = column_from_xpixel (sheet, x);
+      if (tcol > psppire_axis_unit_count (sheet->haxis))
        return FALSE;
-
-      *column = tcol;
     }
 
+  *column = tcol;
+
   return TRUE;
 }
 
 gboolean
-gtk_sheet_get_cell_area (GtkSheet * sheet,
+gtk_sheet_get_cell_area (GtkSheet *sheet,
                         gint row,
                         gint column,
                         GdkRectangle *area)
@@ -3631,54 +2421,48 @@ gtk_sheet_get_cell_area (GtkSheet * sheet,
   g_return_val_if_fail (sheet != NULL, 0);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
 
-  if (row >= yyy_row_count (sheet) || column >= xxx_column_count (sheet))
+  if (row >= psppire_axis_unit_count (sheet->vaxis) || column >= psppire_axis_unit_count (sheet->haxis))
     return FALSE;
 
-  area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL (sheet, column) -
-                                 (sheet->row_titles_visible
-                                  ? sheet->row_title_area.width
-                                  : 0));
-  area->y = (row == -1) ? 0 : (ROW_TOP_YPIXEL (sheet, row) -
-                              (sheet->column_titles_visible
-                               ? sheet->column_title_area.height
-                               : 0));
+  area->x = (column == -1) ? 0 : psppire_axis_pixel_start (sheet->haxis, column);
+  area->y = (row == -1)    ? 0 : psppire_axis_pixel_start (sheet->vaxis, row);
+
   area->width= (column == -1) ? sheet->row_title_area.width
-    : xxx_column_width (sheet, column);
+    : psppire_axis_unit_size (sheet->haxis, column);
 
   area->height= (row == -1) ? sheet->column_title_area.height
-    : yyy_row_height (sheet, row);
+    : psppire_axis_unit_size (sheet->vaxis, row);
 
   return TRUE;
 }
 
-gboolean
-gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
+void
+gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint col)
 {
-  g_return_val_if_fail (sheet != NULL, 0);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
+  g_return_if_fail (sheet != NULL);
+  g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  if (row < - 1 || column < - 1) return FALSE;
-  if (row >= yyy_row_count (sheet) || column >= xxx_column_count (sheet))
-    return FALSE;
+  if (row < -1 || col < -1)
+    return;
 
-  if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
-    gtk_sheet_deactivate_cell (sheet);
+  if (row >= psppire_axis_unit_count (sheet->vaxis)
+      ||
+      col >= psppire_axis_unit_count (sheet->haxis))
+    return;
 
   sheet->active_cell.row = row;
-  sheet->active_cell.col = column;
+  sheet->active_cell.col = col;
+
+  if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
+    return;
 
-  if ( row == -1 || column == -1)
+  if ( row == -1 || col == -1)
     {
-      gtk_sheet_hide_active_cell (sheet);
-      return TRUE;
+      gtk_sheet_hide_entry_widget (sheet);
+      return;
     }
 
-  if (!gtk_sheet_activate_cell (sheet, row, column)) return FALSE;
-
-  if (gtk_sheet_autoscroll (sheet))
-    gtk_sheet_move_query (sheet, row, column);
-
-  return TRUE;
+  change_active_cell (sheet, row, col);
 }
 
 void
@@ -3716,9 +2500,7 @@ gtk_sheet_entry_changed (GtkWidget *widget, gpointer data)
   sheet->active_cell.row = -1;
   sheet->active_cell.col = -1;
 
-  text = gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)));
-
-  GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IS_FROZEN);
+  text = gtk_entry_get_text (gtk_sheet_get_entry (sheet));
 
   if (text && strlen (text) > 0)
     {
@@ -3727,112 +2509,71 @@ gtk_sheet_entry_changed (GtkWidget *widget, gpointer data)
       gtk_sheet_set_cell (sheet, row, col, justification, text);
     }
 
-  if (sheet->freeze_count == 0)
-    GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IS_FROZEN);
-
   sheet->active_cell.row = row;;
   sheet->active_cell.col = col;
 }
 
 
 static void
-gtk_sheet_deactivate_cell (GtkSheet *sheet)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return ;
-  if (sheet->state != GTK_SHEET_NORMAL) return ;
-
-  if ( sheet->active_cell.row == -1 || sheet->active_cell.col == -1 )
-    return ;
-
-  g_signal_emit (sheet, sheet_signals[DEACTIVATE], 0,
-                sheet->active_cell.row,
-                sheet->active_cell.col);
-
-
-  g_signal_handlers_disconnect_by_func (gtk_sheet_get_entry (sheet),
-                                       G_CALLBACK (gtk_sheet_entry_changed),
-                                       sheet);
-
-  gtk_sheet_hide_active_cell (sheet);
-  sheet->active_cell.row = -1;
-  sheet->active_cell.col = -1;
-
-  if (GTK_SHEET_REDRAW_PENDING (sheet))
-    {
-      GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_REDRAW_PENDING);
-      gtk_sheet_range_draw (sheet, NULL);
-    }
-}
-
-static void
-gtk_sheet_hide_active_cell (GtkSheet *sheet)
+gtk_sheet_hide_entry_widget (GtkSheet *sheet)
 {
-  const char *text;
-  gint row, col;
-  GtkJustification justification;
-  GtkSheetCellAttr attributes;
-
-  if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
-
-  row = sheet->active_cell.row;
-  col = sheet->active_cell.col;
-
-  if (row < 0 || col < 0) return;
-
-  if (sheet->freeze_count == 0)
-    GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IS_FROZEN);
-
-  text = gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)));
-
-  gtk_sheet_get_attributes (sheet, row, col, &attributes);
-  justification = attributes.justification;
+  if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
+    return;
 
-  row = sheet->active_cell.row;
-  col = sheet->active_cell.col;
+  if (sheet->active_cell.row < 0 ||
+      sheet->active_cell.col < 0) return;
 
   gtk_widget_hide (sheet->entry_widget);
   gtk_widget_unmap (sheet->entry_widget);
 
-  if (row != -1 && col != -1)
-    gdk_draw_drawable (sheet->sheet_window,
-                    GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
-                    sheet->pixmap,
-                    COLUMN_LEFT_XPIXEL (sheet, col)- 1,
-                    ROW_TOP_YPIXEL (sheet, row)- 1,
-                    COLUMN_LEFT_XPIXEL (sheet, col)- 1,
-                    ROW_TOP_YPIXEL (sheet, row)- 1,
-                    xxx_column_width (sheet, col) + 4,
-                    yyy_row_height (sheet, row)+4);
-
-  gtk_widget_grab_focus (GTK_WIDGET (sheet));
-
   GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (sheet->entry_widget), GTK_VISIBLE);
-
 }
 
-static gboolean
-gtk_sheet_activate_cell (GtkSheet *sheet, gint row, gint col)
+static void
+change_active_cell (GtkSheet *sheet, gint row, gint col)
 {
-  gboolean veto = TRUE;
+  gint old_row, old_col;
+  glong old_handler_id = sheet->entry_handler_id;
 
-  g_return_val_if_fail (sheet != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
+  g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  if (row < 0 || col < 0) return FALSE;
+  if (row < 0 || col < 0)
+    return;
 
-  if ( row > yyy_row_count (sheet) || col > xxx_column_count (sheet))
-    return FALSE;
+  if ( row > psppire_axis_unit_count (sheet->vaxis)
+       || col > psppire_axis_unit_count (sheet->haxis))
+    return;
 
-  if (!veto) return FALSE;
   if (sheet->state != GTK_SHEET_NORMAL)
     {
       sheet->state = GTK_SHEET_NORMAL;
       gtk_sheet_real_unselect_range (sheet, NULL);
     }
 
+
+  g_signal_handler_block   (sheet->entry_widget, sheet->entry_handler_id);
+
+  old_row = sheet->active_cell.row;
+  old_col = sheet->active_cell.col;
+
+  {
+    /* Redraw the neighbourhood of the old active cell */
+    GtkSheetRange r;
+    r.col0 = old_col - 1;
+    r.coli = old_col + 1;
+    r.row0 = old_row - 1;
+    r.rowi = old_row + 1;
+
+    maximize_int (&r.row0, 0);
+    maximize_int (&r.col0, 0);
+    minimize_int (&r.rowi, psppire_axis_unit_count (sheet->vaxis) - 1);
+    minimize_int (&r.coli, psppire_axis_unit_count (sheet->haxis) - 1);
+
+
+    if (  gtk_sheet_range_isvisible (sheet, &r))
+      gtk_sheet_range_draw (sheet, &r);
+  }
+
   sheet->range.row0 = row;
   sheet->range.col0 = col;
   sheet->range.rowi = row;
@@ -3844,26 +2585,23 @@ gtk_sheet_activate_cell (GtkSheet *sheet, gint row, gint col)
 
   GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
 
-  gtk_sheet_show_active_cell (sheet);
+  gtk_sheet_draw_active_cell (sheet);
+  gtk_sheet_show_entry_widget (sheet);
 
-  g_signal_connect (gtk_sheet_get_entry (sheet),
-                   "changed",
-                   G_CALLBACK (gtk_sheet_entry_changed),
-                   sheet);
 
-  _gtkextra_signal_emit (GTK_OBJECT (sheet), sheet_signals [ACTIVATE], row, col, &veto);
+  g_signal_emit (sheet, sheet_signals [ACTIVATE], 0,
+                row, col, old_row, old_col);
 
-  return TRUE;
+  if ( old_handler_id == sheet->entry_handler_id)
+    g_signal_handler_unblock   (sheet->entry_widget, sheet->entry_handler_id);
 }
 
 static void
-gtk_sheet_show_active_cell (GtkSheet *sheet)
+gtk_sheet_show_entry_widget (GtkSheet *sheet)
 {
   GtkEntry *sheet_entry;
   GtkSheetCellAttr attributes;
   gchar *text = NULL;
-  const gchar *old_text;
-  GtkJustification justification;
   gint row, col;
 
   g_return_if_fail (sheet != NULL);
@@ -3882,39 +2620,43 @@ gtk_sheet_show_active_cell (GtkSheet *sheet)
 
   GTK_WIDGET_SET_FLAGS (GTK_WIDGET (sheet->entry_widget), GTK_VISIBLE);
 
-  sheet_entry = GTK_ENTRY (gtk_sheet_get_entry (sheet));
+  sheet_entry = gtk_sheet_get_entry (sheet);
 
   gtk_sheet_get_attributes (sheet, row, col, &attributes);
 
-  justification = GTK_JUSTIFY_LEFT;
-
-  if (gtk_sheet_justify_entry (sheet))
-    justification = attributes.justification;
 
   text = gtk_sheet_cell_get_text (sheet, row, col);
   if ( ! text )
     text = g_strdup ("");
 
-  gtk_entry_set_visibility (GTK_ENTRY (sheet_entry), attributes.is_visible);
-
-
-  /*** Added by John Gotts. Mar 25, 2005 *********/
-  old_text = gtk_entry_get_text (GTK_ENTRY (sheet_entry));
-  if (strcmp (old_text, text) != 0)
+  if ( GTK_IS_ENTRY (sheet_entry))
     {
-      if (!GTK_IS_ITEM_ENTRY (sheet_entry))
-       gtk_entry_set_text (GTK_ENTRY (sheet_entry), text);
-      else
-       gtk_item_entry_set_text (GTK_ITEM_ENTRY (sheet_entry), text, justification);
+      const gchar *old_text = gtk_entry_get_text (GTK_ENTRY (sheet_entry));
+      if (strcmp (old_text, text) != 0)
+       gtk_entry_set_text (sheet_entry, text);
+
+      switch (attributes.justification)
+       {
+       case GTK_JUSTIFY_RIGHT:
+         gtk_entry_set_alignment (GTK_ENTRY (sheet_entry), 1.0);
+         break;
+       case GTK_JUSTIFY_CENTER:
+         gtk_entry_set_alignment (GTK_ENTRY (sheet_entry), 0.5);
+         break;
+       case GTK_JUSTIFY_LEFT:
+       default:
+         gtk_entry_set_alignment (GTK_ENTRY (sheet_entry), 0.0);
+         break;
+       }
     }
 
-  gtk_sheet_entry_set_max_size (sheet);
   gtk_sheet_size_allocate_entry (sheet);
 
+  gtk_widget_set_sensitive (GTK_WIDGET (sheet_entry),
+                           g_sheet_model_is_editable (sheet->model,
+                                                      row, col));
   gtk_widget_map (sheet->entry_widget);
 
-  gtk_widget_grab_focus (GTK_WIDGET (sheet_entry));
-
   dispose_string (sheet, text);
 }
 
@@ -3932,7 +2674,8 @@ gtk_sheet_draw_active_cell (GtkSheet *sheet)
 
   if (row < 0 || col < 0) return;
 
-  if (!gtk_sheet_cell_isvisible (sheet, row, col)) return;
+  if (!gtk_sheet_cell_isvisible (sheet, row, col))
+    return;
 
   range.col0 = range.coli = col;
   range.row0 = range.rowi = row;
@@ -3941,42 +2684,6 @@ gtk_sheet_draw_active_cell (GtkSheet *sheet)
 }
 
 
-static void
-gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height)
-{
-  gint pixmap_width, pixmap_height;
-
-  if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
-
-  if (width == 0 && height == 0)
-    {
-      width = sheet->sheet_window_width + 80;
-      height = sheet->sheet_window_height + 80;
-    }
-
-  if (!sheet->pixmap)
-    {
-      /* allocate */
-      sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
-                                     width, height,
-                                     - 1);
-      if (!GTK_SHEET_IS_FROZEN (sheet)) gtk_sheet_range_draw (sheet, NULL);
-    }
-  else
-    {
-      /* reallocate if sizes don't match */
-      gdk_drawable_get_size (sheet->pixmap,
-                            &pixmap_width, &pixmap_height);
-      if ( (pixmap_width != width) || (pixmap_height != height))
-       {
-         g_object_unref (sheet->pixmap);
-         sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
-                                         width, height,
-                                         - 1);
-         if (!GTK_SHEET_IS_FROZEN (sheet)) gtk_sheet_range_draw (sheet, NULL);
-       }
-    }
-}
 
 static void
 gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
@@ -3997,15 +2704,15 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
   range->col0 = MIN (range->col0, sheet->range.col0);
   range->coli = MAX (range->coli, sheet->range.coli);
 
-  range->row0 = MAX (range->row0, MIN_VISIBLE_ROW (sheet));
-  range->rowi = MIN (range->rowi, MAX_VISIBLE_ROW (sheet));
-  range->col0 = MAX (range->col0, MIN_VISIBLE_COLUMN (sheet));
-  range->coli = MIN (range->coli, MAX_VISIBLE_COLUMN (sheet));
+  range->row0 = MAX (range->row0, min_visible_row (sheet));
+  range->rowi = MIN (range->rowi, max_visible_row (sheet));
+  range->col0 = MAX (range->col0, min_visible_column (sheet));
+  range->coli = MIN (range->coli, max_visible_column (sheet));
 
-  aux_range.row0 = MAX (new_range.row0, MIN_VISIBLE_ROW (sheet));
-  aux_range.rowi = MIN (new_range.rowi, MAX_VISIBLE_ROW (sheet));
-  aux_range.col0 = MAX (new_range.col0, MIN_VISIBLE_COLUMN (sheet));
-  aux_range.coli = MIN (new_range.coli, MAX_VISIBLE_COLUMN (sheet));
+  aux_range.row0 = MAX (new_range.row0, min_visible_row (sheet));
+  aux_range.rowi = MIN (new_range.rowi, max_visible_row (sheet));
+  aux_range.col0 = MAX (new_range.col0, min_visible_column (sheet));
+  aux_range.coli = MIN (new_range.coli, max_visible_column (sheet));
 
   for (i = range->row0; i <= range->rowi; i++)
     {
@@ -4017,7 +2724,6 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
                     j <= new_range.coli && j >= new_range.col0) ? TRUE : FALSE;
 
          if (state == GTK_STATE_SELECTED && selected &&
-             xxx_column_is_visible (sheet, j) && yyy_row_is_visible (sheet, i) &&
              (i == sheet->range.row0 || i == sheet->range.rowi ||
               j == sheet->range.col0 || j == sheet->range.coli ||
               i == new_range.row0 || i == new_range.rowi ||
@@ -4036,11 +2742,11 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
 
              if (mask1 != mask2)
                {
-                 x = COLUMN_LEFT_XPIXEL (sheet, j);
-                 y = ROW_TOP_YPIXEL (sheet, i);
-                 width = COLUMN_LEFT_XPIXEL (sheet, j)- x+
-                   xxx_column_width (sheet, j);
-                 height = ROW_TOP_YPIXEL (sheet, i)- y + yyy_row_height (sheet, i);
+                 x = psppire_axis_pixel_start (sheet->haxis, j);
+                 y = psppire_axis_pixel_start (sheet->vaxis, i);
+                 width = psppire_axis_pixel_start (sheet->haxis, j)- x+
+                   psppire_axis_unit_size (sheet->haxis, j);
+                 height = psppire_axis_pixel_start (sheet->vaxis, i) - y + psppire_axis_unit_size (sheet->vaxis, i);
 
                  if (i == sheet->range.row0)
                    {
@@ -4055,24 +2761,14 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
                    }
                  if (j == sheet->range.coli) width = width + 3;
 
-                 gdk_draw_drawable (sheet->sheet_window,
-                                  GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
-                                  sheet->pixmap,
-                                  x + 1,
-                                  y + 1,
-                                  x + 1,
-                                  y + 1,
-                                  width,
-                                  height);
-
                  if (i != sheet->active_cell.row || j != sheet->active_cell.col)
                    {
-                     x = COLUMN_LEFT_XPIXEL (sheet, j);
-                     y = ROW_TOP_YPIXEL (sheet, i);
-                     width = COLUMN_LEFT_XPIXEL (sheet, j)- x+
-                       xxx_column_width (sheet, j);
+                     x = psppire_axis_pixel_start (sheet->haxis, j);
+                     y = psppire_axis_pixel_start (sheet->vaxis, i);
+                     width = psppire_axis_pixel_start (sheet->haxis, j)- x+
+                       psppire_axis_unit_size (sheet->haxis, j);
 
-                     height = ROW_TOP_YPIXEL (sheet, i)- y + yyy_row_height (sheet, i);
+                     height = psppire_axis_pixel_start (sheet->vaxis, i) - y + psppire_axis_unit_size (sheet->vaxis, i);
 
                      if (i == new_range.row0)
                        {
@@ -4107,14 +2803,13 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
          selected= (i <= new_range.rowi && i >= new_range.row0 &&
                     j <= new_range.coli && j >= new_range.col0) ? TRUE : FALSE;
 
-         if (state == GTK_STATE_SELECTED && !selected &&
-             xxx_column_is_visible (sheet, j) && yyy_row_is_visible (sheet, i))
+         if (state == GTK_STATE_SELECTED && !selected)
            {
 
-             x = COLUMN_LEFT_XPIXEL (sheet, j);
-             y = ROW_TOP_YPIXEL (sheet, i);
-             width = COLUMN_LEFT_XPIXEL (sheet, j)- x+ xxx_column_width (sheet, j);
-             height = ROW_TOP_YPIXEL (sheet, i)- y + yyy_row_height (sheet, i);
+             x = psppire_axis_pixel_start (sheet->haxis, j);
+             y = psppire_axis_pixel_start (sheet->vaxis, i);
+             width = psppire_axis_pixel_start (sheet->haxis, j) - x + psppire_axis_unit_size (sheet->haxis, j);
+             height = psppire_axis_pixel_start (sheet->vaxis, i) - y + psppire_axis_unit_size (sheet->vaxis, i);
 
              if (i == sheet->range.row0)
                {
@@ -4129,15 +2824,6 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
                }
              if (j == sheet->range.coli) width = width + 3;
 
-             gdk_draw_drawable (sheet->sheet_window,
-                              GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
-                              sheet->pixmap,
-                              x + 1,
-                              y + 1,
-                              x + 1,
-                              y + 1,
-                              width,
-                              height);
            }
        }
     }
@@ -4152,14 +2838,13 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
                     j <= new_range.coli && j >= new_range.col0) ? TRUE : FALSE;
 
          if (state != GTK_STATE_SELECTED && selected &&
-             xxx_column_is_visible (sheet, j) && yyy_row_is_visible (sheet, i) &&
              (i != sheet->active_cell.row || j != sheet->active_cell.col))
            {
 
-             x = COLUMN_LEFT_XPIXEL (sheet, j);
-             y = ROW_TOP_YPIXEL (sheet, i);
-             width = COLUMN_LEFT_XPIXEL (sheet, j)- x+ xxx_column_width (sheet, j);
-             height = ROW_TOP_YPIXEL (sheet, i)- y + yyy_row_height (sheet, i);
+             x = psppire_axis_pixel_start (sheet->haxis, j);
+             y = psppire_axis_pixel_start (sheet->vaxis, i);
+             width = psppire_axis_pixel_start (sheet->haxis, j) - x + psppire_axis_unit_size (sheet->haxis, j);
+             height = psppire_axis_pixel_start (sheet->vaxis, i) - y + psppire_axis_unit_size (sheet->vaxis, i);
 
              if (i == new_range.row0)
                {
@@ -4177,251 +2862,93 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
              gdk_draw_rectangle (sheet->sheet_window,
                                  sheet->xor_gc,
                                  TRUE,
-                                 x + 1, y + 1,
-                                 width, height);
-
-           }
-
-       }
-    }
-
-  for (i = aux_range.row0; i <= aux_range.rowi; i++)
-    {
-      for (j = aux_range.col0; j <= aux_range.coli; j++)
-       {
-
-         if (xxx_column_is_visible (sheet, j) && yyy_row_is_visible (sheet, i))
-           {
-
-             state = gtk_sheet_cell_get_state (sheet, i, j);
-
-             mask1 = i == sheet->range.row0 ? 1 : 0;
-             mask1 = i == sheet->range.rowi ? mask1 + 2 : mask1;
-             mask1 = j == sheet->range.col0 ? mask1 + 4 : mask1;
-             mask1 = j == sheet->range.coli ? mask1 + 8 : mask1;
-
-             mask2 = i == new_range.row0 ? 1 : 0;
-             mask2 = i == new_range.rowi ? mask2 + 2 : mask2;
-             mask2 = j == new_range.col0 ? mask2 + 4 : mask2;
-             mask2 = j == new_range.coli ? mask2 + 8 : mask2;
-             if (mask2 != mask1 || (mask2 == mask1 && state != GTK_STATE_SELECTED))
-               {
-                 x = COLUMN_LEFT_XPIXEL (sheet, j);
-                 y = ROW_TOP_YPIXEL (sheet, i);
-                 width = xxx_column_width (sheet, j);
-                 height = yyy_row_height (sheet, i);
-                 if (mask2 & 1)
-                   gdk_draw_rectangle (sheet->sheet_window,
-                                       sheet->xor_gc,
-                                       TRUE,
-                                       x + 1, y - 1,
-                                       width, 3);
-
-
-                 if (mask2 & 2)
-                   gdk_draw_rectangle (sheet->sheet_window,
-                                       sheet->xor_gc,
-                                       TRUE,
-                                       x + 1, y + height - 1,
-                                       width, 3);
-
-                 if (mask2 & 4)
-                   gdk_draw_rectangle (sheet->sheet_window,
-                                       sheet->xor_gc,
-                                       TRUE,
-                                       x - 1, y + 1,
-                                       3, height);
-
-
-                 if (mask2 & 8)
-                   gdk_draw_rectangle (sheet->sheet_window,
-                                       sheet->xor_gc,
-                                       TRUE,
-                                       x + width - 1, y + 1,
-                                       3, height);
-
-
-
-               }
-
-           }
-
-       }
-    }
-
-
-  *range = new_range;
-  gtk_sheet_draw_corners (sheet, new_range);
-
-}
-
-static void
-gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range)
-{
-  GtkWidget *widget;
-  GdkRectangle area;
-  gint i;
-  gint x, y, width, height;
-
-  widget = GTK_WIDGET (sheet);
-
-  x = COLUMN_LEFT_XPIXEL (sheet, new_range.col0);
-  y = ROW_TOP_YPIXEL (sheet, new_range.row0);
-  width = COLUMN_LEFT_XPIXEL (sheet, new_range.coli) - x +
-    xxx_column_width (sheet, new_range.coli);
-
-  height = ROW_TOP_YPIXEL (sheet, new_range.rowi) - y +
-    yyy_row_height (sheet, new_range.rowi);
-
-  area.x = COLUMN_LEFT_XPIXEL (sheet, MIN_VISIBLE_COLUMN (sheet));
-  area.y = ROW_TOP_YPIXEL (sheet, MIN_VISIBLE_ROW (sheet));
-  area.width = sheet->sheet_window_width;
-  area.height = sheet->sheet_window_height;
-
-  if (x < 0)
-    {
-      width = width + x;
-      x = 0;
-    }
-  if (width > area.width) width = area.width + 10;
-  if (y < 0)
-    {
-      height = height + y;
-      y = 0;
-    }
-  if (height > area.height) height = area.height + 10;
-
-  gdk_gc_set_clip_rectangle (sheet->xor_gc, &area);
-
-  for (i = -1; i <= 1; ++i)
-    gdk_draw_rectangle (sheet->sheet_window,
-                       sheet->xor_gc,
-                       FALSE,
-                       x + i,
-                       y + i,
-                       width - 2 * i,
-                       height - 2 * i);
-
-  gdk_gc_set_clip_rectangle (sheet->xor_gc, NULL);
-
-
-  gtk_sheet_draw_corners (sheet, new_range);
-}
-
-static void
-gtk_sheet_draw_corners (GtkSheet *sheet, GtkSheetRange range)
-{
-  gint x, y;
-  guint width = 1;
+                                 x + 1, y + 1,
+                                 width, height);
 
-  if (gtk_sheet_cell_isvisible (sheet, range.row0, range.col0))
-    {
-      x = COLUMN_LEFT_XPIXEL (sheet, range.col0);
-      y = ROW_TOP_YPIXEL (sheet, range.row0);
-      gdk_draw_drawable (sheet->sheet_window,
-                      GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
-                      sheet->pixmap,
-                      x - 1,
-                      y - 1,
-                      x - 1,
-                      y - 1,
-                      3,
-                      3);
-      gdk_draw_rectangle (sheet->sheet_window,
-                         sheet->xor_gc,
-                         TRUE,
-                         x - 1, y - 1,
-                         3, 3);
-    }
+           }
 
-  if (gtk_sheet_cell_isvisible (sheet, range.row0, range.coli) ||
-      sheet->state == GTK_SHEET_COLUMN_SELECTED)
-    {
-      x = COLUMN_LEFT_XPIXEL (sheet, range.coli)+
-       xxx_column_width (sheet, range.coli);
-      y = ROW_TOP_YPIXEL (sheet, range.row0);
-      width = 1;
-      if (sheet->state == GTK_SHEET_COLUMN_SELECTED)
-       {
-         y = ROW_TOP_YPIXEL (sheet, MIN_VISIBLE_ROW (sheet))+3;
-         width = 3;
        }
-      gdk_draw_drawable (sheet->sheet_window,
-                      GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
-                      sheet->pixmap,
-                      x - width,
-                      y - width,
-                      x - width,
-                      y - width,
-                      2 * width + 1,
-                      2 * width + 1);
-      gdk_draw_rectangle (sheet->sheet_window,
-                         sheet->xor_gc,
-                         TRUE,
-                         x - width + width / 2, y - width + width / 2,
-                         2 + width, 2 + width);
     }
 
-  if (gtk_sheet_cell_isvisible (sheet, range.rowi, range.col0) ||
-      sheet->state == GTK_SHEET_ROW_SELECTED)
+  for (i = aux_range.row0; i <= aux_range.rowi; i++)
     {
-      x = COLUMN_LEFT_XPIXEL (sheet, range.col0);
-      y = ROW_TOP_YPIXEL (sheet, range.rowi)+
-       yyy_row_height (sheet, range.rowi);
-      width = 1;
-      if (sheet->state == GTK_SHEET_ROW_SELECTED)
+      for (j = aux_range.col0; j <= aux_range.coli; j++)
        {
-         x = COLUMN_LEFT_XPIXEL (sheet, MIN_VISIBLE_COLUMN (sheet))+3;
-         width = 3;
+         state = gtk_sheet_cell_get_state (sheet, i, j);
+
+         mask1 = i == sheet->range.row0 ? 1 : 0;
+         mask1 = i == sheet->range.rowi ? mask1 + 2 : mask1;
+         mask1 = j == sheet->range.col0 ? mask1 + 4 : mask1;
+         mask1 = j == sheet->range.coli ? mask1 + 8 : mask1;
+
+         mask2 = i == new_range.row0 ? 1 : 0;
+         mask2 = i == new_range.rowi ? mask2 + 2 : mask2;
+         mask2 = j == new_range.col0 ? mask2 + 4 : mask2;
+         mask2 = j == new_range.coli ? mask2 + 8 : mask2;
+         if (mask2 != mask1 || (mask2 == mask1 && state != GTK_STATE_SELECTED))
+           {
+             x = psppire_axis_pixel_start (sheet->haxis, j);
+             y = psppire_axis_pixel_start (sheet->vaxis, i);
+             width = psppire_axis_unit_size (sheet->haxis, j);
+             height = psppire_axis_unit_size (sheet->vaxis, i);
+             if (mask2 & 1)
+               gdk_draw_rectangle (sheet->sheet_window,
+                                   sheet->xor_gc,
+                                   TRUE,
+                                   x + 1, y - 1,
+                                   width, 3);
+
+
+             if (mask2 & 2)
+               gdk_draw_rectangle (sheet->sheet_window,
+                                   sheet->xor_gc,
+                                   TRUE,
+                                   x + 1, y + height - 1,
+                                   width, 3);
+
+             if (mask2 & 4)
+               gdk_draw_rectangle (sheet->sheet_window,
+                                   sheet->xor_gc,
+                                   TRUE,
+                                   x - 1, y + 1,
+                                   3, height);
+
+
+             if (mask2 & 8)
+               gdk_draw_rectangle (sheet->sheet_window,
+                                   sheet->xor_gc,
+                                   TRUE,
+                                   x + width - 1, y + 1,
+                                   3, height);
+           }
        }
-      gdk_draw_drawable (sheet->sheet_window,
-                      GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
-                      sheet->pixmap,
-                      x - width,
-                      y - width,
-                      x - width,
-                      y - width,
-                      2 * width + 1,
-                      2 * width + 1);
-      gdk_draw_rectangle (sheet->sheet_window,
-                         sheet->xor_gc,
-                         TRUE,
-                         x - width + width / 2, y - width + width / 2,
-                         2 + width, 2 + width);
     }
 
-  if (gtk_sheet_cell_isvisible (sheet, range.rowi, range.coli))
-    {
-      x = COLUMN_LEFT_XPIXEL (sheet, range.coli)+
-       xxx_column_width (sheet, range.coli);
-      y = ROW_TOP_YPIXEL (sheet, range.rowi)+
-       yyy_row_height (sheet, range.rowi);
-      width = 1;
-      if (sheet->state == GTK_SHEET_RANGE_SELECTED) width = 3;
-      if (sheet->state == GTK_SHEET_NORMAL) width = 3;
-      gdk_draw_drawable (sheet->sheet_window,
-                      GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
-                      sheet->pixmap,
-                      x - width,
-                      y - width,
-                      x - width,
-                      y - width,
-                      2 * width + 1,
-                      2 * width + 1);
-      gdk_draw_rectangle (sheet->sheet_window,
-                         sheet->xor_gc,
-                         TRUE,
-                         x - width + width / 2, y - width + width / 2,
-                         2 + width, 2 + width);
+  *range = new_range;
+}
 
-    }
 
+
+static void
+gtk_sheet_draw_border (GtkSheet *sheet, GtkSheetRange new_range)
+{
+  GdkRectangle area;
+
+  rectangle_from_range (sheet, &new_range, &area);
+
+  gdk_draw_rectangle (sheet->sheet_window,
+                     sheet->xor_gc,
+                     FALSE,
+                     area.x,
+                     area.y,
+                     area.width + 1,
+                     area.height + 1);
 }
 
 
 static void
-gtk_sheet_real_select_range (GtkSheet * sheet,
-                            const GtkSheetRange * range)
+gtk_sheet_real_select_range (GtkSheet *sheet,
+                            const GtkSheetRange *range)
 {
   gint state;
 
@@ -4436,6 +2963,7 @@ gtk_sheet_real_select_range (GtkSheet * sheet,
 
   state = sheet->state;
 
+#if 0
   if (range->coli != sheet->range.coli || range->col0 != sheet->range.col0 ||
       range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0)
     {
@@ -4443,9 +2971,9 @@ gtk_sheet_real_select_range (GtkSheet * sheet,
     }
   else
     {
-      gtk_sheet_draw_backing_pixmap (sheet, sheet->range);
       gtk_sheet_range_draw_selection (sheet, sheet->range);
     }
+#endif
 
   gtk_sheet_update_primary_selection (sheet);
 
@@ -4454,8 +2982,7 @@ gtk_sheet_real_select_range (GtkSheet * sheet,
 
 
 void
-gtk_sheet_get_selected_range           (GtkSheet *sheet,
-                                        GtkSheetRange *range)
+gtk_sheet_get_selected_range (GtkSheet *sheet, GtkSheetRange *range)
 {
   g_return_if_fail (sheet != NULL);
   *range = sheet->range;
@@ -4463,7 +2990,7 @@ gtk_sheet_get_selected_range              (GtkSheet *sheet,
 
 
 void
-gtk_sheet_select_range (GtkSheet * sheet, const GtkSheetRange *range)
+gtk_sheet_select_range (GtkSheet *sheet, const GtkSheetRange *range)
 {
   g_return_if_fail (sheet != NULL);
 
@@ -4475,8 +3002,6 @@ gtk_sheet_select_range (GtkSheet * sheet, const GtkSheetRange *range)
 
   if (sheet->state != GTK_SHEET_NORMAL)
     gtk_sheet_real_unselect_range (sheet, NULL);
-  else
-    gtk_sheet_deactivate_cell (sheet);
 
   sheet->range.row0 = range->row0;
   sheet->range.rowi = range->rowi;
@@ -4489,11 +3014,10 @@ gtk_sheet_select_range (GtkSheet * sheet, const GtkSheetRange *range)
 
   sheet->state = GTK_SHEET_RANGE_SELECTED;
   gtk_sheet_real_select_range (sheet, NULL);
-
 }
 
 void
-gtk_sheet_unselect_range (GtkSheet * sheet)
+gtk_sheet_unselect_range (GtkSheet *sheet)
 {
   if (! GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
     return;
@@ -4501,13 +3025,13 @@ gtk_sheet_unselect_range (GtkSheet * sheet)
   gtk_sheet_real_unselect_range (sheet, NULL);
   sheet->state = GTK_STATE_NORMAL;
 
-  gtk_sheet_activate_cell (sheet,
-                          sheet->active_cell.row, sheet->active_cell.col);
+  change_active_cell (sheet,
+                sheet->active_cell.row, sheet->active_cell.col);
 }
 
 
 static void
-gtk_sheet_real_unselect_range (GtkSheet * sheet,
+gtk_sheet_real_unselect_range (GtkSheet *sheet,
                               const GtkSheetRange *range)
 {
   g_return_if_fail (sheet != NULL);
@@ -4522,21 +3046,16 @@ gtk_sheet_real_unselect_range (GtkSheet * sheet,
   g_signal_emit (sheet, sheet_signals[SELECT_COLUMN], 0, -1);
   g_signal_emit (sheet, sheet_signals[SELECT_ROW], 0, -1);
 
-  if (gtk_sheet_range_isvisible (sheet, *range))
-    gtk_sheet_draw_backing_pixmap (sheet, *range);
-
   sheet->range.row0 = -1;
   sheet->range.rowi = -1;
   sheet->range.col0 = -1;
   sheet->range.coli = -1;
-
-  gtk_sheet_position_children (sheet);
 }
 
 
 static gint
-gtk_sheet_expose (GtkWidget * widget,
-                 GdkEventExpose * event)
+gtk_sheet_expose (GtkWidget *widget,
+                 GdkEventExpose *event)
 {
   GtkSheet *sheet;
   GtkSheetRange range;
@@ -4545,60 +3064,75 @@ gtk_sheet_expose (GtkWidget * widget,
   g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
 
-
   sheet = GTK_SHEET (widget);
 
-  if (GTK_WIDGET_DRAWABLE (widget))
+  if (!GTK_WIDGET_DRAWABLE (widget))
+    return FALSE;
+
+  /* exposure events on the sheet */
+  if (event->window == sheet->row_title_window &&
+      sheet->row_titles_visible)
     {
-      range.row0 = ROW_FROM_YPIXEL (sheet, event->area.y);
-      range.col0 = COLUMN_FROM_XPIXEL (sheet, event->area.x);
-      range.rowi = ROW_FROM_YPIXEL (sheet, event->area.y + event->area.height);
-      range.coli = COLUMN_FROM_XPIXEL (sheet, event->area.x + event->area.width);
-
-      /* exposure events on the sheet */
-      if (event->window == sheet->row_title_window &&
-         sheet->row_titles_visible)
-       {
-         gint i;
-         for (i = MIN_VISIBLE_ROW (sheet); i <= MAX_VISIBLE_ROW (sheet); i++)
-           gtk_sheet_row_title_button_draw (sheet, i);
-       }
+      draw_row_title_buttons_range (sheet,
+                                   min_visible_row (sheet),
+                                   max_visible_row (sheet));
+    }
 
-      if (event->window == sheet->column_title_window &&
-         sheet->column_titles_visible)
-       {
-         gint i;
-         for (i = MIN_VISIBLE_COLUMN (sheet); i <= MAX_VISIBLE_COLUMN (sheet); i++)
-           gtk_sheet_column_title_button_draw (sheet, i);
-       }
+  if (event->window == sheet->column_title_window &&
+      sheet->column_titles_visible)
+    {
+      draw_column_title_buttons_range (sheet,
+                                      min_visible_column (sheet),
+                                      max_visible_column (sheet));
+    }
 
-      if (event->window == sheet->sheet_window)
+
+  {
+    gint y = event->area.y + sheet->vadjustment->value;
+    gint x = event->area.x + sheet->hadjustment->value;
+
+    if ( sheet->column_titles_visible)
+      y -= sheet->column_title_area.height;
+
+    if ( sheet->row_titles_visible)
+      x -= sheet->row_title_area.width;
+
+    maximize_int (&x, 0);
+    maximize_int (&y, 0);
+
+    range.row0 = row_from_ypixel (sheet, y);
+
+    range.rowi = row_from_ypixel (sheet, y + event->area.height);
+
+    range.col0 = column_from_xpixel (sheet, x);
+
+    range.coli = column_from_xpixel (sheet, x + event->area.width);
+  }
+
+  if (event->window == sheet->sheet_window)
+    {
+      gtk_sheet_range_draw (sheet, &range);
+
+      if (sheet->state != GTK_SHEET_NORMAL)
        {
-         gtk_sheet_draw_backing_pixmap (sheet, range);
+         if (gtk_sheet_range_isvisible (sheet, &sheet->range))
+           gtk_sheet_range_draw (sheet, &sheet->range);
 
-         if (sheet->state != GTK_SHEET_NORMAL)
-           {
-             if (gtk_sheet_range_isvisible (sheet, sheet->range))
-               gtk_sheet_draw_backing_pixmap (sheet, sheet->range);
-             if (GTK_SHEET_IN_RESIZE (sheet) || GTK_SHEET_IN_DRAG (sheet))
-               gtk_sheet_draw_backing_pixmap (sheet, sheet->drag_range);
-
-             if (gtk_sheet_range_isvisible (sheet, sheet->range))
-               gtk_sheet_range_draw_selection (sheet, sheet->range);
-             if (GTK_SHEET_IN_RESIZE (sheet) || GTK_SHEET_IN_DRAG (sheet))
-               draw_xor_rectangle (sheet, sheet->drag_range);
-           }
+         if (GTK_SHEET_IN_RESIZE (sheet) || GTK_SHEET_IN_DRAG (sheet))
+           gtk_sheet_range_draw (sheet, &sheet->drag_range);
 
-         if ((!GTK_SHEET_IN_XDRAG (sheet)) && (!GTK_SHEET_IN_YDRAG (sheet)))
-           {
-             if (sheet->state == GTK_SHEET_NORMAL)
-               gtk_sheet_draw_active_cell (sheet);
-           }
+         if (gtk_sheet_range_isvisible (sheet, &sheet->range))
+           gtk_sheet_range_draw_selection (sheet, sheet->range);
+         if (GTK_SHEET_IN_RESIZE (sheet) || GTK_SHEET_IN_DRAG (sheet))
+           draw_xor_rectangle (sheet, sheet->drag_range);
        }
-    }
 
-  if (sheet->state != GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION (sheet))
-    gtk_widget_grab_focus (GTK_WIDGET (sheet));
+      if ((!GTK_SHEET_IN_XDRAG (sheet)) && (!GTK_SHEET_IN_YDRAG (sheet)))
+       {
+         if (sheet->state == GTK_SHEET_NORMAL)
+           gtk_sheet_draw_active_cell (sheet);
+       }
+    }
 
   (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
 
@@ -4607,12 +3141,13 @@ gtk_sheet_expose (GtkWidget * widget,
 
 
 static gboolean
-gtk_sheet_button_press (GtkWidget * widget,
-                       GdkEventButton * event)
+gtk_sheet_button_press (GtkWidget *widget,
+                       GdkEventButton *event)
 {
   GtkSheet *sheet;
   GdkModifierType mods;
-  gint x, y, row, column;
+  gint x, y;
+  gint  row, column;
   gboolean veto;
 
   g_return_val_if_fail (widget != NULL, FALSE);
@@ -4638,10 +3173,12 @@ gtk_sheet_button_press (GtkWidget * widget,
                     sheet_signals[BUTTON_EVENT_COLUMN], 0,
                     column, event);
 
-      if ( event->type == GDK_2BUTTON_PRESS && event->button == 1)
-       g_signal_emit (sheet,
-                      sheet_signals[DOUBLE_CLICK_COLUMN], 0, column);
-
+      if (g_sheet_model_get_column_sensitivity (sheet->model, column))
+       {
+         if ( event->type == GDK_2BUTTON_PRESS && event->button == 1)
+           g_signal_emit (sheet,
+                          sheet_signals[DOUBLE_CLICK_COLUMN], 0, column);
+       }
     }
   else if (event->window == sheet->row_title_window)
     {
@@ -4649,12 +3186,14 @@ gtk_sheet_button_press (GtkWidget * widget,
                     sheet_signals[BUTTON_EVENT_ROW], 0,
                     row, event);
 
-      if ( event->type == GDK_2BUTTON_PRESS && event->button == 1)
-       g_signal_emit (sheet,
-                      sheet_signals[DOUBLE_CLICK_ROW], 0, row);
+      if (g_sheet_model_get_row_sensitivity (sheet->model, row))
+       {
+         if ( event->type == GDK_2BUTTON_PRESS && event->button == 1)
+           g_signal_emit (sheet,
+                          sheet_signals[DOUBLE_CLICK_ROW], 0, row);
+       }
     }
 
-
   gdk_window_get_pointer (widget->window, NULL, NULL, &mods);
 
   if (! (mods & GDK_BUTTON1_MASK)) return TRUE;
@@ -4664,16 +3203,17 @@ gtk_sheet_button_press (GtkWidget * widget,
   if (event->window == sheet->column_title_window &&
       gtk_sheet_columns_resizable (sheet))
     {
+#if 0
       gtk_widget_get_pointer (widget, &sheet->x_drag, NULL);
-      if (POSSIBLE_XDRAG (sheet, sheet->x_drag, &sheet->drag_cell.col))
+      if ( sheet->row_titles_visible)
+       sheet->x_drag -= sheet->row_title_area.width;
+#endif
+
+      sheet->x_drag = event->x;
+
+      if (on_column_boundary (sheet, sheet->x_drag, &sheet->drag_cell.col))
        {
          guint req;
-         if (event->type == GDK_2BUTTON_PRESS)
-           {
-             gtk_sheet_autoresize_column (sheet, sheet->drag_cell.col);
-             GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
-             return TRUE;
-           }
          gtk_sheet_column_size_request (sheet, sheet->drag_cell.col, &req);
          GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
          gdk_pointer_grab (sheet->column_title_window, FALSE,
@@ -4691,6 +3231,7 @@ gtk_sheet_button_press (GtkWidget * widget,
     {
       gtk_widget_get_pointer (widget, NULL, &sheet->y_drag);
 
+#if AXIS_TRANSITION
       if (POSSIBLE_YDRAG (sheet, sheet->y_drag, &sheet->drag_cell.row))
        {
          guint req;
@@ -4705,6 +3246,7 @@ gtk_sheet_button_press (GtkWidget * widget,
          draw_xor_hline (sheet);
          return TRUE;
        }
+#endif
     }
 
   /* the sheet itself does not handle other than single click events */
@@ -4722,12 +3264,6 @@ gtk_sheet_button_press (GtkWidget * widget,
                        NULL, NULL, event->time);
       gtk_grab_add (GTK_WIDGET (sheet));
 
-      /* This seems to be a kludge to work around a problem where the sheet
-        scrolls to another position.  The timeout scrolls it back to its
-        original posn.          JMD 3 July 2007
-      */
-      gtk_widget_grab_focus (GTK_WIDGET (sheet));
-
       if (sheet->selection_mode != GTK_SELECTION_SINGLE &&
          sheet->selection_mode != GTK_SELECTION_NONE &&
          sheet->cursor_drag->type == GDK_SIZING &&
@@ -4737,7 +3273,6 @@ gtk_sheet_button_press (GtkWidget * widget,
            {
              row = sheet->active_cell.row;
              column = sheet->active_cell.col;
-             gtk_sheet_deactivate_cell (sheet);
              sheet->active_cell.row = row;
              sheet->active_cell.col = column;
              sheet->drag_range = sheet->range;
@@ -4765,7 +3300,6 @@ gtk_sheet_button_press (GtkWidget * widget,
            {
              row = sheet->active_cell.row;
              column = sheet->active_cell.col;
-             gtk_sheet_deactivate_cell (sheet);
              sheet->active_cell.row = row;
              sheet->active_cell.col = column;
              sheet->drag_range = sheet->range;
@@ -4786,7 +3320,7 @@ gtk_sheet_button_press (GtkWidget * widget,
        }
       else
        {
-         gtk_sheet_click_cell (sheet, row, column, &veto);
+         veto = gtk_sheet_click_cell (sheet, row, column);
          if (veto) GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
        }
     }
@@ -4794,13 +3328,17 @@ gtk_sheet_button_press (GtkWidget * widget,
   if (event->window == sheet->column_title_window)
     {
       gtk_widget_get_pointer (widget, &x, &y);
-      column = COLUMN_FROM_XPIXEL (sheet, x);
+      if ( sheet->row_titles_visible)
+       x -= sheet->row_title_area.width;
+
+      x += sheet->hadjustment->value;
+
+      column = column_from_xpixel (sheet, x);
 
-      if (xxx_column_is_sensitive (sheet, column))
+      if (g_sheet_model_get_column_sensitivity (sheet->model, column))
        {
-         gtk_sheet_click_cell (sheet, - 1, column, &veto);
+         veto = gtk_sheet_click_cell (sheet, -1, column);
          gtk_grab_add (GTK_WIDGET (sheet));
-         gtk_widget_grab_focus (GTK_WIDGET (sheet));
          GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
        }
     }
@@ -4808,12 +3346,16 @@ gtk_sheet_button_press (GtkWidget * widget,
   if (event->window == sheet->row_title_window)
     {
       gtk_widget_get_pointer (widget, &x, &y);
-      row = ROW_FROM_YPIXEL (sheet, y);
-      if (yyy_row_is_sensitive (sheet, row))
+      if ( sheet->column_titles_visible)
+       y -= sheet->column_title_area.height;
+
+      y += sheet->vadjustment->value;
+
+      row = row_from_ypixel (sheet, y);
+      if (g_sheet_model_get_row_sensitivity (sheet->model, row))
        {
-         gtk_sheet_click_cell (sheet, row, - 1, &veto);
+         veto = gtk_sheet_click_cell (sheet, row, -1);
          gtk_grab_add (GTK_WIDGET (sheet));
-         gtk_widget_grab_focus (GTK_WIDGET (sheet));
          GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
        }
     }
@@ -4821,122 +3363,114 @@ gtk_sheet_button_press (GtkWidget * widget,
   return TRUE;
 }
 
-static void
-gtk_sheet_click_cell (GtkSheet *sheet, gint row, gint column, gboolean *veto)
+static gboolean
+gtk_sheet_click_cell (GtkSheet *sheet, gint row, gint column)
 {
-  *veto = TRUE;
+  GtkSheetCell cell;
+  gboolean forbid_move;
 
-  if (row >= yyy_row_count (sheet) || column >= xxx_column_count (sheet))
+  cell.row = row;
+  cell.col = column;
+
+  if (row >= psppire_axis_unit_count (sheet->vaxis)
+      || column >= psppire_axis_unit_count (sheet->haxis))
     {
-      *veto = FALSE;
-      return;
+      return FALSE;
     }
 
-  if (column >= 0 && row >= 0)
-    if (! xxx_column_is_visible (sheet, column) || !yyy_row_is_visible (sheet, row))
-      {
-       *veto = FALSE;
-       return;
-      }
-
-  _gtkextra_signal_emit (GTK_OBJECT (sheet), sheet_signals[TRAVERSE],
-                        sheet->active_cell.row, sheet->active_cell.col,
-                        &row, &column, veto);
+  g_signal_emit (sheet, sheet_signals[TRAVERSE], 0,
+                &sheet->active_cell,
+                &cell,
+                &forbid_move);
 
-  if (!*veto)
+  if (forbid_move)
     {
-      if (sheet->state == GTK_STATE_NORMAL) return;
+      if (sheet->state == GTK_STATE_NORMAL)
+       return FALSE;
 
       row = sheet->active_cell.row;
       column = sheet->active_cell.col;
 
-      gtk_sheet_activate_cell (sheet, row, column);
-      return;
+      change_active_cell (sheet, row, column);
+      return FALSE;
     }
 
   if (row == -1 && column >= 0)
     {
-      if (gtk_sheet_autoscroll (sheet))
-       gtk_sheet_move_query (sheet, row, column);
       gtk_sheet_select_column (sheet, column);
-      return;
+      return TRUE;
     }
+
   if (column == -1 && row >= 0)
     {
-      if (gtk_sheet_autoscroll (sheet))
-       gtk_sheet_move_query (sheet, row, column);
       gtk_sheet_select_row (sheet, row);
-      return;
+      return TRUE;
     }
 
-  if (row == - 1 && column == - 1)
+  if (row == -1 && column == -1)
     {
       sheet->range.row0 = 0;
       sheet->range.col0 = 0;
-      sheet->range.rowi = yyy_row_count (sheet) - 1;
-      sheet->range.coli = xxx_column_count (sheet) - 1;
+      sheet->range.rowi = psppire_axis_unit_count (sheet->vaxis) - 1;
+      sheet->range.coli =
+       psppire_axis_unit_count (sheet->haxis) - 1;
       sheet->active_cell.row = 0;
       sheet->active_cell.col = 0;
       gtk_sheet_select_range (sheet, NULL);
-      return;
+      return TRUE;
     }
 
-  if (row != -1 && column != -1)
+  if (sheet->state != GTK_SHEET_NORMAL)
     {
-      if (sheet->state != GTK_SHEET_NORMAL)
-       {
-         sheet->state = GTK_SHEET_NORMAL;
-         gtk_sheet_real_unselect_range (sheet, NULL);
-       }
-      else
-       {
-         gtk_sheet_deactivate_cell (sheet);
-         gtk_sheet_activate_cell (sheet, row, column);
-       }
-
-      if (gtk_sheet_autoscroll (sheet))
-       gtk_sheet_move_query (sheet, row, column);
-      sheet->active_cell.row = row;
-      sheet->active_cell.col = column;
-      sheet->selection_cell.row = row;
-      sheet->selection_cell.col = column;
-      sheet->range.row0 = row;
-      sheet->range.col0 = column;
-      sheet->range.rowi = row;
-      sheet->range.coli = column;
       sheet->state = GTK_SHEET_NORMAL;
-      GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
-      gtk_sheet_draw_active_cell (sheet);
-      return;
+      gtk_sheet_real_unselect_range (sheet, NULL);
+    }
+  else
+    {
+      change_active_cell (sheet, row, column);
     }
 
-  g_assert_not_reached ();
-  gtk_sheet_activate_cell (sheet, sheet->active_cell.row,
-                          sheet->active_cell.col);
+  sheet->active_cell.row = row;
+  sheet->active_cell.col = column;
+  sheet->selection_cell.row = row;
+  sheet->selection_cell.col = column;
+  sheet->range.row0 = row;
+  sheet->range.col0 = column;
+  sheet->range.rowi = row;
+  sheet->range.coli = column;
+  sheet->state = GTK_SHEET_NORMAL;
+  GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
+
+  gtk_sheet_draw_active_cell (sheet);
+
+  gtk_widget_grab_focus (GTK_WIDGET (sheet->entry_widget));
+
+  return TRUE;
 }
 
 static gint
-gtk_sheet_button_release (GtkWidget * widget,
-                         GdkEventButton * event)
+gtk_sheet_button_release (GtkWidget *widget,
+                         GdkEventButton *event)
 {
-  GtkSheet *sheet;
-  gint x, y;
+  gint y;
+  GdkDisplay *display = gtk_widget_get_display (widget);
 
-  sheet = GTK_SHEET (widget);
+  GtkSheet *sheet = GTK_SHEET (widget);
 
   /* release on resize windows */
   if (GTK_SHEET_IN_XDRAG (sheet))
     {
+      gint xpos = event->x;
+      gint width;
       GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
       GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
-      gtk_widget_get_pointer (widget, &x, NULL);
-      gdk_pointer_ungrab (event->time);
+
+      gdk_display_pointer_ungrab (display, event->time);
       draw_xor_vline (sheet);
 
-      gtk_sheet_set_column_width (sheet, sheet->drag_cell.col,
-                                 new_column_width (sheet, sheet->drag_cell.col, &x));
-      sheet->old_hadjustment = -1.;
-      g_signal_emit_by_name (sheet->hadjustment, "value_changed");
+      width = new_column_width (sheet, sheet->drag_cell.col, &xpos);
+
+      gtk_sheet_set_column_width (sheet, sheet->drag_cell.col, width);
       return TRUE;
     }
 
@@ -4945,11 +3479,11 @@ gtk_sheet_button_release (GtkWidget * widget,
       GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_YDRAG);
       GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
       gtk_widget_get_pointer (widget, NULL, &y);
-      gdk_pointer_ungrab (event->time);
+      gdk_display_pointer_ungrab (display, event->time);
       draw_xor_hline (sheet);
 
-      gtk_sheet_set_row_height (sheet, sheet->drag_cell.row, new_row_height (sheet, sheet->drag_cell.row, &y));
-      sheet->old_vadjustment = -1.;
+      gtk_sheet_set_row_height (sheet, sheet->drag_cell.row,
+                               new_row_height (sheet, sheet->drag_cell.row, &y));
       g_signal_emit_by_name (sheet->vadjustment, "value_changed");
       return TRUE;
     }
@@ -4960,7 +3494,7 @@ gtk_sheet_button_release (GtkWidget * widget,
       GtkSheetRange old_range;
       draw_xor_rectangle (sheet, sheet->drag_range);
       GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_DRAG);
-      gdk_pointer_ungrab (event->time);
+      gdk_display_pointer_ungrab (display, event->time);
 
       gtk_sheet_real_unselect_range (sheet, NULL);
 
@@ -4985,7 +3519,7 @@ gtk_sheet_button_release (GtkWidget * widget,
       GtkSheetRange old_range;
       draw_xor_rectangle (sheet, sheet->drag_range);
       GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_RESIZE);
-      gdk_pointer_ungrab (event->time);
+      gdk_display_pointer_ungrab (display, event->time);
 
       gtk_sheet_real_unselect_range (sheet, NULL);
 
@@ -5014,13 +3548,13 @@ gtk_sheet_button_release (GtkWidget * widget,
   if (sheet->state == GTK_SHEET_NORMAL && GTK_SHEET_IN_SELECTION (sheet))
     {
       GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
-      gdk_pointer_ungrab (event->time);
-      gtk_sheet_activate_cell (sheet, sheet->active_cell.row,
+      gdk_display_pointer_ungrab (display, event->time);
+      change_active_cell (sheet, sheet->active_cell.row,
                               sheet->active_cell.col);
     }
 
   if (GTK_SHEET_IN_SELECTION)
-    gdk_pointer_ungrab (event->time);
+    gdk_display_pointer_ungrab (display, event->time);
   gtk_grab_remove (GTK_WIDGET (sheet));
 
   GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
@@ -5028,6 +3562,10 @@ gtk_sheet_button_release (GtkWidget * widget,
   return TRUE;
 }
 
+\f
+
+
+
 /* Shamelessly lifted from gtktooltips */
 static gboolean
 gtk_sheet_subtitle_paint_window (GtkWidget *tip_window)
@@ -5043,10 +3581,17 @@ gtk_sheet_subtitle_paint_window (GtkWidget *tip_window)
   return FALSE;
 }
 
+static void
+destroy_hover_window (GtkSheetHoverTitle *h)
+{
+  gtk_widget_destroy (h->window);
+  g_free (h);
+}
+
 static GtkSheetHoverTitle *
 create_hover_window (void)
 {
-  GtkSheetHoverTitle *hw = malloc (sizeof (*hw));
+  GtkSheetHoverTitle *hw = g_malloc (sizeof (*hw));
 
   hw->window = gtk_window_new (GTK_WINDOW_POPUP);
 
@@ -5095,16 +3640,6 @@ show_subtitle (GtkSheet *sheet, gint row, gint column, const gchar *subtitle)
   if ( ! subtitle )
     return;
 
-  if ( ! sheet->hover_window)
-    {
-      sheet->hover_window = create_hover_window ();
-      gtk_widget_add_events (GTK_WIDGET (sheet), GDK_LEAVE_NOTIFY_MASK);
-
-      g_signal_connect_swapped (sheet, "leave-notify-event",
-                               G_CALLBACK (gtk_widget_hide),
-                               sheet->hover_window->window);
-    }
-
   gtk_label_set_text (GTK_LABEL (sheet->hover_window->label),
                      subtitle);
 
@@ -5150,28 +3685,20 @@ motion_timeout_callback (gpointer data)
 
   if ( gtk_sheet_get_pixel_info (sheet, x, y, &row, &column) )
     {
-      if ( column == -1 && row == -1 )
-       return FALSE;
-
-      if ( column == -1)
+      if (sheet->row_title_under)
        {
-         GSheetRow *row_geo = sheet->row_geometry;
-         gchar *text;
+         gchar *text = g_sheet_model_get_row_subtitle (sheet->model, row);
 
-         text = g_sheet_row_get_subtitle (row_geo, row);
-
-         show_subtitle (sheet, row, column, text);
+         show_subtitle (sheet, row, -1, text);
          g_free (text);
        }
 
-      if ( row == -1)
+      if (sheet->column_title_under)
        {
-         GSheetColumn *col_geo = sheet->column_geometry;
-         gchar *text;
-
-         text = g_sheet_column_get_subtitle (col_geo, column);
+         gchar *text = g_sheet_model_get_column_subtitle (sheet->model,
+                                                          column);
 
-         show_subtitle (sheet, row, column, text );
+         show_subtitle (sheet, -1, column, text);
 
          g_free (text);
        }
@@ -5180,15 +3707,15 @@ motion_timeout_callback (gpointer data)
   return FALSE;
 }
 
-static gint
-gtk_sheet_motion (GtkWidget * widget,
-                 GdkEventMotion * event)
+static gboolean
+gtk_sheet_motion (GtkWidget *widget,  GdkEventMotion *event)
 {
   GtkSheet *sheet;
   GdkModifierType mods;
   GdkCursorType new_cursor;
   gint x, y;
   gint row, column;
+  GdkDisplay *display;
 
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_SHEET (widget), FALSE);
@@ -5196,15 +3723,18 @@ gtk_sheet_motion (GtkWidget * widget,
 
   sheet = GTK_SHEET (widget);
 
+  display = gtk_widget_get_display (widget);
+
   /* selections on the sheet */
   x = event->x;
   y = event->y;
 
-  if (!sheet->hover_window || ! GTK_WIDGET_VISIBLE (sheet->hover_window->window))
+  if (!GTK_WIDGET_VISIBLE (sheet->hover_window->window))
     {
       if ( sheet->motion_timer > 0 )
        g_source_remove (sheet->motion_timer);
-      sheet->motion_timer = g_timeout_add (TIMEOUT_HOVER, motion_timeout_callback, sheet);
+      sheet->motion_timer =
+       g_timeout_add (TIMEOUT_HOVER, motion_timeout_callback, sheet);
     }
   else
     {
@@ -5214,7 +3744,8 @@ gtk_sheet_motion (GtkWidget * widget,
 
       if ( gtk_sheet_get_pixel_info (sheet, wx, wy, &row, &column) )
        {
-         if ( row != sheet->hover_window->row || column != sheet->hover_window->column)
+         if ( row != sheet->hover_window->row ||
+              column != sheet->hover_window->column)
            {
              gtk_widget_hide (sheet->hover_window->window);
            }
@@ -5224,15 +3755,14 @@ gtk_sheet_motion (GtkWidget * widget,
   if (event->window == sheet->column_title_window &&
       gtk_sheet_columns_resizable (sheet))
     {
-      gtk_widget_get_pointer (widget, &x, &y);
       if (!GTK_SHEET_IN_SELECTION (sheet) &&
-         POSSIBLE_XDRAG (sheet, x, &column))
+         on_column_boundary (sheet, x, &column))
        {
          new_cursor = GDK_SB_H_DOUBLE_ARROW;
          if (new_cursor != sheet->cursor_drag->type)
            {
              gdk_cursor_unref (sheet->cursor_drag);
-             sheet->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
+             sheet->cursor_drag = gdk_cursor_new_for_display (display, GDK_SB_H_DOUBLE_ARROW);
              gdk_window_set_cursor (sheet->column_title_window,
                                     sheet->cursor_drag);
            }
@@ -5244,7 +3774,7 @@ gtk_sheet_motion (GtkWidget * widget,
              new_cursor != sheet->cursor_drag->type)
            {
              gdk_cursor_unref (sheet->cursor_drag);
-             sheet->cursor_drag = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
+             sheet->cursor_drag = gdk_cursor_new_for_display (display, GDK_TOP_LEFT_ARROW);
              gdk_window_set_cursor (sheet->column_title_window,
                                     sheet->cursor_drag);
            }
@@ -5254,25 +3784,26 @@ gtk_sheet_motion (GtkWidget * widget,
   if (event->window == sheet->row_title_window &&
       gtk_sheet_rows_resizable (sheet))
     {
-      gtk_widget_get_pointer (widget, &x, &y);
+#if AXIS_TRANSITION
       if (!GTK_SHEET_IN_SELECTION (sheet) && POSSIBLE_YDRAG (sheet, y, &column))
        {
          new_cursor = GDK_SB_V_DOUBLE_ARROW;
          if (new_cursor != sheet->cursor_drag->type)
            {
              gdk_cursor_unref (sheet->cursor_drag);
-             sheet->cursor_drag = gdk_cursor_new (GDK_SB_V_DOUBLE_ARROW);
+             sheet->cursor_drag = gdk_cursor_new_for_display (display, GDK_SB_V_DOUBLE_ARROW);
              gdk_window_set_cursor (sheet->row_title_window, sheet->cursor_drag);
            }
        }
       else
+#endif
        {
          new_cursor = GDK_TOP_LEFT_ARROW;
          if (!GTK_SHEET_IN_YDRAG (sheet) &&
              new_cursor != sheet->cursor_drag->type)
            {
              gdk_cursor_unref (sheet->cursor_drag);
-             sheet->cursor_drag = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
+             sheet->cursor_drag = gdk_cursor_new_for_display (display, GDK_TOP_LEFT_ARROW);
              gdk_window_set_cursor (sheet->row_title_window, sheet->cursor_drag);
            }
        }
@@ -5287,18 +3818,20 @@ gtk_sheet_motion (GtkWidget * widget,
        new_cursor != sheet->cursor_drag->type)
     {
       gdk_cursor_unref (sheet->cursor_drag);
-      sheet->cursor_drag = gdk_cursor_new (GDK_PLUS);
+      sheet->cursor_drag = gdk_cursor_new_for_display (display, GDK_PLUS);
       gdk_window_set_cursor (sheet->sheet_window, sheet->cursor_drag);
     }
 
   new_cursor = GDK_TOP_LEFT_ARROW;
   if ( event->window == sheet->sheet_window &&
-       ! (POSSIBLE_RESIZE (sheet, x, y, &row, &column) || GTK_SHEET_IN_RESIZE (sheet)) && (POSSIBLE_DRAG (sheet, x, y, &row, &column) || GTK_SHEET_IN_DRAG (sheet)) &&
-
+       ! (POSSIBLE_RESIZE (sheet, x, y, &row, &column) ||
+         GTK_SHEET_IN_RESIZE (sheet)) &&
+       (POSSIBLE_DRAG (sheet, x, y, &row, &column) ||
+       GTK_SHEET_IN_DRAG (sheet)) &&
        new_cursor != sheet->cursor_drag->type)
     {
       gdk_cursor_unref (sheet->cursor_drag);
-      sheet->cursor_drag = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
+      sheet->cursor_drag = gdk_cursor_new_for_display (display, GDK_TOP_LEFT_ARROW);
       gdk_window_set_cursor (sheet->sheet_window, sheet->cursor_drag);
     }
 
@@ -5311,7 +3844,7 @@ gtk_sheet_motion (GtkWidget * widget,
        new_cursor != sheet->cursor_drag->type)
     {
       gdk_cursor_unref (sheet->cursor_drag);
-      sheet->cursor_drag = gdk_cursor_new (GDK_SIZING);
+      sheet->cursor_drag = gdk_cursor_new_for_display (display, GDK_SIZING);
       gdk_window_set_cursor (sheet->sheet_window, sheet->cursor_drag);
     }
 
@@ -5321,18 +3854,17 @@ gtk_sheet_motion (GtkWidget * widget,
 
   if (GTK_SHEET_IN_XDRAG (sheet))
     {
-      if (event->is_hint || event->window != widget->window)
-       gtk_widget_get_pointer (widget, &x, NULL);
-      else
-       x = event->x;
+      x = event->x;
 
       new_column_width (sheet, sheet->drag_cell.col, &x);
+#if 0
       if (x != sheet->x_drag)
        {
          draw_xor_vline (sheet);
          sheet->x_drag = x;
          draw_xor_vline (sheet);
        }
+#endif
       return TRUE;
     }
 
@@ -5356,15 +3888,15 @@ gtk_sheet_motion (GtkWidget * widget,
   if (GTK_SHEET_IN_DRAG (sheet))
     {
       GtkSheetRange aux;
-      column = COLUMN_FROM_XPIXEL (sheet, x)- sheet->drag_cell.col;
-      row = ROW_FROM_YPIXEL (sheet, y)- sheet->drag_cell.row;
+      column = column_from_xpixel (sheet, x)- sheet->drag_cell.col;
+      row = row_from_ypixel (sheet, y) - sheet->drag_cell.row;
       if (sheet->state == GTK_SHEET_COLUMN_SELECTED) row = 0;
       if (sheet->state == GTK_SHEET_ROW_SELECTED) column = 0;
       sheet->x_drag = x;
       sheet->y_drag = y;
       aux = sheet->range;
-      if (aux.row0 + row >= 0 && aux.rowi + row < yyy_row_count (sheet) &&
-         aux.col0 + column >= 0 && aux.coli + column < xxx_column_count (sheet))
+      if (aux.row0 + row >= 0 && aux.rowi + row < psppire_axis_unit_count (sheet->vaxis) &&
+         aux.col0 + column >= 0 && aux.coli + column < psppire_axis_unit_count (sheet->haxis))
        {
          aux = sheet->drag_range;
          sheet->drag_range.row0 = sheet->range.row0 + row;
@@ -5386,19 +3918,18 @@ gtk_sheet_motion (GtkWidget * widget,
       GtkSheetRange aux;
       gint v_h, current_col, current_row, col_threshold, row_threshold;
       v_h = 1;
+      if (abs (x - psppire_axis_pixel_start (sheet->haxis, sheet->drag_cell.col)) >
+         abs (y - psppire_axis_pixel_start (sheet->vaxis, sheet->drag_cell.row))) v_h = 2;
 
-      if (abs (x - COLUMN_LEFT_XPIXEL (sheet, sheet->drag_cell.col)) >
-         abs (y - ROW_TOP_YPIXEL (sheet, sheet->drag_cell.row))) v_h = 2;
-
-      current_col = COLUMN_FROM_XPIXEL (sheet, x);
-      current_row = ROW_FROM_YPIXEL (sheet, y);
+      current_col = column_from_xpixel (sheet, x);
+      current_row = row_from_ypixel (sheet, y);
       column = current_col - sheet->drag_cell.col;
       row = current_row - sheet->drag_cell.row;
 
       /*use half of column width resp. row height as threshold to
        expand selection*/
-      col_threshold = COLUMN_LEFT_XPIXEL (sheet, current_col) +
-       xxx_column_width (sheet, current_col) / 2;
+      col_threshold = psppire_axis_pixel_start (sheet->haxis, current_col) +
+       psppire_axis_unit_size (sheet->haxis, current_col) / 2;
       if (column > 0)
        {
          if (x < col_threshold)
@@ -5409,8 +3940,8 @@ gtk_sheet_motion (GtkWidget * widget,
          if (x > col_threshold)
            column +=1;
        }
-      row_threshold = ROW_TOP_YPIXEL (sheet, current_row) +
-       yyy_row_height (sheet, current_row)/2;
+      row_threshold = psppire_axis_pixel_start (sheet->vaxis, current_row) +
+       psppire_axis_unit_size (sheet->vaxis, current_row)/2;
       if (row > 0)
        {
          if (y < row_threshold)
@@ -5433,8 +3964,8 @@ gtk_sheet_motion (GtkWidget * widget,
       else
        row = 0;
 
-      if (aux.row0 + row >= 0 && aux.rowi + row < yyy_row_count (sheet) &&
-         aux.col0 + column >= 0 && aux.coli + column < xxx_column_count (sheet))
+      if (aux.row0 + row >= 0 && aux.rowi + row < psppire_axis_unit_count (sheet->vaxis) &&
+         aux.col0 + column >= 0 && aux.coli + column < psppire_axis_unit_count (sheet->haxis))
        {
          aux = sheet->drag_range;
          sheet->drag_range = sheet->range;
@@ -5468,65 +3999,17 @@ gtk_sheet_motion (GtkWidget * widget,
 }
 
 static gboolean
-gtk_sheet_move_query (GtkSheet *sheet, gint row, gint column)
+gtk_sheet_crossing_notify (GtkWidget *widget,
+                          GdkEventCrossing *event)
 {
-  gint row_move, column_move;
-  gfloat row_align, col_align;
-  guint height, width;
-  gint new_row = row;
-  gint new_col = column;
-
-  row_move = FALSE;
-  column_move = FALSE;
-  row_align = -1.;
-  col_align = -1.;
-
-  height = sheet->sheet_window_height;
-  width = sheet->sheet_window_width;
-
-  if (row >= MAX_VISIBLE_ROW (sheet) && sheet->state != GTK_SHEET_COLUMN_SELECTED)
-    {
-      row_align = 1.;
-      new_row = MIN (yyy_row_count (sheet) - 1, row + 1);
-      row_move = TRUE;
-      if (MAX_VISIBLE_ROW (sheet) == yyy_row_count (sheet) - 1 &&
-         ROW_TOP_YPIXEL (sheet, yyy_row_count (sheet)- 1) +
-         yyy_row_height (sheet, yyy_row_count (sheet)- 1) < height)
-       {
-         row_move = FALSE;
-         row_align = -1.;
-       }
-    }
-  if (row < MIN_VISIBLE_ROW (sheet) && sheet->state != GTK_SHEET_COLUMN_SELECTED)
-    {
-      row_align= 0.;
-      row_move = TRUE;
-    }
-  if (column >= MAX_VISIBLE_COLUMN (sheet) && sheet->state != GTK_SHEET_ROW_SELECTED)
-    {
-      col_align = 1.;
-      new_col = MIN (xxx_column_count (sheet) - 1, column + 1);
-      column_move = TRUE;
-      if (MAX_VISIBLE_COLUMN (sheet) == (xxx_column_count (sheet) - 1) &&
-         COLUMN_LEFT_XPIXEL (sheet, xxx_column_count (sheet) - 1) +
-         xxx_column_width (sheet, xxx_column_count (sheet) - 1) < width)
-       {
-         column_move = FALSE;
-         col_align = -1.;
-       }
-    }
-  if (column < MIN_VISIBLE_COLUMN (sheet) && sheet->state != GTK_SHEET_ROW_SELECTED)
-    {
-      col_align = 0.;
-      column_move = TRUE;
-    }
+  GtkSheet *sheet = GTK_SHEET (widget);
 
-  if (row_move || column_move)
-    {
-      gtk_sheet_moveto (sheet, new_row, new_col, row_align, col_align);
-    }
+  if (event->window == sheet->column_title_window)
+    sheet->column_title_under = event->type == GDK_ENTER_NOTIFY;
+  else if (event->window == sheet->row_title_window)
+    sheet->row_title_under = event->type == GDK_ENTER_NOTIFY;
 
-  return (row_move || column_move);
+  return TRUE;
 }
 
 static void
@@ -5541,7 +4024,6 @@ gtk_sheet_extend_selection (GtkSheet *sheet, gint row, gint column)
 
   if (sheet->selection_mode == GTK_SELECTION_SINGLE) return;
 
-  gtk_sheet_move_query (sheet, row, column);
   gtk_widget_grab_focus (GTK_WIDGET (sheet));
 
   if (GTK_SHEET_IN_DRAG (sheet)) return;
@@ -5551,10 +4033,10 @@ gtk_sheet_extend_selection (GtkSheet *sheet, gint row, gint column)
   switch (sheet->state)
     {
     case GTK_SHEET_ROW_SELECTED:
-      column = xxx_column_count (sheet) - 1;
+      column = psppire_axis_unit_count (sheet->haxis) - 1;
       break;
     case GTK_SHEET_COLUMN_SELECTED:
-      row = yyy_row_count (sheet) - 1;
+      row = psppire_axis_unit_count (sheet->vaxis) - 1;
       break;
     case GTK_SHEET_NORMAL:
       sheet->state = GTK_SHEET_RANGE_SELECTED;
@@ -5564,15 +4046,6 @@ gtk_sheet_extend_selection (GtkSheet *sheet, gint row, gint column)
       sheet->range.row0 = r;
       sheet->range.coli = c;
       sheet->range.rowi = r;
-      gdk_draw_drawable (sheet->sheet_window,
-                      GTK_WIDGET (sheet)->style->fg_gc[GTK_STATE_NORMAL],
-                      sheet->pixmap,
-                      COLUMN_LEFT_XPIXEL (sheet, c)- 1,
-                      ROW_TOP_YPIXEL (sheet, r)- 1,
-                      COLUMN_LEFT_XPIXEL (sheet, c)- 1,
-                      ROW_TOP_YPIXEL (sheet, r)- 1,
-                      xxx_column_width (sheet, c)+4,
-                      yyy_row_height (sheet, r)+4);
       gtk_sheet_range_draw_selection (sheet, sheet->range);
     case GTK_SHEET_RANGE_SELECTED:
       sheet->state = GTK_SHEET_RANGE_SELECTED;
@@ -5602,271 +4075,217 @@ gtk_sheet_entry_key_press (GtkWidget *widget,
   return focus;
 }
 
-static gint
-gtk_sheet_key_press (GtkWidget *widget,
-                    GdkEventKey *key)
+
+/* Number of rows in a step-increment */
+#define ROWS_PER_STEP 1
+
+
+static void
+page_vertical (GtkSheet *sheet, GtkScrollType dir)
 {
-  GtkSheet *sheet;
-  gint row, col;
-  gint state;
-  gboolean extend_selection = FALSE;
-  gboolean force_move = FALSE;
-  gboolean in_selection = FALSE;
-  gboolean veto = TRUE;
-  gint scroll = 1;
+  gint old_row = sheet->active_cell.row ;
+  glong vpixel = psppire_axis_pixel_start (sheet->vaxis, old_row);
 
-  sheet = GTK_SHEET (widget);
+  gint new_row;
+
+  vpixel -= psppire_axis_pixel_start (sheet->vaxis,
+                                    min_visible_row (sheet));
+
+  switch ( dir)
+    {
+    case GTK_SCROLL_PAGE_DOWN:
+      gtk_adjustment_set_value (sheet->vadjustment,
+                               sheet->vadjustment->value +
+                               sheet->vadjustment->page_increment);
+      break;
+    case GTK_SCROLL_PAGE_UP:
+      gtk_adjustment_set_value (sheet->vadjustment,
+                               sheet->vadjustment->value -
+                               sheet->vadjustment->page_increment);
+
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+
+  vpixel += psppire_axis_pixel_start (sheet->vaxis,
+                                    min_visible_row (sheet));
+
+  new_row =  row_from_ypixel (sheet, vpixel);
+
+  change_active_cell (sheet, new_row,
+                          sheet->active_cell.col);
+}
+
+
+static void
+step_sheet (GtkSheet *sheet, GtkScrollType dir)
+{
+  gint current_row = sheet->active_cell.row;
+  gint current_col = sheet->active_cell.col;
+  GtkSheetCell new_cell ;
+  gboolean forbidden = FALSE;
+
+  new_cell.row = current_row;
+  new_cell.col = current_col;
+
+  switch ( dir)
+    {
+    case GTK_SCROLL_STEP_DOWN:
+      new_cell.row++;
+      break;
+    case GTK_SCROLL_STEP_UP:
+      new_cell.row--;
+      break;
+    case GTK_SCROLL_STEP_RIGHT:
+      new_cell.col++;
+      break;
+    case GTK_SCROLL_STEP_LEFT:
+      new_cell.col--;
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+
+  maximize_int (&new_cell.row, 0);
+  maximize_int (&new_cell.col, 0);
+
+  minimize_int (&new_cell.row,
+               psppire_axis_unit_count (sheet->vaxis) - 1);
+
+  minimize_int (&new_cell.col,
+               psppire_axis_unit_count (sheet->haxis) - 1);
+
+  g_signal_emit (sheet, sheet_signals[TRAVERSE], 0,
+                &sheet->active_cell,
+                &new_cell,
+               &forbidden);
+
+  if (forbidden)
+    return;
+
+  change_active_cell (sheet, new_cell.row, new_cell.col);
+
+
+  if ( new_cell.col > max_fully_visible_column (sheet))
+    {
+      glong hpos  =
+       psppire_axis_pixel_start (sheet->haxis,
+                                   new_cell.col + 1);
+      hpos -= sheet->hadjustment->page_size;
+
+      gtk_adjustment_set_value (sheet->hadjustment,
+                               hpos);
+    }
+  else if ( new_cell.col < min_fully_visible_column (sheet))
+    {
+      glong hpos  =
+       psppire_axis_pixel_start (sheet->haxis,
+                                   new_cell.col);
+
+      gtk_adjustment_set_value (sheet->hadjustment,
+                               hpos);
+    }
+
+
+  if ( new_cell.row > max_fully_visible_row (sheet))
+    {
+      glong vpos  =
+       psppire_axis_pixel_start (sheet->vaxis,
+                                   new_cell.row + 1);
+      vpos -= sheet->vadjustment->page_size;
+
+      gtk_adjustment_set_value (sheet->vadjustment,
+                               vpos);
+    }
+  else if ( new_cell.row < min_fully_visible_row (sheet))
+    {
+      glong vpos  =
+       psppire_axis_pixel_start (sheet->vaxis,
+                                   new_cell.row);
+
+      gtk_adjustment_set_value (sheet->vadjustment,
+                               vpos);
+    }
+
+  gtk_widget_grab_focus (GTK_WIDGET (sheet->entry_widget));
+}
 
-  if (key->state & GDK_CONTROL_MASK || key->keyval == GDK_Control_L ||
-      key->keyval == GDK_Control_R) return FALSE;
 
-  extend_selection = (key->state & GDK_SHIFT_MASK) || key->keyval == GDK_Shift_L
-    || key->keyval == GDK_Shift_R;
+static gboolean
+gtk_sheet_key_press (GtkWidget *widget,
+                    GdkEventKey *key)
+{
+  GtkSheet *sheet = GTK_SHEET (widget);
 
-  state = sheet->state;
-  in_selection = GTK_SHEET_IN_SELECTION (sheet);
   GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
 
   switch (key->keyval)
     {
-    case GDK_Return: case GDK_KP_Enter:
-      if (sheet->state == GTK_SHEET_NORMAL &&
-         !GTK_SHEET_IN_SELECTION (sheet))
-       g_signal_stop_emission_by_name (gtk_sheet_get_entry (sheet),
-                                       "key-press-event");
-      row = sheet->active_cell.row;
-      col = sheet->active_cell.col;
-      if (sheet->state == GTK_SHEET_COLUMN_SELECTED)
-       row = MIN_VISIBLE_ROW (sheet)- 1;
-      if (sheet->state == GTK_SHEET_ROW_SELECTED)
-       col = MIN_VISIBLE_COLUMN (sheet);
-      if (row < yyy_row_count (sheet) - 1)
-       {
-         row = row + scroll;
-         while (!yyy_row_is_visible (sheet, row) && row < yyy_row_count (sheet)- 1)
-           row++;
-       }
-      gtk_sheet_click_cell (sheet, row, col, &veto);
-      extend_selection = FALSE;
+    case GDK_Tab:
+    case GDK_Right:
+      step_sheet (sheet, GTK_SCROLL_STEP_RIGHT);
       break;
     case GDK_ISO_Left_Tab:
-      row = sheet->active_cell.row;
-      col = sheet->active_cell.col;
-      if (sheet->state == GTK_SHEET_ROW_SELECTED)
-       col = MIN_VISIBLE_COLUMN (sheet)- 1;
-      if (sheet->state == GTK_SHEET_COLUMN_SELECTED)
-       row = MIN_VISIBLE_ROW (sheet);
-      if (col > 0)
-       {
-         col = col - scroll;
-         while (! xxx_column_is_visible (sheet, col) && col > 0) col--;
-         col = MAX (0, col);
-       }
-      gtk_sheet_click_cell (sheet, row, col, &veto);
-      extend_selection = FALSE;
+    case GDK_Left:
+      step_sheet (sheet, GTK_SCROLL_STEP_LEFT);
       break;
-    case GDK_Tab:
-      row = sheet->active_cell.row;
-      col = sheet->active_cell.col;
-      if (sheet->state == GTK_SHEET_ROW_SELECTED)
-       col = MIN_VISIBLE_COLUMN (sheet)- 1;
-      if (sheet->state == GTK_SHEET_COLUMN_SELECTED)
-       row = MIN_VISIBLE_ROW (sheet);
-      if (col < xxx_column_count (sheet) - 1)
-       {
-         col = col + scroll;
-         while (! xxx_column_is_visible (sheet, col) &&
-                col < xxx_column_count (sheet) - 1)
-           col++;
-       }
-      gtk_sheet_click_cell (sheet, row, col, &veto);
-      extend_selection = FALSE;
+    case GDK_Return:
+    case GDK_Down:
+      step_sheet (sheet, GTK_SCROLL_STEP_DOWN);
       break;
-    case GDK_Page_Up:
-      scroll = MAX_VISIBLE_ROW (sheet)- MIN_VISIBLE_ROW (sheet)+1;
     case GDK_Up:
-      if (extend_selection)
-       {
-         if (state == GTK_STATE_NORMAL)
-           {
-             row = sheet->active_cell.row;
-             col = sheet->active_cell.col;
-             gtk_sheet_click_cell (sheet, row, col, &veto);
-             if (!veto) break;
-           }
-         if (sheet->selection_cell.row > 0)
-           {
-             row = sheet->selection_cell.row - scroll;
-             while (!yyy_row_is_visible (sheet, row) && row > 0) row--;
-             row = MAX (0, row);
-             gtk_sheet_extend_selection (sheet, row, sheet->selection_cell.col);
-           }
-         return TRUE;
-       }
-      col = sheet->active_cell.col;
-      row = sheet->active_cell.row;
-      if (state == GTK_SHEET_COLUMN_SELECTED)
-       row = MIN_VISIBLE_ROW (sheet);
-      if (state == GTK_SHEET_ROW_SELECTED)
-       col = MIN_VISIBLE_COLUMN (sheet);
-      row = row - scroll;
-      while (!yyy_row_is_visible (sheet, row) && row > 0) row--;
-      row = MAX (0, row);
-      gtk_sheet_click_cell (sheet, row, col, &veto);
-      extend_selection = FALSE;
+      step_sheet (sheet, GTK_SCROLL_STEP_UP);
       break;
+
     case GDK_Page_Down:
-      scroll = MAX_VISIBLE_ROW (sheet)- MIN_VISIBLE_ROW (sheet)+1;
-    case GDK_Down:
-      if (extend_selection)
-       {
-         if (state == GTK_STATE_NORMAL)
-           {
-             row = sheet->active_cell.row;
-             col = sheet->active_cell.col;
-             gtk_sheet_click_cell (sheet, row, col, &veto);
-             if (!veto) break;
-           }
-         if (sheet->selection_cell.row < yyy_row_count (sheet)- 1)
-           {
-             row = sheet->selection_cell.row + scroll;
-             while (!yyy_row_is_visible (sheet, row) && row < yyy_row_count (sheet)- 1) row++;
-             row = MIN (yyy_row_count (sheet)- 1, row);
-             gtk_sheet_extend_selection (sheet, row, sheet->selection_cell.col);
-           }
-         return TRUE;
-       }
-      col = sheet->active_cell.col;
-      row = sheet->active_cell.row;
-      if (sheet->active_cell.row < yyy_row_count (sheet)- 1)
-       {
-         if (state == GTK_SHEET_COLUMN_SELECTED)
-           row = MIN_VISIBLE_ROW (sheet)- 1;
-         if (state == GTK_SHEET_ROW_SELECTED)
-           col = MIN_VISIBLE_COLUMN (sheet);
-         row = row + scroll;
-         while (!yyy_row_is_visible (sheet, row) && row < yyy_row_count (sheet)- 1) row++;
-         row = MIN (yyy_row_count (sheet)- 1, row);
-       }
-      gtk_sheet_click_cell (sheet, row, col, &veto);
-      extend_selection = FALSE;
-      break;
-    case GDK_Right:
-      if (extend_selection)
-       {
-         if (state == GTK_STATE_NORMAL)
-           {
-             row = sheet->active_cell.row;
-             col = sheet->active_cell.col;
-             gtk_sheet_click_cell (sheet, row, col, &veto);
-             if (!veto) break;
-           }
-         if (sheet->selection_cell.col < xxx_column_count (sheet) - 1)
-           {
-             col = sheet->selection_cell.col + 1;
-             while (! xxx_column_is_visible (sheet, col) && col < xxx_column_count (sheet) - 1)
-               col++;
-             gtk_sheet_extend_selection (sheet, sheet->selection_cell.row, col);
-           }
-         return TRUE;
-       }
-      col = sheet->active_cell.col;
-      row = sheet->active_cell.row;
-      if (sheet->active_cell.col < xxx_column_count (sheet) - 1)
-       {
-         col ++;
-         if (state == GTK_SHEET_ROW_SELECTED)
-           col = MIN_VISIBLE_COLUMN (sheet)- 1;
-         if (state == GTK_SHEET_COLUMN_SELECTED)
-           row = MIN_VISIBLE_ROW (sheet);
-         while (! xxx_column_is_visible (sheet, col) && col < xxx_column_count (sheet) - 1) col++;
-         if (strlen (gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)))) == 0
-             || force_move)
-           {
-             gtk_sheet_click_cell (sheet, row, col, &veto);
-           }
-         else
-           return FALSE;
-       }
-      extend_selection = FALSE;
+      page_vertical (sheet, GTK_SCROLL_PAGE_DOWN);
       break;
-    case GDK_Left:
-      if (extend_selection)
-       {
-         if (state == GTK_STATE_NORMAL)
-           {
-             row = sheet->active_cell.row;
-             col = sheet->active_cell.col;
-             gtk_sheet_click_cell (sheet, row, col, &veto);
-             if (!veto) break;
-           }
-         if (sheet->selection_cell.col > 0)
-           {
-             col = sheet->selection_cell.col - 1;
-             while (! xxx_column_is_visible (sheet, col) && col > 0) col--;
-             gtk_sheet_extend_selection (sheet, sheet->selection_cell.row, col);
-           }
-         return TRUE;
-       }
-      col = sheet->active_cell.col - 1;
-      row = sheet->active_cell.row;
-      if (state == GTK_SHEET_ROW_SELECTED)
-       col = MIN_VISIBLE_COLUMN (sheet)- 1;
-      if (state == GTK_SHEET_COLUMN_SELECTED)
-       row = MIN_VISIBLE_ROW (sheet);
-      while (! xxx_column_is_visible (sheet, col) && col > 0) col--;
-      col = MAX (0, col);
-
-      if (strlen (gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)))) == 0
-         || force_move)
-       {
-         gtk_sheet_click_cell (sheet, row, col, &veto);
-       }
-      else
-       return FALSE;
-      extend_selection = FALSE;
+    case GDK_Page_Up:
+      page_vertical (sheet, GTK_SCROLL_PAGE_UP);
       break;
+
     case GDK_Home:
-      row = 0;
-      while (!yyy_row_is_visible (sheet, row) && row < yyy_row_count (sheet) - 1) row++;
-      gtk_sheet_click_cell (sheet, row, sheet->active_cell.col, &veto);
-      extend_selection = FALSE;
+      gtk_adjustment_set_value (sheet->vadjustment,
+                               sheet->vadjustment->lower);
+
+      change_active_cell (sheet,  0,
+                              sheet->active_cell.col);
+
       break;
+
     case GDK_End:
-      row = yyy_row_count (sheet) - 1;
-      while (!yyy_row_is_visible (sheet, row) && row > 0) row--;
-      gtk_sheet_click_cell (sheet, row, sheet->active_cell.col, &veto);
-      extend_selection = FALSE;
+      gtk_adjustment_set_value (sheet->vadjustment,
+                               sheet->vadjustment->upper -
+                               sheet->vadjustment->page_size -
+                               sheet->vadjustment->page_increment);
+
+      /*
+       change_active_cellx (sheet,
+       psppire_axis_unit_count (sheet->vaxis) - 1,
+       sheet->active_cell.col);
+      */
+      break;
+    case GDK_Delete:
+      gtk_sheet_real_cell_clear (sheet, sheet->active_cell.row, sheet->active_cell.col);
       break;
     default:
-      if (in_selection)
-       {
-         GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_SELECTION);
-         if (extend_selection) return TRUE;
-       }
-      if (state == GTK_SHEET_ROW_SELECTED)
-       sheet->active_cell.col = MIN_VISIBLE_COLUMN (sheet);
-      if (state == GTK_SHEET_COLUMN_SELECTED)
-       sheet->active_cell.row = MIN_VISIBLE_ROW (sheet);
       return FALSE;
+      break;
     }
 
-  if (extend_selection) return TRUE;
-
-  gtk_sheet_activate_cell (sheet, sheet->active_cell.row,
-                          sheet->active_cell.col);
-
   return TRUE;
 }
 
 static void
-gtk_sheet_size_request (GtkWidget * widget,
-                       GtkRequisition * requisition)
+gtk_sheet_size_request (GtkWidget *widget,
+                       GtkRequisition *requisition)
 {
   GtkSheet *sheet;
-  GList *children;
-  GtkSheetChild *child;
-  GtkRequisition child_requisition;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_SHEET (widget));
@@ -5874,8 +4293,8 @@ gtk_sheet_size_request (GtkWidget * widget,
 
   sheet = GTK_SHEET (widget);
 
-  requisition->width = 3*DEFAULT_COLUMN_WIDTH;
-  requisition->height = 3*DEFAULT_ROW_HEIGHT (widget);
+  requisition->width = 3 * DEFAULT_COLUMN_WIDTH;
+  requisition->height = 3 * DEFAULT_ROW_HEIGHT;
 
   /* compute the size of the column title area */
   if (sheet->column_titles_visible)
@@ -5884,21 +4303,12 @@ gtk_sheet_size_request (GtkWidget * widget,
   /* compute the size of the row title area */
   if (sheet->row_titles_visible)
     requisition->width += sheet->row_title_area.width;
-
-  children = sheet->children;
-  while (children)
-    {
-      child = children->data;
-      children = children->next;
-
-      gtk_widget_size_request (child->widget, &child_requisition);
-    }
 }
 
 
 static void
-gtk_sheet_size_allocate (GtkWidget * widget,
-                        GtkAllocation * allocation)
+gtk_sheet_size_allocate (GtkWidget *widget,
+                        GtkAllocation *allocation)
 {
   GtkSheet *sheet;
   GtkAllocation sheet_allocation;
@@ -5919,22 +4329,11 @@ gtk_sheet_size_allocate (GtkWidget * widget,
                            allocation->width - 2 * border_width,
                            allocation->height - 2 * border_width);
 
-  /* use internal allocation structure for all the math
-   * because it's easier than always subtracting the container
-   * border width */
-  sheet->internal_allocation.x = 0;
-  sheet->internal_allocation.y = 0;
-  sheet->internal_allocation.width = allocation->width - 2 * border_width;
-  sheet->internal_allocation.height = allocation->height - 2 * border_width;
-
   sheet_allocation.x = 0;
   sheet_allocation.y = 0;
   sheet_allocation.width = allocation->width - 2 * border_width;
   sheet_allocation.height = allocation->height - 2 * border_width;
 
-  sheet->sheet_window_width = sheet_allocation.width;
-  sheet->sheet_window_height = sheet_allocation.height;
-
   if (GTK_WIDGET_REALIZED (widget))
     gdk_window_move_resize (sheet->sheet_window,
                            sheet_allocation.x,
@@ -5945,10 +4344,21 @@ gtk_sheet_size_allocate (GtkWidget * widget,
   /* position the window which holds the column title buttons */
   sheet->column_title_area.x = 0;
   sheet->column_title_area.y = 0;
+  sheet->column_title_area.width = sheet_allocation.width ;
+
+
+  /* position the window which holds the row title buttons */
+  sheet->row_title_area.x = 0;
+  sheet->row_title_area.y = 0;
+  sheet->row_title_area.height = sheet_allocation.height;
+
   if (sheet->row_titles_visible)
-    sheet->column_title_area.x = sheet->row_title_area.width;
-  sheet->column_title_area.width = sheet_allocation.width -
-    sheet->column_title_area.x;
+    sheet->column_title_area.x += sheet->row_title_area.width;
+
+  if (sheet->column_titles_visible)
+    sheet->row_title_area.y += sheet->column_title_area.height;
+
+
   if (GTK_WIDGET_REALIZED (widget) && sheet->column_titles_visible)
     gdk_window_move_resize (sheet->column_title_window,
                            sheet->column_title_area.x,
@@ -5956,19 +4366,6 @@ gtk_sheet_size_allocate (GtkWidget * widget,
                            sheet->column_title_area.width,
                            sheet->column_title_area.height);
 
-  sheet->sheet_window_width = sheet_allocation.width;
-  sheet->sheet_window_height = sheet_allocation.height;
-
-  /* column button allocation */
-  size_allocate_column_title_buttons (sheet);
-
-  /* position the window which holds the row title buttons */
-  sheet->row_title_area.x = 0;
-  sheet->row_title_area.y = 0;
-  if (sheet->column_titles_visible)
-    sheet->row_title_area.y = sheet->column_title_area.height;
-  sheet->row_title_area.height = sheet_allocation.height -
-    sheet->row_title_area.y;
 
   if (GTK_WIDGET_REALIZED (widget) && sheet->row_titles_visible)
     gdk_window_move_resize (sheet->row_title_window,
@@ -5977,35 +4374,50 @@ gtk_sheet_size_allocate (GtkWidget * widget,
                            sheet->row_title_area.width,
                            sheet->row_title_area.height);
 
+  if (sheet->haxis)
+    {
+      gint width = sheet->column_title_area.width;
+
+      if ( sheet->row_titles_visible)
+       width -= sheet->row_title_area.width;
+
+      g_object_set (sheet->haxis,
+                   "minimum-extent", width,
+                   NULL);
+    }
+
+
+  if (sheet->vaxis)
+    {
+      gint height = sheet->row_title_area.height;
+
+      if ( sheet->column_titles_visible)
+       height -= sheet->column_title_area.height;
 
-  /* row button allocation */
-  size_allocate_row_title_buttons (sheet);
-  size_allocate_column_title_buttons (sheet);
+      g_object_set (sheet->vaxis,
+                   "minimum-extent", height,
+                   NULL);
+    }
 
-  /* re - scale backing pixmap */
-  gtk_sheet_make_backing_pixmap (sheet, 0, 0);
-  gtk_sheet_position_children (sheet);
 
   /* set the scrollbars adjustments */
   adjust_scrollbars (sheet);
 }
 
 static void
-size_allocate_column_title_buttons (GtkSheet * sheet)
+draw_column_title_buttons (GtkSheet *sheet)
 {
-  gint i;
   gint x, width;
 
   if (!sheet->column_titles_visible) return;
   if (!GTK_WIDGET_REALIZED (sheet))
     return;
 
-  width = sheet->sheet_window_width;
+  gdk_drawable_get_size (sheet->sheet_window, &width, NULL);
   x = 0;
 
   if (sheet->row_titles_visible)
     {
-      width -= sheet->row_title_area.width;
       x = sheet->row_title_area.width;
     }
 
@@ -6020,8 +4432,8 @@ size_allocate_column_title_buttons (GtkSheet * sheet)
                              sheet->column_title_area.height);
     }
 
-
-  if (MAX_VISIBLE_COLUMN (sheet) == xxx_column_count (sheet) - 1)
+  if (max_visible_column (sheet) ==
+      psppire_axis_unit_count (sheet->haxis) - 1)
     gdk_window_clear_area (sheet->column_title_window,
                           0, 0,
                           sheet->column_title_area.width,
@@ -6031,26 +4443,24 @@ size_allocate_column_title_buttons (GtkSheet * sheet)
 
   size_allocate_global_button (sheet);
 
-  for (i = MIN_VISIBLE_COLUMN (sheet); i <= MAX_VISIBLE_COLUMN (sheet); i++)
-    gtk_sheet_column_title_button_draw (sheet, i);
+  draw_column_title_buttons_range (sheet, min_visible_column (sheet), 
+                                  max_visible_column (sheet));
 }
 
 static void
-size_allocate_row_title_buttons (GtkSheet * sheet)
+draw_row_title_buttons (GtkSheet *sheet)
 {
-  gint i;
-  gint y, height;
+  gint y = 0;
+  gint height;
 
   if (!sheet->row_titles_visible) return;
   if (!GTK_WIDGET_REALIZED (sheet))
     return;
 
-  height = sheet->sheet_window_height;
-  y = 0;
+  gdk_drawable_get_size (sheet->sheet_window, NULL, &height);
 
   if (sheet->column_titles_visible)
     {
-      height -= sheet->column_title_area.height;
       y = sheet->column_title_area.height;
     }
 
@@ -6064,7 +4474,8 @@ size_allocate_row_title_buttons (GtkSheet * sheet)
                              sheet->row_title_area.width,
                              sheet->row_title_area.height);
     }
-  if (MAX_VISIBLE_ROW (sheet) == yyy_row_count (sheet)- 1)
+
+  if (max_visible_row (sheet) == psppire_axis_unit_count (sheet->vaxis) - 1)
     gdk_window_clear_area (sheet->row_title_window,
                           0, 0,
                           sheet->row_title_area.width,
@@ -6074,30 +4485,23 @@ size_allocate_row_title_buttons (GtkSheet * sheet)
 
   size_allocate_global_button (sheet);
 
-  for (i = MIN_VISIBLE_ROW (sheet); i <= MAX_VISIBLE_ROW (sheet); i++)
-    {
-      if ( i >= yyy_row_count (sheet))
-       break;
-      gtk_sheet_row_title_button_draw (sheet, i);
-    }
+
+  draw_row_title_buttons_range (sheet, min_visible_row (sheet),
+                               max_visible_row (sheet));
 }
 
 
 static void
 gtk_sheet_size_allocate_entry (GtkSheet *sheet)
 {
-  GtkAllocation shentry_allocation;
+  GtkAllocation entry_alloc;
   GtkSheetCellAttr attributes = { 0 };
   GtkEntry *sheet_entry;
-  GtkStyle *style = NULL, *previous_style = NULL;
-  gint row, col;
-  gint size, max_size, text_size, column_width;
-  const gchar *text;
 
   if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
   if (!GTK_WIDGET_MAPPED (GTK_WIDGET (sheet))) return;
 
-  sheet_entry = GTK_ENTRY (gtk_sheet_get_entry (sheet));
+  sheet_entry = gtk_sheet_get_entry (sheet);
 
   if ( ! gtk_sheet_get_attributes (sheet, sheet->active_cell.row,
                                   sheet->active_cell.col,
@@ -6106,166 +4510,45 @@ gtk_sheet_size_allocate_entry (GtkSheet *sheet)
 
   if ( GTK_WIDGET_REALIZED (sheet->entry_widget) )
     {
-      if (!GTK_WIDGET (sheet_entry)->style)
-       gtk_widget_ensure_style (GTK_WIDGET (sheet_entry));
-
-      previous_style = GTK_WIDGET (sheet_entry)->style;
+      GtkStyle *style = GTK_WIDGET (sheet_entry)->style;
 
-      style = gtk_style_copy (previous_style);
       style->bg[GTK_STATE_NORMAL] = attributes.background;
       style->fg[GTK_STATE_NORMAL] = attributes.foreground;
       style->text[GTK_STATE_NORMAL] = attributes.foreground;
       style->bg[GTK_STATE_ACTIVE] = attributes.background;
       style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
       style->text[GTK_STATE_ACTIVE] = attributes.foreground;
-
-      pango_font_description_free (style->font_desc);
-      g_assert (attributes.font_desc);
-      style->font_desc = pango_font_description_copy (attributes.font_desc);
-
-      GTK_WIDGET (sheet_entry)->style = style;
-      gtk_widget_size_request (sheet->entry_widget, NULL);
-      GTK_WIDGET (sheet_entry)->style = previous_style;
-
-      if (style != previous_style)
-       {
-         if (!GTK_IS_ITEM_ENTRY (sheet->entry_widget))
-           {
-             style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
-             style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
-             style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
-             style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
-           }
-         gtk_widget_set_style (GTK_WIDGET (sheet_entry), style);
-          g_object_unref (style);
-       }
     }
 
-  if (GTK_IS_ITEM_ENTRY (sheet_entry))
-    max_size = GTK_ITEM_ENTRY (sheet_entry)->text_max_size;
-  else
-    max_size = 0;
-
-  text_size = 0;
-  text = gtk_entry_get_text (GTK_ENTRY (sheet_entry));
-  if (text && strlen (text) > 0)
-    text_size = STRING_WIDTH (GTK_WIDGET (sheet), attributes.font_desc, text);
-
-  column_width = xxx_column_width (sheet, sheet->active_cell.col);
-
-  size = MIN (text_size, max_size);
-  size = MAX (size, column_width - 2 * CELLOFFSET);
-
-  row = sheet->active_cell.row;
-  col = sheet->active_cell.col;
-
-  shentry_allocation.x = COLUMN_LEFT_XPIXEL (sheet, sheet->active_cell.col);
-  shentry_allocation.y = ROW_TOP_YPIXEL (sheet, sheet->active_cell.row);
-  shentry_allocation.width = column_width;
-  shentry_allocation.height = yyy_row_height (sheet, sheet->active_cell.row);
+  rectangle_from_cell (sheet, sheet->active_cell.row,
+                      sheet->active_cell.col, &entry_alloc);
 
-  if (GTK_IS_ITEM_ENTRY (sheet->entry_widget))
-    {
-      shentry_allocation.height -= 2 * CELLOFFSET;
-      shentry_allocation.y += CELLOFFSET;
-      shentry_allocation.width = size;
-
-      switch (GTK_ITEM_ENTRY (sheet_entry)->justification)
-       {
-       case GTK_JUSTIFY_CENTER:
-         shentry_allocation.x += column_width / 2 - size / 2;
-         break;
-       case GTK_JUSTIFY_RIGHT:
-         shentry_allocation.x += column_width - size - CELLOFFSET;
-         break;
-       case GTK_JUSTIFY_LEFT:
-       case GTK_JUSTIFY_FILL:
-         shentry_allocation.x += CELLOFFSET;
-         break;
-       }
-    }
-
-  if (!GTK_IS_ITEM_ENTRY (sheet->entry_widget))
-    {
-      shentry_allocation.x += 2;
-      shentry_allocation.y += 2;
-      shentry_allocation.width -= MIN (shentry_allocation.width, 3);
-      shentry_allocation.height -= MIN (shentry_allocation.height, 3);
-    }
+  entry_alloc.width -= BORDER_WIDTH;
+  entry_alloc.height -= BORDER_WIDTH;
+  entry_alloc.x += BORDER_WIDTH / 2;
+  entry_alloc.y += BORDER_WIDTH / 2;
 
-  gtk_widget_size_allocate (sheet->entry_widget, &shentry_allocation);
 
-  if (previous_style == style) g_object_unref (previous_style);
+  gtk_widget_set_size_request (sheet->entry_widget, entry_alloc.width,
+                              entry_alloc.height);
+  gtk_widget_size_allocate (sheet->entry_widget, &entry_alloc);
 }
 
+
+/* Copy the sheet's font to the entry widget */
 static void
-gtk_sheet_entry_set_max_size (GtkSheet *sheet)
+set_entry_widget_font (GtkSheet *sheet)
 {
-  gint i;
-  gint size = 0;
-  gint sizel = 0, sizer = 0;
-  gint row, col;
-  GtkJustification justification;
-  gchar *s = NULL;
-
-  row = sheet->active_cell.row;
-  col = sheet->active_cell.col;
+  GtkRcStyle *style = gtk_widget_get_modifier_style (sheet->entry_widget);
 
-  if ( ! GTK_IS_ITEM_ENTRY (sheet->entry_widget) )
-    return;
-
-  justification = GTK_ITEM_ENTRY (sheet->entry_widget)->justification;
-
-  switch (justification)
-    {
-    case GTK_JUSTIFY_FILL:
-    case GTK_JUSTIFY_LEFT:
-      for (i = col + 1; i <= MAX_VISIBLE_COLUMN (sheet); i++)
-       {
-         if ((s = gtk_sheet_cell_get_text (sheet, row, i)))
-           {
-             g_free (s);
-             break;
-           }
-         size +=xxx_column_width (sheet, i);
-       }
-      size = MIN (size, sheet->sheet_window_width - COLUMN_LEFT_XPIXEL (sheet, col));
-      break;
-    case GTK_JUSTIFY_RIGHT:
-      for (i = col - 1; i >= MIN_VISIBLE_COLUMN (sheet); i--)
-       {
-         if ((s = gtk_sheet_cell_get_text (sheet, row, i)))
-           {
-             g_free (s);
-             break;
-           }
-         size +=xxx_column_width (sheet, i);
-       }
-      break;
-    case GTK_JUSTIFY_CENTER:
-      for (i = col + 1; i <= MAX_VISIBLE_COLUMN (sheet); i++)
-       {
-         sizer += xxx_column_width (sheet, i);
-       }
-      for (i = col - 1; i >= MIN_VISIBLE_COLUMN (sheet); i--)
-       {
-         if ((s = gtk_sheet_cell_get_text (sheet, row, i)))
-           {
-             g_free (s);
-             break;
-           }
-         sizel +=xxx_column_width (sheet, i);
-       }
-      size = 2 * MIN (sizel, sizer);
-      break;
-    }
+  pango_font_description_free (style->font_desc);
+  style->font_desc = pango_font_description_copy (GTK_WIDGET (sheet)->style->font_desc);
 
-  if (size != 0)
-    size += xxx_column_width (sheet, col);
-  GTK_ITEM_ENTRY (sheet->entry_widget)->text_max_size = size;
+  gtk_widget_modify_style (sheet->entry_widget, style);
 }
 
 
+
 static void
 create_sheet_entry (GtkSheet *sheet)
 {
@@ -6274,32 +4557,18 @@ create_sheet_entry (GtkSheet *sheet)
       gtk_widget_unparent (sheet->entry_widget);
     }
 
-  if (sheet->entry_type)
-    {
-      sheet->entry_container = g_object_new (sheet->entry_type, NULL);
-      g_object_ref_sink (sheet->entry_container);
-      sheet->entry_widget = gtk_sheet_get_entry (sheet);
+  sheet->entry_widget = g_object_new (sheet->entry_type, NULL);
+  g_object_ref_sink (sheet->entry_widget);
 
-      if  ( NULL == sheet->entry_widget)
-       {
-         g_warning ("Entry type is %s. It must be GtkEntry subclass, or a widget containing one. "
-                    "Using default", g_type_name (sheet->entry_type));
-         g_object_unref (sheet->entry_container);
-         sheet->entry_widget = sheet->entry_container = gtk_item_entry_new ();
-       }
-      else
-       {
-         sheet->entry_widget = sheet->entry_container ;
-       }
-    }
-  else
+  gtk_widget_size_request (sheet->entry_widget, NULL);
+
+  if ( GTK_IS_ENTRY (sheet->entry_widget))
     {
-      sheet->entry_widget = sheet->entry_container = gtk_item_entry_new ();
-      g_object_ref_sink (sheet->entry_container);
+      g_object_set (sheet->entry_widget,
+                   "has-frame", FALSE,
+                   NULL);
     }
 
-  gtk_widget_size_request (sheet->entry_widget, NULL);
-
   if (GTK_WIDGET_REALIZED (sheet))
     {
       gtk_widget_set_parent_window (sheet->entry_widget, sheet->sheet_window);
@@ -6311,6 +4580,14 @@ create_sheet_entry (GtkSheet *sheet)
                            G_CALLBACK (gtk_sheet_entry_key_press),
                            sheet);
 
+  sheet->entry_handler_id =
+    g_signal_connect (sheet->entry_widget,
+                     "changed",
+                     G_CALLBACK (gtk_sheet_entry_changed),
+                     sheet);
+
+  set_entry_widget_font (sheet);
+
   gtk_widget_show (sheet->entry_widget);
 }
 
@@ -6326,92 +4603,52 @@ find_entry (GtkWidget *w, gpointer user_data)
     }
 }
 
-GtkWidget *
+
+GtkEntry *
 gtk_sheet_get_entry (GtkSheet *sheet)
 {
-  GtkWidget *parent;
-  GtkWidget *entry = NULL;
-  GtkTableChild *table_child;
-  GtkBoxChild *box_child;
-  GList *children = NULL;
+  GtkWidget *w = sheet->entry_widget;
 
   g_return_val_if_fail (sheet != NULL, NULL);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
   g_return_val_if_fail (sheet->entry_widget != NULL, NULL);
 
-  if (GTK_IS_ENTRY (sheet->entry_container))
-    return (sheet->entry_container);
-
-  parent = sheet->entry_container;
-
-  if (GTK_IS_TABLE (parent)) children = GTK_TABLE (parent)->children;
-  if (GTK_IS_BOX (parent)) children = GTK_BOX (parent)->children;
-
-  if (GTK_IS_CONTAINER (parent))
+  while (! GTK_IS_ENTRY (w))
     {
-      gtk_container_forall (GTK_CONTAINER (parent), find_entry, &entry);
+      GtkWidget *entry = NULL;
 
-      if (GTK_IS_ENTRY (entry))
-       return entry;
-    }
+      if (GTK_IS_CONTAINER (w))
+       {
+         gtk_container_forall (GTK_CONTAINER (w), find_entry, &entry);
 
-  if (!children) return NULL;
+         if (NULL == entry)
+           break;
 
-  while (children)
-    {
-      if (GTK_IS_TABLE (parent))
-       {
-         table_child = children->data;
-         entry = table_child->widget;
-       }
-      if (GTK_IS_BOX (parent))
-       {
-         box_child = children->data;
-         entry = box_child->widget;
+         w = entry;
        }
-
-      if (GTK_IS_ENTRY (entry))
-       break;
-      children = children->next;
     }
 
-
-  if (!GTK_IS_ENTRY (entry)) return NULL;
-
-  return (entry);
-
-}
-
-GtkWidget *
-gtk_sheet_get_entry_widget (GtkSheet *sheet)
-{
-  g_return_val_if_fail (sheet != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
-  g_return_val_if_fail (sheet->entry_widget != NULL, NULL);
-
-  return (sheet->entry_widget);
+  return GTK_ENTRY (w);
 }
 
 
 static void
-gtk_sheet_button_draw (GtkSheet *sheet, GdkWindow *window,
+draw_button (GtkSheet *sheet, GdkWindow *window,
                       GtkSheetButton *button, gboolean is_sensitive,
                       GdkRectangle allocation)
 {
   GtkShadowType shadow_type;
   gint text_width = 0, text_height = 0;
-  GtkSheetChild *child = NULL;
   PangoAlignment align = PANGO_ALIGN_LEFT;
 
   gboolean rtl ;
 
   gint state = 0;
-  gint len = 0;
-  gchar *line = 0;
 
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (button != NULL);
 
+
   rtl = gtk_widget_get_direction (GTK_WIDGET (sheet)) == GTK_TEXT_DIR_RTL;
 
   gdk_window_clear_area (window,
@@ -6443,198 +4680,164 @@ gtk_sheet_button_draw (GtkSheet *sheet, GdkWindow *window,
 
   if (button->label_visible)
     {
-
-      text_height = DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet))- 2 * CELLOFFSET;
+      text_height = DEFAULT_ROW_HEIGHT -
+       2 * COLUMN_TITLES_HEIGHT;
 
       gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->fg_gc[button->state],
                                 &allocation);
-      gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->white_gc, &allocation);
+      gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->white_gc,
+                                &allocation);
 
       allocation.y += 2 * sheet->button->style->ythickness;
 
-
-      if (button->label && strlen (button->label)>0)
+      if (button->label && strlen (button->label) > 0)
        {
-         gchar *words = 0;
+         PangoRectangle rect;
+         gchar *line = button->label;
+
          PangoLayout *layout = NULL;
-         gint real_x = allocation.x, real_y = allocation.y;
+         gint real_x = allocation.x;
+         gint real_y = allocation.y;
 
-         words = button->label;
-         line = g_new (gchar, 1);
-         line[0]='\0';
+         layout = gtk_widget_create_pango_layout (GTK_WIDGET (sheet), line);
+         pango_layout_get_extents (layout, NULL, &rect);
 
-         while (words && *words != '\0')
+         text_width = PANGO_PIXELS (rect.width);
+         switch (button->justification)
            {
-             if (*words != '\n')
-               {
-                 len = strlen (line);
-                 line = g_realloc (line, len + 2);
-                 line[len]=*words;
-                 line[len + 1]='\0';
-               }
-             if (*words == '\n' || * (words + 1) == '\0')
-               {
-                 text_width = STRING_WIDTH (GTK_WIDGET (sheet), GTK_WIDGET (sheet)->style->font_desc, line);
-
-                 layout = gtk_widget_create_pango_layout (GTK_WIDGET (sheet), line);
-                 switch (button->justification)
-                   {
-                   case GTK_JUSTIFY_LEFT:
-                     real_x = allocation.x + CELLOFFSET;
-                     align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
-                     break;
-                   case GTK_JUSTIFY_RIGHT:
-                     real_x = allocation.x + allocation.width - text_width - CELLOFFSET;
-                     align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
-                     break;
-                   case GTK_JUSTIFY_CENTER:
-                   default:
-                     real_x = allocation.x + (allocation.width - text_width)/2;
-                     align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
-                     pango_layout_set_justify (layout, TRUE);
-                   }
-                 pango_layout_set_alignment (layout, align);
-                 gtk_paint_layout (GTK_WIDGET (sheet)->style,
-                                   window,
-                                   state,
-                                   FALSE,
-                                   &allocation,
-                                   GTK_WIDGET (sheet),
-                                   "label",
-                                   real_x, real_y,
-                                   layout);
-                 g_object_unref (layout);
-
-                 real_y += text_height + 2;
-
-                 g_free (line);
-                 line = g_new (gchar, 1);
-                 line[0]='\0';
-               }
-             words++;
+           case GTK_JUSTIFY_LEFT:
+             real_x = allocation.x + COLUMN_TITLES_HEIGHT;
+             align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
+             break;
+           case GTK_JUSTIFY_RIGHT:
+             real_x = allocation.x + allocation.width - text_width - COLUMN_TITLES_HEIGHT;
+             align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
+             break;
+           case GTK_JUSTIFY_CENTER:
+           default:
+             real_x = allocation.x + (allocation.width - text_width)/2;
+             align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
+             pango_layout_set_justify (layout, TRUE);
            }
-         g_free (line);
-       }
-
-      gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->fg_gc[button->state],
-                                NULL);
-      gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->white_gc, NULL);
-
-    }
-
-  if ((child = button->child) && (child->widget))
-    {
-      child->x = allocation.x;
-      child->y = allocation.y;
-
-      child->x += (allocation.width - child->widget->requisition.width) / 2;
-      child->y += (allocation.height - child->widget->requisition.height) / 2;
-      allocation.x = child->x;
-      allocation.y = child->y;
-      allocation.width = child->widget->requisition.width;
-      allocation.height = child->widget->requisition.height;
-
-      allocation.x = child->x;
-      allocation.y = child->y;
+         pango_layout_set_alignment (layout, align);
+         gtk_paint_layout (GTK_WIDGET (sheet)->style,
+                           window,
+                           state,
+                           FALSE,
+                           &allocation,
+                           GTK_WIDGET (sheet),
+                           "label",
+                           real_x, real_y,
+                           layout);
+         g_object_unref (layout);
+       }
 
-      gtk_widget_set_state (child->widget, button->state);
+      gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->fg_gc[button->state],
+                                NULL);
+      gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->white_gc, NULL);
 
-      if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) &&
-         GTK_WIDGET_MAPPED (child->widget))
-       {
-         gtk_widget_size_allocate (child->widget,
-                                   &allocation);
-         gtk_widget_queue_draw (child->widget);
-       }
     }
 
   gtk_sheet_button_free (button);
 }
 
 
-/* COLUMN value of - 1 indicates that the area to the right of the rightmost
-   button should be redrawn */
+/* Draw the column title buttons FIRST through to LAST */
 static void
-gtk_sheet_column_title_button_draw (GtkSheet *sheet, gint column)
+draw_column_title_buttons_range (GtkSheet *sheet, gint first, gint last)
 {
-  GdkWindow *window = NULL;
-  GdkRectangle allocation;
-
-  gboolean is_sensitive = FALSE;
-
+  GdkRectangle rect;
+  gint col;
   if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
 
-  if (column >= 0 && ! xxx_column_is_visible (sheet, column)) return;
-  if (column >= 0 && !sheet->column_titles_visible) return;
-  if (column >= 0 && column < MIN_VISIBLE_COLUMN (sheet)) return;
-  if (column >= 0 && column > MAX_VISIBLE_COLUMN (sheet)) return;
+  if (!sheet->column_titles_visible) return;
 
-  window = sheet->column_title_window;
-  allocation.y = 0;
-  allocation.height = sheet->column_title_area.height;
+  g_return_if_fail (first >= min_visible_column (sheet));
+  g_return_if_fail (last <= max_visible_column (sheet));
 
-  if ( column == -1 )
-    {
-      const gint cols = xxx_column_count (sheet) ;
-      allocation.x = COLUMN_LEFT_XPIXEL (sheet, cols - 1)
-       ;
-      allocation.width = sheet->column_title_area.width
-       + sheet->column_title_area.x
-       - allocation.x;
+  rect.y = 0;
+  rect.height = sheet->column_title_area.height;
+  rect.x = psppire_axis_pixel_start (sheet->haxis, first) + CELL_SPACING;
+  rect.width = psppire_axis_pixel_start (sheet->haxis, last) + CELL_SPACING
+    + psppire_axis_unit_size (sheet->haxis, last);
 
-      gdk_window_clear_area (window,
-                            allocation.x, allocation.y,
-                            allocation.width, allocation.height);
-    }
-  else
-    {
-      GtkSheetButton *button = xxx_column_button (sheet, column);
-      allocation.x = COLUMN_LEFT_XPIXEL (sheet, column) + CELL_SPACING;
-      if (sheet->row_titles_visible)
-       allocation.x -= sheet->row_title_area.width;
+  rect.x -= sheet->hadjustment->value;
+
+  minimize_int (&rect.width, sheet->column_title_area.width);
+  maximize_int (&rect.x, 0);
 
-      allocation.width = xxx_column_width (sheet, column);
+  gdk_window_begin_paint_rect (sheet->column_title_window, &rect);
 
-      is_sensitive = xxx_column_is_sensitive (sheet, column);
-      gtk_sheet_button_draw (sheet, window, button,
-                            is_sensitive, allocation);
+  for (col = first ; col <= last ; ++col)
+    {
+      GdkRectangle allocation;
+      gboolean is_sensitive = FALSE;
 
-      /* FIXME: Not freeing this button is correct (sort of),
-        because in PSPP the model always returns a static copy */
+      GtkSheetButton *
+       button = g_sheet_model_get_column_button (sheet->model, col);
+      allocation.y = 0;
+      allocation.x = psppire_axis_pixel_start (sheet->haxis, col)
+       + CELL_SPACING;
+      allocation.x -= sheet->hadjustment->value;
 
-      /* gtk_sheet_button_free (button); */
+      allocation.height = sheet->column_title_area.height;
+      allocation.width = psppire_axis_unit_size (sheet->haxis, col);
+      is_sensitive = g_sheet_model_get_column_sensitivity (sheet->model, col);
 
+      draw_button (sheet, sheet->column_title_window,
+                  button, is_sensitive, allocation);
     }
+
+  gdk_window_end_paint (sheet->column_title_window);
 }
 
+
 static void
-gtk_sheet_row_title_button_draw (GtkSheet *sheet, gint row)
+draw_row_title_buttons_range (GtkSheet *sheet, gint first, gint last)
 {
-  GdkWindow *window = NULL;
-  GdkRectangle allocation;
-  GtkSheetButton *button = NULL;
-  gboolean is_sensitive = FALSE;
+  GdkRectangle rect;
+  gint row;
+  if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
 
+  if (!sheet->row_titles_visible) return;
 
-  if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
+  g_return_if_fail (first >= min_visible_row (sheet));
+  g_return_if_fail (last <= max_visible_row (sheet));
 
-  if (row >= 0 && !yyy_row_is_visible (sheet, row)) return;
-  if (row >= 0 && !sheet->row_titles_visible) return;
-  if (row >= 0 && row < MIN_VISIBLE_ROW (sheet)) return;
-  if (row >= 0 && row > MAX_VISIBLE_ROW (sheet)) return;
+  rect.x = 0;
+  rect.width = sheet->row_title_area.width;
+  rect.y = psppire_axis_pixel_start (sheet->vaxis, first) + CELL_SPACING;
+  rect.height = psppire_axis_pixel_start (sheet->vaxis, last) + CELL_SPACING
+    + psppire_axis_unit_size (sheet->vaxis, last);
 
+  rect.y -= sheet->vadjustment->value;
 
-  window = sheet->row_title_window;
-  button = yyy_row_button (sheet, row);
-  allocation.x = 0;
-  allocation.y = ROW_TOP_YPIXEL (sheet, row) + CELL_SPACING;
-  if (sheet->column_titles_visible)
-    allocation.y -= sheet->column_title_area.height;
-  allocation.width = sheet->row_title_area.width;
-  allocation.height = yyy_row_height (sheet, row);
-  is_sensitive = yyy_row_is_sensitive (sheet, row);
+  minimize_int (&rect.height, sheet->row_title_area.height);
+  maximize_int (&rect.y, 0);
+
+  gdk_window_begin_paint_rect (sheet->row_title_window, &rect);
+  for (row = first; row <= last; ++row)
+    {
+      GdkRectangle allocation;
 
-  gtk_sheet_button_draw (sheet, window, button, is_sensitive, allocation);
+      gboolean is_sensitive = FALSE;
+
+      GtkSheetButton *button =
+       g_sheet_model_get_row_button (sheet->model, row);
+      allocation.x = 0;
+      allocation.y = psppire_axis_pixel_start (sheet->vaxis, row)
+       + CELL_SPACING;
+      allocation.y -= sheet->vadjustment->value;
+
+      allocation.width = sheet->row_title_area.width;
+      allocation.height = psppire_axis_unit_size (sheet->vaxis, row);
+      is_sensitive = g_sheet_model_get_row_sensitivity (sheet->model, row);
+
+      draw_button (sheet, sheet->row_title_window,
+                  button, is_sensitive, allocation);
+    }
+
+  gdk_window_end_paint (sheet->row_title_window);
 }
 
 /* SCROLLBARS
@@ -6644,293 +4847,207 @@ gtk_sheet_row_title_button_draw (GtkSheet *sheet, gint row)
  * vadjustment_value_changed
  * hadjustment_value_changed */
 
+
 static void
-adjust_scrollbars (GtkSheet * sheet)
+update_adjustment (GtkAdjustment *adj, PsppireAxis *axis, gint page_size)
 {
-  if (sheet->vadjustment)
-    {
-      sheet->vadjustment->page_size = sheet->sheet_window_height;
-      sheet->vadjustment->page_increment = sheet->sheet_window_height / 2;
-      sheet->vadjustment->step_increment = DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet));
-      sheet->vadjustment->lower = 0;
-      sheet->vadjustment->upper = SHEET_HEIGHT (sheet) + 80;
-      g_signal_emit_by_name (sheet->vadjustment, "changed");
+  double position =
+    (adj->value + adj->page_size)
+    /
+    (adj->upper - adj->lower);
 
-    }
-
-  if (sheet->hadjustment)
-    {
-      sheet->hadjustment->page_size = sheet->sheet_window_width;
-      sheet->hadjustment->page_increment = sheet->sheet_window_width / 2;
-      sheet->hadjustment->step_increment = DEFAULT_COLUMN_WIDTH;
-      sheet->hadjustment->lower = 0;
-      sheet->hadjustment->upper = SHEET_WIDTH (sheet)+ 80;
-      g_signal_emit_by_name (sheet->hadjustment, "changed");
+  const glong last_item = psppire_axis_unit_count (axis) - 1;
 
-    }
-}
-
-static void
-vadjustment_value_changed (GtkAdjustment * adjustment,
-                          gpointer data)
-{
-  GtkSheet *sheet;
-  gint diff, value, old_value;
-  gint row, new_row;
-  gint y = 0;
+  if (isnan (position) || position < 0)
+    position = 0;
 
-  g_return_if_fail (adjustment != NULL);
-  g_return_if_fail (data != NULL);
-  g_return_if_fail (GTK_IS_SHEET (data));
+  adj->upper =
+    psppire_axis_pixel_start (axis, last_item)
+    +
+    psppire_axis_unit_size (axis, last_item)
+    ;
 
-  sheet = GTK_SHEET (data);
+  adj->lower = 0;
+  adj->page_size = page_size;
 
-  if (GTK_SHEET_IS_FROZEN (sheet)) return;
+  adj->value = position * (adj->upper - adj->lower) - adj->page_size;
 
-  row = ROW_FROM_YPIXEL (sheet, CELL_SPACING);
+  if ( adj->value < adj->lower)
+    adj->value = adj->lower;
 
-  old_value = - sheet->voffset;
+  gtk_adjustment_changed (adj);
+}
 
-  new_row = g_sheet_row_pixel_to_row (sheet->row_geometry,
-                                     adjustment->value);
 
-  y = g_sheet_row_start_pixel (sheet->row_geometry, new_row);
+static void
+adjust_scrollbars (GtkSheet *sheet)
+{
+  gint width, height;
 
-  if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. &&
-      yyy_row_height (sheet, row) > sheet->vadjustment->step_increment)
-    {
-      /* This avoids embarrassing twitching */
-      if (row == new_row && row != yyy_row_count (sheet) - 1 &&
-         adjustment->value - sheet->old_vadjustment >=
-         sheet->vadjustment->step_increment &&
-         new_row + 1 != MIN_VISIBLE_ROW (sheet))
-       {
-         new_row +=1;
-         y = y+yyy_row_height (sheet, row);
-       }
-    }
+  if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
+    return;
 
-  /* Negative old_adjustment enforces the redraw, otherwise avoid
-     spureous redraw */
-  if (sheet->old_vadjustment >= 0. && row == new_row)
-    {
-      sheet->old_vadjustment = sheet->vadjustment->value;
-      return;
-    }
+  gdk_drawable_get_size (sheet->sheet_window, &width, &height);
 
-  sheet->old_vadjustment = sheet->vadjustment->value;
-  adjustment->value = y;
+  if ( sheet->row_titles_visible)
+    width -= sheet->row_title_area.width;
 
+  if (sheet->column_titles_visible)
+    height -= sheet->column_title_area.height;
 
-  if (new_row == 0)
-    {
-      sheet->vadjustment->step_increment = yyy_row_height (sheet, 0);
-    }
-  else
+  if (sheet->vadjustment)
     {
-      sheet->vadjustment->step_increment =
-       MIN (yyy_row_height (sheet, new_row), yyy_row_height (sheet, new_row - 1));
-    }
+      glong last_row = psppire_axis_unit_count (sheet->vaxis) - 1;
 
-  sheet->vadjustment->value = adjustment->value;
+      sheet->vadjustment->step_increment =
+       ROWS_PER_STEP *
+       psppire_axis_unit_size (sheet->vaxis, last_row);
 
-  value = adjustment->value;
+      sheet->vadjustment->page_increment =
+       height -
+       sheet->column_title_area.height -
+       psppire_axis_unit_size (sheet->vaxis, last_row);
 
-  if (value >= - sheet->voffset)
-    {
-      /* scroll down */
-      diff = value + sheet->voffset;
-    }
-  else
-    {
-      /* scroll up */
-      diff = - sheet->voffset - value;
+      update_adjustment (sheet->vadjustment, sheet->vaxis, height);
     }
 
-  sheet->voffset = - value;
-
-  if (GTK_WIDGET_REALIZED (sheet->entry_widget) &&
-      sheet->state == GTK_SHEET_NORMAL &&
-      sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
-      !gtk_sheet_cell_isvisible (sheet, sheet->active_cell.row,
-                                sheet->active_cell.col))
+  if (sheet->hadjustment)
     {
-      const gchar *text;
+      gint last_col = psppire_axis_unit_count (sheet->haxis) - 1;
+      sheet->hadjustment->step_increment = 1;
 
-      text = gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)));
-
-      if (!text || strlen (text) == 0)
-       gtk_sheet_cell_clear (sheet,
-                             sheet->active_cell.row,
-                             sheet->active_cell.col);
-      gtk_widget_unmap (sheet->entry_widget);
-    }
+      sheet->hadjustment->page_increment = width;
 
-  gtk_sheet_position_children (sheet);
+      sheet->hadjustment->upper =
+       psppire_axis_pixel_start (sheet->haxis, last_col)
+       +
+       psppire_axis_unit_size (sheet->haxis, last_col)
+       ;
 
-  gtk_sheet_range_draw (sheet, NULL);
-  size_allocate_row_title_buttons (sheet);
-  size_allocate_global_button (sheet);
+      update_adjustment (sheet->hadjustment, sheet->haxis, width);
+    }
 }
 
 static void
-hadjustment_value_changed (GtkAdjustment * adjustment,
+vadjustment_value_changed (GtkAdjustment *adjustment,
                           gpointer data)
 {
-  GtkSheet *sheet;
-  gint i, diff, value, old_value;
-  gint column, new_column;
-  gint x = 0;
+  GdkRegion *region;
+  GtkSheet *sheet = GTK_SHEET (data);
 
   g_return_if_fail (adjustment != NULL);
-  g_return_if_fail (data != NULL);
-  g_return_if_fail (GTK_IS_SHEET (data));
 
-  sheet = GTK_SHEET (data);
-
-  if (GTK_SHEET_IS_FROZEN (sheet)) return;
+  if ( ! GTK_WIDGET_REALIZED (sheet)) return;
 
-  column = COLUMN_FROM_XPIXEL (sheet, CELL_SPACING);
 
-  old_value = - sheet->hoffset;
+  gtk_widget_hide (sheet->entry_widget);
 
-  for (i = 0; i < xxx_column_count (sheet); i++)
-    {
-      if (xxx_column_is_visible (sheet, i)) x += xxx_column_width (sheet, i);
-      if (x > adjustment->value) break;
-    }
-  x -= xxx_column_width (sheet, i);
-  new_column = i;
+  region =
+    gdk_drawable_get_visible_region (GDK_DRAWABLE (sheet->sheet_window));
 
-  if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 &&
-      xxx_column_width (sheet, i) > sheet->hadjustment->step_increment)
-    {
-      /* This avoids embarrassing twitching */
-      if (column == new_column && column != xxx_column_count (sheet) - 1 &&
-         adjustment->value - sheet->old_hadjustment >=
-         sheet->hadjustment->step_increment &&
-         new_column + 1 != MIN_VISIBLE_COLUMN (sheet))
-       {
-         new_column += 1;
-         x += xxx_column_width (sheet, column);
-       }
-    }
+  gdk_window_begin_paint_region (sheet->sheet_window, region);
 
-  /* Negative old_adjustment enforces the redraw, otherwise avoid spureous redraw */
-  if (sheet->old_hadjustment >= 0. && new_column == column)
-    {
-      sheet->old_hadjustment = sheet->hadjustment->value;
-      return;
-    }
 
-  sheet->old_hadjustment = sheet->hadjustment->value;
-  adjustment->value = x;
+  gtk_sheet_range_draw (sheet, NULL);
+  draw_row_title_buttons (sheet);
+  //  size_allocate_global_button (sheet);
+  gtk_sheet_draw_active_cell (sheet);
 
-  if (new_column == 0)
-    {
-      sheet->hadjustment->step_increment = xxx_column_width (sheet, 0);
-    }
-  else
-    {
-      sheet->hadjustment->step_increment =
-       MIN (xxx_column_width (sheet, new_column), xxx_column_width (sheet, new_column - 1));
-    }
+  gdk_window_end_paint (sheet->sheet_window);
+}
 
 
-  sheet->hadjustment->value = adjustment->value;
+static void
+hadjustment_value_changed (GtkAdjustment *adjustment,
+                          gpointer data)
+{
+  GdkRegion *region;
+  GtkSheet *sheet = GTK_SHEET (data);
 
-  value = adjustment->value;
+  g_return_if_fail (adjustment != NULL);
 
-  if (value >= - sheet->hoffset)
-    {
-      /* scroll right */
-      diff = value + sheet->hoffset;
-    }
-  else
-    {
-      /* scroll left */
-      diff = - sheet->hoffset - value;
-    }
+  if ( ! GTK_WIDGET_REALIZED (sheet)) return;
 
-  sheet->hoffset = - value;
-  if (GTK_WIDGET_REALIZED (sheet->entry_widget) &&
-      sheet->state == GTK_SHEET_NORMAL &&
-      sheet->active_cell.row >= 0 && sheet->active_cell.col >= 0 &&
-      !gtk_sheet_cell_isvisible (sheet, sheet->active_cell.row,
-                                sheet->active_cell.col))
-    {
-      const gchar *text;
+  gtk_widget_hide (sheet->entry_widget);
 
-      text = gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)));
-      if (!text || strlen (text) == 0)
-       gtk_sheet_cell_clear (sheet,
-                             sheet->active_cell.row,
-                             sheet->active_cell.col);
 
-      gtk_widget_unmap (sheet->entry_widget);
-    }
+  region =
+    gdk_drawable_get_visible_region (GDK_DRAWABLE (sheet->sheet_window));
 
-  gtk_sheet_position_children (sheet);
+  gdk_window_begin_paint_region (sheet->sheet_window, region);
 
   gtk_sheet_range_draw (sheet, NULL);
-  size_allocate_column_title_buttons (sheet);
+  draw_column_title_buttons (sheet);
+  //  size_allocate_global_button (sheet);
+
+  gtk_sheet_draw_active_cell (sheet);
+
+  gdk_window_end_paint (sheet->sheet_window);
 }
 
 
 /* COLUMN RESIZING */
 static void
-draw_xor_vline (GtkSheet * sheet)
+draw_xor_vline (GtkSheet *sheet)
 {
-  GtkWidget *widget;
+  gint height;
+  gint xpos = sheet->x_drag;
+  gdk_drawable_get_size (sheet->sheet_window,
+                        NULL, &height);
 
-  g_return_if_fail (sheet != NULL);
 
-  widget = GTK_WIDGET (sheet);
+  if (sheet->row_titles_visible)
+    xpos += sheet->row_title_area.width;
 
-  gdk_draw_line (widget->window, sheet->xor_gc,
-                sheet->x_drag,
+  gdk_draw_line (GTK_WIDGET (sheet)->window, sheet->xor_gc,
+                xpos,
                 sheet->column_title_area.height,
-                sheet->x_drag,
-                sheet->sheet_window_height + 1);
+                xpos,
+                height + CELL_SPACING);
 }
 
 /* ROW RESIZING */
 static void
-draw_xor_hline (GtkSheet * sheet)
+draw_xor_hline (GtkSheet *sheet)
+
 {
-  GtkWidget *widget;
+  gint width;
+  gint ypos = sheet->y_drag;
 
-  g_return_if_fail (sheet != NULL);
+  gdk_drawable_get_size (sheet->sheet_window,
+                        &width, NULL);
 
-  widget = GTK_WIDGET (sheet);
 
-  gdk_draw_line (widget->window, sheet->xor_gc,
-                sheet->row_title_area.width,
-                sheet->y_drag,
+  if (sheet->column_titles_visible)
+    ypos += sheet->column_title_area.height;
 
-                sheet->sheet_window_width + 1,
-                sheet->y_drag);
+  gdk_draw_line (GTK_WIDGET (sheet)->window, sheet->xor_gc,
+                sheet->row_title_area.width,
+                ypos,
+                width + CELL_SPACING,
+                ypos);
 }
 
 /* SELECTED RANGE */
 static void
 draw_xor_rectangle (GtkSheet *sheet, GtkSheetRange range)
 {
-  gint i;
+  gint i = 0;
   GdkRectangle clip_area, area;
   GdkGCValues values;
 
-  area.x = COLUMN_LEFT_XPIXEL (sheet, range.col0);
-  area.y = ROW_TOP_YPIXEL (sheet, range.row0);
-  area.width = COLUMN_LEFT_XPIXEL (sheet, range.coli)- area.x+
-    xxx_column_width (sheet, range.coli);
-  area.height = ROW_TOP_YPIXEL (sheet, range.rowi)- area.y+
-    yyy_row_height (sheet, range.rowi);
+  area.x = psppire_axis_pixel_start (sheet->haxis, range.col0);
+  area.y = psppire_axis_pixel_start (sheet->vaxis, range.row0);
+  area.width = psppire_axis_pixel_start (sheet->haxis, range.coli)- area.x+
+    psppire_axis_unit_size (sheet->haxis, range.coli);
+  area.height = psppire_axis_pixel_start (sheet->vaxis, range.rowi)- area.y +
+    psppire_axis_unit_size (sheet->vaxis, range.rowi);
 
   clip_area.x = sheet->row_title_area.width;
   clip_area.y = sheet->column_title_area.height;
-  clip_area.width = sheet->sheet_window_width;
-  clip_area.height = sheet->sheet_window_height;
+
+  gdk_drawable_get_size (sheet->sheet_window,
+                        &clip_area.width, &clip_area.height);
 
   if (!sheet->row_titles_visible) clip_area.x = 0;
   if (!sheet->column_titles_visible) clip_area.y = 0;
@@ -6957,50 +5074,42 @@ draw_xor_rectangle (GtkSheet *sheet, GtkSheetRange range)
 
   gdk_gc_set_clip_rectangle (sheet->xor_gc, &clip_area);
 
-  for (i = -1; i <= 1; ++i)
-    gdk_draw_rectangle (sheet->sheet_window,
-                       sheet->xor_gc,
-                       FALSE,
-                       area.x + i, area.y + i,
-                       area.width - 2 * i, area.height - 2 * i);
+  gdk_draw_rectangle (sheet->sheet_window,
+                     sheet->xor_gc,
+                     FALSE,
+                     area.x + i, area.y + i,
+                     area.width - 2 * i, area.height - 2 * i);
 
 
   gdk_gc_set_clip_rectangle (sheet->xor_gc, NULL);
 
   gdk_gc_set_foreground (sheet->xor_gc, &values.foreground);
-
 }
 
 
 /* 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 automaticaly corrected if it's beyond min / max limits */
+ * the COLUMN and X position of the cursor; the x cursor position is passed
+ * in as a pointer and automaticaly corrected if it's outside the acceptable
+ * range */
 static guint
-new_column_width (GtkSheet * sheet,
-                 gint column,
-                 gint * x)
+new_column_width (GtkSheet *sheet, gint column, gint *x)
 {
-  gint cx, width;
-  guint min_width;
+  gint left_pos = psppire_axis_pixel_start (sheet->haxis, column)
+    - sheet->hadjustment->value;
 
-  cx = *x;
+  gint width = *x - left_pos;
 
-  min_width = sheet->column_requisition;
-
-  /* you can't shrink a column to less than its minimum width */
-  if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + min_width)
+  if ( width < sheet->column_requisition)
     {
-      *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + min_width;
+      width = sheet->column_requisition;
+      *x = left_pos + width;
     }
 
-  /* calculate new column width making sure it doesn't end up
-   * less than the minimum width */
-  width = cx - COLUMN_LEFT_XPIXEL (sheet, column);
-  if (width < min_width)
-    width = min_width;
+#if AXIS_TRANSITION
+  g_sheet_column_set_width (sheet->column_geometry, column, width);
+#endif
 
-  xxx_set_column_width (sheet, column, width);
-  size_allocate_column_title_buttons (sheet);
+  draw_column_title_buttons (sheet);
 
   return width;
 }
@@ -7009,406 +5118,143 @@ new_column_width (GtkSheet * sheet,
  * the row and y position of the cursor; the y cursor position is passed
  * in as a pointer and automaticaly corrected if it's beyond min / max limits */
 static guint
-new_row_height (GtkSheet * sheet,
-               gint row,
-               gint * y)
+new_row_height (GtkSheet *sheet, gint row, gint *y)
 {
-  gint cy, height;
+  gint height;
   guint min_height;
 
-  cy = *y;
+  gint cy = *y;
   min_height = sheet->row_requisition;
 
-  /* you can't shrink a row to less than its minimum height */
-  if (cy < ROW_TOP_YPIXEL (sheet, row) + min_height)
-
-    {
-      *y = cy = ROW_TOP_YPIXEL (sheet, row) + min_height;
-    }
-
-  /* calculate new row height making sure it doesn't end up
-   * less than the minimum height */
-  height = (cy - ROW_TOP_YPIXEL (sheet, row));
-  if (height < min_height)
-    height = min_height;
-
-  yyy_set_row_height (sheet, row, height);
-  size_allocate_row_title_buttons (sheet);
-
-  return height;
-}
-
-static void
-gtk_sheet_set_column_width (GtkSheet * sheet,
-                           gint column,
-                           guint width)
-{
-  guint min_width;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if (column < 0 || column >= xxx_column_count (sheet))
-    return;
-
-  gtk_sheet_column_size_request (sheet, column, &min_width);
-  if (width < min_width) return;
-
-  xxx_set_column_width (sheet, column, width);
-
-  if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) && !GTK_SHEET_IS_FROZEN (sheet))
-    {
-      size_allocate_column_title_buttons (sheet);
-      adjust_scrollbars (sheet);
-      gtk_sheet_size_allocate_entry (sheet);
-      gtk_sheet_range_draw (sheet, NULL);
-    }
-
-  g_signal_emit (sheet, sheet_signals[CHANGED], 0, -1, column);
-}
-
-
-
-void
-gtk_sheet_set_row_height (GtkSheet * sheet,
-                         gint row,
-                         guint height)
-{
-  guint min_height;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if (row < 0 || row >= yyy_row_count (sheet))
-    return;
-
-  gtk_sheet_row_size_request (sheet, row, &min_height);
-  if (height < min_height) return;
-
-  yyy_set_row_height (sheet, row, height);
-
-  if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) && !GTK_SHEET_IS_FROZEN (sheet))
-    {
-      size_allocate_row_title_buttons (sheet);
-      adjust_scrollbars (sheet);
-      gtk_sheet_size_allocate_entry (sheet);
-      gtk_sheet_range_draw (sheet, NULL);
-    }
-
-  g_signal_emit (sheet, sheet_signals[CHANGED], 0, row, - 1);
-}
-gboolean
-gtk_sheet_get_attributes (const GtkSheet *sheet, gint row, gint col,
-                         GtkSheetCellAttr *attributes)
-{
-  const GdkColor *fg, *bg;
-  const GtkJustification *j ;
-  const PangoFontDescription *font_desc ;
-  const GtkSheetCellBorder *border ;
-
-  g_return_val_if_fail (sheet != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
-
-  if (row < 0 || col < 0) return FALSE;
-
-  init_attributes (sheet, col, attributes);
-
-  if ( !sheet->model)
-    return FALSE;
-
-  attributes->is_editable = g_sheet_model_is_editable (sheet->model, row, col);
-  attributes->is_visible = g_sheet_model_is_visible (sheet->model, row, col);
-
-  fg = g_sheet_model_get_foreground (sheet->model, row, col);
-  if ( fg )
-    attributes->foreground = *fg;
-
-  bg = g_sheet_model_get_background (sheet->model, row, col);
-  if ( bg )
-    attributes->background = *bg;
-
-  j = g_sheet_model_get_justification (sheet->model, row, col);
-  if (j) attributes->justification = *j;
-
-  font_desc = g_sheet_model_get_font_desc (sheet->model, row, col);
-  if ( font_desc ) attributes->font_desc = font_desc;
-
-  border = g_sheet_model_get_cell_border (sheet->model, row, col);
-
-  if ( border ) attributes->border = *border;
-
-  return TRUE;
-}
-
-static void
-init_attributes (const GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
-{
-  /* DEFAULT VALUES */
-  attributes->foreground = GTK_WIDGET (sheet)->style->black;
-  attributes->background = sheet->bg_color;
-  if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
-    {
-      GdkColormap *colormap;
-      colormap = gdk_colormap_get_system ();
-      attributes->background = sheet->bg_color;
-    }
-  attributes->justification = xxx_column_justification (sheet, col);
-  attributes->border.width = 0;
-  attributes->border.line_style = GDK_LINE_SOLID;
-  attributes->border.cap_style = GDK_CAP_NOT_LAST;
-  attributes->border.join_style = GDK_JOIN_MITER;
-  attributes->border.mask = 0;
-  attributes->border.color = GTK_WIDGET (sheet)->style->black;
-  attributes->is_editable = TRUE;
-  attributes->is_visible = TRUE;
-  attributes->font_desc = GTK_WIDGET (sheet)->style->font_desc;
-}
-
-
-/********************************************************************
- * Container Functions:
- * gtk_sheet_add
- * gtk_sheet_put
- * gtk_sheet_attach
- * gtk_sheet_remove
- * gtk_sheet_move_child
- * gtk_sheet_position_child
- * gtk_sheet_position_children
- * gtk_sheet_realize_child
- * gtk_sheet_get_child_at
- ********************************************************************/
-
-GtkSheetChild *
-gtk_sheet_put (GtkSheet *sheet, GtkWidget *child, gint x, gint y)
-{
-  GtkRequisition child_requisition;
-  GtkSheetChild *child_info;
-
-  g_return_val_if_fail (sheet != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
-  g_return_val_if_fail (child != NULL, NULL);
-  g_return_val_if_fail (child->parent == NULL, NULL);
-
-  child_info = g_new (GtkSheetChild, 1);
-  child_info->widget = child;
-  child_info->x = x;
-  child_info->y = y;
-  child_info->attached_to_cell = FALSE;
-  child_info->floating = TRUE;
-  child_info->xpadding = child_info->ypadding = 0;
-  child_info->xexpand = child_info->yexpand = FALSE;
-  child_info->xshrink = child_info->yshrink = FALSE;
-  child_info->xfill = child_info->yfill = FALSE;
-
-  sheet->children = g_list_append (sheet->children, child_info);
-
-  gtk_widget_set_parent (child, GTK_WIDGET (sheet));
-
-  gtk_widget_size_request (child, &child_requisition);
-
-  if (GTK_WIDGET_VISIBLE (GTK_WIDGET (sheet)))
-    {
-      if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) &&
-         (!GTK_WIDGET_REALIZED (child) || GTK_WIDGET_NO_WINDOW (child)))
-       gtk_sheet_realize_child (sheet, child_info);
-
-      if (GTK_WIDGET_MAPPED (GTK_WIDGET (sheet)) &&
-         !GTK_WIDGET_MAPPED (child))
-       gtk_widget_map (child);
-    }
-
-  gtk_sheet_position_child (sheet, child_info);
-
-  /* This will avoid drawing on the titles */
-
-  if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
-    {
-      if (sheet->row_titles_visible)
-       gdk_window_show (sheet->row_title_window);
-      if (sheet->column_titles_visible)
-       gdk_window_show (sheet->column_title_window);
-    }
-
-  return (child_info);
-}
-
-void
-gtk_sheet_attach_floating (GtkSheet *sheet,
-                          GtkWidget *widget,
-                          gint row, gint col)
-{
-  GdkRectangle area;
-  GtkSheetChild *child;
+  /* you can't shrink a row to less than its minimum height */
+  if (cy < psppire_axis_pixel_start (sheet->vaxis, row) + min_height)
 
-  if (row < 0 || col < 0)
     {
-      gtk_sheet_button_attach (sheet, widget, row, col);
-      return;
+      *y = cy = psppire_axis_pixel_start (sheet->vaxis, row) + min_height;
     }
 
-  gtk_sheet_get_cell_area (sheet, row, col, &area);
-  child = gtk_sheet_put (sheet, widget, area.x, area.y);
-  child->attached_to_cell = TRUE;
-  child->row = row;
-  child->col = col;
-}
+  /* calculate new row height making sure it doesn't end up
+   * less than the minimum height */
+  height = (cy - psppire_axis_pixel_start (sheet->vaxis, row));
+  if (height < min_height)
+    height = min_height;
 
-void
-gtk_sheet_attach_default (GtkSheet *sheet,
-                         GtkWidget *widget,
-                         gint row, gint col)
-{
-  if (row < 0 || col < 0)
-    {
-      gtk_sheet_button_attach (sheet, widget, row, col);
-      return;
-    }
+#if AXIS_TRANSITION
+  g_sheet_row_set_height (sheet->row_geometry, row, height);
+#endif
+  draw_row_title_buttons (sheet);
 
-  gtk_sheet_attach (sheet, widget, row, col,
-                   GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+  return height;
 }
 
-void
-gtk_sheet_attach (GtkSheet *sheet,
-                 GtkWidget *widget,
-                 gint row, gint col,
-                 gint xoptions,
-                 gint yoptions,
-                 gint xpadding,
-                 gint ypadding)
+static void
+gtk_sheet_set_column_width (GtkSheet *sheet,
+                           gint column,
+                           guint width)
 {
-  GdkRectangle area;
-  GtkSheetChild *child = NULL;
-
-  if (row < 0 || col < 0)
-    {
-      gtk_sheet_button_attach (sheet, widget, row, col);
-      return;
-    }
+  guint min_width;
 
-  child = g_new0 (GtkSheetChild, 1);
-  child->attached_to_cell = TRUE;
-  child->floating = FALSE;
-  child->widget = widget;
-  child->row = row;
-  child->col = col;
-  child->xpadding = xpadding;
-  child->ypadding = ypadding;
-  child->xexpand = (xoptions & GTK_EXPAND) != 0;
-  child->yexpand = (yoptions & GTK_EXPAND) != 0;
-  child->xshrink = (xoptions & GTK_SHRINK) != 0;
-  child->yshrink = (yoptions & GTK_SHRINK) != 0;
-  child->xfill = (xoptions & GTK_FILL) != 0;
-  child->yfill = (yoptions & GTK_FILL) != 0;
-
-  sheet->children = g_list_append (sheet->children, child);
-
-  gtk_sheet_get_cell_area (sheet, row, col, &area);
-
-  child->x = area.x + child->xpadding;
-  child->y = area.y + child->ypadding;
-
-  if (GTK_WIDGET_VISIBLE (GTK_WIDGET (sheet)))
-    {
-      if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) &&
-         (!GTK_WIDGET_REALIZED (widget) || GTK_WIDGET_NO_WINDOW (widget)))
-       gtk_sheet_realize_child (sheet, child);
+  g_return_if_fail (sheet != NULL);
+  g_return_if_fail (GTK_IS_SHEET (sheet));
 
-      if (GTK_WIDGET_MAPPED (GTK_WIDGET (sheet)) &&
-         !GTK_WIDGET_MAPPED (widget))
-       gtk_widget_map (widget);
-    }
+  if (column < 0 || column >= psppire_axis_unit_count (sheet->haxis))
+    return;
 
-  gtk_sheet_position_child (sheet, child);
+  gtk_sheet_column_size_request (sheet, column, &min_width);
+  if (width < min_width) return;
 
-  /* This will avoid drawing on the titles */
+#if AXIS_TRANSITION
+  g_sheet_column_set_width (sheet->column_geometry, column, width);
+#endif
 
   if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
     {
-      if (GTK_SHEET_ROW_TITLES_VISIBLE (sheet))
-       gdk_window_show (sheet->row_title_window);
-      if (GTK_SHEET_COL_TITLES_VISIBLE (sheet))
-       gdk_window_show (sheet->column_title_window);
+      draw_column_title_buttons (sheet);
+      adjust_scrollbars (sheet);
+      gtk_sheet_size_allocate_entry (sheet);
+      gtk_sheet_range_draw (sheet, NULL);
     }
-
 }
 
-void
-gtk_sheet_button_attach                 (GtkSheet *sheet,
-                                 GtkWidget *widget,
-                                 gint row, gint col)
-{
-  GtkSheetButton *button = 0;
-  GtkSheetChild *child;
-  GtkRequisition button_requisition;
 
-  if (row >= 0 && col >= 0) return;
-  if (row < 0 && col < 0) return;
 
-  child = g_new (GtkSheetChild, 1);
-  child->widget = widget;
-  child->x = 0;
-  child->y = 0;
-  child->attached_to_cell = TRUE;
-  child->floating = FALSE;
-  child->row = row;
-  child->col = col;
-  child->xpadding = child->ypadding = 0;
-  child->xshrink = child->yshrink = FALSE;
-  child->xfill = child->yfill = FALSE;
+static void
+gtk_sheet_set_row_height (GtkSheet *sheet,
+                         gint row,
+                         guint height)
+{
+  guint min_height;
 
+  g_return_if_fail (sheet != NULL);
+  g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  sheet->children = g_list_append (sheet->children, child);
+  if (row < 0 || row >= psppire_axis_unit_count (sheet->vaxis))
+    return;
 
-  gtk_sheet_button_size_request (sheet, button, &button_requisition);
+  gtk_sheet_row_size_request (sheet, row, &min_height);
+  if (height < min_height) return;
 
+#if AXIS_TRANSITION
+  g_sheet_row_set_height (sheet->row_geometry, row, height);
+#endif
 
-  if (GTK_WIDGET_VISIBLE (GTK_WIDGET (sheet)))
+  if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) )
     {
-      if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)) &&
-         (!GTK_WIDGET_REALIZED (widget) || GTK_WIDGET_NO_WINDOW (widget)))
-       gtk_sheet_realize_child (sheet, child);
-
-      if (GTK_WIDGET_MAPPED (GTK_WIDGET (sheet)) &&
-         !GTK_WIDGET_MAPPED (widget))
-       gtk_widget_map (widget);
+      draw_row_title_buttons (sheet);
+      adjust_scrollbars (sheet);
+      gtk_sheet_size_allocate_entry (sheet);
+      gtk_sheet_range_draw (sheet, NULL);
     }
-
-  if (row == -1) size_allocate_column_title_buttons (sheet);
-  if (col == -1) size_allocate_row_title_buttons (sheet);
-
 }
 
-static void
-label_size_request (GtkSheet *sheet, gchar *label, GtkRequisition *req)
+gboolean
+gtk_sheet_get_attributes (const GtkSheet *sheet, gint row, gint col,
+                         GtkSheetCellAttr *attr)
 {
-  gchar *words;
-  gchar word[1000];
-  gint n = 0;
-  gint row_height = DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet)) - 2 * CELLOFFSET + 2;
+  GdkColor *fg, *bg;
+  const GtkJustification *j ;
+  GdkColormap *colormap;
+
+  g_return_val_if_fail (sheet != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
+
+  if (row < 0 || col < 0) return FALSE;
 
-  req->height = 0;
-  req->width = 0;
-  words = label;
+  attr->foreground = GTK_WIDGET (sheet)->style->black;
+  attr->background = sheet->color[BG_COLOR];
 
-  while (words && *words != '\0')
+  attr->border.width = 0;
+  attr->border.line_style = GDK_LINE_SOLID;
+  attr->border.cap_style = GDK_CAP_NOT_LAST;
+  attr->border.join_style = GDK_JOIN_MITER;
+  attr->border.mask = 0;
+  attr->border.color = GTK_WIDGET (sheet)->style->black;
+
+  attr->is_editable = g_sheet_model_is_editable (sheet->model, row, col);
+
+  colormap = gtk_widget_get_colormap (GTK_WIDGET (sheet));
+  fg = g_sheet_model_get_foreground (sheet->model, row, col);
+  if ( fg )
     {
-      if (*words == '\n' || * (words + 1) == '\0')
-       {
-         req->height += row_height;
+      gdk_colormap_alloc_color (colormap, fg, TRUE, TRUE);
+      attr->foreground = *fg;
+    }
 
-         word[n] = '\0';
-         req->width = MAX (req->width, STRING_WIDTH (GTK_WIDGET (sheet), GTK_WIDGET (sheet)->style->font_desc, word));
-         n = 0;
-       }
-      else
-       {
-         word[n++] = *words;
-       }
-      words++;
+  bg = g_sheet_model_get_background (sheet->model, row, col);
+  if ( bg )
+    {
+      gdk_colormap_alloc_color (colormap, bg, TRUE, TRUE);
+      attr->background = *bg;
     }
 
-  if (n > 0) req->height -= 2;
+  attr->justification =
+    g_sheet_model_get_column_justification (sheet->model, col);
+
+  j = g_sheet_model_get_justification (sheet->model, row, col);
+  if (j)
+    attr->justification = *j;
+
+  return TRUE;
 }
 
 static void
@@ -7419,31 +5265,12 @@ gtk_sheet_button_size_request    (GtkSheet *sheet,
   GtkRequisition requisition;
   GtkRequisition label_requisition;
 
-  if (gtk_sheet_autoresize (sheet) && button->label && strlen (button->label) > 0)
-    {
-      label_size_request (sheet, button->label, &label_requisition);
-      label_requisition.width += 2 * CELLOFFSET;
-      label_requisition.height += 2 * CELLOFFSET;
-    }
-  else
-    {
-      label_requisition.height = DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet));
-      label_requisition.width = COLUMN_MIN_WIDTH;
-    }
+  label_requisition.height = DEFAULT_ROW_HEIGHT;
+  label_requisition.width = COLUMN_MIN_WIDTH;
+
+  requisition.height = DEFAULT_ROW_HEIGHT;
+  requisition.width = COLUMN_MIN_WIDTH;
 
-  if (button->child)
-    {
-      gtk_widget_size_request (button->child->widget, &requisition);
-      requisition.width += 2 * button->child->xpadding;
-      requisition.height += 2 * button->child->ypadding;
-      requisition.width += 2 * sheet->button->style->xthickness;
-      requisition.height += 2 * sheet->button->style->ythickness;
-    }
-  else
-    {
-      requisition.height = DEFAULT_ROW_HEIGHT (GTK_WIDGET (sheet));
-      requisition.width = COLUMN_MIN_WIDTH;
-    }
 
   *button_requisition = requisition;
   button_requisition->width = MAX (requisition.width, label_requisition.width);
@@ -7457,31 +5284,14 @@ gtk_sheet_row_size_request (GtkSheet *sheet,
                            guint *requisition)
 {
   GtkRequisition button_requisition;
-  GList *children;
 
   gtk_sheet_button_size_request (sheet,
-                                yyy_row_button (sheet, row),
+                                g_sheet_model_get_row_button (sheet->model, row),
                                 &button_requisition);
 
   *requisition = button_requisition.height;
 
-  children = sheet->children;
-  while (children)
-    {
-      GtkSheetChild *child = (GtkSheetChild *)children->data;
-      GtkRequisition child_requisition;
-
-      if (child->attached_to_cell && child->row == row && child->col != -1 && !child->floating && !child->yshrink)
-       {
-         gtk_widget_get_child_requisition (child->widget, &child_requisition);
-
-         if (child_requisition.height + 2 * child->ypadding > *requisition)
-           *requisition = child_requisition.height + 2 * child->ypadding;
-       }
-      children = children->next;
-    }
-
-  sheet->row_requisition = * requisition;
+  sheet->row_requisition = *requisition;
 }
 
 static void
@@ -7490,8 +5300,8 @@ gtk_sheet_column_size_request (GtkSheet *sheet,
                               guint *requisition)
 {
   GtkRequisition button_requisition;
-  GList *children;
-  GtkSheetButton *button = xxx_column_button (sheet, col);
+
+  GtkSheetButton *button = g_sheet_model_get_column_button (sheet->model, col);
 
   gtk_sheet_button_size_request (sheet,
                                 button,
@@ -7501,157 +5311,9 @@ gtk_sheet_column_size_request (GtkSheet *sheet,
 
   *requisition = button_requisition.width;
 
-  children = sheet->children;
-  while (children)
-    {
-      GtkSheetChild *child = (GtkSheetChild *)children->data;
-      GtkRequisition child_requisition;
-
-      if (child->attached_to_cell && child->col == col && child->row != -1 && !child->floating && !child->xshrink)
-       {
-         gtk_widget_get_child_requisition (child->widget, &child_requisition);
-
-         if (child_requisition.width + 2 * child->xpadding > *requisition)
-           *requisition = child_requisition.width + 2 * child->xpadding;
-       }
-      children = children->next;
-    }
-
   sheet->column_requisition = *requisition;
 }
 
-void
-gtk_sheet_move_child (GtkSheet *sheet, GtkWidget *widget, gint x, gint y)
-{
-  GtkSheetChild *child;
-  GList *children;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  children = sheet->children;
-  while (children)
-    {
-      child = children->data;
-
-      if (child->widget == widget)
-       {
-         child->x = x;
-         child->y = y;
-         child->row = ROW_FROM_YPIXEL (sheet, y);
-         child->col = COLUMN_FROM_XPIXEL (sheet, x);
-         gtk_sheet_position_child (sheet, child);
-         return;
-       }
-
-      children = children->next;
-    }
-
-  g_warning ("Widget must be a GtkSheet child");
-
-}
-
-static void
-gtk_sheet_position_child (GtkSheet *sheet, GtkSheetChild *child)
-{
-  GtkRequisition child_requisition;
-  GtkAllocation child_allocation;
-  gint xoffset = 0;
-  gint yoffset = 0;
-  gint x = 0, y = 0;
-  GdkRectangle area;
-
-  gtk_widget_get_child_requisition (child->widget, &child_requisition);
-
-  if (sheet->column_titles_visible)
-    yoffset = sheet->column_title_area.height;
-
-  if (sheet->row_titles_visible)
-    xoffset = sheet->row_title_area.width;
-
-  if (child->attached_to_cell)
-    {
-      gtk_sheet_get_cell_area (sheet, child->row, child->col, &area);
-      child->x = area.x + child->xpadding;
-      child->y = area.y + child->ypadding;
-
-      if (!child->floating)
-       {
-         if (child_requisition.width + 2 * child->xpadding <= xxx_column_width (sheet, child->col))
-           {
-             if (child->xfill)
-               {
-                 child_requisition.width = child_allocation.width = xxx_column_width (sheet, child->col) - 2 * child->xpadding;
-               }
-             else
-               {
-                 if (child->xexpand)
-                   {
-                     child->x = area.x + xxx_column_width (sheet, child->col) / 2 -
-                       child_requisition.width / 2;
-                   }
-                 child_allocation.width = child_requisition.width;
-               }
-           }
-         else
-           {
-             if (!child->xshrink)
-               {
-                 gtk_sheet_set_column_width (sheet, child->col, child_requisition.width + 2 * child->xpadding);
-               }
-             child_allocation.width = xxx_column_width (sheet, child->col) - 2 * child->xpadding;
-           }
-
-         if (child_requisition.height +
-             2 * child->ypadding <= yyy_row_height (sheet, child->row))
-           {
-             if (child->yfill)
-               {
-                 child_requisition.height = child_allocation.height =
-                   yyy_row_height (sheet, child->row) - 2 * child->ypadding;
-               }
-             else
-               {
-                 if (child->yexpand)
-                   {
-                     child->y = area.y + yyy_row_height (sheet, child->row) / 2
-                       - child_requisition.height / 2;
-                   }
-                 child_allocation.height = child_requisition.height;
-               }
-           }
-         else
-           {
-             if (!child->yshrink)
-               {
-                 gtk_sheet_set_row_height (sheet, child->row, child_requisition.height + 2 * child->ypadding);
-               }
-             child_allocation.height = yyy_row_height (sheet, child->row) -
-               2 * child->ypadding;
-           }
-       }
-      else
-       {
-         child_allocation.width = child_requisition.width;
-         child_allocation.height = child_requisition.height;
-       }
-
-      x = child_allocation.x = child->x + xoffset;
-      y = child_allocation.y = child->y + yoffset;
-    }
-  else
-    {
-      x = child_allocation.x = child->x + sheet->hoffset + xoffset;
-      x = child_allocation.x = child->x + xoffset;
-      y = child_allocation.y = child->y + sheet->voffset + yoffset;
-      y = child_allocation.y = child->y + yoffset;
-      child_allocation.width = child_requisition.width;
-      child_allocation.height = child_requisition.height;
-    }
-
-  gtk_widget_size_allocate (child->widget, &child_allocation);
-  gtk_widget_queue_draw (child->widget);
-}
 
 static void
 gtk_sheet_forall (GtkContainer *container,
@@ -7659,165 +5321,17 @@ gtk_sheet_forall (GtkContainer *container,
                  GtkCallback callback,
                  gpointer callback_data)
 {
-  GtkSheet *sheet;
-  GtkSheetChild *child;
-  GList *children;
+  GtkSheet *sheet = GTK_SHEET (container);
 
-  g_return_if_fail (GTK_IS_SHEET (container));
   g_return_if_fail (callback != NULL);
 
-  sheet = GTK_SHEET (container);
-  children = sheet->children;
-  while (children)
-    {
-      child = children->data;
-      children = children->next;
-
-      (* callback) (child->widget, callback_data);
-    }
-
   if (sheet->button && sheet->button->parent)
     (* callback) (sheet->button, callback_data);
 
-  if (sheet->entry_container && GTK_IS_CONTAINER (sheet->entry_container))
-    (* callback) (sheet->entry_container, callback_data);
-}
-
-
-static void
-gtk_sheet_position_children (GtkSheet *sheet)
-{
-  GList *children;
-  GtkSheetChild *child;
-
-  children = sheet->children;
-
-  while (children)
-    {
-      child = (GtkSheetChild *)children->data;
-
-      if (child->col != -1 && child->row != -1)
-       gtk_sheet_position_child (sheet, child);
-
-      if (child->row == -1)
-       {
-         if (child->col < MIN_VISIBLE_COLUMN (sheet) ||
-             child->col > MAX_VISIBLE_COLUMN (sheet))
-           gtk_sheet_child_hide (child);
-         else
-           gtk_sheet_child_show (child);
-       }
-      if (child->col == -1)
-       {
-         if (child->row < MIN_VISIBLE_ROW (sheet) ||
-             child->row > MAX_VISIBLE_ROW (sheet))
-           gtk_sheet_child_hide (child);
-         else
-           gtk_sheet_child_show (child);
-       }
-
-      children = children->next;
-    }
-}
-
-static void
-gtk_sheet_remove (GtkContainer *container, GtkWidget *widget)
-{
-  GtkSheet *sheet;
-  GList *children;
-  GtkSheetChild *child = 0;
-
-  g_return_if_fail (container != NULL);
-  g_return_if_fail (GTK_IS_SHEET (container));
-
-  sheet = GTK_SHEET (container);
-
-  children = sheet->children;
-
-  while (children)
-    {
-      child = (GtkSheetChild *)children->data;
-
-      if (child->widget == widget) break;
-
-      children = children->next;
-    }
-
-  if (children)
-    {
-      gtk_widget_unparent (widget);
-      child->widget = NULL;
-
-      sheet->children = g_list_remove_link (sheet->children, children);
-      g_list_free_1 (children);
-      g_free (child);
-    }
-
-  gtk_widget_unparent (sheet->button);
-}
-
-static void
-gtk_sheet_realize_child (GtkSheet *sheet, GtkSheetChild *child)
-{
-  GtkWidget *widget;
-
-  widget = GTK_WIDGET (sheet);
-
-  if (GTK_WIDGET_REALIZED (widget))
-    {
-      if (child->row == -1)
-       gtk_widget_set_parent_window (child->widget, sheet->column_title_window);
-      else if (child->col == -1)
-       gtk_widget_set_parent_window (child->widget, sheet->row_title_window);
-      else
-       gtk_widget_set_parent_window (child->widget, sheet->sheet_window);
-    }
-
-  gtk_widget_set_parent (child->widget, widget);
-}
-
-
-
-GtkSheetChild *
-gtk_sheet_get_child_at (GtkSheet *sheet, gint row, gint col)
-{
-  GList *children;
-  GtkSheetChild *child = 0;
-
-  g_return_val_if_fail (sheet != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
-
-  children = sheet->children;
-
-  while (children)
-    {
-      child = (GtkSheetChild *)children->data;
-
-      if (child->attached_to_cell)
-       if (child->row == row && child->col == col) break;
-
-      children = children->next;
-    }
-
-  if (children) return child;
-
-  return NULL;
-}
-
-static void
-gtk_sheet_child_hide (GtkSheetChild *child)
-{
-  g_return_if_fail (child != NULL);
-  gtk_widget_hide (child->widget);
+  if (sheet->entry_widget && GTK_IS_CONTAINER (sheet->entry_widget))
+    (* callback) (sheet->entry_widget, callback_data);
 }
 
-static void
-gtk_sheet_child_show (GtkSheetChild *child)
-{
-  g_return_if_fail (child != NULL);
-
-  gtk_widget_show (child->widget);
-}
 
 GSheetModel *
 gtk_sheet_get_model (const GtkSheet *sheet)
@@ -7836,7 +5350,6 @@ gtk_sheet_button_new (void)
   button->state = GTK_STATE_NORMAL;
   button->label = NULL;
   button->label_visible = TRUE;
-  button->child = NULL;
   button->justification = GTK_JUSTIFY_FILL;
 
   return button;
@@ -7852,7 +5365,6 @@ gtk_sheet_button_free (GtkSheetButton *button)
   g_free (button);
 }
 
-
 static void
 append_cell_text (GString *string, const GtkSheet *sheet, gint r, gint c)
 {
@@ -7865,13 +5377,14 @@ append_cell_text (GString *string, const GtkSheet *sheet, gint r, gint c)
   g_free (celltext);
 }
 
+
 static GString *
 range_to_text (const GtkSheet *sheet)
 {
   gint r, c;
   GString *string;
 
-  if ( !gtk_sheet_range_isvisible (sheet, sheet->range))
+  if ( !gtk_sheet_range_isvisible (sheet, &sheet->range))
     return NULL;
 
   string = g_string_sized_new (80);
@@ -7897,7 +5410,7 @@ range_to_html (const GtkSheet *sheet)
   gint r, c;
   GString *string;
 
-  if ( !gtk_sheet_range_isvisible (sheet, sheet->range))
+  if ( !gtk_sheet_range_isvisible (sheet, &sheet->range))
     return NULL;
 
   string = g_string_sized_new (480);
@@ -7988,7 +5501,7 @@ gtk_sheet_update_primary_selection (GtkSheet *sheet)
   clipboard = gtk_widget_get_clipboard (GTK_WIDGET (sheet),
                                        GDK_SELECTION_PRIMARY);
 
-  if (gtk_sheet_range_isvisible (sheet, sheet->range))
+  if (gtk_sheet_range_isvisible (sheet, &sheet->range))
     {
       if (!gtk_clipboard_set_with_owner (clipboard, targets,
                                         G_N_ELEMENTS (targets),
@@ -8002,4 +5515,3 @@ gtk_sheet_update_primary_selection (GtkSheet *sheet)
        gtk_clipboard_clear (clipboard);
     }
 }
-
index 4f402252aabfd8473a2d5d31be3f1967ca46ce7e..92c4248eff1c6fb42f6974db8103e6a30aa32a86 100644 (file)
 
 #include "gtkextra-sheet.h"
 #include "gsheetmodel.h"
-#include "gsheet-column-iface.h"
-#include "gsheet-row-iface.h"
+#include "psppire-axis.h"
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-typedef enum
-{
-  GTK_SHEET_FOREGROUND,
-  GTK_SHEET_BACKGROUND,
-  GTK_SHEET_FONT,
-  GTK_SHEET_JUSTIFICATION,
-  GTK_SHEET_BORDER,
-  GTK_SHEET_BORDER_COLOR,
-  GTK_SHEET_IS_EDITABLE,
-  GTK_SHEET_IS_VISIBLE
-} GtkSheetAttrType;
+G_BEGIN_DECLS
 
 /* sheet->state */
-
 enum
 {
   GTK_SHEET_NORMAL,
@@ -63,44 +45,27 @@ enum
 
 
 #define GTK_TYPE_SHEET_RANGE (gtk_sheet_range_get_type ())
+#define GTK_TYPE_SHEET_CELL (gtk_sheet_cell_get_type ())
 #define GTK_TYPE_SHEET (gtk_sheet_get_type ())
 
 #define GTK_SHEET(obj)          GTK_CHECK_CAST (obj, gtk_sheet_get_type (), GtkSheet)
 #define GTK_SHEET_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_sheet_get_type (), GtkSheetClass)
 #define GTK_IS_SHEET(obj)       GTK_CHECK_TYPE (obj, gtk_sheet_get_type ())
 
-/* Public flags, for compatibility */
-
-#define GTK_SHEET_ROW_FROZEN(sheet)      !gtk_sheet_rows_resizable (sheet)
-#define GTK_SHEET_COLUMN_FROZEN(sheet)   !gtk_sheet_columns_resizable (sheet)
-#define GTK_SHEET_AUTORESIZE(sheet)      gtk_sheet_autoresize (sheet)
-#define GTK_SHEET_ROW_TITLES_VISIBLE(sheet)   gtk_sheet_row_titles_visible (sheet)
-#define GTK_SHEET_COL_TITLES_VISIBLE(sheet)   gtk_sheet_column_titles_visible (sheet)
-#define GTK_SHEET_AUTO_SCROLL(sheet)     gtk_sheet_autoscroll (sheet)
-#define GTK_SHEET_JUSTIFY_ENTRY(sheet)   gtk_sheet_justify_entry (sheet)
-
 
 typedef struct _GtkSheetClass GtkSheetClass;
 typedef struct _GtkSheetCellAttr     GtkSheetCellAttr;
-typedef struct _GtkSheetCell GtkSheetCell;
+
 typedef struct _GtkSheetHoverTitle GtkSheetHoverTitle;
 
 
 struct _GtkSheetCellAttr
 {
   GtkJustification justification;
-  const PangoFontDescription *font_desc;
   GdkColor foreground;
   GdkColor background;
   GtkSheetCellBorder border;
   gboolean is_editable;
-  gboolean is_visible;
-};
-
-struct _GtkSheetCell
-{
-  gint row;
-  gint col;
 };
 
 struct _GtkSheetHoverTitle
@@ -110,36 +75,31 @@ struct _GtkSheetHoverTitle
   gint row, column;
 };
 
+enum
+  {
+    BG_COLOR,
+    GRID_COLOR,
+    n_COLORS
+  };
+
 struct _GtkSheet
 {
-  GtkContainer container;
-
+  GtkBin parent;
 
   gboolean dispose_has_run;
-  GSheetColumn *column_geometry;
-  GSheetRow *row_geometry;
+  PsppireAxis *haxis;
+  PsppireAxis *vaxis;
 
   guint16 flags;
 
   GSheetModel *model;
 
   GtkSelectionMode selection_mode;
-  gboolean autoresize;
-  gboolean autoscroll;
-  gboolean justify_entry;
 
-  /* Background colors */
-  GdkColor bg_color;
-  GdkColor grid_color;
+  /* Component colors */
+  GdkColor color[n_COLORS];
   gboolean show_grid;
 
-  /* sheet children */
-  GList *children;
-
-  /* allocation rectangle after the container_border_width
-     and the width of the shadow border */
-  GdkRectangle internal_allocation;
-
   gint16 column_requisition;
   gint16 row_requisition;
 
@@ -152,13 +112,12 @@ struct _GtkSheet
   /* The GtkEntry used for editing the cells */
   GtkWidget *entry_widget;
 
-  /* The widget containing entry_widget, or
-     entry_widget itself if no container */
-  GtkWidget *entry_container;
-
   /* The type of entry_widget */
   GtkType entry_type;
 
+  /* Handler of the "changed" callback for the entry widget */
+  glong entry_handler_id;
+
   /* expanding selection */
   GtkSheetCell selection_cell;
 
@@ -171,20 +130,9 @@ struct _GtkSheet
   /* selected range */
   GtkSheetRange range;
 
-  /*the scrolling window and it's height and width to
+  /* the scrolling window and its height and width to
    * make things a little speedier */
   GdkWindow *sheet_window;
-  guint sheet_window_width;
-  guint sheet_window_height;
-
-  /* sheet backing pixmap */
-  GdkPixmap *pixmap;
-
-  /* offsets for scrolling */
-  gint hoffset;
-  gint voffset;
-  gfloat old_hadjustment;
-  gfloat old_vadjustment;
 
   /* border shadow style */
   GtkShadowType shadow_type;
@@ -193,18 +141,20 @@ struct _GtkSheet
   GdkRectangle column_title_area;
   GdkWindow *column_title_window;
   gboolean column_titles_visible;
+  /* TRUE if the cursor is over the column title window */
+  gboolean column_title_under;
 
   /* Row Titles */
   GdkRectangle row_title_area;
   GdkWindow *row_title_window;
   gboolean row_titles_visible;
+  /* TRUE if the cursor is over the row title window */
+  gboolean row_title_under;
 
   /*scrollbars*/
   GtkAdjustment *hadjustment;
   GtkAdjustment *vadjustment;
 
-  gint freeze_count;
-
   /* xor GC for the verticle drag line */
   GdkGC *xor_gc;
 
@@ -233,7 +183,7 @@ struct _GtkSheet
 
 struct _GtkSheetClass
 {
GtkContainerClass parent_class;
 GtkBinClass parent_class;
 
  void (*set_scroll_adjustments) (GtkSheet *sheet,
                                 GtkAdjustment *hadjustment,
@@ -257,9 +207,6 @@ struct _GtkSheetClass
                                gint row, gint column,
                                gint *new_row, gint *new_column);
 
- gboolean (*deactivate)                (GtkSheet *sheet,
-                               gint row, gint column);
-
  gboolean (*activate)          (GtkSheet *sheet,
                                gint row, gint column);
 
@@ -272,151 +219,25 @@ GtkType gtk_sheet_range_get_type (void);
 
 
 /* create a new sheet */
-GtkWidget * gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo,
-                          GSheetModel *model);
-
-
-
-
-/* create a new browser sheet. It cells can not be edited */
-GtkWidget *
-gtk_sheet_new_browser                  (guint rows, guint columns, const gchar *title);
-
-void
-gtk_sheet_construct_browser            (GtkSheet *sheet,
-                                                guint rows, guint columns, const gchar *title);
+GtkWidget * gtk_sheet_new (GSheetModel *model);
 
 /* create a new sheet with custom entry */
 GtkWidget *
-gtk_sheet_new_with_custom_entry        (GSheetRow *vgeo,
-                                        GSheetColumn *hgeo,
-                                        GtkType entry_type);
-void
-gtk_sheet_construct_with_custom_entry  (GtkSheet *sheet,
-                                        GSheetRow *vgeo,
-                                        GSheetColumn *hgeo,
-                                        GtkType entry_type);
-/* change scroll adjustments */
-void
-gtk_sheet_set_hadjustment              (GtkSheet *sheet,
-                                        GtkAdjustment *adjustment);
-void
-gtk_sheet_set_vadjustment              (GtkSheet *sheet,
-                                        GtkAdjustment *adjustment);
-/* Change entry */
-void
-gtk_sheet_change_entry                 (GtkSheet *sheet, GtkType entry_type);
-
-/* Returns sheet's entry widget */
-GtkWidget *
-gtk_sheet_get_entry                    (GtkSheet *sheet);
-GtkWidget *
-gtk_sheet_get_entry_widget             (GtkSheet *sheet);
-
-/* Returns sheet->state
- * Added by Steven Rostedt <steven.rostedt@lmco.com> */
-gint
-gtk_sheet_get_state                    (GtkSheet *sheet);
+gtk_sheet_new_with_custom_entry (GtkType entry_type);
 
-/* Returns sheet's ranges
- * Added by Murray Cumming */
-guint
-gtk_sheet_get_columns_count            (GtkSheet *sheet);
+/* Change entry */
+void gtk_sheet_change_entry            (GtkSheet *sheet, GtkType entry_type);
 
-guint
-gtk_sheet_get_rows_count               (GtkSheet *sheet);
+GtkEntry *gtk_sheet_get_entry    (GtkSheet *sheet);
 
-void
-gtk_sheet_get_visible_range            (GtkSheet *sheet,
-                                        GtkSheetRange *range);
 
-void
-gtk_sheet_get_selected_range           (GtkSheet *sheet,
+void gtk_sheet_get_selected_range (GtkSheet *sheet,
                                         GtkSheetRange *range);
 
-void
-gtk_sheet_set_selection_mode           (GtkSheet *sheet, gint mode);
-
-void
-gtk_sheet_set_autoresize               (GtkSheet *sheet, gboolean autoresize);
-
-gboolean
-gtk_sheet_autoresize                   (GtkSheet *sheet);
-
-void
-gtk_sheet_set_autoscroll               (GtkSheet *sheet, gboolean autoscroll);
-
-gboolean
-gtk_sheet_autoscroll                   (GtkSheet *sheet);
-
-void
-gtk_sheet_set_justify_entry            (GtkSheet *sheet, gboolean justify);
-
-gboolean
-gtk_sheet_justify_entry                        (GtkSheet *sheet);
-
-void
-gtk_sheet_set_locked                   (GtkSheet *sheet, gboolean lock);
-
-gboolean
-gtk_sheet_locked                       (const GtkSheet *sheet);
-
-/* set sheet title */
-void
-gtk_sheet_set_title                    (GtkSheet *sheet, const gchar *title);
-
-/* freeze all visual updates of the sheet.
- * Then thaw the sheet after you have made a number of changes.
- * The updates will occure in a more efficent way than if
- * you made them on a unfrozen sheet */
-void
-gtk_sheet_freeze                       (GtkSheet *sheet);
-void
-gtk_sheet_thaw                         (GtkSheet *sheet);
-/* Background colors */
-void
-gtk_sheet_set_background               (GtkSheet *sheet,
-                                        GdkColor *bg_color);
-void
-gtk_sheet_set_grid                     (GtkSheet *sheet,
-                                        GdkColor *grid_color);
-void
-gtk_sheet_show_grid                    (GtkSheet *sheet,
+void gtk_sheet_show_grid         (GtkSheet *sheet,
                                         gboolean show);
-gboolean
-gtk_sheet_grid_visible                 (GtkSheet *sheet);
-
-/* set/get column title */
-void
-gtk_sheet_set_column_title             (GtkSheet * sheet,
-                                       gint column,
-                                       const gchar * title);
-
-const gchar *
-gtk_sheet_get_column_title             (GtkSheet * sheet,
-                                       gint column);
-
-/* set/get row title */
-void
-gtk_sheet_set_row_title                (GtkSheet * sheet,
-                                       gint row,
-                                       const gchar * title);
-const gchar *
-gtk_sheet_get_row_title                (GtkSheet * sheet,
-                                       gint row);
-
-
-/* set/get button label */
-void
-gtk_sheet_row_button_add_label         (GtkSheet *sheet,
-                                       gint row, const gchar *label);
-const gchar *
-gtk_sheet_row_button_get_label         (GtkSheet *sheet,
-                                       gint row);
-void
-gtk_sheet_row_button_justify           (GtkSheet *sheet,
-                                       gint row, GtkJustification justification);
 
+gboolean gtk_sheet_grid_visible   (GtkSheet *sheet);
 
 
 /* scroll the viewing area of the sheet to the given column
@@ -424,269 +245,62 @@ gtk_sheet_row_button_justify             (GtkSheet *sheet,
  * location the row should appear on the screen, 0.0 being top or left,
  * 1.0 being bottom or right; if row or column is negative then there
  * is no change */
-void
-gtk_sheet_moveto (GtkSheet *sheet,
+void gtk_sheet_moveto (GtkSheet *sheet,
                  gint row,
                  gint column,
                  gfloat row_align,
                   gfloat col_align);
 
 
-void
-gtk_sheet_show_row_titles              (GtkSheet *sheet);
-void
-gtk_sheet_hide_row_titles              (GtkSheet *sheet);
-void
-gtk_sheet_show_column_titles           (GtkSheet *sheet);
-void
-gtk_sheet_hide_column_titles           (GtkSheet *sheet);
-
-gboolean
-gtk_sheet_row_titles_visible           (GtkSheet *sheet);
-
-
-/* set row button sensitivity. If sensitivity is TRUE can be toggled,
- * otherwise it acts as a title */
-void
-gtk_sheet_row_set_sensitivity          (GtkSheet *sheet,
-                                       gint row,  gboolean sensitive);
-
-/* set sensitivity for all row buttons */
-void
-gtk_sheet_rows_set_sensitivity         (GtkSheet *sheet, gboolean sensitive);
-void
-gtk_sheet_rows_set_resizable           (GtkSheet *sheet, gboolean resizable);
-gboolean
-gtk_sheet_rows_resizable               (GtkSheet *sheet);
-
-/* set row visibility. The default value is TRUE. If FALSE, the
- * row is hidden */
-void
-gtk_sheet_row_set_visibility           (GtkSheet *sheet,
-                                        gint row, gboolean visible);
-void
-gtk_sheet_row_label_set_visibility     (GtkSheet *sheet,
-                                        gint row, gboolean visible);
-void
-gtk_sheet_rows_labels_set_visibility   (GtkSheet *sheet, gboolean visible);
-
+void gtk_sheet_show_row_titles         (GtkSheet *sheet);
+void gtk_sheet_hide_row_titles         (GtkSheet *sheet);
+void gtk_sheet_show_column_titles       (GtkSheet *sheet);
+void gtk_sheet_hide_column_titles      (GtkSheet *sheet);
 
 /* select the row. The range is then highlighted, and the bounds are stored
  * in sheet->range  */
-void
-gtk_sheet_select_row                   (GtkSheet * sheet,
-                                       gint row);
+void gtk_sheet_select_row    (GtkSheet * sheet,  gint row);
 
 /* select the column. The range is then highlighted, and the bounds are stored
  * in sheet->range  */
-void
-gtk_sheet_select_column                (GtkSheet * sheet,
-                                       gint column);
-
-/* get scrollbars adjustment */
-GtkAdjustment *
-gtk_sheet_get_vadjustment              (GtkSheet * sheet);
-GtkAdjustment *
-gtk_sheet_get_hadjustment              (GtkSheet * sheet);
+void gtk_sheet_select_column (GtkSheet * sheet,  gint column);
 
 /* highlight the selected range and store bounds in sheet->range */
-void gtk_sheet_select_range            (GtkSheet *sheet,
-                                        const GtkSheetRange *range);
+void gtk_sheet_select_range (GtkSheet *sheet, const GtkSheetRange *range);
+
+void gtk_sheet_get_visible_range (GtkSheet *sheet, GtkSheetRange *range);
+
 
 /* obvious */
 void gtk_sheet_unselect_range          (GtkSheet *sheet);
 
-/* set active cell where the entry will be displayed
- * returns FALSE if current cell can't be deactivated or
- * requested cell can't be activated */
-gboolean
-gtk_sheet_set_active_cell              (GtkSheet *sheet,
-                                       gint row, gint column);
+/* set active cell where the entry will be displayed */
+void gtk_sheet_set_active_cell (GtkSheet *sheet,
+                               gint row, gint column);
 
 /* Sets *ROW and *COLUMN to be the coordinates of the active cell.
    ROW and/or COLUMN may be null if the caller is not interested in their
    values */
-void
-gtk_sheet_get_active_cell              (GtkSheet *sheet,
+void gtk_sheet_get_active_cell (GtkSheet *sheet,
                                        gint *row, gint *column);
 
-/* set cell contents and allocate memory if needed */
-void
-gtk_sheet_set_cell                     (GtkSheet *sheet,
-                                       gint row, gint col,
-                                        GtkJustification justification,
-                                       const gchar *text);
-void
-gtk_sheet_set_cell_text                        (GtkSheet *sheet,
-                                       gint row, gint col,
-                                       const gchar *text);
 /* get cell contents */
-gchar *
-gtk_sheet_cell_get_text                (const GtkSheet *sheet, gint row, gint col);
-
-/* clear cell contents */
-void
-gtk_sheet_cell_clear                   (GtkSheet *sheet, gint row, gint col);
-
-/* clear range contents. If range==NULL the whole sheet will be cleared */
-void
-gtk_sheet_range_clear                  (GtkSheet *sheet,
-                                        const GtkSheetRange *range);
-
-/* get cell state: GTK_STATE_NORMAL, GTK_STATE_SELECTED */
-GtkStateType
-gtk_sheet_cell_get_state               (GtkSheet *sheet, gint row, gint col);
-
-/* get row and column correspondig to the given position in the screen */
-gboolean
-gtk_sheet_get_pixel_info (GtkSheet * sheet,
-                         gint x,
-                         gint y,
-                         gint * row,
-                         gint * column);
-
-/* get area of a given cell */
-gboolean
-gtk_sheet_get_cell_area (GtkSheet *sheet,
-                         gint row,
-                         gint column,
-                         GdkRectangle *area);
-
-/* set row height */
-void
-gtk_sheet_set_row_height (GtkSheet * sheet,
-                         gint row,
-                         guint height);
-
-
-/* delete nrows rows starting in row */
-void
-gtk_sheet_delete_rows                  (GtkSheet *sheet, guint row, guint nrows);
-
-/* append nrows row to the end of the sheet */
-void
-gtk_sheet_add_row                      (GtkSheet *sheet, guint nrows);
-
-/* insert nrows rows before the given row and pull right */
-void
-gtk_sheet_insert_rows                  (GtkSheet *sheet, guint row, guint nrows);
-
-/* set abckground color of the given range */
-void
-gtk_sheet_range_set_background         (GtkSheet *sheet,
-                                       const GtkSheetRange *range,
-                                       const GdkColor *color);
-
-/* set foreground color (text color) of the given range */
-void
-gtk_sheet_range_set_foreground         (GtkSheet *sheet,
-                                       const GtkSheetRange *range,
-                                       const GdkColor *color);
-
-/* set text justification (GTK_JUSTIFY_LEFT, RIGHT, CENTER) of the given range.
- * The default value is GTK_JUSTIFY_LEFT. If autoformat is on, the
- * default justification for numbers is GTK_JUSTIFY_RIGHT */
-void
-gtk_sheet_range_set_justification      (GtkSheet *sheet,
-                                       const GtkSheetRange *range,
-                                       GtkJustification justification);
-void
-gtk_sheet_column_set_justification      (GtkSheet *sheet,
-                                        gint column,
-                                        GtkJustification justification);
-/* set if cell contents can be edited or not in the given range:
- * accepted values are TRUE or FALSE. */
-void
-gtk_sheet_range_set_editable           (GtkSheet *sheet,
-                                       const GtkSheetRange *range,
-                                       gint editable);
-
-/* set if cell contents are visible or not in the given range:
- * accepted values are TRUE or FALSE.*/
-void
-gtk_sheet_range_set_visible            (GtkSheet *sheet,
-                                       const GtkSheetRange *range,
-                                       gboolean visible);
-
-/* set cell border style in the given range.
- * mask values are CELL_LEFT_BORDER, CELL_RIGHT_BORDER, CELL_TOP_BORDER,
- * CELL_BOTTOM_BORDER
- * width is the width of the border line in pixels
- * line_style is the line_style for the border line */
-void
-gtk_sheet_range_set_border             (GtkSheet *sheet,
-                                       const GtkSheetRange *range,
-                                       gint mask,
-                                       guint width,
-                                       gint line_style);
-
-/* set border color for the given range */
-void
-gtk_sheet_range_set_border_color       (GtkSheet *sheet,
-                                       const GtkSheetRange *range,
-                                       const GdkColor *color);
-
-/* set font for the given range */
-void
-gtk_sheet_range_set_font               (GtkSheet *sheet,
-                                       const GtkSheetRange *range,
-                                       PangoFontDescription *font);
+gchar *gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col);
+
 
 /* get cell attributes of the given cell */
 /* TRUE means that the cell is currently allocated */
-gboolean
-gtk_sheet_get_attributes               (const GtkSheet *sheet,
+gboolean gtk_sheet_get_attributes       (const GtkSheet *sheet,
                                        gint row, gint col,
                                        GtkSheetCellAttr *attributes);
 
-
-GtkSheetChild *
-gtk_sheet_put                          (GtkSheet *sheet,
-                                        GtkWidget *widget,
-                                        gint x, gint y);
-void
-gtk_sheet_attach_floating               (GtkSheet *sheet,
-                                         GtkWidget *widget,
-                                         gint row, gint col);
-void
-gtk_sheet_attach_default                (GtkSheet *sheet,
-                                         GtkWidget *widget,
-                                         gint row, gint col);
-void
-gtk_sheet_attach                        (GtkSheet *sheet,
-                                         GtkWidget *widget,
-                                         gint row, gint col,
-                                         gint xoptions,
-                                         gint yoptions,
-                                         gint xpadding,
-                                         gint ypadding);
-
-
-void
-gtk_sheet_move_child                   (GtkSheet *sheet,
-                                        GtkWidget *widget,
-                                        gint x, gint y);
-
-GtkSheetChild *
-gtk_sheet_get_child_at                 (GtkSheet *sheet,
-                                        gint row, gint col);
-
-void
-gtk_sheet_button_attach                        (GtkSheet *sheet,
-                                        GtkWidget *widget,
-                                        gint row, gint col);
-
-
-
-void           gtk_sheet_set_model (GtkSheet *sheet,
+void gtk_sheet_set_model (GtkSheet *sheet,
                                   GSheetModel *model);
 
 GSheetModel * gtk_sheet_get_model (const GtkSheet *sheet);
 
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_END_DECLS
 
 
 #endif /* __GTK_SHEET_H__ */
diff --git a/lib/gtksheet/gtkxpaned.c b/lib/gtksheet/gtkxpaned.c
new file mode 100644 (file)
index 0000000..93bbc23
--- /dev/null
@@ -0,0 +1,3260 @@
+/*******************************************************************************
+**3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 
+**      10        20        30        40        50        60        70        80
+**
+**  library for GtkXPaned-widget, a 2x2 grid-like variation of GtkPaned of gtk+
+**  Copyright (C) 2005-2006 Mirco "MacSlow" Müller <macslow@bangang.de>
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+**
+**  GtkXPaned is based on GtkPaned which was done by...
+**
+**  "Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald"
+**
+**  and later modified by...
+**
+**  "the GTK+ Team and others 1997-2000"
+**
+*******************************************************************************/
+
+#include "gtkxpaned.h"
+#include <gtksheet/psppire-marshal.h>
+#include <gtk/gtkbindings.h>
+#include <gtk/gtksignal.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtkmain.h>
+
+enum WidgetProperties
+{
+       PROP_0,
+       PROP_X_POSITION,
+       PROP_Y_POSITION,
+       PROP_POSITION_SET,
+       PROP_MIN_X_POSITION,
+       PROP_MIN_Y_POSITION,
+       PROP_MAX_X_POSITION,
+       PROP_MAX_Y_POSITION
+};
+
+enum ChildProperties
+{
+       CHILD_PROP_0,
+       CHILD_PROP_RESIZE,
+       CHILD_PROP_SHRINK
+};
+
+enum WidgetSignals
+{
+       CYCLE_CHILD_FOCUS,
+       TOGGLE_HANDLE_FOCUS,
+       MOVE_HANDLE,
+       CYCLE_HANDLE_FOCUS,
+       ACCEPT_POSITION,
+       CANCEL_POSITION,
+       LAST_SIGNAL
+};
+
+static void gtk_xpaned_class_init (GtkXPanedClass* klass);
+
+static void gtk_xpaned_init (GtkXPaned* xpaned);
+
+static void gtk_xpaned_size_request (GtkWidget* widget,
+                                                                        GtkRequisition* requisition);
+
+static void gtk_xpaned_size_allocate (GtkWidget* widget,
+                                                                         GtkAllocation* allocation);
+
+static void gtk_xpaned_set_property (GObject* object,
+                                                                        guint prop_id,
+                                                                        const GValue* value,
+                                                                        GParamSpec* pspec);
+
+static void gtk_xpaned_get_property (GObject* object,
+                                                                        guint prop_id,
+                                                                        GValue* value,
+                                                                        GParamSpec* pspec);
+
+static void gtk_xpaned_set_child_property (GtkContainer* container,
+                                                                                  GtkWidget* child,
+                                                                                  guint property_id,
+                                                                                  const GValue* value,
+                                                                                  GParamSpec* pspec);
+
+static void gtk_xpaned_get_child_property (GtkContainer* container,
+                                                                                  GtkWidget* child,
+                                                                                  guint property_id,
+                                                                                  GValue* value,
+                                                                                  GParamSpec* pspec);
+
+static void gtk_xpaned_finalize (GObject* object);
+
+static void gtk_xpaned_realize (GtkWidget* widget);
+
+static void gtk_xpaned_unrealize (GtkWidget* widget);
+
+static void gtk_xpaned_map (GtkWidget* widget);
+
+static void gtk_xpaned_unmap (GtkWidget* widget);
+
+static gboolean gtk_xpaned_expose (GtkWidget* widget, GdkEventExpose* event);
+
+static gboolean gtk_xpaned_enter (GtkWidget* widget, GdkEventCrossing* event);
+
+static gboolean gtk_xpaned_leave (GtkWidget* widget, GdkEventCrossing* event);
+
+static gboolean gtk_xpaned_button_press (GtkWidget* widget,
+                                                                                GdkEventButton* event);
+
+static gboolean gtk_xpaned_button_release (GtkWidget* widget,
+                                                                                  GdkEventButton* event);
+
+static gboolean gtk_xpaned_motion (GtkWidget* widget, GdkEventMotion* event);
+
+static gboolean gtk_xpaned_focus (GtkWidget* widget,
+                                                                 GtkDirectionType direction);
+
+static void gtk_xpaned_add (GtkContainer* container, GtkWidget* widget);
+
+static void gtk_xpaned_remove (GtkContainer* container, GtkWidget* widget);
+
+static void gtk_xpaned_forall (GtkContainer* container,
+                                                          gboolean include_internals,
+                                                          GtkCallback callback,
+                                                          gpointer callback_data);
+
+static void gtk_xpaned_set_focus_child (GtkContainer* container,
+                                                                           GtkWidget* child);
+
+static void gtk_xpaned_set_saved_focus (GtkXPaned* xpaned, GtkWidget* widget);
+
+static void gtk_xpaned_set_first_xpaned (GtkXPaned* xpaned,
+                                                                                GtkXPaned* first_xpaned);
+
+static void gtk_xpaned_set_last_top_left_child_focus (GtkXPaned* xpaned,
+                                                                                                         GtkWidget* widget);
+
+static void gtk_xpaned_set_last_top_right_child_focus (GtkXPaned* xpaned,
+                                                                                                          GtkWidget* widget);
+
+static void gtk_xpaned_set_last_bottom_left_child_focus (GtkXPaned* xpaned,
+                                                                                                                GtkWidget* widget);
+
+static void gtk_xpaned_set_last_bottom_right_child_focus (GtkXPaned* xpaned,
+                                                                                                                 GtkWidget* widget);
+
+static gboolean gtk_xpaned_cycle_child_focus (GtkXPaned* xpaned,
+                                                                                         gboolean reverse);
+
+static gboolean gtk_xpaned_cycle_handle_focus (GtkXPaned* xpaned,
+                                                                                          gboolean reverse);
+
+static gboolean gtk_xpaned_move_handle (GtkXPaned* xpaned,
+                                                                           GtkScrollType scroll);
+
+static gboolean gtk_xpaned_accept_position (GtkXPaned* xpaned);
+
+static gboolean gtk_xpaned_cancel_position (GtkXPaned* xpaned);
+
+static gboolean gtk_xpaned_toggle_handle_focus (GtkXPaned* xpaned);
+
+static GType gtk_xpaned_child_type (GtkContainer* container);
+
+static GtkContainerClass* parent_class = NULL;
+
+struct _GtkXPanedPrivate
+{
+       GtkWidget *saved_focus;
+       GtkXPaned *first_xpaned;
+};
+
+GType gtk_xpaned_get_type (void)
+{
+       static GType xpaned_type = 0;
+  
+       if (!xpaned_type)
+       {
+               static const GTypeInfo xpaned_info =
+               {
+                       sizeof (GtkXPanedClass),
+                       NULL,           /* base_init */
+                       NULL,           /* base_finalize */
+                       (GClassInitFunc) gtk_xpaned_class_init,
+                       NULL,           /* class_finalize */
+                       NULL,           /* class_data */
+                       sizeof (GtkXPaned),
+                       0,              /* n_preallocs */
+                       (GInstanceInitFunc) gtk_xpaned_init
+               };
+
+               xpaned_type = g_type_register_static (GTK_TYPE_CONTAINER,
+                                                                                         "GtkXPaned",
+                                                                                         &xpaned_info,
+                                                                                         0);
+       }
+
+       return xpaned_type;
+}
+
+GtkWidget* gtk_xpaned_new (void)
+{
+       GtkXPaned* xpaned;
+
+       xpaned = g_object_new (GTK_TYPE_XPANED, NULL);
+
+       return GTK_WIDGET (xpaned);
+}
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void add_tab_bindings (GtkBindingSet* binding_set,
+                                                         GdkModifierType modifiers)
+{
+       gtk_binding_entry_add_signal (binding_set,
+                                                                 GDK_Tab,
+                                                                 modifiers,
+                                                                 "toggle_handle_focus",
+                                                                 0);
+
+       gtk_binding_entry_add_signal (binding_set,
+                                                                 GDK_KP_Tab,
+                                                                 modifiers,
+                                                                 "toggle_handle_focus",
+                                                                 0);
+}
+
+static void add_move_binding (GtkBindingSet* binding_set,
+                                                         guint keyval,
+                                                         GdkModifierType mask,
+                                                         GtkScrollType scroll)
+{
+       gtk_binding_entry_add_signal (binding_set,
+                                                                 keyval,
+                                                                 mask,
+                                                                 "move_handle",
+                                                                 1,
+                                                                 GTK_TYPE_SCROLL_TYPE,
+                                                                 scroll);
+}
+
+static void gtk_xpaned_class_init (GtkXPanedClass* class)
+{
+       GObjectClass* object_class;
+       GtkWidgetClass* widget_class;
+       GtkContainerClass* container_class;
+       GtkXPanedClass* xpaned_class;
+       GtkBindingSet* binding_set;
+
+       object_class = (GObjectClass *) class;
+       widget_class = (GtkWidgetClass *) class;
+       container_class = (GtkContainerClass *) class;
+       xpaned_class = (GtkXPanedClass *) class;
+
+       parent_class = g_type_class_peek_parent (class);
+
+       object_class->set_property = gtk_xpaned_set_property;
+       object_class->get_property = gtk_xpaned_get_property;
+       object_class->finalize = gtk_xpaned_finalize;
+
+       widget_class->realize = gtk_xpaned_realize;
+       widget_class->unrealize = gtk_xpaned_unrealize;
+       widget_class->map = gtk_xpaned_map;
+       widget_class->unmap = gtk_xpaned_unmap;
+       widget_class->expose_event = gtk_xpaned_expose;
+       widget_class->focus = gtk_xpaned_focus;
+       widget_class->enter_notify_event = gtk_xpaned_enter;
+       widget_class->leave_notify_event = gtk_xpaned_leave;
+       widget_class->button_press_event = gtk_xpaned_button_press;
+       widget_class->button_release_event = gtk_xpaned_button_release;
+       widget_class->motion_notify_event = gtk_xpaned_motion;
+       widget_class->size_request = gtk_xpaned_size_request;
+       widget_class->size_allocate = gtk_xpaned_size_allocate;
+
+       container_class->add = gtk_xpaned_add;
+       container_class->remove = gtk_xpaned_remove;
+       container_class->forall = gtk_xpaned_forall;
+       container_class->child_type = gtk_xpaned_child_type;
+       container_class->set_focus_child = gtk_xpaned_set_focus_child;
+       container_class->set_child_property = gtk_xpaned_set_child_property;
+       container_class->get_child_property = gtk_xpaned_get_child_property;
+
+       xpaned_class->cycle_child_focus = gtk_xpaned_cycle_child_focus;
+       xpaned_class->toggle_handle_focus = gtk_xpaned_toggle_handle_focus;
+       xpaned_class->move_handle = gtk_xpaned_move_handle;
+       xpaned_class->cycle_handle_focus = gtk_xpaned_cycle_handle_focus;
+       xpaned_class->accept_position = gtk_xpaned_accept_position;
+       xpaned_class->cancel_position = gtk_xpaned_cancel_position;
+
+       g_object_class_install_property (object_class,
+                                                                        PROP_X_POSITION,
+                                                                        g_param_spec_int ("x-position",
+                                                                                                          ("x-Position"),
+                                                                                                          ("x-Position of paned separator in pixels (0 means all the way to the left)"),
+                                                                                                          0,
+                                                                                                          G_MAXINT,
+                                                                                                          0,
+                                                                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+       g_object_class_install_property (object_class,
+                                                                        PROP_Y_POSITION,
+                                                                        g_param_spec_int ("y-position",
+                                                                                                          "y-Position",
+                                                                                                          "y-Position of paned separator in pixels (0 means all the way to the top)",
+                                                                                                          0,
+                                                                                                          G_MAXINT,
+                                                                                                          0,
+                                                                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+       g_object_class_install_property (object_class,
+                                                                        PROP_POSITION_SET,
+                                                                        g_param_spec_boolean ("position-set",
+                                                                                                                  "Position Set",
+                                                                                                                  "TRUE if the Position property should be used",
+                                                                                                                  FALSE,
+                                                                                                                  G_PARAM_READABLE | G_PARAM_WRITABLE));
+                                  
+       gtk_widget_class_install_style_property (widget_class,
+                                                                                        g_param_spec_int ("handle-size",
+                                                                                                                          "Handle Size",
+                                                                                                                          "Width of handle",
+                                                                                                                          0,
+                                                                                                                          G_MAXINT,
+                                                                                                                          3,
+                                                                                                                          G_PARAM_READABLE));
+       /**
+       * GtkXPaned:min-x-position:
+       *
+       * The smallest possible value for the x-position property. This property is derived from the
+       * size and shrinkability of the widget's children.
+       *
+       * Since: 2.4
+       */
+       g_object_class_install_property (object_class,
+                                                                        PROP_MIN_X_POSITION,
+                                                                        g_param_spec_int ("min-x-position",
+                                                                                                          "Minimal x-Position",
+                                                                                                          "Smallest possible value for the \"x-position\" property",
+                                                                                                          0,
+                                                                                                          G_MAXINT,
+                                                                                                          0,
+                                                                                                          G_PARAM_READABLE));
+
+       /**
+       * GtkXPaned:min-y-position:
+       *
+       * The smallest possible value for the y-position property. This property is derived from the
+       * size and shrinkability of the widget's children.
+       *
+       * Since: 2.4
+       */
+       g_object_class_install_property (object_class,
+                                                                        PROP_MIN_Y_POSITION,
+                                                                        g_param_spec_int ("min-y-position",
+                                                                                                          "Minimal y-Position",
+                                                                                                          "Smallest possible value for the \"y-position\" property",
+                                                                                                          0,
+                                                                                                          G_MAXINT,
+                                                                                                          0,
+                                                                                                          G_PARAM_READABLE));
+
+       /**
+       * GtkPaned:max-x-position:
+       *
+       * The largest possible value for the x-position property. This property is derived from the
+       * size and shrinkability of the widget's children.
+       *
+       * Since: 2.4
+       */
+       g_object_class_install_property (object_class,
+                                                                        PROP_MAX_X_POSITION,
+                                                                        g_param_spec_int ("max-x-position",
+                                                                                                          "Maximal x-Position",
+                                                                                                          "Largest possible value for the \"x-position\" property",
+                                                                                                          0,
+                                                                                                          G_MAXINT,
+                                                                                                          G_MAXINT,
+                                                                                                          G_PARAM_READABLE));
+
+       /**
+       * GtkPaned:max-y-position:
+       *
+       * The largest possible value for the y-position property. This property is derived from the
+       * size and shrinkability of the widget's children.
+       *
+       * Since: 2.4
+       */
+       g_object_class_install_property (object_class,
+                                                                        PROP_MAX_Y_POSITION,
+                                                                        g_param_spec_int ("max-y-position",
+                                                                                                          "Maximal y-Position",
+                                                                                                          "Largest possible value for the \"y-position\" property",
+                                                                                                          0,
+                                                                                                          G_MAXINT,
+                                                                                                          G_MAXINT,
+                                                                                                          G_PARAM_READABLE));
+
+       /**
+       * GtkPaned:resize:
+       *
+       * The "resize" child property determines whether the child expands and 
+       * shrinks along with the paned widget.
+       * 
+       * Since: 2.4 
+       */
+       gtk_container_class_install_child_property (container_class,
+                                                                                               CHILD_PROP_RESIZE,
+                                                                                               g_param_spec_boolean ("resize",
+                                                                                                                                         "Resize",
+                                                                                                                                         "If TRUE, the child expands and shrinks along with the paned widget",
+                                                                                                                                         TRUE,
+                                                                                                                                         G_PARAM_READWRITE));
+
+       /**
+       * GtkPaned:shrink:
+       *
+       * The "shrink" child property determines whether the child can be made 
+       * smaller than its requisition.
+       * 
+       * Since: 2.4 
+       */
+       gtk_container_class_install_child_property (container_class,
+                                                                                               CHILD_PROP_SHRINK,
+                                                                                               g_param_spec_boolean ("shrink", 
+                                                                                                                                         "Shrink",
+                                                                                                                                         "If TRUE, the child can be made smaller than its requisition",
+                                                                                                                                         TRUE,
+                                                                                                                                         G_PARAM_READWRITE));
+
+       signals [CYCLE_CHILD_FOCUS] = g_signal_new ("cycle-child-focus",
+                                                                                               G_TYPE_FROM_CLASS (object_class),
+                                                                                               G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                                                                               G_STRUCT_OFFSET (GtkXPanedClass, cycle_child_focus),
+                                                                                               NULL, NULL,
+                                                                                               psppire_marshal_BOOLEAN__BOOLEAN,
+                                                                                               G_TYPE_BOOLEAN, 1,
+                                                                                               G_TYPE_BOOLEAN);
+
+       signals [TOGGLE_HANDLE_FOCUS] = g_signal_new ("toggle-handle-focus",
+                                                                                                 G_TYPE_FROM_CLASS (object_class),
+                                                                                                 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                                                                                 G_STRUCT_OFFSET (GtkXPanedClass, toggle_handle_focus),
+                                                                                                 NULL, NULL,
+                                                                                                 psppire_marshal_BOOLEAN__VOID,
+                                                                                                 G_TYPE_BOOLEAN, 0);
+
+       signals[MOVE_HANDLE] = g_signal_new ("move-handle",
+                                                                                G_TYPE_FROM_CLASS (object_class),
+                                                                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                                                                G_STRUCT_OFFSET (GtkXPanedClass, move_handle),
+                                                                                NULL, NULL,
+                                                                                psppire_marshal_BOOLEAN__ENUM,
+                                                                                G_TYPE_BOOLEAN, 1,
+                                                                                GTK_TYPE_SCROLL_TYPE);
+
+       signals [CYCLE_HANDLE_FOCUS] = g_signal_new ("cycle-handle-focus",
+                                                                                                G_TYPE_FROM_CLASS (object_class),
+                                                                                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                                                                                G_STRUCT_OFFSET (GtkXPanedClass, cycle_handle_focus),
+                                                                                                NULL, NULL,
+                                                                                                psppire_marshal_BOOLEAN__BOOLEAN,
+                                                                                                G_TYPE_BOOLEAN, 1,
+                                                                                                G_TYPE_BOOLEAN);
+
+       signals [ACCEPT_POSITION] = g_signal_new ("accept-position",
+                                                                                         G_TYPE_FROM_CLASS (object_class),
+                                                                                         G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                                                                         G_STRUCT_OFFSET (GtkXPanedClass, accept_position),
+                                                                                         NULL, NULL,
+                                                                                         psppire_marshal_BOOLEAN__VOID,
+                                                                                         G_TYPE_BOOLEAN, 0);
+
+       signals [CANCEL_POSITION] = g_signal_new ("cancel-position",
+                                                                                         G_TYPE_FROM_CLASS (object_class),
+                                                                                         G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                                                                         G_STRUCT_OFFSET (GtkXPanedClass, cancel_position),
+                                                                                         NULL, NULL,
+                                                                                         psppire_marshal_BOOLEAN__VOID,
+                                                                                         G_TYPE_BOOLEAN, 0);
+
+       binding_set = gtk_binding_set_by_class (class);
+
+       /* F6 and friends */
+       gtk_binding_entry_add_signal (binding_set,
+                                                                 GDK_F6, 0,
+                                                                 "cycle-child-focus", 1, 
+                                                                 G_TYPE_BOOLEAN, FALSE);
+
+       gtk_binding_entry_add_signal (binding_set,
+                                                                 GDK_F6, GDK_SHIFT_MASK,
+                                                                 "cycle-child-focus", 1,
+                                                                 G_TYPE_BOOLEAN, TRUE);
+
+       /* F8 and friends */
+       gtk_binding_entry_add_signal (binding_set,
+                                                                 GDK_F8, 0,
+                                                                 "cycle-handle-focus", 1,
+                                                                 G_TYPE_BOOLEAN, FALSE);
+       gtk_binding_entry_add_signal (binding_set,
+                                                                 GDK_F8, GDK_SHIFT_MASK,
+                                                                 "cycle-handle-focus", 1,
+                                                                 G_TYPE_BOOLEAN, TRUE);
+       add_tab_bindings (binding_set, 0);
+       add_tab_bindings (binding_set, GDK_CONTROL_MASK);
+       add_tab_bindings (binding_set, GDK_SHIFT_MASK);
+       add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK);
+
+       /* accept and cancel positions */
+       gtk_binding_entry_add_signal (binding_set,
+                                                                 GDK_Escape, 0,
+                                                                 "cancel-position", 0);
+
+       gtk_binding_entry_add_signal (binding_set,
+                                                                 GDK_Return, 0,
+                                                                 "accept-position", 0);
+
+       gtk_binding_entry_add_signal (binding_set,
+                                                                 GDK_KP_Enter, 0,
+                                                                 "accept-position", 0);
+
+       gtk_binding_entry_add_signal (binding_set,
+                                                                 GDK_space, 0,
+                                                                 "accept-position", 0);
+                                                                 
+       gtk_binding_entry_add_signal (binding_set,
+                                                                 GDK_KP_Space, 0,
+                                                                 "accept-position", 0);
+
+       /* move handle */
+       add_move_binding (binding_set, GDK_Left, 0, GTK_SCROLL_STEP_LEFT);
+       add_move_binding (binding_set, GDK_KP_Left, 0, GTK_SCROLL_STEP_LEFT);
+       add_move_binding (binding_set, GDK_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT);
+       add_move_binding (binding_set, GDK_KP_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT);
+
+       add_move_binding (binding_set, GDK_Right, 0, GTK_SCROLL_STEP_RIGHT);
+       add_move_binding (binding_set, GDK_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT);
+       add_move_binding (binding_set, GDK_KP_Right, 0, GTK_SCROLL_STEP_RIGHT);
+       add_move_binding (binding_set, GDK_KP_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT);
+
+       add_move_binding (binding_set, GDK_Up, 0, GTK_SCROLL_STEP_UP);
+       add_move_binding (binding_set, GDK_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP);
+       add_move_binding (binding_set, GDK_KP_Up, 0, GTK_SCROLL_STEP_UP);
+       add_move_binding (binding_set, GDK_KP_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP);
+       add_move_binding (binding_set, GDK_Page_Up, 0, GTK_SCROLL_PAGE_UP);
+       add_move_binding (binding_set, GDK_KP_Page_Up, 0, GTK_SCROLL_PAGE_UP);
+
+       add_move_binding (binding_set, GDK_Down, 0, GTK_SCROLL_STEP_DOWN);
+       add_move_binding (binding_set, GDK_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN);
+       add_move_binding (binding_set, GDK_KP_Down, 0, GTK_SCROLL_STEP_DOWN);
+       add_move_binding (binding_set, GDK_KP_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN);
+       add_move_binding (binding_set, GDK_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT);
+       add_move_binding (binding_set, GDK_KP_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT);
+
+       add_move_binding (binding_set, GDK_Home, 0, GTK_SCROLL_START);
+       add_move_binding (binding_set, GDK_KP_Home, 0, GTK_SCROLL_START);
+       add_move_binding (binding_set, GDK_End, 0, GTK_SCROLL_END);
+       add_move_binding (binding_set, GDK_KP_End, 0, GTK_SCROLL_END);
+}
+
+static GType gtk_xpaned_child_type (GtkContainer* container)
+{
+       if (!GTK_XPANED (container)->top_left_child || 
+               !GTK_XPANED (container)->top_right_child ||
+               !GTK_XPANED (container)->bottom_left_child || 
+               !GTK_XPANED (container)->bottom_right_child)
+               return GTK_TYPE_WIDGET;
+         else
+               return G_TYPE_NONE;
+}
+
+static void gtk_xpaned_init (GtkXPaned* xpaned)
+{
+       GTK_WIDGET_SET_FLAGS (xpaned, GTK_NO_WINDOW | GTK_CAN_FOCUS);
+  
+       xpaned->top_left_child = NULL;
+       xpaned->top_right_child = NULL;
+       xpaned->bottom_left_child = NULL;
+       xpaned->bottom_right_child = NULL;
+       xpaned->handle_east = NULL;
+       xpaned->handle_west = NULL;
+       xpaned->handle_north = NULL;
+       xpaned->handle_south = NULL;
+       xpaned->handle_middle = NULL;
+       xpaned->xor_gc = NULL;
+       xpaned->cursor_type_east = GDK_SB_V_DOUBLE_ARROW;
+       xpaned->cursor_type_west = GDK_SB_V_DOUBLE_ARROW;
+       xpaned->cursor_type_north = GDK_SB_H_DOUBLE_ARROW;
+       xpaned->cursor_type_south = GDK_SB_H_DOUBLE_ARROW;
+       xpaned->cursor_type_middle = GDK_FLEUR;
+
+       xpaned->handle_pos_east.width = 5;
+       xpaned->handle_pos_east.height = 5;
+       xpaned->handle_pos_west.width = 5;
+       xpaned->handle_pos_west.height = 5;
+       xpaned->handle_pos_north.width = 5;
+       xpaned->handle_pos_north.height = 5;
+       xpaned->handle_pos_south.width = 5;
+       xpaned->handle_pos_south.height = 5;
+       xpaned->handle_pos_middle.width = 5;
+       xpaned->handle_pos_middle.height = 5;
+
+       xpaned->position_set = FALSE;
+       xpaned->last_allocation.width = -1;
+       xpaned->last_allocation.height = -1;
+       xpaned->in_drag_vert = FALSE;
+       xpaned->in_drag_horiz = FALSE;
+       xpaned->in_drag_vert_and_horiz = FALSE;
+
+       xpaned->maximized[GTK_XPANED_TOP_LEFT] = FALSE;
+       xpaned->maximized[GTK_XPANED_TOP_RIGHT] = FALSE;
+       xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] = FALSE;
+       xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT] = FALSE;
+
+       xpaned->priv = g_new0 (GtkXPanedPrivate, 1);
+       xpaned->last_top_left_child_focus = NULL;
+       xpaned->last_top_right_child_focus = NULL;
+       xpaned->last_bottom_left_child_focus = NULL;
+       xpaned->last_bottom_right_child_focus = NULL;
+       xpaned->in_recursion = FALSE;
+       xpaned->handle_prelit = FALSE;
+       xpaned->original_position.x = -1;
+       xpaned->original_position.y = -1;
+       xpaned->unmaximized_position.x = -1;
+       xpaned->unmaximized_position.y = -1;
+
+       xpaned->handle_pos_east.x = -1;
+       xpaned->handle_pos_east.y = -1;
+       xpaned->handle_pos_west.x = -1;
+       xpaned->handle_pos_west.y = -1;
+       xpaned->handle_pos_north.x = -1;
+       xpaned->handle_pos_north.y = -1;
+       xpaned->handle_pos_south.x = -1;
+       xpaned->handle_pos_south.y = -1;
+       xpaned->handle_pos_middle.x = -1;
+       xpaned->handle_pos_middle.y = -1;
+
+       xpaned->drag_pos.x = -1;
+       xpaned->drag_pos.y = -1;
+}
+
+static void gtk_xpaned_size_request (GtkWidget* widget,
+                                                                        GtkRequisition* requisition)
+{
+       GtkXPaned* xpaned = GTK_XPANED (widget);
+       GtkRequisition child_requisition;
+
+       requisition->width = 0;
+       requisition->height = 0;
+
+       if (xpaned->top_left_child && GTK_WIDGET_VISIBLE (xpaned->top_left_child))
+       {
+               gtk_widget_size_request (xpaned->top_left_child, &child_requisition);
+
+               requisition->width = child_requisition.width;
+               requisition->height = child_requisition.height;
+       }
+
+       if (xpaned->top_right_child && GTK_WIDGET_VISIBLE (xpaned->top_right_child))
+       {
+               gtk_widget_size_request (xpaned->top_right_child, &child_requisition);
+
+               requisition->width += child_requisition.width;
+               requisition->height = MAX (requisition->height, child_requisition.height);
+       }
+
+       if (xpaned->bottom_left_child && GTK_WIDGET_VISIBLE (xpaned->bottom_left_child))
+       {
+               gtk_widget_size_request (xpaned->bottom_left_child, &child_requisition);
+
+               requisition->width = MAX (requisition->width, child_requisition.width);
+               requisition->height += child_requisition.height;
+       }
+
+       if (xpaned->bottom_right_child && GTK_WIDGET_VISIBLE (xpaned->bottom_right_child))
+       {
+               gtk_widget_size_request (xpaned->bottom_right_child, &child_requisition);
+
+               requisition->width = MAX (requisition->width, child_requisition.width);
+               requisition->height = MAX (requisition->height, child_requisition.height);
+       }
+
+       /* add 2 times the set border-width to the GtkXPaneds requisition */
+       requisition->width += GTK_CONTAINER (xpaned)->border_width * 2;
+       requisition->height += GTK_CONTAINER (xpaned)->border_width * 2;
+
+       /* also add the handle "thickness" to GtkXPaneds width- and height-requisitions */
+       if (xpaned->top_left_child && GTK_WIDGET_VISIBLE (xpaned->top_left_child) &&
+               xpaned->top_right_child && GTK_WIDGET_VISIBLE (xpaned->top_right_child) &&
+               xpaned->bottom_left_child && GTK_WIDGET_VISIBLE (xpaned->bottom_left_child) &&
+               xpaned->bottom_right_child && GTK_WIDGET_VISIBLE (xpaned->bottom_right_child))
+       {
+               gint handle_size;
+
+               gtk_widget_style_get (widget, "handle-size", &handle_size, NULL);
+               requisition->width += handle_size;
+               requisition->height += handle_size;
+       }
+}
+
+void
+gtk_xpaned_compute_position (GtkXPaned* xpaned,
+                            const GtkAllocation* allocation,
+                            GtkRequisition* top_left_child_req,
+                            GtkRequisition* top_right_child_req,
+                            GtkRequisition* bottom_left_child_req,
+                            GtkRequisition* bottom_right_child_req);
+
+
+static void gtk_xpaned_size_allocate (GtkWidget* widget,
+                                                                         GtkAllocation* allocation)
+{
+       GtkXPaned* xpaned = GTK_XPANED (widget);
+       gint border_width = GTK_CONTAINER (xpaned)->border_width;
+       GtkAllocation top_left_child_allocation;
+       GtkAllocation top_right_child_allocation;
+       GtkAllocation bottom_left_child_allocation;
+       GtkAllocation bottom_right_child_allocation;
+       GtkRequisition top_left_child_requisition;
+       GtkRequisition top_right_child_requisition;
+       GtkRequisition bottom_left_child_requisition;
+       GtkRequisition bottom_right_child_requisition;
+       gint handle_size;
+
+       /* determine size of handle(s) */
+       gtk_widget_style_get (widget, "handle-size", &handle_size, NULL);
+
+       widget->allocation = *allocation;
+
+       if (xpaned->top_left_child && GTK_WIDGET_VISIBLE (xpaned->top_left_child) &&
+               xpaned->top_right_child && GTK_WIDGET_VISIBLE (xpaned->top_right_child) &&
+               xpaned->bottom_left_child && GTK_WIDGET_VISIBLE (xpaned->bottom_left_child) &&
+               xpaned->bottom_right_child && GTK_WIDGET_VISIBLE (xpaned->bottom_right_child))
+    {
+               /* what sizes do the children want to be at least at */
+               gtk_widget_get_child_requisition (xpaned->top_left_child,
+                                                                                 &top_left_child_requisition);
+               gtk_widget_get_child_requisition (xpaned->top_right_child,
+                                                                                 &top_right_child_requisition);
+               gtk_widget_get_child_requisition (xpaned->bottom_left_child,
+                                                                                 &bottom_left_child_requisition);
+               gtk_widget_get_child_requisition (xpaned->bottom_right_child,
+                                                                                 &bottom_right_child_requisition);
+
+               /* determine the total requisition-sum of all requisitions of borders,
+                * handles, children etc. */
+               gtk_xpaned_compute_position (xpaned,
+                                                                        allocation,
+                                                                        &top_left_child_requisition,
+                                                                        &top_right_child_requisition,
+                                                                        &bottom_left_child_requisition,
+                                                                        &bottom_right_child_requisition);
+
+               /* calculate the current positions and sizes of the handles */
+               xpaned->handle_pos_east.x = widget->allocation.x + border_width + xpaned->top_left_child_size.width + handle_size;
+               xpaned->handle_pos_east.y = widget->allocation.y + border_width + xpaned->top_left_child_size.height;
+               xpaned->handle_pos_east.width = widget->allocation.width - xpaned->top_left_child_size.width - 2 * border_width - handle_size;
+               xpaned->handle_pos_east.height = handle_size;
+
+               xpaned->handle_pos_west.x = widget->allocation.x + border_width;
+               xpaned->handle_pos_west.y = xpaned->handle_pos_east.y;
+               xpaned->handle_pos_west.width = widget->allocation.width - xpaned->handle_pos_east.width - 2 * border_width - handle_size;
+               xpaned->handle_pos_west.height = handle_size;
+
+               xpaned->handle_pos_north.x = xpaned->handle_pos_east.x - handle_size;
+               xpaned->handle_pos_north.y = widget->allocation.y + border_width;
+               xpaned->handle_pos_north.width = handle_size;
+               xpaned->handle_pos_north.height = xpaned->handle_pos_east.y - widget->allocation.y - border_width;
+
+               xpaned->handle_pos_south.x = xpaned->handle_pos_north.x;
+               xpaned->handle_pos_south.y = xpaned->handle_pos_east.y + handle_size;
+               xpaned->handle_pos_south.width = handle_size;
+               xpaned->handle_pos_south.height = widget->allocation.height - xpaned->handle_pos_north.height - 2 * border_width - handle_size;
+
+
+#define CENTRUM 20
+               xpaned->handle_pos_middle.x = xpaned->handle_pos_north.x ;
+               xpaned->handle_pos_middle.y = xpaned->handle_pos_east.y ;
+               xpaned->handle_pos_middle.width = handle_size + CENTRUM ;
+               xpaned->handle_pos_middle.height = handle_size + CENTRUM;
+
+               /* set allocation for top-left child */
+               top_left_child_allocation.x = widget->allocation.x + border_width;
+               top_left_child_allocation.y = widget->allocation.y + border_width;
+               top_left_child_allocation.width = xpaned->handle_pos_west.width;
+               top_left_child_allocation.height = xpaned->handle_pos_north.height;
+
+               /* set allocation for top-right child */
+               top_right_child_allocation.x = widget->allocation.x + border_width + handle_size + top_left_child_allocation.width;
+               top_right_child_allocation.y = widget->allocation.y + border_width;
+               top_right_child_allocation.width = xpaned->handle_pos_east.width;
+               top_right_child_allocation.height = xpaned->handle_pos_north.height;
+
+               /* set allocation for bottom-left child */
+               bottom_left_child_allocation.x = xpaned->handle_pos_west.x;
+               bottom_left_child_allocation.y = xpaned->handle_pos_south.y;
+               bottom_left_child_allocation.width = xpaned->handle_pos_west.width;
+               bottom_left_child_allocation.height = xpaned->handle_pos_south.height;
+
+               /* set allocation for bottom-right child */
+               bottom_right_child_allocation.x = top_right_child_allocation.x;
+               bottom_right_child_allocation.y = bottom_left_child_allocation.y;
+               bottom_right_child_allocation.width = xpaned->handle_pos_east.width;
+               bottom_right_child_allocation.height = xpaned->handle_pos_south.height;
+
+               if (GTK_WIDGET_REALIZED (widget))
+               {
+                       if (GTK_WIDGET_MAPPED (widget))
+                       {
+                               gdk_window_show (xpaned->handle_east);
+                               gdk_window_show (xpaned->handle_west);
+                               gdk_window_show (xpaned->handle_north);
+                               gdk_window_show (xpaned->handle_south);
+                               gdk_window_show (xpaned->handle_middle);
+                       }
+
+                       gdk_window_move_resize (xpaned->handle_east,
+                                                                       xpaned->handle_pos_east.x,
+                                                                       xpaned->handle_pos_east.y,
+                                                                       xpaned->handle_pos_east.width,
+                                                                       xpaned->handle_pos_east.height);
+
+                       gdk_window_move_resize (xpaned->handle_west,
+                                                                       xpaned->handle_pos_west.x,
+                                                                       xpaned->handle_pos_west.y,
+                                                                       xpaned->handle_pos_west.width,
+                                                                       xpaned->handle_pos_west.height);
+
+                       gdk_window_move_resize (xpaned->handle_north,
+                                                                       xpaned->handle_pos_north.x,
+                                                                       xpaned->handle_pos_north.y,
+                                                                       xpaned->handle_pos_north.width,
+                                                                       xpaned->handle_pos_north.height);
+
+                       gdk_window_move_resize (xpaned->handle_south,
+                                                                       xpaned->handle_pos_south.x,
+                                                                       xpaned->handle_pos_south.y,
+                                                                       xpaned->handle_pos_south.width,
+                                                                       xpaned->handle_pos_south.height);
+
+                       gdk_window_move_resize (xpaned->handle_middle,
+                                               xpaned->handle_pos_middle.x,
+                                               xpaned->handle_pos_middle.y,
+                                               xpaned->handle_pos_middle.width,
+                                               xpaned->handle_pos_middle.height);
+               }
+
+               /* Now allocate the childen, making sure, when resizing not to
+               * overlap the windows
+               */
+               if (GTK_WIDGET_MAPPED (widget))
+               {
+                       gtk_widget_size_allocate (xpaned->top_right_child, &top_right_child_allocation);
+                       gtk_widget_size_allocate (xpaned->top_left_child, &top_left_child_allocation);
+                       gtk_widget_size_allocate (xpaned->bottom_left_child, &bottom_left_child_allocation);
+                       gtk_widget_size_allocate (xpaned->bottom_right_child, &bottom_right_child_allocation);
+               }
+       }
+}
+
+static void gtk_xpaned_set_property (GObject* object,
+                                                                        guint prop_id,
+                                                                        const GValue* value,
+                                                                        GParamSpec* pspec)
+{
+       GtkXPaned* xpaned = GTK_XPANED (object);
+  
+       switch (prop_id)
+       {
+               case PROP_X_POSITION:
+                       gtk_xpaned_set_position_x (xpaned, g_value_get_int (value));
+               break;
+
+               case PROP_Y_POSITION:
+                       gtk_xpaned_set_position_y (xpaned, g_value_get_int (value));
+               break;
+
+               case PROP_POSITION_SET:
+                       xpaned->position_set = g_value_get_boolean (value);
+                       gtk_widget_queue_resize (GTK_WIDGET (xpaned));
+               break;
+
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void gtk_xpaned_get_property (GObject* object,
+                                                                        guint prop_id,
+                                                                        GValue* value,
+                                                                        GParamSpec* pspec)
+{
+       GtkXPaned* xpaned = GTK_XPANED (object);
+  
+       switch (prop_id)
+       {
+               case PROP_X_POSITION:
+                       g_value_set_int (value, xpaned->top_left_child_size.width);
+               break;
+
+               case PROP_Y_POSITION:
+                       g_value_set_int (value, xpaned->top_left_child_size.height);
+               break;
+
+               case PROP_POSITION_SET:
+                       g_value_set_boolean (value, xpaned->position_set);
+               break;
+
+               case PROP_MIN_X_POSITION:
+                       g_value_set_int (value, xpaned->min_position.x);
+               break;
+
+               case PROP_MIN_Y_POSITION:
+                       g_value_set_int (value, xpaned->min_position.y);
+               break;
+
+               case PROP_MAX_X_POSITION:
+                       g_value_set_int (value, xpaned->max_position.x);
+               break;
+
+               case PROP_MAX_Y_POSITION:
+                       g_value_set_int (value, xpaned->max_position.y);
+               break;
+
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void gtk_xpaned_set_child_property (GtkContainer* container,
+                                                                                  GtkWidget* child,
+                                                                                  guint property_id,
+                                                                                  const GValue* value,
+                                                                                  GParamSpec* pspec)
+{
+       GtkXPaned* xpaned = GTK_XPANED (container);
+       gboolean old_value = FALSE;
+       gboolean new_value = FALSE;
+
+       g_assert (child == xpaned->top_left_child ||
+                         child == xpaned->top_right_child ||
+                         child == xpaned->bottom_left_child ||
+                         child == xpaned->bottom_right_child);
+
+       new_value = g_value_get_boolean (value);
+
+       switch (property_id)
+       {
+               case CHILD_PROP_RESIZE:
+                       if (child == xpaned->top_left_child)
+                       {
+                               old_value = xpaned->top_left_child_resize;
+                               xpaned->top_left_child_resize = new_value;
+                       }
+                       else if (child == xpaned->top_right_child)
+                       {
+                               old_value = xpaned->top_right_child_resize;
+                               xpaned->top_right_child_resize = new_value;
+                       }
+                       else if (child == xpaned->bottom_left_child)
+                       {
+                               old_value = xpaned->bottom_left_child_resize;
+                               xpaned->bottom_left_child_resize = new_value;
+                       }
+                       else if (child == xpaned->bottom_right_child)
+                       {
+                               old_value = xpaned->bottom_right_child_resize;
+                               xpaned->bottom_right_child_resize = new_value;
+                       }
+               break;
+
+               case CHILD_PROP_SHRINK :
+                       if (child == xpaned->top_left_child)
+                       {
+                               old_value = xpaned->top_left_child_shrink;
+                               xpaned->top_left_child_shrink = new_value;
+                       }
+                       else if (child == xpaned->top_right_child)
+                       {
+                               old_value = xpaned->top_right_child_shrink;
+                               xpaned->top_right_child_shrink = new_value;
+                       }
+                       else if (child == xpaned->bottom_left_child)
+                       {
+                               old_value = xpaned->bottom_left_child_shrink;
+                               xpaned->bottom_left_child_shrink = new_value;
+                       }
+                       else if (child == xpaned->bottom_right_child)
+                       {
+                               old_value = xpaned->bottom_right_child_shrink;
+                               xpaned->bottom_right_child_shrink = new_value;
+                       }
+               break;
+
+               default:
+                       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container,
+                                                                                                                 property_id,
+                                                                                                                 pspec);
+                       old_value = -1; /* quiet gcc */
+               break;
+       }
+
+       if (old_value != new_value)
+               gtk_widget_queue_resize (GTK_WIDGET (container));
+}
+
+static void gtk_xpaned_get_child_property (GtkContainer* container,
+                                                                                  GtkWidget* child,
+                                                                                  guint property_id,
+                                                                                  GValue* value,
+                                                                                  GParamSpec* pspec)
+{
+       GtkXPaned* xpaned = GTK_XPANED (container);
+
+       g_assert (child == xpaned->top_left_child ||
+                         child == xpaned->top_right_child ||
+                         child == xpaned->bottom_left_child ||
+                         child == xpaned->bottom_right_child);
+
+       switch (property_id)
+       {
+               case CHILD_PROP_RESIZE :
+                       if (child == xpaned->top_left_child)
+                               g_value_set_boolean (value, xpaned->top_left_child_resize);
+                       else if (child == xpaned->top_right_child)
+                               g_value_set_boolean (value, xpaned->top_right_child_resize);
+                       else if (child == xpaned->bottom_left_child)
+                               g_value_set_boolean (value, xpaned->bottom_left_child_resize);
+                       else if (child == xpaned->bottom_right_child)
+                               g_value_set_boolean (value, xpaned->bottom_right_child_resize);                 
+               break;
+
+               case CHILD_PROP_SHRINK :
+                       if (child == xpaned->top_left_child)
+                               g_value_set_boolean (value, xpaned->top_left_child_shrink);
+                       else if (child == xpaned->top_right_child)
+                               g_value_set_boolean (value, xpaned->top_right_child_shrink);
+                       else if (child == xpaned->bottom_left_child)
+                               g_value_set_boolean (value, xpaned->bottom_left_child_shrink);
+                       else if (child == xpaned->bottom_right_child)
+                               g_value_set_boolean (value, xpaned->bottom_right_child_shrink);
+               break;
+
+               default:
+                       GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container,
+                                                                                                                 property_id,
+                                                                                                                 pspec);
+               break;
+       }
+}
+
+static void gtk_xpaned_finalize (GObject* object)
+{
+       GtkXPaned* xpaned = GTK_XPANED (object);
+  
+       gtk_xpaned_set_saved_focus (xpaned, NULL);
+       gtk_xpaned_set_first_xpaned (xpaned, NULL);
+
+       g_free (xpaned->priv);
+
+       G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void gtk_xpaned_realize (GtkWidget* widget)
+{
+       GtkXPaned* xpaned;
+       GdkWindowAttr attributes_east;
+       GdkWindowAttr attributes_west;
+       GdkWindowAttr attributes_north;
+       GdkWindowAttr attributes_south;
+       GdkWindowAttr attributes_middle;
+       gint attributes_mask_east;
+       gint attributes_mask_west;
+       gint attributes_mask_north;
+       gint attributes_mask_south;
+       gint attributes_mask_middle;
+
+       GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+       xpaned = GTK_XPANED (widget);
+
+       widget->window = gtk_widget_get_parent_window (widget);
+       g_object_ref (widget->window);
+  
+       attributes_east.window_type = GDK_WINDOW_CHILD;
+       attributes_west.window_type = GDK_WINDOW_CHILD;
+       attributes_north.window_type = GDK_WINDOW_CHILD;
+       attributes_south.window_type = GDK_WINDOW_CHILD;
+       attributes_middle.window_type = GDK_WINDOW_CHILD;
+
+       attributes_east.wclass = GDK_INPUT_ONLY;
+       attributes_west.wclass = GDK_INPUT_ONLY;
+       attributes_north.wclass = GDK_INPUT_ONLY;
+       attributes_south.wclass = GDK_INPUT_ONLY;
+       attributes_middle.wclass = GDK_INPUT_ONLY;
+
+       attributes_east.x = xpaned->handle_pos_east.x;
+       attributes_east.y = xpaned->handle_pos_east.y;
+       attributes_east.width = xpaned->handle_pos_east.width;
+       attributes_east.height = xpaned->handle_pos_east.height;
+
+       attributes_west.x = xpaned->handle_pos_west.x;
+       attributes_west.y = xpaned->handle_pos_west.y;
+       attributes_west.width = xpaned->handle_pos_west.width;
+       attributes_west.height = xpaned->handle_pos_west.height;
+
+       attributes_north.x = xpaned->handle_pos_north.x;
+       attributes_north.y = xpaned->handle_pos_north.y;
+       attributes_north.width = xpaned->handle_pos_north.width;
+       attributes_north.height = xpaned->handle_pos_north.height;
+
+       attributes_south.x = xpaned->handle_pos_south.x;
+       attributes_south.y = xpaned->handle_pos_south.y;
+       attributes_south.width = xpaned->handle_pos_south.width;
+       attributes_south.height = xpaned->handle_pos_south.height;
+
+       attributes_middle.x = xpaned->handle_pos_middle.x;
+       attributes_middle.y = xpaned->handle_pos_middle.y;
+       attributes_middle.width = xpaned->handle_pos_middle.width;
+       attributes_middle.height = xpaned->handle_pos_middle.height;
+
+       attributes_east.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
+                                                                                                       xpaned->cursor_type_east);
+       attributes_west.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
+                                                                                                       xpaned->cursor_type_west);
+       attributes_north.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
+                                                                                                       xpaned->cursor_type_north);
+       attributes_south.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
+                                                                                                       xpaned->cursor_type_south);
+       attributes_middle.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
+                                                                                                       xpaned->cursor_type_middle);
+
+       attributes_east.event_mask = gtk_widget_get_events (widget);
+       attributes_west.event_mask = gtk_widget_get_events (widget);
+       attributes_north.event_mask = gtk_widget_get_events (widget);
+       attributes_south.event_mask = gtk_widget_get_events (widget);
+       attributes_middle.event_mask = gtk_widget_get_events (widget);
+
+       attributes_east.event_mask |= (GDK_BUTTON_PRESS_MASK |
+                                                         GDK_BUTTON_RELEASE_MASK |
+                                                         GDK_ENTER_NOTIFY_MASK |
+                                                         GDK_LEAVE_NOTIFY_MASK |
+                                                         GDK_POINTER_MOTION_MASK |
+                                                         GDK_POINTER_MOTION_HINT_MASK);
+       attributes_west.event_mask |= (GDK_BUTTON_PRESS_MASK |
+                                                         GDK_BUTTON_RELEASE_MASK |
+                                                         GDK_ENTER_NOTIFY_MASK |
+                                                         GDK_LEAVE_NOTIFY_MASK |
+                                                         GDK_POINTER_MOTION_MASK |
+                                                         GDK_POINTER_MOTION_HINT_MASK);
+       attributes_north.event_mask |= (GDK_BUTTON_PRESS_MASK |
+                                                         GDK_BUTTON_RELEASE_MASK |
+                                                         GDK_ENTER_NOTIFY_MASK |
+                                                         GDK_LEAVE_NOTIFY_MASK |
+                                                         GDK_POINTER_MOTION_MASK |
+                                                         GDK_POINTER_MOTION_HINT_MASK);
+       attributes_south.event_mask |= (GDK_BUTTON_PRESS_MASK |
+                                                         GDK_BUTTON_RELEASE_MASK |
+                                                         GDK_ENTER_NOTIFY_MASK |
+                                                         GDK_LEAVE_NOTIFY_MASK |
+                                                         GDK_POINTER_MOTION_MASK |
+                                                         GDK_POINTER_MOTION_HINT_MASK);
+       attributes_middle.event_mask |= (GDK_BUTTON_PRESS_MASK |
+                                                         GDK_BUTTON_RELEASE_MASK |
+                                                         GDK_ENTER_NOTIFY_MASK |
+                                                         GDK_LEAVE_NOTIFY_MASK |
+                                                         GDK_POINTER_MOTION_MASK |
+                                                         GDK_POINTER_MOTION_HINT_MASK);
+
+       attributes_mask_east = GDK_WA_X | GDK_WA_Y | GDK_WA_CURSOR;
+       attributes_mask_west = GDK_WA_X | GDK_WA_Y | GDK_WA_CURSOR;
+       attributes_mask_north = GDK_WA_X | GDK_WA_Y | GDK_WA_CURSOR;
+       attributes_mask_south = GDK_WA_X | GDK_WA_Y | GDK_WA_CURSOR;
+       attributes_mask_middle = GDK_WA_X | GDK_WA_Y | GDK_WA_CURSOR;
+
+       xpaned->handle_east = gdk_window_new (widget->window,
+                                                                                 &attributes_east,
+                                                                                 attributes_mask_east);
+       xpaned->handle_west = gdk_window_new (widget->window,
+                                                                                 &attributes_west,
+                                                                                 attributes_mask_west);
+       xpaned->handle_north = gdk_window_new (widget->window,
+                                                                                 &attributes_north,
+                                                                                 attributes_mask_north);
+       xpaned->handle_south = gdk_window_new (widget->window,
+                                                                                 &attributes_south,
+                                                                                 attributes_mask_south);
+       xpaned->handle_middle = gdk_window_new (widget->window,
+                                                                                 &attributes_middle,
+                                                                                 attributes_mask_middle);
+
+       gdk_window_set_user_data (xpaned->handle_east, xpaned);
+       gdk_window_set_user_data (xpaned->handle_west, xpaned);
+       gdk_window_set_user_data (xpaned->handle_north, xpaned);
+       gdk_window_set_user_data (xpaned->handle_south, xpaned);
+       gdk_window_set_user_data (xpaned->handle_middle, xpaned);
+
+       gdk_cursor_unref (attributes_east.cursor);
+       gdk_cursor_unref (attributes_west.cursor);
+       gdk_cursor_unref (attributes_north.cursor);
+       gdk_cursor_unref (attributes_south.cursor);
+       gdk_cursor_unref (attributes_middle.cursor);
+
+       widget->style = gtk_style_attach (widget->style, widget->window);
+
+       if (xpaned->top_left_child && GTK_WIDGET_VISIBLE (xpaned->top_left_child) &&
+               xpaned->top_right_child && GTK_WIDGET_VISIBLE (xpaned->top_right_child) &&
+               xpaned->bottom_left_child && GTK_WIDGET_VISIBLE (xpaned->bottom_left_child) &&
+               xpaned->bottom_right_child && GTK_WIDGET_VISIBLE (xpaned->bottom_right_child))
+       {
+               gdk_window_show (xpaned->handle_east);
+               gdk_window_show (xpaned->handle_west);
+               gdk_window_show (xpaned->handle_north);
+               gdk_window_show (xpaned->handle_south);
+               gdk_window_show (xpaned->handle_middle);
+       }
+}
+
+static void gtk_xpaned_unrealize (GtkWidget *widget)
+{
+       GtkXPaned* xpaned = GTK_XPANED (widget);
+
+       if (xpaned->xor_gc)
+       {
+               g_object_unref (xpaned->xor_gc);
+               xpaned->xor_gc = NULL;
+       }
+
+       if (xpaned->handle_east)
+       {
+               gdk_window_set_user_data (xpaned->handle_east, NULL);
+               gdk_window_destroy (xpaned->handle_east);
+               xpaned->handle_east = NULL;
+       }
+
+       if (xpaned->handle_west)
+       {
+               gdk_window_set_user_data (xpaned->handle_west, NULL);
+               gdk_window_destroy (xpaned->handle_west);
+               xpaned->handle_west = NULL;
+       }
+
+       if (xpaned->handle_north)
+       {
+               gdk_window_set_user_data (xpaned->handle_north, NULL);
+               gdk_window_destroy (xpaned->handle_north);
+               xpaned->handle_north = NULL;
+       }
+
+       if (xpaned->handle_south)
+       {
+               gdk_window_set_user_data (xpaned->handle_south, NULL);
+               gdk_window_destroy (xpaned->handle_south);
+               xpaned->handle_south = NULL;
+       }
+
+       if (xpaned->handle_middle)
+       {
+               gdk_window_set_user_data (xpaned->handle_middle, NULL);
+               gdk_window_destroy (xpaned->handle_middle);
+               xpaned->handle_middle = NULL;
+       }
+
+       gtk_xpaned_set_last_top_left_child_focus (xpaned, NULL);
+       gtk_xpaned_set_last_top_right_child_focus (xpaned, NULL);
+       gtk_xpaned_set_last_bottom_left_child_focus (xpaned, NULL);
+       gtk_xpaned_set_last_bottom_right_child_focus (xpaned, NULL);
+       gtk_xpaned_set_saved_focus (xpaned, NULL);
+       gtk_xpaned_set_first_xpaned (xpaned, NULL);
+  
+       if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+               (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void gtk_xpaned_map (GtkWidget* widget)
+{
+       GtkXPaned* xpaned = GTK_XPANED (widget);
+
+       gdk_window_show (xpaned->handle_east);
+       gdk_window_show (xpaned->handle_west);
+       gdk_window_show (xpaned->handle_north);
+       gdk_window_show (xpaned->handle_south);
+       gdk_window_show (xpaned->handle_middle);
+
+       GTK_WIDGET_CLASS (parent_class)->map (widget);
+}
+
+static void gtk_xpaned_unmap (GtkWidget* widget)
+{
+       GtkXPaned* xpaned = GTK_XPANED (widget);
+
+       gdk_window_hide (xpaned->handle_east);
+       gdk_window_hide (xpaned->handle_west);
+       gdk_window_hide (xpaned->handle_north);
+       gdk_window_hide (xpaned->handle_south);
+       gdk_window_hide (xpaned->handle_middle);
+
+       GTK_WIDGET_CLASS (parent_class)->unmap (widget);
+}
+
+static gboolean gtk_xpaned_expose (GtkWidget* widget,
+                                                                  GdkEventExpose* event)
+{
+       GtkXPaned* xpaned = GTK_XPANED (widget);
+       gint handle_size;
+       GdkRectangle horizontalClipArea;
+       GdkRectangle verticalClipArea;
+
+       /* determine size of handle(s) */
+       gtk_widget_style_get (widget, "handle-size", &handle_size, NULL);
+
+       /* I want the handle-"thickness" to be at least 3 */
+       g_assert (handle_size >= 3);
+
+       if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget) &&
+               xpaned->top_left_child && GTK_WIDGET_VISIBLE (xpaned->top_left_child) &&
+               xpaned->top_right_child && GTK_WIDGET_VISIBLE (xpaned->top_right_child) &&
+               xpaned->bottom_left_child && GTK_WIDGET_VISIBLE (xpaned->bottom_left_child) &&
+               xpaned->bottom_right_child && GTK_WIDGET_VISIBLE (xpaned->bottom_right_child))
+    {
+               GtkStateType state;
+
+               if (gtk_widget_is_focus (widget))
+                       state = GTK_STATE_SELECTED;
+               else if (xpaned->handle_prelit)
+                       state = GTK_STATE_PRELIGHT;
+               else
+                       state = GTK_WIDGET_STATE (widget);
+
+               horizontalClipArea.x = xpaned->handle_pos_west.x;
+               horizontalClipArea.y = xpaned->handle_pos_west.y;
+               horizontalClipArea.width = xpaned->handle_pos_west.width + handle_size + xpaned->handle_pos_east.width;
+               horizontalClipArea.height = handle_size;
+
+               verticalClipArea.x = xpaned->handle_pos_north.x;
+               verticalClipArea.y = xpaned->handle_pos_north.y;
+               verticalClipArea.width = handle_size;
+               verticalClipArea.height = xpaned->handle_pos_north.height + handle_size + xpaned->handle_pos_south.height;
+
+               gtk_paint_handle (widget->style,
+                                                 widget->window,
+                                                 state,
+                                                 GTK_SHADOW_NONE,
+                                                 &horizontalClipArea,
+                                                 widget,
+                                                 "paned",
+                                                 xpaned->handle_pos_east.x - handle_size - 256 / 2,
+                                                 xpaned->handle_pos_west.y + 1,
+                                                 256 + handle_size,
+                                                 handle_size - 2,
+                                                 /*xpaned->handle_pos_west.x,
+                                                 xpaned->handle_pos_west.y + 1,
+                                                 xpaned->handle_pos_west.width + handle_size + xpaned->handle_pos_east.width,
+                                                 handle_size - 2,*/
+                                                 GTK_ORIENTATION_HORIZONTAL);
+               gtk_paint_handle (widget->style,
+                                                 widget->window,
+                                                 state,
+                                                 GTK_SHADOW_NONE,
+                                                 &verticalClipArea,
+                                                 widget,
+                                                 "paned",
+                                                 xpaned->handle_pos_north.x + 1,
+                                                 xpaned->handle_pos_south.y - handle_size - 256 / 2,
+                                                 handle_size - 2,
+                                                 256 + handle_size,
+                                                 /*xpaned->handle_pos_north.x + 1,
+                                                 xpaned->handle_pos_north.y,
+                                                 handle_size - 2,
+                                                 xpaned->handle_pos_north.height + handle_size + xpaned->handle_pos_south.height,*/
+                                                 GTK_ORIENTATION_VERTICAL);
+       }
+
+       /* Chain up to draw children */
+       GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
+  
+       return FALSE;
+}
+
+static gboolean is_rtl (GtkXPaned* xpaned)
+{
+       if (gtk_widget_get_direction (GTK_WIDGET (xpaned)) == GTK_TEXT_DIR_RTL)
+               return TRUE;
+
+       return FALSE;
+}
+
+static void update_drag (GtkXPaned* xpaned)
+{
+       GdkPoint pos;
+       gint handle_size;
+       GtkRequisition size;
+  
+       gtk_widget_get_pointer (GTK_WIDGET (xpaned), &pos.x, &pos.y);
+
+       if (xpaned->in_drag_vert)
+       {
+               pos.y -= xpaned->drag_pos.y;
+
+               if (is_rtl (xpaned))
+           {
+                       gtk_widget_style_get (GTK_WIDGET (xpaned),
+                                                                 "handle-size", &handle_size,
+                                                                 NULL);
+      
+                       size.height = GTK_WIDGET (xpaned)->allocation.height - pos.y - handle_size;
+               }
+               else
+               {
+                       size.height = pos.y;
+               }
+
+               size.height -= GTK_CONTAINER (xpaned)->border_width;
+
+               size.height = CLAMP (size.height, xpaned->min_position.y, xpaned->max_position.y);
+
+               if (size.height != xpaned->top_left_child_size.height)
+                       gtk_xpaned_set_position_y (xpaned, size.height);
+       }
+
+       if (xpaned->in_drag_horiz)
+       {
+               pos.x -= xpaned->drag_pos.x;
+       
+               if (is_rtl (xpaned))
+           {
+                       gtk_widget_style_get (GTK_WIDGET (xpaned),
+                                                                 "handle-size", &handle_size,
+                                                                 NULL);
+
+                       size.width = GTK_WIDGET (xpaned)->allocation.width - pos.x - handle_size;
+               }
+               else
+               {
+                       size.width = pos.x;
+               }
+
+               size.width -= GTK_CONTAINER (xpaned)->border_width;
+
+               size.width = CLAMP (size.width, xpaned->min_position.x, xpaned->max_position.x);
+
+               if (size.width != xpaned->top_left_child_size.width)
+                       gtk_xpaned_set_position_x (xpaned, size.width);
+       }
+
+       if (xpaned->in_drag_vert_and_horiz)
+       {
+               pos.x -= xpaned->drag_pos.x;
+               pos.y -= xpaned->drag_pos.y;
+
+               if (is_rtl (xpaned))
+           {
+                       gtk_widget_style_get (GTK_WIDGET (xpaned),
+                                                                 "handle-size", &handle_size,
+                                                                 NULL);
+      
+                       size.width = GTK_WIDGET (xpaned)->allocation.width - pos.x - handle_size;
+                       size.height = GTK_WIDGET (xpaned)->allocation.height - pos.y - handle_size;
+               }
+               else
+               {
+                       size.width = pos.x;
+                       size.height = pos.y;
+               }
+
+               size.width -= GTK_CONTAINER (xpaned)->border_width;
+               size.height -= GTK_CONTAINER (xpaned)->border_width;
+
+               size.width = CLAMP (size.width, xpaned->min_position.x, xpaned->max_position.x);
+               size.height = CLAMP (size.height, xpaned->min_position.y, xpaned->max_position.y);
+
+               if (size.width != xpaned->top_left_child_size.width)
+                       gtk_xpaned_set_position_x (xpaned, size.width);
+
+               if (size.height != xpaned->top_left_child_size.height)
+                       gtk_xpaned_set_position_y (xpaned, size.height);
+       }
+}
+
+static gboolean gtk_xpaned_enter (GtkWidget* widget, GdkEventCrossing* event)
+{
+       GtkXPaned* xpaned = GTK_XPANED (widget);
+
+       if (xpaned->in_drag_vert ||
+               xpaned->in_drag_horiz ||
+               xpaned->in_drag_vert_and_horiz)
+               update_drag (xpaned);
+       else
+       {
+               xpaned->handle_prelit = TRUE;
+
+               gtk_widget_queue_draw_area (widget,
+                                                                       xpaned->handle_pos_east.x,
+                                                                       xpaned->handle_pos_east.y,
+                                                                       xpaned->handle_pos_east.width,
+                                                                       xpaned->handle_pos_east.height);
+
+               gtk_widget_queue_draw_area (widget,
+                                                                       xpaned->handle_pos_west.x,
+                                                                       xpaned->handle_pos_west.y,
+                                                                       xpaned->handle_pos_west.width,
+                                                                       xpaned->handle_pos_west.height);
+
+               gtk_widget_queue_draw_area (widget,
+                                                                       xpaned->handle_pos_north.x,
+                                                                       xpaned->handle_pos_north.y,
+                                                                       xpaned->handle_pos_north.width,
+                                                                       xpaned->handle_pos_north.height);
+
+               gtk_widget_queue_draw_area (widget,
+                                                                       xpaned->handle_pos_south.x,
+                                                                       xpaned->handle_pos_south.y,
+                                                                       xpaned->handle_pos_south.width,
+                                                                       xpaned->handle_pos_south.height);
+
+               gtk_widget_queue_draw_area (widget,
+                                                                       xpaned->handle_pos_middle.x,
+                                                                       xpaned->handle_pos_middle.y,
+                                                                       xpaned->handle_pos_middle.width,
+                                                                       xpaned->handle_pos_middle.height);
+       }
+
+       return TRUE;
+}
+
+static gboolean gtk_xpaned_leave (GtkWidget* widget, GdkEventCrossing* event)
+{
+       GtkXPaned* xpaned = GTK_XPANED (widget);
+
+       if (xpaned->in_drag_vert ||
+               xpaned->in_drag_horiz ||
+               xpaned->in_drag_vert_and_horiz)
+               update_drag (xpaned);
+       else
+       {
+               xpaned->handle_prelit = FALSE;
+
+               gtk_widget_queue_draw_area (widget,
+                                                                       xpaned->handle_pos_east.x,
+                                                                       xpaned->handle_pos_east.y,
+                                                                       xpaned->handle_pos_east.width,
+                                                                       xpaned->handle_pos_east.height);
+
+               gtk_widget_queue_draw_area (widget,
+                                                                       xpaned->handle_pos_west.x,
+                                                                       xpaned->handle_pos_west.y,
+                                                                       xpaned->handle_pos_west.width,
+                                                                       xpaned->handle_pos_west.height);
+
+               gtk_widget_queue_draw_area (widget,
+                                                                       xpaned->handle_pos_north.x,
+                                                                       xpaned->handle_pos_north.y,
+                                                                       xpaned->handle_pos_north.width,
+                                                                       xpaned->handle_pos_north.height);
+
+               gtk_widget_queue_draw_area (widget,
+                                                                       xpaned->handle_pos_south.x,
+                                                                       xpaned->handle_pos_south.y,
+                                                                       xpaned->handle_pos_south.width,
+                                                                       xpaned->handle_pos_south.height);
+
+               gtk_widget_queue_draw_area (widget,
+                                                                       xpaned->handle_pos_middle.x,
+                                                                       xpaned->handle_pos_middle.y,
+                                                                       xpaned->handle_pos_middle.width,
+                                                                       xpaned->handle_pos_middle.height);
+       }
+
+       return TRUE;
+}
+
+static gboolean gtk_xpaned_focus (GtkWidget* widget, GtkDirectionType direction)
+{
+       gboolean retval;
+
+       /* This is a hack, but how can this be done without
+       * excessive cut-and-paste from gtkcontainer.c?
+       */
+
+       GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS);
+       retval = (* GTK_WIDGET_CLASS (parent_class)->focus) (widget, direction);
+       GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
+
+  return retval;
+}
+
+static gboolean gtk_xpaned_button_press (GtkWidget* widget,
+                                                                                GdkEventButton* event)
+{
+       GtkXPaned* xpaned = GTK_XPANED (widget);
+
+       /* if any child is currently maximized, jump right back */
+       if (xpaned->maximized[GTK_XPANED_TOP_LEFT]    ||
+               xpaned->maximized[GTK_XPANED_TOP_RIGHT]   ||
+               xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] ||
+               xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT])
+               return FALSE;
+
+       /* if user is dragging the handles around */
+       if (!xpaned->in_drag_vert_and_horiz &&
+                        event->window != xpaned->handle_east &&
+                        event->window != xpaned->handle_west &&
+                        event->window != xpaned->handle_north &&
+                        event->window != xpaned->handle_south &&
+                        event->window == xpaned->handle_middle &&
+                        event->button == 1)
+       {
+               xpaned->in_drag_vert_and_horiz = TRUE;
+
+               /* We need a server grab here, not gtk_grab_add(), since
+               * we don't want to pass events on to the widget's children */
+               if (gdk_pointer_grab (xpaned->handle_middle,
+                                                         FALSE,
+                                                         GDK_POINTER_MOTION_HINT_MASK
+                                                         | GDK_BUTTON1_MOTION_MASK
+                                                         | GDK_BUTTON_RELEASE_MASK
+                                                         | GDK_ENTER_NOTIFY_MASK
+                                                         | GDK_LEAVE_NOTIFY_MASK,
+                                                         NULL,
+                                                         NULL,
+                                                         event->time) == GDK_GRAB_SUCCESS)
+               {
+               }
+
+               xpaned->drag_pos.x = event->x;
+               xpaned->drag_pos.y = event->y;
+
+               return TRUE;
+       }
+       else if (!xpaned->in_drag_vert &&
+               event->window == xpaned->handle_east &&
+               event->window != xpaned->handle_west &&
+               event->window != xpaned->handle_north &&
+               event->window != xpaned->handle_south &&
+               event->window != xpaned->handle_middle &&
+               event->button == 1)
+       {
+               xpaned->in_drag_vert = TRUE;
+
+               /* We need a server grab here, not gtk_grab_add(), since
+               * we don't want to pass events on to the widget's children */
+               if (gdk_pointer_grab (xpaned->handle_east,
+                                                         FALSE,
+                                                         GDK_POINTER_MOTION_HINT_MASK
+                                                         | GDK_BUTTON1_MOTION_MASK
+                                                         | GDK_BUTTON_RELEASE_MASK
+                                                         | GDK_ENTER_NOTIFY_MASK
+                                                         | GDK_LEAVE_NOTIFY_MASK,
+                                                         NULL,
+                                                         NULL,
+                                                         event->time) == GDK_GRAB_SUCCESS)
+               {
+               }
+
+               xpaned->drag_pos.y = event->y;
+
+               return TRUE;
+       }
+       else if (!xpaned->in_drag_vert &&
+                        event->window != xpaned->handle_east &&
+                        event->window == xpaned->handle_west &&
+                        event->window != xpaned->handle_north &&
+                        event->window != xpaned->handle_south &&
+                        event->window != xpaned->handle_middle &&
+                        event->button == 1)
+       {
+               xpaned->in_drag_vert = TRUE;
+
+               /* We need a server grab here, not gtk_grab_add(), since
+               * we don't want to pass events on to the widget's children */
+               if (gdk_pointer_grab (xpaned->handle_west,
+                                                         FALSE,
+                                                         GDK_POINTER_MOTION_HINT_MASK
+                                                         | GDK_BUTTON1_MOTION_MASK
+                                                         | GDK_BUTTON_RELEASE_MASK
+                                                         | GDK_ENTER_NOTIFY_MASK
+                                                         | GDK_LEAVE_NOTIFY_MASK,
+                                                         NULL,
+                                                         NULL,
+                                                         event->time) == GDK_GRAB_SUCCESS)
+               {
+               }
+
+               xpaned->drag_pos.y = event->y;
+
+               return TRUE;
+       }
+       else if (!xpaned->in_drag_horiz &&
+                        event->window != xpaned->handle_east &&
+                        event->window != xpaned->handle_west &&
+                        event->window == xpaned->handle_north &&
+                        event->window != xpaned->handle_south &&
+                        event->window != xpaned->handle_middle &&
+                        event->button == 1)
+       {
+               xpaned->in_drag_horiz = TRUE;
+
+               /* We need a server grab here, not gtk_grab_add(), since
+               * we don't want to pass events on to the widget's children */
+               if (gdk_pointer_grab (xpaned->handle_north,
+                                                         FALSE,
+                                                         GDK_POINTER_MOTION_HINT_MASK
+                                                         | GDK_BUTTON1_MOTION_MASK
+                                                         | GDK_BUTTON_RELEASE_MASK
+                                                         | GDK_ENTER_NOTIFY_MASK
+                                                         | GDK_LEAVE_NOTIFY_MASK,
+                                                         NULL,
+                                                         NULL,
+                                                         event->time) == GDK_GRAB_SUCCESS)
+               {
+               }
+
+               xpaned->drag_pos.x = event->x;
+
+               return TRUE;
+       }
+       else if (!xpaned->in_drag_horiz &&
+                        event->window != xpaned->handle_east &&
+                        event->window != xpaned->handle_west &&
+                        event->window != xpaned->handle_north &&
+                        event->window == xpaned->handle_south &&
+                        event->window != xpaned->handle_middle &&
+                        event->button == 1)
+       {
+               xpaned->in_drag_horiz = TRUE;
+
+               /* We need a server grab here, not gtk_grab_add(), since
+               * we don't want to pass events on to the widget's children */
+               if (gdk_pointer_grab (xpaned->handle_south,
+                                                         FALSE,
+                                                         GDK_POINTER_MOTION_HINT_MASK
+                                                         | GDK_BUTTON1_MOTION_MASK
+                                                         | GDK_BUTTON_RELEASE_MASK
+                                                         | GDK_ENTER_NOTIFY_MASK
+                                                         | GDK_LEAVE_NOTIFY_MASK,
+                                                         NULL,
+                                                         NULL,
+                                                         event->time) == GDK_GRAB_SUCCESS)
+               {
+               }
+
+               xpaned->drag_pos.x = event->x;
+
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static gboolean gtk_xpaned_button_release (GtkWidget* widget,
+                                                                                  GdkEventButton* event)
+{
+       GtkXPaned* xpaned = GTK_XPANED (widget);
+
+       if (xpaned->in_drag_vert && (event->button == 1))
+       {
+               xpaned->in_drag_vert = FALSE;
+               xpaned->drag_pos.y = -1;
+               xpaned->position_set = TRUE;
+               gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
+                                                                       event->time);
+               return TRUE;
+    }
+       else if (xpaned->in_drag_horiz && (event->button == 1))
+       {
+               xpaned->in_drag_horiz = FALSE;
+               xpaned->drag_pos.x = -1;
+               xpaned->position_set = TRUE;
+               gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
+                                                                       event->time);
+               return TRUE;
+    }
+       else if (xpaned->in_drag_vert_and_horiz && (event->button == 1))
+       {
+               xpaned->in_drag_vert_and_horiz = FALSE;
+               xpaned->drag_pos.x = -1;
+               xpaned->drag_pos.y = -1;
+               xpaned->position_set = TRUE;
+               gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
+                                                                       event->time);
+               return TRUE;
+    }
+
+       return FALSE;
+}
+
+static gboolean gtk_xpaned_motion (GtkWidget* widget, GdkEventMotion* event)
+{
+       GtkXPaned* xpaned = GTK_XPANED (widget);
+
+       if (xpaned->in_drag_vert ||
+               xpaned->in_drag_horiz ||
+               xpaned->in_drag_vert_and_horiz)
+
+       {
+               update_drag (xpaned);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+void gtk_xpaned_add_top_left (GtkXPaned* xpaned, GtkWidget *widget)
+{
+       gtk_xpaned_pack_top_left (xpaned, widget, FALSE, TRUE);
+}
+
+void gtk_xpaned_add_top_right (GtkXPaned* xpaned, GtkWidget *widget)
+{
+       gtk_xpaned_pack_top_right (xpaned, widget, FALSE, TRUE);
+}
+
+void gtk_xpaned_add_bottom_left (GtkXPaned* xpaned, GtkWidget *widget)
+{
+       gtk_xpaned_pack_bottom_left (xpaned, widget, FALSE, TRUE);
+}
+
+void gtk_xpaned_add_bottom_right (GtkXPaned* xpaned, GtkWidget *widget)
+{
+       gtk_xpaned_pack_bottom_right (xpaned, widget, FALSE, TRUE);
+}
+
+void gtk_xpaned_pack_top_left (GtkXPaned* xpaned,
+                                                          GtkWidget* child,
+                                                          gboolean   resize,
+                                                          gboolean   shrink)
+{
+       g_return_if_fail (GTK_IS_XPANED (xpaned));
+       g_return_if_fail (GTK_IS_WIDGET (child));
+
+       if (!xpaned->top_left_child)
+       {
+               xpaned->top_left_child = child;
+               xpaned->top_left_child_resize = resize;
+               xpaned->top_left_child_shrink = shrink;
+
+               gtk_widget_set_parent (child, GTK_WIDGET (xpaned));
+       }
+}
+
+void gtk_xpaned_pack_top_right (GtkXPaned* xpaned,
+                                                               GtkWidget* child,
+                                                               gboolean   resize,
+                                                               gboolean   shrink)
+{
+       g_return_if_fail (GTK_IS_XPANED (xpaned));
+       g_return_if_fail (GTK_IS_WIDGET (child));
+
+       if (!xpaned->top_right_child)
+       {
+               xpaned->top_right_child = child;
+               xpaned->top_right_child_resize = resize;
+               xpaned->top_right_child_shrink = shrink;
+
+               gtk_widget_set_parent (child, GTK_WIDGET (xpaned));
+       }
+}
+
+void gtk_xpaned_pack_bottom_left (GtkXPaned* xpaned,
+                                                                 GtkWidget* child,
+                                                                 gboolean   resize,
+                                                                 gboolean   shrink)
+{
+       g_return_if_fail (GTK_IS_XPANED (xpaned));
+       g_return_if_fail (GTK_IS_WIDGET (child));
+
+       if (!xpaned->bottom_left_child)
+       {
+               xpaned->bottom_left_child = child;
+               xpaned->bottom_left_child_resize = resize;
+               xpaned->bottom_left_child_shrink = shrink;
+
+               gtk_widget_set_parent (child, GTK_WIDGET (xpaned));
+       }
+}
+
+void gtk_xpaned_pack_bottom_right (GtkXPaned* xpaned,
+                                                                  GtkWidget* child,
+                                                                  gboolean   resize,
+                                                                  gboolean   shrink)
+{
+       g_return_if_fail (GTK_IS_XPANED (xpaned));
+       g_return_if_fail (GTK_IS_WIDGET (child));
+
+       if (!xpaned->bottom_right_child)
+       {
+               xpaned->bottom_right_child = child;
+               xpaned->bottom_right_child_resize = resize;
+               xpaned->bottom_right_child_shrink = shrink;
+
+               gtk_widget_set_parent (child, GTK_WIDGET (xpaned));
+       }
+}
+
+static void gtk_xpaned_add (GtkContainer* container, GtkWidget* widget)
+{
+       GtkXPaned* xpaned;
+
+       g_return_if_fail (GTK_IS_XPANED (container));
+
+       xpaned = GTK_XPANED (container);
+
+       if (!xpaned->top_left_child)
+               gtk_xpaned_add_top_left (xpaned, widget);
+       else if (!xpaned->top_right_child)
+               gtk_xpaned_add_top_right (xpaned, widget);
+       else if (!xpaned->bottom_left_child)
+               gtk_xpaned_add_bottom_left (xpaned, widget);
+       else if (!xpaned->bottom_right_child)
+               gtk_xpaned_add_bottom_right (xpaned, widget);
+       else
+               g_warning ("GtkXPaned cannot have more than 4 children\n");
+}
+
+static void gtk_xpaned_remove (GtkContainer* container, GtkWidget* widget)
+{
+       GtkXPaned* xpaned;
+       gboolean was_visible;
+
+       xpaned = GTK_XPANED (container);
+       was_visible = GTK_WIDGET_VISIBLE (widget);
+
+       if (xpaned->top_left_child == widget)
+       {
+               gtk_widget_unparent (widget);
+
+               xpaned->top_left_child = NULL;
+
+               if (was_visible && GTK_WIDGET_VISIBLE (container))
+                       gtk_widget_queue_resize (GTK_WIDGET (container));
+       }
+       else if (xpaned->top_right_child == widget)
+       {
+               gtk_widget_unparent (widget);
+
+               xpaned->top_right_child = NULL;
+
+               if (was_visible && GTK_WIDGET_VISIBLE (container))
+                       gtk_widget_queue_resize (GTK_WIDGET (container));
+       }
+       else if (xpaned->bottom_left_child == widget)
+       {
+               gtk_widget_unparent (widget);
+
+               xpaned->bottom_left_child = NULL;
+
+               if (was_visible && GTK_WIDGET_VISIBLE (container))
+                       gtk_widget_queue_resize (GTK_WIDGET (container));
+       }
+       else if (xpaned->bottom_right_child == widget)
+       {
+               gtk_widget_unparent (widget);
+
+               xpaned->bottom_right_child = NULL;
+
+               if (was_visible && GTK_WIDGET_VISIBLE (container))
+                       gtk_widget_queue_resize (GTK_WIDGET (container));
+       }
+       else
+               g_warning ("GtkXPaned has no more children attached\n");
+
+}
+
+static void gtk_xpaned_forall (GtkContainer* container,
+                                                          gboolean      include_internals,
+                                                          GtkCallback   callback,
+                                                          gpointer      callback_data)
+{
+       GtkXPaned* xpaned;
+
+       g_return_if_fail (callback != NULL);
+
+       xpaned = GTK_XPANED (container);
+
+       if (xpaned->top_left_child)
+       (*callback) (xpaned->top_left_child, callback_data);
+       if (xpaned->top_right_child)
+               (*callback) (xpaned->top_right_child, callback_data);
+       if (xpaned->bottom_left_child)
+       (*callback) (xpaned->bottom_left_child, callback_data);
+       if (xpaned->bottom_right_child)
+               (*callback) (xpaned->bottom_right_child, callback_data);
+}
+
+/**
+ * gtk_xpaned_get_position_x:
+ * @paned: a #GtkXPaned widget
+ * 
+ * Obtains the x-position of the divider.
+ * 
+ * Return value: x-position of the divider
+ **/
+gint gtk_xpaned_get_position_x (GtkXPaned* xpaned)
+{
+       g_return_val_if_fail (GTK_IS_XPANED (xpaned), 0);
+
+       return xpaned->top_left_child_size.width;
+}
+
+/**
+ * gtk_xpaned_get_position_y:
+ * @paned: a #GtkXPaned widget
+ * 
+ * Obtains the y-position of the divider.
+ * 
+ * Return value: y-position of the divider
+ **/
+gint gtk_xpaned_get_position_y (GtkXPaned* xpaned)
+{
+       g_return_val_if_fail (GTK_IS_XPANED (xpaned), 0);
+
+       return xpaned->top_left_child_size.height;
+}
+
+/**
+ * gtk_xpaned_set_position_x:
+ * @paned: a #GtkXPaned widget
+ * @xposition: pixel x-position of divider, a negative values
+ *                        of a component mean that the position is unset.
+ * 
+ * Sets the x-position of the divider between the four panes.
+ **/
+void gtk_xpaned_set_position_x (GtkXPaned* xpaned, gint xposition)
+{
+       GObject* object;
+  
+       g_return_if_fail (GTK_IS_XPANED (xpaned));
+
+       /* if any child is currently maximized, jump right back */
+       if (xpaned->maximized[GTK_XPANED_TOP_LEFT]    ||
+               xpaned->maximized[GTK_XPANED_TOP_RIGHT]   ||
+               xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] ||
+               xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT])
+               return;
+
+       object = G_OBJECT (xpaned);
+
+       if (xposition >= 0)
+       {
+               /* We don't clamp here - the assumption is that
+               * if the total allocation changes at the same time
+               * as the position, the position set is with reference
+               * to the new total size. If only the position changes,
+               * then clamping will occur in gtk_paned_compute_position()
+               */
+
+               xpaned->top_left_child_size.width = xposition;
+               xpaned->position_set = TRUE;
+       }
+       else
+       {
+               xpaned->position_set = FALSE;
+       }
+
+       g_object_freeze_notify (object);
+       g_object_notify (object, "x-position");
+       g_object_notify (object, "position-set");
+       g_object_thaw_notify (object);
+
+       gtk_widget_queue_resize (GTK_WIDGET (xpaned));
+}
+
+/**
+ * gtk_xpaned_set_position_y:
+ * @paned: a #GtkXPaned widget
+ * @yposition: pixel y-position of divider, a negative values
+ *                        of a component mean that the position is unset.
+ * 
+ * Sets the y-position of the divider between the four panes.
+ **/
+void gtk_xpaned_set_position_y (GtkXPaned* xpaned, gint yposition)
+{
+       GObject* object;
+  
+       g_return_if_fail (GTK_IS_XPANED (xpaned));
+
+       /* if any child is currently maximized, jump right back */
+       if (xpaned->maximized[GTK_XPANED_TOP_LEFT]    ||
+               xpaned->maximized[GTK_XPANED_TOP_RIGHT]   ||
+               xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] ||
+               xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT])
+               return;
+
+       object = G_OBJECT (xpaned);
+
+       if (yposition >= 0)
+       {
+               /* We don't clamp here - the assumption is that
+               * if the total allocation changes at the same time
+               * as the position, the position set is with reference
+               * to the new total size. If only the position changes,
+               * then clamping will occur in gtk_paned_compute_position()
+               */
+
+               xpaned->top_left_child_size.height = yposition;
+               xpaned->position_set = TRUE;
+       }
+       else
+       {
+               xpaned->position_set = FALSE;
+       }
+
+       g_object_freeze_notify (object);
+       g_object_notify (object, "y-position");
+       g_object_notify (object, "position-set");
+       g_object_thaw_notify (object);
+
+       gtk_widget_queue_resize (GTK_WIDGET (xpaned));
+}
+
+/* this call is private and only intended for internal use! */
+void gtk_xpaned_save_unmaximized_x (GtkXPaned* xpaned)
+{
+       xpaned->unmaximized_position.x = gtk_xpaned_get_position_x (xpaned);
+}
+
+/* this call is private and only intended for internal use! */
+void gtk_xpaned_save_unmaximized_y (GtkXPaned* xpaned)
+{
+       xpaned->unmaximized_position.y = gtk_xpaned_get_position_y (xpaned);
+}
+
+/* this call is private and only intended for internal use! */
+gint gtk_xpaned_fetch_unmaximized_x (GtkXPaned* xpaned)
+{
+       return xpaned->unmaximized_position.x;
+}
+
+/* this call is private and only intended for internal use! */
+gint gtk_xpaned_fetch_unmaximized_y (GtkXPaned* xpaned)
+{
+       return xpaned->unmaximized_position.y;
+}
+
+/**
+ * gtk_xpaned_get_top_left_child:
+ * @xpaned: a #GtkXPaned widget
+ * 
+ * Obtains the top-left child of the xpaned widget.
+ * 
+ * Return value: top-left child, or %NULL if it is not set.
+ *
+ * Since: 2.4
+ **/
+GtkWidget* gtk_xpaned_get_top_left_child (GtkXPaned* xpaned)
+{
+       g_return_val_if_fail (GTK_IS_XPANED (xpaned), NULL);
+
+       return xpaned->top_left_child;
+}
+
+/**
+ * gtk_xpaned_get_top_right_child:
+ * @xpaned: a #GtkXPaned widget
+ * 
+ * Obtains the top-right child of the xpaned widget.
+ * 
+ * Return value: top-right child, or %NULL if it is not set.
+ *
+ * Since: 2.4
+ **/
+GtkWidget* gtk_xpaned_get_top_right_child (GtkXPaned* xpaned)
+{
+       g_return_val_if_fail (GTK_IS_XPANED (xpaned), NULL);
+
+       return xpaned->top_right_child;
+}
+
+/**
+ * gtk_xpaned_get_bottom_left_child:
+ * @xpaned: a #GtkXPaned widget
+ * 
+ * Obtains the bottom-left child of the xpaned widget.
+ * 
+ * Return value: bottom-left child, or %NULL if it is not set.
+ *
+ * Since: 2.4
+ **/
+GtkWidget* gtk_xpaned_get_bottom_left_child (GtkXPaned* xpaned)
+{
+       g_return_val_if_fail (GTK_IS_XPANED (xpaned), NULL);
+
+       return xpaned->bottom_left_child;
+}
+
+/**
+ * gtk_xpaned_get_bottom_right_child:
+ * @xpaned: a #GtkXPaned widget
+ * 
+ * Obtains the bottom-right child of the xpaned widget.
+ * 
+ * Return value: bottom-right child, or %NULL if it is not set.
+ *
+ * Since: 2.4
+ **/
+GtkWidget* gtk_xpaned_get_bottom_right_child (GtkXPaned* xpaned)
+{
+       g_return_val_if_fail (GTK_IS_XPANED (xpaned), NULL);
+
+       return xpaned->bottom_right_child;
+}
+
+gboolean gtk_xpaned_maximize_top_left (GtkXPaned* xpaned, gboolean maximize)
+{
+       if (maximize)
+       {
+               /* see if any child is already maximized */
+               if (!xpaned->maximized[GTK_XPANED_TOP_LEFT] &&
+                       !xpaned->maximized[GTK_XPANED_TOP_RIGHT] &&
+                       !xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] &&
+                       !xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT])
+               {
+                       /* save current position */
+                       gtk_xpaned_save_unmaximized_x (xpaned);
+                       gtk_xpaned_save_unmaximized_y (xpaned);
+
+                       /* set new maximized position */
+                       gtk_xpaned_set_position_x (xpaned, xpaned->max_position.x);
+                       gtk_xpaned_set_position_y (xpaned, xpaned->max_position.y);
+
+                       /* mark maximized flag for top-left child */
+                       xpaned->maximized[GTK_XPANED_TOP_LEFT] = TRUE;
+
+                       return TRUE;
+               }
+               /* already one child maximized, report error */
+               else
+                       return FALSE;
+       }
+       else
+       {
+               /* verify that top-left child is really currently maximized */
+               if (xpaned->maximized[GTK_XPANED_TOP_LEFT])
+               {
+                       /* clear maximized flat for top-left child */
+                       xpaned->maximized[GTK_XPANED_TOP_LEFT] = FALSE;
+
+                       /* restore unmaximized position */
+                       gtk_xpaned_set_position_x (xpaned, gtk_xpaned_fetch_unmaximized_x (xpaned));
+                       gtk_xpaned_set_position_y (xpaned, gtk_xpaned_fetch_unmaximized_y (xpaned));
+
+                       return TRUE;
+               }
+               /* top-left child is currently not maximized, report error */
+               else
+                       return FALSE;
+       }
+}
+
+gboolean gtk_xpaned_maximize_top_right (GtkXPaned* xpaned, gboolean maximize)
+{
+       if (maximize)
+       {
+               /* see if any child is already maximized */
+               if (!xpaned->maximized[GTK_XPANED_TOP_LEFT] &&
+                       !xpaned->maximized[GTK_XPANED_TOP_RIGHT] &&
+                       !xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] &&
+                       !xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT])
+               {
+                       /* save current position */
+                       gtk_xpaned_save_unmaximized_x (xpaned);
+                       gtk_xpaned_save_unmaximized_y (xpaned);
+
+                       /* set new maximized position */
+                       gtk_xpaned_set_position_x (xpaned, xpaned->min_position.x);
+                       gtk_xpaned_set_position_y (xpaned, xpaned->max_position.y);
+               
+                       /* mark maximized flag for top-right child */
+                       xpaned->maximized[GTK_XPANED_TOP_RIGHT] = TRUE;
+
+                       return TRUE;
+               }
+               /* already one child maximized, report error */
+               else
+                       return FALSE;
+       }
+       else
+       {
+               /* verify that top-right child is really currently maximized */
+               if (xpaned->maximized[GTK_XPANED_TOP_RIGHT])
+               {
+                       /* clear maximized flat for top-right child */
+                       xpaned->maximized[GTK_XPANED_TOP_RIGHT] = FALSE;
+
+                       /* restore unmaximized position */
+                       gtk_xpaned_set_position_x (xpaned, gtk_xpaned_fetch_unmaximized_x (xpaned));
+                       gtk_xpaned_set_position_y (xpaned, gtk_xpaned_fetch_unmaximized_y (xpaned));
+
+                       return TRUE;
+               }
+               /* top-right child is currently not maximized, report error */
+               else
+                       return FALSE;
+       }
+}
+
+gboolean gtk_xpaned_maximize_bottom_left (GtkXPaned* xpaned, gboolean maximize)
+{
+       if (maximize)
+       {
+               /* see if any child is already maximized */
+               if (!xpaned->maximized[GTK_XPANED_TOP_LEFT] &&
+                       !xpaned->maximized[GTK_XPANED_TOP_RIGHT] &&
+                       !xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] &&
+                       !xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT])
+               {
+                       /* save current position */
+                       gtk_xpaned_save_unmaximized_x (xpaned);
+                       gtk_xpaned_save_unmaximized_y (xpaned);
+
+                       /* set new maximized position */
+                       gtk_xpaned_set_position_x (xpaned, xpaned->max_position.x);
+                       gtk_xpaned_set_position_y (xpaned, xpaned->min_position.y);
+
+                       /* mark maximized flag for bottom-left child */
+                       xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] = TRUE;
+
+                       return TRUE;
+               }
+               /* already one child maximized, report error */
+               else
+                       return FALSE;
+       }
+       else
+       {
+               /* verify that bottom-left child is really currently maximized */
+               if (xpaned->maximized[GTK_XPANED_BOTTOM_LEFT])
+               {
+                       /* clear maximized flat for bottom-left child */
+                       xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] = FALSE;
+
+                       /* restore unmaximized position */
+                       gtk_xpaned_set_position_x (xpaned, gtk_xpaned_fetch_unmaximized_x (xpaned));
+                       gtk_xpaned_set_position_y (xpaned, gtk_xpaned_fetch_unmaximized_y (xpaned));
+
+                       return TRUE;
+               }
+               /* bottom-left child is currently not maximized, report error */
+               else
+                       return FALSE;
+       }
+}
+
+gboolean gtk_xpaned_maximize_bottom_right (GtkXPaned* xpaned, gboolean maximize)
+{
+       if (maximize)
+       {
+               /* see if any child is already maximized */
+               if (!xpaned->maximized[GTK_XPANED_TOP_LEFT] &&
+                       !xpaned->maximized[GTK_XPANED_TOP_RIGHT] &&
+                       !xpaned->maximized[GTK_XPANED_BOTTOM_LEFT] &&
+                       !xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT])
+               {
+                       /* save current position */
+                       gtk_xpaned_save_unmaximized_x (xpaned);
+                       gtk_xpaned_save_unmaximized_y (xpaned);
+
+                       /* set new maximized position */
+                       gtk_xpaned_set_position_x (xpaned, xpaned->min_position.x);
+                       gtk_xpaned_set_position_y (xpaned, xpaned->min_position.y);
+
+                       /* mark maximized flag for bottom-right child */
+                       xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT] = TRUE;
+
+                       return TRUE;
+               }
+               /* already one child maximized, report error */
+               else
+                       return FALSE;
+       }
+       else
+       {
+               /* verify that bottom-right child is really currently maximized */
+               if (xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT])
+               {
+                       /* clear maximized flat for bottom-right child */
+                       xpaned->maximized[GTK_XPANED_BOTTOM_RIGHT] = FALSE;
+
+                       /* restore unmaximized position */
+                       gtk_xpaned_set_position_x (xpaned, gtk_xpaned_fetch_unmaximized_x (xpaned));
+                       gtk_xpaned_set_position_y (xpaned, gtk_xpaned_fetch_unmaximized_y (xpaned));
+
+                       return TRUE;
+               }
+               /* bottom-right child is currently not maximized, report error */
+               else
+                       return FALSE;
+       }
+}
+
+void
+gtk_xpaned_compute_position (GtkXPaned* xpaned,
+                            const GtkAllocation* allocation,
+                            GtkRequisition* top_left_child_req,
+                            GtkRequisition* top_right_child_req,
+                            GtkRequisition* bottom_left_child_req,
+                            GtkRequisition* bottom_right_child_req)
+{
+  GdkPoint old_position;
+  GdkPoint old_min_position;
+       GdkPoint old_max_position;
+       gint handle_size;
+       gint border_width = GTK_CONTAINER (xpaned)->border_width;
+       float fX;
+       float fY;
+
+       g_return_if_fail (GTK_IS_XPANED (xpaned));
+
+       old_position.x = xpaned->top_left_child_size.width;
+       old_position.y = xpaned->top_left_child_size.height;
+       old_min_position.x = xpaned->min_position.x;
+       old_min_position.y = xpaned->min_position.y;
+       old_max_position.x = xpaned->max_position.x;
+       old_max_position.y = xpaned->max_position.y;
+
+       fX = 100.0f * (float) old_position.x / (float) allocation->width;
+       fY = 100.0f * (float) old_position.y / (float) allocation->height;
+
+       xpaned->min_position.x = xpaned->top_left_child_shrink ? 0 : top_left_child_req->width;
+       xpaned->min_position.y = xpaned->top_left_child_shrink ? 0 : top_left_child_req->height;
+
+       gtk_widget_style_get (GTK_WIDGET (xpaned), "handle-size", &handle_size, NULL);
+
+       xpaned->max_position.x = allocation->width - 2 * border_width - handle_size;
+       xpaned->max_position.y = allocation->height - 2 * border_width - handle_size;
+       if (!xpaned->top_left_child_shrink)
+               xpaned->max_position.x = MAX (1, xpaned->max_position.x - top_left_child_req->width);
+       xpaned->max_position.x = MAX (xpaned->min_position.x, xpaned->max_position.x);
+
+       if (!xpaned->position_set)
+       {
+               if (xpaned->top_left_child_resize && !xpaned->top_right_child_resize)
+               {
+                       xpaned->top_left_child_size.width = MAX (0, allocation->width - top_right_child_req->width);
+                       xpaned->top_left_child_size.height = MAX (0, allocation->height - top_right_child_req->height);
+               }
+               else if (!xpaned->top_left_child_resize && xpaned->top_right_child_resize)
+               {
+                       xpaned->top_left_child_size.width = top_left_child_req->width;
+                       xpaned->top_left_child_size.height = top_left_child_req->height;
+               }
+               else if (top_left_child_req->width + top_right_child_req->width != 0)
+               {
+                       xpaned->top_left_child_size.width = allocation->width * ((gdouble)top_left_child_req->width / (top_left_child_req->width + top_right_child_req->width)) + 0.5;
+               }
+               else if (top_left_child_req->height + top_right_child_req->height != 0)
+               {
+                       xpaned->top_left_child_size.height = allocation->height * ((gdouble)top_left_child_req->height / (top_left_child_req->height + top_right_child_req->height)) + 0.5;
+               }
+               else
+               {
+                       xpaned->top_left_child_size.width = allocation->width * 0.5 + 0.5;
+                       xpaned->top_left_child_size.height = allocation->height * 0.5 + 0.5;
+               }
+       }
+       else
+       {
+               /* If the position was set before the initial allocation.
+               ** (paned->last_allocation <= 0) just clamp it and leave it. */
+               if (xpaned->last_allocation.width > 0)
+               {
+                       if (xpaned->top_left_child_resize && !xpaned->top_right_child_resize)
+                       {
+                               xpaned->top_left_child_size.width += allocation->width
+                                                                                                        - xpaned->last_allocation.width;
+
+                               xpaned->top_left_child_size.height += allocation->height
+                                                                                                         - xpaned->last_allocation.height;
+                       }
+                       else if (!(!xpaned->top_left_child_resize && xpaned->top_right_child_resize))
+                       {
+                               xpaned->top_left_child_size.width = allocation->width
+                                                                                                       * ((gdouble) xpaned->top_left_child_size.width / (xpaned->last_allocation.width))
+                                                                                                       + 0.5;
+
+                               xpaned->top_left_child_size.height = allocation->height
+                                                                                                        * ((gdouble) xpaned->top_left_child_size.height / (xpaned->last_allocation.height))
+                                                                                                        + 0.5;
+                       }
+               }
+               if (xpaned->last_allocation.height > 0)
+               {
+                       if (xpaned->top_left_child_resize && !xpaned->top_right_child_resize)
+                       {
+                               xpaned->top_left_child_size.width += allocation->width - xpaned->last_allocation.width;
+                               xpaned->top_left_child_size.height += allocation->height - xpaned->last_allocation.height;
+                       }
+                       else if (!(!xpaned->top_left_child_resize && xpaned->top_right_child_resize))
+                       {
+                               xpaned->top_left_child_size.width = allocation->width * ((gdouble) xpaned->top_left_child_size.width / (xpaned->last_allocation.width)) + 0.5;
+                               xpaned->top_left_child_size.height = allocation->height * ((gdouble) xpaned->top_left_child_size.height / (xpaned->last_allocation.height)) + 0.5;
+                       }
+               }
+
+    }
+
+       xpaned->top_left_child_size.width = CLAMP (xpaned->top_left_child_size.width,
+                                                                                          xpaned->min_position.x,
+                                                                                          xpaned->max_position.x);
+       xpaned->top_left_child_size.height = CLAMP (xpaned->top_left_child_size.height,
+                                                                                               xpaned->min_position.y,
+                                                                                               xpaned->max_position.y);
+
+       xpaned->top_right_child_size.width = CLAMP (xpaned->top_right_child_size.width,
+                                                                                               xpaned->min_position.x,
+                                                                                               xpaned->max_position.x);
+       xpaned->top_right_child_size.height = CLAMP (xpaned->top_right_child_size.height,
+                                                                                                xpaned->min_position.y,
+                                                                                                xpaned->max_position.y);
+
+       xpaned->bottom_left_child_size.width = CLAMP (xpaned->bottom_left_child_size.width,
+                                                                                                 xpaned->min_position.x,
+                                                                                                 xpaned->max_position.x);
+       xpaned->bottom_left_child_size.height = CLAMP (xpaned->bottom_left_child_size.height,
+                                                                                                  xpaned->min_position.y,
+                                                                                                  xpaned->max_position.y);
+
+       xpaned->bottom_right_child_size.width = CLAMP (xpaned->bottom_right_child_size.width,
+                                                                                                  xpaned->min_position.x,
+                                                                                                  xpaned->max_position.x);
+       xpaned->bottom_right_child_size.height = CLAMP (xpaned->bottom_right_child_size.height,
+                                                                                                       xpaned->min_position.y,
+                                                                                                       xpaned->max_position.y);
+
+       gtk_widget_set_child_visible (xpaned->top_left_child, TRUE);
+       gtk_widget_set_child_visible (xpaned->top_right_child, TRUE);
+       gtk_widget_set_child_visible (xpaned->bottom_left_child, TRUE);
+       gtk_widget_set_child_visible (xpaned->bottom_right_child, TRUE);
+
+       g_object_freeze_notify (G_OBJECT (xpaned));
+
+       if (xpaned->top_left_child_size.width != old_position.x)
+               g_object_notify (G_OBJECT (xpaned), "x-position");
+       if (xpaned->top_left_child_size.height != old_position.y)
+               g_object_notify (G_OBJECT (xpaned), "y-position");
+
+       if (xpaned->top_right_child_size.width != old_position.x)
+               g_object_notify (G_OBJECT (xpaned), "x-position");
+       if (xpaned->top_right_child_size.height != old_position.y)
+               g_object_notify (G_OBJECT (xpaned), "y-position");
+
+       if (xpaned->bottom_left_child_size.width != old_position.x)
+               g_object_notify (G_OBJECT (xpaned), "x-position");
+       if (xpaned->bottom_left_child_size.height != old_position.y)
+               g_object_notify (G_OBJECT (xpaned), "y-position");
+
+       if (xpaned->bottom_right_child_size.width != old_position.x)
+               g_object_notify (G_OBJECT (xpaned), "x-position");
+       if (xpaned->bottom_right_child_size.height != old_position.y)
+               g_object_notify (G_OBJECT (xpaned), "y-position");
+
+       if (xpaned->min_position.x != old_min_position.x)
+               g_object_notify (G_OBJECT (xpaned), "min-x-position");
+       if (xpaned->min_position.y != old_min_position.y)
+               g_object_notify (G_OBJECT (xpaned), "min-y-position");
+
+       if (xpaned->max_position.x != old_max_position.x)
+       g_object_notify (G_OBJECT (xpaned), "max-y-position");
+       if (xpaned->max_position.y != old_max_position.y)
+       g_object_notify (G_OBJECT (xpaned), "max-y-position");
+
+       g_object_thaw_notify (G_OBJECT (xpaned));
+
+       xpaned->last_allocation.width = allocation->width;
+       xpaned->last_allocation.height = allocation->height;
+
+       fX = 100.0f * (float) old_position.x / (float) allocation->width;
+       fY = 100.0f * (float) old_position.y / (float) allocation->height;
+}
+
+static void gtk_xpaned_set_saved_focus (GtkXPaned* xpaned, GtkWidget* widget)
+{
+       if (xpaned->priv->saved_focus)
+               g_object_remove_weak_pointer (G_OBJECT (xpaned->priv->saved_focus),
+                                                                         (gpointer *)&(xpaned->priv->saved_focus));
+
+       xpaned->priv->saved_focus = widget;
+
+       if (xpaned->priv->saved_focus)
+               g_object_add_weak_pointer (G_OBJECT (xpaned->priv->saved_focus),
+                                                                  (gpointer *)&(xpaned->priv->saved_focus));
+}
+
+static void gtk_xpaned_set_first_xpaned (GtkXPaned* xpaned,
+                                                                                GtkXPaned* first_xpaned)
+{
+       if (xpaned->priv->first_xpaned)
+               g_object_remove_weak_pointer (G_OBJECT (xpaned->priv->first_xpaned),
+                                                                         (gpointer *)&(xpaned->priv->first_xpaned));
+
+       xpaned->priv->first_xpaned = first_xpaned;
+
+       if (xpaned->priv->first_xpaned)
+               g_object_add_weak_pointer (G_OBJECT (xpaned->priv->first_xpaned),
+                                                                  (gpointer *)&(xpaned->priv->first_xpaned));
+}
+
+static void gtk_xpaned_set_last_top_left_child_focus (GtkXPaned* xpaned,
+                                                                                                         GtkWidget* widget)
+{
+       if (xpaned->last_top_left_child_focus)
+               g_object_remove_weak_pointer (G_OBJECT (xpaned->last_top_left_child_focus),
+                                                                         (gpointer *)&(xpaned->last_top_left_child_focus));
+
+       xpaned->last_top_left_child_focus = widget;
+
+       if (xpaned->last_top_left_child_focus)
+               g_object_add_weak_pointer (G_OBJECT (xpaned->last_top_left_child_focus),
+                                                                  (gpointer *)&(xpaned->last_top_left_child_focus));
+}
+
+static void gtk_xpaned_set_last_top_right_child_focus (GtkXPaned* xpaned,
+                                                                                                          GtkWidget *widget)
+{
+       if (xpaned->last_top_right_child_focus)
+               g_object_remove_weak_pointer (G_OBJECT (xpaned->last_top_right_child_focus),
+                                                                         (gpointer *)&(xpaned->last_top_right_child_focus));
+
+       xpaned->last_top_right_child_focus = widget;
+
+       if (xpaned->last_top_right_child_focus)
+               g_object_add_weak_pointer (G_OBJECT (xpaned->last_top_right_child_focus),
+                                                                  (gpointer *)&(xpaned->last_top_right_child_focus));
+}
+
+static void gtk_xpaned_set_last_bottom_left_child_focus (GtkXPaned* xpaned,
+                                                                                                                GtkWidget *widget)
+{
+       if (xpaned->last_bottom_left_child_focus)
+               g_object_remove_weak_pointer (G_OBJECT (xpaned->last_bottom_left_child_focus),
+                                                                         (gpointer *)&(xpaned->last_bottom_left_child_focus));
+
+       xpaned->last_bottom_left_child_focus = widget;
+
+       if (xpaned->last_bottom_left_child_focus)
+               g_object_add_weak_pointer (G_OBJECT (xpaned->last_bottom_left_child_focus),
+                                                                  (gpointer *)&(xpaned->last_bottom_left_child_focus));
+}
+
+static void gtk_xpaned_set_last_bottom_right_child_focus (GtkXPaned* xpaned,
+                                                                                                                GtkWidget *widget)
+{
+       if (xpaned->last_bottom_right_child_focus)
+               g_object_remove_weak_pointer (G_OBJECT (xpaned->last_bottom_right_child_focus),
+                                                                         (gpointer *)&(xpaned->last_bottom_right_child_focus));
+
+       xpaned->last_bottom_right_child_focus = widget;
+
+       if (xpaned->last_bottom_right_child_focus)
+               g_object_add_weak_pointer (G_OBJECT (xpaned->last_bottom_right_child_focus),
+                                                                  (gpointer *)&(xpaned->last_bottom_right_child_focus));
+}
+
+static GtkWidget* xpaned_get_focus_widget (GtkXPaned* xpaned)
+{
+       GtkWidget* toplevel;
+
+       toplevel = gtk_widget_get_toplevel (GTK_WIDGET (xpaned));
+       if (GTK_WIDGET_TOPLEVEL (toplevel))
+               return GTK_WINDOW (toplevel)->focus_widget;
+
+       return NULL;
+}
+
+static void gtk_xpaned_set_focus_child (GtkContainer* container,
+                                                                               GtkWidget* focus_child)
+{
+       GtkXPaned* xpaned;
+
+       g_return_if_fail (GTK_IS_XPANED (container));
+
+       xpaned = GTK_XPANED (container);
+
+       if (focus_child == NULL)
+       {
+               GtkWidget* last_focus;
+               GtkWidget* w;
+
+               last_focus = xpaned_get_focus_widget (xpaned);
+
+               if (last_focus)
+               {
+                       /* If there is one or more paned widgets between us and the
+                       * focus widget, we want the topmost of those as last_focus
+                       */
+                       for (w = last_focus; w != GTK_WIDGET (xpaned); w = w->parent)
+                               if (GTK_IS_XPANED (w))
+                                       last_focus = w;
+
+                       if (container->focus_child == xpaned->top_left_child)
+                               gtk_xpaned_set_last_top_left_child_focus (xpaned, last_focus);
+                       else if (container->focus_child == xpaned->top_right_child)
+                               gtk_xpaned_set_last_top_right_child_focus (xpaned, last_focus);
+                       else if (container->focus_child == xpaned->bottom_left_child)
+                               gtk_xpaned_set_last_bottom_left_child_focus (xpaned, last_focus);
+                       else if (container->focus_child == xpaned->bottom_right_child)
+                               gtk_xpaned_set_last_bottom_right_child_focus (xpaned, last_focus);
+               }
+       }
+
+       if (parent_class->set_focus_child)
+               (* parent_class->set_focus_child) (container, focus_child);
+}
+
+static void gtk_xpaned_get_cycle_chain (GtkXPaned* xpaned,
+                                                                               GtkDirectionType direction,
+                                                                               GList** widgets)
+{
+       GtkContainer* container = GTK_CONTAINER (xpaned);
+       GtkWidget* ancestor = NULL;
+       GList* temp_list = NULL;
+       GList* list;
+
+       if (xpaned->in_recursion)
+               return;
+
+       g_assert (widgets != NULL);
+
+       if (xpaned->last_top_left_child_focus &&
+               !gtk_widget_is_ancestor (xpaned->last_top_left_child_focus,
+                                                                GTK_WIDGET (xpaned)))
+       {
+               gtk_xpaned_set_last_top_left_child_focus (xpaned, NULL);
+       }
+
+       if (xpaned->last_top_right_child_focus &&
+               !gtk_widget_is_ancestor (xpaned->last_top_right_child_focus,
+                                                                GTK_WIDGET (xpaned)))
+       {
+               gtk_xpaned_set_last_top_right_child_focus (xpaned, NULL);
+       }
+
+       if (xpaned->last_bottom_left_child_focus &&
+               !gtk_widget_is_ancestor (xpaned->last_bottom_left_child_focus,
+                                                                GTK_WIDGET (xpaned)))
+       {
+               gtk_xpaned_set_last_bottom_left_child_focus (xpaned, NULL);
+       }
+
+       if (xpaned->last_bottom_right_child_focus &&
+               !gtk_widget_is_ancestor (xpaned->last_bottom_right_child_focus,
+                                                                GTK_WIDGET (xpaned)))
+       {
+               gtk_xpaned_set_last_bottom_right_child_focus (xpaned, NULL);
+       }
+
+       if (GTK_WIDGET (xpaned)->parent)
+               ancestor = gtk_widget_get_ancestor (GTK_WIDGET (xpaned)->parent,
+                                                                                       GTK_TYPE_XPANED);
+
+       /* The idea here is that temp_list is a list of widgets we want to cycle
+       * to. The list is prioritized so that the first element is our first
+       * choice, the next our second, and so on.
+       *
+       * We can't just use g_list_reverse(), because we want to try
+       * paned->last_child?_focus before paned->child?, both when we
+       * are going forward and backward.
+       */
+       if (direction == GTK_DIR_TAB_FORWARD)
+       {
+               if (container->focus_child == xpaned->top_left_child)
+               {
+                       temp_list = g_list_append (temp_list, xpaned->last_top_right_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->top_right_child);
+                       temp_list = g_list_append (temp_list, ancestor);
+               }
+               else if (container->focus_child == xpaned->top_right_child)
+               {
+                       temp_list = g_list_append (temp_list, ancestor);
+                       temp_list = g_list_append (temp_list, xpaned->last_bottom_left_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->bottom_left_child);
+               }
+               else if (container->focus_child == xpaned->bottom_left_child)
+               {
+                       temp_list = g_list_append (temp_list, ancestor);
+                       temp_list = g_list_append (temp_list, xpaned->last_bottom_right_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->bottom_right_child);
+               }
+               else if (container->focus_child == xpaned->bottom_right_child)
+               {
+                       temp_list = g_list_append (temp_list, ancestor);
+                       temp_list = g_list_append (temp_list, xpaned->last_top_left_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->top_left_child);
+               }
+               else
+               {
+                       temp_list = g_list_append (temp_list, xpaned->last_top_left_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->top_left_child);
+                       temp_list = g_list_append (temp_list, xpaned->last_top_right_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->top_right_child);
+                       temp_list = g_list_append (temp_list, xpaned->last_bottom_left_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->bottom_left_child);
+                       temp_list = g_list_append (temp_list, xpaned->last_bottom_right_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->bottom_right_child);
+                       temp_list = g_list_append (temp_list, ancestor);
+               }
+       }
+       else
+       {
+               if (container->focus_child == xpaned->top_left_child)
+               {
+                       temp_list = g_list_append (temp_list, ancestor);
+                       temp_list = g_list_append (temp_list, xpaned->last_top_right_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->top_right_child);
+               }
+               else if (container->focus_child == xpaned->top_right_child)
+               {
+                       temp_list = g_list_append (temp_list, xpaned->last_bottom_left_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->bottom_left_child);
+                       temp_list = g_list_append (temp_list, ancestor);
+               }
+               else if (container->focus_child == xpaned->bottom_right_child)
+               {
+                       temp_list = g_list_append (temp_list, xpaned->last_bottom_left_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->bottom_left_child);
+                       temp_list = g_list_append (temp_list, ancestor);
+               }
+               else if (container->focus_child == xpaned->top_right_child)
+               {
+                       temp_list = g_list_append (temp_list, xpaned->last_bottom_left_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->bottom_left_child);
+                       temp_list = g_list_append (temp_list, ancestor);
+               }
+               else
+               {
+                       temp_list = g_list_append (temp_list, xpaned->last_bottom_right_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->bottom_right_child);
+                       temp_list = g_list_append (temp_list, xpaned->last_bottom_left_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->bottom_left_child);
+                       temp_list = g_list_append (temp_list, xpaned->last_top_right_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->top_right_child);
+                       temp_list = g_list_append (temp_list, xpaned->last_top_left_child_focus);
+                       temp_list = g_list_append (temp_list, xpaned->top_left_child);
+                       temp_list = g_list_append (temp_list, ancestor);
+               }
+       }
+
+       /* Walk the list and expand all the paned widgets. */
+       for (list = temp_list; list != NULL; list = list->next)
+       {
+               GtkWidget *widget = list->data;
+
+               if (widget)
+               {
+                       if (GTK_IS_XPANED (widget))
+                       {
+                               xpaned->in_recursion = TRUE;
+                               gtk_xpaned_get_cycle_chain (GTK_XPANED (widget),
+                                                                                       direction,
+                                                                                       widgets);
+                               xpaned->in_recursion = FALSE;
+                       }
+                       else
+                       {
+                               *widgets = g_list_append (*widgets, widget);
+                       }
+               }
+       }
+
+       g_list_free (temp_list);
+}
+
+static gboolean gtk_xpaned_cycle_child_focus (GtkXPaned* xpaned,
+                                                                                         gboolean reversed)
+{
+       GList* cycle_chain = NULL;
+       GList* list;
+
+       GtkDirectionType direction = reversed ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD;
+
+       /* ignore f6 if the handle is focused */
+       if (gtk_widget_is_focus (GTK_WIDGET (xpaned)))
+               return TRUE;
+
+       /* we can't just let the event propagate up the hierarchy,
+       * because the paned will want to cycle focus _unless_ an
+       * ancestor paned handles the event
+       */
+       gtk_xpaned_get_cycle_chain (xpaned, direction, &cycle_chain);
+
+       for (list = cycle_chain; list != NULL; list = list->next)
+               if (gtk_widget_child_focus (GTK_WIDGET (list->data), direction))
+                       break;
+
+       g_list_free (cycle_chain);
+
+       return TRUE;
+}
+
+static void get_child_xpanes (GtkWidget* widget, GList** xpanes)
+{
+       if (GTK_IS_XPANED (widget))
+       {
+               GtkXPaned* xpaned = GTK_XPANED (widget);
+
+               get_child_xpanes (xpaned->top_left_child, xpanes);
+               *xpanes = g_list_prepend (*xpanes, widget);
+               get_child_xpanes (xpaned->top_right_child, xpanes);
+               *xpanes = g_list_prepend (*xpanes, widget);
+               get_child_xpanes (xpaned->bottom_left_child, xpanes);
+               *xpanes = g_list_prepend (*xpanes, widget);
+               get_child_xpanes (xpaned->bottom_right_child, xpanes);
+       }
+       else if (GTK_IS_CONTAINER (widget))
+       {
+               gtk_container_foreach (GTK_CONTAINER (widget),
+                                                          (GtkCallback)get_child_xpanes,
+                                                          xpanes);
+       }
+}
+
+static GList* get_all_xpanes (GtkXPaned* xpaned)
+{
+       GtkXPaned* topmost = NULL;
+       GList* result = NULL;
+       GtkWidget* w;
+  
+       for (w = GTK_WIDGET (xpaned); w != NULL; w = w->parent)
+       {
+               if (GTK_IS_XPANED (w))
+                       topmost = GTK_XPANED (w);
+       }
+
+       g_assert (topmost);
+
+       get_child_xpanes (GTK_WIDGET (topmost), &result);
+
+       return g_list_reverse (result);
+}
+
+static void gtk_xpaned_find_neighbours (GtkXPaned* xpaned,
+                                                                               GtkXPaned** next,
+                                                                               GtkXPaned** prev)
+{
+       GList* all_xpanes;
+       GList* this_link;
+
+       all_xpanes = get_all_xpanes (xpaned);
+       g_assert (all_xpanes);
+
+       this_link = g_list_find (all_xpanes, xpaned);
+
+       g_assert (this_link);
+
+       if (this_link->next)
+               *next = this_link->next->data;
+       else
+               *next = all_xpanes->data;
+
+       if (this_link->prev)
+               *prev = this_link->prev->data;
+       else
+               *prev = g_list_last (all_xpanes)->data;
+
+       g_list_free (all_xpanes);
+}
+
+static gboolean gtk_xpaned_move_handle (GtkXPaned* xpaned, GtkScrollType scroll)
+{
+       if (gtk_widget_is_focus (GTK_WIDGET (xpaned)))
+       {
+               GdkPoint old_position;
+               GdkPoint new_position;
+               gint increment;
+
+               enum
+               {
+                       SINGLE_STEP_SIZE = 1,
+                       PAGE_STEP_SIZE   = 75
+               };
+
+               new_position.x = old_position.x = gtk_xpaned_get_position_x (xpaned);
+               new_position.y = old_position.y = gtk_xpaned_get_position_y (xpaned);
+               increment = 0;
+
+               switch (scroll)
+               {
+                       case GTK_SCROLL_STEP_LEFT:
+                       case GTK_SCROLL_STEP_UP:
+                       case GTK_SCROLL_STEP_BACKWARD:
+                               increment = - SINGLE_STEP_SIZE;
+                       break;
+
+                       case GTK_SCROLL_STEP_RIGHT:
+                       case GTK_SCROLL_STEP_DOWN:
+                       case GTK_SCROLL_STEP_FORWARD:
+                               increment = SINGLE_STEP_SIZE;
+                       break;
+
+                       case GTK_SCROLL_PAGE_LEFT:
+                       case GTK_SCROLL_PAGE_UP:
+                       case GTK_SCROLL_PAGE_BACKWARD:
+                               increment = - PAGE_STEP_SIZE;
+                       break;
+
+                       case GTK_SCROLL_PAGE_RIGHT:
+                       case GTK_SCROLL_PAGE_DOWN:
+                       case GTK_SCROLL_PAGE_FORWARD:
+                               increment = PAGE_STEP_SIZE;
+                       break;
+
+                       case GTK_SCROLL_START:
+                               new_position.x = xpaned->min_position.x;
+                               new_position.y = xpaned->min_position.y;
+                       break;
+
+                       case GTK_SCROLL_END:
+                               new_position.x = xpaned->max_position.x;
+                               new_position.y = xpaned->max_position.y;
+                       break;
+
+                       default:
+                       break;
+               }
+
+               if (increment)
+               {
+                       if (is_rtl (xpaned))
+                               increment = -increment;
+
+                       new_position.x = old_position.x + increment;
+                       new_position.y = old_position.y + increment;
+               }
+
+               new_position.x = CLAMP (new_position.x,
+                                                               xpaned->min_position.x,
+                                                               xpaned->max_position.x);
+
+               new_position.y = CLAMP (new_position.y,
+                                                               xpaned->min_position.y,
+                                                               xpaned->max_position.y);
+
+               if (old_position.x != new_position.x)
+                       gtk_xpaned_set_position_x (xpaned, new_position.x);
+
+               if (old_position.y != new_position.y)
+                       gtk_xpaned_set_position_y (xpaned, new_position.y);
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static void gtk_xpaned_restore_focus (GtkXPaned* xpaned)
+{
+       if (gtk_widget_is_focus (GTK_WIDGET (xpaned)))
+       {
+               if (xpaned->priv->saved_focus &&
+                       GTK_WIDGET_SENSITIVE (xpaned->priv->saved_focus))
+               {
+                       gtk_widget_grab_focus (xpaned->priv->saved_focus);
+               }
+               else
+               {
+                       /* the saved focus is somehow not available for focusing,
+                       * try
+                       *   1) tabbing into the paned widget
+                       * if that didn't work,
+                       *   2) unset focus for the window if there is one
+                       */
+
+                       if (!gtk_widget_child_focus (GTK_WIDGET (xpaned), GTK_DIR_TAB_FORWARD))
+                       {
+                               GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (xpaned));
+             
+                               if (GTK_IS_WINDOW (toplevel))
+                                       gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
+                       }
+               }
+               
+               gtk_xpaned_set_saved_focus (xpaned, NULL);
+               gtk_xpaned_set_first_xpaned (xpaned, NULL);
+    }
+}
+
+static gboolean gtk_xpaned_accept_position (GtkXPaned* xpaned)
+{
+       if (gtk_widget_is_focus (GTK_WIDGET (xpaned)))
+       {
+               xpaned->original_position.x = -1;
+               xpaned->original_position.y = -1;
+               gtk_xpaned_restore_focus (xpaned);
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static gboolean gtk_xpaned_cancel_position (GtkXPaned* xpaned)
+{
+       if (gtk_widget_is_focus (GTK_WIDGET (xpaned)))
+       {
+               if (xpaned->original_position.x != -1)
+               {
+                       gtk_xpaned_set_position_x (xpaned, xpaned->original_position.x);
+                       xpaned->original_position.x = -1;
+               }
+
+               if (xpaned->original_position.y != -1)
+               {
+                       gtk_xpaned_set_position_y (xpaned, xpaned->original_position.y);
+                       xpaned->original_position.y = -1;
+               }
+
+               gtk_xpaned_restore_focus (xpaned);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static gboolean gtk_xpaned_cycle_handle_focus (GtkXPaned* xpaned,
+                                                                                          gboolean reversed)
+{
+       GtkXPaned* next;
+       GtkXPaned* prev;
+
+       if (gtk_widget_is_focus (GTK_WIDGET (xpaned)))
+       {
+               GtkXPaned* focus = NULL;
+
+               if (!xpaned->priv->first_xpaned)
+               {
+                       /* The first_pane has disappeared. As an ad-hoc solution,
+                       * we make the currently focused paned the first_paned. To the
+                       * user this will seem like the paned cycling has been reset.
+                       */
+                       gtk_xpaned_set_first_xpaned (xpaned, xpaned);
+               }
+
+               gtk_xpaned_find_neighbours (xpaned, &next, &prev);
+
+               if (reversed && prev &&
+                       prev != xpaned && xpaned != xpaned->priv->first_xpaned)
+               {
+                       focus = prev;
+               }
+               else if (!reversed &&
+                                next &&
+                                next != xpaned &&
+                                next != xpaned->priv->first_xpaned)
+               {
+                       focus = next;
+               }
+               else
+               {
+                       gtk_xpaned_accept_position (xpaned);
+                       return TRUE;
+               }
+
+               g_assert (focus);
+      
+               gtk_xpaned_set_saved_focus (focus, xpaned->priv->saved_focus);
+               gtk_xpaned_set_first_xpaned (focus, xpaned->priv->first_xpaned);
+      
+               gtk_xpaned_set_saved_focus (xpaned, NULL);
+               gtk_xpaned_set_first_xpaned (xpaned, NULL);
+      
+               gtk_widget_grab_focus (GTK_WIDGET (focus));
+      
+               if (!gtk_widget_is_focus (GTK_WIDGET (xpaned)))
+               {
+                       xpaned->original_position.x = -1;
+                       xpaned->original_position.y = -1;
+                       focus->original_position.x = gtk_xpaned_get_position_x (focus);
+                       focus->original_position.y = gtk_xpaned_get_position_y (focus);
+               }
+       }
+       else
+    {
+               GtkContainer* container = GTK_CONTAINER (xpaned);
+               GtkXPaned* focus;
+               GtkXPaned* first;
+               GtkXPaned* prev;
+               GtkXPaned* next;
+               GtkWidget* toplevel;
+
+               gtk_xpaned_find_neighbours (xpaned, &next, &prev);
+
+               if (container->focus_child == xpaned->top_left_child)
+               {
+                       if (reversed)
+                       {
+                               focus = prev;
+                               first = xpaned;
+                       }
+                       else
+                       {
+                               focus = xpaned;
+                               first = xpaned;
+                       }
+               }
+               else if (container->focus_child == xpaned->top_right_child)
+               {
+                       if (reversed)
+                       {
+                               focus = xpaned;
+                               first = next;
+                       }
+                       else
+                       {
+                               focus = next;
+                               first = next;
+                       }
+               }
+               else
+               {
+                       /* Focus is not inside this xpaned, and we don't have focus.
+                       * Presumably this happened because the application wants us
+                       * to start keyboard navigating.
+                       */
+                       focus = xpaned;
+
+                       if (reversed)
+                               first = xpaned;
+                       else
+                               first = next;
+               }
+
+               toplevel = gtk_widget_get_toplevel (GTK_WIDGET (xpaned));
+
+               if (GTK_IS_WINDOW (toplevel))
+                       gtk_xpaned_set_saved_focus (focus, GTK_WINDOW (toplevel)->focus_widget);
+               gtk_xpaned_set_first_xpaned (focus, first);
+               focus->original_position.x = gtk_xpaned_get_position_x (focus);
+               focus->original_position.y = gtk_xpaned_get_position_y (focus); 
+
+               gtk_widget_grab_focus (GTK_WIDGET (focus));
+       }
+
+       return TRUE;
+}
+
+static gboolean gtk_xpaned_toggle_handle_focus (GtkXPaned* xpaned)
+{
+       /* This function/signal has the wrong name. It is called when you
+       * press Tab or Shift-Tab and what we do is act as if
+       * the user pressed Return and then Tab or Shift-Tab
+       */
+       if (gtk_widget_is_focus (GTK_WIDGET (xpaned)))
+               gtk_xpaned_accept_position (xpaned);
+
+  return FALSE;
+}
+
+/*#define __GTK_XPANED_C__*/
+/*#include "gtkaliasdef.c"*/
diff --git a/lib/gtksheet/gtkxpaned.h b/lib/gtksheet/gtkxpaned.h
new file mode 100644 (file)
index 0000000..47e752e
--- /dev/null
@@ -0,0 +1,175 @@
+/*******************************************************************************
+**3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 
+**      10        20        30        40        50        60        70        80
+**
+**  library for GtkXPaned-widget, a 2x2 grid-like variation of GtkPaned of gtk+
+**  Copyright (C) 2005-2006 Mirco "MacSlow" Müller <macslow@bangang.de>
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+**
+**  GtkXPaned is based on GtkPaned which was done by...
+**
+**  "Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald"
+**
+**  and later modified by...
+**
+**  "the GTK+ Team and others 1997-2000"
+**
+*******************************************************************************/
+
+#ifndef GTK_XPANED_H
+#define GTK_XPANED_H
+
+#include <gtk/gtkcontainer.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_XPANED                  (gtk_xpaned_get_type ())
+#define GTK_XPANED(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_XPANED, GtkXPaned))
+#define GTK_XPANED_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_XPANED, GtkXPanedClass))
+#define GTK_IS_XPANED(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_XPANED))
+#define GTK_IS_XPANED_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_XPANED))
+#define GTK_XPANED_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_XPANED, GtkXPanedClass))
+
+typedef struct _GtkXPaned        GtkXPaned;
+typedef struct _GtkXPanedClass   GtkXPanedClass;
+typedef struct _GtkXPanedPrivate GtkXPanedPrivate;
+
+typedef enum _GtkXPanedChild
+{
+       GTK_XPANED_TOP_LEFT = 0,
+       GTK_XPANED_TOP_RIGHT,
+       GTK_XPANED_BOTTOM_LEFT,
+       GTK_XPANED_BOTTOM_RIGHT
+} GtkXPanedChild;
+       
+struct _GtkXPaned
+{
+       GtkContainer container;
+  
+       GtkWidget* top_left_child;
+       GtkWidget* top_right_child;
+       GtkWidget* bottom_left_child;
+       GtkWidget* bottom_right_child;
+
+       GdkWindow* handle_east;
+       GdkWindow* handle_west;
+       GdkWindow* handle_north;
+       GdkWindow* handle_south;
+       GdkWindow* handle_middle;
+       GdkGC* xor_gc;
+       GdkCursorType cursor_type_east;
+       GdkCursorType cursor_type_west;
+       GdkCursorType cursor_type_north;
+       GdkCursorType cursor_type_south;
+       GdkCursorType cursor_type_middle;
+
+       /*< private >*/
+       GdkRectangle handle_pos_east;
+       GdkRectangle handle_pos_west;
+       GdkRectangle handle_pos_north;
+       GdkRectangle handle_pos_south;
+       GdkRectangle handle_pos_middle;
+       GtkRequisition top_left_child_size;
+       GtkRequisition top_right_child_size;
+       GtkRequisition bottom_left_child_size;
+       GtkRequisition bottom_right_child_size;
+
+       GtkRequisition last_allocation;
+       GdkPoint min_position;
+       GdkPoint max_position;
+       gboolean maximized[4];
+
+       guint position_set : 1;
+       guint in_drag_vert : 1;
+       guint in_drag_horiz : 1;
+       guint in_drag_vert_and_horiz : 1;
+       guint top_left_child_shrink : 1;
+       guint top_left_child_resize : 1;
+       guint top_right_child_shrink : 1;
+       guint top_right_child_resize : 1;
+       guint bottom_left_child_shrink : 1;
+       guint bottom_left_child_resize : 1;
+       guint bottom_right_child_shrink : 1;
+       guint bottom_right_child_resize : 1;
+       guint in_recursion : 1;
+       guint handle_prelit : 1;
+
+       GtkWidget* last_top_left_child_focus;
+       GtkWidget* last_top_right_child_focus;
+       GtkWidget* last_bottom_left_child_focus;
+       GtkWidget* last_bottom_right_child_focus;
+       GtkXPanedPrivate* priv;
+
+       GdkPoint drag_pos;
+       GdkPoint original_position;
+       GdkPoint unmaximized_position;
+};
+
+struct _GtkXPanedClass
+{
+       GtkContainerClass parent_class;
+       gboolean (*cycle_child_focus)   (GtkXPaned* xpaned, gboolean reverse); 
+       gboolean (*toggle_handle_focus) (GtkXPaned* xpaned);
+       gboolean (*move_handle)                 (GtkXPaned* xpaned, GtkScrollType scroll);
+       gboolean (*cycle_handle_focus)  (GtkXPaned* xpaned, gboolean reverse);
+       gboolean (*accept_position)             (GtkXPaned* xpaned);
+       gboolean (*cancel_position)     (GtkXPaned* xpaned);
+};
+
+GType gtk_xpaned_get_type (void) G_GNUC_CONST;
+GtkWidget* gtk_xpaned_new (void);
+void gtk_xpaned_add_top_left (GtkXPaned* xpaned, GtkWidget* child);
+void gtk_xpaned_add_top_right (GtkXPaned* xpaned, GtkWidget* child);
+void gtk_xpaned_add_bottom_left (GtkXPaned* xpaned, GtkWidget* child);
+void gtk_xpaned_add_bottom_right (GtkXPaned* xpaned, GtkWidget* child);
+void gtk_xpaned_pack_top_left (GtkXPaned* xpaned, GtkWidget* child, gboolean resize, gboolean shrink);
+void gtk_xpaned_pack_top_right (GtkXPaned* xpaned, GtkWidget* child, gboolean resize, gboolean shrink);
+void gtk_xpaned_pack_bottom_left (GtkXPaned* xpaned, GtkWidget* child, gboolean resize, gboolean shrink);
+void gtk_xpaned_pack_bottom_right (GtkXPaned* xpaned, GtkWidget* child, gboolean resize, gboolean shrink);
+gint gtk_xpaned_get_position_x (GtkXPaned* xpaned);
+gint gtk_xpaned_get_position_y (GtkXPaned* xpaned);
+void gtk_xpaned_set_position_x (GtkXPaned* xpaned, gint xposition);
+void gtk_xpaned_set_position_y (GtkXPaned* xpaned, gint yposition);
+void gtk_xpaned_save_unmaximized_x (GtkXPaned* xpaned);
+void gtk_xpaned_save_unmaximized_y (GtkXPaned* xpaned);
+gint gtk_xpaned_fetch_unmaximized_x (GtkXPaned* xpaned);
+gint gtk_xpaned_fetch_unmaximized_y (GtkXPaned* xpaned);
+GtkWidget* gtk_xpaned_get_top_left_child (GtkXPaned* xpaned);
+GtkWidget* gtk_xpaned_get_top_right_child (GtkXPaned* xpaned);
+GtkWidget* gtk_xpaned_get_bottom_right_child (GtkXPaned* xpaned);
+GtkWidget* gtk_xpaned_get_bottom_left_child (GtkXPaned* xpaned);
+gboolean gtk_xpaned_maximize_top_left (GtkXPaned* xpaned, gboolean maximize);
+gboolean gtk_xpaned_maximize_top_right (GtkXPaned* xpaned, gboolean maximize);
+gboolean gtk_xpaned_maximize_bottom_left (GtkXPaned* xpaned, gboolean maximize);
+gboolean gtk_xpaned_maximize_bottom_right (GtkXPaned* xpaned, gboolean maximize);
+
+/* Internal function */
+#if !defined (GTK_DISABLE_DEPRECATED) || defined (GTK_COMPILATION)
+void gtk_xpaned_compute_position (GtkXPaned* xpaned,
+                                 const GtkAllocation* allocation,
+                                 GtkRequisition* top_left_child_req,
+                                 GtkRequisition* top_right_child_req,
+                                 GtkRequisition* bottom_left_child_req,
+                                 GtkRequisition* bottom_right_child_req);
+#endif /* !GTK_DISABLE_DEPRECATED || GTK_COMPILATION */
+#ifndef GTK_DISABLE_DEPRECATED
+#define        gtk_xpaned_gutter_size(p,s) (void) 0
+#define        gtk_xpaned_set_gutter_size(p,s) (void) 0
+#endif /* GTK_DISABLE_DEPRECATED */
+
+G_END_DECLS
+
+#endif /* GTK_XPANED_H */
diff --git a/lib/gtksheet/marshaller-list b/lib/gtksheet/marshaller-list
new file mode 100644 (file)
index 0000000..df5ac6c
--- /dev/null
@@ -0,0 +1,12 @@
+#List of custom marshallers used by psppire
+
+BOOLEAN:BOOLEAN
+BOOLEAN:ENUM
+BOOLEAN:BOXED,POINTER
+BOOLEAN:VOID
+VOID:BOXED,BOXED
+VOID:INT,INT
+VOID:INT,INT,INT
+VOID:INT,INT,INT,INT
+VOID:INT,POINTER
+VOID:OBJECT,OBJECT
diff --git a/lib/gtksheet/psppire-axis-hetero.c b/lib/gtksheet/psppire-axis-hetero.c
new file mode 100644 (file)
index 0000000..aad3da7
--- /dev/null
@@ -0,0 +1,263 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2008  Free Software Foundation
+
+   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 <string.h>
+#include <stdlib.h>
+
+#include <libpspp/tower.h>
+#include <libpspp/pool.h>
+#include "psppire-axis-hetero.h"
+#include <gtk/gtk.h>
+
+
+/* --- prototypes --- */
+static void psppire_axis_hetero_class_init (PsppireAxisHeteroClass     *class);
+static void psppire_axis_hetero_init   (PsppireAxisHetero              *axis);
+static void psppire_axis_hetero_finalize   (GObject            *object);
+
+
+/* --- variables --- */
+static GObjectClass     *parent_class = NULL;
+
+
+static gint
+get_unit_at_pixel (const PsppireAxis *a, glong pixel)
+{
+  PsppireAxisHetero *ah = PSPPIRE_AXIS_HETERO (a);
+  const struct tower_node *node;
+  unsigned long int node_start;
+
+  if (pixel >= tower_height (&ah->tower))
+    return tower_count (&ah->tower);
+
+  node = tower_lookup (&ah->tower, pixel, &node_start);
+
+  return tower_node_get_index (node);
+}
+
+
+static gint
+unit_count (const PsppireAxis *a)
+{
+  PsppireAxisHetero *ah = PSPPIRE_AXIS_HETERO (a);
+  return tower_count (&ah->tower);
+}
+
+
+static glong
+pixel_start (const PsppireAxis *a, gint unit)
+{
+  PsppireAxisHetero *ah = PSPPIRE_AXIS_HETERO (a);
+  const struct tower_node *node;
+
+  if ( unit >= tower_count (&ah->tower))
+    return tower_height (&ah->tower);
+
+  node = tower_get (&ah->tower, unit);
+
+  return  tower_node_get_level (node);
+}
+
+
+static gint
+unit_size (const PsppireAxis *a, gint unit)
+{
+  PsppireAxisHetero *ah = PSPPIRE_AXIS_HETERO (a);
+  const struct tower_node *node;
+  if  (unit >= tower_count (&ah->tower))
+    return 0;
+
+  node = tower_get (&ah->tower, unit);
+
+  return tower_node_get_size (node);
+}
+
+
+static glong
+total_size (const PsppireAxis *a)
+{
+  glong s;
+  PsppireAxisHetero *ah = PSPPIRE_AXIS_HETERO (a);
+
+  s =  tower_height (&ah->tower);
+  return s;
+}
+
+static void
+psppire_hetero_iface_init (PsppireAxisIface *iface)
+{
+  iface->unit_size = unit_size;
+  iface->unit_count = unit_count;
+  iface->pixel_start = pixel_start;
+  iface->get_unit_at_pixel = get_unit_at_pixel;
+  iface->total_size = total_size;
+}
+
+/* --- functions --- */
+/**
+ * psppire_axis_hetero_get_type:
+ * @returns: the type ID for accelerator groups.
+ */
+GType
+psppire_axis_hetero_get_type (void)
+{
+  static GType object_type = 0;
+
+  if (!object_type)
+    {
+      static const GTypeInfo object_info = {
+       sizeof (PsppireAxisHeteroClass),
+       (GBaseInitFunc) NULL,
+       (GBaseFinalizeFunc) NULL,
+       (GClassInitFunc) psppire_axis_hetero_class_init,
+       NULL,   /* class_finalize */
+       NULL,   /* class_data */
+       sizeof (PsppireAxisHetero),
+       0,      /* n_preallocs */
+       (GInstanceInitFunc) psppire_axis_hetero_init,
+      };
+
+
+      static const GInterfaceInfo interface_info =
+      {
+       (GInterfaceInitFunc) psppire_hetero_iface_init,
+       NULL,
+       NULL
+      };
+
+      object_type = g_type_register_static (G_TYPE_PSPPIRE_AXIS,
+                                           "PsppireAxisHetero",
+                                           &object_info, 0);
+
+      g_type_add_interface_static (object_type,
+                                  PSPPIRE_TYPE_AXIS_IFACE,
+                                  &interface_info);
+    }
+
+  return object_type;
+}
+
+static void
+psppire_axis_hetero_class_init (PsppireAxisHeteroClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class->finalize = psppire_axis_hetero_finalize;
+}
+
+
+static void
+psppire_axis_hetero_init (PsppireAxisHetero *axis)
+{
+  axis->pool = NULL;
+  psppire_axis_hetero_clear (axis);
+}
+
+
+static void
+psppire_axis_hetero_finalize (GObject *object)
+{
+  PsppireAxisHetero *a = PSPPIRE_AXIS_HETERO (object);
+  pool_destroy (a->pool);
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/**
+ * psppire_axis_hetero_new:
+ * @returns: a new #PsppireAxisHetero object
+ *
+ * Creates a new #PsppireAxisHetero.
+ */
+PsppireAxisHetero*
+psppire_axis_hetero_new (void)
+{
+  return g_object_new (G_TYPE_PSPPIRE_AXIS_HETERO, NULL);
+}
+
+
+void
+psppire_axis_hetero_append (PsppireAxisHetero *a, gint size)
+{
+  struct tower_node *new ;
+
+  g_return_if_fail (PSPPIRE_IS_AXIS_HETERO (a));
+
+  new = pool_malloc (a->pool, sizeof *new);
+
+  tower_insert (&a->tower, size, new, NULL);
+}
+
+
+
+/* Insert a new unit of size SIZE before position POSN */
+void
+psppire_axis_hetero_insert (PsppireAxisHetero *a, gint size, gint posn)
+{
+  struct tower_node *new;
+  struct tower_node *before = NULL;
+
+  g_return_if_fail (PSPPIRE_IS_AXIS_HETERO (a));
+
+  new = pool_malloc (a->pool, sizeof *new);
+
+  if ( posn != tower_count (&a->tower))
+    before = tower_get (&a->tower, posn);
+
+  tower_insert (&a->tower, size, new, before);
+}
+
+
+void
+psppire_axis_hetero_remove (PsppireAxisHetero *a, gint posn)
+{
+  struct tower_node *node;
+
+  g_return_if_fail (PSPPIRE_IS_AXIS_HETERO (a));
+
+  node = tower_get (&a->tower, posn);
+
+  tower_delete (&a->tower, node);
+
+  pool_free (a->pool, node);
+}
+
+
+void
+psppire_axis_hetero_resize_unit (PsppireAxisHetero *a, gint size, gint posn)
+{
+  struct tower_node *node;
+
+  g_return_if_fail (PSPPIRE_IS_AXIS_HETERO (a));
+
+  node = tower_get (&a->tower, posn);
+
+  tower_resize (&a->tower, node, size);
+}
+
+
+void
+psppire_axis_hetero_clear (PsppireAxisHetero *a)
+{
+  g_return_if_fail (PSPPIRE_IS_AXIS_HETERO (a));
+
+  pool_destroy (a->pool);
+  a->pool = pool_create ();
+  tower_init (&a->tower);
+}
+
+
diff --git a/lib/gtksheet/psppire-axis-hetero.h b/lib/gtksheet/psppire-axis-hetero.h
new file mode 100644 (file)
index 0000000..c1b674c
--- /dev/null
@@ -0,0 +1,80 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2008  Free Software Foundation
+
+   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_AXIS_HETERO_H__
+#define PSPPIRE_AXIS_HETERO_H__
+
+
+#include <glib-object.h>
+#include <glib.h>
+
+#include <libpspp/tower.h>
+#include "psppire-axis.h"
+
+G_BEGIN_DECLS
+
+
+/* --- type macros --- */
+#define G_TYPE_PSPPIRE_AXIS_HETERO              (psppire_axis_hetero_get_type ())
+#define PSPPIRE_AXIS_HETERO(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_PSPPIRE_AXIS_HETERO, PsppireAxisHetero))
+#define PSPPIRE_AXIS_HETERO_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_PSPPIRE_AXIS_HETERO, PsppireAxisHeteroClass))
+#define PSPPIRE_IS_AXIS_HETERO(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_PSPPIRE_AXIS_HETERO))
+#define PSPPIRE_IS_AXIS_HETERO_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_PSPPIRE_AXIS_HETERO))
+#define PSPPIRE_AXIS_HETERO_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_PSPPIRE_AXIS_HETERO, PsppireAxisHeteroClass))
+
+
+
+/* --- typedefs & structures --- */
+typedef struct _PsppireAxisHetero         PsppireAxisHetero;
+typedef struct _PsppireAxisHeteroClass PsppireAxisHeteroClass;
+
+struct pool;
+
+struct _PsppireAxisHetero
+{
+  PsppireAxis  parent;
+
+  struct tower tower;
+  struct pool *pool;
+};
+
+struct _PsppireAxisHeteroClass
+{
+  PsppireAxisClass parent_class;
+};
+
+GType          psppire_axis_hetero_get_type (void);
+
+PsppireAxisHetero*   psppire_axis_hetero_new (void);
+
+\f
+/* Interface between axis and model */
+
+void psppire_axis_hetero_clear (PsppireAxisHetero *a);
+
+void psppire_axis_hetero_append (PsppireAxisHetero *a, gint size);
+
+void psppire_axis_hetero_insert (PsppireAxisHetero *a, gint size, gint posn);
+
+void psppire_axis_hetero_remove (PsppireAxisHetero *a, gint posn);
+
+void psppire_axis_hetero_resize_unit (PsppireAxisHetero *a, gint size, gint posn);
+
+
+G_END_DECLS
+
+#endif /* PSPPIRE_AXIS_HETERO_H__ */
diff --git a/lib/gtksheet/psppire-axis-uniform.c b/lib/gtksheet/psppire-axis-uniform.c
new file mode 100644 (file)
index 0000000..8763da1
--- /dev/null
@@ -0,0 +1,196 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2008  Free Software Foundation
+
+   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 <string.h>
+#include <stdlib.h>
+
+#include <libpspp/tower.h>
+#include <libpspp/pool.h>
+#include "psppire-axis-uniform.h"
+#include <gtk/gtk.h>
+
+
+/* --- prototypes --- */
+static void psppire_axis_uniform_class_init (PsppireAxisUniformClass   *class);
+static void psppire_axis_uniform_init  (PsppireAxisUniform             *axis);
+static void psppire_axis_uniform_finalize   (GObject           *object);
+
+
+/* --- variables --- */
+static GObjectClass     *parent_class = NULL;
+
+
+#define UNIT_SIZE 25
+
+static gint
+get_unit_at_pixel (const PsppireAxis *a, glong pixel)
+{
+  gint unit_size;
+  PsppireAxisUniform *au = PSPPIRE_AXIS_UNIFORM (a);
+
+  g_object_get (au, "default-size", &unit_size, NULL);
+
+  return pixel / unit_size;
+}
+
+
+static gint
+unit_count (const PsppireAxis *a)
+{
+  PsppireAxisUniform *au = PSPPIRE_AXIS_UNIFORM (a);
+
+  return au->n_items;
+}
+
+
+static glong
+pixel_start (const PsppireAxis *a, gint unit)
+{
+  gint unit_size;
+  PsppireAxisUniform *au = PSPPIRE_AXIS_UNIFORM (a);
+
+  g_object_get (au, "default-size", &unit_size, NULL);
+
+  return unit * unit_size;
+}
+
+
+static gint
+unit_size (const PsppireAxis *a, gint unit)
+{
+  gint unit_size;
+  PsppireAxisUniform *au = PSPPIRE_AXIS_UNIFORM (a);
+
+  g_object_get (au, "default-size", &unit_size, NULL);
+
+  return unit_size;
+}
+
+
+static glong
+total_size (const PsppireAxis *a)
+{
+  gint unit_size;
+  PsppireAxisUniform *au = PSPPIRE_AXIS_UNIFORM (a);
+
+  g_object_get (au, "default-size", &unit_size, NULL);
+
+  return unit_size * au->n_items;
+}
+
+
+
+static void
+psppire_uniform_iface_init (PsppireAxisIface *iface)
+{
+  iface->unit_size = unit_size;
+  iface->unit_count = unit_count;
+  iface->pixel_start = pixel_start;
+  iface->get_unit_at_pixel = get_unit_at_pixel;
+  iface->total_size = total_size;
+}
+
+/* --- functions --- */
+/**
+ * psppire_axis_uniform_get_type:
+ * @returns: the type ID for accelerator groups.
+ */
+GType
+psppire_axis_uniform_get_type (void)
+{
+  static GType object_type = 0;
+
+  if (!object_type)
+    {
+      static const GTypeInfo object_info = {
+       sizeof (PsppireAxisUniformClass),
+       (GBaseInitFunc) NULL,
+       (GBaseFinalizeFunc) NULL,
+       (GClassInitFunc) psppire_axis_uniform_class_init,
+       NULL,   /* class_finalize */
+       NULL,   /* class_data */
+       sizeof (PsppireAxisUniform),
+       0,      /* n_preallocs */
+       (GInstanceInitFunc) psppire_axis_uniform_init,
+      };
+
+      static const GInterfaceInfo interface_info =
+      {
+       (GInterfaceInitFunc) psppire_uniform_iface_init,
+       NULL,
+       NULL
+      };
+
+
+      object_type = g_type_register_static (G_TYPE_PSPPIRE_AXIS,
+                                           "PsppireAxisUniform",
+                                           &object_info, 0);
+
+
+      g_type_add_interface_static (object_type,
+                                  PSPPIRE_TYPE_AXIS_IFACE,
+                                  &interface_info);
+    }
+
+  return object_type;
+}
+
+static void
+psppire_axis_uniform_class_init (PsppireAxisUniformClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class->finalize = psppire_axis_uniform_finalize;
+}
+
+
+static void
+psppire_axis_uniform_init (PsppireAxisUniform *axis)
+{
+  axis->n_items = 0;
+}
+
+
+static void
+psppire_axis_uniform_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+/**
+ * psppire_axis_uniform_new:
+ * @returns: a new #PsppireAxisUniform object
+ *
+ * Creates a new #PsppireAxisUniform.
+ */
+PsppireAxisUniform*
+psppire_axis_uniform_new (void)
+{
+  return g_object_new (G_TYPE_PSPPIRE_AXIS_UNIFORM, NULL);
+}
+
+
+
+\f
+
+
+void
+psppire_axis_uniform_set_count (PsppireAxisUniform *axis, gint n)
+{
+  axis->n_items = n;
+}
diff --git a/lib/gtksheet/psppire-axis-uniform.h b/lib/gtksheet/psppire-axis-uniform.h
new file mode 100644 (file)
index 0000000..49f434d
--- /dev/null
@@ -0,0 +1,72 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2008  Free Software Foundation
+
+   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_AXIS_UNIFORM_H__
+#define PSPPIRE_AXIS_UNIFORM_H__
+
+
+#include <glib-object.h>
+#include <glib.h>
+
+#include "psppire-axis.h"
+
+G_BEGIN_DECLS
+
+
+/* --- type macros --- */
+#define G_TYPE_PSPPIRE_AXIS_UNIFORM              (psppire_axis_uniform_get_type ())
+#define PSPPIRE_AXIS_UNIFORM(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_PSPPIRE_AXIS_UNIFORM, PsppireAxisUniform))
+#define PSPPIRE_AXIS_UNIFORM_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_PSPPIRE_AXIS_UNIFORM, PsppireAxisUniformClass))
+#define PSPPIRE_IS_AXIS_UNIFORM(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_PSPPIRE_AXIS_UNIFORM))
+#define PSPPIRE_IS_AXIS_UNIFORM_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_PSPPIRE_AXIS_UNIFORM))
+#define PSPPIRE_AXIS_UNIFORM_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_PSPPIRE_AXIS_UNIFORM, PsppireAxisUniformClass))
+
+
+
+/* --- typedefs & structures --- */
+typedef struct _PsppireAxisUniform        PsppireAxisUniform;
+typedef struct _PsppireAxisUniformClass PsppireAxisUniformClass;
+
+struct pool;
+
+struct _PsppireAxisUniform
+{
+  PsppireAxis  parent;
+
+  gint n_items;
+};
+
+struct _PsppireAxisUniformClass
+{
+  PsppireAxisClass parent_class;
+};
+
+GType          psppire_axis_uniform_get_type (void);
+
+PsppireAxisUniform*   psppire_axis_uniform_new (void);
+
+\f
+/* Interface between axis and model */
+
+
+void psppire_axis_uniform_set_count (PsppireAxisUniform *axis, gint n);
+
+
+
+G_END_DECLS
+
+#endif /* PSPPIRE_AXIS_UNIFORM_H__ */
diff --git a/lib/gtksheet/psppire-axis.c b/lib/gtksheet/psppire-axis.c
new file mode 100644 (file)
index 0000000..94c2aa4
--- /dev/null
@@ -0,0 +1,255 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2008  Free Software Foundation
+
+   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 <string.h>
+#include <stdlib.h>
+
+#include <libpspp/tower.h>
+#include <libpspp/pool.h>
+#include <libpspp/misc.h>
+#include "psppire-axis.h"
+#include <gtk/gtk.h>
+
+
+#define PSPPIRE_AXIS_GET_IFACE(obj) \
+  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), PSPPIRE_TYPE_AXIS_IFACE, PsppireAxisIface))
+
+GType
+psppire_axis_iface_get_type (void)
+{
+  static GType psppire_axis_iface_type = 0;
+
+  if (! psppire_axis_iface_type)
+    {
+      static const GTypeInfo psppire_axis_iface_info =
+      {
+        sizeof (PsppireAxisIface), /* class_size */
+       NULL,           /* base init */
+       NULL,           /* base_finalize */
+       NULL,
+       NULL,           /* class_finalize */
+       NULL,           /* class_data */
+       0,
+       0,              /* n_preallocs */
+       NULL
+      };
+
+      psppire_axis_iface_type =
+       g_type_register_static (G_TYPE_INTERFACE, "PsppireAxisIface",
+                               &psppire_axis_iface_info, 0);
+    }
+
+  return psppire_axis_iface_type;
+}
+
+G_DEFINE_ABSTRACT_TYPE(PsppireAxis, psppire_axis, G_TYPE_OBJECT);
+
+
+
+/* --- prototypes --- */
+static void psppire_axis_class_init (PsppireAxisClass  *class);
+static void psppire_axis_init  (PsppireAxis            *axis);
+static void psppire_axis_finalize   (GObject           *object);
+
+
+/* --- variables --- */
+static GObjectClass     *parent_class = NULL;
+
+
+
+enum
+  {
+    PROP_0,
+    PROP_MIN_EXTENT,
+    PROP_DEFAULT_SIZE
+  };
+
+
+static void
+psppire_axis_get_property (GObject         *object,
+                          guint            prop_id,
+                          GValue          *value,
+                          GParamSpec      *pspec)
+{
+  PsppireAxis *axis = PSPPIRE_AXIS (object);
+
+  switch (prop_id)
+    {
+    case PROP_MIN_EXTENT:
+      g_value_set_long (value, axis->min_extent);
+      break;
+    case PROP_DEFAULT_SIZE:
+      g_value_set_int (value, axis->default_size);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    };
+}
+
+
+static void
+psppire_axis_set_property (GObject         *object,
+                          guint            prop_id,
+                          const GValue    *value,
+                          GParamSpec      *pspec)
+{
+  PsppireAxis *axis = PSPPIRE_AXIS (object);
+
+  switch (prop_id)
+    {
+    case PROP_MIN_EXTENT:
+      axis->min_extent = g_value_get_long (value);
+      break;
+    case PROP_DEFAULT_SIZE:
+      axis->default_size = g_value_get_int (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    };
+}
+
+static void
+psppire_axis_class_init (PsppireAxisClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  GParamSpec *min_extent_spec;
+  GParamSpec *default_size_spec;
+
+  object_class->set_property = psppire_axis_set_property;
+  object_class->get_property = psppire_axis_get_property;
+
+  min_extent_spec =
+    g_param_spec_long ("minimum-extent",
+                      "Minimum Extent",
+                      "The smallest extent to which the axis will provide units (typically set to the height/width of the associated widget).",
+                      0, G_MAXLONG,
+                      0,
+                      G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_READABLE );
+
+  g_object_class_install_property (object_class,
+                                   PROP_MIN_EXTENT,
+                                   min_extent_spec);
+
+
+  default_size_spec =
+    g_param_spec_int ("default-size",
+                     "Default Size",
+                     "The size given to units which haven't been explicity inserted",
+                     0, G_MAXINT,
+                     25,
+                     G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_READABLE );
+
+
+  g_object_class_install_property (object_class,
+                                   PROP_DEFAULT_SIZE,
+                                   default_size_spec);
+
+  parent_class = g_type_class_peek_parent (class);
+
+  object_class->finalize = psppire_axis_finalize;
+}
+
+
+static void
+psppire_axis_init (PsppireAxis *axis)
+{
+}
+
+
+static void
+psppire_axis_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+gint
+psppire_axis_unit_size (const PsppireAxis *a, gint unit)
+{
+  g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
+
+  g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_size, -1);
+
+
+  if  (unit >= PSPPIRE_AXIS_GET_IFACE (a)->unit_count(a))
+    return a->default_size;
+
+  return PSPPIRE_AXIS_GET_IFACE (a)->unit_size (a, unit);
+}
+
+gint
+psppire_axis_unit_count (const PsppireAxis *a)
+{
+  glong padding = 0;
+  glong actual_size;
+
+  g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
+  g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->unit_count, -1);
+
+  actual_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
+
+  if ( actual_size < a->min_extent )
+    padding = DIV_RND_UP (a->min_extent - actual_size, a->default_size);
+
+  return PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a) + padding;
+}
+
+
+/* Return the starting pixel of UNIT */
+glong
+psppire_axis_pixel_start (const PsppireAxis *a, gint unit)
+{
+  gint the_count, total_size ;
+  g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
+
+  the_count =  PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a);
+  total_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
+
+  if ( unit >= the_count)
+    {
+      return  total_size + (unit - the_count) * a->default_size;
+    }
+
+  return PSPPIRE_AXIS_GET_IFACE (a)->pixel_start (a, unit);
+}
+
+
+/* Return the unit covered by PIXEL */
+gint
+psppire_axis_get_unit_at_pixel (const PsppireAxis *a, glong pixel)
+{
+  glong total_size;
+
+  g_return_val_if_fail (PSPPIRE_IS_AXIS (a), -1);
+
+  g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a), -1);
+
+  g_return_val_if_fail (PSPPIRE_AXIS_GET_IFACE (a)->get_unit_at_pixel, -1);
+
+  total_size = PSPPIRE_AXIS_GET_IFACE (a)->total_size (a);
+
+  if (pixel >= total_size)
+    {
+      gint n_items = PSPPIRE_AXIS_GET_IFACE (a)->unit_count (a);
+      glong extra = pixel - total_size;
+
+      return n_items - 1 + DIV_RND_UP (extra,  a->default_size);
+    }
+
+  return PSPPIRE_AXIS_GET_IFACE (a)->get_unit_at_pixel (a, pixel);
+}
diff --git a/lib/gtksheet/psppire-axis.h b/lib/gtksheet/psppire-axis.h
new file mode 100644 (file)
index 0000000..4ec2313
--- /dev/null
@@ -0,0 +1,101 @@
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2008  Free Software Foundation
+
+   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_AXIS_H__
+#define PSPPIRE_AXIS_H__
+
+
+#include <glib-object.h>
+#include <glib.h>
+
+#include <libpspp/tower.h>
+
+G_BEGIN_DECLS
+
+
+
+/* --- type macros --- */
+#define G_TYPE_PSPPIRE_AXIS              (psppire_axis_get_type ())
+#define PSPPIRE_AXIS(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_PSPPIRE_AXIS, PsppireAxis))
+#define PSPPIRE_AXIS_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_PSPPIRE_AXIS, PsppireAxisClass))
+#define PSPPIRE_IS_AXIS(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_PSPPIRE_AXIS))
+#define PSPPIRE_IS_AXIS_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_PSPPIRE_AXIS))
+#define PSPPIRE_AXIS_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_PSPPIRE_AXIS, PsppireAxisClass))
+
+
+/* --- typedefs & structures --- */
+typedef struct _PsppireAxis       PsppireAxis;
+typedef struct _PsppireAxisClass PsppireAxisClass;
+
+struct _PsppireAxis
+{
+  GObject             parent;
+
+  glong min_extent;
+  gint default_size;
+};
+
+struct _PsppireAxisClass
+{
+  GObjectClass parent_class;
+};
+
+
+GType          psppire_axis_get_type (void);
+
+
+\f
+
+GType psppire_axis_iface_get_type (void);
+
+#define PSPPIRE_TYPE_AXIS_IFACE (psppire_axis_iface_get_type ())
+
+typedef struct _PsppireAxisIface PsppireAxisIface;
+
+struct _PsppireAxisIface
+{
+  GTypeInterface g_iface;
+
+
+  /* Virtual Table */
+
+  gint  (*unit_size) (const PsppireAxis *a, gint unit);
+
+  gint  (*unit_count) (const PsppireAxis *a);
+
+  glong (*pixel_start) (const PsppireAxis *a, gint unit);
+
+  gint  (*get_unit_at_pixel) (const PsppireAxis *a, glong pixel);
+
+  glong (*total_size ) (const PsppireAxis *a);
+};
+
+
+/* Interface between sheet and axis */
+
+gint psppire_axis_unit_size (const PsppireAxis *a, gint unit);
+
+gint psppire_axis_unit_count (const PsppireAxis *a);
+
+glong psppire_axis_pixel_start (const PsppireAxis *a, gint unit);
+
+gint psppire_axis_get_unit_at_pixel (const PsppireAxis *a, glong pixel);
+
+
+G_END_DECLS
+
+#endif /* PSPPIRE_AXIS_H__ */
index 59c50670dcd19400ab741b07605d4741f1d2fe07..c602e83ff841b1e699d6642af98cfcaf19cb0479 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PSPP 0.7.0\n"
 "Report-Msgid-Bugs-To: pspp-dev@gnu.org\n"
-"POT-Creation-Date: 2008-11-08 12:59+0900\n"
+"POT-Creation-Date: 2008-11-11 13:13+0900\n"
 "PO-Revision-Date: 2008-11-05 08:17+0900\n"
 "Last-Translator: John Darrington <john@darrington.wattle.id.au>\n"
 "Language-Team: John Darrington <john@darrington.wattle.id.au>\n"
@@ -323,13 +323,13 @@ msgid "%s variables are not compatible with %s format %s."
 msgstr ""
 
 #: src/data/format.c:327 src/data/sys-file-reader.c:655
-#: src/ui/gui/data-editor.glade:1190 src/ui/gui/psppire.glade:2176
+#: src/ui/gui/data-editor.glade:1197 src/ui/gui/psppire.glade:2176
 #: src/ui/gui/psppire-var-store.c:605
 msgid "String"
 msgstr ""
 
 #: src/data/format.c:327 src/data/sys-file-reader.c:655
-#: src/ui/gui/data-editor.glade:1079 src/ui/gui/psppire.glade:2131
+#: src/ui/gui/data-editor.glade:1086 src/ui/gui/psppire.glade:2131
 #: src/ui/gui/psppire-var-store.c:598
 msgid "Numeric"
 msgstr ""
@@ -3388,7 +3388,7 @@ msgstr ""
 msgid "Cum"
 msgstr ""
 
-#: src/language/stats/frequencies.q:1056 src/output/charts/plot-hist.c:138
+#: src/language/stats/frequencies.q:1056 src/output/charts/plot-hist.c:140
 msgid "Frequency"
 msgstr ""
 
@@ -4016,28 +4016,28 @@ msgstr ""
 msgid "Only USE ALL is currently implemented."
 msgstr ""
 
-#: src/language/utilities/include.c:91
+#: src/language/utilities/include.c:90
 msgid "Expecting BATCH or INTERACTIVE after SYNTAX."
 msgstr ""
 
-#: src/language/utilities/include.c:108
+#: src/language/utilities/include.c:107
 msgid "Expecting YES or NO after CD."
 msgstr ""
 
-#: src/language/utilities/include.c:125
+#: src/language/utilities/include.c:124
 msgid "Expecting CONTINUE or STOP after ERROR."
 msgstr ""
 
-#: src/language/utilities/include.c:132
+#: src/language/utilities/include.c:131
 #, c-format
 msgid "Unexpected token: `%s'."
 msgstr ""
 
-#: src/language/utilities/include.c:177
+#: src/language/utilities/include.c:176
 msgid "expecting file name"
 msgstr ""
 
-#: src/language/utilities/include.c:189
+#: src/language/utilities/include.c:188
 #, c-format
 msgid "Can't find `%s' in include file search path."
 msgstr ""
@@ -4457,7 +4457,7 @@ msgstr ""
 msgid "creating \"%s\""
 msgstr ""
 
-#: src/output/charts/plot-hist.c:136
+#: src/output/charts/plot-hist.c:138
 msgid "HISTOGRAM"
 msgstr ""
 
@@ -4834,329 +4834,337 @@ msgstr ""
 msgid "Style of bevel around the custom entry button"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:150
+#: src/ui/gui/data-editor.c:152
 msgid "Transformations Pending"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:323
+#: src/ui/gui/data-editor.c:325
 msgid "_Labels"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:324
+#: src/ui/gui/data-editor.c:326
 msgid "Show/hide value labels"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:342 src/ui/gui/data-editor.c:361
-#: src/ui/gui/data-editor.c:1512 src/ui/gui/data-editor.c:1566
+#: src/ui/gui/data-editor.c:344 src/ui/gui/data-editor.c:363
+#: src/ui/gui/data-editor.c:1539 src/ui/gui/data-editor.c:1593
 msgid "Clear"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:343
+#: src/ui/gui/data-editor.c:345
 msgid "Delete the cases at the selected position(s)"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:362
+#: src/ui/gui/data-editor.c:364
 msgid "Delete the variables at the selected position(s)"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:377
+#: src/ui/gui/data-editor.c:379
 msgid "Insert _Variable"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:378
+#: src/ui/gui/data-editor.c:380
 msgid "Create a new variable at the current position"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:396
+#: src/ui/gui/data-editor.c:398
 msgid "Insert Ca_se"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:397
+#: src/ui/gui/data-editor.c:399
 msgid "Create a new case at the current position"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:417
+#: src/ui/gui/data-editor.c:419
 msgid "_Goto Case"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:418
+#: src/ui/gui/data-editor.c:420
 msgid "Jump to a Case in the Data Sheet"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:437
+#: src/ui/gui/data-editor.c:439
 msgid "_Weights"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:438
+#: src/ui/gui/data-editor.c:440
 msgid "Weight cases by variable"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:447 src/ui/gui/data-editor.glade:319
+#: src/ui/gui/data-editor.c:449 src/ui/gui/data-editor.glade:319
 msgid "_Transpose"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:448
+#: src/ui/gui/data-editor.c:450
 msgid "Transpose the cases with the variables"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:459
+#: src/ui/gui/data-editor.c:461
 msgid "S_plit"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:460
+#: src/ui/gui/data-editor.c:462
 msgid "Split the active file"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:470
+#: src/ui/gui/data-editor.c:472
 msgid "_Sort"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:471
+#: src/ui/gui/data-editor.c:473
 msgid "Sort cases in the active file"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:479 src/ui/gui/data-editor.glade:340
+#: src/ui/gui/data-editor.c:481 src/ui/gui/data-editor.glade:340
 msgid "Select _Cases"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:480
+#: src/ui/gui/data-editor.c:482
 msgid "Select cases from the active file"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:489 src/ui/gui/data-editor.glade:369
+#: src/ui/gui/data-editor.c:491 src/ui/gui/data-editor.glade:369
 msgid "_Compute"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:490
+#: src/ui/gui/data-editor.c:492
 msgid "Compute new values for a variable"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:498
+#: src/ui/gui/data-editor.c:500
 msgid "Oneway _ANOVA"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:499
+#: src/ui/gui/data-editor.c:501
 msgid "Perform one way analysis of variance"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:507 src/ui/gui/data-editor.glade:496
+#: src/ui/gui/data-editor.c:509 src/ui/gui/data-editor.glade:496
 msgid "_Independent Samples T Test"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:508
+#: src/ui/gui/data-editor.c:510
 msgid "Calculate T Test for samples from independent groups"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:517 src/ui/gui/data-editor.glade:504
+#: src/ui/gui/data-editor.c:519 src/ui/gui/data-editor.glade:504
 msgid "_Paired Samples T Test"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:518
+#: src/ui/gui/data-editor.c:520
 msgid "Calculate T Test for paired samples"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:527
+#: src/ui/gui/data-editor.c:529
 msgid "One _Sample T Test"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:528
+#: src/ui/gui/data-editor.c:530
 msgid "Calculate T Test for sample from a single distribution"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:537 src/ui/gui/data-editor.glade:593
+#: src/ui/gui/data-editor.c:539 src/ui/gui/data-editor.glade:593
 msgid "Data File _Comments"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:538
+#: src/ui/gui/data-editor.c:540
 msgid "Commentary text for the data file"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:546 src/ui/gui/data-editor.glade:228
+#: src/ui/gui/data-editor.c:548 src/ui/gui/data-editor.glade:228
 msgid "_Find"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:547
+#: src/ui/gui/data-editor.c:549
 msgid "Find Case"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:556 src/ui/gui/data-editor.glade:377
+#: src/ui/gui/data-editor.c:558 src/ui/gui/data-editor.glade:377
 msgid "Ran_k Cases"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:557
+#: src/ui/gui/data-editor.c:559
 msgid "Rank Cases"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:566 src/ui/gui/data-editor.glade:389
+#: src/ui/gui/data-editor.c:568 src/ui/gui/data-editor.glade:389
 msgid "Recode into _Same Variables"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:567
+#: src/ui/gui/data-editor.c:569
 msgid "Recode values into the same Variables"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:576 src/ui/gui/data-editor.glade:396
+#: src/ui/gui/data-editor.c:578 src/ui/gui/data-editor.glade:396
 msgid "Recode into _Different Variables"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:577
+#: src/ui/gui/data-editor.c:579
 msgid "Recode values into different Variables"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:586 src/ui/gui/data-editor.glade:293
+#: src/ui/gui/data-editor.c:588 src/ui/gui/data-editor.glade:293
 #: src/ui/gui/data-editor.glade:584
 msgid "_Variables"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:587
+#: src/ui/gui/data-editor.c:589
 msgid "Jump to Variable"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:595 src/ui/gui/data-editor.glade:450
+#: src/ui/gui/data-editor.c:597 src/ui/gui/data-editor.glade:450
 #: src/ui/gui/oneway.glade:179
 msgid "_Descriptives"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:596
+#: src/ui/gui/data-editor.c:598
 msgid "Calculate descriptive statistics (mean, variance, ...)"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:605 src/ui/gui/data-editor.glade:442
+#: src/ui/gui/data-editor.c:607 src/ui/gui/data-editor.glade:442
 msgid "_Frequencies"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:606
+#: src/ui/gui/data-editor.c:608
 msgid "Generate frequency statistics"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:614 src/ui/gui/data-editor.glade:466
+#: src/ui/gui/data-editor.c:616 src/ui/gui/data-editor.glade:466
 msgid "_Crosstabs"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:615
+#: src/ui/gui/data-editor.c:617
 msgid "Generate crosstabulations"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:624 src/ui/gui/data-editor.glade:458
+#: src/ui/gui/data-editor.c:626 src/ui/gui/data-editor.glade:458
 msgid "_Explore"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:625
+#: src/ui/gui/data-editor.c:627
 msgid "Examine Data by Factors"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:634 src/ui/gui/data-editor.glade:532
+#: src/ui/gui/data-editor.c:636 src/ui/gui/data-editor.glade:532
 msgid "Linear _Regression"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:635
+#: src/ui/gui/data-editor.c:637
 msgid "Estimate parameters of the linear model"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1027
+#: src/ui/gui/data-editor.c:921
+msgid "_Split Window"
+msgstr ""
+
+#: src/ui/gui/data-editor.c:922
+msgid "Split the window vertically and horizontally"
+msgstr ""
+
+#: src/ui/gui/data-editor.c:1042
 msgid "Font Selection"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1099
+#: src/ui/gui/data-editor.c:1126
 msgid "No Split"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1108
+#: src/ui/gui/data-editor.c:1135
 msgid "Split by "
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1133
+#: src/ui/gui/data-editor.c:1160
 msgid "Filter off"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1145
+#: src/ui/gui/data-editor.c:1172
 #, c-format
 msgid "Filter by %s"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1163
+#: src/ui/gui/data-editor.c:1190
 msgid "Weights off"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1175
+#: src/ui/gui/data-editor.c:1202
 #, c-format
 msgid "Weight by %s"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1198 src/ui/gui/data-editor.c:1445
-#: src/ui/gui/data-editor.glade:660
+#: src/ui/gui/data-editor.c:1225 src/ui/gui/data-editor.c:1472
+#: src/ui/gui/data-editor.glade:667
 msgid "Open"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1199
+#: src/ui/gui/data-editor.c:1226
 msgid "Open a data file"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1207 src/ui/gui/data-editor.c:1323
-#: src/ui/gui/data-editor.glade:670
+#: src/ui/gui/data-editor.c:1234 src/ui/gui/data-editor.c:1350
+#: src/ui/gui/data-editor.glade:677
 msgid "Save"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1208 src/ui/gui/data-editor.c:1218
+#: src/ui/gui/data-editor.c:1235 src/ui/gui/data-editor.c:1245
 msgid "Save data to file"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1217
+#: src/ui/gui/data-editor.c:1244
 msgid "Save As"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1226 src/ui/gui/recode-dialog.c:928
+#: src/ui/gui/data-editor.c:1253 src/ui/gui/recode-dialog.c:928
 #: src/ui/gui/recode-dialog.c:1023
 msgid "New"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1227
+#: src/ui/gui/data-editor.c:1254
 msgid "New data file"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1235
+#: src/ui/gui/data-editor.c:1262
 msgid "_Import Text Data"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1236
+#: src/ui/gui/data-editor.c:1263
 msgid "Import text data file"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1331 src/ui/gui/data-editor.c:1453
+#: src/ui/gui/data-editor.c:1358 src/ui/gui/data-editor.c:1480
 msgid "System Files (*.sav)"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1337 src/ui/gui/data-editor.c:1459
+#: src/ui/gui/data-editor.c:1364 src/ui/gui/data-editor.c:1486
 msgid "Portable Files (*.por) "
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1343 src/ui/gui/data-editor.c:1465
+#: src/ui/gui/data-editor.c:1370 src/ui/gui/data-editor.c:1492
 #: src/ui/gui/syntax-editor.c:138 src/ui/gui/syntax-editor.c:522
 msgid "All Files"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1351
+#: src/ui/gui/data-editor.c:1378
 msgid "System File"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1356
+#: src/ui/gui/data-editor.c:1383
 msgid "Portable File"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1503
+#: src/ui/gui/data-editor.c:1530
 msgid "Sort Ascending"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1506
+#: src/ui/gui/data-editor.c:1533
 msgid "Sort Descending"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1509 src/ui/gui/data-editor.glade:150
-#: src/ui/gui/data-editor.glade:801
+#: src/ui/gui/data-editor.c:1536 src/ui/gui/data-editor.glade:150
+#: src/ui/gui/data-editor.glade:808
 msgid "Insert Variable"
 msgstr ""
 
-#: src/ui/gui/data-editor.c:1563 src/ui/gui/data-editor.glade:789
+#: src/ui/gui/data-editor.c:1590 src/ui/gui/data-editor.glade:796
 msgid "Insert Case"
 msgstr ""
 
@@ -5197,7 +5205,7 @@ msgstr ""
 msgid "Insert Cases"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:166 src/ui/gui/data-editor.glade:738
+#: src/ui/gui/data-editor.glade:166 src/ui/gui/data-editor.glade:745
 msgid "Go To Case"
 msgstr ""
 
@@ -5299,173 +5307,177 @@ msgstr ""
 msgid "_Minimize All Windows"
 msgstr "_Minimise All Windows"
 
-#: src/ui/gui/data-editor.glade:622 src/ui/gui/output-viewer.glade:99
+#: src/ui/gui/data-editor.glade:618
+msgid "_Split"
+msgstr ""
+
+#: src/ui/gui/data-editor.glade:629 src/ui/gui/output-viewer.glade:99
 #: src/ui/gui/syntax-editor.glade:254
 msgid "_Help"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:629 src/ui/gui/output-viewer.glade:106
+#: src/ui/gui/data-editor.glade:636 src/ui/gui/output-viewer.glade:106
 #: src/ui/gui/syntax-editor.glade:262
 msgid "_Reference Manual"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:636 src/ui/gui/output-viewer.glade:113
+#: src/ui/gui/data-editor.glade:643 src/ui/gui/output-viewer.glade:113
 #: src/ui/gui/syntax-editor.glade:269
 msgid "_About"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:680
+#: src/ui/gui/data-editor.glade:687
 msgid "Print"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:690
+#: src/ui/gui/data-editor.glade:697
 msgid "Recall"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:708
+#: src/ui/gui/data-editor.glade:715
 msgid "Undo"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:718
+#: src/ui/gui/data-editor.glade:725
 msgid "Redo"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:748
+#: src/ui/gui/data-editor.glade:755
 msgid "Variables"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:769
+#: src/ui/gui/data-editor.glade:776
 msgid "Find"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:821
+#: src/ui/gui/data-editor.glade:828
 msgid "Split File"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:832
+#: src/ui/gui/data-editor.glade:839
 msgid "Weight Cases"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:844
+#: src/ui/gui/data-editor.glade:851
 msgid "Select Cases"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:864 src/ui/gui/data-editor.glade:1452
-#: src/ui/gui/data-editor.glade:1633
+#: src/ui/gui/data-editor.glade:871 src/ui/gui/data-editor.glade:1459
+#: src/ui/gui/data-editor.glade:1640
 msgid "Value Labels"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:875
+#: src/ui/gui/data-editor.glade:882
 msgid "Use Sets"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:907
+#: src/ui/gui/data-editor.glade:914
 msgid "Information Area"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:926
+#: src/ui/gui/data-editor.glade:933
 msgid "Processor Area"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:951
+#: src/ui/gui/data-editor.glade:958
 msgid "Case Counter Area"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:976
+#: src/ui/gui/data-editor.glade:983
 msgid "Filter Use Status Area"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1002
+#: src/ui/gui/data-editor.glade:1009
 msgid "Weight Status Area"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1028
+#: src/ui/gui/data-editor.glade:1035
 msgid "Split File Status Area"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1058
+#: src/ui/gui/data-editor.glade:1065
 msgid "Variable Type"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1094 src/ui/gui/psppire-var-store.c:599
+#: src/ui/gui/data-editor.glade:1101 src/ui/gui/psppire-var-store.c:599
 msgid "Comma"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1110 src/ui/gui/psppire-var-store.c:600
+#: src/ui/gui/data-editor.glade:1117 src/ui/gui/psppire-var-store.c:600
 msgid "Dot"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1126
+#: src/ui/gui/data-editor.glade:1133
 msgid "Scientific notation"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1142 src/ui/gui/psppire-var-store.c:602
+#: src/ui/gui/data-editor.glade:1149 src/ui/gui/psppire-var-store.c:602
 msgid "Date"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1158 src/ui/gui/psppire-var-store.c:603
+#: src/ui/gui/data-editor.glade:1165 src/ui/gui/psppire-var-store.c:603
 msgid "Dollar"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1174
+#: src/ui/gui/data-editor.glade:1181
 msgid "Custom currency"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1268
+#: src/ui/gui/data-editor.glade:1275
 msgid "positive"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1274
+#: src/ui/gui/data-editor.glade:1281
 msgid "negative"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1287
+#: src/ui/gui/data-editor.glade:1294
 msgid "Sample"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1337
+#: src/ui/gui/data-editor.glade:1344
 msgid "Width:"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1381
+#: src/ui/gui/data-editor.glade:1388
 msgid "Decimal Places:"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1550
+#: src/ui/gui/data-editor.glade:1557
 msgid "Value Label:"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1563 src/ui/gui/psppire.glade:2544
+#: src/ui/gui/data-editor.glade:1570 src/ui/gui/psppire.glade:2544
 #: src/ui/gui/recode.glade:185
 msgid "Value:"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1700 src/ui/gui/examine.glade:423
+#: src/ui/gui/data-editor.glade:1707 src/ui/gui/examine.glade:423
 #: src/ui/gui/t-test.glade:460
 msgid "Missing Values"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1718
+#: src/ui/gui/data-editor.glade:1725
 msgid "_Range plus one optional discrete missing value"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1743
+#: src/ui/gui/data-editor.glade:1750
 msgid "_Low:"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1772
+#: src/ui/gui/data-editor.glade:1779
 msgid "_High:"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1813
+#: src/ui/gui/data-editor.glade:1820
 msgid "Di_screte value:"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1860
+#: src/ui/gui/data-editor.glade:1867
 msgid "_No missing values"
 msgstr ""
 
-#: src/ui/gui/data-editor.glade:1878
+#: src/ui/gui/data-editor.glade:1885
 msgid "_Discrete missing values"
 msgstr ""
 
@@ -5785,15 +5797,20 @@ msgstr ""
 msgid "Cannot open %s: %s.\n"
 msgstr ""
 
-#: src/ui/gui/psppire-data-editor.c:604
+#: src/ui/gui/psppire.c:270
+#, c-format
+msgid "%s is neither a system nor portable file"
+msgstr ""
+
+#: src/ui/gui/psppire-data-editor.c:703
 msgid "Data View"
 msgstr ""
 
-#: src/ui/gui/psppire-data-editor.c:607
+#: src/ui/gui/psppire-data-editor.c:706
 msgid "Variable View"
 msgstr ""
 
-#: src/ui/gui/psppire-data-store.c:828
+#: src/ui/gui/psppire-data-store.c:829
 msgid "var"
 msgstr ""
 
index a11a1e596c4446106e7f9adab05a385dc307479b..fd07ed30e71e48647462e163b3e6991e83e42f54 100644 (file)
@@ -693,7 +693,7 @@ axis_clone (const struct axis *old)
   for (node = tower_first (&old->log_to_phy); node != NULL;
        node = tower_next (&old->log_to_phy, node))
     {
-      unsigned long int size = tower_node_get_height (node);
+      unsigned long int size = tower_node_get_size (node);
       struct axis_group *group = tower_data (node, struct axis_group, logical);
       tower_insert (&new->log_to_phy, size, make_axis_group (group->phy_start),
                     NULL);
@@ -717,7 +717,7 @@ axis_hash (const struct axis *axis, struct md4_ctx *ctx)
     {
       struct axis_group *group = tower_data (tn, struct axis_group, logical);
       unsigned long int phy_start = group->phy_start;
-      unsigned long int size = tower_node_get_height (tn);
+      unsigned long int size = tower_node_get_size (tn);
 
       md4_process_bytes (&phy_start, sizeof phy_start, ctx);
       md4_process_bytes (&size, sizeof size, ctx);
@@ -921,7 +921,7 @@ split_axis (struct axis *axis, unsigned long int where)
   if (where > group_start)
     {
       unsigned long int size_1 = where - group_start;
-      unsigned long int size_2 = tower_node_get_height (group_node) - size_1;
+      unsigned long int size_2 = tower_node_get_size (group_node) - size_1;
       struct tower_node *next = tower_next (&axis->log_to_phy, group_node);
       struct tower_node *new = make_axis_group (group->phy_start + size_1);
       tower_resize (&axis->log_to_phy, group_node, size_1);
@@ -961,11 +961,11 @@ merge_axis_nodes (struct axis *axis, struct tower_node *node,
   if (next != NULL)
     {
       struct axis_group *next_group = axis_group_from_tower_node (next);
-      unsigned long this_height = tower_node_get_height (node);
+      unsigned long this_height = tower_node_get_size (node);
 
       if (group->phy_start + this_height == next_group->phy_start)
         {
-          unsigned long next_height = tower_node_get_height (next);
+          unsigned long next_height = tower_node_get_size (next);
           tower_resize (t, node, this_height + next_height);
           if (other_node != NULL && *other_node == next)
             *other_node = tower_next (t, *other_node);
@@ -979,11 +979,11 @@ merge_axis_nodes (struct axis *axis, struct tower_node *node,
   if (prev != NULL)
     {
       struct axis_group *prev_group = axis_group_from_tower_node (prev);
-      unsigned long prev_height = tower_node_get_height (prev);
+      unsigned long prev_height = tower_node_get_size (prev);
 
       if (prev_group->phy_start + prev_height == group->phy_start)
         {
-          unsigned long this_height = tower_node_get_height (node);
+          unsigned long this_height = tower_node_get_size (node);
           group->phy_start = prev_group->phy_start;
           tower_resize (t, node, this_height + prev_height);
           if (other_node != NULL && *other_node == prev)
@@ -1007,7 +1007,7 @@ check_axis_merged (const struct axis *axis UNUSED)
     if (prev != NULL)
       {
         struct axis_group *prev_group = axis_group_from_tower_node (prev);
-        unsigned long prev_height = tower_node_get_height (prev);
+        unsigned long prev_height = tower_node_get_size (prev);
         struct axis_group *node_group = axis_group_from_tower_node (node);
         assert (prev_group->phy_start + prev_height != node_group->phy_start);
       }
index caf8e2fc3490cc81968197e732b74f45a5aa14f3..02c6aa76bc5c991a2bc077ed9bc91a3e60972eea 100644 (file)
@@ -1352,3 +1352,21 @@ dict_var_resized (const struct variable *v, int delta)
        d->callbacks->var_resized (d, var_get_dict_index (v), delta, d->cb_data);
     }
 }
+
+/* Called from variable.c to notify the dictionary that the variable's display width
+   has changed */
+void
+dict_var_display_width_changed (const struct variable *v)
+{
+  if ( var_has_vardict (v))
+    {
+      const struct vardict_info *vdi = var_get_vardict (v);
+      struct dictionary *d;
+
+      d = vdi->dict;
+
+      if ( d->callbacks && d->callbacks->var_display_width_changed )
+       d->callbacks->var_display_width_changed (d, var_get_dict_index (v), d->cb_data);
+    }
+}
+
index bb14f52ebef0fe7560ddab190693f75be8b6457f..682409e24216a11c7492cb39082b30d62f101f19 100644 (file)
@@ -157,6 +157,7 @@ struct dict_callbacks
   void (*weight_changed) (struct dictionary *, int, void *);
   void (*filter_changed) (struct dictionary *, int, void *);
   void (*split_changed) (struct dictionary *, void *);
+  void (*var_display_width_changed) (struct dictionary *, int, void *);
  };
 
 void dict_set_callbacks (struct dictionary *, const struct dict_callbacks *,
index 35440a0de644af2fbeb3a407d7da837fe97aca1d..dfde1bffc0b3802d553c7717da47b82a4300908b 100644 (file)
@@ -41,5 +41,6 @@ void var_clear_vardict (struct variable *);
 /* Called by variable.c, defined in dictionary.c. */
 void dict_var_changed (const struct variable *v);
 void dict_var_resized (const struct variable *v, int delta);
+void dict_var_display_width_changed (const struct variable *v);
 
 #endif /* data/vardict.h */
index d14237d925c3442e4baa8bbf9204a09044f41818..ccbe65dc0ed9757be75091637bb346b276182d84 100644 (file)
@@ -778,9 +778,15 @@ var_get_display_width (const struct variable *v)
 
 /* Sets V's display width to DISPLAY_WIDTH. */
 void
-var_set_display_width (struct variable *v, int display_width)
+var_set_display_width (struct variable *v, int new_width)
 {
-  v->display_width = display_width;
+  int old_width = v->display_width;
+
+  v->display_width = new_width;
+
+  if ( old_width != new_width)
+    dict_var_display_width_changed (v);
+
   dict_var_changed (v);
 }
 
index 3b02515709ca9969c8d67eab5c9c2210e4822d1e..c2f865d90c95512d7ec4d3517c68dff96e0181d4 100644 (file)
@@ -77,4 +77,23 @@ maximize (double *dest, double src)
     *dest = src;
 }
 
+
+/* Set *DEST to the lower of *DEST and SRC */
+static inline void
+minimize_int (int *dest, int src)
+{
+  if (src < *dest)
+    *dest = src;
+}
+
+
+/* Set *DEST to the greater of *DEST and SRC */
+static inline void
+maximize_int (int *dest, int src)
+{
+  if (src > *dest)
+    *dest = src;
+}
+
+
 #endif /* libpspp/misc.h */
index 02447d76237d335170dbbf877f099b41e20d8d8e..e8d253d086731c61dd539962cbc79f9c2b3b0750 100644 (file)
@@ -30,12 +30,59 @@ static struct tower_node *next_node (const struct tower *,
                                      const struct tower_node *);
 static struct tower_node *prev_node (const struct tower *,
                                      const struct tower_node *);
-static unsigned long int get_subtree_height (const struct abt_node *);
+static unsigned long int get_subtree_size (const struct abt_node *);
+static unsigned long int get_subtree_count (const struct abt_node *);
 static void reaugment_tower_node (struct abt_node *,
                                   const struct abt_node *,
                                   const struct abt_node *,
                                   const void *aux);
 
+/* Returns the height of the bottom of the given tower NODE.
+
+   The performance of this function is O(lg n) in the number of
+   nodes in the tower.  It is often possible to avoid calling
+   this function, either by taking advantage of the NODE_START
+   parameter to tower_lookup or by incrementally keeping track of
+   height while iterating through a tower.  In the former case
+   the asymptotic performance is no different, since tower_lookup
+   is also O(lg n), but in the latter case performance improves
+   from O(lg n) to O(1). */
+unsigned long int
+tower_node_get_level (const struct tower_node *node)
+{
+  const struct abt_node *p = &node->abt_node;
+  unsigned long level = get_subtree_size (p->down[0]);
+  while (p->up != NULL) 
+    {
+      if (p == p->up->down[1])
+        level += (get_subtree_size (p->up->down[0]) 
+                  + abt_to_tower_node (p->up)->size);
+      p = p->up;
+    }
+  return level;
+}
+
+/* Returns the index of the given tower NODE.
+
+   The performance of this function is O(lg n) in the number of
+   nodes in the tower.  It is often possible to avoid calling
+   this function by keeping track of the index while iterating
+   through a tower.  Doing so when possible will improve
+   performance from O(lg n) to O(1). */
+unsigned long int
+tower_node_get_index (const struct tower_node *node)
+{
+  const struct abt_node *p = &node->abt_node;
+  unsigned long index = get_subtree_count (p->down[0]);
+  while (p->up != NULL) 
+    {
+      if (p == p->up->down[1])
+        index += get_subtree_count (p->up->down[0]) + 1;
+      p = p->up;
+    }
+  return index;
+}
+
 /* Initializes T as an empty tower. */
 void
 tower_init (struct tower *t)
@@ -51,21 +98,28 @@ tower_is_empty (const struct tower *t)
   return t->abt.root == NULL;
 }
 
+/* Returns the number of nodes in tower T. */
+unsigned long int
+tower_count (const struct tower *t)
+{
+  return get_subtree_count (t->abt.root);
+}
+
 /* Returns the total height of tower T. */
 unsigned long
 tower_height (const struct tower *t)
 {
-  return get_subtree_height (t->abt.root);
+  return get_subtree_size (t->abt.root);
 }
 
-/* Inserts node NEW with the specified HEIGHT into T just below
+/* Inserts node NEW with the specified SIZE into T just below
    node UNDER, or at the top of T if UNDER is a null pointer. */
 void
-tower_insert (struct tower *t, unsigned long height, struct tower_node *new,
+tower_insert (struct tower *t, unsigned long size, struct tower_node *new,
               struct tower_node *under)
 {
-  assert (height > 0);
-  new->height = height;
+  assert (size > 0);
+  new->size = size;
   abt_insert_before (&t->abt, under ? &under->abt_node : NULL,
                      &new->abt_node);
   t->cache_bottom = ULONG_MAX;
@@ -81,13 +135,13 @@ tower_delete (struct tower *t, struct tower_node *node)
   return next;
 }
 
-/* Changes the height of NODE in tower T to NEW_HEIGHT. */
+/* Changes the size of NODE in tower T to NEW_SIZE. */
 void
 tower_resize (struct tower *t, struct tower_node *node,
-              unsigned long new_height)
+              unsigned long new_size)
 {
-  assert (new_height > 0);
-  node->height = new_height;
+  assert (new_size > 0);
+  node->size = new_size;
   abt_reaugmented (&t->abt, &node->abt_node);
   t->cache_bottom = ULONG_MAX;
 }
@@ -135,7 +189,7 @@ tower_lookup (const struct tower *t_,
 
   assert (height < tower_height (t));
 
-  if (height >= t->cache_bottom && height - t->cache_bottom < t->cache->height)
+  if (height >= t->cache_bottom && height - t->cache_bottom < t->cache->size)
     {
       *node_start = t->cache_bottom;
       return t->cache;
@@ -145,8 +199,8 @@ tower_lookup (const struct tower *t_,
   p = t->abt.root;
   for (;;)
     {
-      unsigned long left_height = get_subtree_height (p->down[0]);
-      if (height < left_height)
+      unsigned long left_size = get_subtree_size (p->down[0]);
+      if (height < left_size)
         {
           /* Our goal height must lie within the left subtree. */
           p = p->down[0];
@@ -155,11 +209,11 @@ tower_lookup (const struct tower *t_,
         {
           /* Our goal height cannot be in the left subtree. */
           struct tower_node *node = abt_to_tower_node (p);
-          unsigned long int node_height = node->height;
+          unsigned long int node_size = node->size;
 
-          height -= left_height;
-          *node_start += left_height;
-          if (height < node_height)
+          height -= left_size;
+          *node_start += left_size;
+          if (height < node_size)
             {
               /* Our goal height is in P. */
               t->cache = node;
@@ -170,13 +224,40 @@ tower_lookup (const struct tower *t_,
             {
               /* Our goal height is in the right subtree. */
               p = p->down[1];
-              height -= node_height;
-              *node_start += node_height;
+              height -= node_size;
+              *node_start += node_size;
             }
         }
     }
 }
 
+/* Returns the node with the given 0-based INDEX, which must be
+   less than the number of nodes in T (as returned by
+   tower_count). */
+struct tower_node *
+tower_get (const struct tower *t_, unsigned long int index) 
+{
+  struct tower *t = (struct tower *) t_;
+  struct abt_node *p;
+
+  assert (index < tower_count (t));
+
+  p = t->abt.root;
+  for (;;)
+    {
+      unsigned long left_count = get_subtree_count (p->down[0]);
+      if (index < left_count)
+        p = p->down[0];
+      else if (index == left_count)
+        return abt_to_tower_node (p);
+      else
+        {
+          p = p->down[1];
+          index -= left_count + 1;
+        }
+    }
+}
+
 /* Returns the node at height 0 in tower T, or a null pointer if
    T is empty. */
 struct tower_node *
@@ -253,16 +334,24 @@ prev_node (const struct tower *t, const struct tower_node *node)
   return abt_to_tower_node_null (abt_prev (&t->abt, &node->abt_node));
 }
 
-/* Returns the total height of the nodes in the subtree rooted at
+/* Returns the total size of the nodes in the subtree rooted at
    P, or 0 if P is null. */
 static unsigned long int
-get_subtree_height (const struct abt_node *p)
+get_subtree_size (const struct abt_node *p)
+{
+  return p != NULL ? abt_to_tower_node (p)->subtree_size : 0;
+}
+
+/* Returns the total number of nodes in the subtree rooted at P,
+   or 0 if P is null. */
+static unsigned long int
+get_subtree_count (const struct abt_node *p)
 {
-  return p != NULL ? abt_to_tower_node (p)->subtree_height : 0;
+  return p != NULL ? abt_to_tower_node (p)->subtree_count : 0;
 }
 
-/* Recalculates the subtree_height of NODE based on its LEFT and
-   RIGHT children's subtree_heights. */
+/* Recalculates the subtree_size of NODE based on its LEFT and
+   RIGHT children's subtree_sizes. */
 static void
 reaugment_tower_node (struct abt_node *node_,
                       const struct abt_node *left,
@@ -270,9 +359,18 @@ reaugment_tower_node (struct abt_node *node_,
                       const void *aux UNUSED)
 {
   struct tower_node *node = abt_to_tower_node (node_);
-  node->subtree_height = node->height;
-  if (left != NULL)
-    node->subtree_height += abt_to_tower_node (left)->subtree_height;
-  if (right != NULL)
-    node->subtree_height += abt_to_tower_node (right)->subtree_height;
+  node->subtree_size = node->size;
+  node->subtree_count = 1;
+  if (left != NULL) 
+    {
+      struct tower_node *left_node = abt_to_tower_node (left);
+      node->subtree_size += left_node->subtree_size;
+      node->subtree_count += left_node->subtree_count; 
+    }
+  if (right != NULL) 
+    {
+      struct tower_node *right_node = abt_to_tower_node (right);
+      node->subtree_size += right_node->subtree_size;
+      node->subtree_count += right_node->subtree_count; 
+    }
 }
index 55184e51cdc54b0276a2a557950569221931309f..246984a2c1bfd6cd1c46100fbe95f84140843a92 100644 (file)
 
    This is the analogy behind this data structure.  Each node in
    the data structure has a "thickness", which is actually called
-   the node's "height" because "thickness" is just too awkward a
+   the node's "size" because "thickness" is just too awkward a
    name.  The primary way to look up nodes is by a height from
    the bottom of the tower; any height within a node retrieves
    that node, not just the distance to the bottom of the node.
    You can insert a new node between any two existing nodes, or
    at either end, which shifts up the height of all the nodes
    above it.  You can also delete any node, which shifts down the
-   height of all the nodes above it. */
+   height of all the nodes above it.
+
+   The tower data structure also implements efficient access to
+   nodes by index, i.e. by 0-based count of nodes from the bottom
+   of the tower. */
 
 #ifndef LIBPSPP_TOWER_H
 #define LIBPSPP_TOWER_H
 struct tower_node
   {
     struct abt_node abt_node;         /* ABT node. */
-    unsigned long int subtree_height; /* Node's plus descendants' heights. */
-    unsigned long int height;         /* Height. */
+    unsigned long int subtree_size;   /* Node size plus descendants' sizes. */
+    unsigned long int size;           /* Size. */
+    unsigned long int subtree_count;  /* Number of descendants, plus 1. */
   };
 
-/* Returns the height of a tower node. */
+/* Returns the size of a tower node. */
 static inline unsigned long
-tower_node_get_height (const struct tower_node *node)
+tower_node_get_size (const struct tower_node *node)
 {
-  return node->height;
+  return node->size;
 }
 
+unsigned long int tower_node_get_level (const struct tower_node *);
+unsigned long int tower_node_get_index (const struct tower_node *);
+
 /* A tower. */
 struct tower
   {
@@ -80,13 +88,14 @@ struct tower
 void tower_init (struct tower *);
 
 bool tower_is_empty (const struct tower *);
+unsigned long int tower_count (const struct tower *);
 unsigned long int tower_height (const struct tower *);
 
-void tower_insert (struct tower *, unsigned long int height,
+void tower_insert (struct tower *, unsigned long int size,
                    struct tower_node *new, struct tower_node *under);
 struct tower_node *tower_delete (struct tower *, struct tower_node *);
 void tower_resize (struct tower *, struct tower_node *,
-                   unsigned long int new_height);
+                   unsigned long int new_size);
 void tower_splice (struct tower *dst, struct tower_node *under,
                    struct tower *src,
                    struct tower_node *first, struct tower_node *last);
@@ -94,6 +103,7 @@ void tower_splice (struct tower *dst, struct tower_node *under,
 struct tower_node *tower_lookup (const struct tower *,
                                  unsigned long int level,
                                  unsigned long int *node_start);
+struct tower_node *tower_get (const struct tower *, unsigned long int index);
 struct tower_node *tower_first (const struct tower *);
 struct tower_node *tower_last (const struct tower *);
 struct tower_node *tower_next (const struct tower *,
index f77f88c7935134c94beea5f30abb14a9f6dc6471..ee824660b491ada89fdb8238f90998271506e2bf 100644 (file)
@@ -3,7 +3,7 @@
 bin_PROGRAMS += src/ui/gui/psppire 
 
 src_ui_gui_psppire_CFLAGS = $(GTK_CFLAGS) $(GLADE_CFLAGS) -Wall \
-       -DINSTALLDIR=\"$(bindir)\"
+       -DINSTALLDIR=\"$(bindir)\" -DGDK_MULTIHEAD_SAFE=1
 
 
 src_ui_gui_psppire_LDFLAGS = \
@@ -142,8 +142,6 @@ src_ui_gui_psppire_SOURCES = \
        src/ui/gui/psppire-buttonbox.h \
        src/ui/gui/psppire-hbuttonbox.h \
        src/ui/gui/psppire-vbuttonbox.h \
-       src/ui/gui/psppire-case-file.c \
-       src/ui/gui/psppire-case-file.h \
        src/ui/gui/psppire-data-editor.c \
        src/ui/gui/psppire-data-editor.h \
        src/ui/gui/psppire-data-store.c \
index f7df21c752e746bec52f647f672db0082e387fba..13cc29a941f8be002bcbe10103fbddc590be04e6 100644 (file)
@@ -74,6 +74,9 @@ static void on_edit_paste (GtkAction *a, gpointer data);
 
 
 static GtkWidget * create_data_sheet_variable_popup_menu (struct data_editor *);
+
+static GtkWidget * create_var_sheet_variable_popup_menu (struct data_editor *);
+
 static GtkWidget * create_data_sheet_cases_popup_menu (struct data_editor *);
 
 static void register_data_editor_actions (struct data_editor *de);
@@ -81,6 +84,8 @@ static void on_insert_variable (GtkAction *, gpointer data);
 static void insert_case (GtkAction *a, gpointer data);
 
 static void toggle_value_labels (GtkToggleAction *a, gpointer data);
+static void toggle_split_window (GtkToggleAction *ta, gpointer data);
+
 
 /* Callback for when the dictionary changes properties*/
 static void on_weight_change (GObject *, gint, gpointer);
@@ -914,20 +919,36 @@ new_data_editor (void)
                    "activate",
                    G_CALLBACK (minimise_all_windows), NULL);
 
+  de->toggle_split_window =
+    gtk_toggle_action_new ("toggle-split-window",
+                          _("_Split Window"),
+                          _("Split the window vertically and horizontally"),
+                          "pspp-split-window");
+
+  g_signal_connect (de->toggle_split_window, "toggled",
+                   G_CALLBACK (toggle_split_window),
+                   de);
+
+  gtk_action_connect_proxy (GTK_ACTION (de->toggle_split_window),
+                           get_widget_assert (de->xml,
+                                              "windows_split"));
 
   de->data_sheet_variable_popup_menu =
     GTK_MENU (create_data_sheet_variable_popup_menu (de));
 
+  de->var_sheet_variable_popup_menu =
+    GTK_MENU (create_var_sheet_variable_popup_menu (de));
+
   de->data_sheet_cases_popup_menu =
     GTK_MENU (create_data_sheet_cases_popup_menu (de));
 
 
   g_object_set (de->data_editor,
-               "column-menu", de->data_sheet_variable_popup_menu, NULL);
-
+               "datasheet-column-menu", de->data_sheet_variable_popup_menu,
+               "datasheet-row-menu", de->data_sheet_cases_popup_menu,
+               "varsheet-row-menu", de->var_sheet_variable_popup_menu,
+               NULL);
 
-  g_object_set (de->data_editor,
-               "row-menu", de->data_sheet_cases_popup_menu, NULL);
 
   return de;
 }
@@ -1023,9 +1044,19 @@ static void
 fonts_activate (GtkMenuItem *menuitem, gpointer data)
 {
   struct data_editor *de = data;
+  PangoFontDescription *current_font;
+  gchar *font_name;
   GtkWidget *dialog =
     gtk_font_selection_dialog_new (_("Font Selection"));
 
+
+  current_font = GTK_WIDGET(de->data_editor)->style->font_desc;
+  font_name = pango_font_description_to_string (current_font);
+
+  gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (dialog), font_name);
+
+  g_free (font_name);
+
   gtk_window_set_transient_for (GTK_WINDOW (dialog),
                                GTK_WINDOW (get_widget_assert (de->xml,
                                                               "data_editor")));
@@ -1056,6 +1087,18 @@ toggle_value_labels (GtkToggleAction *ta, gpointer data)
 
 
 
+static void
+toggle_split_window (GtkToggleAction *ta, gpointer data)
+{
+  struct data_editor *de = data;
+
+  psppire_data_editor_split_window (de->data_editor,
+                                   gtk_toggle_action_get_active (ta));
+}
+
+
+
+
 static void
 file_quit (GtkCheckMenuItem *menuitem, gpointer data)
 {
@@ -1590,6 +1633,43 @@ create_data_sheet_cases_popup_menu (struct data_editor *de)
 }
 
 
+static GtkWidget *
+create_var_sheet_variable_popup_menu (struct data_editor *de)
+{
+  GtkWidget *menu = gtk_menu_new ();
+
+  GtkWidget *insert_variable =
+    gtk_menu_item_new_with_label (_("Insert Variable"));
+
+  GtkWidget *delete_variable =
+    gtk_menu_item_new_with_label (_("Clear"));
+
+
+  gtk_action_connect_proxy (de->delete_variables,
+                           delete_variable);
+
+
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), insert_variable);
+
+  g_signal_connect_swapped (G_OBJECT (insert_variable), "activate",
+                           G_CALLBACK (gtk_action_activate),
+                           de->insert_variable);
+
+
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu),
+                        gtk_separator_menu_item_new ());
+
+
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), delete_variable);
+
+
+  gtk_widget_show_all (menu);
+
+  return menu;
+}
+
+
+
 \f
 
 static void
index cdf6080e2d2aef9c98da2fff7bd6ad67755a4828..deff3bb5f34363443429891e54afdb2946351700 100644 (file)
                         <property name="use_underline">True</property>
                       </widget>
                     </child>
+                    <child>
+                      <widget class="GtkCheckMenuItem" id="windows_split">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">_Split</property>
+                        <property name="use_underline">True</property>
+                      </widget>
+                    </child>
                   </widget>
                 </child>
               </widget>
index 9ea0e9169e0ba71e714dc1ed611e2249116e55dc..af282e26fb0f947e6896269c53183967d5be0ad2 100644 (file)
@@ -61,6 +61,8 @@ struct data_editor
   GtkAction *invoke_oneway_anova_dialog;
   GtkAction *invoke_t_test_one_sample_dialog;
 
+  GtkToggleAction *toggle_split_window;
+
 
   /* Actions which do things */
   GtkAction *insert_variable;
@@ -75,6 +77,8 @@ struct data_editor
   GtkMenu *data_sheet_variable_popup_menu;
   GtkMenu *data_sheet_cases_popup_menu;
 
+  GtkMenu *var_sheet_variable_popup_menu;
+
   PsppireDataEditor *data_editor;
 
   gboolean save_as_portable;
index 66d3a2cd19709e8c92be02564749bfa41b6cde94..332e2d8e0c3141c0c95a6690f9c087fbec3af55e 100644 (file)
@@ -221,7 +221,7 @@ find_dialog (GObject *o, gpointer data)
                NULL);
 
   fd.dict = vs->dict;
-  fd.data = ds->case_file->datasheet;
+  fd.data = ds->datasheet;
 
   fd.variable_entry        = get_widget_assert (fd.xml, "find-variable-entry");
   fd.value_entry           = get_widget_assert (fd.xml, "find-value-entry");
index 1007ff967fb50653f21f09782d426f03ee01f62c..bae608afa7ab060aeae46ad5782fc914548efabc 100644 (file)
@@ -242,8 +242,7 @@ execute_syntax (struct getl_interface *sss)
 
   reader = proc_extract_active_file_data (the_dataset);
   if (!lazy_casereader_destroy (reader, lazy_serial))
-    psppire_data_store_set_case_file (the_data_store,
-                                      psppire_case_file_new (reader));
+    psppire_data_store_set_reader (the_data_store, reader);
 
   som_flush ();
 
@@ -254,52 +253,6 @@ execute_syntax (struct getl_interface *sss)
 
 
 
-#ifdef G_ENABLE_DEBUG
-# define g_marshal_value_peek_int(v)      g_value_get_int (v)
-#else
-# define g_marshal_value_peek_int(v)      (v)->data[0].v_int
-#endif
-
-
-/* VOID:INT,INT,INT */
-void
-marshaller_VOID__INT_INT_INT (GClosure     *closure,
-                        GValue       *return_value,
-                        guint         n_param_values,
-                        const GValue *param_values,
-                        gpointer      invocation_hint,
-                        gpointer      marshal_data)
-{
-  typedef void (*GMarshalFunc_VOID__INT_INT_INT) (gpointer     data1,
-                                                 gint         arg_1,
-                                                 gint         arg_2,
-                                                 gint         arg_3,
-                                                 gpointer     data2);
-  register GMarshalFunc_VOID__INT_INT_INT callback;
-  register GCClosure *cc = (GCClosure*) closure;
-  register gpointer data1, data2;
-
-  g_return_if_fail (n_param_values == 4);
-
-  if (G_CCLOSURE_SWAP_DATA (closure))
-    {
-      data1 = closure->data;
-      data2 = g_value_peek_pointer (param_values + 0);
-    }
-  else
-    {
-      data1 = g_value_peek_pointer (param_values + 0);
-      data2 = closure->data;
-    }
-  callback = (GMarshalFunc_VOID__INT_INT_INT) (marshal_data ? marshal_data : cc->callback);
-
-  callback (data1,
-            g_marshal_value_peek_int (param_values + 1),
-            g_marshal_value_peek_int (param_values + 2),
-            g_marshal_value_peek_int (param_values + 3),
-            data2);
-}
-
 /* Create a deep copy of SRC */
 GtkListStore *
 clone_list_store (const GtkListStore *src)
diff --git a/src/ui/gui/psppire-case-file.c b/src/ui/gui/psppire-case-file.c
deleted file mode 100644 (file)
index cdb033f..0000000
+++ /dev/null
@@ -1,448 +0,0 @@
-/* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2006  Free Software Foundation
-
-   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 <string.h>
-#include <stdlib.h>
-
-#include "psppire-case-file.h"
-
-#include <gtksheet/gtkextra-marshal.h>
-
-#include <data/format.h>
-#include <data/case.h>
-#include <data/data-in.h>
-#include <data/datasheet.h>
-#include <data/casereader.h>
-#include <math/sort.h>
-#include <libpspp/misc.h>
-
-#include "xalloc.h"
-#include "xmalloca.h"
-
-/* --- prototypes --- */
-static void psppire_case_file_class_init       (PsppireCaseFileClass   *class);
-static void psppire_case_file_init     (PsppireCaseFile        *case_file);
-static void psppire_case_file_finalize (GObject                *object);
-
-
-/* --- variables --- */
-static GObjectClass     *parent_class = NULL;
-
-enum  {CASE_CHANGED,
-       CASE_INSERTED,
-       CASES_DELETED,
-       n_SIGNALS};
-
-static guint signals [n_SIGNALS];
-
-
-/* --- functions --- */
-/**
- * psppire_case_file_get_type:
- * @returns: the type ID for accelerator groups.
- */
-GType
-psppire_case_file_get_type (void)
-{
-  static GType object_type = 0;
-
-  if (!object_type)
-    {
-      static const GTypeInfo object_info = {
-       sizeof (PsppireCaseFileClass),
-       (GBaseInitFunc) NULL,
-       (GBaseFinalizeFunc) NULL,
-       (GClassInitFunc) psppire_case_file_class_init,
-       NULL,   /* class_finalize */
-       NULL,   /* class_data */
-       sizeof (PsppireCaseFile),
-       0,      /* n_preallocs */
-       (GInstanceInitFunc) psppire_case_file_init,
-      };
-
-      object_type = g_type_register_static (G_TYPE_OBJECT, "PsppireCaseFile",
-                                           &object_info, 0);
-    }
-
-  return object_type;
-}
-
-/* Properties */
-enum
-{
-  PROP_0,
-  PROP_DATASHEET,
-  PROP_READER
-};
-
-
-
-
-static void
-psppire_case_file_set_property (GObject         *object,
-                               guint            prop_id,
-                               const GValue    *value,
-                               GParamSpec      *pspec)
-
-{
-  PsppireCaseFile *cf = PSPPIRE_CASE_FILE (object);
-
-  switch (prop_id)
-    {
-    case PROP_READER:
-      cf->datasheet = datasheet_create (g_value_get_pointer (value));
-      cf->accessible = TRUE;
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    };
-}
-
-static void
-psppire_case_file_get_property (GObject         *object,
-                               guint            prop_id,
-                               GValue          *value,
-                               GParamSpec      *pspec)
-{
-  PsppireCaseFile *cf = PSPPIRE_CASE_FILE (object);
-
-  switch (prop_id)
-    {
-    case PROP_DATASHEET:
-      g_value_set_pointer (value, cf->datasheet);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    };
-}
-
-
-static void
-psppire_case_file_class_init (PsppireCaseFileClass *class)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (class);
-  GParamSpec *datasheet_spec ;
-  GParamSpec *reader_spec ;
-
-  parent_class = g_type_class_peek_parent (class);
-
-  object_class->finalize = psppire_case_file_finalize;
-
-  datasheet_spec =
-    g_param_spec_pointer ("datasheet",
-                         "Datasheet",
-                         "A pointer to the datasheet belonging to this object",
-                         G_PARAM_READABLE );
-  reader_spec =
-    g_param_spec_pointer ("casereader",
-                         "CaseReader",
-                         "A pointer to the case reader from which this object is constructed",
-                         G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE );
-
-  object_class->set_property = psppire_case_file_set_property;
-  object_class->get_property = psppire_case_file_get_property;
-
-  g_object_class_install_property (object_class,
-                                   PROP_DATASHEET,
-                                   datasheet_spec);
-
-  g_object_class_install_property (object_class,
-                                   PROP_READER,
-                                   reader_spec);
-
-  signals [CASE_CHANGED] =
-    g_signal_new ("case-changed",
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_FIRST,
-                 0,
-                 NULL, NULL,
-                 g_cclosure_marshal_VOID__INT,
-                 G_TYPE_NONE,
-                 1,
-                 G_TYPE_INT);
-
-
-  signals [CASE_INSERTED] =
-    g_signal_new ("case-inserted",
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_FIRST,
-                 0,
-                 NULL, NULL,
-                 g_cclosure_marshal_VOID__INT,
-                 G_TYPE_NONE,
-                 1,
-                 G_TYPE_INT);
-
-
-  signals [CASES_DELETED] =
-    g_signal_new ("cases-deleted",
-                 G_TYPE_FROM_CLASS (class),
-                 G_SIGNAL_RUN_FIRST,
-                 0,
-                 NULL, NULL,
-                 gtkextra_VOID__INT_INT,
-                 G_TYPE_NONE,
-                 2,
-                 G_TYPE_INT, G_TYPE_INT);
-}
-
-static void
-psppire_case_file_finalize (GObject *object)
-{
-  PsppireCaseFile *cf = PSPPIRE_CASE_FILE (object);
-
-  if ( cf->accessible)
-    datasheet_destroy (cf->datasheet);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-psppire_case_file_init (PsppireCaseFile *cf)
-{
-  cf->datasheet = NULL;
-  cf->accessible = FALSE;
-}
-
-
-/**
- * psppire_case_file_new:
- * @returns: a new #PsppireCaseFile object
- *
- * Creates a new #PsppireCaseFile.
- */
-PsppireCaseFile*
-psppire_case_file_new (struct casereader *reader)
-{
-  return g_object_new (G_TYPE_PSPPIRE_CASE_FILE,
-                      "casereader", reader,
-                      NULL);
-}
-
-
-gboolean
-psppire_case_file_delete_cases (PsppireCaseFile *cf, casenumber n_cases, casenumber first)
-{
-  g_return_val_if_fail (cf, FALSE);
-  g_return_val_if_fail (cf->datasheet, FALSE);
-  g_return_val_if_fail (cf->accessible, FALSE);
-
-  g_return_val_if_fail (first + n_cases <=
-                       psppire_case_file_get_case_count (cf), FALSE);
-
-  datasheet_delete_rows (cf->datasheet, first, n_cases);
-
-  g_signal_emit (cf, signals [CASES_DELETED], 0, first, n_cases);
-
-  return TRUE;
-}
-
-/* Insert case CC into the case file before POSN */
-gboolean
-psppire_case_file_insert_case (PsppireCaseFile *cf,
-                              struct ccase *cc,
-                              casenumber posn)
-{
-  struct ccase tmp;
-  bool result ;
-
-  g_return_val_if_fail (cf, FALSE);
-  g_return_val_if_fail (cf->datasheet, FALSE);
-  g_return_val_if_fail (cf->accessible, FALSE);
-
-  case_clone (&tmp, cc);
-  result = datasheet_insert_rows (cf->datasheet, posn, &tmp, 1);
-
-  if ( result )
-    g_signal_emit (cf, signals [CASE_INSERTED], 0, posn);
-  else
-    g_warning ("Cannot insert case at position %ld\n", posn);
-
-  return result;
-}
-
-
-casenumber
-psppire_case_file_get_case_count (const PsppireCaseFile *cf)
-{
-  g_return_val_if_fail (cf, FALSE);
-  g_return_val_if_fail (cf->accessible, FALSE);
-
-  if ( ! cf->datasheet)
-    return 0;
-
-  return datasheet_get_row_cnt (cf->datasheet);
-}
-
-/* Copies the IDXth value from case CASENUM into VALUE.
-   If VALUE is null, then memory is allocated is allocated with
-   malloc.  Returns the value if successful, NULL on failure. */
-union value *
-psppire_case_file_get_value (const PsppireCaseFile *cf,
-                             casenumber casenum, size_t idx,
-                             union value *value, int width)
-{
-  bool allocated;
-
-  g_return_val_if_fail (cf, false);
-  g_return_val_if_fail (cf->datasheet, false);
-
-  g_return_val_if_fail (idx < datasheet_get_column_cnt (cf->datasheet), false);
-
-  if (value == NULL)
-    {
-      value = xnmalloc (value_cnt_from_width (width), sizeof *value);
-      allocated = true;
-    }
-  else
-    allocated = false;
-  if (!datasheet_get_value (cf->datasheet, casenum, idx, value, width))
-    {
-      if (allocated)
-        free (value);
-      value = NULL;
-    }
-  return value;
-}
-
-void
-psppire_case_file_clear (PsppireCaseFile *cf)
-{
-  datasheet_destroy (cf->datasheet);
-  cf->datasheet = NULL;
-  g_signal_emit (cf, signals [CASES_DELETED], 0, 0, -1);
-}
-
-/* Set the IDXth value of case C to V.
-   Returns true if successful, false on I/O error. */
-gboolean
-psppire_case_file_set_value (PsppireCaseFile *cf, casenumber casenum, gint idx,
-                           union value *v, gint width)
-{
-  bool ok;
-
-  g_return_val_if_fail (cf, FALSE);
-  g_return_val_if_fail (cf->datasheet, FALSE);
-
-  g_return_val_if_fail (idx < datasheet_get_column_cnt (cf->datasheet), FALSE);
-
-  ok = datasheet_put_value (cf->datasheet, casenum, idx, v, width);
-  if (ok)
-    g_signal_emit (cf, signals [CASE_CHANGED], 0, casenum);
-  return ok;
-}
-
-
-
-/* Set the IDXth value of case C using D_IN */
-gboolean
-psppire_case_file_data_in (PsppireCaseFile *cf, casenumber casenum, gint idx,
-                          struct substring input, const struct fmt_spec *fmt)
-{
-  union value *value = NULL;
-  int width;
-  bool ok;
-
-  g_return_val_if_fail (cf, FALSE);
-  g_return_val_if_fail (cf->datasheet, FALSE);
-
-  g_return_val_if_fail (idx < datasheet_get_column_cnt (cf->datasheet), FALSE);
-
-  width = fmt_var_width (fmt);
-  value = xmalloca (value_cnt_from_width (width) * sizeof *value);
-  ok = (datasheet_get_value (cf->datasheet, casenum, idx, value, width)
-        && data_in (input, LEGACY_NATIVE, fmt->type, 0, 0, 0, value, width)
-        && datasheet_put_value (cf->datasheet, casenum, idx, value, width));
-
-  if (ok)
-    g_signal_emit (cf, signals [CASE_CHANGED], 0, casenum);
-
-  freea (value);
-
-  return TRUE;
-}
-
-
-void
-psppire_case_file_sort (PsppireCaseFile *cf, const struct subcase *ordering)
-{
-  struct casereader *sorted_data;
-  gint c;
-
-  sorted_data = sort_execute (datasheet_make_reader (cf->datasheet), ordering);
-  cf->datasheet = datasheet_create (sorted_data);
-
-  /* FIXME: Need to have a signal to change a range of cases, instead of
-     calling a signal many times */
-  for ( c = 0 ; c < datasheet_get_row_cnt (cf->datasheet) ; ++c )
-    g_signal_emit (cf, signals [CASE_CHANGED], 0, c);
-}
-
-
-/* Resize the cases in the casefile, by inserting N_VALUES into every
-   one of them at the position immediately preceeding WHERE.
-*/
-gboolean
-psppire_case_file_insert_values (PsppireCaseFile *cf,
-                                gint n_values, gint where)
-{
-  g_return_val_if_fail (cf, FALSE);
-  g_return_val_if_fail (cf->accessible, FALSE);
-
-  if ( n_values == 0 )
-    return FALSE;
-
-  g_assert (n_values > 0);
-
-  if ( ! cf->datasheet )
-    cf->datasheet = datasheet_create (NULL);
-
-  {
-    union value *values = xcalloc (n_values, sizeof *values);
-    datasheet_insert_columns (cf->datasheet, values, n_values, where);
-    free (values);
-  }
-
-  return TRUE;
-}
-
-
-/* Fills C with the CASENUMth case.
-   Returns true on success, false otherwise.
- */
-gboolean
-psppire_case_file_get_case (const PsppireCaseFile *cf, casenumber casenum,
-                          struct ccase *c)
-{
-  g_return_val_if_fail (cf, FALSE);
-  g_return_val_if_fail (cf->datasheet, FALSE);
-
-  return datasheet_get_row (cf->datasheet, casenum, c);
-}
-
-
-
-struct casereader *
-psppire_case_file_make_reader (PsppireCaseFile *cf)
-{
-  struct casereader *r = datasheet_make_reader (cf->datasheet);
-  cf->accessible = FALSE;
-  return r;
-}
-
diff --git a/src/ui/gui/psppire-case-file.h b/src/ui/gui/psppire-case-file.h
deleted file mode 100644 (file)
index f4822f4..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2006  Free Software Foundation
-
-   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 __CASE_FILE_H__
-#define __CASE_FILE_H__
-
-
-#include <glib-object.h>
-#include <glib.h>
-
-#include <libpspp/str.h>
-#include <data/case.h>
-
-
-
-G_BEGIN_DECLS
-
-
-/* --- type macros --- */
-#define G_TYPE_PSPPIRE_CASE_FILE              (psppire_case_file_get_type ())
-#define PSPPIRE_CASE_FILE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_PSPPIRE_CASE_FILE, PsppireCaseFile))
-#define PSPPIRE_CASE_FILE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_PSPPIRE_CASE_FILE, PsppireCaseFileClass))
-#define G_IS_PSPPIRE_CASE_FILE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_PSPPIRE_CASE_FILE))
-#define G_IS_PSPPIRE_CASE_FILE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_PSPPIRE_CASE_FILE))
-#define PSPPIRE_CASE_FILE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_PSPPIRE_CASE_FILE, PsppireCaseFileClass))
-
-
-
-
-/* --- typedefs & structures --- */
-typedef struct _PsppireCaseFile           PsppireCaseFile;
-typedef struct _PsppireCaseFileClass PsppireCaseFileClass;
-
-struct ccase;
-struct casereader;
-
-struct _PsppireCaseFile
-{
-  GObject             parent;
-
-  /* <private> */
-  struct datasheet *datasheet;
-  gboolean      accessible;
-};
-
-
-struct _PsppireCaseFileClass
-{
-  GObjectClass parent_class;
-};
-
-
-/* -- PsppireCaseFile --- */
-GType          psppire_case_file_get_type (void);
-
-PsppireCaseFile *psppire_case_file_new (struct casereader *);
-
-gboolean psppire_case_file_insert_case (PsppireCaseFile *cf, struct ccase *c, casenumber row);
-
-inline casenumber psppire_case_file_get_case_count (const PsppireCaseFile *cf);
-
-
-union value * psppire_case_file_get_value (const PsppireCaseFile *cf,
-                                           casenumber, size_t idx,
-                                           union value *, int width);
-
-struct fmt_spec;
-
-gboolean psppire_case_file_data_in (PsppireCaseFile *cf, casenumber c, gint idx,
-                                   struct substring input,
-                                   const struct fmt_spec *);
-
-gboolean psppire_case_file_set_value (PsppireCaseFile *cf, casenumber casenum,
-                                    gint idx, union value *v, gint width);
-
-void psppire_case_file_clear (PsppireCaseFile *cf);
-
-
-gboolean psppire_case_file_delete_cases (PsppireCaseFile *cf, casenumber n_rows,
-                                       casenumber first);
-
-gboolean psppire_case_file_insert_values (PsppireCaseFile *cf, gint n_values, gint where);
-
-struct subcase;
-
-void psppire_case_file_sort (PsppireCaseFile *cf, const struct subcase *);
-
-gboolean psppire_case_file_get_case (const PsppireCaseFile *cf, 
-                                       casenumber casenum,
-                                       struct ccase *c);
-
-
-struct casereader * psppire_case_file_make_reader (PsppireCaseFile *cf);
-
-
-G_END_DECLS
-
-#endif /* __PSPPIRE_CASE_FILE_H__ */
index 1db96b155652fdd04198e4c3ef8bd3dab6a7975a..c68133df2cacab89941e8c58433b16f0714bb6ed 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPPIRE - a graphical user interface for PSPP.
-   Copyrigght (C) 2008 Free Software Foundation, Inc.
+   Copyright (C) 2008 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
 #include <config.h>
 #include <gtk/gtksignal.h>
 #include <gtk/gtk.h>
-#include <gtksheet/gtksheet.h>
+#include <gtksheet/gtkextra-sheet.h>
 #include "psppire-data-editor.h"
 #include "psppire-var-sheet.h"
 
-#include <gtksheet/gsheet-hetero-column.h>
 #include <language/syntax-string-source.h>
 #include "psppire-data-store.h"
+#include <gtksheet/psppire-axis-hetero.h>
+#include <gtksheet/psppire-axis-uniform.h>
 #include "helper.h"
 
+#include <gtksheet/gtkxpaned.h>
 #include <gettext.h>
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 
 
+static void psppire_data_editor_remove_split (PsppireDataEditor *de);
+static void psppire_data_editor_set_split (PsppireDataEditor *de);
+
 enum {
   DATA_SELECTION_CHANGED,
   DATA_AVAILABLE_CHANGED,
@@ -104,8 +109,12 @@ psppire_data_editor_finalize (GObject *obj)
 
 
 
-static void popup_variable_menu (GtkSheet *sheet, gint column,
-                                GdkEventButton *event, gpointer data);
+static void popup_variable_column_menu (GtkSheet *sheet, gint column,
+                                       GdkEventButton *event, gpointer data);
+
+static void popup_variable_row_menu (GtkSheet *sheet, gint row,
+                                    GdkEventButton *event, gpointer data);
+
 
 static void popup_cases_menu (GtkSheet *sheet, gint row,
                              GdkEventButton *event, gpointer data);
@@ -113,21 +122,30 @@ static void popup_cases_menu (GtkSheet *sheet, gint row,
 
 
 
+
 /* Callback which occurs when the data sheet's column title
    is double clicked */
 static gboolean
 on_data_column_clicked (PsppireDataEditor *de, gint col, gpointer data)
 {
-
+  GtkSheetRange visible_range;
   gint current_row, current_column;
 
-  gtk_notebook_set_current_page (GTK_NOTEBOOK (de), PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
+  gtk_notebook_set_current_page (GTK_NOTEBOOK (de),
+                                PSPPIRE_DATA_EDITOR_VARIABLE_VIEW);
 
   gtk_sheet_get_active_cell (GTK_SHEET (de->var_sheet),
                             &current_row, &current_column);
 
   gtk_sheet_set_active_cell (GTK_SHEET (de->var_sheet), col, current_column);
 
+
+  gtk_sheet_get_visible_range (GTK_SHEET (de->var_sheet), &visible_range);
+
+  if ( col < visible_range.row0 || col > visible_range.rowi)
+    gtk_sheet_moveto (GTK_SHEET (de->var_sheet), col, current_column, 0.5, 0.5);
+
+
   return FALSE;
 }
 
@@ -143,57 +161,270 @@ on_var_row_clicked (PsppireDataEditor *de, gint row, gpointer data)
 
   gtk_notebook_set_current_page (GTK_NOTEBOOK(de), PSPPIRE_DATA_EDITOR_DATA_VIEW);
 
-  gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet),
+  gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet[0]),
                             &current_row, &current_column);
 
-  gtk_sheet_set_active_cell (GTK_SHEET (de->data_sheet), current_row, row);
+  gtk_sheet_set_active_cell (GTK_SHEET (de->data_sheet[0]), current_row, row);
 
-  gtk_sheet_get_visible_range (GTK_SHEET (de->data_sheet), &visible_range);
+  gtk_sheet_get_visible_range (GTK_SHEET (de->data_sheet[0]), &visible_range);
 
   if ( row < visible_range.col0 || row > visible_range.coli)
-    {
-      gtk_sheet_moveto (GTK_SHEET (de->data_sheet),
-                       current_row, row, 0, 0);
-    }
+    gtk_sheet_moveto (GTK_SHEET (de->data_sheet[0]), -1, row, 0.5, 0.5);
 
   return FALSE;
 }
 
 
+/* Moves the focus to a new cell.
+   Returns TRUE iff the move should be disallowed */
+static gboolean
+traverse_cell_callback (GtkSheet *sheet,
+                       GtkSheetCell *existing_cell,
+                       GtkSheetCell *new_cell,
+                       gpointer data)
+{
+  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
+  const PsppireDict *dict = de->data_store->dict;
+
+  if ( new_cell->col >= psppire_dict_get_var_cnt (dict))
+    return TRUE;
+
+  return FALSE;
+}
+
 
 enum
   {
     PROP_0,
     PROP_DATA_STORE,
     PROP_VAR_STORE,
-    PROP_COLUMN_MENU,
-    PROP_ROW_MENU,
+    PROP_VS_ROW_MENU,
+    PROP_DS_COLUMN_MENU,
+    PROP_DS_ROW_MENU,
     PROP_VALUE_LABELS,
     PROP_CURRENT_CASE,
     PROP_CURRENT_VAR,
-    PROP_DATA_SELECTED
+    PROP_DATA_SELECTED,
+    PROP_SPLIT_WINDOW
   };
 
+
+#define DEFAULT_ROW_HEIGHT 25
+
+static void
+new_data_callback (PsppireDataStore *ds, gpointer data)
+{
+  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
+  gint i;
+  for (i = 0 ; i < 4 ; ++i)
+    {
+      PsppireAxisUniform *vaxis;
+      casenumber n_cases =  psppire_data_store_get_case_count (ds);
+
+      g_object_get (de->data_sheet[i], "vertical-axis", &vaxis, NULL);
+
+      psppire_axis_uniform_set_count (vaxis, n_cases);
+    }
+}
+
+static void
+case_inserted_callback (PsppireDataStore *ds, gint before, gpointer data)
+{
+  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
+
+  gint i;
+
+  for (i = 0 ; i < 4 ; ++i)
+    {
+      PsppireAxisUniform *vaxis;
+      casenumber n_cases =  psppire_data_store_get_case_count (ds);
+
+      g_object_get (de->data_sheet[i], "vertical-axis", &vaxis, NULL);
+
+      psppire_axis_uniform_set_count (vaxis, n_cases + 1);
+    }
+}
+
+
+static void
+cases_deleted_callback (PsppireDataStore *ds, gint first, gint n_cases, gpointer data)
+{
+  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
+
+  gint i;
+
+  for (i = 0 ; i < 4 ; ++i)
+    {
+      PsppireAxisUniform *vaxis;
+      casenumber case_count =  psppire_data_store_get_case_count (ds);
+
+      g_object_get (de->data_sheet[i], "vertical-axis", &vaxis, NULL);
+
+      psppire_axis_uniform_set_count (vaxis, case_count - n_cases);
+    }
+}
+
+
+
+/* Return the width (in pixels) of an upper case M when rendered in the
+   current font of W
+*/
+static gint
+width_of_m (GtkWidget *w)
+{
+  PangoRectangle rect;
+  PangoLayout *layout = gtk_widget_create_pango_layout (w, "M");
+
+  pango_layout_get_pixel_extents (layout, NULL, &rect);
+
+  g_object_unref (layout);
+
+  return rect.width;
+}
+
+static void
+new_variables_callback (PsppireDict *dict, gpointer data)
+{
+  gint v, i;
+  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
+  gint m_width = width_of_m (GTK_WIDGET (de));
+
+  PsppireAxisHetero *vaxis;
+  g_object_get (de->var_sheet, "vertical-axis", &vaxis, NULL);
+
+  psppire_axis_hetero_clear (vaxis);
+
+  for (v = 0 ; v < psppire_dict_get_var_cnt (dict); ++v)
+    psppire_axis_hetero_append (vaxis, DEFAULT_ROW_HEIGHT);
+
+  for (i = 0 ; i < 4 ; ++i)
+    {
+      PsppireAxisHetero *haxis;
+      g_object_get (de->data_sheet[i], "horizontal-axis", &haxis, NULL);
+
+      psppire_axis_hetero_clear (haxis);
+
+      for (v = 0 ; v < psppire_dict_get_var_cnt (dict); ++v)
+       {
+         const struct variable *var = psppire_dict_get_variable (dict, v);
+
+         psppire_axis_hetero_append (haxis, m_width * var_get_display_width (var));
+       }
+    }
+}
+
+static void
+insert_variable_callback (PsppireDict *dict, gint x, gpointer data)
+{
+  gint i;
+
+  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
+
+  gint m_width  = width_of_m (GTK_WIDGET (de));
+
+  PsppireAxisHetero *var_vaxis;
+  g_object_get (de->var_sheet, "vertical-axis", &var_vaxis, NULL);
+
+  psppire_axis_hetero_insert (var_vaxis, DEFAULT_ROW_HEIGHT, x);
+
+  for (i = 0 ; i < 4 ; ++i)
+    {
+      const struct variable *var = psppire_dict_get_variable (dict, x);
+      PsppireAxisHetero *haxis;
+      g_object_get (de->data_sheet[i], "horizontal-axis", &haxis, NULL);
+
+      psppire_axis_hetero_insert (haxis, m_width * var_get_display_width (var), x);
+    }
+}
+
+
+static void
+delete_variable_callback (PsppireDict *dict, gint posn,
+                         gint x UNUSED, gint y UNUSED, gpointer data)
+{
+  gint i;
+  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
+
+  PsppireAxisHetero *var_vaxis;
+  g_object_get (de->var_sheet, "vertical-axis", &var_vaxis, NULL);
+
+  psppire_axis_hetero_remove (var_vaxis, posn);
+
+  for (i = 0 ; i < 4 ; ++i)
+    {
+      PsppireAxisHetero *haxis;
+      g_object_get (de->data_sheet[i], "horizontal-axis", &haxis, NULL);
+
+      psppire_axis_hetero_remove (haxis, posn);
+    }
+}
+
+
+static void
+rewidth_variable_callback (PsppireDict *dict, gint posn, gpointer data)
+{
+  gint i;
+  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
+  gint m_width = width_of_m (GTK_WIDGET (de));
+
+  for (i = 0 ; i < 4 ; ++i)
+    {
+      const struct variable *var = psppire_dict_get_variable (dict, posn);
+      PsppireAxisHetero *haxis;
+      g_object_get (de->data_sheet[i], "horizontal-axis", &haxis, NULL);
+
+      psppire_axis_hetero_resize_unit (haxis,
+                                      m_width *
+                                      var_get_display_width (var), posn);
+    }
+}
+
+
 static void
 psppire_data_editor_set_property (GObject         *object,
                                  guint            prop_id,
                                  const GValue    *value,
                                  GParamSpec      *pspec)
 {
+  int i;
   PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (object);
 
   switch (prop_id)
     {
+    case PROP_SPLIT_WINDOW:
+      psppire_data_editor_split_window (de, g_value_get_boolean (value));
+      break;
     case PROP_DATA_STORE:
       if ( de->data_store) g_object_unref (de->data_store);
       de->data_store = g_value_get_pointer (value);
       g_object_ref (de->data_store);
 
-      g_object_set (de->data_sheet,
-                   "row-geometry", de->data_store,
-                   "column-geometry", de->data_store,
-                   "model", de->data_store,
-                   NULL);
+      for (i = 0 ; i < 4 ; ++i )
+       g_object_set (de->data_sheet[i],
+                     "model", de->data_store,
+                     NULL);
+
+      g_signal_connect (de->data_store->dict, "backend-changed",
+                       G_CALLBACK (new_variables_callback), de);
+
+      g_signal_connect (de->data_store->dict, "variable-inserted",
+                       G_CALLBACK (insert_variable_callback), de);
+
+      g_signal_connect (de->data_store->dict, "variable-deleted",
+                       G_CALLBACK (delete_variable_callback), de);
+
+      g_signal_connect (de->data_store->dict, "variable-display-width-changed",
+                       G_CALLBACK (rewidth_variable_callback), de);
+
+      g_signal_connect (de->data_store, "backend-changed",
+                       G_CALLBACK (new_data_callback), de);
+
+      g_signal_connect (de->data_store, "case-inserted",
+                       G_CALLBACK (case_inserted_callback), de);
+
+      g_signal_connect (de->data_store, "cases-deleted",
+                       G_CALLBACK (cases_deleted_callback), de);
+
       break;
     case PROP_VAR_STORE:
       if ( de->var_store) g_object_unref (de->var_store);
@@ -201,23 +432,30 @@ psppire_data_editor_set_property (GObject         *object,
       g_object_ref (de->var_store);
 
       g_object_set (de->var_sheet,
-                   "row-geometry", de->var_store,
                    "model", de->var_store,
                    NULL);
       break;
-    case PROP_COLUMN_MENU:
+    case PROP_VS_ROW_MENU:
+      {
+       GObject *menu = g_value_get_object (value);
+
+       g_signal_connect (de->var_sheet, "button-event-row",
+                         G_CALLBACK (popup_variable_row_menu), menu);
+      }
+      break;
+    case PROP_DS_COLUMN_MENU:
       {
        GObject *menu = g_value_get_object (value);
 
-       g_signal_connect (de->data_sheet, "button-event-column",
-                         G_CALLBACK (popup_variable_menu), menu);
+       g_signal_connect (de->data_sheet[0], "button-event-column",
+                         G_CALLBACK (popup_variable_column_menu), menu);
       }
       break;
-    case PROP_ROW_MENU:
+    case PROP_DS_ROW_MENU:
       {
        GObject *menu = g_value_get_object (value);
 
-       g_signal_connect (de->data_sheet, "button-event-row",
+       g_signal_connect (de->data_sheet[0], "button-event-row",
                          G_CALLBACK (popup_cases_menu), menu);
       }
       break;
@@ -228,14 +466,14 @@ psppire_data_editor_set_property (GObject         *object,
        switch (gtk_notebook_get_current_page (GTK_NOTEBOOK (object)))
          {
          case PSPPIRE_DATA_EDITOR_DATA_VIEW:
-           gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet), &row, &col);
-           gtk_sheet_set_active_cell (GTK_SHEET (de->data_sheet), row, var);
-           gtk_sheet_moveto (GTK_SHEET (de->data_sheet), row, var, 0.5, 0.5);
+           gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet[0]), &row, &col);
+           gtk_sheet_set_active_cell (GTK_SHEET (de->data_sheet[0]), row, var);
+           gtk_sheet_moveto (GTK_SHEET (de->data_sheet[0]), -1, var, 0.5, 0.5);
            break;
          case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
            gtk_sheet_get_active_cell (GTK_SHEET (de->var_sheet), &row, &col);
            gtk_sheet_set_active_cell (GTK_SHEET (de->var_sheet), var, col);
-           gtk_sheet_moveto (GTK_SHEET (de->var_sheet), var, col,  0.5, 0.5);
+           gtk_sheet_moveto (GTK_SHEET (de->var_sheet), var, -1,  0.5, 0.5);
            break;
          default:
            g_assert_not_reached ();
@@ -247,9 +485,9 @@ psppire_data_editor_set_property (GObject         *object,
       {
        gint row, col;
        gint case_num = g_value_get_long (value);
-       gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet), &row, &col);
-       gtk_sheet_set_active_cell (GTK_SHEET (de->data_sheet), case_num, col);
-       gtk_sheet_moveto (GTK_SHEET (de->data_sheet), case_num, col, 0.5, 0.5);
+       gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet[0]), &row, &col);
+       gtk_sheet_set_active_cell (GTK_SHEET (de->data_sheet[0]), case_num, col);
+       gtk_sheet_moveto (GTK_SHEET (de->data_sheet[0]), case_num, -1, 0.5, 0.5);
       }
       break;
     case PROP_VALUE_LABELS:
@@ -274,6 +512,9 @@ psppire_data_editor_get_property (GObject         *object,
 
   switch (prop_id)
     {
+    case PROP_SPLIT_WINDOW:
+      g_value_set_boolean (value, de->split);
+      break;
     case PROP_DATA_STORE:
       g_value_set_pointer (value, de->data_store);
       break;
@@ -283,14 +524,14 @@ psppire_data_editor_get_property (GObject         *object,
     case PROP_CURRENT_CASE:
       {
        gint row, column;
-       gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet), &row, &column);
+       gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet[0]), &row, &column);
        g_value_set_long (value, row);
       }
       break;
     case PROP_CURRENT_VAR:
       {
        gint row, column;
-       gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet), &row, &column);
+       gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet[0]), &row, &column);
        g_value_set_long (value, column);
       }
       break;
@@ -310,11 +551,13 @@ psppire_data_editor_class_init (PsppireDataEditorClass *klass)
   GParamSpec *data_store_spec ;
   GParamSpec *var_store_spec ;
   GParamSpec *column_menu_spec;
-  GParamSpec *row_menu_spec;
+  GParamSpec *ds_row_menu_spec;
+  GParamSpec *vs_row_menu_spec;
   GParamSpec *value_labels_spec;
   GParamSpec *current_case_spec;
   GParamSpec *current_var_spec;
   GParamSpec *data_selected_spec;
+  GParamSpec *split_window_spec;
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   parent_class = g_type_class_peek_parent (klass);
@@ -346,27 +589,40 @@ psppire_data_editor_class_init (PsppireDataEditorClass *klass)
                                    var_store_spec);
 
   column_menu_spec =
-    g_param_spec_object ("column-menu",
-                        "Column Menu",
-                        "A menu to be displayed when button 3 is pressed in the column title buttons",
+    g_param_spec_object ("datasheet-column-menu",
+                        "Data Sheet Column Menu",
+                        "A menu to be displayed when button 3 is pressed in thedata sheet's column title buttons",
                         GTK_TYPE_MENU,
                         G_PARAM_WRITABLE);
 
   g_object_class_install_property (object_class,
-                                   PROP_COLUMN_MENU,
+                                   PROP_DS_COLUMN_MENU,
                                    column_menu_spec);
 
 
-  row_menu_spec =
-    g_param_spec_object ("row-menu",
-                        "Row Menu",
-                        "A menu to be displayed when button 3 is pressed in the row title buttons",
+  ds_row_menu_spec =
+    g_param_spec_object ("datasheet-row-menu",
+                        "Data Sheet Row Menu",
+                        "A menu to be displayed when button 3 is pressed in the data sheet's row title buttons",
+                        GTK_TYPE_MENU,
+                        G_PARAM_WRITABLE);
+
+  g_object_class_install_property (object_class,
+                                   PROP_DS_ROW_MENU,
+                                   ds_row_menu_spec);
+
+
+  vs_row_menu_spec =
+    g_param_spec_object ("varsheet-row-menu",
+                        "Variable Sheet Row Menu",
+                        "A menu to be displayed when button 3 is pressed in the variable sheet's row title buttons",
                         GTK_TYPE_MENU,
                         G_PARAM_WRITABLE);
 
   g_object_class_install_property (object_class,
-                                   PROP_ROW_MENU,
-                                   row_menu_spec);
+                                   PROP_VS_ROW_MENU,
+                                   vs_row_menu_spec);
+
 
   value_labels_spec =
     g_param_spec_boolean ("value-labels",
@@ -419,6 +675,17 @@ psppire_data_editor_class_init (PsppireDataEditorClass *klass)
 
 
 
+  split_window_spec =
+    g_param_spec_boolean ("split",
+                         "Split Window",
+                         "True iff the data sheet is split",
+                         FALSE,
+                         G_PARAM_READABLE | G_PARAM_WRITABLE);
+
+  g_object_class_install_property (object_class,
+                                   PROP_SPLIT_WINDOW,
+                                   split_window_spec);
+
   data_editor_signals [DATA_SELECTION_CHANGED] =
     g_signal_new ("data-selection-changed",
                  G_TYPE_FROM_CLASS (klass),
@@ -468,7 +735,10 @@ psppire_data_editor_class_init (PsppireDataEditorClass *klass)
 
 /* Update the data_ref_entry with the reference of the active cell */
 static gint
-update_data_ref_entry (const GtkSheet *sheet, gint row, gint col, gpointer data)
+update_data_ref_entry (const GtkSheet *sheet,
+                      gint row, gint col,
+                      gint old_row, gint old_col,
+                      gpointer data)
 {
   PsppireDataEditor *de = data;
 
@@ -533,7 +803,7 @@ datum_entry_activate (GtkEntry *entry, gpointer data)
 
   const gchar *text = gtk_entry_get_text (entry);
 
-  gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet), &row, &column);
+  gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet[0]), &row, &column);
 
   if ( row == -1 || column == -1)
     return;
@@ -541,9 +811,7 @@ datum_entry_activate (GtkEntry *entry, gpointer data)
   psppire_data_store_set_string (de->data_store, text, row, column);
 }
 
-
 static void on_activate (PsppireDataEditor *de);
-static void on_deactivate (PsppireDataEditor *de);
 static gboolean on_switch_page (PsppireDataEditor *de, GtkNotebookPage *p, gint pagenum, gpointer data);
 static void on_select_range (PsppireDataEditor *de);
 
@@ -563,16 +831,99 @@ on_map (GtkWidget *w)
 }
 
 
+static void
+init_sheet (PsppireDataEditor *de, int i,
+           GtkAdjustment *hadj, GtkAdjustment *vadj)
+{
+  PsppireAxisHetero *haxis = psppire_axis_hetero_new ();
+  PsppireAxisUniform *vaxis = psppire_axis_uniform_new ();
+  de->sheet_bin[i] = gtk_scrolled_window_new (hadj, vadj);
+
+  de->data_sheet[i] = gtk_sheet_new (NULL);
+
+  g_object_set (de->sheet_bin[i],
+               "border-width", 3,
+               "shadow-type",  GTK_SHADOW_ETCHED_IN,
+               NULL);
+
+  g_object_set (haxis, "default-size", 75, NULL);
+  g_object_set (vaxis, "default-size", 25, NULL);
+
+  g_object_set (de->data_sheet[i],
+               "horizontal-axis", haxis,
+               "vertical-axis", vaxis,
+               NULL);
+
+  gtk_container_add (GTK_CONTAINER (de->sheet_bin[i]), de->data_sheet[i]);
+
+  g_signal_connect (de->data_sheet[i], "traverse",
+                   G_CALLBACK (traverse_cell_callback), de);
+
+  gtk_widget_show (de->sheet_bin[i]);
+}
+
+
+static void
+init_data_sheet (PsppireDataEditor *de)
+{
+  GtkAdjustment *va0, *ha0;
+  GtkAdjustment *va1, *ha1;
+  GtkWidget *sheet ;
+
+  de->split = TRUE;
+  de->paned = gtk_xpaned_new ();
+
+  init_sheet (de, 0, NULL, NULL);
+  gtk_widget_show (de->sheet_bin[0]);
+  va0 = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (de->sheet_bin[0]));
+  ha0 = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (de->sheet_bin[0]));
+
+  g_object_set (de->sheet_bin[0], "vscrollbar-policy", GTK_POLICY_NEVER, NULL);
+  g_object_set (de->sheet_bin[0], "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
+
+  init_sheet (de, 1, NULL, va0);
+  gtk_widget_show (de->sheet_bin[1]);
+  sheet = gtk_bin_get_child (GTK_BIN (de->sheet_bin[1]));
+  gtk_sheet_hide_row_titles (GTK_SHEET (sheet));
+  ha1 = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (de->sheet_bin[1]));
+  g_object_set (de->sheet_bin[1], "vscrollbar-policy", GTK_POLICY_ALWAYS, NULL);
+  g_object_set (de->sheet_bin[1], "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
+
+  init_sheet (de, 2, ha0, NULL);
+  gtk_widget_show (de->sheet_bin[2]);
+  sheet = gtk_bin_get_child (GTK_BIN (de->sheet_bin[2]));
+  gtk_sheet_hide_column_titles (GTK_SHEET (sheet));
+  g_object_set (de->sheet_bin[2], "vscrollbar-policy", GTK_POLICY_NEVER, NULL);
+  g_object_set (de->sheet_bin[2], "hscrollbar-policy", GTK_POLICY_ALWAYS, NULL);
+  va1 = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (de->sheet_bin[2]));
+
+  init_sheet (de, 3, ha1, va1);
+  gtk_widget_show (de->sheet_bin[3]);
+  sheet = gtk_bin_get_child (GTK_BIN (de->sheet_bin[3]));
+  gtk_sheet_hide_column_titles (GTK_SHEET (sheet));
+  gtk_sheet_hide_row_titles (GTK_SHEET (sheet));
+  g_object_set (de->sheet_bin[3], "vscrollbar-policy", GTK_POLICY_ALWAYS, NULL);
+  g_object_set (de->sheet_bin[3], "hscrollbar-policy", GTK_POLICY_ALWAYS, NULL);
+
+  gtk_xpaned_pack_top_left (GTK_XPANED (de->paned), de->sheet_bin[0], TRUE, TRUE);
+  gtk_xpaned_pack_top_right (GTK_XPANED (de->paned), de->sheet_bin[1], TRUE, TRUE);
+  gtk_xpaned_pack_bottom_left (GTK_XPANED (de->paned), de->sheet_bin[2], TRUE, TRUE);
+  gtk_xpaned_pack_bottom_right (GTK_XPANED (de->paned), de->sheet_bin[3], TRUE, TRUE);
+
+  gtk_xpaned_set_position_y (GTK_XPANED (de->paned), 150);
+  gtk_xpaned_set_position_x (GTK_XPANED (de->paned), 350);
+}
+
+
 static void
 psppire_data_editor_init (PsppireDataEditor *de)
 {
-  GtkWidget *vbox = gtk_vbox_new (FALSE, 0);
   GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
-  GtkWidget *sw_ds = gtk_scrolled_window_new (NULL, NULL);
   GtkWidget *sw_vs = gtk_scrolled_window_new (NULL, NULL);
 
+  init_data_sheet (de);
 
-  de->data_sheet = gtk_sheet_new (NULL, NULL, NULL);
+  de->data_vbox = gtk_vbox_new (FALSE, 0);
   de->var_sheet = psppire_var_sheet_new ();
 
   g_object_set (de, "tab-pos", GTK_POS_BOTTOM, NULL);
@@ -594,19 +945,21 @@ psppire_data_editor_init (PsppireDataEditor *de)
   gtk_widget_show_all (sw_vs);
 
 
-  gtk_container_add (GTK_CONTAINER (sw_ds), de->data_sheet);
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-  gtk_box_pack_start (GTK_BOX (vbox), sw_ds, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (de->data_vbox), hbox, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (de->data_vbox), de->paned, TRUE, TRUE, 0);
+
 
-  gtk_widget_show_all (vbox);
+  psppire_data_editor_remove_split (de);
 
-  gtk_notebook_append_page (GTK_NOTEBOOK (de), vbox,
+  gtk_widget_show_all (de->data_vbox);
+
+  gtk_notebook_append_page (GTK_NOTEBOOK (de), de->data_vbox,
                            gtk_label_new_with_mnemonic (_("Data View")));
 
   gtk_notebook_append_page (GTK_NOTEBOOK (de), sw_vs,
                            gtk_label_new_with_mnemonic (_("Variable View")));
 
-  g_signal_connect (de->data_sheet, "activate",
+  g_signal_connect (de->data_sheet[0], "activate",
                    G_CALLBACK (update_data_ref_entry),
                    de);
 
@@ -615,7 +968,7 @@ psppire_data_editor_init (PsppireDataEditor *de)
                    de);
 
 
-  g_signal_connect_swapped (de->data_sheet,
+  g_signal_connect_swapped (de->data_sheet[0],
                    "double-click-column",
                    G_CALLBACK (on_data_column_clicked),
                    de);
@@ -625,22 +978,18 @@ psppire_data_editor_init (PsppireDataEditor *de)
                    G_CALLBACK (on_var_row_clicked),
                    de);
 
-  g_signal_connect_swapped (de->data_sheet, "activate",
+  g_signal_connect_swapped (de->data_sheet[0], "activate",
                            G_CALLBACK (on_activate),
                            de);
 
-  g_signal_connect_swapped (de->data_sheet, "deactivate",
-                           G_CALLBACK (on_deactivate),
-                           de);
-
-  g_signal_connect_swapped (de->data_sheet, "select-range",
+  g_signal_connect_swapped (de->data_sheet[0], "select-range",
                            G_CALLBACK (on_select_range),
                            de);
 
-  g_signal_connect (de->data_sheet, "select-row",
+  g_signal_connect (de->data_sheet[0], "select-row",
                    G_CALLBACK (on_select_row), de);
 
-  g_signal_connect (de->data_sheet, "select-column",
+  g_signal_connect (de->data_sheet[0], "select-column",
                    G_CALLBACK (on_select_variable), de);
 
 
@@ -655,6 +1004,12 @@ psppire_data_editor_init (PsppireDataEditor *de)
 
   g_signal_connect (de, "map", G_CALLBACK (on_map), NULL);
 
+
+
+  //     gtk_sheet_hide_column_titles (de->var_sheet);
+  //  gtk_sheet_hide_row_titles (de->data_sheet);
+
+
   de->dispose_has_run = FALSE;
 }
 
@@ -663,14 +1018,71 @@ GtkWidget*
 psppire_data_editor_new (PsppireVarStore *var_store,
                         PsppireDataStore *data_store)
 {
-  GtkWidget *widget;
+  return  g_object_new (PSPPIRE_DATA_EDITOR_TYPE,
+                                    "var-store",  var_store,
+                                    "data-store",  data_store,
+                                    NULL);
+}
+
+
+static void
+psppire_data_editor_remove_split (PsppireDataEditor *de)
+{
+  if ( !de->split ) return;
+  de->split = FALSE;
+
+  g_object_ref (de->sheet_bin[0]);
+  gtk_container_remove (GTK_CONTAINER (de->paned), de->sheet_bin[0]);
+
+  g_object_ref (de->paned);
+  gtk_container_remove (GTK_CONTAINER (de->data_vbox), de->paned);
 
-  widget =  g_object_new (PSPPIRE_DATA_EDITOR_TYPE,
-                         "var-store",  var_store,
-                         "data-store",  data_store,
-                         NULL);
+  gtk_box_pack_start (GTK_BOX (de->data_vbox), de->sheet_bin[0],
+                     TRUE, TRUE, 0);
 
-  return widget;
+  g_object_unref (de->sheet_bin[0]);
+
+  g_object_set (de->sheet_bin[0], "vscrollbar-policy",
+               GTK_POLICY_ALWAYS, NULL);
+
+  g_object_set (de->sheet_bin[0], "hscrollbar-policy",
+               GTK_POLICY_ALWAYS, NULL);
+}
+
+
+static void
+psppire_data_editor_set_split (PsppireDataEditor *de)
+{
+  if ( de->split ) return;
+  de->split = TRUE;
+
+  g_object_ref (de->sheet_bin[0]);
+  gtk_container_remove (GTK_CONTAINER (de->data_vbox), de->sheet_bin[0]);
+
+  gtk_xpaned_pack_top_left (GTK_XPANED (de->paned), de->sheet_bin [0],
+                           TRUE, TRUE);
+
+  gtk_box_pack_start (GTK_BOX (de->data_vbox), de->paned,
+                     TRUE, TRUE, 0);
+
+  g_object_unref (de->paned);
+
+  g_object_set (de->sheet_bin[0], "vscrollbar-policy",
+               GTK_POLICY_NEVER, NULL);
+
+  g_object_set (de->sheet_bin[0], "hscrollbar-policy",
+               GTK_POLICY_NEVER, NULL);
+}
+
+void
+psppire_data_editor_split_window (PsppireDataEditor *de, gboolean split)
+{
+  if (split )
+    psppire_data_editor_set_split (de);
+  else
+    psppire_data_editor_remove_split (de);
+
+  gtk_widget_show_all (de->data_vbox);
 }
 
 static void data_sheet_set_clip (GtkSheet *sheet);
@@ -682,7 +1094,7 @@ static void data_sheet_contents_received_callback (GtkClipboard *clipboard,
 void
 psppire_data_editor_clip_copy (PsppireDataEditor *de)
 {
-  data_sheet_set_clip (GTK_SHEET (de->data_sheet));
+  data_sheet_set_clip (GTK_SHEET (de->data_sheet[0]));
 }
 
 void
@@ -708,16 +1120,16 @@ psppire_data_editor_clip_cut (PsppireDataEditor *de)
   GtkSheetRange range;
   PsppireDataStore *ds = de->data_store;
 
-  data_sheet_set_clip (GTK_SHEET (de->data_sheet));
+  data_sheet_set_clip (GTK_SHEET (de->data_sheet[0]));
 
   /* Now blank all the cells */
-  gtk_sheet_get_selected_range (GTK_SHEET (de->data_sheet), &range);
+  gtk_sheet_get_selected_range (GTK_SHEET (de->data_sheet[0]), &range);
 
    /* If nothing selected, then use active cell */
   if ( range.row0 < 0 || range.col0 < 0 )
     {
       gint row, col;
-      gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet), &row, &col);
+      gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet[0]), &row, &col);
 
       range.row0 = range.rowi = row;
       range.col0 = range.coli = col;
@@ -758,7 +1170,7 @@ psppire_data_editor_clip_cut (PsppireDataEditor *de)
     }
 
   /* and remove the selection */
-  gtk_sheet_unselect_range (GTK_SHEET (de->data_sheet));
+  gtk_sheet_unselect_range (GTK_SHEET (de->data_sheet[0]));
 }
 
 
@@ -767,7 +1179,7 @@ psppire_data_editor_clip_cut (PsppireDataEditor *de)
 /* Popup menu related stuff */
 
 static void
-popup_variable_menu (GtkSheet *sheet, gint column,
+popup_variable_column_menu (GtkSheet *sheet, gint column,
                     GdkEventButton *event, gpointer data)
 {
   GtkMenu *menu = GTK_MENU (data);
@@ -789,6 +1201,29 @@ popup_variable_menu (GtkSheet *sheet, gint column,
 }
 
 
+static void
+popup_variable_row_menu (GtkSheet *sheet, gint row,
+                    GdkEventButton *event, gpointer data)
+{
+  GtkMenu *menu = GTK_MENU (data);
+
+  PsppireVarStore *var_store =
+    PSPPIRE_VAR_STORE (gtk_sheet_get_model (sheet));
+
+  const struct variable *v =
+    psppire_dict_get_variable (var_store->dict, row);
+
+  if ( v && event->button == 3)
+    {
+      gtk_sheet_select_row (sheet, row);
+
+      gtk_menu_popup (menu,
+                     NULL, NULL, NULL, NULL,
+                     event->button, event->time);
+    }
+}
+
+
 static void
 popup_cases_menu (GtkSheet *sheet, gint row,
                  GdkEventButton *event, gpointer data)
@@ -840,7 +1275,7 @@ void
 psppire_data_editor_sort_ascending  (PsppireDataEditor *de)
 {
   GtkSheetRange range;
-  gtk_sheet_get_selected_range (GTK_SHEET(de->data_sheet), &range);
+  gtk_sheet_get_selected_range (GTK_SHEET(de->data_sheet[0]), &range);
 
   do_sort (de->data_store,  range.col0, FALSE);
 }
@@ -852,7 +1287,7 @@ void
 psppire_data_editor_sort_descending (PsppireDataEditor *de)
 {
   GtkSheetRange range;
-  gtk_sheet_get_selected_range (GTK_SHEET(de->data_sheet), &range);
+  gtk_sheet_get_selected_range (GTK_SHEET(de->data_sheet[0]), &range);
 
   do_sort (de->data_store,  range.col0, TRUE);
 }
@@ -865,14 +1300,26 @@ psppire_data_editor_sort_descending (PsppireDataEditor *de)
 void
 psppire_data_editor_insert_variable (PsppireDataEditor *de)
 {
-  glong posn = -1;
+  glong posn = 0;
 
-  if ( de->data_sheet->state == GTK_SHEET_COLUMN_SELECTED )
-    posn = GTK_SHEET (de->data_sheet)->range.col0;
-  else
-    posn = GTK_SHEET (de->data_sheet)->active_cell.col;
-
-  if ( posn == -1 ) posn = 0;
+  switch (gtk_notebook_get_current_page (GTK_NOTEBOOK (de)))
+    {
+    case PSPPIRE_DATA_EDITOR_DATA_VIEW:
+      if ( de->data_sheet[0]->state == GTK_SHEET_COLUMN_SELECTED )
+       posn = GTK_SHEET (de->data_sheet[0])->range.col0;
+      else
+       posn = GTK_SHEET (de->data_sheet[0])->active_cell.col;
+      break;
+    case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
+      if ( de->var_sheet->state == GTK_SHEET_ROW_SELECTED )
+       posn = GTK_SHEET (de->var_sheet)->range.row0;
+      else
+       posn = GTK_SHEET (de->var_sheet)->active_cell.row;
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    };
 
   psppire_dict_insert_variable (de->data_store->dict, posn, NULL);
 }
@@ -883,10 +1330,10 @@ psppire_data_editor_insert_case (PsppireDataEditor *de)
 {
   glong posn = -1;
 
-  if ( de->data_sheet->state == GTK_SHEET_ROW_SELECTED )
-    posn = GTK_SHEET (de->data_sheet)->range.row0;
+  if ( de->data_sheet[0]->state == GTK_SHEET_ROW_SELECTED )
+    posn = GTK_SHEET (de->data_sheet[0])->range.row0;
   else
-    posn = GTK_SHEET (de->data_sheet)->active_cell.row;
+    posn = GTK_SHEET (de->data_sheet[0])->active_cell.row;
 
   if ( posn == -1 ) posn = 0;
 
@@ -897,12 +1344,12 @@ psppire_data_editor_insert_case (PsppireDataEditor *de)
 void
 psppire_data_editor_delete_cases    (PsppireDataEditor *de)
 {
-  gint first = GTK_SHEET (de->data_sheet)->range.row0;
-  gint n = GTK_SHEET (de->data_sheet)->range.rowi - first + 1;
+  gint first = GTK_SHEET (de->data_sheet[0])->range.row0;
+  gint n = GTK_SHEET (de->data_sheet[0])->range.rowi - first + 1;
 
   psppire_data_store_delete_cases (de->data_store, first, n);
 
-  gtk_sheet_unselect_range (GTK_SHEET (de->data_sheet));
+  gtk_sheet_unselect_range (GTK_SHEET (de->data_sheet[0]));
 }
 
 /* Delete the variables currently selected in the
@@ -915,8 +1362,8 @@ psppire_data_editor_delete_variables (PsppireDataEditor *de)
   switch (gtk_notebook_get_current_page (GTK_NOTEBOOK (de)))
     {
     case PSPPIRE_DATA_EDITOR_DATA_VIEW:
-      first = GTK_SHEET (de->data_sheet)->range.col0;
-      n = GTK_SHEET (de->data_sheet)->range.coli - first + 1;
+      first = GTK_SHEET (de->data_sheet[0])->range.col0;
+      n = GTK_SHEET (de->data_sheet[0])->range.coli - first + 1;
       break;
     case PSPPIRE_DATA_EDITOR_VARIABLE_VIEW:
       first = GTK_SHEET (de->var_sheet)->range.row0;
@@ -929,7 +1376,7 @@ psppire_data_editor_delete_variables (PsppireDataEditor *de)
 
   psppire_dict_delete_variables (de->var_store->dict, first, n);
 
-  gtk_sheet_unselect_range (GTK_SHEET (de->data_sheet));
+  gtk_sheet_unselect_range (GTK_SHEET (de->data_sheet[0]));
   gtk_sheet_unselect_range (GTK_SHEET (de->var_sheet));
 }
 
@@ -938,14 +1385,30 @@ void
 psppire_data_editor_show_grid (PsppireDataEditor *de, gboolean grid_visible)
 {
   gtk_sheet_show_grid (GTK_SHEET (de->var_sheet), grid_visible);
-  gtk_sheet_show_grid (GTK_SHEET (de->data_sheet), grid_visible);
+  gtk_sheet_show_grid (GTK_SHEET (de->data_sheet[0]), grid_visible);
+}
+
+
+static void
+set_font (GtkWidget *w, gpointer data)
+{
+  PangoFontDescription *font_desc = data;
+  GtkRcStyle *style = gtk_widget_get_modifier_style (w);
+
+  pango_font_description_free (style->font_desc);
+  style->font_desc = pango_font_description_copy (font_desc);
+
+  gtk_widget_modify_style (w, style);
+
+  if ( GTK_IS_CONTAINER (w))
+    gtk_container_foreach (GTK_CONTAINER (w), set_font, font_desc);
 }
 
 void
 psppire_data_editor_set_font (PsppireDataEditor *de, PangoFontDescription *font_desc)
 {
-  psppire_data_store_set_font (de->data_store, font_desc);
-  psppire_var_store_set_font (de->var_store, font_desc);
+  set_font (GTK_WIDGET (de), font_desc);
+  gtk_container_foreach (GTK_CONTAINER (de), set_font, font_desc);
 }
 
 
@@ -960,11 +1423,13 @@ emit_selected_signal (PsppireDataEditor *de)
   g_signal_emit (de, data_editor_signals[DATA_SELECTION_CHANGED], 0, data_selected);
 }
 
+
 static void
 on_activate (PsppireDataEditor *de)
 {
   gint row, col;
-  gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet), &row, &col);
+  gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet[0]), &row, &col);
+
 
   if ( row < psppire_data_store_get_case_count (de->data_store)
        &&
@@ -978,18 +1443,12 @@ on_activate (PsppireDataEditor *de)
 }
 
 
-static void
-on_deactivate (PsppireDataEditor *de)
-{
-  emit_selected_signal (de);
-}
-
 static void
 on_select_range (PsppireDataEditor *de)
 {
   GtkSheetRange range;
 
-  gtk_sheet_get_selected_range (GTK_SHEET (de->data_sheet), &range);
+  gtk_sheet_get_selected_range (GTK_SHEET (de->data_sheet[0]), &range);
 
   if ( range.rowi < psppire_data_store_get_case_count (de->data_store)
        &&
@@ -1004,7 +1463,8 @@ on_select_range (PsppireDataEditor *de)
 
 
 static gboolean
-on_switch_page (PsppireDataEditor *de, GtkNotebookPage *p, gint pagenum, gpointer data)
+on_switch_page (PsppireDataEditor *de, GtkNotebookPage *p,
+               gint pagenum, gpointer data)
 {
   if ( pagenum != PSPPIRE_DATA_EDITOR_DATA_VIEW )
     {
@@ -1028,7 +1488,7 @@ data_is_selected (PsppireDataEditor *de)
   if ( gtk_notebook_get_current_page (GTK_NOTEBOOK (de)) != PSPPIRE_DATA_EDITOR_DATA_VIEW)
     return FALSE;
 
-  gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet), &row, &col);
+  gtk_sheet_get_active_cell (GTK_SHEET (de->data_sheet[0]), &row, &col);
 
   if ( row >= psppire_data_store_get_case_count (de->data_store)
        ||
@@ -1037,7 +1497,7 @@ data_is_selected (PsppireDataEditor *de)
       return FALSE;
     }
 
-  gtk_sheet_get_selected_range (GTK_SHEET (de->data_sheet), &range);
+  gtk_sheet_get_selected_range (GTK_SHEET (de->data_sheet[0]), &range);
 
   if ( range.rowi >= psppire_data_store_get_case_count (de->data_store)
        ||
@@ -1160,7 +1620,7 @@ data_sheet_set_clip (GtkSheet *sheet)
     {
       struct ccase old;
 
-      if (psppire_case_file_get_case (ds->case_file, i, &old))
+      if (psppire_data_store_get_case (ds, i, &old))
         {
           struct ccase new;
 
@@ -1377,7 +1837,7 @@ data_sheet_contents_received_callback (GtkClipboard *clipboard,
   c = (char *) sd->data;
 
   /* Paste text to selected position */
-  gtk_sheet_get_active_cell (GTK_SHEET (data_editor->data_sheet),
+  gtk_sheet_get_active_cell (GTK_SHEET (data_editor->data_sheet[0]),
                             &row, &column);
 
   g_return_if_fail (row >= 0);
@@ -1440,3 +1900,5 @@ on_owner_change (GtkClipboard *clip, GdkEventOwnerChange *event, gpointer data)
   g_signal_emit (de, data_editor_signals[DATA_AVAILABLE_CHANGED], 0,
                 compatible_target);
 }
+
+
index b896c54578aa97c9685ae7fd126804419097d66f..7716f52c0e7876b5d48cb432450532dee00232bf 100644 (file)
@@ -46,10 +46,17 @@ struct _PsppireDataEditor
   gboolean dispose_has_run;
   GtkWidget *cell_ref_entry;
   GtkWidget *datum_entry;
-  GtkWidget *data_sheet;
   GtkWidget *var_sheet;
   PsppireDataStore *data_store;
   PsppireVarStore *var_store;
+
+  GtkWidget *sheet_bin[4];
+  GtkWidget *data_sheet[4];
+
+  GtkWidget *data_vbox;
+
+  GtkWidget *paned;
+  gboolean split;
 };
 
 
@@ -73,7 +80,7 @@ void           psppire_data_editor_insert_case     (PsppireDataEditor *);
 void           psppire_data_editor_delete_cases    (PsppireDataEditor *);
 void           psppire_data_editor_set_font        (PsppireDataEditor *, PangoFontDescription *);
 void           psppire_data_editor_delete_cases    (PsppireDataEditor *);
-
+void           psppire_data_editor_split_window    (PsppireDataEditor *, gboolean );
 
 
 G_END_DECLS
index afbe3d2fe31f82fb83b4149a2a9656b902d9bc7a..2059d75ad716e42439a616f671f9b3701d155960 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPPIRE - a graphical user interface for PSPP.
-   Copyright (C) 2006  Free Software Foundation
+   Copyright (C) 2006, 2008  Free Software Foundation
 
    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
 #include <data/variable.h>
 
 #include <gtksheet/gsheetmodel.h>
-#include <gtksheet/gsheet-column-iface.h>
-#include <gtksheet/gsheet-row-iface.h>
+#include <gtksheet/psppire-marshal.h>
 
 #include <pango/pango-context.h>
 
 #include "psppire-data-store.h"
-#include "psppire-case-file.h"
 #include "helper.h"
 
 #include <data/dictionary.h>
 #include <data/data-in.h>
 #include <data/format.h>
 
+#include <math/sort.h>
+
+#include "xalloc.h"
+#include "xmalloca.h"
+
+
 
 static void psppire_data_store_init            (PsppireDataStore      *data_store);
 static void psppire_data_store_class_init      (PsppireDataStoreClass *class);
 static void psppire_data_store_sheet_model_init (GSheetModelIface *iface);
-static void psppire_data_store_sheet_column_init (GSheetColumnIface *iface);
-static void psppire_data_store_sheet_row_init (GSheetRowIface *iface);
 
 static void psppire_data_store_finalize        (GObject           *object);
 static void psppire_data_store_dispose        (GObject           *object);
@@ -55,15 +57,29 @@ static gboolean psppire_data_store_clear_datum (GSheetModel *model,
                                          glong row, glong column);
 
 
-#define MIN_COLUMNS 10
+static gboolean psppire_data_store_insert_case (PsppireDataStore *ds,
+                                               struct ccase *cc,
+                                               casenumber posn);
+
+
+static gboolean psppire_data_store_data_in (PsppireDataStore *ds,
+                                           casenumber casenum, gint idx,
+                                           struct substring input,
+                                           const struct fmt_spec *fmt);
+
 
-#define TRAILING_ROWS 10
 
 static GObjectClass *parent_class = NULL;
 
 
-enum  {FONT_CHANGED,
-       n_SIGNALS};
+enum
+  {
+    BACKEND_CHANGED,
+    CASES_DELETED,
+    CASE_INSERTED,
+    CASE_CHANGED,
+    n_SIGNALS
+  };
 
 static guint signals [n_SIGNALS];
 
@@ -95,35 +111,15 @@ psppire_data_store_get_type (void)
        NULL
       };
 
-      static const GInterfaceInfo sheet_column_info =
-      {
-       (GInterfaceInitFunc) psppire_data_store_sheet_column_init,
-       NULL,
-       NULL
-      };
-
-      static const GInterfaceInfo sheet_row_info =
-      {
-       (GInterfaceInitFunc) psppire_data_store_sheet_row_init,
-       NULL,
-       NULL
-      };
-
 
-      data_store_type = g_type_register_static (G_TYPE_OBJECT, "PsppireDataStore",
+      data_store_type = g_type_register_static (G_TYPE_OBJECT,
+                                               "PsppireDataStore",
                                                &data_store_info, 0);
 
       g_type_add_interface_static (data_store_type,
                                   G_TYPE_SHEET_MODEL,
                                   &sheet_model_info);
 
-      g_type_add_interface_static (data_store_type,
-                                  G_TYPE_SHEET_COLUMN,
-                                  &sheet_column_info);
-
-      g_type_add_interface_static (data_store_type,
-                                  G_TYPE_SHEET_ROW,
-                                  &sheet_row_info);
     }
 
   return data_store_type;
@@ -141,8 +137,8 @@ psppire_data_store_class_init (PsppireDataStoreClass *class)
   object_class->finalize = psppire_data_store_finalize;
   object_class->dispose = psppire_data_store_dispose;
 
-  signals [FONT_CHANGED] =
-    g_signal_new ("font_changed",
+  signals [BACKEND_CHANGED] =
+    g_signal_new ("backend-changed",
                  G_TYPE_FROM_CLASS (class),
                  G_SIGNAL_RUN_FIRST,
                  0,
@@ -150,10 +146,62 @@ psppire_data_store_class_init (PsppireDataStoreClass *class)
                  g_cclosure_marshal_VOID__VOID,
                  G_TYPE_NONE,
                  0);
+
+  signals [CASE_INSERTED] =
+    g_signal_new ("case-inserted",
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_FIRST,
+                 0,
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__INT,
+                 G_TYPE_NONE,
+                 1,
+                 G_TYPE_INT);
+
+
+  signals [CASE_CHANGED] =
+    g_signal_new ("case-changed",
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_FIRST,
+                 0,
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__INT,
+                 G_TYPE_NONE,
+                 1,
+                 G_TYPE_INT);
+
+  signals [CASES_DELETED] =
+    g_signal_new ("cases-deleted",
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_FIRST,
+                 0,
+                 NULL, NULL,
+                 psppire_marshal_VOID__INT_INT,
+                 G_TYPE_NONE,
+                 2,
+                 G_TYPE_INT,
+                 G_TYPE_INT);
 }
 
 
 
+static gboolean
+psppire_data_store_insert_values (PsppireDataStore *ds,
+                                 gint n_values, gint where);
+
+static union value *
+psppire_data_store_get_value (const PsppireDataStore *ds,
+                             casenumber casenum, size_t idx,
+                             union value *value, int width);
+
+
+static gboolean
+psppire_data_store_set_value (PsppireDataStore *ds, casenumber casenum,
+                             gint idx, union value *v, gint width);
+
+
+
+
 static glong
 psppire_data_store_get_var_count (const GSheetModel *model)
 {
@@ -165,7 +213,7 @@ psppire_data_store_get_var_count (const GSheetModel *model)
 casenumber
 psppire_data_store_get_case_count (const PsppireDataStore *store)
 {
-  return psppire_case_file_get_case_count (store->case_file);
+  return datasheet_get_row_cnt (store->datasheet);
 }
 
 size_t
@@ -174,7 +222,7 @@ psppire_data_store_get_value_count (const PsppireDataStore *store)
   return psppire_dict_get_value_cnt (store->dict);
 }
 
-casenumber
+static casenumber
 psppire_data_store_get_case_count_wrapper (const GSheetModel *model)
 {
   const PsppireDataStore *store = PSPPIRE_DATA_STORE (model);
@@ -185,20 +233,10 @@ static void
 psppire_data_store_init (PsppireDataStore *data_store)
 {
   data_store->dict = 0;
-  data_store->case_file = NULL;
-  data_store->width_of_m = 10;
+  data_store->datasheet = NULL;
   data_store->dispose_has_run = FALSE;
 }
 
-const PangoFontDescription *
-psppire_data_store_get_font_desc (const GSheetModel *model,
-                             glong row, glong column)
-{
-  PsppireDataStore *store = PSPPIRE_DATA_STORE (model);
-
-  return store->font_desc;
-}
-
 static inline gchar *
 psppire_data_store_get_string_wrapper (const GSheetModel *model, glong row,
                                       glong column)
@@ -218,6 +256,14 @@ psppire_data_store_set_string_wrapper (GSheetModel *model,
 
 
 
+static gchar * get_column_subtitle (const GSheetModel *model, gint col);
+static gchar * get_column_button_label (const GSheetModel *model, gint col);
+static gboolean get_column_sensitivity (const GSheetModel *model, gint col);
+static GtkJustification get_column_justification (const GSheetModel *model, gint col);
+
+static gchar * get_row_button_label (const GSheetModel *model, gint row);
+static gboolean get_row_sensitivity (const GSheetModel *model, gint row);
+
 
 static void
 psppire_data_store_sheet_model_init (GSheetModelIface *iface)
@@ -227,67 +273,18 @@ psppire_data_store_sheet_model_init (GSheetModelIface *iface)
   iface->set_string = psppire_data_store_set_string_wrapper;
   iface->clear_datum = psppire_data_store_clear_datum;
   iface->is_editable = NULL;
-  iface->is_visible = NULL;
   iface->get_foreground = NULL;
   iface->get_background = NULL;
-  iface->get_font_desc = psppire_data_store_get_font_desc;
-  iface->get_cell_border = NULL;
   iface->get_column_count = psppire_data_store_get_var_count;
   iface->get_row_count = psppire_data_store_get_case_count_wrapper;
-}
 
-static
-gboolean always_true ()
-{
-  return TRUE;
-}
+  iface->get_column_subtitle = get_column_subtitle;
+  iface->get_column_title = get_column_button_label;
+  iface->get_column_sensitivity = get_column_sensitivity;
+  iface->get_column_justification = get_column_justification;
 
-
-static void
-delete_cases_callback (GtkWidget *w,
-        casenumber first, casenumber n_cases, gpointer data)
-{
-  PsppireDataStore *store  ;
-
-  g_return_if_fail (data);
-
-  store  = PSPPIRE_DATA_STORE (data);
-
-  g_assert (first >= 0);
-
-  g_sheet_model_rows_deleted (G_SHEET_MODEL (store), first, n_cases);
-}
-
-
-static void
-insert_case_callback (GtkWidget *w, casenumber casenum, gpointer data)
-{
-  PsppireDataStore *store  ;
-
-  g_return_if_fail (data);
-
-  store  = PSPPIRE_DATA_STORE (data);
-
-  g_sheet_model_range_changed (G_SHEET_MODEL (store),
-                              casenum, -1,
-                              psppire_case_file_get_case_count (store->case_file),
-                              -1);
-
-  g_sheet_model_rows_inserted (G_SHEET_MODEL (store), casenum, 1);
-}
-
-
-static void
-changed_case_callback (GtkWidget *w, gint casenum, gpointer data)
-{
-  PsppireDataStore *store  ;
-  g_return_if_fail (data);
-
-  store  = PSPPIRE_DATA_STORE (data);
-
-  g_sheet_model_range_changed (G_SHEET_MODEL (store),
-                                casenum, -1,
-                                casenum, -1);
+  iface->get_row_title = get_row_button_label;
+  iface->get_row_sensitivity = get_row_sensitivity;
 }
 
 
@@ -301,18 +298,24 @@ delete_variable_callback (GObject *obj, gint dict_index,
 {
   PsppireDataStore *store  = PSPPIRE_DATA_STORE (data);
 
+
   g_sheet_model_columns_deleted (G_SHEET_MODEL (store), dict_index, 1);
+#if AXIS_TRANSITION
+
 
   g_sheet_column_columns_changed (G_SHEET_COLUMN (store),
                                   dict_index, -1);
+#endif
 }
 
 
+
 static void
 variable_changed_callback (GObject *obj, gint var_num, gpointer data)
 {
   PsppireDataStore *store  = PSPPIRE_DATA_STORE (data);
 
+#if AXIS_TRANSITION
   g_sheet_column_columns_changed (G_SHEET_COLUMN (store),
                                  var_num, 1);
 
@@ -320,6 +323,7 @@ variable_changed_callback (GObject *obj, gint var_num, gpointer data)
   g_sheet_model_range_changed (G_SHEET_MODEL (store),
                               -1, var_num,
                               -1, var_num);
+#endif
 }
 
 static void
@@ -346,10 +350,13 @@ insert_variable_callback (GObject *obj, gint var_num, gpointer data)
       posn = 0;
     }
 
-  psppire_case_file_insert_values (store->case_file, 1, posn);
+  psppire_data_store_insert_values (store, 1, posn);
+
+#if AXIS_TRANSITION
 
   g_sheet_column_columns_changed (G_SHEET_COLUMN (store),
                                  var_num, 1);
+#endif
 
   g_sheet_model_columns_inserted (G_SHEET_MODEL (store), var_num, 1);
 }
@@ -366,7 +373,7 @@ dict_size_change_callback (GObject *obj,
   const gint new_val_width = value_cnt_from_width (var_get_width (v));
 
   if ( adjustment > 0 )
-    psppire_case_file_insert_values (store->case_file, adjustment,
+    psppire_data_store_insert_values (store, adjustment,
                                     new_val_width - adjustment +
                                     var_get_case_index(v));
 }
@@ -392,28 +399,20 @@ psppire_data_store_new (PsppireDict *dict)
   return retval;
 }
 
-
 void
-psppire_data_store_set_case_file (PsppireDataStore *ds,
-                                 PsppireCaseFile *cf)
+psppire_data_store_set_reader (PsppireDataStore *ds,
+                              struct casereader *reader)
 {
   gint i;
-  if ( ds->case_file)  g_object_unref (ds->case_file);
 
+  if ( ds->datasheet)
+    datasheet_destroy (ds->datasheet);
 
-  ds->case_file = cf;
+  ds->datasheet = datasheet_create (reader);
 
   g_sheet_model_range_changed (G_SHEET_MODEL (ds),
                               -1, -1, -1, -1);
 
-  for (i = 0 ; i < n_cf_signals ; ++i )
-    {
-      if ( ds->cf_handler_id [i] > 0 )
-       g_signal_handler_disconnect (ds->case_file,
-                                    ds->cf_handler_id[i]);
-    }
-
-
   if ( ds->dict )
     for (i = 0 ; i < n_dict_signals; ++i )
       {
@@ -424,20 +423,7 @@ psppire_data_store_set_case_file (PsppireDataStore *ds,
          }
       }
 
-  ds->cf_handler_id [CASES_DELETED] =
-    g_signal_connect (ds->case_file, "cases-deleted",
-                     G_CALLBACK (delete_cases_callback),
-                     ds);
-
-  ds->cf_handler_id [CASE_INSERTED] =
-    g_signal_connect (ds->case_file, "case-inserted",
-                     G_CALLBACK (insert_case_callback),
-                     ds);
-
-  ds->cf_handler_id [CASE_CHANGED] =
-    g_signal_connect (ds->case_file, "case-changed",
-                     G_CALLBACK (changed_case_callback),
-                     ds);
+  g_signal_emit (ds, signals[BACKEND_CHANGED], 0);
 }
 
 
@@ -493,8 +479,9 @@ psppire_data_store_set_dictionary (PsppireDataStore *data_store, PsppireDict *di
   /* The entire model has changed */
   g_sheet_model_range_changed (G_SHEET_MODEL (data_store), -1, -1, -1, -1);
 
+#if AXIS_TRANSITION
   g_sheet_column_columns_changed (G_SHEET_COLUMN (data_store), 0, -1);
-
+#endif
 
   if ( data_store->dict )
     for (i = 0 ; i < n_dict_signals; ++i )
@@ -524,7 +511,11 @@ psppire_data_store_dispose (GObject *object)
   if (ds->dispose_has_run)
     return;
 
-  if (ds->case_file) g_object_unref (ds->case_file);
+  if (ds->datasheet)
+    {
+      datasheet_destroy (ds->datasheet);
+      ds->datasheet = NULL;
+    }
 
   /* must chain up */
   (* parent_class->dispose) (object);
@@ -533,16 +524,6 @@ psppire_data_store_dispose (GObject *object)
 }
 
 
-gboolean
-psppire_data_store_delete_cases (PsppireDataStore *ds,
-                                casenumber first, casenumber count)
-{
-  g_return_val_if_fail (ds, FALSE);
-
-  return psppire_case_file_delete_cases (ds->case_file, count, first);
-}
-
-
 
 /* Insert a blank case before POSN */
 gboolean
@@ -553,7 +534,7 @@ psppire_data_store_insert_new_case (PsppireDataStore *ds, casenumber posn)
   struct ccase cc;
   g_return_val_if_fail (ds, FALSE);
 
-  val_cnt = datasheet_get_column_cnt (ds->case_file->datasheet) ;
+  val_cnt = datasheet_get_column_cnt (ds->datasheet) ;
 
   g_return_val_if_fail (val_cnt > 0, FALSE);
 
@@ -572,7 +553,7 @@ psppire_data_store_insert_new_case (PsppireDataStore *ds, casenumber posn)
       case_data_rw (&cc, pv)->f = SYSMIS;
     }
 
-  result = psppire_case_file_insert_case (ds->case_file, &cc, posn);
+  result = psppire_data_store_insert_case (ds, &cc, posn);
 
   case_destroy (&cc);
 
@@ -591,12 +572,12 @@ psppire_data_store_get_string (PsppireDataStore *store, glong row, glong column)
   GString *s;
 
   g_return_val_if_fail (store->dict, NULL);
-  g_return_val_if_fail (store->case_file, NULL);
+  g_return_val_if_fail (store->datasheet, NULL);
 
   if (column >= psppire_dict_get_var_cnt (store->dict))
     return NULL;
 
-  if ( row >= psppire_case_file_get_case_count (store->case_file))
+  if ( row >= psppire_data_store_get_case_count (store))
     return NULL;
 
   pv = psppire_dict_get_variable (store->dict, column);
@@ -607,7 +588,7 @@ psppire_data_store_get_string (PsppireDataStore *store, glong row, glong column)
 
   g_assert (idx >= 0);
 
-  v = psppire_case_file_get_value (store->case_file, row, idx, NULL,
+  v = psppire_data_store_get_value (store, row, idx, NULL,
                                    var_get_width (pv));
 
   g_return_val_if_fail (v, NULL);
@@ -662,8 +643,10 @@ psppire_data_store_clear_datum (GSheetModel *model,
   else
     memcpy (v.s, "", MAX_SHORT_STRING);
 
-  psppire_case_file_set_value (store->case_file, row, index, &v,
-                             var_get_width (pv));
+  psppire_data_store_set_value (store, row, index, &v,
+                               var_get_width (pv));
+
+  g_sheet_model_range_changed (model, row, col, row, col);
 
   return TRUE;
 }
@@ -689,32 +672,16 @@ psppire_data_store_set_string (PsppireDataStore *store,
   if (row == n_cases)
     psppire_data_store_insert_new_case (store, row);
 
-  psppire_case_file_data_in (store->case_file, row,
-                             var_get_case_index (pv), ss_cstr (text),
-                             var_get_write_format (pv));
+  psppire_data_store_data_in (store, row,
+                             var_get_case_index (pv), ss_cstr (text),
+                             var_get_write_format (pv));
+
+  g_sheet_model_range_changed (G_SHEET_MODEL (store), row, col, row, col);
 
   return TRUE;
 }
 
 
-void
-psppire_data_store_set_font (PsppireDataStore *store,
-                           const PangoFontDescription *fd)
-{
-  g_return_if_fail (store);
-  g_return_if_fail (PSPPIRE_IS_DATA_STORE (store));
-
-  store->font_desc = fd;
-#if 0
-  store->width_of_m = calc_m_width (fd);
-#endif
-  g_signal_emit (store, signals [FONT_CHANGED], 0);
-
-
-  g_sheet_model_range_changed (G_SHEET_MODEL (store),
-                                -1, -1, -1, -1);
-}
-
 
 void
 psppire_data_store_show_labels (PsppireDataStore *store, gboolean show_labels)
@@ -730,11 +697,14 @@ psppire_data_store_show_labels (PsppireDataStore *store, gboolean show_labels)
 
 
 void
-psppire_data_store_clear (PsppireDataStore *data_store)
+psppire_data_store_clear (PsppireDataStore *ds)
 {
-  psppire_case_file_clear (data_store->case_file);
+  datasheet_destroy (ds->datasheet);
+  ds->datasheet = NULL;
 
-  psppire_dict_clear (data_store->dict);
+  psppire_dict_clear (ds->dict);
+
+  g_signal_emit (ds, signals [CASES_DELETED], 0, 0, -1);
 }
 
 
@@ -746,12 +716,6 @@ psppire_data_store_get_reader (PsppireDataStore *ds)
   int i;
   struct casereader *reader ;
 
-  for (i = 0 ; i < n_cf_signals ; ++i )
-    {
-      g_signal_handler_disconnect (ds->case_file, ds->cf_handler_id[i]);
-      ds->cf_handler_id[i] = 0 ;
-    }
-
   if ( ds->dict )
     for (i = 0 ; i < n_dict_signals; ++i )
       {
@@ -759,7 +723,10 @@ psppire_data_store_get_reader (PsppireDataStore *ds)
                                ds->dict_handler_id[i]);
       }
 
-  reader = psppire_case_file_make_reader (ds->case_file);
+  reader = datasheet_make_reader (ds->datasheet);
+
+  /* We must not reference this again */
+  ds->datasheet = NULL;
 
   return reader;
 }
@@ -768,203 +735,276 @@ psppire_data_store_get_reader (PsppireDataStore *ds)
 
 /* Column related funcs */
 
-static glong
-geometry_get_column_count (const GSheetColumn *geom)
-{
-  PsppireDataStore *ds = PSPPIRE_DATA_STORE (geom);
 
-  return MAX (MIN_COLUMNS, psppire_dict_get_var_cnt (ds->dict));
-}
+static const gchar null_var_name[]=N_("var");
 
+\f
 
+/* Row related funcs */
 
-static gint
-geometry_get_width (const GSheetColumn *geom, glong unit)
+static gchar *
+get_row_button_label (const GSheetModel *model, gint unit)
 {
-  const struct variable *pv ;
-  PsppireDataStore *ds = PSPPIRE_DATA_STORE (geom);
+  gchar *s = g_strdup_printf (_("%d"), unit + FIRST_CASE_NUMBER);
 
-  if ( unit >= psppire_dict_get_var_cnt (ds->dict) )
-    return ds->width_of_m * 8 ;
+  gchar *text =  pspp_locale_to_utf8 (s, -1, 0);
 
-  pv = psppire_dict_get_variable (ds->dict, unit);
-
-  if ( pv == NULL )
-    return ds->width_of_m * 8 ;
+  g_free (s);
 
-  return ds->width_of_m * var_get_display_width (pv);
+  return text;
 }
 
-static void
-geometry_set_width (GSheetColumn *geom, glong unit, gint width)
-{
-  PsppireDataStore *ds = PSPPIRE_DATA_STORE (geom);
 
-  struct variable *pv = psppire_dict_get_variable (ds->dict, unit);
+static gboolean
+get_row_sensitivity (const GSheetModel *model, gint unit)
+{
+  PsppireDataStore *ds = PSPPIRE_DATA_STORE (model);
 
-  var_set_display_width (pv, width / ds->width_of_m );
+  return (unit < psppire_data_store_get_case_count (ds));
 }
 
 
+\f
 
-static GtkJustification
-geometry_get_justification (const GSheetColumn *geom, glong unit)
-{
-  PsppireDataStore *ds = PSPPIRE_DATA_STORE (geom);
-  const struct variable *pv ;
+/* Column related stuff */
 
+static gchar *
+get_column_subtitle (const GSheetModel *model, gint col)
+{
+  gchar *text;
+  const struct variable *v ;
+  PsppireDataStore *ds = PSPPIRE_DATA_STORE (model);
 
-  if ( unit >= psppire_dict_get_var_cnt (ds->dict) )
-    return GTK_JUSTIFY_LEFT;
+  if ( col >= psppire_dict_get_var_cnt (ds->dict) )
+    return NULL;
 
-  pv = psppire_dict_get_variable (ds->dict, unit);
+  v = psppire_dict_get_variable (ds->dict, col);
 
-  return (var_get_alignment (pv) == ALIGN_LEFT ? GTK_JUSTIFY_LEFT
-          : var_get_alignment (pv) == ALIGN_RIGHT ? GTK_JUSTIFY_RIGHT
-          : GTK_JUSTIFY_CENTER);
-}
+  if ( ! var_has_label (v))
+    return NULL;
 
+  text =  pspp_locale_to_utf8 (var_get_label (v), -1, 0);
 
-static const gchar null_var_name[]=N_("var");
+  return text;
+}
 
 static gchar *
-geometry_get_column_button_label (const GSheetColumn *geom, glong unit)
+get_column_button_label (const GSheetModel *model, gint col)
 {
   gchar *text;
   struct variable *pv ;
-  PsppireDataStore *ds = PSPPIRE_DATA_STORE (geom);
+  PsppireDataStore *ds = PSPPIRE_DATA_STORE (model);
 
-  if ( unit >= psppire_dict_get_var_cnt (ds->dict) )
+  if ( col >= psppire_dict_get_var_cnt (ds->dict) )
     return g_locale_to_utf8 (null_var_name, -1, 0, 0, 0);
 
-  pv = psppire_dict_get_variable (ds->dict, unit);
+  pv = psppire_dict_get_variable (ds->dict, col);
 
   text =  pspp_locale_to_utf8 (var_get_name (pv), -1, 0);
 
   return text;
 }
 
-
-static gchar *
-geometry_get_column_subtitle (const GSheetColumn *geom, glong unit)
+static gboolean
+get_column_sensitivity (const GSheetModel *model, gint col)
 {
-  gchar *text;
-  const struct variable *v ;
-  PsppireDataStore *ds = PSPPIRE_DATA_STORE (geom);
+  PsppireDataStore *ds = PSPPIRE_DATA_STORE (model);
 
-  if ( unit >= psppire_dict_get_var_cnt (ds->dict) )
-    return NULL;
+  return (col < psppire_dict_get_var_cnt (ds->dict));
+}
 
-  v = psppire_dict_get_variable (ds->dict, unit);
 
-  if ( ! var_has_label (v))
-    return NULL;
 
-  text =  pspp_locale_to_utf8 (var_get_label (v), -1, 0);
+static GtkJustification
+get_column_justification (const GSheetModel *model, gint col)
+{
+  PsppireDataStore *ds = PSPPIRE_DATA_STORE (model);
+  const struct variable *pv ;
 
-  return text;
+  if ( col >= psppire_dict_get_var_cnt (ds->dict) )
+    return GTK_JUSTIFY_LEFT;
+
+  pv = psppire_dict_get_variable (ds->dict, col);
+
+  return (var_get_alignment (pv) == ALIGN_LEFT ? GTK_JUSTIFY_LEFT
+          : var_get_alignment (pv) == ALIGN_RIGHT ? GTK_JUSTIFY_RIGHT
+          : GTK_JUSTIFY_CENTER);
 }
 
 
-static gboolean
-geometry_get_sensitivity (const GSheetColumn *geom, glong unit)
+
+\f
+
+
+/* Fills C with the CASENUMth case.
+   Returns true on success, false otherwise.
+ */
+gboolean
+psppire_data_store_get_case (const PsppireDataStore *ds,
+                            casenumber casenum,
+                            struct ccase *c)
 {
-  PsppireDataStore *ds = PSPPIRE_DATA_STORE (geom);
+  g_return_val_if_fail (ds, FALSE);
+  g_return_val_if_fail (ds->datasheet, FALSE);
 
-  return (unit < psppire_dict_get_var_cnt (ds->dict));
+  return datasheet_get_row (ds->datasheet, casenum, c);
 }
 
 
-static void
-psppire_data_store_sheet_column_init (GSheetColumnIface *iface)
+gboolean
+psppire_data_store_delete_cases (PsppireDataStore *ds, casenumber first,
+                                casenumber n_cases)
 {
-  iface->get_column_count = geometry_get_column_count;
-  iface->get_width = geometry_get_width;
-  iface->set_width = geometry_set_width;
-  iface->get_visibility = always_true;
-  iface->get_sensitivity = geometry_get_sensitivity;
-  iface->get_justification = geometry_get_justification;
-  iface->get_button_label = geometry_get_column_button_label;
-  iface->get_subtitle = geometry_get_column_subtitle;
-}
+  g_return_val_if_fail (ds, FALSE);
+  g_return_val_if_fail (ds->datasheet, FALSE);
 
+  g_return_val_if_fail (first + n_cases <=
+                       psppire_data_store_get_case_count (ds), FALSE);
 
-/* Row related funcs */
 
-static glong
-geometry_get_row_count (const GSheetRow *geom)
-{
-  PsppireDataStore *ds = PSPPIRE_DATA_STORE (geom);
+  datasheet_delete_rows (ds->datasheet, first, n_cases);
 
-  return TRAILING_ROWS + psppire_case_file_get_case_count (ds->case_file);
+  g_signal_emit (ds, signals [CASES_DELETED], 0, first, n_cases);
+  g_sheet_model_rows_deleted (G_SHEET_MODEL (ds), first, n_cases);
+
+  return TRUE;
 }
 
-#define ROW_HEIGHT 25
 
-static gint
-geometry_get_height (const GSheetRow *geom, glong unit)
-{
-  return ROW_HEIGHT;
-}
 
-static guint
-geometry_get_top_ypixel (const GSheetRow *geo, glong row)
+/* Insert case CC into the case file before POSN */
+static gboolean
+psppire_data_store_insert_case (PsppireDataStore *ds,
+                               struct ccase *cc,
+                               casenumber posn)
 {
-  return row * ROW_HEIGHT;
+  struct ccase tmp;
+  bool result ;
+
+  g_return_val_if_fail (ds, FALSE);
+  g_return_val_if_fail (ds->datasheet, FALSE);
+
+  case_clone (&tmp, cc);
+  result = datasheet_insert_rows (ds->datasheet, posn, &tmp, 1);
+
+  if ( result )
+    {
+      g_signal_emit (ds, signals [CASE_INSERTED], 0, posn);
+      g_sheet_model_rows_inserted (G_SHEET_MODEL (ds), posn, 1);
+    }
+  else
+    g_warning ("Cannot insert case at position %ld\n", posn);
+
+  return result;
 }
 
-static glong
-geometry_pixel_to_row (const GSheetRow *geo, guint pixel)
+
+/* Copies the IDXth value from case CASENUM into VALUE.
+   If VALUE is null, then memory is allocated is allocated with
+   malloc.  Returns the value if successful, NULL on failure. */
+static union value *
+psppire_data_store_get_value (const PsppireDataStore *ds,
+                             casenumber casenum, size_t idx,
+                             union value *value, int width)
 {
-  glong row  = pixel / ROW_HEIGHT;
+  bool allocated;
+
+  g_return_val_if_fail (ds, false);
+  g_return_val_if_fail (ds->datasheet, false);
 
-  if (row >= geometry_get_row_count (geo))
-    row = geometry_get_row_count (geo) - 1;
+  g_return_val_if_fail (idx < datasheet_get_column_cnt (ds->datasheet), false);
 
-  return row;
+  if (value == NULL)
+    {
+      value = xnmalloc (value_cnt_from_width (width), sizeof *value);
+      allocated = true;
+    }
+  else
+    allocated = false;
+  if (!datasheet_get_value (ds->datasheet, casenum, idx, value, width))
+    {
+      if (allocated)
+        free (value);
+      value = NULL;
+    }
+  return value;
 }
 
 
+
+/* Set the IDXth value of case C to V.
+   Returns true if successful, false on I/O error. */
 static gboolean
-geometry_get_row_sensitivity (const GSheetRow *geom, glong unit)
+psppire_data_store_set_value (PsppireDataStore *ds, casenumber casenum,
+                             gint idx, union value *v, gint width)
 {
-  PsppireDataStore *ds = PSPPIRE_DATA_STORE (geom);
+  bool ok;
 
+  g_return_val_if_fail (ds, FALSE);
+  g_return_val_if_fail (ds->datasheet, FALSE);
+
+  g_return_val_if_fail (idx < datasheet_get_column_cnt (ds->datasheet), FALSE);
 
-  return (unit < psppire_case_file_get_case_count (ds->case_file));
+  ok = datasheet_put_value (ds->datasheet, casenum, idx, v, width);
+  if (ok)
+    g_signal_emit (ds, signals [CASE_CHANGED], 0, casenum);
+
+  return ok;
 }
 
 
-static gchar *
-geometry_get_row_button_label (const GSheetRow *geom, glong unit)
+
+
+/* Set the IDXth value of case C using D_IN */
+static gboolean
+psppire_data_store_data_in (PsppireDataStore *ds, casenumber casenum, gint idx,
+                           struct substring input, const struct fmt_spec *fmt)
 {
-  gchar *text;
-  gchar *s;
-  PsppireDataStore *ds = PSPPIRE_DATA_STORE (geom);
+  union value *value = NULL;
+  int width;
+  bool ok;
 
-  if ( unit >
-       TRAILING_ROWS + psppire_case_file_get_case_count (ds->case_file))
-    return 0;
+  g_return_val_if_fail (ds, FALSE);
+  g_return_val_if_fail (ds->datasheet, FALSE);
 
-  s = g_strdup_printf (_("%ld"), unit + FIRST_CASE_NUMBER);
+  g_return_val_if_fail (idx < datasheet_get_column_cnt (ds->datasheet), FALSE);
 
-  text =  pspp_locale_to_utf8 (s, -1, 0);
+  width = fmt_var_width (fmt);
+  value = xmalloca (value_cnt_from_width (width) * sizeof *value);
+  ok = (datasheet_get_value (ds->datasheet, casenum, idx, value, width)
+        && data_in (input, LEGACY_NATIVE, fmt->type, 0, 0, 0, value, width)
+        && datasheet_put_value (ds->datasheet, casenum, idx, value, width));
 
-  g_free (s);
+  freea (value);
 
-  return text;
+  if (ok)
+    g_signal_emit (ds, signals [CASE_CHANGED], 0, casenum);
+
+  return ok;
 }
 
-static void
-psppire_data_store_sheet_row_init (GSheetRowIface *iface)
+/* Resize the cases in the casefile, by inserting N_VALUES into every
+   one of them at the position immediately preceeding WHERE.
+*/
+static gboolean
+psppire_data_store_insert_values (PsppireDataStore *ds,
+                                 gint n_values, gint where)
 {
-  iface->get_row_count = geometry_get_row_count;
+  g_return_val_if_fail (ds, FALSE);
+
+  if ( n_values == 0 )
+    return FALSE;
+
+  g_assert (n_values > 0);
 
-  iface->get_height = geometry_get_height;
-  iface->set_height = 0;
-  iface->get_visibility = always_true;
-  iface->get_sensitivity = geometry_get_row_sensitivity;
-  iface->top_ypixel = geometry_get_top_ypixel;
-  iface->pixel_to_row = geometry_pixel_to_row;
-  iface->get_button_label = geometry_get_row_button_label;
+  if ( ! ds->datasheet )
+    ds->datasheet = datasheet_create (NULL);
+
+  {
+    union value *values = xcalloc (n_values, sizeof *values);
+    datasheet_insert_columns (ds->datasheet, values, n_values, where);
+    free (values);
+  }
+
+  return TRUE;
 }
index 55dcf0683d7e49e96d699b870487244207367027..44b11725babd667a32bb561a00bc3c6e896f78a7 100644 (file)
 #ifndef __PSPPIRE_DATA_STORE_H__
 #define __PSPPIRE_DATA_STORE_H__
 
-#include <gtksheet/gsheetmodel.h>
 #include "psppire-dict.h"
-#include "psppire-case-file.h"
 
 #define FIRST_CASE_NUMBER 1
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+G_BEGIN_DECLS
 
 #define GTK_TYPE_DATA_STORE           (psppire_data_store_get_type ())
 
@@ -57,14 +53,6 @@ typedef struct _PsppireDataStoreClass  PsppireDataStoreClass;
 struct dictionary;
 
 
-enum cf_signal_handler {
-  CASES_DELETED,
-  CASE_INSERTED,
-  CASE_CHANGED,
-  n_cf_signals
-};
-
-
 enum dict_signal_handler {
   VARIABLE_INSERTED,
   VARIABLE_CHANGED,
@@ -73,8 +61,9 @@ enum dict_signal_handler {
   n_dict_signals
 };
 
-void do_this_thing (PsppireDict *, struct dictionary *, void *);
 
+struct datasheet;
+struct casereader;
 
 struct _PsppireDataStore
 {
@@ -83,47 +72,32 @@ struct _PsppireDataStore
   /*< private >*/
   gboolean dispose_has_run ;
   PsppireDict *dict;
-  PsppireCaseFile *case_file;
-  const PangoFontDescription *font_desc;
-
-  /* The width of an upper case 'M' rendered in the current font */
-  gint width_of_m ;
+  struct datasheet *datasheet;
 
   gboolean show_labels;
 
-  /* Geometry */
-  gint margin_width;
-
-  gint cf_handler_id [n_cf_signals];
+  //  gint cf_handler_id [n_cf_signals];
   gint dict_handler_id [n_dict_signals];
 };
 
 struct _PsppireDataStoreClass
 {
   GObjectClass parent_class;
-
-  /* Padding for future expansion */
-  void (*_gtk_reserved1) (void);
-  void (*_gtk_reserved2) (void);
-  void (*_gtk_reserved3) (void);
-  void (*_gtk_reserved4) (void);
 };
 
 
-inline GType psppire_data_store_get_type (void) G_GNUC_CONST;
+GType psppire_data_store_get_type (void) G_GNUC_CONST;
 PsppireDataStore *psppire_data_store_new     (PsppireDict *dict);
 
-void psppire_data_store_set_case_file (PsppireDataStore *data_store,
-                                      PsppireCaseFile *cf);
+
+void psppire_data_store_set_reader (PsppireDataStore *ds,
+                                   struct casereader *reader);
 
 void psppire_data_store_set_dictionary (PsppireDataStore *data_store,
                                        PsppireDict *dict);
 
-void psppire_data_store_set_font (PsppireDataStore *store,
-                                const PangoFontDescription *fd);
-
 void psppire_data_store_show_labels (PsppireDataStore *store,
-                                   gboolean show_labels);
+                                    gboolean show_labels);
 
 void psppire_data_store_clear (PsppireDataStore *data_store);
 
@@ -142,12 +116,19 @@ gboolean psppire_data_store_set_string (PsppireDataStore *ds,
                                        const gchar *text,
                                        glong row, glong column);
 
-inline casenumber psppire_data_store_get_case_count (const PsppireDataStore *ds);
+casenumber psppire_data_store_get_case_count (const PsppireDataStore *ds);
 size_t psppire_data_store_get_value_count (const PsppireDataStore *ds);
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
 
+\f
+
+gboolean psppire_data_store_get_case (const PsppireDataStore *ds,
+                                     casenumber casenum,
+                                     struct ccase *c);
+
+
+
+
+G_END_DECLS
 
 #endif /* __PSPPIRE_DATA_STORE_H__ */
index e6f1373a54d969ed76de022e0135924ace674c8c..4572ba0b6ef7bff91ec0026995b29676c7257fab 100644 (file)
@@ -19,7 +19,7 @@
 #include <stdlib.h>
 
 #include <gtk/gtk.h>
-#include <gtksheet/gtkextra-marshal.h>
+#include <gtksheet/psppire-marshal.h>
 
 #include "psppire-dict.h"
 #include <data/dictionary.h>
 #include "helper.h"
 #include "message-dialog.h"
 
-/* --- prototypes --- */
-static void psppire_dict_class_init    (PsppireDictClass       *class);
-static void psppire_dict_init  (PsppireDict            *dict);
-static void psppire_dict_finalize      (GObject                *object);
-
-static void dictionary_tree_model_init (GtkTreeModelIface *iface);
-
-
-/* --- variables --- */
-static GObjectClass     *parent_class = NULL;
 
 enum  {
   BACKEND_CHANGED,
@@ -48,6 +38,7 @@ enum  {
   VARIABLE_RESIZED,
   VARIABLE_INSERTED,
   VARIABLE_DELETED,
+  VARIABLE_DISPLAY_WIDTH_CHANGED,
 
   WEIGHT_CHANGED,
   FILTER_CHANGED,
@@ -55,6 +46,18 @@ enum  {
   n_SIGNALS
 };
 
+
+/* --- prototypes --- */
+static void psppire_dict_class_init    (PsppireDictClass       *class);
+static void psppire_dict_init  (PsppireDict            *dict);
+static void psppire_dict_finalize      (GObject                *object);
+
+static void dictionary_tree_model_init (GtkTreeModelIface *iface);
+
+
+/* --- variables --- */
+static GObjectClass     *parent_class = NULL;
+
 static guint signals [n_SIGNALS];
 
 /* --- functions --- */
@@ -93,8 +96,6 @@ psppire_dict_get_type (void)
 
       g_type_add_interface_static (object_type, GTK_TYPE_TREE_MODEL,
                                   &tree_model_info);
-
-
     }
 
   return object_type;
@@ -152,7 +153,7 @@ psppire_dict_class_init (PsppireDictClass *class)
                  G_SIGNAL_RUN_FIRST,
                  0,
                  NULL, NULL,
-                 marshaller_VOID__INT_INT_INT,
+                 psppire_marshal_VOID__INT_INT_INT,
                  G_TYPE_NONE,
                  3,
                  G_TYPE_INT,
@@ -166,12 +167,23 @@ psppire_dict_class_init (PsppireDictClass *class)
                  G_SIGNAL_RUN_FIRST,
                  0,
                  NULL, NULL,
-                 gtkextra_VOID__INT_INT,
+                 psppire_marshal_VOID__INT_INT,
                  G_TYPE_NONE,
                  2,
                  G_TYPE_INT,
                  G_TYPE_INT);
 
+  signals [VARIABLE_DISPLAY_WIDTH_CHANGED] =
+    g_signal_new ("variable-display-width-changed",
+                 G_TYPE_FROM_CLASS (class),
+                 G_SIGNAL_RUN_FIRST,
+                 0,
+                 NULL, NULL,
+                 g_cclosure_marshal_VOID__INT,
+                 G_TYPE_NONE,
+                 1,
+                 G_TYPE_INT);
+
 
   signals [WEIGHT_CHANGED] =
     g_signal_new ("weight-changed",
@@ -223,7 +235,10 @@ psppire_dict_finalize (GObject *object)
 static void
 addcb (struct dictionary *d, int idx, void *pd)
 {
-  g_signal_emit (pd, signals [VARIABLE_INSERTED], 0, idx);
+  PsppireDict *dict = PSPPIRE_DICT (pd);
+
+  if ( ! dict->disable_insert_signal)
+    g_signal_emit (dict, signals [VARIABLE_INSERTED], 0, idx);
 }
 
 static void
@@ -264,6 +279,13 @@ split_changed_callback (struct dictionary *d, void *pd)
   g_signal_emit (pd, signals [SPLIT_CHANGED], 0);
 }
 
+static void
+variable_display_width_callback (struct dictionary *d, int idx, void *pd)
+{
+  g_signal_emit (pd, signals [VARIABLE_DISPLAY_WIDTH_CHANGED], 0, idx);
+}
+
+
 
 static const struct dict_callbacks gui_callbacks =
   {
@@ -273,13 +295,15 @@ static const struct dict_callbacks gui_callbacks =
     resize_cb,
     weight_changed_callback,
     filter_changed_callback,
-    split_changed_callback
+    split_changed_callback,
+    variable_display_width_callback
   };
 
 static void
 psppire_dict_init (PsppireDict *psppire_dict)
 {
   psppire_dict->stamp = g_random_int ();
+  psppire_dict->disable_insert_signal = FALSE;
 }
 
 /**
@@ -349,9 +373,15 @@ psppire_dict_insert_variable (PsppireDict *d, gint idx, const gchar *name)
   if ( ! name )
     name = auto_generate_var_name (d);
 
+  d->disable_insert_signal = TRUE;
+
   var = dict_create_var (d->dict, name, 0);
 
   dict_reorder_var (d->dict, var, idx);
+
+  d->disable_insert_signal = FALSE;
+
+  g_signal_emit (d, signals[VARIABLE_INSERTED], 0, idx);
 }
 
 /* Delete N variables beginning at FIRST */
index f645b355a6b0d5b90100fc60606e96d8240b1968..534f0707ea22df8bc6084a1d8193c917d4ae0e0a 100644 (file)
@@ -38,7 +38,6 @@ G_BEGIN_DECLS
 #define PSPPIRE_DICT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_PSPPIRE_DICT, PsppireDictClass))
 
 
-
 /* --- typedefs & structures --- */
 typedef struct _PsppireDict       PsppireDict;
 typedef struct _PsppireDictClass PsppireDictClass;
@@ -50,6 +49,7 @@ struct _PsppireDict
   GObject             parent;
   struct dictionary *dict;
 
+  gboolean disable_insert_signal;
   /* For GtkTreeModelIface */
   gint stamp;
 };
@@ -96,7 +96,7 @@ void psppire_dict_resize_variable (PsppireDict *,
 gboolean psppire_dict_check_name (const PsppireDict *dict,
                              const gchar *name, gboolean report);
 
-inline gint psppire_dict_get_next_value_idx (const PsppireDict *dict);
+gint psppire_dict_get_next_value_idx (const PsppireDict *dict);
 
 gboolean psppire_dict_rename_var (PsppireDict *dict, struct variable *v,
                              const gchar *text);
index 256f3c93930a66dcbaf849ed2234f306414ad81b..c17301056586ac8ad6c844e2a64face30e0ab44f 100644 (file)
@@ -1,4 +1,3 @@
-
 /* PSPPIRE - a graphical user interface for PSPP.
    Copyright (C) 2008 Free Software Foundation, Inc.
 
 
 #include <config.h>
 #include "psppire-var-sheet.h"
+#include <gtksheet/psppire-axis-hetero.h>
 
 #include <glade/glade.h>
 #include "helper.h"
-#include <gtksheet/gsheet-hetero-column.h>
+
 #include "customentry.h"
 #include <data/variable.h>
 #include "psppire-var-store.h"
@@ -33,7 +33,7 @@
 static void psppire_var_sheet_class_init  (PsppireVarSheetClass *klass);
 static void psppire_var_sheet_init        (PsppireVarSheet      *vs);
 
-enum 
+enum
   {
     PSPPIRE_VAR_SHEET_MAY_CREATE_VARS = 1
   };
@@ -96,20 +96,6 @@ struct column_parameters
   gint width ;
 };
 
-static const struct column_parameters column_def[] = {
-  { N_("Name"),    80},
-  { N_("Type"),    100},
-  { N_("Width"),   57},
-  { N_("Decimals"),91},
-  { N_("Label"),   95},
-  { N_("Values"),  103},
-  { N_("Missing"), 95},
-  { N_("Columns"), 80},
-  { N_("Align"),   69},
-  { N_("Measure"), 99},
-};
-
-
 #define n_ALIGNMENTS 3
 
 const gchar *const alignments[n_ALIGNMENTS + 1]={
@@ -251,103 +237,94 @@ change_measure (GtkComboBox *cb,
 }
 
 
-
+/* Moves the focus to a new cell.
+   Returns TRUE iff the move should be disallowed */
 static gboolean
 traverse_cell_callback (GtkSheet *sheet,
-                       gint row, gint column,
-                       gint *new_row, gint *new_column
-                       )
+                       const GtkSheetCell *existing_cell,
+                       GtkSheetCell *new_cell)
 {
   PsppireVarSheet *var_sheet = PSPPIRE_VAR_SHEET (sheet);
   PsppireVarStore *var_store = PSPPIRE_VAR_STORE (gtk_sheet_get_model (sheet));
 
   gint n_vars = psppire_var_store_get_var_cnt (var_store);
 
-  if (*new_row >= n_vars && !var_sheet->may_create_vars)
-    return FALSE;
+  if (new_cell->row >= n_vars && !var_sheet->may_create_vars)
+    return TRUE;
 
-  if ( row == n_vars && *new_row >= n_vars)
+  if ( existing_cell->row == n_vars && new_cell->row >= n_vars)
     {
-      GtkEntry *entry = GTK_ENTRY (gtk_sheet_get_entry (sheet));
+      GtkEntry *entry = gtk_sheet_get_entry (sheet);
 
       const gchar *name = gtk_entry_get_text (entry);
 
       if (! psppire_dict_check_name (var_store->dict, name, TRUE))
-       return FALSE;
+       return TRUE;
 
-      psppire_dict_insert_variable (var_store->dict, row, name);
+      psppire_dict_insert_variable (var_store->dict, existing_cell->row, name);
 
-      return TRUE;
+      return FALSE;
     }
 
+
   /* If the destination cell is outside the current  variables, then
      automatically create variables for the new rows.
   */
-  if ( ((*new_row > n_vars) ||
-        (*new_row == n_vars && *new_column != PSPPIRE_VAR_STORE_COL_NAME)) )
+  if ( ((new_cell->row > n_vars) ||
+        (new_cell->row == n_vars &&
+        new_cell->col != PSPPIRE_VAR_STORE_COL_NAME)) )
     {
       gint i;
-      for ( i = n_vars ; i <= *new_row; ++i )
+      for ( i = n_vars ; i <= new_cell->row; ++i )
        psppire_dict_insert_variable (var_store->dict, i, NULL);
     }
 
-  return TRUE;
+  return FALSE;
 }
 
 
 
 
 /*
-   Callback whenever the pointer leaves a cell on the var sheet.
-*/
-static gboolean
-var_sheet_cell_entry_leave (GtkSheet * sheet, gint row, gint column,
-                           gpointer data)
-{
-  gtk_sheet_change_entry (sheet, GTK_TYPE_ENTRY);
-  return TRUE;
-}
-
-
-/*
-   Callback whenever the pointer enters a cell on the var sheet.
+   Callback whenever the active cell changes on the var sheet.
 */
-static gboolean
-var_sheet_cell_entry_enter (PsppireVarSheet *vs, gint row, gint column,
-                           gpointer data)
+static void
+var_sheet_change_active_cell (PsppireVarSheet *vs,
+                             gint row, gint column,
+                             gint oldrow, gint oldcolumn,
+                             gpointer data)
 {
   GtkSheetCellAttr attributes;
-  PsppireVarStore *var_store ;
+  PsppireVarStore *var_store;
   PsppireVarSheetClass *vs_class =
     PSPPIRE_VAR_SHEET_CLASS(G_OBJECT_GET_CLASS (vs));
 
   struct variable *var ;
   GtkSheet *sheet = GTK_SHEET (vs);
 
-  g_return_val_if_fail (sheet != NULL, FALSE);
+  g_return_if_fail (sheet != NULL);
 
   var_store = PSPPIRE_VAR_STORE (gtk_sheet_get_model (sheet));
 
   g_assert (var_store);
 
-  if ( row >= psppire_var_store_get_var_cnt (var_store))
-    return TRUE;
+  g_return_if_fail (oldcolumn == PSPPIRE_VAR_STORE_COL_NAME ||
+                   row < psppire_var_store_get_var_cnt (var_store));
 
   gtk_sheet_get_attributes (sheet, row, column, &attributes);
 
-
   var = psppire_var_store_get_var (var_store, row);
 
   switch (column)
     {
     case PSPPIRE_VAR_STORE_COL_ALIGN:
       {
+       GtkEntry *entry;
        static GtkListStore *list_store = NULL;
        GtkComboBoxEntry *cbe;
        gtk_sheet_change_entry (sheet, GTK_TYPE_COMBO_BOX_ENTRY);
-       cbe =
-         GTK_COMBO_BOX_ENTRY (gtk_sheet_get_entry (sheet)->parent);
-
+       entry = gtk_sheet_get_entry (sheet);
+       cbe = GTK_COMBO_BOX_ENTRY (GTK_WIDGET (entry)->parent);
 
        if ( ! list_store) list_store = create_label_list (alignments);
 
@@ -363,12 +340,11 @@ var_sheet_cell_entry_enter (PsppireVarSheet *vs, gint row, gint column,
 
     case PSPPIRE_VAR_STORE_COL_MEASURE:
       {
+       GtkEntry *entry;
        GtkComboBoxEntry *cbe;
        gtk_sheet_change_entry (sheet, GTK_TYPE_COMBO_BOX_ENTRY);
-       cbe =
-         GTK_COMBO_BOX_ENTRY (gtk_sheet_get_entry (sheet)->parent);
-
-
+       entry = gtk_sheet_get_entry (sheet);
+       cbe = GTK_COMBO_BOX_ENTRY (GTK_WIDGET (entry)->parent);
 
        gtk_combo_box_set_model (GTK_COMBO_BOX (cbe),
                                GTK_TREE_MODEL (vs_class->measure_list));
@@ -504,19 +480,12 @@ var_sheet_cell_entry_enter (PsppireVarSheet *vs, gint row, gint column,
       gtk_sheet_change_entry (sheet, GTK_TYPE_ENTRY);
       break;
     }
-
-
-  return TRUE;
 }
 
 
-
-
 static void
 psppire_var_sheet_init (PsppireVarSheet *vs)
 {
-  gint i;
-  GObject *geo = g_sheet_hetero_column_new (75, PSPPIRE_VAR_STORE_n_COLS);
   GladeXML *xml = XML_NEW ("data-editor.glade");
 
   vs->val_labs_dialog = val_labs_dialog_create (xml);
@@ -528,24 +497,8 @@ psppire_var_sheet_init (PsppireVarSheet *vs)
   vs->dispose_has_run = FALSE;
   vs->may_create_vars = TRUE;
 
-  for (i = 0 ; i < PSPPIRE_VAR_STORE_n_COLS ; ++i )
-    {
-      g_sheet_hetero_column_set_button_label (G_SHEET_HETERO_COLUMN (geo), i,
-                                             gettext (column_def[i].label));
-
-      g_sheet_hetero_column_set_width (G_SHEET_HETERO_COLUMN (geo), i,
-                                      column_def[i].width);
-    }
-
-  g_object_set (vs, "column-geometry", geo, NULL);
-
-
   g_signal_connect (vs, "activate",
-                   G_CALLBACK (var_sheet_cell_entry_enter),
-                   NULL);
-
-  g_signal_connect (vs, "deactivate",
-                   G_CALLBACK (var_sheet_cell_entry_leave),
+                   G_CALLBACK (var_sheet_change_active_cell),
                    NULL);
 
   g_signal_connect (vs, "traverse",
@@ -553,8 +506,43 @@ psppire_var_sheet_init (PsppireVarSheet *vs)
 }
 
 
+static const struct column_parameters column_def[] = {
+  { N_("Name"),    80},
+  { N_("Type"),    100},
+  { N_("Width"),   57},
+  { N_("Decimals"),91},
+  { N_("Label"),   95},
+  { N_("Values"),  103},
+  { N_("Missing"), 95},
+  { N_("Columns"), 80},
+  { N_("Align"),   69},
+  { N_("Measure"), 99},
+};
+
 GtkWidget*
 psppire_var_sheet_new (void)
 {
-  return GTK_WIDGET (g_object_new (psppire_var_sheet_get_type (), NULL));
+  gint i;
+  PsppireAxisHetero *ha = psppire_axis_hetero_new ();
+  PsppireAxisHetero *va = psppire_axis_hetero_new ();
+
+  GtkWidget *w = g_object_new (psppire_var_sheet_get_type (), NULL);
+
+  for (i = 0 ; i < 10 ; ++i)
+    psppire_axis_hetero_append (ha, column_def[i].width);
+
+
+  g_object_set (va,
+               "default-size", 25,
+               NULL);
+
+  g_object_set (ha, "minimum-extent", 0,
+               NULL);
+
+  g_object_set (w,
+               "horizontal-axis", ha,
+               "vertical-axis", va,
+               NULL);
+
+  return w;
 }
index fa356b812d60dc47e3b160e8079b3c6caf8cfc70..19b50028a68566079f0eae03dc5fb6eef9814797 100644 (file)
@@ -28,7 +28,6 @@
 #include <gtksheet/gsheetmodel.h>
 
 #include "psppire-var-store.h"
-#include <gtksheet/gsheet-row-iface.h>
 #include "helper.h"
 
 #include <data/dictionary.h>
@@ -44,7 +43,7 @@
 
 enum
   {
-    PSPPIRE_VAR_STORE_TRAILING_ROWS = 1,
+    PROP_0,
     PSPPIRE_VAR_STORE_FORMAT_TYPE
   };
 
@@ -71,10 +70,6 @@ static glong psppire_var_store_get_column_count (const GSheetModel * model);
 static gchar *text_for_column (const struct variable *pv, gint c, GError **err);
 
 
-static void psppire_var_store_sheet_row_init (GSheetRowIface *iface);
-
-
-
 static GObjectClass *parent_class = NULL;
 
 GType
@@ -128,24 +123,11 @@ psppire_var_store_get_type (void)
        NULL
       };
 
-      static const GInterfaceInfo sheet_row_info =
-      {
-       (GInterfaceInitFunc) psppire_var_store_sheet_row_init,
-       NULL,
-       NULL
-      };
-
       var_store_type = g_type_register_static (G_TYPE_OBJECT, "PsppireVarStore", &var_store_info, 0);
 
       g_type_add_interface_static (var_store_type,
                                   G_TYPE_SHEET_MODEL,
                                   &sheet_model_info);
-
-      g_type_add_interface_static (var_store_type,
-                                  G_TYPE_SHEET_ROW,
-                                  &sheet_row_info);
-
-
     }
 
   return var_store_type;
@@ -161,10 +143,6 @@ psppire_var_store_set_property (GObject      *object,
 
   switch (property_id)
     {
-    case PSPPIRE_VAR_STORE_TRAILING_ROWS:
-      self->trailing_rows = g_value_get_int (value);
-      break;
-
     case PSPPIRE_VAR_STORE_FORMAT_TYPE:
       self->format_type = g_value_get_enum (value);
       break;
@@ -185,10 +163,6 @@ psppire_var_store_get_property (GObject      *object,
 
   switch (property_id)
     {
-    case PSPPIRE_VAR_STORE_TRAILING_ROWS:
-      g_value_set_int (value, self->trailing_rows);
-      break;
-
     case PSPPIRE_VAR_STORE_FORMAT_TYPE:
       g_value_set_enum (value, self->format_type);
       break;
@@ -213,20 +187,6 @@ psppire_var_store_class_init (PsppireVarStoreClass *class)
   object_class->set_property = psppire_var_store_set_property;
   object_class->get_property = psppire_var_store_get_property;
 
-  /* The minimum value for trailing-rows is 1 to prevent the
-     var-store from ever having 0 rows, which breaks invariants
-     in gtksheet. */
-  pspec = g_param_spec_int ("trailing-rows",
-                            "Trailing rows",
-                            "Number of rows displayed after last variable",
-                            1  /* minimum value */,
-                            100 /* maximum value */,
-                            40  /* default value */,
-                            G_PARAM_READWRITE);
-  g_object_class_install_property (object_class,
-                                   PSPPIRE_VAR_STORE_TRAILING_ROWS,
-                                   pspec);
-
   pspec = g_param_spec_enum ("format-type",
                              "Variable format type",
                              ("Whether variables have input or output "
@@ -234,22 +194,21 @@ psppire_var_store_class_init (PsppireVarStoreClass *class)
                              G_TYPE_PSPPIRE_VAR_STORE_FORMAT_TYPE,
                              PSPPIRE_VAR_STORE_OUTPUT_FORMATS,
                              G_PARAM_READWRITE);
+
   g_object_class_install_property (object_class,
                                    PSPPIRE_VAR_STORE_FORMAT_TYPE,
                                    pspec);
 }
 
+#define DISABLED_COLOR "gray"
+
 static void
 psppire_var_store_init (PsppireVarStore *var_store)
 {
-  GdkColormap *colormap = gdk_colormap_get_system ();
-
-  g_assert (gdk_color_parse ("gray", &var_store->disabled));
-
-  gdk_colormap_alloc_color (colormap, &var_store->disabled, FALSE, TRUE);
+  if ( ! gdk_color_parse (DISABLED_COLOR, &var_store->disabled))
+       g_critical ("Could not parse color \"%s\"", DISABLED_COLOR);
 
   var_store->dict = 0;
-  var_store->trailing_rows = 40;
   var_store->format_type = PSPPIRE_VAR_STORE_OUTPUT_FORMATS;
 }
 
@@ -308,7 +267,7 @@ psppire_var_store_is_editable (const GSheetModel *model, glong row, glong column
 }
 
 
-static const GdkColor *
+static GdkColor *
 psppire_var_store_get_foreground (const GSheetModel *model, glong row, glong column)
 {
   PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
@@ -320,17 +279,9 @@ psppire_var_store_get_foreground (const GSheetModel *model, glong row, glong col
 }
 
 
-const PangoFontDescription *
-psppire_var_store_get_font_desc (const GSheetModel *model,
-                             glong row, glong column)
-{
-  PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
-
-  return store->font_desc;
-}
-
-
-
+static gchar *get_column_title (const GSheetModel *model, gint col);
+static gchar *get_row_title (const GSheetModel *model, gint row);
+static gboolean get_row_sensitivity (const GSheetModel *model, gint row);
 
 static void
 psppire_var_store_sheet_model_init (GSheetModelIface *iface)
@@ -342,14 +293,15 @@ psppire_var_store_sheet_model_init (GSheetModelIface *iface)
   iface->set_string = psppire_var_store_set_string;
   iface->clear_datum = psppire_var_store_clear;
   iface->is_editable = psppire_var_store_is_editable;
-  iface->is_visible = NULL;
   iface->get_foreground = psppire_var_store_get_foreground;
   iface->get_background = NULL;
-  iface->get_font_desc = psppire_var_store_get_font_desc;
-  iface->get_cell_border = NULL;
-}
+  iface->get_justification = NULL;
 
+  iface->get_column_title = get_column_title;
 
+  iface->get_row_title = get_row_title;
+  iface->get_row_sensitivity = get_row_sensitivity;
+}
 
 /**
  * psppire_var_store_new:
@@ -763,18 +715,6 @@ psppire_var_store_get_var_cnt (PsppireVarStore  *store)
 }
 
 
-void
-psppire_var_store_set_font (PsppireVarStore *store, const PangoFontDescription *fd)
-{
-  g_return_if_fail (store);
-  g_return_if_fail (PSPPIRE_IS_VAR_STORE (store));
-
-  store->font_desc = fd;
-
-  g_sheet_model_range_changed (G_SHEET_MODEL (store), -1, -1, -1, -1);
-}
-
-
 static glong
 psppire_var_store_get_row_count (const GSheetModel * model)
 {
@@ -793,33 +733,15 @@ psppire_var_store_get_column_count (const GSheetModel * model)
   return PSPPIRE_VAR_STORE_n_COLS ;
 }
 
+\f
 
 /* Row related funcs */
 
-static glong
-geometry_get_row_count (const GSheetRow *geom)
-{
-  gint rows = 0;
-  PsppireVarStore *vs = PSPPIRE_VAR_STORE (geom);
-
-  if (vs->dict)
-    rows =  psppire_dict_get_var_cnt (vs->dict);
-
-  return rows + vs->trailing_rows;
-}
-
-
-static gint
-geometry_get_height (const GSheetRow *geom, glong row)
-{
-  return 25;
-}
-
 
 static gboolean
-geometry_is_sensitive (const GSheetRow *geom, glong row)
+get_row_sensitivity (const GSheetModel *model, gint row)
 {
-  PsppireVarStore *vs = PSPPIRE_VAR_STORE (geom);
+  PsppireVarStore *vs = PSPPIRE_VAR_STORE (model);
 
   if ( ! vs->dict)
     return FALSE;
@@ -827,32 +749,34 @@ geometry_is_sensitive (const GSheetRow *geom, glong row)
   return  row < psppire_dict_get_var_cnt (vs->dict);
 }
 
-static
-gboolean always_true ()
-{
-  return TRUE;
-}
-
 
 static gchar *
-geometry_get_button_label (const GSheetRow *geom, glong unit)
+get_row_title (const GSheetModel *model, gint unit)
 {
-  gchar *label = g_strdup_printf (_("%ld"), unit + 1);
-
-  return label;
+  return g_strdup_printf (_("%d"), unit + 1);
 }
 
-static void
-psppire_var_store_sheet_row_init (GSheetRowIface *iface)
-{
-  iface->get_row_count =     geometry_get_row_count;
-  iface->get_height =        geometry_get_height;
-  iface->set_height =        0;
-  iface->get_visibility =    always_true;
-  iface->get_sensitivity =   geometry_is_sensitive;
 
-  iface->get_button_label = geometry_get_button_label;
-}
+\f
 
+static const gchar *column_titles[] = {
+  N_("Name"),
+  N_("Type"),
+  N_("Width"),
+  N_("Decimals"),
+  N_("Label"),
+  N_("Values"),
+  N_("Missing"),
+  N_("Columns"),
+  N_("Align"),
+  N_("Measure"),
+};
 
 
+static gchar *
+get_column_title (const GSheetModel *model, gint col)
+{
+  if ( col >= 10)
+    return NULL;
+  return g_strdup (gettext (column_titles[col]));
+}
index a4782efceb04e009126e7408eb10289ed1f85438..cf4375898f737fd782196c51cf7143cc8334b4d4 100644 (file)
@@ -17,7 +17,6 @@
 #ifndef __PSPPIRE_VAR_STORE_H__
 #define __PSPPIRE_VAR_STORE_H__
 
-#include <gtksheet/gsheetmodel.h>
 #include "psppire-dict.h"
 #include <gdk/gdk.h>
 
@@ -66,8 +65,6 @@ struct _PsppireVarStore
   /*< private >*/
   PsppireDict *dict;
   GdkColor disabled;
-  const PangoFontDescription *font_desc;
-  gint trailing_rows;
   PsppireVarStoreFormatType format_type;
 };
 
index d36a802cb0e828a9a9d7c46c81aa312d8e5958d2..02415d68bc3df8a6250d0a115f622c52de6c787f 100644 (file)
@@ -72,9 +72,7 @@ struct dataset * the_dataset = NULL;
 static void
 replace_casereader (struct casereader *s)
 {
-  PsppireCaseFile *pcf = psppire_case_file_new (s);
-
-  psppire_data_store_set_case_file (the_data_store, pcf);
+  psppire_data_store_set_reader (the_data_store, s);
 }
 
 #define _(msgid) gettext (msgid)
index a029198ae328e831621c61d70b1719f0efa7b565..73220e3b9ae4eb843dcd45ba783eed01c80f3b6e 100644 (file)
@@ -1623,12 +1623,10 @@ prepare_formats_page (struct import_assistant *ia)
      hold a reference via ia->formats.dict. */
   var_store = psppire_var_store_new (psppire_dict);
   g_object_set (var_store,
-                "trailing-rows", 1,
                 "format-type", PSPPIRE_VAR_STORE_INPUT_FORMATS,
                 (void *) NULL);
   var_sheet = PSPPIRE_VAR_SHEET (psppire_var_sheet_new ());
   g_object_set (var_sheet,
-                "row-geometry", var_store,
                 "model", var_store,
                 "may-create-vars", FALSE,
                 (void *) NULL);
index 504e19f409aa05bb8a4df7b6969d6197d91f739b..c603c3a876a61ee2ce5e21815d93e6a8e829e1c6 100644 (file)
@@ -245,7 +245,7 @@ next_composition (int n, int *k, int parts[])
 /* A block expected to be found in a tower. */
 struct expected_block
   {
-    int height;         /* Expected height of bottom of block. */
+    int size;           /* Expected thickness of block. */
     int x;              /* Expected value for `x' member. */
   };
 
@@ -259,6 +259,7 @@ check_tower (struct tower *t,
   struct tower_node *node;
   size_t i;
 
+  check (tower_count (t) == block_cnt);
   check (tower_is_empty (t) == (block_cnt == 0));
 
   total_height = 0;
@@ -266,7 +267,7 @@ check_tower (struct tower *t,
     {
       unsigned long int level;
       for (level = total_height;
-           level < total_height + blocks[i].height;
+           level < total_height + blocks[i].size;
            level++)
         {
           struct tower_node *found;
@@ -275,8 +276,11 @@ check_tower (struct tower *t,
           check (found != NULL);
           check (tower_node_to_block (found)->x == blocks[i].x);
           check (block_start == total_height);
+          check (tower_node_get_level (found) == total_height);
+          check (tower_node_get_index (found) == i);
+          check (tower_get (t, i) == found);
         }
-      total_height += blocks[i].height;
+      total_height += blocks[i].size;
     }
   check (tower_height (t) == total_height);
 
@@ -284,7 +288,7 @@ check_tower (struct tower *t,
        node != NULL;
        node = tower_next (t, node), i++)
     {
-      check (tower_node_get_height (node) == blocks[i].height);
+      check (tower_node_get_size (node) == blocks[i].size);
       check (tower_node_to_block (node)->x == blocks[i].x);
     }
   check (i == block_cnt);
@@ -293,7 +297,7 @@ check_tower (struct tower *t,
        node != NULL;
        node = tower_prev (t, node), i--)
     {
-      check (tower_node_get_height (node) == blocks[i].height);
+      check (tower_node_get_size (node) == blocks[i].size);
       check (tower_node_to_block (node)->x == blocks[i].x);
     }
   check (i == SIZE_MAX);
@@ -312,19 +316,19 @@ test_insert (void)
     {
       unsigned int composition_cnt;
       struct expected_block *expected;
-      int *heights;
+      int *sizes;
       int block_cnt;
       int *order;
       struct block *blocks;
 
       expected = xnmalloc (cnt, sizeof *expected);
-      heights = xnmalloc (cnt, sizeof *heights);
+      sizes = xnmalloc (cnt, sizeof *sizes);
       order = xnmalloc (cnt, sizeof *order);
       blocks = xnmalloc (cnt, sizeof *blocks);
 
       block_cnt = 0;
       composition_cnt = 0;
-      while (next_composition (cnt, &block_cnt, heights))
+      while (next_composition (cnt, &block_cnt, sizes))
         {
           int i, j;
           unsigned int permutation_cnt;
@@ -338,7 +342,7 @@ test_insert (void)
               struct tower t;
 
               /* Inserts the block_cnt blocks with the given
-                 heights[] into T in the order given by order[]. */
+                 sizes[] into T in the order given by order[]. */
               tower_init (&t);
               for (i = 0; i < block_cnt; i++)
                 {
@@ -354,14 +358,14 @@ test_insert (void)
                         && (under == NULL || under->x > order[j]))
                       under = &blocks[order[j]];
 
-                  tower_insert (&t, heights[idx], &blocks[idx].node,
+                  tower_insert (&t, sizes[idx], &blocks[idx].node,
                                 under != NULL ? &under->node : NULL);
                 }
 
               /* Check that the result is what we expect. */
               for (i = 0; i < block_cnt; i++)
                 {
-                  expected[i].height = heights[i];
+                  expected[i].size = sizes[i];
                   expected[i].x = i;
                 }
               check_tower (&t, expected, block_cnt);
@@ -375,14 +379,14 @@ test_insert (void)
       check (composition_cnt == 1 << (cnt - 1));
 
       free (expected);
-      free (heights);
+      free (sizes);
       free (order);
       free (blocks);
     }
 }
 
 /* Tests deleting blocks from towers that initially contain all
-   possible sets of block heights into a tower in all possible
+   possible sets of block sizes into a tower in all possible
    orders, up to a specified maximum tower height. */
 static void
 test_delete (void)
@@ -394,19 +398,19 @@ test_delete (void)
     {
       unsigned int composition_cnt;
       struct expected_block *expected;
-      int *heights;
+      int *sizes;
       int block_cnt;
       int *order;
       struct block *blocks;
 
       expected = xnmalloc (cnt, sizeof *expected);
-      heights = xnmalloc (cnt, sizeof *heights);
+      sizes = xnmalloc (cnt, sizeof *sizes);
       order = xnmalloc (cnt, sizeof *order);
       blocks = xnmalloc (cnt, sizeof *blocks);
 
       block_cnt = 0;
       composition_cnt = 0;
-      while (next_composition (cnt, &block_cnt, heights))
+      while (next_composition (cnt, &block_cnt, sizes))
         {
           int i;
           unsigned int permutation_cnt;
@@ -424,9 +428,9 @@ test_delete (void)
               for (i = 0; i < block_cnt; i++)
                 {
                   blocks[i].x = i;
-                  tower_insert (&t, heights[i], &blocks[i].node, NULL);
+                  tower_insert (&t, sizes[i], &blocks[i].node, NULL);
                   expected[i].x = i;
-                  expected[i].height = heights[i];
+                  expected[i].size = sizes[i];
                 }
               check_tower (&t, expected, block_cnt);
 
@@ -459,14 +463,14 @@ test_delete (void)
       check (composition_cnt == 1 << (cnt - 1));
 
       free (expected);
-      free (heights);
+      free (sizes);
       free (order);
       free (blocks);
     }
 }
 
-/* Tests towers containing all possible block heights, resizing
-   the blocks to all possible heights that conserve the total
+/* Tests towers containing all possible block sizes, resizing
+   the blocks to all possible sizes that conserve the total
    tower height, up to a maximum total tower height. */
 static void
 test_resize (void)
@@ -478,27 +482,27 @@ test_resize (void)
     {
       unsigned int composition_cnt;
       struct expected_block *expected;
-      int *heights, *new_heights;
+      int *sizes, *new_sizes;
       int block_cnt;
       int *order;
       struct block *blocks;
 
       expected = xnmalloc (cnt, sizeof *expected);
-      heights = xnmalloc (cnt, sizeof *heights);
-      new_heights = xnmalloc (cnt, sizeof *new_heights);
+      sizes = xnmalloc (cnt, sizeof *sizes);
+      new_sizes = xnmalloc (cnt, sizeof *new_sizes);
       order = xnmalloc (cnt, sizeof *order);
       blocks = xnmalloc (cnt, sizeof *blocks);
 
       block_cnt = 0;
       composition_cnt = 0;
-      while (next_composition (cnt, &block_cnt, heights))
+      while (next_composition (cnt, &block_cnt, sizes))
         {
           int i;
           unsigned int resizes = 0;
 
-          for (resizes = 0, first_k_composition (cnt, block_cnt, new_heights);
+          for (resizes = 0, first_k_composition (cnt, block_cnt, new_sizes);
                (resizes == 0
-                || next_k_composition (cnt, block_cnt, new_heights));
+                || next_k_composition (cnt, block_cnt, new_sizes));
                resizes++)
             {
               struct tower t;
@@ -508,18 +512,18 @@ test_resize (void)
               for (i = 0; i < block_cnt; i++)
                 {
                   blocks[i].x = i;
-                  tower_insert (&t, heights[i], &blocks[i].node, NULL);
+                  tower_insert (&t, sizes[i], &blocks[i].node, NULL);
                   expected[i].x = i;
-                  expected[i].height = heights[i];
+                  expected[i].size = sizes[i];
                 }
               check_tower (&t, expected, block_cnt);
 
               /* Resize all the blocks. */
               for (i = 0; i < block_cnt; i++)
                 {
-                  if (expected[i].height != new_heights[i] || rand () % 2)
-                    tower_resize (&t, &blocks[i].node, new_heights[i]);
-                  expected[i].height = new_heights[i];
+                  if (expected[i].size != new_sizes[i] || rand () % 2)
+                    tower_resize (&t, &blocks[i].node, new_sizes[i]);
+                  expected[i].size = new_sizes[i];
                 }
               check_tower (&t, expected, block_cnt);
             }
@@ -530,8 +534,8 @@ test_resize (void)
       check (composition_cnt == 1 << (cnt - 1));
 
       free (expected);
-      free (new_heights);
-      free (heights);
+      free (new_sizes);
+      free (sizes);
       free (order);
       free (blocks);
     }
@@ -549,20 +553,20 @@ test_splice_out (void)
     {
       unsigned int composition_cnt;
       struct expected_block *expected;
-      int *heights, *new_heights;
+      int *sizes, *new_sizes;
       int block_cnt;
       int *order;
       struct block *blocks;
 
       expected = xnmalloc (cnt, sizeof *expected);
-      heights = xnmalloc (cnt, sizeof *heights);
-      new_heights = xnmalloc (cnt, sizeof *new_heights);
+      sizes = xnmalloc (cnt, sizeof *sizes);
+      new_sizes = xnmalloc (cnt, sizeof *new_sizes);
       order = xnmalloc (cnt, sizeof *order);
       blocks = xnmalloc (cnt, sizeof *blocks);
 
       block_cnt = 0;
       composition_cnt = 0;
-      while (next_composition (cnt, &block_cnt, heights))
+      while (next_composition (cnt, &block_cnt, sizes))
         {
           int i, j;
 
@@ -579,9 +583,9 @@ test_splice_out (void)
                 for (k = 0; k < block_cnt; k++)
                   {
                     blocks[k].x = k;
-                    tower_insert (&src, heights[k], &blocks[k].node, NULL);
+                    tower_insert (&src, sizes[k], &blocks[k].node, NULL);
                     expected[k].x = k;
-                    expected[k].height = heights[k];
+                    expected[k].size = sizes[k];
                   }
                 check_tower (&src, expected, block_cnt);
 
@@ -598,8 +602,8 @@ test_splice_out (void)
       check (composition_cnt == 1 << (cnt - 1));
 
       free (expected);
-      free (new_heights);
-      free (heights);
+      free (new_sizes);
+      free (sizes);
       free (order);
       free (blocks);
     }
@@ -617,20 +621,20 @@ test_splice_in (void)
     {
       unsigned int composition_cnt;
       struct expected_block *expected;
-      int *heights, *new_heights;
+      int *sizes, *new_sizes;
       int block_cnt;
       int *order;
       struct block *blocks;
 
       expected = xnmalloc (cnt, sizeof *expected);
-      heights = xnmalloc (cnt, sizeof *heights);
-      new_heights = xnmalloc (cnt, sizeof *new_heights);
+      sizes = xnmalloc (cnt, sizeof *sizes);
+      new_sizes = xnmalloc (cnt, sizeof *new_sizes);
       order = xnmalloc (cnt, sizeof *order);
       blocks = xnmalloc (cnt, sizeof *blocks);
 
       block_cnt = 0;
       composition_cnt = 0;
-      while (next_composition (cnt, &block_cnt, heights))
+      while (next_composition (cnt, &block_cnt, sizes))
         {
           int i, j;
 
@@ -648,9 +652,9 @@ test_splice_in (void)
                   {
                     blocks[k].x = k;
                     tower_insert (k >= i && k < j ? &src : &dst,
-                                  heights[k], &blocks[k].node, NULL);
+                                  sizes[k], &blocks[k].node, NULL);
                     expected[k].x = k;
-                    expected[k].height = heights[k];
+                    expected[k].size = sizes[k];
                   }
 
                 /* Splice SRC into DST. */
@@ -663,8 +667,8 @@ test_splice_in (void)
       check (composition_cnt == 1 << (cnt - 1));
 
       free (expected);
-      free (new_heights);
-      free (heights);
+      free (new_sizes);
+      free (sizes);
       free (order);
       free (blocks);
     }