X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Ftext-data-import-dialog.c;h=e5c48fdb217c83684c640520bd993f2d4a20e4b9;hb=bc19562deb692e6db3271eb0402e9f9c99e4cbcb;hp=8eebf9775677954e17f0a19f73ca9a8273a16e45;hpb=f15c854d8500105766b2f5666bb62b983ff24f88;p=pspp-builds.git diff --git a/src/ui/gui/text-data-import-dialog.c b/src/ui/gui/text-data-import-dialog.c index 8eebf977..e5c48fdb 100644 --- a/src/ui/gui/text-data-import-dialog.c +++ b/src/ui/gui/text-data-import-dialog.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2008, 2009 Free Software Foundation + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,39 +16,38 @@ #include -#include - - - -#include "checkbox-treeview.h" -#include "descriptives-dialog.h" +#include "ui/gui/text-data-import-dialog.h" #include - #include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "executor.h" - -#include "error.h" -#include "xalloc.h" +#include "data/data-in.h" +#include "data/data-out.h" +#include "data/format-guesser.h" +#include "data/value-labels.h" +#include "language/data-io/data-parser.h" +#include "language/lexer/lexer.h" +#include "libpspp/assertion.h" +#include "libpspp/i18n.h" +#include "libpspp/message.h" +#include "ui/gui/checkbox-treeview.h" +#include "ui/gui/descriptives-dialog.h" +#include "ui/gui/dialog-common.h" +#include "ui/gui/executor.h" +#include "ui/gui/helper.h" +#include "ui/gui/psppire-data-window.h" +#include "ui/gui/psppire-dialog.h" +#include "ui/gui/psppire-var-sheet.h" +#include "ui/gui/psppire-var-store.h" +#include "ui/gui/widget-io.h" +#include "ui/syntax-gen.h" + +#include "gl/error.h" +#include "gl/xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -227,13 +226,13 @@ static GtkTreeViewColumn *make_data_column (struct import_assistant *, gint column_idx); static GtkTreeView *create_data_tree_view (bool input, GtkContainer *parent, struct import_assistant *); -static void escape_underscores (const char *in, char *out); +static char *escape_underscores (const char *in); static void push_watch_cursor (struct import_assistant *); static void pop_watch_cursor (struct import_assistant *); /* Pops up the Text Data Import assistant. */ void -text_data_import_assistant (GObject *o, GtkWindow *parent_window) +text_data_import_assistant (GtkWindow *parent_window) { struct import_assistant *ia; @@ -259,18 +258,10 @@ text_data_import_assistant (GObject *o, GtkWindow *parent_window) switch (ia->asst.response) { case GTK_RESPONSE_APPLY: - { - char *syntax = generate_syntax (ia); - execute_syntax (create_syntax_string_source (syntax)); - free (syntax); - } + free (execute_syntax_string (generate_syntax (ia))); break; case PSPPIRE_RESPONSE_PASTE: - { - char *syntax = generate_syntax (ia); - paste_syntax_in_new_window (syntax); - free (syntax); - } + free (paste_syntax_to_window (generate_syntax (ia))); break; default: break; @@ -338,7 +329,7 @@ apply_dict (const struct dictionary *dict, struct string *s) const struct val_lab *vl = labels[i]; ds_put_cstr (s, "\n "); syntax_gen_value (s, &vl->value, width, format); - ds_put_char (s, ' '); + ds_put_byte (s, ' '); syntax_gen_string (s, ss_cstr (val_lab_get_label (vl))); } free (labels); @@ -398,9 +389,9 @@ generate_syntax (const struct import_assistant *ia) if (ia->first_line.skip_lines > 0) ds_put_format (&s, " /FIRSTCASE=%d\n", ia->first_line.skip_lines + 1); ds_put_cstr (&s, " /DELIMITERS=\""); - if (ds_find_char (&ia->separators.separators, '\t') != SIZE_MAX) + if (ds_find_byte (&ia->separators.separators, '\t') != SIZE_MAX) ds_put_cstr (&s, "\\t"); - if (ds_find_char (&ia->separators.separators, '\\') != SIZE_MAX) + if (ds_find_byte (&ia->separators.separators, '\\') != SIZE_MAX) ds_put_cstr (&s, "\\\\"); for (i = 0; i < ds_length (&ia->separators.separators); i++) { @@ -408,7 +399,7 @@ generate_syntax (const struct import_assistant *ia) if (c == '"') ds_put_cstr (&s, "\"\""); else if (c != '\t' && c != '\\') - ds_put_char (&s, c); + ds_put_byte (&s, c); } ds_put_cstr (&s, "\"\n"); if (!ds_is_empty (&ia->separators.quotes)) @@ -458,7 +449,7 @@ init_file (struct import_assistant *ia, GtkWindow *parent_window) stream = fopen (file->file_name, "r"); if (stream == NULL) { - msg (ME, _("Could not open \"%s\": %s"), + msg (ME, _("Could not open `%s': %s"), file->file_name, strerror (errno)); return false; } @@ -474,10 +465,10 @@ init_file (struct import_assistant *ia, GtkWindow *parent_window) if (feof (stream)) break; else if (ferror (stream)) - msg (ME, _("Error reading \"%s\": %s"), + msg (ME, _("Error reading `%s': %s"), file->file_name, strerror (errno)); else - msg (ME, _("Failed to read \"%s\", because it contains a line " + msg (ME, _("Failed to read `%s', because it contains a line " "over %d bytes long and therefore appears not to be " "a text file."), file->file_name, MAX_LINE_LEN); @@ -491,7 +482,7 @@ init_file (struct import_assistant *ia, GtkWindow *parent_window) if (file->line_cnt == 0) { - msg (ME, _("\"%s\" is empty."), file->file_name); + msg (ME, _("`%s' is empty."), file->file_name); fclose (stream); destroy_file (ia); return false; @@ -720,8 +711,7 @@ close_assistant (struct import_assistant *ia, int response) /* The "intro" page of the assistant. */ -static void on_intro_amount_changed (GtkToggleButton *button, - struct import_assistant *); +static void on_intro_amount_changed (struct import_assistant *); /* Initializes IA's intro substructure. */ static void @@ -730,21 +720,47 @@ init_intro_page (struct import_assistant *ia) GtkBuilder *builder = ia->asst.builder; struct intro_page *p = &ia->intro; struct string s; + GtkWidget *hbox_n_cases ; + GtkWidget *hbox_percent ; + GtkWidget *table ; + + + p->n_cases_spin = gtk_spin_button_new_with_range (0, INT_MAX, 100); + + hbox_n_cases = widget_scanf (_("Only the first %4d cases"), &p->n_cases_spin); + + table = get_widget_assert (builder, "button-table"); + + gtk_table_attach_defaults (GTK_TABLE (table), hbox_n_cases, + 1, 2, + 1, 2); + + p->percent_spin = gtk_spin_button_new_with_range (0, 100, 10); + + hbox_percent = widget_scanf (_("Only the first %3d %% of file (approximately)"), &p->percent_spin); + + gtk_table_attach_defaults (GTK_TABLE (table), hbox_percent, + 1, 2, + 2, 3); p->page = add_page_to_assistant (ia, get_widget_assert (builder, "Intro"), GTK_ASSISTANT_PAGE_INTRO); + p->all_cases_button = get_widget_assert (builder, "import-all-cases"); + p->n_cases_button = get_widget_assert (builder, "import-n-cases"); - p->n_cases_spin = get_widget_assert (builder, "n-cases-spin"); + p->percent_button = get_widget_assert (builder, "import-percent"); - p->percent_spin = get_widget_assert (builder, "percent-spin"); - g_signal_connect (p->all_cases_button, "toggled", + + g_signal_connect_swapped (p->all_cases_button, "toggled", G_CALLBACK (on_intro_amount_changed), ia); - g_signal_connect (p->n_cases_button, "toggled", + g_signal_connect_swapped (p->n_cases_button, "toggled", G_CALLBACK (on_intro_amount_changed), ia); - g_signal_connect (p->percent_button, "toggled", + g_signal_connect_swapped (p->percent_button, "toggled", G_CALLBACK (on_intro_amount_changed), ia); + on_intro_amount_changed (ia); + ds_init_empty (&s); ds_put_cstr (&s, _("This assistant will guide you through the process of " "importing data into PSPP from a text file with one line " @@ -790,8 +806,7 @@ reset_intro_page (struct import_assistant *ia) /* Called when one of the radio buttons is clicked. */ static void -on_intro_amount_changed (GtkToggleButton *button UNUSED, - struct import_assistant *ia) +on_intro_amount_changed (struct import_assistant *ia) { struct intro_page *p = &ia->intro; @@ -799,7 +814,7 @@ on_intro_amount_changed (GtkToggleButton *button UNUSED, gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON (p->n_cases_button))); - gtk_widget_set_sensitive (ia->intro.percent_spin, + gtk_widget_set_sensitive (p->percent_spin, gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON (p->percent_button))); } @@ -857,13 +872,16 @@ create_lines_tree_view (GtkContainer *parent, struct import_assistant *ia) size_t max_line_length; gint content_width, header_width; size_t i; + gchar *title = _("Text"); make_tree_view (ia, 0, &tree_view); - column = gtk_tree_view_column_new_with_attributes ( - "Text", ia->asst.fixed_renderer, - "text", TEXT_IMPORT_MODEL_COLUMN_LINE, - (void *) NULL); + column = gtk_tree_view_column_new_with_attributes + ( + title, ia->asst.fixed_renderer, + "text", TEXT_IMPORT_MODEL_COLUMN_LINE, + (void *) NULL + ); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); max_line_length = 0; @@ -875,7 +893,7 @@ create_lines_tree_view (GtkContainer *parent, struct import_assistant *ia) content_width = get_monospace_width (tree_view, ia->asst.fixed_renderer, max_line_length); - header_width = get_string_width (tree_view, ia->asst.prop_renderer, "Text"); + header_width = get_string_width (tree_view, ia->asst.prop_renderer, title); gtk_tree_view_column_set_fixed_width (column, MAX (content_width, header_width)); gtk_tree_view_append_column (tree_view, column); @@ -1142,7 +1160,7 @@ split_fields (struct import_assistant *ia) clear_fields (ia); /* Is space in the set of separators? */ - space_sep = ss_find_char (ds_ss (&s->separators), ' ') != SIZE_MAX; + space_sep = ss_find_byte (ds_ss (&s->separators), ' ') != SIZE_MAX; /* Split all the lines, not just those from ia->first_line.skip_lines on, so that we split the line that @@ -1169,9 +1187,9 @@ split_fields (struct import_assistant *ia) field = text; } else if (!ds_is_empty (&s->quotes) - && ds_find_char (&s->quotes, text.string[0]) != SIZE_MAX) + && ds_find_byte (&s->quotes, text.string[0]) != SIZE_MAX) { - int quote = ss_get_char (&text); + int quote = ss_get_byte (&text); if (!s->escape) ss_get_until (&text, quote, &field); else @@ -1180,18 +1198,18 @@ split_fields (struct import_assistant *ia) int c; ds_init_empty (&s); - while ((c = ss_get_char (&text)) != EOF) + while ((c = ss_get_byte (&text)) != EOF) if (c != quote) - ds_put_char (&s, c); - else if (ss_match_char (&text, quote)) - ds_put_char (&s, quote); + ds_put_byte (&s, c); + else if (ss_match_byte (&text, quote)) + ds_put_byte (&s, quote); else break; field = ds_ss (&s); } } else - ss_get_chars (&text, ss_cspan (text, ds_ss (&s->separators)), + ss_get_bytes (&text, ss_cspan (text, ds_ss (&s->separators)), &field); if (column_idx >= s->column_cnt) @@ -1216,7 +1234,7 @@ split_fields (struct import_assistant *ia) ss_ltrim (&text, ss_cstr (" ")); if (ss_is_empty (text)) break; - if (ss_find_char (ds_ss (&s->separators), ss_first (text)) + if (ss_find_byte (ds_ss (&s->separators), ss_first (text)) != SIZE_MAX) ss_advance (&text, 1); } @@ -1238,15 +1256,13 @@ choose_column_names (struct import_assistant *ia) name_row = f->variable_names && f->skip_lines ? f->skip_lines : 0; for (col = s->columns; col < &s->columns[s->column_cnt]; col++) { - char name[VAR_NAME_LEN + 1]; - char *hint; + char *hint, *name; hint = name_row ? ss_xstrdup (col->contents[name_row - 1]) : NULL; - if (!dict_make_unique_var_name (dict, hint, &generated_name_count, name)) - NOT_REACHED (); + name = dict_make_unique_var_name (dict, hint, &generated_name_count); free (hint); - col->name = xstrdup (name); + col->name = name; dict_create_var_assert (dict, name, 0); } dict_destroy (dict); @@ -1304,7 +1320,7 @@ find_commonest_chars (unsigned long int histogram[UCHAR_MAX + 1], if (max_count > 0) { ds_clear (result); - ds_put_char (result, max); + ds_put_byte (result, max); } else ds_assign_cstr (result, def); @@ -1360,7 +1376,7 @@ set_separators (struct import_assistant *ia) } } - ds_put_char (&custom, c); + ds_put_byte (&custom, c); next:; } @@ -1403,7 +1419,7 @@ get_separators (struct import_assistant *ia) const struct separator *sep = &separators[i]; GtkWidget *button = get_widget_assert (ia->asst.builder, sep->name); if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) - ds_put_char (&s->separators, sep->c); + ds_put_byte (&s->separators, sep->c); } if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (s->custom_cb))) @@ -1543,6 +1559,7 @@ init_formats_page (struct import_assistant *ia) p->data_tree_view = GTK_TREE_VIEW (get_widget_assert (builder, "data")); p->modified_vars = NULL; p->modified_var_cnt = 0; + p->dict = NULL; } /* Frees IA's formats substructure. */ @@ -1583,7 +1600,6 @@ prepare_formats_page (struct import_assistant *ia) for (column_idx = 0; column_idx < s->column_cnt; column_idx++) { struct variable *modified_var; - char name[VAR_NAME_LEN + 1]; modified_var = (column_idx < p->modified_var_cnt ? p->modified_vars[column_idx] : NULL); @@ -1592,11 +1608,11 @@ prepare_formats_page (struct import_assistant *ia) struct column *column = &s->columns[column_idx]; struct variable *var; struct fmt_spec format; + char *name; size_t row; /* Choose variable name. */ - if (!dict_make_unique_var_name (dict, column->name, &number, name)) - NOT_REACHED (); + name = dict_make_unique_var_name (dict, column->name, &number); /* Choose variable format. */ fmt_guesser_clear (fg); @@ -1608,13 +1624,17 @@ prepare_formats_page (struct import_assistant *ia) /* Create variable. */ var = dict_create_var_assert (dict, name, fmt_var_width (&format)); var_set_both_formats (var, &format); + + free (name); } else { - if (!dict_make_unique_var_name (dict, var_get_name (modified_var), - &number, name)) - NOT_REACHED (); - dict_clone_var_assert (dict, modified_var, name); + char *name; + + name = dict_make_unique_var_name (dict, var_get_name (modified_var), + &number); + dict_clone_var_as_assert (dict, modified_var, name); + free (name); } } fmt_guesser_destroy (fg); @@ -1747,18 +1767,18 @@ parse_field (struct import_assistant *ia, tooltip = NULL; if (field.string != NULL) { - msg_disable (); - if (!data_in (field, LEGACY_NATIVE, in->type, 0, 0, 0, - &val, var_get_width (var))) + char *error; + + error = data_in (field, C_ENCODING, in->type, &val, var_get_width (var), + dict_get_encoding (ia->formats.dict)); + if (error != NULL) { - char fmt_string[FMT_STRING_LEN_MAX + 1]; - fmt_to_string (in, fmt_string); - tooltip = xasprintf (_("Field content \"%.*s\" cannot be parsed in " - "format %s."), + tooltip = xasprintf (_("Cannot parse field content `%.*s' as " + "format %s: %s"), (int) field.length, field.string, - fmt_string); + fmt_name (in->type), error); + free (error); } - msg_enable (); } else { @@ -1768,7 +1788,7 @@ parse_field (struct import_assistant *ia, } if (outputp != NULL) { - *outputp = data_out (&val, &out); + *outputp = data_out (&val, dict_get_encoding (ia->formats.dict), &out); } value_destroy (&val, var_get_width (var)); @@ -1906,7 +1926,7 @@ add_line_number_column (const struct import_assistant *ia, GtkTreeViewColumn *column; column = gtk_tree_view_column_new_with_attributes ( - "Line", ia->asst.prop_renderer, + _("Line"), ia->asst.prop_renderer, "text", TEXT_IMPORT_MODEL_COLUMN_LINE_NUMBER, (void *) NULL); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); @@ -1923,8 +1943,8 @@ get_monospace_width (GtkTreeView *treeview, GtkCellRenderer *renderer, gint width; ds_init_empty (&s); - ds_put_char_multiple (&s, '0', char_cnt); - ds_put_char (&s, ' '); + ds_put_byte_multiple (&s, '0', char_cnt); + ds_put_byte (&s, ' '); width = get_string_width (treeview, renderer, ds_cstr (&s)); ds_destroy (&s); @@ -1948,17 +1968,17 @@ make_data_column (struct import_assistant *ia, GtkTreeView *tree_view, { struct variable *var = NULL; struct column *column = NULL; - char name[(VAR_NAME_LEN * 2) + 1]; size_t char_cnt; gint content_width, header_width; GtkTreeViewColumn *tree_column; + char *name; if (input) column = &ia->separators.columns[dict_idx]; else var = dict_get_var (ia->formats.dict, dict_idx); - escape_underscores (input ? column->name : var_get_name (var), name); + name = escape_underscores (input ? column->name : var_get_name (var)); char_cnt = input ? column->width : var_get_print_format (var)->w; content_width = get_monospace_width (tree_view, ia->asst.fixed_renderer, char_cnt); @@ -1978,6 +1998,8 @@ make_data_column (struct import_assistant *ia, GtkTreeView *tree_view, gtk_tree_view_column_set_fixed_width (tree_column, MAX (content_width, header_width)); + free (name); + return tree_column; } @@ -2008,16 +2030,22 @@ create_data_tree_view (bool input, GtkContainer *parent, return tree_view; } -static void -escape_underscores (const char *in, char *out) +static char * +escape_underscores (const char *in) { + char *out = xmalloc (2 * strlen (in) + 1); + char *p; + + p = out; for (; *in != '\0'; in++) { if (*in == '_') - *out++ = '_'; - *out++ = *in; + *p++ = '_'; + *p++ = *in; } - *out = '\0'; + *p = '\0'; + + return out; } /* TextImportModel, a GtkTreeModel implementation used by some