Merge branch 'rewrite-sheet' of ssh://jmd@git.sv.gnu.org/srv/git/pspp into rewrite...
[pspp-builds.git] / lib / gtksheet / gtksheet.c
index f7ca3c28457cc6b14607f782da05b9de2955f144..8b25902c3b1cc2421c2e5e101b9dbeb77bc7aff8 100644 (file)
@@ -87,9 +87,9 @@ enum
 #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 @@ dispose_string (const GtkSheet *sheet, gchar *text)
     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 @@ max_fully_visible_row (const GtkSheet *sheet)
   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--;
@@ -185,26 +169,11 @@ max_fully_visible_row (const GtkSheet *sheet)
 }
 
 
-/* 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);
 }
 
 
@@ -221,7 +190,7 @@ min_fully_visible_column (const GtkSheet *sheet)
 {
   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;
@@ -243,9 +212,9 @@ max_fully_visible_column (const GtkSheet *sheet)
 {
   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--;
 
@@ -320,9 +289,9 @@ POSSIBLE_DRAG (const GtkSheet *sheet, gint x, gint y,
   *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)
@@ -343,14 +312,14 @@ POSSIBLE_DRAG (const GtkSheet *sheet, gint x, gint y,
       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;
@@ -372,8 +341,8 @@ POSSIBLE_RESIZE (const GtkSheet *sheet, gint x, gint y,
        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);
@@ -382,7 +351,7 @@ POSSIBLE_RESIZE (const GtkSheet *sheet, gint x, gint y,
     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);
@@ -400,7 +369,7 @@ rectangle_from_range (GtkSheet *sheet, const GtkSheetRange *range,
 {
   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)
@@ -413,9 +382,9 @@ rectangle_from_range (GtkSheet *sheet, const GtkSheetRange *range,
   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) +
@@ -706,15 +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
   };
 
@@ -729,13 +695,15 @@ gtk_sheet_set_row_geometry (GtkSheet *sheet, GSheetRow *geo)
 }
 
 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);
 }
 
 
@@ -753,11 +721,8 @@ gtk_sheet_set_property (GObject         *object,
     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));
-      if ( sheet->column_geometry)
-       g_signal_connect (sheet->column_geometry, "columns_changed",
-                         G_CALLBACK (column_titles_changed), sheet);
+    case PROP_HAXIS:
+      gtk_sheet_set_horizontal_axis (sheet, g_value_get_pointer (value));
       break;
     case PROP_MODEL:
       gtk_sheet_set_model (sheet, g_value_get_pointer (value));
@@ -781,8 +746,8 @@ gtk_sheet_get_property (GObject         *object,
     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);
@@ -800,7 +765,7 @@ gtk_sheet_class_init (GtkSheetClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   GParamSpec *row_geo_spec ;
-  GParamSpec *col_geo_spec ;
+  GParamSpec *haxis_spec ;
   GParamSpec *model_spec ;
 
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
@@ -1009,10 +974,10 @@ gtk_sheet_class_init (GtkSheetClass *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 =
@@ -1030,8 +995,8 @@ gtk_sheet_class_init (GtkSheetClass *klass)
                                    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,
@@ -1070,7 +1035,7 @@ static void
 gtk_sheet_init (GtkSheet *sheet)
 {
   sheet->model = NULL;
-  sheet->column_geometry = NULL;
+  sheet->haxis = NULL;
   sheet->row_geometry = NULL;
 
   sheet->flags = 0;
@@ -1149,7 +1114,6 @@ columns_inserted_deleted_callback (GSheetModel *model, gint first_column,
                                   gint n_columns,
                                   gpointer data)
 {
-  gint i;
   GtkSheet *sheet = GTK_SHEET (data);
 
   GtkSheetRange range;
@@ -1161,7 +1125,7 @@ columns_inserted_deleted_callback (GSheetModel *model, gint first_column,
    */
   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);
@@ -1169,8 +1133,8 @@ columns_inserted_deleted_callback (GSheetModel *model, gint first_column,
   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);
 }
