From a6df7a4863f51dd4121a067f947335fba197617b Mon Sep 17 00:00:00 2001 From: John Darrington Date: Sun, 14 May 2006 00:01:39 +0000 Subject: [PATCH] Fixed some memory leaks in GUI. --- lib/gtksheet/ChangeLog | 6 ++ lib/gtksheet/gsheetmodel.c | 22 +++++++- lib/gtksheet/gsheetmodel.h | 10 +++- lib/gtksheet/gtksheet.c | 97 ++++++++++++++++++++++----------- lib/gtksheet/gtksheet.h | 4 +- src/ui/gui/ChangeLog | 8 +++ src/ui/gui/data-sheet.c | 2 +- src/ui/gui/helper.c | 4 +- src/ui/gui/helper.h | 2 +- src/ui/gui/psppire-data-store.c | 2 + src/ui/gui/psppire-var-store.c | 1 + 11 files changed, 116 insertions(+), 42 deletions(-) diff --git a/lib/gtksheet/ChangeLog b/lib/gtksheet/ChangeLog index 2d2cfd04..32d12736 100644 --- a/lib/gtksheet/ChangeLog +++ b/lib/gtksheet/ChangeLog @@ -1,3 +1,9 @@ +Sat May 13 07:58:32 WST 2006 John Darrington + + * gsheetmodel.c gsheetmodel.h gtksheet.c gtksheeet.h: Added + free_strings flag to tell the sheet whether to free the string + data passed from the model. + Thu May 11 22:20:04 WST 2006 John Darrington * gtksheet.c, gtksheet.h: Fixed broken deallocation of sheet->pixmap. diff --git a/lib/gtksheet/gsheetmodel.c b/lib/gtksheet/gsheetmodel.c index 3f066578..3a447188 100644 --- a/lib/gtksheet/gsheetmodel.c +++ b/lib/gtksheet/gsheetmodel.c @@ -113,6 +113,23 @@ g_sheet_model_base_init (gpointer g_class) } } + +/** + * g_sheet_model_free_strings + * @sheet_model: A #GSheetModel + * + * Returns: True if strings obtained with get_string should be freed by the + * sheet when no longer required. + **/ +inline gboolean +g_sheet_model_free_strings (const GSheetModel *sheet_model) +{ + g_return_val_if_fail (G_IS_SHEET_MODEL (sheet_model), FALSE); + + return G_SHEET_MODEL_GET_IFACE (sheet_model)->free_strings; +} + + /** * g_sheet_model_get_string: * @sheet_model: A #GSheetModel @@ -122,7 +139,7 @@ g_sheet_model_base_init (gpointer g_class) * Retrieves the datum at location ROW, COLUMN in the form of a string. * Returns: The string representation of the datum, or NULL on error. **/ -inline const gchar * +inline gchar * g_sheet_model_get_string (const GSheetModel *sheet_model, gint row, gint column) { @@ -393,3 +410,6 @@ g_sheet_model_get_cell_border (const GSheetModel *model, return G_SHEET_MODEL_GET_IFACE (model)->get_cell_border (model, row, column); } + + + diff --git a/lib/gtksheet/gsheetmodel.h b/lib/gtksheet/gsheetmodel.h index 50746462..4ee06836 100644 --- a/lib/gtksheet/gsheetmodel.h +++ b/lib/gtksheet/gsheetmodel.h @@ -15,6 +15,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + #ifndef __G_SHEET_MODEL_H__ #define __G_SHEET_MODEL_H__ @@ -70,6 +71,8 @@ struct _GSheetModelIface { GTypeInterface g_iface; + gboolean free_strings; + /* Signals */ void (* range_changed) (GSheetModel *sheet_model, gint row0, gint col0, @@ -82,9 +85,9 @@ struct _GSheetModelIface gint row, gint n_rows); - /* Virtual Table */ - const gchar * (* get_string) (const GSheetModel *sheet_model, + + gchar * (* get_string) (const GSheetModel *sheet_model, gint row, gint column); gboolean (* set_string) (GSheetModel *sheet_model, @@ -118,7 +121,7 @@ struct _GSheetModelIface GType g_sheet_model_get_type (void) G_GNUC_CONST; -inline const gchar * g_sheet_model_get_string (const GSheetModel *sheet_model, +inline gchar * g_sheet_model_get_string (const GSheetModel *sheet_model, gint row, gint column); inline gboolean g_sheet_model_set_string (GSheetModel *sheet_model, @@ -163,6 +166,7 @@ inline const PangoFontDescription *g_sheet_model_get_font_desc inline const GtkSheetCellBorder * g_sheet_model_get_cell_border (const GSheetModel *model, gint row, gint column); +inline gboolean g_sheet_model_free_strings (const GSheetModel *sheet_model); diff --git a/lib/gtksheet/gtksheet.c b/lib/gtksheet/gtksheet.c index 2e9e416d..c7c3f7a8 100644 --- a/lib/gtksheet/gtksheet.c +++ b/lib/gtksheet/gtksheet.c @@ -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+. @@ -101,8 +101,19 @@ enum #define DEFAULT_COLUMN_WIDTH 80 +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) @@ -1488,21 +1499,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; - 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) ) { @@ -3054,7 +3067,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); @@ -3091,6 +3104,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); @@ -3130,7 +3144,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, @@ -3149,7 +3163,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, @@ -3158,7 +3172,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, @@ -3176,7 +3190,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, @@ -3506,7 +3520,7 @@ gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col, { GSheetModel *model ; gboolean changed ; - const gchar *old_text ; + gchar *old_text ; GtkSheetRange range; gint text_width; @@ -3530,14 +3544,19 @@ gtk_sheet_set_cell(GtkSheet *sheet, gint row, gint col, if (0 != safe_strcmp(old_text, text)) changed = g_sheet_model_set_string(model, text, row, col); + if ( g_sheet_model_free_strings(model)) + g_free(old_text); + + if(changed && attributes.is_visible) { - const gchar *s = gtk_sheet_cell_get_text(sheet, row, col); + 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; @@ -3609,7 +3628,7 @@ gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean dele { GSheetModel *model = gtk_sheet_get_model(sheet); - const gchar *old_text = gtk_sheet_cell_get_text(sheet, row, column); + gchar *old_text = gtk_sheet_cell_get_text(sheet, row, column); if (old_text && strlen(old_text) > 0 ) { @@ -3620,6 +3639,7 @@ gtk_sheet_real_cell_clear (GtkSheet *sheet, gint row, gint column, gboolean dele row, column); } + dispose_string (sheet, old_text); } void @@ -3670,8 +3690,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); @@ -4051,9 +4084,9 @@ 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); @@ -4081,7 +4114,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 @@ -6431,10 +6464,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){ diff --git a/lib/gtksheet/gtksheet.h b/lib/gtksheet/gtksheet.h index 3fecbc92..18c39f25 100644 --- a/lib/gtksheet/gtksheet.h +++ b/lib/gtksheet/gtksheet.h @@ -540,8 +540,8 @@ gtk_sheet_set_cell_text (GtkSheet *sheet, gint row, gint col, const gchar *text); /* get cell contents */ -const gchar * -gtk_sheet_cell_get_text (GtkSheet *sheet, gint row, gint col); +gchar * +gtk_sheet_cell_get_text (const GtkSheet *sheet, gint row, gint col); /* clear cell contents */ void diff --git a/src/ui/gui/ChangeLog b/src/ui/gui/ChangeLog index 6aba2cf8..c5311ede 100644 --- a/src/ui/gui/ChangeLog +++ b/src/ui/gui/ChangeLog @@ -1,3 +1,11 @@ +Sat May 13 08:00:50 WST 2006 John Darrington + + * data-sheet.c, helper.c, helper.h, psppire-data-store.c, + psppire-var-store.c: + + Set free_strings flag so that the gtksheet frees the string data + when it's done with them. + Thu May 11 22:25:49 WST 2006 John Darrington * data-sheet.c helper.c helper.h psppire-data-store.c psppire-var-store.c diff --git a/src/ui/gui/data-sheet.c b/src/ui/gui/data-sheet.c index 20869dcb..a9d980de 100644 --- a/src/ui/gui/data-sheet.c +++ b/src/ui/gui/data-sheet.c @@ -85,7 +85,7 @@ click2column(GtkWidget *w, gint col, gpointer data) /* Update the data_ref_entry with the reference of the active cell */ static gint -update_data_ref_entry(GtkSheet *sheet, gint row, gint col) +update_data_ref_entry(const GtkSheet *sheet, gint row, gint col) { /* The entry where the reference to the current cell is displayed */ diff --git a/src/ui/gui/helper.c b/src/ui/gui/helper.c index e3c4ee08..d2defd69 100644 --- a/src/ui/gui/helper.c +++ b/src/ui/gui/helper.c @@ -77,12 +77,12 @@ get_widget_assert(GladeXML *xml, const gchar *name) } /* Converts a string in the pspp locale to utf-8 */ -const char * +char * pspp_locale_to_utf8(const gchar *text, gssize len, GError **err) { GError *tmp_error = 0; - const gchar *s; + gchar *s; if ( ! text ) return 0; diff --git a/src/ui/gui/helper.h b/src/ui/gui/helper.h index 3ec352d9..5776c2b5 100644 --- a/src/ui/gui/helper.h +++ b/src/ui/gui/helper.h @@ -39,7 +39,7 @@ gboolean text_to_value(const gchar *text, union value *v, GtkWidget * get_widget_assert(GladeXML *xml, const gchar *name); /* Converts a string in the pspp locale to utf-8 */ -const char * pspp_locale_to_utf8(const gchar *text, gssize len, GError **err); +char * pspp_locale_to_utf8(const gchar *text, gssize len, GError **err); #endif diff --git a/src/ui/gui/psppire-data-store.c b/src/ui/gui/psppire-data-store.c index 4a517db1..53aa827d 100644 --- a/src/ui/gui/psppire-data-store.c +++ b/src/ui/gui/psppire-data-store.c @@ -29,6 +29,7 @@ #include "psppire-variable.h" #include "psppire-data-store.h" +#include "helper.h" #include #include @@ -147,6 +148,7 @@ psppire_data_store_get_font_desc(GSheetModel *model, static void psppire_data_store_sheet_model_init (GSheetModelIface *iface) { + iface->free_strings = TRUE; iface->get_string = psppire_data_store_get_string; iface->set_string = psppire_data_store_set_string; iface->clear_datum = psppire_data_store_clear_datum; diff --git a/src/ui/gui/psppire-var-store.c b/src/ui/gui/psppire-var-store.c index 77ea7343..09e1e716 100644 --- a/src/ui/gui/psppire-var-store.c +++ b/src/ui/gui/psppire-var-store.c @@ -199,6 +199,7 @@ psppire_var_store_get_font_desc(GSheetModel *model, static void psppire_var_store_sheet_model_init (GSheetModelIface *iface) { + iface->free_strings = TRUE; iface->get_string = psppire_var_store_get_string; iface->set_string = psppire_var_store_set_string; iface->clear_datum = psppire_var_store_clear; -- 2.30.2