1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * GtkAccelGroup: Accelerator 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/.
32 #include "gtkaccelgroup.h"
33 #include "gdk/gdkkeysyms.h"
34 #include "gtksignal.h"
35 #include "gtkwidget.h"
39 typedef void (*GtkSignalAddAccelerator) (GtkObject *object,
40 guint accel_signal_id,
41 GtkAccelGroup *accel_group,
43 GdkModifierType accel_mods,
44 GtkAccelFlags accel_flags,
46 typedef void (*GtkSignalRemoveAccelerator) (GtkObject *object,
47 GtkAccelGroup *accel_group,
49 GdkModifierType accel_mods,
52 /* --- variables --- */
53 static GtkAccelGroup *default_accel_group = NULL;
54 static guint default_accel_mod_mask = (GDK_SHIFT_MASK |
57 static const gchar *accel_groups_key = "gtk-accel-groups";
58 static guint accel_groups_key_id = 0;
59 static const gchar *accel_entries_key = "gtk-accel-entries";
60 static guint accel_entries_key_id = 0;
61 static GHashTable *accel_entry_hash_table = NULL;
62 static GMemChunk *accel_tables_mem_chunk = NULL;
63 static GMemChunk *accel_entries_mem_chunk = NULL;
66 /* --- functions --- */
68 gtk_accel_entries_equal (gconstpointer a,
71 const GtkAccelEntry *e1;
72 const GtkAccelEntry *e2;
77 return ((e1->accel_group == e2->accel_group) &&
78 (e1->accelerator_key == e2->accelerator_key) &&
79 (e1->accelerator_mods == e2->accelerator_mods));
83 gtk_accel_entries_hash (gconstpointer a)
85 const GtkAccelEntry *e;
90 h = (gulong) e->accel_group;
91 h ^= e->accelerator_key << 16;
92 h ^= e->accelerator_key >> 16;
93 h ^= e->accelerator_mods;
99 gtk_accel_group_new (void)
101 GtkAccelGroup *accel_group;
103 if (!accel_groups_key_id)
105 accel_groups_key_id = g_quark_from_static_string (accel_groups_key);
106 accel_entries_key_id = g_quark_from_static_string (accel_entries_key);
108 accel_entry_hash_table = g_hash_table_new (gtk_accel_entries_hash,
109 gtk_accel_entries_equal);
111 accel_tables_mem_chunk = g_mem_chunk_create (GtkAccelGroup, 8, G_ALLOC_AND_FREE);
112 accel_entries_mem_chunk = g_mem_chunk_create (GtkAccelEntry, 64, G_ALLOC_AND_FREE);
115 accel_group = g_chunk_new (GtkAccelGroup, accel_tables_mem_chunk);
117 accel_group->ref_count = 1;
118 accel_group->lock_count = 0;
119 accel_group->modifier_mask = gtk_accelerator_get_default_mod_mask ();
120 accel_group->attach_objects = NULL;
126 gtk_accel_group_get_default (void)
128 if (!default_accel_group)
129 default_accel_group = gtk_accel_group_new ();
131 return default_accel_group;
135 gtk_accel_group_ref (GtkAccelGroup *accel_group)
137 g_return_val_if_fail (accel_group != NULL, NULL);
139 accel_group->ref_count += 1;
145 gtk_accel_group_unref (GtkAccelGroup *accel_group)
147 g_return_if_fail (accel_group != NULL);
148 g_return_if_fail (accel_group->ref_count > 0);
150 accel_group->ref_count -= 1;
151 if (accel_group->ref_count == 0)
153 g_return_if_fail (accel_group != default_accel_group);
154 g_return_if_fail (accel_group->attach_objects == NULL);
156 g_chunk_free (accel_group, accel_tables_mem_chunk);
161 gtk_accel_group_object_destroy (GtkObject *object)
163 GSList *free_list, *slist;
165 free_list = gtk_object_get_data_by_id (object, accel_groups_key_id);
166 gtk_object_set_data_by_id (object, accel_groups_key_id, NULL);
168 for (slist = free_list; slist; slist = slist->next)
170 GtkAccelGroup *accel_group;
172 accel_group = slist->data;
173 accel_group->attach_objects = g_slist_remove (accel_group->attach_objects, object);
174 gtk_accel_group_unref (accel_group);
176 g_slist_free (free_list);
180 gtk_accel_group_attach (GtkAccelGroup *accel_group,
185 g_return_if_fail (accel_group != NULL);
186 g_return_if_fail (object != NULL);
187 g_return_if_fail (GTK_IS_OBJECT (object));
188 g_return_if_fail (g_slist_find (accel_group->attach_objects, object) == NULL);
190 accel_group->attach_objects = g_slist_prepend (accel_group->attach_objects, object);
191 gtk_accel_group_ref (accel_group);
192 slist = gtk_object_get_data_by_id (object, accel_groups_key_id);
194 gtk_signal_connect (object,
196 GTK_SIGNAL_FUNC (gtk_accel_group_object_destroy),
198 slist = g_slist_prepend (slist, accel_group);
199 gtk_object_set_data_by_id (object, accel_groups_key_id, slist);
203 gtk_accel_group_detach (GtkAccelGroup *accel_group,
208 g_return_if_fail (accel_group != NULL);
209 g_return_if_fail (object != NULL);
210 g_return_if_fail (GTK_IS_OBJECT (object));
211 g_return_if_fail (g_slist_find (accel_group->attach_objects, object) != NULL);
213 accel_group->attach_objects = g_slist_remove (accel_group->attach_objects, object);
214 gtk_accel_group_unref (accel_group);
215 slist = gtk_object_get_data_by_id (object, accel_groups_key_id);
216 slist = g_slist_remove (slist, accel_group);
218 gtk_signal_disconnect_by_func (object,
219 GTK_SIGNAL_FUNC (gtk_accel_group_object_destroy),
221 gtk_object_set_data_by_id (object, accel_groups_key_id, slist);
225 gtk_accel_group_lock (GtkAccelGroup *accel_group)
227 g_return_if_fail (accel_group != NULL);
229 accel_group->lock_count += 1;
233 gtk_accel_group_unlock (GtkAccelGroup *accel_group)
235 g_return_if_fail (accel_group != NULL);
237 if (accel_group->lock_count)
238 accel_group->lock_count -= 1;
241 static GtkAccelEntry*
242 gtk_accel_group_lookup (GtkAccelGroup *accel_group,
244 GdkModifierType accel_mods)
246 GtkAccelEntry key_entry = { 0 };
248 key_entry.accel_group = accel_group;
249 key_entry.accelerator_key = gdk_keyval_to_lower (accel_key);
250 key_entry.accelerator_mods = accel_mods & accel_group->modifier_mask;
252 return g_hash_table_lookup (accel_entry_hash_table, &key_entry);
256 gtk_accel_group_activate (GtkAccelGroup *accel_group,
258 GdkModifierType accel_mods)
260 GtkAccelEntry *entry;
262 g_return_val_if_fail (accel_group != NULL, FALSE);
264 entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
265 if (entry && entry->signal_id &&
266 (!GTK_IS_WIDGET (entry->object) || GTK_WIDGET_IS_SENSITIVE (entry->object)))
268 gtk_signal_emit (entry->object, entry->signal_id);
275 gtk_accel_groups_activate (GtkObject *object,
277 GdkModifierType accel_mods)
279 g_return_val_if_fail (object != NULL, FALSE);
280 g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
282 if (gtk_accelerator_valid (accel_key, accel_mods))
286 for (slist = gtk_accel_groups_from_object (object); slist; slist = slist->next)
287 if (gtk_accel_group_activate (slist->data, accel_key, accel_mods))
289 return gtk_accel_group_activate (gtk_accel_group_get_default (), accel_key, accel_mods);
296 gtk_accel_group_lock_entry (GtkAccelGroup *accel_group,
298 GdkModifierType accel_mods)
300 GtkAccelEntry *entry;
302 g_return_if_fail (accel_group != NULL);
304 entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
306 entry->accel_flags |= GTK_ACCEL_LOCKED;
310 gtk_accel_group_unlock_entry (GtkAccelGroup *accel_group,
312 GdkModifierType accel_mods)
314 GtkAccelEntry *entry;
316 g_return_if_fail (accel_group != NULL);
318 entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
320 entry->accel_flags &= ~GTK_ACCEL_LOCKED;
324 gtk_accel_group_get_entry (GtkAccelGroup *accel_group,
326 GdkModifierType accel_mods)
328 g_return_val_if_fail (accel_group != NULL, 0);
330 return gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
334 gtk_accel_group_add (GtkAccelGroup *accel_group,
336 GdkModifierType accel_mods,
337 GtkAccelFlags accel_flags,
339 const gchar *accel_signal)
341 guint accel_signal_id = 0;
342 guint add_accelerator_signal_id = 0;
343 guint remove_accelerator_signal_id = 0;
348 GSList *attach_objects;
349 GtkAccelEntry *entry;
351 g_return_if_fail (accel_group != NULL);
352 g_return_if_fail (object != NULL);
353 g_return_if_fail (GTK_IS_OBJECT (object));
354 g_return_if_fail (accel_signal != NULL);
356 /* check for required signals in the objects branch
358 signal = (gchar*) accel_signal;
359 accel_signal_id = gtk_signal_lookup (signal, GTK_OBJECT_TYPE (object));
362 signal = "add-accelerator";
363 add_accelerator_signal_id = gtk_signal_lookup (signal, GTK_OBJECT_TYPE (object));
365 if (add_accelerator_signal_id)
367 signal = "remove-accelerator";
368 remove_accelerator_signal_id = gtk_signal_lookup (signal, GTK_OBJECT_TYPE (object));
370 if (!accel_signal_id ||
371 !add_accelerator_signal_id ||
372 !remove_accelerator_signal_id)
374 g_warning ("gtk_accel_group_add(): could not find signal \"%s\""
375 "in the `%s' class ancestry",
377 gtk_type_name (GTK_OBJECT_TYPE (object)));
380 g_signal_query (accel_signal_id, &query);
381 if (!query.signal_id || query.n_params > 0)
383 g_warning ("gtk_accel_group_add(): signal \"%s\" in the `%s' class ancestry"
384 "cannot be used as accelerator signal",
386 gtk_type_name (GTK_OBJECT_TYPE (object)));
391 /* prematurely abort if the group/entry is already locked
393 if (accel_group->lock_count > 0)
395 entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
396 if (entry && entry->accel_flags & GTK_ACCEL_LOCKED)
399 /* make sure our structures stay alive
401 gtk_accel_group_ref (accel_group);
402 gtk_object_ref (object);
404 /* remove an existing entry
407 gtk_signal_emit (entry->object, remove_accelerator_signal_id,
409 gdk_keyval_to_lower (accel_key),
410 accel_mods & accel_group->modifier_mask);
412 /* abort if the entry still exists
414 entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
417 gtk_accel_group_unref (accel_group);
418 gtk_object_unref (object);
423 /* collect accel groups and remove existing entries
425 attach_objects = accel_group->attach_objects;
427 for (attach_objects = accel_group->attach_objects; attach_objects; attach_objects = attach_objects->next)
431 tmp_groups = gtk_object_get_data_by_id (attach_objects->data, accel_groups_key_id);
434 groups = g_slist_prepend (groups, tmp_groups->data);
435 gtk_accel_group_ref (tmp_groups->data);
436 tmp_groups = tmp_groups->next;
439 for (slist = groups; slist; slist = slist->next)
441 GtkAccelGroup *tmp_group;
443 tmp_group = slist->data;
445 /* we only remove the accelerator if neccessary
447 if (tmp_group->lock_count == 0)
449 entry = gtk_accel_group_lookup (tmp_group, accel_key, accel_mods);
450 if (entry && !(entry->accel_flags & GTK_ACCEL_LOCKED))
451 gtk_signal_emit (entry->object, remove_accelerator_signal_id,
453 gdk_keyval_to_lower (accel_key),
454 accel_mods & tmp_group->modifier_mask);
456 gtk_accel_group_unref (tmp_group);
458 g_slist_free (groups);
460 /* now install the new accelerator
462 entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
464 gtk_signal_emit (object, add_accelerator_signal_id,
467 gdk_keyval_to_lower (accel_key),
468 accel_mods & accel_group->modifier_mask,
469 accel_flags & GTK_ACCEL_MASK);
471 /* and release the structures again
473 gtk_accel_group_unref (accel_group);
474 gtk_object_unref (object);
478 gtk_accel_group_delete_entries (GtkObject *object)
480 GSList *free_slist, *slist;
482 gtk_signal_disconnect_by_func (object,
483 GTK_SIGNAL_FUNC (gtk_accel_group_delete_entries),
486 /* we remove all entries of this object the hard
487 * way (i.e. without signal emission).
489 free_slist = gtk_object_get_data_by_id (object, accel_entries_key_id);
490 gtk_object_set_data_by_id (object, accel_entries_key_id, NULL);
491 for (slist = free_slist; slist; slist = slist->next)
493 GtkAccelEntry *entry;
497 g_hash_table_remove (accel_entry_hash_table, entry);
498 gtk_accel_group_unref (entry->accel_group);
499 g_chunk_free (entry, accel_entries_mem_chunk);
501 g_slist_free (free_slist);
505 gtk_accel_group_handle_add (GtkObject *object,
506 guint accel_signal_id,
507 GtkAccelGroup *accel_group,
509 GdkModifierType accel_mods,
510 GtkAccelFlags accel_flags)
512 GtkAccelEntry *entry;
514 g_return_if_fail (object != NULL);
515 g_return_if_fail (GTK_IS_OBJECT (object));
516 g_return_if_fail (accel_group != NULL);
517 g_return_if_fail (accel_signal_id > 0);
519 if (!gtk_accelerator_valid (accel_key, accel_mods))
522 entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
527 gtk_accel_group_ref (accel_group);
529 entry = g_chunk_new (GtkAccelEntry, accel_entries_mem_chunk);
530 entry->accel_group = accel_group;
531 entry->accelerator_key = gdk_keyval_to_lower (accel_key);
532 entry->accelerator_mods = accel_mods & accel_group->modifier_mask;
533 entry->accel_flags = accel_flags & GTK_ACCEL_MASK;
534 entry->object = object;
535 entry->signal_id = accel_signal_id;
537 g_hash_table_insert (accel_entry_hash_table, entry, entry);
539 slist = gtk_object_get_data_by_id (object, accel_entries_key_id);
541 gtk_signal_connect (object,
543 GTK_SIGNAL_FUNC (gtk_accel_group_delete_entries),
545 slist = g_slist_prepend (slist, entry);
546 gtk_object_set_data_by_id (object, accel_entries_key_id, slist);
551 gtk_accel_group_remove (GtkAccelGroup *accel_group,
553 GdkModifierType accel_mods,
556 GtkAccelEntry *entry;
557 guint remove_accelerator_signal_id = 0;
559 g_return_if_fail (accel_group != NULL);
560 g_return_if_fail (object != NULL);
561 g_return_if_fail (GTK_IS_OBJECT (object));
563 /* check for required signals in the objects branch
565 remove_accelerator_signal_id = gtk_signal_lookup ("remove-accelerator", GTK_OBJECT_TYPE (object));
566 if (!remove_accelerator_signal_id)
568 g_warning ("gtk_accel_group_remove(): could not find signal \"%s\""
569 "in the `%s' class ancestry",
570 "remove-accelerator",
571 gtk_type_name (GTK_OBJECT_TYPE (object)));
575 /* prematurely abort if the entry is locked
577 if (accel_group->lock_count > 0)
579 entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
581 entry->accel_flags & GTK_ACCEL_LOCKED)
583 if (entry->object != object)
585 g_warning ("gtk_accel_group_remove(): invalid object reference for accel-group entry");
589 /* make sure our structures stay alive
591 gtk_accel_group_ref (accel_group);
592 gtk_object_ref (object);
596 gtk_signal_emit (entry->object, remove_accelerator_signal_id,
598 gdk_keyval_to_lower (accel_key),
599 accel_mods & accel_group->modifier_mask);
601 /* and release the structures again
603 gtk_accel_group_unref (accel_group);
604 gtk_object_unref (object);
608 gtk_accel_group_handle_remove (GtkObject *object,
609 GtkAccelGroup *accel_group,
611 GdkModifierType accel_mods)
613 GtkAccelEntry *entry;
615 g_return_if_fail (object != NULL);
616 g_return_if_fail (GTK_IS_OBJECT (object));
617 g_return_if_fail (accel_group != NULL);
619 entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
622 if (entry->object == object)
626 g_hash_table_remove (accel_entry_hash_table, entry);
628 slist = gtk_object_get_data_by_id (object, accel_entries_key_id);
631 slist = g_slist_remove (slist, entry);
633 gtk_signal_disconnect_by_func (object,
634 GTK_SIGNAL_FUNC (gtk_accel_group_delete_entries),
636 gtk_object_set_data_by_id (object, accel_entries_key_id, slist);
638 gtk_accel_group_unref (accel_group);
640 g_chunk_free (entry, accel_entries_mem_chunk);
644 g_warning ("gtk_accel_group_handle_remove(): invalid object reference for accel-group entry");
647 g_warning ("gtk_accel_group_handle_remove(): attempt to remove unexisting accel-group entry");
651 gtk_accel_group_create_add (GtkType class_type,
652 GtkSignalRunType signal_flags,
653 guint handler_offset)
655 g_return_val_if_fail (GTK_TYPE_IS_OBJECT (class_type), 0);
657 return gtk_signal_new ("add-accelerator",
661 gtk_marshal_VOID__UINT_BOXED_UINT_FLAGS_FLAGS,
664 GTK_TYPE_ACCEL_GROUP,
666 GTK_TYPE_GDK_MODIFIER_TYPE,
667 GTK_TYPE_ACCEL_FLAGS);
671 gtk_accel_group_create_remove (GtkType class_type,
672 GtkSignalRunType signal_flags,
673 guint handler_offset)
675 g_return_val_if_fail (GTK_TYPE_IS_OBJECT (class_type), 0);
677 return gtk_signal_new ("remove-accelerator",
681 gtk_marshal_VOID__BOXED_UINT_FLAGS,
683 GTK_TYPE_ACCEL_GROUP,
685 GTK_TYPE_GDK_MODIFIER_TYPE);
689 gtk_accel_groups_from_object (GtkObject *object)
691 g_return_val_if_fail (object != NULL, NULL);
692 g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
694 return gtk_object_get_data_by_id (object, accel_groups_key_id);
698 gtk_accel_group_entries_from_object (GtkObject *object)
700 g_return_val_if_fail (object != NULL, NULL);
701 g_return_val_if_fail (GTK_IS_OBJECT (object), NULL);
703 return gtk_object_get_data_by_id (object, accel_entries_key_id);
707 gtk_accelerator_valid (guint keyval,
708 GdkModifierType modifiers)
710 static const guint invalid_accelerator_vals[] = {
711 GDK_BackSpace, GDK_Delete, GDK_KP_Delete,
712 GDK_Shift_L, GDK_Shift_R, GDK_Shift_Lock, GDK_Caps_Lock, GDK_ISO_Lock,
713 GDK_Control_L, GDK_Control_R, GDK_Meta_L, GDK_Meta_R,
714 GDK_Alt_L, GDK_Alt_R, GDK_Super_L, GDK_Super_R, GDK_Hyper_L, GDK_Hyper_R,
715 GDK_Mode_switch, GDK_Num_Lock, GDK_Multi_key,
716 GDK_Scroll_Lock, GDK_Sys_Req,
717 GDK_Up, GDK_Down, GDK_Left, GDK_Right, GDK_Tab, GDK_ISO_Left_Tab,
718 GDK_KP_Up, GDK_KP_Down, GDK_KP_Left, GDK_KP_Right, GDK_KP_Tab,
719 GDK_First_Virtual_Screen, GDK_Prev_Virtual_Screen,
720 GDK_Next_Virtual_Screen, GDK_Last_Virtual_Screen,
721 GDK_Terminate_Server, GDK_AudibleBell_Enable,
726 modifiers &= GDK_MODIFIER_MASK;
729 return keyval >= 0x20;
731 ac_val = invalid_accelerator_vals;
734 if (keyval == *ac_val++)
741 static inline gboolean
742 is_alt (const gchar *string)
744 return ((string[0] == '<') &&
745 (string[1] == 'a' || string[1] == 'A') &&
746 (string[2] == 'l' || string[2] == 'L') &&
747 (string[3] == 't' || string[3] == 'T') &&
751 static inline gboolean
752 is_ctl (const gchar *string)
754 return ((string[0] == '<') &&
755 (string[1] == 'c' || string[1] == 'C') &&
756 (string[2] == 't' || string[2] == 'T') &&
757 (string[3] == 'l' || string[3] == 'L') &&
761 static inline gboolean
762 is_modx (const gchar *string)
764 return ((string[0] == '<') &&
765 (string[1] == 'm' || string[1] == 'M') &&
766 (string[2] == 'o' || string[2] == 'O') &&
767 (string[3] == 'd' || string[3] == 'D') &&
768 (string[4] >= '1' && string[4] <= '5') &&
772 static inline gboolean
773 is_ctrl (const gchar *string)
775 return ((string[0] == '<') &&
776 (string[1] == 'c' || string[1] == 'C') &&
777 (string[2] == 't' || string[2] == 'T') &&
778 (string[3] == 'r' || string[3] == 'R') &&
779 (string[4] == 'l' || string[4] == 'L') &&
783 static inline gboolean
784 is_shft (const gchar *string)
786 return ((string[0] == '<') &&
787 (string[1] == 's' || string[1] == 'S') &&
788 (string[2] == 'h' || string[2] == 'H') &&
789 (string[3] == 'f' || string[3] == 'F') &&
790 (string[4] == 't' || string[4] == 'T') &&
794 static inline gboolean
795 is_shift (const gchar *string)
797 return ((string[0] == '<') &&
798 (string[1] == 's' || string[1] == 'S') &&
799 (string[2] == 'h' || string[2] == 'H') &&
800 (string[3] == 'i' || string[3] == 'I') &&
801 (string[4] == 'f' || string[4] == 'F') &&
802 (string[5] == 't' || string[5] == 'T') &&
806 static inline gboolean
807 is_control (const gchar *string)
809 return ((string[0] == '<') &&
810 (string[1] == 'c' || string[1] == 'C') &&
811 (string[2] == 'o' || string[2] == 'O') &&
812 (string[3] == 'n' || string[3] == 'N') &&
813 (string[4] == 't' || string[4] == 'T') &&
814 (string[5] == 'r' || string[5] == 'R') &&
815 (string[6] == 'o' || string[6] == 'O') &&
816 (string[7] == 'l' || string[7] == 'L') &&
820 static inline gboolean
821 is_release (const gchar *string)
823 return ((string[0] == '<') &&
824 (string[1] == 'r' || string[1] == 'R') &&
825 (string[2] == 'e' || string[2] == 'E') &&
826 (string[3] == 'l' || string[3] == 'L') &&
827 (string[4] == 'e' || string[4] == 'E') &&
828 (string[5] == 'a' || string[5] == 'A') &&
829 (string[6] == 's' || string[6] == 'S') &&
830 (string[7] == 'e' || string[7] == 'E') &&
835 gtk_accelerator_parse (const gchar *accelerator,
836 guint *accelerator_key,
837 GdkModifierType*accelerator_mods)
840 GdkModifierType mods;
844 *accelerator_key = 0;
845 if (accelerator_mods)
846 *accelerator_mods = 0;
847 g_return_if_fail (accelerator != NULL);
851 len = strlen (accelerator);
854 if (*accelerator == '<')
856 if (len >= 9 && is_release (accelerator))
860 mods |= GDK_RELEASE_MASK;
862 else if (len >= 9 && is_control (accelerator))
866 mods |= GDK_CONTROL_MASK;
868 else if (len >= 7 && is_shift (accelerator))
872 mods |= GDK_SHIFT_MASK;
874 else if (len >= 6 && is_shft (accelerator))
878 mods |= GDK_SHIFT_MASK;
880 else if (len >= 6 && is_ctrl (accelerator))
884 mods |= GDK_CONTROL_MASK;
886 else if (len >= 6 && is_modx (accelerator))
888 static const guint mod_vals[] = {
889 GDK_MOD1_MASK, GDK_MOD2_MASK, GDK_MOD3_MASK,
890 GDK_MOD4_MASK, GDK_MOD5_MASK
895 mods |= mod_vals[*accelerator - '1'];
898 else if (len >= 5 && is_ctl (accelerator))
902 mods |= GDK_CONTROL_MASK;
904 else if (len >= 5 && is_alt (accelerator))
908 mods |= GDK_MOD1_MASK;
914 last_ch = *accelerator;
915 while (last_ch && last_ch != '>')
917 last_ch = *accelerator;
925 keyval = gdk_keyval_from_name (accelerator);
932 *accelerator_key = gdk_keyval_to_lower (keyval);
933 if (accelerator_mods)
934 *accelerator_mods = mods;
938 gtk_accelerator_name (guint accelerator_key,
939 GdkModifierType accelerator_mods)
941 static const gchar text_release[] = "<Release>";
942 static const gchar text_shift[] = "<Shift>";
943 static const gchar text_control[] = "<Control>";
944 static const gchar text_mod1[] = "<Alt>";
945 static const gchar text_mod2[] = "<Mod2>";
946 static const gchar text_mod3[] = "<Mod3>";
947 static const gchar text_mod4[] = "<Mod4>";
948 static const gchar text_mod5[] = "<Mod5>";
953 accelerator_mods &= GDK_MODIFIER_MASK;
955 keyval_name = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
960 if (accelerator_mods & GDK_RELEASE_MASK)
961 l += sizeof (text_release) - 1;
962 if (accelerator_mods & GDK_SHIFT_MASK)
963 l += sizeof (text_shift) - 1;
964 if (accelerator_mods & GDK_CONTROL_MASK)
965 l += sizeof (text_control) - 1;
966 if (accelerator_mods & GDK_MOD1_MASK)
967 l += sizeof (text_mod1) - 1;
968 if (accelerator_mods & GDK_MOD2_MASK)
969 l += sizeof (text_mod2) - 1;
970 if (accelerator_mods & GDK_MOD3_MASK)
971 l += sizeof (text_mod3) - 1;
972 if (accelerator_mods & GDK_MOD4_MASK)
973 l += sizeof (text_mod4) - 1;
974 if (accelerator_mods & GDK_MOD5_MASK)
975 l += sizeof (text_mod5) - 1;
976 l += strlen (keyval_name);
978 accelerator = g_new (gchar, l + 1);
982 if (accelerator_mods & GDK_RELEASE_MASK)
984 strcpy (accelerator + l, text_release);
985 l += sizeof (text_release) - 1;
987 if (accelerator_mods & GDK_SHIFT_MASK)
989 strcpy (accelerator + l, text_shift);
990 l += sizeof (text_shift) - 1;
992 if (accelerator_mods & GDK_CONTROL_MASK)
994 strcpy (accelerator + l, text_control);
995 l += sizeof (text_control) - 1;
997 if (accelerator_mods & GDK_MOD1_MASK)
999 strcpy (accelerator + l, text_mod1);
1000 l += sizeof (text_mod1) - 1;
1002 if (accelerator_mods & GDK_MOD2_MASK)
1004 strcpy (accelerator + l, text_mod2);
1005 l += sizeof (text_mod2) - 1;
1007 if (accelerator_mods & GDK_MOD3_MASK)
1009 strcpy (accelerator + l, text_mod3);
1010 l += sizeof (text_mod3) - 1;
1012 if (accelerator_mods & GDK_MOD4_MASK)
1014 strcpy (accelerator + l, text_mod4);
1015 l += sizeof (text_mod4) - 1;
1017 if (accelerator_mods & GDK_MOD5_MASK)
1019 strcpy (accelerator + l, text_mod5);
1020 l += sizeof (text_mod5) - 1;
1022 strcpy (accelerator + l, keyval_name);
1028 gtk_accelerator_set_default_mod_mask (GdkModifierType default_mod_mask)
1030 default_accel_mod_mask = default_mod_mask & GDK_MODIFIER_MASK;
1034 gtk_accelerator_get_default_mod_mask (void)
1036 return default_accel_mod_mask;