@@ -1181,7 +1145,6 @@ static void
 rows_inserted_deleted_callback (GSheetModel *model, gint first_row,
                                gint n_rows, gpointer data)
 {
-  gint i;
   GtkSheet *sheet = GTK_SHEET (data);
 
   GtkSheetRange range;
@@ -1194,15 +1157,14 @@ rows_inserted_deleted_callback (GSheetModel *model, gint first_row,
   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);
 }
@@ -1236,16 +1198,14 @@ range_update_callback (GSheetModel *m, gint row0, gint col0,
 
   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;
     }
@@ -1276,11 +1236,10 @@ range_update_callback (GSheetModel *m, gint row0, gint col0,
  * Returns: the new sheet widget
  */
 GtkWidget *
-gtk_sheet_new (GSheetRow *vgeo, GSheetColumn *hgeo, GSheetModel *model)
+gtk_sheet_new (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;
@@ -1326,27 +1285,6 @@ gtk_sheet_set_model (GtkSheet *sheet, GSheetModel *model)
 }
 
 
-/* Call back for when the column titles have changed.
-   FIRST is the first column changed.
-   N_COLUMNS is the number of columns which have changed, or -1, which
-   indicates that the column has changed to its right-most extremity
-*/
-static void
-column_titles_changed (GtkWidget *w, gint first, gint n_columns, gpointer data)
-{
-  GtkSheet *sheet = GTK_SHEET (data);
-  gboolean extremity = FALSE;
-
-  if ( n_columns == -1 )
-    {
-      extremity = TRUE;
-      n_columns = g_sheet_column_get_column_count (sheet->column_geometry) - 1 ;
-    }
-
-  if ( extremity)
-    gtk_sheet_column_title_button_draw (sheet, -1);
-}
-
 void
 gtk_sheet_change_entry (GtkSheet *sheet, GtkType entry_type)
 {
@@ -1399,7 +1337,7 @@ gtk_sheet_get_columns_count (GtkSheet *sheet)
   g_return_val_if_fail (sheet != NULL, 0);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
 
-  return g_sheet_column_get_column_count (sheet->column_geometry);
+  return psppire_axis_unit_count (sheet->haxis);
 }
 
 static void
@@ -1408,42 +1346,6 @@ gtk_sheet_set_column_width (GtkSheet *sheet,
                            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 >= g_sheet_column_get_column_count (sheet->column_geometry) || 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 > g_sheet_column_get_width (sheet->column_geometry, column) )
-    {
-      gtk_sheet_set_column_width (sheet, column, text_width);
-    }
-}
-
 void
 gtk_sheet_show_column_titles (GtkSheet *sheet)
 {
@@ -1565,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));
 
@@ -1582,7 +1484,7 @@ gtk_sheet_moveto (GtkSheet *sheet,
 
   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);
   }
@@ -1625,7 +1527,7 @@ gtk_sheet_select_row (GtkSheet *sheet, gint row)
   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;
 
@@ -1640,7 +1542,7 @@ gtk_sheet_select_column (GtkSheet *sheet, gint column)
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  if (column < 0 || column >= 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)
@@ -1673,10 +1575,10 @@ gtk_sheet_range_isvisible (const GtkSheet *sheet,
   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))
@@ -1781,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;
@@ -2155,7 +2057,7 @@ gtk_sheet_cell_draw (GtkSheet *sheet, gint row, gint col)
     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);
@@ -2355,16 +2257,11 @@ gtk_sheet_range_draw_selection (GtkSheet *sheet, GtkSheetRange range)
   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);
 }
@@ -2380,7 +2277,7 @@ gtk_sheet_set_cell (GtkSheet *sheet, gint row, gint col,
   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;
 
@@ -2390,6 +2287,9 @@ gtk_sheet_set_cell (GtkSheet *sheet, gint row, gint col,
 
   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);
 }
@@ -2402,7 +2302,7 @@ gtk_sheet_cell_clear (GtkSheet *sheet, gint row, gint column)
 
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
-  if (column >= 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;
@@ -2439,7 +2339,7 @@ gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col)
   g_return_val_if_fail (sheet != NULL, NULL);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), NULL);
 
