Add "dictionary" property to PsppireVarStore and use it.
[pspp-builds.git] / src / ui / gui / psppire-var-store.c
index 3b3011f0a10a4837c70daa0a408196957b4c4c0f..ece728127c142733b6986844146d22e06129b9fb 100644 (file)
@@ -1,11 +1,9 @@
-/* psppire-var-store.c
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2006, 2009  Free Software Foundation
 
 
-   PSPPIRE --- A Graphical User Interface for PSPP
-   Copyright (C) 2006  Free Software Foundation
-
-   This program is free software; you can redistribute it and/or modify
+   This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -14,9 +12,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA. */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
 #include <string.h>
 
 #include <config.h>
 #include <string.h>
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 
-
+#include <libpspp/i18n.h>
 
 #include <gobject/gvaluecollector.h>
 
 
 #include <gobject/gvaluecollector.h>
 
-#include <gtksheet/gsheetmodel.h>
+#include <ui/gui/sheet/psppire-sheetmodel.h>
 
 #include "psppire-var-store.h"
 
 #include "psppire-var-store.h"
-#include "var-sheet.h"
 #include "helper.h"
 
 #include <data/dictionary.h>
 #include <data/variable.h>
 #include "helper.h"
 
 #include <data/dictionary.h>
 #include <data/variable.h>
+#include <data/format.h>
 #include <data/missing-values.h>
 
 #include "val-labs-dialog.h"
 #include "missing-val-dialog.h"
 #include <data/value-labels.h>
 
 #include <data/missing-values.h>
 
 #include "val-labs-dialog.h"
 #include "missing-val-dialog.h"
 #include <data/value-labels.h>
 
+#include "var-display.h"
+
+static void
+var_change_callback (GtkWidget *w, gint n, gpointer data)
+{
+  PsppireSheetModel *model = PSPPIRE_SHEET_MODEL (data);
+
+  psppire_sheet_model_range_changed (model,
+                                n, 0, n, PSPPIRE_VAR_STORE_n_COLS);
+}
+
+
+static void
+var_delete_callback (GtkWidget *w, gint dict_idx, gint case_idx, gint val_cnt, gpointer data)
+{
+  PsppireSheetModel *model = PSPPIRE_SHEET_MODEL (data);
+
+  psppire_sheet_model_rows_deleted (model, dict_idx, 1);
+}
+
+
+
+static void
+var_insert_callback (GtkWidget *w, glong row, gpointer data)
+{
+  PsppireSheetModel *model = PSPPIRE_SHEET_MODEL (data);
+
+  psppire_sheet_model_rows_inserted (model, row, 1);
+}
+
+static void
+refresh (PsppireDict  *d, gpointer data)
+{
+  PsppireVarStore *vs = data;
+
+  psppire_sheet_model_range_changed (PSPPIRE_SHEET_MODEL (vs), -1, -1, -1, -1);
+}
 
 
-#define TRAILING_ROWS 40
+enum
+  {
+    PROP_0,
+    PSPPIRE_VAR_STORE_FORMAT_TYPE,
+    PSPPIRE_VAR_STORE_DICT
+  };
 
 static void         psppire_var_store_init            (PsppireVarStore      *var_store);
 static void         psppire_var_store_class_init      (PsppireVarStoreClass *class);
 
 static void         psppire_var_store_init            (PsppireVarStore      *var_store);
 static void         psppire_var_store_class_init      (PsppireVarStoreClass *class);
-static void         psppire_var_store_sheet_model_init (GSheetModelIface *iface);
+static void         psppire_var_store_sheet_model_init (PsppireSheetModelIface *iface);
 static void         psppire_var_store_finalize        (GObject           *object);
 static void         psppire_var_store_finalize        (GObject           *object);
+static void         psppire_var_store_dispose        (GObject           *object);
 
 
-static gchar *psppire_var_store_get_string (const GSheetModel *sheet_model, gint row, gint column);
 
 
-static gboolean  psppire_var_store_clear (GSheetModel *model,  gint row, gint col);
+static gchar *psppire_var_store_get_string (const PsppireSheetModel *sheet_model, glong row, glong column);
 
 
+static gboolean  psppire_var_store_clear (PsppireSheetModel *model,  glong row, glong col);
 
 
-static gboolean psppire_var_store_set_string (GSheetModel *model,
-                                         const gchar *text, gint row, gint column);
 
 
-static gint psppire_var_store_get_row_count (const GSheetModel * model);
+static gboolean psppire_var_store_set_string (PsppireSheetModel *model,
+                                         const gchar *text, glong row, glong column);
 
 
-static gchar *text_for_column (const struct variable *pv, gint c, GError **err);
+static glong psppire_var_store_get_row_count (const PsppireSheetModel * model);
+static glong psppire_var_store_get_column_count (const PsppireSheetModel * model);
 
 
+static gchar *text_for_column (PsppireVarStore *vs, const struct variable *pv,
+                              gint c, GError **err);
 
 
-static void psppire_var_store_sheet_row_init (GSheetRowIface *iface);
 
 
+static GObjectClass *parent_class = NULL;
 
 
+GType
+psppire_var_store_format_type_get_type (void)
+{
+  static GType etype = 0;
+  if (etype == 0)
+    {
+      static const GEnumValue values[] =
+       {
+         { PSPPIRE_VAR_STORE_INPUT_FORMATS,
+            "PSPPIRE_VAR_STORE_INPUT_FORMATS",
+            "input" },
+         { PSPPIRE_VAR_STORE_OUTPUT_FORMATS,
+            "PSPPIRE_VAR_STORE_OUTPUT_FORMATS",
+            "output" },
+         { 0, NULL, NULL }
+       };
+
+      etype = g_enum_register_static
+       (g_intern_static_string ("PsppireVarStoreFormatType"), values);
 
 
-static GObjectClass *parent_class = NULL;
+    }
+  return etype;
+}
 
 GType
 psppire_var_store_get_type (void)
 
 GType
 psppire_var_store_get_type (void)
