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