Filter patterns, check_visible() and check_sensitive()

master
Yevgen Muntyan 2006-08-22 23:21:14 -05:00
parent 6841eb4d9f
commit 23e4e9d53e
2 changed files with 278 additions and 10 deletions

View File

@ -15,29 +15,63 @@
#include "mooedit/mooeditaction.h"
#include "mooedit/mooeditaction-factory.h"
#include "mooedit/mooedit-private.h"
#include "mooutils/eggregex.h"
#include <string.h>
typedef enum {
FILTER_SENSITIVE,
FILTER_VISIBLE
} FilterType;
#define N_FILTERS 2
struct _MooEditActionPrivate {
MooEdit *doc;
GSList *langs;
EggRegex *filters[N_FILTERS];
};
typedef struct {
EggRegex *regex;
guint use_count;
} RegexRef;
typedef struct {
GHashTable *hash;
} FilterStore;
static FilterStore filter_store;
G_DEFINE_TYPE (MooEditAction, moo_edit_action, MOO_TYPE_ACTION);
enum {
PROP_0,
PROP_DOC,
PROP_LANGS
PROP_LANGS,
PROP_FILTER_SENSITIVE,
PROP_FILTER_VISIBLE
};
static EggRegex *get_filter_regex (const char *pattern);
static void unuse_filter_regex (EggRegex *regex);
static gboolean moo_edit_action_check_visible (MooEditAction *action);
static gboolean moo_edit_action_check_sensitive (MooEditAction *action);
static void moo_edit_action_check_state (MooEditAction *action);
static void
moo_edit_action_finalize (GObject *object)
{
guint i;
MooEditAction *action = MOO_EDIT_ACTION (object);
for (i = 0; i < N_FILTERS; ++i)
if (action->priv->filters[i])
unuse_filter_regex (action->priv->filters[i]);
g_slist_foreach (action->priv->langs, (GFunc) g_free, NULL);
g_slist_free (action->priv->langs);
@ -45,6 +79,16 @@ moo_edit_action_finalize (GObject *object)
}
static const char *
moo_edit_action_get_filter (MooEditAction *action,
FilterType type)
{
g_assert (type < N_FILTERS);
return action->priv->filters[type] ?
egg_regex_get_pattern (action->priv->filters[type]) : NULL;
}
static void
moo_edit_action_get_property (GObject *object,
guint prop_id,
@ -59,6 +103,14 @@ moo_edit_action_get_property (GObject *object,
g_value_set_object (value, action->priv->doc);
break;
case PROP_FILTER_VISIBLE:
g_value_set_string (value, moo_edit_action_get_filter (action, FILTER_VISIBLE));
break;
case PROP_FILTER_SENSITIVE:
g_value_set_string (value, moo_edit_action_get_filter (action, FILTER_SENSITIVE));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@ -91,6 +143,21 @@ moo_edit_action_get_doc (MooEditAction *action)
}
static void
moo_edit_action_set_filter (MooEditAction *action,
const char *filter,
FilterType type)
{
EggRegex *tmp;
g_assert (type < N_FILTERS);
tmp = action->priv->filters[type];
action->priv->filters[type] = filter ? get_filter_regex (filter) : NULL;
unuse_filter_regex (tmp);
}
static void
moo_edit_action_set_property (GObject *object,
guint prop_id,
@ -110,6 +177,18 @@ moo_edit_action_set_property (GObject *object,
moo_edit_action_set_langs (action, g_value_get_string (value));
break;
case PROP_FILTER_SENSITIVE:
moo_edit_action_set_filter (action,
g_value_get_string (value),
FILTER_SENSITIVE);
break;
case PROP_FILTER_VISIBLE:
moo_edit_action_set_filter (action,
g_value_get_string (value),
FILTER_VISIBLE);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@ -123,19 +202,89 @@ moo_edit_action_init (MooEditAction *action)
}
static const char *
get_current_line (MooEdit *doc)
{
char *line;
line = g_object_get_data (G_OBJECT (doc), "moo-edit-current-line");
if (!line)
{
GtkTextIter line_start, line_end;
GtkTextBuffer *buffer;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (doc));
gtk_text_buffer_get_iter_at_mark (buffer, &line_start,
gtk_text_buffer_get_insert (buffer));
line_end = line_start;
gtk_text_iter_set_line_offset (&line_start, 0);
if (!gtk_text_iter_ends_line (&line_end))
gtk_text_iter_forward_to_line_end (&line_end);
line = gtk_text_buffer_get_slice (buffer, &line_start, &line_end, TRUE);
g_object_set_data_full (G_OBJECT (doc), "moo-edit-current-line", line, g_free);
}
return line;
}
static gboolean
moo_edit_action_check_visible_real (MooEditAction *action)
{
MooLang *lang;
gboolean visible = TRUE;
EggRegex *filter = action->priv->filters[FILTER_VISIBLE];
if (!action->priv->doc)
return gtk_action_get_visible (GTK_ACTION (action));
if (!action->priv->langs && !filter)
return gtk_action_get_visible (GTK_ACTION (action));
if (visible && action->priv->langs)
{
lang = moo_text_view_get_lang (MOO_TEXT_VIEW (action->priv->doc));
if (!g_slist_find_custom (action->priv->langs, moo_lang_id (lang), (GCompareFunc) strcmp))
visible = FALSE;
}
if (visible && filter)
{
const char *line = get_current_line (action->priv->doc);
if (!egg_regex_match (filter, line, 0))
visible = FALSE;
}
return visible;
}
static gboolean
moo_edit_action_check_sensitive_real (MooEditAction *action)
{
const char *line;
EggRegex *filter = action->priv->filters[FILTER_SENSITIVE];
if (!action->priv->doc || !filter)
return gtk_action_get_visible (GTK_ACTION (action));
line = get_current_line (action->priv->doc);
return egg_regex_match (filter, line, 0);
}
static void
moo_edit_action_check_state_real (MooEditAction *action)
{
MooLang *lang;
gboolean active;
gboolean visible, sensitive;
if (!action->priv->doc || !action->priv->langs)
return;
visible = moo_edit_action_check_visible (action);
sensitive = moo_edit_action_check_sensitive (action);
lang = moo_text_view_get_lang (MOO_TEXT_VIEW (action->priv->doc));
active = g_slist_find_custom (action->priv->langs, moo_lang_id (lang), (GCompareFunc) strcmp) != NULL;
g_object_set (action, "visible", active, "sensitive", active, NULL);
g_object_set (action, "sensitive", sensitive, "visible", visible, NULL);
}
@ -149,6 +298,8 @@ moo_edit_action_class_init (MooEditActionClass *klass)
gobject_class->get_property = moo_edit_action_get_property;
klass->check_state = moo_edit_action_check_state_real;
klass->check_visible = moo_edit_action_check_visible_real;
klass->check_sensitive = moo_edit_action_check_sensitive_real;
g_type_class_add_private (klass, sizeof (MooEditActionPrivate));
@ -167,9 +318,47 @@ moo_edit_action_class_init (MooEditActionClass *klass)
"langs",
NULL,
G_PARAM_WRITABLE));
g_object_class_install_property (gobject_class,
PROP_FILTER_SENSITIVE,
g_param_spec_string ("filter-sensitive",
"filter-sensitive",
"filter-sensitive",
NULL,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_FILTER_VISIBLE,
g_param_spec_string ("filter-visible",
"filter-visible",
"filter-visible",
NULL,
G_PARAM_READWRITE));
}
static gboolean
moo_edit_action_check_visible (MooEditAction *action)
{
g_return_val_if_fail (MOO_IS_EDIT_ACTION (action), TRUE);
if (MOO_EDIT_ACTION_GET_CLASS (action)->check_visible)
return MOO_EDIT_ACTION_GET_CLASS (action)->check_visible (action);
else
return gtk_action_get_visible (GTK_ACTION (action));
}
static gboolean
moo_edit_action_check_sensitive (MooEditAction *action)
{
g_return_val_if_fail (MOO_IS_EDIT_ACTION (action), TRUE);
if (MOO_EDIT_ACTION_GET_CLASS (action)->check_sensitive)
return MOO_EDIT_ACTION_GET_CLASS (action)->check_sensitive (action);
else
return gtk_action_get_sensitive (GTK_ACTION (action));
}
static void
moo_edit_action_check_state (MooEditAction *action)
{
@ -192,3 +381,79 @@ _moo_edit_check_actions (MooEdit *edit)
actions = g_list_delete_link (actions, actions);
}
}
static void
regex_ref_free (RegexRef *ref)
{
if (ref)
{
egg_regex_unref (ref->regex);
g_free (ref);
}
}
static void
init_filter_store (void)
{
if (!filter_store.hash)
filter_store.hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
(GDestroyNotify) regex_ref_free);
}
static EggRegex *
get_filter_regex (const char *pattern)
{
RegexRef *ref;
g_return_val_if_fail (pattern != NULL, NULL);
init_filter_store ();
ref = g_hash_table_lookup (filter_store.hash, pattern);
if (!ref)
{
EggRegex *regex;
GError *error = NULL;
regex = egg_regex_new (pattern, 0, 0, &error);
if (!regex)
{
g_warning ("%s: %s", G_STRLOC, error->message);
g_error_free (error);
return NULL;
}
egg_regex_optimize (regex, NULL);
ref = g_new0 (RegexRef, 1);
ref->regex = regex;
g_hash_table_insert (filter_store.hash, g_strdup (pattern), ref);
}
ref->use_count++;
return ref->regex;
}
static void
unuse_filter_regex (EggRegex *regex)
{
RegexRef *ref;
const char *pattern;
g_return_if_fail (regex != NULL);
init_filter_store ();
pattern = egg_regex_get_pattern (regex);
ref = g_hash_table_lookup (filter_store.hash, pattern);
g_return_if_fail (ref != NULL);
if (!--ref->use_count)
g_hash_table_remove (filter_store.hash, pattern);
}

View File

@ -41,7 +41,10 @@ struct _MooEditActionClass
{
MooActionClass parent_class;
void (*check_state) (MooEditAction *action);
void (*check_state) (MooEditAction *action);
gboolean (*check_visible) (MooEditAction *action);
gboolean (*check_sensitive) (MooEditAction *action);
};