gtk2/gtk/gtkbindings.c

1144 lines
27 KiB
C
Raw Normal View History

fixed an assertment. Sat Jun 6 06:01:24 1998 Tim Janik <timj@gtk.org> * gtk/gtksignal.c (gtk_signal_emitv): fixed an assertment. * gtk/makeenums.awk: a script to generate the GtkEnumValue arrays from, this should eventually be done by gentypeinfo.el somewhen. * gtk/gtkenumvalues.c: new generated file to hold GtkEnumValue arrays. * gtk/gtktypeutils.h: new function gtk_enum_values() to retrive all the enum values of an enum type. * gtk/gtk.defs: * gtk/gtkcurve.h: * gtk/gtkobject.h: * gtk/gtkprivate.h: * gtk/gtkwidget.h: * gtk/gtkenums.h: brought enum/flags definitions in sync, added a few more enum definitions for bindings and pattern matching. * some more macro and GtkType fixups in various places. * gdk/gdktypes.h (enum): added a new value GDK_AFTER_MASK, which is used as a key-release modifier for the binding system. Fri Jun 5 06:06:06 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenu.h (struct _GtkMenu): removed GList*children, since it was a stale list pointer that is already present in GtkMenuShell. * gtk/gtkmenushell.h (struct _GtkMenuShellClass): added a signal GtkMenuShell::selection_done which is emitted after the menu shell poped down again and all possible menu items have been activated. Thu Jun 4 02:20:42 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenushell.c (gtk_menu_shell_button_release): flush the x-queue before activation of the menuitem, so the menu is actually taken off the screen prior to any menu item activation. * gtk/gtkctree.c (gtk_ctree_get_row_data): allow function invokation for NULL nodes. * gtk/gtkwidget.h: * gtk/gtkwidget.c: new function gtk_widget_stop_accelerator to stop the emission of the "add-accelerator" signal on a widget. this is usefull to prevent accelerator installation on certain widgets. * gtk/gtknotebook.c (gtk_notebook_menu_item_create): keep the menu labels left justified, by setting their alignment. stop accelerator installation for the menu items, since we use dynamic menus. Wed Jun 3 06:41:22 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenufactory.c: adaptions to use the new accel groups. people should *really* use GtkItemFactory. this is only for preserving source compatibility where possible, use of GtkMenuFactory is deprecated as of now. * gtk/gtkobject.h (gtk_object_class_add_user_signal): new function to create user signals of type GTK_RUN_NO_RECURSE. don't know why i missed this possibility when i added gtk_object_class_add_user_signal in late january. * gtk/gtkmain.c (gtk_init): ignore subsequent function calls. Sun May 31 07:31:09 1998 Tim Janik <timj@gtk.org> * gtk/gtkaccelgroup.h: * gtk/gtkaccelgroup.c: new implementation of the accelerator concept. * gtk/gtkaccellabel.h: * gtk/gtkaccellabel.c: new widget derived from GtkLabel whitch features display of the accelerators associated with a certain widget. * gtk/gtkitemfactory.h: * gtk/gtkitemfactory.c: new widget, item factory with automatic rc parsing and accelerator handling. * gtk/gtkmenu.c (gtk_menu_reposition): new function to care for positioning a menu. (gtk_menu_map): removed the allocation code. (gtk_menu_size_allocate): care for redrawing of children and resize our widget->window correctly. (gtk_menu_key_press): feature the new accelerator groups. * gtk/gtkmenuitem.c (gtk_menu_item_size_allocate): reposition the submenu if neccessary. * gtk/gtkmenuitem.c: * gtk/gtkcheckmenuitem.c: * gtk/gtkradiomenuitem.c: use GtkAccelLabel in the *_new_with_label() function variants. * gdk/gdk.c: (gdk_keyval_from_name): (gdk_keyval_name): new functions for keyval<->key-name associations. (gdk_keyval_to_upper): (gdk_keyval_to_lower): (gdk_keyval_is_upper): (gdk_keyval_is_lower): new functions to check/translate keyvalues with regards to their cases. Wed May 27 00:48:10 1998 Tim Janik <timj@gtk.org> * gtk/gtkwidget.c (gtk_widget_class_path): new function to calculate a widget's class path. (gtk_widget_path): new function to calculate a widget's name path. * gtk/gtkrc.c: newly introduced GtkPatternSpec structures to speed up pattern matching, features reversed pattern matches.
1998-06-07 06:48:56 +00:00
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* GtkBindingSet: Keybinding manager for GtkObjects.
* Copyright (C) 1998 Tim Janik
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <ctype.h>
#include <strings.h>
#include <stdarg.h>
#include "gtkbindings.h"
#include "gtksignal.h"
#include "gtkwidget.h"
/* --- defines --- */
new functions gtk_selection_data_copy and gtk_selection_data_free. Tue Jun 9 01:57:23 1998 Tim Janik <timj@gtk.org> * gtk/gtkselection.h: * gtk/gtkselection.c: new functions gtk_selection_data_copy and gtk_selection_data_free. * gtk/gtkwidget.c (gtk_widget_class_init): fixed gtk_signal_new() call for "selection_received", which was completely bogus. * other fixups to gtk_signal_new() calls all over the place. * gtk/gtktypebuiltins.h: types as variables (formerly macros). * gtk/gtktypebuiltins_vars.c: type variable implementations. * gtk/gtktypebuiltins_ids.c: array entries for builtin type declarations. * gtk/gtktypebuiltins_evals.c: enum value arrays. * gtk/gtk-boxed.defs: gtk and gdk structure definitions, used to build gtk.defs. * gtk/gtk.defs: generated file with scheme syntax for type definitions of gtk and gdk structures and enums. * gtk/gtktypeutils.h: * gtk/gtktypeutils.c: reworked type ids, so they are variables not macros anymore (this fixes binary incompatibility with new enum definitions). * gtk/gtkwidget.c (gtk_widget_real_key_press_event): proccess possible key bindings for this widget. * gtk/gtkwindow.c (gtk_window_key_press_event): chain parent class' handler. * gtk/gtkobject.h: * gtk/gtkobject.c: removed gtk_object_class_new_user_signal_no_recurse() again. new functions gtk_object_class_user_signal_new () and gtk_object_class_user_signal_newv (), to feature the GtkSignalRunType flag on the signal creation. Mon Jun 8 20:52:21 1998 Tim Janik <timj@gtk.org> * gtk/gtkcontainer.h: new signal GtkContainer::set_focus_child.
1998-06-09 07:11:55 +00:00
#define BINDING_MOD_MASK() (gtk_accelerator_get_default_mod_mask ())
fixed an assertment. Sat Jun 6 06:01:24 1998 Tim Janik <timj@gtk.org> * gtk/gtksignal.c (gtk_signal_emitv): fixed an assertment. * gtk/makeenums.awk: a script to generate the GtkEnumValue arrays from, this should eventually be done by gentypeinfo.el somewhen. * gtk/gtkenumvalues.c: new generated file to hold GtkEnumValue arrays. * gtk/gtktypeutils.h: new function gtk_enum_values() to retrive all the enum values of an enum type. * gtk/gtk.defs: * gtk/gtkcurve.h: * gtk/gtkobject.h: * gtk/gtkprivate.h: * gtk/gtkwidget.h: * gtk/gtkenums.h: brought enum/flags definitions in sync, added a few more enum definitions for bindings and pattern matching. * some more macro and GtkType fixups in various places. * gdk/gdktypes.h (enum): added a new value GDK_AFTER_MASK, which is used as a key-release modifier for the binding system. Fri Jun 5 06:06:06 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenu.h (struct _GtkMenu): removed GList*children, since it was a stale list pointer that is already present in GtkMenuShell. * gtk/gtkmenushell.h (struct _GtkMenuShellClass): added a signal GtkMenuShell::selection_done which is emitted after the menu shell poped down again and all possible menu items have been activated. Thu Jun 4 02:20:42 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenushell.c (gtk_menu_shell_button_release): flush the x-queue before activation of the menuitem, so the menu is actually taken off the screen prior to any menu item activation. * gtk/gtkctree.c (gtk_ctree_get_row_data): allow function invokation for NULL nodes. * gtk/gtkwidget.h: * gtk/gtkwidget.c: new function gtk_widget_stop_accelerator to stop the emission of the "add-accelerator" signal on a widget. this is usefull to prevent accelerator installation on certain widgets. * gtk/gtknotebook.c (gtk_notebook_menu_item_create): keep the menu labels left justified, by setting their alignment. stop accelerator installation for the menu items, since we use dynamic menus. Wed Jun 3 06:41:22 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenufactory.c: adaptions to use the new accel groups. people should *really* use GtkItemFactory. this is only for preserving source compatibility where possible, use of GtkMenuFactory is deprecated as of now. * gtk/gtkobject.h (gtk_object_class_add_user_signal): new function to create user signals of type GTK_RUN_NO_RECURSE. don't know why i missed this possibility when i added gtk_object_class_add_user_signal in late january. * gtk/gtkmain.c (gtk_init): ignore subsequent function calls. Sun May 31 07:31:09 1998 Tim Janik <timj@gtk.org> * gtk/gtkaccelgroup.h: * gtk/gtkaccelgroup.c: new implementation of the accelerator concept. * gtk/gtkaccellabel.h: * gtk/gtkaccellabel.c: new widget derived from GtkLabel whitch features display of the accelerators associated with a certain widget. * gtk/gtkitemfactory.h: * gtk/gtkitemfactory.c: new widget, item factory with automatic rc parsing and accelerator handling. * gtk/gtkmenu.c (gtk_menu_reposition): new function to care for positioning a menu. (gtk_menu_map): removed the allocation code. (gtk_menu_size_allocate): care for redrawing of children and resize our widget->window correctly. (gtk_menu_key_press): feature the new accelerator groups. * gtk/gtkmenuitem.c (gtk_menu_item_size_allocate): reposition the submenu if neccessary. * gtk/gtkmenuitem.c: * gtk/gtkcheckmenuitem.c: * gtk/gtkradiomenuitem.c: use GtkAccelLabel in the *_new_with_label() function variants. * gdk/gdk.c: (gdk_keyval_from_name): (gdk_keyval_name): new functions for keyval<->key-name associations. (gdk_keyval_to_upper): (gdk_keyval_to_lower): (gdk_keyval_is_upper): (gdk_keyval_is_lower): new functions to check/translate keyvalues with regards to their cases. Wed May 27 00:48:10 1998 Tim Janik <timj@gtk.org> * gtk/gtkwidget.c (gtk_widget_class_path): new function to calculate a widget's class path. (gtk_widget_path): new function to calculate a widget's name path. * gtk/gtkrc.c: newly introduced GtkPatternSpec structures to speed up pattern matching, features reversed pattern matches.
1998-06-07 06:48:56 +00:00
/* --- variables --- */
static GHashTable *binding_entry_hash_table = NULL;
static GSList *binding_set_list = NULL;
static const gchar *key_class_binding_set = "gtk-class-binding-set";
static guint key_id_class_binding_set = 0;
/* --- functions --- */
static GtkBindingSignal*
binding_signal_new (const gchar *signal_name,
guint n_args)
{
GtkBindingSignal *signal;
signal = g_new (GtkBindingSignal, 1);
signal->next = NULL;
signal->signal_name = g_strdup (signal_name);
signal->n_args = n_args;
signal->args = g_new0 (GtkBindingArg, n_args);
return signal;
}
static void
binding_signal_free (GtkBindingSignal *sig)
{
guint i;
for (i = 0; i < sig->n_args; i++)
{
if (sig->args[i].arg_type == GTK_BINDING_ARG_STRING)
g_free (sig->args[i].d.string_data);
}
g_free (sig->args);
g_free (sig->signal_name);
g_free (sig);
}
static guint
binding_entry_hash (gpointer key)
{
register GtkBindingEntry *e = key;
register guint h;
h = e->keyval;
h ^= e->modifiers;
return h;
}
static gint
binding_entries_compare (gpointer a,
gpointer b)
{
register GtkBindingEntry *ea = a;
register GtkBindingEntry *eb = b;
return (ea->keyval == eb->keyval && ea->modifiers == eb->modifiers);
}
static GtkBindingEntry*
binding_entry_new (GtkBindingSet *binding_set,
guint keyval,
guint modifiers)
{
GtkBindingEntry *entry;
if (!binding_entry_hash_table)
binding_entry_hash_table = g_hash_table_new (binding_entry_hash, binding_entries_compare);
entry = g_new (GtkBindingEntry, 1);
entry->keyval = keyval;
entry->modifiers = modifiers;
entry->binding_set = binding_set,
entry->destroyed = FALSE;
entry->in_emission = FALSE;
entry->signals = NULL;
entry->set_next = binding_set->entries;
binding_set->entries = entry;
entry->hash_next = g_hash_table_lookup (binding_entry_hash_table, entry);
g_hash_table_freeze (binding_entry_hash_table);
if (entry->hash_next)
g_hash_table_remove (binding_entry_hash_table, entry->hash_next);
g_hash_table_insert (binding_entry_hash_table, entry, entry);
g_hash_table_thaw (binding_entry_hash_table);
return entry;
}
static void
binding_entry_free (GtkBindingEntry *entry)
{
GtkBindingSignal *sig;
g_assert (entry->set_next == NULL &&
entry->hash_next == NULL &&
entry->in_emission == FALSE &&
entry->destroyed == TRUE);
entry->destroyed = FALSE;
sig = entry->signals;
while (sig)
{
GtkBindingSignal *prev;
prev = sig;
sig = prev->next;
binding_signal_free (prev);
}
g_free (entry);
}
static void
binding_entry_destroy (GtkBindingEntry *entry)
{
GtkBindingEntry *o_entry;
register GtkBindingEntry *tmp;
GtkBindingEntry *begin;
register GtkBindingEntry *last;
/* unlink from binding set
*/
last = NULL;
tmp = entry->binding_set->entries;
while (tmp)
{
if (tmp == entry)
{
if (last)
last->set_next = entry->set_next;
else
entry->binding_set->entries = entry->set_next;
break;
}
last = tmp;
tmp = last->set_next;
}
entry->set_next = NULL;
o_entry = g_hash_table_lookup (binding_entry_hash_table, entry);
begin = o_entry;
last = NULL;
tmp = begin;
while (tmp)
{
if (tmp == entry)
{
if (last)
last->hash_next = entry->hash_next;
else
begin = entry->hash_next;
break;
}
last = tmp;
tmp = last->hash_next;
}
entry->hash_next = NULL;
if (!begin)
g_hash_table_remove (binding_entry_hash_table, entry);
else if (begin != o_entry)
{
g_hash_table_freeze (binding_entry_hash_table);
g_hash_table_remove (binding_entry_hash_table, entry);
g_hash_table_insert (binding_entry_hash_table, begin, begin);
g_hash_table_thaw (binding_entry_hash_table);
}
entry->destroyed = TRUE;
if (!entry->in_emission)
binding_entry_free (entry);
}
static GtkBindingEntry*
binding_ht_lookup_list (guint keyval,
guint modifiers)
{
GtkBindingEntry lookup_entry = { 0 };
if (!binding_entry_hash_table)
return NULL;
lookup_entry.keyval = keyval;
lookup_entry.modifiers = modifiers;
return g_hash_table_lookup (binding_entry_hash_table, &lookup_entry);
}
static GtkBindingEntry*
binding_ht_lookup_entry (GtkBindingSet *set,
guint keyval,
guint modifiers)
{
GtkBindingEntry lookup_entry = { 0 };
GtkBindingEntry *entry;
if (!binding_entry_hash_table)
return NULL;
lookup_entry.keyval = keyval;
lookup_entry.modifiers = modifiers;
entry = g_hash_table_lookup (binding_entry_hash_table, &lookup_entry);
for (; entry; entry = entry->hash_next)
if (entry->binding_set == set)
return entry;
return NULL;
}
static gboolean
binding_compose_params (GtkBindingArg *args,
GtkSignalQuery *query,
GtkArg **params_p)
{
GtkArg *params;
const GtkType *types;
guint i;
gboolean valid;
params = g_new0 (GtkArg, query->nparams);
*params_p = params;
types = query->params;
valid = TRUE;
for (i = 0; i < query->nparams && valid; i++)
{
params->type = *types;
params->name = NULL;
switch (args->arg_type)
{
case GTK_BINDING_ARG_STRING:
if (params->type == GTK_TYPE_STRING)
GTK_VALUE_STRING (*params) = args->d.string_data;
else
valid = FALSE;
break;
case GTK_BINDING_ARG_DOUBLE:
if (params->type == GTK_TYPE_FLOAT)
GTK_VALUE_FLOAT (*params) = args->d.double_data;
else if (params->type == GTK_TYPE_DOUBLE)
GTK_VALUE_DOUBLE (*params) = args->d.double_data;
else
valid = FALSE;
break;
case GTK_BINDING_ARG_LONG:
if (params->type == GTK_TYPE_BOOL &&
(args->d.long_data == 0 ||
args->d.long_data == 1))
GTK_VALUE_BOOL (*params) = args->d.long_data;
else if (params->type == GTK_TYPE_INT)
GTK_VALUE_INT (*params) = args->d.long_data;
else if (params->type == GTK_TYPE_UINT &&
args->d.long_data >= 0)
GTK_VALUE_UINT (*params) = args->d.long_data;
else if (params->type == GTK_TYPE_LONG)
GTK_VALUE_LONG (*params) = args->d.long_data;
else if (params->type == GTK_TYPE_ULONG &&
args->d.long_data >= 0)
GTK_VALUE_ULONG (*params) = args->d.long_data;
else if (params->type == GTK_TYPE_FLOAT)
GTK_VALUE_FLOAT (*params) = args->d.long_data;
else if (params->type == GTK_TYPE_DOUBLE)
GTK_VALUE_DOUBLE (*params) = args->d.long_data;
else
valid = FALSE;
break;
default:
valid = FALSE;
break;
}
types++;
params++;
args++;
}
if (!valid)
{
g_free (*params_p);
*params_p = NULL;
}
return valid;
}
static void
gtk_binding_entry_activate (GtkBindingEntry *entry,
GtkObject *object)
{
GtkBindingSignal *sig;
gboolean old_emission;
old_emission = entry->in_emission;
entry->in_emission = TRUE;
gtk_object_ref (object);
for (sig = entry->signals; sig; sig = sig->next)
{
GtkSignalQuery *query;
guint signal_id;
GtkArg *params = NULL;
new functions gtk_selection_data_copy and gtk_selection_data_free. Tue Jun 9 01:57:23 1998 Tim Janik <timj@gtk.org> * gtk/gtkselection.h: * gtk/gtkselection.c: new functions gtk_selection_data_copy and gtk_selection_data_free. * gtk/gtkwidget.c (gtk_widget_class_init): fixed gtk_signal_new() call for "selection_received", which was completely bogus. * other fixups to gtk_signal_new() calls all over the place. * gtk/gtktypebuiltins.h: types as variables (formerly macros). * gtk/gtktypebuiltins_vars.c: type variable implementations. * gtk/gtktypebuiltins_ids.c: array entries for builtin type declarations. * gtk/gtktypebuiltins_evals.c: enum value arrays. * gtk/gtk-boxed.defs: gtk and gdk structure definitions, used to build gtk.defs. * gtk/gtk.defs: generated file with scheme syntax for type definitions of gtk and gdk structures and enums. * gtk/gtktypeutils.h: * gtk/gtktypeutils.c: reworked type ids, so they are variables not macros anymore (this fixes binary incompatibility with new enum definitions). * gtk/gtkwidget.c (gtk_widget_real_key_press_event): proccess possible key bindings for this widget. * gtk/gtkwindow.c (gtk_window_key_press_event): chain parent class' handler. * gtk/gtkobject.h: * gtk/gtkobject.c: removed gtk_object_class_new_user_signal_no_recurse() again. new functions gtk_object_class_user_signal_new () and gtk_object_class_user_signal_newv (), to feature the GtkSignalRunType flag on the signal creation. Mon Jun 8 20:52:21 1998 Tim Janik <timj@gtk.org> * gtk/gtkcontainer.h: new signal GtkContainer::set_focus_child.
1998-06-09 07:11:55 +00:00
gchar *accelerator = NULL;
fixed an assertment. Sat Jun 6 06:01:24 1998 Tim Janik <timj@gtk.org> * gtk/gtksignal.c (gtk_signal_emitv): fixed an assertment. * gtk/makeenums.awk: a script to generate the GtkEnumValue arrays from, this should eventually be done by gentypeinfo.el somewhen. * gtk/gtkenumvalues.c: new generated file to hold GtkEnumValue arrays. * gtk/gtktypeutils.h: new function gtk_enum_values() to retrive all the enum values of an enum type. * gtk/gtk.defs: * gtk/gtkcurve.h: * gtk/gtkobject.h: * gtk/gtkprivate.h: * gtk/gtkwidget.h: * gtk/gtkenums.h: brought enum/flags definitions in sync, added a few more enum definitions for bindings and pattern matching. * some more macro and GtkType fixups in various places. * gdk/gdktypes.h (enum): added a new value GDK_AFTER_MASK, which is used as a key-release modifier for the binding system. Fri Jun 5 06:06:06 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenu.h (struct _GtkMenu): removed GList*children, since it was a stale list pointer that is already present in GtkMenuShell. * gtk/gtkmenushell.h (struct _GtkMenuShellClass): added a signal GtkMenuShell::selection_done which is emitted after the menu shell poped down again and all possible menu items have been activated. Thu Jun 4 02:20:42 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenushell.c (gtk_menu_shell_button_release): flush the x-queue before activation of the menuitem, so the menu is actually taken off the screen prior to any menu item activation. * gtk/gtkctree.c (gtk_ctree_get_row_data): allow function invokation for NULL nodes. * gtk/gtkwidget.h: * gtk/gtkwidget.c: new function gtk_widget_stop_accelerator to stop the emission of the "add-accelerator" signal on a widget. this is usefull to prevent accelerator installation on certain widgets. * gtk/gtknotebook.c (gtk_notebook_menu_item_create): keep the menu labels left justified, by setting their alignment. stop accelerator installation for the menu items, since we use dynamic menus. Wed Jun 3 06:41:22 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenufactory.c: adaptions to use the new accel groups. people should *really* use GtkItemFactory. this is only for preserving source compatibility where possible, use of GtkMenuFactory is deprecated as of now. * gtk/gtkobject.h (gtk_object_class_add_user_signal): new function to create user signals of type GTK_RUN_NO_RECURSE. don't know why i missed this possibility when i added gtk_object_class_add_user_signal in late january. * gtk/gtkmain.c (gtk_init): ignore subsequent function calls. Sun May 31 07:31:09 1998 Tim Janik <timj@gtk.org> * gtk/gtkaccelgroup.h: * gtk/gtkaccelgroup.c: new implementation of the accelerator concept. * gtk/gtkaccellabel.h: * gtk/gtkaccellabel.c: new widget derived from GtkLabel whitch features display of the accelerators associated with a certain widget. * gtk/gtkitemfactory.h: * gtk/gtkitemfactory.c: new widget, item factory with automatic rc parsing and accelerator handling. * gtk/gtkmenu.c (gtk_menu_reposition): new function to care for positioning a menu. (gtk_menu_map): removed the allocation code. (gtk_menu_size_allocate): care for redrawing of children and resize our widget->window correctly. (gtk_menu_key_press): feature the new accelerator groups. * gtk/gtkmenuitem.c (gtk_menu_item_size_allocate): reposition the submenu if neccessary. * gtk/gtkmenuitem.c: * gtk/gtkcheckmenuitem.c: * gtk/gtkradiomenuitem.c: use GtkAccelLabel in the *_new_with_label() function variants. * gdk/gdk.c: (gdk_keyval_from_name): (gdk_keyval_name): new functions for keyval<->key-name associations. (gdk_keyval_to_upper): (gdk_keyval_to_lower): (gdk_keyval_is_upper): (gdk_keyval_is_lower): new functions to check/translate keyvalues with regards to their cases. Wed May 27 00:48:10 1998 Tim Janik <timj@gtk.org> * gtk/gtkwidget.c (gtk_widget_class_path): new function to calculate a widget's class path. (gtk_widget_path): new function to calculate a widget's name path. * gtk/gtkrc.c: newly introduced GtkPatternSpec structures to speed up pattern matching, features reversed pattern matches.
1998-06-07 06:48:56 +00:00
signal_id = gtk_signal_lookup (sig->signal_name, GTK_OBJECT_TYPE (object));
if (!signal_id)
{
accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
"could not find signal \"%s\" in the `%s' class ancestry",
entry->binding_set->set_name,
accelerator,
sig->signal_name,
gtk_type_name (GTK_OBJECT_TYPE (object)));
g_free (accelerator);
continue;
}
query = gtk_signal_query (signal_id);
if (query->nparams != sig->n_args ||
query->return_val != GTK_TYPE_NONE ||
!binding_compose_params (sig->args, query, &params))
{
accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
"signature mismatch for signal \"%s\" in the `%s' class ancestry",
entry->binding_set->set_name,
accelerator,
sig->signal_name,
gtk_type_name (GTK_OBJECT_TYPE (object)));
}
new functions gtk_selection_data_copy and gtk_selection_data_free. Tue Jun 9 01:57:23 1998 Tim Janik <timj@gtk.org> * gtk/gtkselection.h: * gtk/gtkselection.c: new functions gtk_selection_data_copy and gtk_selection_data_free. * gtk/gtkwidget.c (gtk_widget_class_init): fixed gtk_signal_new() call for "selection_received", which was completely bogus. * other fixups to gtk_signal_new() calls all over the place. * gtk/gtktypebuiltins.h: types as variables (formerly macros). * gtk/gtktypebuiltins_vars.c: type variable implementations. * gtk/gtktypebuiltins_ids.c: array entries for builtin type declarations. * gtk/gtktypebuiltins_evals.c: enum value arrays. * gtk/gtk-boxed.defs: gtk and gdk structure definitions, used to build gtk.defs. * gtk/gtk.defs: generated file with scheme syntax for type definitions of gtk and gdk structures and enums. * gtk/gtktypeutils.h: * gtk/gtktypeutils.c: reworked type ids, so they are variables not macros anymore (this fixes binary incompatibility with new enum definitions). * gtk/gtkwidget.c (gtk_widget_real_key_press_event): proccess possible key bindings for this widget. * gtk/gtkwindow.c (gtk_window_key_press_event): chain parent class' handler. * gtk/gtkobject.h: * gtk/gtkobject.c: removed gtk_object_class_new_user_signal_no_recurse() again. new functions gtk_object_class_user_signal_new () and gtk_object_class_user_signal_newv (), to feature the GtkSignalRunType flag on the signal creation. Mon Jun 8 20:52:21 1998 Tim Janik <timj@gtk.org> * gtk/gtkcontainer.h: new signal GtkContainer::set_focus_child.
1998-06-09 07:11:55 +00:00
else if (!(query->signal_flags & GTK_RUN_ACTION))
{
accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
"signal \"%s\" in the `%s' class ancestry cannot be used for action emissions",
entry->binding_set->set_name,
accelerator,
sig->signal_name,
gtk_type_name (GTK_OBJECT_TYPE (object)));
}
g_free (accelerator);
fixed an assertment. Sat Jun 6 06:01:24 1998 Tim Janik <timj@gtk.org> * gtk/gtksignal.c (gtk_signal_emitv): fixed an assertment. * gtk/makeenums.awk: a script to generate the GtkEnumValue arrays from, this should eventually be done by gentypeinfo.el somewhen. * gtk/gtkenumvalues.c: new generated file to hold GtkEnumValue arrays. * gtk/gtktypeutils.h: new function gtk_enum_values() to retrive all the enum values of an enum type. * gtk/gtk.defs: * gtk/gtkcurve.h: * gtk/gtkobject.h: * gtk/gtkprivate.h: * gtk/gtkwidget.h: * gtk/gtkenums.h: brought enum/flags definitions in sync, added a few more enum definitions for bindings and pattern matching. * some more macro and GtkType fixups in various places. * gdk/gdktypes.h (enum): added a new value GDK_AFTER_MASK, which is used as a key-release modifier for the binding system. Fri Jun 5 06:06:06 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenu.h (struct _GtkMenu): removed GList*children, since it was a stale list pointer that is already present in GtkMenuShell. * gtk/gtkmenushell.h (struct _GtkMenuShellClass): added a signal GtkMenuShell::selection_done which is emitted after the menu shell poped down again and all possible menu items have been activated. Thu Jun 4 02:20:42 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenushell.c (gtk_menu_shell_button_release): flush the x-queue before activation of the menuitem, so the menu is actually taken off the screen prior to any menu item activation. * gtk/gtkctree.c (gtk_ctree_get_row_data): allow function invokation for NULL nodes. * gtk/gtkwidget.h: * gtk/gtkwidget.c: new function gtk_widget_stop_accelerator to stop the emission of the "add-accelerator" signal on a widget. this is usefull to prevent accelerator installation on certain widgets. * gtk/gtknotebook.c (gtk_notebook_menu_item_create): keep the menu labels left justified, by setting their alignment. stop accelerator installation for the menu items, since we use dynamic menus. Wed Jun 3 06:41:22 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenufactory.c: adaptions to use the new accel groups. people should *really* use GtkItemFactory. this is only for preserving source compatibility where possible, use of GtkMenuFactory is deprecated as of now. * gtk/gtkobject.h (gtk_object_class_add_user_signal): new function to create user signals of type GTK_RUN_NO_RECURSE. don't know why i missed this possibility when i added gtk_object_class_add_user_signal in late january. * gtk/gtkmain.c (gtk_init): ignore subsequent function calls. Sun May 31 07:31:09 1998 Tim Janik <timj@gtk.org> * gtk/gtkaccelgroup.h: * gtk/gtkaccelgroup.c: new implementation of the accelerator concept. * gtk/gtkaccellabel.h: * gtk/gtkaccellabel.c: new widget derived from GtkLabel whitch features display of the accelerators associated with a certain widget. * gtk/gtkitemfactory.h: * gtk/gtkitemfactory.c: new widget, item factory with automatic rc parsing and accelerator handling. * gtk/gtkmenu.c (gtk_menu_reposition): new function to care for positioning a menu. (gtk_menu_map): removed the allocation code. (gtk_menu_size_allocate): care for redrawing of children and resize our widget->window correctly. (gtk_menu_key_press): feature the new accelerator groups. * gtk/gtkmenuitem.c (gtk_menu_item_size_allocate): reposition the submenu if neccessary. * gtk/gtkmenuitem.c: * gtk/gtkcheckmenuitem.c: * gtk/gtkradiomenuitem.c: use GtkAccelLabel in the *_new_with_label() function variants. * gdk/gdk.c: (gdk_keyval_from_name): (gdk_keyval_name): new functions for keyval<->key-name associations. (gdk_keyval_to_upper): (gdk_keyval_to_lower): (gdk_keyval_is_upper): (gdk_keyval_is_lower): new functions to check/translate keyvalues with regards to their cases. Wed May 27 00:48:10 1998 Tim Janik <timj@gtk.org> * gtk/gtkwidget.c (gtk_widget_class_path): new function to calculate a widget's class path. (gtk_widget_path): new function to calculate a widget's name path. * gtk/gtkrc.c: newly introduced GtkPatternSpec structures to speed up pattern matching, features reversed pattern matches.
1998-06-07 06:48:56 +00:00
g_free (query);
new functions gtk_selection_data_copy and gtk_selection_data_free. Tue Jun 9 01:57:23 1998 Tim Janik <timj@gtk.org> * gtk/gtkselection.h: * gtk/gtkselection.c: new functions gtk_selection_data_copy and gtk_selection_data_free. * gtk/gtkwidget.c (gtk_widget_class_init): fixed gtk_signal_new() call for "selection_received", which was completely bogus. * other fixups to gtk_signal_new() calls all over the place. * gtk/gtktypebuiltins.h: types as variables (formerly macros). * gtk/gtktypebuiltins_vars.c: type variable implementations. * gtk/gtktypebuiltins_ids.c: array entries for builtin type declarations. * gtk/gtktypebuiltins_evals.c: enum value arrays. * gtk/gtk-boxed.defs: gtk and gdk structure definitions, used to build gtk.defs. * gtk/gtk.defs: generated file with scheme syntax for type definitions of gtk and gdk structures and enums. * gtk/gtktypeutils.h: * gtk/gtktypeutils.c: reworked type ids, so they are variables not macros anymore (this fixes binary incompatibility with new enum definitions). * gtk/gtkwidget.c (gtk_widget_real_key_press_event): proccess possible key bindings for this widget. * gtk/gtkwindow.c (gtk_window_key_press_event): chain parent class' handler. * gtk/gtkobject.h: * gtk/gtkobject.c: removed gtk_object_class_new_user_signal_no_recurse() again. new functions gtk_object_class_user_signal_new () and gtk_object_class_user_signal_newv (), to feature the GtkSignalRunType flag on the signal creation. Mon Jun 8 20:52:21 1998 Tim Janik <timj@gtk.org> * gtk/gtkcontainer.h: new signal GtkContainer::set_focus_child.
1998-06-09 07:11:55 +00:00
if (accelerator)
continue;
fixed an assertment. Sat Jun 6 06:01:24 1998 Tim Janik <timj@gtk.org> * gtk/gtksignal.c (gtk_signal_emitv): fixed an assertment. * gtk/makeenums.awk: a script to generate the GtkEnumValue arrays from, this should eventually be done by gentypeinfo.el somewhen. * gtk/gtkenumvalues.c: new generated file to hold GtkEnumValue arrays. * gtk/gtktypeutils.h: new function gtk_enum_values() to retrive all the enum values of an enum type. * gtk/gtk.defs: * gtk/gtkcurve.h: * gtk/gtkobject.h: * gtk/gtkprivate.h: * gtk/gtkwidget.h: * gtk/gtkenums.h: brought enum/flags definitions in sync, added a few more enum definitions for bindings and pattern matching. * some more macro and GtkType fixups in various places. * gdk/gdktypes.h (enum): added a new value GDK_AFTER_MASK, which is used as a key-release modifier for the binding system. Fri Jun 5 06:06:06 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenu.h (struct _GtkMenu): removed GList*children, since it was a stale list pointer that is already present in GtkMenuShell. * gtk/gtkmenushell.h (struct _GtkMenuShellClass): added a signal GtkMenuShell::selection_done which is emitted after the menu shell poped down again and all possible menu items have been activated. Thu Jun 4 02:20:42 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenushell.c (gtk_menu_shell_button_release): flush the x-queue before activation of the menuitem, so the menu is actually taken off the screen prior to any menu item activation. * gtk/gtkctree.c (gtk_ctree_get_row_data): allow function invokation for NULL nodes. * gtk/gtkwidget.h: * gtk/gtkwidget.c: new function gtk_widget_stop_accelerator to stop the emission of the "add-accelerator" signal on a widget. this is usefull to prevent accelerator installation on certain widgets. * gtk/gtknotebook.c (gtk_notebook_menu_item_create): keep the menu labels left justified, by setting their alignment. stop accelerator installation for the menu items, since we use dynamic menus. Wed Jun 3 06:41:22 1998 Tim Janik <timj@gtk.org> * gtk/gtkmenufactory.c: adaptions to use the new accel groups. people should *really* use GtkItemFactory. this is only for preserving source compatibility where possible, use of GtkMenuFactory is deprecated as of now. * gtk/gtkobject.h (gtk_object_class_add_user_signal): new function to create user signals of type GTK_RUN_NO_RECURSE. don't know why i missed this possibility when i added gtk_object_class_add_user_signal in late january. * gtk/gtkmain.c (gtk_init): ignore subsequent function calls. Sun May 31 07:31:09 1998 Tim Janik <timj@gtk.org> * gtk/gtkaccelgroup.h: * gtk/gtkaccelgroup.c: new implementation of the accelerator concept. * gtk/gtkaccellabel.h: * gtk/gtkaccellabel.c: new widget derived from GtkLabel whitch features display of the accelerators associated with a certain widget. * gtk/gtkitemfactory.h: * gtk/gtkitemfactory.c: new widget, item factory with automatic rc parsing and accelerator handling. * gtk/gtkmenu.c (gtk_menu_reposition): new function to care for positioning a menu. (gtk_menu_map): removed the allocation code. (gtk_menu_size_allocate): care for redrawing of children and resize our widget->window correctly. (gtk_menu_key_press): feature the new accelerator groups. * gtk/gtkmenuitem.c (gtk_menu_item_size_allocate): reposition the submenu if neccessary. * gtk/gtkmenuitem.c: * gtk/gtkcheckmenuitem.c: * gtk/gtkradiomenuitem.c: use GtkAccelLabel in the *_new_with_label() function variants. * gdk/gdk.c: (gdk_keyval_from_name): (gdk_keyval_name): new functions for keyval<->key-name associations. (gdk_keyval_to_upper): (gdk_keyval_to_lower): (gdk_keyval_is_upper): (gdk_keyval_is_lower): new functions to check/translate keyvalues with regards to their cases. Wed May 27 00:48:10 1998 Tim Janik <timj@gtk.org> * gtk/gtkwidget.c (gtk_widget_class_path): new function to calculate a widget's class path. (gtk_widget_path): new function to calculate a widget's name path. * gtk/gtkrc.c: newly introduced GtkPatternSpec structures to speed up pattern matching, features reversed pattern matches.
1998-06-07 06:48:56 +00:00
gtk_signal_emitv (object, signal_id, params);
g_free (params);
if (GTK_OBJECT_DESTROYED (object) || entry->destroyed)
break;
}
gtk_object_unref (object);
entry->in_emission = old_emission;
if (entry->destroyed && !entry->in_emission)
binding_entry_free (entry);
}
GtkBindingSet*
gtk_binding_set_new (const gchar *set_name)
{
GtkBindingSet *binding_set;
g_return_val_if_fail (set_name != NULL, NULL);
binding_set = g_new (GtkBindingSet, 1);
binding_set->set_name = g_strdup (set_name);
binding_set->widget_path_pspecs = NULL;
binding_set->widget_class_pspecs = NULL;
binding_set->class_branch_pspecs = NULL;
binding_set->entries = NULL;
binding_set->current = NULL;
binding_set_list = g_slist_prepend (NULL, binding_set);
return binding_set;
}
GtkBindingSet*
gtk_binding_set_by_class (gpointer object_class)
{
GtkObjectClass *class = object_class;
GtkBindingSet* binding_set;
g_return_val_if_fail (GTK_IS_OBJECT_CLASS (class), NULL);
if (!key_id_class_binding_set)
key_id_class_binding_set = g_dataset_force_id (key_class_binding_set);
binding_set = g_dataset_id_get_data (class, key_id_class_binding_set);
if (binding_set)
return binding_set;
binding_set = gtk_binding_set_new (gtk_type_name (class->type));
gtk_binding_set_add_path (binding_set,
GTK_PATH_CLASS,
gtk_type_name (class->type),
GTK_PATH_PRIO_GTK);
g_dataset_id_set_data (class, key_id_class_binding_set, binding_set);
return binding_set;
}
GtkBindingSet*
gtk_binding_set_find (const gchar *set_name)
{
GSList *slist;
g_return_val_if_fail (set_name != NULL, NULL);
for (slist = binding_set_list; slist; slist = slist->next)
{
GtkBindingSet *binding_set;
binding_set = slist->data;
if (g_str_equal (binding_set->set_name, (gpointer) set_name))
return binding_set;
}
return NULL;
}
gboolean
gtk_binding_set_activate (GtkBindingSet *binding_set,
guint keyval,
guint modifiers,
GtkObject *object)
{
GtkBindingEntry *entry;
g_return_val_if_fail (binding_set != NULL, FALSE);
g_return_val_if_fail (object != NULL, FALSE);
g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
keyval = gdk_keyval_to_lower (keyval);
modifiers = modifiers & BINDING_MOD_MASK ();
if (!GTK_OBJECT_DESTROYED (object))
{
entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
if (entry)
{
gtk_binding_entry_activate (entry, object);
return TRUE;
}
}
return FALSE;
}
void
gtk_binding_entry_clear (GtkBindingSet *binding_set,
guint keyval,
guint modifiers)
{
GtkBindingEntry *entry;
g_return_if_fail (binding_set != NULL);
keyval = gdk_keyval_to_lower (keyval);
modifiers = modifiers & BINDING_MOD_MASK ();
entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
if (entry)
binding_entry_destroy (entry);
entry = binding_entry_new (binding_set, keyval, modifiers);
}
void
gtk_binding_entry_remove (GtkBindingSet *binding_set,
guint keyval,
guint modifiers)
{
GtkBindingEntry *entry;
g_return_if_fail (binding_set != NULL);
keyval = gdk_keyval_to_lower (keyval);
modifiers = modifiers & BINDING_MOD_MASK ();
entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
if (entry)
binding_entry_destroy (entry);
}
void
gtk_binding_entry_add_signall (GtkBindingSet *binding_set,
guint keyval,
guint modifiers,
const gchar *signal_name,
GSList *binding_args)
{
GtkBindingEntry *entry;
GtkBindingSignal *signal, **signal_p;
GSList *slist;
guint n = 0;
GtkBindingArg *arg;
g_return_if_fail (binding_set != NULL);
g_return_if_fail (signal_name != NULL);
keyval = gdk_keyval_to_lower (keyval);
modifiers = modifiers & BINDING_MOD_MASK ();
signal = binding_signal_new (signal_name, g_slist_length (binding_args));
arg = signal->args;
for (slist = binding_args; slist; slist = slist->next)
{
GtkBindingArg *tmp_arg;
tmp_arg = slist->data;
if (!tmp_arg)
{
g_warning ("gtk_binding_entry_add_signall(): arg[%u] is `NULL'", n);
binding_signal_free (signal);
return;
}
arg->arg_type = tmp_arg->arg_type;
switch (tmp_arg->arg_type)
{
case GTK_BINDING_ARG_INT:
case GTK_BINDING_ARG_LONG:
arg->d.long_data = tmp_arg->d.long_data;
break;
case GTK_BINDING_ARG_FLOAT:
case GTK_BINDING_ARG_DOUBLE:
arg->d.double_data = tmp_arg->d.double_data;
break;
case GTK_BINDING_ARG_STRING:
if (!tmp_arg->d.string_data)
{
g_warning ("gtk_binding_entry_add_signall(): value of `string' arg[%u] is `NULL'", n);
arg->d.string_data = NULL;
binding_signal_free (signal);
return;
}
arg->d.string_data = g_strdup (tmp_arg->d.string_data);
break;
default:
g_warning ("gtk_binding_entry_add_signall(): unsupported type `%s' for arg[%u]",
gtk_type_name (arg->arg_type), n);
binding_signal_free (signal);
return;
}
arg++;
n++;
}
entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
if (!entry)
{
gtk_binding_entry_add (binding_set, keyval, modifiers);
entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
}
signal_p = &entry->signals;
while (*signal_p)
signal_p = &(*signal_p)->next;
*signal_p = signal;
}
void
gtk_binding_entry_add_signal (GtkBindingSet *binding_set,
guint keyval,
guint modifiers,
const gchar *signal_name,
guint n_args,
...)
{
GSList *slist, *free_slist;
va_list args;
guint i;
g_return_if_fail (binding_set != NULL);
g_return_if_fail (signal_name != NULL);
keyval = gdk_keyval_to_lower (keyval);
modifiers = modifiers & BINDING_MOD_MASK ();
va_start (args, n_args);
slist = NULL;
for (i = 0; i < n_args; i++)
{
GtkBindingArg *arg;
arg = g_new0 (GtkBindingArg, 1);
slist = g_slist_prepend (slist, arg);
arg->arg_type = va_arg (args, GtkType);
switch (arg->arg_type)
{
case GTK_BINDING_ARG_INT:
arg->d.long_data = va_arg (args, gint);
break;
case GTK_BINDING_ARG_LONG:
arg->d.long_data = va_arg (args, glong);
break;
case GTK_BINDING_ARG_FLOAT:
arg->d.double_data = va_arg (args, gfloat);
break;
case GTK_BINDING_ARG_DOUBLE:
arg->d.double_data = va_arg (args, gdouble);
break;
case GTK_BINDING_ARG_STRING:
arg->d.string_data = va_arg (args, gchar*);
if (!arg->d.string_data)
{
g_warning ("gtk_binding_entry_add_signal(): value of `string' arg[%u] is `NULL'", i);
i = n_args + 2;
}
break;
default:
g_warning ("gtk_binding_entry_add_signal(): unsupported type `%s' for arg[%u]",
gtk_type_name (arg->arg_type), i);
i = n_args + 2;
break;
}
}
va_end (args);
if (i == n_args + 1 || i == 0)
{
slist = g_slist_reverse (slist);
gtk_binding_entry_add_signall (binding_set, keyval, modifiers, signal_name, slist);
}
free_slist = slist;
while (slist)
{
g_free (slist->data);
slist = slist->next;
}
g_slist_free (free_slist);
}
void
gtk_binding_set_add_path (GtkBindingSet *binding_set,
GtkPathType path_type,
const gchar *path_pattern,
GtkPathPriorityType priority)
{
GtkPatternSpec *pspec;
GSList **slist_p, *slist;
static guint seq_id = 0;
g_return_if_fail (binding_set != NULL);
g_return_if_fail (path_pattern != NULL);
priority &= GTK_PATH_PRIO_MASK;
switch (path_type)
{
case GTK_PATH_WIDGET:
slist_p = &binding_set->widget_path_pspecs;
break;
case GTK_PATH_WIDGET_CLASS:
slist_p = &binding_set->widget_class_pspecs;
break;
case GTK_PATH_CLASS:
slist_p = &binding_set->class_branch_pspecs;
break;
default:
g_assert_not_reached ();
slist_p = NULL;
break;
}
pspec = g_new (GtkPatternSpec, 1);
gtk_pattern_spec_init (pspec, path_pattern);
pspec->seq_id = seq_id++ & 0x0fffffff;
pspec->seq_id |= priority << 28;
pspec->user_data = binding_set;
slist = *slist_p;
while (slist)
{
GtkPatternSpec *tmp_pspec;
tmp_pspec = slist->data;
slist = slist->next;
if (tmp_pspec->pattern_length == pspec->pattern_length &&
g_str_equal (tmp_pspec->pattern_reversed, pspec->pattern_reversed))
{
gtk_pattern_spec_free_segs (pspec);
g_free (pspec);
pspec = NULL;
}
}
if (pspec)
*slist_p = g_slist_prepend (*slist_p, pspec);
}
static inline gboolean
binding_match_activate (GSList *pspec_list,
GtkObject *object,
guint path_length,
gchar *path,
gchar *path_reversed)
{
GSList *slist;
for (slist = pspec_list; slist; slist = slist->next)
{
GtkPatternSpec *pspec;
pspec = slist->data;
if (gtk_pattern_match (pspec, path_length, path, path_reversed))
{
GtkBindingSet *binding_set;
binding_set = pspec->user_data;
gtk_binding_entry_activate (binding_set->current, object);
return TRUE;
}
}
return FALSE;
}
static gint
gtk_binding_pattern_compare (gpointer a,
gpointer b)
{
register GtkPatternSpec *pa = a;
register GtkPatternSpec *pb = b;
return pa->seq_id < pb->seq_id ? -1 : 1;
}
static inline GSList*
gtk_binding_entries_sort_patterns (GtkBindingEntry *entries,
GtkPathType path_id)
{
GSList *patterns;
patterns = NULL;
while (entries)
{
register GtkBindingSet *binding_set;
GSList *slist = NULL;
binding_set = entries->binding_set;
binding_set->current = entries;
switch (path_id)
{
case GTK_PATH_WIDGET:
slist = binding_set->widget_path_pspecs;
break;
case GTK_PATH_WIDGET_CLASS:
slist = binding_set->widget_class_pspecs;
break;
case GTK_PATH_CLASS:
slist = binding_set->class_branch_pspecs;
break;
}
for (; slist; slist = slist->next)
{
GtkPatternSpec *pspec;
pspec = slist->data;
patterns = g_slist_insert_sorted (patterns, pspec, gtk_binding_pattern_compare);
}
entries = entries->hash_next;
}
return patterns;
}
gboolean
gtk_bindings_activate (GtkObject *object,
guint keyval,
guint modifiers)
{
GtkBindingEntry *entries;
GtkWidget *widget;
gboolean handled = FALSE;
g_return_val_if_fail (object != NULL, FALSE);
g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
if (!GTK_IS_WIDGET (object) || GTK_OBJECT_DESTROYED (object))
return FALSE;
widget = GTK_WIDGET (object);
keyval = gdk_keyval_to_lower (keyval);
modifiers = modifiers & BINDING_MOD_MASK ();
entries = binding_ht_lookup_list (keyval, modifiers);
if (!entries)
return FALSE;
if (!handled)
{
guint path_length;
gchar *path, *path_reversed;
GSList *patterns;
gtk_widget_path (widget, &path_length, &path, &path_reversed);
patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET);
handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
g_slist_free (patterns);
g_free (path);
g_free (path_reversed);
}
if (!handled)
{
guint path_length;
gchar *path, *path_reversed;
GSList *patterns;
gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET_CLASS);
handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
g_slist_free (patterns);
g_free (path);
g_free (path_reversed);
}
if (!handled)
{
GSList *patterns;
GtkType class_type;
patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_CLASS);
class_type = GTK_OBJECT_TYPE (object);
while (class_type && !handled)
{
guint path_length;
gchar *path, *path_reversed;
path = gtk_type_name (class_type);
path_reversed = g_strdup (path);
g_strreverse (path_reversed);
path_length = strlen (path);
handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
g_free (path_reversed);
class_type = gtk_type_parent (class_type);
}
g_slist_free (patterns);
}
return handled;
}
/* Patterns
*/
static inline gboolean
gtk_pattern_ph_match (const gchar *match_pattern,
const gchar *match_string)
{
register const gchar *pattern, *string;
register gchar ch;
pattern = match_pattern;
string = match_string;
ch = *pattern;
pattern++;
while (ch)
{
switch (ch)
{
case '?':
if (!*string)
return FALSE;
string++;
break;
case '*':
do
{
ch = *pattern;
pattern++;
if (ch == '?')
{
if (!*string)
return FALSE;
string++;
}
}
while (ch == '*' || ch == '?');
if (!ch)
return TRUE;
do
{
while (ch != *string)
{
if (!*string)
return FALSE;
string++;
}
string++;
if (gtk_pattern_ph_match (pattern, string))
return TRUE;
}
while (*string);
break;
default:
if (ch == *string)
string++;
else
return FALSE;
break;
}
ch = *pattern;
pattern++;
}
return *string == 0;
}
gboolean
gtk_pattern_match (GtkPatternSpec *pspec,
guint string_length,
const gchar *string,
const gchar *string_reversed)
{
g_return_val_if_fail (pspec != NULL, FALSE);
g_return_val_if_fail (string != NULL, FALSE);
g_return_val_if_fail (string_reversed != NULL, FALSE);
switch (pspec->match_type)
{
case GTK_MATCH_ALL:
return gtk_pattern_ph_match (pspec->pattern, string);
case GTK_MATCH_ALL_TAIL:
return gtk_pattern_ph_match (pspec->pattern_reversed, string_reversed);
case GTK_MATCH_HEAD:
if (pspec->pattern_length > string_length)
return FALSE;
else if (pspec->pattern_length == string_length)
return strcmp (pspec->pattern, string) == 0;
else if (pspec->pattern_length)
return strncmp (pspec->pattern, string, pspec->pattern_length) == 0;
else
return TRUE;
case GTK_MATCH_TAIL:
if (pspec->pattern_length > string_length)
return FALSE;
else if (pspec->pattern_length == string_length)
return strcmp (pspec->pattern_reversed, string_reversed) == 0;
else if (pspec->pattern_length)
return strncmp (pspec->pattern_reversed,
string_reversed,
pspec->pattern_length) == 0;
else
return TRUE;
case GTK_MATCH_EXACT:
if (pspec->pattern_length != string_length)
return FALSE;
else
return strcmp (pspec->pattern_reversed, string_reversed) == 0;
default:
g_return_val_if_fail (pspec->match_type < GTK_MATCH_LAST, FALSE);
return FALSE;
}
}
void
gtk_pattern_spec_init (GtkPatternSpec *pspec,
const gchar *pattern)
{
gchar *p;
g_return_if_fail (pspec != NULL);
pspec->match_type = GTK_MATCH_ALL;
pspec->seq_id = 0;
pspec->user_data = NULL;
if (!pattern)
pattern = "";
pspec->pattern = g_strdup (pattern);
pspec->pattern_length = strlen (pspec->pattern);
pspec->pattern_reversed = g_strdup (pspec->pattern);
g_strreverse (pspec->pattern_reversed);
if (pspec->pattern_reversed[0] != '*')
pspec->match_type = GTK_MATCH_ALL_TAIL;
if (strchr (pspec->pattern, '?'))
return;
if (!strchr (pspec->pattern, '*'))
{
pspec->match_type = GTK_MATCH_EXACT;
return;
}
p = pspec->pattern;
while (*p == '*')
p++;
if (p > pspec->pattern &&
!strchr (p, '*'))
{
gchar *t;
pspec->match_type = GTK_MATCH_TAIL;
t = pspec->pattern;
pspec->pattern = g_strdup (p);
g_free (t);
g_free (pspec->pattern_reversed);
pspec->pattern_reversed = g_strdup (pspec->pattern);
g_strreverse (pspec->pattern_reversed);
pspec->pattern_length = strlen (pspec->pattern);
return;
}
p = pspec->pattern_reversed;
while (*p == '*')
p++;
if (p > pspec->pattern_reversed &&
!strchr (p, '*'))
{
gchar *t;
pspec->match_type = GTK_MATCH_HEAD;
t = pspec->pattern_reversed;
pspec->pattern_reversed = g_strdup (p);
g_free (t);
pspec->pattern = g_strdup (pspec->pattern_reversed);
g_strreverse (pspec->pattern);
pspec->pattern_length = strlen (pspec->pattern);
}
}
gboolean
gtk_pattern_match_string (GtkPatternSpec *pspec,
const gchar *string)
{
gchar *string_reversed;
guint length;
gboolean ergo;
g_return_val_if_fail (pspec != NULL, FALSE);
g_return_val_if_fail (string != NULL, FALSE);
length = strlen (string);
string_reversed = g_strdup (string);
g_strreverse (string_reversed);
ergo = gtk_pattern_match (pspec, length, string, string_reversed);
g_free (string_reversed);
return ergo;
}
gboolean
gtk_pattern_match_simple (const gchar *pattern,
const gchar *string)
{
GtkPatternSpec pspec;
gboolean ergo;
g_return_val_if_fail (pattern != NULL, FALSE);
g_return_val_if_fail (string != NULL, FALSE);
gtk_pattern_spec_init (&pspec, pattern);
ergo = gtk_pattern_match_string (&pspec, string);
gtk_pattern_spec_free_segs (&pspec);
return ergo;
}
void
gtk_pattern_spec_free_segs (GtkPatternSpec *pspec)
{
g_return_if_fail (pspec != NULL);
g_free (pspec->pattern);
pspec->pattern = NULL;
g_free (pspec->pattern_reversed);
pspec->pattern_reversed = NULL;
}