X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fui%2Fgui%2Fpsppire-delimited-text.c;h=b232ef309226ca052846f449d92f9fcfebc9ff2d;hb=b525a9596e60d5ae4c6c464b4a426b77ade3dd72;hp=fec2f707723ff3971074f5cd699fa81ceac7974c;hpb=d4ff0e074d703dbeb8af5aa3ac470ddda5ebe301;p=pspp diff --git a/src/ui/gui/psppire-delimited-text.c b/src/ui/gui/psppire-delimited-text.c index fec2f70772..b232ef3092 100644 --- a/src/ui/gui/psppire-delimited-text.c +++ b/src/ui/gui/psppire-delimited-text.c @@ -35,46 +35,80 @@ enum PROP_FIRST_LINE }; +struct enclosure +{ + gunichar opening; + gunichar closing; +}; + +static const struct enclosure enclosures[3] = + { + {'(', ')'}, + {'"', '"'}, + {'\'', '\''} + }; + static void count_delims (PsppireDelimitedText *tf) { - if (tf->child) + if (tf->child == NULL) + return; + + tf->max_delimiters = 0; + GtkTreeIter iter; + gboolean valid; + for (valid = gtk_tree_model_get_iter_first (tf->child, &iter); + valid; + valid = gtk_tree_model_iter_next (tf->child, &iter)) { - tf->max_delimiters = 0; - GtkTreeIter iter; - gboolean valid; - for (valid = gtk_tree_model_get_iter_first (tf->child, &iter); - valid; - valid = gtk_tree_model_iter_next (tf->child, &iter)) - { - // FIXME: Box these lines to avoid constant allocation/deallocation - gchar *foo = 0; - gtk_tree_model_get (tf->child, &iter, 1, &foo, -1); + gint enc = -1; + // FIXME: Box these lines to avoid constant allocation/deallocation + gchar *line = NULL; + gtk_tree_model_get (tf->child, &iter, 1, &line, -1); + { + char *p; + gint count = 0; + for (p = line; ; p = g_utf8_find_next_char (p, NULL)) { - char *line = foo; - gint count = 0; - while (*line) + 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) { GSList *del; for (del = tf->delimiters; del; del = g_slist_next (del)) { - if (*line == GPOINTER_TO_INT (del->data)) + if (c == GPOINTER_TO_INT (del->data)) count++; } - line++; } - tf->max_delimiters = MAX (tf->max_delimiters, count); } - g_free (foo); - } + tf->max_delimiters = MAX (tf->max_delimiters, count); + } + g_free (line); } - // g_print ("Max Number of delimiters per row: %d\n", tf->max_delimiters); } static void cache_invalidate (PsppireDelimitedText *tf) { - memset (tf->cache_starts, 0, 512); + memset (tf->cache_starts, 0, sizeof tf->cache_starts); if (tf->const_cache.string) { ss_dealloc (&tf->const_cache); @@ -98,6 +132,7 @@ psppire_delimited_text_set_property (GObject *object, break; case PROP_CHILD: tf->child = g_value_get_object (value); + g_return_if_fail (PSPPIRE_IS_TEXT_FILE (tf->child)); break; case PROP_DELIMITERS: g_slist_free (tf->delimiters); @@ -134,15 +169,18 @@ psppire_delimited_text_get_property (GObject *object, }; } - -static void psppire_delimited_text_init (PsppireDelimitedText *text_file); -static void psppire_delimited_text_class_init (PsppireDelimitedTextClass *class); - static void psppire_delimited_text_finalize (GObject *object); static void psppire_delimited_text_dispose (GObject *object); static GObjectClass *parent_class = NULL; +static gint +n_lines (PsppireDelimitedText *file) +{ + PsppireTextFile *child = PSPPIRE_TEXT_FILE (file->child); + + return child->maximum_lines; +} static gboolean __tree_get_iter (GtkTreeModel *tree_model, @@ -153,7 +191,6 @@ __tree_get_iter (GtkTreeModel *tree_model, if (path == NULL) return FALSE; - // g_print ("%s:%d %s %s\n", __FILE__, __LINE__, __FUNCTION__, gtk_tree_path_to_string (path)); gint *indices = gtk_tree_path_get_indices (path); @@ -162,12 +199,11 @@ __tree_get_iter (GtkTreeModel *tree_model, gint n = *indices; - gint children = gtk_tree_model_iter_n_children (file->child, NULL); + gint children = n_lines (file); if (n >= children - file->first_line) return FALSE; - // g_print ("%s:%d %s %d Children: %d\n", __FILE__, __LINE__, __FUNCTION__, n, children); iter->user_data = GINT_TO_POINTER (n); iter->stamp = file->stamp; @@ -185,9 +221,8 @@ __tree_iter_next (GtkTreeModel *tree_model, gint n = GPOINTER_TO_INT (iter->user_data); - // g_print ("%s:%d %s %d\n", __FILE__, __LINE__, __FUNCTION__, n); - gint children = gtk_tree_model_iter_n_children (file->child, NULL); + gint children = n_lines (file); if (n + 1 >= children - file->first_line) return FALSE; @@ -202,7 +237,6 @@ static GType __tree_get_column_type (GtkTreeModel *tree_model, gint index) { - // g_print ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); if (index == 0) return G_TYPE_INT; @@ -213,7 +247,6 @@ static gboolean __iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter) { - g_print ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); return 0; } @@ -223,7 +256,6 @@ __iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child) { - g_print ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); return 0; } @@ -231,13 +263,12 @@ static GtkTreePath * __tree_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter) { - // g_print ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); PsppireDelimitedText *file = PSPPIRE_DELIMITED_TEXT (tree_model); g_return_val_if_fail (file->stamp == iter->stamp, FALSE); gint n = GPOINTER_TO_INT (iter->user_data); - gint children = gtk_tree_model_iter_n_children (file->child, NULL); + gint children = n_lines (file); if (n >= children - file->first_line) return NULL; @@ -251,7 +282,6 @@ __iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent) { - g_print ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); return 0; } @@ -260,15 +290,17 @@ static gint __tree_model_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter) { - g_print ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + PsppireDelimitedText *file = PSPPIRE_DELIMITED_TEXT (tree_model); g_assert (iter == NULL); - return 0; + + gint children = n_lines (file); + + return children - file->first_line; } static GtkTreeModelFlags __tree_model_get_flags (GtkTreeModel *model) { - // g_print ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); g_return_val_if_fail (PSPPIRE_IS_DELIMITED_TEXT (model), (GtkTreeModelFlags) 0); return GTK_TREE_MODEL_LIST_ONLY; @@ -277,7 +309,6 @@ __tree_model_get_flags (GtkTreeModel *model) static gint __tree_model_get_n_columns (GtkTreeModel *tree_model) { - // g_print ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); PsppireDelimitedText *tf = PSPPIRE_DELIMITED_TEXT (tree_model); /* + 1 for the trailing field and +1 for the leading line number column */ @@ -291,7 +322,6 @@ __iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *parent, gint n) { - // g_print ("%s:%d %s %d\n", __FILE__, __LINE__, __FUNCTION__, n); PsppireDelimitedText *file = PSPPIRE_DELIMITED_TEXT (tree_model); g_assert (parent == NULL); @@ -314,6 +344,18 @@ __iter_nth_child (GtkTreeModel *tree_model, } +static void +nullify_char (struct substring cs) +{ + int char_len = ss_first_mblen (cs); + while (char_len > 0) + { + cs.string[char_len - 1] = '\0'; + char_len--; + } +} + + /* Split row N into it's delimited fields (if it is not already cached) and set this row as the current cache. */ static void @@ -324,7 +366,7 @@ split_row_into_fields (PsppireDelimitedText *file, gint n) return; } - memset (file->cache_starts, 0, 512); + memset (file->cache_starts, 0, sizeof file->cache_starts); /* Cache miss */ if (file->const_cache.string) { @@ -335,25 +377,47 @@ split_row_into_fields (PsppireDelimitedText *file, gint n) struct substring cs = file->const_cache; int field = 0; file->cache_starts[0] = cs.string; + gint enc = -1; for (; UINT32_MAX != ss_first_mb (cs); ss_get_mb (&cs)) { - ucs4_t xx = ss_first_mb (cs); - GSList *del; - for (del = file->delimiters; del; del = g_slist_next (del)) + ucs4_t character = ss_first_mb (cs); + gboolean char_is_quote = FALSE; + if (enc == -1) { - if (xx == GPOINTER_TO_INT (del->data)) + gint i; + for (i = 0; i < 3; ++i) { - field++; - int char_len = ss_first_mblen (cs); - file->cache_starts[field] = cs.string + char_len; - while (char_len > 0) + if (character == enclosures[i].opening) { - cs.string[char_len - 1] = '\0'; - char_len--; + enc = i; + char_is_quote = TRUE; + file->cache_starts[field] += ss_first_mblen (cs); + break; + } + } + } + else if (character == enclosures[enc].closing) + { + char_is_quote = TRUE; + nullify_char (cs); + enc = -1; + } + + if (enc == -1 && char_is_quote == FALSE) + { + GSList *del; + for (del = file->delimiters; del; del = g_slist_next (del)) + { + if (character == GPOINTER_TO_INT (del->data)) + { + field++; + int char_len = ss_first_mblen (cs); + file->cache_starts[field] = cs.string + char_len; + nullify_char (cs); + break; } - break; } } } @@ -378,14 +442,12 @@ __get_value (GtkTreeModel *tree_model, gint column, GValue *value) { - // g_print ("%s:%d %s Col: %d\n", __FILE__, __LINE__, __FUNCTION__, column); PsppireDelimitedText *file = PSPPIRE_DELIMITED_TEXT (tree_model); g_return_if_fail (iter->stamp == file->stamp); gint n = GPOINTER_TO_INT (iter->user_data) + file->first_line; - // g_print ("%s:%d Row: %d\n", __FILE__, __LINE__, n); if (column == 0) { @@ -420,44 +482,9 @@ __tree_model_init (GtkTreeModelIface *iface) iface->iter_parent = __iter_parent; } - -GType -psppire_delimited_text_get_type (void) -{ - static GType text_file_type = 0; - - if (!text_file_type) - { - static const GTypeInfo text_file_info = - { - sizeof (PsppireDelimitedTextClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) psppire_delimited_text_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (PsppireDelimitedText), - 0, - (GInstanceInitFunc) psppire_delimited_text_init, - }; - - static const GInterfaceInfo tree_model_info = { - (GInterfaceInitFunc) __tree_model_init, - NULL, - NULL - }; - - text_file_type = g_type_register_static (G_TYPE_OBJECT, - "PsppireDelimitedText", - &text_file_info, 0); - - g_type_add_interface_static (text_file_type, GTK_TYPE_TREE_MODEL, - &tree_model_info); - } - - return text_file_type; -} - +G_DEFINE_TYPE_WITH_CODE (PsppireDelimitedText, psppire_delimited_text, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, + __tree_model_init)) static void psppire_delimited_text_class_init (PsppireDelimitedTextClass *class) @@ -465,7 +492,7 @@ psppire_delimited_text_class_init (PsppireDelimitedTextClass *class) GObjectClass *object_class; parent_class = g_type_class_peek_parent (class); - object_class = (GObjectClass*) class; + object_class = G_OBJECT_CLASS (class); GParamSpec *first_line_spec = g_param_spec_int ("first-line", @@ -517,7 +544,7 @@ psppire_delimited_text_init (PsppireDelimitedText *text_file) text_file->const_cache.string = NULL; text_file->const_cache.length = 0; text_file->cache_row = -1; - memset (text_file->cache_starts, 0, 512); + memset (text_file->cache_starts, 0, sizeof text_file->cache_starts); text_file->max_delimiters = 0; @@ -526,15 +553,13 @@ psppire_delimited_text_init (PsppireDelimitedText *text_file) } -GtkTreeModel * +PsppireDelimitedText * psppire_delimited_text_new (GtkTreeModel *child) { - PsppireDelimitedText *retval = + return g_object_new (PSPPIRE_TYPE_DELIMITED_TEXT, "child", child, NULL); - - return retval; } static void