Internationalisation.
[pspp-builds.git] / lib / gtksheet / gtksheet.c
index 7f5acedf4cfe3f0905cc063148fb3b048a7d0419..6d47cfb9943ce05bf23f9841cf3146a258b4a2b1 100644 (file)
@@ -1,4 +1,4 @@
-/* This version of GtkSheet has been heavily modified, for the specific 
+/* This version of GtkSheet has been *heavily* modified, for the specific 
    requirements of PSPPIRE. */
 
 /* GtkSheet widget for Gtk+.
@@ -79,6 +79,9 @@ enum
 #define GTK_SHEET_SET_FLAGS(sheet,flag)    (GTK_SHEET_FLAGS (sheet) |= (flag))
 #define GTK_SHEET_UNSET_FLAGS(sheet,flag)  (GTK_SHEET_FLAGS (sheet) &= ~(flag))
 
+#define GTK_SHEET_IS_LOCKED(sheet)   (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_LOCKED)
+
+
 #define GTK_SHEET_IS_FROZEN(sheet)   (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IS_FROZEN)
 #define GTK_SHEET_IN_XDRAG(sheet)    (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_XDRAG)
 #define GTK_SHEET_IN_YDRAG(sheet)    (GTK_SHEET_FLAGS (sheet) & GTK_SHEET_IN_YDRAG)
@@ -102,7 +105,19 @@ enum
 
 
 
+static gboolean gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col);
+
+static inline
+void dispose_string (const GtkSheet *sheet, gchar *text)
+{
+  GSheetModel *model  = gtk_sheet_get_model(sheet);
+
+  if ( ! model ) 
+    return;
 
+  if (g_sheet_model_free_strings(model))
+    g_free(text);
+}
 
 static inline 
 guint DEFAULT_ROW_HEIGHT(GtkWidget *widget) 
@@ -246,7 +261,7 @@ ROW_FROM_YPIXEL(GtkSheet *sheet, gint y)
   return (yyy_row_ypixel_to_row(sheet, y));
 }
 
-static inline const GtkSheetButton *
+static inline GtkSheetButton *
 xxx_column_button(GtkSheet *sheet, gint col)
 {
   GSheetColumn *col_geo = sheet->column_geometry;
@@ -394,7 +409,7 @@ static inline gint SHEET_HEIGHT(GtkSheet *sheet)
 }
 
 
-static inline const GtkSheetButton *
+static inline GtkSheetButton *
 yyy_row_button(GtkSheet *sheet, gint row)
 {
   GSheetRow *row_geo = sheet->row_geometry;
@@ -706,7 +721,7 @@ static void gtk_sheet_button_size_request   (GtkSheet *sheet,
                                                 GtkRequisition *requisition);
 
 /* Attributes routines */
-static void init_attributes                    (GtkSheet *sheet, gint col,  
+static void init_attributes                    (const GtkSheet *sheet, gint col,  
                                                 GtkSheetCellAttr *attributes);
 
 
@@ -1123,20 +1138,51 @@ gtk_sheet_init (GtkSheet *sheet)
 }
 
 
+/* Callback which occurs whenever columns are inserted/deleted in the model */
 static void 
