From d95d0e9115778f6ca80de9056094eeda846b23c6 Mon Sep 17 00:00:00 2001 From: Yevgen Muntyan <17531749+muntyan@users.noreply.github.com> Date: Mon, 17 Apr 2006 21:31:25 -0500 Subject: [PATCH] Renamed MooTextCompletion back to MooCompletion; removed signals; removed GtkTreeModelFilter stuff --- moo.kdevelop | 2 +- moo/mooedit/Makefile.incl | 4 +- moo/mooedit/moocompletion.c | 764 ++++++++++++++++++++ moo/mooedit/moocompletion.h | 107 +++ moo/mooedit/mootextcompletion.c | 737 ------------------- moo/mooedit/mootextcompletion.h | 104 --- moo/mooedit/plugins/completion/completion.c | 44 +- moo/mooutils/moomarshals.list | 2 +- 8 files changed, 888 insertions(+), 876 deletions(-) create mode 100644 moo/mooedit/moocompletion.c create mode 100644 moo/mooedit/moocompletion.h delete mode 100644 moo/mooedit/mootextcompletion.c delete mode 100644 moo/mooedit/mootextcompletion.h diff --git a/moo.kdevelop b/moo.kdevelop index 78ab6f9e..60642203 100644 --- a/moo.kdevelop +++ b/moo.kdevelop @@ -33,7 +33,7 @@ moo/libmoo.la - optimized + debug ./medit diff --git a/moo/mooedit/Makefile.incl b/moo/mooedit/Makefile.incl index 02db760c..53a5cc91 100644 --- a/moo/mooedit/Makefile.incl +++ b/moo/mooedit/Makefile.incl @@ -7,6 +7,7 @@ mooedit_srcdir = $(srcdir)/$(mooedit) mooedit_include_headers = \ $(mooedit)/moocmdview.h \ + $(mooedit)/moocompletion.h \ $(mooedit)/mooedit-script.h \ $(mooedit)/mooedit.h \ $(mooedit)/mooeditconfig.h \ @@ -21,7 +22,6 @@ mooedit_include_headers = \ $(mooedit)/mooplugin-macro.h \ $(mooedit)/mooplugin.h \ $(mooedit)/mootextbuffer.h \ - $(mooedit)/mootextcompletion.h \ $(mooedit)/mootextiter.h \ $(mooedit)/mootextpopup.h \ $(mooedit)/mootextsearch.h \ @@ -60,6 +60,7 @@ mooedit_sources = \ $(mooedit_noinst_headers) \ $(mooedit)/gtksourceiter.c \ $(mooedit)/moocmdview.c \ + $(mooedit)/moocompletion.c \ $(mooedit)/mooedit-script.c \ $(mooedit)/mooedit.c \ $(mooedit)/mooeditconfig.c \ @@ -83,7 +84,6 @@ mooedit_sources = \ $(mooedit)/mooplugin.c \ $(mooedit)/mootextbtree.c \ $(mooedit)/mootextbuffer.c \ - $(mooedit)/mootextcompletion.c \ $(mooedit)/mootextfind.c \ $(mooedit)/mootextpopup.c \ $(mooedit)/mootextsearch.c \ diff --git a/moo/mooedit/moocompletion.c b/moo/mooedit/moocompletion.c new file mode 100644 index 00000000..214847a1 --- /dev/null +++ b/moo/mooedit/moocompletion.c @@ -0,0 +1,764 @@ +/* + * moocompletion.c + * + * Copyright (C) 2004-2006 by Yevgen Muntyan + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * See COPYING file that comes with this distribution. + */ + +#include "mooedit/moocompletion.h" +#include "mooedit/mootextpopup.h" +#include "mooutils/moomarshals.h" +#include "mooutils/eggregex.h" +#include +#include +#include + + +struct _MooCompletionPrivate { + GtkListStore *store; + GSList *groups; + MooCompletionGroup *active_group; + + GtkTextView *doc; + GtkTextBuffer *buffer; + GtkTextMark *start; + GtkTextMark *end; + + MooTextPopup *popup; + guint working : 1; + guint in_update : 1; +}; + +struct _MooCompletionGroup { + guint ref_count; + + EggRegex *regex; + guint *parens; + guint n_parens; + + GCompletion *cmpl; + GList *data; + + MooCompletionStringFunc string_func; + MooCompletionFreeFunc free_func; + MooCompletionCmpFunc cmp_func; +}; + + +static void moo_completion_dispose (GObject *object); + +static void moo_completion_update (MooCompletion *cmpl); +static void moo_completion_populate (MooCompletion *cmpl, + MooCompletionGroup *group, + const char *text, + char **prefix); +static void moo_completion_complete (MooCompletion *cmpl, + gpointer data); + +static void moo_completion_connect_popup (MooCompletion *cmpl); +static void moo_completion_disconnect_popup (MooCompletion *cmpl); + +static gboolean moo_completion_empty (MooCompletion *cmpl); +static gboolean moo_completion_unique (MooCompletion *cmpl, + GtkTreeIter *iter); +static gpointer moo_completion_get_data (MooCompletion *cmpl, + GtkTreeIter *iter); + +static gboolean moo_completion_group_find (MooCompletionGroup *group, + const char *line, + int *start_pos, + int *end_pos); +static GList *moo_completion_group_complete (MooCompletionGroup *group, + const char *text, + char **prefix); + + +G_DEFINE_TYPE (MooCompletion, moo_completion, G_TYPE_OBJECT) + + +static void +moo_completion_dispose (GObject *object) +{ + MooCompletion *cmpl = MOO_COMPLETION (object); + + if (cmpl->priv) + { + moo_completion_set_doc (cmpl, NULL); + + g_object_unref (cmpl->priv->store); + g_slist_foreach (cmpl->priv->groups, (GFunc) moo_completion_group_unref, NULL); + g_slist_free (cmpl->priv->groups); + + if (cmpl->priv->popup) + { + moo_completion_disconnect_popup (cmpl); + g_object_unref (cmpl->priv->popup); + } + + g_free (cmpl->priv); + cmpl->priv = NULL; + } + + G_OBJECT_CLASS(moo_completion_parent_class)->dispose (object); +} + + +static void +moo_completion_class_init (MooCompletionClass *klass) +{ + G_OBJECT_CLASS(klass)->dispose = moo_completion_dispose; +} + + +static void +moo_completion_init (MooCompletion *cmpl) +{ + cmpl->priv = g_new0 (MooCompletionPrivate, 1); + cmpl->priv->store = gtk_list_store_new (1, G_TYPE_POINTER); + cmpl->priv->popup = moo_text_popup_new (NULL); + moo_completion_connect_popup (cmpl); +} + + +void +moo_completion_try_complete (MooCompletion *cmpl, + gboolean insert_unique) +{ + GSList *l; + MooCompletionGroup *group; + GtkTextIter start, end; + GtkTreeIter iter; + gboolean found = FALSE; + int start_pos, end_pos; + char *prefix = NULL, *text = NULL, *line; + + g_return_if_fail (MOO_IS_COMPLETION (cmpl)); + g_return_if_fail (cmpl->priv->buffer != NULL); + g_return_if_fail (!cmpl->priv->working); + + cmpl->priv->working = TRUE; + + gtk_text_buffer_get_iter_at_mark (cmpl->priv->buffer, &end, + gtk_text_buffer_get_insert (cmpl->priv->buffer)); + start = end; + + if (!gtk_text_iter_starts_line (&start)) + gtk_text_iter_set_line_offset (&start, 0); + + line = gtk_text_buffer_get_slice (cmpl->priv->buffer, &start, &end, TRUE); + + for (l = cmpl->priv->groups; !found && l != NULL; l = l->next) + { + group = l->data; + found = moo_completion_group_find (group, line, &start_pos, &end_pos); + } + + if (found) + { + cmpl->priv->active_group = group; + + gtk_text_iter_set_line_index (&start, start_pos); + gtk_text_iter_set_line_index (&end, end_pos); + + text = gtk_text_buffer_get_slice (cmpl->priv->buffer, &start, &end, TRUE); + moo_completion_set_region (cmpl, &start, &end); + moo_completion_populate (cmpl, group, text, &prefix); + } + + if (!found || moo_completion_empty (cmpl)) + { + cmpl->priv->active_group = NULL; + cmpl->priv->working = FALSE; + goto out; + } + + if (insert_unique && moo_completion_unique (cmpl, &iter)) + { + gpointer data = moo_completion_get_data (cmpl, &iter); + moo_completion_complete (cmpl, data); + cmpl->priv->working = FALSE; + goto out; + } + + if (prefix && strcmp (text, prefix)) + { + gtk_text_buffer_begin_user_action (cmpl->priv->buffer); + gtk_text_buffer_delete (cmpl->priv->buffer, &start, &end); + gtk_text_buffer_insert (cmpl->priv->buffer, &start, prefix, -1); + gtk_text_buffer_end_user_action (cmpl->priv->buffer); + } + + moo_completion_get_region (cmpl, &start, NULL); + moo_text_popup_show (cmpl->priv->popup, &start); + +out: + g_free (text); + g_free (prefix); + g_free (line); +} + + +static void +moo_completion_update (MooCompletion *cmpl) +{ + GtkTextIter start, end; + GList *list; + char *text; + + g_return_if_fail (cmpl->priv->working); + g_return_if_fail (cmpl->priv->active_group != NULL); + + moo_completion_get_region (cmpl, &start, &end); + text = gtk_text_buffer_get_slice (cmpl->priv->buffer, &start, &end, TRUE); + + list = moo_completion_group_complete (cmpl->priv->active_group, text, NULL); + gtk_list_store_clear (cmpl->priv->store); + + if (list) + { + while (list) + { + GtkTreeIter iter; + gtk_list_store_append (cmpl->priv->store, &iter); + gtk_list_store_set (cmpl->priv->store, &iter, 0, list->data, -1); + list = list->next; + } + + moo_text_popup_update (cmpl->priv->popup); + } + else + { + moo_completion_hide (cmpl); + } + + g_free (text); +} + + +static void +moo_completion_complete (MooCompletion *cmpl, + gpointer data) +{ + char *text, *old_text; + GtkTextIter start, end; + + g_return_if_fail (cmpl->priv->active_group != NULL); + + text = cmpl->priv->active_group->string_func ? + cmpl->priv->active_group->string_func (data) : data; + g_return_if_fail (text != NULL); + + moo_completion_get_region (cmpl, &start, &end); + old_text = gtk_text_buffer_get_slice (cmpl->priv->buffer, + &start, &end, TRUE); + + if (strcmp (text, old_text)) + { + gtk_text_buffer_begin_user_action (cmpl->priv->buffer); + gtk_text_buffer_delete (cmpl->priv->buffer, &start, &end); + gtk_text_buffer_insert (cmpl->priv->buffer, &start, text, -1); + gtk_text_buffer_end_user_action (cmpl->priv->buffer); + } + + moo_completion_hide (cmpl); + + g_free (old_text); +} + + +static void +moo_completion_populate (MooCompletion *cmpl, + MooCompletionGroup *group, + const char *text, + char **prefix) +{ + GList *list; + + gtk_list_store_clear (cmpl->priv->store); + list = moo_completion_group_complete (group, text, prefix); + + while (list) + { + GtkTreeIter iter; + gtk_list_store_append (cmpl->priv->store, &iter); + gtk_list_store_set (cmpl->priv->store, &iter, 0, list->data, -1); + list = list->next; + } +} + + +static gboolean +moo_completion_empty (MooCompletion *cmpl) +{ + return !gtk_tree_model_iter_n_children (GTK_TREE_MODEL (cmpl->priv->store), NULL); +} + + +static gboolean +moo_completion_unique (MooCompletion *cmpl, + GtkTreeIter *iter) +{ + return gtk_tree_model_iter_n_children (GTK_TREE_MODEL (cmpl->priv->store), NULL) == 1 && + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (cmpl->priv->store), iter); +} + + +static gpointer +moo_completion_get_data (MooCompletion *cmpl, + GtkTreeIter *iter) +{ + gpointer data = NULL; + gtk_tree_model_get (GTK_TREE_MODEL (cmpl->priv->store), iter, 0, &data, -1); + return data; +} + + +static void +on_popup_activate (MooCompletion *cmpl, + GtkTreeModel *model, + GtkTreeIter *iter) +{ + gpointer data = NULL; + gtk_tree_model_get (model, iter, 0, &data, -1); + moo_completion_complete (cmpl, data); +} + + +static void +moo_completion_connect_popup (MooCompletion *cmpl) +{ + moo_text_popup_set_model (cmpl->priv->popup, + GTK_TREE_MODEL (cmpl->priv->store)); + g_signal_connect_swapped (cmpl->priv->popup, "activate", + G_CALLBACK (on_popup_activate), cmpl); + g_signal_connect_swapped (cmpl->priv->popup, "text-changed", + G_CALLBACK (moo_completion_update), cmpl); + g_signal_connect_swapped (cmpl->priv->popup, "hide", + G_CALLBACK (moo_completion_hide), cmpl); +} + + +static void +moo_completion_disconnect_popup (MooCompletion *cmpl) +{ + moo_text_popup_set_model (cmpl->priv->popup, NULL); + g_signal_handlers_disconnect_by_func (cmpl->priv->popup, + (gpointer) on_popup_activate, + cmpl); + g_signal_handlers_disconnect_by_func (cmpl->priv->popup, + (gpointer) moo_completion_update, + cmpl); + g_signal_handlers_disconnect_by_func (cmpl->priv->popup, + (gpointer) moo_completion_hide, + cmpl); +} + + +void +moo_completion_hide (MooCompletion *cmpl) +{ + g_return_if_fail (MOO_IS_COMPLETION (cmpl)); + + if (cmpl->priv->working) + { + cmpl->priv->working = FALSE; + moo_text_popup_hide (cmpl->priv->popup); + gtk_list_store_clear (cmpl->priv->store); + } +} + + +void +moo_completion_set_doc (MooCompletion *cmpl, + GtkTextView *doc) +{ + g_return_if_fail (MOO_IS_COMPLETION (cmpl)); + g_return_if_fail (!doc || GTK_IS_TEXT_VIEW (doc)); + + if (cmpl->priv->doc == doc) + return; + + moo_completion_hide (cmpl); + + if (cmpl->priv->doc) + { + if (cmpl->priv->start) + gtk_text_buffer_delete_mark (cmpl->priv->buffer, cmpl->priv->start); + if (cmpl->priv->end) + gtk_text_buffer_delete_mark (cmpl->priv->buffer, cmpl->priv->end); + g_object_unref (cmpl->priv->doc); + cmpl->priv->start = cmpl->priv->end = NULL; + cmpl->priv->buffer = NULL; + cmpl->priv->doc = NULL; + } + + if (doc) + { + cmpl->priv->doc = g_object_ref (doc); + cmpl->priv->buffer = gtk_text_view_get_buffer (doc); + } + + moo_text_popup_set_doc (cmpl->priv->popup, doc); +} + + +GtkTextView * +moo_completion_get_doc (MooCompletion *cmpl) +{ + g_return_val_if_fail (MOO_IS_COMPLETION (cmpl), NULL); + return cmpl->priv->doc; +} + + +MooTextPopup * +moo_completion_get_popup (MooCompletion *cmpl) +{ + g_return_val_if_fail (MOO_IS_COMPLETION (cmpl), NULL); + return cmpl->priv->popup; +} + + +gboolean +moo_completion_get_region (MooCompletion *cmpl, + GtkTextIter *start, + GtkTextIter *end) +{ + g_return_val_if_fail (MOO_IS_COMPLETION (cmpl), FALSE); + + if (cmpl->priv->start) + { + if (start) + gtk_text_buffer_get_iter_at_mark (cmpl->priv->buffer, start, + cmpl->priv->start); + if (end) + gtk_text_buffer_get_iter_at_mark (cmpl->priv->buffer, end, + cmpl->priv->end); + return TRUE; + } + else + { + return FALSE; + } +} + + +void +moo_completion_set_region (MooCompletion *cmpl, + const GtkTextIter *start, + const GtkTextIter *end) +{ + g_return_if_fail (MOO_IS_COMPLETION (cmpl)); + g_return_if_fail (start && end); + g_return_if_fail (cmpl->priv->buffer != NULL); + + if (!cmpl->priv->start) + { + cmpl->priv->start = gtk_text_buffer_create_mark (cmpl->priv->buffer, NULL, start, TRUE); + cmpl->priv->end = gtk_text_buffer_create_mark (cmpl->priv->buffer, NULL, end, FALSE); + } + else + { + gtk_text_buffer_move_mark (cmpl->priv->buffer, cmpl->priv->start, start); + gtk_text_buffer_move_mark (cmpl->priv->buffer, cmpl->priv->end, end); + } + + moo_text_popup_set_position (cmpl->priv->popup, start); + moo_completion_update (cmpl); +} + + +MooCompletion * +moo_completion_new (void) +{ + return g_object_new (MOO_TYPE_COMPLETION, NULL); +} + + +static void +text_cell_data_func (G_GNUC_UNUSED GtkTreeViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter, + MooCompletionGroup *group) +{ + gpointer data = NULL; + char *text; + + g_return_if_fail (group != NULL); + + gtk_tree_model_get (tree_model, iter, 0, &data, -1); + text = group->string_func ? group->string_func (data) : data; + g_return_if_fail (text != NULL); + + g_object_set (cell, "text", text, NULL); +} + + +MooCompletion * +moo_completion_new_text (GList *words, + gboolean sorted) +{ + MooCompletion *cmpl; + MooCompletionGroup *group; + GtkCellRenderer *cell; + + cmpl = moo_completion_new (); + group = moo_completion_group_new_text (sorted); + moo_completion_group_add_data (group, words); + moo_completion_group_set_pattern (group, "\\w*", NULL, 0); + moo_completion_add_group (cmpl, group); + moo_completion_group_unref (group); + + cell = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (cmpl->priv->popup->column, cell, TRUE); + gtk_tree_view_column_set_cell_data_func (cmpl->priv->popup->column, cell, + (GtkTreeCellDataFunc) text_cell_data_func, + moo_completion_group_ref (group), + (GtkDestroyNotify) moo_completion_group_unref); + + return cmpl; +} + + +void +moo_completion_add_group (MooCompletion *cmpl, + MooCompletionGroup *group) +{ + g_return_if_fail (MOO_IS_COMPLETION (cmpl)); + g_return_if_fail (group != NULL); + g_return_if_fail (g_slist_find (cmpl->priv->groups, group) == NULL); + cmpl->priv->groups = g_slist_append (cmpl->priv->groups, + moo_completion_group_ref (group)); +} + + +/****************************************************************************/ +/* MooCompletionGroup + */ + +MooCompletionGroup * +moo_completion_group_new (MooCompletionStringFunc string_func, + MooCompletionFreeFunc free_func, + MooCompletionCmpFunc cmp_func) +{ + MooCompletionGroup *group = g_new0 (MooCompletionGroup, 1); + + group->ref_count = 1; + group->cmpl = g_completion_new (string_func); + group->string_func = string_func; + group->free_func = free_func; + group->cmp_func = cmp_func; + + return group; +} + + +MooCompletionGroup * +moo_completion_group_new_text (gboolean sorted) +{ + return moo_completion_group_new (NULL, g_free, + sorted ? (MooCompletionCmpFunc) strcmp : NULL); +} + + +void +moo_completion_group_set_data (MooCompletionGroup *group, + GList *data) +{ + g_return_if_fail (group != NULL); + + g_completion_clear_items (group->cmpl); + + if (group->free_func) + g_list_foreach (group->data, (GFunc) group->free_func, NULL); + g_list_free (group->data); + + group->data = data; + + if (group->cmp_func) + group->data = g_list_sort (group->data, (GCompareFunc) group->cmp_func); + + g_completion_add_items (group->cmpl, group->data); +} + + +void +moo_completion_group_add_data (MooCompletionGroup *group, + GList *data) +{ + g_return_if_fail (group != NULL); + + if (!data) + return; + + g_completion_clear_items (group->cmpl); + + group->data = g_list_concat (group->data, data); + + if (group->cmp_func) + group->data = g_list_sort (group->data, (GCompareFunc) group->cmp_func); + + g_completion_add_items (group->cmpl, group->data); +} + + +static gboolean +moo_completion_group_find (MooCompletionGroup *group, + const char *line, + int *start_pos_p, + int *end_pos_p) +{ + g_return_val_if_fail (group != NULL, FALSE); + g_return_val_if_fail (line != NULL, FALSE); + g_return_val_if_fail (group->regex != NULL, FALSE); + + egg_regex_clear (group->regex); + + if (egg_regex_match (group->regex, line, -1, 0) >= 1) + { + guint i; + + for (i = 0; i < group->n_parens; ++i) + { + int start_pos = -1, end_pos = -1; + + egg_regex_fetch_pos (group->regex, line, group->parens[i], + &start_pos, &end_pos); + + if (start_pos >= 0 && end_pos >= 0) + { + if (start_pos_p) + *start_pos_p = start_pos; + if (end_pos_p) + *end_pos_p = end_pos; + return TRUE; + } + } + } + + return FALSE; +} + + +static GList * +moo_completion_group_complete (MooCompletionGroup *group, + const char *text, + char **prefix) +{ + char *dummy = NULL; + GList *retval; + + if (!prefix) + prefix = &dummy; + + retval = g_completion_complete_utf8 (group->cmpl, text, prefix); + + g_free (dummy); + return retval; +} + + +void +moo_completion_group_set_pattern (MooCompletionGroup *group, + const char *pattern, + const guint *parens, + guint n_parens) +{ + EggRegex *regex; + GError *error = NULL; + char *real_pattern; + + g_return_if_fail (group != NULL); + g_return_if_fail (pattern && pattern[0]); + g_return_if_fail (!parens || n_parens); + + real_pattern = g_strdup_printf ("%s$", pattern); + regex = egg_regex_new (real_pattern, 0, 0, &error); + + if (error) + { + g_warning ("%s: %s", G_STRLOC, error->message); + goto err; + } + + egg_regex_optimize (regex, &error); + + if (error) + { + g_warning ("%s: %s", G_STRLOC, error->message); + g_error_free (error); + } + + egg_regex_unref (group->regex); + group->regex = regex; + + g_free (group->parens); + + if (!parens) + { + group->parens = g_new0 (guint, 1); + group->n_parens = 1; + } + else + { + group->parens = g_memdup (parens, n_parens * sizeof (guint)); + group->n_parens = n_parens; + } + + return; + +err: + if (error) + g_error_free (error); + g_free (real_pattern); + egg_regex_unref (regex); +} + + +GType +moo_completion_group_get_type (void) +{ + static GType type; + + if (!type) + type = g_boxed_type_register_static ("MooCompletionGroup", + (GBoxedCopyFunc) moo_completion_group_ref, + (GBoxedFreeFunc) moo_completion_group_unref); + + return type; +} + + +MooCompletionGroup * +moo_completion_group_ref (MooCompletionGroup *group) +{ + g_return_val_if_fail (group != NULL, NULL); + group->ref_count++; + return group; +} + + +void +moo_completion_group_unref (MooCompletionGroup *group) +{ + g_return_if_fail (group != NULL); + + if (!(--group->ref_count)) + { + egg_regex_unref (group->regex); + g_free (group->parens); + g_completion_free (group->cmpl); + + if (group->free_func) + g_list_foreach (group->data, (GFunc) group->free_func, NULL); + g_list_free (group->data); + + g_free (group); + } +} diff --git a/moo/mooedit/moocompletion.h b/moo/mooedit/moocompletion.h new file mode 100644 index 00000000..f02985b4 --- /dev/null +++ b/moo/mooedit/moocompletion.h @@ -0,0 +1,107 @@ +/* + * moocompletion.h + * + * Copyright (C) 2004-2006 by Yevgen Muntyan + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * See COPYING file that comes with this distribution. + */ + +#ifndef __MOO_COMPLETION_H__ +#define __MOO_COMPLETION_H__ + +#include "mooedit/mootextpopup.h" +#include + +G_BEGIN_DECLS + +#define MOO_TYPE_COMPLETION_GROUP (moo_completion_group_get_type ()) +#define MOO_TYPE_COMPLETION (moo_completion_get_type ()) +#define MOO_COMPLETION(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_COMPLETION, MooCompletion)) +#define MOO_COMPLETION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_COMPLETION, MooCompletionClass)) +#define MOO_IS_COMPLETION(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOO_TYPE_COMPLETION)) +#define MOO_IS_COMPLETION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_COMPLETION)) +#define MOO_COMPLETION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_COMPLETION, MooCompletionClass)) + + +typedef struct _MooCompletion MooCompletion; +typedef struct _MooCompletionPrivate MooCompletionPrivate; +typedef struct _MooCompletionClass MooCompletionClass; +typedef struct _MooCompletionGroup MooCompletionGroup; + +struct _MooCompletion +{ + GObject parent; + MooCompletionPrivate *priv; +}; + +struct _MooCompletionClass +{ + GObjectClass parent_class; +}; + + +/* same as GCompletionFunc - must not allocate a new string; + but, it's safe to return static string and rewrite it on each call */ +typedef char* (*MooCompletionStringFunc) (gpointer data); +typedef void (*MooCompletionFreeFunc) (gpointer data); +typedef int (*MooCompletionCmpFunc) (gpointer data1, + gpointer data2); + + +GType moo_completion_get_type (void) G_GNUC_CONST; +GType moo_completion_group_get_type (void) G_GNUC_CONST; + +MooCompletionGroup *moo_completion_group_new_text (gboolean sorted); +MooCompletionGroup *moo_completion_group_new (MooCompletionStringFunc string_func, + MooCompletionFreeFunc free_func, + MooCompletionCmpFunc cmp_func); +/* these two steal data */ +void moo_completion_group_set_data (MooCompletionGroup *group, + GList *data); +void moo_completion_group_add_data (MooCompletionGroup *group, + GList *data); + +void moo_completion_group_set_pattern (MooCompletionGroup *group, + const char *pattern, + const guint *parens, + guint n_parens); + +MooCompletionGroup *moo_completion_group_ref (MooCompletionGroup *group); +void moo_completion_group_unref (MooCompletionGroup *group); + +MooCompletion *moo_completion_new (void); +/* steals words */ +MooCompletion *moo_completion_new_text (GList *words, + gboolean sorted); + +void moo_completion_try_complete (MooCompletion *cmpl, + gboolean insert_unique); +void moo_completion_hide (MooCompletion *cmpl); + +void moo_completion_set_doc (MooCompletion *cmpl, + GtkTextView *doc); +GtkTextView *moo_completion_get_doc (MooCompletion *cmpl); + +GtkListStore *moo_completion_get_store (MooCompletion *cmpl); + +void moo_completion_add_group (MooCompletion *cmpl, + MooCompletionGroup *group); + +MooTextPopup *moo_completion_get_popup (MooCompletion *cmpl); + +gboolean moo_completion_get_region (MooCompletion *cmpl, + GtkTextIter *start, + GtkTextIter *end); +void moo_completion_set_region (MooCompletion *cmpl, + const GtkTextIter *start, + const GtkTextIter *end); + + +G_END_DECLS + +#endif /* __MOO_COMPLETION_H__ */ diff --git a/moo/mooedit/mootextcompletion.c b/moo/mooedit/mootextcompletion.c deleted file mode 100644 index 44a12830..00000000 --- a/moo/mooedit/mootextcompletion.c +++ /dev/null @@ -1,737 +0,0 @@ -/* - * mootextcompletion.c - * - * Copyright (C) 2004-2006 by Yevgen Muntyan - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * See COPYING file that comes with this distribution. - */ - -#include "mooedit/mootextcompletion.h" -#include "mooedit/mootextpopup.h" -#include "mooutils/moomarshals.h" -#include "mooutils/eggregex.h" -#include -#include -#include - - -struct _MooTextCompletionPrivate { - GtkTreeModel *model; - GtkTreeModelFilter *filter; - int text_column; - MooTextCompletionFilterFunc filter_func; - gpointer data; - GDestroyNotify notify; - - EggRegex *regex; - guint *parens; - guint n_parens; - - char *line; - char *text; - guint text_len; - - GtkTextView *doc; - GtkTextBuffer *buffer; - GtkTextMark *start; - GtkTextMark *end; - - MooTextPopup *popup; - guint working : 1; - guint in_update : 1; -}; - - -static void moo_text_completion_dispose (GObject *object); - -static gboolean moo_text_completion_update_real (MooTextCompletion *cmpl); -static gboolean moo_text_completion_complete_real (MooTextCompletion *cmpl, - GtkTreeModel *model, - GtkTreeIter *iter); - -static void moo_text_completion_populate (MooTextCompletion *cmpl, - GtkTextIter *match_start, - GtkTextIter *match_end, - const char *match, - guint paren); -static void moo_text_completion_emit_complete (MooTextCompletion *cmpl, - GtkTreeModel *model, - GtkTreeIter *iter); - -static void moo_text_completion_connect_popup (MooTextCompletion *cmpl); -static void moo_text_completion_disconnect_popup(MooTextCompletion *cmpl); - -static gboolean moo_text_completion_empty (MooTextCompletion *cmpl); -static gboolean moo_text_completion_unique (MooTextCompletion *cmpl, - GtkTreeIter *iter); - -static gboolean filter_model_visible_func (GtkTreeModel *model, - GtkTreeIter *iter, - gpointer data); -static gboolean default_filter_func (MooTextCompletion *cmpl, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer data); - - -G_DEFINE_TYPE (MooTextCompletion, moo_text_completion, G_TYPE_OBJECT) - -enum { - POPULATE, - UPDATE, - COMPLETE, - NUM_SIGNALS -}; - -static guint signals[NUM_SIGNALS]; - - -static void -moo_text_completion_dispose (GObject *object) -{ - MooTextCompletion *cmpl = MOO_TEXT_COMPLETION (object); - - if (cmpl->priv) - { - moo_text_completion_set_doc (cmpl, NULL); - moo_text_completion_set_model (cmpl, NULL); - - if (cmpl->priv->notify) - cmpl->priv->notify (cmpl->priv->data); - - if (cmpl->priv->regex) - egg_regex_unref (cmpl->priv->regex); - - if (cmpl->priv->popup) - { - moo_text_completion_disconnect_popup (cmpl); - g_object_unref (cmpl->priv->popup); - } - - g_free (cmpl->priv->parens); - g_free (cmpl->priv->text); - g_free (cmpl->priv->line); - g_free (cmpl->priv); - cmpl->priv = NULL; - } - - G_OBJECT_CLASS(moo_text_completion_parent_class)->dispose (object); -} - - -static void -moo_text_completion_class_init (MooTextCompletionClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->dispose = moo_text_completion_dispose; - klass->complete = moo_text_completion_complete_real; - klass->update = moo_text_completion_update_real; - - signals[POPULATE] = - g_signal_new ("populate", - G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MooTextCompletionClass, populate), - NULL, NULL, - _moo_marshal_VOID__BOXED_BOXED_STRING_UINT, - G_TYPE_NONE, 4, - GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE, - GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE, - G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE, - G_TYPE_UINT); - - signals[UPDATE] = - g_signal_new ("update", - G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MooTextCompletionClass, update), - g_signal_accumulator_true_handled, NULL, - _moo_marshal_BOOLEAN__VOID, - G_TYPE_BOOLEAN, 0); - - signals[COMPLETE] = - g_signal_new ("complete", - G_OBJECT_CLASS_TYPE (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MooTextCompletionClass, complete), - g_signal_accumulator_true_handled, NULL, - _moo_marshal_BOOLEAN__OBJECT_BOXED, - G_TYPE_BOOLEAN, 2, - GTK_TYPE_TREE_MODEL, - GTK_TYPE_TREE_ITER | G_SIGNAL_TYPE_STATIC_SCOPE); -} - - -static void -moo_text_completion_init (MooTextCompletion *cmpl) -{ - cmpl->priv = g_new0 (MooTextCompletionPrivate, 1); - cmpl->priv->text_column = -1; - cmpl->priv->filter_func = default_filter_func; - cmpl->priv->popup = moo_text_popup_new (NULL); - moo_text_completion_connect_popup (cmpl); - cmpl->priv->regex = egg_regex_new ("\\b\\w+$", 0, 0, NULL); - cmpl->priv->parens = g_new0 (guint, 1); - cmpl->priv->n_parens = 1; -} - - -static gboolean -filter_model_visible_func (GtkTreeModel *model, - GtkTreeIter *iter, - gpointer data) -{ - MooTextCompletion *cmpl = data; - return cmpl->priv->filter_func (cmpl, model, iter, - cmpl->priv->data); -} - - -static gboolean -default_filter_func (MooTextCompletion *cmpl, - GtkTreeModel *model, - GtkTreeIter *iter, - G_GNUC_UNUSED gpointer dummy) -{ - gboolean visible = TRUE; - char *text = NULL; - - if (!cmpl->priv->text) - return TRUE; - - g_return_val_if_fail (cmpl->priv->text_column >= 0, TRUE); - - gtk_tree_model_get (model, iter, cmpl->priv->text_column, &text, -1); - g_return_val_if_fail (text != NULL, TRUE); - - if (cmpl->priv->text_len) - visible = !strncmp (text, cmpl->priv->text, cmpl->priv->text_len); - - g_free (text); - return visible; -} - - -MooTextCompletion * -moo_text_completion_new (void) -{ - return g_object_new (MOO_TYPE_TEXT_COMPLETION, NULL); -} - - -void -moo_text_completion_try_complete (MooTextCompletion *cmpl) -{ - GtkTextIter start, end; - GtkTreeIter iter; - gboolean found = FALSE; - guint paren = 0; - - g_return_if_fail (MOO_IS_TEXT_COMPLETION (cmpl)); - g_return_if_fail (cmpl->priv->buffer != NULL); - g_return_if_fail (cmpl->priv->model != NULL); - g_return_if_fail (!cmpl->priv->working); - - cmpl->priv->working = TRUE; - - gtk_text_buffer_get_iter_at_mark (cmpl->priv->buffer, &end, - gtk_text_buffer_get_insert (cmpl->priv->buffer)); - start = end; - - if (!gtk_text_iter_starts_line (&start)) - gtk_text_iter_set_line_offset (&start, 0); - - g_free (cmpl->priv->line); - cmpl->priv->line = gtk_text_buffer_get_slice (cmpl->priv->buffer, &start, &end, TRUE); - - egg_regex_clear (cmpl->priv->regex); - - if (egg_regex_match (cmpl->priv->regex, cmpl->priv->line, -1, 0) >= 1) - { - guint i; - - for (i = 0; i < cmpl->priv->n_parens; ++i) - { - int start_pos = -1, end_pos = -1; - - egg_regex_fetch_pos (cmpl->priv->regex, cmpl->priv->line, - cmpl->priv->parens[i], &start_pos, &end_pos); - - if (start_pos >= 0 && end_pos >= 0) - { - found = TRUE; - paren = i; - gtk_text_iter_set_line_index (&start, start_pos); - gtk_text_iter_set_line_index (&end, end_pos); - break; - } - } - } - - g_free (cmpl->priv->text); - - if (found) - { - cmpl->priv->text = gtk_text_buffer_get_slice (cmpl->priv->buffer, &start, &end, TRUE); - cmpl->priv->text_len = strlen (cmpl->priv->text); - moo_text_completion_set_region (cmpl, &start, &end); - moo_text_completion_populate (cmpl, &start, &end, cmpl->priv->text, paren); - } - else - { - cmpl->priv->text = NULL; - cmpl->priv->text_len = 0; - moo_text_completion_set_region (cmpl, &end, &end); - moo_text_completion_populate (cmpl, &end, &end, NULL, 0); - } - - if (moo_text_completion_empty (cmpl)) - { - cmpl->priv->working = FALSE; - return; - } - - if (moo_text_completion_unique (cmpl, &iter)) - { - moo_text_completion_emit_complete (cmpl, GTK_TREE_MODEL (cmpl->priv->filter), &iter); - cmpl->priv->working = FALSE; - return; - } - - moo_text_popup_show (cmpl->priv->popup, &start); -} - - -static gboolean -moo_text_completion_update_real (MooTextCompletion *cmpl) -{ - GtkTextIter start, end; - - g_return_val_if_fail (cmpl->priv->working, TRUE); - - moo_text_completion_get_region (cmpl, &start, &end); - g_free (cmpl->priv->text); - cmpl->priv->text = gtk_text_buffer_get_slice (cmpl->priv->buffer, &start, &end, TRUE); - cmpl->priv->text_len = strlen (cmpl->priv->text); - - gtk_tree_model_filter_refilter (cmpl->priv->filter); - - return TRUE; -} - - -static gboolean -moo_text_completion_complete_real (MooTextCompletion *cmpl, - GtkTreeModel *model, - GtkTreeIter *iter) -{ - char *text = NULL; - GtkTextIter start, end; - - g_return_val_if_fail (cmpl->priv->text_column >= 0, FALSE); - - gtk_tree_model_get (model, iter, cmpl->priv->text_column, &text, -1); - g_return_val_if_fail (text != 0, FALSE); - - moo_text_completion_get_region (cmpl, &start, &end); - gtk_text_buffer_begin_user_action (cmpl->priv->buffer); - gtk_text_buffer_delete (cmpl->priv->buffer, &start, &end); - gtk_text_buffer_insert (cmpl->priv->buffer, &start, text, -1); - gtk_text_buffer_end_user_action (cmpl->priv->buffer); - - g_free (text); - return TRUE; -} - - -static void -moo_text_completion_populate (MooTextCompletion *cmpl, - GtkTextIter *match_start, - GtkTextIter *match_end, - const char *match, - guint paren) -{ - g_signal_emit (cmpl, signals[POPULATE], 0, match_start, match_end, match, paren); -} - - -static void -moo_text_completion_emit_complete (MooTextCompletion *cmpl, - GtkTreeModel *model, - GtkTreeIter *iter) -{ - gboolean retval; - g_signal_emit (cmpl, signals[COMPLETE], 0, model, iter, &retval); -} - - -static gboolean -moo_text_completion_empty (MooTextCompletion *cmpl) -{ - return !cmpl->priv->filter || - !gtk_tree_model_iter_n_children (GTK_TREE_MODEL (cmpl->priv->filter), NULL); -} - - -static gboolean -moo_text_completion_unique (MooTextCompletion *cmpl, - GtkTreeIter *iter) -{ - return cmpl->priv->filter && - gtk_tree_model_iter_n_children (GTK_TREE_MODEL (cmpl->priv->filter), NULL) == 1 && - gtk_tree_model_get_iter_first (GTK_TREE_MODEL (cmpl->priv->filter), iter); -} - - -static void -moo_text_completion_update (MooTextCompletion *cmpl) -{ - gboolean retval; - - if (!cmpl->priv->working || cmpl->priv->in_update) - return; - - cmpl->priv->in_update = TRUE; - g_signal_emit (cmpl, signals[UPDATE], 0, &retval); - cmpl->priv->in_update = FALSE; - - if (moo_text_completion_empty (cmpl)) - moo_text_completion_hide (cmpl); - else - moo_text_popup_update (cmpl->priv->popup); -} - - -static void -on_popup_activate (MooTextCompletion *cmpl, - GtkTreeModel *model, - GtkTreeIter *iter) -{ - moo_text_completion_emit_complete (cmpl, model, iter); -} - - -static void -moo_text_completion_connect_popup (MooTextCompletion *cmpl) -{ - g_signal_connect_swapped (cmpl->priv->popup, "activate", - G_CALLBACK (on_popup_activate), cmpl); - g_signal_connect_swapped (cmpl->priv->popup, "text-changed", - G_CALLBACK (moo_text_completion_update), cmpl); - g_signal_connect_swapped (cmpl->priv->popup, "hide", - G_CALLBACK (moo_text_completion_hide), cmpl); -} - - -static void -moo_text_completion_disconnect_popup (MooTextCompletion *cmpl) -{ - g_signal_handlers_disconnect_by_func (cmpl->priv->popup, - (gpointer) on_popup_activate, - cmpl); - g_signal_handlers_disconnect_by_func (cmpl->priv->popup, - (gpointer) moo_text_completion_update, - cmpl); - g_signal_handlers_disconnect_by_func (cmpl->priv->popup, - (gpointer) moo_text_completion_hide, - cmpl); -} - - -void -moo_text_completion_complete (MooTextCompletion *cmpl) -{ - GtkTreeIter iter; - - g_return_if_fail (MOO_IS_TEXT_COMPLETION (cmpl)); - g_return_if_fail (cmpl->priv->working); - - if (moo_text_completion_unique (cmpl, &iter)) - moo_text_completion_emit_complete (cmpl, GTK_TREE_MODEL (cmpl->priv->filter), &iter); - else - moo_text_popup_activate (cmpl->priv->popup); - - moo_text_completion_hide (cmpl); -} - - -void -moo_text_completion_hide (MooTextCompletion *cmpl) -{ - g_return_if_fail (MOO_IS_TEXT_COMPLETION (cmpl)); - - if (cmpl->priv->working) - { - cmpl->priv->working = FALSE; - moo_text_popup_hide (cmpl->priv->popup); - } -} - - -void -moo_text_completion_set_doc (MooTextCompletion *cmpl, - GtkTextView *doc) -{ - g_return_if_fail (MOO_IS_TEXT_COMPLETION (cmpl)); - g_return_if_fail (!doc || GTK_IS_TEXT_VIEW (doc)); - - if (cmpl->priv->doc == doc) - return; - - moo_text_completion_hide (cmpl); - - g_free (cmpl->priv->line); - g_free (cmpl->priv->text); - cmpl->priv->line = NULL; - cmpl->priv->text = NULL; - cmpl->priv->text_len = 0; - - if (cmpl->priv->doc) - { - if (cmpl->priv->start) - gtk_text_buffer_delete_mark (cmpl->priv->buffer, cmpl->priv->start); - if (cmpl->priv->end) - gtk_text_buffer_delete_mark (cmpl->priv->buffer, cmpl->priv->end); - g_object_unref (cmpl->priv->doc); - cmpl->priv->start = cmpl->priv->end = NULL; - cmpl->priv->buffer = NULL; - cmpl->priv->doc = NULL; - } - - if (doc) - { - cmpl->priv->doc = g_object_ref (doc); - cmpl->priv->buffer = gtk_text_view_get_buffer (doc); - } - - moo_text_popup_set_doc (cmpl->priv->popup, doc); -} - - -GtkTextView * -moo_text_completion_get_doc (MooTextCompletion *cmpl) -{ - g_return_val_if_fail (MOO_IS_TEXT_COMPLETION (cmpl), NULL); - return cmpl->priv->doc; -} - - -void -moo_text_completion_set_model (MooTextCompletion *cmpl, - GtkTreeModel *model) -{ - g_return_if_fail (MOO_IS_TEXT_COMPLETION (cmpl)); - g_return_if_fail (!model || GTK_IS_TREE_MODEL (model)); - - if (cmpl->priv->model == model) - return; - - moo_text_completion_hide (cmpl); - - if (cmpl->priv->model) - { - g_object_unref (cmpl->priv->filter); - g_object_unref (cmpl->priv->model); - cmpl->priv->filter = NULL; - cmpl->priv->model = NULL; - } - - if (model) - { - cmpl->priv->model = g_object_ref (model); - cmpl->priv->filter = GTK_TREE_MODEL_FILTER ( - gtk_tree_model_filter_new (cmpl->priv->model, NULL)); - gtk_tree_model_filter_set_visible_func (cmpl->priv->filter, - filter_model_visible_func, - cmpl, NULL); - } - - moo_text_popup_set_model (cmpl->priv->popup, - GTK_TREE_MODEL (cmpl->priv->filter)); -} - - -GtkTreeModel * -moo_text_completion_get_model (MooTextCompletion *cmpl) -{ - g_return_val_if_fail (MOO_IS_TEXT_COMPLETION (cmpl), NULL); - return cmpl->priv->model; -} - - -void -moo_text_completion_set_filter_func (MooTextCompletion *cmpl, - MooTextCompletionFilterFunc func, - gpointer data, - GDestroyNotify notify) -{ - g_return_if_fail (MOO_IS_TEXT_COMPLETION (cmpl)); - - if (!func) - return moo_text_completion_set_filter_func (cmpl, default_filter_func, NULL, NULL); - - if (cmpl->priv->notify) - cmpl->priv->notify (cmpl->priv->data); - - cmpl->priv->filter_func = func; - cmpl->priv->notify = notify; - cmpl->priv->data = data; - - moo_text_completion_update (cmpl); -} - - -void -moo_text_completion_set_regex (MooTextCompletion *cmpl, - const char *pattern, - const guint *parens, - guint n_parens) -{ - EggRegex *regex; - GError *error = NULL; - char *real_pattern; - - g_return_if_fail (MOO_IS_TEXT_COMPLETION (cmpl)); - g_return_if_fail (pattern && pattern[0]); - g_return_if_fail (!parens || n_parens); - - moo_text_completion_hide (cmpl); - - real_pattern = g_strdup_printf ("%s$", pattern); - regex = egg_regex_new (real_pattern, 0, 0, &error); - - if (error) - { - g_warning ("%s: %s", G_STRLOC, error->message); - goto err; - } - - egg_regex_optimize (regex, &error); - - if (error) - { - g_warning ("%s: %s", G_STRLOC, error->message); - g_error_free (error); - } - - egg_regex_unref (cmpl->priv->regex); - g_free (cmpl->priv->parens); - - if (!parens) - { - cmpl->priv->parens = g_new0 (guint, 1); - cmpl->priv->n_parens = 1; - } - else - { - cmpl->priv->parens = g_memdup (parens, n_parens * sizeof (guint)); - cmpl->priv->n_parens = n_parens; - } - - return; - -err: - if (error) - g_error_free (error); - g_free (real_pattern); - egg_regex_unref (regex); -} - - -void -moo_text_completion_set_text_column (MooTextCompletion *cmpl, - int column) -{ - g_return_if_fail (MOO_IS_TEXT_COMPLETION (cmpl)); - cmpl->priv->text_column = column; -} - - -MooTextPopup * -moo_text_completion_get_popup (MooTextCompletion *cmpl) -{ - g_return_val_if_fail (MOO_IS_TEXT_COMPLETION (cmpl), NULL); - return cmpl->priv->popup; -} - - -gboolean -moo_text_completion_get_region (MooTextCompletion *cmpl, - GtkTextIter *start, - GtkTextIter *end) -{ - g_return_val_if_fail (MOO_IS_TEXT_COMPLETION (cmpl), FALSE); - - if (cmpl->priv->start) - { - if (start) - gtk_text_buffer_get_iter_at_mark (cmpl->priv->buffer, start, - cmpl->priv->start); - if (end) - gtk_text_buffer_get_iter_at_mark (cmpl->priv->buffer, end, - cmpl->priv->end); - return TRUE; - } - else - { - return FALSE; - } -} - - -void -moo_text_completion_set_region (MooTextCompletion *cmpl, - const GtkTextIter *start, - const GtkTextIter *end) -{ - g_return_if_fail (MOO_IS_TEXT_COMPLETION (cmpl)); - g_return_if_fail (start && end); - g_return_if_fail (cmpl->priv->buffer != NULL); - - if (!cmpl->priv->start) - { - cmpl->priv->start = gtk_text_buffer_create_mark (cmpl->priv->buffer, NULL, start, TRUE); - cmpl->priv->end = gtk_text_buffer_create_mark (cmpl->priv->buffer, NULL, end, FALSE); - } - else - { - gtk_text_buffer_move_mark (cmpl->priv->buffer, cmpl->priv->start, start); - gtk_text_buffer_move_mark (cmpl->priv->buffer, cmpl->priv->end, end); - } - - moo_text_popup_set_position (cmpl->priv->popup, start); - moo_text_completion_update (cmpl); -} - - -MooTextCompletion * -moo_text_completion_new_text (GtkTextView *doc, - GtkTreeModel *model, - int text_column) -{ - MooTextCompletion *cmpl; - GtkCellRenderer *cell; - - g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL); - g_return_val_if_fail (gtk_tree_model_get_column_type (model, text_column) == G_TYPE_STRING, NULL); - - cmpl = moo_text_completion_new (); - moo_text_completion_set_model (cmpl, model); - moo_text_completion_set_text_column (cmpl, text_column); - - cell = gtk_cell_renderer_text_new (); - gtk_tree_view_column_pack_start (cmpl->priv->popup->column, cell, TRUE); - gtk_tree_view_column_set_attributes (cmpl->priv->popup->column, cell, - "text", text_column, NULL); - - if (doc) - moo_text_completion_set_doc (cmpl, doc); - - return cmpl; -} diff --git a/moo/mooedit/mootextcompletion.h b/moo/mooedit/mootextcompletion.h deleted file mode 100644 index c5d9678b..00000000 --- a/moo/mooedit/mootextcompletion.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * mootextcompletion.h - * - * Copyright (C) 2004-2006 by Yevgen Muntyan - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * See COPYING file that comes with this distribution. - */ - -#ifndef __MOO_TEXT_COMPLETION_H__ -#define __MOO_TEXT_COMPLETION_H__ - -#include "mooedit/mootextpopup.h" - -G_BEGIN_DECLS - - -#define MOO_TYPE_TEXT_COMPLETION (moo_text_completion_get_type ()) -#define MOO_TEXT_COMPLETION(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_TEXT_COMPLETION, MooTextCompletion)) -#define MOO_TEXT_COMPLETION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_TEXT_COMPLETION, MooTextCompletionClass)) -#define MOO_IS_TEXT_COMPLETION(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOO_TYPE_TEXT_COMPLETION)) -#define MOO_IS_TEXT_COMPLETION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_TEXT_COMPLETION)) -#define MOO_TEXT_COMPLETION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_TEXT_COMPLETION, MooTextCompletionClass)) - - -typedef struct _MooTextCompletion MooTextCompletion; -typedef struct _MooTextCompletionPrivate MooTextCompletionPrivate; -typedef struct _MooTextCompletionClass MooTextCompletionClass; - -typedef gboolean (*MooTextCompletionFilterFunc) (MooTextCompletion *cmpl, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer data); - -struct _MooTextCompletion -{ - GObject parent; - MooTextCompletionPrivate *priv; -}; - -struct _MooTextCompletionClass -{ - GObjectClass parent_class; - - void (*populate) (MooTextCompletion *cmpl, - GtkTextIter *match_start, - GtkTextIter *match_end, - const char *match, - guint paren); - - gboolean (*update) (MooTextCompletion *cmpl); - gboolean (*complete) (MooTextCompletion *cmpl, - GtkTreeModel *model, - GtkTreeIter *iter); -}; - - -GType moo_text_completion_get_type (void) G_GNUC_CONST; - -MooTextCompletion *moo_text_completion_new (void); -MooTextCompletion *moo_text_completion_new_text (GtkTextView *doc, - GtkTreeModel *model, - int text_column); - -void moo_text_completion_try_complete (MooTextCompletion *cmpl); -void moo_text_completion_complete (MooTextCompletion *cmpl); -void moo_text_completion_hide (MooTextCompletion *cmpl); - -void moo_text_completion_set_doc (MooTextCompletion *cmpl, - GtkTextView *doc); -GtkTextView *moo_text_completion_get_doc (MooTextCompletion *cmpl); - -void moo_text_completion_set_model (MooTextCompletion *cmpl, - GtkTreeModel *model); -GtkTreeModel *moo_text_completion_get_model (MooTextCompletion *cmpl); - -void moo_text_completion_set_filter_func (MooTextCompletion *cmpl, - MooTextCompletionFilterFunc func, - gpointer data, - GDestroyNotify notify); -void moo_text_completion_set_regex (MooTextCompletion *cmpl, - const char *pattern, - const guint *parens, - guint n_parens); -void moo_text_completion_set_text_column (MooTextCompletion *cmpl, - int column); - -MooTextPopup *moo_text_completion_get_popup (MooTextCompletion *cmpl); - -gboolean moo_text_completion_get_region (MooTextCompletion *cmpl, - GtkTextIter *start, - GtkTextIter *end); -void moo_text_completion_set_region (MooTextCompletion *cmpl, - const GtkTextIter *start, - const GtkTextIter *end); - - -G_END_DECLS - -#endif /* __MOO_TEXT_COMPLETION_H__ */ diff --git a/moo/mooedit/plugins/completion/completion.c b/moo/mooedit/plugins/completion/completion.c index e9bc49ca..79487703 100644 --- a/moo/mooedit/plugins/completion/completion.c +++ b/moo/mooedit/plugins/completion/completion.c @@ -12,7 +12,7 @@ */ #include "completion.h" -#include "mooedit/mootextcompletion.h" +#include "mooedit/moocompletion.h" #include "mooutils/mooutils-misc.h" #include #include @@ -22,7 +22,7 @@ typedef struct { char *path; time_t mtime; - GtkListStore *store; + MooCompletion *cmpl; } CmplData; static CmplData *cmpl_data_new (void); @@ -55,13 +55,11 @@ cmpl_data_read_file (CmplData *data) GError *error = NULL; char *contents; char **words, **p; - GList *list = NULL, *l; + GList *list = NULL; - g_return_if_fail (data->store == NULL); + g_return_if_fail (data->cmpl == NULL); g_return_if_fail (data->path != NULL); - data->store = gtk_list_store_new (1, G_TYPE_STRING); - g_file_get_contents (data->path, &contents, NULL, &error); if (error) @@ -93,19 +91,11 @@ cmpl_data_read_file (CmplData *data) g_free (*p); } - list = g_list_sort (list, (GCompareFunc) strcmp); + data->cmpl = moo_completion_new_text (list, TRUE); g_message ("read %d words from %s", g_list_length (list), data->path); - for (l = list; l != NULL; l = l->next) - { - GtkTreeIter iter; - gtk_list_store_append (data->store, &iter); - gtk_list_store_set (data->store, &iter, 0, l->data, -1); - g_free (l->data); - } - g_free (contents); - g_strfreev (words); + g_free (words); } @@ -123,7 +113,7 @@ cmpl_plugin_load_data (CmplPlugin *plugin, data = cmpl_data_new (); g_hash_table_insert (plugin->data, g_strdup (id), data); } - else if (!data->store && data->path) + else if (!data->cmpl && data->path) { cmpl_data_read_file (data); } @@ -143,10 +133,10 @@ static void cmpl_data_clear (CmplData *data) { g_free (data->path); - if (data->store) - g_object_unref (data->store); + if (data->cmpl) + g_object_unref (data->cmpl); data->path = NULL; - data->store = NULL; + data->cmpl = NULL; } @@ -275,23 +265,15 @@ _completion_complete (CmplPlugin *plugin, { MooLang *lang; CmplData *data; - MooTextCompletion *cmpl; lang = moo_text_view_get_lang (MOO_TEXT_VIEW (doc)); data = cmpl_plugin_load_data (plugin, lang ? lang->id : NULL); g_return_if_fail (data != NULL); - cmpl = g_object_get_data (G_OBJECT (doc), "moo-completion"); - - if (!cmpl) + if (data->cmpl) { - cmpl = moo_text_completion_new_text (GTK_TEXT_VIEW (doc), - GTK_TREE_MODEL (data->store), - 0); - g_object_set_data_full (G_OBJECT (doc), "moo-completion", - cmpl, g_object_unref); + moo_completion_set_doc (data->cmpl, GTK_TEXT_VIEW (doc)); + moo_completion_try_complete (data->cmpl, TRUE); } - - moo_text_completion_try_complete (cmpl); } diff --git a/moo/mooutils/moomarshals.list b/moo/mooutils/moomarshals.list index 4a7305f7..37721a2b 100644 --- a/moo/mooutils/moomarshals.list +++ b/moo/mooutils/moomarshals.list @@ -4,6 +4,7 @@ BOOL:ENUM,INT,BOOL BOOL:INT BOOL:OBJECT,BOXED BOOL:OBJECT,OBJECT +BOOL:POINTER BOOL:STRING BOOL:STRING,BOOL BOOL:STRING,OBJECT,OBJECT,INT,INT,UINT @@ -17,7 +18,6 @@ OBJECT:OBJECT VOID:BOOL VOID:BOXED VOID:BOXED,BOXED -VOID:BOXED,BOXED,STRING,UINT VOID:BOXED,OBJECT VOID:BOXED,POINTER VOID:CHAR,STRING,UINT