pspp-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Pspp-cvs] psppire ./ChangeLog ./NEWS ./README ./TODO ./co...


From: John Darrington
Subject: [Pspp-cvs] psppire ./ChangeLog ./NEWS ./README ./TODO ./co...
Date: Sat, 28 Jan 2006 08:48:08 +0000

CVSROOT:        /cvsroot/pspp
Module name:    psppire
Branch:         
Changes by:     John Darrington <address@hidden>        06/01/28 08:48:08

Modified files:
        .              : ChangeLog NEWS README TODO configure.ac 
                         psppire.glade pspplogo.png 
        gtk_sheet      : Makefile.am README gtkextra-marshal.c 
                         gtkextra-marshal.h gtkitementry.c gtksheet.c 
                         gtksheet.h 
        src            : ChangeLog Makefile.am data_sheet.c data_sheet.h 
                         error-dialog.c error-dialog.h main.c 
                         missing_val_dialog.c missing_val_dialog.h 
                         val_labs_dialog.c val_labs_dialog.h var_sheet.c 
                         var_sheet.h var_type_dialog.c var_type_dialog.h 
Added files:
        gtk_sheet      : COPYING.LGPL ChangeLog gsheet-column-iface.c 
                         gsheet-column-iface.h gsheet-hetero-column.c 
                         gsheet-hetero-column.h gsheet-row-iface.c 
                         gsheet-row-iface.h gsheet-uniform-column.c 
                         gsheet-uniform-column.h gsheet-uniform-row.c 
                         gsheet-uniform-row.h gsheetmodel.c 
                         gsheetmodel.h gtkextra-sheet.h 
        src            : menu-actions.c menu-actions.h 
                         psppire-case-array.c psppire-case-array.h 
                         psppire-data-store.c psppire-data-store.h 
                         psppire-dict.c psppire-dict.h psppire-object.c 
                         psppire-object.h psppire-var-store.c 
                         psppire-var-store.h psppire-variable.c 
                         psppire-variable.h 
Removed files:
        .              : mkinstalldirs 
        src            : callbacks.c callbacks.h pspp-dict.c pspp-dict.h 
                         pspp-object.c pspp-object.h 

Log message:
        Separated the Data from the View.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/ChangeLog.diff?tr1=1.1.1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/NEWS.diff?tr1=1.1.1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/README.diff?tr1=1.7&tr2=1.8&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/TODO.diff?tr1=1.20&tr2=1.21&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/configure.ac.diff?tr1=1.7&tr2=1.8&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/psppire.glade.diff?tr1=1.17&tr2=1.18&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/pspplogo.png.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/COPYING.LGPL?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/ChangeLog?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/Makefile.am.diff?tr1=1.3&tr2=1.4&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/README.diff?tr1=1.1.1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gsheet-column-iface.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gsheet-column-iface.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gsheet-hetero-column.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gsheet-hetero-column.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gsheet-row-iface.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gsheet-row-iface.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gsheet-uniform-column.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gsheet-uniform-column.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gsheet-uniform-row.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gsheet-uniform-row.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gsheetmodel.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gsheetmodel.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gtkextra-marshal.c.diff?tr1=1.1.1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gtkextra-marshal.h.diff?tr1=1.1.1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gtkextra-sheet.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gtkitementry.c.diff?tr1=1.1.1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gtksheet.c.diff?tr1=1.12&tr2=1.13&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/gtk_sheet/gtksheet.h.diff?tr1=1.6&tr2=1.7&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/ChangeLog.diff?tr1=1.12&tr2=1.13&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/Makefile.am.diff?tr1=1.14&tr2=1.15&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/data_sheet.c.diff?tr1=1.27&tr2=1.28&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/data_sheet.h.diff?tr1=1.3&tr2=1.4&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/error-dialog.c.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/error-dialog.h.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/main.c.diff?tr1=1.13&tr2=1.14&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/menu-actions.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/menu-actions.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/missing_val_dialog.c.diff?tr1=1.4&tr2=1.5&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/missing_val_dialog.h.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/psppire-case-array.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/psppire-case-array.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/psppire-data-store.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/psppire-data-store.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/psppire-dict.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/psppire-dict.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/psppire-object.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/psppire-object.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/psppire-var-store.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/psppire-var-store.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/psppire-variable.c?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/psppire-variable.h?rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/val_labs_dialog.c.diff?tr1=1.6&tr2=1.7&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/val_labs_dialog.h.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/var_sheet.c.diff?tr1=1.31&tr2=1.32&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/var_sheet.h.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/var_type_dialog.c.diff?tr1=1.10&tr2=1.11&r1=text&r2=text
http://cvs.savannah.gnu.org/viewcvs/pspp/psppire/src/var_type_dialog.h.diff?tr1=1.7&tr2=1.8&r1=text&r2=text

Patches:
Index: psppire/ChangeLog
diff -u psppire/ChangeLog:1.1.1.1 psppire/ChangeLog:1.2
--- psppire/ChangeLog:1.1.1.1   Tue Nov  2 11:17:19 2004
+++ psppire/ChangeLog   Sat Jan 28 08:48:07 2006
@@ -1,3 +1,7 @@
+Sat Jan 28 16:22:23 WST 2006 John Darrington <address@hidden>
+
+    * Separated the data out of the GtkSheet.
+
 Tue Nov  2 19:00:28 WST 2004 John Darrington <address@hidden>
 
     * Very first incarnation
Index: psppire/NEWS
diff -u psppire/NEWS:1.1.1.1 psppire/NEWS:1.2
--- psppire/NEWS:1.1.1.1        Tue Nov  2 11:17:19 2004
+++ psppire/NEWS        Sat Jan 28 08:48:07 2006
@@ -0,0 +1,5 @@
+New features:
+* Display Labels in data sheet now works.
+* You can now insert and delete rows in data and variable sheets. Any number 
of rows can be
+  deleted, by selecting them first.
+* The program no longer leaks memory at such an alarming rate.
Index: psppire/README
diff -u psppire/README:1.7 psppire/README:1.8
--- psppire/README:1.7  Thu Dec 22 08:56:59 2005
+++ psppire/README      Sat Jan 28 08:48:07 2006
@@ -1,4 +1,4 @@
-This is pre - alpha software.  If it doesn't work, then feedback will be
+This is pre-alpha software.  If it doesn't work, then feedback will be
 appreciated,  but complaints will be ignored.
 
 What you can do with it so far:
Index: psppire/TODO
diff -u psppire/TODO:1.20 psppire/TODO:1.21
--- psppire/TODO:1.20   Fri Dec 23 06:50:09 2005
+++ psppire/TODO        Sat Jan 28 08:48:07 2006
@@ -37,26 +37,30 @@
 Task List
 =========
 
-* Value labels currently don't work properly for Date, Dot, Comma variables.
-
-* Implement mechanism for handling errors (use GError ?). 
+Things Requiring Immediate Attention
+------------------------------------
+* Comment the code better.
+* Row title buttons need to be disabled for non-populated rows.
+* In data sheet, incomplete entries (eg dates) causes error dialogs.
+* Annoying error dialogs in var sheet (eg when entering var name "gender").
+* Changing fonts should set cell height appropriately.
+* When selecting rows for deletion, row title buttons don't get highlighted.
 
+Longer Term Issues
+------------------
 * Load/Save portable files.
-
-* data_sheet.c: value_format_func is one big memory leak.
-
-* The number of cases is limited to the hard coded sheet dimensions. It 
+* The number of cases is limited to the hard coded maximum. It 
   needs to be unlimited.
-
-* Inserting variables in middle of var sheet.
-
-* Deleting more than one variable at once.
-
 * Changing variable types and/or formats should do sensible conversion of
   data values.
+* Use the text entry area on the data sheet.
+* Optimise away all "for(i=0;i<column_count(sheet);++i)" lines in gtksheet.c
 
-* Wishlist:
-
-** Support clipboard to cut and paste to/from Gnumeric and other Psppire 
-   instances.
+Wishlist
+--------
+* Can't Quit using the window decoration button.
+* Add "Are you sure?" dialog on exit with unsaved data.
+* Support clipboard to cut and paste to/from Gnumeric and other Psppire 
+  instances.
+* Docbook documentation.
 
Index: psppire/configure.ac
diff -u psppire/configure.ac:1.7 psppire/configure.ac:1.8
--- psppire/configure.ac:1.7    Sun Dec 11 01:05:02 2005
+++ psppire/configure.ac        Sat Jan 28 08:48:07 2006
@@ -16,6 +16,7 @@
 
 AC_CHECK_SIZEOF(double, 8)
 
+
 PKG_CHECK_MODULES(PACKAGE, gtk+-2.0 >= 2.6.0)
 PKG_CHECK_MODULES(GLADE, libglade-2.0)
 AC_SUBST(PACKAGE_CFLAGS)
Index: psppire/gtk_sheet/Makefile.am
diff -u psppire/gtk_sheet/Makefile.am:1.3 psppire/gtk_sheet/Makefile.am:1.4
--- psppire/gtk_sheet/Makefile.am:1.3   Fri Nov  4 01:08:25 2005
+++ psppire/gtk_sheet/Makefile.am       Sat Jan 28 08:48:08 2006
@@ -4,16 +4,19 @@
 
 noinst_LIBRARIES = libgtksheet.a
 
-libgtksheet_a_SOURCES = \
-  gtkextra.c \
-  gtkextrafeatures.h \
-  gtkextra-marshal.c \
-  gtkextra-marshal.h \
-  gtkiconlist.c \
-  gtkiconlist.h \
-  gtkitementry.c \
-  gtkitementry.h \
-  gtksheet.c \
-  gtksheet.h 
-
+EXTRA_DIST = README COPYING.LGPL
 
+libgtksheet_a_SOURCES = \
+ gsheet-column-iface.c gsheet-column-iface.h \
+ gsheet-hetero-column.c gsheet-hetero-column.h \
+ gsheetmodel.c gsheetmodel.h \
+ gsheet-row-iface.c gsheet-row-iface.h \
+ gsheet-uniform-column.c gsheet-uniform-column.h \
+ gsheet-uniform-row.c gsheet-uniform-row.h \
+ gtkextra-sheet.h \
+ gtksheet.c gtksheet.h \
+ gtkextra.c \
+ gtkextrafeatures.h \
+ gtkextra-marshal.c gtkextra-marshal.h \
+ gtkiconlist.c gtkiconlist.h \
+ gtkitementry.c gtkitementry.h 
Index: psppire/gtk_sheet/README
diff -u psppire/gtk_sheet/README:1.1.1.1 psppire/gtk_sheet/README:1.2
--- psppire/gtk_sheet/README:1.1.1.1    Tue Nov  2 11:18:29 2004
+++ psppire/gtk_sheet/README    Sat Jan 28 08:48:08 2006
@@ -1 +1,11 @@
 This is not part of the GNU PSPP program, but is used with GNU PSPP.
+
+This directory contains a version of the GtkSheet widget from the gtk-extra 
+project at http://gtkextra.sourceforge.net  The version found here has 
+major modifications developed for the needs of PSPP.  Every effort has been
+made to keep GtkSheet application independent. Thus, it should be possible
+to use this modified software for other applications.  However, the API is
+substantially different from the original.
+
+Files in this directory ONLY are licensed under the GNU Lesser General Public 
+License.  See COPYING.LGPL
Index: psppire/gtk_sheet/gtkextra-marshal.c
diff -u psppire/gtk_sheet/gtkextra-marshal.c:1.1.1.1 
psppire/gtk_sheet/gtkextra-marshal.c:1.2
--- psppire/gtk_sheet/gtkextra-marshal.c:1.1.1.1        Tue Nov  2 11:17:30 2004
+++ psppire/gtk_sheet/gtkextra-marshal.c        Sat Jan 28 08:48:08 2006
@@ -584,6 +584,49 @@
             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,
Index: psppire/gtk_sheet/gtkextra-marshal.h
diff -u psppire/gtk_sheet/gtkextra-marshal.h:1.1.1.1 
psppire/gtk_sheet/gtkextra-marshal.h:1.2
--- psppire/gtk_sheet/gtkextra-marshal.h:1.1.1.1        Tue Nov  2 11:17:30 2004
+++ psppire/gtk_sheet/gtkextra-marshal.h        Sat Jan 28 08:48:08 2006
@@ -137,6 +137,15 @@
                                     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,
Index: psppire/gtk_sheet/gtkitementry.c
diff -u psppire/gtk_sheet/gtkitementry.c:1.1.1.1 
psppire/gtk_sheet/gtkitementry.c:1.2
--- psppire/gtk_sheet/gtkitementry.c:1.1.1.1    Tue Nov  2 11:17:46 2004
+++ psppire/gtk_sheet/gtkitementry.c    Sat Jan 28 08:48:08 2006
@@ -860,6 +860,8 @@
        case GTK_MOVEMENT_PARAGRAPHS:
        case GTK_MOVEMENT_PAGES:
          break;
+       default:
+         break;
        }
     }
   else
@@ -893,6 +895,8 @@
        case GTK_MOVEMENT_PARAGRAPHS:
        case GTK_MOVEMENT_PAGES:
          break;
+       default:
+         break;
        }
     }
 
Index: psppire/gtk_sheet/gtksheet.c
diff -u psppire/gtk_sheet/gtksheet.c:1.12 psppire/gtk_sheet/gtksheet.c:1.13
--- psppire/gtk_sheet/gtksheet.c:1.12   Fri Dec 23 23:34:03 2005
+++ psppire/gtk_sheet/gtksheet.c        Sat Jan 28 08:48:08 2006
@@ -1,3 +1,6 @@
+/* This version of GtkSheet has been heavily modified, for the specific 
+   requirements of PSPPIRE. */
+
 /* GtkSheet widget for Gtk+.
  * Copyright (C) 1999-2001 Adrian E. Feiguin <address@hidden>
  *
@@ -5,19 +8,18 @@
  * Memory allocation routines inspired on SC (Spreadsheet Calculator)
  *
  * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * 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.
+ * 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
- * 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.
+ * 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
  */
 /**
  * SECTION:gtksheet
@@ -56,6 +58,8 @@
 #include "gtkitementry.h"
 #include "gtksheet.h"
 #include "gtkextra-marshal.h"
+#include "gsheetmodel.h"
+
 
 /* sheet flags */
 enum
@@ -96,19 +100,12 @@
 #define CELLOFFSET 4
 #define DEFAULT_COLUMN_WIDTH 80
 
-static inline gint
-gtk_sheet_row_height(GtkSheet *sheet, gint row)
-{
-  return sheet->row[row].height;
-}
 
-static inline gint
-gtk_sheet_column_width(GtkSheet *sheet, gint col)
-{
-  return sheet->column[col].width;
-}
 
-static inline guint DEFAULT_ROW_HEIGHT(GtkWidget *widget) 
+
+
+static inline 
+guint DEFAULT_ROW_HEIGHT(GtkWidget *widget) 
 { 
   if(!widget->style->font_desc) return 24;
   else {
@@ -136,7 +133,7 @@
   }
 }
 static inline guint STRING_WIDTH(GtkWidget *widget,
-                                 PangoFontDescription *font, const gchar *text)
+                                 const PangoFontDescription *font, const gchar 
*text)
 {
   PangoRectangle rect;
   PangoLayout *layout;
@@ -164,12 +161,80 @@
   }
 }
 
+
+static gint
+yyy_row_is_visible(GtkSheet *sheet, gint row)
+{
+  GSheetRow *row_geo = sheet->row_geometry;
+
+  return g_sheet_row_get_visibility(row_geo, row, sheet);
+}
+
+
+static gint
+yyy_row_is_sensitive(GtkSheet *sheet, gint row)
+{
+  GSheetRow *row_geo = sheet->row_geometry;
+
+  return g_sheet_row_get_sensitivity(row_geo, row, sheet);
+}
+
+
+
+static inline gint
+yyy_row_count(const GtkSheet *sheet)
+{
+  GSheetRow *row_geo = sheet->row_geometry;
+
+  return g_sheet_row_get_row_count(row_geo, sheet);
+}
+
+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, sheet);
+}
+
+static gint
+yyy_row_top_ypixel(GtkSheet *sheet, gint row)
+{
+  GSheetRow *geo = sheet->row_geometry;
+
+  gint y = g_sheet_row_start_pixel(geo, row, sheet);
+
+  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(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, sheet);
+}
+
+
 /* gives the top pixel of the given row in context of
  * the sheet's voffset */
 static inline gint
-ROW_TOP_YPIXEL(GtkSheet *sheet, gint nrow)
+ROW_TOP_YPIXEL(GtkSheet *sheet, gint row)
 {
-   return (sheet->voffset + sheet->row[nrow].top_ypixel);
+  return (sheet->voffset + yyy_row_top_ypixel(sheet, row));
 }
 
 
@@ -178,21 +243,102 @@
 static inline gint 
 ROW_FROM_YPIXEL(GtkSheet *sheet, gint y)
 {
-  gint i, cy;
+  return (yyy_row_ypixel_to_row(sheet, y));
+}
+
+static inline const GtkSheetButton *
+xxx_column_button(GtkSheet *sheet, gint col)
+{
+  GSheetColumn *col_geo = sheet->column_geometry;
 
-  cy = sheet->voffset;
-  if(sheet->column_titles_visible) cy += sheet->column_title_area.height;
-  if(y < cy) return 0;
-  for (i = 0; i <= sheet->maxrow; i++)
-    {
-      if (y >= cy  && y <= (cy + sheet->row[i].height) && 
sheet->row[i].is_visible)
-       return i;
-      if(sheet->row[i].is_visible) cy += sheet->row[i].height;
+  return g_sheet_column_get_button(col_geo, col, sheet);
+}
 
-    }
 
-  /* no match */
-  return sheet->maxrow;
+static inline gint
+xxx_column_left_xpixel(GtkSheet *sheet, gint col)
+{
+  GSheetColumn *geo = sheet->column_geometry;
+
+  gint x = g_sheet_column_start_pixel(geo, col, sheet);
+
+  if ( sheet->row_titles_visible ) 
+    x += sheet->row_title_area.width;
+
+  return x;
+}
+
+static inline gint
+xxx_column_width(const GtkSheet *sheet, gint col)
+{
+  GSheetColumn *col_geo = sheet->column_geometry;
+
+  return g_sheet_column_get_width(col_geo, col, sheet);
+}
+
+
+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, sheet);
+}
+
+static inline void
+xxx_column_set_left_column(GtkSheet *sheet, gint col, gint i)
+{
+  GSheetColumn *col_geo = sheet->column_geometry;
+
+  g_sheet_column_set_left_text_column(col_geo, col, i, sheet);
+}
+
+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, sheet);
+}
+
+static inline void
+xxx_column_set_right_column(GtkSheet *sheet, gint col, gint i)
+{
+  GSheetColumn *col_geo = sheet->column_geometry;
+
+  g_sheet_column_set_right_text_column(col_geo, col, i, sheet);
+}
+
+static inline gint
+xxx_column_right_column(const GtkSheet *sheet, gint col)
+{
+  GSheetColumn *col_geo = sheet->column_geometry;
+
+  return g_sheet_column_get_right_text_column(col_geo, col, sheet);
+}
+
+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, sheet);
+}
+
+static inline gint
+xxx_column_is_visible(GtkSheet *sheet, gint col)
+{
+  GSheetColumn *col_geo = sheet->column_geometry;
+
+  return g_sheet_column_get_visibility(col_geo, col, sheet);
+}
+
+
+static inline gint
+xxx_column_is_sensitive(GtkSheet *sheet, gint col)
+{
+  GSheetColumn *col_geo = sheet->column_geometry;
+
+  return g_sheet_column_get_sensitivity(col_geo, col, sheet);
 }
 
 
@@ -201,7 +347,15 @@
 static inline gint
 COLUMN_LEFT_XPIXEL(GtkSheet *sheet, gint ncol)
 {
-   return (sheet->hoffset + sheet->column[ncol].left_xpixel);
+  return (sheet->hoffset + xxx_column_left_xpixel(sheet, ncol));
+}
+
+static inline gint
+xxx_column_count(const GtkSheet *sheet)
+{
+  GSheetColumn *col_geo = sheet->column_geometry;
+
+  return g_sheet_column_get_column_count(col_geo, sheet);
 }
 
 /* returns the column index from a x pixel location in the 
@@ -213,43 +367,62 @@
   gint i, cx;
 
   cx = sheet->hoffset;
-  if(sheet->row_titles_visible) cx += sheet->row_title_area.width;
+  if( sheet->row_titles_visible ) 
+    cx += sheet->row_title_area.width;
+
   if(x < cx) return 0;
-  for (i = 0; i <= sheet->maxcol; i++)
+  for (i = 0; i < xxx_column_count(sheet); i++)
     {
-      if (x >= cx  && x <= (cx + sheet->column[i].width) && 
sheet->column[i].is_visible)
+      if (x >= cx  && x <= (cx + xxx_column_width(sheet, i)) && 
+         xxx_column_is_visible(sheet, i))
        return i;
-      if(sheet->column[i].is_visible) cx += sheet->column[i].width;
-
+      if( xxx_column_is_visible(sheet, i))
+       cx += xxx_column_width(sheet, i);
     }
 
   /* no match */
-  return sheet->maxcol;
+  return xxx_column_count(sheet) - 1;
 }
 
 /* returns the total height of the sheet */
 static inline gint SHEET_HEIGHT(GtkSheet *sheet)
 {
-  gint i,cx;
- 
-  cx = 0;
-  if(sheet->column_titles_visible) cx += sheet->column_title_area.height;
-  for (i=0;i<=sheet->maxrow; i++)
-   if(sheet->row[i].is_visible) cx += sheet->row[i].height;
-  
-  return cx;
+  const gint n_rows = yyy_row_count(sheet);
+
+  return yyy_row_top_ypixel(sheet, n_rows - 1) + 
+    yyy_row_height(sheet, n_rows - 1);
+}
+
+
+static inline const GtkSheetButton *
+yyy_row_button(GtkSheet *sheet, gint row)
+{
+  GSheetRow *row_geo = sheet->row_geometry;
+
+  return g_sheet_row_get_button(row_geo, row, sheet);
 }
 
 
+
+
+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, sheet);
+}
+
+
+
 /* returns the total width of the sheet */
 static inline gint SHEET_WIDTH(GtkSheet *sheet)
 {
   gint i,cx;
+
+  cx = ( sheet->row_titles_visible ? sheet->row_title_area.width : 0);
  
-  cx = 0;
-  if(sheet->row_titles_visible) cx += sheet->row_title_area.width;
-  for (i=0;i<=sheet->maxcol; i++)
-   if(sheet->column[i].is_visible) cx += sheet->column[i].width;
+  for (i=0; i < xxx_column_count(sheet); i++)
+    if(xxx_column_is_visible(sheet, i)) cx += xxx_column_width(sheet, i);
   
   return cx;
 }
@@ -270,14 +443,14 @@
 
  xdrag=COLUMN_LEFT_XPIXEL(sheet,column)+CELL_SPACING;
  if(x <= xdrag+DRAG_WIDTH/2 && column != 0){
-   while(!sheet->column[column-1].is_visible && column>0) column--;
+   while(! xxx_column_is_visible(sheet, column-1) && column>0) column--;
    *drag_column=column-1;
-   return sheet->column[column-1].is_sensitive;
+   return xxx_column_is_sensitive(sheet, column-1);
  }
 
- xdrag+=sheet->column[column].width;
+ xdrag+= xxx_column_width(sheet, column);
  if(x >= xdrag-DRAG_WIDTH/2 && x <= xdrag+DRAG_WIDTH/2)
-   return sheet->column[column].is_sensitive;
+   return xxx_column_is_sensitive(sheet, column);
 
  return FALSE;
 } 
@@ -292,15 +465,15 @@
 
  ydrag=ROW_TOP_YPIXEL(sheet,row)+CELL_SPACING;
  if(y <= ydrag+DRAG_WIDTH/2 && row != 0){
-   while(!sheet->row[row-1].is_visible && row>0) row--;
+   while(!yyy_row_is_visible(sheet, row-1) && row>0) row--;
    *drag_row=row-1;
-   return sheet->row[row-1].is_sensitive;
+   return yyy_row_is_sensitive(sheet, row-1);
  }
 
- ydrag+=sheet->row[row].height;
+ ydrag+=yyy_row_height(sheet, row);
 
  if(y >= ydrag-DRAG_WIDTH/2 && y <= ydrag+DRAG_WIDTH/2)
-   return sheet->row[row].is_sensitive;
+   return yyy_row_is_sensitive(sheet, row);
  
  
  return FALSE;
@@ -316,14 +489,14 @@
 
   if(x>=COLUMN_LEFT_XPIXEL(sheet,sheet->range.col0)-DRAG_WIDTH/2 &&
      x<=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
-        sheet->column[sheet->range.coli].width+DRAG_WIDTH/2){
-     ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.row0);
+     xxx_column_width(sheet, sheet->range.coli) + DRAG_WIDTH/2){
+    ydrag=ROW_TOP_YPIXEL(sheet,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)+
-           sheet->row[sheet->range.rowi].height;
+           yyy_row_height(sheet, sheet->range.rowi);
      if(y>=ydrag-DRAG_WIDTH/2 && y<=ydrag+DRAG_WIDTH/2){
         *drag_row=sheet->range.rowi;
         return TRUE;
@@ -332,14 +505,14 @@
 
   if(y>=ROW_TOP_YPIXEL(sheet,sheet->range.row0)-DRAG_WIDTH/2 &&
      y<=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
-        sheet->row[sheet->range.rowi].height+DRAG_WIDTH/2){
+        yyy_row_height(sheet, sheet->range.rowi)+DRAG_WIDTH/2){
      xdrag=COLUMN_LEFT_XPIXEL(sheet,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)+
-           sheet->column[sheet->range.coli].width;
+           xxx_column_width(sheet, sheet->range.coli);
      if(x>=xdrag-DRAG_WIDTH/2 && x<=xdrag+DRAG_WIDTH/2){
         *drag_column=sheet->range.coli;
         return TRUE;
@@ -354,10 +527,10 @@
   gint xdrag, ydrag;
   
   xdrag=COLUMN_LEFT_XPIXEL(sheet,sheet->range.coli)+
-           sheet->column[sheet->range.coli].width;
+    xxx_column_width(sheet, sheet->range.coli);
 
   ydrag=ROW_TOP_YPIXEL(sheet,sheet->range.rowi)+
-           sheet->row[sheet->range.rowi].height;
+           yyy_row_height(sheet, sheet->range.rowi);
 
   if(sheet->state == GTK_SHEET_COLUMN_SELECTED) 
         ydrag = ROW_TOP_YPIXEL(sheet, sheet->view.row0);
@@ -523,33 +696,20 @@
 
 static void size_allocate_column_title_buttons         (GtkSheet * sheet);
 static void size_allocate_row_title_buttons    (GtkSheet * sheet);
-static void gtk_sheet_recalc_top_ypixels       (GtkSheet *sheet, 
-                                                gint row);
-static void gtk_sheet_recalc_left_xpixels      (GtkSheet *sheet, 
-                                                gint column);
-static void row_button_set                     (GtkSheet *sheet, 
-                                                gint row);
-static void column_button_set                  (GtkSheet *sheet, 
-                                                gint column);
-static void row_button_release                         (GtkSheet *sheet, 
-                                                gint row);
-static void column_button_release              (GtkSheet *sheet, 
-                                                gint column);
+
+
 static void gtk_sheet_button_draw              (GtkSheet *sheet, 
                                                 gint row, gint column);
 static void size_allocate_global_button        (GtkSheet *sheet);
 static void gtk_sheet_button_size_request      (GtkSheet *sheet,
-                                                GtkSheetButton *button, 
+                                                const GtkSheetButton *button, 
                                                 GtkRequisition *requisition);
 
 /* Attributes routines */
-
-static void gtk_sheet_set_cell_attributes      (GtkSheet *sheet, 
-                                                gint row, gint col,
-                                                GtkSheetCellAttr attributes);
-
 static void init_attributes                    (GtkSheet *sheet, gint col,  
                                                 GtkSheetCellAttr *attributes);
+
+
 /* Memory allocation routines */
 static void gtk_sheet_real_range_clear                 (GtkSheet *sheet, 
                                                 const GtkSheetRange *range, 
@@ -558,17 +718,7 @@
                                                 gint row,
                                                 gint column,
                                                 gboolean delete);
-static GtkSheetCell * gtk_sheet_cell_new       (void);
-static gint AddRow                             (GtkSheet *sheet, gint nrows);
-static gint AddColumn                          (GtkSheet *sheet, gint ncols);
-static gint InsertRow                          (GtkSheet *sheet, gint row, 
gint nrows);
-static gint InsertColumn                       (GtkSheet *sheet, gint col, 
gint ncols);
-static gint DeleteRow                          (GtkSheet *sheet, gint row, 
gint nrows);
-static gint DeleteColumn                       (GtkSheet *sheet, gint col, 
gint ncols);
-static gint GrowSheet                          (GtkSheet *sheet, 
-                                                gint newrows, gint newcols);
-static gint CheckBounds                                (GtkSheet *sheet, 
-                                                gint row, gint col);
+
 
 /* Container Functions */
 static void gtk_sheet_remove                   (GtkContainer *container,
@@ -900,6 +1050,9 @@
 static void 
 gtk_sheet_init (GtkSheet *sheet)
 {
+  sheet->column_geometry = NULL;
+  sheet->row_geometry = NULL;
+
   sheet->children = NULL;
 
   sheet->flags = 0;
@@ -910,17 +1063,11 @@
   GTK_WIDGET_UNSET_FLAGS (sheet, GTK_NO_WINDOW);
   GTK_WIDGET_SET_FLAGS (sheet, GTK_CAN_FOCUS);
 
-  sheet->maxrow = 0;
-  sheet->maxcol = 0;
-
   sheet->view.row0 = 0;
   sheet->view.col0 = 0;
   sheet->view.rowi = 0;
   sheet->view.coli = 0;
 
-  sheet->maxallocrow = 0;
-  sheet->maxalloccol = 0;
-
   sheet->column_title_window=NULL;
   sheet->column_title_area.x=0;
   sheet->column_title_area.y=0;
@@ -930,9 +1077,10 @@
   sheet->row_title_window=NULL;
   sheet->row_title_area.x=0;
   sheet->row_title_area.y=0;
-  sheet->row_title_area.width=DEFAULT_COLUMN_WIDTH;
+  sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
   sheet->row_title_area.height=0;
 
+
   sheet->active_cell.row=0;
   sheet->active_cell.col=0;
   sheet->selection_cell.row=0;
@@ -967,69 +1115,168 @@
   sheet->x_drag = 0;
   sheet->y_drag = 0;
 
-  gdk_color_white(gdk_colormap_get_system(), &sheet->bg_color);
+  gdk_color_parse("white", &sheet->bg_color);
+  gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
   gdk_color_parse("gray", &sheet->grid_color);
   gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
   sheet->show_grid = TRUE;
 }
 
+
+static void 
+rows_deleted_callback (GSheetModel *m, gint first_row, gint n_rows,
+                     gpointer data)
+{
+  GtkSheet *sheet = GTK_SHEET(data);
+
+  GtkSheetRange range;
+
+  range.row0 = first_row;
+  range.col0 = 0;
+  range.rowi = yyy_row_count(sheet) - 1;
+  range.coli = xxx_column_count(sheet) - 1;
+  
+  gtk_sheet_range_draw(sheet, &range);
+}
+
+/* 
+   If row0 or rowi are negative, then all rows will be updated.
+   If col0 or coli are negative, then all columns will be updated.
+*/
+static void 
+range_update_callback (GSheetModel *m, gint row0, gint col0, 
+     gint rowi, gint coli, gpointer data)
+{
+  GtkSheet *sheet = GTK_SHEET(data);
+
+  GtkSheetRange range;
+
+  range.row0 = row0;
+  range.col0 = col0;
+  range.rowi = rowi;
+  range.coli = coli;
+
+  if( ( row0 < 0  && col0 < 0 ) || ( rowi < 0  && coli < 0 ) )
+    {
+      gtk_sheet_range_draw(sheet, NULL);
+      return;
+    }
+  else if ( row0 < 0 || rowi < 0 )
+    {
+      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);
+    }
+  
+  gtk_sheet_range_draw(sheet, &range);
+}
+
+
+static void gtk_sheet_construct        (GtkSheet *sheet,
+                                GSheetRow *vgeo,
+                                GSheetColumn *hgeo,
+                                const gchar *title);
+
+
 /**
  * gtk_sheet_new:
  * @rows: initial number of rows
  * @columns: initial number of columns
  * @title: sheet title
+ * @model: the model to use for the sheet data
  *
  * Creates a new sheet widget with the given number of rows and columns.
  *
  * Returns: the new sheet widget
  */
 GtkWidget *
-gtk_sheet_new (guint rows, guint columns, const gchar *title)
+gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, const gchar *title,
+              GSheetModel *model)
 {
   GtkWidget *widget;
 
-  /* sanity check */
-  g_return_val_if_fail (columns >= MINCOLS, NULL);
-  g_return_val_if_fail (rows >= MINROWS, NULL);
-
   widget = gtk_type_new (gtk_sheet_get_type ());
 
-  gtk_sheet_construct(GTK_SHEET(widget), rows, columns, title);
+  gtk_sheet_construct(GTK_SHEET(widget), vgeo, hgeo, title);
+
+  if (model) 
+    gtk_sheet_set_model(GTK_SHEET(widget), model);
+
 
   return widget;
 }
 
+
+/**
+ * gtk_sheet_set_model
+ * @sheet: the sheet to set the model for
+ * @model: the model to use for the sheet data
+ *
+ * Sets the model for a GtkSheet
+ *
+ */
 void
-gtk_sheet_construct (GtkSheet *sheet, guint rows, guint columns, const gchar 
*title)
+gtk_sheet_set_model(GtkSheet *sheet, GSheetModel *model)
+{
+  g_return_if_fail (GTK_IS_SHEET (sheet));
+  g_return_if_fail (G_IS_SHEET_MODEL (model));
+
+  sheet->model = model;
+
+  g_signal_connect(model, "range_changed", 
+                  G_CALLBACK(range_update_callback), sheet);
+
+  g_signal_connect(model, "rows_deleted",
+                  G_CALLBACK(rows_deleted_callback), sheet);
+
+}
+
+
+
+static void
+column_titles_changed(GtkWidget *w, gint first, gint n_columns, gpointer data)
+{
+  GtkSheet *sheet = GTK_SHEET(data);
+
+
+  if(!GTK_SHEET_IS_FROZEN(sheet)){  
+    gint i;
+    for ( i = first ; i <= MAX_VISIBLE_COLUMN(sheet) ; ++i ) 
+      {
+       gtk_sheet_button_draw(sheet, -1, i);
+       gtk_signal_emit(GTK_OBJECT(sheet), sheet_signals[CHANGED], -1, i);
+      }
+  }
+}
+
+static void
+gtk_sheet_construct (GtkSheet *sheet, 
+                    GSheetRow *vgeo,
+                    GSheetColumn *hgeo,
+                    const gchar *title)
 {
-  sheet->row=(GtkSheetRow *)g_malloc(sizeof(GtkSheetRow));
-  sheet->column=(GtkSheetColumn *)g_malloc(sizeof(GtkSheetColumn));
-  sheet->data=(GtkSheetCell ***)g_malloc(sizeof(GtkSheetCell **));
+  g_return_if_fail(G_IS_SHEET_COLUMN(hgeo));
+  g_return_if_fail(G_IS_SHEET_ROW(vgeo));
 
-  sheet->data[0] = (GtkSheetCell **)g_malloc(sizeof(GtkSheetCell 
*)+sizeof(gdouble));
-  sheet->data[0][0] = NULL;
+  sheet->column_geometry = hgeo;
+  sheet->row_geometry = vgeo;
+  
 
   sheet->columns_resizable = TRUE;
   sheet->rows_resizable = TRUE;
+
   sheet->row_titles_visible = TRUE;
+  sheet->row_title_area.width = DEFAULT_COLUMN_WIDTH;
+
   sheet->column_titles_visible = TRUE;
   sheet->autoscroll = TRUE;
   sheet->justify_entry = TRUE;
   sheet->locked = FALSE;
-  sheet->encode_func = NULL;
-  sheet->decode_func = NULL;
-  sheet->coding_data = NULL;
-
-  /* set number of rows and columns */
-  GrowSheet(sheet, MINROWS, MINCOLS);
-
-  /* Init row an column zero */
-  AddRow(sheet,-1);
-  AddColumn(sheet,-1);
-
-  /* Add rows and columns */
-  AddRow(sheet,rows-1);
-  AddColumn(sheet,columns-1);
+
 
   /* create sheet entry */
   sheet->entry_type = 0;
@@ -1041,33 +1288,14 @@
   if(title)
      sheet->name = g_strdup(title);
 
-}
-
-
-GtkWidget *
-gtk_sheet_new_browser(guint rows, guint columns, const gchar *title)
-{
-  GtkWidget *widget;
-  
-  widget = gtk_type_new (gtk_sheet_get_type ());
+  g_signal_connect(sheet->column_geometry, "columns_changed", 
+                  G_CALLBACK(column_titles_changed), sheet);
 
-  gtk_sheet_construct_browser(GTK_SHEET(widget), rows, columns, title);
- 
-  return widget;
 }
 
-void
-gtk_sheet_construct_browser(GtkSheet *sheet, guint rows, guint columns, 
-                           const gchar *title)
-{
-  gtk_sheet_construct(sheet, rows, columns, title);
-
-  gtk_sheet_set_locked(sheet, TRUE);
-  sheet->autoresize = TRUE;
-}
 
 GtkWidget *
-gtk_sheet_new_with_custom_entry (guint rows, guint columns, const gchar *title,
+gtk_sheet_new_with_custom_entry (GSheetRow *rows, GSheetColumn *columns, const 
gchar *title,
                                  GtkType entry_type)
 {
   GtkWidget *widget;
@@ -1082,17 +1310,19 @@
 
 void
 gtk_sheet_construct_with_custom_entry (GtkSheet *sheet, 
-                                      guint rows, guint columns, 
+                                      GSheetRow *vgeo,
+                                      GSheetColumn *hgeo,
                                       const gchar *title,
                                       GtkType entry_type)
 {
-  gtk_sheet_construct(sheet, rows, columns, title);
+  gtk_sheet_construct(sheet, vgeo, hgeo, title);
 
   sheet->entry_type = entry_type;
   create_sheet_entry(sheet);
 }
 
 
+
 void
 gtk_sheet_change_entry(GtkSheet *sheet, GtkType entry_type)
 {
@@ -1113,10 +1343,12 @@
   if(state == GTK_SHEET_NORMAL)
     {
       gtk_sheet_show_active_cell(sheet); 
-      gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
-                         "changed",
-                         (GtkSignalFunc)gtk_sheet_entry_changed,
-                         GTK_OBJECT(GTK_WIDGET(sheet)));
+      g_signal_connect(G_OBJECT(gtk_sheet_get_entry(sheet)),
+                        "changed",
+                        G_CALLBACK(gtk_sheet_entry_changed),
+                        sheet);
+
+
     }
  
 }
@@ -1150,9 +1382,10 @@
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  if(!color)
-    gdk_color_white(gdk_colormap_get_system(), &sheet->bg_color);
-  else
+  if(!color) {
+    gdk_color_parse("white", &sheet->bg_color);
+    gdk_color_alloc(gdk_colormap_get_system(), &sheet->bg_color);
+  } else
     sheet->bg_color = *color;
 
   if(!GTK_SHEET_IS_FROZEN(sheet)) 
@@ -1165,9 +1398,10 @@
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  if(!color)
-    gdk_color_black(gdk_colormap_get_system(), &sheet->grid_color);
-  else
+  if(!color){
+    gdk_color_parse("black", &sheet->grid_color);
+    gdk_color_alloc(gdk_colormap_get_system(), &sheet->grid_color);
+  }else
     sheet->grid_color = *color;
 
   if(!GTK_SHEET_IS_FROZEN(sheet)) 
@@ -1175,25 +1409,25 @@
 }
 
 guint
-gtk_sheet_get_columns_count(const GtkSheet *sheet)
+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 sheet->maxcol + 1;
+  return xxx_column_count(sheet);
 }
 
 guint
-gtk_sheet_get_rows_count(const GtkSheet *sheet)
+gtk_sheet_get_rows_count(GtkSheet *sheet)
 {
   g_return_val_if_fail (sheet != NULL, 0);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
 
-  return sheet->maxrow + 1;
+  return yyy_row_count(sheet);
 }
 
 gint
-gtk_sheet_get_state(const GtkSheet *sheet)
+gtk_sheet_get_state(GtkSheet *sheet)
 {
   g_return_val_if_fail (sheet != NULL, 0);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
@@ -1231,6 +1465,47 @@
   return sheet->autoresize;
 }
 
+static void
+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;
+
+  g_print("%s:%d Iterating rows\n",__FILE__, __LINE__);
+  for (row = 0; row < yyy_row_count(sheet); row++){
+    const 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);
+      }
+    }
+  }
+
+  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)
 {
@@ -1408,10 +1683,10 @@
  if(width < COLUMN_MIN_WIDTH) return;
 
  sheet->row_title_area.width = width;
- sheet->view.col0=COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
- sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
- gtk_sheet_recalc_top_ypixels(sheet, 0);
- gtk_sheet_recalc_left_xpixels(sheet, 0);
+ sheet->view.col0 = COLUMN_FROM_XPIXEL(sheet, sheet->row_title_area.width+1);
+ sheet->view.coli = COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
+
+
  adjust_scrollbars(sheet);
 
  sheet->old_hadjustment = -1.;
@@ -1429,8 +1704,7 @@
  sheet->column_title_area.height = height;
  sheet->view.row0=ROW_FROM_YPIXEL(sheet, sheet->column_title_area.height+1);
  sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
- gtk_sheet_recalc_top_ypixels(sheet, 0);
- gtk_sheet_recalc_left_xpixels(sheet, 0);
+
  adjust_scrollbars(sheet);
 
  sheet->old_vadjustment = -1.;
@@ -1448,8 +1722,8 @@
  if(sheet->column_titles_visible) return;
 
  sheet->column_titles_visible = TRUE;
- gtk_sheet_recalc_top_ypixels(sheet, 0);
- gtk_sheet_recalc_left_xpixels(sheet, 0);
+
+
  if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
   gdk_window_show(sheet->column_title_window);
   gdk_window_move_resize (sheet->column_title_window,
@@ -1458,13 +1732,15 @@
                           sheet->column_title_area.width,
                           sheet->column_title_area.height);
 
-  for(col = MIN_VISIBLE_COLUMN(sheet); col <= MAX_VISIBLE_COLUMN(sheet); 
col++){
-    GtkSheetChild *child;
-    child = sheet->column[col].button.child;
-    if(child){
+  for(col = MIN_VISIBLE_COLUMN(sheet); 
+      col <= MAX_VISIBLE_COLUMN(sheet); 
+      col++)
+    {
+      const GtkSheetButton *button = xxx_column_button(sheet, col);
+      GtkSheetChild *child = button->child;
+      if(child)
         gtk_sheet_child_show(child);
     }
-  }
   adjust_scrollbars(sheet);
  } 
 
@@ -1475,6 +1751,7 @@
  size_allocate_global_button(sheet);
 }
 