-rows_deleted_callback (GSheetModel *m, gint first_row, gint n_rows,
+columns_inserted_deleted_callback (GSheetModel *model, gint first_column, gint n_columns,
                      gpointer data)
 {
   GtkSheet *sheet = GTK_SHEET(data);
 
   GtkSheetRange range;
+  gint model_columns = g_sheet_model_get_column_count(model);
+
+
+  /* Need to update all the columns starting from the first column and onwards.
+   * Previous column are unchanged, so don't need to be updated.
+   */
+  range.col0 = first_column;
+  range.row0 = 0;
+  range.coli = xxx_column_count(sheet) - 1;
+  range.rowi = yyy_row_count(sheet) - 1;
+
+  if (sheet->active_cell.col >= model_columns)
+    gtk_sheet_activate_cell(sheet, sheet->active_cell.row, model_columns - 1);
+  
+  gtk_sheet_range_draw(sheet, &range);
+}
+
 
+/* Callback which occurs whenever rows are inserted/deleted in the model */
+static void 
+rows_inserted_deleted_callback (GSheetModel *m, gint first_row, gint n_rows,
+                     gpointer data)
+{
+  GtkSheet *sheet = GTK_SHEET(data);
+
+  GtkSheetRange range;
+
+  /* Need to update all the rows starting from the first row and onwards.
+   * Previous rows are unchanged, so don't need to be updated.
+   */
   range.row0 = first_row;
   range.col0 = 0;
   range.rowi = yyy_row_count(sheet) - 1;
   range.coli = xxx_column_count(sheet) - 1;
   
   gtk_sheet_range_draw(sheet, &range);
+
 }
 
 /* 
@@ -1230,8 +1276,17 @@ gtk_sheet_set_model(GtkSheet *sheet, GSheetModel *model)
   g_signal_connect(model, "range_changed", 
                   G_CALLBACK(range_update_callback), sheet);
 
+  g_signal_connect(model, "rows_inserted",
+                  G_CALLBACK(rows_inserted_deleted_callback), sheet);
+
   g_signal_connect(model, "rows_deleted",
-                  G_CALLBACK(rows_deleted_callback), sheet);
+                  G_CALLBACK(rows_inserted_deleted_callback), sheet);
+
+  g_signal_connect(model, "columns_inserted",
+                  G_CALLBACK(columns_inserted_deleted_callback), sheet);
+
+  g_signal_connect(model, "columns_deleted",
+                  G_CALLBACK(columns_inserted_deleted_callback), sheet);
 
 }
 
@@ -1275,7 +1330,6 @@ gtk_sheet_construct (GtkSheet *sheet,
   sheet->column_titles_visible = TRUE;
   sheet->autoscroll = TRUE;
   sheet->justify_entry = TRUE;
-  sheet->locked = FALSE;
 
 
   /* create sheet entry */
@@ -1481,22 +1535,23 @@ gtk_sheet_autoresize_column (GtkSheet *sheet, gint column)
   g_return_if_fail (GTK_IS_SHEET (sheet));
   if (column >= xxx_column_count(sheet) || column < 0) return;
 
-  g_print("%s:%d Iterating rows\n",__FILE__, __LINE__);
-  for (row = 0; row < yyy_row_count(sheet); row++){
-    const gchar *text = gtk_sheet_cell_get_text(sheet, row, column);
-    if (text && strlen(text) > 0){
-      GtkSheetCellAttr attributes;
-
-      gtk_sheet_get_attributes(sheet, row, column, &attributes);
-      if(attributes.is_visible){
-        gint width = STRING_WIDTH(GTK_WIDGET(sheet),
-                                  attributes.font_desc,
-                                 text)
-                   + 2*CELLOFFSET + attributes.border.width;
-        text_width = MAX (text_width, width);
+  for (row = 0; row < yyy_row_count(sheet); row++)
+    {
+      gchar *text = gtk_sheet_cell_get_text(sheet, row, column);
+      if (text && strlen(text) > 0){
+       GtkSheetCellAttr attributes;
+
+       gtk_sheet_get_attributes(sheet, row, column, &attributes);
+       if(attributes.is_visible){
+         gint width = STRING_WIDTH(GTK_WIDGET(sheet),
+                                   attributes.font_desc,
+                                   text)
+           + 2*CELLOFFSET + attributes.border.width;
+         text_width = MAX (text_width, width);
+       }
       }
+      dispose_string(sheet, text);
     }
-  }
 
   if(text_width > xxx_column_width(sheet, column) )
     {
@@ -1566,16 +1621,33 @@ gtk_sheet_set_locked             (GtkSheet *sheet, gboolean locked)
   g_return_if_fail (sheet != NULL);
   g_return_if_fail (GTK_IS_SHEET (sheet));
 
-  sheet->locked = locked;
+  if ( locked ) 
+    {
+      GTK_SHEET_SET_FLAGS(sheet,GTK_SHEET_IS_LOCKED);
+      gtk_widget_hide(sheet->sheet_entry);
+      gtk_widget_unmap(sheet->sheet_entry);
+    }
+  else
+    {
+      GTK_SHEET_UNSET_FLAGS(sheet,GTK_SHEET_IS_LOCKED);
+      if (GTK_WIDGET_MAPPED(GTK_WIDGET(sheet)))
+       {
+         gtk_widget_show (sheet->sheet_entry);
+         gtk_widget_map (sheet->sheet_entry);
+       }
+    }
+
+  gtk_entry_set_editable(GTK_ENTRY(sheet->sheet_entry), locked);
+
 }
 
 gboolean
-gtk_sheet_locked                    (GtkSheet *sheet)
+gtk_sheet_locked                    (const GtkSheet *sheet)
 {
   g_return_val_if_fail (sheet != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
 
-  return sheet->locked;
+  return GTK_SHEET_IS_LOCKED(sheet);
 }
 
 /* This routine has problems with gtk+-1.2 related with the
@@ -1736,10 +1808,11 @@ gtk_sheet_show_column_titles(GtkSheet *sheet)
       col <= MAX_VISIBLE_COLUMN(sheet); 
       col++)
     {
-      const GtkSheetButton *button = xxx_column_button(sheet, col);
+      GtkSheetButton *button = xxx_column_button(sheet, col);
       GtkSheetChild *child = button->child;
       if(child)
         gtk_sheet_child_show(child);
+      gtk_sheet_button_free(button);
     }
   adjust_scrollbars(sheet);
  } 
@@ -1810,10 +1883,11 @@ gtk_sheet_hide_column_titles(GtkSheet *sheet)
       col <= MAX_VISIBLE_COLUMN(sheet); 
       col++)
     {
-      const GtkSheetButton *button = xxx_column_button(sheet, col);
+      GtkSheetButton *button = xxx_column_button(sheet, col);
       GtkSheetChild *child = button->child;
       if(child)
         gtk_sheet_child_hide(child);
+      gtk_sheet_button_free(button);
   }
   adjust_scrollbars(sheet);
  }
@@ -2776,7 +2850,7 @@ gtk_sheet_unrealize (GtkWidget * widget)
   gdk_window_destroy (sheet->row_title_window);
 
   if (sheet->pixmap){
-    g_free (sheet->pixmap);
+    g_object_unref(sheet->pixmap);
     sheet->pixmap = NULL;
   }
 
@@ -2822,10 +2896,14 @@ gtk_sheet_map (GtkWidget * widget)
            gdk_window_show (sheet->row_title_window);
       }
 
-      if(!GTK_WIDGET_MAPPED (sheet->sheet_entry)){
-                 gtk_widget_show (sheet->sheet_entry);
-                 gtk_widget_map (sheet->sheet_entry);
-      }
+      if(!GTK_WIDGET_MAPPED (sheet->sheet_entry)
+        && ! gtk_sheet_locked(sheet)
+        && sheet->active_cell.row  >=0
+        && sheet->active_cell.col  >=0 )
+       {
+         gtk_widget_show (sheet->sheet_entry);
+         gtk_widget_map (sheet->sheet_entry);
+       }
 
       if (GTK_WIDGET_VISIBLE (sheet->button) &&
          !GTK_WIDGET_MAPPED (sheet->button)){
@@ -3048,7 +3126,7 @@ gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
   PangoContext *context = gtk_widget_get_pango_context(GTK_WIDGET(sheet)); 
   gint ascent, descent, y_pos;
 
-  const gchar *label;
+  gchar *label;
 
   g_return_if_fail (sheet != NULL);
 
@@ -3085,6 +3163,7 @@ gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
   clip_area = area;
 
   layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), label);
+  dispose_string(sheet, label);
   pango_layout_set_font_description (layout, attributes.font_desc);
 
   pango_layout_get_pixel_extents (layout, NULL, &rect);
@@ -3124,7 +3203,7 @@ gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
           area.x+=area.width;
           if(!gtk_sheet_clip_text(sheet)){          
            for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
-             if(gtk_sheet_cell_get_text(sheet, row, i)) break;
+             if( !gtk_sheet_cell_empty(sheet, row, i)) break;
              if(size>=text_width+CELLOFFSET) break;
              size+=xxx_column_width(sheet, i);
             xxx_column_set_right_column(sheet, i, 
@@ -3143,7 +3222,7 @@ gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
          area.x+=area.width/2;
           if(!gtk_sheet_clip_text(sheet)){          
            for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
-             if(gtk_sheet_cell_get_text(sheet, row, i)) break;
+             if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
              if(sizer>=text_width/2) break;
              sizer+= xxx_column_width(sheet, i);
             xxx_column_set_left_column(sheet, i, 
@@ -3152,7 +3231,7 @@ gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
                                            xxx_column_left_column(sheet, i)));
            }
            for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
-             if(gtk_sheet_cell_get_text(sheet, row, i)) break;
+             if( ! gtk_sheet_cell_empty(sheet, row, i)) break;
              if(sizel>=text_width/2) break;
              sizel+=xxx_column_width(sheet, i);
             xxx_column_set_right_column(sheet, i, 
@@ -3170,7 +3249,7 @@ gtk_sheet_cell_draw_label (GtkSheet *sheet, gint row, gint col)
           size=area.width;
           if(!gtk_sheet_clip_text(sheet)){          
            for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
-             if(gtk_sheet_cell_get_text(sheet, row, i)) break;
+             if(! gtk_sheet_cell_empty(sheet, row, i)) break;
              if(size>=text_width+CELLOFFSET) break;
              size+=xxx_column_width(sheet, i);
             xxx_column_set_left_column(sheet, i, 
@@ -3498,52 +3577,63 @@ gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col,
                    GtkJustification justification,
                    const gchar *text)
 {
GtkSheetRange range;
gint text_width;
- GtkSheetCellAttr attributes;
 GSheetModel *model ;
 gboolean changed ;
+  gchar *old_text ; 
 
- g_return_if_fail (sheet != NULL);
- g_return_if_fail (GTK_IS_SHEET (sheet));
- if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
- if (col < 0 || row < 0) return;
+  GtkSheetRange range;
+  gint text_width;
+  GtkSheetCellAttr attributes;
 
- gtk_sheet_get_attributes(sheet, row, col, &attributes);
+  g_return_if_fail (sheet != NULL);
+  g_return_if_fail (GTK_IS_SHEET (sheet));
+  if (col >= xxx_column_count(sheet) || row >= yyy_row_count(sheet)) return;
+  if (col < 0 || row < 0) return;
+
+  gtk_sheet_get_attributes(sheet, row, col, &attributes);
 
- attributes.justification = justification;
 attributes.justification = justification;
 
GSheetModel *model =  gtk_sheet_get_model(sheet);
 model =  gtk_sheet_get_model(sheet);
 
const gchar *old_text = g_sheet_model_get_string(model, row, col);
 old_text = g_sheet_model_get_string(model, row, col);
 
gboolean changed = FALSE;
+  changed = FALSE;
 
- if (0 != safe_strcmp(old_text, text))
-   changed = g_sheet_model_set_string(model, text, row, col);
 if (0 != safe_strcmp(old_text, text))
+    changed = g_sheet_model_set_string(model, text, row, col);
 
- if(changed && attributes.is_visible){
-   const gchar *s = gtk_sheet_cell_get_text(sheet, row, col);
-   text_width = 0;
-   if(s && strlen(s) > 0) {
-     text_width = STRING_WIDTH(GTK_WIDGET(sheet), attributes.font_desc, text);
-   }
+  if ( g_sheet_model_free_strings(model))
+    g_free(old_text);
+
+
+  if(changed && attributes.is_visible)
+    {
+      gchar *s = gtk_sheet_cell_get_text(sheet, row, col);
+      text_width = 0;
+      if(s && strlen(s) > 0) {
+       text_width = STRING_WIDTH(GTK_WIDGET(sheet), 
+                                 attributes.font_desc, text);
+      }
+      dispose_string(sheet, s);
 
-   range.row0 = row;
-   range.rowi = row;
-   range.col0 = sheet->view.col0;
-   range.coli = sheet->view.coli;
+    range.row0 = row;
+    range.rowi = row;
+    range.col0 = sheet->view.col0;
+    range.coli = sheet->view.coli;
 
-   if(gtk_sheet_autoresize(sheet) &&
-      text_width > xxx_column_width(sheet, col) - 2*CELLOFFSET-attributes.border.width){
+    if(gtk_sheet_autoresize(sheet) &&
+       text_width > xxx_column_width(sheet, col) - 2*CELLOFFSET-attributes.border.width){
       gtk_sheet_set_column_width(sheet, col, text_width+2*CELLOFFSET+attributes.border.width);
       GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
-   }
-   else
-     if(!GTK_SHEET_IS_FROZEN(sheet))
-       gtk_sheet_range_draw(sheet, &range);
- }
+    }
+    else
+      if(!GTK_SHEET_IS_FROZEN(sheet))
+       gtk_sheet_range_draw(sheet, &range);
 }
 
- if ( changed ) 
-   gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
 if ( changed ) 
+    gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[CHANGED], row, col);
 
 }
 
@@ -3595,12 +3685,10 @@ gtk_sheet_cell_delete (GtkSheet *sheet, gint row, gint column)
 static void
 gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean delete)
 {
-  const gchar *old_text;
-
-  old_text = gtk_sheet_cell_get_text(sheet, row, column); 
   GSheetModel *model =  gtk_sheet_get_model(sheet);
 
+  gchar *old_text = gtk_sheet_cell_get_text(sheet, row, column); 
   if (old_text && strlen(old_text) > 0 )
     {
       g_sheet_model_datum_clear(model, row, column);
@@ -3610,6 +3698,7 @@ gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean dele
                        row, column);
     }  
 
+  dispose_string (sheet, old_text);
 }
     
 void
@@ -3660,8 +3749,21 @@ gtk_sheet_real_range_clear (GtkSheet *sheet, const GtkSheetRange *range,
 }
 
 
-const gchar *     
-gtk_sheet_cell_get_text (GtkSheet *sheet, gint row, gint col)
+static gboolean
+gtk_sheet_cell_empty (const GtkSheet *sheet, gint row, gint col)
+{
+  gboolean empty;
+  char *text = gtk_sheet_cell_get_text(sheet, row, col);
+  empty = (text == NULL );
+  dispose_string(sheet, text);
+
+  return empty;
+}
+
+
+gchar *     
+gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col)
 {
   GSheetModel *model;
   g_return_val_if_fail (sheet != NULL, NULL);
@@ -3793,7 +3895,7 @@ gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
  g_return_val_if_fail (sheet != NULL, 0);
  g_return_val_if_fail (GTK_IS_SHEET (sheet), 0);
 
- if(row < 0 || column < 0) return FALSE;
+ if(row < -1 || column < -1) return FALSE;
  if(row >= yyy_row_count(sheet) || column >= xxx_column_count(sheet)) 
    return FALSE;
 
@@ -3802,9 +3904,15 @@ gtk_sheet_set_active_cell (GtkSheet *sheet, gint row, gint column)
        if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
    }
 
- sheet->active_cell.row=row;
- sheet->active_cell.col=column;
+ sheet->active_cell.row = row;
+ sheet->active_cell.col = column;
  
+ if ( row == -1 || column == -1)
+   {
+     gtk_sheet_hide_active_cell(sheet);
+     return TRUE;
+   }
+
  if(!gtk_sheet_activate_cell(sheet, row, column)) return FALSE;
  
  if(gtk_sheet_autoscroll(sheet))
@@ -3852,11 +3960,12 @@ gtk_sheet_entry_changed(GtkWidget *widget, gpointer data)
 
  GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
 
- if(text && strlen(text) > 0){
-      gtk_sheet_get_attributes(sheet, row, col, &attributes); 
-      justification=attributes.justification;
-      gtk_sheet_set_cell(sheet, row, col, justification, text);
- }
+ if(text && strlen(text) > 0)
+   {
+     gtk_sheet_get_attributes(sheet, row, col, &attributes); 
+     justification = attributes.justification;
+     gtk_sheet_set_cell(sheet, row, col, justification, text);
+   }
 
  if(sheet->freeze_count == 0)
         GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IS_FROZEN);
@@ -3883,13 +3992,16 @@ gtk_sheet_deactivate_cell(GtkSheet *sheet)
 
  if(!veto) return FALSE;
 
+ if ( sheet->active_cell.row == -1 || sheet->active_cell.col == -1 )
+   return TRUE;
+
  gtk_signal_disconnect_by_func(GTK_OBJECT(gtk_sheet_get_entry(sheet)),
                               (GtkSignalFunc) gtk_sheet_entry_changed,
                               GTK_OBJECT(GTK_WIDGET(sheet)));
 
  gtk_sheet_hide_active_cell(sheet);
- sheet->active_cell.row=-1;
- sheet->active_cell.col=-1;
+ sheet->active_cell.row = -1;
+ sheet->active_cell.col = -1;
  
  if(GTK_SHEET_REDRAW_PENDING(sheet)){
    GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_REDRAW_PENDING);
@@ -3922,7 +4034,8 @@ gtk_sheet_hide_active_cell(GtkSheet *sheet)
  gtk_sheet_get_attributes(sheet, row, col, &attributes); 
  justification=attributes.justification;
 
- if(text && strlen(text)!=0){
+ if(text && strlen(text) != 0) 
+ {
       gtk_sheet_set_cell(sheet, row, col, justification, text);
       gtk_signal_emit(GTK_OBJECT(sheet),sheet_signals[SET_CELL], row, col);
  }
@@ -3939,6 +4052,7 @@ gtk_sheet_hide_active_cell(GtkSheet *sheet)
  row_button_release(sheet, row);
 #endif
 
+ gtk_widget_hide(sheet->sheet_entry);
  gtk_widget_unmap(sheet->sheet_entry);
 
  if(row != -1 && col != -1)
@@ -4025,7 +4139,7 @@ gtk_sheet_show_active_cell(GtkSheet *sheet)
  /* Don't show the active cell, if there is no active cell: */
  if(!(row >= 0 && col >= 0)) /* e.g row or coll == -1. */
    return;
-  
+
  if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sheet))) return;
  if(sheet->state != GTK_SHEET_NORMAL) return;
  if(GTK_SHEET_IN_SELECTION(sheet)) return;
@@ -4041,17 +4155,16 @@ gtk_sheet_show_active_cell(GtkSheet *sheet)
  if(gtk_sheet_justify_entry(sheet))
       justification = attributes.justification;
 
- text = g_strdup(gtk_sheet_cell_get_text(sheet, row, col));
-
if(!text) text = g_strdup("");
+ text = gtk_sheet_cell_get_text(sheet, row, col);
+ if ( ! text ) 
       text = g_strdup("");
 
  gtk_entry_set_visibility(GTK_ENTRY(sheet_entry), attributes.is_visible);
 
- if(gtk_sheet_locked(sheet) || !attributes.is_editable){ 
-            gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE);
- }else{
-            gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE);
- }
+ if(gtk_sheet_locked(sheet) || !attributes.is_editable)
+   gtk_entry_set_editable(GTK_ENTRY(sheet_entry), FALSE);
+ else
+   gtk_entry_set_editable(GTK_ENTRY(sheet_entry), TRUE);
 
 /*** Added by John Gotts. Mar 25, 2005 *********/
  old_text = gtk_entry_get_text(GTK_ENTRY(sheet_entry));
