From 1ba9ab71de8a6528beaf22de3ee6d2eb697eb61d Mon Sep 17 00:00:00 2001 From: John Darrington Date: Thu, 25 May 2006 10:29:14 +0000 Subject: [PATCH] Plugged memory leaks in GUI, and converted most of the strings to UTF8, so that internationalised data files are now rendered OK. Fixed a buglet in PRINT command. --- lib/gtksheet/ChangeLog | 7 + lib/gtksheet/gsheet-column-iface.c | 21 +-- lib/gtksheet/gsheet-column-iface.h | 4 +- lib/gtksheet/gsheet-hetero-column.c | 4 +- lib/gtksheet/gsheet-row-iface.c | 10 +- lib/gtksheet/gsheet-row-iface.h | 6 +- lib/gtksheet/gsheet-uniform-row.c | 4 +- lib/gtksheet/gtkextra-sheet.h | 3 + lib/gtksheet/gtksheet.c | 83 +++++++++--- src/language/data-io/ChangeLog | 6 + src/language/data-io/print.c | 5 +- src/output/ChangeLog | 4 + src/output/table.h | 2 - src/ui/gui/ChangeLog | 5 + src/ui/gui/psppire-var-store.c | 200 +++++++++++++++------------- tests/automake.mk | 1 + tests/bugs/print-crash.sh | 75 +++++++++++ 17 files changed, 292 insertions(+), 148 deletions(-) create mode 100755 tests/bugs/print-crash.sh diff --git a/lib/gtksheet/ChangeLog b/lib/gtksheet/ChangeLog index b4a99709..8c2a073d 100644 --- a/lib/gtksheet/ChangeLog +++ b/lib/gtksheet/ChangeLog @@ -1,3 +1,10 @@ +Thu May 25 17:58:51 WST 2006 John Darrington + + * gsheet-column-iface.c gsheet-column-iface.h gsheet-hetero-column.c + gsheet-row-iface.c gsheet-row-iface.h gsheet-uniform-row.c + gtksheet-extra.h gtksheet.c: Plugged memory leaks. Rationalised the way + that GtkSheetButtons are created. + Sat May 20 21:02:03 WST 2006 John Darrington * gsheetmodel.c gsheetmodel.h: Added columns-inserted and columns-deleted diff --git a/lib/gtksheet/gsheet-column-iface.c b/lib/gtksheet/gsheet-column-iface.c index a4cc9f36..5abd21bc 100644 --- a/lib/gtksheet/gsheet-column-iface.c +++ b/lib/gtksheet/gsheet-column-iface.c @@ -25,7 +25,7 @@ #include #include "gsheet-column-iface.h" #include "gtkextra-marshal.h" - +#include "gtkextra-sheet.h" enum { COLUMNS_CHANGED, @@ -73,8 +73,6 @@ g_sheet_column_get_type (void) } -static GtkSheetButton default_button; - static void g_sheet_column_base_init (gpointer g_class) { @@ -95,12 +93,6 @@ g_sheet_column_base_init (gpointer g_class) G_TYPE_INT); - default_button.state = GTK_STATE_NORMAL; - default_button.label = NULL; - default_button.label_visible = TRUE; - default_button.child = NULL; - default_button.justification = GTK_JUSTIFY_FILL; - initialized = TRUE; } } @@ -159,21 +151,20 @@ g_sheet_column_get_sensitivity(const GSheetColumn *column, } -inline const GtkSheetButton * +inline GtkSheetButton * g_sheet_column_get_button(const GSheetColumn *column, gint col, const GtkSheet *sheet) { - static GtkSheetButton button ; + GtkSheetButton *button = gtk_sheet_button_new(); + GSheetColumnIface *iface = G_SHEET_COLUMN_GET_IFACE (column); g_return_val_if_fail (G_IS_SHEET_COLUMN (column), FALSE); - memcpy(&button, &default_button, sizeof (button)); - if ( iface->get_button_label) - button.label = iface->get_button_label(column, col, sheet); + button->label = iface->get_button_label(column, col, sheet); - return &button; + return button; } inline GtkJustification diff --git a/lib/gtksheet/gsheet-column-iface.h b/lib/gtksheet/gsheet-column-iface.h index 4e3e5a1b..6c997080 100644 --- a/lib/gtksheet/gsheet-column-iface.h +++ b/lib/gtksheet/gsheet-column-iface.h @@ -71,7 +71,7 @@ struct _GSheetColumnIface GtkStateType (*get_button_state)(const GSheetColumn *geo, gint col, const GtkSheet *); - const gchar * (*get_button_label)(const GSheetColumn *geo, gint col, const GtkSheet *); + gchar * (*get_button_label)(const GSheetColumn *geo, gint col, const GtkSheet *); gboolean (*get_button_visibility)(const GSheetColumn *geo, gint col, const GtkSheet *); const GtkSheetChild * (*get_button_child)(const GSheetColumn *geo, @@ -99,7 +99,7 @@ inline gboolean g_sheet_column_get_sensitivity(const GSheetColumn *gcolumn, gint col, const GtkSheet *sheet); -inline const GtkSheetButton *g_sheet_column_get_button(const GSheetColumn *gcolumn, +inline GtkSheetButton *g_sheet_column_get_button(const GSheetColumn *gcolumn, gint col, const GtkSheet *sheet); inline GtkJustification g_sheet_column_get_justification(const GSheetColumn *gcolumn, gint col, const GtkSheet *sheet); diff --git a/lib/gtksheet/gsheet-hetero-column.c b/lib/gtksheet/gsheet-hetero-column.c index e4235656..1285e9f2 100644 --- a/lib/gtksheet/gsheet-hetero-column.c +++ b/lib/gtksheet/gsheet-hetero-column.c @@ -128,12 +128,12 @@ g_sheet_hetero_column_get_visibility(const GSheetColumn *geom, gint u) -static const gchar * +static gchar * g_sheet_hetero_column_get_button_label(const GSheetColumn *geom, gint u) { GSheetHeteroColumn *hg = G_SHEET_HETERO_COLUMN(geom); - return hg->col[u].button.label; + return g_locale_to_utf8(hg->col[u].button.label, -1, 0, 0, 0); } diff --git a/lib/gtksheet/gsheet-row-iface.c b/lib/gtksheet/gsheet-row-iface.c index 01a96afe..7c716d85 100644 --- a/lib/gtksheet/gsheet-row-iface.c +++ b/lib/gtksheet/gsheet-row-iface.c @@ -154,22 +154,20 @@ g_sheet_row_get_sensitivity(const GSheetRow *row_geo, } -const GtkSheetButton * +GtkSheetButton * g_sheet_row_get_button(const GSheetRow *row_geo, gint row, const GtkSheet *sheet) { - static GtkSheetButton button ; + GtkSheetButton *button = gtk_sheet_button_new(); GSheetRowIface *iface = G_SHEET_ROW_GET_IFACE (row_geo); g_return_val_if_fail (G_IS_SHEET_ROW (row_geo), FALSE); - memcpy(&button, &default_button, sizeof (button)); - if ( iface->get_button_label) - button.label = iface->get_button_label(row_geo, row, sheet); + button->label = iface->get_button_label(row_geo, row, sheet); - return &button; + return button; } diff --git a/lib/gtksheet/gsheet-row-iface.h b/lib/gtksheet/gsheet-row-iface.h index a6a62b27..8575620a 100644 --- a/lib/gtksheet/gsheet-row-iface.h +++ b/lib/gtksheet/gsheet-row-iface.h @@ -69,8 +69,8 @@ struct _GSheetRowIface GtkStateType (*get_button_state)(const GSheetRow *geo, gint row, const GtkSheet *); - const gchar * (*get_button_label)(const GSheetRow *geo, gint row, - const GtkSheet *); + gchar * (*get_button_label)(const GSheetRow *geo, gint row, + const GtkSheet *); gboolean (*get_button_visibility)(const GSheetRow *geo, gint row, const GtkSheet *); @@ -101,7 +101,7 @@ gboolean g_sheet_row_get_sensitivity(const GSheetRow *grow, gint row, const GtkSheet *sheet); -const GtkSheetButton *g_sheet_row_get_button(const GSheetRow *grow, +GtkSheetButton *g_sheet_row_get_button(const GSheetRow *grow, gint row, const GtkSheet *sheet); diff --git a/lib/gtksheet/gsheet-uniform-row.c b/lib/gtksheet/gsheet-uniform-row.c index 6ab1c8ff..f25480fb 100644 --- a/lib/gtksheet/gsheet-uniform-row.c +++ b/lib/gtksheet/gsheet-uniform-row.c @@ -123,9 +123,7 @@ g_sheet_uniform_row_get_visibility(const GSheetRow *geom, gint u) static const gchar * g_sheet_uniform_row_get_button_label(const GSheetRow *geom, gint u) { - static gchar *label; - g_free(label); - label = g_strdup_printf("%d", u); + gchar *label = g_strdup_printf("%d", u); return label; } diff --git a/lib/gtksheet/gtkextra-sheet.h b/lib/gtksheet/gtkextra-sheet.h index bfc714ca..0bd573c8 100644 --- a/lib/gtksheet/gtkextra-sheet.h +++ b/lib/gtksheet/gtkextra-sheet.h @@ -68,6 +68,9 @@ typedef struct _GtkSheetButton GtkSheetButton; +GtkSheetButton * gtk_sheet_button_new(void); + +inline void gtk_sheet_button_free(GtkSheetButton *button); #endif /* __GTK_EXTRA_SHEET_H__ */ diff --git a/lib/gtksheet/gtksheet.c b/lib/gtksheet/gtksheet.c index caed10ba..bd506728 100644 --- a/lib/gtksheet/gtksheet.c +++ b/lib/gtksheet/gtksheet.c @@ -260,7 +260,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; @@ -408,7 +408,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; @@ -1807,10 +1807,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); } @@ -1881,10 +1882,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); } @@ -6248,6 +6250,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; @@ -6260,34 +6263,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 @@ -6467,7 +6488,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; @@ -6642,6 +6663,8 @@ gtk_sheet_button_draw (GtkSheet *sheet, gint row, gint column) gtk_widget_queue_draw(child->widget); } } + + gtk_sheet_button_free(button); } @@ -7886,3 +7909,25 @@ gtk_sheet_get_model(const GtkSheet *sheet) return sheet->model; } + +GtkSheetButton * +gtk_sheet_button_new(void) +{ + GtkSheetButton *button = g_slice_new(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_slice_free(GtkSheetButton, button); +} diff --git a/src/language/data-io/ChangeLog b/src/language/data-io/ChangeLog index 21b2ed3c..23f215cf 100644 --- a/src/language/data-io/ChangeLog +++ b/src/language/data-io/ChangeLog @@ -1,3 +1,9 @@ +Thu May 25 18:26:26 WST 2006 John Darrington + + * print.c (print_trns_free): Made the code agree with the comment, by + not freeing PRT. Has the side effect that the command no longer + crashes on invalid syntax. + Tue May 9 20:55:46 2006 Ben Pfaff * get.c (cmd_match_files): Fix memory leak replacing default_dict. diff --git a/src/language/data-io/print.c b/src/language/data-io/print.c index 63270160..b96ee13b 100644 --- a/src/language/data-io/print.c +++ b/src/language/data-io/print.c @@ -141,7 +141,7 @@ static int internal_cmd_print (int f) { int table = 0; /* Print table? */ - struct print_trns *trns; /* malloc()'d transformation. */ + struct print_trns *trns = NULL; /* malloc()'d transformation. */ struct file_handle *fh = NULL; /* Fill in prt to facilitate error-handling. */ @@ -966,7 +966,7 @@ print_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED) return TRNS_CONTINUE; } -/* Frees all the data inside print_trns T. Does not free T. */ +/* Frees all the data inside print_trns PRT. Does not free PRT. */ static bool print_trns_free (void *prt_) { @@ -996,7 +996,6 @@ print_trns_free (void *prt_) if (prt->writer != NULL) ok = dfm_close_writer (prt->writer); free (prt->line); - free (prt); return ok; } diff --git a/src/output/ChangeLog b/src/output/ChangeLog index e4f21a00..04d1dd1a 100644 --- a/src/output/ChangeLog +++ b/src/output/ChangeLog @@ -1,3 +1,7 @@ +Thu May 25 18:02:53 WST 2006 John Darrington + + * table.c: Removed redundant extern declaration. + Sun May 14 14:03:56 2006 Ben Pfaff * output.c (outp_eject_page): Always make sure that a page is open diff --git a/src/output/table.h b/src/output/table.h index 51031da2..6245d12b 100644 --- a/src/output/table.h +++ b/src/output/table.h @@ -102,8 +102,6 @@ struct tab_table int col_ofs, row_ofs; /* X and Y offsets. */ }; -extern int tab_hit; - /* Number of rows in TABLE. */ #define tab_nr(TABLE) ((TABLE)->nr) diff --git a/src/ui/gui/ChangeLog b/src/ui/gui/ChangeLog index 4fe6e3f3..5782b9b5 100644 --- a/src/ui/gui/ChangeLog +++ b/src/ui/gui/ChangeLog @@ -1,3 +1,8 @@ +Thu May 25 18:01:17 WST 2006 John Darrington + + * psppire-var-store.c: Converted strings to utf8 and returned them on the + heap. + Sat May 20 21:08:18 WST 2006 John Darrington * data-sheet.c, menu-actions.c menu-actions: Fixed data sheet so that diff --git a/src/ui/gui/psppire-var-store.c b/src/ui/gui/psppire-var-store.c index 09e1e716..aba27034 100644 --- a/src/ui/gui/psppire-var-store.c +++ b/src/ui/gui/psppire-var-store.c @@ -49,7 +49,7 @@ static void psppire_var_store_class_init (PsppireVarStoreClass *cla static void psppire_var_store_sheet_model_init (GSheetModelIface *iface); static void psppire_var_store_finalize (GObject *object); -static const gchar *psppire_var_store_get_string(GSheetModel *sheet_model, gint row, gint column); +static gchar *psppire_var_store_get_string(GSheetModel *sheet_model, gint row, gint column); static gboolean psppire_var_store_clear(GSheetModel *model, gint row, gint col); @@ -58,7 +58,7 @@ static gboolean psppire_var_store_set_string(GSheetModel *model, const gchar *text, gint row, gint column); -static const gchar *text_for_column(const struct PsppireVariable *pv, gint c); +static gchar *text_for_column(const struct PsppireVariable *pv, gint c, GError **err); static GObjectClass *parent_class = NULL; @@ -297,11 +297,9 @@ psppire_var_store_finalize (GObject *object) (* parent_class->finalize) (object); } -static const gchar * +static gchar * psppire_var_store_get_string(GSheetModel *model, gint row, gint column) { - const gchar *s ; - PsppireVarStore *store = PSPPIRE_VAR_STORE(model); struct PsppireVariable *pv; @@ -311,9 +309,7 @@ psppire_var_store_get_string(GSheetModel *model, gint row, gint column) pv = psppire_dict_get_variable (store->dict, row); - s = text_for_column(pv, column); - - return pspp_locale_to_utf8(s, -1, 0); + return text_for_column(pv, column, 0); } @@ -416,13 +412,9 @@ psppire_var_store_set_string(GSheetModel *model, } -#define MAX_CELL_TEXT_LEN 255 - -static const gchar * -text_for_column(const struct PsppireVariable *pv, gint c) +static gchar * +text_for_column(const struct PsppireVariable *pv, gint c, GError **err) { - static gchar buf[MAX_CELL_TEXT_LEN]; - static gchar none[]=_("None"); static const gchar *const type_label[] = @@ -444,23 +436,23 @@ text_for_column(const struct PsppireVariable *pv, gint c) switch (c) { case COL_NAME: - return psppire_variable_get_name(pv); + return pspp_locale_to_utf8(psppire_variable_get_name(pv), -1, err); break; case COL_TYPE: { switch ( write_spec->type ) { case FMT_F: - return type_label[VT_NUMERIC]; + return g_locale_to_utf8(type_label[VT_NUMERIC], -1, 0, 0, err); break; case FMT_COMMA: - return type_label[VT_COMMA]; + return g_locale_to_utf8(type_label[VT_COMMA], -1, 0, 0, err); break; case FMT_DOT: - return type_label[VT_DOT]; + return g_locale_to_utf8(type_label[VT_DOT], -1, 0, 0, err); break; case FMT_E: - return type_label[VT_SCIENTIFIC]; + return g_locale_to_utf8(type_label[VT_SCIENTIFIC], -1, 0, 0, err); break; case FMT_DATE: case FMT_EDATE: @@ -475,20 +467,20 @@ text_for_column(const struct PsppireVariable *pv, gint c) case FMT_DTIME: case FMT_WKDAY: case FMT_MONTH: - return type_label[VT_DATE]; + return g_locale_to_utf8(type_label[VT_DATE], -1, 0, 0, err); break; case FMT_DOLLAR: - return type_label[VT_DOLLAR]; + return g_locale_to_utf8(type_label[VT_DOLLAR], -1, 0, 0, err); break; case FMT_CCA: case FMT_CCB: case FMT_CCC: case FMT_CCD: case FMT_CCE: - return type_label[VT_CUSTOM]; + return g_locale_to_utf8(type_label[VT_CUSTOM], -1, 0, 0, err); break; case FMT_A: - return type_label[VT_STRING]; + return g_locale_to_utf8(type_label[VT_STRING], -1, 0, 0, err); break; default: g_warning("Unknown format: \"%s\"\n", @@ -499,93 +491,109 @@ text_for_column(const struct PsppireVariable *pv, gint c) break; case COL_WIDTH: { - g_snprintf(buf, MAX_CELL_TEXT_LEN, "%d", write_spec->w); - return buf; + gchar *s; + GString *gstr = g_string_sized_new(10); + g_string_printf(gstr, "%d", write_spec->w); + s = g_locale_to_utf8(gstr->str, gstr->len, 0, 0, err); + g_string_free(gstr, TRUE); + return s; } break; case COL_DECIMALS: { - g_snprintf(buf, MAX_CELL_TEXT_LEN, "%d", write_spec->d); - return buf; + gchar *s; + GString *gstr = g_string_sized_new(10); + g_string_printf(gstr, "%d", write_spec->d); + s = g_locale_to_utf8(gstr->str, gstr->len, 0, 0, err); + g_string_free(gstr, TRUE); + return s; } break; case COL_COLUMNS: { - g_snprintf(buf, MAX_CELL_TEXT_LEN, - "%d", psppire_variable_get_columns(pv)); - return buf; + gchar *s; + GString *gstr = g_string_sized_new(10); + g_string_printf(gstr, "%d", psppire_variable_get_columns(pv)); + s = g_locale_to_utf8(gstr->str, gstr->len, 0, 0, err); + g_string_free(gstr, TRUE); + return s; } break; case COL_LABEL: - return psppire_variable_get_label(pv); + return g_locale_to_utf8(psppire_variable_get_label(pv), -1, 0, 0, err); break; + case COL_MISSING: { - const struct missing_values *miss = psppire_variable_get_missing(pv); - if ( mv_is_empty(miss)) - return none; - else - { - if ( ! mv_has_range (miss)) - { - const int n = mv_n_values(miss); - gchar *mv[4] = {0,0,0,0}; - gint i; - for(i = 0 ; i < n; ++i ) - { - union value v; - mv_peek_value(miss, &v, i); - mv[i] = value_to_text(v, *write_spec); - } - g_stpcpy(buf, ""); - for(i = 0 ; i < n; ++i ) - { - if ( i > 0) - g_strlcat(buf, ", ", MAX_CELL_TEXT_LEN); - g_strlcat(buf, mv[i], MAX_CELL_TEXT_LEN); - g_free(mv[i]); - } - } - else - { - gchar *l, *h; - union value low, high; - mv_peek_range(miss, &low.f, &high.f); + gchar *s; + const struct missing_values *miss = psppire_variable_get_missing(pv); + if ( mv_is_empty(miss)) + return g_locale_to_utf8(none, -1, 0, 0, err); + else + { + if ( ! mv_has_range (miss)) + { + GString *gstr = g_string_sized_new(10); + const int n = mv_n_values(miss); + gchar *mv[4] = {0,0,0,0}; + gint i; + for(i = 0 ; i < n; ++i ) + { + union value v; + mv_peek_value(miss, &v, i); + mv[i] = value_to_text(v, *write_spec); + if ( i > 0 ) + g_string_append(gstr, ", "); + g_string_append(gstr, mv[i]); + g_free(mv[i]); + } + s = pspp_locale_to_utf8(gstr->str, gstr->len, err); + g_string_free(gstr, TRUE); + } + else + { + GString *gstr = g_string_sized_new(10); + gchar *l, *h; + union value low, high; + mv_peek_range(miss, &low.f, &high.f); - l = value_to_text(low, *write_spec); - h = value_to_text(high, *write_spec); - - g_snprintf(buf, MAX_CELL_TEXT_LEN, "%s - %s", l, h); - g_free(l); - g_free(h); - - if ( mv_has_value(miss)) - { - gchar buf2[MAX_CELL_TEXT_LEN]; - gchar *s = 0; - union value v; - mv_peek_value(miss, &v, 0); - - s = value_to_text(v, *write_spec); - - g_snprintf(buf2, MAX_CELL_TEXT_LEN, "%s, %s", buf, s); - free(s); - g_stpcpy(buf, buf2); - } - } - - return buf; - } + l = value_to_text(low, *write_spec); + h = value_to_text(high, *write_spec); + + g_string_printf(gstr, "%s - %s", l, h); + g_free(l); + g_free(h); + + if ( mv_has_value(miss)) + { + gchar *ss = 0; + union value v; + mv_peek_value(miss, &v, 0); + + ss = value_to_text(v, *write_spec); + + g_string_append(gstr, ", "); + g_string_append(gstr, ss); + free(ss); + } + s = pspp_locale_to_utf8(gstr->str, gstr->len, err); + g_string_free(gstr, TRUE); + } + + return s; + } } break; case COL_VALUES: { const struct val_labs *vls = psppire_variable_get_value_labels(pv); - if ( ! vls || 0 == val_labs_count(vls)) - return none; + if ( ! vls || 0 == val_labs_count(vls) ) + return g_locale_to_utf8(none, -1, 0, 0, err); else { - struct val_labs_iterator *ip=0; + gchar *ss; + GString *gstr = g_string_sized_new(10); + struct val_labs_iterator *ip = 0; struct val_lab *vl = val_labs_first_sorted (vls, &ip); g_assert(vl); @@ -593,22 +601,27 @@ text_for_column(const struct PsppireVariable *pv, gint c) { gchar *const vstr = value_to_text(vl->value, *write_spec); - g_snprintf(buf, MAX_CELL_TEXT_LEN, "{%s,\"%s\"}_", vstr, vl->label); + g_string_printf(gstr, "{%s,\"%s\"}_", vstr, vl->label); g_free(vstr); } val_labs_done(&ip); - - return buf; + + ss = pspp_locale_to_utf8(gstr->str, gstr->len, err); + g_string_free(gstr, TRUE); + return ss; } } break; case COL_ALIGN: - return alignments[psppire_variable_get_alignment(pv)]; + return g_locale_to_utf8(alignments[psppire_variable_get_alignment(pv)], + -1, -0, 0, err); break; case COL_MEASURE: - return measures[psppire_variable_get_measure(pv)]; + return g_locale_to_utf8(measures[psppire_variable_get_measure(pv)], + -1, -0, 0, err); break; + } return 0; } @@ -636,3 +649,4 @@ psppire_var_store_set_font(PsppireVarStore *store, PangoFontDescription *fd) + diff --git a/tests/automake.mk b/tests/automake.mk index e8094484..03378596 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -91,6 +91,7 @@ TESTS = \ tests/bugs/computebug.sh \ tests/bugs/compute-lv.sh \ tests/bugs/temp-freq.sh \ + tests/bugs/print-crash.sh \ tests/xforms/casefile.sh \ tests/stats/descript-basic.sh \ tests/stats/descript-missing.sh \ diff --git a/tests/bugs/print-crash.sh b/tests/bugs/print-crash.sh new file mode 100755 index 00000000..d362ede1 --- /dev/null +++ b/tests/bugs/print-crash.sh @@ -0,0 +1,75 @@ +#!/bin/sh + +# This program tests for a bug which crashed when deallocating after a bad +# PRINT command. + +TEMPDIR=/tmp/pspp-tst-$$ +TESTFILE=$TEMPDIR/`basename $0`.sps + +# ensure that top_srcdir and top_builddir are absolute +if [ -z "$top_srcdir" ] ; then top_srcdir=. ; fi +if [ -z "$top_builddir" ] ; then top_builddir=. ; fi +top_srcdir=`cd $top_srcdir; pwd` +top_builddir=`cd $top_builddir; pwd` + +PSPP=$top_builddir/src/ui/terminal/pspp + +export STAT_CONFIG_PATH=$top_srcdir/config + + +cleanup() +{ + if [ x"$PSPP_TEST_NO_CLEANUP" != x ] ; then + echo "NOT cleaning $TEMPDIR" + return ; + fi + rm -rf $TEMPDIR +} + + +fail() +{ + echo $activity + echo FAILED + cleanup; + exit 1; +} + + +no_result() +{ + echo $activity + echo NO RESULT; + cleanup; + exit 2; +} + +pass() +{ + cleanup; + exit 0; +} + +mkdir -p $TEMPDIR + +cd $TEMPDIR + +cat > $TESTFILE << EOF +DATA LIST LIST /a * b *. +BEGIN DATA. +1 2 +3 4 +END DATA. + +PRINT F8.2 +LIST. +EOF +if [ $? -ne 0 ] ; then no_result ; fi + + +activity="run program" +$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE > /dev/null +if [ $? -ne 1 ] ; then fail ; fi + + +pass; -- 2.30.2