Merge branch 'rewrite-sheet' of ssh://jmd@git.sv.gnu.org/srv/git/pspp into rewrite...
authorJohn Darrington <john@darrington.wattle.id.au>
Mon, 24 Nov 2008 13:16:02 +0000 (22:16 +0900)
committerJohn Darrington <john@darrington.wattle.id.au>
Mon, 24 Nov 2008 13:16:02 +0000 (22:16 +0900)
Conflicts:

lib/gtksheet/gtksheet.c

1  2 
lib/gtksheet/gtksheet.c
lib/gtksheet/psppire-axis.c
lib/gtksheet/psppire-axis.h
src/data/dictionary.c
src/data/dictionary.h
src/data/vardict.h
src/data/variable.c
src/ui/gui/psppire-data-editor.c
src/ui/gui/psppire-dict.c
src/ui/gui/psppire-dict.h
src/ui/gui/psppire-var-sheet.c

diff --combined lib/gtksheet/gtksheet.c
index 31f242d28f1283648c517f7d122a2a1bd53a3751,e38b389553d33d694189cb7cd4af56d7dd44157e..8b25902c3b1cc2421c2e5e101b9dbeb77bc7aff8
@@@ -87,9 -87,9 +87,9 @@@ enu
  #define DEFAULT_ROW_HEIGHT 25
  
  static void gtk_sheet_update_primary_selection (GtkSheet *sheet);
- static void gtk_sheet_column_title_button_draw (GtkSheet *sheet, gint column);
+ static void draw_column_title_buttons_range (GtkSheet *sheet, gint first, gint n);
+ static void draw_row_title_buttons_range (GtkSheet *sheet, gint first, gint n);
  
