+
+static void
+first_line_append_syntax (const PsppireImportAssistant *ia, struct string *s)
+{
+ gint first_case = 0;
+ g_object_get (ia->delimiters_model, "first-line", &first_case, NULL);
+
+ if (first_case > 0)
+ ds_put_format (s, " /FIRSTCASE=%d\n", first_case + 1);
+}
+
+/* Emits PSPP syntax to S that applies the dictionary attributes
+ (such as missing values and value labels) of the variables in
+ DICT. */
+static void
+apply_dict (const struct dictionary *dict, struct string *s)
+{
+ size_t n_vars = dict_get_n_vars (dict);
+
+ for (size_t i = 0; i < n_vars; i++)
+ {
+ struct variable *var = dict_get_var (dict, i);
+ const char *name = var_get_name (var);
+ enum val_type type = var_get_type (var);
+ int width = var_get_width (var);
+ enum measure measure = var_get_measure (var);
+ enum var_role role = var_get_role (var);
+ enum alignment alignment = var_get_alignment (var);
+ const struct fmt_spec *format = var_get_print_format (var);
+
+ if (var_has_missing_values (var))
+ {
+ const struct missing_values *mv = var_get_missing_values (var);
+ size_t j;
+
+ syntax_gen_pspp (s, "MISSING VALUES %ss (", name);
+ for (j = 0; j < mv_n_values (mv); j++)
+ {
+ if (j)
+ ds_put_cstr (s, ", ");
+ syntax_gen_value (s, mv_get_value (mv, j), width, format);
+ }
+
+ if (mv_has_range (mv))
+ {
+ double low, high;
+ if (mv_has_value (mv))
+ ds_put_cstr (s, ", ");
+ mv_get_range (mv, &low, &high);
+ syntax_gen_num_range (s, low, high, format);
+ }
+ ds_put_cstr (s, ").\n");
+ }
+ if (var_has_value_labels (var))
+ {
+ const struct val_labs *vls = var_get_value_labels (var);
+ const struct val_lab **labels = val_labs_sorted (vls);
+ size_t n_labels = val_labs_count (vls);
+
+ syntax_gen_pspp (s, "VALUE LABELS %ss", name);
+ for (size_t j = 0; j < n_labels; j++)
+ {
+ const struct val_lab *vl = labels[j];
+ ds_put_cstr (s, "\n ");
+ syntax_gen_value (s, &vl->value, width, format);
+ ds_put_byte (s, ' ');
+ syntax_gen_string (s, ss_cstr (val_lab_get_escaped_label (vl)));
+ }
+ free (labels);
+ ds_put_cstr (s, ".\n");
+ }
+ if (var_has_label (var))
+ syntax_gen_pspp (s, "VARIABLE LABELS %ss %sq.\n",
+ name, var_get_label (var));
+ if (measure != var_default_measure_for_type (type)
+ && measure != MEASURE_UNKNOWN)
+ syntax_gen_pspp (s, "VARIABLE LEVEL %ss (%ss).\n",
+ name, measure_to_syntax (measure));
+ if (role != ROLE_INPUT)
+ syntax_gen_pspp (s, "VARIABLE ROLE /%ss %ss.\n",
+ var_role_to_syntax (role), name);
+ if (alignment != var_default_alignment (type))
+ syntax_gen_pspp (s, "VARIABLE ALIGNMENT %ss (%ss).\n",
+ name, alignment_to_syntax (alignment));
+ if (var_get_display_width (var) != var_default_display_width (width))
+ syntax_gen_pspp (s, "VARIABLE WIDTH %ss (%d).\n",
+ name, var_get_display_width (var));
+ }
+}
+
+
+static void
+intro_append_syntax (const PsppireImportAssistant *ia, struct string *s)
+{
+ gint first_line = 0;
+ g_object_get (ia->delimiters_model, "first-line", &first_line, NULL);
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ia->n_cases_button)))
+ ds_put_format (s, "SELECT IF ($CASENUM <= %d).\n",
+ gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (ia->n_cases_spin)) - first_line);
+ else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ia->percent_button)))
+ ds_put_format (s, "SAMPLE %.4g.\n",
+ gtk_spin_button_get_value (GTK_SPIN_BUTTON (ia->percent_spin)) / 100.0);
+}
+
+
+static void
+formats_append_syntax (const PsppireImportAssistant *ia, struct string *s)
+{
+ g_return_if_fail (ia->dict);
+
+ ds_put_cstr (s, " /VARIABLES=\n");
+
+ int n_vars = dict_get_n_vars (ia->dict);
+ for (int i = 0; i < n_vars; i++)
+ {
+ struct variable *var = dict_get_var (ia->dict, i);
+ char format_string[FMT_STRING_LEN_MAX + 1];
+ fmt_to_string (var_get_print_format (var), format_string);
+ ds_put_format (s, " %s %s%s\n",
+ var_get_name (var), format_string,
+ i == n_vars - 1 ? "." : "");
+ }
+}
+
+static void
+separators_append_syntax (const PsppireImportAssistant *ia, struct string *s)
+{
+ int i;
+
+ ds_put_cstr (s, " /DELIMITERS=\"");
+
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (get_widget_assert (ia->text_builder, "tab"))))
+ ds_put_cstr (s, "\\t");
+ for (i = 0; i < N_SEPARATORS; i++)
+ {
+ const struct separator *seps = &separators[i];
+ GtkWidget *button = get_widget_assert (ia->text_builder, seps->name);
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
+ {
+ if (seps->c == '\t')
+ continue;
+
+ ds_put_byte (s, seps->c);
+ }
+ }
+ ds_put_cstr (s, "\"\n");
+
+ gunichar quote = get_quote_character (ia);
+ if (quote)
+ {
+ GString *quote_s = g_string_new (NULL);
+ g_string_append_unichar (quote_s, quote);
+ syntax_gen_pspp (s, " /QUALIFIER=%sq\n", quote_s->str);
+ g_string_free (quote_s, TRUE);
+ }
+}
+
+
+void
+text_spec_gen_syntax (PsppireImportAssistant *ia, struct string *s)
+{
+ gchar *file_name = NULL;
+ gchar *encoding = NULL;
+ g_object_get (ia->text_file,
+ "file-name", &file_name,
+ "encoding", &encoding,
+ NULL);
+
+ if (file_name == NULL)
+ return;
+
+ syntax_gen_pspp (s,
+ "GET DATA"
+ "\n /TYPE=TXT"
+ "\n /FILE=%sq\n",
+ file_name);
+ if (encoding && strcmp (encoding, "Auto"))
+ syntax_gen_pspp (s, " /ENCODING=%sq\n", encoding);
+
+ ds_put_cstr (s,
+ " /ARRANGEMENT=DELIMITED\n"
+ " /DELCASE=LINE\n");
+
+ first_line_append_syntax (ia, s);
+ separators_append_syntax (ia, s);
+
+ formats_append_syntax (ia, s);
+ apply_dict (ia->dict, s);
+ intro_append_syntax (ia, s);
+}