gui: Honor quotes in the text data import dialog.
[pspp] / src / ui / gui / psppire-import-textfile.c
index 4c0e9bc9cdd58ba86e1d01617f635ecf60f394cd..c3192f555bacc408e88def19be1a38958a82b713 100644 (file)
 static void choose_column_names (PsppireImportAssistant *ia);
 
 /* Revises the contents of the fields tree view based on the
-   currently chosen set of separators. */
+   currently chosen set of separators and quotes. */
 static void
 revise_fields_preview (PsppireImportAssistant *ia)
 {
+  GSList *delimiters = NULL;
+  for (int i = 0; i < N_SEPARATORS; i++)
+    {
+      const struct separator *s = &separators[i];
+      GtkWidget *button = get_widget_assert (ia->text_builder, s->name);
+      if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
+       {
+         delimiters = g_slist_prepend (delimiters,  GINT_TO_POINTER (s->c));
+       }
+    }
+
+  GtkComboBoxText *cbt = GTK_COMBO_BOX_TEXT (ia->quote_combo);
+  GtkToggleButton *quote_cb = GTK_TOGGLE_BUTTON (ia->quote_cb);
+  const gchar *quotes = (gtk_toggle_button_get_active (quote_cb)
+                         ? gtk_combo_box_text_get_active_text (cbt)
+                         : "");
+
+  g_object_set (ia->delimiters_model,
+                "delimiters", delimiters,
+                "quotes", quotes,
+                NULL);
+
   choose_column_names (ia);
 }
 
@@ -75,8 +97,8 @@ choose_likely_separators (PsppireImportAssistant *ia)
   gboolean valid;
   GtkTreeIter iter;
 
-  struct hmap count_map[SEPARATOR_CNT];
-  for (int j = 0; j < SEPARATOR_CNT; ++j)
+  struct hmap count_map[N_SEPARATORS];
+  for (int j = 0; j < N_SEPARATORS; ++j)
     hmap_init (count_map + j);
 
   GtkTreePath *p = gtk_tree_path_new_from_indices (first_line, -1);
@@ -88,7 +110,7 @@ choose_likely_separators (PsppireImportAssistant *ia)
       gchar *line_text = NULL;
       gtk_tree_model_get (GTK_TREE_MODEL (ia->text_file), &iter, 1, &line_text, -1);
 
-      gint *counts = xzalloc (sizeof *counts * SEPARATOR_CNT);
+      gint *counts = XCALLOC (N_SEPARATORS, gint);
 
       struct substring cs = ss_cstr (line_text);
       for (;
@@ -98,7 +120,7 @@ choose_likely_separators (PsppireImportAssistant *ia)
          ucs4_t character = ss_first_mb (cs);
 
          int s;
-         for (s = 0; s < SEPARATOR_CNT; ++s)
+         for (s = 0; s < N_SEPARATORS; ++s)
            {
              if (character == separators[s].c)
                counts[s]++;
@@ -106,7 +128,7 @@ choose_likely_separators (PsppireImportAssistant *ia)
        }
 
       int j;
-      for (j = 0; j < SEPARATOR_CNT; ++j)
+      for (j = 0; j < N_SEPARATORS; ++j)
        {
          if (counts[j] > 0)
            {
@@ -120,7 +142,7 @@ choose_likely_separators (PsppireImportAssistant *ia)
 
              if (cn == NULL)
                {
-                 struct separator_count_node *new_cn = xzalloc (sizeof *new_cn);
+                 struct separator_count_node *new_cn = XZALLOC (struct separator_count_node);
                  new_cn->occurance = counts[j];
                  new_cn->quantity = 1;
                  hmap_insert (&count_map[j], &new_cn->node, hash);
@@ -139,7 +161,7 @@ choose_likely_separators (PsppireImportAssistant *ia)
     {
       int most_frequent = -1;
       int largest = 0;
-      for (int j = 0; j < SEPARATOR_CNT; ++j)
+      for (int j = 0; j < N_SEPARATORS; ++j)
         {
           struct separator_count_node *cn;
           struct separator_count_node *next;
@@ -420,8 +442,8 @@ intro_on_enter (PsppireImportAssistant *ia, GtkWidget *page, enum IMPORT_ASSISTA
                                       "preview purposes in the following screens.  ",
                                       "Only the first %zu lines of the file will be shown for "
                                       "preview purposes in the following screens.  ",
-                                      ia->text_file->line_cnt),
-                        ia->text_file->line_cnt);
+                                      ia->text_file->n_lines),
+                        ia->text_file->n_lines);
        }
     }
 
@@ -533,20 +555,6 @@ static void
 on_separator_toggle (GtkToggleButton *toggle UNUSED,
                      PsppireImportAssistant *ia)
 {
-  int i;
-  GSList *delimiters = NULL;
-  for (i = 0; i < SEPARATOR_CNT; i++)
-    {
-      const struct separator *s = &separators[i];
-      GtkWidget *button = get_widget_assert (ia->text_builder, s->name);
-      if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
-       {
-         delimiters = g_slist_prepend (delimiters,  GINT_TO_POINTER (s->c));
-       }
-    }
-
-  g_object_set (ia->delimiters_model, "delimiters", delimiters, NULL);
-
   revise_fields_preview (ia);
 }
 
@@ -596,20 +604,23 @@ static void
 reset_separators_page (PsppireImportAssistant *ia)
 {
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ia->custom_cb), FALSE);
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ia->quote_cb), FALSE);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ia->quote_cb), TRUE);
   gtk_entry_set_text (GTK_ENTRY (ia->custom_entry), "");
 