@@ -4071,7 +4184,7 @@ gtk_sheet_show_active_cell(GtkSheet *sheet)
 
  gtk_widget_grab_focus(GTK_WIDGET(sheet_entry));
 
g_free(text);
dispose_string(sheet, text);
 }
 
 static void
@@ -4085,7 +4198,7 @@ gtk_sheet_draw_active_cell(GtkSheet *sheet)
     row = sheet->active_cell.row;
     col = sheet->active_cell.col;
  
-    if(row<0 || col<0) return;
+    if(row < 0 || col < 0) return;
 
     if(!gtk_sheet_cell_isvisible(sheet, row, col)) return;
 #if 0
@@ -4094,7 +4207,6 @@ gtk_sheet_draw_active_cell(GtkSheet *sheet)
 #endif
     gtk_sheet_draw_backing_pixmap(sheet, sheet->range);
     gtk_sheet_draw_border(sheet, sheet->range);
-
 }
 
 
@@ -4125,7 +4237,7 @@ gtk_sheet_make_backing_pixmap (GtkSheet *sheet, guint width, guint height)
                           &pixmap_width, &pixmap_height);
       if ((pixmap_width != width) || (pixmap_height != height))
        {
-          g_free(sheet->pixmap);
+         g_object_unref(sheet->pixmap);
          sheet->pixmap = gdk_pixmap_new (sheet->sheet_window,
                                               width, height,
                                               -1);
@@ -4612,6 +4724,9 @@ gtk_sheet_select_range(GtkSheet * sheet, const GtkSheetRange *range)
   if(range->row0 < 0 || range->rowi < 0) return;
   if(range->col0 < 0 || range->coli < 0) return;
 
+
+  if ( gtk_sheet_locked(sheet)) return ;
+
   if(sheet->state != GTK_SHEET_NORMAL) 
        gtk_sheet_real_unselect_range(sheet, NULL);
   else
@@ -4872,35 +4987,40 @@ gtk_sheet_button_press (GtkWidget * widget,
         GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_RESIZE);
      }
      else if(sheet->cursor_drag->type==GDK_TOP_LEFT_ARROW &&
-            !GTK_SHEET_IN_SELECTION(sheet) && !GTK_SHEET_IN_DRAG(sheet)) {
-            if(sheet->state==GTK_STATE_NORMAL) {
-              row=sheet->active_cell.row;
-              column=sheet->active_cell.col;
-              if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
-              sheet->active_cell.row=row;
-              sheet->active_cell.col=column;
-              sheet->drag_range=sheet->range;
-              sheet->state=GTK_SHEET_RANGE_SELECTED;
-              gtk_sheet_select_range(sheet, &sheet->drag_range);
-            }
-            sheet->x_drag=x;
-            sheet->y_drag=y;
-            if(row < sheet->range.row0) row++;
-            if(row > sheet->range.rowi) row--;
-            if(column < sheet->range.col0) column++;
-            if(column > sheet->range.coli) column--;
-            sheet->drag_cell.row=row;
-            sheet->drag_cell.col=column;
-            sheet->drag_range=sheet->range;
-            draw_xor_rectangle(sheet, sheet->drag_range);
-            GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
-          }
-          else 
-          {
-           gtk_sheet_click_cell(sheet, row, column, &veto);
-           if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
-          }
-
+            !GTK_SHEET_IN_SELECTION(sheet) 
+            && ! GTK_SHEET_IN_DRAG(sheet)
+            && ! gtk_sheet_locked(sheet)
+            && sheet->active_cell.row >= 0
+            && sheet->active_cell.col >= 0
+            ) 
+       {
+        if(sheet->state==GTK_STATE_NORMAL) {
+          row=sheet->active_cell.row;
+          column=sheet->active_cell.col;
+          if(!gtk_sheet_deactivate_cell(sheet)) return FALSE;
+          sheet->active_cell.row=row;
+          sheet->active_cell.col=column;
+          sheet->drag_range=sheet->range;
+          sheet->state=GTK_SHEET_RANGE_SELECTED;
+          gtk_sheet_select_range(sheet, &sheet->drag_range);
+        }
+        sheet->x_drag=x;
+        sheet->y_drag=y;
+        if(row < sheet->range.row0) row++;
+        if(row > sheet->range.rowi) row--;
+        if(column < sheet->range.col0) column++;
+        if(column > sheet->range.coli) column--;
+        sheet->drag_cell.row=row;
+        sheet->drag_cell.col=column;
+        sheet->drag_range=sheet->range;
+        draw_xor_rectangle(sheet, sheet->drag_range);
+        GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_DRAG);
+       }
+     else 
+       {
+        gtk_sheet_click_cell(sheet, row, column, &veto);
+        if(veto) GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_IN_SELECTION);
+       }
     }
 
     if(event->window == sheet->column_title_window){
@@ -6017,7 +6137,7 @@ static void
 gtk_sheet_size_allocate_entry(GtkSheet *sheet)
 {
  GtkAllocation shentry_allocation;
- GtkSheetCellAttr attributes;
+ GtkSheetCellAttr attributes = { 0 };
  GtkEntry *sheet_entry;
  GtkStyle *style = NULL, *previous_style = NULL;
  gint row, col;
@@ -6029,40 +6149,41 @@ gtk_sheet_size_allocate_entry(GtkSheet *sheet)
 
  sheet_entry = GTK_ENTRY(gtk_sheet_get_entry(sheet));
 
- gtk_sheet_get_attributes(sheet, sheet->active_cell.row, sheet->active_cell.col, &attributes); 
+ gtk_sheet_get_attributes(sheet, sheet->active_cell.row, sheet->active_cell.col,                               &attributes);
 
- if(GTK_WIDGET_REALIZED(sheet->sheet_entry)){
+ if(GTK_WIDGET_REALIZED(sheet->sheet_entry))
+    {
 
-  if(!GTK_WIDGET(sheet_entry)->style) 
+      if(!GTK_WIDGET(sheet_entry)->style) 
         gtk_widget_ensure_style(GTK_WIDGET(sheet_entry));
 
-  previous_style = GTK_WIDGET(sheet_entry)->style;
-
-  style = gtk_style_copy(previous_style);
-  style->bg[GTK_STATE_NORMAL] = attributes.background;
-  style->fg[GTK_STATE_NORMAL] = attributes.foreground;
-  style->text[GTK_STATE_NORMAL] = attributes.foreground;
-  style->bg[GTK_STATE_ACTIVE] = attributes.background;
-  style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
-  style->text[GTK_STATE_ACTIVE] = attributes.foreground;
-
-  pango_font_description_free(style->font_desc);
-  style->font_desc = pango_font_description_copy(attributes.font_desc);
-
-  GTK_WIDGET(sheet_entry)->style = style;
-  gtk_widget_size_request(sheet->sheet_entry, NULL);
-  GTK_WIDGET(sheet_entry)->style = previous_style;
-
-  if(style != previous_style){
-    if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
-      style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
-      style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
-      style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
-      style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
+      previous_style = GTK_WIDGET(sheet_entry)->style;
+
+      style = gtk_style_copy(previous_style);
+      style->bg[GTK_STATE_NORMAL] = attributes.background;
+      style->fg[GTK_STATE_NORMAL] = attributes.foreground;
+      style->text[GTK_STATE_NORMAL] = attributes.foreground;
+      style->bg[GTK_STATE_ACTIVE] = attributes.background;
+      style->fg[GTK_STATE_ACTIVE] = attributes.foreground;
+      style->text[GTK_STATE_ACTIVE] = attributes.foreground;
+
+      pango_font_description_free(style->font_desc);
+      style->font_desc = pango_font_description_copy(attributes.font_desc);
+
+      GTK_WIDGET(sheet_entry)->style = style;
+      gtk_widget_size_request(sheet->sheet_entry, NULL);
+      GTK_WIDGET(sheet_entry)->style = previous_style;
+
+      if(style != previous_style){
+       if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
+         style->bg[GTK_STATE_NORMAL] = previous_style->bg[GTK_STATE_NORMAL];
+         style->fg[GTK_STATE_NORMAL] = previous_style->fg[GTK_STATE_NORMAL];
+         style->bg[GTK_STATE_ACTIVE] = previous_style->bg[GTK_STATE_ACTIVE];
+         style->fg[GTK_STATE_ACTIVE] = previous_style->fg[GTK_STATE_ACTIVE];
+       }
+       gtk_widget_set_style(GTK_WIDGET(sheet_entry), style);
+      }
     }
-    gtk_widget_set_style(GTK_WIDGET(sheet_entry), style);
-  }
- }
 
  if(GTK_IS_ITEM_ENTRY(sheet_entry))
     max_size = GTK_ITEM_ENTRY(sheet_entry)->text_max_size;
@@ -6112,12 +6233,13 @@ gtk_sheet_size_allocate_entry(GtkSheet *sheet)
 
  }
 