- static void gtk_sheet_row_title_button_draw (GtkSheet *sheet, gint row);
  
  static void gtk_sheet_set_row_height (GtkSheet *sheet,
                                      gint row,
@@@ -113,22 -113,6 +113,6 @@@ dispose_string (const GtkSheet *sheet, 
      g_free (text);
  }
  
- static
- guint STRING_WIDTH (GtkWidget *widget,
-                   const PangoFontDescription *font, const gchar *text)
- {
-   PangoRectangle rect;
-   PangoLayout *layout;
-   layout = gtk_widget_create_pango_layout (widget, text);
-   pango_layout_set_font_description (layout, font);
-   pango_layout_get_extents (layout, NULL, &rect);
-   g_object_unref (layout);
-   return PANGO_PIXELS (rect.width);
- }
  /* Return the row containing pixel Y */
  static gint
  yyy_row_ypixel_to_row (const GtkSheet *sheet, gint y)
@@@ -176,7 -160,7 +160,7 @@@ max_fully_visible_row (const GtkSheet *
    glong row = max_visible_row (sheet);
  
    if ( g_sheet_row_start_pixel (sheet->row_geometry, row)
 -       + 
 +       +
         g_sheet_row_get_height (sheet->row_geometry, row)
         > sheet->vadjustment->value)
      row--;
  }
  
  
 -/* returns the column index from a pixel location */
 +/* returns the column index from a pixel location */
  static inline gint
 -column_from_xpixel (const GtkSheet *sheet, gint x)
 +column_from_xpixel (const GtkSheet *sheet, gint pixel)
  {
 -  gint i;
 -  gint cx = 0;
 -
 -  if (x < 0) return -1;
 -  for (i = 0;
 -       i < g_sheet_column_get_column_count (sheet->column_geometry); i++)
 -    {
 -      if (x >= cx &&
 -        x <= (cx + g_sheet_column_get_width (sheet->column_geometry, i)))
 -      return i;
 -
 -      cx += g_sheet_column_get_width (sheet->column_geometry, i);
 -    }
 -
 -  /* no match */
 -  return g_sheet_column_get_column_count (sheet->column_geometry) - 1;
 +  return psppire_axis_get_unit_at_pixel (sheet->haxis, pixel);
  }
  
  
@@@ -206,7 -205,7 +190,7 @@@ min_fully_visible_column (const GtkShee
  {
    glong col = min_visible_column (sheet);
  
 -  if ( g_sheet_column_start_pixel (sheet->column_geometry, col) < sheet->hadjustment->value)
 +  if ( psppire_axis_pixel_start (sheet->haxis, col) < sheet->hadjustment->value)
      col++;
  
    return col;
@@@ -228,9 -227,9 +212,9 @@@ max_fully_visible_column (const GtkShee
  {
    glong col = max_visible_column (sheet);
  
 -  if ( g_sheet_column_start_pixel (sheet->column_geometry, col)
 +  if ( psppire_axis_pixel_start (sheet->haxis, col)
         + 
 -       g_sheet_column_get_width (sheet->column_geometry, col)
 +       psppire_axis_unit_size (sheet->haxis, col)
         > sheet->hadjustment->value)
      col--;
  
@@@ -305,9 -304,9 +289,9 @@@ POSSIBLE_DRAG (const GtkSheet *sheet, g
    *drag_column = column_from_xpixel (sheet, x);
    *drag_row = yyy_row_ypixel_to_row (sheet, y);
  
 -  if (x >= g_sheet_column_start_pixel (sheet->column_geometry, sheet->range.col0) - DRAG_WIDTH / 2 &&
 -      x <= g_sheet_column_start_pixel (sheet->column_geometry, sheet->range.coli) +
 -      g_sheet_column_get_width (sheet->column_geometry, sheet->range.coli) + DRAG_WIDTH / 2)
 +  if (x >= psppire_axis_pixel_start (sheet->haxis, sheet->range.col0) - DRAG_WIDTH / 2 &&
 +      x <= psppire_axis_pixel_start (sheet->haxis, sheet->range.coli) +
 +      psppire_axis_unit_size (sheet->haxis, sheet->range.coli) + DRAG_WIDTH / 2)
      {
        ydrag = g_sheet_row_start_pixel (sheet->row_geometry, sheet->range.row0);
        if (y >= ydrag - DRAG_WIDTH / 2 && y <= ydrag + DRAG_WIDTH / 2)
        y <= g_sheet_row_start_pixel (sheet->row_geometry, sheet->range.rowi) +
        g_sheet_row_get_height (sheet->row_geometry, sheet->range.rowi) + DRAG_WIDTH / 2)
      {
 -      xdrag = g_sheet_column_start_pixel (sheet->column_geometry, sheet->range.col0);
 +      xdrag = psppire_axis_pixel_start (sheet->haxis, sheet->range.col0);
        if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2)
        {
          *drag_column = sheet->range.col0;
          return TRUE;
        }
 -      xdrag = g_sheet_column_start_pixel (sheet->column_geometry, sheet->range.coli) +
 -      g_sheet_column_get_width (sheet->column_geometry, sheet->range.coli);
 +      xdrag = psppire_axis_pixel_start (sheet->haxis, sheet->range.coli) +
 +      psppire_axis_unit_size (sheet->haxis, sheet->range.coli);
        if (x >= xdrag - DRAG_WIDTH / 2 && x <= xdrag + DRAG_WIDTH / 2)
        {
          *drag_column = sheet->range.coli;
@@@ -357,8 -356,8 +341,8 @@@ POSSIBLE_RESIZE (const GtkSheet *sheet
         sheet->range.col0 < 0 || sheet->range.coli < 0 )
      return FALSE;
  
 -  xdrag = g_sheet_column_start_pixel (sheet->column_geometry, sheet->range.coli)+
 -    g_sheet_column_get_width (sheet->column_geometry, sheet->range.coli);
 +  xdrag = psppire_axis_pixel_start (sheet->haxis, sheet->range.coli)+
 +    psppire_axis_unit_size (sheet->haxis, sheet->range.coli);
  
    ydrag = g_sheet_row_start_pixel (sheet->row_geometry, sheet->range.rowi) +
      g_sheet_row_get_height (sheet->row_geometry, sheet->range.rowi);
      ydrag = g_sheet_row_start_pixel (sheet->row_geometry, min_visible_row (sheet));
  
    if (sheet->state == GTK_SHEET_ROW_SELECTED)
 -    xdrag = g_sheet_column_start_pixel (sheet->column_geometry, min_visible_column (sheet));
 +    xdrag = psppire_axis_pixel_start (sheet->haxis, min_visible_column (sheet));
  
    *drag_column = column_from_xpixel (sheet, x);
    *drag_row = yyy_row_ypixel_to_row (sheet, y);
@@@ -385,7 -384,7 +369,7 @@@ rectangle_from_range (GtkSheet *sheet, 
  {
    g_return_val_if_fail (range, FALSE);
  
 -  r->x = g_sheet_column_start_pixel (sheet->column_geometry, range->col0);
 +  r->x = psppire_axis_pixel_start (sheet->haxis, range->col0);
    r->x -= round (sheet->hadjustment->value);
  
    if ( sheet->row_titles_visible)
    if ( sheet->column_titles_visible)
      r->y += sheet->column_title_area.height;
  
 -  r->width = g_sheet_column_start_pixel (sheet->column_geometry, range->coli) -
 -    g_sheet_column_start_pixel (sheet->column_geometry, range->col0) +
 -    g_sheet_column_get_width (sheet->column_geometry, range->coli);
 +  r->width = psppire_axis_pixel_start (sheet->haxis, range->coli) -
 +    psppire_axis_pixel_start (sheet->haxis, range->col0) +
 +    psppire_axis_unit_size (sheet->haxis, range->coli);
  
    r->height = g_sheet_row_start_pixel (sheet->row_geometry, range->rowi) -
      g_sheet_row_start_pixel (sheet->row_geometry, range->row0) +
@@@ -691,15 -690,12 +675,12 @@@ gtk_sheet_cell_get_type (void
  }
  \f
  
- static void column_titles_changed (GtkWidget *w, gint first, gint n_columns,
-                                  gpointer data);
  /* Properties */
  enum
    {
      PROP_0,
      PROP_ROW_GEO,
 -    PROP_COL_GEO,
 +    PROP_HAXIS,
      PROP_MODEL
    };
  
@@@ -714,15 -710,13 +695,15 @@@ gtk_sheet_set_row_geometry (GtkSheet *s
  }
  
  static void
 -gtk_sheet_set_column_geometry (GtkSheet *sheet, GSheetColumn *geo)
 +gtk_sheet_set_horizontal_axis (GtkSheet *sheet, PsppireAxis *a)
  {
 -  if ( sheet->column_geometry ) g_object_unref (sheet->column_geometry);
 +  if ( sheet->haxis )
 +    g_object_unref (sheet->haxis);
  
 -  sheet->column_geometry = geo;
 +  sheet->haxis = a;
  
 -  if ( sheet->column_geometry ) g_object_ref (sheet->column_geometry);
 +  if ( sheet->haxis )
 +    g_object_ref (sheet->haxis);
  }
  
  
@@@ -740,8 -734,8 +721,8 @@@ gtk_sheet_set_property (GObjec
      case PROP_ROW_GEO:
        gtk_sheet_set_row_geometry (sheet, g_value_get_pointer (value));
        break;
 -    case PROP_COL_GEO:
 -      gtk_sheet_set_column_geometry (sheet, g_value_get_pointer (value));
 +    case PROP_HAXIS:
 +      gtk_sheet_set_horizontal_axis (sheet, g_value_get_pointer (value));
        break;
      case PROP_MODEL:
        gtk_sheet_set_model (sheet, g_value_get_pointer (value));
@@@ -765,8 -759,8 +746,8 @@@ gtk_sheet_get_property (GObjec
      case PROP_ROW_GEO:
        g_value_set_pointer (value, sheet->row_geometry);
        break;
 -    case PROP_COL_GEO:
 -      g_value_set_pointer (value, sheet->column_geometry);
 +    case PROP_HAXIS:
 +      g_value_set_pointer (value, sheet->haxis);
        break;
      case PROP_MODEL:
        g_value_set_pointer (value, sheet->model);
@@@ -784,7 -778,7 +765,7 @@@ gtk_sheet_class_init (GtkSheetClass *kl
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
  
    GParamSpec *row_geo_spec ;
 -  GParamSpec *col_geo_spec ;
 +  GParamSpec *haxis_spec ;
    GParamSpec *model_spec ;
  
    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
                          "A pointer to the model of the row geometry",
                          G_PARAM_READABLE | G_PARAM_WRITABLE );
  
 -  col_geo_spec =
 -    g_param_spec_pointer ("column-geometry",
 -                        "Column Geometry",
 -                        "A pointer to the model of the column geometry",
 +  haxis_spec =
 +    g_param_spec_pointer ("horizontal-axis",
 +                        "Horizontal Axis",
 +                        "A pointer to the PsppireAxis object for the columns",
                          G_PARAM_READABLE | G_PARAM_WRITABLE );
  
    model_spec =
                                     row_geo_spec);
  
    g_object_class_install_property (object_class,
 -                                   PROP_COL_GEO,
 -                                   col_geo_spec);
 +                                   PROP_HAXIS,
 +                                   haxis_spec);
  
    g_object_class_install_property (object_class,
                                     PROP_MODEL,
@@@ -1054,7 -1048,7 +1035,7 @@@ static voi
  gtk_sheet_init (GtkSheet *sheet)
  {
    sheet->model = NULL;
 -  sheet->column_geometry = NULL;
 +  sheet->haxis = NULL;
    sheet->row_geometry = NULL;
  
    sheet->flags = 0;
@@@ -1133,7 -1127,6 +1114,6 @@@ columns_inserted_deleted_callback (GShe
                                   gint n_columns,
                                   gpointer data)
  {
-   gint i;
    GtkSheet *sheet = GTK_SHEET (data);
  
    GtkSheetRange range;
     */
    range.col0 = first_column;
    range.row0 = 0;
 -  range.coli = g_sheet_column_get_column_count (sheet->column_geometry) - 1;
 +  range.coli = psppire_axis_unit_count (sheet->haxis) - 1;
    range.rowi = g_sheet_row_get_row_count (sheet->row_geometry) - 1;
  
    adjust_scrollbars (sheet);
    if (sheet->active_cell.col >= model_columns)
      change_active_cell (sheet, sheet->active_cell.row, model_columns - 1);
  
-   for (i = first_column; i <= max_visible_column (sheet); i++)
-     gtk_sheet_column_title_button_draw (sheet, i);
+   draw_column_title_buttons_range (sheet,
+                                  first_column, max_visible_column (sheet));
  
    gtk_sheet_range_draw (sheet, &range);
  }
@@@ -1165,7 -1158,6 +1145,6 @@@ static voi
  rows_inserted_deleted_callback (GSheetModel *model, gint first_row,
                                gint n_rows, gpointer data)
  {
-   gint i;
    GtkSheet *sheet = GTK_SHEET (data);
  
    GtkSheetRange range;
    range.row0 = first_row;
    range.col0 = 0;
    range.rowi = g_sheet_row_get_row_count (sheet->row_geometry) - 1;
 -  range.coli = g_sheet_column_get_column_count (sheet->column_geometry) - 1;
 +  range.coli = psppire_axis_unit_count (sheet->haxis) - 1;
  
    adjust_scrollbars (sheet);
  
    if (sheet->active_cell.row >= model_rows)
      change_active_cell (sheet, model_rows - 1, sheet->active_cell.col);
  
-   for (i = first_row; i <= max_visible_row (sheet); i++)
-     gtk_sheet_row_title_button_draw (sheet, i);
+   draw_row_title_buttons_range (sheet, first_row, max_visible_row (sheet));
  
    gtk_sheet_range_draw (sheet, &range);
  }
@@@ -1220,16 -1211,14 +1198,14 @@@ range_update_callback (GSheetModel *m, 
  
    if ( ( row0 < 0 && col0 < 0 ) || ( rowi < 0 && coli < 0 ) )
      {
-       gint i;
        gtk_sheet_range_draw (sheet, NULL);
        adjust_scrollbars (sheet);
  
-       for (i = min_visible_row (sheet); i <= max_visible_row (sheet); i++)
-       gtk_sheet_row_title_button_draw (sheet, i);
+       draw_row_title_buttons_range (sheet, min_visible_row (sheet),
+                                      max_visible_row (sheet));
  
-       for (i = min_visible_column (sheet);
-          i <= max_visible_column (sheet); i++)
-       gtk_sheet_column_title_button_draw (sheet, i);
+       draw_column_title_buttons_range (sheet, min_visible_column (sheet),
+                                      max_visible_column (sheet));
  
        return;
      }
   * Returns: the new sheet widget
   */
  GtkWidget *
 -gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, GSheetModel *model)
 +gtk_sheet_new (GSheetRow *vgeo, void *hgeo, GSheetModel *model)
  {
    GtkWidget *widget = g_object_new (GTK_TYPE_SHEET,
                                    "row-geometry", vgeo,
 -                                  "column-geometry", hgeo,
                                    "model", model,
                                    NULL);
    return widget;
@@@ -1309,27 -1299,6 +1285,6 @@@ gtk_sheet_set_model (GtkSheet *sheet, G
  }
  
  
- /* Call back for when the column titles have changed.
-    FIRST is the first column changed.
-    N_COLUMNS is the number of columns which have changed, or -1, which
-    indicates that the column has changed to its right-most extremity
- */
- static void
- column_titles_changed (GtkWidget *w, gint first, gint n_columns, gpointer data)
- {
-   GtkSheet *sheet = GTK_SHEET (data);
-   gboolean extremity = FALSE;
-   if ( n_columns == -1 )
-     {
-       extremity = TRUE;
-       n_columns = psppire_axis_unit_count (sheet->haxis) - 1 ;
-     }
-   if ( extremity)
-     gtk_sheet_column_title_button_draw (sheet, -1);
- }
  void
  gtk_sheet_change_entry (GtkSheet *sheet, GtkType entry_type)
  {
@@@ -1382,7 -1351,7 +1337,7 @@@ gtk_sheet_get_columns_count (GtkSheet *
    g_return_val_if_fail (sheet != NULL, 0);
    g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
  
 -  return g_sheet_column_get_column_count (sheet->column_geometry);
 +  return psppire_axis_unit_count (sheet->haxis);
  }
  
  static void
@@@ -1391,42 -1360,6 +1346,6 @@@ gtk_sheet_set_column_width (GtkSheet *s
                            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 >= psppire_axis_unit_count (sheet->haxis) || column < 0) return;
-   for (row = 0; row < g_sheet_row_get_row_count (sheet->row_geometry); row++)
-     {
-       gchar *text = gtk_sheet_cell_get_text (sheet, row, column);
-       if (text && strlen (text) > 0)
-       {
-         GtkSheetCellAttr attributes;
-         gtk_sheet_get_attributes (sheet, row, column, &attributes);
-         if (attributes.is_visible)
-           {
-             gint width = STRING_WIDTH (GTK_WIDGET (sheet),
-                                        attributes.font_desc,
-                                        text)
-               + 2 * COLUMN_TITLES_HEIGHT + attributes.border.width;
-             text_width = MAX (text_width, width);
-           }
-       }
-       dispose_string (sheet, text);
-     }
-   if (text_width > psppire_axis_unit_size (sheet->haxis, column) )
-     {
-       gtk_sheet_set_column_width (sheet, column, text_width);
-     }
- }
  void
  gtk_sheet_show_column_titles (GtkSheet *sheet)
  {
@@@ -1548,7 -1481,7 +1467,7 @@@ gtk_sheet_moveto (GtkSheet *sheet
    g_return_if_fail (col_align <= 1);
  
    g_return_if_fail (col <
 -                  g_sheet_column_get_column_count (sheet->column_geometry));
 +                  psppire_axis_unit_count (sheet->haxis));
    g_return_if_fail (row <
                    g_sheet_row_get_row_count (sheet->row_geometry));
  
  
    if (col >= 0)
    {
 -    gint x =  g_sheet_column_start_pixel (sheet->column_geometry, col);
 +    gint x =  psppire_axis_pixel_start (sheet->haxis, col);
  
      gtk_adjustment_set_value (sheet->hadjustment, x - width * col_align);
    }
@@@ -1608,7 -1541,7 +1527,7 @@@ gtk_sheet_select_row (GtkSheet *sheet, 
    sheet->range.row0 = row;
    sheet->range.col0 = 0;
    sheet->range.rowi = row;
 -  sheet->range.coli = g_sheet_column_get_column_count (sheet->column_geometry) - 1;
 +  sheet->range.coli = psppire_axis_unit_count (sheet->haxis) - 1;
    sheet->active_cell.row = row;
    sheet->active_cell.col = 0;
  
@@@ -1623,7 -1556,7 +1542,7 @@@ gtk_sheet_select_column (GtkSheet *shee
    g_return_if_fail (sheet != NULL);
    g_return_if_fail (GTK_IS_SHEET (sheet));
  
 -  if (column < 0 || column >= g_sheet_column_get_column_count (sheet->column_geometry))
 +  if (column < 0 || column >= psppire_axis_unit_count (sheet->haxis))
      return;
  
    if (sheet->state != GTK_SHEET_NORMAL)
@@@ -1656,10 -1589,10 +1575,10 @@@ gtk_sheet_range_isvisible (const GtkShe
    if (range.rowi < 0 || range.rowi >= g_sheet_row_get_row_count (sheet->row_geometry))
      return FALSE;
  
 -  if (range.col0 < 0 || range.col0 >= g_sheet_column_get_column_count (sheet->column_geometry))
 +  if (range.col0 < 0 || range.col0 >= psppire_axis_unit_count (sheet->haxis))
      return FALSE;
  
 -  if (range.coli < 0 || range.coli >= g_sheet_column_get_column_count (sheet->column_geometry))
 +  if (range.coli < 0 || range.coli >= psppire_axis_unit_count (sheet->haxis))
      return FALSE;
  
    if (range.rowi < min_visible_row (sheet))
@@@ -1764,7 -1697,7 +1683,7 @@@ gtk_sheet_dispose  (GObject *object
  
    if (sheet->model) g_object_unref (sheet->model);
    if (sheet->row_geometry) g_object_unref (sheet->row_geometry);
 -  if (sheet->column_geometry) g_object_unref (sheet->column_geometry);
 +  if (sheet->haxis) g_object_unref (sheet->haxis);
  
    g_object_unref (sheet->entry_container);
    sheet->entry_container = NULL;
@@@ -2138,7 -2071,7 +2057,7 @@@ gtk_sheet_cell_draw (GtkSheet *sheet, g
      return;
  
    if (col < 0 ||
 -      col >= g_sheet_column_get_column_count (sheet->column_geometry))
 +      col >= psppire_axis_unit_count (sheet->haxis))
      return;
  
    gtk_sheet_get_attributes (sheet, row, col, &attributes);
@@@ -2338,16 -2271,16 +2257,11 @@@ gtk_sheet_range_draw_selection (GtkShee
    gtk_sheet_draw_border (sheet, sheet->range);
  }
  
--static void gtk_sheet_set_cell (GtkSheet *sheet, gint row, gint col,
--                              GtkJustification justification,
--                              const gchar *text);
--
--
  static inline gint
  safe_strcmp (const gchar *s1, const gchar *s2)
  {
    if ( !s1 && !s2) return 0;
--  if ( !s1) return - 1;
++  if ( !s1) return -1;
    if ( !s2) return +1;
    return strcmp (s1, s2);
  }
@@@ -2363,7 -2296,7 +2277,7 @@@ gtk_sheet_set_cell (GtkSheet *sheet, gi
    g_return_if_fail (sheet != NULL);
    g_return_if_fail (GTK_IS_SHEET (sheet));
  
 -  if (col >= g_sheet_column_get_column_count (sheet->column_geometry)
 +  if (col >= psppire_axis_unit_count (sheet->haxis)
        || row >= g_sheet_row_get_row_count (sheet->row_geometry))
      return;
  
  
    old_text = g_sheet_model_get_string (model, row, col);
  
++  if (0 != safe_strcmp (old_text, text))
++    g_sheet_model_set_string (model, text, row, col);
++
    if ( g_sheet_model_free_strings (model))
      g_free (old_text);
  }
@@@ -2385,7 -2318,7 +2302,7 @@@ gtk_sheet_cell_clear (GtkSheet *sheet, 
  
    g_return_if_fail (sheet != NULL);
    g_return_if_fail (GTK_IS_SHEET (sheet));
 -  if (column >= g_sheet_column_get_column_count (sheet->column_geometry) ||
 +  if (column >= psppire_axis_unit_count (sheet->haxis) ||
        row >= g_sheet_row_get_row_count (sheet->row_geometry)) return;
  
    if (column < 0 || row < 0) return;
@@@ -2422,7 -2355,7 +2339,7 @@@ gtk_sheet_cell_get_text (const GtkShee
    g_return_val_if_fail (sheet != NULL, NULL);
    g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
  
 -  if (col >= g_sheet_column_get_column_count (sheet->column_geometry) || row >= g_sheet_row_get_row_count (sheet->row_geometry))
 +  if (col >= psppire_axis_unit_count (sheet->haxis) || row >= g_sheet_row_get_row_count (sheet->row_geometry))
      return NULL;
    if (col < 0 || row < 0) return NULL;
  
@@@ -2443,7 -2376,7 +2360,7 @@@ gtk_sheet_cell_get_state (GtkSheet *she
  
    g_return_val_if_fail (sheet != NULL, 0);
    g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
 -  if (col >= g_sheet_column_get_column_count (sheet->column_geometry) || row >= g_sheet_row_get_row_count (sheet->row_geometry)) return 0;
 +  if (col >= psppire_axis_unit_count (sheet->haxis) || row >= g_sheet_row_get_row_count (sheet->row_geometry)) return 0;
    if (col < 0 || row < 0) return 0;
  
    state = sheet->state;
@@@ -2526,7 -2459,7 +2443,7 @@@ gtk_sheet_get_pixel_info (GtkSheet *she
    else
      {
        tcol = column_from_xpixel (sheet, x);
 -      if (tcol > g_sheet_column_get_column_count (sheet->column_geometry))
 +      if (tcol > psppire_axis_unit_count (sheet->haxis))
        return FALSE;
      }
  
@@@ -2544,14 -2477,14 +2461,14 @@@ gtk_sheet_get_cell_area (GtkSheet *shee
    g_return_val_if_fail (sheet != NULL, 0);
    g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
  
 -  if (row >= g_sheet_row_get_row_count (sheet->row_geometry) || column >= g_sheet_column_get_column_count (sheet->column_geometry))
 +  if (row >= g_sheet_row_get_row_count (sheet->row_geometry) || column >= psppire_axis_unit_count (sheet->haxis))
      return FALSE;
  
 -  area->x = (column == -1) ? 0 : g_sheet_column_start_pixel (sheet->column_geometry, column);
 +  area->x = (column == -1) ? 0 : psppire_axis_pixel_start (sheet->haxis, column);
    area->y = (row == -1)    ? 0 : g_sheet_row_start_pixel (sheet->row_geometry, row);
  
    area->width= (column == -1) ? sheet->row_title_area.width
 -    : g_sheet_column_get_width (sheet->column_geometry, column);
 +    : psppire_axis_unit_size (sheet->haxis, column);
  
    area->height= (row == -1) ? sheet->column_title_area.height
      : g_sheet_row_get_height (sheet->row_geometry, row);
@@@ -2570,7 -2503,7 +2487,7 @@@ gtk_sheet_set_active_cell (GtkSheet *sh
  
    if (row >= g_sheet_row_get_row_count (sheet->row_geometry)
        ||
 -      col >= g_sheet_column_get_column_count (sheet->column_geometry))
 +      col >= psppire_axis_unit_count (sheet->haxis))
      return;
  
    sheet->active_cell.row = row;
@@@ -2625,6 -2558,6 +2542,8 @@@ gtk_sheet_entry_changed (GtkWidget *wid
  
    text = gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)));
  
++
++
    if (text && strlen (text) > 0)
      {
        gtk_sheet_get_attributes (sheet, row, col, &attributes);
@@@ -2679,7 -2612,7 +2598,7 @@@ change_active_cell (GtkSheet *sheet, gi
      return;
  
    if ( row > g_sheet_row_get_row_count (sheet->row_geometry)
 -       || col > g_sheet_column_get_column_count (sheet->column_geometry))
 +       || col > psppire_axis_unit_count (sheet->haxis))
      return;
  
    if (sheet->state != GTK_SHEET_NORMAL)
@@@ -2778,7 -2711,6 +2697,6 @@@ gtk_sheet_show_active_cell (GtkSheet *s
    gtk_widget_grab_focus (GTK_WIDGET (sheet_entry));
  
    dispose_string (sheet, text);
  }
  
  static void
@@@ -2863,10 -2795,10 +2781,10 @@@ gtk_sheet_new_selection (GtkSheet *shee
  
              if (mask1 != mask2)
                {
 -                x = g_sheet_column_start_pixel (sheet->column_geometry, j);
 +                x = psppire_axis_pixel_start (sheet->haxis, j);
                  y = g_sheet_row_start_pixel (sheet->row_geometry, i);
 -                width = g_sheet_column_start_pixel (sheet->column_geometry, j)- x+
 -                  g_sheet_column_get_width (sheet->column_geometry, j);
 +                width = psppire_axis_pixel_start (sheet->haxis, j)- x+
 +                  psppire_axis_unit_size (sheet->haxis, j);
                  height = g_sheet_row_start_pixel (sheet->row_geometry, i) - y + g_sheet_row_get_height (sheet->row_geometry, i);
  
                  if (i == sheet->range.row0)
  
                  if (i != sheet->active_cell.row || j != sheet->active_cell.col)
                    {
 -                    x = g_sheet_column_start_pixel (sheet->column_geometry, j);
 +                    x = psppire_axis_pixel_start (sheet->haxis, j);
                      y = g_sheet_row_start_pixel (sheet->row_geometry, i);
 -                    width = g_sheet_column_start_pixel (sheet->column_geometry, j)- x+
 -                      g_sheet_column_get_width (sheet->column_geometry, j);
 +                    width = psppire_axis_pixel_start (sheet->haxis, j)- x+
 +                      psppire_axis_unit_size (sheet->haxis, j);
  
                      height = g_sheet_row_start_pixel (sheet->row_geometry, i) - y + g_sheet_row_get_height (sheet->row_geometry, i);
  
          if (state == GTK_STATE_SELECTED && !selected)
            {
  
 -            x = g_sheet_column_start_pixel (sheet->column_geometry, j);
 +            x = psppire_axis_pixel_start (sheet->haxis, j);
              y = g_sheet_row_start_pixel (sheet->row_geometry, i);
 -            width = g_sheet_column_start_pixel (sheet->column_geometry, j) - x + g_sheet_column_get_width (sheet->column_geometry, j);
 +            width = psppire_axis_pixel_start (sheet->haxis, j) - x + psppire_axis_unit_size (sheet->haxis, j);
              height = g_sheet_row_start_pixel (sheet->row_geometry, i) - y + g_sheet_row_get_height (sheet->row_geometry, i);
  
              if (i == sheet->range.row0)
              (i != sheet->active_cell.row || j != sheet->active_cell.col))
            {
  
 -            x = g_sheet_column_start_pixel (sheet->column_geometry, j);
 +            x = psppire_axis_pixel_start (sheet->haxis, j);
              y = g_sheet_row_start_pixel (sheet->row_geometry, i);
 -            width = g_sheet_column_start_pixel (sheet->column_geometry, j) - x + g_sheet_column_get_width (sheet->column_geometry, j);
 +            width = psppire_axis_pixel_start (sheet->haxis, j) - x + psppire_axis_unit_size (sheet->haxis, j);
              height = g_sheet_row_start_pixel (sheet->row_geometry, i) - y + g_sheet_row_get_height (sheet->row_geometry, i);
  
              if (i == new_range.row0)
          mask2 = j == new_range.coli ? mask2 + 8 : mask2;
          if (mask2 != mask1 || (mask2 == mask1 && state != GTK_STATE_SELECTED))
            {
 -            x = g_sheet_column_start_pixel (sheet->column_geometry, j);
 +            x = psppire_axis_pixel_start (sheet->haxis, j);
              y = g_sheet_row_start_pixel (sheet->row_geometry, i);
 -            width = g_sheet_column_get_width (sheet->column_geometry, j);
 +            width = psppire_axis_unit_size (sheet->haxis, j);
              height = g_sheet_row_get_height (sheet->row_geometry, i);
              if (mask2 & 1)
                gdk_draw_rectangle (sheet->sheet_window,
@@@ -3197,19 -3129,17 +3115,17 @@@ gtk_sheet_expose (GtkWidget *widget
    if (event->window == sheet->row_title_window &&
        sheet->row_titles_visible)
      {
-       gint i;
-       for (i = min_visible_row (sheet); i <= max_visible_row (sheet); i++)
-       gtk_sheet_row_title_button_draw (sheet, i);
+       draw_row_title_buttons_range (sheet,
+                                   min_visible_row (sheet),
+                                   max_visible_row (sheet));
      }
  
    if (event->window == sheet->column_title_window &&
        sheet->column_titles_visible)
      {
-       gint i;
-       for (i = min_visible_column (sheet);
-          i <= max_visible_column (sheet);
-          ++i)
-       gtk_sheet_column_title_button_draw (sheet, i);
+       draw_column_title_buttons_range (sheet,
+                                      min_visible_column (sheet),
+                                      max_visible_column (sheet));
      }
  
  
@@@ -3302,7 -3232,7 +3218,7 @@@ gtk_sheet_button_press (GtkWidget *widg
                     sheet_signals[BUTTON_EVENT_COLUMN], 0,
                     column, event);
  
 -      if (g_sheet_column_get_sensitivity (sheet->column_geometry, column))
 +      if (g_sheet_model_get_column_sensitivity (sheet->model, column))
        {
          if ( event->type == GDK_2BUTTON_PRESS && event->button == 1)
            g_signal_emit (sheet,
        if (on_column_boundary (sheet, sheet->x_drag, &sheet->drag_cell.col))
        {
          guint req;
-         if (event->type == GDK_2BUTTON_PRESS)
-           {
-             gtk_sheet_autoresize_column (sheet, sheet->drag_cell.col);
-             GTK_SHEET_UNSET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
-             return TRUE;
-           }
          gtk_sheet_column_size_request (sheet, sheet->drag_cell.col, &req);
          GTK_SHEET_SET_FLAGS (sheet, GTK_SHEET_IN_XDRAG);
          gdk_pointer_grab (sheet->column_title_window, FALSE,
  
        column = column_from_xpixel (sheet, x);
  
 -      if (g_sheet_column_get_sensitivity (sheet->column_geometry, column))
 +      if (g_sheet_model_get_column_sensitivity (sheet->model, column))
        {
          veto = gtk_sheet_click_cell (sheet, -1, column);
          gtk_grab_add (GTK_WIDGET (sheet));
@@@ -3515,7 -3439,7 +3425,7 @@@ gtk_sheet_click_cell (GtkSheet *sheet, 
    cell.col = column;
  
    if (row >= g_sheet_row_get_row_count (sheet->row_geometry)
 -      || column >= g_sheet_column_get_column_count (sheet->column_geometry))
 +      || column >= psppire_axis_unit_count (sheet->haxis))
      {
        return FALSE;
      }
        sheet->range.col0 = 0;
        sheet->range.rowi = g_sheet_row_get_row_count (sheet->row_geometry) - 1;
        sheet->range.coli =
 -      g_sheet_column_get_column_count (sheet->column_geometry) - 1;
 +      psppire_axis_unit_count (sheet->haxis) - 1;
        sheet->active_cell.row = 0;
        sheet->active_cell.col = 0;
        gtk_sheet_select_range (sheet, NULL);
@@@ -3826,7 -3750,9 +3736,7 @@@ motion_timeout_callback (gpointer data
        if (sheet->row_title_under)
        {
          GSheetRow *row_geo = sheet->row_geometry;
 -        gchar *text;
 -
 -        text = g_sheet_row_get_subtitle (row_geo, row);
 +        gchar *text = g_sheet_row_get_subtitle (row_geo, row);
  
          show_subtitle (sheet, row, -1, text);
          g_free (text);
  
        if (sheet->column_title_under)
        {
 -        GSheetColumn *col_geo = sheet->column_geometry;
 -        gchar *text;
 -
 -        text = g_sheet_column_get_subtitle (col_geo, column);
 +        gchar *text = g_sheet_model_get_column_subtitle (sheet->model,
 +                                                         column);
  
          show_subtitle (sheet, -1, column, text);
  
@@@ -4033,7 -3961,7 +3943,7 @@@ gtk_sheet_motion (GtkWidget *widget,  G
        sheet->y_drag = y;
        aux = sheet->range;
        if (aux.row0 + row >= 0 && aux.rowi + row < g_sheet_row_get_row_count (sheet->row_geometry) &&
 -        aux.col0 + column >= 0 && aux.coli + column < g_sheet_column_get_column_count (sheet->column_geometry))
 +        aux.col0 + column >= 0 && aux.coli + column < psppire_axis_unit_count (sheet->haxis))
        {
          aux = sheet->drag_range;
          sheet->drag_range.row0 = sheet->range.row0 + row;
        GtkSheetRange aux;
        gint v_h, current_col, current_row, col_threshold, row_threshold;
        v_h = 1;
 -      if (abs (x - g_sheet_column_start_pixel (sheet->column_geometry, sheet->drag_cell.col)) >
 +      if (abs (x - psppire_axis_pixel_start (sheet->haxis, sheet->drag_cell.col)) >
          abs (y - g_sheet_row_start_pixel (sheet->row_geometry, sheet->drag_cell.row))) v_h = 2;
  
        current_col = column_from_xpixel (sheet, x);
  
        /*use half of column width resp. row height as threshold to
        expand selection*/
 -      col_threshold = g_sheet_column_start_pixel (sheet->column_geometry, current_col) +
 -      g_sheet_column_get_width (sheet->column_geometry, current_col) / 2;
 +      col_threshold = psppire_axis_pixel_start (sheet->haxis, current_col) +
 +      psppire_axis_unit_size (sheet->haxis, current_col) / 2;
        if (column > 0)
        {
          if (x < col_threshold)
        row = 0;
  
        if (aux.row0 + row >= 0 && aux.rowi + row < g_sheet_row_get_row_count (sheet->row_geometry) &&
 -        aux.col0 + column >= 0 && aux.coli + column < g_sheet_column_get_column_count (sheet->column_geometry))
 +        aux.col0 + column >= 0 && aux.coli + column < psppire_axis_unit_count (sheet->haxis))
        {
          aux = sheet->drag_range;
          sheet->drag_range = sheet->range;
@@@ -4170,7 -4098,7 +4080,7 @@@ gtk_sheet_extend_selection (GtkSheet *s
    switch (sheet->state)
      {
      case GTK_SHEET_ROW_SELECTED:
 -      column = g_sheet_column_get_column_count (sheet->column_geometry) - 1;
 +      column = psppire_axis_unit_count (sheet->haxis) - 1;
        break;
      case GTK_SHEET_COLUMN_SELECTED:
        row = g_sheet_row_get_row_count (sheet->row_geometry) - 1;
@@@ -4295,7 -4223,7 +4205,7 @@@ step_sheet (GtkSheet *sheet, GtkScrollT
                g_sheet_row_get_row_count (sheet->row_geometry) - 1);
  
    minimize_int (&new_cell.col,
 -              g_sheet_column_get_column_count (sheet->column_geometry) - 1);
 +              psppire_axis_unit_count (sheet->haxis) - 1);
  
    g_signal_emit (sheet, sheet_signals[TRAVERSE], 0,
                 &sheet->active_cell,
    if ( new_cell.col > max_fully_visible_column (sheet))
      {
        glong hpos  =
 -      g_sheet_column_start_pixel (sheet->column_geometry,
 +      psppire_axis_pixel_start (sheet->haxis,
                                    new_cell.col + 1);
        hpos -= sheet->hadjustment->page_size;
  
    else if ( new_cell.col < min_fully_visible_column (sheet))
      {
        glong hpos  =
 -      g_sheet_column_start_pixel (sheet->column_geometry,
 +      psppire_axis_pixel_start (sheet->haxis,
                                    new_cell.col);
  
        gtk_adjustment_set_value (sheet->hadjustment,
@@@ -4503,9 -4431,6 +4413,6 @@@ gtk_sheet_size_allocate (GtkWidget *wid
                            sheet->column_title_area.height);
  
  
-   /* column button allocation */
-   draw_column_title_buttons (sheet);
    /* position the window which holds the row title buttons */
    sheet->row_title_area.x = 0;
    sheet->row_title_area.y = 0;
                            sheet->row_title_area.height);
  
  
-   /* row button allocation */
-   draw_row_title_buttons (sheet);
-   draw_column_title_buttons (sheet);
    /* set the scrollbars adjustments */
    adjust_scrollbars (sheet);
  }
  static void
  draw_column_title_buttons (GtkSheet *sheet)
  {
-   gint i;
    gint x, width;
  
    if (!sheet->column_titles_visible) return;
      }
  
    if (max_visible_column (sheet) ==
 -      g_sheet_column_get_column_count (sheet->column_geometry) - 1)
 +      psppire_axis_unit_count (sheet->haxis) - 1)
      gdk_window_clear_area (sheet->column_title_window,
                           0, 0,
                           sheet->column_title_area.width,
  
    size_allocate_global_button (sheet);
  
-   for (i = min_visible_column (sheet); i <= max_visible_column (sheet); i++)
-     gtk_sheet_column_title_button_draw (sheet, i);
+   draw_column_title_buttons_range (sheet, min_visible_column (sheet), 
+                                  max_visible_column (sheet));
  }
  
  static void
  draw_row_title_buttons (GtkSheet *sheet)
  {
-   gint i;
    gint y = 0;
    gint height;
  
  
    size_allocate_global_button (sheet);
  
-   for (i = min_visible_row (sheet); i <= max_visible_row (sheet); i++)
-     {
-       if ( i >= g_sheet_row_get_row_count (sheet->row_geometry))
-       break;
-       gtk_sheet_row_title_button_draw (sheet, i);
-     }
+   draw_row_title_buttons_range (sheet, min_visible_row (sheet),
+                               max_visible_row (sheet));
  }
  
  
@@@ -4777,7 -4693,7 +4675,7 @@@ gtk_sheet_get_entry_widget (GtkSheet *s
  
  
  static void
gtk_sheet_button_draw (GtkSheet *sheet, GdkWindow *window,
draw_button (GtkSheet *sheet, GdkWindow *window,
                       GtkSheetButton *button, gboolean is_sensitive,
                       GdkRectangle allocation)
  {
    gboolean rtl ;
  
    gint state = 0;
-   gint len = 0;
-   gchar *line = 0;
  
    g_return_if_fail (sheet != NULL);
    g_return_if_fail (button != NULL);
  
    if (button->label_visible)
      {
-       text_height = DEFAULT_ROW_HEIGHT - 
+       text_height = DEFAULT_ROW_HEIGHT -
        2 * COLUMN_TITLES_HEIGHT;
  
        gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->fg_gc[button->state],
  
        allocation.y += 2 * sheet->button->style->ythickness;
  
        if (button->label && strlen (button->label)>0)
        {
-         gchar *words = 0;
+         PangoRectangle rect;
+         gchar *line = button->label;
          PangoLayout *layout = NULL;
-         gint real_x = allocation.x, real_y = allocation.y;
+         gint real_x = allocation.x;
+         gint real_y = allocation.y;
  
-         words = button->label;
-         line = g_new (gchar, 1);
-         line[0]='\0';
+         layout = gtk_widget_create_pango_layout (GTK_WIDGET (sheet), line);
+         pango_layout_get_extents (layout, NULL, &rect);
  
-         while (words && *words != '\0')
+         text_width = PANGO_PIXELS (rect.width);
+         switch (button->justification)
            {
-             if (*words != '\n')
-               {
-                 len = strlen (line);
-                 line = g_realloc (line, len + 2);
-                 line[len]=*words;
-                 line[len + 1]='\0';
-               }
-             if (*words == '\n' || * (words + 1) == '\0')
-               {
-                 text_width = STRING_WIDTH (GTK_WIDGET (sheet), GTK_WIDGET (sheet)->style->font_desc, line);
-                 layout = gtk_widget_create_pango_layout (GTK_WIDGET (sheet), line);
-                 switch (button->justification)
-                   {
-                   case GTK_JUSTIFY_LEFT:
-                     real_x = allocation.x + COLUMN_TITLES_HEIGHT;
-                     align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
-                     break;
-                   case GTK_JUSTIFY_RIGHT:
-                     real_x = allocation.x + allocation.width - text_width - COLUMN_TITLES_HEIGHT;
-                     align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
-                     break;
-                   case GTK_JUSTIFY_CENTER:
-                   default:
-                     real_x = allocation.x + (allocation.width - text_width)/2;
-                     align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
-                     pango_layout_set_justify (layout, TRUE);
-                   }
-                 pango_layout_set_alignment (layout, align);
-                 gtk_paint_layout (GTK_WIDGET (sheet)->style,
-                                   window,
-                                   state,
-                                   FALSE,
-                                   &allocation,
-                                   GTK_WIDGET (sheet),
-                                   "label",
-                                   real_x, real_y,
-                                   layout);
-                 g_object_unref (layout);
-                 real_y += text_height + 2;
-                 g_free (line);
-                 line = g_new (gchar, 1);
-                 line[0]='\0';
-               }
-             words++;
+           case GTK_JUSTIFY_LEFT:
+             real_x = allocation.x + COLUMN_TITLES_HEIGHT;
+             align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
+             break;
+           case GTK_JUSTIFY_RIGHT:
+             real_x = allocation.x + allocation.width - text_width - COLUMN_TITLES_HEIGHT;
+             align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
+             break;
+           case GTK_JUSTIFY_CENTER:
+           default:
+             real_x = allocation.x + (allocation.width - text_width)/2;
+             align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
+             pango_layout_set_justify (layout, TRUE);
            }
-         g_free (line);
+         pango_layout_set_alignment (layout, align);
+         gtk_paint_layout (GTK_WIDGET (sheet)->style,
+                           window,
+                           state,
+                           FALSE,
+                           &allocation,
+                           GTK_WIDGET (sheet),
+                           "label",
+                           real_x, real_y,
+                           layout);
+         g_object_unref (layout);
        }
  
        gdk_gc_set_clip_rectangle (GTK_WIDGET (sheet)->style->fg_gc[button->state],
    gtk_sheet_button_free (button);
  }
  
+ /* Draw the column title buttons FIRST through to LAST */
  static void
gtk_sheet_column_title_button_draw (GtkSheet *sheet, gint column)
draw_column_title_buttons_range (GtkSheet *sheet, gint first, gint last)
  {
-   GdkRectangle allocation;
-   GtkSheetButton *button = NULL;
-   gboolean is_sensitive = FALSE;
+   GdkRegion *region;
+   gint col;
    if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
  
    if (!sheet->column_titles_visible) return;
  
-   if (column < min_visible_column (sheet)) return;
-   if (column > max_visible_column (sheet)) return;
+   g_return_if_fail (first >= min_visible_column (sheet));
+   g_return_if_fail (last <= max_visible_column (sheet));
  
-   button = g_sheet_model_get_column_button (sheet->model, column);
-   allocation.y = 0;
-   allocation.x = psppire_axis_pixel_start (sheet->haxis, column) + CELL_SPACING;
-   allocation.x -= sheet->hadjustment->value;
+   region =
+     gdk_drawable_get_visible_region (GDK_DRAWABLE (sheet->column_title_window));
  
-   allocation.height = sheet->column_title_area.height;
-   allocation.width = psppire_axis_unit_size (sheet->haxis, column);
-   is_sensitive = g_sheet_model_get_column_sensitivity (sheet->model, column);
+   gdk_window_begin_paint_region (sheet->column_title_window, region);
  
-   gtk_sheet_button_draw (sheet, sheet->column_title_window,
-                        button, is_sensitive, allocation);
+   for (col = first ; col <= last ; ++col)
+     {
+       GdkRectangle allocation;
+       gboolean is_sensitive = FALSE;
+       GtkSheetButton *
 -      button = g_sheet_column_get_button (sheet->column_geometry, col);
++      button = g_sheet_model_get_column_button (sheet->model, col);
+       allocation.y = 0;
 -      allocation.x =
 -      g_sheet_column_start_pixel (sheet->column_geometry, col)
++      allocation.x = psppire_axis_pixel_start (sheet->haxis, col)
+       + CELL_SPACING;
+       allocation.x -= sheet->hadjustment->value;
+       allocation.height = sheet->column_title_area.height;
 -      allocation.width =
 -      g_sheet_column_get_width (sheet->column_geometry, col);
 -      is_sensitive =
 -      g_sheet_column_get_sensitivity (sheet->column_geometry, col);
++      allocation.width = psppire_axis_unit_size (sheet->haxis, col);
++      is_sensitive = g_sheet_model_get_column_sensitivity (sheet->model, col);
+       draw_button (sheet, sheet->column_title_window,
+                  button, is_sensitive, allocation);
+     }
+   gdk_window_end_paint (sheet->column_title_window);
  }
  
  
  static void
gtk_sheet_row_title_button_draw (GtkSheet *sheet, gint row)
draw_row_title_buttons_range (GtkSheet *sheet, gint first, gint last)
  {
-   GdkRectangle allocation;
-   GtkSheetButton *button = NULL;
-   gboolean is_sensitive = FALSE;
+   GdkRegion *region;
+   gint row;
    if (!GTK_WIDGET_REALIZED (GTK_WIDGET (sheet))) return;
  
    if (!sheet->row_titles_visible) return;
  
-   if (row < min_visible_row (sheet)) return;
-   if (row > max_visible_row (sheet)) return;
+   g_return_if_fail (first >= min_visible_row (sheet));
+   g_return_if_fail (last <= max_visible_row (sheet));
  
-   button = g_sheet_row_get_button (sheet->row_geometry, row);
-   allocation.x = 0;
-   allocation.y = g_sheet_row_start_pixel (sheet->row_geometry, row) + CELL_SPACING;
-   allocation.y -= sheet->vadjustment->value;
  
-   allocation.width = sheet->row_title_area.width;
-   allocation.height = g_sheet_row_get_height (sheet->row_geometry, row);
-   is_sensitive = g_sheet_row_get_sensitivity (sheet->row_geometry, row);
+   region =
+     gdk_drawable_get_visible_region (GDK_DRAWABLE (sheet->row_title_window));
+   gdk_window_begin_paint_region (sheet->row_title_window, region);
+   for (row = first; row <= last; ++row)
+     {
+       GdkRectangle allocation;
+       gboolean is_sensitive = FALSE;
+       GtkSheetButton *button =
+       g_sheet_row_get_button (sheet->row_geometry, row);
+       allocation.x = 0;
+       allocation.y = g_sheet_row_start_pixel (sheet->row_geometry, row)
+       + CELL_SPACING;
+       allocation.y -= sheet->vadjustment->value;
+       allocation.width = sheet->row_title_area.width;
+       allocation.height = g_sheet_row_get_height (sheet->row_geometry, row);
+       is_sensitive = g_sheet_row_get_sensitivity (sheet->row_geometry, row);
+       draw_button (sheet, sheet->row_title_window,
+                  button, is_sensitive, allocation);
+     }
  
-   gtk_sheet_button_draw (sheet, sheet->row_title_window,
-                        button, is_sensitive, allocation);
+   gdk_window_end_paint (sheet->row_title_window);
  }
  
  /* SCROLLBARS
@@@ -5023,12 -4947,12 +4926,12 @@@ adjust_scrollbars (GtkSheet *sheet
  
        sheet->hadjustment->page_increment = width;
  
 -      last_col = g_sheet_column_get_column_count (sheet->column_geometry) - 1;
 +      last_col = psppire_axis_unit_count (sheet->haxis) - 1;
  
        sheet->hadjustment->upper =
 -      g_sheet_column_start_pixel (sheet->column_geometry, last_col)
 +      psppire_axis_pixel_start (sheet->haxis, last_col)
        +
 -      g_sheet_column_get_width (sheet->column_geometry, last_col)
 +      psppire_axis_unit_size (sheet->haxis, last_col)
        ;
  
        sheet->hadjustment->lower = 0;
@@@ -5143,10 -5067,10 +5046,10 @@@ draw_xor_rectangle (GtkSheet *sheet, Gt
    GdkRectangle clip_area, area;
    GdkGCValues values;
  
 -  area.x = g_sheet_column_start_pixel (sheet->column_geometry, range.col0);
 +  area.x = psppire_axis_pixel_start (sheet->haxis, range.col0);
    area.y = g_sheet_row_start_pixel (sheet->row_geometry, range.row0);
 -  area.width = g_sheet_column_start_pixel (sheet->column_geometry, range.coli)- area.x+
 -    g_sheet_column_get_width (sheet->column_geometry, range.coli);
 +  area.width = psppire_axis_pixel_start (sheet->haxis, range.coli)- area.x+
 +    psppire_axis_unit_size (sheet->haxis, range.coli);
    area.height = g_sheet_row_start_pixel (sheet->row_geometry, range.rowi)- area.y +
      g_sheet_row_get_height (sheet->row_geometry, range.rowi);
  
  static guint
  new_column_width (GtkSheet *sheet, gint column, gint *x)
  {
 -  gint left_pos = g_sheet_column_start_pixel (sheet->column_geometry, column)
 +  gint left_pos = psppire_axis_pixel_start (sheet->haxis, column)
      - sheet->hadjustment->value;
  
    gint width = *x - left_pos;
        *x = left_pos + width;
      }
  
 +#if AXIS_TRANSITION
    g_sheet_column_set_width (sheet->column_geometry, column, width);
 +#endif
  
    draw_column_title_buttons (sheet);
  
@@@ -5262,15 -5184,13 +5165,15 @@@ gtk_sheet_set_column_width (GtkSheet *s
    g_return_if_fail (sheet != NULL);
    g_return_if_fail (GTK_IS_SHEET (sheet));
  
 -  if (column < 0 || column >= g_sheet_column_get_column_count (sheet->column_geometry))
 +  if (column < 0 || column >= psppire_axis_unit_count (sheet->haxis))
      return;
  
    gtk_sheet_column_size_request (sheet, column, &min_width);
    if (width < min_width) return;
  
 +#if AXIS_TRANSITION
    g_sheet_column_set_width (sheet->column_geometry, column, width);
 +#endif
  
    if (GTK_WIDGET_REALIZED (GTK_WIDGET (sheet)))
      {
@@@ -5357,7 -5277,7 +5260,7 @@@ gtk_sheet_get_attributes (const GtkShee
      }
  
    attr->justification =
 -    g_sheet_column_get_justification (sheet->column_geometry, col);
 +    g_sheet_model_get_column_justification (sheet->model, col);
  
    j = g_sheet_model_get_justification (sheet->model, row, col);
    if (j)
@@@ -5417,7 -5337,7 +5320,7 @@@ gtk_sheet_column_size_request (GtkShee
  {
    GtkRequisition button_requisition;
  
 -  GtkSheetButton *button = g_sheet_column_get_button (sheet->column_geometry, col);
 +  GtkSheetButton *button = g_sheet_model_get_column_button (sheet->model, col);
  
    gtk_sheet_button_size_request (sheet,
                                 button,
@@@ -5481,6 -5401,7 +5384,6 @@@ gtk_sheet_button_free (GtkSheetButton *
    g_free (button);
  }
  
 -
  static void
  append_cell_text (GString *string, const GtkSheet *sheet, gint r, gint c)
  {
index 2a69fbef07351a6d4ca7d24ed981a2c0a9ab142c,0000000000000000000000000000000000000000..a3609afae6101fa925cb9705513dbd577c8763f4
mode 100644,000000..100644
--- /dev/null
@@@ -1,181 -1,0 +1,204 @@@
-   tower_init (&axis->tower);
 +/* PSPPIRE - a graphical user interface for PSPP.
 +   Copyright (C) 2008  Free Software Foundation
 +
 +   This program is free software: you can redistribute it and/or modify
 +   it under the terms of the GNU General Public License as published by
 +   the Free Software Foundation, either version 3 of the License, or
 +   (at your option) any later version.
 +
 +   This program is distributed in the hope that it will be useful,
 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +   GNU General Public License for more details.
 +
 +   You should have received a copy of the GNU General Public License
 +   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 +
 +#include <config.h>
 +#include <string.h>
 +#include <stdlib.h>
 +
 +#include <libpspp/tower.h>
++#include <libpspp/pool.h>
 +#include "psppire-axis.h"
 +#include <gtk/gtk.h>
 +
 +
 +/* --- prototypes --- */
 +static void psppire_axis_class_init (PsppireAxisClass *class);
 +static void psppire_axis_init (PsppireAxis            *axis);
 +static void psppire_axis_finalize   (GObject          *object);
 +
 +
 +/* --- variables --- */
 +static GObjectClass     *parent_class = NULL;
 +
 +/* --- functions --- */
 +/**
 + * psppire_axis_get_type:
 + * @returns: the type ID for accelerator groups.
 + */
 +GType
 +psppire_axis_get_type (void)
 +{
 +  static GType object_type = 0;
 +
 +  if (!object_type)
 +    {
 +      static const GTypeInfo object_info = {
 +      sizeof (PsppireAxisClass),
 +      (GBaseInitFunc) NULL,
 +      (GBaseFinalizeFunc) NULL,
 +      (GClassInitFunc) psppire_axis_class_init,
 +      NULL,   /* class_finalize */
 +      NULL,   /* class_data */
 +      sizeof (PsppireAxis),
 +      0,      /* n_preallocs */
 +      (GInstanceInitFunc) psppire_axis_init,
 +      };
 +
 +      object_type = g_type_register_static (G_TYPE_OBJECT,
 +                                          "PsppireAxis",
 +                                          &object_info, 0);
 +    }
 +
 +  return object_type;
 +}
 +
 +
 +static void
 +psppire_axis_class_init (PsppireAxisClass *class)
 +{
 +  GObjectClass *object_class = G_OBJECT_CLASS (class);
 +
 +  parent_class = g_type_class_peek_parent (class);
 +
 +  object_class->finalize = psppire_axis_finalize;
 +}
 +
 +static void
 +psppire_axis_init (PsppireAxis *axis)
 +{
- psppire_axis_new (gint w)
++  axis->pool = NULL;
++  psppire_axis_clear (axis);
 +}
 +
 +
 +static void
 +psppire_axis_finalize (GObject *object)
 +{
++  PsppireAxis *a = PSPPIRE_AXIS (object);
++  pool_destroy (a->pool);
 +  G_OBJECT_CLASS (parent_class)->finalize (object);
 +}
 +
 +/**
 + * psppire_axis_new:
 + * @returns: a new #PsppireAxis object
 + *
 + * Creates a new #PsppireAxis.
 + */
 +PsppireAxis*
-   PsppireAxis *new_axis = g_object_new (G_TYPE_PSPPIRE_AXIS, NULL);
-   new_axis->width = w;
-   return new_axis;
++psppire_axis_new (void)
 +{
-   if ( a->width == -1)
-     {
-       const struct tower_node *node;
-       if  (unit >= tower_count (&a->tower))
-       return 0;
++  return g_object_new (G_TYPE_PSPPIRE_AXIS, NULL);
 +}
 +
 +
 +gint
 +psppire_axis_unit_size (PsppireAxis *a, gint unit)
 +{
-       node = tower_get (&a->tower, unit);
-       return tower_node_get_size (node);
-     }
++  const struct tower_node *node;
++  if  (unit >= tower_count (&a->tower))
++    return 0;
 +
-   return a->width;
++  node = tower_get (&a->tower, unit);
 +
-   if (a->width == -1)
-     return tower_count (&a->tower);
-   return 600;
++  return tower_node_get_size (node);
 +}
 +
 +gint
 +psppire_axis_unit_count (PsppireAxis *a)
 +{
-   if ( a->width == -1 )
-     {
-       const struct tower_node *node;
++  return tower_count (&a->tower);
 +}
 +
 +glong
 +psppire_axis_pixel_start (PsppireAxis *a, gint unit)
 +{
-       if ( unit >= tower_count (&a->tower))
-       return tower_height (&a->tower);
++  const struct tower_node *node;
 +
-       node = tower_get (&a->tower, unit);
-       return  tower_node_get_level (node);
-     }
++  if ( unit >= tower_count (&a->tower))
++    return tower_height (&a->tower);
 +
-   return a->width * unit;
++  node = tower_get (&a->tower, unit);
 +
-   if (a->width == -1)
-     {
-       const struct tower_node *node;
-       unsigned long int node_start;
++  return  tower_node_get_level (node);
 +}
 +
 +gint
 +psppire_axis_get_unit_at_pixel (PsppireAxis *a, glong pixel)
 +{
-       if (pixel >= tower_height (&a->tower))
-       return tower_count (&a->tower);
++  const struct tower_node *node;
++  unsigned long int node_start;
 +
-       node = tower_lookup (&a->tower, pixel, &node_start);
++  if (pixel >= tower_height (&a->tower))
++    return tower_count (&a->tower);
 +
-       return tower_node_get_index (node);
-     }
++  node = tower_lookup (&a->tower, pixel, &node_start);
 +
-   return pixel / a->width;
++  return tower_node_get_index (node);
++}
 +
- psppire_axis_append (PsppireAxis *a, gint width)
++void
++psppire_axis_append (PsppireAxis *a, gint size)
++{
++  struct tower_node *new = pool_malloc (a->pool, sizeof *new);
++
++  tower_insert (&a->tower, size, new, NULL);
 +}
 +
++
++
++/* Insert a new unit of size SIZE before position POSN */
 +void
-   struct tower_node *new = g_slice_alloc0 (sizeof *new);
-   tower_insert (&a->tower, width, new, NULL);
++psppire_axis_insert (PsppireAxis *a, gint size, gint posn)
 +{
++  struct tower_node *new = pool_malloc (a->pool, sizeof *new);
++
++  struct tower_node *before = tower_get (&a->tower, posn);
++
++  tower_insert (&a->tower, size, new, before);
++}
++
++
++void
++psppire_axis_remove (PsppireAxis *a, gint posn)
++{
++  struct tower_node *node = tower_get (&a->tower, posn);
++
++  tower_delete (&a->tower, node);
++
++  pool_free (a->pool, node);
 +}
 +
 +
++void
++psppire_axis_resize_unit (PsppireAxis *a, gint size, gint posn)
++{
++  struct tower_node *node = tower_get (&a->tower, posn);
++
++  tower_resize (&a->tower, node, size);
++}
++
 +
 +
++void
++psppire_axis_clear (PsppireAxis *a)
++{
++  pool_destroy (a->pool);
++  a->pool = pool_create ();
++  tower_init (&a->tower);
++}
++
 +
index 8c362d6e11036b31f784b1d21bda348b209edf03,0000000000000000000000000000000000000000..72484773e895c88767b794887e065609440b46a6
mode 100644,000000..100644
--- /dev/null
@@@ -1,82 -1,0 +1,92 @@@
-   gint width ;
 +/* PSPPIRE - a graphical user interface for PSPP.
 +   Copyright (C) 2008  Free Software Foundation
 +
 +   This program is free software: you can redistribute it and/or modify
 +   it under the terms of the GNU General Public License as published by
 +   the Free Software Foundation, either version 3 of the License, or
 +   (at your option) any later version.
 +
 +   This program is distributed in the hope that it will be useful,
 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +   GNU General Public License for more details.
 +
 +   You should have received a copy of the GNU General Public License
 +   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 +
 +
 +#ifndef PSPPIRE_AXIS_H__
 +#define PSPPIRE_AXIS_H__
 +
 +
 +#include <glib-object.h>
 +#include <glib.h>
 +
 +#include <libpspp/tower.h>
 +
 +G_BEGIN_DECLS
 +
 +
 +/* --- type macros --- */
 +#define G_TYPE_PSPPIRE_AXIS              (psppire_axis_get_type ())
 +#define PSPPIRE_AXIS(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_PSPPIRE_AXIS, PsppireAxis))
 +#define PSPPIRE_AXIS_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_PSPPIRE_AXIS, PsppireAxisClass))
 +#define PSPPIRE_IS_AXIS(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_PSPPIRE_AXIS))
 +#define PSPPIRE_IS_AXIS_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_PSPPIRE_AXIS))
 +#define PSPPIRE_AXIS_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_PSPPIRE_AXIS, PsppireAxisClass))
 +
 +
 +
 +/* --- typedefs & structures --- */
 +typedef struct _PsppireAxis      PsppireAxis;
 +typedef struct _PsppireAxisClass PsppireAxisClass;
 +
++struct pool;
 +
 +struct _PsppireAxis
 +{
 +  GObject             parent;
- PsppireAxis*   psppire_axis_new (gint w);
 +
 +  struct tower tower;
++  struct pool *pool;
 +};
 +
 +struct _PsppireAxisClass
 +{
 +  GObjectClass parent_class;
 +
 +};
 +
 +GType          psppire_axis_get_type (void);
 +
- void psppire_axis_append (PsppireAxis *a, gint width);
++PsppireAxis*   psppire_axis_new (void);
 +
 +\f
 +/* Interface between sheet and axis */
 +
 +gint psppire_axis_unit_size (PsppireAxis *a, gint unit);
 +
 +gint psppire_axis_unit_count (PsppireAxis *a);
 +
 +glong psppire_axis_pixel_start (PsppireAxis *a, gint unit);
 +
 +gint psppire_axis_get_unit_at_pixel (PsppireAxis *a, glong pixel);
 +
 +
 +
 +/* Interface between axis and model */
 +
++void psppire_axis_clear (PsppireAxis *a);
++
++void psppire_axis_append (PsppireAxis *a, gint size);
++
++void psppire_axis_insert (PsppireAxis *a, gint size, gint posn);
++
++void psppire_axis_remove (PsppireAxis *a, gint posn);
++
++void psppire_axis_resize_unit (PsppireAxis *a, gint size, gint posn);
++
 +
 +G_END_DECLS
 +
 +#endif /* PSPPIRE_AXIS_H__ */
diff --combined src/data/dictionary.c
index caf8e2fc3490cc81968197e732b74f45a5aa14f3,caf8e2fc3490cc81968197e732b74f45a5aa14f3..02c6aa76bc5c991a2bc077ed9bc91a3e60972eea
@@@ -1352,3 -1352,3 +1352,21 @@@ dict_var_resized (const struct variabl
        d->callbacks->var_resized (d, var_get_dict_index (v), delta, d->cb_data);
      }
  }
++
++/* Called from variable.c to notify the dictionary that the variable's display width
++   has changed */
++void
++dict_var_display_width_changed (const struct variable *v)
++{
++  if ( var_has_vardict (v))
++    {
++      const struct vardict_info *vdi = var_get_vardict (v);
++      struct dictionary *d;
++
++      d = vdi->dict;
++
++      if ( d->callbacks && d->callbacks->var_display_width_changed )
++      d->callbacks->var_display_width_changed (d, var_get_dict_index (v), d->cb_data);
++    }
++}
++
diff --combined src/data/dictionary.h
index bb14f52ebef0fe7560ddab190693f75be8b6457f,bb14f52ebef0fe7560ddab190693f75be8b6457f..682409e24216a11c7492cb39082b30d62f101f19
@@@ -157,6 -157,6 +157,7 @@@ struct dict_callback
    void (*weight_changed) (struct dictionary *, int, void *);
    void (*filter_changed) (struct dictionary *, int, void *);
    void (*split_changed) (struct dictionary *, void *);
++  void (*var_display_width_changed) (struct dictionary *, int, void *);
   };
  
  void dict_set_callbacks (struct dictionary *, const struct dict_callbacks *,
diff --combined src/data/vardict.h
index 35440a0de644af2fbeb3a407d7da837fe97aca1d,35440a0de644af2fbeb3a407d7da837fe97aca1d..dfde1bffc0b3802d553c7717da47b82a4300908b
@@@ -41,5 -41,5 +41,6 @@@ void var_clear_vardict (struct variabl
  /* Called by variable.c, defined in dictionary.c. */
  void dict_var_changed (const struct variable *v);
  void dict_var_resized (const struct variable *v, int delta);
++void dict_var_display_width_changed (const struct variable *v);
  
  #endif /* data/vardict.h */
diff --combined src/data/variable.c
index d14237d925c3442e4baa8bbf9204a09044f41818,d14237d925c3442e4baa8bbf9204a09044f41818..ccbe65dc0ed9757be75091637bb346b276182d84
@@@ -778,9 -778,9 +778,15 @@@ var_get_display_width (const struct var
  
  /* Sets V's display width to DISPLAY_WIDTH. */
  void
--var_set_display_width (struct variable *v, int display_width)
++var_set_display_width (struct variable *v, int new_width)
  {
--  v->display_width = display_width;
++  int old_width = v->display_width;
++
++  v->display_width = new_width;
++
++  if ( old_width != new_width)
++    dict_var_display_width_changed (v);
++
    dict_var_changed (v);
  }
  
index fe4fcb62a5ed8b81d5035e4326fe02f41a96f44a,072e55bad3dc54e2bffe5e50d589563123faa18c..2e1dee8954aa5a59dd7d3707d19c96fcecd04eb9
@@@ -21,6 -21,7 +21,6 @@@
  #include "psppire-data-editor.h"
  #include "psppire-var-sheet.h"
  
 -#include <gtksheet/gsheet-hetero-column.h>
  #include <language/syntax-string-source.h>
  #include "psppire-data-store.h"
  #include "helper.h"
@@@ -198,6 -199,6 +198,81 @@@ enu
      PROP_SPLIT_WINDOW
    };
  
++
++#define WIDTH_OF_M 10
++
++static void
++new_variables_callback (PsppireDict *dict, gpointer data)
++{
++  gint v, i;
++  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
++
++  for (i = 0 ; i < 4 ; ++i)
++    {
++      PsppireAxis *haxis;
++      g_object_get (de->data_sheet[i], "horizontal-axis", &haxis, NULL);
++
++      psppire_axis_clear (haxis);
++
++      for (v = 0 ; v < psppire_dict_get_var_cnt (dict); ++v)
++      {
++        const struct variable *var = psppire_dict_get_variable (dict, v);
++
++        psppire_axis_append (haxis, 10 * var_get_display_width (var));
++      }
++    }
++}
++
++static void
++insert_variable_callback (PsppireDict *dict, gint x, gpointer data)
++{
++  gint i;
++  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
++
++  for (i = 0 ; i < 4 ; ++i)
++    {
++      const struct variable *var = psppire_dict_get_variable (dict, x);
++      PsppireAxis *haxis;
++      g_object_get (de->data_sheet[i], "horizontal-axis", &haxis, NULL);
++
++      psppire_axis_insert (haxis, WIDTH_OF_M * var_get_display_width (var), x);
++    }
++}
++
++
++static void
++delete_variable_callback (PsppireDict *dict, gint posn, gint x UNUSED, gint y UNUSED, gpointer data)
++{
++  gint i;
++  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
++
++  for (i = 0 ; i < 4 ; ++i)
++    {
++      PsppireAxis *haxis;
++      g_object_get (de->data_sheet[i], "horizontal-axis", &haxis, NULL);
++
++      psppire_axis_remove (haxis, posn);
++    }
++}
++
++
++static void
++rewidth_variable_callback (PsppireDict *dict, gint posn, gpointer data)
++{
++  gint i;
++  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
++
++  for (i = 0 ; i < 4 ; ++i)
++    {
++      const struct variable *var = psppire_dict_get_variable (dict, posn);
++      PsppireAxis *haxis;
++      g_object_get (de->data_sheet[i], "horizontal-axis", &haxis, NULL);
++
++      psppire_axis_resize_unit (haxis, WIDTH_OF_M * var_get_display_width (var), posn);
++    }
++}
++
++
  static void
  psppire_data_editor_set_property (GObject         *object,
                                  guint            prop_id,
        for (i = 0 ; i < 4 ; ++i )
        g_object_set (de->data_sheet[i],
                      "row-geometry", de->data_store,
 -                    "column-geometry", de->data_store,
                      "model", de->data_store,
                      NULL);
++
++      g_signal_connect (de->data_store->dict, "backend-changed",   G_CALLBACK (new_variables_callback), de);
++      g_signal_connect (de->data_store->dict, "variable-inserted", G_CALLBACK (insert_variable_callback), de);
++      g_signal_connect (de->data_store->dict, "variable-deleted",  G_CALLBACK (delete_variable_callback), de);
++      //      g_signal_connect (de->data_store->dict, "variable-changed",  G_CALLBACK (alter_variable_callback), de);
++      g_signal_connect (de->data_store->dict, "variable-display-width-changed",  G_CALLBACK (rewidth_variable_callback), de);
        break;
      case PROP_VAR_STORE:
        if ( de->var_store) g_object_unref (de->var_store);
@@@ -611,7 -613,6 +692,7 @@@ static voi
  init_sheet (PsppireDataEditor *de, int i,
            GtkAdjustment *hadj, GtkAdjustment *vadj)
  {
-   PsppireAxis *haxis = psppire_axis_new (100);
++  PsppireAxis *haxis = psppire_axis_new ();
    de->sheet_bin[i] = gtk_scrolled_window_new (hadj, vadj);
  
    de->data_sheet[i] = gtk_sheet_new (NULL, NULL, NULL);
                "shadow-type",  GTK_SHADOW_ETCHED_IN,
                NULL);
  
 +  g_object_set (de->data_sheet[i],
 +              "horizontal-axis", haxis,
 +              NULL);
 +
    gtk_container_add (GTK_CONTAINER (de->sheet_bin[i]), de->data_sheet[i]);
  
    g_signal_connect (de->data_sheet[i], "traverse",
@@@ -789,16 -786,16 +870,10 @@@ GtkWidget
  psppire_data_editor_new (PsppireVarStore *var_store,
                         PsppireDataStore *data_store)
  {
--  GtkWidget *widget;
--
--  widget =  g_object_new (PSPPIRE_DATA_EDITOR_TYPE,
--                        "var-store",  var_store,
--                        "data-store",  data_store,
--                        NULL);
--
--
--
--  return widget;
++  return  g_object_new (PSPPIRE_DATA_EDITOR_TYPE,
++                                   "var-store",  var_store,
++                                   "data-store",  data_store,
++                                   NULL);
  }
  
  
index e6f1373a54d969ed76de022e0135924ace674c8c,e6f1373a54d969ed76de022e0135924ace674c8c..8f7fed618fcedbfd8e8d4463eca07dff111ee2c5
  #include "helper.h"
  #include "message-dialog.h"
  
--/* --- prototypes --- */
--static void psppire_dict_class_init   (PsppireDictClass       *class);
--static void psppire_dict_init (PsppireDict            *dict);
--static void psppire_dict_finalize     (GObject                *object);
--
--static void dictionary_tree_model_init (GtkTreeModelIface *iface);
--
--
--/* --- variables --- */
--static GObjectClass     *parent_class = NULL;
  
  enum  {
    BACKEND_CHANGED,
@@@ -48,6 -48,6 +38,7 @@@
    VARIABLE_RESIZED,
    VARIABLE_INSERTED,
    VARIABLE_DELETED,
++  VARIABLE_DISPLAY_WIDTH_CHANGED,
  
    WEIGHT_CHANGED,
    FILTER_CHANGED,
    n_SIGNALS
  };
  
++
++/* --- prototypes --- */
++static void psppire_dict_class_init   (PsppireDictClass       *class);
++static void psppire_dict_init (PsppireDict            *dict);
++static void psppire_dict_finalize     (GObject                *object);
++
++static void dictionary_tree_model_init (GtkTreeModelIface *iface);
++
++
++/* --- variables --- */
++static GObjectClass     *parent_class = NULL;
++
  static guint signals [n_SIGNALS];
  
  /* --- functions --- */
@@@ -93,8 -93,8 +96,6 @@@ psppire_dict_get_type (void
  
        g_type_add_interface_static (object_type, GTK_TYPE_TREE_MODEL,
                                   &tree_model_info);
--
--
      }
  
    return object_type;
@@@ -172,6 -172,6 +173,17 @@@ psppire_dict_class_init (PsppireDictCla
                  G_TYPE_INT,
                  G_TYPE_INT);
  
++  signals [VARIABLE_DISPLAY_WIDTH_CHANGED] =
++    g_signal_new ("variable-display-width-changed",
++                G_TYPE_FROM_CLASS (class),
++                G_SIGNAL_RUN_FIRST,
++                0,
++                NULL, NULL,
++                g_cclosure_marshal_VOID__INT,
++                G_TYPE_NONE,
++                1,
++                G_TYPE_INT);
++
  
    signals [WEIGHT_CHANGED] =
      g_signal_new ("weight-changed",
@@@ -223,7 -223,7 +235,10 @@@ psppire_dict_finalize (GObject *object
  static void
  addcb (struct dictionary *d, int idx, void *pd)
  {
--  g_signal_emit (pd, signals [VARIABLE_INSERTED], 0, idx);
++  PsppireDict *dict = PSPPIRE_DICT (pd);
++
++  if ( ! dict->disable_insert_signal)
++    g_signal_emit (dict, signals [VARIABLE_INSERTED], 0, idx);
  }
  
  static void
@@@ -264,6 -264,6 +279,13 @@@ split_changed_callback (struct dictiona
    g_signal_emit (pd, signals [SPLIT_CHANGED], 0);
  }
  
++static void
++variable_display_width_callback (struct dictionary *d, int idx, void *pd)
++{
++  g_signal_emit (pd, signals [VARIABLE_DISPLAY_WIDTH_CHANGED], 0, idx);
++}
++
++
  
  static const struct dict_callbacks gui_callbacks =
    {
      resize_cb,
      weight_changed_callback,
      filter_changed_callback,
--    split_changed_callback
++    split_changed_callback,
++    variable_display_width_callback
    };
  
  static void
  psppire_dict_init (PsppireDict *psppire_dict)
  {
    psppire_dict->stamp = g_random_int ();
++  psppire_dict->disable_insert_signal = FALSE;
  }
  
  /**
@@@ -349,9 -349,9 +373,15 @@@ psppire_dict_insert_variable (PsppireDi
    if ( ! name )
      name = auto_generate_var_name (d);
  
++  d->disable_insert_signal = TRUE;
++
    var = dict_create_var (d->dict, name, 0);
  
    dict_reorder_var (d->dict, var, idx);
++
++  d->disable_insert_signal = FALSE;
++
++  g_signal_emit (d, signals[VARIABLE_INSERTED], 0, idx);
  }
  
  /* Delete N variables beginning at FIRST */
index 1bf8bd3523b849aac1c2918f2794895c088714af,1bf8bd3523b849aac1c2918f2794895c088714af..534f0707ea22df8bc6084a1d8193c917d4ae0e0a
@@@ -38,7 -38,7 +38,6 @@@ G_BEGIN_DECL
  #define PSPPIRE_DICT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_PSPPIRE_DICT, PsppireDictClass))
  
  
--
  /* --- typedefs & structures --- */
  typedef struct _PsppireDict      PsppireDict;
  typedef struct _PsppireDictClass PsppireDictClass;
@@@ -50,6 -50,6 +49,7 @@@ struct _PsppireDic
    GObject             parent;
    struct dictionary *dict;
  
++  gboolean disable_insert_signal;
    /* For GtkTreeModelIface */
    gint stamp;
  };
index 5406949108968a467a6b1686b73d93eda5f07dc3,0708bf3e047f8c416ce0d2cc6500a7ad75282520..033652025a870812214b84dcf630702cb04942a2
@@@ -19,7 -19,7 +19,7 @@@
  
  #include <glade/glade.h>
  #include "helper.h"
 -#include <gtksheet/gsheet-hetero-column.h>
 +
  #include "customentry.h"
  #include <data/variable.h>
  #include "psppire-var-store.h"
@@@ -95,6 -95,20 +95,6 @@@ struct column_parameter
    gint width ;
  };
  
 -static const struct column_parameters column_def[] = {
 -  { N_("Name"),    80},
 -  { N_("Type"),    100},
 -  { N_("Width"),   57},
 -  { N_("Decimals"),91},
 -  { N_("Label"),   95},
 -  { N_("Values"),  103},
 -  { N_("Missing"), 95},
 -  { N_("Columns"), 80},
 -  { N_("Align"),   69},
 -  { N_("Measure"), 99},
 -};
 -
 -
  #define n_ALIGNMENTS 3
  
  const gchar *const alignments[n_ALIGNMENTS + 1]={
@@@ -488,7 -502,8 +488,7 @@@ var_sheet_change_active_cell (PsppireVa
  static void
  psppire_var_sheet_init (PsppireVarSheet *vs)
  {
 -  gint i;
 -  GObject *geo = g_sheet_hetero_column_new (75, PSPPIRE_VAR_STORE_n_COLS);
 +  // gint i;
    GladeXML *xml = XML_NEW ("data-editor.glade");
  
    vs->val_labs_dialog = val_labs_dialog_create (xml);
    vs->dispose_has_run = FALSE;
    vs->may_create_vars = TRUE;
  
 +#if 0
    for (i = 0 ; i < PSPPIRE_VAR_STORE_n_COLS ; ++i )
      {
 -      g_sheet_hetero_column_set_button_label (G_SHEET_HETERO_COLUMN (geo), i,
 -                                            gettext (column_def[i].label));
 -
        g_sheet_hetero_column_set_width (G_SHEET_HETERO_COLUMN (geo), i,
                                       column_def[i].width);
      }
 -
 -  g_object_set (vs, "column-geometry", geo, NULL);
 +#endif
  
    g_signal_connect (vs, "activate",
                    G_CALLBACK (var_sheet_change_active_cell),
  }
  
  
 +static const struct column_parameters column_def[] = {
 +  { N_("Name"),    80},
 +  { N_("Type"),    100},
 +  { N_("Width"),   57},
 +  { N_("Decimals"),91},
 +  { N_("Label"),   95},
 +  { N_("Values"),  103},
 +  { N_("Missing"), 95},
 +  { N_("Columns"), 80},
 +  { N_("Align"),   69},
 +  { N_("Measure"), 99},
 +};
 +
  GtkWidget*
  psppire_var_sheet_new (void)
  {
 -  return GTK_WIDGET (g_object_new (psppire_var_sheet_get_type (), NULL));
 +  gint i;
-   PsppireAxis *a = psppire_axis_new (-1);
++  PsppireAxis *a = psppire_axis_new ();
 +  GtkWidget *w = g_object_new (psppire_var_sheet_get_type (), NULL);
 +
 +  for (i = 0 ; i < 10 ; ++i)
 +    psppire_axis_append (a, column_def[i].width);
 +
 +  g_object_set (w,
 +              "horizontal-axis", a,
 +              NULL);
 +
 +  return w;
  }