+
 void
 gtk_sheet_show_row_titles(GtkSheet *sheet)
 {
@@ -1483,8 +1760,8 @@
  if(sheet->row_titles_visible) return;
 
  sheet->row_titles_visible = TRUE;
- gtk_sheet_recalc_top_ypixels(sheet, 0);
- gtk_sheet_recalc_left_xpixels(sheet, 0);
+
+
  if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
   gdk_window_show(sheet->row_title_window);
   gdk_window_move_resize (sheet->row_title_window,
@@ -1493,12 +1770,16 @@
                           sheet->row_title_area.width,
                           sheet->row_title_area.height);
 
-  for(row = MIN_VISIBLE_ROW(sheet); row <= MAX_VISIBLE_ROW(sheet); row++){
-    GtkSheetChild *child;
-    child = sheet->row[row].button.child;
-    if(child){
-        gtk_sheet_child_show(child);
-    }
+  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);
  }
@@ -1518,20 +1799,21 @@
  if(!sheet->column_titles_visible) return;
 
  sheet->column_titles_visible = FALSE;
- gtk_sheet_recalc_top_ypixels(sheet, 0);
- gtk_sheet_recalc_left_xpixels(sheet, 0);
+
  if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))){
   if(sheet->column_title_window) 
     gdk_window_hide(sheet->column_title_window);
   if(GTK_WIDGET_VISIBLE(sheet->button)) 
     gtk_widget_hide(sheet->button);
 
-  for(col = MIN_VISIBLE_COLUMN(sheet); col <= MAX_VISIBLE_COLUMN(sheet); 
col++){
-    GtkSheetChild *child;
-    child = sheet->column[col].button.child;
-    if(child){
+  for(col = MIN_VISIBLE_COLUMN(sheet); 
+      col <= MAX_VISIBLE_COLUMN(sheet); 
+      col++)
+    {
+      const GtkSheetButton *button = xxx_column_button(sheet, col);
+      GtkSheetChild *child = button->child;
+      if(child)
         gtk_sheet_child_hide(child);
-    }
   }
   adjust_scrollbars(sheet);
  }
@@ -1550,20 +1832,23 @@
  if(!sheet->row_titles_visible) return;
 
  sheet->row_titles_visible = FALSE;
- gtk_sheet_recalc_top_ypixels(sheet, 0);
- gtk_sheet_recalc_left_xpixels(sheet, 0);
+
+
  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++){
-    GtkSheetChild *child;
-    child = sheet->row[row].button.child;
-    if(child){
+  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);
  }
 
@@ -1589,239 +1874,6 @@
   return sheet->row_titles_visible;
 }
 
-void
-gtk_sheet_set_column_title (GtkSheet * sheet,
-                           gint column,
-                           const gchar * title)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if (sheet->column[column].name)
-    g_free (sheet->column[column].name);
-
-  sheet->column[column].name = g_strdup(title);
-}
-
-void
-gtk_sheet_set_row_title (GtkSheet * sheet,
-                        gint row,
-                        const gchar * title)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if (sheet->row[row].name)
-    g_free (sheet->row[row].name);
-
-  sheet->row[row].name = g_strdup (title);
-}
-
-const gchar *
-gtk_sheet_get_row_title (GtkSheet * sheet,
-                        gint row)
-{
-  g_return_val_if_fail (sheet != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
-
-  return(sheet->row[row].name);
-}
-
-const gchar *
-gtk_sheet_get_column_title (GtkSheet * sheet,
-                           gint column)
-{
-  g_return_val_if_fail (sheet != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
-
-  return(sheet->column[column].name);
-}
-
-void
-gtk_sheet_row_button_add_label(GtkSheet *sheet, gint row, const gchar *label)
-{
-  GtkSheetButton *button;
-  GtkRequisition req;
-  gboolean aux;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(row < 0 || row > sheet->maxrow) return;
-
-  button = &sheet->row[row].button;
-  if (button->label) g_free (button->label);
-  button->label = g_strdup (label);
-
-  aux = gtk_sheet_autoresize(sheet);
-  gtk_sheet_set_autoresize(sheet, TRUE);
-  gtk_sheet_button_size_request(sheet, button, &req);
-  gtk_sheet_set_autoresize(sheet, aux);
-
-  if(req.height > sheet->row[row].height)
-     gtk_sheet_set_row_height(sheet, row, req.height);
-
-  if(req.width > sheet->row_title_area.width){
-     gtk_sheet_set_row_titles_width(sheet, req.width);
-  }
-
-  if(!GTK_SHEET_IS_FROZEN(sheet)){
-    gtk_sheet_button_draw(sheet, row, -1);
-    gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, -1);
-  }
-}  
-
-const gchar *
-gtk_sheet_row_button_get_label(GtkSheet *sheet, gint row)
-{
-  g_return_val_if_fail (sheet != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
-
-  if(row < 0 || row > sheet->maxrow) return NULL;
-
-  return (sheet->row[row].button.label);
-}
-
-void
-gtk_sheet_row_label_set_visibility(GtkSheet *sheet, gint row, gboolean visible)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(row < 0 || row > sheet->maxrow) return;
-
-  sheet->row[row].button.label_visible = visible;
-
-  if(!GTK_SHEET_IS_FROZEN(sheet)){  
-    gtk_sheet_button_draw(sheet, row, -1);
-    gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, -1);
-  }
-}
-
-void
-gtk_sheet_rows_labels_set_visibility(GtkSheet *sheet, gboolean visible)
-{
-  gint i;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  for(i = 0; i <= sheet->maxrow; i++)
-    gtk_sheet_row_label_set_visibility(sheet, i, visible);
-}
-
-
-void
-gtk_sheet_column_button_add_label(GtkSheet *sheet, gint column, const gchar 
*label)
-{
-  GtkSheetButton *button;
-  GtkRequisition req;
-  gboolean aux;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(column < 0 || column >sheet->maxcol) return;
-
-  button = &sheet->column[column].button;
-  if (button->label) g_free (button->label);
-  button->label = g_strdup (label);
-
-  aux = gtk_sheet_autoresize(sheet);
-  gtk_sheet_set_autoresize(sheet, TRUE);
-  gtk_sheet_button_size_request(sheet, button, &req);
-  gtk_sheet_set_autoresize(sheet, aux);
-
-  if(req.width > sheet->column[column].width)
-     gtk_sheet_set_column_width(sheet, column, req.width);
-
-  if(req.height > sheet->column_title_area.height)
-     gtk_sheet_set_column_titles_height(sheet, req.height);
-
-  if(!GTK_SHEET_IS_FROZEN(sheet)){
-    gtk_sheet_button_draw(sheet, -1, column);
-    gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, column);
-  }
-}  
-
-const gchar *
-gtk_sheet_column_button_get_label(GtkSheet *sheet, gint column)
-{
-  g_return_val_if_fail (sheet != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
-
-  if(column < 0 || column >sheet->maxcol) return NULL;
-
-  return(sheet->column[column].button.label);
-}
-
-void
-gtk_sheet_column_label_set_visibility(GtkSheet *sheet, gint col, gboolean 
visible)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(col < 0 || col > sheet->maxcol) return;
-
-  sheet->column[col].button.label_visible = visible;
-
-  if(!GTK_SHEET_IS_FROZEN(sheet)){  
-    gtk_sheet_button_draw(sheet, -1, col);
-    gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, col);
-  }
-}
-
-void
-gtk_sheet_columns_labels_set_visibility(GtkSheet *sheet, gboolean visible)
-{
-  gint i;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  for(i = 0; i <= sheet->maxcol; i++)
-    gtk_sheet_column_label_set_visibility(sheet, i, visible);
-}
-
-void
-gtk_sheet_row_button_justify(GtkSheet *sheet, gint row, 
-                             GtkJustification justification)
-{
-  GtkSheetButton *button;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(row < 0 || row > sheet->maxrow) return;
-
-  button = &sheet->row[row].button;
-  button->justification = justification;
-
-  if(!GTK_SHEET_IS_FROZEN(sheet)){  
-    gtk_sheet_button_draw(sheet, row, -1);
-    gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, -1);
-  }
-}  
-
-void
-gtk_sheet_column_button_justify(GtkSheet *sheet, gint column, 
-                                GtkJustification justification)
-{
-  GtkSheetButton *button;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(column < 0 || column > sheet->maxcol) return;
-
-  button = &sheet->column[column].button;
-  button->justification = justification;
-
-  if(!GTK_SHEET_IS_FROZEN(sheet)){  
-    gtk_sheet_button_draw(sheet, -1, column);
-    gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], -1, column);
-  }
-}  
 
 
 void
@@ -1841,9 +1893,9 @@
   g_return_if_fail (sheet->hadjustment != NULL);
   g_return_if_fail (sheet->vadjustment != NULL);
 
-  if (row < 0 || row > sheet->maxrow)
+  if (row < 0 || row >= yyy_row_count(sheet))
     return;
-  if (column < 0 || column > sheet->maxcol)
+  if (column < 0 || column >= xxx_column_count(sheet))
     return;
 
   height = sheet->sheet_window_height;
@@ -1853,17 +1905,21 @@
 
   if (row >= 0 && row_align >=0.)
     {
+/*
       y = ROW_TOP_YPIXEL(sheet, row) - sheet->voffset -
           row_align*height-
-          (1.-row_align)*sheet->row[row].height;
+          (1.-row_align)*yyy_row_height(sheet, row);
+*/
+      y = ROW_TOP_YPIXEL (sheet, row) - sheet->voffset
+        - (gint) ( row_align*height + (1. - 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.){
         while(min_row >= 0 && min_row > MIN_VISIBLE_ROW(sheet)){
-         if(sheet->row[min_row].is_visible) 
-                adjust += sheet->row[min_row].height;
+         if(yyy_row_is_visible(sheet, min_row))
+                adjust += yyy_row_height(sheet, min_row);
          if(adjust >= height){
            break;
          }
@@ -1871,7 +1927,7 @@
         }
         min_row = MAX(min_row, 0);
         y = ROW_TOP_YPIXEL(sheet, min_row) - sheet->voffset +
-            sheet->row[min_row].height - 1;
+            yyy_row_height(sheet, min_row) - 1;
       }
 
       if (y < 0)
@@ -1888,17 +1944,24 @@
   /* adjust horizontal scrollbar */
   if (column >= 0 && col_align >= 0.)
     {
+/*
       x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset -
           col_align*width -
           (1.-col_align)*sheet->column[column].width;
+*/
+      x = COLUMN_LEFT_XPIXEL (sheet, column) - sheet->hoffset
+        - (gint) ( col_align*width + (1.-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.){
         while(min_col >= 0 && min_col > MIN_VISIBLE_COLUMN(sheet)){
-         if(sheet->column[min_col].is_visible) 
-                adjust += sheet->column[min_col].width;
+         if(xxx_column_is_visible(sheet, min_col))
+          adjust += xxx_column_width(sheet, min_col);
+        
          if(adjust >= width){
            break;
          }
@@ -1906,7 +1969,7 @@
         }
         min_col = MAX(min_col, 0);
         x = COLUMN_LEFT_XPIXEL(sheet, min_col) - sheet->hoffset +
-            sheet->column[min_col].width - 1;
+         xxx_column_width(sheet, min_col) - 1;
       }
 
       if (x < 0)
@@ -1921,36 +1984,6 @@
     }
 }
 
-void 
-gtk_sheet_column_set_sensitivity(GtkSheet *sheet, gint column, gboolean 
sensitive)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(column < 0 || column > sheet->maxcol) return;
-
-  sheet->column[column].is_sensitive=sensitive;
-  if(!sensitive)
-     sheet->column[column].button.state=GTK_STATE_INSENSITIVE;
-  else
-     sheet->column[column].button.state=GTK_STATE_NORMAL;
-
-  if(GTK_WIDGET_REALIZED(sheet) && !GTK_SHEET_IS_FROZEN(sheet))
-      gtk_sheet_button_draw(sheet, -1, column);
-}
-
-
-void
-gtk_sheet_columns_set_sensitivity(GtkSheet *sheet, gboolean sensitive)
-{
-  gint i;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  for(i=0; i<=sheet->maxcol; i++)
-     gtk_sheet_column_set_sensitivity(sheet, i, sensitive);
-}
 
 void
 gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable)
@@ -1970,37 +2003,6 @@
   return sheet->columns_resizable;
 }
 
-void 
-gtk_sheet_row_set_sensitivity(GtkSheet *sheet, gint row,  gboolean sensitive)
-{
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(row < 0 || row > sheet->maxrow) return;
-
-  sheet->row[row].is_sensitive=sensitive;
-  if(!sensitive)
-     sheet->row[row].button.state=GTK_STATE_INSENSITIVE;
-  else
-     sheet->row[row].button.state=GTK_STATE_NORMAL;
-
-  if(GTK_WIDGET_REALIZED(sheet) && !GTK_SHEET_IS_FROZEN(sheet))
-      gtk_sheet_button_draw(sheet, row, -1);
-}
-
-void
-gtk_sheet_rows_set_sensitivity(GtkSheet *sheet, gboolean sensitive)
-{
-  gint i;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  for(i=0; i<=sheet->maxrow; i++)
-     gtk_sheet_row_set_sensitivity(sheet, i, sensitive);
-}
-
 
 void
 gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable)
@@ -2020,45 +2022,6 @@
   return sheet->rows_resizable;
 }
 
-void
-gtk_sheet_column_set_visibility(GtkSheet *sheet, gint column, gboolean visible)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(column < 0 || column > sheet->maxcol) return;
-  if(sheet->column[column].is_visible == visible) return;
-
-  sheet->column[column].is_visible = visible;
-
-  gtk_sheet_recalc_left_xpixels(sheet, column);
-
-  if(!GTK_SHEET_IS_FROZEN(sheet) && 
-    gtk_sheet_cell_isvisible(sheet, MIN_VISIBLE_ROW(sheet), column)){
-      gtk_sheet_range_draw(sheet, NULL);
-      size_allocate_column_title_buttons(sheet);
-  }
-}
-
-void
-gtk_sheet_row_set_visibility(GtkSheet *sheet, gint row, gboolean visible)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(row < 0 || row > sheet->maxrow) return;
-  if(sheet->row[row].is_visible == visible) return;
-
-  sheet->row[row].is_visible = visible;
-
-  gtk_sheet_recalc_top_ypixels(sheet, row);
-
-  if(!GTK_SHEET_IS_FROZEN(sheet) && 
-    gtk_sheet_cell_isvisible(sheet, row, MIN_VISIBLE_COLUMN(sheet))){
-      gtk_sheet_range_draw(sheet, NULL);
-      size_allocate_row_title_buttons(sheet);
-  }
-}
 
 void
 gtk_sheet_select_row (GtkSheet * sheet,
@@ -2067,7 +2030,7 @@
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  if (row < 0 || row > sheet->maxrow)
+  if (row < 0 || row >= yyy_row_count(sheet))
     return;
 
   if(sheet->state != GTK_SHEET_NORMAL) 
@@ -2083,7 +2046,7 @@
   sheet->range.row0=row;
   sheet->range.col0=0;
   sheet->range.rowi=row;
-  sheet->range.coli=sheet->maxcol;
+  sheet->range.coli = xxx_column_count(sheet) - 1;
   sheet->active_cell.row=row;
   sheet->active_cell.col=0;
 
@@ -2101,7 +2064,7 @@
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  if (column < 0 || column > sheet->maxcol)
+  if (column < 0 || column >= xxx_column_count(sheet))
     return;
 
   if(sheet->state != GTK_SHEET_NORMAL) 
@@ -2116,7 +2079,7 @@
   sheet->state=GTK_SHEET_COLUMN_SELECTED;                     
   sheet->range.row0=0;
   sheet->range.col0=column;
-  sheet->range.rowi=sheet->maxrow;
+  sheet->range.rowi= yyy_row_count(sheet) - 1;
   sheet->range.coli=column;
   sheet->active_cell.row=0;
   sheet->active_cell.col=column;
@@ -2196,9 +2159,9 @@
   x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
   y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
   width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+ 
-             sheet->column[sheet->clip_range.coli].width-1;
+    xxx_column_width(sheet, sheet->clip_range.coli) - 1;
   height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
-             sheet->row[sheet->clip_range.rowi].height-1;
+    yyy_row_height(sheet, sheet->clip_range.rowi)-1;
 
   clip_area.x=COLUMN_LEFT_XPIXEL(sheet, MIN_VISIBLE_COLUMN(sheet));
   clip_area.y=ROW_TOP_YPIXEL(sheet, MIN_VISIBLE_ROW(sheet));
@@ -2276,9 +2239,9 @@
   x=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.col0)+1;
   y=ROW_TOP_YPIXEL(sheet,sheet->clip_range.row0)+1;
   width=COLUMN_LEFT_XPIXEL(sheet,sheet->clip_range.coli)-x+ 
-             sheet->column[sheet->clip_range.coli].width-1;
+    xxx_column_width(sheet, sheet->clip_range.coli) - 1;
   height=ROW_TOP_YPIXEL(sheet,sheet->clip_range.rowi)-y+
-             sheet->row[sheet->clip_range.rowi].height-1;
+             yyy_row_height(sheet, sheet->clip_range.rowi)-1;
 
   if(x<0) {
      width=width+x+1;
@@ -2309,16 +2272,16 @@
 {
   g_return_val_if_fail (sheet != NULL, FALSE);
 
-  if (range.row0 < 0 || range.row0 > sheet->maxrow)
+  if (range.row0 < 0 || range.row0 >= yyy_row_count(sheet))
     return FALSE;
 
-  if (range.rowi < 0 || range.rowi > sheet->maxrow)
+  if (range.rowi < 0 || range.rowi >= yyy_row_count(sheet))
     return FALSE;
 
-  if (range.col0 < 0 || range.col0 > sheet->maxcol)
+  if (range.col0 < 0 || range.col0 >= xxx_column_count(sheet))
     return FALSE;
 
-  if (range.coli < 0 || range.coli > sheet->maxcol)
+  if (range.coli < 0 || range.coli >= xxx_column_count(sheet))
     return FALSE;
 
   if (range.rowi < MIN_VISIBLE_ROW (sheet))
@@ -2351,7 +2314,7 @@
 }
 
 void 
-gtk_sheet_get_visible_range(const GtkSheet *sheet, GtkSheetRange *range)
+gtk_sheet_get_visible_range(GtkSheet *sheet, GtkSheetRange *range)
 {
 
   g_return_if_fail (sheet != NULL);
@@ -2500,19 +2463,6 @@
   gtk_sheet_range_clear (sheet, NULL);
   gtk_sheet_range_delete(sheet, NULL);
 
-  gtk_sheet_delete_rows (sheet, 0, sheet->maxrow + 1);
-  gtk_sheet_delete_columns (sheet, 0, sheet->maxcol + 1);
-
-  DeleteRow (sheet, 0, sheet->maxrow + 1);
-  DeleteColumn (sheet, 0, sheet->maxcol + 1);
-
-  g_free(sheet->row);
-  sheet->row = NULL;
-  g_free(sheet->column);
-  sheet->column = NULL;
-  g_free(sheet->data);
-  sheet->data = NULL;
-
   if(sheet->name){
       g_free(sheet->name);
       sheet->name = NULL;
@@ -2688,6 +2638,8 @@
   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);
+
   gdk_window_set_background (sheet->sheet_window, &widget->style->white);
   gdk_window_show (sheet->sheet_window);
 
@@ -2966,10 +2918,10 @@
   /* bail now if we arn't drawable yet */
   if (!GTK_WIDGET_DRAWABLE (sheet)) return;
 
-  if (row < 0 || row > sheet->maxrow) return;
-  if (col < 0 || col > sheet->maxcol) return;
-  if (!sheet->column[col].is_visible) return;
-  if (!sheet->row[row].is_visible) 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);
 
@@ -2984,8 +2936,8 @@
 
   area.x=COLUMN_LEFT_XPIXEL(sheet,col);
   area.y=ROW_TOP_YPIXEL(sheet,row);
-  area.width=sheet->column[col].width;
-  area.height=sheet->row[row].height;
+  area.width= xxx_column_width(sheet, col);
+  area.height=yyy_row_height(sheet, row);
 
   gdk_draw_rectangle (sheet->pixmap,
                      bg_gc,
@@ -3022,10 +2974,10 @@
   /* bail now if we arn't drawable yet */
   if (!GTK_WIDGET_DRAWABLE (sheet)) return;
 
-  if (row < 0 || row > sheet->maxrow) return;
-  if (col < 0 || col > sheet->maxcol) return;
-  if (!sheet->column[col].is_visible) return;
-  if (!sheet->row[row].is_visible) 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);
 
@@ -3040,8 +2992,8 @@
 
   area.x=COLUMN_LEFT_XPIXEL(sheet,col);
   area.y=ROW_TOP_YPIXEL(sheet,row);
-  area.width=sheet->column[col].width;
-  area.height=sheet->row[row].height;
+  area.width=xxx_column_width(sheet, col);
+  area.height=yyy_row_height(sheet, row);
 
   width = attributes.border.width;
   gdk_gc_set_line_attributes(sheet->fg_gc, attributes.border.width,
@@ -3096,7 +3048,7 @@
   PangoContext *context = gtk_widget_get_pango_context(GTK_WIDGET(sheet)); 
   gint ascent, descent, y_pos;
 
-
+  const gchar *label;
 
   g_return_if_fail (sheet != NULL);
 
@@ -3104,19 +3056,14 @@
    if (!GTK_WIDGET_DRAWABLE (sheet))
     return;
 
-  if (row > sheet->maxallocrow) return;
-  if (col > sheet->maxalloccol) return;
-  if (!sheet->data[row]) return;
-  if (!sheet->data[row][col]) return;
-
-  const gchar *label = gtk_sheet_cell_get_text(sheet, row, col);
-  if (!label || strlen(label)==0)
+  label = gtk_sheet_cell_get_text(sheet, row, col);
+  if (!label)
       return;
 
-  if (row < 0 || row > sheet->maxrow) return;
-  if (col < 0 || col > sheet->maxcol) return;
-  if (!sheet->column[col].is_visible) return;
-  if (!sheet->row[row].is_visible) 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);
@@ -3132,8 +3079,8 @@
 
   area.x=COLUMN_LEFT_XPIXEL(sheet,col);
   area.y=ROW_TOP_YPIXEL(sheet,row);
-  area.width=sheet->column[col].width;
-  area.height=sheet->row[row].height;
+  area.width  = xxx_column_width(sheet, col);
+  area.height = yyy_row_height(sheet, row);
 
   clip_area = area;
 
@@ -3179,8 +3126,10 @@
            for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
              if(gtk_sheet_cell_get_text(sheet, row, i)) break;
              if(size>=text_width+CELLOFFSET) break;
-             size+=sheet->column[i].width;
-             sheet->column[i].right_text_column = MAX(col, 
sheet->column[i].right_text_column);
+             size+=xxx_column_width(sheet, i);
+            xxx_column_set_right_column(sheet, i, 
+                                        MAX(col,
+                                            xxx_column_right_column(sheet, 
i)));
            }
            area.width=size;
           }
@@ -3196,14 +3145,19 @@
            for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
              if(gtk_sheet_cell_get_text(sheet, row, i)) break;
              if(sizer>=text_width/2) break;
-             sizer+=sheet->column[i].width;
-             sheet->column[i].left_text_column = MIN(col, 
sheet->column[i].left_text_column);
+             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_get_text(sheet, row, i)) break;
              if(sizel>=text_width/2) break;
-             sizel+=sheet->column[i].width;
-             sheet->column[i].right_text_column = MAX(col, 
sheet->column[i].right_text_column);
+             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);
           }
@@ -3218,8 +3172,12 @@
            for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
              if(gtk_sheet_cell_get_text(sheet, row, i)) break;
              if(size>=text_width+CELLOFFSET) break;
-             size+=sheet->column[i].width;
-             sheet->column[i].left_text_column = MIN(col, 
sheet->column[i].left_text_column);
+             size+=xxx_column_width(sheet, i);
+            xxx_column_set_left_column(sheet, i, 
+                                       MIN(
+                                           col, 
+                                           xxx_column_left_column(sheet, i)));
+
            }
            area.width=size;
           }
@@ -3289,33 +3247,40 @@
    drawing_range.coli=MIN(range->coli, MAX_VISIBLE_COLUMN(sheet));
  }
 
- if(drawing_range.coli == sheet->maxcol){
-  area.x=COLUMN_LEFT_XPIXEL(sheet,sheet->maxcol)+
-         sheet->column[sheet->maxcol].width+1;
-  area.y=0;
-
-  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_pixmap(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);                  
- }
- if(drawing_range.rowi == sheet->maxrow){
+ 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;
+
+     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_pixmap(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);                  
+   }
+ 
+ if(drawing_range.rowi == yyy_row_count(sheet) - 1){
   area.x=0;
-  
area.y=ROW_TOP_YPIXEL(sheet,sheet->maxrow)+sheet->row[sheet->maxrow].height+1;
+  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);
 
@@ -3353,21 +3318,18 @@
 
  for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
   for(j=drawing_range.col0; j<=drawing_range.coli; j++)
-     if(i<=sheet->maxallocrow && j<=sheet->maxalloccol &&
-        sheet->data[i] && sheet->data[i][j])
                   gtk_sheet_cell_draw_label (sheet, i, j);
      
  for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
-  for(j=sheet->column[drawing_range.col0].left_text_column; 
j<drawing_range.col0; j++)
-     if(i<=sheet->maxallocrow && j<=sheet->maxalloccol && 
-        sheet->data[i] && sheet->data[i][j])
-                  gtk_sheet_cell_draw_label (sheet, i, j);
+   for(j= xxx_column_left_column(sheet, drawing_range.col0);
+       j<drawing_range.col0; j++)
+     gtk_sheet_cell_draw_label (sheet, i, j);
     
  for(i=drawing_range.row0; i<=drawing_range.rowi; i++)