@@ -97,55 +159,134 @@ psppire_var_store_get_type (void)
        NULL
       };
 
        NULL
       };
 
-      static const GInterfaceInfo sheet_row_info =
-      {
-       (GInterfaceInitFunc) psppire_var_store_sheet_row_init,
-       NULL,
-       NULL
-      };
-
       var_store_type = g_type_register_static (G_TYPE_OBJECT, "PsppireVarStore", &var_store_info, 0);
 
       g_type_add_interface_static (var_store_type,
       var_store_type = g_type_register_static (G_TYPE_OBJECT, "PsppireVarStore", &var_store_info, 0);
 
       g_type_add_interface_static (var_store_type,
-                                  G_TYPE_SHEET_MODEL,
+                                  PSPPIRE_TYPE_SHEET_MODEL,
                                   &sheet_model_info);
                                   &sheet_model_info);
+    }
 
 
-      g_type_add_interface_static (var_store_type,
-                                  G_TYPE_SHEET_ROW,
-                                  &sheet_row_info);
+  return var_store_type;
+}
 
 
+static void
+psppire_var_store_set_property (GObject      *object,
+                                guint         property_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  PsppireVarStore *self = (PsppireVarStore *) object;
+
+  switch (property_id)
+    {
+    case PSPPIRE_VAR_STORE_FORMAT_TYPE:
+      self->format_type = g_value_get_enum (value);
+      break;
+
+    case PSPPIRE_VAR_STORE_DICT:
+      if ( self->dictionary)
+       g_object_unref (self->dictionary);
+      self->dictionary = g_value_dup_object (value);
+      g_signal_connect (self->dictionary, "variable-changed", G_CALLBACK (var_change_callback),
+                       self);
 
 
+      g_signal_connect (self->dictionary, "variable-deleted", G_CALLBACK (var_delete_callback),
+                       self);
+
+      g_signal_connect (self->dictionary, "variable-inserted",
+                       G_CALLBACK (var_insert_callback), self);
+
+      g_signal_connect (self->dictionary, "backend-changed", G_CALLBACK (refresh),
+                       self);
+
+      /* The entire model has changed */
+      psppire_sheet_model_range_changed (PSPPIRE_SHEET_MODEL (self), -1, -1, -1, -1);
+
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+      break;
     }
     }
+}
 
 
-  return var_store_type;
+static void
+psppire_var_store_get_property (GObject      *object,
+                        guint         property_id,
+                        GValue       *value,
+                        GParamSpec   *pspec)
+{
+  PsppireVarStore *self = (PsppireVarStore *) object;
+
+  switch (property_id)
+    {
+    case PSPPIRE_VAR_STORE_FORMAT_TYPE:
+      g_value_set_enum (value, self->format_type);
+      break;
+
+    case PSPPIRE_VAR_STORE_DICT:
+      g_value_take_object (value, self->dictionary);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
 }
 
 }
 