-  if (col >= 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;
 
@@ -2460,7 +2360,7 @@ gtk_sheet_cell_get_state (GtkSheet *sheet, gint row, gint col)
 
   g_return_val_if_fail (sheet != NULL, 0);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
-  if (col >= 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;
@@ -2543,7 +2443,7 @@ gtk_sheet_get_pixel_info (GtkSheet *sheet,
   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;
     }
 
@@ -2561,14 +2461,14 @@ gtk_sheet_get_cell_area (GtkSheet *sheet,
   g_return_val_if_fail (sheet != NULL, 0);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
 
-  if (row >= 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);
@@ -2587,7 +2487,7 @@ gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint col)
 
   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;
@@ -2642,6 +2542,8 @@ gtk_sheet_entry_changed (GtkWidget *widget, gpointer data)
 
   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);
@@ -2696,7 +2598,7 @@ change_active_cell (GtkSheet *sheet, gint row, gint col)
     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)
@@ -2795,7 +2697,6 @@ gtk_sheet_show_active_cell (GtkSheet *sheet)
   gtk_widget_grab_focus (GTK_WIDGET (sheet_entry));
 
   dispose_string (sheet, text);
-
 }
 
 static void
@@ -2880,10 +2781,10 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
 
              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)
@@ -2901,10 +2802,10 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
 
                  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);
 
@@ -2944,9 +2845,9 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
          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)
@@ -2979,9 +2880,9 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
              (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)
@@ -3025,9 +2926,9 @@ gtk_sheet_new_selection (GtkSheet *sheet, GtkSheetRange *range)
          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,
@@ -3214,19 +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));
     }
 
 
@@ -3319,7 +3218,7 @@ gtk_sheet_button_press (GtkWidget *widget,
                     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,
@@ -3361,12 +3260,6 @@ gtk_sheet_button_press (GtkWidget *widget,
       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,
@@ -3492,7 +3385,7 @@ gtk_sheet_button_press (GtkWidget *widget,
 
       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));
@@ -3532,7 +3425,7 @@ gtk_sheet_click_cell (GtkSheet *sheet, gint row, gint column)
   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;
     }
@@ -3572,7 +3465,7 @@ gtk_sheet_click_cell (GtkSheet *sheet, gint row, gint column)
       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);
@@ -3843,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);
@@ -3853,10 +3744,8 @@ motion_timeout_callback (gpointer data)
 
       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);
 
@@ -4054,7 +3943,7 @@ gtk_sheet_motion (GtkWidget *widget,  GdkEventMotion *event)
       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;
@@ -4076,7 +3965,7 @@ gtk_sheet_motion (GtkWidget *widget,  GdkEventMotion *event)
       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);