-  for(j=drawing_range.coli+1; 
j<=sheet->column[drawing_range.coli].right_text_column; j++)
-     if(i<=sheet->maxallocrow && j<=sheet->maxalloccol && 
-        sheet->data[i] && sheet->data[i][j])
-                  gtk_sheet_cell_draw_label (sheet, i, j); 
+   for(j = drawing_range.coli+1; 
+       j <= xxx_column_right_column(sheet, drawing_range.coli);
+       j++)
+     gtk_sheet_cell_draw_label (sheet, i, j); 
 
   gtk_sheet_draw_backing_pixmap(sheet, drawing_range);
 
@@ -3413,15 +3375,17 @@
    for(j=range.col0; j<=range.coli; j++){
 
     if(gtk_sheet_cell_get_state(sheet, i, j)==GTK_STATE_SELECTED && 
-       sheet->column[j].is_visible && sheet->row[i].is_visible){
+       xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
 
+#if 0
       row_button_set(sheet, i);
       column_button_set(sheet, j);
+#endif
 
       area.x=COLUMN_LEFT_XPIXEL(sheet,j);
       area.y=ROW_TOP_YPIXEL(sheet,i);
-      area.width=sheet->column[j].width;
-      area.height=sheet->row[i].height;
+      area.width= xxx_column_width(sheet, j);
+      area.height=yyy_row_height(sheet, i);
 
       if(i==sheet->range.row0){
             area.y=area.y+2;
@@ -3454,13 +3418,15 @@
 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+sheet->column[range.coli].width;
-  height=ROW_TOP_YPIXEL(sheet, range.rowi)-y+sheet->row[range.rowi].height;
+  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;
@@ -3487,8 +3453,10 @@
   y = (sheet->column_titles_visible)
        ? MAX(y, sheet->column_title_area.height) : MAX(y, 0);
 
-  if(range.coli==sheet->maxcol) width=sheet->sheet_window_width-x;
-  if(range.rowi==sheet->maxrow) height=sheet->sheet_window_height-y;
+  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_pixmap(sheet->sheet_window,
                   GTK_WIDGET(sheet)->style->fg_gc[GTK_STATE_NORMAL],
@@ -3501,107 +3469,6 @@
                   height+1);                  
 }
 
-static GtkSheetCell *
-gtk_sheet_cell_new()
-{
- GtkSheetCell *cell;
- cell = g_new0(GtkSheetCell, 1);
- cell->link = NULL;
- cell->attributes = NULL;
- return cell;
-}
-
-/* Return the GValue of the cell at ROW, COL into VALUE.
-   VALUE must be uninitialised (zero filled), and will be
-   initilized by this function.
-   It is the caller's responsibility to uninitialise it when 
-   no longer required.
- */
-void
-gtk_sheet_get_cell_value(GtkSheet *sheet, 
-                        gint row, gint col, GValue *value)
-
-{
-  GtkSheetCell *cell;
-  GtkSheetCellAttr attributes;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-  if (col > sheet->maxcol || row > sheet->maxrow) return;
-  if (col < 0 || row < 0) return;
-
-  CheckBounds(sheet, row, col);
-
-  cell = sheet->data[row][col];
-
-  g_value_init(value, G_VALUE_TYPE(&cell->value));
-  g_value_copy(&cell->value, value);
-}
-
-/* Set the value of the cell at ROW, COL to be VALUE.
-   VALUE is copied by the function and will not be owned or modified */
-void 
-gtk_sheet_set_cell_value(GtkSheet *sheet, 
-                        gint row, gint col, const GValue *value)
-{
-  GtkSheetCell *cell;
-  GtkSheetCellAttr attributes;
-  GtkSheetRange range;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-  if (col > sheet->maxcol || row > sheet->maxrow) return;
-  if (col < 0 || row < 0) return;
-
-  CheckBounds(sheet, row, col);
-
-  cell = sheet->data[row][col];
-
-  if ( cell == NULL ) 
-    {
-      cell = gtk_sheet_cell_new();
-      cell->row = row;
-      cell->col = col;
-    }
-
-  if ( G_IS_VALUE(&cell->value))
-    g_value_unset(&cell->value);
-
-  g_value_init(&cell->value, G_VALUE_TYPE(value));
-  g_value_copy(value, &cell->value);
-
- gtk_sheet_get_attributes(sheet, row, col, &attributes);
-
- if(attributes.is_visible){
-   gint text_width;
-   const gchar *text = gtk_sheet_cell_get_text(sheet, row, col);
-   text_width = 0;
-   if(text && strlen(text) > 0) 
-     {
-       text_width = STRING_WIDTH(GTK_WIDGET(sheet), 
-                                attributes.font_desc, 
-                                text);
-     }
-
-   range.row0 = row;
-   range.rowi = row;
-   range.col0 = sheet->view.col0;
-   range.coli = sheet->view.coli;
-
-   if(gtk_sheet_autoresize(sheet) &&
-      text_width > 
sheet->column[col].width-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);
- }
-
-
- gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
-}
-
 
 void 
 gtk_sheet_set_cell_text(GtkSheet *sheet, gint row, gint col, const gchar *text)
@@ -3610,93 +3477,55 @@
 
  g_return_if_fail (sheet != NULL);
  g_return_if_fail (GTK_IS_SHEET (sheet));
- if (col > sheet->maxcol || row > sheet->maxrow) return;
+ 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 ( !s2) return +1;
+  return strcmp(s1, s2);
+}
 
 void 
 gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col, 
                    GtkJustification justification,
                    const gchar *text)
 {
- GtkSheetCell **cell;
  GtkSheetRange range;
  gint text_width;
  GtkSheetCellAttr attributes;
 
  g_return_if_fail (sheet != NULL);
  g_return_if_fail (GTK_IS_SHEET (sheet));
- if (col > sheet->maxcol || row > sheet->maxrow) return;
+ if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
  if (col < 0 || row < 0) return;
 
- CheckBounds(sheet, row, col);
-
- cell=&sheet->data[row][col];
-
- if(*cell==NULL)
-  (*cell) = gtk_sheet_cell_new();
-
  gtk_sheet_get_attributes(sheet, row, col, &attributes);
 
- (*cell)->row = row;
- (*cell)->col = col;
-
  attributes.justification = justification;
- gtk_sheet_set_cell_attributes(sheet, row, col, attributes);
 
- if ( G_IS_VALUE( &(*cell)->value))
-   {
-     GType the_type = G_VALUE_TYPE(&(*cell)->value);
+ GSheetModel *model =  gtk_sheet_get_model(sheet);
 
-     g_value_unset( &(*cell)->value);
-     g_value_init(&(*cell)->value, the_type);
-   }
- else
-   g_value_init(&(*cell)->value, G_TYPE_STRING);
+ const gchar *old_text = g_sheet_model_get_string(model, row, col);
 
- if ( sheet->encode_func)
-   {
-     sheet->encode_func(row, col, text, &(*cell)->value);
-   }
- else
-   {
-     if ( G_TYPE_STRING == G_VALUE_TYPE(&(*cell)->value))
-        g_value_set_string (&(*cell)->value, text);
-     else
-       {
-        GValue value = {0};
-        g_value_init(&value, G_TYPE_STRING);
-        g_value_set_string (&value, text);
- 
-        if (! g_value_type_transformable(G_TYPE_STRING, 
-                                         G_VALUE_TYPE(&(*cell)->value)))
-          {
-            g_warning ("Transformation from string to %s not possible."
-                       " Hint: Use g_value_register_transform_func or set "
-                       "a encode function using gtk_sheet_set_coding.", 
-                       G_VALUE_TYPE_NAME(&(*cell)->value));
-          }
-        else 
-          {
-            g_assert (g_value_transform(&value, &(*cell)->value));
-          }
-        g_value_unset(&value);
-       }
-   }
+ gboolean changed = FALSE;
+
+ if (0 != safe_strcmp(old_text, text))
+   changed = g_sheet_model_set_string(model, text, row, col);
 
- if(attributes.is_visible){
-   const gchar *text = gtk_sheet_cell_get_text(sheet, row, col);
+ if(changed && attributes.is_visible){
+   const gchar *s = gtk_sheet_cell_get_text(sheet, row, col);
    text_width = 0;
-   if(text && strlen(text) > 0) 
-     {
-       text_width = STRING_WIDTH(GTK_WIDGET(sheet), 
-                                attributes.font_desc, 
-                                text);
-     }
+   if(s && strlen(s) > 0) {
+     text_width = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
+   }
 
    range.row0 = row;
    range.rowi = row;
@@ -3704,7 +3533,7 @@
    range.coli = sheet->view.coli;
 
    if(gtk_sheet_autoresize(sheet) &&
-      text_width > 
sheet->column[col].width-2*CELLOFFSET-attributes.border.width){
+      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);
    }
@@ -3712,10 +3541,13 @@
      if(!GTK_SHEET_IS_FROZEN(sheet))
        gtk_sheet_range_draw(sheet, &range);
  }
- gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
+
+ if ( changed ) 
+   gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
 
 }
 
+
 void
 gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
 {
@@ -3723,8 +3555,7 @@
 
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
-  if (column > sheet->maxcol || row > sheet->maxrow) return;
-  if (column > sheet->maxalloccol || row > sheet->maxallocrow) return;
+  if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
   if (column < 0 || row < 0) return;
 
   range.row0 = row;
@@ -3746,8 +3577,7 @@
 
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
-  if (column > sheet->maxcol || row > sheet->maxrow) return;
-  if (column > sheet->maxalloccol || row > sheet->maxallocrow) return;
+  if (column >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
   if (column < 0 || row < 0) return;
 
   range.row0 = row;
@@ -3765,35 +3595,21 @@
 static void
 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean 
delete)
 {
-  gpointer link;
-
-  if(row > sheet->maxallocrow || column > sheet->maxalloccol) return;
-  if(!sheet->data[row]) return;
-  if(!sheet->data[row][column]) return;
+  const gchar *old_text;
 
-  link = gtk_sheet_get_link(sheet, row, column); 
+  old_text = gtk_sheet_cell_get_text(sheet, row, column); 
+ 
+  GSheetModel *model =  gtk_sheet_get_model(sheet);
 
-  if ( G_IS_VALUE(&sheet->data[row][column]->value))
+  if (old_text && strlen(old_text) > 0 )
     {
-      g_value_reset(&sheet->data[row][column]->value);
-
+      g_sheet_model_datum_clear(model, row, column);
+      
       if(GTK_IS_OBJECT(sheet) && G_OBJECT(sheet)->ref_count > 0)
-       gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CLEAR_CELL], row, 
column);
+       gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CLEAR_CELL], 
+                       row, column);
     }  
 
-  if(delete){ 
-     if(sheet->data[row][column]->attributes){
-         g_free(sheet->data[row][column]->attributes);
-         sheet->data[row][column]->attributes = NULL;
-     }
-     sheet->data[row][column]->link = NULL;
-
-     if(sheet->data[row][column]) g_free(sheet->data[row][column]);
-
-     sheet->data[row][column] = NULL;
-
-  }
-
 }
     
 void
@@ -3814,6 +3630,7 @@
   gtk_sheet_real_range_clear(sheet, range, TRUE);
 }
  
+
 static void
 gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range, 
                             gboolean delete)
@@ -3823,20 +3640,20 @@
 
   if(!range){
     clear.row0=0;
-    clear.rowi=sheet->maxallocrow;
+    clear.rowi = yyy_row_count(sheet) - 1;
     clear.col0=0;
-    clear.coli=sheet->maxalloccol;
+    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, sheet->maxallocrow);
-  clear.coli=MIN(clear.coli, sheet->maxalloccol);
+  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, delete);
+      gtk_sheet_real_cell_clear(sheet, i, j, delete);
     }
 
   gtk_sheet_range_draw(sheet, NULL);
@@ -3846,86 +3663,20 @@
 const gchar *     
 gtk_sheet_cell_get_text (GtkSheet *sheet, gint row, gint col)
 {
+  GSheetModel *model;
   g_return_val_if_fail (sheet != NULL, NULL);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
 
-  if(col > sheet->maxcol || row > sheet->maxrow) return NULL;
+  if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) 
+    return NULL;
   if(col < 0 || row < 0) return NULL;
-  if(row > sheet->maxallocrow || col > sheet->maxalloccol) return NULL;
-  if(!sheet->data[row]) return NULL;
-
-  GtkSheetCell *cell = sheet->data[row][col];
-  if(!cell) return NULL;
-
-  if ( sheet->decode_func ) 
-    {
-      return sheet->decode_func(row, col, &cell->value);
-    }
-  else
-    {
-      if (G_IS_VALUE(&cell->value))
-       {
-         const gchar *text;
-         if ( G_VALUE_HOLDS(&cell->value, G_TYPE_STRING)) 
-           text = g_value_get_string(&cell->value);
-         else
-           {
-             GValue new_value = {0};
-             g_value_init(&new_value, G_TYPE_STRING);
-             g_value_transform(&cell->value, &new_value);
-             text = g_value_get_string(&new_value);
-             g_value_unset(&new_value);
-           }
-         return text;
-       }
-    }
-
-  return NULL;
-}
-
-void 
-gtk_sheet_link_cell(GtkSheet *sheet, gint row, gint col, gpointer link)
-{
- g_return_if_fail (sheet != NULL);
- g_return_if_fail (GTK_IS_SHEET (sheet));
- if(col > sheet->maxcol || row > sheet->maxrow) return;
- if(col < 0 || row < 0) return;
-
- if(row > sheet->maxallocrow || col > sheet->maxalloccol ||
-    !sheet->data[row] || !sheet->data[row][col])
-       gtk_sheet_set_cell_text(sheet, row, col, "");
-
- sheet->data[row][col]->link = link;
-}
-
-gpointer 
-gtk_sheet_get_link(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 > sheet->maxcol || row > sheet->maxrow) return NULL;
- if(col < 0 || row < 0) return NULL;
 
- if (row > sheet->maxallocrow || col > sheet->maxalloccol) return NULL; 
- if (!sheet->data[row]) return NULL; /* Added by Chris Howell */ 
- if (!sheet->data[row][col]) return NULL; /* Added by Bob Lissner */ 
+  model =  gtk_sheet_get_model(sheet);
 
- return(sheet->data[row][col]->link);
-}
+  if ( !model ) 
+    return NULL;
 
-void
-gtk_sheet_remove_link(GtkSheet *sheet, gint row, gint col)
-{
- g_return_if_fail (sheet != NULL);
- g_return_if_fail (GTK_IS_SHEET (sheet));
- if(col > sheet->maxcol || row > sheet->maxrow) return;
- if(col < 0 || row < 0) return;
- 
- /* Fixed by Andreas Voegele */
- if(row < sheet->maxallocrow && col < sheet->maxalloccol &&
-    sheet->data[row] && sheet->data[row][col] &&
-    sheet->data[row][col]->link)
-                            sheet->data[row][col]->link = NULL;
+  return g_sheet_model_get_string(model, row, col);
 }
 
 
@@ -3937,30 +3688,31 @@
 
  g_return_val_if_fail (sheet != NULL, 0);
  g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
- if(col > sheet->maxcol || row > sheet->maxrow) return 0;
+ if(col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return 0;
  if(col < 0 || row < 0) return 0;
 
  state = sheet->state;
  range = &sheet->range;
 
- switch (state){
-                case GTK_SHEET_NORMAL:
-                     return GTK_STATE_NORMAL;
-                    break;
-               case GTK_SHEET_ROW_SELECTED:
-                     if(row>=range->row0 && row<=range->rowi) 
-                                        return GTK_STATE_SELECTED;
-                    break;
-                case GTK_SHEET_COLUMN_SELECTED:
-                     if(col>=range->col0 && col<=range->coli) 
-                                        return GTK_STATE_SELECTED;
-                    break;
-               case GTK_SHEET_RANGE_SELECTED:
-                     if(row >= range->row0 && row <= range->rowi && \
-                        col >= range->col0 && col <= range->coli)
-                                        return GTK_STATE_SELECTED;
-                    break;
- }
+ switch (state)
+   {
+   case GTK_SHEET_NORMAL:
+     return GTK_STATE_NORMAL;
+     break;
+   case GTK_SHEET_ROW_SELECTED:
+     if(row>=range->row0 && row<=range->rowi) 
+       return GTK_STATE_SELECTED;
+     break;
+   case GTK_SHEET_COLUMN_SELECTED:
+     if(col>=range->col0 && col<=range->coli) 
+       return GTK_STATE_SELECTED;
+     break;
+   case GTK_SHEET_RANGE_SELECTED:
+     if(row >= range->row0 && row <= range->rowi && \
+       col >= range->col0 && col <= range->coli)
+       return GTK_STATE_SELECTED;
+     break;
+   }
  return GTK_STATE_NORMAL;
 }
 
@@ -3979,13 +3731,13 @@
   /* bounds checking, return false if the user clicked 
    * on a blank area */
   trow = ROW_FROM_YPIXEL (sheet, y);
-  if (trow > sheet->maxrow)
+  if (trow >= yyy_row_count(sheet))
     return FALSE;
 
   *row = trow;
 
   tcol = COLUMN_FROM_XPIXEL (sheet, x);
-  if (tcol > sheet->maxcol)
+  if (tcol >= xxx_column_count(sheet))
     return FALSE;
 
  *column = tcol;
@@ -4002,7 +3754,8 @@
   g_return_val_if_fail (sheet != NULL, 0);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
 
-  if(row > sheet->maxrow || column > sheet->maxcol) return FALSE;
+  if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)) 
+    return FALSE;
 
   area->x = (column == -1) ? 0 : (COLUMN_LEFT_XPIXEL(sheet, column) -
                                  (sheet->row_titles_visible
@@ -4013,9 +3766,10 @@
                                ? sheet->column_title_area.height
                                : 0));
   area->width= (column == -1) ? sheet->row_title_area.width
-                              : sheet->column[column].width;
+    : xxx_column_width(sheet, column);
+
   area->height= (row == -1) ? sheet->column_title_area.height
-                            : sheet->row[row].height;
+                            : yyy_row_height(sheet, row);
 
 /*
   if(row < 0 || column < 0) return FALSE;
@@ -4028,7 +3782,7 @@
            area->y -= sheet->column_title_area.height;
 
   area->width=sheet->column[column].width;
-  area->height=sheet->row[row].height;  
+  area->height=yyy_row_height(sheet, row);  
 */
   return TRUE;
 }
@@ -4040,7 +3794,8 @@
  g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
 
  if(row < 0 || column < 0) return FALSE;
- if(row > sheet->maxrow || column > sheet->maxcol) return FALSE;
+ if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)) 
+   return FALSE;
 
  if(GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)))
    {
@@ -4093,32 +3848,21 @@
  sheet->active_cell.row=-1;
  sheet->active_cell.col=-1;
 
- text=gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
+ text = gtk_entry_get_text(GTK_ENTRY(gtk_sheet_get_entry(sheet)));
 
  GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
 
- if(text && strlen(text)!=0){
+ if(text && strlen(text) > 0){
       gtk_sheet_get_attributes(sheet, row, col, &attributes); 
       justification=attributes.justification;
       gtk_sheet_set_cell(sheet, row, col, justification, text);
  }
- else
- {
-   /* Added by Matias Mutchinick */
-   if(row < sheet->maxallocrow && col < sheet->maxalloccol && 
-      sheet->data[row] && sheet->data[row][col] )
-     {
-       if ( G_IS_VALUE(&sheet->data[row][col]->value))
-        g_value_reset(&sheet->data[row][col]->value);
-     }
- }
 
  if(sheet->freeze_count == 0)
         GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
  
  sheet->active_cell.row=row;;
  sheet->active_cell.col=col;
-
 }
 
 
@@ -4190,8 +3934,10 @@
  row=sheet->active_cell.row;
  col=sheet->active_cell.col;
 
+#if 0
  column_button_release(sheet, col);
  row_button_release(sheet, row);
+#endif
 
  gtk_widget_unmap(sheet->sheet_entry);
 
@@ -4203,11 +3949,9 @@
                    ROW_TOP_YPIXEL(sheet,row)-1,
                    COLUMN_LEFT_XPIXEL(sheet,col)-1,
                    ROW_TOP_YPIXEL(sheet,row)-1,
-                   sheet->column[col].width+4,
-                   sheet->row[row].height+4);   
+                  xxx_column_width(sheet, col) + 4,
+                   yyy_row_height(sheet, row)+4);   
 
- GTK_WIDGET_UNSET_FLAGS(sheet->sheet_entry, GTK_HAS_FOCUS);
- GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet), GTK_HAS_FOCUS);
  gtk_widget_grab_focus(GTK_WIDGET(sheet));
 
  GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet->sheet_entry), GTK_VISIBLE);
@@ -4223,7 +3967,8 @@
  g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
 
  if(row < 0 || col < 0) return FALSE;
- if(row > sheet->maxrow || col > sheet->maxcol) return FALSE;
+ if(row >= yyy_row_count(sheet) || col >= xxx_column_count(sheet)) 
+   return FALSE;
 
 /* _gtkextra_signal_emit(GTK_OBJECT(sheet),sheet_signals[ACTIVATE], row, col, 
&veto);
  if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return veto;
@@ -4243,16 +3988,18 @@
  sheet->active_cell.col=col;
  sheet->selection_cell.row=row;
  sheet->selection_cell.col=col;
+#if 0
  row_button_set(sheet, row);
  column_button_set(sheet, col); 
+#endif
 
  GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
  gtk_sheet_show_active_cell(sheet);
 
- gtk_signal_connect(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
-                   "changed",
-                    (GtkSignalFunc)gtk_sheet_entry_changed,
-                    GTK_OBJECT(GTK_WIDGET(sheet)));
+   g_signal_connect(G_OBJECT(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);
 
@@ -4262,7 +4009,6 @@
 static void
 gtk_sheet_show_active_cell(GtkSheet *sheet)
 {
-
  GtkEntry *sheet_entry;
  GtkSheetCellAttr attributes;
  gchar *text = NULL;
@@ -4295,15 +4041,7 @@
  if(gtk_sheet_justify_entry(sheet))
       justification = attributes.justification;
 
- if(row <= sheet->maxallocrow && col <= sheet->maxalloccol) {
-   if(sheet->data[row] && sheet->data[row][col]) 
-     {
-       GtkSheetCell *cell = sheet->data[row][col];
-       const gchar *t  = gtk_sheet_cell_get_text(sheet, row, col);
-       if(t)
-        text = g_strdup(t);
-     }
- }
+ text = g_strdup(gtk_sheet_cell_get_text(sheet, row, col));
 
  if(!text) text = g_strdup("");
 
@@ -4317,7 +4055,8 @@
 
 /*** Added by John Gotts. Mar 25, 2005 *********/
  old_text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
- if (strcmp(old_text, text) != 0) {
+ if (strcmp(old_text, text) != 0) 
+{
   if(!GTK_IS_ITEM_ENTRY(sheet_entry))
      gtk_entry_set_text(GTK_ENTRY(sheet_entry), text);
   else
@@ -4331,8 +4070,6 @@
  gtk_sheet_draw_active_cell(sheet);
 
  gtk_widget_grab_focus(GTK_WIDGET(sheet_entry));
- GTK_WIDGET_SET_FLAGS(GTK_WIDGET(sheet_entry), GTK_HAS_FOCUS);
- GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(sheet), GTK_HAS_FOCUS);
 
  g_free(text);
 }
@@ -4351,10 +4088,10 @@
     if(row<0 || col<0) return;
 
     if(!gtk_sheet_cell_isvisible(sheet, row, col)) return;
- 
+#if 0
     row_button_set(sheet, row);
     column_button_set(sheet, col);
-
+#endif
     gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
     gtk_sheet_draw_border(sheet, sheet->range);
 