- if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry)){
-   shentry_allocation.x += 2;
-   shentry_allocation.y += 2;
-   shentry_allocation.width -= MIN(shentry_allocation.width, 3);
-   shentry_allocation.height -= MIN(shentry_allocation.height, 3);
- }
+ if(!GTK_IS_ITEM_ENTRY(sheet->sheet_entry))
+   {
+     shentry_allocation.x += 2;
+     shentry_allocation.y += 2;
+     shentry_allocation.width -= MIN(shentry_allocation.width, 3);
+     shentry_allocation.height -= MIN(shentry_allocation.height, 3);
+   }
 
  gtk_widget_size_allocate(sheet->sheet_entry, &shentry_allocation);
 
@@ -6132,6 +6254,7 @@ gtk_sheet_entry_set_max_size(GtkSheet *sheet)
  gint sizel=0, sizer=0;
  gint row,col;
  GtkJustification justification;
+ gchar *s = NULL;
 
  row=sheet->active_cell.row;
  col=sheet->active_cell.col;
@@ -6144,34 +6267,52 @@ gtk_sheet_entry_set_max_size(GtkSheet *sheet)
   case GTK_JUSTIFY_FILL:
   case GTK_JUSTIFY_LEFT:
     for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
-     if(gtk_sheet_cell_get_text(sheet, row, i)) break;
+      if((s = gtk_sheet_cell_get_text(sheet, row, i)))
+       {
+         g_free(s);
+         break;
+       }
      size+=xxx_column_width(sheet, i);
     }
     size = MIN(size, sheet->sheet_window_width - COLUMN_LEFT_XPIXEL(sheet, col));
     break;
