$(MAKE) -C $(top_builddir)/src
test: ibus-daemon
- $(builddir)/ibus-daemon -v
+ $(ENV) \
+ G_DEBUG=fatal_warnings \
+ $(builddir)/ibus-daemon -v
g_assert (g_list_find (dbus->connections, connection) == NULL);
- g_object_ref (connection);
+ g_object_ref_sink (connection);
dbus->connections = g_list_append (dbus->connections, connection);
g_signal_connect (connection,
if (connection != skip_connection) {
ibus_connection_send (IBUS_CONNECTION (connection), message);
}
- g_object_unref (connection);
}
g_list_free (recipients);
}
g_return_val_if_fail (g_hash_table_lookup (dbus->objects, path) == NULL, FALSE);
- g_object_ref (object);
+ g_object_ref_sink (object);
g_hash_table_insert (dbus->objects, (gpointer)path, object);
g_signal_connect (object, "destroy", G_CALLBACK (_object_destroy_cb), dbus);
NULL);
engine->desc = desc;
- g_object_ref (desc);
+ g_object_ref_sink (desc);
if (desc->layout != NULL && desc->layout[0] != '\0') {
- engine->keymap = ibus_keymap_new (desc->layout);
+ engine->keymap = ibus_keymap_get (desc->layout);
}
if (engine->keymap == NULL) {
- engine->keymap = ibus_keymap_new ("us");
+ engine->keymap = ibus_keymap_get ("us");
}
return engine;
bus_engine_proxy_init (BusEngineProxy *engine)
{
engine->enabled = FALSE;
- engine->prop_list = NULL;
engine->desc = NULL;
engine->keymap = NULL;
}
static void
bus_engine_proxy_real_destroy (BusEngineProxy *engine)
{
- if (engine->prop_list) {
- g_object_unref (engine->prop_list);
- engine->prop_list = NULL;
- }
-
if (ibus_proxy_get_connection ((IBusProxy *) engine)) {
ibus_proxy_call ((IBusProxy *) engine,
"Destroy",
g_signal_emit (engine, engine_signals[UPDATE_PREEDIT_TEXT], 0,
text, cursor_pos, visible);
- g_object_unref (text);
+ if (g_object_is_floating (text))
+ g_object_unref (text);
}
else if (g_strcmp0 (name, "UpdateAuxiliaryText") == 0) {
IBusText *text;
goto failed;
g_signal_emit (engine, engine_signals[UPDATE_AUXILIARY_TEXT], 0, text, visible);
- g_object_unref (text);
+ if (g_object_is_floating (text))
+ g_object_unref (text);
}
else if (g_strcmp0 (name, "UpdateLookupTable") == 0) {
IBusLookupTable *table;
goto failed;
g_signal_emit (engine, engine_signals[UPDATE_LOOKUP_TABLE], 0, table, visible);
- g_object_unref (table);
+ if (g_object_is_floating (table))
+ g_object_unref (table);
}
else if (g_strcmp0 (name, "RegisterProperties") == 0) {
gboolean retval;
-
- if (engine->prop_list) {
- g_object_unref (engine->prop_list);
- engine->prop_list = NULL;
- }
+ IBusPropList *prop_list;
retval = ibus_message_get_args (message,
&error,
- IBUS_TYPE_PROP_LIST, &engine->prop_list,
+ IBUS_TYPE_PROP_LIST, &prop_list,
G_TYPE_INVALID);
if (!retval) {
- engine->prop_list = NULL;
goto failed;
}
- g_signal_emit (engine, engine_signals[REGISTER_PROPERTIES], 0, engine->prop_list);
+ g_signal_emit (engine, engine_signals[REGISTER_PROPERTIES], 0, prop_list);
+
+ if (g_object_is_floating (prop_list))
+ g_object_unref (prop_list);
+
}
else if (g_strcmp0 (name, "UpdateProperty") == 0) {
IBusProperty *prop;
goto failed;
g_signal_emit (engine, engine_signals[UPDATE_PROPERTY], 0, prop);
- g_object_unref (prop);
+ if (g_object_is_floating (prop))
+ g_object_unref (prop);
}
else
return FALSE;
"connection", connection,
NULL);
- g_object_ref (component);
+ g_object_ref_sink (component);
factory->component = component;
g_object_set_data ((GObject *)factory->component, "factory", factory);
g_assert (ibus->config == config);
+ g_object_unref (ibus->config);
ibus->config = NULL;
- g_object_unref (config);
}
static void
g_return_if_fail (connection != NULL);
ibus->panel = bus_panel_proxy_new (connection);
+ g_object_ref_sink (ibus->panel);
g_signal_connect (ibus->panel,
"destroy",
"path", IBUS_PATH_CONFIG,
"connection", connection,
NULL);
+ g_object_ref_sink (ibus->config);
g_signal_connect (ibus->config,
"value-changed",
if (factory) {
bus_ibus_impl_add_factory (ibus, factory);
- g_object_unref (factory);
}
}
#endif
ibus->hotkey_profile = ibus_hotkey_profile_new ();
- ibus->keymap = ibus_keymap_new ("us");
+ ibus->keymap = ibus_keymap_get ("us");
ibus->use_sys_layout = FALSE;
}
bus_input_context_set_engine (context, engine);
- g_object_unref (engine);
}
static void
if (next_desc != NULL) {
engine = bus_ibus_impl_create_engine (next_desc);
bus_input_context_set_engine (context, engine);
- g_object_unref (engine);
}
}
}
context = bus_input_context_new (connection, client);
+ g_object_ref_sink (context);
ibus->contexts = g_list_append (ibus->contexts, context);
static const struct {
g_assert (BUS_IS_IBUS_IMPL (ibus));
g_assert (BUS_IS_FACTORY_PROXY (factory));
- g_object_ref (factory);
+ g_object_ref_sink (factory);
ibus->factory_list = g_list_append (ibus->factory_list, factory);
g_signal_connect (factory, "destroy", G_CALLBACK (_factory_destroy_cb), ibus);
return reply;
}
+ g_object_ref_sink (component);
factory = bus_factory_proxy_new (component, connection);
if (factory == NULL) {
}
bus_ibus_impl_add_factory (ibus, factory);
- g_object_unref (factory);
engines = ibus_component_get_engines (component);
IBUS_CONNECTION (connection));
#endif
- g_object_ref (connection);
+ g_object_ref_sink (connection);
context->connection = connection;
context->client = g_strdup (client);
0);
text_empty = ibus_text_new_from_string ("");
+ g_object_ref_sink (text_empty);
lookup_table_empty = ibus_lookup_table_new (9, 0, FALSE, FALSE);
+ g_object_ref_sink (lookup_table_empty);
props_empty = ibus_prop_list_new ();
+ g_object_ref_sink (props_empty);
}
static void
context->w = 0;
context->h = 0;
- g_object_ref (text_empty);
+ g_object_ref_sink (text_empty);
context->preedit_text = text_empty;
context->preedit_cursor_pos = 0;
context->preedit_visible = FALSE;
- g_object_ref (text_empty);
+ g_object_ref_sink (text_empty);
context->auxiliary_text = text_empty;
context->auxiliary_visible = FALSE;
- g_object_ref (lookup_table_empty);
+ g_object_ref_sink (lookup_table_empty);
context->lookup_table = lookup_table_empty;
context->lookup_table_visible = FALSE;
- g_object_ref (props_empty);
}
static void
g_object_unref (context->preedit_text);
}
- context->preedit_text = (IBusText *) g_object_ref (text ? text : text_empty);
+ context->preedit_text = (IBusText *) g_object_ref_sink (text ? text : text_empty);
context->preedit_cursor_pos = cursor_pos;
context->preedit_visible = visible;
g_object_unref (context->auxiliary_text);
}
- context->auxiliary_text = (IBusText *) g_object_ref (text ? text : text_empty);
+ context->auxiliary_text = (IBusText *) g_object_ref_sink (text ? text : text_empty);
context->auxiliary_visible = visible;
if (context->capabilities & IBUS_CAP_AUXILIARY_TEXT) {
g_object_unref (context->lookup_table);
}
- context->lookup_table = (IBusLookupTable *) g_object_ref (table ? table : lookup_table_empty);
+ context->lookup_table = (IBusLookupTable *) g_object_ref_sink (table ? table : lookup_table_empty);
context->lookup_table_visible = visible;
if (context->capabilities & IBUS_CAP_LOOKUP_TABLE) {
else {
gint i;
context->engine = engine;
- g_object_ref (context->engine);
+ g_object_ref_sink (context->engine);
for (i = 0; signals[i].name != NULL; i++) {
g_signal_connect (context->engine,
recipient = g_slice_new (BusRecipient);
- g_object_ref (connection);
+ g_object_ref_sink (connection);
recipient->connection = connection;
recipient->refcount = 1;
for (link = rule->recipients; link != NULL; link = link->next) {
BusRecipient *recipient = (BusRecipient *) link->data;
- g_object_ref (recipient->connection);
recipients = g_list_append (recipients, recipient->connection);
}
if (panel->focused_context != NULL)
bus_panel_proxy_focus_out (panel, panel->focused_context);
- g_object_ref (context);
+ g_object_ref_sink (context);
panel->focused_context = context;
const gchar *path = ibus_service_get_path ((IBusService *)context);
IBusObservedPath *path;
path = ibus_observed_path_new_from_xml_node (pp->data, FALSE);
if (path) {
+ g_object_ref_sink (path);
registry->observed_paths = g_list_append (registry->observed_paths, path);
}
}
IBusComponent *component;
component = ibus_component_new_from_xml_node (pp->data);
if (component) {
+ g_object_ref_sink (component);
registry->components = g_list_append (registry->components, component);
}
}
ibusimcontext->ibuscontext = ibus_bus_create_input_context (_bus, "test");
g_return_if_fail (ibusimcontext->ibuscontext != NULL);
+ g_object_ref_sink (ibusimcontext->ibuscontext);
g_signal_connect (ibusimcontext->ibuscontext,
"commit-text",
ibus_message_iter_next (&array_iter);
ibus_attr_list_append (attr_list, attr);
- g_object_unref (attr);
}
ibus_message_iter_next (iter);
g_assert (IBUS_IS_ATTR_LIST (attr_list));
g_assert (IBUS_IS_ATTRIBUTE (attr));
- g_object_ref (attr);
+ g_object_ref_sink (attr);
g_array_append_val (attr_list->attributes, attr);
}
g_return_val_if_fail (retval, FALSE);
ibus_message_iter_next (&array_iter);
+ g_object_ref_sink (path);
component->observed_paths = g_list_append (component->observed_paths, path);
}
ibus_message_iter_next (iter);
IBusObservedPath *path;
path = ibus_observed_path_new_from_xml_node ((XMLNode *)p->data, access_fs);
+ g_object_ref_sink (path);
component->observed_paths = g_list_append (component->observed_paths, path);
if (access_fs && path->is_dir && path->is_exist) {
IBusObservedPath *p;
p = ibus_observed_path_new (path, access_fs);
+ g_object_ref_sink (p);
component->observed_paths = g_list_append (component->observed_paths, p);
if (access_fs && p->is_dir && p->is_exist) {
g_assert (IBUS_IS_COMPONENT (component));
g_assert (IBUS_IS_ENGINE_DESC (engine));
+ g_object_ref_sink (engine);
component->engines = g_list_append (component->engines, engine);
g_object_set_data ((GObject *)engine, "component", component);
}
else {
g_value_set_object (value, NULL);
}
- g_list_foreach (connections, (GFunc) g_object_unref, NULL);
g_list_free (connections);
}
break;
g_warn_if_fail (result);
}
+static void
+_connection_destroy_cb (IBusConnection *connection,
+ gpointer user_data)
+{
+ g_hash_table_remove (_connections, user_data);
+ g_object_unref (connection);
+}
+
IBusConnection *
ibus_connection_open (const gchar *address)
{
}
connection = ibus_connection_new ();
+ g_object_ref_sink (connection);
+
ibus_connection_set_connection (connection, dbus_connection, TRUE);
- g_hash_table_insert (_connections, dbus_connection, connection);
+ g_hash_table_insert (_connections, dbus_connection, g_object_ref (connection));
+
+ g_signal_connect (connection, "destroy", G_CALLBACK (_connection_destroy_cb), dbus_connection);
return connection;
}
case PROP_CONNECTION:
priv->connection = g_value_get_object (value);
- g_object_ref (priv->connection);
+ g_object_ref_sink (priv->connection);
ibus_service_add_to_connection ((IBusService *) engine,
priv->connection);
break;
NULL);
priv = IBUS_FACTORY_GET_PRIVATE (factory);
- priv->connection = g_object_ref (connection);
+ priv->connection = g_object_ref_sink (connection);
ibus_service_add_to_connection ((IBusService *)factory, connection);
return factory;
G_TYPE_INVALID);
if (retval) {
g_signal_emit (context, context_signals[COMMIT_TEXT], 0, text);
- g_object_unref (text);
+ if (g_object_is_floating (text))
+ g_object_unref (text);
}
break;
}
text,
cursor_pos,
visible);
- g_object_unref (text);
+ if (g_object_is_floating (text))
+ g_object_unref (text);
}
break;
}
0,
text,
visible);
- g_object_unref (text);
+ if (g_object_is_floating (text))
+ g_object_unref (text);
}
}
else if (g_strcmp0 (name, "UpdateLookupTable") == 0) {
0,
table,
visible);
- g_object_unref (table);
+ if (g_object_is_floating (table))
+ g_object_unref (table);
}
}
else if (g_strcmp0 (name, "RegisterProperties") == 0) {
context_signals[REGISTER_PROPERTIES],
0,
prop_list);
- g_object_unref (prop_list);
+ if (g_object_is_floating (prop_list))
+ g_object_unref (prop_list);
}
}
else if (g_strcmp0 (name, "UpdateProperty") == 0) {
G_TYPE_INVALID);
if (retval) {
g_signal_emit (context, context_signals[UPDATE_PROPERTY], 0, prop);
- g_object_unref (prop);
+ if (g_object_is_floating (prop))
+ g_object_unref (prop);
}
}
else if (g_strcmp0 (name, "ForwardKeyEvent") == 0) {
gpointer user_data)
{
g_hash_table_remove (keymaps, keymap->name);
+ g_object_unref (keymap);
}
IBusKeymap *
-ibus_keymap_new (const gchar *name)
+ibus_keymap_get (const gchar *name)
{
g_assert (name != NULL);
}
keymap = g_object_new (IBUS_TYPE_KEYMAP, NULL);
+ g_object_ref_sink (keymap);
+
if (!ibus_keymap_load (name, keymap->keymap)) {
g_object_unref (keymap);
return NULL;
return keymap;
}
-
guint32
ibus_keymap_lookup_keysym (IBusKeymap *keymap,
guint16 keycode,
GType ibus_keymap_get_type (void);
/**
- * ibus_keymap_new:
+ * ibus_keymap_get:
* @name: The keymap file to be loaded, such as 'us', 'jp'.
- * @returns: A newly allocated IBusKeymap; or NULL if failed.
+ * @returns: An IBusKeymap associated with the giving name; or NULL if failed.
*
- * New an IBusKeymap.
+ * Get an IBusKeymap associated with the giving name.
*
* This function loads the keymap file specified in @name
* in the IBUS_DATA_DIR/keymaps directory.
*/
-IBusKeymap *ibus_keymap_new (const gchar *name);
+IBusKeymap *ibus_keymap_get (const gchar *name);
/**
* ibus_keymap_lookup_keysym:
ibus_message_iter_next (&array_iter);
ibus_lookup_table_append_candidate (table, text);
- g_object_unref (text);
}
ibus_message_iter_next (iter);
ibus_message_iter_next (&array_iter);
ibus_lookup_table_append_label (table, text);
- g_object_unref (text);
}
ibus_message_iter_next (iter);
text = (IBusText *) ibus_serializable_copy ((IBusSerializable *) text);
ibus_lookup_table_append_candidate (dest, text);
- g_object_unref (text);
}
// copy labels
text = (IBusText *) ibus_serializable_copy ((IBusSerializable *) text);
ibus_lookup_table_append_label (dest, text);
- g_object_unref (text);
}
return TRUE;
g_assert (IBUS_IS_LOOKUP_TABLE (table));
g_assert (IBUS_IS_TEXT (text));
- g_object_ref (text);
+ g_object_ref_sink (text);
g_array_append_val (table->candidates, text);
}
g_assert (IBUS_IS_LOOKUP_TABLE (table));
g_assert (IBUS_IS_TEXT (text));
- g_object_ref (text);
+ g_object_ref_sink (text);
g_array_append_val (table->labels, text);
}
IBusObservedPath *sub;
sub = g_object_new (IBUS_TYPE_OBSERVED_PATH, NULL);
+ g_object_ref_sink (sub);
sub->path = g_build_filename (path->path, name, NULL);
ibus_observed_path_fill_stat (sub);
static gboolean
ibus_observed_path_parse_xml_node (IBusObservedPath *path,
- XMLNode *node)
+ XMLNode *node)
{
g_assert (IBUS_IS_OBSERVED_PATH (path));
g_assert (node);
else {
g_value_set_object (value, NULL);
}
- g_list_foreach (connections, (GFunc) g_object_unref, NULL);
g_list_free (connections);
}
break;
else {
reply = ibus_message_new_method_return (message);
}
+
+ if (prop_list != NULL && g_object_is_floating (prop_list))
+ g_object_unref (prop_list);
}
else if (ibus_message_is_method_call (message, IBUS_INTERFACE_PANEL, "UpdateAuxiliaryText")) {
IBusText *text = NULL;
else {
reply = ibus_message_new_method_return (message);
}
+
+ if (text != NULL && g_object_is_floating (text))
+ g_object_unref (text);
}
else if (ibus_message_is_method_call (message, IBUS_INTERFACE_PANEL, "UpdateLookupTable")) {
IBusLookupTable *table = NULL;
else {
reply = ibus_message_new_method_return (message);
}
+
+ if (table != NULL && g_object_is_floating (table))
+ g_object_unref (table);
}
else if (ibus_message_is_method_call (message, IBUS_INTERFACE_PANEL, "UpdatePreeditText")) {
IBusText *text = NULL;
else {
reply = ibus_message_new_method_return (message);
}
+
+ if (text != NULL && g_object_is_floating (text))
+ g_object_unref (text);
}
else if (ibus_message_is_method_call (message, IBUS_INTERFACE_PANEL, "UpdateProperty")) {
IBusProperty *property = NULL;
else {
reply = ibus_message_new_method_return (message);
}
+
+ if (property != NULL && g_object_is_floating (property))
+ g_object_unref (property);
}
else if (ibus_message_is_method_call (message, IBUS_INTERFACE_PANEL, "SetCursorLocation")) {
guint x, y, w, h;
ibus_message_iter_next (iter);
retval = ibus_message_iter_get (iter, IBUS_TYPE_TEXT, &prop->label);
+ g_object_ref_sink (prop->label);
g_return_val_if_fail (retval, FALSE);
ibus_message_iter_next (iter);
prop->icon = g_strdup (p);
retval = ibus_message_iter_get (iter, IBUS_TYPE_TEXT, &prop->tooltip);
+ g_object_ref_sink (prop->tooltip);
g_return_val_if_fail (retval, FALSE);
ibus_message_iter_next (iter);
ibus_message_iter_next (iter);
retval = ibus_message_iter_get (iter, IBUS_TYPE_PROP_LIST, &prop->sub_props);
+ g_object_ref_sink (prop->sub_props);
g_return_val_if_fail (retval, FALSE);
ibus_message_iter_next (iter);
prop->label = ibus_text_new_from_static_string ("");
}
else {
- prop->label = g_object_ref (label);
+ prop->label = g_object_ref_sink (label);
}
}
if (tooltip == NULL) {
prop->tooltip = ibus_text_new_from_static_string ("");
+ g_object_ref_sink (prop->tooltip);
}
else {
- prop->tooltip = g_object_ref (tooltip);
+ prop->tooltip = tooltip;
+ g_object_ref_sink (prop->tooltip);
}
}
}
if (prop_list) {
- g_object_ref (prop_list);
prop->sub_props = prop_list;
+ g_object_ref_sink (prop_list);
}
- else
+ else {
prop->sub_props = ibus_prop_list_new ();
+ g_object_ref_sink (prop->sub_props);
+ }
}
gboolean
if (prop->label) {
g_object_unref (prop->label);
}
- prop->label = (IBusText *) g_object_ref (prop_update->label);
+ prop->label = (IBusText *) g_object_ref_sink (prop_update->label);
if (prop->tooltip) {
g_object_unref (prop->tooltip);
}
- prop->tooltip = (IBusText *) g_object_ref (prop_update->tooltip);
+ prop->tooltip = (IBusText *) g_object_ref_sink (prop_update->tooltip);
prop->visible = prop_update->visible;
prop->state = prop_update->state;
prop->sensitive = prop_update->sensitive;
{
gboolean retval;
IBusMessageIter array_iter;
- IBusSerializable *object;
+ IBusProperty *prop;
retval = parent_class->deserialize ((IBusSerializable *) prop_list, iter);
g_return_val_if_fail (retval, FALSE);
g_return_val_if_fail (retval, FALSE);
while (ibus_message_iter_get_arg_type (&array_iter) != G_TYPE_INVALID) {
- retval = ibus_message_iter_get (&array_iter, IBUS_TYPE_PROPERTY, &object);
+ retval = ibus_message_iter_get (&array_iter, IBUS_TYPE_PROPERTY, &prop);
g_return_val_if_fail (retval, FALSE);
ibus_message_iter_next (&array_iter);
- ibus_prop_list_append (prop_list, (IBusProperty *)object);
- g_object_unref (object);
+ ibus_prop_list_append (prop_list, prop);
}
ibus_message_iter_next (iter);
while ((prop = ibus_prop_list_get ((IBusPropList *)src, i)) != NULL) {
prop = (IBusProperty *) ibus_serializable_copy ((IBusSerializable *) prop);
ibus_prop_list_append (dest, prop);
- g_object_unref (prop);
i ++;
}
return TRUE;
g_assert (IBUS_IS_PROP_LIST (prop_list));
g_assert (IBUS_IS_PROPERTY (prop));
- g_object_ref (prop);
+ g_object_ref_sink (prop);
g_array_append_val (prop_list->properties, prop);
}
case PROP_CONNECTION:
g_assert (priv->connection == NULL);
priv->connection = IBUS_CONNECTION (g_value_get_object (value));
- g_object_ref (priv->connection);
+ g_object_ref_sink (priv->connection);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec);
ibus_connection_set_connection (connection, new_connection, FALSE);
g_signal_emit (server, server_signals[NEW_CONNECTION], 0, connection);
- g_object_unref (connection);
+
+ if (g_object_is_floating (connection)) {
+ /* release connection if it is still floating */
+ g_object_unref (connection);
+ }
}
static gboolean
g_return_val_if_fail (priv->path != NULL, FALSE);
g_return_val_if_fail (g_list_find (priv->connections, connection) == NULL, FALSE);
- g_object_ref (connection);
+ g_object_ref_sink (connection);
retval = ibus_connection_register_object_path (connection, priv->path,
(IBusMessageFunc) _service_message_function, service);
IBusServicePrivate *priv;
priv = IBUS_SERVICE_GET_PRIVATE (service);
- GList *l;
-
- l = g_list_copy (priv->connections);
- g_list_foreach (l, (GFunc) g_object_ref, NULL);
- return l;
+ return g_list_copy (priv->connections);
}
gboolean
retval = ibus_message_iter_append (iter, G_TYPE_STRING, &text->text);
g_return_val_if_fail (retval, FALSE);
- if (text->attrs == NULL)
+ if (text->attrs == NULL) {
text->attrs = ibus_attr_list_new ();
+ g_object_ref_sink (text->attrs);
+ }
retval = ibus_message_iter_append (iter, IBUS_TYPE_ATTR_LIST, &text->attrs);
g_return_val_if_fail (retval, FALSE);
}
retval = ibus_message_iter_get (iter, IBUS_TYPE_ATTR_LIST, &text->attrs);
+ g_object_ref_sink (text->attrs);
g_return_val_if_fail (retval, FALSE);
ibus_message_iter_next (iter);
dest->text = g_strdup (src->text);
dest->is_static = FALSE;
- if (src->attrs)
+ if (src->attrs) {
dest->attrs = (IBusAttrList *)ibus_serializable_copy ((IBusSerializable *)src->attrs);
+ g_object_ref_sink (dest->attrs);
+ }
return TRUE;
}
attr = ibus_attribute_new (type, value, start_index, end_index);
ibus_attr_list_append (text->attrs, attr);
- g_object_unref (attr);
}
guint
g_type_init ();
- IBusKeymap *keymap = ibus_keymap_new (argc > 1 ? argv[1] : "us");
+ IBusKeymap *keymap = ibus_keymap_get (argc > 1 ? argv[1] : "us");
g_object_unref (keymap);
return 0;