@@ -4434,7 +4171,7 @@
         j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
 
     if(state==GTK_STATE_SELECTED && selected &&
-       sheet->column[j].is_visible && sheet->row[i].is_visible &&
+       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 ||
@@ -4453,8 +4190,9 @@
        if(mask1 != mask2){
          x=COLUMN_LEFT_XPIXEL(sheet,j);
          y=ROW_TOP_YPIXEL(sheet, i);  
-         width=COLUMN_LEFT_XPIXEL(sheet, j)-x+sheet->column[j].width;
-         height=ROW_TOP_YPIXEL(sheet, i)-y+sheet->row[i].height;
+         width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
+          xxx_column_width(sheet, j);
+         height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
 
          if(i==sheet->range.row0){
             y=y-3;
@@ -4480,8 +4218,10 @@
          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+sheet->column[j].width;
-           height=ROW_TOP_YPIXEL(sheet, i)-y+sheet->row[i].height;
+           width=COLUMN_LEFT_XPIXEL(sheet, j)-x+
+            xxx_column_width(sheet, j);
+
+           height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
 
            if(i==new_range.row0){
                y=y+2;
@@ -4513,12 +4253,12 @@
         j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
 
     if(state==GTK_STATE_SELECTED && !selected &&   
-       sheet->column[j].is_visible && sheet->row[i].is_visible){
+       xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
 
       x=COLUMN_LEFT_XPIXEL(sheet,j);
       y=ROW_TOP_YPIXEL(sheet, i);  
-      width=COLUMN_LEFT_XPIXEL(sheet, j)-x+sheet->column[j].width;
-      height=ROW_TOP_YPIXEL(sheet, i)-y+sheet->row[i].height;
+      width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
+      height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
 
       if(i==sheet->range.row0){
             y=y-3;
@@ -4552,13 +4292,13 @@
         j<=new_range.coli && j>=new_range.col0) ? TRUE : FALSE;
 
     if(state!=GTK_STATE_SELECTED && selected &&
-       sheet->column[j].is_visible && sheet->row[i].is_visible &&
+       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+sheet->column[j].width;
-      height=ROW_TOP_YPIXEL(sheet, i)-y+sheet->row[i].height;
+      width=COLUMN_LEFT_XPIXEL(sheet, j)-x+ xxx_column_width(sheet, j);
+      height=ROW_TOP_YPIXEL(sheet, i)-y+yyy_row_height(sheet, i);
 
       if(i==new_range.row0){
             y=y+2;
@@ -4585,7 +4325,7 @@
   for(i=aux_range.row0; i<=aux_range.rowi; i++){
    for(j=aux_range.col0; j<=aux_range.coli; j++){     
 
-    if(sheet->column[j].is_visible && sheet->row[i].is_visible){
+    if(xxx_column_is_visible(sheet, j) && yyy_row_is_visible(sheet, i)){
 
        state=gtk_sheet_cell_get_state(sheet, i, j);
 
@@ -4601,8 +4341,8 @@
        if(mask2!=mask1 || (mask2==mask1 && state!=GTK_STATE_SELECTED)){
          x=COLUMN_LEFT_XPIXEL(sheet,j);
          y=ROW_TOP_YPIXEL(sheet, i);  
-         width=sheet->column[j].width;
-         height=sheet->row[i].height;
+         width=xxx_column_width(sheet, j);
+         height=yyy_row_height(sheet, i);
          if(mask2 & 1)
                gdk_draw_rectangle (sheet->sheet_window,
                                   sheet->xor_gc,
@@ -4661,9 +4401,10 @@
   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+ 
-             sheet->column[new_range.coli].width;
+    xxx_column_width(sheet, new_range.coli);
+
   height=ROW_TOP_YPIXEL(sheet,new_range.rowi)-y+
-             sheet->row[new_range.rowi].height;
+             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));
@@ -4724,7 +4465,7 @@
   if(gtk_sheet_cell_isvisible(sheet, range.row0, range.coli) ||
      sheet->state == GTK_SHEET_COLUMN_SELECTED){
        x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
-         sheet->column[range.coli].width;
+         xxx_column_width(sheet, range.coli);
        y=ROW_TOP_YPIXEL(sheet,range.row0);
        width = 1;
        if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
@@ -4752,7 +4493,7 @@
      sheet->state == GTK_SHEET_ROW_SELECTED){
        x=COLUMN_LEFT_XPIXEL(sheet,range.col0);
        y=ROW_TOP_YPIXEL(sheet,range.rowi)+
-         sheet->row[range.rowi].height;
+         yyy_row_height(sheet, range.rowi);
        width = 1;
        if(sheet->state == GTK_SHEET_ROW_SELECTED) 
          {
@@ -4777,9 +4518,9 @@
 
   if(gtk_sheet_cell_isvisible(sheet, range.rowi, range.coli)){
        x=COLUMN_LEFT_XPIXEL(sheet,range.coli)+
-         sheet->column[range.coli].width;
+         xxx_column_width(sheet, range.coli);
        y=ROW_TOP_YPIXEL(sheet,range.rowi)+
-         sheet->row[range.rowi].height;
+         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;
@@ -4807,7 +4548,6 @@
 gtk_sheet_real_select_range (GtkSheet * sheet,
                             GtkSheetRange * range)
 {
-  gint i;
   gint state;
 
   g_return_if_fail (sheet != NULL);
@@ -4819,6 +4559,7 @@
 
   state=sheet->state;
 
+#if 0
   if(state==GTK_SHEET_COLUMN_SELECTED || state==GTK_SHEET_RANGE_SELECTED){
    for(i=sheet->range.col0; i< range->col0; i++)
     column_button_release(sheet, i);
@@ -4838,6 +4579,7 @@
     row_button_set(sheet, i);
    }
   }
+#endif
 
   if(range->coli != sheet->range.coli || range->col0 != sheet->range.col0 ||
      range->rowi != sheet->range.rowi || range->row0 != sheet->range.row0)
@@ -4906,8 +4648,6 @@
 gtk_sheet_real_unselect_range (GtkSheet * sheet,
                               const GtkSheetRange *range)
 {
-  gint i;
- 
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_WIDGET_REALIZED(GTK_WIDGET(sheet)));
 
@@ -4922,6 +4662,7 @@
     gtk_sheet_draw_backing_pixmap(sheet, *range);
   }
 
+#if 0
   for(i=range->col0; i<=range->coli; i++){
      column_button_release(sheet, i);
   }
@@ -4929,6 +4670,7 @@
   for(i=range->row0; i<=range->rowi; i++){
      row_button_release(sheet, i);
   }
+#endif
 
   gtk_sheet_position_children(sheet);
 }
@@ -4983,8 +4725,6 @@
                    draw_xor_rectangle(sheet, sheet->drag_range);
         }
 
-#if 0   /* This seems to create infinite expose events when non
-          standard entry widgets are active */
         if((!GTK_SHEET_IN_XDRAG(sheet)) && (!GTK_SHEET_IN_YDRAG(sheet))){
              if(sheet->state == GTK_SHEET_NORMAL){ 
                  gtk_sheet_draw_active_cell(sheet);
@@ -4992,7 +4732,6 @@
                          gtk_widget_queue_draw(sheet->sheet_entry);
              }
         }
-#endif
 
 
       }
@@ -5041,7 +4780,7 @@
     }
 
   
-/* 
+/*
   if(event->type != GDK_BUTTON_PRESS) return TRUE;
 */
   gdk_window_get_pointer(widget->window, NULL, NULL, &mods);
@@ -5056,6 +4795,11 @@
        gtk_widget_get_pointer (widget, &sheet->x_drag, NULL);
         if(POSSIBLE_XDRAG(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,
@@ -5088,6 +4832,9 @@
         }
       }
 
+  /* the sheet itself does not handle other than single click events */
+  if(event->type != GDK_BUTTON_PRESS) return FALSE;
+
   /* selections on the sheet */
     if(event->window == sheet->sheet_window){
      gtk_widget_get_pointer (widget, &x, &y);
@@ -5099,8 +4846,6 @@
                       NULL, NULL, event->time);
      gtk_grab_add(GTK_WIDGET(sheet));
      sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet); 
-     GTK_WIDGET_UNSET_FLAGS(sheet->sheet_entry, GTK_HAS_FOCUS);
-     GTK_WIDGET_SET_FLAGS(GTK_SHEET(sheet), GTK_HAS_FOCUS);
      gtk_widget_grab_focus(GTK_WIDGET(sheet));
 
      if(sheet->selection_mode != GTK_SELECTION_SINGLE &&
@@ -5161,12 +4906,10 @@
     if(event->window == sheet->column_title_window){
      gtk_widget_get_pointer (widget, &x, &y);
      column = COLUMN_FROM_XPIXEL(sheet, x);
-     if(sheet->column[column].is_sensitive){;
+     if(xxx_column_is_sensitive(sheet, column)){
        gtk_sheet_click_cell(sheet, -1, column, &veto);
        gtk_grab_add(GTK_WIDGET(sheet));
        sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet); 
-       GTK_WIDGET_UNSET_FLAGS(sheet->sheet_entry, GTK_HAS_FOCUS);
-       GTK_WIDGET_SET_FLAGS(GTK_SHEET(sheet), GTK_HAS_FOCUS);
        gtk_widget_grab_focus(GTK_WIDGET(sheet));
        GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
      }
@@ -5175,12 +4918,10 @@
     if(event->window == sheet->row_title_window){
      gtk_widget_get_pointer (widget, &x, &y);
      row = ROW_FROM_YPIXEL(sheet, y);
-     if(sheet->row[row].is_sensitive){
+     if(yyy_row_is_sensitive(sheet, row)){
        gtk_sheet_click_cell(sheet, row, -1, &veto);
        gtk_grab_add(GTK_WIDGET(sheet));
        sheet->timer=gtk_timeout_add(TIMEOUT_SCROLL, gtk_sheet_scroll, sheet); 
-       GTK_WIDGET_UNSET_FLAGS(sheet->sheet_entry, GTK_HAS_FOCUS);
-       GTK_WIDGET_SET_FLAGS(GTK_SHEET(sheet), GTK_HAS_FOCUS);
        gtk_widget_grab_focus(GTK_WIDGET(sheet));
        GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
      }
@@ -5224,13 +4965,13 @@
 {
       *veto = TRUE;
 
-      if(row > sheet->maxrow || column > sheet->maxcol){
+      if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)){
           *veto = FALSE;
           return;
       }
 
       if(column >= 0 && row >= 0)
-       if(!sheet->column[column].is_visible || !sheet->row[row].is_visible) 
+       if(! xxx_column_is_visible(sheet, column) || !yyy_row_is_visible(sheet, 
row)) 
          {
            *veto = FALSE;
            return;
@@ -5245,6 +4986,7 @@
 
            row = sheet->active_cell.row;
            column = sheet->active_cell.col;
+
            gtk_sheet_activate_cell(sheet, row, column);
            return;
       }
@@ -5265,8 +5007,8 @@
       if(row==-1 && column ==-1){
           sheet->range.row0=0;
           sheet->range.col0=0;
-          sheet->range.rowi=sheet->maxrow;
-          sheet->range.coli=sheet->maxcol;
+          sheet->range.rowi = yyy_row_count(sheet) - 1;
+          sheet->range.coli = xxx_column_count(sheet) - 1;
          sheet->active_cell.row=0;
          sheet->active_cell.col=0;
          gtk_sheet_select_range(sheet, NULL);
@@ -5302,6 +5044,7 @@
          return;
       }
 
+      g_assert_not_reached();
       gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
                                      sheet->active_cell.col);
 }
@@ -5547,8 +5290,8 @@
        sheet->x_drag=x;
        sheet->y_drag=y;
        aux=sheet->range;
-       if(aux.row0+row >= 0 && aux.rowi+row <= sheet->maxrow &&
-          aux.col0+column >= 0 && aux.coli+column <= sheet->maxcol){
+       if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
+          aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
              aux=sheet->drag_range;
              sheet->drag_range.row0=sheet->range.row0+row;
              sheet->drag_range.col0=sheet->range.col0+column;
@@ -5577,7 +5320,7 @@
        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)+gtk_sheet_column_width 
(sheet,current_col)/2;
+       col_threshold = COLUMN_LEFT_XPIXEL(sheet,current_col)+xxx_column_width 
(sheet,current_col)/2;
        if (column > 0){
          if (x < col_threshold)
            column-=1;
@@ -5586,7 +5329,7 @@
          if (x > col_threshold) 
           column+=1;
        }
-       row_threshold = ROW_TOP_YPIXEL(sheet,current_row)+gtk_sheet_row_height 
(sheet, current_row)/2;
+       row_threshold = ROW_TOP_YPIXEL(sheet,current_row)+yyy_row_height 
(sheet, current_row)/2;
        if (row > 0){
          if(y < row_threshold)
            row-=1;
@@ -5607,8 +5350,8 @@
        else
            row=0;
 
-       if(aux.row0+row >= 0 && aux.rowi+row <= sheet->maxrow &&
-          aux.col0+column >= 0 && aux.coli+column <= sheet->maxcol){
+       if(aux.row0+row >= 0 && aux.rowi+row < yyy_row_count(sheet) &&
+          aux.col0+column >= 0 && aux.coli+column < xxx_column_count(sheet)){
 
              aux=sheet->drag_range;
              sheet->drag_range=sheet->range;
@@ -5661,11 +5404,11 @@
 
   if(row>=MAX_VISIBLE_ROW(sheet) && sheet->state!=GTK_SHEET_COLUMN_SELECTED) {
           row_align = 1.;
-         new_row = MIN(sheet->maxrow, row + 1);
+         new_row = MIN(yyy_row_count(sheet), row + 1);
           row_move = TRUE;
-          if(MAX_VISIBLE_ROW(sheet) == sheet->maxrow &&
-             ROW_TOP_YPIXEL(sheet, sheet->maxrow) + 
-             sheet->row[sheet->maxrow].height < height){
+          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.;
           }
@@ -5676,14 +5419,15 @@
   }
   if(column>=MAX_VISIBLE_COLUMN(sheet) && 
sheet->state!=GTK_SHEET_ROW_SELECTED) {
           col_align = 1.;
-          new_col = MIN(sheet->maxcol, column + 1);
+          new_col = MIN(xxx_column_count(sheet) - 1, column + 1);
           column_move = TRUE;
-          if(MAX_VISIBLE_COLUMN(sheet) == sheet->maxcol &&
-             COLUMN_LEFT_XPIXEL(sheet, sheet->maxcol) + 
-             sheet->column[sheet->maxcol].width < width){
-                 column_move = FALSE;
-                col_align = -1.;
-          }
+          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.;
@@ -5718,10 +5462,10 @@
 
    switch(sheet->state){
     case GTK_SHEET_ROW_SELECTED:
-        column = sheet->maxcol;
+        column = xxx_column_count(sheet) - 1;
          break;
     case GTK_SHEET_COLUMN_SELECTED:
-        row = sheet->maxrow;
+        row = yyy_row_count(sheet) - 1;
          break; 
     case GTK_SHEET_NORMAL:
         sheet->state=GTK_SHEET_RANGE_SELECTED;
@@ -5738,8 +5482,8 @@
                    ROW_TOP_YPIXEL(sheet,r)-1,
                    COLUMN_LEFT_XPIXEL(sheet,c)-1,
                    ROW_TOP_YPIXEL(sheet,r)-1,
-                   sheet->column[c].width+4,
-                   sheet->row[r].height+4);   
+                   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;
@@ -5816,9 +5560,10 @@
            row = MIN_VISIBLE_ROW(sheet)-1;
       if(sheet->state == GTK_SHEET_ROW_SELECTED)
            col = MIN_VISIBLE_COLUMN(sheet);
-      if(row < sheet->maxrow){
+      if(row < yyy_row_count(sheet) - 1){
            row = row + scroll;
-           while(!sheet->row[row].is_visible && row<sheet->maxrow) row++;
+           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;
@@ -5832,7 +5577,7 @@
            row = MIN_VISIBLE_ROW(sheet);
       if(col > 0){
            col = col - scroll; 
-           while(!sheet->column[col].is_visible && col>0) col--;
+           while(! xxx_column_is_visible(sheet, col) && col>0) col--;
           col=MAX(0, col);
       }       
       gtk_sheet_click_cell(sheet, row, col, &veto);
@@ -5845,10 +5590,13 @@
            col = MIN_VISIBLE_COLUMN(sheet)-1;
       if(sheet->state == GTK_SHEET_COLUMN_SELECTED) 
            row = MIN_VISIBLE_ROW(sheet);
-      if(col < sheet->maxcol){
-           col = col + scroll; 
-           while(!sheet->column[col].is_visible && col<sheet->maxcol) col++;
-      }       
+      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;
       break;
@@ -5876,7 +5624,7 @@
         }
         if(sheet->selection_cell.row > 0){
           row = sheet->selection_cell.row - scroll;
-          while(!sheet->row[row].is_visible && row > 0) row--;
+          while(!yyy_row_is_visible(sheet, row) && row > 0) row--;
           row = MAX(0, row);
           gtk_sheet_extend_selection(sheet, row, sheet->selection_cell.col);
         }
@@ -5889,7 +5637,7 @@
       if(state==GTK_SHEET_ROW_SELECTED) 
              col = MIN_VISIBLE_COLUMN(sheet);
       row = row - scroll;
-      while(!sheet->row[row].is_visible && row > 0) row--;
+      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;
@@ -5904,24 +5652,24 @@
            gtk_sheet_click_cell(sheet, row, col, &veto);
            if(!veto) break;
         }
-        if(sheet->selection_cell.row < sheet->maxrow){
+        if(sheet->selection_cell.row < yyy_row_count(sheet)-1){
           row = sheet->selection_cell.row + scroll;
-          while(!sheet->row[row].is_visible && row < sheet->maxrow) row++;
-          row = MIN(sheet->maxrow, row);
+          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 < sheet->maxrow){
+      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(!sheet->row[row].is_visible && row < sheet->maxrow) row++;
-           row = MIN(sheet->maxrow, row);
+           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;
@@ -5934,22 +5682,24 @@
            gtk_sheet_click_cell(sheet, row, col, &veto);
            if(!veto) break;
         }
-        if(sheet->selection_cell.col < sheet->maxcol){
-          col = sheet->selection_cell.col + 1;
-          while(!sheet->column[col].is_visible && col < sheet->maxcol) col++;
-          gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
-        }
+        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 < sheet->maxcol){
+      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(!sheet->column[col].is_visible && col < sheet->maxcol) col++;
+           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);
@@ -5969,7 +5719,7 @@
         }
         if(sheet->selection_cell.col > 0){
           col = sheet->selection_cell.col - 1;
-          while(!sheet->column[col].is_visible && col > 0) col--;          
+          while(! xxx_column_is_visible(sheet, col) && col > 0) col--;         
 
           gtk_sheet_extend_selection(sheet, sheet->selection_cell.row, col);
         }
        return TRUE;
@@ -5980,7 +5730,7 @@
                 col = MIN_VISIBLE_COLUMN(sheet)-1;
       if(state==GTK_SHEET_COLUMN_SELECTED) 
                 row = MIN_VISIBLE_ROW(sheet);
-      while(!sheet->column[col].is_visible && col > 0) col--;
+      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
@@ -5993,13 +5743,13 @@
       break;
     case GDK_Home:
       row=0;
-      while(!sheet->row[row].is_visible && row < sheet->maxrow) row++;
+      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;
       break;
     case GDK_End:
-      row=sheet->maxrow;
-      while(!sheet->row[row].is_visible && row > 0) row--;
+      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;
       break;
@@ -6209,7 +5959,7 @@
   }
 
 
-  if(MAX_VISIBLE_COLUMN(sheet) == sheet->maxcol)
+  if(MAX_VISIBLE_COLUMN(sheet) == xxx_column_count(sheet) - 1)
      gdk_window_clear_area (sheet->column_title_window,
                            0,0,
                            sheet->column_title_area.width, 
@@ -6240,16 +5990,17 @@
       y = sheet->column_title_area.height;
     }
     
-  if(sheet->row_title_area.height != height || sheet->row_title_area.y != y){
-     sheet->row_title_area.y = y;
-     sheet->row_title_area.height = height;
-     gdk_window_move_resize (sheet->row_title_window,
-                            sheet->row_title_area.x,
-                            sheet->row_title_area.y,
-                            sheet->row_title_area.width,
-                            sheet->row_title_area.height);
-  }
-  if(MAX_VISIBLE_ROW(sheet) == sheet->maxrow)
+  if(sheet->row_title_area.height != height || sheet->row_title_area.y != y)
+    {
+      sheet->row_title_area.y = y;
+      sheet->row_title_area.height = height;
+      gdk_window_move_resize (sheet->row_title_window,
+                             sheet->row_title_area.x,
+                             sheet->row_title_area.y,
+                             sheet->row_title_area.width,
+                             sheet->row_title_area.height);
+    }
+  if(MAX_VISIBLE_ROW(sheet) == yyy_row_count(sheet)-1)
     gdk_window_clear_area (sheet->row_title_window,
                           0,0,
                           sheet->row_title_area.width, 
@@ -6261,34 +6012,6 @@
       gtk_sheet_button_draw(sheet,i,-1);
 }
          
-static void
-gtk_sheet_recalc_top_ypixels(GtkSheet *sheet, gint row)
-{
-  gint i, cy;
-
-  cy = sheet->column_title_area.height;
-  if(!sheet->column_titles_visible) cy = 0;
-  for(i=0; i<=sheet->maxrow; i++){
-      sheet->row[i].top_ypixel=cy;
-      if(sheet->row[i].is_visible) cy+=sheet->row[i].height;
-  }
-}
-
-static void
-gtk_sheet_recalc_left_xpixels(GtkSheet *sheet, gint column)
-{
-  gint i, cx;
-
-  cx = sheet->row_title_area.width;
-  if(!sheet->row_titles_visible) cx = 0;
-  for(i=0; i<=sheet->maxcol; i++){
-      sheet->column[i].left_xpixel=cx;
-      if(sheet->column[i].is_visible) cx+=sheet->column[i].width;
-  }
-
-}
-
-
 
 static void
 gtk_sheet_size_allocate_entry(GtkSheet *sheet)
@@ -6352,7 +6075,7 @@
      text_size = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
  }
 
- column_width=sheet->column[sheet->active_cell.col].width;
+ column_width=xxx_column_width(sheet, sheet->active_cell.col);
 
  size=MIN(text_size, max_size);
  size=MAX(size,column_width-2*CELLOFFSET);
@@ -6363,7 +6086,7 @@
  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 = sheet->row[sheet->active_cell.row].height;
+ shentry_allocation.height = yyy_row_height(sheet, sheet->active_cell.row);
 
  if(GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
 
@@ -6422,31 +6145,31 @@
   case GTK_JUSTIFY_LEFT:
     for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
      if(gtk_sheet_cell_get_text(sheet, row, i)) break;
-     size+=sheet->column[i].width;
+     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(gtk_sheet_cell_get_text(sheet, row, i)) break;
-     size+=sheet->column[i].width;
+     size+=xxx_column_width(sheet, i);
     }
     break;
   case GTK_JUSTIFY_CENTER:
     for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
 /*     if(gtk_sheet_cell_get_text(sheet, row, i)) break;
 */
-     sizer+=sheet->column[i].width;
+     sizer+=xxx_column_width(sheet, i);
     }
     for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
      if(gtk_sheet_cell_get_text(sheet, row, i)) break;
-     sizel+=sheet->column[i].width;
+     sizel+=xxx_column_width(sheet, i);
     }
     size=2*MIN(sizel, sizer);
     break;
  }
 
- if(size!=0) size+=sheet->column[col].width;
+ if(size!=0) size+=xxx_column_width(sheet, col);
  GTK_ITEM_ENTRY(sheet->sheet_entry)->text_max_size=size;
 
 }
@@ -6457,13 +6180,10 @@
  GtkWidget *widget;
  GtkWidget *parent;
  GtkWidget *entry;
- GtkStyle *style;
  gint found_entry = FALSE;
 
  widget = GTK_WIDGET(sheet);
 
- style = gtk_style_copy(GTK_WIDGET(sheet)->style); 
-
  if(sheet->sheet_entry){
     /* avoids warnings */
     gtk_widget_ref(sheet->sheet_entry);
@@ -6539,7 +6259,7 @@
 }
 
 GtkWidget * 
-gtk_sheet_get_entry(const GtkSheet *sheet)
+gtk_sheet_get_entry(GtkSheet *sheet)
 {
  GtkWidget *parent;
  GtkWidget *entry = NULL;
@@ -6591,7 +6311,7 @@
 }
 
 GtkWidget * 
-gtk_sheet_get_entry_widget(const GtkSheet *sheet)
+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);
@@ -6600,6 +6320,7 @@
  return (sheet->sheet_entry);
 }
 
+#if 0
 /* BUTTONS */
 static void
 row_button_set (GtkSheet *sheet, gint row)
@@ -6612,16 +6333,6 @@
 }
 
 static void
-column_button_set (GtkSheet *sheet, gint column)
-{
-  if(sheet->column[column].button.state == GTK_STATE_ACTIVE) return;
-
-  sheet->column[column].button.state = GTK_STATE_ACTIVE;
-  gtk_sheet_button_draw(sheet, -1, column);
- 
-}
-
-static void
 row_button_release (GtkSheet *sheet, gint row)
 {
   if(sheet->row[row].button.state == GTK_STATE_NORMAL) return;
@@ -6629,15 +6340,7 @@
   sheet->row[row].button.state = GTK_STATE_NORMAL;
   gtk_sheet_button_draw(sheet, row, -1);
 }
-
-static void
-column_button_release (GtkSheet *sheet, gint column)
-{
-  if(sheet->column[column].button.state == GTK_STATE_NORMAL) return;
-
-  sheet->column[column].button.state = GTK_STATE_NORMAL;
-  gtk_sheet_button_draw(sheet, -1, column);
-}
+#endif
 
 static void
 gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column)
@@ -6648,15 +6351,14 @@
   gint x = 0, y = 0;
   gint index = 0;
   gint text_width = 0, text_height = 0;
-  GtkSheetButton *button = NULL;
+  const GtkSheetButton *button = NULL;
   GtkSheetChild *child = NULL;
   GdkRectangle allocation;
   gboolean is_sensitive = FALSE;
   gint state = 0;
   gint len = 0;
   gchar *line = 0;
-  gchar *words = 0;
-  gchar label[10];
+
   PangoAlignment align = PANGO_ALIGN_LEFT; 
   gboolean rtl;
 
@@ -6664,37 +6366,37 @@
 
   if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
 
-  if(row >= 0 && !sheet->row[row].is_visible) return;
-  if(column >= 0 && !sheet->column[column].is_visible) return;
+  if(row >= 0 && !yyy_row_is_visible(sheet, row)) return;
+  if(column >= 0 && ! xxx_column_is_visible(sheet, column)) return;
   if(row >= 0 && !sheet->row_titles_visible) 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(row>=0 && row <MIN_VISIBLE_ROW(sheet)) return;
-  if(row>=0 && row >MAX_VISIBLE_ROW(sheet)) return;
+  if(column>=0 && column < MIN_VISIBLE_COLUMN(sheet)) return;
+  if(column>=0 && column > MAX_VISIBLE_COLUMN(sheet)) return;
+  if(row>=0 && row < MIN_VISIBLE_ROW(sheet)) return;
+  if(row>=0 && row > MAX_VISIBLE_ROW(sheet)) return;
   if( (row == -1) && (column == -1) ) return; 
 
   if(row==-1){
      window=sheet->column_title_window;
-     button=&sheet->column[column].button;
+     button= xxx_column_button(sheet, column);
      index=column;
      x = COLUMN_LEFT_XPIXEL(sheet, column)+CELL_SPACING;
      if(sheet->row_titles_visible) x -= sheet->row_title_area.width;
      y = 0;
-     width = sheet->column[column].width;
+     width = xxx_column_width(sheet, column);
      height = sheet->column_title_area.height;
-     is_sensitive=sheet->column[column].is_sensitive;
+     is_sensitive=xxx_column_is_sensitive(sheet, column);
   }
-  else if(column==-1){
+  if(column==-1){
      window=sheet->row_title_window;
-     button=&sheet->row[row].button;
+     button = yyy_row_button(sheet, row);
      index=row;
      x = 0;
      y = ROW_TOP_YPIXEL(sheet, row)+CELL_SPACING;
      if(sheet->column_titles_visible) y-=sheet->column_title_area.height;
      width = sheet->row_title_area.width;
-     height = sheet->row[row].height;
-     is_sensitive=sheet->row[row].is_sensitive;
+     height = yyy_row_height(sheet, row);
+     is_sensitive=yyy_row_is_sensitive(sheet, row);
   }
 
   allocation.x = x;
@@ -6733,12 +6435,11 @@
                               &allocation);
     gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->white_gc, &allocation);
 
-/*
-    y += DEFAULT_ROW_HEIGHT(GTK_WIDGET(sheet))/2 + 
sheet->button->style->ythickness + DEFAULT_FONT_DESCENT(GTK_WIDGET(sheet));
-*/
     y += 2*sheet->button->style->ythickness;
 
+
     if(button->label && strlen(button->label)>0){
+           gchar *words = 0;
            PangoLayout *layout = NULL;
            gint real_x = x, real_y = y;
 
@@ -6793,40 +6494,40 @@
              words++;
            }
            g_free(line);
-    }else{
-           PangoLayout *layout = NULL;
-           gint real_x = x, real_y = y;
+    }
+    if(button->label && strlen(button->label) > 0){
+      PangoLayout *layout = NULL;
+      gint real_x = x, real_y = y;
 
-           sprintf(label,"%d",index);
-           text_width = STRING_WIDTH(GTK_WIDGET(sheet), 
GTK_WIDGET(sheet)->style->font_desc, label);
+      text_width = STRING_WIDTH(GTK_WIDGET(sheet), 
GTK_WIDGET(sheet)->style->font_desc, button->label);
 
-           layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), label);
-           switch(button->justification){
-             case GTK_JUSTIFY_LEFT:
-               real_x = x + CELLOFFSET;
-               align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
-               break;
-             case GTK_JUSTIFY_RIGHT:
-               real_x = x + width - text_width - CELLOFFSET;
-               align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
-               break;
-             case GTK_JUSTIFY_CENTER:
-             default:
-               real_x = x + (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(G_OBJECT(layout));
+      layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), 
button->label);
+      switch(button->justification){
+      case GTK_JUSTIFY_LEFT:
+       real_x = x + CELLOFFSET;
+       align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
+       break;
+      case GTK_JUSTIFY_RIGHT:
+       real_x = x + width - text_width - CELLOFFSET;
+       align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
+       break;
+      case GTK_JUSTIFY_CENTER:
+      default:
+       real_x = x + (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(G_OBJECT(layout));
     }
 
     gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
@@ -6955,7 +6656,6 @@
   g_return_if_fail (data != NULL);
 
   sheet = GTK_SHEET (data);
-
 }
 
 
@@ -6983,22 +6683,20 @@
     
   old_value = -sheet->voffset;
 
-  for(i=0; i<= sheet->maxrow; i++){
-   if(sheet->row[i].is_visible) y+=sheet->row[i].height;
-   if(y > adjustment->value) break;
-  }
-  y-=sheet->row[i].height;
-  new_row=i;
+  new_row = g_sheet_row_pixel_to_row(sheet->row_geometry,
+                                    adjustment->value,sheet);
+
+  y = g_sheet_row_start_pixel(sheet->row_geometry, new_row, sheet);
 
   if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 
0. &&
-      sheet->row[i].height > sheet->vadjustment->step_increment){
+      yyy_row_height(sheet, i) > sheet->vadjustment->step_increment){
 /* This avoids embarrassing twitching */
-          if(row == new_row && row != sheet->maxrow &&
+          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+sheet->row[row].height;
+                y=y+yyy_row_height(sheet, row);
           }
   }
 
@@ -7013,11 +6711,10 @@
 
  
   if(new_row == 0){
-   sheet->vadjustment->step_increment=
-   sheet->row[0].height;
+   sheet->vadjustment->step_increment=  yyy_row_height(sheet, 0);
   }else{
    sheet->vadjustment->step_increment=
-   MIN(sheet->row[new_row].height, sheet->row[new_row-1].height);
+   MIN(yyy_row_height(sheet, new_row), yyy_row_height(sheet, new_row-1));
   }
 
   sheet->vadjustment->value=adjustment->value;
@@ -7089,22 +6786,23 @@
 
   old_value = -sheet->hoffset;
 
-  for(i=0; i<= sheet->maxcol; i++){
-   if(sheet->column[i].is_visible) x+=sheet->column[i].width;
-   if(x > adjustment->value) break;
-  }
-  x-=sheet->column[i].width;
+  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;
 
   if (adjustment->value > sheet->old_hadjustment && sheet->old_hadjustment > 0 
&&
-      sheet->column[i].width > sheet->hadjustment->step_increment){
+      xxx_column_width(sheet, i) > sheet->hadjustment->step_increment){
 /* This avoids embarrassing twitching */
-          if(column == new_column && column != sheet->maxcol &&
+          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=x+sheet->column[column].width;
+             x=x+xxx_column_width(sheet, column);
           }
   }
 
@@ -7119,10 +6817,10 @@
 
   if(new_column == 0){
    sheet->hadjustment->step_increment=
-   sheet->column[0].width;
+   xxx_column_width(sheet, 0);
   }else{
    sheet->hadjustment->step_increment=
-   MIN(sheet->column[new_column].width, sheet->column[new_column-1].width);
+   MIN(xxx_column_width(sheet, new_column), xxx_column_width(sheet, 
new_column-1));
   }
 
 
@@ -7218,9 +6916,9 @@
    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+
-                                        sheet->column[range.coli].width;
+                                        xxx_column_width(sheet, range.coli);
    area.height=ROW_TOP_YPIXEL(sheet, range.rowi)-area.y+
-                                        sheet->row[range.rowi].height;
+                                        yyy_row_height(sheet, range.rowi);
 
    clip_area.x=sheet->row_title_area.width;
    clip_area.y=sheet->column_title_area.height;
@@ -7250,7 +6948,7 @@
 
    gdk_gc_set_clip_rectangle(sheet->xor_gc, &clip_area);
 
-   for(i=-1;i<=1;i=++i)
+   for(i=-1;i<=1;++i)
      gdk_draw_rectangle(sheet->sheet_window,
                         sheet->xor_gc,
                        FALSE,
@@ -7274,16 +6972,16 @@
                  gint * x)
 {
   gint cx, width;
-  GtkRequisition requisition;
+  guint min_width;
 
   cx = *x;
 
-  requisition.width = sheet->column[column].requisition;
+  min_width = sheet->column_requisition;
 
   /* you can't shrink a column to less than its minimum width */
-  if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + requisition.width)
+  if (cx < COLUMN_LEFT_XPIXEL (sheet, column) + min_width)
     {
-      *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + requisition.width;
+      *x = cx = COLUMN_LEFT_XPIXEL (sheet, column) + min_width;
     }
 
   /* don't grow past the end of the window */
@@ -7296,11 +6994,10 @@
   /* 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 < requisition.width)
-    width = requisition.width;
+  if (width < min_width)
+    width = min_width;
 
-  sheet->column[column].width = width;
-  gtk_sheet_recalc_left_xpixels(sheet, column+1);
+  xxx_set_column_width(sheet, column, width);
   sheet->view.coli=COLUMN_FROM_XPIXEL(sheet, sheet->sheet_window_width);
   size_allocate_column_title_buttons (sheet);
   
@@ -7315,18 +7012,17 @@
                gint row,
                gint * y)
 {
-  GtkRequisition requisition;
   gint cy, height;
+  guint min_height;
 
   cy = *y;
-
-  requisition.height = sheet->row[row].requisition;
+  min_height = sheet->row_requisition;
 
   /* you can't shrink a row to less than its minimum height */
-  if (cy < ROW_TOP_YPIXEL (sheet, row) + requisition.height)
+  if (cy < ROW_TOP_YPIXEL (sheet, row) + min_height)
 
     {
-      *y = cy = ROW_TOP_YPIXEL (sheet, row) + requisition.height;
+      *y = cy = ROW_TOP_YPIXEL (sheet, row) + min_height;
     }
 
   /* don't grow past the end of the window */
