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