+
 static void
 psppire_var_store_class_init (PsppireVarStoreClass *class)
 {
   GObjectClass *object_class;
 static void
 psppire_var_store_class_init (PsppireVarStoreClass *class)
 {
   GObjectClass *object_class;
+  GParamSpec *format_pspec;
+  GParamSpec *dict_pspec;
 
   parent_class = g_type_class_peek_parent (class);
   object_class = (GObjectClass*) class;
 
   object_class->finalize = psppire_var_store_finalize;
 
   parent_class = g_type_class_peek_parent (class);
   object_class = (GObjectClass*) class;
 
   object_class->finalize = psppire_var_store_finalize;
+  object_class->dispose = psppire_var_store_dispose;
+  object_class->set_property = psppire_var_store_set_property;
+  object_class->get_property = psppire_var_store_get_property;
+
+  format_pspec = g_param_spec_enum ("format-type",
+                             "Variable format type",
+                             ("Whether variables have input or output "
+                              "formats"),
+                             PSPPIRE_TYPE_VAR_STORE_FORMAT_TYPE,
+                             PSPPIRE_VAR_STORE_OUTPUT_FORMATS,
+                             G_PARAM_READWRITE);
+
+  g_object_class_install_property (object_class,
+                                   PSPPIRE_VAR_STORE_FORMAT_TYPE,
+                                   format_pspec);
+
+  dict_pspec = g_param_spec_object ("dictionary",
+                                   "Dictionary",
+                                   "The PsppireDict represented by this var store",
+                                   PSPPIRE_TYPE_DICT,
+                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+                                   
+  g_object_class_install_property (object_class,
+                                   PSPPIRE_VAR_STORE_DICT,
+                                   dict_pspec);
 }
 
 }
 
+#define DISABLED_COLOR "gray"
 
 static void
 psppire_var_store_init (PsppireVarStore *var_store)
 {
 
 static void
 psppire_var_store_init (PsppireVarStore *var_store)
 {
-  GdkColormap *colormap = gdk_colormap_get_system ();
-
-  g_assert (gdk_color_parse ("gray", &var_store->disabled));
+  if ( ! gdk_color_parse (DISABLED_COLOR, &var_store->disabled))
+       g_critical ("Could not parse color \"%s\"", DISABLED_COLOR);
 
 
-  gdk_colormap_alloc_color (colormap, &var_store->disabled, FALSE, TRUE);
-
-  var_store->dict = 0;
+  var_store->dictionary = NULL;
+  var_store->format_type = PSPPIRE_VAR_STORE_OUTPUT_FORMATS;
 }
 
 static gboolean
 }
 
 static gboolean
-psppire_var_store_item_editable (PsppireVarStore *var_store, gint row, gint column)
+psppire_var_store_item_editable (PsppireVarStore *var_store, glong row, glong column)
 {
   const struct fmt_spec *write_spec ;
 
 {
   const struct fmt_spec *write_spec ;
 
@@ -154,10 +295,10 @@ psppire_var_store_item_editable (PsppireVarStore *var_store, gint row, gint colu
   if ( !pv )
     return TRUE;
 
   if ( !pv )
     return TRUE;
 
-  if ( VAR_STRING == var_get_type (pv) && column == COL_DECIMALS )
+  if ( var_is_alpha (pv) && column == PSPPIRE_VAR_STORE_COL_DECIMALS )
     return FALSE;
 
     return FALSE;
 
-  write_spec =var_get_write_format (pv);
+  write_spec = var_get_print_format (pv);
 
   switch ( write_spec->type )
     {
 
   switch ( write_spec->type )
     {
@@ -174,7 +315,7 @@ psppire_var_store_item_editable (PsppireVarStore *var_store, gint row, gint colu
     case FMT_DTIME:
     case FMT_WKDAY:
     case FMT_MONTH:
     case FMT_DTIME:
     case FMT_WKDAY:
     case FMT_MONTH:
-      if ( column == COL_DECIMALS || column == COL_WIDTH)
+      if ( column == PSPPIRE_VAR_STORE_COL_DECIMALS || column == PSPPIRE_VAR_STORE_COL_WIDTH)
        return FALSE;
       break;
     default:
        return FALSE;
       break;
     default:
@@ -186,21 +327,21 @@ psppire_var_store_item_editable (PsppireVarStore *var_store, gint row, gint colu
 
 
 struct variable *
 
 
 struct variable *
-psppire_var_store_get_var (PsppireVarStore *store, gint row)
+psppire_var_store_get_var (PsppireVarStore *store, glong row)
 {
 {
-  return psppire_dict_get_variable (store->dict, row);
+  return psppire_dict_get_variable (store->dictionary, row);
 }
 
 static gboolean
 }
 
 static gboolean
-psppire_var_store_is_editable (const GSheetModel *model, gint row, gint column)
+psppire_var_store_is_editable (const PsppireSheetModel *model, glong row, glong column)
 {
   PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
   return psppire_var_store_item_editable (store, row, column);
 }
 
 
 {
   PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
   return psppire_var_store_item_editable (store, row, column);
 }
 
 
-static const GdkColor *
-psppire_var_store_get_foreground (const GSheetModel *model, gint row, gint column)
+static GdkColor *
+psppire_var_store_get_foreground (const PsppireSheetModel *model, glong row, glong column)
 {
   PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
 
 {
   PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
 
@@ -211,34 +352,31 @@ psppire_var_store_get_foreground (const GSheetModel *model, gint row, gint colum
 }
 
 
 }
 
 
-const PangoFontDescription *
-psppire_var_store_get_font_desc (const GSheetModel *model,
-                             gint row, gint column)
-{
-  PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
-
-  return store->font_desc;
-}
-
-
+static gchar *get_column_title (const PsppireSheetModel *model, gint col);
+static gchar *get_row_title (const PsppireSheetModel *model, gint row);
+static gboolean get_row_sensitivity (const PsppireSheetModel *model, gint row);
 
 static void
 
 static void
-psppire_var_store_sheet_model_init (GSheetModelIface *iface)
+psppire_var_store_sheet_model_init (PsppireSheetModelIface *iface)
 {
   iface->get_row_count = psppire_var_store_get_row_count;
 {
   iface->get_row_count = psppire_var_store_get_row_count;
+  iface->get_column_count = psppire_var_store_get_column_count;
   iface->free_strings = TRUE;
   iface->get_string = psppire_var_store_get_string;
   iface->set_string = psppire_var_store_set_string;
   iface->clear_datum = psppire_var_store_clear;
   iface->is_editable = psppire_var_store_is_editable;
   iface->free_strings = TRUE;
   iface->get_string = psppire_var_store_get_string;
   iface->set_string = psppire_var_store_set_string;
   iface->clear_datum = psppire_var_store_clear;
   iface->is_editable = psppire_var_store_is_editable;
-  iface->is_visible = NULL;
   iface->get_foreground = psppire_var_store_get_foreground;
   iface->get_background = NULL;
   iface->get_foreground = psppire_var_store_get_foreground;
   iface->get_background = NULL;
-  iface->get_font_desc = psppire_var_store_get_font_desc;
-  iface->get_cell_border = NULL;
-}
+  iface->get_justification = NULL;
+
+  iface->get_column_title = get_column_title;
 
 
+  iface->get_row_title = get_row_title;
+  iface->get_row_sensitivity = get_row_sensitivity;
 
 
+  iface->get_row_overstrike = NULL;
+}
 
 /**
  * psppire_var_store_new:
 
 /**
  * psppire_var_store_new:
@@ -252,43 +390,14 @@ psppire_var_store_new (PsppireDict *dict)
 {
   PsppireVarStore *retval;
 
 {
   PsppireVarStore *retval;
 
-  retval = g_object_new (GTK_TYPE_VAR_STORE, NULL);
+  retval = g_object_new (GTK_TYPE_VAR_STORE, "dictionary", dict, NULL);
 
 
-  psppire_var_store_set_dictionary (retval, dict);
+  //  psppire_var_store_set_dictionary (retval, dict);
 
   return retval;
 }
 
 
   return retval;
 }
 
-static void
-var_change_callback (GtkWidget *w, gint n, gpointer data)
-{
-  GSheetModel *model = G_SHEET_MODEL (data);
-
-  g_sheet_model_range_changed (model,
-                                n, 0, n, n_COLS);
-}
-
-
-static void
-var_delete_callback (GtkWidget *w, gint first, gint n, gpointer data)
-{
-  GSheetModel *model = G_SHEET_MODEL (data);
-
-  g_sheet_model_rows_deleted (model, first, n);
-}
-
-
-
-static void
-var_insert_callback (GtkWidget *w, gint row, gpointer data)
-{
-  GSheetModel *model = G_SHEET_MODEL (data);
-
-  g_sheet_model_rows_inserted (model, row, 1);
-}
-
-
-
+#if 0
 /**
  * psppire_var_store_replace_set_dictionary:
  * @var_store: The variable store
 /**
  * psppire_var_store_replace_set_dictionary:
  * @var_store: The variable store
@@ -307,16 +416,19 @@ psppire_var_store_set_dictionary (PsppireVarStore *var_store, PsppireDict *dict)
   g_signal_connect (dict, "variable-changed", G_CALLBACK (var_change_callback),
                   var_store);
 
   g_signal_connect (dict, "variable-changed", G_CALLBACK (var_change_callback),
                   var_store);
 
-  g_signal_connect (dict, "variables-deleted", G_CALLBACK (var_delete_callback),
+  g_signal_connect (dict, "variable-deleted", G_CALLBACK (var_delete_callback),
                   var_store);
 
                   var_store);
 
-  g_signal_connect (dict, "variable-inserted", G_CALLBACK (var_insert_callback),
-                  var_store);
+  g_signal_connect (dict, "variable-inserted",
+                   G_CALLBACK (var_insert_callback), var_store);
 
 
+  g_signal_connect (dict, "backend-changed", G_CALLBACK (refresh),
+                   var_store);
 
   /* The entire model has changed */
 
   /* The entire model has changed */
-  g_sheet_model_range_changed (G_SHEET_MODEL (var_store), -1, -1, -1, -1);
+  psppire_sheet_model_range_changed (PSPPIRE_SHEET_MODEL (var_store), -1, -1, -1, -1);
 }
 }
+#endif
 
 static void
 psppire_var_store_finalize (GObject *object)
 
 static void
 psppire_var_store_finalize (GObject *object)
@@ -325,19 +437,33 @@ psppire_var_store_finalize (GObject *object)
   (* parent_class->finalize) (object);
 }
 
   (* parent_class->finalize) (object);
 }
 
+static void
+psppire_var_store_dispose (GObject *object)
+{
+  PsppireVarStore *self = PSPPIRE_VAR_STORE (object);
+
+  if (self->dictionary)
+    g_object_unref (self->dictionary);
+
+  /* must chain up */
+  (* parent_class->finalize) (object);
+}
+
+
 static gchar *
 static gchar *
-psppire_var_store_get_string (const GSheetModel *model, gint row, gint column)
+psppire_var_store_get_string (const PsppireSheetModel *model,
+                             glong row, glong column)
 {
   PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
 
   struct variable *pv;
 
 {
   PsppireVarStore *store = PSPPIRE_VAR_STORE (model);
 
   struct variable *pv;
 
-  if ( row >= psppire_dict_get_var_cnt (store->dict))
+  if ( row >= psppire_dict_get_var_cnt (store->dictionary))
     return 0;
 
     return 0;
 
-  pv = psppire_dict_get_variable (store->dict, row);
+  pv = psppire_dict_get_variable (store->dictionary, row);
 
 
-  return text_for_column (pv, column, 0);
+  return text_for_column (store, pv, column, 0);
 }
 
 
 }
 
 
@@ -346,13 +472,13 @@ psppire_var_store_get_string (const GSheetModel *model, gint row, gint column)
    Returns true if anything was updated, false otherwise.
 */
 static gboolean
    Returns true if anything was updated, false otherwise.
 */
 static gboolean
-psppire_var_store_clear (GSheetModel *model,  gint row, gint col)
+psppire_var_store_clear (PsppireSheetModel *model,  glong row, glong col)
 {
   struct variable *pv ;
 
   PsppireVarStore *var_store = PSPPIRE_VAR_STORE (model);
 
 {
   struct variable *pv ;
 
   PsppireVarStore *var_store = PSPPIRE_VAR_STORE (model);
 
-  if ( row >= psppire_dict_get_var_cnt (var_store->dict))
+  if ( row >= psppire_dict_get_var_cnt (var_store->dictionary))
       return FALSE;
 
   pv = psppire_var_store_get_var (var_store, row);
       return FALSE;
 
   pv = psppire_var_store_get_var (var_store, row);
@@ -362,8 +488,8 @@ psppire_var_store_clear (GSheetModel *model,  gint row, gint col)
 
   switch (col)
     {
 
   switch (col)
     {
-    case COL_LABEL:
-      var_set_label (pv, 0);
+    case PSPPIRE_VAR_STORE_COL_LABEL:
+      var_set_label (pv, NULL);
       return TRUE;
       break;
     }
       return TRUE;
       break;
     }
@@ -376,14 +502,14 @@ psppire_var_store_clear (GSheetModel *model,  gint row, gint col)
    Returns true if anything was updated, false otherwise.
 */
 static gboolean
    Returns true if anything was updated, false otherwise.
 */
 static gboolean
-psppire_var_store_set_string (GSheetModel *model,
-                         const gchar *text, gint row, gint col)
+psppire_var_store_set_string (PsppireSheetModel *model,
+                         const gchar *text, glong row, glong col)
 {
   struct variable *pv ;
 
   PsppireVarStore *var_store = PSPPIRE_VAR_STORE (model);
 
 {
   struct variable *pv ;
 
   PsppireVarStore *var_store = PSPPIRE_VAR_STORE (model);
 
-  if ( row >= psppire_dict_get_var_cnt (var_store->dict))
+  if ( row >= psppire_dict_get_var_cnt (var_store->dictionary))
       return FALSE;
 
   pv = psppire_var_store_get_var (var_store, row);
       return FALSE;
 
   pv = psppire_var_store_get_var (var_store, row);
@@ -393,31 +519,45 @@ psppire_var_store_set_string (GSheetModel *model,
 
   switch (col)
     {
 
   switch (col)
     {
-    case COL_NAME:
-      return psppire_dict_rename_var (var_store->dict, pv, text);
-      break;
-    case COL_COLUMNS:
+    case PSPPIRE_VAR_STORE_COL_NAME:
+      {
+       gboolean ok;
+       ok =  psppire_dict_rename_var (var_store->dictionary, pv, text);
+       return ok;
+      }
+    case PSPPIRE_VAR_STORE_COL_COLUMNS:
       if ( ! text) return FALSE;
       var_set_display_width (pv, atoi (text));
       return TRUE;
       break;
       if ( ! text) return FALSE;
       var_set_display_width (pv, atoi (text));
       return TRUE;
       break;
-    case COL_WIDTH:
+    case PSPPIRE_VAR_STORE_COL_WIDTH:
       {
       {
-       int width = atoi (text);
-       if ( ! text) return FALSE;
+       const int width = atoi (text);
+       if ( ! text)
+         return FALSE;
+
+       if (width < 0)
+         return FALSE;
+
        if ( var_is_alpha (pv))
        if ( var_is_alpha (pv))
+         {
+           if ( width > MAX_STRING )
+             return FALSE;
            var_set_width (pv, width);
            var_set_width (pv, width);
+         }
        else
          {
        else
          {
+            bool for_input
+              = var_store->format_type == PSPPIRE_VAR_STORE_INPUT_FORMATS;
            struct fmt_spec fmt ;
            fmt = *var_get_write_format (pv);
            struct fmt_spec fmt ;
            fmt = *var_get_write_format (pv);
-           if ( width < fmt_min_output_width (fmt.type)
+           if ( width < fmt_min_width (fmt.type, for_input)
                 ||
                 ||
-                width > fmt_max_output_width (fmt.type))
+                width > fmt_max_width (fmt.type, for_input))
              return FALSE;
 
            fmt.w = width;
              return FALSE;
 
            fmt.w = width;
-           fmt.d = MIN (fmt_max_output_decimals (fmt.type, width), fmt.d);
+           fmt.d = MIN (fmt_max_decimals (fmt.type, width, for_input), fmt.d);
 
            var_set_both_formats (pv, &fmt);
          }
 
            var_set_both_formats (pv, &fmt);
          }
@@ -425,17 +565,20 @@ psppire_var_store_set_string (GSheetModel *model,
        return TRUE;
       }
       break;
        return TRUE;
       }
       break;
-    case COL_DECIMALS:
+    case PSPPIRE_VAR_STORE_COL_DECIMALS:
       {
       {
+        bool for_input
+          = var_store->format_type == PSPPIRE_VAR_STORE_INPUT_FORMATS;
        int decimals;
        struct fmt_spec fmt;
        if ( ! text) return FALSE;
        decimals = atoi (text);
        fmt = *var_get_write_format (pv);
        if ( decimals >
        int decimals;
        struct fmt_spec fmt;
        if ( ! text) return FALSE;
        decimals = atoi (text);
        fmt = *var_get_write_format (pv);
        if ( decimals >
-            fmt_max_output_decimals (fmt.type,
-                                     fmt.w
-                                     ))
+            fmt_max_decimals (fmt.type,
+                               fmt.w,
+                               for_input
+                               ))
          return FALSE;
 
        fmt.d = decimals;
          return FALSE;
 
        fmt.d = decimals;
@@ -443,15 +586,17 @@ psppire_var_store_set_string (GSheetModel *model,
        return TRUE;
       }
       break;
        return TRUE;
       }
       break;
-    case COL_LABEL:
-      var_set_label (pv, text);
-      return TRUE;
+    case PSPPIRE_VAR_STORE_COL_LABEL:
+      {
+       var_set_label (pv, text);
+       return TRUE;
+      }
       break;
       break;
-    case COL_TYPE:
-    case COL_VALUES:
-    case COL_MISSING:
-    case COL_ALIGN:
-    case COL_MEASURE:
+    case PSPPIRE_VAR_STORE_COL_TYPE:
+    case PSPPIRE_VAR_STORE_COL_VALUES:
+    case PSPPIRE_VAR_STORE_COL_MISSING:
+    case PSPPIRE_VAR_STORE_COL_ALIGN:
+    case PSPPIRE_VAR_STORE_COL_MEASURE:
       /* These can be modified only by their respective dialog boxes */
       return FALSE;
       break;
       /* These can be modified only by their respective dialog boxes */
       return FALSE;
       break;
@@ -464,11 +609,13 @@ psppire_var_store_set_string (GSheetModel *model,
 }
 
 
 }
 
 
+static const gchar none[] = N_("None");
+
 static  gchar *
 static  gchar *
-text_for_column (const struct variable *pv, gint c, GError **err)
+text_for_column (PsppireVarStore *vs,
+                const struct variable *pv, gint c, GError **err)
 {
 {
-  static gchar none[] = N_("None");
-
+  PsppireDict *dict = vs->dictionary;
   static const gchar *const type_label[] =
     {
       N_("Numeric"),
   static const gchar *const type_label[] =
     {
       N_("Numeric"),
@@ -480,6 +627,7 @@ text_for_column (const struct variable *pv, gint c, GError **err)
       N_("Custom"),
       N_("String")
     };
       N_("Custom"),
       N_("String")
     };
+
   enum {VT_NUMERIC, VT_COMMA, VT_DOT, VT_SCIENTIFIC, VT_DATE, VT_DOLLAR,
        VT_CUSTOM, VT_STRING};
 
   enum {VT_NUMERIC, VT_COMMA, VT_DOT, VT_SCIENTIFIC, VT_DATE, VT_DOLLAR,
        VT_CUSTOM, VT_STRING};
 
@@ -487,10 +635,10 @@ text_for_column (const struct variable *pv, gint c, GError **err)
 
   switch (c)
     {
 
   switch (c)
     {
-    case COL_NAME:
-      return pspp_locale_to_utf8 ( var_get_name (pv), -1, err);
+    case PSPPIRE_VAR_STORE_COL_NAME:
+      return xstrdup (var_get_name (pv));
       break;
       break;
-    case COL_TYPE:
+    case PSPPIRE_VAR_STORE_COL_TYPE:
       {
        switch ( write_spec->type )
          {
       {
        switch ( write_spec->type )
          {
@@ -544,7 +692,7 @@ text_for_column (const struct variable *pv, gint c, GError **err)
          }
       }
       break;
          }
       }
       break;
-    case COL_WIDTH:
+    case PSPPIRE_VAR_STORE_COL_WIDTH:
       {
        gchar *s;
        GString *gstr = g_string_sized_new (10);
       {
        gchar *s;
        GString *gstr = g_string_sized_new (10);
@@ -554,7 +702,7 @@ text_for_column (const struct variable *pv, gint c, GError **err)
        return s;
       }
       break;
        return s;
       }
       break;
-    case COL_DECIMALS:
+    case PSPPIRE_VAR_STORE_COL_DECIMALS:
       {
        gchar *s;
        GString *gstr = g_string_sized_new (10);
       {
        gchar *s;
        GString *gstr = g_string_sized_new (10);
@@ -564,7 +712,7 @@ text_for_column (const struct variable *pv, gint c, GError **err)
        return s;
       }
       break;
        return s;
       }
       break;
-    case COL_COLUMNS:
+    case PSPPIRE_VAR_STORE_COL_COLUMNS:
       {
        gchar *s;
        GString *gstr = g_string_sized_new (10);
       {
        gchar *s;
        GString *gstr = g_string_sized_new (10);
@@ -574,101 +722,42 @@ text_for_column (const struct variable *pv, gint c, GError **err)
        return s;
       }
       break;
        return s;
       }
       break;
-    case COL_LABEL:
-      return pspp_locale_to_utf8 (var_get_label (pv), -1, err);
+    case PSPPIRE_VAR_STORE_COL_LABEL:
+      {
+       const char *label = var_get_label (pv);
+       if (label)
+         return xstrdup (label);
+       return NULL;
+      }
       break;
 
       break;
 
-    case COL_MISSING:
+    case PSPPIRE_VAR_STORE_COL_MISSING:
       {
       {
-       gchar *s;
-       const struct missing_values *miss = var_get_missing_values (pv);
-       if ( mv_is_empty (miss))
-         return g_locale_to_utf8 (gettext (none), -1, 0, 0, err);
-       else
-         {
-           if ( ! mv_has_range (miss))
-             {
-               GString *gstr = g_string_sized_new (10);
-               const int n = mv_n_values (miss);
-               gchar *mv[4] = {0,0,0,0};
-               gint i;
-               for (i = 0 ; i < n; ++i )
-                 {
-                   union value v;
-                   mv_peek_value (miss, &v, i);
-                   mv[i] = value_to_text (v, *write_spec);
-                   if ( i > 0 )
-                     g_string_append (gstr, ", ");
-                   g_string_append (gstr, mv[i]);
-                   g_free (mv[i]);
-                 }
-               s = pspp_locale_to_utf8 (gstr->str, gstr->len, err);
-               g_string_free (gstr, TRUE);
-             }
-           else
-             {
-               GString *gstr = g_string_sized_new (10);
-               gchar *l, *h;
-               union value low, high;
-               mv_peek_range (miss, &low.f, &high.f);
-
-               l = value_to_text (low, *write_spec);
-               h = value_to_text (high, *write_spec);
-
-               g_string_printf (gstr, "%s - %s", l, h);
-               g_free (l);
-               g_free (h);
-
-               if ( mv_has_value (miss))
-                 {
-                   gchar *ss = 0;
-                   union value v;
-                   mv_peek_value (miss, &v, 0);
-
-                   ss = value_to_text (v, *write_spec);
-
-                   g_string_append (gstr, ", ");
-                   g_string_append (gstr, ss);
-                   free (ss);
-                 }
-               s = pspp_locale_to_utf8 (gstr->str, gstr->len, err);
-               g_string_free (gstr, TRUE);
-             }
-
-           return s;
-         }
+       return missing_values_to_string (dict, pv, err);
       }
       break;
       }
       break;
-    case COL_VALUES:
+    case PSPPIRE_VAR_STORE_COL_VALUES:
       {
        if ( ! var_has_value_labels (pv))
          return g_locale_to_utf8 (gettext (none), -1, 0, 0, err);
        else
          {
       {
        if ( ! var_has_value_labels (pv))
          return g_locale_to_utf8 (gettext (none), -1, 0, 0, err);
        else
          {
-           gchar *ss;
-           GString *gstr = g_string_sized_new (10);
            const struct val_labs *vls = var_get_value_labels (pv);
            const struct val_labs *vls = var_get_value_labels (pv);
-           struct val_labs_iterator *ip = 0;
-           struct val_lab *vl = val_labs_first_sorted (vls, &ip);
+            const struct val_lab **labels = val_labs_sorted (vls);
+           const struct val_lab *vl = labels[0];
+            free (labels);
 
            g_assert (vl);
 
            {
 
            g_assert (vl);
 
            {
-             gchar *const vstr = value_to_text (vl->value, *write_spec);
+             gchar *const vstr = value_to_text (vl->value, dict, *write_spec);
 
 
-             g_string_printf (gstr, "{%s,\"%s\"}_", vstr, vl->label);
-             g_free (vstr);
+             return g_strdup_printf ( "{%s,\"%s\"}_", vstr, val_lab_get_label (vl));
            }
            }
-
-           val_labs_done (&ip);
-
-           ss = pspp_locale_to_utf8 (gstr->str, gstr->len, err);
-           g_string_free (gstr, TRUE);
-           return ss;
          }
       }
       break;
          }
       }
       break;
-    case COL_ALIGN:
+    case PSPPIRE_VAR_STORE_COL_ALIGN:
       {
        const gint align = var_get_alignment (pv);
 
       {
        const gint align = var_get_alignment (pv);
 
@@ -676,13 +765,9 @@ text_for_column (const struct variable *pv, gint c, GError **err)
        return g_locale_to_utf8 (gettext (alignments[align]), -1, 0, 0, err);
       }
       break;
        return g_locale_to_utf8 (gettext (alignments[align]), -1, 0, 0, err);
       }
       break;
-    case COL_MEASURE:
+    case PSPPIRE_VAR_STORE_COL_MEASURE:
       {
       {
-       const gint measure = var_get_measure (pv);
-
-       g_assert (measure < n_MEASURES);
-       return g_locale_to_utf8 (gettext (measures[measure]),
-                                -1, 0, 0, err);
+       return measure_to_string (pv, err);
       }
       break;
     }
       }
       break;
     }
@@ -695,91 +780,72 @@ text_for_column (const struct variable *pv, gint c, GError **err)
 gint
 psppire_var_store_get_var_cnt (PsppireVarStore  *store)
 {
 gint
 psppire_var_store_get_var_cnt (PsppireVarStore  *store)
 {
-  return psppire_dict_get_var_cnt (store->dict);
+  return psppire_dict_get_var_cnt (store->dictionary);
 }
 
 
 }
 
 
-void
-psppire_var_store_set_font (PsppireVarStore *store, const PangoFontDescription *fd)
-{
-  g_return_if_fail (store);
-  g_return_if_fail (PSPPIRE_IS_VAR_STORE (store));
-
-  store->font_desc = fd;
-
-  g_sheet_model_range_changed (G_SHEET_MODEL (store), -1, -1, -1, -1);
-}
-
-
-static gint
-psppire_var_store_get_row_count (const GSheetModel * model)
+static glong
+psppire_var_store_get_row_count (const PsppireSheetModel * model)
 {
   gint rows = 0;
   PsppireVarStore *vs = PSPPIRE_VAR_STORE (model);
 
 {
   gint rows = 0;
   PsppireVarStore *vs = PSPPIRE_VAR_STORE (model);
 
-  if (vs->dict)
-    rows =  psppire_dict_get_var_cnt (vs->dict);
+  if (vs->dictionary)
+    rows =  psppire_dict_get_var_cnt (vs->dictionary);
 
   return rows ;
 }
 
 
   return rows ;
 }
 
-/* Row related funcs */
-
-static gint
-geometry_get_row_count (const GSheetRow *geom, gpointer data)
+static glong
+psppire_var_store_get_column_count (const PsppireSheetModel * model)
 {
 {
-  gint rows = 0;
-  PsppireVarStore *vs = PSPPIRE_VAR_STORE (geom);
-
-  if (vs->dict)
-    rows =  psppire_dict_get_var_cnt (vs->dict);
-
-  return rows + TRAILING_ROWS;
+  return PSPPIRE_VAR_STORE_n_COLS ;
 }
 
 }
 
+\f
 
 
-static gint
-geometry_get_height (const GSheetRow *geom, gint row, gpointer data)
-{
-  return 25;
-}
+/* Row related funcs */
 
 
 static gboolean
 
 
 static gboolean
-geometry_is_sensitive (const GSheetRow *geom, gint row, gpointer data)
+get_row_sensitivity (const PsppireSheetModel *model, gint row)
 {
 {
-  PsppireVarStore *vs = PSPPIRE_VAR_STORE (geom);
+  PsppireVarStore *vs = PSPPIRE_VAR_STORE (model);
 
 
-  if ( ! vs->dict)
+  if ( ! vs->dictionary)
     return FALSE;
 
     return FALSE;
 
-  return  row < psppire_dict_get_var_cnt (vs->dict);
+  return  row < psppire_dict_get_var_cnt (vs->dictionary);
 }
 
 }
 
-static
-gboolean always_true ()
+
+static gchar *
+get_row_title (const PsppireSheetModel *model, gint unit)
 {
 {
-  return TRUE;
+  return g_strdup_printf (_("%d"), unit + 1);
 }
 
 
 }
 
 
-static gchar *
-geometry_get_button_label (const GSheetRow *geom, gint unit, gpointer data)
-{
-  gchar *label = g_strdup_printf (_("%d"), unit);
+\f
 
 
-  return label;
-}
+static const gchar *column_titles[] = {
+  N_("Name"),
+  N_("Type"),
+  N_("Width"),
+  N_("Decimals"),
+  N_("Label"),
+  N_("Values"),
+  N_("Missing"),
+  N_("Columns"),
+  N_("Align"),
+  N_("Measure"),
+};
 
 
 
 
-static void
-psppire_var_store_sheet_row_init (GSheetRowIface *iface)
+static gchar *
+get_column_title (const PsppireSheetModel *model, gint col)
 {
 {
-  iface->get_row_count =     geometry_get_row_count;
-  iface->get_height =        geometry_get_height;
-  iface->set_height =        0;
-  iface->get_visibility =    always_true;
-  iface->get_sensitivity =   geometry_is_sensitive;
-
-  iface->get_button_label = geometry_get_button_label;
+  if ( col >= 10)
+    return NULL;
+  return g_strdup (gettext (column_titles[col]));
 }
 }