]> Pileus Git - ~andy/gtk/blob - gtk/gtkbindings.c
Correctly select default printer when there is more than one (CUPS)
[~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 GtkObjects.
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 "gtkwidget.h"
38 #include "gtkrc.h"
39 #include "gtkalias.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_Tab)
136         keyval = GDK_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 (GtkObject       *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                             GtkObject       *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 #GtkObject 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   GtkObjectClass *class = object_class;
609   GtkBindingSet* binding_set;
610
611   g_return_val_if_fail (GTK_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                           GtkObject      *object)
676 {
677   GtkBindingEntry *entry;
678   
679   g_return_val_if_fail (binding_set != NULL, FALSE);
680   g_return_val_if_fail (GTK_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_add:
711  * @binding_set: #a GtkBindingSet to clear an entry of
712  * @keyval:      key value of binding to clear
713  * @modifiers:   key modifier of binding to clear
714  *
715  * Adds a binding entry.
716  *
717  * Deprecated: 2.12: Use gtk_binding_entry_add_signal() instead.
718  */
719
720 /**
721  * gtk_binding_entry_clear:
722  * @binding_set: binding set to clear an entry of
723  * @keyval:      key value of binding to clear
724  * @modifiers:   key modifier of binding to clear
725  *
726  * Clears a binding entry.
727  *
728  * Deprecated: 2.12: Use gtk_binding_entry_remove() instead.
729  */
730 void
731 gtk_binding_entry_clear (GtkBindingSet  *binding_set,
732                          guint           keyval,
733                          GdkModifierType modifiers)
734 {
735   g_return_if_fail (binding_set != NULL);
736
737   gtk_binding_entry_clear_internal (binding_set, keyval, modifiers);
738 }
739
740 /**
741  * gtk_binding_entry_skip:
742  * @binding_set: a #GtkBindingSet to skip an entry of
743  * @keyval:      key value of binding to skip
744  * @modifiers:   key modifier of binding to skip
745  *
746  * Install a binding on @binding_set which causes key lookups
747  * to be aborted, to prevent bindings from lower priority sets
748  * to be activated.
749  *
750  * Since: 2.12
751  */
752 void
753 gtk_binding_entry_skip (GtkBindingSet  *binding_set,
754                         guint           keyval,
755                         GdkModifierType modifiers)
756 {
757   GtkBindingEntry *entry;
758
759   g_return_if_fail (binding_set != NULL);
760
761   keyval = gdk_keyval_to_lower (keyval);
762   modifiers = modifiers & BINDING_MOD_MASK ();
763
764   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
765   if (entry)
766     binding_entry_destroy (entry);
767
768   entry = binding_entry_new (binding_set, keyval, modifiers);
769   entry->marks_unbound = TRUE;
770 }
771
772 /**
773  * gtk_binding_entry_remove:
774  * @binding_set: a #GtkBindingSet to remove an entry of
775  * @keyval:      key value of binding to remove
776  * @modifiers:   key modifier of binding to remove
777  *
778  * Remove a binding previously installed via
779  * gtk_binding_entry_add_signal() on @binding_set.
780  */
781 void
782 gtk_binding_entry_remove (GtkBindingSet  *binding_set,
783                           guint           keyval,
784                           GdkModifierType modifiers)
785 {
786   GtkBindingEntry *entry;
787   
788   g_return_if_fail (binding_set != NULL);
789   
790   keyval = gdk_keyval_to_lower (keyval);
791   modifiers = modifiers & BINDING_MOD_MASK ();
792   
793   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
794   if (entry)
795     binding_entry_destroy (entry);
796 }
797
798 /**
799  * gtk_binding_entry_add_signall:
800  * @binding_set:  a #GtkBindingSet to add a signal to
801  * @keyval:       key value
802  * @modifiers:    key modifier
803  * @signal_name:  signal name to be bound
804  * @binding_args: list of #GtkBindingArg signal arguments
805  *
806  * Override or install a new key binding for @keyval with @modifiers on
807  * @binding_set.
808  */
809 void
810 gtk_binding_entry_add_signall (GtkBindingSet  *binding_set,
811                                guint           keyval,
812                                GdkModifierType modifiers,
813                                const gchar    *signal_name,
814                                GSList         *binding_args)
815 {
816   _gtk_binding_entry_add_signall (binding_set,
817                                   keyval, modifiers,
818                                   signal_name, binding_args);
819 }
820
821 void
822 _gtk_binding_entry_add_signall (GtkBindingSet  *binding_set,
823                                 guint          keyval,
824                                 GdkModifierType modifiers,
825                                 const gchar    *signal_name,
826                                 GSList        *binding_args)
827 {
828   GtkBindingEntry *entry;
829   GtkBindingSignal *signal, **signal_p;
830   GSList *slist;
831   guint n = 0;
832   GtkBindingArg *arg;
833   
834   g_return_if_fail (binding_set != NULL);
835   g_return_if_fail (signal_name != NULL);
836   
837   keyval = gdk_keyval_to_lower (keyval);
838   modifiers = modifiers & BINDING_MOD_MASK ();
839   
840   signal = binding_signal_new (signal_name, g_slist_length (binding_args));
841   
842   arg = signal->args;
843   for (slist = binding_args; slist; slist = slist->next)
844     {
845       GtkBindingArg *tmp_arg;
846       
847       tmp_arg = slist->data;
848       if (!tmp_arg)
849         {
850           g_warning ("gtk_binding_entry_add_signall(): arg[%u] is `NULL'", n);
851           binding_signal_free (signal);
852           return;
853         }
854       switch (G_TYPE_FUNDAMENTAL (tmp_arg->arg_type))
855         {
856         case  G_TYPE_LONG:
857           arg->arg_type = G_TYPE_LONG;
858           arg->d.long_data = tmp_arg->d.long_data;
859           break;
860         case  G_TYPE_DOUBLE:
861           arg->arg_type = G_TYPE_DOUBLE;
862           arg->d.double_data = tmp_arg->d.double_data;
863           break;
864         case  G_TYPE_STRING:
865           if (tmp_arg->arg_type != GTK_TYPE_IDENTIFIER)
866             arg->arg_type = G_TYPE_STRING;
867           else
868             arg->arg_type = GTK_TYPE_IDENTIFIER;
869           arg->d.string_data = g_strdup (tmp_arg->d.string_data);
870           if (!arg->d.string_data)
871             {
872               g_warning ("gtk_binding_entry_add_signall(): value of `string' arg[%u] is `NULL'", n);
873               binding_signal_free (signal);
874               return;
875             }
876           break;
877         default:
878           g_warning ("gtk_binding_entry_add_signall(): unsupported type `%s' for arg[%u]",
879                      g_type_name (arg->arg_type), n);
880           binding_signal_free (signal);
881           return;
882         }
883       arg++;
884       n++;
885     }
886   
887   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
888   if (!entry)
889     {
890       gtk_binding_entry_clear_internal (binding_set, keyval, modifiers);
891       entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
892     }
893   signal_p = &entry->signals;
894   while (*signal_p)
895     signal_p = &(*signal_p)->next;
896   *signal_p = signal;
897 }
898
899 /**
900  * gtk_binding_entry_add_signal:
901  * @binding_set: a #GtkBindingSet to install an entry for
902  * @keyval:      key value of binding to install
903  * @modifiers:   key modifier of binding to install
904  * @signal_name: signal to execute upon activation
905  * @n_args:      number of arguments to @signal_name
906  * @Varargs:     arguments to @signal_name
907  *
908  * Override or install a new key binding for @keyval with @modifiers on
909  * @binding_set. When the binding is activated, @signal_name will be
910  * emitted on the target widget, with @n_args @Varargs used as
911  * arguments.
912  */
913 void
914 gtk_binding_entry_add_signal (GtkBindingSet  *binding_set,
915                               guint           keyval,
916                               GdkModifierType modifiers,
917                               const gchar    *signal_name,
918                               guint           n_args,
919                               ...)
920 {
921   GSList *slist, *free_slist;
922   va_list args;
923   guint i;
924
925   g_return_if_fail (binding_set != NULL);
926   g_return_if_fail (signal_name != NULL);
927   
928   va_start (args, n_args);
929   slist = NULL;
930   for (i = 0; i < n_args; i++)
931     {
932       GtkBindingArg *arg;
933
934       arg = g_slice_new0 (GtkBindingArg);
935       slist = g_slist_prepend (slist, arg);
936
937       arg->arg_type = va_arg (args, GType);
938       switch (G_TYPE_FUNDAMENTAL (arg->arg_type))
939         {
940         case G_TYPE_CHAR:
941         case G_TYPE_UCHAR:
942         case G_TYPE_INT:
943         case G_TYPE_UINT:
944         case G_TYPE_BOOLEAN:
945         case G_TYPE_ENUM:
946         case G_TYPE_FLAGS:
947           arg->arg_type = G_TYPE_LONG;
948           arg->d.long_data = va_arg (args, gint);
949           break;
950         case G_TYPE_LONG:
951         case G_TYPE_ULONG:
952           arg->arg_type = G_TYPE_LONG;
953           arg->d.long_data = va_arg (args, glong);
954           break;
955         case G_TYPE_FLOAT:
956         case G_TYPE_DOUBLE:
957           arg->arg_type = G_TYPE_DOUBLE;
958           arg->d.double_data = va_arg (args, gdouble);
959           break;
960         case G_TYPE_STRING:
961           if (arg->arg_type != GTK_TYPE_IDENTIFIER)
962             arg->arg_type = G_TYPE_STRING;
963           arg->d.string_data = va_arg (args, gchar*);
964           if (!arg->d.string_data)
965             {
966               g_warning ("gtk_binding_entry_add_signal(): type `%s' arg[%u] is `NULL'",
967                          g_type_name (arg->arg_type),
968                          i);
969               i += n_args + 1;
970             }
971           break;
972         default:
973           g_warning ("gtk_binding_entry_add_signal(): unsupported type `%s' for arg[%u]",
974                      g_type_name (arg->arg_type), i);
975           i += n_args + 1;
976           break;
977         }
978     }
979   va_end (args);
980
981   if (i == n_args || i == 0)
982     {
983       slist = g_slist_reverse (slist);
984       _gtk_binding_entry_add_signall (binding_set, keyval, modifiers, signal_name, slist);
985     }
986
987   free_slist = slist;
988   while (slist)
989     {
990       g_slice_free (GtkBindingArg, slist->data);
991       slist = slist->next;
992     }
993   g_slist_free (free_slist);
994 }
995
996 /**
997  * gtk_binding_set_add_path:
998  * @binding_set:  a #GtkBindingSet to add a path to
999  * @path_type:    path type the pattern applies to
1000  * @path_pattern: the actual match pattern
1001  * @priority:     binding priority
1002  *
1003  * This function is used internally by the GtkRC parsing mechanism to
1004  * assign match patterns to #GtkBindingSet structures.
1005  */
1006 void
1007 gtk_binding_set_add_path (GtkBindingSet      *binding_set,
1008                           GtkPathType         path_type,
1009                           const gchar        *path_pattern,
1010                           GtkPathPriorityType priority)
1011 {
1012   PatternSpec *pspec;
1013   GSList **slist_p, *slist;
1014   static guint seq_id = 0;
1015   
1016   g_return_if_fail (binding_set != NULL);
1017   g_return_if_fail (path_pattern != NULL);
1018   g_return_if_fail (priority <= GTK_PATH_PRIO_MASK);
1019
1020   priority &= GTK_PATH_PRIO_MASK;
1021   
1022   switch (path_type)
1023     {
1024     case  GTK_PATH_WIDGET:
1025       slist_p = &binding_set->widget_path_pspecs;
1026       break;
1027     case  GTK_PATH_WIDGET_CLASS:
1028       slist_p = &binding_set->widget_class_pspecs;
1029       break;
1030     case  GTK_PATH_CLASS:
1031       slist_p = &binding_set->class_branch_pspecs;
1032       break;
1033     default:
1034       g_assert_not_reached ();
1035       slist_p = NULL;
1036       break;
1037     }
1038   
1039   pspec = g_new (PatternSpec, 1);
1040   pspec->type = path_type;
1041   if (path_type == GTK_PATH_WIDGET_CLASS)
1042     {
1043       pspec->pspec = NULL;
1044       pspec->path = _gtk_rc_parse_widget_class_path (path_pattern);
1045     }
1046   else
1047     {
1048       pspec->pspec = g_pattern_spec_new (path_pattern);
1049       pspec->path = NULL;
1050     }
1051     
1052   pspec->seq_id = priority << 28;
1053   pspec->user_data = binding_set;
1054   
1055   slist = *slist_p;
1056   while (slist)
1057     {
1058       PatternSpec *tmp_pspec;
1059       
1060       tmp_pspec = slist->data;
1061       slist = slist->next;
1062       
1063       if (g_pattern_spec_equal (tmp_pspec->pspec, pspec->pspec))
1064         {
1065           GtkPathPriorityType lprio = tmp_pspec->seq_id >> 28;
1066
1067           pattern_spec_free (pspec);
1068           pspec = NULL;
1069           if (lprio < priority)
1070             {
1071               tmp_pspec->seq_id &= 0x0fffffff;
1072               tmp_pspec->seq_id |= priority << 28;
1073             }
1074           break;
1075         }
1076     }
1077   if (pspec)
1078     {
1079       pspec->seq_id |= seq_id++ & 0x0fffffff;
1080       *slist_p = g_slist_prepend (*slist_p, pspec);
1081     }
1082 }
1083
1084 static gboolean
1085 binding_match_activate (GSList          *pspec_list,
1086                         GtkObject       *object,
1087                         guint            path_length,
1088                         gchar           *path,
1089                         gchar           *path_reversed,
1090                         gboolean        *unbound)
1091 {
1092   GSList *slist;
1093
1094   *unbound = FALSE;
1095
1096   for (slist = pspec_list; slist; slist = slist->next)
1097     {
1098       PatternSpec *pspec;
1099       GtkBindingSet *binding_set;
1100
1101       binding_set = NULL;
1102       pspec = slist->data;
1103       
1104       if (pspec->type == GTK_PATH_WIDGET_CLASS)
1105         {
1106           if (_gtk_rc_match_widget_class (pspec->path, path_length, path, path_reversed))
1107             binding_set = pspec->user_data;
1108         }
1109       else
1110         {
1111           if (g_pattern_match (pspec->pspec, path_length, path, path_reversed))
1112             binding_set = pspec->user_data;
1113         }
1114
1115       if (binding_set)
1116         {
1117           if (binding_set->current->marks_unbound)
1118             {
1119               *unbound = TRUE;
1120               return FALSE;
1121             }
1122
1123           if (gtk_binding_entry_activate (binding_set->current, object))
1124             return TRUE;
1125         }
1126     }
1127
1128   return FALSE;
1129 }
1130
1131 static gint
1132 gtk_binding_pattern_compare (gconstpointer new_pattern,
1133                              gconstpointer existing_pattern)
1134 {
1135   register const PatternSpec *np  = new_pattern;
1136   register const PatternSpec *ep  = existing_pattern;
1137
1138   /* walk the list as long as the existing patterns have
1139    * higher priorities.
1140    */
1141
1142   return np->seq_id < ep->seq_id;
1143 }
1144
1145 static GSList*
1146 gtk_binding_entries_sort_patterns (GSList      *entries,
1147                                    GtkPathType  path_id,
1148                                    gboolean     is_release)
1149 {
1150   GSList *patterns;
1151   GSList *tmp_list;
1152
1153   patterns = NULL;
1154   for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
1155     {
1156       GtkBindingEntry *entry = tmp_list->data;
1157       GtkBindingSet *binding_set;
1158
1159       binding_set = entry->binding_set;
1160       binding_set->current = NULL;
1161     }
1162   
1163   for (; entries; entries = entries->next)
1164     {
1165       GtkBindingEntry *entry = entries->data;
1166       GtkBindingSet *binding_set;
1167       GSList *slist = NULL;
1168
1169       if (is_release != ((entry->modifiers & GDK_RELEASE_MASK) != 0))
1170         continue;
1171
1172       binding_set = entry->binding_set;
1173
1174       if (binding_set->current)
1175         continue;
1176       binding_set->current = entry;
1177
1178       switch (path_id)
1179         {
1180         case GTK_PATH_WIDGET:
1181           slist = binding_set->widget_path_pspecs;
1182           break;
1183         case GTK_PATH_WIDGET_CLASS:
1184           slist = binding_set->widget_class_pspecs;
1185           break;
1186         case GTK_PATH_CLASS:
1187           slist = binding_set->class_branch_pspecs;
1188           break;
1189         }
1190
1191       for (; slist; slist = slist->next)
1192         {
1193           PatternSpec *pspec;
1194
1195           pspec = slist->data;
1196           patterns = g_slist_insert_sorted (patterns, pspec, gtk_binding_pattern_compare);
1197         }
1198     }
1199
1200   return patterns;
1201 }
1202
1203 static gboolean
1204 gtk_bindings_activate_list (GtkObject *object,
1205                             GSList    *entries,
1206                             gboolean   is_release)
1207 {
1208   GtkWidget *widget = GTK_WIDGET (object);
1209   gboolean handled = FALSE;
1210
1211   if (!entries)
1212     return FALSE;
1213
1214   if (!handled)
1215     {
1216       guint path_length;
1217       gchar *path, *path_reversed;
1218       GSList *patterns;
1219       gboolean unbound;
1220
1221       gtk_widget_path (widget, &path_length, &path, &path_reversed);
1222       patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET, is_release);
1223       handled = binding_match_activate (patterns, object, path_length, path, path_reversed, &unbound);
1224       g_slist_free (patterns);
1225       g_free (path);
1226       g_free (path_reversed);
1227
1228       if (unbound)
1229         return FALSE;
1230     }
1231
1232   if (!handled)
1233     {
1234       guint path_length;
1235       gchar *path, *path_reversed;
1236       GSList *patterns;
1237       gboolean unbound;
1238
1239       gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
1240       patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET_CLASS, is_release);
1241       handled = binding_match_activate (patterns, object, path_length, path, path_reversed, &unbound);
1242       g_slist_free (patterns);
1243       g_free (path);
1244       g_free (path_reversed);
1245
1246       if (unbound)
1247         return FALSE;
1248     }
1249
1250   if (!handled)
1251     {
1252       GSList *patterns;
1253       GType class_type;
1254       gboolean unbound = FALSE;
1255
1256       patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_CLASS, is_release);
1257       class_type = G_TYPE_FROM_INSTANCE (object);
1258       while (class_type && !handled)
1259         {
1260           guint path_length;
1261           gchar *path;
1262           gchar *path_reversed;
1263
1264           path = g_strdup (g_type_name (class_type));
1265           path_reversed = g_strdup (path);
1266           g_strreverse (path_reversed);
1267           path_length = strlen (path);
1268           handled = binding_match_activate (patterns, object, path_length, path, path_reversed, &unbound);
1269           g_free (path);
1270           g_free (path_reversed);
1271
1272           if (unbound)
1273             break;
1274
1275           class_type = g_type_parent (class_type);
1276         }
1277       g_slist_free (patterns);
1278
1279       if (unbound)
1280         return FALSE;
1281     }
1282
1283   return handled;
1284 }
1285
1286 /**
1287  * gtk_bindings_activate:
1288  * @object: object to activate when binding found
1289  * @keyval: key value of the binding
1290  * @modifiers: key modifier of the binding
1291  *
1292  * Find a key binding matching @keyval and @modifiers and activate the
1293  * binding on @object.
1294  *
1295  * Return value: %TRUE if a binding was found and activated
1296  */
1297 gboolean
1298 gtk_bindings_activate (GtkObject       *object,
1299                        guint            keyval,
1300                        GdkModifierType  modifiers)
1301 {
1302   GSList *entries = NULL;
1303   GdkDisplay *display;
1304   GtkKeyHash *key_hash;
1305   gboolean handled = FALSE;
1306   gboolean is_release;
1307
1308   g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
1309
1310   if (!GTK_IS_WIDGET (object))
1311     return FALSE;
1312
1313   is_release = (modifiers & GDK_RELEASE_MASK) != 0;
1314   modifiers = modifiers & BINDING_MOD_MASK () & ~GDK_RELEASE_MASK;
1315
1316   display = gtk_widget_get_display (GTK_WIDGET (object));
1317   key_hash = binding_key_hash_for_keymap (gdk_keymap_get_for_display (display));
1318   
1319   entries = _gtk_key_hash_lookup_keyval (key_hash, keyval, modifiers);
1320
1321   handled = gtk_bindings_activate_list (object, entries, is_release);
1322
1323   g_slist_free (entries);
1324
1325   return handled;
1326 }
1327
1328 /**
1329  * gtk_bindings_activate_event:
1330  * @object: a #GtkObject (generally must be a widget)
1331  * @event: a #GdkEventKey
1332  * 
1333  * Looks up key bindings for @object to find one matching
1334  * @event, and if one was found, activate it.
1335  * 
1336  * Return value: %TRUE if a matching key binding was found
1337  */
1338 gboolean
1339 gtk_bindings_activate_event (GtkObject   *object,
1340                              GdkEventKey *event)
1341 {
1342   GSList *entries = NULL;
1343   GdkDisplay *display;
1344   GtkKeyHash *key_hash;
1345   gboolean handled = FALSE;
1346
1347   g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
1348
1349   if (!GTK_IS_WIDGET (object))
1350     return FALSE;
1351
1352   display = gtk_widget_get_display (GTK_WIDGET (object));
1353   key_hash = binding_key_hash_for_keymap (gdk_keymap_get_for_display (display));
1354
1355   entries = _gtk_key_hash_lookup (key_hash,
1356                                   event->hardware_keycode,
1357                                   event->state,
1358                                   BINDING_MOD_MASK () & ~GDK_RELEASE_MASK,
1359                                   event->group);
1360   
1361   handled = gtk_bindings_activate_list (object, entries,
1362                                         event->type == GDK_KEY_RELEASE);
1363
1364   g_slist_free (entries);
1365
1366   return handled;
1367 }
1368
1369 static guint
1370 gtk_binding_parse_signal (GScanner       *scanner,
1371                           GtkBindingSet  *binding_set,
1372                           guint           keyval,
1373                           GdkModifierType modifiers)
1374 {
1375   gchar *signal;
1376   guint expected_token = 0;
1377   GSList *args;
1378   GSList *slist;
1379   gboolean done;
1380   gboolean negate;
1381   gboolean need_arg;
1382   gboolean seen_comma;
1383
1384   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1385   
1386   g_scanner_get_next_token (scanner);
1387   if (scanner->token != G_TOKEN_STRING)
1388     return G_TOKEN_STRING;
1389   g_scanner_peek_next_token (scanner);
1390   if (scanner->next_token != '(')
1391     {
1392       g_scanner_get_next_token (scanner);
1393       return '(';
1394     }
1395   signal = g_strdup (scanner->value.v_string);
1396   g_scanner_get_next_token (scanner);
1397
1398   negate = FALSE;
1399   args = NULL;
1400   done = FALSE;
1401   need_arg = TRUE;
1402   seen_comma = FALSE;
1403   scanner->config->scan_symbols = FALSE;
1404   do
1405     {
1406       if (need_arg)
1407         expected_token = G_TOKEN_INT;
1408       else
1409         expected_token = ')';
1410       g_scanner_get_next_token (scanner);
1411       switch (scanner->token)
1412         {
1413           GtkBindingArg *arg;
1414
1415         case G_TOKEN_FLOAT:
1416           if (need_arg)
1417             {
1418               need_arg = FALSE;
1419               arg = g_new (GtkBindingArg, 1);
1420               arg->arg_type = G_TYPE_DOUBLE;
1421               arg->d.double_data = scanner->value.v_float;
1422               if (negate)
1423                 {
1424                   arg->d.double_data = - arg->d.double_data;
1425                   negate = FALSE;
1426                 }
1427               args = g_slist_prepend (args, arg);
1428             }
1429           else
1430             done = TRUE;
1431           break;
1432         case G_TOKEN_INT:
1433           if (need_arg)
1434             {
1435               need_arg = FALSE;
1436               arg = g_new (GtkBindingArg, 1);
1437               arg->arg_type = G_TYPE_LONG;
1438               arg->d.long_data = scanner->value.v_int;
1439               if (negate)
1440                 {
1441                   arg->d.long_data = - arg->d.long_data;
1442                   negate = FALSE;
1443                 }
1444               args = g_slist_prepend (args, arg);
1445             }
1446           else
1447             done = TRUE;
1448           break;
1449         case G_TOKEN_STRING:
1450           if (need_arg && !negate)
1451             {
1452               need_arg = FALSE;
1453               arg = g_new (GtkBindingArg, 1);
1454               arg->arg_type = G_TYPE_STRING;
1455               arg->d.string_data = g_strdup (scanner->value.v_string);
1456               args = g_slist_prepend (args, arg);
1457             }
1458           else
1459             done = TRUE;
1460           break;
1461         case G_TOKEN_IDENTIFIER:
1462           if (need_arg && !negate)
1463             {
1464               need_arg = FALSE;
1465               arg = g_new (GtkBindingArg, 1);
1466               arg->arg_type = GTK_TYPE_IDENTIFIER;
1467               arg->d.string_data = g_strdup (scanner->value.v_identifier);
1468               args = g_slist_prepend (args, arg);
1469             }
1470           else
1471             done = TRUE;
1472           break;
1473         case '-':
1474           if (!need_arg)
1475             done = TRUE;
1476           else if (negate)
1477             {
1478               expected_token = G_TOKEN_INT;
1479               done = TRUE;
1480             }
1481           else
1482             negate = TRUE;
1483           break;
1484         case ',':
1485           seen_comma = TRUE;
1486           if (need_arg)
1487             done = TRUE;
1488           else
1489             need_arg = TRUE;
1490           break;
1491         case ')':
1492           if (!(need_arg && seen_comma) && !negate)
1493             {
1494               args = g_slist_reverse (args);
1495               _gtk_binding_entry_add_signall (binding_set,
1496                                               keyval,
1497                                               modifiers,
1498                                               signal,
1499                                               args);
1500               expected_token = G_TOKEN_NONE;
1501             }
1502           done = TRUE;
1503           break;
1504         default:
1505           done = TRUE;
1506           break;
1507         }
1508     }
1509   while (!done);
1510   scanner->config->scan_symbols = TRUE;
1511   
1512   for (slist = args; slist; slist = slist->next)
1513     {
1514       GtkBindingArg *arg;
1515
1516       arg = slist->data;
1517       if (G_TYPE_FUNDAMENTAL (arg->arg_type) == G_TYPE_STRING)
1518         g_free (arg->d.string_data);
1519       g_free (arg);
1520     }
1521   g_slist_free (args);
1522   g_free (signal);
1523
1524   return expected_token;
1525 }
1526
1527 static inline guint
1528 gtk_binding_parse_bind (GScanner       *scanner,
1529                         GtkBindingSet  *binding_set)
1530 {
1531   guint keyval = 0;
1532   GdkModifierType modifiers = 0;
1533   gboolean unbind = FALSE;
1534
1535   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1536   
1537   g_scanner_get_next_token (scanner);
1538   if (scanner->token != GTK_RC_TOKEN_BIND &&
1539       scanner->token != GTK_RC_TOKEN_UNBIND)
1540     return GTK_RC_TOKEN_BIND;
1541   unbind = scanner->token == GTK_RC_TOKEN_UNBIND;
1542   g_scanner_get_next_token (scanner);
1543   if (scanner->token != G_TOKEN_STRING)
1544     return G_TOKEN_STRING;
1545   gtk_accelerator_parse (scanner->value.v_string, &keyval, &modifiers);
1546   modifiers &= BINDING_MOD_MASK ();
1547   if (keyval == 0)
1548     return G_TOKEN_STRING;
1549
1550   if (unbind)
1551     {
1552       gtk_binding_entry_skip (binding_set, keyval, modifiers);
1553       return G_TOKEN_NONE;
1554     }
1555
1556   g_scanner_get_next_token (scanner);
1557
1558   if (scanner->token != '{')
1559     return '{';
1560
1561   gtk_binding_entry_clear_internal (binding_set, keyval, modifiers);
1562
1563   g_scanner_peek_next_token (scanner);
1564   while (scanner->next_token != '}')
1565     {
1566       switch (scanner->next_token)
1567         {
1568           guint expected_token;
1569
1570         case G_TOKEN_STRING:
1571           expected_token = gtk_binding_parse_signal (scanner,
1572                                                      binding_set,
1573                                                      keyval,
1574                                                      modifiers);
1575           if (expected_token != G_TOKEN_NONE)
1576             return expected_token;
1577           break;
1578         default:
1579           g_scanner_get_next_token (scanner);
1580           return '}';
1581         }
1582       g_scanner_peek_next_token (scanner);
1583     }
1584   g_scanner_get_next_token (scanner);
1585
1586   return G_TOKEN_NONE;
1587 }
1588
1589 /**
1590  * gtk_binding_parse_binding:
1591  * @scanner: GtkRC scanner
1592  *
1593  * Parse a binding entry from a gtkrc file.
1594  *
1595  * Return value: expected token upon errors, %G_TOKEN_NONE on success.
1596  *
1597  * Deprecated: 2.12: There should be no need to call this function outside GTK+.
1598  */
1599 guint
1600 gtk_binding_parse_binding (GScanner *scanner)
1601 {
1602   return _gtk_binding_parse_binding (scanner);
1603 }
1604
1605 guint
1606 _gtk_binding_parse_binding (GScanner *scanner)
1607 {
1608   gchar *name;
1609   GtkBindingSet *binding_set;
1610
1611   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1612
1613   g_scanner_get_next_token (scanner);
1614   if (scanner->token != GTK_RC_TOKEN_BINDING)
1615     return GTK_RC_TOKEN_BINDING;
1616   g_scanner_get_next_token (scanner);
1617   if (scanner->token != G_TOKEN_STRING)
1618     return G_TOKEN_STRING;
1619   name = g_strdup (scanner->value.v_string);
1620
1621   g_scanner_get_next_token (scanner);
1622   if (scanner->token != '{')
1623     {
1624       g_free (name);
1625       return G_TOKEN_STRING;
1626     }
1627
1628   binding_set = gtk_binding_set_find (name);
1629   if (!binding_set)
1630     {
1631       binding_set = gtk_binding_set_new (name);
1632       binding_set->parsed = 1;
1633     }
1634   g_free (name);
1635
1636   g_scanner_peek_next_token (scanner);
1637   while (scanner->next_token != '}')
1638     {
1639       switch (scanner->next_token)
1640         {
1641           guint expected_token;
1642
1643         case GTK_RC_TOKEN_BIND:
1644         case GTK_RC_TOKEN_UNBIND:
1645           expected_token = gtk_binding_parse_bind (scanner, binding_set);
1646           if (expected_token != G_TOKEN_NONE)
1647             return expected_token;
1648           break;
1649         default:
1650           g_scanner_get_next_token (scanner);
1651           return '}';
1652         }
1653       g_scanner_peek_next_token (scanner);
1654     }
1655   g_scanner_get_next_token (scanner);
1656
1657   return G_TOKEN_NONE;
1658 }
1659
1660 static void
1661 free_pattern_specs (GSList *pattern_specs)
1662 {
1663   GSList *slist;
1664
1665   for (slist = pattern_specs; slist; slist = slist->next)
1666     {
1667       PatternSpec *pspec;
1668
1669       pspec = slist->data;
1670
1671       pattern_spec_free (pspec);
1672     }
1673
1674   g_slist_free (pattern_specs);
1675 }
1676
1677 static void
1678 binding_set_delete (GtkBindingSet *binding_set)
1679 {
1680   GtkBindingEntry *entry, *next;
1681
1682   entry = binding_set->entries;
1683   while (entry)
1684     {
1685       next = entry->set_next;
1686       binding_entry_destroy (entry);
1687       entry = next;
1688     }
1689   
1690   free_pattern_specs (binding_set->widget_path_pspecs);
1691   free_pattern_specs (binding_set->widget_class_pspecs);
1692   free_pattern_specs (binding_set->class_branch_pspecs);
1693
1694   g_free (binding_set);
1695 }
1696
1697 /**
1698  * _gtk_binding_reset_parsed:
1699  * 
1700  * Remove all binding sets that were added by gtk_binding_parse_binding().
1701  */
1702 void
1703 _gtk_binding_reset_parsed (void)
1704 {
1705   GSList *slist, *next;
1706   
1707   slist = binding_set_list;
1708   while (slist)
1709     {
1710       GtkBindingSet *binding_set;
1711
1712       binding_set = slist->data;
1713       next = slist->next;
1714
1715       if (binding_set->parsed)
1716         {
1717           binding_set_list = g_slist_delete_link (binding_set_list, slist);
1718           binding_set_delete (binding_set);
1719         }
1720
1721       slist = next;
1722     }
1723 }
1724
1725 #define __GTK_BINDINGS_C__
1726 #include "gtkaliasdef.c"