]> Pileus Git - ~andy/gtk/blob - gtk/gtkbindings.c
Add optional colord support to the CUPS print module
[~andy/gtk] / gtk / gtkbindings.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * GtkBindingSet: Keybinding manager for GObjects.
5  * Copyright (C) 1998 Tim Janik
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /*
24  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
25  * file for a list of people on the GTK+ Team.  See the ChangeLog
26  * files for a list of changes.  These files are distributed with
27  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28  */
29
30 #include "config.h"
31 #include <string.h>
32 #include <stdarg.h>
33
34 #include "gtkbindingsprivate.h"
35 #include "gtkkeyhash.h"
36 #include "gtkwidget.h"
37 #include "gtkrc.h"
38 #include "gtkintl.h"
39
40 /**
41  * SECTION:gtkbindings
42  * @Title: Bindings
43  * @Short_description: Key bindings for individual widgets
44  * @See_also: Keyboard Accelerators, Mnemonics, #GtkCssProvider
45  *
46  * #GtkBindingSet provides a mechanism for configuring GTK+ key bindings
47  * through CSS files. This eases key binding adjustments for application
48  * developers as well as users and provides GTK+ users or administrators
49  * with high key  binding configurability which requires no application
50  * or toolkit side changes.
51  *
52  * <refsect2 id="gtk-bindings-install">
53  * <title>Installing a key binding</title>
54  * <para>
55  * A CSS file binding consists of a 'binding-set' definition and a match
56  * statement to apply the binding set to specific widget types. Details
57  * on the matching mechanism are described under
58  * <link linkend="gtkcssprovider-selectors">Selectors</link>
59  * in the #GtkCssProvider documentation. Inside the binding set definition,
60  * key combinations are bound to one or more specific signal emissions on
61  * the target widget. Key combinations are strings consisting of an optional
62  * #GdkModifierType name and <link linkend="gdk-Keyboard-Handling">key names</link>
63  * such as those defined in <filename>&lt;gdk/gdkkeysyms.h&gt;</filename>
64  * or returned from gdk_keyval_name(), they have to be parsable by
65  * gtk_accelerator_parse(). Specifications of signal emissions consist
66  * of a string identifying the signal name, and a list of signal specific
67  * arguments in parenthesis.
68  * </para>
69  * <para>
70  * For example for binding Control and the left or right cursor keys
71  * of a #GtkEntry widget to the #GtkEntry::move-cursor signal (so movement
72  * occurs in 3-character steps), the following binding can be used:
73  * <informalexample><programlisting>
74  * @binding-set MoveCursor3
75  * {
76  *   bind "&lt;Control&gt;Right" { "move-cursor" (visual-positions, 3, 0) };
77  *   bind "&lt;Control&gt;Left" { "move-cursor" (visual-positions, -3, 0) };
78  * };
79  * GtkEntry
80  * {
81  *   gtk-key-bindings: MoveCursor3
82  * }
83  * </programlisting></informalexample>
84  * </para>
85  * </refsect2>
86  * <refsect2 id="gtk-bindings-unbind">
87  * <title>Unbinding existing key bindings</title>
88  * <para>
89  * GTK+ already defines a number of useful bindings for the widgets
90  * it provides. Because custom bindings set up in CSS files take
91  * precedence over the default bindings shipped with GTK+, overriding
92  * existing bindings as demonstrated in
93  * <link linkend="gtk-bindings-install">Installing a key binding</link>
94  * works as expected. The same mechanism can not be used to "unbind"
95  * existing bindings, however.
96  * <informalexample><programlisting>
97  * @binding-set MoveCursor3
98  * {
99  *   bind "&lt;Control&gt;Right" {  };
100  *   bind "&lt;Control&gt;Left" {  };
101  * };
102  * GtkEntry
103  * {
104  *   gtk-key-bindings: MoveCursor3
105  * }
106  * </programlisting></informalexample>
107  * The above example will not have the desired effect of causing
108  * "&lt;Control&gt;Right" and "&lt;Control&gt;Left" key presses to
109  * be ignored by GTK+. Instead, it just causes any existing bindings
110  * from the bindings set "MoveCursor3" to be deleted, so when
111  * "&lt;Control&gt;Right" or "&lt;Control&gt;Left" are pressed, no
112  * binding for these keys is found in binding set "MoveCursor3".
113  * GTK+ will thus continue to search for matching key bindings, and will
114  * eventually lookup and find the default GTK+ bindings for entries which
115  * implement word movement. To keep GTK+ from activating its default
116  * bindings, the "unbind" keyword can be used like this:
117  * <informalexample><programlisting>
118  * @binding-set MoveCursor3
119  * {
120  *   unbind "&lt;Control&gt;Right";
121  *   unbind "&lt;Control&gt;Left";
122  * };
123  * GtkEntry
124  * {
125  *   gtk-key-bindings: MoveCursor3
126  * }
127  * </programlisting></informalexample>
128  * Now, GTK+ will find a match when looking up "&lt;Control&gt;Right"
129  * and "&lt;Control&gt;Left" key presses before it resorts to its default
130  * bindings, and the match instructs it to abort ("unbind") the search,
131  * so the key presses are not consumed by this widget. As usual, further
132  * processing of the key presses, e.g. by an entry's parent widget, is
133  * now possible.
134  * </para>
135  * </refsect2>
136  */
137
138 /* --- defines --- */
139 #define BINDING_MOD_MASK() (gtk_accelerator_get_default_mod_mask () | GDK_RELEASE_MASK)
140
141
142 #define GTK_TYPE_IDENTIFIER (gtk_identifier_get_type ())
143 GType gtk_identifier_get_type (void) G_GNUC_CONST;
144
145
146 /* --- structures --- */
147 typedef struct {
148   GtkPathType   type;
149   GPatternSpec *pspec;
150   gpointer      user_data;
151   guint         seq_id;
152 } PatternSpec;
153
154 typedef enum {
155   GTK_BINDING_TOKEN_BIND,
156   GTK_BINDING_TOKEN_UNBIND
157 } GtkBindingTokens;
158
159 /* --- variables --- */
160 static GHashTable       *binding_entry_hash_table = NULL;
161 static GSList           *binding_key_hashes = NULL;
162 static GSList           *binding_set_list = NULL;
163 static const gchar       key_class_binding_set[] = "gtk-class-binding-set";
164 static GQuark            key_id_class_binding_set = 0;
165
166
167 /* --- functions --- */
168 GType
169 gtk_identifier_get_type (void)
170 {
171   static GType our_type = 0;
172
173   if (our_type == 0)
174     {
175       GTypeInfo tinfo = { 0, };
176       our_type = g_type_register_static (G_TYPE_STRING, I_("GtkIdentifier"), &tinfo, 0);
177     }
178
179   return our_type;
180 }
181
182 static void
183 pattern_spec_free (PatternSpec *pspec)
184 {
185   if (pspec->pspec)
186     g_pattern_spec_free (pspec->pspec);
187   g_free (pspec);
188 }
189
190 static GtkBindingSignal*
191 binding_signal_new (const gchar *signal_name,
192                     guint        n_args)
193 {
194   GtkBindingSignal *signal;
195
196   signal = (GtkBindingSignal *) g_slice_alloc0 (sizeof (GtkBindingSignal) + n_args * sizeof (GtkBindingArg));
197   signal->next = NULL;
198   signal->signal_name = (gchar *)g_intern_string (signal_name);
199   signal->n_args = n_args;
200   signal->args = (GtkBindingArg *)(signal + 1);
201
202   return signal;
203 }
204
205 static void
206 binding_signal_free (GtkBindingSignal *sig)
207 {
208   guint i;
209
210   for (i = 0; i < sig->n_args; i++)
211     {
212       if (G_TYPE_FUNDAMENTAL (sig->args[i].arg_type) == G_TYPE_STRING)
213         g_free (sig->args[i].d.string_data);
214     }
215   g_slice_free1 (sizeof (GtkBindingSignal) + sig->n_args * sizeof (GtkBindingArg), sig);
216 }
217
218 static guint
219 binding_entry_hash (gconstpointer  key)
220 {
221   register const GtkBindingEntry *e = key;
222   register guint h;
223
224   h = e->keyval;
225   h ^= e->modifiers;
226
227   return h;
228 }
229
230 static gint
231 binding_entries_compare (gconstpointer  a,
232                          gconstpointer  b)
233 {
234   register const GtkBindingEntry *ea = a;
235   register const GtkBindingEntry *eb = b;
236
237   return (ea->keyval == eb->keyval && ea->modifiers == eb->modifiers);
238 }
239
240 static void
241 binding_key_hash_insert_entry (GtkKeyHash      *key_hash,
242                                GtkBindingEntry *entry)
243 {
244   guint keyval = entry->keyval;
245
246   /* We store lowercased accelerators. To deal with this, if <Shift>
247    * was specified, uppercase.
248    */
249   if (entry->modifiers & GDK_SHIFT_MASK)
250     {
251       if (keyval == GDK_KEY_Tab)
252         keyval = GDK_KEY_ISO_Left_Tab;
253       else
254         keyval = gdk_keyval_to_upper (keyval);
255     }
256
257   _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers & ~GDK_RELEASE_MASK, entry);
258 }
259
260 static void
261 binding_key_hash_destroy (gpointer data)
262 {
263   GtkKeyHash *key_hash = data;
264
265   binding_key_hashes = g_slist_remove (binding_key_hashes, key_hash);
266   _gtk_key_hash_free (key_hash);
267 }
268
269 static void
270 insert_entries_into_key_hash (gpointer key,
271                               gpointer value,
272                               gpointer data)
273 {
274   GtkKeyHash *key_hash = data;
275   GtkBindingEntry *entry = value;
276
277   for (; entry; entry = entry->hash_next)
278     binding_key_hash_insert_entry (key_hash, entry);
279 }
280
281 static GtkKeyHash *
282 binding_key_hash_for_keymap (GdkKeymap *keymap)
283 {
284   static GQuark key_hash_quark = 0;
285   GtkKeyHash *key_hash;
286
287   if (!key_hash_quark)
288     key_hash_quark = g_quark_from_static_string ("gtk-binding-key-hash");
289
290   key_hash = g_object_get_qdata (G_OBJECT (keymap), key_hash_quark);
291
292   if (!key_hash)
293     {
294       key_hash = _gtk_key_hash_new (keymap, NULL);
295       g_object_set_qdata_full (G_OBJECT (keymap), key_hash_quark, key_hash, binding_key_hash_destroy);
296
297       if (binding_entry_hash_table)
298         g_hash_table_foreach (binding_entry_hash_table,
299                               insert_entries_into_key_hash,
300                               key_hash);
301
302       binding_key_hashes = g_slist_prepend (binding_key_hashes, key_hash);
303     }
304
305   return key_hash;
306 }
307
308
309 static GtkBindingEntry*
310 binding_entry_new (GtkBindingSet  *binding_set,
311                    guint           keyval,
312                    GdkModifierType modifiers)
313 {
314   GSList *tmp_list;
315   GtkBindingEntry *entry;
316
317   if (!binding_entry_hash_table)
318     binding_entry_hash_table = g_hash_table_new (binding_entry_hash, binding_entries_compare);
319
320   entry = g_new (GtkBindingEntry, 1);
321   entry->keyval = keyval;
322   entry->modifiers = modifiers;
323   entry->binding_set = binding_set,
324   entry->destroyed = FALSE;
325   entry->in_emission = FALSE;
326   entry->marks_unbound = FALSE;
327   entry->signals = NULL;
328
329   entry->set_next = binding_set->entries;
330   binding_set->entries = entry;
331
332   entry->hash_next = g_hash_table_lookup (binding_entry_hash_table, entry);
333   if (entry->hash_next)
334     g_hash_table_remove (binding_entry_hash_table, entry->hash_next);
335   g_hash_table_insert (binding_entry_hash_table, entry, entry);
336
337   for (tmp_list = binding_key_hashes; tmp_list; tmp_list = tmp_list->next)
338     {
339       GtkKeyHash *key_hash = tmp_list->data;
340       binding_key_hash_insert_entry (key_hash, entry);
341     }
342
343   return entry;
344 }
345
346 static void
347 binding_entry_free (GtkBindingEntry *entry)
348 {
349   GtkBindingSignal *sig;
350
351   g_assert (entry->set_next == NULL &&
352             entry->hash_next == NULL &&
353             entry->in_emission == FALSE &&
354             entry->destroyed == TRUE);
355
356   entry->destroyed = FALSE;
357
358   sig = entry->signals;
359   while (sig)
360     {
361       GtkBindingSignal *prev;
362
363       prev = sig;
364       sig = prev->next;
365       binding_signal_free (prev);
366     }
367   g_free (entry);
368 }
369
370 static void
371 binding_entry_destroy (GtkBindingEntry *entry)
372 {
373   GtkBindingEntry *o_entry;
374   register GtkBindingEntry *tmp;
375   GtkBindingEntry *begin;
376   register GtkBindingEntry *last;
377   GSList *tmp_list;
378
379   /* unlink from binding set
380    */
381   last = NULL;
382   tmp = entry->binding_set->entries;
383   while (tmp)
384     {
385       if (tmp == entry)
386         {
387           if (last)
388             last->set_next = entry->set_next;
389           else
390             entry->binding_set->entries = entry->set_next;
391           break;
392         }
393       last = tmp;
394       tmp = last->set_next;
395     }
396   entry->set_next = NULL;
397
398   o_entry = g_hash_table_lookup (binding_entry_hash_table, entry);
399   begin = o_entry;
400   last = NULL;
401   tmp = begin;
402   while (tmp)
403     {
404       if (tmp == entry)
405         {
406           if (last)
407             last->hash_next = entry->hash_next;
408           else
409             begin = entry->hash_next;
410           break;
411         }
412       last = tmp;
413       tmp = last->hash_next;
414     }
415   entry->hash_next = NULL;
416
417   if (!begin)
418     g_hash_table_remove (binding_entry_hash_table, entry);
419   else if (begin != o_entry)
420     {
421       g_hash_table_remove (binding_entry_hash_table, entry);
422       g_hash_table_insert (binding_entry_hash_table, begin, begin);
423     }
424
425   for (tmp_list = binding_key_hashes; tmp_list; tmp_list = tmp_list->next)
426     {
427       GtkKeyHash *key_hash = tmp_list->data;
428       _gtk_key_hash_remove_entry (key_hash, entry);
429     }
430
431   entry->destroyed = TRUE;
432
433   if (!entry->in_emission)
434     binding_entry_free (entry);
435 }
436
437 static GtkBindingEntry*
438 binding_ht_lookup_entry (GtkBindingSet  *set,
439                          guint           keyval,
440                          GdkModifierType modifiers)
441 {
442   GtkBindingEntry lookup_entry = { 0 };
443   GtkBindingEntry *entry;
444
445   if (!binding_entry_hash_table)
446     return NULL;
447
448   lookup_entry.keyval = keyval;
449   lookup_entry.modifiers = modifiers;
450
451   entry = g_hash_table_lookup (binding_entry_hash_table, &lookup_entry);
452   for (; entry; entry = entry->hash_next)
453     if (entry->binding_set == set)
454       return entry;
455
456   return NULL;
457 }
458
459 static gboolean
460 binding_compose_params (GObject         *object,
461                         GtkBindingArg   *args,
462                         GSignalQuery    *query,
463                         GValue         **params_p)
464 {
465   GValue *params;
466   const GType *types;
467   guint i;
468   gboolean valid;
469
470   params = g_new0 (GValue, query->n_params + 1);
471   *params_p = params;
472
473   /* The instance we emit on is the first object in the array
474    */
475   g_value_init (params, G_TYPE_OBJECT);
476   g_value_set_object (params, G_OBJECT (object));
477   params++;
478
479   types = query->param_types;
480   valid = TRUE;
481   for (i = 1; i < query->n_params + 1 && valid; i++)
482     {
483       GValue tmp_value = { 0, };
484
485       g_value_init (params, *types);
486
487       switch (G_TYPE_FUNDAMENTAL (args->arg_type))
488         {
489         case G_TYPE_DOUBLE:
490           g_value_init (&tmp_value, G_TYPE_DOUBLE);
491           g_value_set_double (&tmp_value, args->d.double_data);
492           break;
493         case G_TYPE_LONG:
494           g_value_init (&tmp_value, G_TYPE_LONG);
495           g_value_set_long (&tmp_value, args->d.long_data);
496           break;
497         case G_TYPE_STRING:
498           /* gtk_rc_parse_flags/enum() has fancier parsing for this; we can't call
499            * that since we don't have a GParamSpec, so just do something simple
500            */
501           if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_ENUM)
502             {
503               GEnumClass *class = G_ENUM_CLASS (g_type_class_ref (*types));
504
505               valid = FALSE;
506
507               if (args->arg_type == GTK_TYPE_IDENTIFIER)
508                 {
509                   GEnumValue *enum_value = NULL;
510                   enum_value = g_enum_get_value_by_name (class, args->d.string_data);
511                   if (!enum_value)
512                     enum_value = g_enum_get_value_by_nick (class, args->d.string_data);
513                   if (enum_value)
514                     {
515                       g_value_init (&tmp_value, *types);
516                       g_value_set_enum (&tmp_value, enum_value->value);
517                       valid = TRUE;
518                     }
519                 }
520
521               g_type_class_unref (class);
522             }
523           /* This is just a hack for compatibility with GTK+-1.2 where a string
524            * could be used for a single flag value / without the support for multiple
525            * values in gtk_rc_parse_flags(), this isn't very useful.
526            */
527           else if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_FLAGS)
528             {
529               GFlagsClass *class = G_FLAGS_CLASS (g_type_class_ref (*types));
530
531               valid = FALSE;
532
533               if (args->arg_type == GTK_TYPE_IDENTIFIER)
534                 {
535                   GFlagsValue *flags_value = NULL;
536                   flags_value = g_flags_get_value_by_name (class, args->d.string_data);
537                   if (!flags_value)
538                     flags_value = g_flags_get_value_by_nick (class, args->d.string_data);
539                   if (flags_value)
540                     {
541                       g_value_init (&tmp_value, *types);
542                       g_value_set_flags (&tmp_value, flags_value->value);
543                       valid = TRUE;
544                     }
545                 }
546
547               g_type_class_unref (class);
548             }
549           else
550             {
551               g_value_init (&tmp_value, G_TYPE_STRING);
552               g_value_set_static_string (&tmp_value, args->d.string_data);
553             }
554           break;
555         default:
556           valid = FALSE;
557           break;
558         }
559
560       if (valid)
561         {
562           if (!g_value_transform (&tmp_value, params))
563             valid = FALSE;
564
565           g_value_unset (&tmp_value);
566         }
567
568       types++;
569       params++;
570       args++;
571     }
572
573   if (!valid)
574     {
575       guint j;
576
577       for (j = 0; j < i; j++)
578         g_value_unset (&(*params_p)[j]);
579
580       g_free (*params_p);
581       *params_p = NULL;
582     }
583
584   return valid;
585 }
586
587 static gboolean
588 gtk_binding_entry_activate (GtkBindingEntry *entry,
589                             GObject         *object)
590 {
591   GtkBindingSignal *sig;
592   gboolean old_emission;
593   gboolean handled = FALSE;
594   gint i;
595
596   old_emission = entry->in_emission;
597   entry->in_emission = TRUE;
598
599   g_object_ref (object);
600
601   for (sig = entry->signals; sig; sig = sig->next)
602     {
603       GSignalQuery query;
604       guint signal_id;
605       GValue *params = NULL;
606       GValue return_val = { 0, };
607       gchar *accelerator = NULL;
608
609       signal_id = g_signal_lookup (sig->signal_name, G_OBJECT_TYPE (object));
610       if (!signal_id)
611         {
612           accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
613           g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
614                      "could not find signal \"%s\" in the `%s' class ancestry",
615                      entry->binding_set->set_name,
616                      accelerator,
617                      sig->signal_name,
618                      g_type_name (G_OBJECT_TYPE (object)));
619           g_free (accelerator);
620           continue;
621         }
622
623       g_signal_query (signal_id, &query);
624       if (query.n_params != sig->n_args ||
625           (query.return_type != G_TYPE_NONE && query.return_type != G_TYPE_BOOLEAN) ||
626           !binding_compose_params (object, sig->args, &query, &params))
627         {
628           accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
629           g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
630                      "signature mismatch for signal \"%s\" in the `%s' class ancestry",
631                      entry->binding_set->set_name,
632                      accelerator,
633                      sig->signal_name,
634                      g_type_name (G_OBJECT_TYPE (object)));
635         }
636       else if (!(query.signal_flags & G_SIGNAL_ACTION))
637         {
638           accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
639           g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
640                      "signal \"%s\" in the `%s' class ancestry cannot be used for action emissions",
641                      entry->binding_set->set_name,
642                      accelerator,
643                      sig->signal_name,
644                      g_type_name (G_OBJECT_TYPE (object)));
645         }
646       g_free (accelerator);
647       if (accelerator)
648         continue;
649
650       if (query.return_type == G_TYPE_BOOLEAN)
651         g_value_init (&return_val, G_TYPE_BOOLEAN);
652
653       g_signal_emitv (params, signal_id, 0, &return_val);
654
655       if (query.return_type == G_TYPE_BOOLEAN)
656         {
657           if (g_value_get_boolean (&return_val))
658             handled = TRUE;
659           g_value_unset (&return_val);
660         }
661       else
662         handled = TRUE;
663
664       for (i = 0; i < query.n_params + 1; i++)
665         g_value_unset (&params[i]);
666       g_free (params);
667
668       if (entry->destroyed)
669         break;
670     }
671
672   g_object_unref (object);
673
674   entry->in_emission = old_emission;
675   if (entry->destroyed && !entry->in_emission)
676     binding_entry_free (entry);
677
678   return handled;
679 }
680
681 /**
682  * gtk_binding_set_new: (skip)
683  * @set_name: unique name of this binding set
684  *
685  * GTK+ maintains a global list of binding sets. Each binding set has
686  * a unique name which needs to be specified upon creation.
687  *
688  * Return value: (transfer full): new binding set
689  */
690 GtkBindingSet*
691 gtk_binding_set_new (const gchar *set_name)
692 {
693   GtkBindingSet *binding_set;
694
695   g_return_val_if_fail (set_name != NULL, NULL);
696
697   binding_set = g_new (GtkBindingSet, 1);
698   binding_set->set_name = (gchar *) g_intern_string (set_name);
699   binding_set->widget_path_pspecs = NULL;
700   binding_set->widget_class_pspecs = NULL;
701   binding_set->class_branch_pspecs = NULL;
702   binding_set->entries = NULL;
703   binding_set->current = NULL;
704   binding_set->parsed = FALSE;
705
706   binding_set_list = g_slist_prepend (binding_set_list, binding_set);
707
708   return binding_set;
709 }
710
711 /**
712  * gtk_binding_set_by_class: (skip)
713  * @object_class: a valid #GObject class
714  *
715  * This function returns the binding set named after the type name of
716  * the passed in class structure. New binding sets are created on
717  * demand by this function.
718  *
719  * Return value: (transfer full): the binding set corresponding to
720  *     @object_class
721  */
722 GtkBindingSet*
723 gtk_binding_set_by_class (gpointer object_class)
724 {
725   GObjectClass *class = object_class;
726   GtkBindingSet* binding_set;
727
728   g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
729
730   if (!key_id_class_binding_set)
731     key_id_class_binding_set = g_quark_from_static_string (key_class_binding_set);
732
733   binding_set = g_dataset_id_get_data (class, key_id_class_binding_set);
734
735   if (binding_set)
736     return binding_set;
737
738   binding_set = gtk_binding_set_new (g_type_name (G_OBJECT_CLASS_TYPE (class)));
739   g_dataset_id_set_data (class, key_id_class_binding_set, binding_set);
740
741   return binding_set;
742 }
743
744 static GtkBindingSet*
745 gtk_binding_set_find_interned (const gchar *set_name)
746 {
747   GSList *slist;
748
749   for (slist = binding_set_list; slist; slist = slist->next)
750     {
751       GtkBindingSet *binding_set;
752
753       binding_set = slist->data;
754       if (binding_set->set_name == set_name)
755         return binding_set;
756     }
757
758   return NULL;
759 }
760
761 /**
762  * gtk_binding_set_find:
763  * @set_name: unique binding set name
764  *
765  * Find a binding set by its globally unique name.
766  *
767  * The @set_name can either be a name used for gtk_binding_set_new()
768  * or the type name of a class used in gtk_binding_set_by_class().
769  *
770  * Return value: (transfer none): %NULL or the specified binding set
771  */
772 GtkBindingSet*
773 gtk_binding_set_find (const gchar *set_name)
774 {
775   g_return_val_if_fail (set_name != NULL, NULL);
776
777   return gtk_binding_set_find_interned (g_intern_string (set_name));
778 }
779
780 /**
781  * gtk_binding_set_activate:
782  * @binding_set: a #GtkBindingSet set to activate
783  * @keyval:      key value of the binding
784  * @modifiers:   key modifier of the binding
785  * @object:      object to activate when binding found
786  *
787  * Find a key binding matching @keyval and @modifiers within
788  * @binding_set and activate the binding on @object.
789  *
790  * Return value: %TRUE if a binding was found and activated
791  */
792 gboolean
793 gtk_binding_set_activate (GtkBindingSet  *binding_set,
794                           guint           keyval,
795                           GdkModifierType modifiers,
796                           GObject        *object)
797 {
798   GtkBindingEntry *entry;
799
800   g_return_val_if_fail (binding_set != NULL, FALSE);
801   g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
802
803   keyval = gdk_keyval_to_lower (keyval);
804   modifiers = modifiers & BINDING_MOD_MASK ();
805
806   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
807   if (entry)
808     return gtk_binding_entry_activate (entry, object);
809
810   return FALSE;
811 }
812
813 static void
814 gtk_binding_entry_clear_internal (GtkBindingSet  *binding_set,
815                                   guint           keyval,
816                                   GdkModifierType modifiers)
817 {
818   GtkBindingEntry *entry;
819
820   keyval = gdk_keyval_to_lower (keyval);
821   modifiers = modifiers & BINDING_MOD_MASK ();
822
823   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
824   if (entry)
825     binding_entry_destroy (entry);
826
827   entry = binding_entry_new (binding_set, keyval, modifiers);
828 }
829
830 /**
831  * gtk_binding_entry_skip:
832  * @binding_set: a #GtkBindingSet to skip an entry of
833  * @keyval:      key value of binding to skip
834  * @modifiers:   key modifier of binding to skip
835  *
836  * Install a binding on @binding_set which causes key lookups
837  * to be aborted, to prevent bindings from lower priority sets
838  * to be activated.
839  *
840  * Since: 2.12
841  */
842 void
843 gtk_binding_entry_skip (GtkBindingSet  *binding_set,
844                         guint           keyval,
845                         GdkModifierType modifiers)
846 {
847   GtkBindingEntry *entry;
848
849   g_return_if_fail (binding_set != NULL);
850
851   keyval = gdk_keyval_to_lower (keyval);
852   modifiers = modifiers & BINDING_MOD_MASK ();
853
854   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
855   if (entry)
856     binding_entry_destroy (entry);
857
858   entry = binding_entry_new (binding_set, keyval, modifiers);
859   entry->marks_unbound = TRUE;
860 }
861
862 /**
863  * gtk_binding_entry_remove:
864  * @binding_set: a #GtkBindingSet to remove an entry of
865  * @keyval:      key value of binding to remove
866  * @modifiers:   key modifier of binding to remove
867  *
868  * Remove a binding previously installed via
869  * gtk_binding_entry_add_signal() on @binding_set.
870  */
871 void
872 gtk_binding_entry_remove (GtkBindingSet  *binding_set,
873                           guint           keyval,
874                           GdkModifierType modifiers)
875 {
876   GtkBindingEntry *entry;
877
878   g_return_if_fail (binding_set != NULL);
879
880   keyval = gdk_keyval_to_lower (keyval);
881   modifiers = modifiers & BINDING_MOD_MASK ();
882
883   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
884   if (entry)
885     binding_entry_destroy (entry);
886 }
887
888 /**
889  * gtk_binding_entry_add_signall:
890  * @binding_set:  a #GtkBindingSet to add a signal to
891  * @keyval:       key value
892  * @modifiers:    key modifier
893  * @signal_name:  signal name to be bound
894  * @binding_args: (transfer none) (element-type GtkBindingArg):
895  *     list of #GtkBindingArg signal arguments
896  *
897  * Override or install a new key binding for @keyval with @modifiers on
898  * @binding_set.
899  */
900 void
901 gtk_binding_entry_add_signall (GtkBindingSet  *binding_set,
902                                guint           keyval,
903                                GdkModifierType modifiers,
904                                const gchar    *signal_name,
905                                GSList         *binding_args)
906 {
907   _gtk_binding_entry_add_signall (binding_set,
908                                   keyval, modifiers,
909                                   signal_name, binding_args);
910 }
911
912 void
913 _gtk_binding_entry_add_signall (GtkBindingSet  *binding_set,
914                                 guint          keyval,
915                                 GdkModifierType modifiers,
916                                 const gchar    *signal_name,
917                                 GSList        *binding_args)
918 {
919   GtkBindingEntry *entry;
920   GtkBindingSignal *signal, **signal_p;
921   GSList *slist;
922   guint n = 0;
923   GtkBindingArg *arg;
924
925   g_return_if_fail (binding_set != NULL);
926   g_return_if_fail (signal_name != NULL);
927
928   keyval = gdk_keyval_to_lower (keyval);
929   modifiers = modifiers & BINDING_MOD_MASK ();
930
931   signal = binding_signal_new (signal_name, g_slist_length (binding_args));
932
933   arg = signal->args;
934   for (slist = binding_args; slist; slist = slist->next)
935     {
936       GtkBindingArg *tmp_arg;
937
938       tmp_arg = slist->data;
939       if (!tmp_arg)
940         {
941           g_warning ("gtk_binding_entry_add_signall(): arg[%u] is `NULL'", n);
942           binding_signal_free (signal);
943           return;
944         }
945       switch (G_TYPE_FUNDAMENTAL (tmp_arg->arg_type))
946         {
947         case  G_TYPE_LONG:
948           arg->arg_type = G_TYPE_LONG;
949           arg->d.long_data = tmp_arg->d.long_data;
950           break;
951         case  G_TYPE_DOUBLE:
952           arg->arg_type = G_TYPE_DOUBLE;
953           arg->d.double_data = tmp_arg->d.double_data;
954           break;
955         case  G_TYPE_STRING:
956           if (tmp_arg->arg_type != GTK_TYPE_IDENTIFIER)
957             arg->arg_type = G_TYPE_STRING;
958           else
959             arg->arg_type = GTK_TYPE_IDENTIFIER;
960           arg->d.string_data = g_strdup (tmp_arg->d.string_data);
961           if (!arg->d.string_data)
962             {
963               g_warning ("gtk_binding_entry_add_signall(): value of `string' arg[%u] is `NULL'", n);
964               binding_signal_free (signal);
965               return;
966             }
967           break;
968         default:
969           g_warning ("gtk_binding_entry_add_signall(): unsupported type `%s' for arg[%u]",
970                      g_type_name (arg->arg_type), n);
971           binding_signal_free (signal);
972           return;
973         }
974       arg++;
975       n++;
976     }
977
978   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
979   if (!entry)
980     {
981       gtk_binding_entry_clear_internal (binding_set, keyval, modifiers);
982       entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
983     }
984   signal_p = &entry->signals;
985   while (*signal_p)
986     signal_p = &(*signal_p)->next;
987   *signal_p = signal;
988 }
989
990 /**
991  * gtk_binding_entry_add_signal:
992  * @binding_set: a #GtkBindingSet to install an entry for
993  * @keyval:      key value of binding to install
994  * @modifiers:   key modifier of binding to install
995  * @signal_name: signal to execute upon activation
996  * @n_args:      number of arguments to @signal_name
997  * @Varargs:     arguments to @signal_name
998  *
999  * Override or install a new key binding for @keyval with @modifiers on
1000  * @binding_set. When the binding is activated, @signal_name will be
1001  * emitted on the target widget, with @n_args @Varargs used as
1002  * arguments.
1003  */
1004 void
1005 gtk_binding_entry_add_signal (GtkBindingSet  *binding_set,
1006                               guint           keyval,
1007                               GdkModifierType modifiers,
1008                               const gchar    *signal_name,
1009                               guint           n_args,
1010                               ...)
1011 {
1012   GSList *slist, *free_slist;
1013   va_list args;
1014   guint i;
1015
1016   g_return_if_fail (binding_set != NULL);
1017   g_return_if_fail (signal_name != NULL);
1018
1019   va_start (args, n_args);
1020   slist = NULL;
1021   for (i = 0; i < n_args; i++)
1022     {
1023       GtkBindingArg *arg;
1024
1025       arg = g_slice_new0 (GtkBindingArg);
1026       slist = g_slist_prepend (slist, arg);
1027
1028       arg->arg_type = va_arg (args, GType);
1029       switch (G_TYPE_FUNDAMENTAL (arg->arg_type))
1030         {
1031         case G_TYPE_CHAR:
1032         case G_TYPE_UCHAR:
1033         case G_TYPE_INT:
1034         case G_TYPE_UINT:
1035         case G_TYPE_BOOLEAN:
1036         case G_TYPE_ENUM:
1037         case G_TYPE_FLAGS:
1038           arg->arg_type = G_TYPE_LONG;
1039           arg->d.long_data = va_arg (args, gint);
1040           break;
1041         case G_TYPE_LONG:
1042         case G_TYPE_ULONG:
1043           arg->arg_type = G_TYPE_LONG;
1044           arg->d.long_data = va_arg (args, glong);
1045           break;
1046         case G_TYPE_FLOAT:
1047         case G_TYPE_DOUBLE:
1048           arg->arg_type = G_TYPE_DOUBLE;
1049           arg->d.double_data = va_arg (args, gdouble);
1050           break;
1051         case G_TYPE_STRING:
1052           if (arg->arg_type != GTK_TYPE_IDENTIFIER)
1053             arg->arg_type = G_TYPE_STRING;
1054           arg->d.string_data = va_arg (args, gchar*);
1055           if (!arg->d.string_data)
1056             {
1057               g_warning ("gtk_binding_entry_add_signal(): type `%s' arg[%u] is `NULL'",
1058                          g_type_name (arg->arg_type),
1059                          i);
1060               i += n_args + 1;
1061             }
1062           break;
1063         default:
1064           g_warning ("gtk_binding_entry_add_signal(): unsupported type `%s' for arg[%u]",
1065                      g_type_name (arg->arg_type), i);
1066           i += n_args + 1;
1067           break;
1068         }
1069     }
1070   va_end (args);
1071
1072   if (i == n_args || i == 0)
1073     {
1074       slist = g_slist_reverse (slist);
1075       _gtk_binding_entry_add_signall (binding_set, keyval, modifiers, signal_name, slist);
1076     }
1077
1078   free_slist = slist;
1079   while (slist)
1080     {
1081       g_slice_free (GtkBindingArg, slist->data);
1082       slist = slist->next;
1083     }
1084   g_slist_free (free_slist);
1085 }
1086
1087 static guint
1088 gtk_binding_parse_signal (GScanner       *scanner,
1089                           GtkBindingSet  *binding_set,
1090                           guint           keyval,
1091                           GdkModifierType modifiers)
1092 {
1093   gchar *signal;
1094   guint expected_token = 0;
1095   GSList *args;
1096   GSList *slist;
1097   gboolean done;
1098   gboolean negate;
1099   gboolean need_arg;
1100   gboolean seen_comma;
1101
1102   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1103
1104   g_scanner_get_next_token (scanner);
1105
1106   if (scanner->token != G_TOKEN_STRING)
1107     return G_TOKEN_STRING;
1108
1109   g_scanner_peek_next_token (scanner);
1110
1111   if (scanner->next_token != '(')
1112     {
1113       g_scanner_get_next_token (scanner);
1114       return '(';
1115     }
1116
1117   signal = g_strdup (scanner->value.v_string);
1118   g_scanner_get_next_token (scanner);
1119
1120   negate = FALSE;
1121   args = NULL;
1122   done = FALSE;
1123   need_arg = TRUE;
1124   seen_comma = FALSE;
1125   scanner->config->scan_symbols = FALSE;
1126
1127   do
1128     {
1129       GtkBindingArg *arg;
1130
1131       if (need_arg)
1132         expected_token = G_TOKEN_INT;
1133       else
1134         expected_token = ')';
1135
1136       g_scanner_get_next_token (scanner);
1137
1138       switch ((guint) scanner->token)
1139         {
1140         case G_TOKEN_FLOAT:
1141           if (need_arg)
1142             {
1143               need_arg = FALSE;
1144               arg = g_new (GtkBindingArg, 1);
1145               arg->arg_type = G_TYPE_DOUBLE;
1146               arg->d.double_data = scanner->value.v_float;
1147
1148               if (negate)
1149                 {
1150                   arg->d.double_data = - arg->d.double_data;
1151                   negate = FALSE;
1152                 }
1153               args = g_slist_prepend (args, arg);
1154             }
1155           else
1156             done = TRUE;
1157
1158           break;
1159         case G_TOKEN_INT:
1160           if (need_arg)
1161             {
1162               need_arg = FALSE;
1163               arg = g_new (GtkBindingArg, 1);
1164               arg->arg_type = G_TYPE_LONG;
1165               arg->d.long_data = scanner->value.v_int;
1166
1167               if (negate)
1168                 {
1169                   arg->d.long_data = - arg->d.long_data;
1170                   negate = FALSE;
1171                 }
1172               args = g_slist_prepend (args, arg);
1173             }
1174           else
1175             done = TRUE;
1176           break;
1177         case G_TOKEN_STRING:
1178           if (need_arg && !negate)
1179             {
1180               need_arg = FALSE;
1181               arg = g_new (GtkBindingArg, 1);
1182               arg->arg_type = G_TYPE_STRING;
1183               arg->d.string_data = g_strdup (scanner->value.v_string);
1184               args = g_slist_prepend (args, arg);
1185             }
1186           else
1187             done = TRUE;
1188
1189           break;
1190         case G_TOKEN_IDENTIFIER:
1191           if (need_arg && !negate)
1192             {
1193               need_arg = FALSE;
1194               arg = g_new (GtkBindingArg, 1);
1195               arg->arg_type = GTK_TYPE_IDENTIFIER;
1196               arg->d.string_data = g_strdup (scanner->value.v_identifier);
1197               args = g_slist_prepend (args, arg);
1198             }
1199           else
1200             done = TRUE;
1201
1202           break;
1203         case '-':
1204           if (!need_arg)
1205             done = TRUE;
1206           else if (negate)
1207             {
1208               expected_token = G_TOKEN_INT;
1209               done = TRUE;
1210             }
1211           else
1212             negate = TRUE;
1213
1214           break;
1215         case ',':
1216           seen_comma = TRUE;
1217           if (need_arg)
1218             done = TRUE;
1219           else
1220             need_arg = TRUE;
1221
1222           break;
1223         case ')':
1224           if (!(need_arg && seen_comma) && !negate)
1225             {
1226               args = g_slist_reverse (args);
1227               _gtk_binding_entry_add_signall (binding_set,
1228                                               keyval,
1229                                               modifiers,
1230                                               signal,
1231                                               args);
1232               expected_token = G_TOKEN_NONE;
1233             }
1234
1235           done = TRUE;
1236           break;
1237         default:
1238           done = TRUE;
1239           break;
1240         }
1241     }
1242   while (!done);
1243
1244   scanner->config->scan_symbols = TRUE;
1245
1246   for (slist = args; slist; slist = slist->next)
1247     {
1248       GtkBindingArg *arg;
1249
1250       arg = slist->data;
1251
1252       if (G_TYPE_FUNDAMENTAL (arg->arg_type) == G_TYPE_STRING)
1253         g_free (arg->d.string_data);
1254       g_free (arg);
1255     }
1256
1257   g_slist_free (args);
1258   g_free (signal);
1259
1260   return expected_token;
1261 }
1262
1263 static inline guint
1264 gtk_binding_parse_bind (GScanner       *scanner,
1265                         GtkBindingSet  *binding_set)
1266 {
1267   guint keyval = 0;
1268   GdkModifierType modifiers = 0;
1269   gboolean unbind = FALSE;
1270
1271   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1272
1273   g_scanner_get_next_token (scanner);
1274
1275   if (scanner->token != G_TOKEN_SYMBOL)
1276     return G_TOKEN_SYMBOL;
1277
1278   if (scanner->value.v_symbol != GUINT_TO_POINTER (GTK_BINDING_TOKEN_BIND) &&
1279       scanner->value.v_symbol != GUINT_TO_POINTER (GTK_BINDING_TOKEN_UNBIND))
1280     return G_TOKEN_SYMBOL;
1281
1282   unbind = (scanner->value.v_symbol == GUINT_TO_POINTER (GTK_BINDING_TOKEN_UNBIND));
1283   g_scanner_get_next_token (scanner);
1284
1285   if (scanner->token != (guint) G_TOKEN_STRING)
1286     return G_TOKEN_STRING;
1287
1288   gtk_accelerator_parse (scanner->value.v_string, &keyval, &modifiers);
1289   modifiers &= BINDING_MOD_MASK ();
1290
1291   if (keyval == 0)
1292     return G_TOKEN_STRING;
1293
1294   if (unbind)
1295     {
1296       gtk_binding_entry_skip (binding_set, keyval, modifiers);
1297       return G_TOKEN_NONE;
1298     }
1299
1300   g_scanner_get_next_token (scanner);
1301
1302   if (scanner->token != '{')
1303     return '{';
1304
1305   gtk_binding_entry_clear_internal (binding_set, keyval, modifiers);
1306   g_scanner_peek_next_token (scanner);
1307
1308   while (scanner->next_token != '}')
1309     {
1310       guint expected_token;
1311
1312       switch (scanner->next_token)
1313         {
1314         case G_TOKEN_STRING:
1315           expected_token = gtk_binding_parse_signal (scanner,
1316                                                      binding_set,
1317                                                      keyval,
1318                                                      modifiers);
1319           if (expected_token != G_TOKEN_NONE)
1320             return expected_token;
1321           break;
1322         default:
1323           g_scanner_get_next_token (scanner);
1324           return '}';
1325         }
1326
1327       g_scanner_peek_next_token (scanner);
1328     }
1329
1330   g_scanner_get_next_token (scanner);
1331
1332   return G_TOKEN_NONE;
1333 }
1334
1335 static GScanner *
1336 create_signal_scanner (void)
1337 {
1338   GScanner *scanner;
1339
1340   scanner = g_scanner_new (NULL);
1341   scanner->config->cset_identifier_nth = G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_";
1342
1343   g_scanner_scope_add_symbol (scanner, 0, "bind", GUINT_TO_POINTER (GTK_BINDING_TOKEN_BIND));
1344   g_scanner_scope_add_symbol (scanner, 0, "unbind", GUINT_TO_POINTER (GTK_BINDING_TOKEN_UNBIND));
1345
1346   g_scanner_set_scope (scanner, 0);
1347
1348   return scanner;
1349 }
1350
1351 /**
1352  * gtk_binding_entry_add_signal_from_string:
1353  * @binding_set: a #GtkBindingSet
1354  * @signal_desc: a signal description
1355  *
1356  * Parses a signal description from @signal_desc and incorporates
1357  * it into @binding_set.
1358  *
1359  * Signal descriptions may either bind a key combination to
1360  * one or more signals:
1361  * <informalexample><programlisting>
1362  *   bind "key" {
1363  *     "signalname" (param, ...)
1364  *     ...
1365  *   }
1366  * </programlisting></informalexample>
1367  *
1368  * Or they may also unbind a key combination:
1369  * <informalexample><programlisting>
1370  *   unbind "key"
1371  * </programlisting></informalexample>
1372  *
1373  * Key combinations must be in a format that can be parsed by
1374  * gtk_accelerator_parse().
1375  *
1376  * Returns: %G_TOKEN_NONE if the signal was successfully parsed and added,
1377  *     the expected token otherwise
1378  *
1379  * Since: 3.0
1380  */
1381 GTokenType
1382 gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set,
1383                                           const gchar   *signal_desc)
1384 {
1385   static GScanner *scanner = NULL;
1386   GTokenType ret;
1387
1388   g_return_val_if_fail (binding_set != NULL, G_TOKEN_NONE);
1389   g_return_val_if_fail (signal_desc != NULL, G_TOKEN_NONE);
1390
1391   if (G_UNLIKELY (!scanner))
1392     scanner = create_signal_scanner ();
1393
1394   g_scanner_input_text (scanner, signal_desc,
1395                         (guint) strlen (signal_desc));
1396
1397   ret = gtk_binding_parse_bind (scanner, binding_set);
1398
1399   /* Reset for next use */
1400   g_scanner_set_scope (scanner, 0);
1401
1402   return ret;
1403 }
1404
1405 /**
1406  * gtk_binding_set_add_path:
1407  * @binding_set: a #GtkBindingSet to add a path to
1408  * @path_type: path type the pattern applies to
1409  * @path_pattern: the actual match pattern
1410  * @priority: binding priority
1411  *
1412  * This function was used internally by the GtkRC parsing mechanism
1413  * to assign match patterns to #GtkBindingSet structures.
1414  *
1415  * In GTK+ 3, these match patterns are unused.
1416  *
1417  * Deprecated: 3.0
1418  */
1419 void
1420 gtk_binding_set_add_path (GtkBindingSet       *binding_set,
1421                           GtkPathType          path_type,
1422                           const gchar         *path_pattern,
1423                           GtkPathPriorityType  priority)
1424 {
1425   PatternSpec *pspec;
1426   GSList **slist_p, *slist;
1427   static guint seq_id = 0;
1428
1429   g_return_if_fail (binding_set != NULL);
1430   g_return_if_fail (path_pattern != NULL);
1431   g_return_if_fail (priority <= GTK_PATH_PRIO_MASK);
1432
1433   priority &= GTK_PATH_PRIO_MASK;
1434
1435   switch (path_type)
1436     {
1437     case  GTK_PATH_WIDGET:
1438       slist_p = &binding_set->widget_path_pspecs;
1439       break;
1440     case  GTK_PATH_WIDGET_CLASS:
1441       slist_p = &binding_set->widget_class_pspecs;
1442       break;
1443     case  GTK_PATH_CLASS:
1444       slist_p = &binding_set->class_branch_pspecs;
1445       break;
1446     default:
1447       g_assert_not_reached ();
1448       slist_p = NULL;
1449       break;
1450     }
1451
1452   pspec = g_new (PatternSpec, 1);
1453   pspec->type = path_type;
1454   if (path_type == GTK_PATH_WIDGET_CLASS)
1455     pspec->pspec = NULL;
1456   else
1457     pspec->pspec = g_pattern_spec_new (path_pattern);
1458
1459   pspec->seq_id = priority << 28;
1460   pspec->user_data = binding_set;
1461
1462   slist = *slist_p;
1463   while (slist)
1464     {
1465       PatternSpec *tmp_pspec;
1466
1467       tmp_pspec = slist->data;
1468       slist = slist->next;
1469
1470       if (g_pattern_spec_equal (tmp_pspec->pspec, pspec->pspec))
1471         {
1472           GtkPathPriorityType lprio = tmp_pspec->seq_id >> 28;
1473
1474           pattern_spec_free (pspec);
1475           pspec = NULL;
1476           if (lprio < priority)
1477             {
1478               tmp_pspec->seq_id &= 0x0fffffff;
1479               tmp_pspec->seq_id |= priority << 28;
1480             }
1481           break;
1482         }
1483     }
1484   if (pspec)
1485     {
1486       pspec->seq_id |= seq_id++ & 0x0fffffff;
1487       *slist_p = g_slist_prepend (*slist_p, pspec);
1488     }
1489 }
1490
1491 static gint
1492 find_entry_with_binding (GtkBindingEntry *entry,
1493                          GtkBindingSet   *binding_set)
1494 {
1495   return (entry->binding_set == binding_set) ? 0 : 1;
1496 }
1497
1498 static gboolean
1499 binding_activate (GtkBindingSet *binding_set,
1500                   GSList        *entries,
1501                   GObject       *object,
1502                   gboolean       is_release,
1503                   gboolean      *unbound)
1504 {
1505   GtkBindingEntry *entry;
1506   GSList *elem;
1507
1508   elem = g_slist_find_custom (entries, binding_set,
1509                               (GCompareFunc) find_entry_with_binding);
1510
1511   if (!elem)
1512     return FALSE;
1513
1514   entry = elem->data;
1515
1516   if (is_release != ((entry->modifiers & GDK_RELEASE_MASK) != 0))
1517     return FALSE;
1518
1519   if (entry->marks_unbound)
1520     {
1521       *unbound = TRUE;
1522       return FALSE;
1523     }
1524
1525   if (gtk_binding_entry_activate (entry, object))
1526     return TRUE;
1527
1528   return FALSE;
1529 }
1530
1531 static gboolean
1532 gtk_bindings_activate_list (GObject  *object,
1533                             GSList   *entries,
1534                             gboolean  is_release)
1535 {
1536   GtkStyleContext *context;
1537   GtkBindingSet *binding_set;
1538   GtkStateFlags state;
1539   gboolean handled = FALSE;
1540   gboolean unbound = FALSE;
1541   GPtrArray *array;
1542
1543   if (!entries)
1544     return FALSE;
1545
1546   context = gtk_widget_get_style_context (GTK_WIDGET (object));
1547   state = gtk_widget_get_state_flags (GTK_WIDGET (object));
1548
1549   gtk_style_context_get (context, state,
1550                          "gtk-key-bindings", &array,
1551                          NULL);
1552   if (array)
1553     {
1554       gint i;
1555
1556       for (i = 0; i < array->len; i++)
1557         {
1558           binding_set = g_ptr_array_index (array, i);
1559           handled = binding_activate (binding_set, entries,
1560                                       object, is_release,
1561                                       &unbound);
1562           if (handled)
1563             break;
1564         }
1565
1566       g_ptr_array_unref (array);
1567
1568       if (unbound)
1569         return FALSE;
1570     }
1571
1572   if (!handled)
1573     {
1574       GType class_type;
1575
1576       class_type = G_TYPE_FROM_INSTANCE (object);
1577
1578       while (class_type && !handled)
1579         {
1580           binding_set = gtk_binding_set_find_interned (g_type_name (class_type));
1581           class_type = g_type_parent (class_type);
1582
1583           if (!binding_set)
1584             continue;
1585
1586           handled = binding_activate (binding_set, entries,
1587                                       object, is_release,
1588                                       &unbound);
1589         }
1590
1591       if (unbound)
1592         return FALSE;
1593     }
1594
1595   return handled;
1596 }
1597
1598 /**
1599  * gtk_bindings_activate:
1600  * @object: object to activate when binding found
1601  * @keyval: key value of the binding
1602  * @modifiers: key modifier of the binding
1603  *
1604  * Find a key binding matching @keyval and @modifiers and activate the
1605  * binding on @object.
1606  *
1607  * Return value: %TRUE if a binding was found and activated
1608  */
1609 gboolean
1610 gtk_bindings_activate (GObject         *object,
1611                        guint            keyval,
1612                        GdkModifierType  modifiers)
1613 {
1614   GSList *entries = NULL;
1615   GdkDisplay *display;
1616   GtkKeyHash *key_hash;
1617   gboolean handled = FALSE;
1618   gboolean is_release;
1619
1620   if (!GTK_IS_WIDGET (object))
1621     return FALSE;
1622
1623   is_release = (modifiers & GDK_RELEASE_MASK) != 0;
1624   modifiers = modifiers & BINDING_MOD_MASK () & ~GDK_RELEASE_MASK;
1625
1626   display = gtk_widget_get_display (GTK_WIDGET (object));
1627   key_hash = binding_key_hash_for_keymap (gdk_keymap_get_for_display (display));
1628
1629   entries = _gtk_key_hash_lookup_keyval (key_hash, keyval, modifiers);
1630
1631   handled = gtk_bindings_activate_list (object, entries, is_release);
1632
1633   g_slist_free (entries);
1634
1635   return handled;
1636 }
1637
1638 /**
1639  * gtk_bindings_activate_event:
1640  * @object: a #GObject (generally must be a widget)
1641  * @event: a #GdkEventKey
1642  *
1643  * Looks up key bindings for @object to find one matching
1644  * @event, and if one was found, activate it.
1645  *
1646  * Return value: %TRUE if a matching key binding was found
1647  *
1648  * Since: 2.4
1649  */
1650 gboolean
1651 gtk_bindings_activate_event (GObject     *object,
1652                              GdkEventKey *event)
1653 {
1654   GSList *entries = NULL;
1655   GdkDisplay *display;
1656   GtkKeyHash *key_hash;
1657   gboolean handled = FALSE;
1658
1659   if (!GTK_IS_WIDGET (object))
1660     return FALSE;
1661
1662   display = gtk_widget_get_display (GTK_WIDGET (object));
1663   key_hash = binding_key_hash_for_keymap (gdk_keymap_get_for_display (display));
1664
1665   entries = _gtk_key_hash_lookup (key_hash,
1666                                   event->hardware_keycode,
1667                                   event->state,
1668                                   BINDING_MOD_MASK () & ~GDK_RELEASE_MASK,
1669                                   event->group);
1670
1671   handled = gtk_bindings_activate_list (object, entries,
1672                                         event->type == GDK_KEY_RELEASE);
1673
1674   g_slist_free (entries);
1675
1676   return handled;
1677 }