-void
-gtk_binding_set_add_path (GtkBindingSet *binding_set,
- GtkPathType path_type,
- const gchar *path_pattern,
- GtkPathPriorityType priority)
-{
- PatternSpec *pspec;
- GSList **slist_p, *slist;
- static guint seq_id = 0;
-
- g_return_if_fail (binding_set != NULL);
- g_return_if_fail (path_pattern != NULL);
- g_return_if_fail (priority <= GTK_PATH_PRIO_MASK);
-
- priority &= GTK_PATH_PRIO_MASK;
-
- switch (path_type)
- {
- case GTK_PATH_WIDGET:
- slist_p = &binding_set->widget_path_pspecs;
- break;
- case GTK_PATH_WIDGET_CLASS:
- slist_p = &binding_set->widget_class_pspecs;
- break;
- case GTK_PATH_CLASS:
- slist_p = &binding_set->class_branch_pspecs;
- break;
- default:
- g_assert_not_reached ();
- slist_p = NULL;
- break;
- }
-
- pspec = g_new (PatternSpec, 1);
- pspec->pspec = g_pattern_spec_new (path_pattern);
- pspec->seq_id = priority << 28;
- pspec->user_data = binding_set;
-
- slist = *slist_p;
- while (slist)
- {
- PatternSpec *tmp_pspec;
-
- tmp_pspec = slist->data;
- slist = slist->next;
-
- if (g_pattern_spec_equal (tmp_pspec->pspec, pspec->pspec))
- {
- GtkPathPriorityType lprio = tmp_pspec->seq_id >> 28;
-
- g_pattern_spec_free (pspec->pspec);
- g_free (pspec);
- pspec = NULL;
- if (lprio < priority)
- {
- tmp_pspec->seq_id &= 0x0fffffff;
- tmp_pspec->seq_id |= priority << 28;
- }
- break;
- }
- }
- if (pspec)
- {
- pspec->seq_id |= seq_id++ & 0x0fffffff;
- *slist_p = g_slist_prepend (*slist_p, pspec);
- }
-}
-
-static inline gboolean
-binding_match_activate (GSList *pspec_list,
- GtkObject *object,
- guint path_length,
- const gchar *path,
- const gchar *path_reversed)
-{
- GSList *slist;
-
- for (slist = pspec_list; slist; slist = slist->next)
- {
- PatternSpec *pspec;
-
- pspec = slist->data;
- if (g_pattern_match (pspec->pspec, path_length, path, path_reversed))
- {
- GtkBindingSet *binding_set;
-
- binding_set = pspec->user_data;
-
- if (gtk_binding_entry_activate (binding_set->current, object))
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static gint
-gtk_binding_pattern_compare (gconstpointer new_pattern,
- gconstpointer existing_pattern)
-{
- register const PatternSpec *np = new_pattern;
- register const PatternSpec *ep = existing_pattern;
-
- /* walk the list as long as the existing patterns have
- * higher priorities.
- */
-
- return np->seq_id < ep->seq_id;
-}
-
-static inline GSList*
-gtk_binding_entries_sort_patterns (GtkBindingEntry *entries,
- GtkPathType path_id)
-{
- GSList *patterns;
-
- patterns = NULL;
- while (entries)
- {
- register GtkBindingSet *binding_set;
- GSList *slist = NULL;
-
- binding_set = entries->binding_set;
- binding_set->current = entries;
-
- switch (path_id)
- {
- case GTK_PATH_WIDGET:
- slist = binding_set->widget_path_pspecs;
- break;
- case GTK_PATH_WIDGET_CLASS:
- slist = binding_set->widget_class_pspecs;
- break;
- case GTK_PATH_CLASS:
- slist = binding_set->class_branch_pspecs;
- break;
- }
-
- for (; slist; slist = slist->next)
- {
- PatternSpec *pspec;
-
- pspec = slist->data;
- patterns = g_slist_insert_sorted (patterns, pspec, gtk_binding_pattern_compare);
- }
-
- entries = entries->hash_next;
- }
-
- return patterns;
-}
-
-
-gboolean
-gtk_bindings_activate (GtkObject *object,
- guint keyval,
- GdkModifierType modifiers)
-{
- GtkBindingEntry *entries;
- GtkWidget *widget;
- gboolean handled = FALSE;
-
- g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
-
- if (!GTK_IS_WIDGET (object))
- return FALSE;
-
- widget = GTK_WIDGET (object);
-
- keyval = gdk_keyval_to_lower (keyval);
- modifiers = modifiers & BINDING_MOD_MASK ();
-
- entries = binding_ht_lookup_list (keyval, modifiers);
-
- if (!entries)
- return FALSE;
-
- if (!handled)
- {
- guint path_length;
- gchar *path, *path_reversed;
- GSList *patterns;
-
- gtk_widget_path (widget, &path_length, &path, &path_reversed);
- patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET);
- handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
- g_slist_free (patterns);
- g_free (path);
- g_free (path_reversed);
- }
-
- if (!handled)
- {
- guint path_length;
- gchar *path, *path_reversed;
- GSList *patterns;
-
- gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
- patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET_CLASS);
- handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
- g_slist_free (patterns);
- g_free (path);
- g_free (path_reversed);
- }
-
- if (!handled)
- {
- GSList *patterns;
- GtkType class_type;
-
- patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_CLASS);
- class_type = GTK_OBJECT_TYPE (object);
- while (class_type && !handled)
- {
- guint path_length;
- const gchar *path;
- gchar *path_reversed;
-
- path = gtk_type_name (class_type);
- path_reversed = g_strdup (path);
- g_strreverse (path_reversed);
- path_length = strlen (path);
- handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
- g_free (path_reversed);
-
- class_type = gtk_type_parent (class_type);
- }
- g_slist_free (patterns);
- }
-
- return handled;
-}
-