Renamed MooTextCompletion back to MooCompletion; removed signals; removed GtkTreeModelFilter stuff
This commit is contained in:
parent
823788610b
commit
d95d0e9115
@ -33,7 +33,7 @@
|
||||
<kdevautoproject>
|
||||
<general>
|
||||
<activetarget>moo/libmoo.la</activetarget>
|
||||
<useconfiguration>optimized</useconfiguration>
|
||||
<useconfiguration>debug</useconfiguration>
|
||||
</general>
|
||||
<run>
|
||||
<mainprogram>./medit</mainprogram>
|
||||
|
@ -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 \
|
||||
|
764
moo/mooedit/moocompletion.c
Normal file
764
moo/mooedit/moocompletion.c
Normal file
@ -0,0 +1,764 @@
|
||||
/*
|
||||
* moocompletion.c
|
||||
*
|
||||
* Copyright (C) 2004-2006 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
*
|
||||
* 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 <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
107
moo/mooedit/moocompletion.h
Normal file
107
moo/mooedit/moocompletion.h
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* moocompletion.h
|
||||
*
|
||||
* Copyright (C) 2004-2006 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
*
|
||||
* 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 <gtk/gtkliststore.h>
|
||||
|
||||
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__ */
|
@ -1,737 +0,0 @@
|
||||
/*
|
||||
* mootextcompletion.c
|
||||
*
|
||||
* Copyright (C) 2004-2006 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
*
|
||||
* 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 <gtk/gtk.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* mootextcompletion.h
|
||||
*
|
||||
* Copyright (C) 2004-2006 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
*
|
||||
* 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__ */
|
@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "completion.h"
|
||||
#include "mooedit/mootextcompletion.h"
|
||||
#include "mooedit/moocompletion.h"
|
||||
#include "mooutils/mooutils-misc.h"
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user