-  case GTK_JUSTIFY_RIGHT:
-    for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
-     if(gtk_sheet_cell_get_text(sheet, row, i)) break;
-     size+=xxx_column_width(sheet, i);
-    }
+ case GTK_JUSTIFY_RIGHT:
+   for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--)
+     {
+       if((s = gtk_sheet_cell_get_text(sheet, row, i)))
+        {
+          g_free(s);
+          break;
+        }
+       size+=xxx_column_width(sheet, i);
+     }
     break;
   case GTK_JUSTIFY_CENTER:
     for(i=col+1; i<=MAX_VISIBLE_COLUMN(sheet); i++){
-/*     if(gtk_sheet_cell_get_text(sheet, row, i)) break;
+/*     if((s = gtk_sheet_cell_get_text(sheet, row, i)))
+            {
+            g_free(s);
+            break;
+            }
 */
      sizer+=xxx_column_width(sheet, i);
     }
-    for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--){
-     if(gtk_sheet_cell_get_text(sheet, row, i)) break;
-     sizel+=xxx_column_width(sheet, i);
-    }
+    for(i=col-1; i>=MIN_VISIBLE_COLUMN(sheet); i--)
+      {
+       if((s = gtk_sheet_cell_get_text(sheet, row, i)))
+         {
+           g_free(s);
+           break;
+         }
+       sizel+=xxx_column_width(sheet, i);
+      }
     size=2*MIN(sizel, sizer);
     break;
  }
 
