]> Pileus Git - ~andy/gtk/blob - gtk/gtkbindings.c
Hide GtkTreeViewColumn buttons when header_window is not visible
[~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   gpointer      user_data;
51   guint         seq_id;
52 } PatternSpec;
53
54
55 /* --- variables --- */
56 static GHashTable       *binding_entry_hash_table = NULL;
57 static GSList           *binding_key_hashes = NULL;
58 static GSList           *binding_set_list = NULL;
59 static const gchar       key_class_binding_set[] = "gtk-class-binding-set";
60 static GQuark            key_id_class_binding_set = 0;
61
62
63 /* --- functions --- */
64 static void
65 pattern_spec_free (PatternSpec *pspec)
66 {
67   if (pspec->pspec)
68     g_pattern_spec_free (pspec->pspec);
69   g_free (pspec);
70 }
71
72 static GtkBindingSignal*
73 binding_signal_new (const gchar *signal_name,
74                     guint        n_args)
75 {
76   GtkBindingSignal *signal;
77
78   signal = (GtkBindingSignal *) g_slice_alloc0 (sizeof (GtkBindingSignal) + n_args * sizeof (GtkBindingArg));
79   signal->next = NULL;
80   signal->signal_name = (gchar *)g_intern_string (signal_name);
81   signal->n_args = n_args;
82   signal->args = (GtkBindingArg *)(signal + 1);
83   
84   return signal;
85 }
86
87 static void
88 binding_signal_free (GtkBindingSignal *sig)
89 {
90   guint i;
91   
92   for (i = 0; i < sig->n_args; i++)
93     {
94       if (G_TYPE_FUNDAMENTAL (sig->args[i].arg_type) == G_TYPE_STRING)
95         g_free (sig->args[i].d.string_data);
96     }
97   g_slice_free1 (sizeof (GtkBindingSignal) + sig->n_args * sizeof (GtkBindingArg), sig);
98 }
99
100 static guint
101 binding_entry_hash (gconstpointer  key)
102 {
103   register const GtkBindingEntry *e = key;
104   register guint h;
105
106   h = e->keyval;
107   h ^= e->modifiers;
108
109   return h;
110 }
111
112 static gint
113 binding_entries_compare (gconstpointer  a,
114                          gconstpointer  b)
115 {
116   register const GtkBindingEntry *ea = a;
117   register const GtkBindingEntry *eb = b;
118
119   return (ea->keyval == eb->keyval && ea->modifiers == eb->modifiers);
120 }
121
122 static void
123 binding_key_hash_insert_entry (GtkKeyHash      *key_hash,
124                                GtkBindingEntry *entry)
125 {
126   guint keyval = entry->keyval;
127   
128   /* We store lowercased accelerators. To deal with this, if <Shift>
129    * was specified, uppercase.
130    */
131   if (entry->modifiers & GDK_SHIFT_MASK)
132     {
133       if (keyval == GDK_KEY_Tab)
134         keyval = GDK_KEY_ISO_Left_Tab;
135       else
136         keyval = gdk_keyval_to_upper (keyval);
137     }
138   
139   _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers & ~GDK_RELEASE_MASK, entry);
140 }
141
142 static void
143 binding_key_hash_destroy (gpointer data)
144 {
145   GtkKeyHash *key_hash = data;
146   
147   binding_key_hashes = g_slist_remove (binding_key_hashes, key_hash);
148   _gtk_key_hash_free (key_hash);
149 }
150
151 static void
152 insert_entries_into_key_hash (gpointer key,
153                               gpointer value,
154                               gpointer data)
155 {
156   GtkKeyHash *key_hash = data;
157   GtkBindingEntry *entry = value;
158
159   for (; entry; entry = entry->hash_next)
160     binding_key_hash_insert_entry (key_hash, entry);
161 }
162
163 static GtkKeyHash *
164 binding_key_hash_for_keymap (GdkKeymap *keymap)
165 {
166   static GQuark key_hash_quark = 0;
167   GtkKeyHash *key_hash;
168
169   if (!key_hash_quark)
170     key_hash_quark = g_quark_from_static_string ("gtk-binding-key-hash");
171   
172   key_hash = g_object_get_qdata (G_OBJECT (keymap), key_hash_quark);
173
174   if (!key_hash)
175     {
176       key_hash = _gtk_key_hash_new (keymap, NULL);
177       g_object_set_qdata_full (G_OBJECT (keymap), key_hash_quark, key_hash, binding_key_hash_destroy);
178
179       if (binding_entry_hash_table)
180         g_hash_table_foreach (binding_entry_hash_table,
181                               insert_entries_into_key_hash,
182                               key_hash);
183
184       binding_key_hashes = g_slist_prepend (binding_key_hashes, key_hash);
185     }
186
187   return key_hash;
188 }
189
190
191 static GtkBindingEntry*
192 binding_entry_new (GtkBindingSet  *binding_set,
193                    guint           keyval,
194                    GdkModifierType modifiers)
195 {
196   GSList *tmp_list;
197   GtkBindingEntry *entry;
198   
199   if (!binding_entry_hash_table)
200     binding_entry_hash_table = g_hash_table_new (binding_entry_hash, binding_entries_compare);
201
202   entry = g_new (GtkBindingEntry, 1);
203   entry->keyval = keyval;
204   entry->modifiers = modifiers;
205   entry->binding_set = binding_set,
206   entry->destroyed = FALSE;
207   entry->in_emission = FALSE;
208   entry->marks_unbound = FALSE;
209   entry->signals = NULL;
210
211   entry->set_next = binding_set->entries;
212   binding_set->entries = entry;
213
214   entry->hash_next = g_hash_table_lookup (binding_entry_hash_table, entry);
215   if (entry->hash_next)
216     g_hash_table_remove (binding_entry_hash_table, entry->hash_next);
217   g_hash_table_insert (binding_entry_hash_table, entry, entry);
218
219   for (tmp_list = binding_key_hashes; tmp_list; tmp_list = tmp_list->next)
220     {
221       GtkKeyHash *key_hash = tmp_list->data;
222       binding_key_hash_insert_entry (key_hash, entry);
223     }
224   
225   return entry;
226 }
227
228 static void
229 binding_entry_free (GtkBindingEntry *entry)
230 {
231   GtkBindingSignal *sig;
232
233   g_assert (entry->set_next == NULL &&
234             entry->hash_next == NULL &&
235             entry->in_emission == FALSE &&
236             entry->destroyed == TRUE);
237
238   entry->destroyed = FALSE;
239   
240   sig = entry->signals;
241   while (sig)
242     {
243       GtkBindingSignal *prev;
244       
245       prev = sig;
246       sig = prev->next;
247       binding_signal_free (prev);
248     }
249   g_free (entry);
250 }
251
252 static void
253 binding_entry_destroy (GtkBindingEntry *entry)
254 {
255   GtkBindingEntry *o_entry;
256   register GtkBindingEntry *tmp;
257   GtkBindingEntry *begin;
258   register GtkBindingEntry *last;
259   GSList *tmp_list;
260
261   /* unlink from binding set
262    */
263   last = NULL;
264   tmp = entry->binding_set->entries;
265   while (tmp)
266     {
267       if (tmp == entry)
268         {
269           if (last)
270             last->set_next = entry->set_next;
271           else
272             entry->binding_set->entries = entry->set_next;
273           break;
274         }
275       last = tmp;
276       tmp = last->set_next;
277     }
278   entry->set_next = NULL;
279   
280   o_entry = g_hash_table_lookup (binding_entry_hash_table, entry);
281   begin = o_entry;
282   last = NULL;
283   tmp = begin;
284   while (tmp)
285     {
286       if (tmp == entry)
287         {
288           if (last)
289             last->hash_next = entry->hash_next;
290           else
291             begin = entry->hash_next;
292           break;
293         }
294       last = tmp;
295       tmp = last->hash_next;
296     }
297   entry->hash_next = NULL;
298   
299   if (!begin)
300     g_hash_table_remove (binding_entry_hash_table, entry);
301   else if (begin != o_entry)
302     {
303       g_hash_table_remove (binding_entry_hash_table, entry);
304       g_hash_table_insert (binding_entry_hash_table, begin, begin);
305     }
306
307   for (tmp_list = binding_key_hashes; tmp_list; tmp_list = tmp_list->next)
308     {
309       GtkKeyHash *key_hash = tmp_list->data;
310       _gtk_key_hash_remove_entry (key_hash, entry);
311     }
312
313   entry->destroyed = TRUE;
314
315   if (!entry->in_emission)
316     binding_entry_free (entry);
317 }
318
319 static GtkBindingEntry*
320 binding_ht_lookup_entry (GtkBindingSet  *set,
321                          guint           keyval,
322                          GdkModifierType modifiers)
323 {
324   GtkBindingEntry lookup_entry = { 0 };
325   GtkBindingEntry *entry;
326   
327   if (!binding_entry_hash_table)
328     return NULL;
329   
330   lookup_entry.keyval = keyval;
331   lookup_entry.modifiers = modifiers;
332   
333   entry = g_hash_table_lookup (binding_entry_hash_table, &lookup_entry);
334   for (; entry; entry = entry->hash_next)
335     if (entry->binding_set == set)
336       return entry;
337
338   return NULL;
339 }
340
341 static gboolean
342 binding_compose_params (GObject         *object,
343                         GtkBindingArg   *args,
344                         GSignalQuery    *query,
345                         GValue         **params_p)
346 {
347   GValue *params;
348   const GType *types;
349   guint i;
350   gboolean valid;
351   
352   params = g_new0 (GValue, query->n_params + 1);
353   *params_p = params;
354
355   /* The instance we emit on is the first object in the array
356    */
357   g_value_init (params, G_TYPE_OBJECT);
358   g_value_set_object (params, G_OBJECT (object));
359   params++;
360   
361   types = query->param_types;
362   valid = TRUE;
363   for (i = 1; i < query->n_params + 1 && valid; i++)
364     {
365       GValue tmp_value = { 0, };
366
367       g_value_init (params, *types);
368
369       switch (G_TYPE_FUNDAMENTAL (args->arg_type))
370         {
371         case G_TYPE_DOUBLE:
372           g_value_init (&tmp_value, G_TYPE_DOUBLE);
373           g_value_set_double (&tmp_value, args->d.double_data);
374           break;
375         case G_TYPE_LONG:
376           g_value_init (&tmp_value, G_TYPE_LONG);
377           g_value_set_long (&tmp_value, args->d.long_data);
378           break;
379         case G_TYPE_STRING:
380           /* gtk_rc_parse_flags/enum() has fancier parsing for this; we can't call
381            * that since we don't have a GParamSpec, so just do something simple
382            */
383           if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_ENUM)
384             {
385               GEnumClass *class = G_ENUM_CLASS (g_type_class_ref (*types));
386               
387               valid = FALSE;
388               
389               if (args->arg_type == GTK_TYPE_IDENTIFIER)
390                 {
391                   GEnumValue *enum_value = NULL;
392                   enum_value = g_enum_get_value_by_name (class, args->d.string_data);
393                   if (!enum_value)
394                     enum_value = g_enum_get_value_by_nick (class, args->d.string_data);
395                   if (enum_value)
396                     {
397                       g_value_init (&tmp_value, *types);
398                       g_value_set_enum (&tmp_value, enum_value->value);
399                       valid = TRUE;
400                     }
401                 }
402
403               g_type_class_unref (class);
404             }
405           /* This is just a hack for compatibility with GTK+-1.2 where a string
406            * could be used for a single flag value / without the support for multiple
407            * values in gtk_rc_parse_flags(), this isn't very useful.
408            */
409           else if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_FLAGS)
410             {
411               GFlagsClass *class = G_FLAGS_CLASS (g_type_class_ref (*types));
412               
413               valid = FALSE;
414               
415               if (args->arg_type == GTK_TYPE_IDENTIFIER)
416                 {
417                   GFlagsValue *flags_value = NULL;
418                   flags_value = g_flags_get_value_by_name (class, args->d.string_data);
419                   if (!flags_value)
420                     flags_value = g_flags_get_value_by_nick (class, args->d.string_data);
421                   if (flags_value)
422                     {
423                       g_value_init (&tmp_value, *types);
424                       g_value_set_flags (&tmp_value, flags_value->value);
425                       valid = TRUE;
426                     }
427                 }
428
429               g_type_class_unref (class);
430             }
431           else
432             {
433               g_value_init (&tmp_value, G_TYPE_STRING);
434               g_value_set_static_string (&tmp_value, args->d.string_data);
435             }
436           break;
437         default:
438           valid = FALSE;
439           break;
440         }
441
442       if (valid)
443         {
444           if (!g_value_transform (&tmp_value, params))
445             valid = FALSE;
446
447           g_value_unset (&tmp_value);
448         }
449       
450       types++;
451       params++;
452       args++;
453     }
454   
455   if (!valid)
456     {
457       guint j;
458
459       for (j = 0; j < i; j++)
460         g_value_unset (&(*params_p)[j]);
461       
462       g_free (*params_p);
463       *params_p = NULL;
464     }
465   
466   return valid;
467 }
468
469 static gboolean
470 gtk_binding_entry_activate (GtkBindingEntry *entry,
471                             GObject         *object)
472 {
473   GtkBindingSignal *sig;
474   gboolean old_emission;
475   gboolean handled = FALSE;
476   gint i;
477   
478   old_emission = entry->in_emission;
479   entry->in_emission = TRUE;
480   
481   g_object_ref (object);
482   
483   for (sig = entry->signals; sig; sig = sig->next)
484     {
485       GSignalQuery query;
486       guint signal_id;
487       GValue *params = NULL;
488       GValue return_val = { 0, };
489       gchar *accelerator = NULL;
490       
491       signal_id = g_signal_lookup (sig->signal_name, G_OBJECT_TYPE (object));
492       if (!signal_id)
493         {
494           accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
495           g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
496                      "could not find signal \"%s\" in the `%s' class ancestry",
497                      entry->binding_set->set_name,
498                      accelerator,
499                      sig->signal_name,
500                      g_type_name (G_OBJECT_TYPE (object)));
501           g_free (accelerator);
502           continue;
503         }
504       
505       g_signal_query (signal_id, &query);
506       if (query.n_params != sig->n_args ||
507           (query.return_type != G_TYPE_NONE && query.return_type != G_TYPE_BOOLEAN) || 
508           !binding_compose_params (object, sig->args, &query, &params))
509         {
510           accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
511           g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
512                      "signature mismatch for signal \"%s\" in the `%s' class ancestry",
513                      entry->binding_set->set_name,
514                      accelerator,
515                      sig->signal_name,
516                      g_type_name (G_OBJECT_TYPE (object)));
517         }
518       else if (!(query.signal_flags & G_SIGNAL_ACTION))
519         {
520           accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
521           g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
522                      "signal \"%s\" in the `%s' class ancestry cannot be used for action emissions",
523                      entry->binding_set->set_name,
524                      accelerator,
525                      sig->signal_name,
526                      g_type_name (G_OBJECT_TYPE (object)));
527         }
528       g_free (accelerator);
529       if (accelerator)
530         continue;
531
532       if (query.return_type == G_TYPE_BOOLEAN)
533         g_value_init (&return_val, G_TYPE_BOOLEAN);
534       
535       g_signal_emitv (params, signal_id, 0, &return_val);
536
537       if (query.return_type == G_TYPE_BOOLEAN)
538         {
539           if (g_value_get_boolean (&return_val))
540             handled = TRUE;
541           g_value_unset (&return_val);
542         }
543       else
544         handled = TRUE;
545       
546       for (i = 0; i < query.n_params + 1; i++)
547         g_value_unset (&params[i]);
548       g_free (params);
549       
550       if (entry->destroyed)
551         break;
552     }
553   
554   g_object_unref (object);
555
556   entry->in_emission = old_emission;
557   if (entry->destroyed && !entry->in_emission)
558     binding_entry_free (entry);
559
560   return handled;
561 }
562
563 /**
564  * gtk_binding_set_new:
565  * @set_name: unique name of this binding set
566  *
567  * GTK+ maintains a global list of binding sets. Each binding set has
568  * a unique name which needs to be specified upon creation.
569  *
570  * Return value: new binding set
571  */
572 GtkBindingSet*
573 gtk_binding_set_new (const gchar *set_name)
574 {
575   GtkBindingSet *binding_set;
576   
577   g_return_val_if_fail (set_name != NULL, NULL);
578   
579   binding_set = g_new (GtkBindingSet, 1);
580   binding_set->set_name = (gchar *) g_intern_string (set_name);
581   binding_set->widget_path_pspecs = NULL;
582   binding_set->widget_class_pspecs = NULL;
583   binding_set->class_branch_pspecs = NULL;
584   binding_set->entries = NULL;
585   binding_set->current = NULL;
586   binding_set->parsed = FALSE;
587   
588   binding_set_list = g_slist_prepend (binding_set_list, binding_set);
589   
590   return binding_set;
591 }
592
593 /**
594  * gtk_binding_set_by_class:
595  * @object_class: a valid #GObject class
596  *
597  * This function returns the binding set named after the type name of
598  * the passed in class structure. New binding sets are created on
599  * demand by this function.
600  *
601  * Return value: the binding set corresponding to @object_class
602  */
603 GtkBindingSet*
604 gtk_binding_set_by_class (gpointer object_class)
605 {
606   GObjectClass *class = object_class;
607   GtkBindingSet* binding_set;
608
609   g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
610
611   if (!key_id_class_binding_set)
612     key_id_class_binding_set = g_quark_from_static_string (key_class_binding_set);
613
614   binding_set = g_dataset_id_get_data (class, key_id_class_binding_set);
615
616   if (binding_set)
617     return binding_set;
618
619   binding_set = gtk_binding_set_new (g_type_name (G_OBJECT_CLASS_TYPE (class)));
620   gtk_binding_set_add_path (binding_set,
621                             GTK_PATH_CLASS,
622                             g_type_name (G_OBJECT_CLASS_TYPE (class)),
623                             GTK_PATH_PRIO_GTK);
624   g_dataset_id_set_data (class, key_id_class_binding_set, binding_set);
625
626   return binding_set;
627 }
628
629 /**
630  * gtk_binding_set_find:
631  * @set_name: unique binding set name
632  *
633  * Find a binding set by its globally unique name. The @set_name can
634  * either be a name used for gtk_binding_set_new() or the type name of
635  * a class used in gtk_binding_set_by_class().
636  *
637  * Return value: %NULL or the specified binding set
638  */
639 GtkBindingSet*
640 gtk_binding_set_find (const gchar *set_name)
641 {
642   GSList *slist;
643   
644   g_return_val_if_fail (set_name != NULL, NULL);
645   
646   for (slist = binding_set_list; slist; slist = slist->next)
647     {
648       GtkBindingSet *binding_set;
649       
650       binding_set = slist->data;
651       if (g_str_equal (binding_set->set_name, (gpointer) set_name))
652         return binding_set;
653     }
654   return NULL;
655 }
656
657 /**
658  * gtk_binding_set_activate:
659  * @binding_set: a #GtkBindingSet set to activate
660  * @keyval:      key value of the binding
661  * @modifiers:   key modifier of the binding
662  * @object:      object to activate when binding found
663  *
664  * Find a key binding matching @keyval and @modifiers within
665  * @binding_set and activate the binding on @object.
666  *
667  * Return value: %TRUE if a binding was found and activated
668  */
669 gboolean
670 gtk_binding_set_activate (GtkBindingSet  *binding_set,
671                           guint           keyval,
672                           GdkModifierType modifiers,
673                           GObject        *object)
674 {
675   GtkBindingEntry *entry;
676   
677   g_return_val_if_fail (binding_set != NULL, FALSE);
678   g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
679   
680   keyval = gdk_keyval_to_lower (keyval);
681   modifiers = modifiers & BINDING_MOD_MASK ();
682   
683   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
684   if (entry)
685     return gtk_binding_entry_activate (entry, object);
686   
687   return FALSE;
688 }
689
690 static void
691 gtk_binding_entry_clear_internal (GtkBindingSet  *binding_set,
692                                   guint           keyval,
693                                   GdkModifierType modifiers)
694 {
695   GtkBindingEntry *entry;
696
697   keyval = gdk_keyval_to_lower (keyval);
698   modifiers = modifiers & BINDING_MOD_MASK ();
699
700   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
701   if (entry)
702     binding_entry_destroy (entry);
703
704   entry = binding_entry_new (binding_set, keyval, modifiers);
705 }
706
707 /**
708  * gtk_binding_entry_skip:
709  * @binding_set: a #GtkBindingSet to skip an entry of
710  * @keyval:      key value of binding to skip
711  * @modifiers:   key modifier of binding to skip
712  *
713  * Install a binding on @binding_set which causes key lookups
714  * to be aborted, to prevent bindings from lower priority sets
715  * to be activated.
716  *
717  * Since: 2.12
718  */
719 void
720 gtk_binding_entry_skip (GtkBindingSet  *binding_set,
721                         guint           keyval,
722                         GdkModifierType modifiers)
723 {
724   GtkBindingEntry *entry;
725
726   g_return_if_fail (binding_set != NULL);
727
728   keyval = gdk_keyval_to_lower (keyval);
729   modifiers = modifiers & BINDING_MOD_MASK ();
730
731   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
732   if (entry)
733     binding_entry_destroy (entry);
734
735   entry = binding_entry_new (binding_set, keyval, modifiers);
736   entry->marks_unbound = TRUE;
737 }
738
739 /**
740  * gtk_binding_entry_remove:
741  * @binding_set: a #GtkBindingSet to remove an entry of
742  * @keyval:      key value of binding to remove
743  * @modifiers:   key modifier of binding to remove
744  *
745  * Remove a binding previously installed via
746  * gtk_binding_entry_add_signal() on @binding_set.
747  */
748 void
749 gtk_binding_entry_remove (GtkBindingSet  *binding_set,
750                           guint           keyval,
751                           GdkModifierType modifiers)
752 {
753   GtkBindingEntry *entry;
754   
755   g_return_if_fail (binding_set != NULL);
756   
757   keyval = gdk_keyval_to_lower (keyval);
758   modifiers = modifiers & BINDING_MOD_MASK ();
759   
760   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
761   if (entry)
762     binding_entry_destroy (entry);
763 }
764
765 /**
766  * gtk_binding_entry_add_signall:
767  * @binding_set:  a #GtkBindingSet to add a signal to
768  * @keyval:       key value
769  * @modifiers:    key modifier
770  * @signal_name:  signal name to be bound
771  * @binding_args: (transfer none) (element-type GtkBindingArg):
772  *     list of #GtkBindingArg signal arguments
773  *
774  * Override or install a new key binding for @keyval with @modifiers on
775  * @binding_set.
776  */
777 void
778 gtk_binding_entry_add_signall (GtkBindingSet  *binding_set,
779                                guint           keyval,
780                                GdkModifierType modifiers,
781                                const gchar    *signal_name,
782                                GSList         *binding_args)
783 {
784   _gtk_binding_entry_add_signall (binding_set,
785                                   keyval, modifiers,
786                                   signal_name, binding_args);
787 }
788
789 void
790 _gtk_binding_entry_add_signall (GtkBindingSet  *binding_set,
791                                 guint          keyval,
792                                 GdkModifierType modifiers,
793                                 const gchar    *signal_name,
794                                 GSList        *binding_args)
795 {
796   GtkBindingEntry *entry;
797   GtkBindingSignal *signal, **signal_p;
798   GSList *slist;
799   guint n = 0;
800   GtkBindingArg *arg;
801   
802   g_return_if_fail (binding_set != NULL);
803   g_return_if_fail (signal_name != NULL);
804   
805   keyval = gdk_keyval_to_lower (keyval);
806   modifiers = modifiers & BINDING_MOD_MASK ();
807   
808   signal = binding_signal_new (signal_name, g_slist_length (binding_args));
809   
810   arg = signal->args;
811   for (slist = binding_args; slist; slist = slist->next)
812     {
813       GtkBindingArg *tmp_arg;
814       
815       tmp_arg = slist->data;
816       if (!tmp_arg)
817         {
818           g_warning ("gtk_binding_entry_add_signall(): arg[%u] is `NULL'", n);
819           binding_signal_free (signal);
820           return;
821         }
822       switch (G_TYPE_FUNDAMENTAL (tmp_arg->arg_type))
823         {
824         case  G_TYPE_LONG:
825           arg->arg_type = G_TYPE_LONG;
826           arg->d.long_data = tmp_arg->d.long_data;
827           break;
828         case  G_TYPE_DOUBLE:
829           arg->arg_type = G_TYPE_DOUBLE;
830           arg->d.double_data = tmp_arg->d.double_data;
831           break;
832         case  G_TYPE_STRING:
833           if (tmp_arg->arg_type != GTK_TYPE_IDENTIFIER)
834             arg->arg_type = G_TYPE_STRING;
835           else
836             arg->arg_type = GTK_TYPE_IDENTIFIER;
837           arg->d.string_data = g_strdup (tmp_arg->d.string_data);
838           if (!arg->d.string_data)
839             {
840               g_warning ("gtk_binding_entry_add_signall(): value of `string' arg[%u] is `NULL'", n);
841               binding_signal_free (signal);
842               return;
843             }
844           break;
845         default:
846           g_warning ("gtk_binding_entry_add_signall(): unsupported type `%s' for arg[%u]",
847                      g_type_name (arg->arg_type), n);
848           binding_signal_free (signal);
849           return;
850         }
851       arg++;
852       n++;
853     }
854   
855   entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
856   if (!entry)
857     {
858       gtk_binding_entry_clear_internal (binding_set, keyval, modifiers);
859       entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
860     }
861   signal_p = &entry->signals;
862   while (*signal_p)
863     signal_p = &(*signal_p)->next;
864   *signal_p = signal;
865 }
866
867 /**
868  * gtk_binding_entry_add_signal:
869  * @binding_set: a #GtkBindingSet to install an entry for
870  * @keyval:      key value of binding to install
871  * @modifiers:   key modifier of binding to install
872  * @signal_name: signal to execute upon activation
873  * @n_args:      number of arguments to @signal_name
874  * @Varargs:     arguments to @signal_name
875  *
876  * Override or install a new key binding for @keyval with @modifiers on
877  * @binding_set. When the binding is activated, @signal_name will be
878  * emitted on the target widget, with @n_args @Varargs used as
879  * arguments.
880  */
881 void
882 gtk_binding_entry_add_signal (GtkBindingSet  *binding_set,
883                               guint           keyval,
884                               GdkModifierType modifiers,
885                               const gchar    *signal_name,
886                               guint           n_args,
887                               ...)
888 {
889   GSList *slist, *free_slist;
890   va_list args;
891   guint i;
892
893   g_return_if_fail (binding_set != NULL);
894   g_return_if_fail (signal_name != NULL);
895   
896   va_start (args, n_args);
897   slist = NULL;
898   for (i = 0; i < n_args; i++)
899     {
900       GtkBindingArg *arg;
901
902       arg = g_slice_new0 (GtkBindingArg);
903       slist = g_slist_prepend (slist, arg);
904
905       arg->arg_type = va_arg (args, GType);
906       switch (G_TYPE_FUNDAMENTAL (arg->arg_type))
907         {
908         case G_TYPE_CHAR:
909         case G_TYPE_UCHAR:
910         case G_TYPE_INT:
911         case G_TYPE_UINT:
912         case G_TYPE_BOOLEAN:
913         case G_TYPE_ENUM:
914         case G_TYPE_FLAGS:
915           arg->arg_type = G_TYPE_LONG;
916           arg->d.long_data = va_arg (args, gint);
917           break;
918         case G_TYPE_LONG:
919         case G_TYPE_ULONG:
920           arg->arg_type = G_TYPE_LONG;
921           arg->d.long_data = va_arg (args, glong);
922           break;
923         case G_TYPE_FLOAT:
924         case G_TYPE_DOUBLE:
925           arg->arg_type = G_TYPE_DOUBLE;
926           arg->d.double_data = va_arg (args, gdouble);
927           break;
928         case G_TYPE_STRING:
929           if (arg->arg_type != GTK_TYPE_IDENTIFIER)
930             arg->arg_type = G_TYPE_STRING;
931           arg->d.string_data = va_arg (args, gchar*);
932           if (!arg->d.string_data)
933             {
934               g_warning ("gtk_binding_entry_add_signal(): type `%s' arg[%u] is `NULL'",
935                          g_type_name (arg->arg_type),
936                          i);
937               i += n_args + 1;
938             }
939           break;
940         default:
941           g_warning ("gtk_binding_entry_add_signal(): unsupported type `%s' for arg[%u]",
942                      g_type_name (arg->arg_type), i);
943           i += n_args + 1;
944           break;
945         }
946     }
947   va_end (args);
948
949   if (i == n_args || i == 0)
950     {
951       slist = g_slist_reverse (slist);
952       _gtk_binding_entry_add_signall (binding_set, keyval, modifiers, signal_name, slist);
953     }
954
955   free_slist = slist;
956   while (slist)
957     {
958       g_slice_free (GtkBindingArg, slist->data);
959       slist = slist->next;
960     }
961   g_slist_free (free_slist);
962 }
963
964 /**
965  * gtk_binding_set_add_path:
966  * @binding_set:  a #GtkBindingSet to add a path to
967  * @path_type:    path type the pattern applies to
968  * @path_pattern: the actual match pattern
969  * @priority:     binding priority
970  *
971  * This function is used internally by the GtkRC parsing mechanism to
972  * assign match patterns to #GtkBindingSet structures.
973  *
974  * Deprecated: 3.0
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     pspec->pspec = NULL;
1013   else
1014     pspec->pspec = g_pattern_spec_new (path_pattern);
1015
1016   pspec->seq_id = priority << 28;
1017   pspec->user_data = binding_set;
1018   
1019   slist = *slist_p;
1020   while (slist)
1021     {
1022       PatternSpec *tmp_pspec;
1023       
1024       tmp_pspec = slist->data;
1025       slist = slist->next;
1026       
1027       if (g_pattern_spec_equal (tmp_pspec->pspec, pspec->pspec))
1028         {
1029           GtkPathPriorityType lprio = tmp_pspec->seq_id >> 28;
1030
1031           pattern_spec_free (pspec);
1032           pspec = NULL;
1033           if (lprio < priority)
1034             {
1035               tmp_pspec->seq_id &= 0x0fffffff;
1036               tmp_pspec->seq_id |= priority << 28;
1037             }
1038           break;
1039         }
1040     }
1041   if (pspec)
1042     {
1043       pspec->seq_id |= seq_id++ & 0x0fffffff;
1044       *slist_p = g_slist_prepend (*slist_p, pspec);
1045     }
1046 }
1047
1048 static gboolean
1049 binding_match_activate (GSList          *pspec_list,
1050                         GObject         *object,
1051                         guint            path_length,
1052                         gchar           *path,
1053                         gchar           *path_reversed,
1054                         gboolean        *unbound)
1055 {
1056   GSList *slist;
1057
1058   *unbound = FALSE;
1059
1060   for (slist = pspec_list; slist; slist = slist->next)
1061     {
1062       PatternSpec *pspec;
1063       GtkBindingSet *binding_set;
1064
1065       binding_set = NULL;
1066       pspec = slist->data;
1067
1068       if (pspec->type != GTK_PATH_WIDGET_CLASS)
1069         {
1070           if (g_pattern_match (pspec->pspec, path_length, path, path_reversed))
1071             binding_set = pspec->user_data;
1072         }
1073
1074       if (binding_set)
1075         {
1076           if (binding_set->current->marks_unbound)
1077             {
1078               *unbound = TRUE;
1079               return FALSE;
1080             }
1081
1082           if (gtk_binding_entry_activate (binding_set->current, object))
1083             return TRUE;
1084         }
1085     }
1086
1087   return FALSE;
1088 }
1089
1090 static gint
1091 gtk_binding_pattern_compare (gconstpointer new_pattern,
1092                              gconstpointer existing_pattern)
1093 {
1094   register const PatternSpec *np  = new_pattern;
1095   register const PatternSpec *ep  = existing_pattern;
1096
1097   /* walk the list as long as the existing patterns have
1098    * higher priorities.
1099    */
1100
1101   return np->seq_id < ep->seq_id;
1102 }
1103
1104 static GSList*
1105 gtk_binding_entries_sort_patterns (GSList      *entries,
1106                                    GtkPathType  path_id,
1107                                    gboolean     is_release)
1108 {
1109   GSList *patterns;
1110   GSList *tmp_list;
1111
1112   patterns = NULL;
1113   for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
1114     {
1115       GtkBindingEntry *entry = tmp_list->data;
1116       GtkBindingSet *binding_set;
1117
1118       binding_set = entry->binding_set;
1119       binding_set->current = NULL;
1120     }
1121   
1122   for (; entries; entries = entries->next)
1123     {
1124       GtkBindingEntry *entry = entries->data;
1125       GtkBindingSet *binding_set;
1126       GSList *slist = NULL;
1127
1128       if (is_release != ((entry->modifiers & GDK_RELEASE_MASK) != 0))
1129         continue;
1130
1131       binding_set = entry->binding_set;
1132
1133       if (binding_set->current)
1134         continue;
1135       binding_set->current = entry;
1136
1137       switch (path_id)
1138         {
1139         case GTK_PATH_WIDGET:
1140           slist = binding_set->widget_path_pspecs;
1141           break;
1142         case GTK_PATH_WIDGET_CLASS:
1143           slist = binding_set->widget_class_pspecs;
1144           break;
1145         case GTK_PATH_CLASS:
1146           slist = binding_set->class_branch_pspecs;
1147           break;
1148         }
1149
1150       for (; slist; slist = slist->next)
1151         {
1152           PatternSpec *pspec;
1153
1154           pspec = slist->data;
1155           patterns = g_slist_insert_sorted (patterns, pspec, gtk_binding_pattern_compare);
1156         }
1157     }
1158
1159   return patterns;
1160 }
1161
1162 static gboolean
1163 gtk_bindings_activate_list (GObject   *object,
1164                             GSList    *entries,
1165                             gboolean   is_release)
1166 {
1167   gboolean handled = FALSE;
1168
1169   if (!entries)
1170     return FALSE;
1171
1172   /* FIXME: Add back binding parsing from user config files */
1173
1174   if (!handled)
1175     {
1176       GSList *patterns;
1177       GType class_type;
1178       gboolean unbound = FALSE;
1179
1180       patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_CLASS, is_release);
1181       class_type = G_TYPE_FROM_INSTANCE (object);
1182       while (class_type && !handled)
1183         {
1184           guint path_length;
1185           gchar *path;
1186           gchar *path_reversed;
1187
1188           path = g_strdup (g_type_name (class_type));
1189           path_reversed = g_strdup (path);
1190           g_strreverse (path_reversed);
1191           path_length = strlen (path);
1192           handled = binding_match_activate (patterns, object, path_length, path, path_reversed, &unbound);
1193           g_free (path);
1194           g_free (path_reversed);
1195
1196           if (unbound)
1197             break;
1198
1199           class_type = g_type_parent (class_type);
1200         }
1201       g_slist_free (patterns);
1202
1203       if (unbound)
1204         return FALSE;
1205     }
1206
1207   return handled;
1208 }
1209
1210 /**
1211  * gtk_bindings_activate:
1212  * @object: object to activate when binding found
1213  * @keyval: key value of the binding
1214  * @modifiers: key modifier of the binding
1215  *
1216  * Find a key binding matching @keyval and @modifiers and activate the
1217  * binding on @object.
1218  *
1219  * Return value: %TRUE if a binding was found and activated
1220  */
1221 gboolean
1222 gtk_bindings_activate (GObject         *object,
1223                        guint            keyval,
1224                        GdkModifierType  modifiers)
1225 {
1226   GSList *entries = NULL;
1227   GdkDisplay *display;
1228   GtkKeyHash *key_hash;
1229   gboolean handled = FALSE;
1230   gboolean is_release;
1231
1232   if (!GTK_IS_WIDGET (object))
1233     return FALSE;
1234
1235   is_release = (modifiers & GDK_RELEASE_MASK) != 0;
1236   modifiers = modifiers & BINDING_MOD_MASK () & ~GDK_RELEASE_MASK;
1237
1238   display = gtk_widget_get_display (GTK_WIDGET (object));
1239   key_hash = binding_key_hash_for_keymap (gdk_keymap_get_for_display (display));
1240   
1241   entries = _gtk_key_hash_lookup_keyval (key_hash, keyval, modifiers);
1242
1243   handled = gtk_bindings_activate_list (object, entries, is_release);
1244
1245   g_slist_free (entries);
1246
1247   return handled;
1248 }
1249
1250 /**
1251  * gtk_bindings_activate_event:
1252  * @object: a #GObject (generally must be a widget)
1253  * @event: a #GdkEventKey
1254  * 
1255  * Looks up key bindings for @object to find one matching
1256  * @event, and if one was found, activate it.
1257  * 
1258  * Return value: %TRUE if a matching key binding was found
1259  *
1260  * Since: 2.4
1261  */
1262 gboolean
1263 gtk_bindings_activate_event (GObject     *object,
1264                              GdkEventKey *event)
1265 {
1266   GSList *entries = NULL;
1267   GdkDisplay *display;
1268   GtkKeyHash *key_hash;
1269   gboolean handled = FALSE;
1270
1271   if (!GTK_IS_WIDGET (object))
1272     return FALSE;
1273
1274   display = gtk_widget_get_display (GTK_WIDGET (object));
1275   key_hash = binding_key_hash_for_keymap (gdk_keymap_get_for_display (display));
1276
1277   entries = _gtk_key_hash_lookup (key_hash,
1278                                   event->hardware_keycode,
1279                                   event->state,
1280                                   BINDING_MOD_MASK () & ~GDK_RELEASE_MASK,
1281                                   event->group);
1282   
1283   handled = gtk_bindings_activate_list (object, entries,
1284                                         event->type == GDK_KEY_RELEASE);
1285
1286   g_slist_free (entries);
1287
1288   return handled;
1289 }