@@ -4086,8 +3975,8 @@ gtk_sheet_motion (GtkWidget *widget,  GdkEventMotion *event)
 
       /*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)
@@ -4123,7 +4012,7 @@ gtk_sheet_motion (GtkWidget *widget,  GdkEventMotion *event)
        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;
@@ -4191,7 +4080,7 @@ gtk_sheet_extend_selection (GtkSheet *sheet, gint row, gint column)
   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;
@@ -4316,7 +4205,7 @@ step_sheet (GtkSheet *sheet, GtkScrollType dir)
                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,
@@ -4331,7 +4220,7 @@ step_sheet (GtkSheet *sheet, GtkScrollType dir)
   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;
 
@@ -4341,7 +4230,7 @@ step_sheet (GtkSheet *sheet, GtkScrollType dir)
   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,
@@ -4524,9 +4413,6 @@ gtk_sheet_size_allocate (GtkWidget *widget,
                            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;
@@ -4546,10 +4432,6 @@ gtk_sheet_size_allocate (GtkWidget *widget,
                            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);
 }
@@ -4557,7 +4439,6 @@ gtk_sheet_size_allocate (GtkWidget *widget,
 static void
 draw_column_title_buttons (GtkSheet *sheet)
 {
-  gint i;
   gint x, width;
 
   if (!sheet->column_titles_visible) return;
@@ -4584,7 +4465,7 @@ draw_column_title_buttons (GtkSheet *sheet)
     }
 
   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,
@@ -4594,14 +4475,13 @@ draw_column_title_buttons (GtkSheet *sheet)
 
   size_allocate_global_button (sheet);
 
-  for (i = min_visible_column (sheet); i <= max_visible_column (sheet); i++)
-    gtk_sheet_column_title_button_draw (sheet, i);
+  draw_column_title_buttons_range (sheet, min_visible_column (sheet), 
+                                  max_visible_column (sheet));
 }
 
 static void
 draw_row_title_buttons (GtkSheet *sheet)
 {
-  gint i;
   gint y = 0;
   gint height;
 
@@ -4637,12 +4517,9 @@ draw_row_title_buttons (GtkSheet *sheet)
 
   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));
 }
 
 
@@ -4798,7 +4675,7 @@ gtk_sheet_get_entry_widget (GtkSheet *sheet)
 
 
 static void
-gtk_sheet_button_draw (GtkSheet *sheet, GdkWindow *window,
+draw_button (GtkSheet *sheet, GdkWindow *window,
                       GtkSheetButton *button, gboolean is_sensitive,
                       GdkRectangle allocation)
 {
@@ -4809,8 +4686,6 @@ gtk_sheet_button_draw (GtkSheet *sheet, GdkWindow *window,
   gboolean rtl ;
 
   gint state = 0;
-  gint len = 0;
-  gchar *line = 0;
 
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (button != NULL);
@@ -4847,8 +4722,7 @@ gtk_sheet_button_draw (GtkSheet *sheet, GdkWindow *window,
 
   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],
@@ -4858,68 +4732,46 @@ gtk_sheet_button_draw (GtkSheet *sheet, GdkWindow *window,
 
       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],
@@ -4931,60 +4783,90 @@ gtk_sheet_button_draw (GtkSheet *sheet, GdkWindow *window,
   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_column_get_button (sheet->column_geometry, column);
-  allocation.y = 0;
-  allocation.x = g_sheet_column_start_pixel (sheet->column_geometry, 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 = g_sheet_column_get_width (sheet->column_geometry, column);
-  is_sensitive = g_sheet_column_get_sensitivity (sheet->column_geometry, 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_model_get_column_button (sheet->model, col);
+      allocation.y = 0;
+      allocation.x = psppire_axis_pixel_start (sheet->haxis, col)
+       + CELL_SPACING;
+      allocation.x -= sheet->hadjustment->value;
+
+      allocation.height = sheet->column_title_area.height;
+      allocation.width = psppire_axis_unit_size (sheet->haxis, col);
+      is_sensitive = g_sheet_model_get_column_sensitivity (sheet->model, col);
+
+      draw_button (sheet, sheet->column_title_window,
+                  button, is_sensitive, allocation);
+    }
+
+  gdk_window_end_paint (sheet->column_title_window);
 }
 
 
 static void
-gtk_sheet_row_title_button_draw (GtkSheet *sheet, gint row)
+draw_row_title_buttons_range (GtkSheet *sheet, gint first, gint last)
 {
-  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));
 
-  gtk_sheet_button_draw (sheet, sheet->row_title_window,
-                        button, is_sensitive, allocation);
+  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);
+    }
+
+  gdk_window_end_paint (sheet->row_title_window);
 }
 
 /* SCROLLBARS
@@ -5044,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;
@@ -5164,10 +5046,10 @@ draw_xor_rectangle (GtkSheet *sheet, GtkSheetRange range)
   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);
 
@@ -5222,7 +5104,7 @@ draw_xor_rectangle (GtkSheet *sheet, GtkSheetRange range)
 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;
@@ -5233,7 +5115,9 @@ new_column_width (GtkSheet *sheet, gint column, gint *x)
       *x = left_pos + width;
     }
 
+#if AXIS_TRANSITION
   g_sheet_column_set_width (sheet->column_geometry, column, width);
+#endif
 
   draw_column_title_buttons (sheet);
 
@@ -5281,13 +5165,15 @@ gtk_sheet_set_column_width (GtkSheet *sheet,
   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)))
     {
@@ -5374,7 +5260,7 @@ gtk_sheet_get_attributes (const GtkSheet *sheet, gint row, gint col,
     }
 
   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)
@@ -5434,7 +5320,7 @@ gtk_sheet_column_size_request (GtkSheet *sheet,
 {
   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,
@@ -5498,7 +5384,6 @@ gtk_sheet_button_free (GtkSheetButton *button)
   g_free (button);
 }
 
-
 static void
 append_cell_text (GString *string, const GtkSheet *sheet, gint r, gint c)
 {