- if(size!=0) size+=xxx_column_width(sheet, col);
GTK_ITEM_ENTRY(sheet->sheet_entry)->text_max_size=size;
-
+ if(size != 0) 
  size += xxx_column_width(sheet, col);
+ GTK_ITEM_ENTRY(sheet->sheet_entry)->text_max_size = size;
 }
 
 static void
@@ -6351,7 +6492,7 @@ gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column)
   gint x = 0, y = 0;
   gint index = 0;
   gint text_width = 0, text_height = 0;
-  const GtkSheetButton *button = NULL;
+  GtkSheetButton *button = NULL;
   GtkSheetChild *child = NULL;
   GdkRectangle allocation;
   gboolean is_sensitive = FALSE;
@@ -6422,10 +6563,10 @@ gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column)
      shadow_type = GTK_SHADOW_OUT;
 
   if(state != GTK_STATE_NORMAL && state != GTK_STATE_INSENSITIVE)
-  gtk_paint_box (sheet->button->style, window,
-                 button->state, shadow_type, 
-                 &allocation, GTK_WIDGET(sheet->button),
-                 "button", x, y, width, height);
+    gtk_paint_box (sheet->button->style, window,
+                  button->state, shadow_type, 
+                  &allocation, GTK_WIDGET(sheet->button),
+                  "button", x, y, width, height);
 
   if(button->label_visible){
 
@@ -6495,40 +6636,6 @@ gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column)
            }
            g_free(line);
     }