-  for (gint i = 0; i < SEPARATOR_CNT; i++)
+  for (gint i = 0; i < N_SEPARATORS; i++)
     {
       const struct separator *s = &separators[i];
       GtkWidget *button = get_widget_assert (ia->text_builder, s->name);
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
     }
 
-  repopulate_delimiter_columns (ia);
+  if (ia->delimiters_model)
+    {
+      repopulate_delimiter_columns (ia);
 
-  revise_fields_preview (ia);
-  choose_likely_separators (ia);
+      revise_fields_preview (ia);
+      choose_likely_separators (ia);
+    }
 }
 
 /* Called just before the separators page becomes visible in the
@@ -655,6 +666,7 @@ separators_page_create (PsppireImportAssistant *ia)
                            gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ia->custom_cb)));
 
   gtk_combo_box_set_active (GTK_COMBO_BOX (ia->quote_combo), 0);
+  gtk_entry_set_max_length (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (ia->quote_combo))), 2);
 
   if (ia->fields_tree_view == NULL)
     {
@@ -673,7 +685,7 @@ separators_page_create (PsppireImportAssistant *ia)
                     G_CALLBACK (on_separators_custom_entry_notify), ia);
   g_signal_connect (ia->custom_cb, "toggled",
                     G_CALLBACK (on_separators_custom_cb_toggle), ia);
-  for (i = 0; i < SEPARATOR_CNT; i++)
+  for (i = 0; i < N_SEPARATORS; i++)
     g_signal_connect (get_widget_assert (builder, separators[i].name),
                       "toggled", G_CALLBACK (on_separator_toggle), ia);
 
@@ -721,6 +733,7 @@ my_read (struct casereader *reader, void *aux, casenumber idx)
              char *xx = data_in (ss_cstr (ss),
                                  "UTF-8",
                                  var_get_write_format (var)->type,
+                                  settings_get_fmt_settings (),
                                  v, var_get_width (var), "UTF-8");
 
              free (xx);
@@ -741,7 +754,7 @@ my_destroy (struct casereader *reader, void *aux)
 }
 
 static void
-my_advance (struct casereader *reader, void *aux, casenumber cnt)
+my_advance (struct casereader *reader, void *aux, casenumber n)
 {
   g_print ("%s:%d\n", __FILE__, __LINE__);
 }
@@ -749,7 +762,7 @@ my_advance (struct casereader *reader, void *aux, casenumber cnt)
 static struct casereader *
 textfile_create_reader (PsppireImportAssistant *ia)
 {
-  int n_vars = dict_get_var_cnt (ia->dict);
+  int n_vars = dict_get_n_vars (ia->dict);
 
   int i;
 
@@ -823,7 +836,7 @@ ia_variable_changed_cb (GObject *obj, gint var_num, guint what,
   PsppireImportAssistant *ia  = PSPPIRE_IMPORT_ASSISTANT (data);
 
   struct caseproto *proto = caseproto_create();
-  for (int i = 0; i < dict_get_var_cnt (ia->dict); i++)
+  for (int i = 0; i < dict_get_n_vars (ia->dict); i++)
     {
       const struct variable *var = dict_get_var (ia->dict, i);
       int width = var_get_width (var);
@@ -880,9 +893,9 @@ first_line_append_syntax (const PsppireImportAssistant *ia, struct string *s)
 static void
 apply_dict (const struct dictionary *dict, struct string *s)
 {
-  size_t var_cnt = dict_get_var_cnt (dict);
+  size_t n_vars = dict_get_n_vars (dict);
 
-  for (size_t i = 0; i < var_cnt; i++)
+  for (size_t i = 0; i < n_vars; i++)
     {
       struct variable *var = dict_get_var (dict, i);
       const char *name = var_get_name (var);
@@ -971,22 +984,19 @@ intro_append_syntax (const PsppireImportAssistant *ia, struct string *s)
 static void
 formats_append_syntax (const PsppireImportAssistant *ia, struct string *s)
 {
-  int i;
-  int var_cnt;
-
   g_return_if_fail (ia->dict);
 
   ds_put_cstr (s, "  /VARIABLES=\n");
 
-  var_cnt = dict_get_var_cnt (ia->dict);
-  for (i = 0; i < var_cnt; i++)
+  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 == var_cnt - 1 ? "." : "");
+                    i == n_vars - 1 ? "." : "");
     }
 }
 
@@ -999,7 +1009,7 @@ separators_append_syntax (const PsppireImportAssistant *ia, struct string *s)
 
   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 < SEPARATOR_CNT; i++)
+  for (i = 0; i < N_SEPARATORS; i++)
     {
       const struct separator *seps = &separators[i];
       GtkWidget *button = get_widget_assert (ia->text_builder, seps->name);