@@ -7339,18 +7035,17 @@
   /* 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 < requisition.height)
-    height = requisition.height;
+  if (height < min_height)
+    height = min_height;
 
-  sheet->row[row].height = height;
-  gtk_sheet_recalc_top_ypixels(sheet, row);
+  yyy_set_row_height(sheet, row, height);
   sheet->view.rowi=ROW_FROM_YPIXEL(sheet, sheet->sheet_window_height-1);
   size_allocate_row_title_buttons (sheet);
 
   return height;
 }
 
-void
+static void
 gtk_sheet_set_column_width (GtkSheet * sheet,
                            gint column,
                            guint width)
@@ -7360,15 +7055,13 @@
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  if (column < 0 || column > sheet->maxcol)
+  if (column < 0 || column >= xxx_column_count(sheet))
     return;
 
   gtk_sheet_column_size_request(sheet, column, &min_width);
   if(width < min_width) return;
 
-  sheet->column[column].width = width;
-
-  gtk_sheet_recalc_left_xpixels(sheet, column+1);
+  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);
@@ -7382,6 +7075,8 @@
 
 }
 
+
+
 void
 gtk_sheet_set_row_height (GtkSheet * sheet,
                            gint row,
@@ -7392,15 +7087,13 @@
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  if (row < 0 || row > sheet->maxrow)
+  if (row < 0 || row >= yyy_row_count(sheet))
     return;
 
   gtk_sheet_row_size_request(sheet, row, &min_height);
   if(height < min_height) return;
 
-  sheet->row[row].height = height;
-
-  gtk_sheet_recalc_top_ypixels(sheet, row+1);
+  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);
@@ -7415,676 +7108,48 @@
 }
 
 
-void
-gtk_sheet_add_column(GtkSheet *sheet, guint ncols)
+gboolean
+gtk_sheet_get_attributes(GtkSheet *sheet, gint row, gint col, GtkSheetCellAttr 
*attributes)
 {
+ g_return_val_if_fail (sheet != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
 
- g_return_if_fail (sheet != NULL);
- g_return_if_fail (GTK_IS_SHEET (sheet));
-
- AddColumn(sheet, ncols);
-
- if(!GTK_WIDGET_REALIZED(sheet)) return;
+ if(row < 0 || col < 0) return FALSE;
 
- adjust_scrollbars(sheet);
+ init_attributes(sheet, col, attributes);
 
- if(sheet->state==GTK_SHEET_ROW_SELECTED) sheet->range.coli+=ncols;
+ if ( !sheet->model) 
+        return FALSE;
 
- sheet->old_hadjustment = -1.;
- if(!GTK_SHEET_IS_FROZEN(sheet) && sheet->hadjustment)
-      gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), 
-                              "value_changed");
-}
+ attributes->is_editable = g_sheet_model_is_editable(sheet->model, row, col);
+ attributes->is_visible = g_sheet_model_is_visible(sheet->model, row, col);
 
-void
-gtk_sheet_add_row(GtkSheet *sheet, guint nrows)
-{
+ const GdkColor *fg = g_sheet_model_get_foreground(sheet->model, row, col);
+ if ( fg ) 
+   attributes->foreground =  *fg;
 
- g_return_if_fail (sheet != NULL);
- g_return_if_fail (GTK_IS_SHEET (sheet));
+ const GdkColor *bg = g_sheet_model_get_background(sheet->model, row, col);
+ if ( bg ) 
+   attributes->background =  *bg;
 
- AddRow(sheet, nrows);
+ const GtkJustification *j = g_sheet_model_get_justification(sheet->model,
+                                                              row, col);
+ if (j)   attributes->justification = *j;
 
- if(!GTK_WIDGET_REALIZED(sheet)) return;
+ const PangoFontDescription *font_desc = 
+   g_sheet_model_get_font_desc(sheet->model, row, col);
+ if ( font_desc )  attributes->font_desc = font_desc;
 
- if(sheet->state==GTK_SHEET_COLUMN_SELECTED) sheet->range.rowi+=nrows;
+ const GtkSheetCellBorder *border = 
+  g_sheet_model_get_cell_border(sheet->model, row, col);
 
- adjust_scrollbars(sheet);
+ if ( border )    attributes->border = *border;
 
- sheet->old_vadjustment = -1.;
- if(!GTK_SHEET_IS_FROZEN(sheet) && sheet->vadjustment)
-      gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), 
-                              "value_changed");
+ return TRUE;
 }
 
-void
-gtk_sheet_insert_rows(GtkSheet *sheet, guint row, guint nrows)
-{
- GList *children;
- GtkSheetChild *child;
-
- 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);
-
- InsertRow(sheet, row, nrows);
-
- children = sheet->children;
- while(children)
-   {
-     child = (GtkSheetChild *)children->data;
-
-     if(child->attached_to_cell)
-        if(child->row >= row) child->row += nrows; 
-
-     children = children->next;
-   }
-
- if(!GTK_WIDGET_REALIZED(sheet)) return;
-
- if(sheet->state==GTK_SHEET_COLUMN_SELECTED) sheet->range.rowi+=nrows;
- adjust_scrollbars(sheet);
- 
- sheet->old_vadjustment = -1.;
- if(!GTK_SHEET_IS_FROZEN(sheet) && sheet->vadjustment)
-      gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), 
-                              "value_changed");
-
-}
-
-void
-gtk_sheet_insert_columns(GtkSheet *sheet, guint col, guint ncols)
-{
- GList *children;
- GtkSheetChild *child;
-
- 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);
-
- InsertColumn(sheet, col, ncols);
-
- children = sheet->children;
- while(children)
-   {
-     child = (GtkSheetChild *)children->data;
-
-     if(child->attached_to_cell)
-        if(child->col >= col) child->col += ncols; 
-
-     children = children->next;
-   }
-
- if(!GTK_WIDGET_REALIZED(sheet)) return;
-
- if(sheet->state==GTK_SHEET_ROW_SELECTED) sheet->range.coli+=ncols;
- adjust_scrollbars(sheet);
-
- sheet->old_hadjustment = -1.;
- if(!GTK_SHEET_IS_FROZEN(sheet) && sheet->hadjustment)
-      gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), 
-                              "value_changed");
-
-}
-
-void
-gtk_sheet_delete_rows(GtkSheet *sheet, guint row, guint nrows)
-{
- GList *children;
- GtkSheetChild *child;
- gint irow, icol;
- gboolean veto;
-
- g_return_if_fail (sheet != NULL);
- g_return_if_fail (GTK_IS_SHEET (sheet));
-
- nrows = MIN(nrows, sheet->maxrow-row+1);
-
- if(GTK_WIDGET_REALIZED(sheet))
-   gtk_sheet_real_unselect_range(sheet, NULL);
-
- DeleteRow(sheet, row, nrows);
-
- children = sheet->children;
- while(children)
-   {
-     child = (GtkSheetChild *)children->data;
-
-     if(child->attached_to_cell &&
-        child->row >= row && child->row < row+nrows){  
-              gtk_container_remove(GTK_CONTAINER(sheet), child->widget);
-              children = sheet->children;
-     } else
-        children = children->next;
-   }
-
- children = sheet->children;
- while(children)
-   {
-     child = (GtkSheetChild *)children->data;
-
-     if(child->attached_to_cell && child->row > row) child->row -= nrows; 
-     children = children->next;
-   }
-
- if(!GTK_WIDGET_REALIZED(sheet)) return;
-
- irow = sheet->active_cell.row;
- icol = sheet->active_cell.col;
-
- sheet->active_cell.row = -1;
- sheet->active_cell.col = -1;
-
-/* if(sheet->state == GTK_SHEET_ROW_SELECTED)
-*/
-
- irow = MIN(irow, sheet->maxrow);
- irow = MAX(irow, 0);
- gtk_sheet_click_cell(sheet, irow, icol, &veto);
-
- gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
-                                       sheet->active_cell.col);
-
- adjust_scrollbars(sheet);
-
- sheet->old_vadjustment = -1.;
- if(!GTK_SHEET_IS_FROZEN(sheet) && sheet->vadjustment)
-      gtk_signal_emit_by_name (GTK_OBJECT (sheet->vadjustment), 
-                              "value_changed");
-
-}
-
-void
-gtk_sheet_delete_columns(GtkSheet *sheet, guint col, guint ncols)
-{
- GList *children;
- GtkSheetChild *child;
- gint irow, icol;
- gboolean veto;
-
- g_return_if_fail (sheet != NULL);
- g_return_if_fail (GTK_IS_SHEET (sheet));
-
- ncols = MIN(ncols, sheet->maxcol-col+1);
-
- if(GTK_WIDGET_REALIZED(sheet))
-   gtk_sheet_real_unselect_range(sheet, NULL);
-
- DeleteColumn(sheet, col, ncols);
-
- children = sheet->children;
- while(children)
-   {
-     child = (GtkSheetChild *)children->data;
-
-     if(child->attached_to_cell &&
-        child->col >= col && child->col < col+ncols){  
-              gtk_container_remove(GTK_CONTAINER(sheet), child->widget);
-              children = sheet->children;
-     } else
-        children = children->next;
-   }
-
- children = sheet->children;
- while(children)
-   {
-     child = (GtkSheetChild *)children->data;
-
-     if(child->attached_to_cell && child->col > col) child->col -= ncols; 
-     children = children->next;
-   }
-
- if(!GTK_WIDGET_REALIZED(sheet)) return;
-
- irow = sheet->active_cell.row;
- icol = sheet->active_cell.col;
-
- sheet->active_cell.row = -1;
- sheet->active_cell.col = -1;
-
-/* if(sheet->state == GTK_SHEET_COLUMN_SELECTED)
-*/
-
- icol = MIN(icol, sheet->maxcol);
- icol = MAX(icol, 0);
- gtk_sheet_click_cell(sheet, irow, icol, &veto);
-
- gtk_sheet_activate_cell(sheet, sheet->active_cell.row,
-                                       sheet->active_cell.col);
-
- adjust_scrollbars(sheet);
-
- sheet->old_hadjustment = -1.;
- if(!GTK_SHEET_IS_FROZEN(sheet) && sheet->hadjustment)
-      gtk_signal_emit_by_name (GTK_OBJECT (sheet->hadjustment), 
-                              "value_changed");
-
-}
-
-
-void
-gtk_sheet_set_coding(GtkSheet *sheet, GtkSheetEncodeFunc encode, 
-                    GtkSheetDecodeFunc decode,
-                    gpointer data)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  sheet->encode_func = encode;
-  sheet->decode_func = decode;
-  sheet->coding_data = data;
-}
-
-
-void
-gtk_sheet_range_set_type(GtkSheet *sheet, const GtkSheetRange *urange, 
-                        GType type, Conversion convert)
-{
-  gint i, j;
-  GtkSheetRange range;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(!urange) 
-    range = sheet->range;
-  else
-    range = *urange;
-
-  for (i=range.row0; i<=range.rowi; i++)
-    {
-      for (j=range.col0; j<=range.coli; j++)
-       {
-         GtkSheetCell *cell;
-
-         CheckBounds(sheet, i, j);
-
-         cell = sheet->data[i][j];
-
-         if(cell == NULL) 
-           {
-             cell = gtk_sheet_cell_new();
-             cell->row = i;
-             cell->col = j;
-           }
-
-         if ( G_IS_VALUE(&cell->value))
-           {
-
-             if ( G_VALUE_TYPE(&cell->value) == type )
-               continue;
-
-             if ( convert) 
-               {
-                 convert(type, i, j, &cell->value);
-               }
-             else
-               {
-                 GValue new_value = {0};             
-                 g_value_init(&new_value, type);
-                 if (!g_value_transform(&cell->value, &new_value))
-                   {
-                     g_warning("Failed to transform cell value at %d, %d\n", 
-                               i, j);
-                     g_value_unset(&cell->value);
-                     g_value_init(&cell->value, type);
-                     continue;
-                   }
-                 g_value_unset(&cell->value);
-                 g_value_init(&cell->value, type);
-                 g_value_copy(&new_value, &cell->value);
-
-                 g_value_unset(&new_value);
-               }
-           }
-         else
-           g_value_init(&cell->value, type);
-       }
-    }
-}
-
-void
-gtk_sheet_range_set_background(GtkSheet *sheet, const GtkSheetRange *urange, 
const GdkColor *color)
-{
-  gint i, j;
-  GtkSheetCellAttr attributes;
-  GtkSheetRange range;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(!urange) 
-     range = sheet->range;
-  else
-     range = *urange;
-
-  for (i=range.row0; i<=range.rowi; i++)
-    for (j=range.col0; j<=range.coli; j++){
-      gtk_sheet_get_attributes(sheet, i, j, &attributes);
-      if(color != NULL)
-        attributes.background = *color;
-      else
-        attributes.background = sheet->bg_color;
- 
-      gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 
-    }
-
-  range.row0--;
-  range.col0--;
-  range.rowi++;
-  range.coli++;
-
-  if(!GTK_SHEET_IS_FROZEN(sheet))
-      gtk_sheet_range_draw(sheet, &range);
-
-}
-
-void
-gtk_sheet_range_set_foreground(GtkSheet *sheet, const GtkSheetRange *urange, 
const GdkColor *color)
-{
-  gint i, j;
-  GtkSheetCellAttr attributes;
-  GtkSheetRange range;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(!urange) 
-     range = sheet->range;
-  else
-     range = *urange;
-
-  for (i=range.row0; i<=range.rowi; i++)
-    for (j=range.col0; j<=range.coli; j++){
-      gtk_sheet_get_attributes(sheet, i, j, &attributes);
-
-      if(color != NULL)
-        attributes.foreground = *color;
-      else
-        gdk_color_black(gdk_colormap_get_system(), &attributes.foreground);
- 
-      gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 
-    }
-
-  if(!GTK_SHEET_IS_FROZEN(sheet))
-      gtk_sheet_range_draw(sheet, &range);
-
-}
-
-void
-gtk_sheet_range_set_justification(GtkSheet *sheet, const GtkSheetRange 
*urange, 
-                                  GtkJustification just)
-{
-  gint i, j;
-  GtkSheetCellAttr attributes;
-  GtkSheetRange range;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(!urange) 
-     range = sheet->range;
-  else
-     range = *urange;
-
-  for (i=range.row0; i<=range.rowi; i++)
-    for (j=range.col0; j<=range.coli; j++){
-      gtk_sheet_get_attributes(sheet, i, j, &attributes);
-      attributes.justification = just;
-      gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 
-    }
-
-  range.col0 = sheet->view.col0;    
-  range.coli = sheet->view.coli;    
-
-  if(!GTK_SHEET_IS_FROZEN(sheet))
-      gtk_sheet_range_draw(sheet, &range);
-
-}
-
-void
-gtk_sheet_column_set_justification(GtkSheet *sheet, gint col, 
-                                   GtkJustification justification)
-{
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(col > sheet->maxcol) return;
-
-  sheet->column[col].justification = justification;
-  
-  if(GTK_WIDGET_REALIZED(sheet) && !GTK_SHEET_IS_FROZEN(sheet) &&
-     col >= MIN_VISIBLE_COLUMN(sheet) && col <= MAX_VISIBLE_COLUMN(sheet))
-          gtk_sheet_range_draw(sheet, NULL);
-
-}
-
-void
-gtk_sheet_range_set_editable(GtkSheet *sheet, const GtkSheetRange *urange, 
gboolean editable)
-{
-  gint i, j;
-  GtkSheetCellAttr attributes;
-  GtkSheetRange range;
- 
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(!urange) 
-     range = sheet->range;
-  else
-     range = *urange;
-
-  for (i=range.row0; i<=range.rowi; i++)
-    for (j=range.col0; j<=range.coli; j++){
-      gtk_sheet_get_attributes(sheet, i, j, &attributes);
-      attributes.is_editable = editable;
-      gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 
-    }
- 
-  if(!GTK_SHEET_IS_FROZEN(sheet))
-      gtk_sheet_range_draw(sheet, &range);
-
-}
-
-void
-gtk_sheet_range_set_visible(GtkSheet *sheet, const GtkSheetRange *urange, 
gboolean visible)
-{
-  gint i, j;
-  GtkSheetCellAttr attributes;
-  GtkSheetRange range;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(!urange) 
-     range = sheet->range;
-  else
-     range = *urange;
-
-  for (i=range.row0; i<=range.rowi; i++)
-    for (j=range.col0; j<=range.coli; j++){
-      gtk_sheet_get_attributes(sheet, i, j, &attributes);
-      attributes.is_visible=visible;
-      gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 
-    }
- 
-  if(!GTK_SHEET_IS_FROZEN(sheet))
-      gtk_sheet_range_draw(sheet, &range);
-
-}
-
-void
-gtk_sheet_range_set_border(GtkSheet *sheet, const GtkSheetRange *urange, gint 
mask, 
-guint width, gint line_style)
-{
-  gint i, j;
-  GtkSheetCellAttr attributes;
-  GtkSheetRange range;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(!urange) 
-     range = sheet->range;
-  else
-     range = *urange;
-
-  for (i=range.row0; i<=range.rowi; i++)
-    for (j=range.col0; j<=range.coli; j++){
-      gtk_sheet_get_attributes(sheet, i, j, &attributes);
-      attributes.border.mask = mask;
-      attributes.border.width = width;
-      attributes.border.line_style=line_style;
-      attributes.border.cap_style=GDK_CAP_NOT_LAST;
-      attributes.border.join_style=GDK_JOIN_MITER;
-      gtk_sheet_set_cell_attributes(sheet, i, j, attributes);      
-    }
-
-  range.row0--; 
-  range.col0--; 
-  range.rowi++; 
-  range.coli++; 
-
-  if(!GTK_SHEET_IS_FROZEN(sheet))
-      gtk_sheet_range_draw(sheet, &range);
-
-}
-
-void
-gtk_sheet_range_set_border_color(GtkSheet *sheet, const GtkSheetRange *urange, 
const GdkColor *color)
-{
-  gint i, j;
-  GtkSheetCellAttr attributes;
-  GtkSheetRange range;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(!urange) 
-     range = sheet->range;
-  else
-     range = *urange;
-
-  for (i=range.row0; i<=range.rowi; i++)
-    for (j=range.col0; j<=range.coli; j++){
-      gtk_sheet_get_attributes(sheet, i, j, &attributes);
-      attributes.border.color = *color;
-      gtk_sheet_set_cell_attributes(sheet, i, j, attributes); 
-    }
- 
-  if(!GTK_SHEET_IS_FROZEN(sheet))
-      gtk_sheet_range_draw(sheet, &range);
-
-}
-
-void
-gtk_sheet_range_set_font(GtkSheet *sheet, const GtkSheetRange *urange, 
PangoFontDescription *font)
-{
-  gint i, j;
-  gint font_height;
-  GtkSheetCellAttr attributes;
-  GtkSheetRange range;
-  PangoContext *context;
-  PangoFontMetrics *metrics;
-
-  g_return_if_fail (sheet != NULL);
-  g_return_if_fail (GTK_IS_SHEET (sheet));
-
-  if(!urange) 
-     range = sheet->range;
-  else
-     range = *urange;
-
-  gtk_sheet_freeze(sheet);
-
-  context = gtk_widget_get_pango_context(GTK_WIDGET(sheet)); 
-  metrics = pango_context_get_metrics(context,
-                                font,
-                                pango_context_get_language(context)); 
-  font_height = pango_font_metrics_get_descent(metrics) + 
-                pango_font_metrics_get_ascent(metrics);
-  font_height = PANGO_PIXELS(font_height) + 2*CELLOFFSET;
-
-  for (i=range.row0; i<=range.rowi; i++)
-    for (j=range.col0; j<=range.coli; j++){
-      gtk_sheet_get_attributes(sheet, i, j, &attributes);
-      attributes.font_desc = font; 
-      if(font_height > sheet->row[i].height){
-          sheet->row[i].height = font_height;
-          gtk_sheet_recalc_top_ypixels(sheet, i);
-      }
-
-      gtk_sheet_set_cell_attributes(sheet, i, j, attributes);  
-    }
-
-  gtk_sheet_thaw(sheet);
-  pango_font_metrics_unref(metrics);
-}
-
-static void
-gtk_sheet_set_cell_attributes(GtkSheet *sheet, gint row, gint col, 
GtkSheetCellAttr attributes)
-{
-  GtkSheetCell **cell;
-
-  if(row > sheet->maxrow || col >sheet->maxcol) return;
-
-  CheckBounds(sheet, row, col);
-
-  cell = &sheet->data[row][col];
-
-  if(*cell==NULL){
-   (*cell) = gtk_sheet_cell_new();
-   (*cell)->row = row;
-   (*cell)->col = col;
-  }
-
-  if((*cell)->attributes == NULL) 
-      (*cell)->attributes = g_new(GtkSheetCellAttr, 1);
-
-  *((*cell)->attributes) = attributes;
-}
-
-gboolean
-gtk_sheet_get_attributes(GtkSheet *sheet, gint row, gint col, GtkSheetCellAttr 
*attributes)
-{
- GtkSheetCell **cell = NULL;
-
- 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;
-
- if(row > sheet->maxallocrow || col > sheet->maxalloccol){
-    init_attributes(sheet, col, attributes);
-    return FALSE;
- }
-
- if(row <= sheet->maxallocrow && col <= sheet->maxalloccol){
-    if(sheet->data[row] && sheet->data[row][col])
-                                    cell = &sheet->data[row][col];
-    if(cell == NULL || *cell == NULL){
-      init_attributes(sheet, col, attributes);
-      return FALSE;
-    } else
-      if((*cell)->attributes == NULL){
-         init_attributes(sheet, col, attributes);
-         return FALSE;
-      }else{
-         *attributes = *(sheet->data[row][col]->attributes);
-         if(sheet->column[col].justification != GTK_JUSTIFY_FILL)
-              attributes->justification = sheet->column[col].justification;
-      }
- }   
- 
- return TRUE;
-}
-
-static void
-init_attributes(GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
+static void
+init_attributes(GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
 {
  /* DEFAULT VALUES */    
  attributes->foreground = GTK_WIDGET(sheet)->style->black;
@@ -8095,7 +7160,7 @@
    gdk_color_black(colormap, &attributes->foreground);
    attributes->background = sheet->bg_color;
  }
- attributes->justification = sheet->column[col].justification;
+ 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;
@@ -8104,349 +7169,11 @@
  attributes->border.color = GTK_WIDGET(sheet)->style->black;
  attributes->is_editable = TRUE;
  attributes->is_visible = TRUE;
- attributes->font = GTK_WIDGET(sheet)->style->private_font;
  attributes->font_desc = GTK_WIDGET(sheet)->style->font_desc;
 
 }       
  
-/**********************************************************************
- * Memory allocation routines: 
- * AddRow & AddColumn allocate memory for GtkSheetColumn & GtkSheetRow structs.
- * InsertRow 
- * InsertColumn
- * DeleteRow
- * DeleteColumn
- * GrowSheet allocates memory for the sheet cells contents using an array of 
- * pointers. Alternative to this could be a linked list or a hash table.
- * CheckBounds checks whether the given cell is currently allocated or not. 
- * If not, it calls to GrowSheet.
- **********************************************************************/
 
-static gint
-AddColumn(GtkSheet *tbl, gint ncols)
-{
-   gint i;
-
-   if(ncols == -1 && tbl->maxcol == 0)
-     {
-       ncols = 1;
-     }
-   else
-     {
-       tbl->maxcol += ncols;
-       tbl->column = (GtkSheetColumn *)g_realloc(tbl->column,(tbl->maxcol+1)*
-                                                 sizeof(GtkSheetColumn));
-     }
-
-   for(i=tbl->maxcol-ncols+1; i<= tbl->maxcol; i++){
-        tbl->column[i].width=DEFAULT_COLUMN_WIDTH;
-       tbl->column[i].button.label=NULL;
-       tbl->column[i].button.child=NULL;
-        tbl->column[i].button.state=GTK_STATE_NORMAL;
-        tbl->column[i].button.justification=GTK_JUSTIFY_CENTER;
-        tbl->column[i].button.label_visible = TRUE;
-        tbl->column[i].name=NULL;
-        tbl->column[i].is_visible=TRUE;
-        tbl->column[i].is_sensitive=TRUE;
-        tbl->column[i].left_text_column=i;
-        tbl->column[i].right_text_column=i;
-        tbl->column[i].justification=GTK_JUSTIFY_FILL;
-        tbl->column[i].requisition=DEFAULT_COLUMN_WIDTH;
-        if(i>0)
-        {
-           tbl->column[i].left_text_column=tbl->column[i-1].left_text_column;
-           tbl->column[i].left_xpixel=tbl->column[i-1].left_xpixel +
-                                     tbl->column[i-1].width;
-       }
-        else
-        {
-          tbl->column[i].left_xpixel=tbl->row_title_area.width;
-          if(!tbl->row_titles_visible) 
-                        tbl->column[i].left_xpixel=0;
-        }
-   }
-   return TRUE;
-}
-
-static gint
-AddRow(GtkSheet *tbl, gint nrows)
-{
-   gint i;
-
-   if(nrows == -1 && tbl->maxrow == 0)
-     {
-       nrows = 1;
-     }
-   else
-     {
-       tbl->maxrow += nrows;
-       tbl->row = (GtkSheetRow *)g_realloc(tbl->row,(tbl->maxrow+1)*
-                                            sizeof(GtkSheetRow));
-     }
-
-   for(i=tbl->maxrow-nrows+1; i<= tbl->maxrow; i++){
-        
tbl->row[i].requisition=tbl->row[i].height=DEFAULT_ROW_HEIGHT(GTK_WIDGET(tbl));
-       tbl->row[i].button.label=NULL;
-       tbl->row[i].button.child=NULL;
-        tbl->row[i].button.state=GTK_STATE_NORMAL;
-        tbl->row[i].button.justification=GTK_JUSTIFY_CENTER;
-        tbl->row[i].button.label_visible = TRUE;
-        tbl->row[i].name=NULL;
-        tbl->row[i].is_visible=TRUE;
-        tbl->row[i].is_sensitive=TRUE;
-        if(i>0)
-           
tbl->row[i].top_ypixel=tbl->row[i-1].top_ypixel+tbl->row[i-1].height;
-       else
-        {
-          tbl->row[i].top_ypixel=tbl->column_title_area.height;
-           if(!tbl->column_titles_visible) 
-                        tbl->row[i].top_ypixel=0;
-        } 
-   }
-   return TRUE;
-}
-
-static gint
-InsertRow(GtkSheet *tbl, gint row, gint nrows)
-{
-  GtkSheetCell **pp;
-  gint i,j;
-  GtkSheetCell **auxdata;
-  GtkSheetRow auxrow;
-
-  AddRow(tbl,nrows);
-
-  for(i=tbl->maxrow; i>=row+nrows; i--){
-    auxrow = tbl->row[i];  
-    tbl->row[i]=tbl->row[i-nrows];    
-    tbl->row[i].is_visible=tbl->row[i-nrows].is_visible;
-    tbl->row[i].is_sensitive=tbl->row[i-nrows].is_sensitive;
-    if(auxrow.is_visible) 
-               
tbl->row[i].top_ypixel+=nrows*DEFAULT_ROW_HEIGHT(GTK_WIDGET(tbl));
-    tbl->row[i-nrows]=auxrow;
-  }
-
-  if(row <= tbl->maxallocrow){
-   
-    GrowSheet(tbl,nrows,0);
-
-    for(i=tbl->maxallocrow; i>=row+nrows; i--){
-      auxdata = tbl->data[i];
-      tbl->data[i]=tbl->data[i-nrows];
-
-      pp= tbl->data[i];
-      for(j=0; j<=tbl->maxalloccol; j++,pp++){
-        if(*pp!=(GtkSheetCell *)NULL)
-                                    (*pp)->row=i;
-      
-      }
-      tbl->data[i-nrows]=auxdata;
-    }
-  }
-  gtk_sheet_recalc_top_ypixels(tbl, 0);
-  return TRUE;
-}  
-
-static gint 
-InsertColumn(GtkSheet *tbl, gint col, gint ncols)
-{
-  gint i,j;
-  GtkSheetColumn auxcol;
-
-  AddColumn(tbl,ncols);
-
-  for(i=tbl->maxcol; i>=col+ncols; i--){
-    auxcol = tbl->column[i];
-    tbl->column[i]=tbl->column[i-ncols];
-    tbl->column[i].is_visible=tbl->column[i-ncols].is_visible;
-    tbl->column[i].is_sensitive=tbl->column[i-ncols].is_sensitive;
-    tbl->column[i].left_text_column=tbl->column[i-ncols].left_text_column;
-    tbl->column[i].right_text_column=tbl->column[i-ncols].right_text_column;
-    tbl->column[i].justification=tbl->column[i-ncols].justification;
-    if(auxcol.is_visible) 
tbl->column[i].left_xpixel+=ncols*DEFAULT_COLUMN_WIDTH;
-    tbl->column[i-ncols]=auxcol;
-  }
-
-  if(col <= tbl->maxalloccol){
-   
-    GrowSheet(tbl,0,ncols);
-
-    for(i=0; i<=tbl->maxallocrow; i++){
-      for(j=tbl->maxalloccol; j>=col+ncols; j--){
-        gtk_sheet_real_cell_clear(tbl, i, j, TRUE);
-        tbl->data[i][j]=tbl->data[i][j-ncols];
-        if(tbl->data[i][j]) tbl->data[i][j]->col=j;
-        tbl->data[i][j-ncols]=NULL;
-      }
-    }
-  }
-  gtk_sheet_recalc_left_xpixels(tbl, 0);
-  return TRUE;
-}
-
-static gint
-DeleteRow(GtkSheet *tbl, gint row, gint nrows)
-{
-  GtkSheetCell **auxdata = NULL;
-  gint i,j;
-
-  if(nrows <= 0 || row > tbl->maxrow) return TRUE;
-
-  nrows=MIN(nrows,tbl->maxrow-row+1);
-
-  for(i=row; i<row+nrows; i++){
-    if(tbl->row[i].name){
-            g_free(tbl->row[i].name);
-            tbl->row[i].name = NULL;
-    }
-    if(tbl->row[i].button.label){
-            g_free(tbl->row[i].button.label);
-            tbl->row[i].button.label = NULL;
-    }
-  }           
-
-  for(i=row; i<=tbl->maxrow-nrows; i++){
-    if(i+nrows <= tbl->maxrow){ 
-      tbl->row[i]=tbl->row[i+nrows];
-    }
-  }
-
-  if(row <= tbl->maxallocrow){
-
-    for(i=row; i<=tbl->maxrow-nrows; i++){
-      if(i<=tbl->maxallocrow){
-        auxdata=tbl->data[i];
-        for(j=0; j<=tbl->maxalloccol; j++){
-              gtk_sheet_real_cell_clear(tbl, i, j, TRUE);
-        }
-      }
-      if(i+nrows<=tbl->maxallocrow){
-        tbl->data[i]=tbl->data[i+nrows];
-        tbl->data[i+nrows]=auxdata;
-        for(j=0; j<=tbl->maxalloccol; j++){
-            if(tbl->data[i][j]) tbl->data[i][j]->row=i;
-        }
-      }
-    }
-
-    for(i=tbl->maxrow-nrows+1; i<=tbl->maxallocrow; i++){
-           if(i > 0 && tbl->data[i]){
-                g_free(tbl->data[i]);
-                tbl->data[i] = NULL;
-           }
-    }
-
-    tbl->maxallocrow-=MIN(nrows,tbl->maxallocrow-row+1);
-    tbl->maxallocrow = MIN(tbl->maxallocrow, tbl->maxrow);
-
-  }
-
-  tbl->maxrow-=nrows;
-  gtk_sheet_recalc_top_ypixels(tbl, 0);
-  return TRUE;
-} 
-
-static gint
-DeleteColumn(GtkSheet *tbl, gint column, gint ncols)
-{
-  gint i,j;
-  GtkSheetColumn auxcol;
-
-  ncols = MIN(ncols,tbl->maxcol-column+1);
-
-  if(ncols <= 0 || column > tbl->maxcol) return TRUE;
-
-  for(i=column; i<column+ncols; i++){
-    auxcol=tbl->column[i];
-    if(tbl->column[i].name){
-             g_free(tbl->column[i].name);
-             tbl->column[i].name = NULL;
-    }
-    if(tbl->column[i].button.label){
-             g_free(tbl->column[i].button.label);
-             tbl->column[i].button.label = NULL;
-    }
-  }
-
-  for(i=column; i<=tbl->maxcol-ncols; i++){
-    if(i+ncols <= tbl->maxcol){
-      tbl->column[i]=tbl->column[i+ncols];    
-    } 
-  }
-
-  if(column <= tbl->maxalloccol){
-
-    for(i=column; i<=tbl->maxcol-ncols; i++){
-      if(i<=tbl->maxalloccol){
-        for(j=0; j<=tbl->maxallocrow; j++){
-              gtk_sheet_real_cell_clear(tbl, j, i, TRUE);
-              if(i+ncols <= tbl->maxalloccol){
-                  tbl->data[j][i] = tbl->data[j][i+ncols];
-                  tbl->data[j][i+ncols] = NULL;
-                 if(tbl->data[j][i]) tbl->data[j][i]->col=i;
-              }
-        }
-      }
-
-    }
-
-    tbl->maxalloccol-=MIN(ncols,tbl->maxalloccol-column+1);
-    tbl->maxalloccol = MIN(tbl->maxalloccol, tbl->maxcol);
-  }
-  tbl->maxcol-=ncols;
-  gtk_sheet_recalc_left_xpixels(tbl, 0);
-  return TRUE;
-}  
-
-static gint
-GrowSheet(GtkSheet *tbl, gint newrows, gint newcols)
-{
-  gint i,j;
-  gint inirow, inicol;
-
-  inirow = tbl->maxallocrow + 1;  
-  inicol = tbl->maxalloccol + 1;  
-
-  tbl->maxalloccol = tbl->maxalloccol + newcols;
-  tbl->maxallocrow = tbl->maxallocrow + newrows;
-
-  if(newrows>0){
-      tbl->data = (GtkSheetCell***)
-                 g_realloc(tbl->data,(tbl->maxallocrow+1)*sizeof(GtkSheetCell 
**)+sizeof(double));
-
-      for(i=inirow; i <= tbl->maxallocrow; i++){
-        tbl->data[i] = (GtkSheetCell **) \
-                       g_malloc((tbl->maxcol+1)*sizeof(GtkSheetCell 
*)+sizeof(double));
-        for(j=0; j<inicol; j++) {
-          tbl->data[i][j] = NULL;
-        }
-      }
-          
-  }
-
-  if(newcols>0){
-      for(i=0; i <= tbl->maxallocrow; i++) {
-        tbl->data[i] = (GtkSheetCell **) \
-                       
g_realloc(tbl->data[i],(tbl->maxalloccol+1)*sizeof(GtkSheetCell 
*)+sizeof(double));
-        for(j=inicol; j <= tbl->maxalloccol; j++) {
-          tbl->data[i][j] = NULL;
-       }
-      }
-  }
-
-  return(0);
-}         
-
-static gint
-CheckBounds(GtkSheet *tbl, gint row, gint col)
-{
-  gint newrows=0,newcols=0;
-
-  if(col>tbl->maxalloccol) newcols=col-tbl->maxalloccol;
-  if(row>tbl->maxallocrow) newrows=row-tbl->maxallocrow;
-  if(newrows>0 || newcols>0) GrowSheet(tbl, newrows, newcols);
-  return(0);
-} 
 
 /********************************************************************
  * Container Functions:
@@ -8636,33 +7363,11 @@
   child->xshrink = child->yshrink = FALSE;
   child->xfill = child->yfill = FALSE;
 
-  if(row == -1){
-     button = &sheet->column[col].button;
-     button->child = child;
-  }
-  else
-  {
-     button = &sheet->row[row].button;
-     button->child = child;
-  }
 
   sheet->children = g_list_append(sheet->children, child);
 
   gtk_sheet_button_size_request(sheet, button, &button_requisition);
 
-  if(row == -1){
-       if(button_requisition.height > sheet->column_title_area.height)
-             sheet->column_title_area.height = button_requisition.height; 
-       if(button_requisition.width > sheet->column[col].width)
-             sheet->column[col].width = button_requisition.width; 
-  }
-
-  if(col == -1){
-       if(button_requisition.width > sheet->row_title_area.width)
-             sheet->row_title_area.width = button_requisition.width; 
-       if(button_requisition.height > sheet->row[row].height)
-             sheet->row[row].height = button_requisition.height; 
-  }
 
   if (GTK_WIDGET_VISIBLE(GTK_WIDGET(sheet)))
     {
@@ -8710,7 +7415,7 @@
 
 static void
 gtk_sheet_button_size_request  (GtkSheet *sheet,
-                                 GtkSheetButton *button, 
+                                 const GtkSheetButton *button, 
                                  GtkRequisition *button_requisition)
 {
   GtkRequisition requisition;
@@ -8753,7 +7458,9 @@
   GtkRequisition button_requisition;
   GList *children;
 
-  gtk_sheet_button_size_request(sheet, &sheet->row[row].button, 
&button_requisition);
+  gtk_sheet_button_size_request(sheet, 
+                               yyy_row_button(sheet, row),
+                               &button_requisition);
 
   *requisition = button_requisition.height;
 
@@ -8771,7 +7478,7 @@
     children = children->next;
   }
 
-  sheet->row[row].requisition = *requisition;
+  sheet->row_requisition = * requisition;
 }
 
 static void
@@ -8782,7 +7489,9 @@
   GtkRequisition button_requisition;
   GList *children;
 
-  gtk_sheet_button_size_request(sheet, &sheet->column[col].button, 
&button_requisition);
+  gtk_sheet_button_size_request(sheet, 
+                               xxx_column_button(sheet, col),
+                               &button_requisition);
 
   *requisition = button_requisition.width;
 
@@ -8800,7 +7509,7 @@
     children = children->next;
   }
 
-  sheet->column[col].requisition = *requisition;
+  sheet->column_requisition = *requisition;
 }
 
 void
@@ -8861,8 +7570,8 @@
       if(sheet->column_titles_visible) 
                                     child->y-=sheet->column_title_area.height;
 
-      width = sheet->column[child->col].width;
-      height = sheet->row[child->row].height;
+      width = xxx_column_width(sheet, child->col);
+      height = yyy_row_height(sheet, child->row);
 */
       
       gtk_sheet_get_cell_area(sheet, child->row, child->col, &area);
@@ -8870,12 +7579,12 @@
       child->y = area.y + child->ypadding;
 
       if(!child->floating){
-        if(child_requisition.width + 2*child->xpadding <= 
sheet->column[child->col].width){
+        if(child_requisition.width + 2*child->xpadding <= 
xxx_column_width(sheet, child->col)){
           if(child->xfill){
-            child_requisition.width = child_allocation.width = 
sheet->column[child->col].width - 2*child->xpadding;
+            child_requisition.width = child_allocation.width = 
xxx_column_width(sheet, child->col) - 2*child->xpadding;
           } else {
             if(child->xexpand){
-              child->x = area.x + sheet->column[child->col].width / 2 -
+              child->x = area.x + xxx_column_width(sheet, child->col) / 2 -
                                   child_requisition.width / 2;
             }
             child_allocation.width = child_requisition.width;
@@ -8884,15 +7593,15 @@
           if(!child->xshrink){
             gtk_sheet_set_column_width(sheet, child->col, 
child_requisition.width + 2 * child->xpadding);
           }
-          child_allocation.width = sheet->column[child->col].width - 
2*child->xpadding;
+          child_allocation.width = xxx_column_width(sheet, child->col) - 
2*child->xpadding;
         }
 
-        if(child_requisition.height + 2*child->ypadding <= 
sheet->row[child->row].height){
+        if(child_requisition.height + 2*child->ypadding <= 
yyy_row_height(sheet, child->row)){
           if(child->yfill){
-            child_requisition.height = child_allocation.height = 
sheet->row[child->row].height - 2*child->ypadding;
+            child_requisition.height = child_allocation.height = 
yyy_row_height(sheet, child->row) - 2*child->ypadding;
           } else {
             if(child->yexpand){
-              child->y = area.y + sheet->row[child->row].height / 2 -
+              child->y = area.y + yyy_row_height(sheet, child->row) / 2 -
                                   child_requisition.height / 2;
             }
             child_allocation.height = child_requisition.height;
@@ -8901,7 +7610,7 @@
           if(!child->yshrink){
             gtk_sheet_set_row_height(sheet, child->row, 
child_requisition.height + 2 * child->ypadding);
           }
-          child_allocation.height = sheet->row[child->row].height - 
2*child->ypadding;
+          child_allocation.height = yyy_row_height(sheet, child->row) - 
2*child->ypadding;
         }
       } else {
         child_allocation.width = child_requisition.width;
@@ -9014,12 +7723,6 @@
 
   if (children)
    {
-     if(child->row == -1)
-        sheet->row[child->col].button.child = NULL;
-
-     if(child->col == -1)
-        sheet->column[child->row].button.child = NULL;
-
      gtk_widget_unparent (widget);
      child->widget = NULL;
 
@@ -9091,3 +7794,12 @@
 
   gtk_widget_show(child->widget);
 }
+
+GSheetModel *
+gtk_sheet_get_model(const GtkSheet *sheet)
+{
+  g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
+
+  return sheet->model;
+}
+
Index: psppire/gtk_sheet/gtksheet.h
diff -u psppire/gtk_sheet/gtksheet.h:1.6 psppire/gtk_sheet/gtksheet.h:1.7
--- psppire/gtk_sheet/gtksheet.h:1.6    Fri Dec 23 23:34:03 2005
+++ psppire/gtk_sheet/gtksheet.h        Sat Jan 28 08:48:08 2006
@@ -1,3 +1,7 @@
+/* This version of GtkSheet has been heavily modified, for the specific 
+   requirements of PSPPIRE. */
+
+
 /* GtkSheet widget for Gtk+.
  * Copyright (C) 1999-2001 Adrian E. Feiguin <address@hidden>
  *
@@ -5,24 +9,30 @@
  * Memory allocation routines inspired on SC (Spreadsheet Calculator)
  *
  * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * 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.
+ * 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
- * Library General Public License for more details.
+ * Lesser 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.
+ * 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 __GTK_SHEET_H__
 #define __GTK_SHEET_H__
 
+#include <gtk/gtk.h>
+
+#include "gtkextra-sheet.h"
+#include "gsheetmodel.h"
+#include "gsheet-column-iface.h"
+#include "gsheet-row-iface.h"
+
 
 #ifdef __cplusplus
 extern "C" {
@@ -51,13 +61,6 @@
   GTK_SHEET_RANGE_SELECTED
 };
      
-enum
-{
-  GTK_SHEET_LEFT_BORDER     = 1 << 0, 
-  GTK_SHEET_RIGHT_BORDER    = 1 << 1, 
-  GTK_SHEET_TOP_BORDER      = 1 << 2, 
-  GTK_SHEET_BOTTOM_BORDER   = 1 << 3 
-}; 
 
 #define GTK_TYPE_SHEET_RANGE (gtk_sheet_range_get_type ())
 #define GTK_TYPE_SHEET (gtk_sheet_get_type ())
@@ -78,60 +81,16 @@
 #define GTK_SHEET_AUTO_SCROLL(sheet)     gtk_sheet_autoscroll(sheet)
 #define GTK_SHEET_JUSTIFY_ENTRY(sheet)   gtk_sheet_justify_entry(sheet)
 
-typedef struct _GtkSheet GtkSheet;
+
 typedef struct _GtkSheetClass GtkSheetClass;
-typedef struct _GtkSheetChild GtkSheetChild;
-typedef struct _GtkSheetRow GtkSheetRow;
-typedef struct _GtkSheetColumn GtkSheetColumn;
-typedef struct _GtkSheetCell GtkSheetCell;
-typedef struct _GtkSheetRange GtkSheetRange;
-typedef struct _GtkSheetButton       GtkSheetButton;
 typedef struct _GtkSheetCellAttr     GtkSheetCellAttr;
-typedef struct _GtkSheetCellBorder     GtkSheetCellBorder;
-
-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;
-};
-
-struct _GtkSheetButton
-{
-  GtkStateType state;
-  gchar *label;
-
-  gboolean label_visible;
-  GtkSheetChild *child;
-
-  GtkJustification justification;
-};
+typedef struct _GtkSheetCell GtkSheetCell;
 
-struct _GtkSheetCellBorder
-{
-  gint8 mask;
-  guint width;
-  GdkLineStyle line_style;
-  GdkCapStyle cap_style;
-  GdkJoinStyle join_style;
-  GdkColor color;
-};
 
 struct _GtkSheetCellAttr
 {
   GtkJustification justification;
-  GdkFont *font;
-  PangoFontDescription *font_desc;
+  const PangoFontDescription *font_desc;
   GdkColor foreground;
   GdkColor background;
   GtkSheetCellBorder border;
@@ -141,68 +100,21 @@
 
 struct _GtkSheetCell
 {
-  GdkRectangle area;
   gint row;
   gint col;
-
-  GtkSheetCellAttr *attributes;
-
-  GValue value;
-
-  gpointer link;
-};
-
-struct _GtkSheetRange
-{
-  gint row0,col0; /* upper-left cell */
-  gint rowi,coli; /* lower-right cell */
 };
 
 
-struct _GtkSheetRow
-{
- gchar *name;
- gint height;
- gint top_ypixel;
- guint16 requisition;
-
- GtkSheetButton button;
- gboolean is_sensitive;
- gboolean is_visible;
-};
-
-struct _GtkSheetColumn
-{
- gchar *name;
- gint width;
- gint left_xpixel;
- guint16 requisition;
-
- GtkSheetButton button;
-
- gint left_text_column; /* min left column displaying text on this column */
- gint right_text_column; /* max right column displaying text on this column */
-
- GtkJustification justification;
- gboolean is_sensitive;
- gboolean is_visible;
-};
-
-
-/* A user supplied function which converts TEXT into the value DEST, 
-   appropriate for the cell at ROW, COL */
-typedef void (*GtkSheetEncodeFunc)(gint row, gint col, const gchar *text, 
GValue *dest);
-
-/* A user supplied function which converts the value SRC for into TEXT for 
-   display at ROW, COL */
-typedef const gchar* (*GtkSheetDecodeFunc)(gint row, gint col, const GValue 
*src);
-
-
 struct _GtkSheet{
   GtkContainer container;
 
+  GSheetColumn *column_geometry;
+  GSheetRow *row_geometry;
+
   guint16 flags;
 
+  GSheetModel *model;
+
   GtkSelectionMode selection_mode;
   gboolean autoresize;
   gboolean autoscroll;
@@ -226,27 +138,15 @@
 
   gchar *name;
 
-  GtkSheetRow *row;
-  GtkSheetColumn *column;
+  gint16 column_requisition;
+  gint16 row_requisition;
 
   gboolean rows_resizable;
   gboolean columns_resizable;
 
-  /* max number of diplayed cells */
-  gint maxrow;
-  gint maxcol;
-
   /* Displayed range */
-
   GtkSheetRange view; 
 
-  /* sheet data: dynamically allocated array of cell pointers */
-  GtkSheetCell ***data;
-
-  /* max number of allocated cells */
-  gint maxallocrow;
-  gint maxalloccol;
-
   /* active cell */
   GtkSheetCell active_cell;
   GtkWidget *sheet_entry;
@@ -326,12 +226,6 @@
 
   /* clipped range */
   GtkSheetRange clip_range;
-
-  /* formatting/deformatting */
-  GtkSheetEncodeFunc encode_func;
-  GtkSheetDecodeFunc decode_func;
-  gpointer coding_data;
-
 };
 
 struct _GtkSheetClass
@@ -390,13 +284,14 @@
 GType gtk_sheet_get_type (void);
 GtkType gtk_sheet_range_get_type (void);
 
+
 /* create a new sheet */
-GtkWidget *
-gtk_sheet_new                          (guint rows, guint columns, const gchar 
*title);
+GtkWidget * gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo,
+                          const gchar *title,
+                          GSheetModel *model);
+
+
 
-void
-gtk_sheet_construct                    (GtkSheet *sheet,
-                                                guint rows, guint columns, 
const gchar *title);
 
 /* create a new browser sheet. It cells can not be edited */
 GtkWidget *
@@ -408,39 +303,16 @@
 
 /* create a new sheet with custom entry */
 GtkWidget *
-gtk_sheet_new_with_custom_entry        (guint rows, guint columns, 
+gtk_sheet_new_with_custom_entry        (GSheetRow *vgeo,
+                                        GSheetColumn *hgeo,
                                          const gchar *title,
                                         GtkType entry_type);
 void
 gtk_sheet_construct_with_custom_entry  (GtkSheet *sheet,
-                                                guint rows, guint columns, 
+                                        GSheetRow *vgeo,
+                                        GSheetColumn *hgeo,
                                          const gchar *title,
                                         GtkType entry_type);
-
-
-typedef void (*Conversion)(GType newtype, 
-                          gint row, gint col, GValue *val);
-
-/* Set the GValue type for the given range.
-   Any cells in the range are already of this type, then these cells will
-   be unaffected.  Otherwise their values are cleared, and the type is set.
-*/
-void
-gtk_sheet_range_set_type                (GtkSheet *sheet, 
-                                        const GtkSheetRange *urange, 
-                                        GType type, Conversion convert);
-
-/* Set the text transformation functions.
-   It is the programmer's responisibility to ensure that they
-   agree with the cell type 
-*/
-void
-gtk_sheet_set_coding(GtkSheet *sheet, GtkSheetEncodeFunc encode, 
-                    GtkSheetDecodeFunc decode,
-                    gpointer data);
-
-
-
 /* change scroll adjustments */
 void
 gtk_sheet_set_hadjustment              (GtkSheet *sheet,
@@ -454,25 +326,25 @@
 
 /* Returns sheet's entry widget */
 GtkWidget *
-gtk_sheet_get_entry                    (const GtkSheet *sheet);
+gtk_sheet_get_entry                    (GtkSheet *sheet);
 GtkWidget *
-gtk_sheet_get_entry_widget             (const GtkSheet *sheet);
+gtk_sheet_get_entry_widget             (GtkSheet *sheet);
 
 /* Returns sheet->state 
  * Added by Steven Rostedt <address@hidden> */
 gint
-gtk_sheet_get_state                    (const GtkSheet *sheet);
+gtk_sheet_get_state                    (GtkSheet *sheet);
 
 /* Returns sheet's ranges 
  * Added by Murray Cumming */
 guint
-gtk_sheet_get_columns_count            (const GtkSheet *sheet);
+gtk_sheet_get_columns_count            (GtkSheet *sheet);
 
 guint
-gtk_sheet_get_rows_count               (const GtkSheet *sheet);
+gtk_sheet_get_rows_count               (GtkSheet *sheet);
 
 void
-gtk_sheet_get_visible_range            (const GtkSheet *sheet,
+gtk_sheet_get_visible_range            (GtkSheet *sheet,
                                         GtkSheetRange *range);
 void
 gtk_sheet_set_selection_mode           (GtkSheet *sheet, gint mode);
@@ -551,25 +423,19 @@
 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);
-void
-gtk_sheet_column_button_add_label      (GtkSheet *sheet, 
-                                       gint column, const gchar *label);
 const gchar *
 gtk_sheet_row_button_get_label         (GtkSheet *sheet, 
                                        gint row);
-const gchar *
-gtk_sheet_column_button_get_label      (GtkSheet *sheet, 
-                                       gint column);
 void
 gtk_sheet_row_button_justify           (GtkSheet *sheet, 
                                        gint row, GtkJustification 
justification);
-void
-gtk_sheet_column_button_justify                (GtkSheet *sheet, 
-                                       gint column, GtkJustification 
justification);
+
+
 
 /* scroll the viewing area of the sheet to the given column
  * and row; row_align and col_align are between 0-1 representing the
@@ -583,39 +449,14 @@
                  gfloat row_align,
                   gfloat col_align);
 
-/* resize column/row titles window */
-void 
-gtk_sheet_set_row_titles_width(GtkSheet *sheet, guint width);
-void 
-gtk_sheet_set_column_titles_height(GtkSheet *sheet, guint height);
 
-/* show/hide column/row titles window */
-void
-gtk_sheet_show_column_titles           (GtkSheet *sheet);
 void
 gtk_sheet_show_row_titles              (GtkSheet *sheet);
 void
-gtk_sheet_hide_column_titles           (GtkSheet *sheet);
-void
 gtk_sheet_hide_row_titles              (GtkSheet *sheet);
 gboolean
-gtk_sheet_column_titles_visible                (GtkSheet *sheet);
-gboolean
 gtk_sheet_row_titles_visible           (GtkSheet *sheet);
 
-/* set column button sensitivity. If sensitivity is TRUE it can be toggled,  
- *  otherwise it acts as a title */
-void 
-gtk_sheet_column_set_sensitivity       (GtkSheet *sheet, 
-                                       gint column, gboolean sensitive);
-
-/* set sensitivity for all column buttons */
-void
-gtk_sheet_columns_set_sensitivity      (GtkSheet *sheet, gboolean sensitive);
-void
-gtk_sheet_columns_set_resizable                (GtkSheet *sheet, gboolean 
resizable);
-gboolean
-gtk_sheet_columns_resizable            (GtkSheet *sheet);
 
 /* set row button sensitivity. If sensitivity is TRUE can be toggled, 
  * otherwise it acts as a title */
@@ -631,17 +472,6 @@
 gboolean
 gtk_sheet_rows_resizable               (GtkSheet *sheet);
 
-/* set column visibility. The default value is TRUE. If FALSE, the 
- * column is hidden */
-void
-gtk_sheet_column_set_visibility                (GtkSheet *sheet, 
-                                       gint column, gboolean visible);
-void
-gtk_sheet_column_label_set_visibility  (GtkSheet *sheet, 
-                                       gint column, gboolean visible);
-void
-gtk_sheet_columns_labels_set_visibility        (GtkSheet *sheet, gboolean 
visible);
-
 /* set row visibility. The default value is TRUE. If FALSE, the 
  * row is hidden */
 void
@@ -705,40 +535,14 @@
                                        gint row, gint col, 
                                         GtkJustification justification,
                                        const gchar *text);
-
 void 
 gtk_sheet_set_cell_text                        (GtkSheet *sheet, 
                                        gint row, gint col,
                                        const gchar *text);
-
-/* Set the value of the cell at ROW, COL to be VALUE.
-   VALUE is copied by the function and will not be owned or modified.
-*/
-void
-gtk_sheet_set_cell_value               (GtkSheet *sheet, 
-                                        gint row, gint col,
-                                        const GValue *value);
-
-
-/* Return the GValue of the cell at ROW, COL into VALUE.
-   VALUE must be uninitialised (zero filled), and will be
-   initilized by this function.
-   It is the caller's responsibility to uninitialise it when 
-   no longer required.
- */
-void
-gtk_sheet_get_cell_value               (GtkSheet *sheet, 
-                                        gint row, gint col,
-                                        GValue *value);
-
-
-
-
 /* get cell contents */
 const gchar *     
 gtk_sheet_cell_get_text                (GtkSheet *sheet, gint row, gint col);
 
-
 /* clear cell contents */
 void 
 gtk_sheet_cell_clear                   (GtkSheet *sheet, gint row, gint col);
@@ -759,17 +563,7 @@
 GtkStateType
 gtk_sheet_cell_get_state               (GtkSheet *sheet, gint row, gint col);
 
-/* Handles cell links */
-void
-gtk_sheet_link_cell                    (GtkSheet *sheet, gint row, gint col,
-                                        gpointer link);
-
-gpointer
-gtk_sheet_get_link                     (GtkSheet *sheet, gint row, gint col);
-void
-gtk_sheet_remove_link                  (GtkSheet *sheet, gint row, gint col);
-
-/* get row and column corresponding to the given position in the screen */
+/* get row and column correspondig to the given position in the screen */
 gboolean
 gtk_sheet_get_pixel_info (GtkSheet * sheet,
                          gint x,
@@ -784,21 +578,16 @@
                          gint column,
                          GdkRectangle *area);
 
-/* set column width */
-void
-gtk_sheet_set_column_width (GtkSheet * sheet,
-                           gint column,
-                           guint width);
-
 /* set row height */
 void
 gtk_sheet_set_row_height (GtkSheet * sheet,
                          gint row,
                          guint height);
 
-/* append ncols columns to the end of the sheet */
+
+/* delete nrows rows starting in row */
 void
-gtk_sheet_add_column                   (GtkSheet *sheet, guint ncols);
+gtk_sheet_delete_rows                  (GtkSheet *sheet, guint row, guint 
nrows);
 
 /* append nrows row to the end of the sheet */
 void
@@ -808,20 +597,7 @@
 void
 gtk_sheet_insert_rows                  (GtkSheet *sheet, guint row, guint 
nrows);
 
-/* insert ncols columns before the given col and pull down */
- void
-gtk_sheet_insert_columns               (GtkSheet *sheet, guint col, guint 
ncols);
-
-/* delete nrows rows starting in row */
-void
-gtk_sheet_delete_rows                  (GtkSheet *sheet, guint row, guint 
nrows);
-
-/* delete ncols columns starting in col */
-void
-gtk_sheet_delete_columns               (GtkSheet *sheet, guint col, guint 
ncols);
-
-
-/* set background color of the given range */
+/* set abckground color of the given range */
 void
 gtk_sheet_range_set_background         (GtkSheet *sheet, 
                                        const GtkSheetRange *range, 
@@ -927,6 +703,13 @@
                                         gint row, gint col);
                        
 
+
+void           gtk_sheet_set_model(GtkSheet *sheet, 
+                                  GSheetModel *model);
+
+GSheetModel * gtk_sheet_get_model(const GtkSheet *sheet);
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
Index: psppire/psppire.glade
diff -u psppire/psppire.glade:1.17 psppire/psppire.glade:1.18
--- psppire/psppire.glade:1.17  Thu Dec 22 08:56:59 2005
+++ psppire/psppire.glade       Sat Jan 28 08:48:07 2006
@@ -138,6 +138,15 @@
                      <signal name="activate" handler="on_delete1_activate" 
last_modification_time="Tue, 23 Mar 2004 10:22:51 GMT"/>
                    </widget>
                  </child>
+
+                 <child>
+                   <widget class="GtkMenuItem" id="insert1">
+                     <property name="visible">True</property>
+                     <property name="label" 
translatable="yes">_Insert</property>
+                     <property name="use_underline">True</property>
+                     <signal name="activate" handler="on_insert1_activate" 
last_modification_time="Mon, 02 Jan 2006 12:46:02 GMT"/>
+                   </widget>
+                 </child>
                </widget>
              </child>
            </widget>
@@ -200,7 +209,7 @@
                      <property name="visible">True</property>
                      <property name="label" translatable="yes">Value 
Labels</property>
                      <property name="use_underline">True</property>
-                     <property name="active">True</property>
+                     <property name="active">False</property>
                      <signal name="activate" 
handler="on_value_labels1_activate" last_modification_time="Thu, 24 Nov 2005 
10:42:04 GMT"/>
                    </widget>
                  </child>
Index: psppire/pspplogo.png
Index: psppire/src/ChangeLog
diff -u psppire/src/ChangeLog:1.12 psppire/src/ChangeLog:1.13
--- psppire/src/ChangeLog:1.12  Thu Dec 22 08:56:59 2005
+++ psppire/src/ChangeLog       Sat Jan 28 08:48:08 2006
@@ -1,77 +1,7 @@
-Thu Dec 22 16:54:56 WST 2005 John Darrington <address@hidden>
+Sat Jan 28 16:22:23 WST 2006 John Darrington <address@hidden>
 
-       * var_type_dialog.[ch] var_sheet.c: Added callback function to update
-       the variable sheet when the var_type_dialog is closed using OK.
+    * Separated the data out of the GtkSheet.
 
-Sun Dec 18 12:41:56 WST 2005 John Darrington <address@hidden>
+Tue Nov  2 19:00:28 WST 2004 John Darrington <address@hidden>
 
-       * var_type_dialog.c: Implemented custom currency type selection.
-
-Wed Dec 14 19:37:01 WST 2005 John Darrington <address@hidden>
-
-       * val_labs_dialog.c: When entering value, treeview item is now 
-         automatically selected.
-
-       * var_type_dialog.c: Implemented the actions for the dollar format.
-         Also, date and dollar treeviews are automatically selected even
-         when no valid format is present.
-
-Mon Dec 12 15:50:47 WST 2005 John Darrington <address@hidden>
-
-       * val_labs_dialog.[ch]: Fixed problem with value labels on non numeric
-       data.
-
-Mon Nov 28 15:11:52 WST 2005 John Darrington <address@hidden>
-
-       * data_sheet.c var_sheet.c: Implemented the input and display of
-       Align and Measure parameters
-
-Sun Nov 27 16:16:35 WST 2005 John Darrington <address@hidden>
-
-       * data_sheet.[ch] var_sheet.[ch]:  Implemented switching between 
-       data and var sheet by double clicking on row/column title.
-
-       * callbacks.c: Implemented the Data/Variables menu.
-
-       * val_labs_dialog.[ch]: New files. 
-               
-Fri Nov 25 20:02:21 WST 2005 John Darrington <address@hidden>
-
-       * callbacks.[ch] main.c : Title bar now shows name of active file.
-         Fixed display of About dialog.
-
-Thu Nov 24 20:41:27 WST 2005 John Darrington <address@hidden>
-
-       * callbacks.c: Eye Candy --- implemented the Fonts and Gridlines 
-         menus
-
-Wed Nov 23 20:38:00 WST 2005 John Darrington <address@hidden>
-
-       * data_sheet.c: Converted string data to utf8 before displaying.
-
-       * customentry.[ch]: New files.
-
-       * var_sheet.c: Made Values, Missing and Type columns use the new
-         customentry widget.  Changed the var type dialog to popup on custom
-         entry button click instead of whenever cell is entered.
-
-Sun Nov 20 20:21:57 WST 2005 John Darrington <address@hidden>
-
-       * data_sheet.c: Made new variables' values default to SYSMIS or null
-         string.  Made a very crude attempt to convert between value types.
-
-       * pspp-dict.c var_sheet.c: Added a variable_added signal.
-
-       * var_type_dialog.c: Made dialog transient on main window.
-
-       * data_sheet.c: Greyed unpopulated columns using the
-         gtk_sheet_set_sensitivity function which I've just discovered.
-
-Sun Nov 13 09:32:52 WST 2005 John Darrington <address@hidden>
-
-       * Fixed the maximum and minimum values of the SpinButtons.
-       * Fixed some memory allocation errors writing string values.
-
-Sun Nov 13 08:33:58 WST 2005 John Darrington <address@hidden>
-
-       * Started this Changelog
+    * Very first incarnation.
Index: psppire/src/Makefile.am
diff -u psppire/src/Makefile.am:1.14 psppire/src/Makefile.am:1.15
--- psppire/src/Makefile.am:1.14        Fri Dec 23 23:34:03 2005
+++ psppire/src/Makefile.am     Sat Jan 28 08:48:08 2006
@@ -16,13 +16,17 @@
 
 psppire_SOURCES = \
        main.c \
-       pspp-object.c pspp-object.h \
-       pspp-dict.c pspp-dict.h \
+       psppire-object.c psppire-object.h \
+       psppire-dict.c psppire-dict.h \
+       psppire-case-array.c psppire-case-array.h \
+       psppire-data-store.c psppire-data-store.h \
+       psppire-var-store.c psppire-var-store.h \
+       psppire-variable.c psppire-variable.h \
        error-dialog.c error-dialog.h \
-       callbacks.c callbacks.h\
        customentry.c customentry.h \
        var_type_dialog.c var_type_dialog.h \
        val_labs_dialog.c val_labs_dialog.h \
+       menu-actions.h menu-actions.c \
        missing_val_dialog.c missing_val_dialog.h \
        data_sheet.c  \
        var_sheet.c \
Index: psppire/src/data_sheet.c
diff -u psppire/src/data_sheet.c:1.27 psppire/src/data_sheet.c:1.28
--- psppire/src/data_sheet.c:1.27       Sun Jan 22 01:22:55 2006
+++ psppire/src/data_sheet.c    Sat Jan 28 08:48:08 2006
@@ -1,6 +1,6 @@
 /* 
    PSPPIRE --- A Graphical User Interface for PSPP
-   Copyright (C) 2004, 2005  Free Software Foundation
+   Copyright (C) 2004, 2005, 2006  Free Software Foundation
    Written by John Darrington
 
    This program is free software; you can redistribute it and/or modify
@@ -16,7 +16,8 @@
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA. */
+   02110-1301, USA. 
+*/
 
 #include <psppire-conf.h>
 
@@ -26,14 +27,18 @@
 #include <ctype.h>
 
 #include "gtksheet.h"
-#include "pspp-dict.h"
-#include "sfm-write.h"
+
+#include "gsheet-uniform-row.h"
+
+#include "psppire-dict.h"
+#include "psppire-variable.h"
+#include "psppire-data-store.h"
+
 #include "value-labels.h"
 #include "case.h"
-#include "file-handle-def.h"
 #include "data-in.h"
 
-#include "callbacks.h"
+#include "menu-actions.h"
 #include "data_sheet.h"
 
 #include "misc.h"
@@ -45,58 +50,23 @@
 extern GladeXML *xml;
 
 
-static PSPP_Dict *pspp_dictionary ; 
-
-static gint last_populated_row = -1;
-static gint n_initial_columns = 10;
-
-
-static void repopulate_columns(GtkSheet *sheet, PSPP_Dict *dict, 
-                              gint from, gint to);
-
-
-/* True if values should be displayed as labels */
-static gboolean display_labels = FALSE;
-
-/* Repair any damage that may have been done to the data sheet */
-void
-psppire_data_sheet_redisplay(GtkSheet *sheet)
+static gboolean 
+traverse_callback (GtkSheet * sheet, 
+                       gint row, gint col, 
+                       gint *new_row, gint *new_column
+                       )
 {
-  repopulate_columns(sheet, pspp_dictionary, 0, 
-                    gtk_sheet_get_columns_count(sheet) - 1);
-}
+  PsppireDataStore *data_store = 
PSPPIRE_DATA_STORE(gtk_sheet_get_model(sheet));
 
-/* Return the width that an  'M' character would occupy when typeset at
-   row, col */
-static guint 
-M_width(GtkSheet *sheet, gint row, gint col)
-{
-  GtkSheetCellAttr attributes;
-
-  gtk_sheet_get_attributes(sheet, row, col, &attributes);
-
-  PangoRectangle rect;
-  PangoLayout *layout;
+  const gint n_vars = psppire_dict_get_var_cnt(data_store->dict);
 
-  layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), "M");
-  pango_layout_set_font_description (layout, 
-                                    attributes.font_desc);
-
-  pango_layout_get_extents (layout, NULL, &rect);
+  if ( *new_column >= n_vars ) 
+    return FALSE;
 
-  g_object_unref(G_OBJECT(layout));
-  return PANGO_PIXELS(rect.width);
+  return TRUE;
 }
 
 
-/* Return the number of pixels corresponding to a column of 
-   WIDTH characters */
-static guint 
-columnWidthToPixels(GtkSheet *sheet, gint column, guint width)
-{
-  return (M_width(sheet, 1, column) * width);
-}
-
 
 /* Callback which occurs when the column title is double clicked */
 static gboolean
@@ -122,12 +92,17 @@
   /* The entry where the reference to the current cell is displayed */
   GtkEntry *cell_ref_entry;
 
+  PsppireDataStore *data_store = 
PSPPIRE_DATA_STORE(gtk_sheet_get_model(sheet));
+
+
   if ( !xml) 
     return FALSE;
 
-  const struct variable *var = pspp_dict_get_var(pspp_dictionary, col);
+  const struct PsppireVariable *pv = 
+    psppire_dict_get_variable(data_store->dict, col);
 
-  gchar *text = g_strdup_printf("%d: %s", row, var?var->name:"");
+  gchar *text = g_strdup_printf("%d: %s", row, 
+                               pv ? psppire_variable_get_name(pv) : "");
   
   cell_ref_entry = GTK_ENTRY(get_widget_assert(xml, "cell_ref_entry"));
 
@@ -138,456 +113,8 @@
   return FALSE;
 }
 
-/* Set cell row, col to SYSMIS */
-static void
-data_sheet_set_cell_sysmis(GtkSheet *sheet, gint row, gint col)
-{
-  const struct variable *var = pspp_dict_get_var(pspp_dictionary, col);
-
-  GValue value = {0};    
-  if ( var->type == NUMERIC ) 
-    {
-      g_value_init(&value, G_TYPE_DOUBLE);
-      g_value_set_double(&value, SYSMIS);
-    }
-  else
-    {
-      g_value_init(&value, G_TYPE_STRING);
-      g_value_set_string(&value, "");
-    }
-
-  gtk_sheet_set_cell_value(sheet, row, col, &value);
-
-  g_value_unset(&value);
-
-}
-
-
-/* Callback which occurs after a cell has been modified */
-static gint 
-data_sheet_set_cell(GtkSheet *sheet, gint row, gint col)
-{
-  gint c;   gint r;
-
-  const gint cols = pspp_dict_get_var_cnt(pspp_dictionary);
-
-  /* If there are gaps between the row just modified, 
-     and the last_populated_row, set the gaps to SYSMIS */
-
-  for ( r = last_populated_row + 1; r < row ; ++r ) 
-    {
-      for ( c = 0 ; c < cols ; ++c ) 
-       data_sheet_set_cell_sysmis(sheet, r, c);
-    }
-
-  if ( row > last_populated_row ) 
-    {
-      for ( c = 0 ; c < col ; ++c ) 
-       data_sheet_set_cell_sysmis(sheet, row, c);
-      for ( c = col + 1 ; c < cols ; ++c ) 
-       data_sheet_set_cell_sysmis(sheet, row, c);
-
-      last_populated_row = row;
-      repopulate_columns(sheet, pspp_dictionary, 0, cols - 1);
-    }
-
-  return FALSE;
-}
-
-
-/* This nasty piece of work is a temporary hack.
-   Converting data between variable types ought to be a 
-   transformation, and not the responsibility of the GUI
-*/
-static void 
-convert(GType to, gint row, gint col, GValue *value)
-{
-  double v;
-
-  switch  (G_VALUE_TYPE(value))
-    {
-    case G_TYPE_STRING:
-      if ( to == G_TYPE_DOUBLE ) 
-       {
-         const gchar *s = g_value_get_string(value);
-         if ( !s ) 
-           v = SYSMIS;
-         else 
-           {
-             bool found_digit = false;
-             const gchar *ss = s;
-             while (*ss)
-               {
-                 if (isdigit(*ss++))
-                   {
-                     found_digit = true;
-                     break;
-                   }
-               }
-             if ( !found_digit ) 
-               v = SYSMIS;
-             else if ( 0 == sscanf(s, "%lf", &v) ) 
-               v = SYSMIS;
-           }
-
-         g_value_unset(value);
-         g_value_init(value, to);
-
-         g_value_set_double(value, v);
-       }
-      break;
-    case G_TYPE_DOUBLE:
-      if ( to == G_TYPE_STRING ) 
-       {
-         gchar *s=0;
-         v = g_value_get_double(value);
-         if ( v == SYSMIS) 
-           s = g_strdup("");
-         else
-           s = g_strdup_printf("%g", v);
-         g_value_unset(value);
-         g_value_init(value, to);
-
-         g_value_set_string(value, s);
-         g_free(s);
-       }
-      break;
-    default:
-      g_assert_not_reached();
-      break;
-    }
-
-
-}
-
-
-/* Update COLUMN of the data sheet */
-static gint
-update_column(GtkSheet *sheet, gint column, PSPP_Dict *dict)
-{
-  GtkSheetRange range;
-
-  if ( column >= gtk_sheet_get_columns_count(sheet) ) 
-    {
-      gtk_sheet_add_column(sheet, 
-                          column - gtk_sheet_get_columns_count(sheet) + 1);
-    }
-
-  const struct variable *var = pspp_dict_get_var(dict, column);
-
-  range.row0 = 0; range.rowi = gtk_sheet_get_rows_count(sheet) - 1;
-  range.col0 = range.coli = column;
-  gtk_sheet_range_set_editable(sheet, &range, TRUE);
-
-
-  gtk_sheet_range_set_type(sheet, &range, 
-                          (var->type == ALPHA)?G_TYPE_STRING:G_TYPE_DOUBLE,
-                          convert);
-
-
-  /* Kludge: Happily GtkJustification is defined similarly
-     to enum alignment from pspp/var.h */
-  gtk_sheet_column_set_justification(sheet, column, var->alignment);
-  gtk_sheet_column_button_add_label(sheet, column, var->name);
-  gtk_sheet_column_set_sensitivity(sheet, column, TRUE);
-
-
-  gtk_sheet_set_column_width (sheet, column, 
-                             columnWidthToPixels(sheet, column, 
-                                                 var->display_width));
-  return FALSE;
-}
-
-/* Callback for when a variable has been added */
-static gint
-add_variable(GObject *obj, gint column, gpointer data)
-{
-  gint r;
-
-  PSPP_Dict *dict = PSPP_DICT(obj);
 
-  GtkSheet *sheet = GTK_SHEET(data);
-
-  update_column(sheet, column, dict);
-
-  for ( r = 0 ; r <= last_populated_row; ++r)
-    data_sheet_set_cell_sysmis(sheet, r, column);
-
-  return FALSE;
-}
-
-
-/* Callback for when a variable has changed */
-static gint
-update_variable(GObject *obj, gint column, gpointer data)
-{
-  GtkSheet *sheet = GTK_SHEET(data);
-  PSPP_Dict *dict = PSPP_DICT(obj);
-
-  /* 
-  g_assert ( column < gtk_sheet_get_columns_count(sheet));
-  */
-
-  return update_column(sheet, column, dict);
-}
-
-
-/* Repopulate the columns starting at position FROM, to position TO inclusive*/
-static void
-repopulate_columns(GtkSheet *sheet, PSPP_Dict *dict, gint from, gint to)
-{
-  gint col;
-
-  for ( col = from ; col <= to ; ++col ) 
-    {
-      if ( col < pspp_dict_get_var_cnt(dict)) 
-       {
-         const struct variable *var = pspp_dict_get_var(dict, col);      
-
-         /* Kludge: Happily GtkJustification is defined similarly
-            to enum alignment from pspp/var.h */
-         gtk_sheet_column_set_justification(sheet, col,
-                                            var->alignment);
-         gtk_sheet_column_button_add_label (sheet, col, var->name);
-         gtk_sheet_set_column_width (sheet, col, 
-                                     columnWidthToPixels(sheet, col, 
-                                                         var->display_width));
-         gtk_sheet_column_set_sensitivity(sheet, col, TRUE);
-
-       }
-      else
-       {
-         GtkSheetRange this_column;
-         this_column.col0 = this_column.coli = col;
-         this_column.row0 = 0;
-         this_column.rowi = gtk_sheet_get_rows_count(sheet) - 1 ;
-
-
-         gtk_sheet_column_button_add_label (sheet, col, _("var"));
-         gtk_sheet_column_set_sensitivity(sheet, col, FALSE);
-
-         /* Clear the column which relates to variables no longer valid, 
-            and disable them
-         */
-         gtk_sheet_range_clear (sheet, &this_column);
-         gtk_sheet_range_set_editable(sheet, &this_column, FALSE);
-         gtk_sheet_set_column_width(sheet, col, 80);
-       }
-    }
-}
-
-
-/* Remove a variable from the data sheet */
-static gint
-remove_variable(GObject *obj, gint column, gpointer data)
-{
-  PSPP_Dict *dict = PSPP_DICT(obj);
-
-  GtkSheet *sheet = GTK_SHEET(data);
-  
-  gtk_sheet_delete_columns (sheet, column, 1);
-  gtk_sheet_add_column(sheet, 1);
-
-  repopulate_columns(sheet, dict, column, 
-                    gtk_sheet_get_columns_count(sheet) - 1);
-
-  return FALSE;
-}
-
-
-/* Change the width of COL to WIDTH characters */
-static void
-adjust_column_width(GtkSheet *sheet, gint col, gint width)
-{
-  struct variable *var = pspp_dict_get_var(pspp_dictionary, col);
-
-  if ( ! var) 
-    return;
-
-  const gint unit_width = M_width(sheet, 0, col);
-
-
-  if ( var->display_width != width / unit_width ) 
-    {
-      var->display_width = width / unit_width  ;
-      pspp_dict_var_changed(pspp_dictionary, col);
-    }
-}
-
-/* Clear the entire sheet */
-void
-psppire_data_sheet_clear(GtkSheet *sheet)
-{
-  g_return_if_fail(sheet);
-
-  gtk_sheet_set_active_cell(sheet, 0, 0);
-
-  /* get rid of all the cells */
-  gtk_sheet_range_delete (sheet, NULL);
-
-  /* Delete any excess columns */
-  gtk_sheet_delete_columns(sheet, 0, 
-                          gtk_sheet_get_columns_count(sheet) - 
n_initial_columns);
-
-  last_populated_row = -1;
-
-  repopulate_columns(sheet, pspp_dictionary, 0,
-                    gtk_sheet_get_columns_count(sheet) - 1);
-}
-
-
-
-/* Associate a  dictionary with the data sheet */
-void
-psppire_data_sheet_set_dictionary(GtkSheet *sheet, PSPP_Dict *d)
-{
-  pspp_dictionary  = d;
-
-  g_signal_connect(pspp_dictionary, "variable_changed",
-                  G_CALLBACK(update_variable), sheet);
-
-  g_signal_connect(pspp_dictionary, "variable_added",
-                  G_CALLBACK(add_variable), sheet);
-
-
-  g_signal_connect(pspp_dictionary, "variable_deleted",
-                  G_CALLBACK(remove_variable), sheet);
-}
-
-
-/* Convert the value in SRC to TEXT using the format for the cell at
-   ROW, COL */
-static const gchar *
-value_format_func(gint row, gint col, const GValue *src)
-{
-  struct ccase mycase;
-
-  if ( row > last_populated_row) 
-    return 0;
-
-  if ( ! pspp_dictionary ) 
-    return 0;
-
-  const struct variable *v = pspp_dict_get_var (pspp_dictionary, col);
-
-  if ( !v ) 
-    return 0;
-
-  const int ni = dict_get_next_value_idx(pspp_dictionary->dict);
-  if ( ni == 0 ) 
-    return 0;
-
-  case_create(&mycase, ni);
-
-  union value *val = case_data_rw (&mycase, v->fv);
-
-  if ( G_VALUE_HOLDS(src, G_TYPE_STRING) )
-    {
-      g_assert(v->type == ALPHA);
-      const gchar* text = g_value_get_string(src);
-      if ( text) 
-       {
-         memset(val->s, 0, v->width);
-         memcpy(val->s, text, 
-                v->width < strlen(text)? v->width : strlen(text));
-       }
-      else
-       goto lossage;
-    }
-  else if ( G_VALUE_HOLDS(src, G_TYPE_DOUBLE) )
-    {
-      g_assert(v->type == NUMERIC);
-      val->f = g_value_get_double(src);
-    }
-  else
-    goto lossage;
-
-  const struct fmt_spec *fp = &v->write;
-
-  gchar *s;
-  if ( ! display_labels ||   0 == (s = val_labs_find (v->val_labs, *val))) 
-    {
-      s = malloc(sizeof(gchar) * (fp->w + 1));
-
-      /* Converts binary value V into printable form in the exactly
-        FP->W character in buffer S according to format specification
-        FP.  No null terminator is appended to the buffer.  */
-      data_out (s, fp, val);
-      s[fp->w] = '\0';
-    }
-
-  case_destroy(&mycase);
-
-  /* FIXME: Check for errors in this conversion.
-   *   Is the current locale the correct one to use anyway?
-   */
-  return g_locale_to_utf8(s, fp->w, 0, 0, 0);
-
- lossage:
-  case_destroy(&mycase);
-  return 0;
-}
-
-
-/* Converts TEXT to a value appropriate for storage at cell ROW, COL.
-   The result is placed into DEST */
-static void 
-value_encode_func(gint row, gint col, const gchar *text, GValue *dest)
-{
-  if ( ! pspp_dictionary )
-    return; 
-
-  const struct variable *v = pspp_dict_get_var (pspp_dictionary, col);
-
-  if ( ! v ) 
-    return;
-
-  struct ccase mycase;
-
-  case_create(&mycase, dict_get_next_value_idx(pspp_dictionary->dict));
-
-  union value *val = case_data_rw (&mycase, v->fv);
-
-  struct data_in d_in;
-  d_in.s = text;
-  d_in.e = text + strlen(text);
-  d_in.v = val;
-  d_in.f1 = d_in.f2 = 0;
-  d_in.format = v->write;
-  d_in.flags = 0;
-
-  if ( ! data_in(&d_in) ) 
-    {
-      g_warning("Can\'t encode string at %d, %d\n",row, col);
-      goto finish;
-    }
-
-  if ( v->type == ALPHA) 
-    {
-      g_assert(G_VALUE_TYPE(dest) == G_TYPE_STRING);
-
-      if ( ! text) 
-       {
-         g_value_set_string(dest, "");
-         goto finish;
-       }
-      
-      gchar *t = malloc(sizeof(gchar) * (v->width + 1) );
-      memcpy(t, val->s, v->width);
-      t[v->width] = '\0';
-      g_value_set_string(dest, t);
-      g_free(t);
-    }
-  else
-    {
-      g_assert(G_VALUE_TYPE(dest) == G_TYPE_DOUBLE);
-      g_value_set_double(dest, val->f);
-    }
-
- finish:
-  case_destroy(&mycase);
-  
-}
+extern PsppireDataStore *data_store ;
 
 
 GtkWidget*
@@ -597,41 +124,21 @@
   GtkWidget *sheet;
   gint i;
 
-  const gint rows = 46;
-
-  GtkSheetRange entire_sheet= {0,0,0,0};
-  entire_sheet.rowi = rows - 1;
-  entire_sheet.coli = n_initial_columns - 1;
-
-  sheet = gtk_sheet_new(rows, n_initial_columns, "data sheet"); 
-
-  gtk_sheet_set_coding(GTK_SHEET(sheet), 
-                      value_encode_func, value_format_func, 0);
-
-  g_signal_connect(sheet, "new_column_width", 
-                  G_CALLBACK(adjust_column_width), 0);
-
-  gtk_sheet_columns_set_sensitivity(GTK_SHEET(sheet), FALSE);
-  for (i = 0 ; i < n_initial_columns ; ++i ) 
-    {
-      gtk_sheet_column_button_add_label (GTK_SHEET(sheet), i, _("var"));
-    }
+  const gint rows = 10046;
 
-  /* We want to control column widths ourself */
-  gtk_sheet_set_autoresize(GTK_SHEET(sheet), FALSE);
+  GObject *row_geometry = g_sheet_uniform_row_new(25, rows); 
 
-  /* Whilst there's no variables the entire sheet is uneditable */
-  gtk_sheet_range_set_editable(GTK_SHEET(sheet), &entire_sheet, FALSE);
+  sheet = gtk_sheet_new(G_SHEET_ROW(row_geometry), 
+                       G_SHEET_COLUMN(data_store), "data sheet", 0); 
 
 
-  g_signal_connect (GTK_OBJECT (sheet), "set_cell",
-                   GTK_SIGNAL_FUNC (data_sheet_set_cell),
-                   0);
-
   g_signal_connect (GTK_OBJECT (sheet), "activate",
                    GTK_SIGNAL_FUNC (update_data_ref_entry),
                    0);
 
+  g_signal_connect (GTK_OBJECT (sheet), "traverse",
+                   GTK_SIGNAL_FUNC (traverse_callback), 0);
+
 
   g_signal_connect (GTK_OBJECT (sheet), "double-click-column",
                    GTK_SIGNAL_FUNC (click2column),
@@ -641,93 +148,3 @@
 
   return sheet;
 }
-
-void
-psppire_create_system_file(GtkSheet *sheet, PSPP_Dict *d, struct file_handle 
*handle)
-{
-  gint r;
-
-  g_assert(handle);
-
-  const struct sfm_write_options wo = {
-    true, /* writeable */
-    false, /* dont compress */
-    3 /* version */
-  }; 
-
-  g_print("Writing system file %s\n",fh_get_filename(handle));
-  
-  struct sfm_writer *writer = sfm_open_writer(handle, d->dict, wo);
-
-  g_assert(writer);
-
-  gint var_cnt = pspp_dict_get_var_cnt(d); 
-
-  for (r = 0 ; r <= last_populated_row ; ++r ) 
-    {
-      struct ccase mycase;
-      gint c;
-
-      case_create(&mycase, dict_get_next_value_idx(d->dict));
-
-      for ( c = 0 ; c < var_cnt ; ++c ) 
-       {
-         struct variable *v = dict_get_var (d->dict, c);
-
-         union value *value = case_data_rw (&mycase, v->fv);
-         
-         GValue gval = {0};
-         gtk_sheet_get_cell_value(sheet, r, c, &gval);
-
-         if ( v->type == ALPHA) 
-           {
-             g_assert(G_VALUE_HOLDS(&gval, G_TYPE_STRING));
-
-             const gchar *text = g_value_get_string(&gval);
-             memset(value->s, ' ', v->width);
-             if ( text ) 
-               {
-                 memcpy(value->s, text, 
-                        strlen(text) < v->width ? strlen(text) : v->width);
-               }
-           }
-         else
-           {
-             g_assert(G_VALUE_HOLDS(&gval, G_TYPE_DOUBLE));
-             value->f = g_value_get_double(&gval);
-           }
-       }
-
-      if ( ! sfm_write_case(writer, &mycase) ) 
-       g_warning("Failed to write case %d\n",r);
-
-      case_destroy(&mycase);
-
-    }
-
-  sfm_close_writer(writer);
-}
-
-
-
-
-/* Set a the cell ROW, COL to VALUE */
-void
-data_sheet_set_cell_value(GtkSheet *sheet, gint row, gint col, 
-                         const GValue *value)
-{
-  g_return_if_fail(sheet);
-
-  gtk_sheet_set_cell_value(sheet, row, col, value);
-
-  if (row > last_populated_row)
-    last_populated_row = row;
-}
-
-
-void
-psppire_data_sheet_set_show_labels(GtkSheet *sheet, gboolean show_labels)
-{
-  display_labels = show_labels;
-}
-
Index: psppire/src/data_sheet.h
diff -u psppire/src/data_sheet.h:1.3 psppire/src/data_sheet.h:1.4
--- psppire/src/data_sheet.h:1.3        Fri Dec 23 23:34:03 2005
+++ psppire/src/data_sheet.h    Sat Jan 28 08:48:08 2006
@@ -23,12 +23,14 @@
 #define DATA_SHEET_H
 
 #include <gtksheet.h>
+#include <psppire-case-array.h>
+#include <psppire-dict.h>
 
 void psppire_data_sheet_clear(GtkSheet *sheet);
 
-
-void psppire_data_sheet_set_dictionary(GtkSheet *sheet, PSPP_Dict *d);
-
+#if 0
+void psppire_data_sheet_set_dictionary(GtkSheet *sheet, PsppireDict *d);
+#endif
 
 GtkWidget* psppire_data_sheet_create (gchar *widget_name, 
                                      gchar *string1, 
@@ -45,8 +47,7 @@
 /* Repair any damage that may have been done to the data sheet */
 void psppire_data_sheet_redisplay(GtkSheet *sheet);
 
-void psppire_create_system_file(GtkSheet *sheet, PSPP_Dict *d, 
-                               struct file_handle *handle);
+guint columnWidthToPixels(GtkSheet *sheet, gint column, guint width);
 
 
 #endif
Index: psppire/src/error-dialog.c
diff -u psppire/src/error-dialog.c:1.2 psppire/src/error-dialog.c:1.3
--- psppire/src/error-dialog.c:1.2      Fri Dec 23 23:34:03 2005
+++ psppire/src/error-dialog.c  Sat Jan 28 08:48:08 2006
@@ -126,7 +126,8 @@
 }
 
 
-void msg(int klass, const char *fmt, ...)
+void 
+msg(int klass, const char *fmt, ...)
 {
   va_list ap;
   va_start(ap, fmt);
Index: psppire/src/error-dialog.h
diff -u psppire/src/error-dialog.h:1.1 psppire/src/error-dialog.h:1.2
--- psppire/src/error-dialog.h:1.1      Fri Dec 23 06:50:09 2005
+++ psppire/src/error-dialog.h  Sat Jan 28 08:48:08 2006
@@ -22,8 +22,10 @@
 #ifndef ERROR_DIALOG_H
 #define ERROR_DIALOG_H
 
-
+#include "error.h"
 
 void vmsg(int klass, const char *fmt, va_list args);
+void  msg(int klass, const char *fmt, ...);
+
 
 #endif
Index: psppire/src/main.c
diff -u psppire/src/main.c:1.13 psppire/src/main.c:1.14
--- psppire/src/main.c:1.13     Fri Dec 23 23:34:03 2005
+++ psppire/src/main.c  Sat Jan 28 08:48:08 2006
@@ -28,15 +28,26 @@
 #include <gtk/gtk.h>
 #include <gtk/gtk.h>
 #include <glade/glade.h>
-#include "callbacks.h"
-#include "pspp-dict.h"
+#include "menu-actions.h"
+#include "psppire-dict.h"
+#include "psppire-var-store.h"
+#include "psppire-data-store.h"
 
 #include "misc.h"
 #include "data_sheet.h"
 #include "var_sheet.h"
+#include "psppire-case-array.h"
 
 GladeXML *xml;
 
+
+PsppireDict *the_dictionary = 0;
+PsppireCaseArray *the_cases = 0;
+
+
+PsppireDataStore *data_store = 0;
+
+
 int 
 main(int argc, char *argv[]) 
 {
@@ -45,28 +56,39 @@
 
   glade_init();
 
+  the_dictionary = psppire_dict_new();
+
+  /* Create the model for the var_sheet */
+  PsppireVarStore *var_store = psppire_var_store_new(the_dictionary);
+
+  /* Create the model for the data sheet */
+  the_cases = psppire_case_array_new(100, 20);
+
+  data_store = psppire_data_store_new(the_dictionary, the_cases);
+
+
   /* load the interface */
   xml = glade_xml_new("psppire.glade", NULL, NULL);
 
   if ( !xml ) 
     {
-      g_print("Is psppire.glade in current directory\n");
+      g_print("Is psppire.glade in current directory?\n");
       return 1;
     }
 
-
   GtkWidget *data_editor = get_widget_assert(xml, "data_editor");
   gtk_window_set_icon_from_file(GTK_WINDOW(data_editor), "psppicon.png",0);
 
   /* connect the signals in the interface */
   glade_xml_signal_autoconnect(xml);
 
-  GtkWidget *var_sheet  = get_widget_assert(xml, "variable_sheet");
-  GtkWidget *data_sheet = get_widget_assert(xml, "data_sheet");
+  GtkSheet *var_sheet  = GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
+  GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
 
-  PSPP_Dict *d = psppire_var_sheet_get_dictionary(var_sheet);
+  gtk_sheet_set_model(var_sheet, G_SHEET_MODEL(var_store));
   
-  psppire_data_sheet_set_dictionary(GTK_SHEET(data_sheet), d);
+  gtk_sheet_set_model(data_sheet, G_SHEET_MODEL(data_store));
+
 
   gtk_init_add(callbacks_on_init, 0);
 
Index: psppire/src/missing_val_dialog.c
diff -u psppire/src/missing_val_dialog.c:1.4 
psppire/src/missing_val_dialog.c:1.5
--- psppire/src/missing_val_dialog.c:1.4        Fri Dec 23 23:34:03 2005
+++ psppire/src/missing_val_dialog.c    Sat Jan 28 08:48:08 2006
@@ -1,6 +1,6 @@
 /* 
     PSPPIRE --- A Graphical User Interface for PSPP
-    Copyright (C) 2005  Free Software Foundation
+    Copyright (C) 2005, 2006  Free Software Foundation
     Written by John Darrington
 
     This program is free software; you can redistribute it and/or modify
@@ -26,6 +26,7 @@
 #include "misc.h"
 #include "var.h"
 #include "data-in.h"
+#include "psppire-variable.h"
 
 #include <gtk/gtk.h>
 #include <glade/glade.h>
@@ -76,6 +77,8 @@
 missing_val_dialog_accept(GtkWidget *w, gpointer data)
 {
   struct missing_val_dialog *dialog = data;
+
+  const struct fmt_spec *write_spec = 
psppire_variable_get_write_spec(dialog->pv);
   
   if ( gtk_toggle_button_get_active(dialog->button_discrete))
     {
@@ -85,19 +88,24 @@
       mv_set_type(&dialog->mvl, MV_NONE);
       for(i = 0 ; i < 3 ; ++i ) 
        {
-         const gchar *text = gtk_entry_get_text(GTK_ENTRY(dialog->mv[i]));
+         gchar *text = 
+           g_strdup(gtk_entry_get_text(GTK_ENTRY(dialog->mv[i])));
 
          union value v;
          if ( !text || strlen(g_strstrip(text)) == 0 )
-           continue;
+           {
+             g_free(text);
+             continue;
+           }
 
-         if ( text_to_value(text, &v, dialog->var->write))
+         if ( text_to_value(text, &v, *write_spec))
            {
              nvals++;
              mv_add_value (&dialog->mvl, &v);
            }
          else 
              badvals++;
+         g_free(text);
        }
       if ( nvals == 0 || badvals > 0 ) 
        {
@@ -115,9 +123,9 @@
       const gchar *low_text = gtk_entry_get_text(GTK_ENTRY(dialog->low));
       const gchar *high_text = gtk_entry_get_text(GTK_ENTRY(dialog->high));
 
-      if ( text_to_value(low_text, &low_val, dialog->var->write)
+      if ( text_to_value(low_text, &low_val, *write_spec)
           && 
-          text_to_value(high_text, &high_val, dialog->var->write) ) 
+          text_to_value(high_text, &high_val, *write_spec) ) 
        {
          if ( low_val.f > high_val.f ) 
            {
@@ -133,8 +141,8 @@
          return;
        }
 
-      const gchar *discrete_text = 
-       gtk_entry_get_text(GTK_ENTRY(dialog->discrete));
+      gchar *discrete_text = 
+       g_strdup(gtk_entry_get_text(GTK_ENTRY(dialog->discrete)));
 
 
       mv_set_type(&dialog->mvl, MV_NONE);
@@ -144,21 +152,23 @@
        {
          union value discrete_val;
          if ( !text_to_value(discrete_text, &discrete_val, 
-                             dialog->var->write))
+                             *write_spec))
            {
              err_dialog(_("Incorrect value for variable type"),
                         GTK_WINDOW(dialog->window) );
+             g_free(discrete_text);
              return;
            }
          mv_add_value(&dialog->mvl, &discrete_val);
        }
+      g_free(discrete_text);
     }
 
   
   if (gtk_toggle_button_get_active(dialog->button_none))
     mv_set_type(&dialog->mvl, MV_NONE);
 
-  mv_copy(&dialog->var->miss, &dialog->mvl);
+  psppire_variable_set_missing(dialog->pv, &dialog->mvl);
 
   gtk_widget_hide(dialog->window);
 }
@@ -246,9 +256,11 @@
 {
   gint i;
   g_return_if_fail(dialog);
-  g_assert(dialog->var);
+  g_return_if_fail(dialog->pv);
+
+  mv_copy (&dialog->mvl, psppire_variable_get_missing(dialog->pv));
 
-  mv_copy (&dialog->mvl, &dialog->var->miss);
+  const struct fmt_spec *write_spec = 
psppire_variable_get_write_spec(dialog->pv);
 
   /* Blank all entry boxes and make them insensitive */
   gtk_entry_set_text(GTK_ENTRY(dialog->low), "");
@@ -259,7 +271,7 @@
   gtk_widget_set_sensitive(dialog->discrete, FALSE);   
 
   gtk_widget_set_sensitive(GTK_WIDGET(dialog->button_range), 
-                          dialog->var->type == NUMERIC);
+                          psppire_variable_get_type(dialog->pv) == NUMERIC);
 
   for(i = 0 ; i < 3 ; ++i ) 
     {
@@ -274,8 +286,8 @@
       gchar *high_text;
       mv_peek_range(&dialog->mvl, &low.f, &high.f);
 
-      low_text = value_to_text(low, dialog->var->write);
-      high_text = value_to_text(high, dialog->var->write);
+      low_text = value_to_text(low, *write_spec);
+      high_text = value_to_text(high, *write_spec);
       
       gtk_entry_set_text(GTK_ENTRY(dialog->low), low_text);
       gtk_entry_set_text(GTK_ENTRY(dialog->high), high_text);
@@ -287,7 +299,7 @@
          gchar *text;
          union value value;
          mv_peek_value(&dialog->mvl, &value, 0);
-         text = value_to_text(value, dialog->var->write);
+         text = value_to_text(value, *write_spec);
          gtk_entry_set_text(GTK_ENTRY(dialog->discrete), text);
          g_free(text);
        }
@@ -309,7 +321,7 @@
              union value value;
 
              mv_peek_value(&dialog->mvl, &value, i);
-             gchar *text = value_to_text(value, dialog->var->write);
+             gchar *text = value_to_text(value, *write_spec);
              gtk_entry_set_text(GTK_ENTRY(dialog->mv[i]), text);
              g_free(text);
            }
Index: psppire/src/missing_val_dialog.h
diff -u psppire/src/missing_val_dialog.h:1.1 
psppire/src/missing_val_dialog.h:1.2
--- psppire/src/missing_val_dialog.h:1.1        Sat Dec  3 00:13:34 2005
+++ psppire/src/missing_val_dialog.h    Sat Jan 28 08:48:08 2006
@@ -18,8 +18,8 @@
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     02110-1301, USA. */
 
-#ifndef __PSPP_MISSING_VAL_DIALOG_H
-#define __PSPP_MISSING_VAL_DIALOG_H
+#ifndef __PSPPIRE_MISSING_VAL_DIALOG_H
+#define __PSPPIRE_MISSING_VAL_DIALOG_H
 
 /*  This module describes the behaviour of the Missing Values dialog box,
     used for input of the missing values in the variable sheet */
@@ -35,7 +35,7 @@
   GtkWidget *window;
 
   /* The variable whose missing values are to be updated */
-  struct variable *var;
+  struct PsppireVariable *pv;
   
   /* local copy */
   struct missing_values mvl;
Index: psppire/src/val_labs_dialog.c
diff -u psppire/src/val_labs_dialog.c:1.6 psppire/src/val_labs_dialog.c:1.7
--- psppire/src/val_labs_dialog.c:1.6   Fri Dec 23 23:34:03 2005
+++ psppire/src/val_labs_dialog.c       Sat Jan 28 08:48:08 2006
@@ -27,6 +27,7 @@
 #include "val_labs_dialog.h"
 #include "value-labels.h"
 #include "misc.h"
+#include "psppire-variable.h"
 
 /* This callback occurs when the text in the label entry box 
    is changed */
@@ -39,7 +40,9 @@
   union value v;
   const gchar *text = gtk_entry_get_text(GTK_ENTRY(dialog->value_entry));
 
-  text_to_value(text, &v, dialog->var->write);
+  text_to_value(text, &v, 
+               *psppire_variable_get_write_spec(dialog->pv));
+
 
   if ( val_labs_find (dialog->labs, v) ) 
     {
@@ -103,7 +106,9 @@
   const gchar *text = gtk_entry_get_text(GTK_ENTRY(dialog->value_entry));
 
   union value v;
-  text_to_value(text, &v, dialog->var->write);
+  text_to_value(text, &v, 
+               *psppire_variable_get_write_spec(dialog->pv));
+
 
   g_signal_handler_block(GTK_ENTRY(dialog->label_entry), 
                         dialog->change_handler_id);
@@ -137,8 +142,8 @@
 {
   struct val_labs_dialog *dialog = data;
 
-  val_labs_destroy(dialog->var->val_labs);
-  dialog->var->val_labs = val_labs_copy(dialog->labs);
+  psppire_variable_set_value_labels(dialog->pv, dialog->labs);
+
   val_labs_destroy (dialog->labs);
   dialog->labs = 0;
 
@@ -198,7 +203,8 @@
   
   union value v;
   
-  text_to_value(val_text, &v, dialog->var->write);
+  text_to_value(val_text, &v, 
+               *psppire_variable_get_write_spec(dialog->pv));
 
   val_labs_replace (dialog->labs, v,
                    gtk_entry_get_text(GTK_ENTRY(dialog->label_entry)));
@@ -220,7 +226,9 @@
 
   const gchar *text = gtk_entry_get_text(GTK_ENTRY(dialog->value_entry));
 
-  text_to_value(text, &v, dialog->var->write);
+  text_to_value(text, &v, 
+               *psppire_variable_get_write_spec(dialog->pv));
+
 
   if ( ! val_labs_add (dialog->labs, v,
                       gtk_entry_get_text(GTK_ENTRY(dialog->label_entry)) ) )
@@ -263,7 +271,8 @@
 
   struct val_lab * vl  = get_selected_tuple(dialog);
 
-  gchar *const text = value_to_text(vl->value, dialog->var->write);
+  gchar *const text = value_to_text(vl->value, 
+                                   
*psppire_variable_get_write_spec(dialog->pv));
 
   g_signal_handler_block(GTK_ENTRY(dialog->value_entry), 
                         dialog->value_handler_id);
@@ -397,7 +406,10 @@
       vl;
       vl = val_labs_next(dialog->labs, &vli))
     {
-      gchar *const vstr  = value_to_text(vl->value, dialog->var->write);
+      gchar *const vstr  = 
+       value_to_text(vl->value, 
+                     *psppire_variable_get_write_spec(dialog->pv));
+
                                           
       
       gchar *const text = g_strdup_printf("%s = \"%s\"",
@@ -425,7 +437,10 @@
 val_labs_dialog_show(struct val_labs_dialog *dialog)
 {
   g_assert(!dialog->labs);
-  dialog->labs = val_labs_copy(dialog->var->val_labs);
+  dialog->labs = val_labs_copy(
+                              psppire_variable_get_value_labels(dialog->pv)
+                              );
+
 
   gtk_widget_set_sensitive(dialog->remove_button, FALSE);
   gtk_widget_set_sensitive(dialog->change_button, FALSE);
Index: psppire/src/val_labs_dialog.h
diff -u psppire/src/val_labs_dialog.h:1.2 psppire/src/val_labs_dialog.h:1.3
--- psppire/src/val_labs_dialog.h:1.2   Mon Dec 12 07:52:51 2005
+++ psppire/src/val_labs_dialog.h       Sat Jan 28 08:48:08 2006
@@ -20,8 +20,8 @@
 
 
 
-#ifndef __PSPP_VAL_LABS_DIALOG_H
-#define __PSPP_VAL_LABS_DIALOG_H
+#ifndef __PSPPIRE_VAL_LABS_DIALOG_H
+#define __PSPPIRE_VAL_LABS_DIALOG_H
 
 
 /*  This module describes the behaviour of the Value Labels dialog box,
@@ -38,8 +38,9 @@
 {
   GtkWidget *window;
 
+
   /* The variable to be updated */
-  struct variable *var;
+  struct PsppireVariable *pv;
 
   /* Local copy of labels */
   struct val_labs *labs;
Index: psppire/src/var_sheet.c
diff -u psppire/src/var_sheet.c:1.31 psppire/src/var_sheet.c:1.32
--- psppire/src/var_sheet.c:1.31        Fri Dec 23 23:34:03 2005
+++ psppire/src/var_sheet.c     Sat Jan 28 08:48:08 2006
@@ -1,6 +1,6 @@
 /* 
    PSPPIRE --- A Graphical User Interface for PSPP
-   Copyright (C) 2004,2005  Free Software Foundation
+   Copyright (C) 2004, 2005, 2006  Free Software Foundation
    Written by John Darrington
 
    This program is free software; you can redistribute it and/or modify
@@ -33,11 +33,16 @@
 #include <stdlib.h>
 #include <string.h>
 
+#define min(A,B) ((A < B)?A:B)
+
 #include "gtksheet.h"
+#include "gsheet-hetero-column.h"
+#include "psppire-var-store.h"
 
 
-#include "callbacks.h"
-#include "pspp-dict.h"
+#include "menu-actions.h"
+#include "psppire-dict.h"
+#include "psppire-variable.h"
 #include "var_type_dialog.h"
 #include "var_sheet.h"
 #include "customentry.h"
@@ -49,35 +54,19 @@
 #define _(A) A
 #define N_(A) A
 
-/* The dictionary associated with this var sheet */
-static PSPP_Dict *pspp_dictionary;
-
 
-static gint last_populated_row = -1;
-static struct var_type_dialog *var_type_dialog;
-static struct val_labs_dialog *val_labs_dialog;
-static struct missing_val_dialog *missing_val_dialog;
 static const gint n_initial_rows = 40;
 
 
-static gint var_sheet_update_callback(GObject *obj, 
-                                     gint var_idx, gpointer data);
-
-static gint update_variable(GtkSheet *sheet, gint row, gint col);
-
-
 extern GladeXML *xml;
 
-static GdkColor enabled;
-static GdkColor disabled;
-
 struct column_parameters
 {
   gchar label[20];  
   gint width ;
 };
 
-const struct column_parameters column_def[] = {
+static const struct column_parameters column_def[] = {
   {N_("Name"),    80},
   {N_("Type"),    100},
   {N_("Width"),   57}, 
@@ -90,22 +79,6 @@
   {N_("Measure"), 99}, 
 };
 
-enum {COL_NAME, 
-      COL_TYPE, 
-      COL_WIDTH, 
-      COL_DECIMALS, 
-      COL_LABEL, 
-      COL_VALUES, 
-      COL_MISSING, 
-      COL_COLUMNS, 
-      COL_ALIGN, 
-      COL_MEASURE, 
-      n_COLS};
-
-
-static void psppire_var_sheet_unblock(GtkSheet *sheet);
-
-static void psppire_var_sheet_block(GtkSheet *sheet);
 
 static gboolean
 click2row(GtkWidget *w, gint row, gpointer data)
@@ -124,29 +97,15 @@
 }
 
 
-/* Returns a valid name for a new variable in DICT.
-   The return value must be freed when no longer required. */
-static gchar * 
-auto_generate_var_name(PSPP_Dict *dict)
-{
-  gint d = 0;
-  gchar *name;
-
-  while (name = g_strdup_printf("VAR%05d",d++), 
-        pspp_dict_lookup_var(dict, name))
-    g_free(name);
 
-  return name;
-}
-
-static  const gchar *alignments[]={
+const gchar *alignments[]={
   _("Left"),
   _("Right"),
   _("Centre"),
   0
 };
 
-static  const gchar *measures[]={
+const gchar *measures[]={
   _("Nominal"),
   _("Ordinal"),
   _("Scale"),
@@ -180,38 +139,66 @@
 change_alignment(GtkComboBox *cb,
     gpointer user_data)
 {
-  struct variable *var = user_data;
+  struct PsppireVariable *pv = user_data;
   gint active_item = gtk_combo_box_get_active(cb);
 
   if ( active_item < 0 ) return ;
 
-  var->alignment = active_item;
-
-  /* Inform the dictionary of the change so that it can emit a signal 
-     to let the data sheet know */
-  pspp_dict_var_changed(pspp_dictionary, var->index);
-
+  psppire_variable_set_alignment(pv, active_item);
 }
 
 
-/* Callback for when the alignment combo box 
+
+/* Callback for when the measure combo box 
    item is selected */
 static void        
 change_measure(GtkComboBox *cb,
     gpointer user_data)
 {
-  struct variable *var = user_data;
+  struct PsppireVariable *pv = user_data;
   gint active_item = gtk_combo_box_get_active(cb);
 
   if ( active_item < 0 ) return ;
 
-  var->measure = active_item + 1;
+  psppire_variable_set_measure(pv, active_item);
 }
 
-static void
-set_variable_changed(struct variable *var)
+
+
+static gboolean 
+traverse_cell_callback (GtkSheet * sheet, 
+                       gint row, gint column, 
+                       gint *new_row, gint *new_column
+                       )
 {
-  pspp_dict_var_changed(pspp_dictionary, var->index);
+  PsppireVarStore *var_store = PSPPIRE_VAR_STORE(gtk_sheet_get_model(sheet));
+
+  gint n_vars = psppire_var_store_get_var_cnt(var_store);
+
+  if ( row == n_vars && *new_row >= n_vars)
+    {
+      GtkEntry *entry = GTK_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;
+      
+      psppire_dict_insert_variable(var_store->dict, row, name);
+
+      return TRUE;
+    }
+
+  /* If the destination cell is outside the current  variables, then
+     accept the destination only as the name column of the first blank row
+  */
+  if ( *new_row > n_vars) 
+    return FALSE;
+  
+  if ( *new_row >= n_vars && *new_column != COL_NAME) 
+    return FALSE;
+
+  return TRUE;
 }
 
 
@@ -224,6 +211,11 @@
 {
   g_return_val_if_fail(sheet != NULL, FALSE);
 
+  PsppireVarStore *var_store = PSPPIRE_VAR_STORE(gtk_sheet_get_model(sheet));
+
+  if ( row >= psppire_var_store_get_var_cnt(var_store))
+    return TRUE;
+
   if ( leaving ) 
     {
       gtk_sheet_change_entry(sheet, GTK_TYPE_ENTRY);
@@ -233,6 +225,8 @@
   GtkSheetCellAttr attributes;
   gtk_sheet_get_attributes(sheet, row, column, &attributes);
 
+  struct PsppireVariable *pv = psppire_var_store_get_variable(var_store, row);
+
   switch (column)
     {
     case COL_ALIGN:
@@ -251,10 +245,9 @@
 
        gtk_combo_box_entry_set_text_column (cbe, 0);
 
-       struct variable *var = pspp_dict_get_var(pspp_dictionary, row);      
-       
+
        g_signal_connect(G_OBJECT(cbe),"changed", 
-                        G_CALLBACK(change_alignment), var);
+                        G_CALLBACK(change_alignment), pv);
       }
       break;
     case COL_MEASURE:
@@ -273,18 +266,16 @@
 
        gtk_combo_box_entry_set_text_column (cbe, 0);
 
-       struct variable *var = pspp_dict_get_var(pspp_dictionary, row);      
-
        g_signal_connect(G_OBJECT(cbe),"changed", 
-                        G_CALLBACK(change_measure), var);
+                        G_CALLBACK(change_measure), pv);
       }
       break;
 
     case COL_VALUES:
       {
-       PsppireCustomEntry *customEntry;
+       static struct val_labs_dialog *val_labs_dialog = 0;
 
-       struct variable *var = pspp_dict_get_var(pspp_dictionary, row);      
+       PsppireCustomEntry *customEntry;
 
        gtk_sheet_change_entry(sheet, PSPPIRE_CUSTOM_ENTRY_TYPE);
 
@@ -295,7 +286,7 @@
        if (!val_labs_dialog ) 
            val_labs_dialog = val_labs_dialog_create(xml);
 
-       val_labs_dialog->var = var;
+       val_labs_dialog->pv = pv;
 
        g_signal_connect_swapped(GTK_OBJECT(customEntry),
                                 "clicked",
@@ -305,6 +296,7 @@
       break;
     case COL_MISSING:
       {
+       static struct missing_val_dialog *missing_val_dialog = 0;
        PsppireCustomEntry *customEntry;
        
        gtk_sheet_change_entry(sheet, PSPPIRE_CUSTOM_ENTRY_TYPE);
@@ -312,11 +304,10 @@
        customEntry = 
          PSPPIRE_CUSTOM_ENTRY(gtk_sheet_get_entry(sheet));
 
-
        if (!missing_val_dialog ) 
            missing_val_dialog = missing_val_dialog_create(xml);
 
-       missing_val_dialog->var = pspp_dict_get_var(pspp_dictionary, row);
+       missing_val_dialog->pv = psppire_var_store_get_variable(var_store, row);
 
        g_signal_connect_swapped(GTK_OBJECT(customEntry),
                                 "clicked",
@@ -327,9 +318,9 @@
 
     case COL_TYPE:
       {
-       PsppireCustomEntry *customEntry;
+       static struct var_type_dialog *var_type_dialog = 0;
 
-       struct variable *var = pspp_dict_get_var(pspp_dictionary, row);      
+       PsppireCustomEntry *customEntry;
 
        gtk_sheet_change_entry(sheet, PSPPIRE_CUSTOM_ENTRY_TYPE);
 
@@ -339,13 +330,10 @@
 
        /* Popup the Variable Type dialog box */
        if (!var_type_dialog ) 
-         {
            var_type_dialog = var_type_dialog_create(xml);
 
-         }
 
-       var_type_dialog_set_variable(var_type_dialog, 
-                                    set_variable_changed, var);
+       var_type_dialog->pv = pv;
 
        g_signal_connect_swapped(GTK_OBJECT(customEntry),
                                 "clicked",
@@ -361,20 +349,23 @@
          {
            gint r_min, r_max;
 
-           const gint current_value  = 
-             atoi(gtk_sheet_cell_get_text(sheet, row, column));
+           const gchar *s = gtk_sheet_cell_get_text(sheet, row, column);
+
+           if (!s) 
+             return FALSE;
 
-           struct variable *var = pspp_dict_get_var(pspp_dictionary, row);
- 
+           const gint current_value  = atoi(s);
+
+           const struct fmt_spec *fmt = psppire_variable_get_write_spec(pv);
            switch (column) 
              {
              case COL_WIDTH:
-               r_min = 1;
-               r_max = var->type == ALPHA ? 255 : 40;
+               r_min = fmt->d + 1;
+               r_max = (psppire_variable_get_type(pv) == ALPHA) ? 255 : 40;
                break;
              case COL_DECIMALS:
-               r_min = 0;
-               r_max = 16;
+               r_min = 0 ; 
+               r_max = min(fmt->w - 1, 16);
                break;
              case COL_COLUMNS:
                r_min = 1;
@@ -384,7 +375,6 @@
                g_assert_not_reached();
              }
 
-
            GtkObject *adj =  
              gtk_adjustment_new(current_value,
                                 r_min, r_max,
@@ -410,349 +400,8 @@
   return TRUE;
 }
 
-/* Callback whenever the cell on the var sheet is entered */
-static gboolean 
-var_sheet_cell_set (GtkSheet * sheet, gint row, gint column)
-{
-  g_return_val_if_fail(sheet, FALSE);
-  
-  if ( ! pspp_dictionary ) 
-    return  FALSE;
-
-  gint r;
-  /* Fill out any rows above, which are empty */
-  for ( r = last_populated_row + 1 ; r < row ; ++r ) 
-    {
-      gchar *name = auto_generate_var_name(pspp_dictionary);
-      pspp_dict_set_name(pspp_dictionary, r, name);
-      g_free(name);
-    }
-  if ( row - 1 > last_populated_row)
-    last_populated_row = row - 1;
-
-  struct variable *var = pspp_dict_get_var(pspp_dictionary, row);      
-  
-  /* Fill out any cells to the left which are empty */
-  if ( var == NULL && column != 0 ) 
-    {
-      gchar *name = auto_generate_var_name(pspp_dictionary);
-      pspp_dict_set_name(pspp_dictionary, row, name);
-      g_free(name);
-      last_populated_row = row ;
-      var = pspp_dict_get_var(pspp_dictionary, row);      
-    }
-
-  /* Add the necessary number of rows to the sheet */
-  const gint n_new_rows =
-    n_initial_rows - gtk_sheet_get_rows_count(sheet) +  
-    (last_populated_row + 1) ;
-  
-  g_assert(n_new_rows >= 0);
-
-  gtk_sheet_add_row(sheet, n_new_rows);
-
-  g_assert(gtk_sheet_get_rows_count(sheet) - last_populated_row 
-           == n_initial_rows + 1);
-
-  return FALSE;
-}
-
-
-
-static GString *
-gint_to_gstring(gint x)
-{
-  GString *s = g_string_new ("x");
-
-  g_string_printf (s, "%d",x);
-           
-  return s;
-}
-
-
-/* Change the editability of the cells URANGE in SHEET according to the flag
-   EDITABLE */
-void
-var_sheet_range_set_editable(GtkSheet *sheet, 
-                            const GtkSheetRange *urange, 
-                            gboolean editable)
-{
-  gtk_sheet_range_set_editable (sheet, urange, editable);
-  
-  gtk_sheet_range_set_foreground (sheet,
-                                 urange,
-                                 editable ? &enabled : &disabled);
-
-  gtk_sheet_range_set_background (sheet,
-                                 urange,
-                                 &sheet->bg_color);
-}
-
-
-
-
-/* Populate ROW according to the variable VAR */
-static void
-populate_row_from_var(GtkSheet *sheet, const struct variable *var, 
-                     gint row)
-{
-  gint c;
-  if (!var)
-    {
-      GtkSheetRange range;
-      range.row0 = range.rowi = row;
-      range.col0 = 0 ; range.coli = gtk_sheet_get_columns_count(sheet) - 1;
-      gtk_sheet_range_clear (sheet, &range);
-      return;
-    }
-
-  const struct fmt_spec *write_spec = &var->write;
-
-  /* Set the editability of the cells */
-
-  GtkSheetRange range;
-  range.col0 = 0;
-  range.coli = n_COLS;
-  range.row0 = range.rowi = row;
-
-  var_sheet_range_set_editable (sheet, &range, TRUE);
-
-  /* Certain types must disable certain columns */
-  switch ( write_spec->type ) 
-    {
-    case FMT_A:
-      {
-       /* Strings don't have decimal places */
-       GtkSheetRange range;
-       range.col0 = range.coli = COL_DECIMALS;
-       range.row0 = range.rowi = row;
-
-       var_sheet_range_set_editable (sheet, &range, FALSE);
-      }
-      break;
-      
-    case FMT_DATE:     
-    case FMT_EDATE:    
-    case FMT_SDATE:    
-    case FMT_ADATE:    
-    case FMT_JDATE:    
-    case FMT_QYR:      
-    case FMT_MOYR:     
-    case FMT_WKYR:     
-    case FMT_DATETIME: 
-    case FMT_TIME:     
-    case FMT_DTIME:    
-    case FMT_WKDAY:    
-    case FMT_MONTH:    
-      {
-       /* Dates don't have decimal places and the width is automatic */
-       GtkSheetRange range;
-       range.col0 = COL_WIDTH;
-       range.coli = COL_DECIMALS;
-       range.row0 = range.rowi = row;
-       var_sheet_range_set_editable (sheet, &range, FALSE);
-      }
-      break;
-    }
-
-  for ( c = 0 ; c < n_COLS ; ++c ) 
-    {
-      switch (c)
-       {
-       case COL_NAME:
-         gtk_sheet_set_cell_text (sheet, row, c, var->name);
-         break;
-       case COL_TYPE:
-         {
-           switch ( write_spec->type ) 
-             {
-             case FMT_F:
-               gtk_sheet_set_cell_text(sheet, row, c, _("Numeric"));
-               break;
-             case FMT_COMMA:
-               gtk_sheet_set_cell_text(sheet, row, c, _("Comma"));
-               break;
-             case FMT_DOT:
-               gtk_sheet_set_cell_text(sheet, row, c, _("Dot"));
-               break;
-             case FMT_E:
-               gtk_sheet_set_cell_text(sheet, row, c, _("Scientific"));
-               break;
-             case FMT_DATE:    
-             case FMT_EDATE:   
-             case FMT_SDATE:   
-             case FMT_ADATE:   
-             case FMT_JDATE:   
-             case FMT_QYR:     
-             case FMT_MOYR:    
-             case FMT_WKYR:    
-             case FMT_DATETIME:        
-             case FMT_TIME:    
-             case FMT_DTIME:   
-             case FMT_WKDAY:   
-             case FMT_MONTH:   
-               gtk_sheet_set_cell_text(sheet, row, c, _("Date"));
-               break;
-             case FMT_DOLLAR:
-               gtk_sheet_set_cell_text(sheet, row, c, _("Dollar"));
-               break;
-             case FMT_CCA:
-             case FMT_CCB:
-             case FMT_CCC:
-             case FMT_CCD:
-             case FMT_CCE:
-               gtk_sheet_set_cell_text(sheet, row, c, _("Custom"));
-               break;
-             case FMT_A:
-               gtk_sheet_set_cell_text(sheet, row, c, _("String"));
-               break;
-             default:
-               g_warning("Unknown format: \"%s\"\n", 
-                               fmt_to_string(write_spec));
-               break;
-             }
-         }
-         break;
-       case COL_WIDTH:
-         {
-           GString *s = gint_to_gstring(var->write.w);
-           gtk_sheet_set_cell_text(sheet, row, c, s->str);       
-           g_string_free(s, TRUE);
-         }
-         break;
-       case COL_DECIMALS:
-         {
-           GString *s = gint_to_gstring(var->write.d);
-           gtk_sheet_set_cell_text(sheet, row, c, s->str);       
-           g_string_free(s, TRUE);
-         }
-         break;
-       case COL_COLUMNS:
-         {
-           GString *s = gint_to_gstring(var->display_width);
-           gtk_sheet_set_cell_text(sheet, row, c, s->str);       
-           g_string_free(s, TRUE);
-         }
-         break;
-       case COL_LABEL:
-         if (var->label)
-           gtk_sheet_set_cell_text(sheet, row, c, var->label);   
-         else
-           gtk_sheet_cell_clear(sheet, row, c);
-         break;
-       case COL_MISSING:
-         if ( mv_is_empty(&var->miss )) 
-           gtk_sheet_set_cell_text(sheet, row, c, _("None"));
-         else
-           {
-             gchar *text = 0;
-             if ( ! mv_has_range (&var->miss))
-               {
-                 const int n = mv_n_values(&var->miss);
-                 gchar *mv[4] = {0,0,0,0};
-                 gint i;
-                 for(i = 0 ; i < n; ++i ) 
-                   {
-                     union value v;
-                     mv_peek_value(&var->miss, &v, i);
-                     mv[i] = value_to_text(v, var->write);
-                   }
-                 text = g_strjoinv(", ", mv);
-                 for(i = 0 ; i < n; ++i ) 
-                   g_free(mv[i]);
-                 
-               }
-             else
-               {
-                 gchar *l, *h;
-                 union value low, high;
-                 mv_peek_range(&var->miss, &low.f, &high.f);
-                 
-                 l = value_to_text(low, var->write);
-                 h = value_to_text(high, var->write);
-
-                 text = g_strdup_printf("%s - %s", l, h);
-                 g_free(l);
-                 g_free(h);
-                 
-                 if ( mv_has_value(&var->miss)) 
-                   {
-                     gchar *s = 0;
-                     union value v;
-                     mv_peek_value(&var->miss, &v, 0);
-
-                     s = value_to_text(v, var->write);
-
-                     gchar *s2 = g_strdup_printf("%s, %s", text, s);
-                     free(s);
-                     free(text);
-                     text = s2;
-                   }
-               }
-
-             gtk_sheet_set_cell_text(sheet, row, c, text);
-             g_free(text);
-           }
-         break;
-       case COL_VALUES:
-         if ( ! var->val_labs || 0 == val_labs_count(var->val_labs)) 
-           gtk_sheet_set_cell_text(sheet, row, c, _("None"));
-         else
-           {
-             struct val_labs_iterator *ip=0;
-             struct val_lab *vl = val_labs_first_sorted (var->val_labs, &ip);
-
-             g_assert(vl);
-
-             gchar *const vstr = value_to_text(vl->value, var->write);
-             gchar *const text = 
-               g_strdup_printf("{%s,\"%s\"}_", vstr, vl->label);
-
-             gtk_sheet_set_cell_text(sheet, row, c, text);
-             
-             g_free(text);
-             g_free(vstr);
-
-             val_labs_done(&ip);
-           }
-         break;
-       case COL_ALIGN:
-         gtk_sheet_set_cell_text(sheet, row, c, alignments[var->alignment]);
-         break;
-       case COL_MEASURE:
-         gtk_sheet_set_cell_text(sheet, row, c, measures[var->measure-1]);
-         break;
-       }
-    }
-}
-
-/* Remove a variable from the variable sheet */
-static gint
-remove_variable(GObject *obj, gint idx, gpointer data)
-{
-  GtkSheet *sheet = GTK_SHEET(data);
-
-  g_signal_handlers_block_by_func(sheet,
-                  G_CALLBACK(var_sheet_cell_set), 0);
-  g_signal_handlers_block_by_func(sheet,
-                  G_CALLBACK(var_sheet_cell_change_entry), 0);
 
 
-  gtk_sheet_delete_rows(sheet, idx, 1);
-
-  last_populated_row--;
-
-  g_signal_handlers_unblock_by_func(sheet,
-                  G_CALLBACK(var_sheet_cell_set), 0);
-  g_signal_handlers_unblock_by_func(sheet,
-                  G_CALLBACK(var_sheet_cell_change_entry), 0);
-
-  g_assert(gtk_sheet_get_rows_count(sheet) - last_populated_row 
-           == n_initial_rows + 1);
-
-  return FALSE;
-}
-
 /* Create the var sheet */
 GtkWidget*
 psppire_variable_sheet_create (gchar *widget_name, 
@@ -760,16 +409,17 @@
                               gchar *string2,
                               gint int1, gint int2)
 {
-  GtkWidget *sheet;
   gint i;
+  GtkWidget *sheet;
 
-  sheet = gtk_sheet_new(n_initial_rows, n_COLS, "variable sheet"); 
+  GObject *geo = g_sheet_hetero_column_new(75, n_COLS);
+  GObject *row_geometry = g_sheet_uniform_row_new(25, n_initial_rows); 
 
-  gtk_sheet_range_set_editable (GTK_SHEET(sheet), 0, TRUE);
 
-  g_signal_connect (GTK_OBJECT (sheet), "activate",
-                   GTK_SIGNAL_FUNC (var_sheet_cell_set),
-                   0);
+
+  sheet = gtk_sheet_new(G_SHEET_ROW(row_geometry),
+                       G_SHEET_COLUMN(geo), 
+                       "variable sheet", 0); 
 
   g_signal_connect (GTK_OBJECT (sheet), "activate",
                    GTK_SIGNAL_FUNC (var_sheet_cell_change_entry),
@@ -779,10 +429,8 @@
                    GTK_SIGNAL_FUNC (var_sheet_cell_change_entry),
                    (void *) 1);
 
-
-  g_signal_connect (GTK_OBJECT (sheet), "set_cell",
-                   GTK_SIGNAL_FUNC (update_variable),
-                   0);
+  g_signal_connect (GTK_OBJECT (sheet), "traverse",
+                   GTK_SIGNAL_FUNC (traverse_cell_callback), 0);
 
 
   g_signal_connect (GTK_OBJECT (sheet), "double-click-row",
@@ -791,25 +439,12 @@
 
   for (i = 0 ; i < n_COLS ; ++i ) 
     {
-      gtk_sheet_column_button_add_label(GTK_SHEET(sheet), i, 
-                                        column_def[i].label);
-      gtk_sheet_set_column_width(GTK_SHEET(sheet), i, 
-                                 column_def[i].width);
-    }
+      g_sheet_hetero_column_set_button_label(G_SHEET_HETERO_COLUMN(geo), i, 
+                                              column_def[i].label);
 
-  /* Set the enabled colour to the default foreground colour */
-  GtkSheetCellAttr attributes;
-  g_assert(gtk_sheet_get_attributes (GTK_SHEET(sheet), 0, 0, &attributes));
-  enabled = attributes.foreground;
-
-  g_assert(gdk_color_parse("gray",&disabled));
-
-  GdkColormap *colormap = gdk_colormap_get_system();
-
-  gdk_colormap_alloc_color (colormap, &disabled, FALSE, TRUE);
-
-  PSPP_Dict *d = pspp_dict_new();
-  psppire_var_sheet_set_dictionary(GTK_SHEET(sheet), d);
+      g_sheet_hetero_column_set_width(G_SHEET_HETERO_COLUMN(geo), i, 
+                                              column_def[i].width);
+    }
 
   gtk_widget_show(sheet);
 
@@ -817,221 +452,3 @@
 }
 
 
-/* Update a variable.
-   This callback is invoked whenever a cell on the var_sheet is
-   changed
-*/
-static gint
-update_variable(GtkSheet *sheet, gint row, gint col)
-{
-  g_return_val_if_fail(sheet, FALSE);
-
-  g_assert(pspp_dictionary);
-  g_assert(G_IS_PSPP_DICT(pspp_dictionary));
-  
-  struct variable *old_var = pspp_dict_get_var(pspp_dictionary, row);
-
-  struct fmt_spec fmt;
-
-  if ( old_var) 
-    fmt = old_var->write;
-  
-  switch (col)
-    {
-    case COL_NAME:
-      {
-       const gchar *name = gtk_sheet_cell_get_text(sheet, row, col);
-       if ( old_var && (0 == strcmp(old_var->name, name)))
-         return FALSE;
-
-       if ( ! var_is_valid_name(name, 0 ) )
-         {
-           g_print("That name is not valid\n");
-           if ( old_var)
-             gtk_sheet_set_cell_text(sheet, row, col, old_var->name);
-           else
-             gtk_sheet_cell_clear(sheet, row, col);
-         }
-       else if (
-                pspp_dict_lookup_var(pspp_dictionary, name)
-                && 
-                /* Allow changes of case */
-                ( !old_var || 
-                  0 != strcasecmp(old_var->name, name))
-                )
-         {
-           g_print("Duplicate variable name\n");
-           gtk_sheet_set_cell_text(sheet, row, col, old_var->name);
-         }
-       else 
-         {
-           pspp_dict_set_name(pspp_dictionary, row, name);
-         }
-      }
-      break;
-    case COL_COLUMNS:
-      old_var->display_width =
-       atoi(gtk_sheet_cell_get_text(sheet, row, col));
-      pspp_dict_var_changed(pspp_dictionary, row);
-      break;
-    case COL_WIDTH:
-      fmt.w = atoi(gtk_sheet_cell_get_text(sheet, row, col));
-      if ( old_var && old_var->type == ALPHA ) 
-       old_var->width = fmt.w ;
-      break;
-    case COL_DECIMALS:
-      fmt.d = atoi(gtk_sheet_cell_get_text(sheet, row, col));
-      break;
-    case COL_LABEL:
-      {
-       const gchar *text = gtk_sheet_cell_get_text(sheet, row, col);
-
-       if ( !old_var->label || 0 != strcmp(old_var->label, text))
-         {
-           free(old_var->label);
-           old_var->label = g_strdup(text);
-         }
-      }
-      break;
-    }
-
-  if ( old_var ) 
-    {
-      if ( check_output_specifier(&fmt, true) 
-          && 
-          check_specifier_type(&fmt, old_var->type, true)
-          && 
-          check_specifier_width(&fmt, old_var->width, true)
-          ) 
-       {
-         old_var->write = old_var->print = fmt;
-       }
-      pspp_dict_var_changed(pspp_dictionary, row);
-    }
-
-  if ( row > last_populated_row ) 
-    last_populated_row = row ;
-
-  return FALSE;
-}
-
-
-
-/* This callback is invoked whenever a variable in the dictionary 
-   has changed.  VAR_IDX is the index of the changed variable. */
-static gint
-var_sheet_update_callback(GObject *obj, gint var_idx, gpointer data)
-{
-  PSPP_Dict *dict = PSPP_DICT(obj);
-  GtkSheet *sheet   = GTK_SHEET(data);
-
-  struct variable *var = pspp_dict_get_var(dict, var_idx);
-
-  populate_row_from_var(sheet, var, var_idx);
-
-  return FALSE;
-}
-
-
-/* Returns the dictionary associated with the sheet */
-PSPP_Dict *
-psppire_var_sheet_get_dictionary(GtkWidget *sheet)
-{
-  return pspp_dictionary;
-}
-
-
-/* Associate a dictionary with the var sheet.
-   If there is already a dictionary associated, then it will be destroyed.
- */
-void
-psppire_var_sheet_set_dictionary(GtkSheet *sheet, PSPP_Dict *d)
-{
-  gint v;
-
-  g_assert(sheet);
-
-  if ( pspp_dictionary) 
-    g_object_unref(pspp_dictionary);
-
-  pspp_dictionary  = d;
-
-  const int c = pspp_dict_get_var_cnt(d);
-
-  gtk_sheet_add_row(sheet, c);
-  last_populated_row = c - 1;
-
-
-  g_signal_connect(d, "variable_changed",
-                  G_CALLBACK(var_sheet_update_callback), sheet);
-
-  g_signal_connect(d, "variable_added",
-                  G_CALLBACK(var_sheet_update_callback), sheet);
-
-  g_signal_connect(d, "variable_deleted",
-                  G_CALLBACK(remove_variable), sheet);
-
-  for (v = 0 ; v < c ; ++v ) 
-    pspp_dict_var_changed(d, v);
-
-}
-
-
-/* Blank the sheet. And reset it ready for a fresh set of variables. */
-void
-psppire_var_sheet_clear(GtkSheet *sheet)
-{
-  g_return_if_fail(sheet);
-
-  psppire_var_sheet_block(sheet);
-
-  gtk_sheet_set_active_cell(sheet, 0, 0);
-
-  gtk_sheet_delete_rows(sheet, 
-                       0, last_populated_row + 1);
-
-  gtk_sheet_range_delete(sheet, NULL);
-
-  last_populated_row = -1;
-
-  var_sheet_range_set_editable(sheet, 0, FALSE);
-  
-  psppire_var_sheet_unblock(sheet);
-
-  g_assert( gtk_sheet_get_rows_count(sheet) == n_initial_rows );
-}
-
-
-
-static void
-psppire_var_sheet_unblock(GtkSheet *sheet)
-{
-  g_signal_handlers_unblock_by_func(sheet,
-                                   G_CALLBACK(var_sheet_cell_change_entry), 
-                                   0);
-
-  g_signal_handlers_unblock_by_func(sheet,
-                                   G_CALLBACK(var_sheet_cell_set), 0);
-
-  g_signal_handlers_unblock_by_func(sheet,
-                                   G_CALLBACK(update_variable), 
-                                   0);
-
-}
-
-
-static void
-psppire_var_sheet_block(GtkSheet *sheet)
-{
-  g_signal_handlers_block_by_func(sheet,
-                                   G_CALLBACK(update_variable), 
-                                   0);
-
-  g_signal_handlers_block_by_func(sheet,
-                                   G_CALLBACK(var_sheet_cell_change_entry), 
-                                   0);
-
-  g_signal_handlers_block_by_func(sheet,
-                                   G_CALLBACK(var_sheet_cell_set), 0);
-}
-
Index: psppire/src/var_sheet.h
diff -u psppire/src/var_sheet.h:1.1 psppire/src/var_sheet.h:1.2
--- psppire/src/var_sheet.h:1.1 Sat Nov 12 07:52:06 2005
+++ psppire/src/var_sheet.h     Sat Jan 28 08:48:08 2006
@@ -1,6 +1,6 @@
 /* 
    PSPPIRE --- A Graphical User Interface for PSPP
-   Copyright (C) 2004,2005  Free Software Foundation
+   Copyright (C) 2004, 2005, 2006  Free Software Foundation
    Written by John Darrington
 
    This program is free software; you can redistribute it and/or modify
@@ -22,6 +22,23 @@
 #ifndef VAR_SHEET_H
 #define VAR_SHEET_H
 
+#include "gtksheet.h"
+
+#include "psppire-dict.h"
+
+enum {COL_NAME, 
+      COL_TYPE, 
+      COL_WIDTH, 
+      COL_DECIMALS, 
+      COL_LABEL, 
+      COL_VALUES, 
+      COL_MISSING, 
+      COL_COLUMNS, 
+      COL_ALIGN, 
+      COL_MEASURE, 
+      n_COLS};
+
+
 void var_sheet_range_set_editable(GtkSheet *sheet, 
                                  const GtkSheetRange *urange, 
                                  gboolean editable);
@@ -34,17 +51,9 @@
                                          gint int1, gint int2);
 
 
-/* Returns the dictionary associated with the sheet */
-PSPP_Dict * psppire_var_sheet_get_dictionary(GtkWidget *sheet);
-
-/* Associate a dictionary with the var sheet..
-   If there is already a dictionary associated, then it will be destroyed.
- */
-void psppire_var_sheet_set_dictionary(GtkSheet *sheet, PSPP_Dict *d);
-
+extern const gchar *alignments[];
 
-/* Blank the sheet */
-void psppire_var_sheet_clear(GtkSheet *sheet);
+extern const gchar *measures[];
 
 
 #endif
Index: psppire/src/var_type_dialog.c
diff -u psppire/src/var_type_dialog.c:1.10 psppire/src/var_type_dialog.c:1.11
--- psppire/src/var_type_dialog.c:1.10  Fri Dec 23 23:34:03 2005
+++ psppire/src/var_type_dialog.c       Sat Jan 28 08:48:08 2006
@@ -29,11 +29,15 @@
 #include <string.h>
 
 #include "var_type_dialog.h"
+
+#include "psppire-variable.h"
+
 #include "misc.h"
 
 #include "var.h"
 #include "settings.h"
 
+
 struct tgs
 {
   struct var_type_dialog *dialog;
@@ -124,16 +128,16 @@
 static void
 set_local_width_decimals(struct var_type_dialog *dialog)
 {
-  *dialog->fmt_l = dialog->var->write;
+  dialog->fmt_l = * psppire_variable_get_write_spec(dialog->pv);
 
   switch (dialog->active_button) 
     {
     case BUTTON_STRING:
-      force_max( dialog->fmt_l->w, 255);
+      force_max( dialog->fmt_l.w, 255);
       break;
     default:
-      force_max( dialog->fmt_l->w, 40);
-      force_max( dialog->fmt_l->d, 16);
+      force_max( dialog->fmt_l.w, 40);
+      force_max( dialog->fmt_l.d, 16);
       break;
     }
 }
@@ -254,13 +258,12 @@
 update_width_decimals(const struct var_type_dialog *dialog)
 {
   g_assert(dialog);
-  g_assert(dialog->fmt_l);
 
-  gchar *text = g_strdup_printf("%d", dialog->fmt_l->w);
+  gchar *text = g_strdup_printf("%d", dialog->fmt_l.w);
   gtk_entry_set_text(GTK_ENTRY(dialog->entry_width), text);
   g_free(text);
 
-  text = g_strdup_printf("%d", dialog->fmt_l->d);
+  text = g_strdup_printf("%d", dialog->fmt_l.d);
   gtk_entry_set_text(GTK_ENTRY(dialog->entry_decimals), text);
   g_free(text);
 }
@@ -276,12 +279,12 @@
     return;
 
   const gchar *text = gtk_entry_get_text(GTK_ENTRY(dialog->entry_decimals));
-  dialog->fmt_l->d = atoi(text);
+  dialog->fmt_l.d = atoi(text);
 
   text = gtk_entry_get_text(GTK_ENTRY(dialog->entry_width));
-  dialog->fmt_l->w = atoi(text);
+  dialog->fmt_l.w = atoi(text);
 
-  if ( ! check_output_specifier(dialog->fmt_l, 0))
+  if ( ! check_output_specifier(&dialog->fmt_l, 0))
     {
       gtk_label_set_text(GTK_LABEL(dialog->label_psample), "---");
       gtk_label_set_text(GTK_LABEL(dialog->label_nsample), "---");
@@ -292,12 +295,12 @@
       union value v;
       v.f = 1234.56;
 
-      sample_text = value_to_text(v, *dialog->fmt_l);
+      sample_text = value_to_text(v, dialog->fmt_l);
       gtk_label_set_text(GTK_LABEL(dialog->label_psample), sample_text);
       g_free(sample_text);
 
       v.f = -v.f;
-      sample_text = value_to_text(v, *dialog->fmt_l);
+      sample_text = value_to_text(v, dialog->fmt_l);
       gtk_label_set_text(GTK_LABEL(dialog->label_nsample), sample_text);
       g_free(sample_text);
     }
@@ -320,8 +323,7 @@
 
   gtk_tree_model_get_value(model, &iter, 1, &the_value);
 
-  *dialog->fmt_l = *(struct fmt_spec *) g_value_get_pointer(&the_value);
-  
+  dialog->fmt_l = *(struct fmt_spec *) g_value_get_pointer(&the_value);
 }
 
 
@@ -343,8 +345,8 @@
 
   gtk_tree_model_get_value(model, &iter, 1, &the_value);
 
-  *dialog->fmt_l = custom_format;
-  dialog->fmt_l->type = *(int*) g_value_get_pointer(&the_value);
+  dialog->fmt_l = custom_format;
+  dialog->fmt_l.type = *(int*) g_value_get_pointer(&the_value);
 
 }
 
@@ -360,8 +362,6 @@
 
   struct var_type_dialog *dialog = g_malloc(sizeof(struct var_type_dialog));
 
-  dialog->fmt_l = g_malloc(sizeof *dialog->fmt_l);
-
   dialog->window = get_widget_assert(xml,"var_type_dialog");
 
   gtk_window_set_transient_for(GTK_WINDOW(dialog->window), 
@@ -663,27 +663,23 @@
 }
 
 /* Set up the state of the dialog box to match the variable VAR */
-void
-var_type_dialog_set_variable(struct var_type_dialog *dialog, 
-                            variable_changed_func set_variable_changed,
-                            struct variable *var)
+static void
+var_type_dialog_set_state(struct var_type_dialog *dialog)
 {
-  /* Populate width and decimals */
-  const struct fmt_spec write_spec = var->write;
-
   g_assert(dialog);
+  g_assert(dialog->pv);
+
+  /* Populate width and decimals */
+  const struct fmt_spec *write_spec = 
psppire_variable_get_write_spec(dialog->pv);
 
-  dialog->var = var;
-  dialog->var_change_func = set_variable_changed;
-  
   GString *str = g_string_new("");
   
-  g_string_printf(str, "%d", write_spec.d);
+  g_string_printf(str, "%d", write_spec->d);
 
   gtk_entry_set_text(GTK_ENTRY(dialog->entry_decimals), 
                     str->str);
 
-  g_string_printf(str, "%d", write_spec.w);
+  g_string_printf(str, "%d", write_spec->w);
 
   gtk_entry_set_text(GTK_ENTRY(dialog->entry_width), 
                     str->str);
@@ -691,7 +687,7 @@
   g_string_free(str, TRUE);
 
   /* Populate the radio button states */
-  switch (write_spec.type)
+  switch (write_spec->type)
     {
     case FMT_F:
       var_type_dialog_set_active_button(dialog, BUTTON_NUMERIC);
@@ -714,7 +710,7 @@
       var_type_dialog_set_active_button(dialog, BUTTON_DOLLAR);
       gtk_widget_show_all(dialog->width_decimals);
       
-      select_treeview_from_format(dialog->dollar_treeview, &var->write);
+      select_treeview_from_format(dialog->dollar_treeview, write_spec);
       break;
     case FMT_DATE:     
     case FMT_EDATE:    
@@ -732,7 +728,7 @@
       var_type_dialog_set_active_button(dialog, BUTTON_DATE);
       gtk_widget_hide(dialog->width_decimals);
       gtk_widget_show(dialog->date_format_list);
-      select_treeview_from_format(dialog->date_format_treeview, &var->write);
+      select_treeview_from_format(dialog->date_format_treeview, write_spec);
       break;
     case FMT_CCA:
     case FMT_CCB:
@@ -741,7 +737,7 @@
     case FMT_CCE:
       var_type_dialog_set_active_button(dialog, BUTTON_CUSTOM);
       select_treeview_from_format_type(dialog->custom_treeview, 
-                                      var->write.type);
+                                      write_spec->type);
       gtk_widget_show_all(dialog->width_decimals);
       break;
     default:
@@ -755,6 +751,8 @@
 void 
 var_type_dialog_show(struct var_type_dialog *dialog)
 {
+  var_type_dialog_set_state(dialog);
+
   gtk_widget_show(dialog->window);
 }
 
@@ -780,12 +778,10 @@
 static gint
 on_var_type_ok_clicked(GtkWidget *w, gpointer data)
 {
-
   struct var_type_dialog *dialog = data;
 
   g_assert(dialog);
-  g_assert(dialog->var);
-
+  g_assert(dialog->pv);
 
   gint width = atoi(gtk_entry_get_text
               (GTK_ENTRY(dialog->entry_width)));
@@ -818,9 +814,8 @@
       break;
     case BUTTON_DATE:
     case BUTTON_CUSTOM:
-      g_assert(dialog->fmt_l);
-      g_assert(check_output_specifier(dialog->fmt_l, TRUE));
-      result = memcpy(&spec, dialog->fmt_l, sizeof(struct fmt_spec));
+      g_assert(check_output_specifier(&dialog->fmt_l, TRUE));
+      result = memcpy(&spec, &dialog->fmt_l, sizeof(struct fmt_spec));
       break;
     case BUTTON_DOLLAR:
       result = make_output_format_try(&spec, FMT_DOLLAR, width, decimals);
@@ -833,14 +828,12 @@
 
   if ( result == true ) 
     {
-      dialog->var->type = new_type;
-      dialog->var->width = new_width;
-      dialog->var->write = dialog->var->print = spec;
+      psppire_variable_set_type(dialog->pv, new_type);
+      psppire_variable_set_width(dialog->pv, new_width);
+      psppire_variable_set_write_spec(dialog->pv, spec);
+      psppire_variable_set_print_spec(dialog->pv, spec);
     }
 
-
-  dialog->var_change_func(dialog->var);
-
   gtk_widget_hide(dialog->window);
 
   return FALSE;
Index: psppire/src/var_type_dialog.h
diff -u psppire/src/var_type_dialog.h:1.7 psppire/src/var_type_dialog.h:1.8
--- psppire/src/var_type_dialog.h:1.7   Thu Dec 22 08:56:59 2005
+++ psppire/src/var_type_dialog.h       Sat Jan 28 08:48:08 2006
@@ -19,13 +19,14 @@
     02110-1301, USA. */
 
 
-#ifndef __PSPP_VAR_TYPE_DIALOG_H
-#define __PSPP_VAR_TYPE_DIALOG_H
+#ifndef __PSPPIRE_VAR_TYPE_DIALOG_H
+#define __PSPPIRE_VAR_TYPE_DIALOG_H
 
 
 /*  This module describes the behaviour of the Variable Type dialog box,
     used for input of the variable type parameter in the var sheet */
 
+#include "format.h"
 
 enum 
   {
@@ -49,13 +50,16 @@
   GtkWidget *window;
 
   /* Variable to be updated */
+  struct PsppireVariable *pv;
+#if 0
   struct variable *var;
 
   /* Function to be run when the dialog changes a variable */
   variable_changed_func var_change_func;
+#endif
 
   /* Local copy of format specifier */
-  struct fmt_spec *fmt_l;
+  struct fmt_spec fmt_l;
 
   /* Toggle Buttons */
   GtkWidget *radioButton[num_BUTTONS];




reply via email to

[Prev in Thread] Current Thread [Next in Thread]