-    if(button->label && strlen(button->label) > 0){
-      PangoLayout *layout = NULL;
-      gint real_x = x, real_y = y;
-
-      text_width = STRING_WIDTH(GTK_WIDGET(sheet), GTK_WIDGET(sheet)->style->font_desc, button->label);
-
-      layout = gtk_widget_create_pango_layout (GTK_WIDGET(sheet), button->label);
-      switch(button->justification){
-      case GTK_JUSTIFY_LEFT:
-       real_x = x + CELLOFFSET;
-       align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
-       break;
-      case GTK_JUSTIFY_RIGHT:
-       real_x = x + width - text_width - CELLOFFSET;
-       align = rtl ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT;
-       break;
-      case GTK_JUSTIFY_CENTER:
-      default:
-       real_x = x + (width - text_width)/2;
-       align = rtl ? PANGO_ALIGN_RIGHT : PANGO_ALIGN_LEFT;
-       pango_layout_set_justify (layout, TRUE);
-      }
-      pango_layout_set_alignment (layout, align);
-      gtk_paint_layout (GTK_WIDGET(sheet)->style,
-                       window,
-                       state,
-                       FALSE,
-                       &allocation,
-                       GTK_WIDGET(sheet),
-                       "label",
-                       real_x, real_y,
-                       layout);
-      g_object_unref(G_OBJECT(layout));
-    }
 
     gdk_gc_set_clip_rectangle(GTK_WIDGET(sheet)->style->fg_gc[button->state],
                             NULL);
