1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * GtkBindingSet: Keybinding manager for GtkObjects.
5 * Copyright (C) 1998 Tim Janik
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.
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.
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.
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/.
33 #include "gtkbindings.h"
34 #include "gtksignal.h"
35 #include "gtkwidget.h"
40 #define BINDING_MOD_MASK() (gtk_accelerator_get_default_mod_mask () | GDK_RELEASE_MASK)
43 /* --- structures --- */
51 /* --- variables --- */
52 static GHashTable *binding_entry_hash_table = NULL;
53 static GSList *binding_set_list = NULL;
54 static const gchar *key_class_binding_set = "gtk-class-binding-set";
55 static GQuark key_id_class_binding_set = 0;
58 /* --- functions --- */
59 static GtkBindingSignal*
60 binding_signal_new (const gchar *signal_name,
63 GtkBindingSignal *signal;
65 signal = g_new (GtkBindingSignal, 1);
67 signal->signal_name = g_strdup (signal_name);
68 signal->n_args = n_args;
69 signal->args = g_new0 (GtkBindingArg, n_args);
75 binding_signal_free (GtkBindingSignal *sig)
79 for (i = 0; i < sig->n_args; i++)
81 if (GTK_FUNDAMENTAL_TYPE (sig->args[i].arg_type) == GTK_TYPE_STRING)
82 g_free (sig->args[i].d.string_data);
85 g_free (sig->signal_name);
90 binding_entry_hash (gconstpointer key)
92 register const GtkBindingEntry *e = key;
102 binding_entries_compare (gconstpointer a,
105 register const GtkBindingEntry *ea = a;
106 register const GtkBindingEntry *eb = b;
108 return (ea->keyval == eb->keyval && ea->modifiers == eb->modifiers);
111 static GtkBindingEntry*
112 binding_entry_new (GtkBindingSet *binding_set,
116 GtkBindingEntry *entry;
118 if (!binding_entry_hash_table)
119 binding_entry_hash_table = g_hash_table_new (binding_entry_hash, binding_entries_compare);
121 entry = g_new (GtkBindingEntry, 1);
122 entry->keyval = keyval;
123 entry->modifiers = modifiers;
124 entry->binding_set = binding_set,
125 entry->destroyed = FALSE;
126 entry->in_emission = FALSE;
127 entry->signals = NULL;
129 entry->set_next = binding_set->entries;
130 binding_set->entries = entry;
132 entry->hash_next = g_hash_table_lookup (binding_entry_hash_table, entry);
133 if (entry->hash_next)
134 g_hash_table_remove (binding_entry_hash_table, entry->hash_next);
135 g_hash_table_insert (binding_entry_hash_table, entry, entry);
141 binding_entry_free (GtkBindingEntry *entry)
143 GtkBindingSignal *sig;
145 g_assert (entry->set_next == NULL &&
146 entry->hash_next == NULL &&
147 entry->in_emission == FALSE &&
148 entry->destroyed == TRUE);
150 entry->destroyed = FALSE;
152 sig = entry->signals;
155 GtkBindingSignal *prev;
159 binding_signal_free (prev);
165 binding_entry_destroy (GtkBindingEntry *entry)
167 GtkBindingEntry *o_entry;
168 register GtkBindingEntry *tmp;
169 GtkBindingEntry *begin;
170 register GtkBindingEntry *last;
172 /* unlink from binding set
175 tmp = entry->binding_set->entries;
181 last->set_next = entry->set_next;
183 entry->binding_set->entries = entry->set_next;
187 tmp = last->set_next;
189 entry->set_next = NULL;
191 o_entry = g_hash_table_lookup (binding_entry_hash_table, entry);
200 last->hash_next = entry->hash_next;
202 begin = entry->hash_next;
206 tmp = last->hash_next;
208 entry->hash_next = NULL;
211 g_hash_table_remove (binding_entry_hash_table, entry);
212 else if (begin != o_entry)
214 g_hash_table_remove (binding_entry_hash_table, entry);
215 g_hash_table_insert (binding_entry_hash_table, begin, begin);
218 entry->destroyed = TRUE;
220 if (!entry->in_emission)
221 binding_entry_free (entry);
224 static GtkBindingEntry*
225 binding_ht_lookup_list (guint keyval,
228 GtkBindingEntry lookup_entry = { 0 };
230 if (!binding_entry_hash_table)
233 lookup_entry.keyval = keyval;
234 lookup_entry.modifiers = modifiers;
236 return g_hash_table_lookup (binding_entry_hash_table, &lookup_entry);
239 static GtkBindingEntry*
240 binding_ht_lookup_entry (GtkBindingSet *set,
244 GtkBindingEntry lookup_entry = { 0 };
245 GtkBindingEntry *entry;
247 if (!binding_entry_hash_table)
250 lookup_entry.keyval = keyval;
251 lookup_entry.modifiers = modifiers;
253 entry = g_hash_table_lookup (binding_entry_hash_table, &lookup_entry);
254 for (; entry; entry = entry->hash_next)
255 if (entry->binding_set == set)
262 binding_compose_params (GtkObject *object,
272 params = g_new0 (GValue, query->n_params + 1);
275 /* The instance we emit on is the first object in the array
277 g_value_init (params, G_TYPE_OBJECT);
278 g_value_set_object (params, G_OBJECT (object));
281 types = query->param_types;
283 for (i = 1; i < query->n_params + 1 && valid; i++)
285 GValue tmp_value = { 0, };
287 g_value_init (params, *types);
289 switch (G_TYPE_FUNDAMENTAL (args->arg_type))
292 g_value_init (&tmp_value, G_TYPE_DOUBLE);
293 g_value_set_double (&tmp_value, args->d.double_data);
296 g_value_init (&tmp_value, G_TYPE_LONG);
297 g_value_set_long (&tmp_value, args->d.long_data);
300 /* gtk_rc_parse_flags/enum() has fancier parsing for this; we can't call
301 * that since we don't have a GParamSpec, so just do something simple
303 if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_ENUM)
305 GEnumClass *class = G_ENUM_CLASS (g_type_class_ref (*types));
309 if (args->arg_type == GTK_TYPE_IDENTIFIER)
311 GEnumValue *enum_value = NULL;
312 enum_value = g_enum_get_value_by_name (class, args->d.string_data);
314 enum_value = g_enum_get_value_by_nick (class, args->d.string_data);
317 g_value_set_enum (&tmp_value, enum_value->value);
322 g_type_class_unref (class);
324 /* This is just a hack for compatibility with GTK+-1.2 where a string
325 * could be used for a single flag value / without the support for multiple
326 * values in gtk_rc_parse_flags(), this isn't very useful.
328 else if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_FLAGS)
330 GFlagsClass *class = G_FLAGS_CLASS (g_type_class_ref (*types));
334 if (args->arg_type == GTK_TYPE_IDENTIFIER)
336 GFlagsValue *flags_value = NULL;
337 flags_value = g_flags_get_value_by_name (class, args->d.string_data);
339 flags_value = g_flags_get_value_by_nick (class, args->d.string_data);
342 g_value_set_flags (&tmp_value, flags_value->value);
347 g_type_class_unref (class);
351 g_value_init (&tmp_value, G_TYPE_STRING);
352 g_value_set_static_string (params, args->d.string_data);
360 if (valid && !g_value_transform (&tmp_value, params))
363 g_value_unset (&tmp_value);
374 for (j = 0; j < i; j++)
375 g_value_unset (&(*params_p)[j]);
385 gtk_binding_entry_activate (GtkBindingEntry *entry,
388 GtkBindingSignal *sig;
389 gboolean old_emission;
390 gboolean handled = FALSE;
393 old_emission = entry->in_emission;
394 entry->in_emission = TRUE;
396 g_object_ref (object);
398 for (sig = entry->signals; sig; sig = sig->next)
402 GValue *params = NULL;
403 GValue return_val = { 0, };
404 gchar *accelerator = NULL;
406 signal_id = g_signal_lookup (sig->signal_name, G_OBJECT_TYPE (object));
409 accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
410 g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
411 "could not find signal \"%s\" in the `%s' class ancestry",
412 entry->binding_set->set_name,
415 g_type_name (G_OBJECT_TYPE (object)));
416 g_free (accelerator);
420 g_signal_query (signal_id, &query);
421 if (query.n_params != sig->n_args ||
422 (query.return_type != G_TYPE_NONE && query.return_type != G_TYPE_BOOLEAN) ||
423 !binding_compose_params (object, sig->args, &query, ¶ms))
425 accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
426 g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
427 "signature mismatch for signal \"%s\" in the `%s' class ancestry",
428 entry->binding_set->set_name,
431 g_type_name (G_OBJECT_TYPE (object)));
433 else if (!(query.signal_flags & GTK_RUN_ACTION))
435 accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
436 g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
437 "signal \"%s\" in the `%s' class ancestry cannot be used for action emissions",
438 entry->binding_set->set_name,
441 g_type_name (G_OBJECT_TYPE (object)));
443 g_free (accelerator);
447 if (query.return_type == G_TYPE_BOOLEAN)
448 g_value_init (&return_val, G_TYPE_BOOLEAN);
450 g_signal_emitv (params, signal_id, 0, &return_val);
452 if (query.return_type == G_TYPE_BOOLEAN)
454 if (g_value_get_boolean (&return_val))
456 g_value_unset (&return_val);
461 for (i = 0; i < query.n_params + 1; i++)
462 g_value_unset (¶ms[i]);
465 if (entry->destroyed)
469 g_object_unref (object);
471 entry->in_emission = old_emission;
472 if (entry->destroyed && !entry->in_emission)
473 binding_entry_free (entry);
479 gtk_binding_set_new (const gchar *set_name)
481 GtkBindingSet *binding_set;
483 g_return_val_if_fail (set_name != NULL, NULL);
485 binding_set = g_new (GtkBindingSet, 1);
486 binding_set->set_name = g_strdup (set_name);
487 binding_set->widget_path_pspecs = NULL;
488 binding_set->widget_class_pspecs = NULL;
489 binding_set->class_branch_pspecs = NULL;
490 binding_set->entries = NULL;
491 binding_set->current = NULL;
493 binding_set_list = g_slist_prepend (binding_set_list, binding_set);
499 gtk_binding_set_by_class (gpointer object_class)
501 GtkObjectClass *class = object_class;
502 GtkBindingSet* binding_set;
504 g_return_val_if_fail (GTK_IS_OBJECT_CLASS (class), NULL);
506 if (!key_id_class_binding_set)
507 key_id_class_binding_set = g_quark_from_static_string (key_class_binding_set);
509 binding_set = g_dataset_id_get_data (class, key_id_class_binding_set);
514 binding_set = gtk_binding_set_new (gtk_type_name (GTK_CLASS_TYPE (class)));
515 gtk_binding_set_add_path (binding_set,
517 gtk_type_name (GTK_CLASS_TYPE (class)),
519 g_dataset_id_set_data (class, key_id_class_binding_set, binding_set);
525 gtk_binding_set_find (const gchar *set_name)
529 g_return_val_if_fail (set_name != NULL, NULL);
531 for (slist = binding_set_list; slist; slist = slist->next)
533 GtkBindingSet *binding_set;
535 binding_set = slist->data;
536 if (g_str_equal (binding_set->set_name, (gpointer) set_name))
543 gtk_binding_set_activate (GtkBindingSet *binding_set,
548 GtkBindingEntry *entry;
550 g_return_val_if_fail (binding_set != NULL, FALSE);
551 g_return_val_if_fail (object != NULL, FALSE);
552 g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
554 keyval = gdk_keyval_to_lower (keyval);
555 modifiers = modifiers & BINDING_MOD_MASK ();
557 entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
559 return gtk_binding_entry_activate (entry, object);
565 gtk_binding_entry_clear (GtkBindingSet *binding_set,
569 GtkBindingEntry *entry;
571 g_return_if_fail (binding_set != NULL);
573 keyval = gdk_keyval_to_lower (keyval);
574 modifiers = modifiers & BINDING_MOD_MASK ();
576 entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
578 binding_entry_destroy (entry);
580 entry = binding_entry_new (binding_set, keyval, modifiers);
584 gtk_binding_entry_remove (GtkBindingSet *binding_set,
588 GtkBindingEntry *entry;
590 g_return_if_fail (binding_set != NULL);
592 keyval = gdk_keyval_to_lower (keyval);
593 modifiers = modifiers & BINDING_MOD_MASK ();
595 entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
597 binding_entry_destroy (entry);
601 gtk_binding_entry_add_signall (GtkBindingSet *binding_set,
604 const gchar *signal_name,
605 GSList *binding_args)
607 GtkBindingEntry *entry;
608 GtkBindingSignal *signal, **signal_p;
613 g_return_if_fail (binding_set != NULL);
614 g_return_if_fail (signal_name != NULL);
616 keyval = gdk_keyval_to_lower (keyval);
617 modifiers = modifiers & BINDING_MOD_MASK ();
619 signal = binding_signal_new (signal_name, g_slist_length (binding_args));
622 for (slist = binding_args; slist; slist = slist->next)
624 GtkBindingArg *tmp_arg;
626 tmp_arg = slist->data;
629 g_warning ("gtk_binding_entry_add_signall(): arg[%u] is `NULL'", n);
630 binding_signal_free (signal);
633 switch (GTK_FUNDAMENTAL_TYPE (tmp_arg->arg_type))
636 arg->arg_type = GTK_TYPE_LONG;
637 arg->d.long_data = tmp_arg->d.long_data;
639 case GTK_TYPE_DOUBLE:
640 arg->arg_type = GTK_TYPE_DOUBLE;
641 arg->d.double_data = tmp_arg->d.double_data;
643 case GTK_TYPE_STRING:
644 if (tmp_arg->arg_type != GTK_TYPE_IDENTIFIER)
645 arg->arg_type = GTK_TYPE_STRING;
647 arg->arg_type = GTK_TYPE_IDENTIFIER;
648 arg->d.string_data = g_strdup (tmp_arg->d.string_data);
649 if (!arg->d.string_data)
651 g_warning ("gtk_binding_entry_add_signall(): value of `string' arg[%u] is `NULL'", n);
652 binding_signal_free (signal);
657 g_warning ("gtk_binding_entry_add_signall(): unsupported type `%s' for arg[%u]",
658 gtk_type_name (arg->arg_type), n);
659 binding_signal_free (signal);
666 entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
669 gtk_binding_entry_add (binding_set, keyval, modifiers);
670 entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
672 signal_p = &entry->signals;
674 signal_p = &(*signal_p)->next;
679 gtk_binding_entry_add_signal (GtkBindingSet *binding_set,
682 const gchar *signal_name,
686 GSList *slist, *free_slist;
690 g_return_if_fail (binding_set != NULL);
691 g_return_if_fail (signal_name != NULL);
693 keyval = gdk_keyval_to_lower (keyval);
694 modifiers = modifiers & BINDING_MOD_MASK ();
696 va_start (args, n_args);
698 for (i = 0; i < n_args; i++)
702 arg = g_new0 (GtkBindingArg, 1);
703 slist = g_slist_prepend (slist, arg);
705 arg->arg_type = va_arg (args, GtkType);
706 switch (GTK_FUNDAMENTAL_TYPE (arg->arg_type))
708 /* for elaborated commenting about var args collection, take a look
709 * at gtk_arg_collect_value() in gtkargcollector.c
718 arg->arg_type = GTK_TYPE_LONG;
719 arg->d.long_data = va_arg (args, gint);
723 arg->arg_type = GTK_TYPE_LONG;
724 arg->d.long_data = va_arg (args, glong);
727 case GTK_TYPE_DOUBLE:
728 arg->arg_type = GTK_TYPE_DOUBLE;
729 arg->d.double_data = va_arg (args, gdouble);
731 case GTK_TYPE_STRING:
732 if (arg->arg_type != GTK_TYPE_IDENTIFIER)
733 arg->arg_type = GTK_TYPE_STRING;
734 arg->d.string_data = va_arg (args, gchar*);
735 if (!arg->d.string_data)
737 g_warning ("gtk_binding_entry_add_signal(): type `%s' arg[%u] is `NULL'",
738 gtk_type_name (arg->arg_type),
744 g_warning ("gtk_binding_entry_add_signal(): unsupported type `%s' for arg[%u]",
745 gtk_type_name (arg->arg_type), i);
752 if (i == n_args || i == 0)
754 slist = g_slist_reverse (slist);
755 gtk_binding_entry_add_signall (binding_set, keyval, modifiers, signal_name, slist);
761 g_free (slist->data);
764 g_slist_free (free_slist);
768 gtk_binding_set_add_path (GtkBindingSet *binding_set,
769 GtkPathType path_type,
770 const gchar *path_pattern,
771 GtkPathPriorityType priority)
774 GSList **slist_p, *slist;
775 static guint seq_id = 0;
777 g_return_if_fail (binding_set != NULL);
778 g_return_if_fail (path_pattern != NULL);
779 g_return_if_fail (priority <= GTK_PATH_PRIO_MASK);
781 priority &= GTK_PATH_PRIO_MASK;
785 case GTK_PATH_WIDGET:
786 slist_p = &binding_set->widget_path_pspecs;
788 case GTK_PATH_WIDGET_CLASS:
789 slist_p = &binding_set->widget_class_pspecs;
792 slist_p = &binding_set->class_branch_pspecs;
795 g_assert_not_reached ();
800 pspec = g_new (PatternSpec, 1);
801 pspec->pspec = g_pattern_spec_new (path_pattern);
802 pspec->seq_id = priority << 28;
803 pspec->user_data = binding_set;
808 PatternSpec *tmp_pspec;
810 tmp_pspec = slist->data;
813 if (g_pattern_spec_equal (tmp_pspec->pspec, pspec->pspec))
815 GtkPathPriorityType lprio = tmp_pspec->seq_id >> 28;
817 g_pattern_spec_free (pspec->pspec);
820 if (lprio < priority)
822 tmp_pspec->seq_id &= 0x0fffffff;
823 tmp_pspec->seq_id |= priority << 28;
830 pspec->seq_id |= seq_id++ & 0x0fffffff;
831 *slist_p = g_slist_prepend (*slist_p, pspec);
835 static inline gboolean
836 binding_match_activate (GSList *pspec_list,
840 const gchar *path_reversed)
844 for (slist = pspec_list; slist; slist = slist->next)
849 if (g_pattern_match (pspec->pspec, path_length, path, path_reversed))
851 GtkBindingSet *binding_set;
853 binding_set = pspec->user_data;
855 if (gtk_binding_entry_activate (binding_set->current, object))
864 gtk_binding_pattern_compare (gconstpointer new_pattern,
865 gconstpointer existing_pattern)
867 register const PatternSpec *np = new_pattern;
868 register const PatternSpec *ep = existing_pattern;
870 /* walk the list as long as the existing patterns have
874 return np->seq_id < ep->seq_id;
877 static inline GSList*
878 gtk_binding_entries_sort_patterns (GtkBindingEntry *entries,
886 register GtkBindingSet *binding_set;
887 GSList *slist = NULL;
889 binding_set = entries->binding_set;
890 binding_set->current = entries;
894 case GTK_PATH_WIDGET:
895 slist = binding_set->widget_path_pspecs;
897 case GTK_PATH_WIDGET_CLASS:
898 slist = binding_set->widget_class_pspecs;
901 slist = binding_set->class_branch_pspecs;
905 for (; slist; slist = slist->next)
910 patterns = g_slist_insert_sorted (patterns, pspec, gtk_binding_pattern_compare);
913 entries = entries->hash_next;
921 gtk_bindings_activate (GtkObject *object,
925 GtkBindingEntry *entries;
927 gboolean handled = FALSE;
929 g_return_val_if_fail (object != NULL, FALSE);
930 g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
932 if (!GTK_IS_WIDGET (object))
935 widget = GTK_WIDGET (object);
937 keyval = gdk_keyval_to_lower (keyval);
938 modifiers = modifiers & BINDING_MOD_MASK ();
940 entries = binding_ht_lookup_list (keyval, modifiers);
948 gchar *path, *path_reversed;
951 gtk_widget_path (widget, &path_length, &path, &path_reversed);
952 patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET);
953 handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
954 g_slist_free (patterns);
956 g_free (path_reversed);
962 gchar *path, *path_reversed;
965 gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
966 patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET_CLASS);
967 handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
968 g_slist_free (patterns);
970 g_free (path_reversed);
978 patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_CLASS);
979 class_type = GTK_OBJECT_TYPE (object);
980 while (class_type && !handled)
984 gchar *path_reversed;
986 path = gtk_type_name (class_type);
987 path_reversed = g_strdup (path);
988 g_strreverse (path_reversed);
989 path_length = strlen (path);
990 handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
991 g_free (path_reversed);
993 class_type = gtk_type_parent (class_type);
995 g_slist_free (patterns);
1002 gtk_binding_parse_signal (GScanner *scanner,
1003 GtkBindingSet *binding_set,
1008 guint expected_token = 0;
1014 gboolean seen_comma;
1016 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1018 g_scanner_get_next_token (scanner);
1019 if (scanner->token != G_TOKEN_STRING)
1020 return G_TOKEN_STRING;
1021 g_scanner_peek_next_token (scanner);
1022 if (scanner->next_token != '(')
1024 g_scanner_get_next_token (scanner);
1027 signal = g_strdup (scanner->value.v_string);
1028 g_scanner_get_next_token (scanner);
1035 scanner->config->scan_symbols = FALSE;
1039 expected_token = G_TOKEN_INT;
1041 expected_token = ')';
1042 g_scanner_get_next_token (scanner);
1043 switch (scanner->token)
1051 arg = g_new (GtkBindingArg, 1);
1052 arg->arg_type = GTK_TYPE_DOUBLE;
1053 arg->d.double_data = scanner->value.v_float;
1056 arg->d.double_data = - arg->d.double_data;
1059 args = g_slist_prepend (args, arg);
1068 arg = g_new (GtkBindingArg, 1);
1069 arg->arg_type = GTK_TYPE_LONG;
1070 arg->d.long_data = scanner->value.v_int;
1073 arg->d.long_data = - arg->d.long_data;
1076 args = g_slist_prepend (args, arg);
1081 case G_TOKEN_STRING:
1082 if (need_arg && !negate)
1085 arg = g_new (GtkBindingArg, 1);
1086 arg->arg_type = GTK_TYPE_STRING;
1087 arg->d.string_data = g_strdup (scanner->value.v_string);
1088 args = g_slist_prepend (args, arg);
1093 case G_TOKEN_IDENTIFIER:
1094 if (need_arg && !negate)
1097 arg = g_new (GtkBindingArg, 1);
1098 arg->arg_type = GTK_TYPE_IDENTIFIER;
1099 arg->d.string_data = g_strdup (scanner->value.v_identifier);
1100 args = g_slist_prepend (args, arg);
1110 expected_token = G_TOKEN_INT;
1124 if (!(need_arg && seen_comma) && !negate)
1126 args = g_slist_reverse (args);
1127 gtk_binding_entry_add_signall (binding_set,
1132 expected_token = G_TOKEN_NONE;
1142 scanner->config->scan_symbols = TRUE;
1144 for (slist = args; slist; slist = slist->next)
1149 if (GTK_FUNDAMENTAL_TYPE (arg->arg_type) == GTK_TYPE_STRING)
1150 g_free (arg->d.string_data);
1153 g_slist_free (args);
1156 return expected_token;
1160 gtk_binding_parse_bind (GScanner *scanner,
1161 GtkBindingSet *binding_set)
1164 guint modifiers = 0;
1166 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1168 g_scanner_get_next_token (scanner);
1169 if (scanner->token != GTK_RC_TOKEN_BIND)
1170 return GTK_RC_TOKEN_BIND;
1171 g_scanner_get_next_token (scanner);
1172 if (scanner->token != G_TOKEN_STRING)
1173 return G_TOKEN_STRING;
1174 gtk_accelerator_parse (scanner->value.v_string, &keyval, &modifiers);
1175 modifiers &= BINDING_MOD_MASK ();
1177 return G_TOKEN_STRING;
1179 g_scanner_get_next_token (scanner);
1180 if (scanner->token != '{')
1183 gtk_binding_entry_clear (binding_set, keyval, modifiers);
1185 g_scanner_peek_next_token (scanner);
1186 while (scanner->next_token != '}')
1188 switch (scanner->next_token)
1190 guint expected_token;
1192 case G_TOKEN_STRING:
1193 expected_token = gtk_binding_parse_signal (scanner,
1197 if (expected_token != G_TOKEN_NONE)
1198 return expected_token;
1201 g_scanner_get_next_token (scanner);
1204 g_scanner_peek_next_token (scanner);
1206 g_scanner_get_next_token (scanner);
1208 return G_TOKEN_NONE;
1212 gtk_binding_parse_binding (GScanner *scanner)
1215 GtkBindingSet *binding_set;
1217 g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
1219 g_scanner_get_next_token (scanner);
1220 if (scanner->token != GTK_RC_TOKEN_BINDING)
1221 return GTK_RC_TOKEN_BINDING;
1222 g_scanner_get_next_token (scanner);
1223 if (scanner->token != G_TOKEN_STRING)
1224 return G_TOKEN_STRING;
1225 name = g_strdup (scanner->value.v_string);
1227 g_scanner_get_next_token (scanner);
1228 if (scanner->token != '{')
1231 return G_TOKEN_STRING;
1234 binding_set = gtk_binding_set_find (name);
1236 binding_set = gtk_binding_set_new (name);
1239 g_scanner_peek_next_token (scanner);
1240 while (scanner->next_token != '}')
1242 switch (scanner->next_token)
1244 guint expected_token;
1246 case GTK_RC_TOKEN_BIND:
1247 expected_token = gtk_binding_parse_bind (scanner, binding_set);
1248 if (expected_token != G_TOKEN_NONE)
1249 return expected_token;
1252 g_scanner_get_next_token (scanner);
1255 g_scanner_peek_next_token (scanner);
1257 g_scanner_get_next_token (scanner);
1259 return G_TOKEN_NONE;