PROP_0,
PROP_CHILD,
PROP_DELIMITERS,
+ PROP_QUOTES,
PROP_FIRST_LINE
};
-struct enclosure
-{
- gunichar opening;
- gunichar closing;
-};
-
-static const struct enclosure enclosures[3] =
- {
- {'(', ')'},
- {'"', '"'},
- {'\'', '\''}
- };
-
static void
count_delims (PsppireDelimitedText *tf)
{
valid;
valid = gtk_tree_model_iter_next (tf->child, &iter))
{
- gint enc = -1;
+ gunichar quote = -1;
// FIXME: Box these lines to avoid constant allocation/deallocation
gchar *line = NULL;
gtk_tree_model_get (tf->child, &iter, 1, &line, -1);
const gunichar c = g_utf8_get_char (p);
if (c == 0)
break;
- if (enc == -1)
- {
- gint i;
- for (i = 0; i < 3; ++i)
- {
- if (c == enclosures[i].opening)
- {
- enc = i;
- break;
- }
- }
- }
- else if (c == enclosures[enc].closing)
- {
- enc = -1;
- }
- if (enc == -1)
+
+ if (c == quote)
+ quote = -1;
+ else if (c == tf->quotes[0] || c == tf->quotes[1])
+ quote = c;
+
+ if (quote == -1)
{
GSList *del;
for (del = tf->delimiters; del; del = g_slist_next (del))
g_slist_free (tf->delimiters);
tf->delimiters = g_slist_copy (g_value_get_pointer (value));
break;
+ case PROP_QUOTES:
+ {
+ tf->quotes[0] = tf->quotes[1] = -1;
+
+ const gchar *s = g_value_get_string (value);
+ for (size_t i = 0; i < 2 && s && s[0]; i++)
+ {
+ tf->quotes[i] = g_utf8_get_char (s);
+ s = g_utf8_find_next_char (s, NULL);
+ }
+ }
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_DELIMITERS:
g_value_set_pointer (value, text_file->delimiters);
break;
+ case PROP_QUOTES:
+ {
+ GString *s = g_string_new (NULL);
+ for (size_t i = 0; i < 2; i++)
+ {
+ gunichar quote = text_file->quotes[i];
+ if (quote && quote != -1)
+ g_string_append_unichar (s, quote);
+ }
+ }
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
struct substring cs = file->const_cache;
int field = 0;
file->cache_starts[0] = cs.string;
- gint enc = -1;
+ gunichar quote = -1;
for (;
UINT32_MAX != ss_first_mb (cs);
ss_get_mb (&cs))
{
ucs4_t character = ss_first_mb (cs);
gboolean char_is_quote = FALSE;
- if (enc == -1)
- {
- gint i;
- for (i = 0; i < 3; ++i)
- {
- if (character == enclosures[i].opening)
- {
- enc = i;
- char_is_quote = TRUE;
- file->cache_starts[field] += ss_first_mblen (cs);
- break;
- }
- }
- }
- else if (character == enclosures[enc].closing)
+ if (quote == -1)
+ {
+ if (character == file->quotes[0] || character == file->quotes[1])
+ {
+ quote = character;
+ char_is_quote = TRUE;
+ file->cache_starts[field] += ss_first_mblen (cs);
+ }
+ }
+ else if (character == quote)
{
char_is_quote = TRUE;
nullify_char (cs);
- enc = -1;
+ quote = -1;
}
- if (enc == -1 && char_is_quote == FALSE)
+ if (quote == -1 && char_is_quote == FALSE)
{
GSList *del;
for (del = file->delimiters; del; del = g_slist_next (del))
P_("A GSList of gunichars which delimit the fields."),
G_PARAM_READWRITE);
+ GParamSpec *quotes_spec =
+ g_param_spec_string ("quotes",
+ "Field Quotes",
+ P_("A string of characters that quote the fields."),
+ P_(""),
+ G_PARAM_READWRITE);
+
GParamSpec *child_spec =
g_param_spec_object ("child",
"Child Model",
PROP_DELIMITERS,
delimiters_spec);
+ g_object_class_install_property (object_class,
+ PROP_QUOTES,
+ quotes_spec);
+
g_object_class_install_property (object_class,
PROP_FIRST_LINE,
first_line_spec);
text_file->max_delimiters = 0;
+ text_file->quotes[0] = text_file->quotes[1] = -1;
+
text_file->dispose_has_run = FALSE;
text_file->stamp = g_random_int ();
}
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);
}
on_separator_toggle (GtkToggleButton *toggle UNUSED,
PsppireImportAssistant *ia)
{
- int i;
- GSList *delimiters = NULL;
- for (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));
- }
- }
-
- g_object_set (ia->delimiters_model, "delimiters", delimiters, NULL);
-
revise_fields_preview (ia);
}
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 < N_SEPARATORS; i++)
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
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)
{