@@ -6560,6 +6667,8 @@ gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column)
               gtk_widget_queue_draw(child->widget);
             }
   }
+
+  gtk_sheet_button_free(button);
    
 }
 
@@ -6665,7 +6774,6 @@ vadjustment_value_changed (GtkAdjustment * adjustment,
 {
   GtkSheet *sheet;
   gint diff, value, old_value;
-  gint i;
   gint row, new_row;
   gint y=0;
 
@@ -6689,7 +6797,7 @@ vadjustment_value_changed (GtkAdjustment * adjustment,
   y = g_sheet_row_start_pixel(sheet->row_geometry, new_row, sheet);
 
   if (adjustment->value > sheet->old_vadjustment && sheet->old_vadjustment > 0. &&
-      yyy_row_height(sheet, i) > sheet->vadjustment->step_increment){
+      yyy_row_height(sheet, row) > sheet->vadjustment->step_increment){
 /* This avoids embarrassing twitching */
           if(row == new_row && row != yyy_row_count(sheet) - 1 &&
              adjustment->value - sheet->old_vadjustment >= 
@@ -7109,8 +7217,14 @@ gtk_sheet_set_row_height (GtkSheet * sheet,
 
 
 gboolean
-gtk_sheet_get_attributes(GtkSheet *sheet, gint row, gint col, GtkSheetCellAttr *attributes)
+gtk_sheet_get_attributes(const GtkSheet *sheet, gint row, gint col, 
+                        GtkSheetCellAttr *attributes)
 {
+ const GdkColor *fg, *bg; 
+ const GtkJustification *j ; 
+ const PangoFontDescription *font_desc ;
+ const GtkSheetCellBorder *border ;
+
  g_return_val_if_fail (sheet != NULL, FALSE);
  g_return_val_if_fail (GTK_IS_SHEET (sheet), FALSE);
 
@@ -7119,37 +7233,34 @@ gtk_sheet_get_attributes(GtkSheet *sheet, gint row, gint col, GtkSheetCellAttr *
  init_attributes(sheet, col, attributes);
 
  if ( !sheet->model) 
-        return FALSE;
+   return FALSE;
 
  attributes->is_editable = g_sheet_model_is_editable(sheet->model, row, col);
  attributes->is_visible = g_sheet_model_is_visible(sheet->model, row, col);
 
const GdkColor *fg = g_sheet_model_get_foreground(sheet->model, row, col);
+ fg = g_sheet_model_get_foreground(sheet->model, row, col);
  if ( fg ) 
    attributes->foreground =  *fg;
 
const GdkColor *bg = g_sheet_model_get_background(sheet->model, row, col);
+ bg = g_sheet_model_get_background(sheet->model, row, col);
  if ( bg ) 
    attributes->background =  *bg;
 
- const GtkJustification *j = g_sheet_model_get_justification(sheet->model,
-                                                              row, col);
+ j = g_sheet_model_get_justification(sheet->model, row, col);
  if (j)   attributes->justification = *j;
 
- const PangoFontDescription *font_desc = 
-   g_sheet_model_get_font_desc(sheet->model, row, col);
+ font_desc = g_sheet_model_get_font_desc(sheet->model, row, col);
  if ( font_desc )  attributes->font_desc = font_desc;
 
- const GtkSheetCellBorder *border = 
-  g_sheet_model_get_cell_border(sheet->model, row, col);
+ border = g_sheet_model_get_cell_border(sheet->model, row, col);
 
- if ( border )    attributes->border = *border;
+ if ( border ) attributes->border = *border;
 
  return TRUE;
 }
 
 static void
-init_attributes(GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
+init_attributes(const GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
 {
  /* DEFAULT VALUES */    
  attributes->foreground = GTK_WIDGET(sheet)->style->black;
@@ -7170,9 +7281,7 @@ init_attributes(GtkSheet *sheet, gint col, GtkSheetCellAttr *attributes)
  attributes->is_editable = TRUE;
  attributes->is_visible = TRUE;
  attributes->font_desc = GTK_WIDGET(sheet)->style->font_desc;
-
 }       
 
 
 /********************************************************************
@@ -7344,7 +7453,7 @@ gtk_sheet_button_attach           (GtkSheet *sheet,
                                 GtkWidget *widget, 
                                 gint row, gint col)
 {
-  GtkSheetButton *button;
+  GtkSheetButton *button = 0;
   GtkSheetChild *child;
   GtkRequisition button_requisition;
 
@@ -7803,3 +7912,25 @@ gtk_sheet_get_model(const GtkSheet *sheet)
   return sheet->model;
 }
 
+
+GtkSheetButton *
+gtk_sheet_button_new(void)
+{
+  GtkSheetButton *button = g_malloc(sizeof(GtkSheetButton));
+  
+  button->state = GTK_STATE_NORMAL;
+  button->label = NULL;
+  button->label_visible = TRUE;
+  button->child = NULL;
+  button->justification = GTK_JUSTIFY_FILL;
+
+  return button;
+}
+
+
+inline void
+gtk_sheet_button_free(GtkSheetButton *button)
+{
+  g_free(button->label);
+  g_free(button);
+}