diff options
Diffstat (limited to 'src')
75 files changed, 21854 insertions, 0 deletions
diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..f39eb28 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,12 @@ +ibusmarshalers.c +ibusmarshalers.h +test-attribute +test-bus +test-engine +test-keynames +test-lookuptable +test-proxy +test-server +test-text +stamp-ibusenumtypes.h +stamp-ibusmarshalers.h diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..e8c6614 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,209 @@ +# vim:set noet ts=4: +# +# ibus - The Input Bus +# +# Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place, Suite 330, +# Boston, MA 02111-1307 USA + +INCLUDES = \ + -I$(top_srcdir) \ + $(NULL) + +# ibus library +lib_LTLIBRARIES = libibus.la +ibus_built_public_h_sources = \ + ibusmarshalers.h \ + ibusenumtypes.h \ + $(NULl) +ibus_built_c_sources = \ + ibusmarshalers.c \ + ibusenumtypes.c \ + $(NULL) +ibus_built_sources = \ + $(ibus_built_public_h_sources) \ + $(ibus_built_c_sources) \ + $(NULL) +ibus_public_h_sources = \ + ibus.h \ + ibusshare.h \ + ibusdebug.h \ + ibusobject.h \ + ibusserializable.h \ + ibusconnection.h \ + ibusserver.h \ + ibusproxy.h \ + ibusservice.h \ + ibusfactory.h \ + ibusengine.h \ + ibustext.h \ + ibusattribute.h \ + ibusproperty.h \ + ibuslookuptable.h \ + ibusinputcontext.h \ + ibusconfig.h \ + ibusconfigservice.h \ + ibusmessage.h \ + ibuspendingcall.h \ + ibuserror.h \ + ibuskeysyms.h \ + ibustypes.h \ + ibusbus.h \ + ibushotkey.h \ + ibusxml.h \ + ibusenginedesc.h \ + ibusobservedpath.h \ + ibuscomponent.h \ + $(NULL) +ibus_h_sources = \ + ibusinternal.h \ + ibusconfigprivate.h \ + keyname-table.h \ + $(ibus_public_h_sources) \ + $(ibus_built_public_h_sources) \ + $(NULL) +ibus_c_sources = \ + ibusshare.c \ + ibusinternal.c \ + ibusobject.c \ + ibusserializable.c \ + ibusconnection.c \ + ibusserver.c \ + ibusproxy.c \ + ibusservice.c \ + ibusfactory.c \ + ibusengine.c \ + ibustext.c \ + ibusattribute.c \ + ibusproperty.c \ + ibuslookuptable.c \ + ibusinputcontext.c \ + ibusconfig.c \ + ibusconfigservice.c \ + ibusmessage.c \ + ibuspendingcall.c \ + ibuserror.c \ + ibusbus.c \ + ibuskeynames.c \ + ibushotkey.c \ + ibusxml.c \ + ibusenginedesc.c \ + ibusobservedpath.c \ + ibuscomponent.c \ + $(ibus_built_c_sources) \ + $(NULL) + +ibusincludedir = $(includedir)/ibus-1.0 +ibusinclude_HEADERS = \ + $(ibus_public_h_sources) \ + $(ibus_built_public_h_sources) \ + $(NULL) + +libibus_la_SOURCES = \ + $(ibus_h_sources) \ + $(ibus_c_sources) \ + $(NULL) +libibus_la_CFLAGS = \ + @X11_CFLAGS@ \ + @GLIB2_CFLAGS@ \ + @GOBJECT2_CFLAGS@ \ + @GIO2_CFLAGS@ \ + @DBUS_CFLAGS@ \ + -DG_LOG_DOMAIN=\"IBUS\" \ + $(NULL) +libibus_la_LDFLAGS = \ + @X11_LIBS@ \ + @GLIB2_LIBS@ \ + @GOBJECT2_LIBS@ \ + @GIO2_LIBS@ \ + @DBUS_LIBS@ \ + -version-info @LT_VERSION_INFO@ \ + $(NULL) + +BUILT_SOURCES = \ + $(ibus_built_sources) \ + $(NULL) + + +# test programs +DEPS = \ + libibus.la \ + $(NULL) +AM_CFLAGS = \ + @X11_CFLAGS@ \ + @GLIB2_CFLAGS@ \ + @GOBJECT2_CFLAGS@ \ + @GIO2_CFLAGS@ \ + @DBUS_CFLAGS@ \ + -DG_LOG_DOMAIN=\"IBUS\" \ + $(NULL) +AM_LDFLAGS = \ + $(DEPS) \ + $(NULL) + +TESTS = \ + test-text \ + test-keynames \ + test-attribute \ + test-lookuptable \ + $(NULL) +noinst_PROGRAMS = $(TESTS) +test_text_DEPENDENCIES = $(DEPS) +test_keynames_DEPENDENCIES = $(DEPS) +test_attribute_DEPENDENCIES = $(DEPS) +test_lookuptable_DEPENDENCIES = $(DEPS) + +# gen enum types +ibusenumtypes.h: stamp-ibusenumtypes.h + @true +stamp-ibusenumtypes.h: @REBUILD@ $(ibus_public_h_sources) ibusenumtypes.h.template + ( cd $(srcdir) && $(GLIB_MKENUMS) --template ibusenumtypes.h.template \ + $(ibus_public_h_sources) ) | sed 's/i_bus_/ibus_/g' | sed 's/I_TYPE_BUS_/IBUS_TYPE_/g' >> xgen-geth \ + && (cmp -s xgen-geth ibusenumtypes.h || cp xgen-geth ibusenumtypes.h ) \ + && rm -f xgen-geth \ + && echo timestamp > $(@F) +ibusenumtypes.c: @REBUILD@ $(ibus_public_h_sources) ibusenumtypes.c.template + ( cd $(srcdir) && $(GLIB_MKENUMS) --template ibusenumtypes.c.template \ + $(ibus_public_h_sources) ) | sed 's/i_bus_/ibus_/g' | sed 's/I_TYPE_BUS_/IBUS_TYPE_/g' > xgen-getc \ + && cp xgen-getc ibusenumtypes.c \ + && rm -f xgen-getc + +# gen marshal +ibusmarshalers.h: stamp-ibusmarshalers.h + @true +stamp-ibusmarshalers.h: ibusmarshalers.list + $(GLIB_GENMARSHAL) --prefix=ibus_marshal $(srcdir)/ibusmarshalers.list --header >> xgen-gmh \ + && (cmp -s xgen-gmh ibusmarshalers.h || cp xgen-gmh ibusmarshalers.h) \ + && rm -f xgen-gmh \ + && echo timestamp > $(@F) +ibusmarshalers.c: ibusmarshalers.list + (echo "#include \"ibusmarshalers.h\""; \ + $(GLIB_GENMARSHAL) --prefix=ibus_marshal $(srcdir)/ibusmarshalers.list --body; \ + echo ) >> xgen-gmc \ + && cp xgen-gmc ibusmarshalers.c \ + && rm -f xgen-gmc + +EXTRA_DIST = \ + ibusmarshalers.list \ + ibusenumtypes.h.template \ + ibusenumtypes.c.template \ + $(NULL) + +CLEANFILES = \ + $(BUILT_SOURCES) \ + stamp-ibusmarshalers.h \ + stamp-ibusenumtypes.h \ + $(NULL) diff --git a/src/ibus.h b/src/ibus.h new file mode 100644 index 0000000..23b270a --- /dev/null +++ b/src/ibus.h @@ -0,0 +1,51 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_H_ +#define __IBUS_H_ + +#include <ibusshare.h> +#include <ibusobject.h> +#include <ibusserializable.h> +#include <ibustext.h> +#include <ibusconnection.h> +#include <ibusserver.h> +#include <ibusproxy.h> +#include <ibusservice.h> +#include <ibusfactory.h> +#include <ibusengine.h> +#include <ibusattribute.h> +#include <ibusproperty.h> +#include <ibuslookuptable.h> +#include <ibusbus.h> +#include <ibuskeysyms.h> +#include <ibusmessage.h> +#include <ibuspendingcall.h> +#include <ibuserror.h> +#include <ibusenumtypes.h> +#include <ibushotkey.h> +#include <ibusxml.h> +#include <ibusenginedesc.h> +#include <ibusobservedpath.h> +#include <ibuscomponent.h> +#include <ibusconfig.h> +#include <ibusconfigservice.h> + +#endif + diff --git a/src/ibusattribute.c b/src/ibusattribute.c new file mode 100644 index 0000000..7b41ab2 --- /dev/null +++ b/src/ibusattribute.c @@ -0,0 +1,433 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibusattribute.h" + +/* functions prototype */ +static void ibus_attribute_class_init (IBusAttributeClass *klass); +static void ibus_attribute_init (IBusAttribute *attr); +// static void ibus_attribute_destroy (IBusAttribute *attr); +static gboolean ibus_attribute_serialize (IBusAttribute *attr, + IBusMessageIter *iter); +static gboolean ibus_attribute_deserialize (IBusAttribute *attr, + IBusMessageIter *iter); +static gboolean ibus_attribute_copy (IBusAttribute *dest, + const IBusAttribute *src); + +static void ibus_attr_list_class_init (IBusAttrListClass *klass); +static void ibus_attr_list_init (IBusAttrList *attr_list); +static void ibus_attr_list_destroy (IBusAttrList *attr_list); +static gboolean ibus_attr_list_serialize (IBusAttrList *attr_list, + IBusMessageIter *iter); +static gboolean ibus_attr_list_deserialize (IBusAttrList *attr_list, + IBusMessageIter *iter); +static gboolean ibus_attr_list_copy (IBusAttrList *dest, + const IBusAttrList *src); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_attribute_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusAttributeClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_attribute_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusAttribute), + 0, + (GInstanceInitFunc) ibus_attribute_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusAttribute", + &type_info, + 0); + } + + return type; +} + +static void +ibus_attribute_class_init (IBusAttributeClass *klass) +{ + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + // object_class->destroy = (IBusObjectDestroyFunc) ibus_attribute_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_attribute_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_attribute_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_attribute_copy; + + g_string_append (serializable_class->signature, "uuuu"); +} + +static void +ibus_attribute_init (IBusAttribute *attr) +{ +} + +// static void +// ibus_attribute_destroy (IBusAttribute *attr) +// { +// IBUS_OBJECT (parent_class)->destroy ((IBusObject *)attr); +// } + +static gboolean +ibus_attribute_serialize (IBusAttribute *attr, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *) attr, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_ATTRIBUTE (attr), FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &attr->type); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &attr->value); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &attr->start_index); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &attr->end_index); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_attribute_deserialize (IBusAttribute *attr, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->deserialize ((IBusSerializable *) attr, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_ATTRIBUTE (attr), FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &attr->type); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &attr->value); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &attr->start_index); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &attr->end_index); + g_return_val_if_fail (retval, FALSE); + + return TRUE; + +} + +static gboolean +ibus_attribute_copy (IBusAttribute *dest, + const IBusAttribute *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_ATTRIBUTE (dest), FALSE); + g_return_val_if_fail (IBUS_IS_ATTRIBUTE (src), FALSE); + + dest->type = src->type; + dest->value = src->value; + dest->start_index = src->start_index; + dest->end_index = src->end_index; + + return TRUE; +} + +IBusAttribute * +ibus_attribute_new (guint type, + guint value, + guint start_index, + guint end_index) +{ + g_return_val_if_fail ( + type == IBUS_ATTR_TYPE_UNDERLINE || + type == IBUS_ATTR_TYPE_FOREGROUND || + type == IBUS_ATTR_TYPE_BACKGROUND, NULL); + + IBusAttribute *attr = IBUS_ATTRIBUTE (g_object_new (IBUS_TYPE_ATTRIBUTE, 0)); + + attr->type = type; + attr->value = value; + attr->start_index = start_index; + attr->end_index = end_index; + + return attr; +} + +IBusAttribute * +ibus_attr_underline_new (guint underline_type, + guint start_index, + guint end_index) +{ + g_return_val_if_fail ( + underline_type == IBUS_ATTR_UNDERLINE_NONE || + underline_type == IBUS_ATTR_UNDERLINE_SINGLE || + underline_type == IBUS_ATTR_UNDERLINE_DOUBLE || + underline_type == IBUS_ATTR_UNDERLINE_LOW, NULL); + + return ibus_attribute_new (IBUS_ATTR_TYPE_UNDERLINE, + underline_type, + start_index, + end_index); +} + +IBusAttribute * +ibus_attr_foreground_new (guint color, + guint start_index, + guint end_index) +{ + return ibus_attribute_new (IBUS_ATTR_TYPE_FOREGROUND, + color, + start_index, + end_index); +} + +IBusAttribute * +ibus_attr_background_new (guint color, + guint start_index, + guint end_index) +{ + return ibus_attribute_new (IBUS_ATTR_TYPE_BACKGROUND, + color, + start_index, + end_index); +} + +GType +ibus_attr_list_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusAttrListClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_attr_list_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusAttrList), + 0, + (GInstanceInitFunc) ibus_attr_list_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusAttrList", + &type_info, + 0); + } + + return type; +} + +static void +ibus_attr_list_class_init (IBusAttrListClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_attr_list_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_attr_list_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_attr_list_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_attr_list_copy; + + g_string_append (serializable_class->signature, "av"); +} + +static void +ibus_attr_list_init (IBusAttrList *attr_list) +{ + attr_list->attributes = g_array_new (TRUE, TRUE, sizeof (IBusAttribute *)); +} + +static void +ibus_attr_list_destroy (IBusAttrList *attr_list) +{ + g_return_if_fail (IBUS_IS_ATTR_LIST (attr_list)); + + gint i; + for (i = 0;; i++) { + IBusAttribute *attr; + + attr = ibus_attr_list_get (attr_list, i); + if (attr == NULL) + break; + + g_object_unref (attr); + } + + g_array_free (attr_list->attributes, TRUE); + + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)attr_list); +} + +static gboolean +ibus_attr_list_serialize (IBusAttrList *attr_list, + IBusMessageIter *iter) +{ + IBusMessageIter array_iter; + gboolean retval; + guint i; + + retval = parent_class->serialize ((IBusSerializable *)attr_list, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_ATTR_LIST (attr_list), FALSE); + + retval = ibus_message_iter_open_container (iter, + IBUS_TYPE_ARRAY, + "v", + &array_iter); + g_return_val_if_fail (retval, FALSE); + + for (i = 0;; i++) { + IBusAttribute *attr; + + attr = ibus_attr_list_get (attr_list, i); + if (attr == NULL) + break; + + retval = ibus_message_iter_append (&array_iter, IBUS_TYPE_ATTRIBUTE, &attr); + g_return_val_if_fail (retval, FALSE); + } + + retval = ibus_message_iter_close_container (iter, &array_iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_attr_list_deserialize (IBusAttrList *attr_list, + IBusMessageIter *iter) +{ + DBusMessageIter array_iter; + gboolean retval; + + retval = parent_class->deserialize ((IBusSerializable *)attr_list, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_ARRAY, &array_iter); + g_return_val_if_fail (retval, FALSE); + + while (ibus_message_iter_get_arg_type (&array_iter) != G_TYPE_INVALID) { + IBusAttribute *attr; + + retval = ibus_message_iter_get (&array_iter, IBUS_TYPE_ATTRIBUTE, &attr); + + g_return_val_if_fail (retval, FALSE); + + ibus_attr_list_append (attr_list, attr); + } + + ibus_message_iter_next (iter); + + return TRUE; +} + + + +static gboolean +ibus_attr_list_copy (IBusAttrList *dest, + const IBusAttrList *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_ATTRIBUTE (dest), FALSE); + g_return_val_if_fail (IBUS_IS_ATTRIBUTE (src), FALSE); + + gint i; + for (i = 0; ; i++) { + IBusAttribute *attr = ibus_attr_list_get ((IBusAttrList *)src, i); + if (attr == NULL) { + break; + } + + attr = (IBusAttribute *) ibus_serializable_copy ((IBusSerializable *) attr); + if (attr == NULL) { + g_warning ("can not copy attribute"); + continue; + } + + ibus_attr_list_append (dest, attr); + } + return TRUE; +} + +IBusAttrList * +ibus_attr_list_new () +{ + IBusAttrList *attr_list; + attr_list = g_object_new (IBUS_TYPE_ATTR_LIST, 0); + return attr_list; +} + +void +ibus_attr_list_append (IBusAttrList *attr_list, + IBusAttribute *attr) +{ + g_return_if_fail (IBUS_IS_ATTR_LIST (attr_list)); + g_return_if_fail (IBUS_IS_ATTRIBUTE (attr)); + + g_array_append_val (attr_list->attributes, attr); +} + +IBusAttribute * +ibus_attr_list_get (IBusAttrList *attr_list, + guint index) +{ + g_return_val_if_fail (attr_list != NULL, NULL); + IBusAttribute *attr = NULL; + + if (index < attr_list->attributes->len) { + attr = g_array_index (attr_list->attributes, IBusAttribute *, index); + } + + return attr; +} + + diff --git a/src/ibusattribute.h b/src/ibusattribute.h new file mode 100644 index 0000000..3a0ff7f --- /dev/null +++ b/src/ibusattribute.h @@ -0,0 +1,126 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_ATTRIBUTE_H_ +#define __IBUS_ATTRIBUTE_H_ + +#include "ibusserializable.h" + +/* + * Type macros. + */ +/* define IBusAttribute macros */ +#define IBUS_TYPE_ATTRIBUTE \ + (ibus_attribute_get_type ()) +#define IBUS_ATTRIBUTE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_ATTRIBUTE, IBusAttribute)) +#define IBUS_ATTRIBUTE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_ATTRIBUTE, IBusAttributeClass)) +#define IBUS_IS_ATTRIBUTE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_ATTRIBUTE)) +#define IBUS_IS_ATTRIBUTE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_ATTRIBUTE)) +#define IBUS_ATTRIBUTE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_ATTRIBUTE, IBusAttributeClass)) + +/* define IBusAttrList macros */ +#define IBUS_TYPE_ATTR_LIST \ + (ibus_attr_list_get_type ()) +#define IBUS_ATTR_LIST(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_ATTR_LIST, IBusAttrList)) +#define IBUS_ATTR_LIST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_ATTR_LIST, IBusAttrListClass)) +#define IBUS_IS_ATTR_LIST(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_ATTR_LIST)) +#define IBUS_IS_ATTR_LIST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_ATTR_LIST)) +#define IBUS_ATTR_LIST_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_ATTR_LIST, IBusAttrListClass)) + +typedef enum { + IBUS_ATTR_TYPE_UNDERLINE = 1, + IBUS_ATTR_TYPE_FOREGROUND = 2, + IBUS_ATTR_TYPE_BACKGROUND = 3, +} IBusAttrType; + +typedef enum { + IBUS_ATTR_UNDERLINE_NONE = 0, + IBUS_ATTR_UNDERLINE_SINGLE = 1, + IBUS_ATTR_UNDERLINE_DOUBLE = 2, + IBUS_ATTR_UNDERLINE_LOW = 3, +} IBusAttrUnderline; + +G_BEGIN_DECLS + +typedef struct _IBusAttribute IBusAttribute; +typedef struct _IBusAttributeClass IBusAttributeClass; +typedef struct _IBusAttrList IBusAttrList; +typedef struct _IBusAttrListClass IBusAttrListClass; + +struct _IBusAttribute { + IBusSerializable parent; + + /* members */ + guint type; + guint value; + guint start_index; + guint end_index; +}; + +struct _IBusAttributeClass { + IBusSerializableClass parent; +}; + +struct _IBusAttrList { + IBusSerializable parent; + + /* members */ + GArray *attributes; +}; + +struct _IBusAttrListClass { + IBusSerializableClass parent; +}; + +GType ibus_attribute_get_type (); +IBusAttribute *ibus_attribute_new (guint type, + guint value, + guint start_index, + guint end_index); +IBusAttribute *ibus_attr_underline_new (guint underline_type, + guint start_index, + guint end_index); +IBusAttribute *ibus_attr_foreground_new (guint color, + guint start_index, + guint end_index); +IBusAttribute *ibus_attr_background_new (guint color, + guint start_index, + guint end_index); + + +GType ibus_attr_list_get_type (); +IBusAttrList *ibus_attr_list_new (); +void ibus_attr_list_append (IBusAttrList *attr_list, + IBusAttribute *attr); +IBusAttribute *ibus_attr_list_get (IBusAttrList *attr_list, + guint index); + +G_END_DECLS +#endif + diff --git a/src/ibusbus.c b/src/ibusbus.c new file mode 100644 index 0000000..be72770 --- /dev/null +++ b/src/ibusbus.c @@ -0,0 +1,773 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 <gio/gio.h> +#include "ibusbus.h" +#include "ibusinternal.h" +#include "ibusshare.h" +#include "ibusconnection.h" + +#define IBUS_BUS_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_BUS, IBusBusPrivate)) + +enum { + CONNECTED, + DISCONNECTED, + NAME_OWNER_CHANGED, + LAST_SIGNAL, +}; + + +/* IBusBusPriv */ +struct _IBusBusPrivate { + GFileMonitor *monitor; + IBusConnection *connection; + gboolean watch_dbus_signal; +}; +typedef struct _IBusBusPrivate IBusBusPrivate; + +static guint bus_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_bus_class_init (IBusBusClass *klass); +static void ibus_bus_init (IBusBus *bus); +static void ibus_bus_destroy (IBusObject *object); +static void ibus_bus_watch_dbus_signal + (IBusBus *bus); +static void ibus_bus_unwatch_dbus_signal + (IBusBus *bus); +static IBusObjectClass *parent_class = NULL; + +GType +ibus_bus_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusBusClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_bus_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusBus), + 0, + (GInstanceInitFunc) ibus_bus_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "IBusBus", + &type_info, + (GTypeFlags)0); + } + + return type; +} + +IBusBus * +ibus_bus_new (void) +{ + IBusBus *bus = IBUS_BUS (g_object_new (IBUS_TYPE_BUS, NULL)); + + return bus; +} + +static void +ibus_bus_class_init (IBusBusClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusBusPrivate)); + + ibus_object_class->destroy = ibus_bus_destroy; + + // install signals + bus_signals[CONNECTED] = + g_signal_new (I_("connected"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + bus_signals[DISCONNECTED] = + g_signal_new (I_("disconnected"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); +#if 0 + bus_signals[NAME_OWNER_CHANGED] = + g_signal_new (I_("name-owner-changed"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__STRING_STRING_STRING, + G_TYPE_NONE, + 3, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE, + G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE + ); +#endif +} + +#if 0 +static gboolean +_connection_dbus_signal_cb (IBusConnection *connection, + DBusMessage *message, + IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + g_assert (message != NULL); + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) { + DBusError error; + const gchar *name; + const gchar *old_name; + const gchar *new_name; + gboolean retval; + + dbus_error_init (&error); + retval = dbus_message_get_args (message, &error, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &old_name, + DBUS_TYPE_STRING, &new_name, + DBUS_TYPE_INVALID); + if (!retval) { + g_warning ("%s: %s", error.name, error.message); + dbus_error_free (&error); + } + else { + g_signal_emit (bus, + bus_signals[NAME_OWNER_CHANGED], + 0, + name, + old_name, + new_name); + } + } + + return FALSE; +} +#endif + +static void +_connection_destroy_cb (IBusConnection *connection, + IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + g_assert (priv->connection == connection); + g_object_unref (priv->connection); + priv->connection = NULL; + + g_signal_emit (bus, bus_signals[DISCONNECTED], 0); +} + +static void +ibus_bus_connect (IBusBus *bus) +{ + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + g_assert (priv->connection == NULL); + + priv->connection = ibus_connection_open (ibus_get_address ()); + + if (priv->connection) { + ibus_bus_hello (bus); +#if 0 + g_signal_connect (priv->connection, + "dbus-signal", + (GCallback) _connection_dbus_signal_cb, + bus); +#endif + g_signal_connect (priv->connection, + "destroy", + (GCallback) _connection_destroy_cb, + bus); + g_signal_emit (bus, bus_signals[CONNECTED], 0); + + if (priv->watch_dbus_signal) { + ibus_bus_watch_dbus_signal (bus); + } + } +} + +static void +_changed_cb (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + IBusBus *bus) +{ + static GFile *socket_file = NULL; + + if (socket_file == NULL) { + socket_file = g_file_new_for_path (ibus_get_socket_path ()); + } + + if (event_type == G_FILE_MONITOR_EVENT_CREATED) { + if (g_file_equal (file, socket_file)) { + ibus_bus_connect (bus); + } + } +} + +static void +ibus_bus_init (IBusBus *bus) +{ + gchar *path; + GFile *file; + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + priv->connection = NULL; + priv->watch_dbus_signal = FALSE; + + ibus_bus_connect (bus); + + path = g_strdup_printf ("/tmp/ibus-%s/", ibus_get_user_name ()); + file = g_file_new_for_path (path); + priv->monitor = g_file_monitor_directory (file, 0, NULL, NULL); + + g_signal_connect (priv->monitor, "changed", (GCallback) _changed_cb, bus); + + g_object_unref (file); + g_free (path); +} + +static void +ibus_bus_destroy (IBusObject *object) +{ + IBusBus *bus; + IBusBusPrivate *priv; + + bus = IBUS_BUS (object); + priv = IBUS_BUS_GET_PRIVATE (bus); + + if (priv->monitor) { + g_object_unref (priv->monitor); + priv->monitor = NULL; + } + + if (priv->connection) { + ibus_object_destroy (IBUS_OBJECT (priv->connection)); + priv->connection = NULL; + } + + IBUS_OBJECT_CLASS (parent_class)->destroy (object); +} + +gboolean +ibus_bus_is_connected (IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + if (priv->connection) { + return ibus_connection_is_connected (priv->connection); + } + + return FALSE; +} + + +IBusInputContext * +ibus_bus_create_input_context (IBusBus *bus, + const gchar *client_name) +{ + g_assert (IBUS_IS_BUS (bus)); + g_assert (client_name != NULL); + g_assert (ibus_bus_is_connected (bus)); + + gchar *path; + DBusMessage *call = NULL; + DBusMessage *reply = NULL; + IBusError *error; + IBusInputContext *context = NULL; + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + call = ibus_message_new_method_call (IBUS_SERVICE_IBUS, + IBUS_PATH_IBUS, + IBUS_INTERFACE_IBUS, + "CreateInputContext"); + ibus_message_append_args (call, + G_TYPE_STRING, &client_name, + G_TYPE_INVALID); + + reply = ibus_connection_send_with_reply_and_block (priv->connection, + call, + -1, + &error); + ibus_message_unref (call); + + if (reply == NULL) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + return NULL; + } + + if ((error = ibus_error_new_from_message (reply)) != NULL) { + g_warning ("%s: %s", error->name, error->message); + ibus_message_unref (reply); + ibus_error_free (error); + return NULL; + } + + if (!ibus_message_get_args (reply, + &error, + IBUS_TYPE_OBJECT_PATH, &path, + G_TYPE_INVALID)) { + g_warning ("%s: %s", error->name, error->message); + ibus_message_unref (reply); + ibus_error_free (error); + + return NULL; + } + + context = ibus_input_context_new (path, priv->connection); + ibus_message_unref (reply); + + return context; +} + +static void +ibus_bus_watch_dbus_signal (IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + + const gchar *rule; + + rule = "type='signal'," \ + "path='" DBUS_PATH_DBUS "'," \ + "interface='" DBUS_INTERFACE_DBUS "'"; + + ibus_bus_add_match (bus, rule); + +} + +static void +ibus_bus_unwatch_dbus_signal (IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + g_assert (ibus_bus_is_connected (bus)); + + const gchar *rule; + + rule = "type='signal'," \ + "path='" DBUS_PATH_DBUS "'," \ + "interface='" DBUS_INTERFACE_DBUS "'"; + + ibus_bus_remove_match (bus, rule); +} + +void +ibus_bus_set_watch_dbus_signal (IBusBus *bus, + gboolean watch) +{ + g_assert (IBUS_IS_BUS (bus)); + + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + if (priv->watch_dbus_signal == watch) + return; + + priv->watch_dbus_signal = watch; + + if (ibus_bus_is_connected (bus)) { + if (watch) { + ibus_bus_watch_dbus_signal (bus); + } + else { + ibus_bus_unwatch_dbus_signal (bus); + } + } +} + + +static gboolean +ibus_bus_call (IBusBus *bus, + const gchar *name, + const gchar *path, + const gchar *interface, + const gchar *member, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_BUS (bus)); + g_assert (ibus_bus_is_connected (bus)); + g_assert (name != NULL); + g_assert (path != NULL); + g_assert (interface != NULL); + g_assert (member); + + IBusMessage *message, *reply; + IBusError *error; + va_list args; + GType type; + gboolean retval; + IBusBusPrivate *priv; + + priv = IBUS_BUS_GET_PRIVATE (bus); + + message = ibus_message_new_method_call (name, path, interface, member); + + va_start (args, first_arg_type); + ibus_message_append_args_valist (message, first_arg_type, args); + va_end (args); + + reply = ibus_connection_send_with_reply_and_block ( + priv->connection, + message, + -1, + &error); + ibus_message_unref (message); + + if (reply == NULL) { + g_warning ("%s : %s", error->name, error->message); + ibus_error_free (error); + return FALSE; + } + + if ((error = ibus_error_new_from_message (reply)) != NULL) { + g_warning ("%s : %s", error->name, error->message); + ibus_error_free (error); + ibus_message_unref (reply); + return FALSE; + } + + va_start (args, first_arg_type); + + type = first_arg_type; + + while (type != G_TYPE_INVALID) { + va_arg (args, gpointer); + type = va_arg (args, GType); + } + + type = va_arg (args, GType); + if (type != G_TYPE_INVALID) { + retval = ibus_message_get_args_valist (reply, &error, type, args); + } + else { + retval = TRUE; + } + va_end (args); + + ibus_message_unref (reply); + + if (!retval) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + return FALSE; + } + + return TRUE; +} + +const gchar * +ibus_bus_hello (IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + + gchar *unique_name = NULL; + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "Hello", + G_TYPE_INVALID, + G_TYPE_STRING, &unique_name, + G_TYPE_INVALID); + + if (result) + return unique_name; + + return NULL; +} + +guint +ibus_bus_request_name (IBusBus *bus, + const gchar *name, + guint flags) +{ + g_assert (IBUS_IS_BUS (bus)); + + guint retval; + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RequestName", + G_TYPE_STRING, &name, + G_TYPE_UINT, &flags, + G_TYPE_INVALID, + G_TYPE_UINT, &retval, + G_TYPE_INVALID); + + if (result) + return retval; + + return 0; +} + +guint +ibus_bus_release_name (IBusBus *bus, + const gchar *name) +{ + g_assert (IBUS_IS_BUS (bus)); + + guint retval; + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "ReleaseName", + G_TYPE_STRING, &name, + G_TYPE_INVALID, + G_TYPE_UINT, &retval, + G_TYPE_INVALID); + + if (result) + return retval; + + return 0; +} + +gboolean +ibus_bus_name_has_owner (IBusBus *bus, + const gchar *name) +{ + g_assert (IBUS_IS_BUS (bus)); + + gboolean retval; + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "NameHasOwner", + G_TYPE_STRING, &name, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, &retval, + G_TYPE_INVALID); + + if (result) + return retval; + + return FALSE; +} + +GList * +ibus_bus_list_names (IBusBus *bus) +{ + return NULL; +} + +void +ibus_bus_add_match (IBusBus *bus, + const gchar *rule) +{ + g_assert (IBUS_IS_BUS (bus)); + + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "AddMatch", + G_TYPE_STRING, &rule, + G_TYPE_INVALID, + G_TYPE_INVALID); +} + +void +ibus_bus_remove_match (IBusBus *bus, + const gchar *rule) +{ + g_assert (IBUS_IS_BUS (bus)); + + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RemoveMatch", + G_TYPE_STRING, &rule, + G_TYPE_INVALID, + G_TYPE_INVALID); +} + +const gchar * +ibus_bus_get_name_owner (IBusBus *bus, + const gchar *name) +{ + g_assert (IBUS_IS_BUS (bus)); + + gchar *owner = NULL; + gboolean result; + + result = ibus_bus_call (bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RemoveMatch", + G_TYPE_STRING, &name, + G_TYPE_INVALID, + G_TYPE_STRING, &owner, + G_TYPE_INVALID); + + if (result) + return owner; + + return NULL; +} + +IBusConnection * +ibus_bus_get_connection (IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + return priv->connection; +} + +gboolean +ibus_bus_kill (IBusBus *bus) +{ + g_assert (IBUS_IS_BUS (bus)); + + gboolean result; + result = ibus_bus_call (bus, + IBUS_SERVICE_IBUS, + IBUS_PATH_IBUS, + IBUS_INTERFACE_IBUS, + "Kill", + G_TYPE_INVALID, + G_TYPE_INVALID); + return result; +} + +gboolean +ibus_bus_register_component (IBusBus *bus, + IBusComponent *component) +{ + g_assert (IBUS_IS_BUS (bus)); + g_assert (IBUS_IS_COMPONENT (component)); + + gboolean result; + + result = ibus_bus_call (bus, + IBUS_SERVICE_IBUS, + IBUS_PATH_IBUS, + IBUS_INTERFACE_IBUS, + "RegisterComponent", + IBUS_TYPE_COMPONENT, &component, + G_TYPE_INVALID, + G_TYPE_INVALID); + + return result; + + +#if 0 + IBusMessage *message, *reply; + IBusError *error; + + IBusBusPrivate *priv; + priv = IBUS_BUS_GET_PRIVATE (bus); + + message = ibus_message_new_method_call (IBUS_SERVICE_IBUS, + IBUS_PATH_IBUS, + IBUS_INTERFACE_IBUS, + "RegisterComponent"); + + ibus_message_append_args (message, + IBUS_TYPE_COMPONENT, &component, + G_TYPE_INVALID); + + reply = ibus_connection_send_with_reply_and_block ( + priv->connection, + message, + -1, + &error); + ibus_message_unref (message); + + if (reply == NULL) { + g_warning ("%s : %s", error->name, error->message); + ibus_error_free (error); + return FALSE; + } + + if ((error = ibus_error_from_message (reply)) != NULL) { + g_warning ("%s : %s", error->name, error->message); + ibus_error_free (error); + ibus_message_unref (reply); + return FALSE; + } + + return TRUE; +#endif +} + +GList * +ibus_bus_list_engines (IBusBus *bus) +{ + return NULL; +} + +GList * +ibus_bus_list_active_engines (IBusBus *bus) +{ + return NULL; +} diff --git a/src/ibusbus.h b/src/ibusbus.h new file mode 100644 index 0000000..e548c82 --- /dev/null +++ b/src/ibusbus.h @@ -0,0 +1,97 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_BUS_H_ +#define __IBUS_BUS_H_ + +#include <dbus/dbus.h> +#include "ibusinputcontext.h" +#include "ibusconfig.h" +#include "ibuscomponent.h" + + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_BUS \ + (ibus_bus_get_type ()) +#define IBUS_BUS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_BUS, IBusBus)) +#define IBUS_BUS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_BUS, IBusBusClass)) +#define IBUS_IS_BUS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_BUS)) +#define IBUS_IS_BUS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_BUS)) +#define IBUS_BUS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_BUS, IBusBusClass)) + +G_BEGIN_DECLS + +typedef struct _IBusBus IBusBus; +typedef struct _IBusBusClass IBusBusClass; + +struct _IBusBus { + IBusObject parent; + /* instance members */ +}; + +struct _IBusBusClass { + IBusObjectClass parent; + /* class members */ +}; + +GType ibus_bus_get_type (void); +IBusBus *ibus_bus_new (void); +gboolean ibus_bus_is_connected (IBusBus *bus); +IBusConnection + *ibus_bus_get_connection (IBusBus *bus); +/* declare dbus methods */ +const gchar *ibus_bus_hello (IBusBus *bus); +guint ibus_bus_request_name (IBusBus *bus, + const gchar *name, + guint flags); +guint ibus_bus_release_name (IBusBus *bus, + const gchar *name); +gboolean ibus_bus_name_has_owner (IBusBus *bus, + const gchar *name); +GList *ibus_bus_list_names (IBusBus *bus); +void ibus_bus_add_match (IBusBus *bus, + const gchar *rule); +void ibus_bus_remove_match (IBusBus *bus, + const gchar *rule); +const gchar *ibus_bus_get_name_owner (IBusBus *bus, + const gchar *name); +/* declare ibus methods */ +gboolean ibus_bus_kill (IBusBus *bus); +IBusInputContext + *ibus_bus_create_input_context + (IBusBus *bus, + const gchar *client_name); +gboolean ibus_bus_register_component(IBusBus *bus, + IBusComponent *component); +GList *ibus_bus_list_engines (IBusBus *bus); +GList *ibus_bus_list_active_engines + (IBusBus *bus); + +G_END_DECLS +#endif + diff --git a/src/ibuscomponent.c b/src/ibuscomponent.c new file mode 100644 index 0000000..9ca487d --- /dev/null +++ b/src/ibuscomponent.c @@ -0,0 +1,743 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 <glib/gstdio.h> +#include "ibuscomponent.h" + +enum { + LAST_SIGNAL, +}; + + +/* IBusComponentPriv */ +struct _IBusComponentPrivate { + gpointer pad; +}; +typedef struct _IBusComponentPrivate IBusComponentPrivate; + +#define IBUS_COMPONENT_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUS_TYPE_COMPONENT, IBusComponentPrivate)) + +// static guint _signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_component_class_init (IBusComponentClass *klass); +static void ibus_component_init (IBusComponent *component); +static void ibus_component_destroy (IBusComponent *component); +static gboolean ibus_component_serialize (IBusComponent *component, + IBusMessageIter *iter); +static gboolean ibus_component_deserialize (IBusComponent *component, + IBusMessageIter *iter); +static gboolean ibus_component_copy (IBusComponent *dest, + const IBusComponent *src); +static gboolean ibus_component_parse_xml_node + (IBusComponent *component, + XMLNode *node, + gboolean access_fs); + +static void ibus_component_parse_engines(IBusComponent *component, + XMLNode *node); +static void ibus_component_parse_observed_paths + (IBusComponent *component, + XMLNode *node, + gboolean access_fs); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_component_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusComponentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_component_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusComponent), + 0, + (GInstanceInitFunc) ibus_component_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusComponent", + &type_info, + (GTypeFlags)0); + } + + return type; +} + + +static void +ibus_component_class_init (IBusComponentClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_component_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_component_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_component_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_component_copy; + + g_string_append (serializable_class->signature, "ssssssssavav"); +} + + + +static void +ibus_component_init (IBusComponent *component) +{ + component->name = NULL; + component->description = NULL; + component->version = NULL; + component->license = NULL; + component->author = NULL; + component->homepage = NULL; + component->exec = NULL; + component->textdomain = NULL; + component->engines = NULL; + component->observed_paths = NULL; +} + +static void +ibus_component_destroy (IBusComponent *component) +{ + GList *p; + + g_free (component->name); + g_free (component->description); + g_free (component->version); + g_free (component->license); + g_free (component->author); + g_free (component->homepage); + g_free (component->exec); + g_free (component->textdomain); + + component->name = NULL; + component->description = NULL; + component->version = NULL; + component->license = NULL; + component->author = NULL; + component->homepage = NULL; + component->exec = NULL; + component->textdomain = NULL; + + g_list_foreach (component->observed_paths, (GFunc)g_object_unref, NULL); + g_list_free (component->observed_paths); + component->observed_paths = NULL; + + for (p = component->engines; p != NULL; p = p->next) { + g_object_steal_data ((GObject *)p->data, "component"); + ibus_object_destroy ((IBusObject *)p->data); + g_object_unref (p->data); + } + g_list_free (component->engines); + component->engines = NULL; + + IBUS_OBJECT_CLASS (parent_class)->destroy (IBUS_OBJECT (component)); +} + +static gboolean +ibus_component_serialize (IBusComponent *component, + IBusMessageIter *iter) +{ + gboolean retval; + IBusMessageIter array_iter; + GList *p; + + retval = parent_class->serialize ((IBusSerializable *)component, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->name); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->description); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->version); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->license); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->author); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->homepage); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->exec); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &component->textdomain); + g_return_val_if_fail (retval, FALSE); + + /* serialize observed paths */ + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_ARRAY, "v", &array_iter); + g_return_val_if_fail (retval, FALSE); + + for (p = component->observed_paths; p != NULL; p = p->next) { + retval = ibus_message_iter_append (&array_iter, IBUS_TYPE_OBSERVED_PATH, &(p->data)); + g_return_val_if_fail (retval, FALSE); + } + retval = ibus_message_iter_close_container (iter, &array_iter); + g_return_val_if_fail (retval, FALSE); + + /* serialize engine desc */ + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_ARRAY, "v", &array_iter); + g_return_val_if_fail (retval, FALSE); + + for (p = component->engines; p != NULL; p = p->next) { + retval = ibus_message_iter_append (&array_iter, IBUS_TYPE_ENGINE_DESC, &(p->data)); + g_return_val_if_fail (retval, FALSE); + } + retval = ibus_message_iter_close_container (iter, &array_iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_component_deserialize (IBusComponent *component, + IBusMessageIter *iter) +{ + gboolean retval; + gchar *str; + IBusMessageIter array_iter; + + retval = parent_class->deserialize ((IBusSerializable *)component, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->name = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->description = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->version = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->license = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->author = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->homepage = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->exec = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + component->textdomain = g_strdup (str); + + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_ARRAY, &array_iter); + g_return_val_if_fail (retval, FALSE); + while (ibus_message_iter_get_arg_type (&array_iter) != G_TYPE_INVALID) { + IBusObservedPath *path; + retval = ibus_message_iter_get (&array_iter, IBUS_TYPE_OBSERVED_PATH, &path); + component->observed_paths = g_list_append (component->observed_paths, path); + } + ibus_message_iter_next (iter); + + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_ARRAY, &array_iter); + g_return_val_if_fail (retval, FALSE); + + while (ibus_message_iter_get_arg_type (&array_iter) != G_TYPE_INVALID) { + IBusEngineDesc *engine; + retval = ibus_message_iter_get (&array_iter, IBUS_TYPE_ENGINE_DESC, &engine); + ibus_component_add_engine (component, engine); + } + ibus_message_iter_next (iter); + + return TRUE; +} + +static gboolean +ibus_component_copy (IBusComponent *dest, + const IBusComponent *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + + dest->name = g_strdup (src->name); + dest->description = g_strdup (src->description); + dest->version = g_strdup (src->version); + dest->license = g_strdup (src->license); + dest->author = g_strdup (src->author); + dest->homepage = g_strdup (src->homepage); + dest->exec = g_strdup (src->exec); + dest->textdomain = g_strdup (src->textdomain); + + dest->observed_paths = g_list_copy (src->observed_paths); + g_list_foreach (dest->observed_paths, (GFunc) g_object_ref, NULL); + + dest->engines = g_list_copy (src->engines); + g_list_foreach (dest->engines, (GFunc) g_object_ref, NULL); + + return TRUE; +} + + +#define g_string_append_indent(string, indent) \ + { \ + gint i; \ + for (i = 0; i < (indent); i++) { \ + g_string_append (string, " "); \ + } \ + } + +void +ibus_component_output (IBusComponent *component, + GString *output, + gint indent) +{ + g_assert (IBUS_IS_COMPONENT (component)); + GList *p; + + g_string_append_indent (output, indent); + g_string_append (output, "<component>\n"); + +#define OUTPUT_ENTRY(field, element) \ + { \ + gchar *escape_text = g_markup_escape_text (component->field, -1); \ + g_string_append_indent (output, indent + 1); \ + g_string_append_printf (output, "<"element">%s</"element">\n", \ + escape_text); \ + g_free (escape_text); \ + } +#define OUTPUT_ENTRY_1(name) OUTPUT_ENTRY(name, #name) + OUTPUT_ENTRY_1 (name); + OUTPUT_ENTRY_1 (description); + OUTPUT_ENTRY_1 (version); + OUTPUT_ENTRY_1 (license); + OUTPUT_ENTRY_1 (author); + OUTPUT_ENTRY_1 (homepage); + OUTPUT_ENTRY_1 (exec); + OUTPUT_ENTRY_1 (textdomain); +#undef OUTPUT_ENTRY +#undef OUTPUT_ENTRY_1 + + if (component->observed_paths) { + g_string_append_indent (output, indent + 1); + g_string_append (output, "<observed-paths>\n"); + + for (p = component->observed_paths; p != NULL; p = p->next ) { + IBusObservedPath *path = (IBusObservedPath *) p->data; + + g_string_append_indent (output, indent + 2); + g_string_append_printf (output, "<path mtime=\"%ld\" >%s</path>\n", + path->mtime, + path->path); + } + + g_string_append_indent (output, indent + 1); + g_string_append (output, "</observed-paths>\n"); + } + + ibus_component_output_engines (component, output, indent + 1); + + g_string_append_indent (output, indent); + g_string_append (output, "</component>\n"); +} + +void +ibus_component_output_engines (IBusComponent *component, + GString *output, + gint indent) +{ + g_assert (IBUS_IS_COMPONENT (component)); + g_assert (output); + + GList *p; + + g_string_append_indent (output, indent); + g_string_append (output, "<engines>\n"); + + for (p = component->engines; p != NULL; p = p->next) { + ibus_engine_desc_output ((IBusEngineDesc *)p->data, output, indent + 2); + } + + g_string_append_indent (output, indent); + g_string_append (output, "</engines>\n"); +} + +static gboolean +ibus_component_parse_xml_node (IBusComponent *component, + XMLNode *node, + gboolean access_fs) +{ + g_assert (component); + g_assert (node); + + if (G_UNLIKELY (g_strcmp0 (node->name, "component") != 0)) { + return FALSE; + } + + GList *p; + for (p = node->sub_nodes; p != NULL; p = p->next) { + XMLNode *sub_node = (XMLNode *)p->data; + +#define PARSE_ENTRY(field_name, element_name) \ + if (g_strcmp0 (sub_node->name, element_name) == 0) { \ + if (component->field_name != NULL) { \ + g_free (component->field_name); \ + } \ + component->field_name = g_strdup (sub_node->text); \ + continue; \ + } +#define PARSE_ENTRY_1(name) PARSE_ENTRY (name, #name) + PARSE_ENTRY_1 (name); + PARSE_ENTRY_1 (description); + PARSE_ENTRY_1 (version); + PARSE_ENTRY_1 (license); + PARSE_ENTRY_1 (author); + PARSE_ENTRY_1 (homepage); + PARSE_ENTRY_1 (exec); + PARSE_ENTRY_1 (textdomain); +#undef PARSE_ENTRY +#undef PARSE_ENTRY_1 + + if (g_strcmp0 (sub_node->name, "engines") == 0) { + ibus_component_parse_engines (component, sub_node); + continue; + } + + if (g_strcmp0 (sub_node->name, "observed-paths") == 0) { + ibus_component_parse_observed_paths (component, sub_node, access_fs); + continue; + } + + g_warning ("<component> element contains invalidate element <%s>", sub_node->name); + } + + return TRUE; +} + + +static void +ibus_component_parse_engines (IBusComponent *component, + XMLNode *node) +{ + g_assert (IBUS_IS_COMPONENT (component)); + g_assert (node); + + gchar *exec = NULL; + gchar **p; + XMLNode *engines_node = NULL; + + if (g_strcmp0 (node->name, "engines") != 0) { + return; + } + + for (p = node->attributes; *p != NULL; p += 2) { + if (g_strcmp0 (*p, "exec") == 0) { + exec = *(p + 1); + break; + } + } + + if (exec != NULL) { + gchar *output = NULL; + if (g_spawn_command_line_sync (exec, &output, NULL, NULL, NULL)) { + engines_node = ibus_xml_parse_buffer (output); + g_free (output); + + if (engines_node) { + if (g_strcmp0 (engines_node->name, "engines") != 0) { + ibus_xml_free (engines_node); + engines_node = NULL; + } + } + node = engines_node; + } + } + + GList *pl; + for (pl = node->sub_nodes; pl != NULL; pl = pl->next) { + IBusEngineDesc *engine; + engine = ibus_engine_desc_new_from_xml_node ((XMLNode *)pl->data); + + if (G_UNLIKELY (engine == NULL)) + continue; + ibus_component_add_engine (component, engine); + } + + if (engines_node) { + ibus_xml_free (engines_node); + } +} + +static void +ibus_component_parse_observed_paths (IBusComponent *component, + XMLNode *node, + gboolean access_fs) +{ + g_assert (IBUS_IS_COMPONENT (component)); + g_assert (node); + + if (g_strcmp0 (node->name, "observed-paths") != 0) { + return; + } + + GList *p; + for (p = node->sub_nodes; p != NULL; p = p->next) { + IBusObservedPath *path; + + path = ibus_observed_path_new_from_xml_node ((XMLNode *)p->data, access_fs); + component->observed_paths = g_list_append (component->observed_paths, path); + + if (access_fs && path->is_dir && path->is_exist) { + component->observed_paths = g_list_concat (component->observed_paths, + ibus_observed_path_traverse (path)); + } + } +} + +IBusComponent * +ibus_component_new (const gchar *name, + const gchar *descritpion, + const gchar *version, + const gchar *license, + const gchar *author, + const gchar *homepage, + const gchar *exec, + const gchar *textdomain) +{ + + IBusComponent *component; + component = (IBusComponent *)g_object_new (IBUS_TYPE_COMPONENT, NULL); + + component->name = g_strdup (name); + component->description = g_strdup (descritpion); + component->version = g_strdup (version); + component->license = g_strdup (license); + component->author = g_strdup (author); + component->homepage = g_strdup (homepage); + component->exec = g_strdup (exec); + component->textdomain = g_strdup (textdomain); + + return component; +} + + +IBusComponent * +ibus_component_new_from_xml_node (XMLNode *node) +{ + g_assert (node); + + IBusComponent *component; + + component = (IBusComponent *)g_object_new (IBUS_TYPE_COMPONENT, NULL); + if (!ibus_component_parse_xml_node (component, node, FALSE)) { + g_object_unref (component); + component = NULL; + } + + return component; +} + +IBusComponent * +ibus_component_new_from_file (const gchar *filename) +{ + g_assert (filename); + + XMLNode *node; + struct stat buf; + IBusComponent *component; + gboolean retval; + + if (g_stat (filename, &buf) != 0) { + g_warning ("Can not get stat of file %s", filename); + return NULL; + } + + node = ibus_xml_parse_file (filename); + + if (!node) { + return NULL; + } + + component = (IBusComponent *)g_object_new (IBUS_TYPE_COMPONENT, NULL); + retval = ibus_component_parse_xml_node (component, node, TRUE); + ibus_xml_free (node); + + if (!retval) { + g_object_unref (component); + component = NULL; + } + else { + IBusObservedPath *path; + path = ibus_observed_path_new (filename, TRUE); + component->observed_paths = g_list_prepend (component->observed_paths, path); + } + + return component; +} + +void +ibus_component_add_observed_path (IBusComponent *component, + const gchar *path, + gboolean access_fs) +{ + IBusObservedPath *p; + + p = ibus_observed_path_new (path, access_fs); + component->observed_paths = g_list_append (component->observed_paths, p); + + if (access_fs && p->is_dir && p->is_exist) { + component->observed_paths = g_list_concat (component->observed_paths, + ibus_observed_path_traverse (p)); + } +} + +void +ibus_component_add_engine (IBusComponent *component, + IBusEngineDesc *engine) +{ + g_assert (IBUS_IS_COMPONENT (component)); + g_assert (IBUS_IS_ENGINE_DESC (engine)); + + component->engines = g_list_append (component->engines, engine); + g_object_set_data ((GObject *)engine, "component", component); +} + +GList * +ibus_component_get_engines (IBusComponent *component) +{ + return g_list_copy (component->engines); +} + +static void +ibus_component_child_cb (GPid pid, + gint status, + IBusComponent *component) +{ + g_assert (IBUS_IS_COMPONENT (component)); + g_assert (component->pid == pid); + + g_spawn_close_pid (pid); + component->pid = 0; +} + +gboolean +ibus_component_start (IBusComponent *component) +{ + g_assert (IBUS_IS_COMPONENT (component)); + + if (component->pid != 0) + return TRUE; + + gint argc; + gchar **argv; + gboolean retval; + GError *error; + + error = NULL; + if (!g_shell_parse_argv (component->exec, &argc, &argv, &error)) { + g_warning ("Can not parse component %s exec: %s", component->name, error->message); + g_error_free (error); + return FALSE; + } + + error = NULL; + retval = g_spawn_async (NULL, argv, NULL, + G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, + &(component->pid), &error); + g_strfreev (argv) + ; + if (!retval) { + g_warning ("Can not execute component %s: %s", component->name, error->message); + g_error_free (error); + return FALSE; + } + + g_child_watch_add (component->pid, (GChildWatchFunc) ibus_component_child_cb, component); + + return TRUE; +} + +gboolean +ibus_component_stop (IBusComponent *component) +{ + g_assert (IBUS_IS_COMPONENT (component)); + + if (component->pid == 0) + return TRUE; + + kill (component->pid, SIGTERM); + return TRUE; +} + +gboolean +ibus_component_is_running (IBusComponent *component) +{ + g_assert (IBUS_IS_COMPONENT (component)); + + return (component->pid != 0); +} + + +gboolean +ibus_component_check_modification (IBusComponent *component) +{ + g_assert (IBUS_IS_COMPONENT (component)); + + GList *p; + + for (p = component->observed_paths; p != NULL; p = p->next) { + if (ibus_observed_path_check_modification ((IBusObservedPath *)p->data)) + return TRUE; + } + return FALSE; +} + + +IBusComponent * +ibus_component_get_from_engine (IBusEngineDesc *engine) +{ + g_assert (IBUS_IS_ENGINE_DESC (engine)); + + IBusComponent *component; + + component = (IBusComponent *)g_object_get_data ((GObject *)engine, "component"); + return component; +} diff --git a/src/ibuscomponent.h b/src/ibuscomponent.h new file mode 100644 index 0000000..1d5d25a --- /dev/null +++ b/src/ibuscomponent.h @@ -0,0 +1,115 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_COMPONENT_H_ +#define __IBUS_COMPONENT_H_ + +#include "ibusserializable.h" +#include "ibusobservedpath.h" +#include "ibusenginedesc.h" +#include "ibusxml.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_COMPONENT \ + (ibus_component_get_type ()) +#define IBUS_COMPONENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_COMPONENT, IBusComponent)) +#define IBUS_COMPONENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_COMPONENT, IBusComponentClass)) +#define IBUS_IS_COMPONENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_COMPONENT)) +#define IBUS_IS_COMPONENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_COMPONENT)) +#define IBUS_COMPONENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_COMPONENT, IBusComponentClass)) + +G_BEGIN_DECLS + +typedef struct _IBusComponent IBusComponent; +typedef struct _IBusComponentClass IBusComponentClass; + +struct _IBusComponent { + IBusSerializable parent; + /* instance members */ + + gchar *name; + gchar *description; + gchar *version; + gchar *license; + gchar *author; + gchar *homepage; + gchar *exec; + + /* text domain for dgettext */ + gchar *textdomain; + + /* engines */ + GList *engines; + + /* observed paths */ + GList *observed_paths; + + GPid pid; +}; + +struct _IBusComponentClass { + IBusSerializableClass parent; + + /* class members */ +}; + +GType ibus_component_get_type (void); +IBusComponent *ibus_component_new (const gchar *name, + const gchar *descritpion, + const gchar *version, + const gchar *license, + const gchar *author, + const gchar *homepage, + const gchar *exec, + const gchar *textdomain); +IBusComponent *ibus_component_new_from_xml_node + (XMLNode *node); +IBusComponent *ibus_component_new_from_file (const gchar *filename); +void ibus_component_add_observed_path + (IBusComponent *component, + const gchar *path, + gboolean access_fs); +void ibus_component_add_engine (IBusComponent *component, + IBusEngineDesc *engine); +GList *ibus_component_get_engines (IBusComponent *component); +void ibus_component_output (IBusComponent *component, + GString *output, + gint indent); +void ibus_component_output_engines (IBusComponent *component, + GString *output, + gint indent); +gboolean ibus_component_check_modification + (IBusComponent *component); +gboolean ibus_component_start (IBusComponent *component); +gboolean ibus_component_stop (IBusComponent *component); +gboolean ibus_component_is_running (IBusComponent *component); +IBusComponent *ibus_component_get_from_engine (IBusEngineDesc *engine); + +G_END_DECLS +#endif + diff --git a/src/ibusconfig.c b/src/ibusconfig.c new file mode 100644 index 0000000..9ebc799 --- /dev/null +++ b/src/ibusconfig.c @@ -0,0 +1,357 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibusinternal.h" +#include "ibusmarshalers.h" +#include "ibusshare.h" +#include "ibusconfig.h" + +#define IBUS_CONFIG_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_CONFIG, IBusConfigPrivate)) + +enum { + VALUE_CHANGED, + LAST_SIGNAL, +}; + + +/* IBusConfigPriv */ +struct _IBusConfigPrivate { + gpointer pad; +}; +typedef struct _IBusConfigPrivate IBusConfigPrivate; + +#if 0 +struct _BusPair { + GValue car; + GValue cdr; +}; +typedef struct _BusPair BusPair; +#endif + +static guint config_signals[LAST_SIGNAL] = { 0 }; + +#if 0 +/* functions prototype */ +static BusPair *bus_pair_new (GType car_type, + GType cdr_type, + gpointer car, + gpointer cdr); +static BusPair *bus_pair_copy (BusPair *pair); +static void bus_pair_free (BusPair *pair); +#endif +static void ibus_config_class_init (IBusConfigClass *klass); +static void ibus_config_init (IBusConfig *config); +static void ibus_config_real_destroy (IBusConfig *config); + +static gboolean ibus_config_ibus_signal (IBusProxy *proxy, + IBusMessage *message); + +static IBusProxyClass *parent_class = NULL; + +#if 0 +static BusPair * +bus_pair_new (GType car_type, + GType cdr_type, + gpointer car, + gpointer cdr) +{ + + g_assert (car_type == G_TYPE_STRING || + car_type == G_TYPE_INT || + car_type == G_TYPE_BOOLEAN || + car_type == G_TYPE_DOUBLE); + g_assert (cdr_type == G_TYPE_STRING || + cdr_type == G_TYPE_INT || + cdr_type == G_TYPE_BOOLEAN || + cdr_type == G_TYPE_DOUBLE); + g_assert (car != NULL); + g_assert (cdr != NULL); + + BusPair *pair; + + pair = g_slice_new0 (BusPair); + + g_value_init (&(pair->car), car_type); + g_value_init (&(pair->cdr), cdr_type); + + switch (car_type) { + case G_TYPE_STRING: + g_value_set_string (&(pair->car), *(gchar **)car); + break; + case G_TYPE_INT: + g_value_set_int (&(pair->car), *(gint32 *)car); + break; + case G_TYPE_BOOLEAN: + g_value_set_boolean (&(pair->car), *(gboolean *)car); + break; + case G_TYPE_DOUBLE: + g_value_set_double (&(pair->car), *(gdouble *)car); + break; + } + + switch (cdr_type) { + case G_TYPE_STRING: + g_value_set_string (&(pair->cdr), *(gchar **)cdr); + break; + case G_TYPE_INT: + g_value_set_int (&(pair->cdr), *(gint32 *)car); + break; + case G_TYPE_BOOLEAN: + g_value_set_boolean (&(pair->cdr), *(gboolean *)cdr); + break; + case G_TYPE_DOUBLE: + g_value_set_double (&(pair->cdr), *(gdouble *)cdr); + break; + } + return pair; +} + +static BusPair * +bus_pair_copy (BusPair *pair) +{ + g_assert (pair != NULL); + + BusPair *new_pair; + + new_pair = g_slice_new0 (BusPair); + g_value_copy (&(pair->car), &(new_pair->car)); + g_value_copy (&(pair->cdr), &(new_pair->cdr)); + return new_pair; +} + +static void +bus_pair_free (BusPair *pair) +{ + g_assert (pair == NULL); + + g_value_unset (&(pair->car)); + g_value_unset (&(pair->cdr)); + + g_slice_free (BusPair, pair); +} + +#endif + +GType +ibus_config_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusConfigClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_config_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusConfig), + 0, + (GInstanceInitFunc) ibus_config_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_PROXY, + "IBusConfig", + &type_info, + (GTypeFlags)0); + } + return type; +} + +IBusConfig * +ibus_config_new (IBusConnection *connection) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + + GObject *obj; + obj = g_object_new (IBUS_TYPE_CONFIG, + "name", IBUS_SERVICE_CONFIG, + "path", IBUS_PATH_CONFIG, + "connection", connection, + NULL); + + return IBUS_CONFIG (obj); +} + +static void +ibus_config_class_init (IBusConfigClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + IBusProxyClass *proxy_class = IBUS_PROXY_CLASS (klass); + + + parent_class = (IBusProxyClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusConfigPrivate)); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_config_real_destroy; + + proxy_class->ibus_signal = ibus_config_ibus_signal; + + /* install signals */ + config_signals[VALUE_CHANGED] = + g_signal_new (I_("value-changed"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__STRING_STRING_BOXED, + G_TYPE_NONE, + 3, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_VALUE | G_SIGNAL_TYPE_STATIC_SCOPE); +} + +static void +ibus_config_init (IBusConfig *config) +{ + IBusConfigPrivate *priv; + priv = IBUS_CONFIG_GET_PRIVATE (config); +} + +static void +ibus_config_real_destroy (IBusConfig *config) +{ + if (ibus_proxy_get_connection ((IBusProxy *) config) != NULL) { + ibus_proxy_call ((IBusProxy *) config, + "Destroy", + G_TYPE_INVALID); + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (config)); +} + + +static gboolean +ibus_config_ibus_signal (IBusProxy *proxy, + IBusMessage *message) +{ + g_assert (IBUS_IS_CONFIG (proxy)); + g_assert (message != NULL); + + IBusConfig *config; + config = IBUS_CONFIG (proxy); + + if (ibus_message_is_signal (message, IBUS_INTERFACE_CONFIG, "ValueChanged")) { + gchar *section; + gchar *name; + GValue value = { 0 }; + IBusError *error = NULL; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, §ion, + G_TYPE_STRING, &name, + G_TYPE_VALUE, &value, + G_TYPE_INVALID); + if (!retval) { + g_warning ("%s: Can not parse arguments of ValueChanges.", DBUS_ERROR_INVALID_ARGS); + return FALSE; + } + + g_signal_emit (config, + config_signals[VALUE_CHANGED], + 0, + section, + name, + &value); + g_value_unset (&value); + + g_signal_stop_emission_by_name (config, "ibus-signal"); + + return TRUE; + } + + return FALSE; +} + +gboolean +ibus_config_get_value (IBusConfig *config, + const gchar *section, + const gchar *name, + GValue *value) +{ + g_assert (IBUS_IS_CONFIG (config)); + g_assert (section != NULL); + g_assert (name != NULL); + g_assert (value != NULL); + + IBusMessage *reply; + IBusError *error; + gboolean retval; + + reply = ibus_proxy_call_with_reply_and_block ((IBusProxy *) config, + "GetValue", + -1, + &error, + G_TYPE_STRING, §ion, + G_TYPE_STRING, &name, + G_TYPE_INVALID); + if (reply == NULL) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + return FALSE; + } + + if ((error = ibus_error_new_from_message (reply)) != NULL) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + ibus_message_unref (reply); + return FALSE; + } + + retval = ibus_message_get_args (reply, + &error, + G_TYPE_VALUE, value, + G_TYPE_INVALID); + ibus_message_unref (reply); + if (!retval) { + g_warning ("%s: %s", error->name, error->message); + return FALSE; + } + + return TRUE; +} + +gboolean +ibus_config_set_value (IBusConfig *config, + const gchar *section, + const gchar *name, + const GValue *value) +{ + g_assert (IBUS_IS_CONFIG (config)); + g_assert (section != NULL); + g_assert (name != NULL); + g_assert (value != NULL); + + gboolean retval; + + retval = ibus_proxy_call ((IBusProxy *) config, + "SetValue", + G_TYPE_STRING, §ion, + G_TYPE_STRING, &name, + G_TYPE_VALUE, value, + G_TYPE_INVALID); + g_assert (retval); + return TRUE; +} diff --git a/src/ibusconfig.h b/src/ibusconfig.h new file mode 100644 index 0000000..734218f --- /dev/null +++ b/src/ibusconfig.h @@ -0,0 +1,70 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __CONFIG_H_ +#define __CONFIG_H_ + +#include "ibusproxy.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_CONFIG \ + (ibus_config_get_type ()) +#define IBUS_CONFIG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_CONFIG, IBusConfig)) +#define IBUS_CONFIG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_CONFIG, IBusConfigClass)) +#define IBUS_IS_CONFIG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_CONFIG)) +#define IBUS_IS_CONFIG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_CONFIG)) +#define IBUS_CONFIG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_CONFIG, IBusConfigClass)) + +G_BEGIN_DECLS + +typedef struct _IBusConfig IBusConfig; +typedef struct _IBusConfigClass IBusConfigClass; + +struct _IBusConfig { + IBusProxy parent; + /* instance members */ +}; + +struct _IBusConfigClass { + IBusProxyClass parent; + /* class members */ +}; + +GType ibus_config_get_type (void); +IBusConfig *ibus_config_new (IBusConnection *connection); +gboolean ibus_config_get_value (IBusConfig *config, + const gchar *section, + const gchar *name, + GValue *value); +gboolean ibus_config_set_value (IBusConfig *config, + const gchar *section, + const gchar *name, + const GValue *value); +G_END_DECLS +#endif + diff --git a/src/ibusconfigprivate.h b/src/ibusconfigprivate.h new file mode 100644 index 0000000..0bd3b8e --- /dev/null +++ b/src/ibusconfigprivate.h @@ -0,0 +1,221 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_CONFIG_PRIVATE_H_ +#define __IBUS_CONFIG_PRIVATE_H_ + +static void +_from_dbus_value (IBusMessageIter *iter, + GValue *value) +{ + g_assert (iter != NULL); + g_assert (value != NULL); + + gint type; + IBusMessageIter sub_iter; + + type = ibus_message_iter_get_arg_type (iter); + if (type == IBUS_TYPE_VARIANT) { + ibus_message_iter_recurse (iter, IBUS_TYPE_VARIANT, &sub_iter); + ibus_message_iter_next (iter); + iter = &sub_iter; + type = ibus_message_iter_get_arg_type (iter); + } + + switch (type) { + case G_TYPE_STRING: + { + gchar *v; + g_value_init (value, G_TYPE_STRING); + ibus_message_iter_get_basic (iter, &v); + g_value_set_string (value, v); + } + break; + case G_TYPE_INT: + { + gint v; + g_value_init (value, G_TYPE_INT); + ibus_message_iter_get_basic (iter, &v); + g_value_set_int (value, v); + } + break; + case G_TYPE_UINT: + { + guint v; + g_value_init (value, G_TYPE_UINT); + ibus_message_iter_get_basic (iter, &v); + g_value_set_uint (value, v); + } + break; + case G_TYPE_BOOLEAN: + { + gboolean v; + g_value_init (value, G_TYPE_BOOLEAN); + ibus_message_iter_get_basic (iter, &v); + g_value_set_boolean (value, v); + } + break; + case G_TYPE_DOUBLE: + { + gdouble v; + g_value_init (value, G_TYPE_DOUBLE); + ibus_message_iter_get_basic (iter, &v); + g_value_set_double (value, v); + } + break; + default: + if (type == IBUS_TYPE_ARRAY) { + GValue v = { 0 }; + IBusMessageIter sub_iter; + gint sub_type; + GValueArray *array; + + + sub_type = ibus_message_iter_get_element_type (iter); + g_assert (sub_type == G_TYPE_STRING || + sub_type == G_TYPE_INT || + sub_type == G_TYPE_UINT || + sub_type == G_TYPE_BOOLEAN || + sub_type == G_TYPE_DOUBLE || + sub_type == IBUS_TYPE_VARIANT); + + g_value_init (value, G_TYPE_VALUE_ARRAY); + array = g_value_array_new (0); + ibus_message_iter_recurse (iter, IBUS_TYPE_ARRAY, &sub_iter); + while (ibus_message_iter_get_arg_type (&sub_iter) != G_TYPE_INVALID) { + _from_dbus_value (&sub_iter, &v); + g_value_array_append (array, &v); + g_value_unset (&v); + } + g_value_take_boxed (value, array); + ibus_message_iter_next (iter); + break; + } + + g_debug ("type=%s", g_type_name (type)); + + g_assert_not_reached(); + } +} + +static void +_to_dbus_value (IBusMessageIter *iter, + const GValue *value) +{ + IBusMessageIter sub_iter; + gboolean retval; + + + switch (G_VALUE_TYPE (value)) { + case G_TYPE_STRING: + { + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_VARIANT, "s", &sub_iter); + g_assert (retval); + + const gchar *v = g_value_get_string (value); + ibus_message_iter_append (&sub_iter, + G_TYPE_STRING, + &v); + ibus_message_iter_close_container (iter, &sub_iter); + } + break; + case G_TYPE_INT: + { + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_VARIANT, "i", &sub_iter); + g_assert (retval); + + gint v = g_value_get_int (value); + ibus_message_iter_append (&sub_iter, + G_TYPE_INT, + &v); + ibus_message_iter_close_container (iter, &sub_iter); + } + break; + case G_TYPE_UINT: + { + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_VARIANT, "u", &sub_iter); + g_assert (retval); + + guint v = g_value_get_uint (value); + ibus_message_iter_append (&sub_iter, + G_TYPE_UINT, + &v); + ibus_message_iter_close_container (iter, &sub_iter); + } + break; + case G_TYPE_BOOLEAN: + { + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_VARIANT, "b", &sub_iter); + g_assert (retval); + + gboolean v = g_value_get_boolean (value); + ibus_message_iter_append (&sub_iter, + G_TYPE_BOOLEAN, + &v); + ibus_message_iter_close_container (iter, &sub_iter); + } + break; + case G_TYPE_DOUBLE: + { + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_VARIANT, "d", &sub_iter); + g_assert (retval); + + gdouble v = g_value_get_double (value); + ibus_message_iter_append (&sub_iter, + G_TYPE_DOUBLE, + &v); + ibus_message_iter_close_container (iter, &sub_iter); + } + break; + default: + if (G_TYPE_VALUE_ARRAY == G_VALUE_TYPE (value)) { + IBusMessageIter sub_sub_iter; + GType type = G_TYPE_INVALID; + gint i; + + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_VARIANT, "av", &sub_iter); + g_assert (retval); + + GValueArray *array = (GValueArray *)g_value_get_boxed (value); + ibus_message_iter_open_container (&sub_iter, + IBUS_TYPE_ARRAY, + "v", + &sub_sub_iter); + if (array->n_values > 0) { + type = G_VALUE_TYPE (&array->values[0]); + g_assert (type == G_TYPE_STRING || + type == G_TYPE_INT || + type == G_TYPE_UINT || + type == G_TYPE_BOOLEAN || + type == G_TYPE_DOUBLE); + } + for (i = 0; i < array->n_values; i++) { + g_assert (type == G_VALUE_TYPE (&array->values[i])); + _to_dbus_value (&sub_sub_iter, &array->values[i]); + } + ibus_message_iter_close_container (&sub_iter, &sub_sub_iter); + ibus_message_iter_close_container (iter, &sub_iter); + break; + } + g_assert_not_reached(); + } + +} +#endif + diff --git a/src/ibusconfigservice.c b/src/ibusconfigservice.c new file mode 100644 index 0000000..6465add --- /dev/null +++ b/src/ibusconfigservice.c @@ -0,0 +1,314 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibusshare.h" +#include "ibusconfigservice.h" + +enum { + LAST_SIGNAL, +}; + +enum { + PROP_0, + PROP_CONNECTION, +}; + +// static guint config_service_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_config_service_class_init (IBusConfigServiceClass *klass); +static void ibus_config_service_init (IBusConfigService *config); +static void ibus_config_service_set_property (IBusConfigService *config, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void ibus_config_service_get_property (IBusConfigService *config, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void ibus_config_service_destroy (IBusConfigService *config); +static gboolean ibus_config_service_ibus_message (IBusConfigService *config, + IBusConnection *connection, + IBusMessage *message); +static gboolean ibus_config_service_set_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + const GValue *value, + IBusError **error); +static gboolean ibus_config_service_get_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GValue *value, + IBusError **error); + +static IBusServiceClass *parent_class = NULL; + +GType +ibus_config_service_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusConfigServiceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_config_service_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusConfigService), + 0, + (GInstanceInitFunc) ibus_config_service_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERVICE, + "IBusConfigService", + &type_info, + (GTypeFlags) 0); + } + return type; +} + +IBusConfigService * +ibus_config_service_new (IBusConnection *connection) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusConfigService *config; + + config = (IBusConfigService *) g_object_new (IBUS_TYPE_CONFIG_SERVICE, + "path", IBUS_PATH_CONFIG, + "connection", connection, + NULL); + + return config; +} + +static void +ibus_config_service_class_init (IBusConfigServiceClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass); + + gobject_class->set_property = (GObjectSetPropertyFunc) ibus_config_service_set_property; + gobject_class->get_property = (GObjectGetPropertyFunc) ibus_config_service_get_property; + + IBUS_OBJECT_CLASS (gobject_class)->destroy = (IBusObjectDestroyFunc) ibus_config_service_destroy; + + IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_config_service_ibus_message; + + klass->set_value = ibus_config_service_set_value; + klass->get_value = ibus_config_service_get_value; + + g_object_class_install_property (gobject_class, + PROP_CONNECTION, + g_param_spec_object ("connection", + "connection", + "The connection of config object", + IBUS_TYPE_CONNECTION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +ibus_config_service_init (IBusConfigService *config) +{ +} + +static void +ibus_config_service_set_property (IBusConfigService *config, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_CONNECTION: + ibus_service_add_to_connection ((IBusService *) config, + g_value_get_object (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (config, prop_id, pspec); + } +} + +static void +ibus_config_service_get_property (IBusConfigService *config, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_CONNECTION: + { + GList *connections = ibus_service_get_connections ((IBusService *) config); + if (connections) { + g_value_set_object (value, connections->data); + } + else { + g_value_set_object (value, NULL); + } + g_list_foreach (connections, (GFunc) g_object_unref, NULL); + g_list_free (connections); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (config, prop_id, pspec); + } +} + +static void +ibus_config_service_destroy (IBusConfigService *config) +{ + IBUS_OBJECT_CLASS(parent_class)->destroy ((IBusObject *) config); +} + +static gboolean +ibus_config_service_ibus_message (IBusConfigService *config, + IBusConnection *connection, + IBusMessage *message) +{ + g_assert (IBUS_IS_CONFIG_SERVICE (config)); + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + + IBusMessage *reply = NULL; + + if (ibus_message_is_method_call (message, IBUS_INTERFACE_CONFIG, "SetValue")) { + gchar *section; + gchar *name; + GValue value = { 0 }; + IBusError *error = NULL; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, §ion, + G_TYPE_STRING, &name, + G_TYPE_VALUE, &value, + G_TYPE_INVALID); + if (!retval) { + reply = ibus_message_new_error_printf (message, + DBUS_ERROR_INVALID_ARGS, + "Can not parse arguments 1 of SetValue"); + ibus_error_free (error); + } + else if (!IBUS_CONFIG_SERVICE_GET_CLASS (config)->set_value (config, section, name, &value, &error)) { + reply = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + } + else { + reply = ibus_message_new_method_return (message); + } + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_CONFIG, "GetValue")) { + gchar *section; + gchar *name; + GValue value = { 0 }; + IBusError *error = NULL; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, §ion, + G_TYPE_STRING, &name, + G_TYPE_INVALID); + + if (!retval) { + reply = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + } + else if (!IBUS_CONFIG_SERVICE_GET_CLASS (config)->get_value (config, section, name, &value, &error)) { + reply = ibus_message_new_error (message, + error->name, + error->message); + ibus_error_free (error); + } + else { + reply = ibus_message_new_method_return (message); + ibus_message_append_args (reply, + G_TYPE_VALUE, &value, + G_TYPE_INVALID); + g_value_unset (&value); + } + } + + if (reply) { + ibus_connection_send (connection, reply); + ibus_message_unref (reply); + return TRUE; + } + + return parent_class->ibus_message ((IBusService *) config, connection, message); +} + +static gboolean +ibus_config_service_set_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + const GValue *value, + IBusError **error) +{ + if (error) { + *error = ibus_error_new_from_printf (DBUS_ERROR_FAILED, + "Can not set value [%s, %s]", + section, name); + } + return FALSE; +} + +static gboolean +ibus_config_service_get_value (IBusConfigService *config, + const gchar *section, + const gchar *name, + GValue *value, + IBusError **error) +{ + if (error) { + *error = ibus_error_new_from_printf (DBUS_ERROR_FAILED, + "Can not get value [%s, %s]", + section, name); + } + return FALSE; +} + +void +ibus_config_service_value_changed (IBusConfigService *config, + const gchar *section, + const gchar *name, + const GValue *value) +{ + g_assert (IBUS_IS_CONFIG_SERVICE (config)); + g_assert (section); + g_assert (name); + g_assert (G_IS_VALUE (value)); + + ibus_service_send_signal ((IBusService *) config, + IBUS_INTERFACE_CONFIG, + "ValueChanged", + G_TYPE_STRING, §ion, + G_TYPE_STRING, &name, + G_TYPE_VALUE, value, + G_TYPE_INVALID); +} diff --git a/src/ibusconfigservice.h b/src/ibusconfigservice.h new file mode 100644 index 0000000..f04a5eb --- /dev/null +++ b/src/ibusconfigservice.h @@ -0,0 +1,85 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_CONFIG_SERVICE_H_ +#define __IBUS_CONFIG_SERVICE_H_ + +#include "ibuserror.h" +#include "ibusservice.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_CONFIG_SERVICE \ + (ibus_config_service_get_type ()) +#define IBUS_CONFIG_SERVICE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_CONFIG_SERVICE, IBusConfigService)) +#define IBUS_CONFIG_SERVICE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_CONFIG_SERVICE, IBusConfigServiceClass)) +#define IBUS_IS_CONFIG_SERVICE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_CONFIG_SERVICE)) +#define IBUS_IS_CONFIG_SERVICE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_CONFIG_SERVICE)) +#define IBUS_CONFIG_SERVICE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_CONFIG_SERVICE, IBusConfigServiceClass)) + +G_BEGIN_DECLS + +typedef struct _IBusConfigService IBusConfigService; +typedef struct _IBusConfigServiceClass IBusConfigServiceClass; + +struct _IBusConfigService { + IBusService parent; + + /* instance members */ +}; + +struct _IBusConfigServiceClass { + IBusServiceClass parent; + + /* class members */ + gboolean (* set_value) (IBusConfigService *config, + const gchar *section, + const gchar *name, + const GValue *value, + IBusError **error); + gboolean (* get_value) (IBusConfigService *config, + const gchar *section, + const gchar *name, + GValue *value, + IBusError **error); + + /*< private >*/ + /* padding */ + gpointer pdummy[14]; +}; + +GType ibus_config_service_get_type (void); +IBusConfigService *ibus_config_service_new (IBusConnection *connection); +void ibus_config_service_value_changed + (IBusConfigService *config, + const gchar *section, + const gchar *name, + const GValue *value); + +G_END_DECLS +#endif + diff --git a/src/ibusconnection.c b/src/ibusconnection.c new file mode 100644 index 0000000..90776cd --- /dev/null +++ b/src/ibusconnection.c @@ -0,0 +1,697 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 <stdarg.h> +#include "ibusmessage.h" +#include "ibusconnection.h" +#include "ibusinternal.h" + +#define IBUS_CONNECTION_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_CONNECTION, IBusConnectionPrivate)) + +enum { + IBUS_SIGNAL, + IBUS_MESSAGE, + IBUS_MESSAGE_SENT, + DISCONNECTED, + LAST_SIGNAL, +}; + + +/* IBusConnectionPriv */ +struct _IBusConnectionPrivate { + DBusConnection *connection; + gboolean shared; +}; +typedef struct _IBusConnectionPrivate IBusConnectionPrivate; + +static guint connection_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_connection_class_init (IBusConnectionClass *klass); +static void ibus_connection_init (IBusConnection *connection); +static void ibus_connection_destroy (IBusConnection *connection); + +static gboolean ibus_connection_ibus_message(IBusConnection *connection, + IBusMessage *message); +static gboolean ibus_connection_ibus_signal (IBusConnection *connection, + IBusMessage *message); +static void ibus_connection_disconnected(IBusConnection *connection); +static DBusHandlerResult + _connection_handle_message_cb(DBusConnection *dbus_connection, + IBusMessage *message, + IBusConnection *connection); + +static IBusObjectClass *parent_class = NULL; +static GHashTable *_connections = NULL; + +GType +ibus_connection_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusConnectionClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_connection_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusConnection), + 0, + (GInstanceInitFunc) ibus_connection_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "IBusConnection", + &type_info, + (GTypeFlags)0); + } + + return type; +} + +IBusConnection * +ibus_connection_new (void) +{ + GObject *object; + object = g_object_new (IBUS_TYPE_CONNECTION, NULL); + return IBUS_CONNECTION (object); +} + +static void +ibus_connection_class_init (IBusConnectionClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusConnectionPrivate)); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_connection_destroy; + + klass->ibus_message = ibus_connection_ibus_message; + klass->ibus_signal = ibus_connection_ibus_signal; + klass->disconnected = ibus_connection_disconnected; + + connection_signals[IBUS_MESSAGE] = + g_signal_new (I_("ibus-message"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusConnectionClass, ibus_message), + NULL, NULL, + ibus_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, 1, + G_TYPE_POINTER); + + connection_signals[IBUS_SIGNAL] = + g_signal_new (I_("ibus-signal"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusConnectionClass, ibus_signal), + NULL, NULL, + ibus_marshal_BOOL__POINTER, + G_TYPE_BOOLEAN, 1, + G_TYPE_POINTER); + + connection_signals[IBUS_MESSAGE_SENT] = + g_signal_new (I_("ibus-message-sent"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusConnectionClass, ibus_message_sent), + NULL, NULL, + ibus_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + + connection_signals[DISCONNECTED] = + g_signal_new (I_("disconnected"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusConnectionClass, disconnected), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + +} + +static void +ibus_connection_init (IBusConnection *connection) +{ + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + priv->connection = NULL; + priv->shared = FALSE; +} + +static void +ibus_connection_destroy (IBusConnection *connection) +{ + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + if (priv->connection) { + dbus_connection_remove_filter (priv->connection, + (DBusHandleMessageFunction) _connection_handle_message_cb, + connection); + } + + if (!priv->shared && priv->connection) { + dbus_connection_close (priv->connection); + dbus_connection_unref (priv->connection); + priv->connection = NULL; + goto _out; + } + + if (priv->shared && priv->connection) { + g_warn_if_fail (_connections != NULL); + if (_connections != NULL) { + g_hash_table_remove (_connections, priv->connection); + } + dbus_connection_unref (priv->connection); + priv->connection = NULL; + goto _out; + } +_out: + parent_class->destroy (IBUS_OBJECT (connection)); +} + +static gboolean +ibus_connection_ibus_message (IBusConnection *connection, + IBusMessage *message) +{ + gboolean retval = FALSE; + + if (ibus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL) + g_signal_emit (connection, connection_signals[IBUS_SIGNAL], 0, message, &retval); + + return retval; +} + +static gboolean +ibus_connection_ibus_signal (IBusConnection *connection, IBusMessage *message) +{ + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + if (ibus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")) { + g_signal_emit (connection, connection_signals[DISCONNECTED], 0); + return FALSE; + } + return FALSE; +} + +static void +ibus_connection_disconnected (IBusConnection *connection) +{ + ibus_object_destroy (IBUS_OBJECT (connection)); +} + +static DBusHandlerResult +_connection_handle_message_cb (DBusConnection *dbus_connection, + IBusMessage *message, + IBusConnection *connection) +{ + gboolean retval = FALSE; + + gint type; + + type = ibus_message_get_type (message); + g_signal_emit (connection, connection_signals[IBUS_MESSAGE], 0, message, &retval); + + if (retval) + return DBUS_HANDLER_RESULT_HANDLED; + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static gint +_get_slot () +{ + static gint slot = -1; + if (slot == -1) { + dbus_connection_allocate_data_slot (&slot); + } + return slot; +} + +void +ibus_connection_set_connection (IBusConnection *connection, DBusConnection *dbus_connection, gboolean shared) +{ + gboolean result; + IBusConnectionPrivate *priv; + + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (dbus_connection != NULL); + g_assert (dbus_connection_get_is_connected (dbus_connection)); + + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + g_assert (priv->connection == NULL); + + priv->connection = dbus_connection_ref (dbus_connection); + priv->shared = shared; + + dbus_connection_set_data (priv->connection, _get_slot(), connection, NULL); + + result = dbus_connection_add_filter (priv->connection, + (DBusHandleMessageFunction) _connection_handle_message_cb, + connection, NULL); + + dbus_connection_setup (priv->connection, NULL); + g_warn_if_fail (result); +} + +IBusConnection * +ibus_connection_open (const gchar *address) +{ + g_assert (address != NULL); + + DBusError error; + DBusConnection *dbus_connection; + IBusConnection *connection; + + if (_connections == NULL) { + _connections = g_hash_table_new (g_direct_hash, g_direct_equal); + } + + + dbus_error_init (&error); + dbus_connection = dbus_connection_open (address, &error); + if (dbus_connection == NULL) { + g_warning ("Connect to %s failed. %s.", address, error.message); + dbus_error_free (&error); + return NULL; + } + + connection = g_hash_table_lookup (_connections, dbus_connection); + + if (connection) { + dbus_connection_unref (dbus_connection); + g_object_ref (connection); + return connection; + } + + connection = ibus_connection_new (); + ibus_connection_set_connection (connection, dbus_connection, TRUE); + g_hash_table_insert (_connections, dbus_connection, connection); + + return connection; +} + +IBusConnection * +ibus_connection_open_private (const gchar *address) +{ + g_assert (address != NULL); + + DBusError error; + DBusConnection *dbus_connection; + IBusConnection *connection; + + dbus_error_init (&error); + dbus_connection = dbus_connection_open_private (address, &error); + if (dbus_connection == NULL) { + g_warning ("Connect to %s failed. %s.", address, error.message); + dbus_error_free (&error); + return NULL; + } + + connection = ibus_connection_new (); + ibus_connection_set_connection (connection, dbus_connection, FALSE); + + return connection; +} + +void ibus_connection_close (IBusConnection *connection) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + dbus_connection_close (priv->connection); +} + +gboolean +ibus_connection_is_connected (IBusConnection *connection) +{ + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + if (priv->connection == NULL) { + return FALSE; + } + return dbus_connection_get_is_connected (priv->connection); +} + +DBusConnection * +ibus_connection_get_connection (IBusConnection *connection) +{ + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + return priv->connection; +} + +typedef struct _VTableCallData { + IBusMessageFunc message_func; + gpointer user_data; +}VTableCallData; + +void +_unregister_function (DBusConnection *dbus_connection, VTableCallData *data) +{ + g_slice_free (VTableCallData, data); +} + +DBusHandlerResult +_message_function (DBusConnection *dbus_connection, + DBusMessage *message, + VTableCallData *data) +{ + gboolean retval; + IBusConnection *connection; + + connection = IBUS_CONNECTION (dbus_connection_get_data (dbus_connection, _get_slot())); + retval = data->message_func (connection, message, data->user_data); + + return retval ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +gboolean +ibus_connection_register_object_path (IBusConnection *connection, + const gchar *path, IBusMessageFunc message_func, gpointer user_data) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (path != NULL); + g_assert (message_func != NULL); + + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + gboolean retval; + DBusObjectPathVTable vtable = {0}; + VTableCallData *data; + + vtable.unregister_function = (DBusObjectPathUnregisterFunction) _unregister_function; + vtable.message_function = (DBusObjectPathMessageFunction) _message_function; + + data = g_slice_new (VTableCallData); + data->message_func = message_func; + data->user_data = user_data; + + retval = dbus_connection_register_object_path (priv->connection, path, &vtable, data); + if (!retval) { + g_warning ("Out of memory!"); + return FALSE; + } + return TRUE; +} + +gboolean +ibus_connection_unregister_object_path (IBusConnection *connection, const gchar *path) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (path != NULL); + + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + gboolean retval; + + retval = dbus_connection_unregister_object_path (priv->connection, path); + if (!retval) { + g_warning ("Out of memory!"); + return FALSE; + } + + return TRUE; +} + + +gboolean +ibus_connection_send (IBusConnection *connection, + IBusMessage *message) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + + gboolean retval; + IBusConnectionPrivate *priv; + + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + retval = dbus_connection_send (priv->connection, message, NULL); + + if (retval) { + g_signal_emit (connection, + connection_signals[IBUS_MESSAGE_SENT], + 0, + message); + } + + return retval; +} + + +gboolean +ibus_connection_send_signal (IBusConnection *connection, + const gchar *path, + const gchar *interface, + const gchar *name, + GType first_arg_type, + ...) +{ + va_list args; + gboolean retval; + + va_start (args, first_arg_type); + retval = ibus_connection_send_signal_valist (connection, + path, + interface, + name, + first_arg_type, + args); + va_end (args); + return retval; +} + +gboolean +ibus_connection_send_signal_valist (IBusConnection *connection, + const gchar *path, + const gchar *interface, + const gchar *name, + GType first_arg_type, + va_list args) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (interface != NULL); + g_assert (name != NULL); + + gboolean retval; + IBusMessage *message; + + message = ibus_message_new_signal (path, interface, name); + + ibus_message_append_args_valist (message, first_arg_type, args); + retval = ibus_connection_send (connection, message); + ibus_message_unref (message); + + return retval; +} + +gboolean +ibus_connection_send_valist (IBusConnection *connection, + gint message_type, + const gchar *path, + const gchar *interface, + const gchar *name, + GType first_arg_type, + va_list args) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (interface != NULL); + g_assert (name != NULL); + + gboolean retval; + IBusMessage *message; + + message = ibus_message_new (message_type); + ibus_message_set_path (message, path); + ibus_message_set_interface (message, interface); + ibus_message_set_member (message, name); + + ibus_message_append_args_valist (message, first_arg_type, args); + retval = ibus_connection_send (connection, message); + ibus_message_unref (message); + + return retval; +} + +gboolean +ibus_connection_send_with_reply (IBusConnection *connection, + IBusMessage *message, + IBusPendingCall **pending_return, + gint timeout_milliseconds) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + g_assert (pending_return != NULL); + g_assert (timeout_milliseconds > 0 || timeout_milliseconds == -1); + + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + return dbus_connection_send_with_reply (priv->connection, + message, + pending_return, + timeout_milliseconds); +} + +IBusMessage * +ibus_connection_send_with_reply_and_block (IBusConnection *connection, + IBusMessage *message, + gint timeout_milliseconds, + IBusError **error) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + g_assert (timeout_milliseconds > 0 || timeout_milliseconds == -1); + + IBusError *_error; + IBusMessage *reply; + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + _error = ibus_error_new (); + + reply = dbus_connection_send_with_reply_and_block (priv->connection, + message, + timeout_milliseconds, + _error); + + if (reply != NULL) { + g_signal_emit (connection, + connection_signals[IBUS_MESSAGE_SENT], + 0, + message); + } + + if (reply == NULL && error != NULL) { + *error = _error; + } + else + ibus_error_free (_error); + + return reply; +} + +gboolean +ibus_connection_call (IBusConnection *connection, + const gchar *name, + const gchar *path, + const gchar *interface, + const gchar *member, + IBusError **error, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (name != NULL); + g_assert (path != NULL); + g_assert (interface != NULL); + g_assert (member != NULL); + + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + g_assert (dbus_connection_get_is_connected (priv->connection)); + + IBusMessage *message, *reply; + IBusError *tmp_error; + va_list args; + GType type; + gboolean retval; + + message = ibus_message_new_method_call (name, path, interface, member); + + va_start (args, first_arg_type); + + ibus_message_append_args_valist (message, first_arg_type, args); + + va_end (args); + + reply = ibus_connection_send_with_reply_and_block ( + connection, + message, + -1, + error); + ibus_message_unref (message); + + if (reply == NULL) { + return FALSE; + } + + if ((tmp_error = ibus_error_new_from_message (reply)) != NULL) { + if (error) { + *error = tmp_error; + } + else + ibus_error_free (tmp_error); + ibus_message_unref (reply); + return FALSE; + } + + va_start (args, first_arg_type); + + type = first_arg_type; + + while (type != DBUS_TYPE_INVALID) { + va_arg (args, gpointer); + type = va_arg (args, GType); + } + type = va_arg (args, GType); + + if (type != G_TYPE_INVALID) { + retval = ibus_message_get_args_valist (reply, error, type, args); + } + + va_end (args); + + ibus_message_unref (reply); + + if (!retval) { + return FALSE; + } + + return TRUE; +} + +void +ibus_connection_flush (IBusConnection *connection) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (ibus_connection_is_connected (connection)); + + IBusConnectionPrivate *priv; + + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + dbus_connection_flush (priv->connection); +} diff --git a/src/ibusconnection.h b/src/ibusconnection.h new file mode 100644 index 0000000..e4a70f7 --- /dev/null +++ b/src/ibusconnection.h @@ -0,0 +1,147 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_CONNECTION_H_ +#define __IBUS_CONNECTION_H_ + +#include <dbus/dbus.h> +#include "ibusmessage.h" +#include "ibuspendingcall.h" +#include "ibusobject.h" +#include "ibuserror.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_CONNECTION \ + (ibus_connection_get_type ()) +#define IBUS_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_CONNECTION, IBusConnection)) +#define IBUS_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_CONNECTION, IBusConnectionClass)) +#define IBUS_IS_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_CONNECTION)) +#define IBUS_IS_CONNECTION_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_CONNECTION)) +#define IBUS_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_CONNECTION, IBusConnectionClass)) + +G_BEGIN_DECLS + +typedef struct _IBusConnection IBusConnection; +typedef struct _IBusConnectionClass IBusConnectionClass; + +typedef gboolean (* IBusIBusMessageFunc)(IBusConnection *connection, + IBusMessage *message); +typedef gboolean (* IBusIBusSignalFunc) (IBusConnection *connection, + IBusMessage *message); +typedef gboolean (* IBusMessageFunc) (IBusConnection *connection, + IBusMessage *message, + gpointer user_data); +typedef void (* IBusConnectionReplyFunc) + (IBusConnection *connection, + IBusMessage *reply, + gpointer user_data); + +struct _IBusConnection { + IBusObject parent; + /* instance members */ +}; + +struct _IBusConnectionClass { + IBusObjectClass parent; + + /* signals */ + gboolean (* ibus_message) (IBusConnection *connection, + IBusMessage *message); + gboolean (* ibus_signal) (IBusConnection *connection, + IBusMessage *message); + void (* ibus_message_sent) + (IBusConnection *connection, + IBusMessage *message); + void (* disconnected) (IBusConnection *connection); + + /*< private >*/ + /* padding */ + gpointer pdummy[4]; +}; + +GType ibus_connection_get_type (void); +IBusConnection *ibus_connection_new (void); +void ibus_connection_set_connection (IBusConnection *connection, + DBusConnection *dbus_connection, + gboolean shared); +IBusConnection *ibus_connection_open (const gchar *address); +IBusConnection *ibus_connection_open_private (const gchar *address); +void ibus_connection_close (IBusConnection *connection); +gboolean ibus_connection_is_connected (IBusConnection *connection); +DBusConnection *ibus_connection_get_connection (IBusConnection *connection); +gboolean ibus_connection_send (IBusConnection *connection, + IBusMessage *message); +gboolean ibus_connection_send_signal (IBusConnection *connection, + const gchar *path, + const gchar *interface, + const gchar *name, + GType first_arg_type, + ...); +gboolean ibus_connection_send_signal_valist (IBusConnection *connection, + const gchar *path, + const gchar *interface, + const gchar *name, + GType first_arg_type, + va_list args); +gboolean ibus_connection_send_valist (IBusConnection *connection, + gint message_type, + const gchar *path, + const gchar *interface, + const gchar *name, + GType first_arg_type, + va_list args); +gboolean ibus_connection_send_with_reply (IBusConnection *connection, + IBusMessage *message, + IBusPendingCall **pending_return, + gint timeout_milliseconds); +IBusMessage *ibus_connection_send_with_reply_and_block + (IBusConnection *connection, + IBusMessage *message, + gint timeout_milliseconds, + IBusError **error); +gboolean ibus_connection_call (IBusConnection *connection, + const gchar *name, + const gchar *path, + const gchar *interface, + const gchar *member, + IBusError **error, + GType first_arg_type, + ...); +void ibus_connection_flush (IBusConnection *connection); +gboolean ibus_connection_register_object_path + (IBusConnection *connection, + const gchar *path, + IBusMessageFunc message_func, + gpointer user_data); +gboolean ibus_connection_unregister_object_path + (IBusConnection *connection, + const gchar *path); + +G_END_DECLS +#endif + diff --git a/src/ibusdebug.h b/src/ibusdebug.h new file mode 100644 index 0000000..7a59a8d --- /dev/null +++ b/src/ibusdebug.h @@ -0,0 +1,27 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_DEBUG_H_ +#define __IBUS_DEBUG_H_ + +#define ibus_warning(msg, args...) \ + g_warning("%s:%d, " msg, __FILE__, __LINE__, ##args) + +#endif + diff --git a/src/ibusengine.c b/src/ibusengine.c new file mode 100644 index 0000000..ddedcde --- /dev/null +++ b/src/ibusengine.c @@ -0,0 +1,957 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 <stdarg.h> +#include "ibusengine.h" +#include "ibusinternal.h" +#include "ibusshare.h" + +#define IBUS_ENGINE_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_ENGINE, IBusEnginePrivate)) + +enum { + PROCESS_KEY_EVENT, + FOCUS_IN, + FOCUS_OUT, + RESET, + ENABLE, + DISABLE, + SET_CURSOR_LOCATION, + SET_CAPABILITIES, + PAGE_UP, + PAGE_DOWN, + CURSOR_UP, + CURSOR_DOWN, + PROPERTY_ACTIVATE, + PROPERTY_SHOW, + PROPERTY_HIDE, + LAST_SIGNAL, +}; + +enum { + PROP_0, + PROP_NAME, + PROP_CONNECTION, +}; + + +/* IBusEnginePriv */ +struct _IBusEnginePrivate { + gchar *name; + IBusConnection *connection; +}; +typedef struct _IBusEnginePrivate IBusEnginePrivate; + +static guint engine_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_engine_class_init (IBusEngineClass *klass); +static void ibus_engine_init (IBusEngine *engine); +static void ibus_engine_destroy (IBusEngine *engine); +static void ibus_engine_set_property (IBusEngine *engine, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void ibus_engine_get_property (IBusEngine *engine, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static gboolean ibus_engine_ibus_message (IBusEngine *engine, + IBusConnection *connection, + IBusMessage *message); +static gboolean ibus_engine_process_key_event + (IBusEngine *engine, + guint keyval, + guint state); +static void ibus_engine_focus_in (IBusEngine *engine); +static void ibus_engine_focus_out (IBusEngine *engine); +static void ibus_engine_reset (IBusEngine *engine); +static void ibus_engine_enable (IBusEngine *engine); +static void ibus_engine_disable (IBusEngine *engine); +static void ibus_engine_set_cursor_location + (IBusEngine *engine, + gint x, + gint y, + gint w, + gint h); +static void ibus_engine_set_capabilities + (IBusEngine *engine, + guint caps); +static void ibus_engine_page_up (IBusEngine *engine); +static void ibus_engine_page_down (IBusEngine *engine); +static void ibus_engine_cursor_up (IBusEngine *engine); +static void ibus_engine_cursor_down (IBusEngine *engine); +static void ibus_engine_property_activate + (IBusEngine *engine, + const gchar *prop_name, + gint prop_state); +static void ibus_engine_property_show (IBusEngine *engine, + const gchar *prop_name); +static void ibus_engine_property_hide (IBusEngine *engine, + const gchar *prop_name); + + +static IBusServiceClass *parent_class = NULL; + +GType +ibus_engine_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusEngineClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_engine_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusEngine), + 0, + (GInstanceInitFunc) ibus_engine_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERVICE, + "IBusEngine", + &type_info, + (GTypeFlags) 0); + } + return type; +} + +IBusEngine * +ibus_engine_new (const gchar *name, + const gchar *path, + IBusConnection *connection) +{ + g_assert (path); + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusEngine *engine; + + engine = (IBusEngine *) g_object_new (IBUS_TYPE_ENGINE, + "name", name, + "path", path, + "connection", connection, + NULL); + + return engine; +} + +static void +ibus_engine_class_init (IBusEngineClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusEnginePrivate)); + + gobject_class->set_property = (GObjectSetPropertyFunc) ibus_engine_set_property; + gobject_class->get_property = (GObjectGetPropertyFunc) ibus_engine_get_property; + + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_engine_destroy; + + IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_engine_ibus_message; + + klass->process_key_event = ibus_engine_process_key_event; + klass->focus_in = ibus_engine_focus_in; + klass->focus_out = ibus_engine_focus_out; + klass->reset = ibus_engine_reset; + klass->enable = ibus_engine_enable; + klass->disable = ibus_engine_disable; + klass->page_up = ibus_engine_page_up; + klass->page_down = ibus_engine_page_down; + klass->cursor_up = ibus_engine_cursor_up; + klass->cursor_down = ibus_engine_cursor_down; + klass->property_activate = ibus_engine_property_activate; + klass->property_show = ibus_engine_property_show; + klass->property_hide = ibus_engine_property_hide; + klass->set_cursor_location = ibus_engine_set_cursor_location; + klass->set_capabilities = ibus_engine_set_capabilities; + + + /* install properties */ + g_object_class_install_property (gobject_class, + PROP_NAME, + g_param_spec_string ("name", + "name", + "engine name", + "noname", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + + g_object_class_install_property (gobject_class, + PROP_CONNECTION, + g_param_spec_object ("connection", + "connection", + "The connection of engine object", + IBUS_TYPE_CONNECTION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /* install signals */ + engine_signals[PROCESS_KEY_EVENT] = + g_signal_new (I_("process-key-event"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, process_key_event), + NULL, NULL, + ibus_marshal_BOOL__UINT_UINT, + G_TYPE_BOOLEAN, + 2, + G_TYPE_UINT, + G_TYPE_UINT); + + engine_signals[FOCUS_IN] = + g_signal_new (I_("focus-in"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, focus_in), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[FOCUS_OUT] = + g_signal_new (I_("focus-out"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, focus_out), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[RESET] = + g_signal_new (I_("reset"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, reset), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[ENABLE] = + g_signal_new (I_("enable"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, enable), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[DISABLE] = + g_signal_new (I_("disable"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, disable), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[SET_CURSOR_LOCATION] = + g_signal_new (I_("set-cursor-location"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, set_cursor_location), + NULL, NULL, + ibus_marshal_VOID__INT_INT_INT_INT, + G_TYPE_NONE, 4, + G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT); + + engine_signals[SET_CAPABILITIES] = + g_signal_new (I_("set-capabilities"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, set_capabilities), + NULL, NULL, + ibus_marshal_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + engine_signals[PAGE_UP] = + g_signal_new (I_("page-up"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, page_up), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[PAGE_DOWN] = + g_signal_new (I_("page-down"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, page_down), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[CURSOR_UP] = + g_signal_new (I_("cursor-up"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, cursor_up), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[CURSOR_DOWN] = + g_signal_new (I_("cursor-down"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, cursor_down), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + engine_signals[PROPERTY_ACTIVATE] = + g_signal_new (I_("property-activate"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, property_activate), + NULL, NULL, + ibus_marshal_VOID__STRING_INT, + G_TYPE_NONE, 0); + + engine_signals[PROPERTY_SHOW] = + g_signal_new (I_("property-show"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, property_show), + NULL, NULL, + ibus_marshal_VOID__STRING, + G_TYPE_NONE, 0); + + engine_signals[PROPERTY_HIDE] = + g_signal_new (I_("property-hide"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusEngineClass, property_hide), + NULL, NULL, + ibus_marshal_VOID__STRING, + G_TYPE_NONE, 0); + +} + +static void +ibus_engine_init (IBusEngine *engine) +{ + IBusEnginePrivate *priv; + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + priv->name = NULL; + priv->connection = NULL; +} + +static void +ibus_engine_destroy (IBusEngine *engine) +{ + IBusEnginePrivate *priv; + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + g_free (priv->name); + + if (priv->connection) { + g_object_unref (priv->connection); + priv->connection = NULL; + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (engine)); +} + +static void +ibus_engine_set_property (IBusEngine *engine, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + IBusEnginePrivate *priv; + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + switch (prop_id) { + case PROP_NAME: + priv->name = g_strdup (g_value_dup_string (value)); + break; + + case PROP_CONNECTION: + priv->connection = g_value_get_object (value); + g_object_ref (priv->connection); + ibus_service_add_to_connection ((IBusService *) engine, + priv->connection); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec); + } +} + +static void +ibus_engine_get_property (IBusEngine *engine, + guint prop_id, GValue *value, GParamSpec *pspec) +{ + IBusEnginePrivate *priv; + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + + case PROP_CONNECTION: + g_value_set_object (value, priv->connection); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (engine, prop_id, pspec); + } +} + +static gboolean +ibus_engine_ibus_message (IBusEngine *engine, + IBusConnection *connection, + IBusMessage *message) +{ + g_assert (IBUS_IS_ENGINE (engine)); + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + + IBusEnginePrivate *priv; + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + g_assert (priv->connection == connection); + + IBusMessage *return_message = NULL; + IBusMessage *error_message = NULL; + + static const struct { + gchar *member; + guint signal_id; + } no_arg_methods[] = { + {"FocusIn", FOCUS_IN}, + {"FocusOut", FOCUS_OUT}, + {"Reset", RESET}, + {"Enable", ENABLE}, + {"Disable", DISABLE}, + {"PageUp", PAGE_UP}, + {"PageDown", PAGE_DOWN}, + {"CursorUp", CURSOR_UP}, + {"CursorDown", CURSOR_DOWN}, + {NULL, 0}, + }; + gint i; + + for (i = 0; no_arg_methods[i].member != NULL; i++) { + if (!ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, no_arg_methods[i].member)) + continue; + + IBusMessageIter iter; + ibus_message_iter_init (message, &iter); + if (ibus_message_iter_has_next (&iter)) { + error_message = ibus_message_new_error_printf (message, + "%s.%s: Method does not have arguments", + IBUS_INTERFACE_ENGINE, no_arg_methods[i].member); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + } + + g_signal_emit (engine, engine_signals[no_arg_methods[i].signal_id], 0); + return_message = ibus_message_new_method_return (message); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + } + + + if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "ProcessKeyEvent")) { + guint keyval, state; + gboolean retval; + IBusError *error = NULL; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_UINT, &keyval, + G_TYPE_UINT, &state, + G_TYPE_INVALID); + + if (!retval) + goto _keypress_fail; + + retval = FALSE; + g_signal_emit (engine, + engine_signals[PROCESS_KEY_EVENT], + 0, + keyval, + state, + &retval); + + return_message = ibus_message_new_method_return (message); + ibus_message_append_args (return_message, + G_TYPE_BOOLEAN, &retval, + DBUS_TYPE_INVALID); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + + _keypress_fail: + error_message = ibus_message_new_error_printf (message, + "%s.%s: Can not match signature (ubu) of method", + IBUS_INTERFACE_ENGINE, "ProcessKeyEvent"); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyActivate")) { + gchar *name; + gint state; + gboolean retval; + IBusError *error = NULL; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &name, + G_TYPE_INT, &state, + G_TYPE_INVALID); + + if (!retval) + goto _property_activate_fail; + + g_signal_emit (engine, + engine_signals[PROPERTY_ACTIVATE], + 0, + name, + state); + + return_message = ibus_message_new_method_return (message); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + + _property_activate_fail: + error_message = ibus_message_new_error_printf (message, + "%s.%s: Can not match signature (si) of method", + IBUS_INTERFACE_ENGINE, + "PropertyActivate"); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyShow")) { + gchar *name; + gboolean retval; + IBusError *error; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &name, + G_TYPE_INVALID); + + if (!retval) + goto _property_show_fail; + + g_signal_emit (engine, + engine_signals[PROPERTY_SHOW], + 0, + name); + + return_message = ibus_message_new_method_return (message); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + + _property_show_fail: + error_message = ibus_message_new_error_printf (message, + "%s.%s: Can not match signature (s) of method", + IBUS_INTERFACE_ENGINE, + "PropertyShow"); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "PropertyHide")) { + gchar *name; + gboolean retval; + IBusError *error = NULL; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &name, + G_TYPE_INVALID); + if (!retval) + goto _property_hide_fail; + + g_signal_emit (engine, engine_signals[PROPERTY_HIDE], 0, name); + + return_message = ibus_message_new_method_return (message); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + + _property_hide_fail: + error_message = ibus_message_new_error_printf (message, + "%s.%s: Can not match signature (s) of method", + IBUS_INTERFACE_ENGINE, "PropertyHide"); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "SetCursorLocation")) { + gint x, y, w, h; + gboolean retval; + IBusError *error = NULL; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_INT, &x, + G_TYPE_INT, &y, + G_TYPE_INT, &w, + G_TYPE_INT, &h, + G_TYPE_INVALID); + if (!retval) + goto _set_cursor_location_fail; + + engine->cursor_area.x = x; + engine->cursor_area.y = y; + engine->cursor_area.width = w; + engine->cursor_area.height = h; + + g_signal_emit (engine, + engine_signals[SET_CURSOR_LOCATION], + 0, + x, y, w, h); + + return_message = ibus_message_new_method_return (message); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + + _set_cursor_location_fail: + error_message = ibus_message_new_error_printf (message, + "%s.%s: Can not match signature (iiii) of method", + IBUS_INTERFACE_ENGINE, + "SetCursorLocation"); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "SetCapabilities")) { + guint caps; + gboolean retval; + IBusError *error = NULL; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_UINT, &caps, + G_TYPE_INVALID); + + if (!retval) + goto _set_capabilities_fail; + + engine->client_capabilities = caps; + + g_signal_emit (engine, engine_signals[SET_CAPABILITIES], 0, caps); + + return_message = ibus_message_new_method_return (message); + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + return TRUE; + + _set_capabilities_fail: + error_message = ibus_message_new_error_printf (message, + "%s.%s: Can not match signature (u) of method", + IBUS_INTERFACE_ENGINE, "SetCapabilities"); + ibus_connection_send (connection, error_message); + ibus_message_unref (error_message); + return TRUE; + } + else if (ibus_message_is_method_call (message, IBUS_INTERFACE_ENGINE, "Destroy")) { + return_message = ibus_message_new_method_return (message); + + ibus_connection_send (connection, return_message); + ibus_message_unref (return_message); + + ibus_object_destroy ((IBusObject *) engine); + } + + return parent_class->ibus_message ((IBusService *) engine, connection, message); +} + +static gboolean +ibus_engine_process_key_event (IBusEngine *engine, + guint keyval, + guint state) +{ + // g_debug ("process-key-event (%d, %d)", keyval, state); + return FALSE; +} + +static void +ibus_engine_focus_in (IBusEngine *engine) +{ + // g_debug ("focus-in"); +} + +static void +ibus_engine_focus_out (IBusEngine *engine) +{ + // g_debug ("focus-out"); +} + +static void +ibus_engine_reset (IBusEngine *engine) +{ + // g_debug ("reset"); +} + +static void +ibus_engine_enable (IBusEngine *engine) +{ + // g_debug ("enable"); +} + +static void +ibus_engine_disable (IBusEngine *engine) +{ + // g_debug ("disable"); +} + +static void +ibus_engine_set_cursor_location (IBusEngine *engine, + gint x, + gint y, + gint w, + gint h) +{ + // g_debug ("set-cursor-location (%d, %d, %d, %d)", x, y, w, h); +} + +static void +ibus_engine_set_capabilities (IBusEngine *engine, + guint caps) +{ + // g_debug ("set-capabilities (0x%04x)", caps); +} + +static void +ibus_engine_page_up (IBusEngine *engine) +{ + // g_debug ("page-up"); +} + +static void +ibus_engine_page_down (IBusEngine *engine) +{ + // g_debug ("page-down"); +} + +static void +ibus_engine_cursor_up (IBusEngine *engine) +{ + // g_debug ("cursor-up"); +} + +static void +ibus_engine_cursor_down (IBusEngine *engine) +{ + // g_debug ("cursor-down"); +} + +static void +ibus_engine_property_activate (IBusEngine *engine, + const gchar *prop_name, gint prop_state) +{ + // g_debug ("property-activate ('%s', %d)", prop_name, prop_state); +} + +static void +ibus_engine_property_show (IBusEngine *engine, const gchar *prop_name) +{ + // g_debug ("property-show ('%s')", prop_name); +} + +static void +ibus_engine_property_hide (IBusEngine *engine, const gchar *prop_name) +{ + // g_debug ("property-hide ('%s')", prop_name); +} + +static void +_send_signal (IBusEngine *engine, + const gchar *name, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_ENGINE (engine)); + g_assert (name != NULL); + + va_list args; + const gchar *path; + IBusEnginePrivate *priv; + + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + path = ibus_service_get_path ((IBusService *)engine); + + va_start (args, first_arg_type); + ibus_connection_send_signal_valist (priv->connection, + path, + IBUS_INTERFACE_ENGINE, + name, + first_arg_type, + args); + va_end (args); +} + +void +ibus_engine_commit_text (IBusEngine *engine, + IBusText *text) +{ + _send_signal (engine, + "CommitText", + IBUS_TYPE_TEXT, &text, + G_TYPE_INVALID); +} + +void +ibus_engine_update_preedit_text (IBusEngine *engine, + IBusText *text, + guint cursor_pos, + gboolean visible) +{ + _send_signal (engine, + "UpdatePreeditText", + IBUS_TYPE_TEXT, &text, + G_TYPE_UINT, &cursor_pos, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); +} + +void +ibus_engine_show_preedit_text (IBusEngine *engine) +{ + _send_signal (engine, + "ShowPreeditText", + G_TYPE_INVALID); +} + +void ibus_engine_hide_preedit_text (IBusEngine *engine) +{ + _send_signal (engine, + "HidePreeditText", + G_TYPE_INVALID); +} + +void ibus_engine_update_auxiliary_text (IBusEngine *engine, + IBusText *text, + gboolean visible) +{ + _send_signal (engine, + "UpdateAuxiliaryText", + IBUS_TYPE_TEXT, &text, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); +} + +void +ibus_engine_show_auxiliary_text (IBusEngine *engine) +{ + _send_signal (engine, + "ShowAuxiliaryText", + G_TYPE_INVALID); +} + +void +ibus_engine_hide_auxiliary_text (IBusEngine *engine) +{ + _send_signal (engine, + "HideAuxiliaryText", + G_TYPE_INVALID); +} + +void ibus_engine_update_lookup_table (IBusEngine *engine, + IBusLookupTable *table, + gboolean visible) +{ + _send_signal (engine, + "UpdateLookupTable", + IBUS_TYPE_LOOKUP_TABLE, &table, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); +} + +void ibus_engine_show_lookup_table (IBusEngine *engine) +{ + _send_signal (engine, + "ShowLookupTable", + G_TYPE_INVALID); +} + +void ibus_engine_hide_lookup_table (IBusEngine *engine) +{ + _send_signal (engine, + "HideLookupTable", + G_TYPE_INVALID); +} + +void ibus_engine_forward_key_event (IBusEngine *engine, + guint keyval, + gboolean is_press, + guint state) +{ + _send_signal (engine, + "HideLookupTable", + G_TYPE_UINT, &keyval, + G_TYPE_BOOLEAN, &is_press, + G_TYPE_UINT, &state, + G_TYPE_INVALID); +} + +void +ibus_engine_register_properties (IBusEngine *engine, + IBusPropList *prop_list) +{ + _send_signal (engine, + "RegisterProperties", + IBUS_TYPE_PROP_LIST, &prop_list, + G_TYPE_INVALID); +} + +void +ibus_engine_update_property (IBusEngine *engine, + IBusProperty *prop) +{ + _send_signal (engine, + "UpdateProperty", + IBUS_TYPE_PROPERTY, &prop, + G_TYPE_INVALID); +} + +const gchar * +ibus_engine_get_name (IBusEngine *engine) +{ + g_assert (IBUS_IS_ENGINE (engine)); + + IBusEnginePrivate *priv; + priv = IBUS_ENGINE_GET_PRIVATE (engine); + + return priv->name; +} + diff --git a/src/ibusengine.h b/src/ibusengine.h new file mode 100644 index 0000000..0a827af --- /dev/null +++ b/src/ibusengine.h @@ -0,0 +1,152 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_ENGINE_H_ +#define __IBUS_ENGINE_H_ + +#include <dbus/dbus.h> +#include "ibusservice.h" +#include "ibusattribute.h" +#include "ibuslookuptable.h" +#include "ibusproperty.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_ENGINE \ + (ibus_engine_get_type ()) +#define IBUS_ENGINE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_ENGINE, IBusEngine)) +#define IBUS_ENGINE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_ENGINE, IBusEngineClass)) +#define IBUS_IS_ENGINE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_ENGINE)) +#define IBUS_IS_ENGINE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_ENGINE)) +#define IBUS_ENGINE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_ENGINE, IBusEngineClass)) + +G_BEGIN_DECLS + +typedef struct _IBusEngine IBusEngine; +typedef struct _IBusEngineClass IBusEngineClass; + +struct _IBusEngine { + IBusService parent; + /* instance members */ + gboolean enabled; + gboolean has_focus; + + /* cursor location */ + IBusRectangle cursor_area; + guint client_capabilities; +}; + +struct _IBusEngineClass { + IBusServiceClass parent; + + /* class members */ + gboolean (* process_key_event) + (IBusEngine *engine, + guint keyval, + guint state); + void (* focus_in) (IBusEngine *engine); + void (* focus_out) (IBusEngine *engine); + void (* reset) (IBusEngine *engine); + void (* enable) (IBusEngine *engine); + void (* disable) (IBusEngine *engine); + void (* set_cursor_location) + (IBusEngine *engine, + gint x, + gint y, + gint w, + gint h); + void (* set_capabilities) + (IBusEngine *engine, + guint caps); + + void (* page_up) (IBusEngine *engine); + void (* page_down) (IBusEngine *engine); + void (* cursor_up) (IBusEngine *engine); + void (* cursor_down) (IBusEngine *engine); + + void (* property_activate) + (IBusEngine *engine, + const gchar *prop_name, + gint prop_state); + void (* property_show) (IBusEngine *engine, + const gchar *prop_name); + void (* property_hide) (IBusEngine *engine, + const gchar *prop_name); + + /*< private >*/ + /* padding */ + gpointer pdummy[9]; +}; + +GType ibus_engine_get_type (void); +IBusEngine *ibus_engine_new (const gchar *name, + const gchar *path, + IBusConnection *connection); +void ibus_engine_commit_text (IBusEngine *engine, + IBusText *text); +void ibus_engine_update_preedit_text + (IBusEngine *engine, + IBusText *text, + guint cursor_pos, + gboolean visible); +void ibus_engine_show_preedit_text + (IBusEngine *engine); +void ibus_engine_hide_preedit_text + (IBusEngine *engine); +void ibus_engine_update_auxiliary_text + (IBusEngine *engine, + IBusText *text, + gboolean visible); +void ibus_engine_show_auxiliary_text + (IBusEngine *engine); +void ibus_engine_hide_auxiliary_text + (IBusEngine *engine); +void ibus_engine_update_lookup_table + (IBusEngine *engine, + IBusLookupTable *lookup_table, + gboolean visible); +void ibus_engine_show_lookup_table + (IBusEngine *engine); +void ibus_engine_hide_lookup_table + (IBusEngine *engine); + +void ibus_engine_forward_key_event + (IBusEngine *engine, + guint keyval, + gboolean is_press, + guint state); + +void ibus_engine_register_properties + (IBusEngine *engine, + IBusPropList *prop_list); +void ibus_engine_update_property(IBusEngine *engine, + IBusProperty *prop); +const gchar *ibus_engine_get_name (IBusEngine *engine); + +G_END_DECLS +#endif + diff --git a/src/ibusenginedesc.c b/src/ibusenginedesc.c new file mode 100644 index 0000000..0410b67 --- /dev/null +++ b/src/ibusenginedesc.c @@ -0,0 +1,356 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibusenginedesc.h" +#include "ibusxml.h" + +enum { + LAST_SIGNAL, +}; + + +/* IBusEngineDescPriv */ +struct _IBusEngineDescPrivate { + gpointer pad; +}; +typedef struct _IBusEngineDescPrivate IBusEngineDescPrivate; + +#define IBUS_ENGINE_DESC_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BUS_TYPE_ENGINE_INFO, IBusEngineDescPrivate)) + +// static guint _signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_engine_desc_class_init (IBusEngineDescClass *klass); +static void ibus_engine_desc_init (IBusEngineDesc *desc); +static void ibus_engine_desc_destroy (IBusEngineDesc *desc); +static gboolean ibus_engine_desc_serialize (IBusEngineDesc *desc, + IBusMessageIter *iter); +static gboolean ibus_engine_desc_deserialize (IBusEngineDesc *desc, + IBusMessageIter *iter); +static gboolean ibus_engine_desc_copy (IBusEngineDesc *dest, + const IBusEngineDesc *src); +static gboolean ibus_engine_desc_parse_xml_node (IBusEngineDesc *desc, + XMLNode *node); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_engine_desc_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusEngineDescClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_engine_desc_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusEngineDesc), + 0, + (GInstanceInitFunc) ibus_engine_desc_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusEngineDesc", + &type_info, + (GTypeFlags)0); + } + + return type; +} + + +static void +ibus_engine_desc_class_init (IBusEngineDescClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_engine_desc_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_engine_desc_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_engine_desc_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_engine_desc_copy; + + g_string_append (serializable_class->signature, "ssssssss"); +} + +static void +ibus_engine_desc_init (IBusEngineDesc *desc) +{ + + desc->name = NULL; + desc->longname = NULL; + desc->description = NULL; + desc->language = NULL; + desc->license = NULL; + desc->author = NULL; + desc->icon = NULL; + desc->layout = NULL; +} + +static void +ibus_engine_desc_destroy (IBusEngineDesc *desc) +{ + g_free (desc->name); + g_free (desc->longname); + g_free (desc->description); + g_free (desc->language); + g_free (desc->license); + g_free (desc->author); + g_free (desc->icon); + g_free (desc->layout); + + IBUS_OBJECT_CLASS (parent_class)->destroy (IBUS_OBJECT (desc)); +} + +static gboolean +ibus_engine_desc_serialize (IBusEngineDesc *desc, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *)desc, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->name); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->longname); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->description); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->language); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->license); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->author); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->icon); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &desc->layout); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_engine_desc_deserialize (IBusEngineDesc *desc, + IBusMessageIter *iter) +{ + gboolean retval; + gchar *str; + + retval = parent_class->deserialize ((IBusSerializable *)desc, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->name = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->longname = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->description = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->language = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->license = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->author = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->icon = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + desc->layout = g_strdup (str); + + return TRUE; +} + +static gboolean +ibus_engine_desc_copy (IBusEngineDesc *dest, + const IBusEngineDesc *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + + dest->name = g_strdup (src->name); + dest->longname = g_strdup (src->longname); + dest->description = g_strdup (src->description); + dest->language = g_strdup (src->language); + dest->license = g_strdup (src->license); + dest->author = g_strdup (src->author); + dest->icon = g_strdup (src->icon); + dest->layout = g_strdup (src->layout); + + return TRUE; +} + +#define g_string_append_indent(string, indent) \ + { \ + gint i; \ + for (i = 0; i < (indent); i++) { \ + g_string_append (string, " "); \ + } \ + } + +void +ibus_engine_desc_output (IBusEngineDesc *desc, + GString *output, + gint indent) +{ + g_string_append_indent (output, indent); + g_string_append (output, "<engine>\n"); +#define OUTPUT_ENTRY(field, element) \ + { \ + gchar *escape_text = g_markup_escape_text (desc->field, -1); \ + g_string_append_indent (output, indent + 1); \ + g_string_append_printf (output, "<"element">%s</"element">\n", \ + escape_text); \ + g_free (escape_text); \ + } +#define OUTPUT_ENTRY_1(name) OUTPUT_ENTRY(name, #name) + OUTPUT_ENTRY_1(name); + OUTPUT_ENTRY_1(longname); + OUTPUT_ENTRY_1(description); + OUTPUT_ENTRY_1(language); + OUTPUT_ENTRY_1(license); + OUTPUT_ENTRY_1(author); + OUTPUT_ENTRY_1(icon); + OUTPUT_ENTRY_1(layout); +#undef OUTPUT_ENTRY +#undef OUTPUT_ENTRY_1 + g_string_append_indent (output, indent); + g_string_append (output, "</engine>\n"); +} + +static gboolean +ibus_engine_desc_parse_xml_node (IBusEngineDesc *desc, + XMLNode *node) +{ + GList *p; + for (p = node->sub_nodes; p != NULL; p = p->next) { + XMLNode *sub_node = (XMLNode *) p->data; + +#define PARSE_ENTRY(field_name, element_name) \ + if (g_strcmp0 (sub_node->name, element_name) == 0) { \ + if (desc->field_name != NULL) { \ + g_free (desc->field_name); \ + } \ + desc->field_name = g_strdup (sub_node->text); \ + continue; \ + } +#define PARSE_ENTRY_1(name) PARSE_ENTRY(name, #name) + PARSE_ENTRY_1(name); + PARSE_ENTRY_1(longname); + PARSE_ENTRY_1(description); + PARSE_ENTRY_1(language); + PARSE_ENTRY_1(license); + PARSE_ENTRY_1(author); + PARSE_ENTRY_1(icon); + PARSE_ENTRY_1(layout); +#undef PARSE_ENTRY +#undef PARSE_ENTRY1 + g_warning ("<engines> element contains invalidate element <%s>", sub_node->name); + } + return TRUE; +} + +IBusEngineDesc * +ibus_engine_desc_new (const gchar *name, + const gchar *longname, + const gchar *description, + const gchar *language, + const gchar *license, + const gchar *author, + const gchar *icon, + const gchar *layout) +{ + g_assert (name); + g_assert (longname); + g_assert (description); + g_assert (language); + g_assert (license); + g_assert (author); + g_assert (icon); + g_assert (layout); + + IBusEngineDesc *desc; + desc = (IBusEngineDesc *)g_object_new (IBUS_TYPE_ENGINE_DESC, NULL); + + desc->name = g_strdup (name); + desc->longname = g_strdup (longname); + desc->description = g_strdup (description); + desc->language = g_strdup (language); + desc->license = g_strdup (license); + desc->author = g_strdup (author); + desc->icon = g_strdup (icon); + desc->layout = g_strdup (layout); + + return desc; +} + +IBusEngineDesc * +ibus_engine_desc_new_from_xml_node (XMLNode *node) +{ + g_assert (node); + + IBusEngineDesc *desc; + + if (G_UNLIKELY (g_strcmp0 (node->name, "engine") != 0)) { + return NULL; + } + + desc = (IBusEngineDesc *)g_object_new (IBUS_TYPE_ENGINE_DESC, NULL); + + if (!ibus_engine_desc_parse_xml_node (desc, node)) { + g_object_unref (desc); + desc = NULL; + } + + return desc; +} + diff --git a/src/ibusenginedesc.h b/src/ibusenginedesc.h new file mode 100644 index 0000000..ffc5a52 --- /dev/null +++ b/src/ibusenginedesc.h @@ -0,0 +1,86 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __ENGINE_DESC_H_ +#define __ENGINE_DESC_H_ + +#include "ibusserializable.h" +#include "ibusxml.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_ENGINE_DESC \ + (ibus_engine_desc_get_type ()) +#define IBUS_ENGINE_DESC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_ENGINE_DESC, IBusEngineDesc)) +#define IBUS_ENGINE_DESC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_ENGINE_DESC, IBusEngineDescClass)) +#define IBUS_IS_ENGINE_DESC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_ENGINE_DESC)) +#define IBUS_IS_ENGINE_DESC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_ENGINE_DESC)) +#define IBUS_ENGINE_DESC_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_ENGINE_DESC, IBusEngineDescClass)) + +G_BEGIN_DECLS + +typedef struct _IBusEngineDesc IBusEngineDesc; +typedef struct _IBusEngineDescClass IBusEngineDescClass; +typedef struct _BusComponent BusComponent; + +struct _IBusEngineDesc { + IBusSerializable parent; + /* instance members */ + + gchar *name; + gchar *longname; + gchar *description; + gchar *language; + gchar *license; + gchar *author; + gchar *icon; + gchar *layout; +}; + +struct _IBusEngineDescClass { + IBusSerializableClass parent; + + /* class members */ +}; + +GType ibus_engine_desc_get_type (void); +IBusEngineDesc *ibus_engine_desc_new (const gchar *name, + const gchar *longname, + const gchar *description, + const gchar *language, + const gchar *license, + const gchar *author, + const gchar *icon, + const gchar *layout); +IBusEngineDesc *ibus_engine_desc_new_from_xml_node + (XMLNode *node); +void ibus_engine_desc_output (IBusEngineDesc *info, + GString *output, + gint indent); +G_END_DECLS +#endif + diff --git a/src/ibusenumtypes.c b/src/ibusenumtypes.c new file mode 100644 index 0000000..591b3f0 --- /dev/null +++ b/src/ibusenumtypes.c @@ -0,0 +1,146 @@ + +/* Generated data (by glib-mkenums) */ + +#include "ibus.h" + +/* enumerations from "ibusobject.h" */ +GType +ibus_object_flags_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GFlagsValue values[] = { + { IBUS_IN_DESTRUCTION, "IBUS_IN_DESTRUCTION", "in-destruction" }, + { IBUS_DESTROYED, "IBUS_DESTROYED", "destroyed" }, + { IBUS_RESERVED_1, "IBUS_RESERVED_1", "reserved-1" }, + { IBUS_RESERVED_2, "IBUS_RESERVED_2", "reserved-2" }, + { 0, NULL, NULL } + }; + etype = g_flags_register_static (g_intern_static_string ("IBusObjectFlags"), values); + } + return etype; +} + +/* enumerations from "ibusattribute.h" */ +GType +ibus_attr_type_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GEnumValue values[] = { + { IBUS_ATTR_TYPE_UNDERLINE, "IBUS_ATTR_TYPE_UNDERLINE", "underline" }, + { IBUS_ATTR_TYPE_FOREGROUND, "IBUS_ATTR_TYPE_FOREGROUND", "foreground" }, + { IBUS_ATTR_TYPE_BACKGROUND, "IBUS_ATTR_TYPE_BACKGROUND", "background" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static (g_intern_static_string ("IBusAttrType"), values); + } + return etype; +} + +GType +ibus_attr_underline_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GEnumValue values[] = { + { IBUS_ATTR_UNDERLINE_NONE, "IBUS_ATTR_UNDERLINE_NONE", "none" }, + { IBUS_ATTR_UNDERLINE_SINGLE, "IBUS_ATTR_UNDERLINE_SINGLE", "single" }, + { IBUS_ATTR_UNDERLINE_DOUBLE, "IBUS_ATTR_UNDERLINE_DOUBLE", "double" }, + { IBUS_ATTR_UNDERLINE_LOW, "IBUS_ATTR_UNDERLINE_LOW", "low" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static (g_intern_static_string ("IBusAttrUnderline"), values); + } + return etype; +} + +/* enumerations from "ibusproperty.h" */ +GType +ibus_prop_type_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GEnumValue values[] = { + { PROP_TYPE_NORMAL, "PROP_TYPE_NORMAL", "normal" }, + { PROP_TYPE_TOGGLE, "PROP_TYPE_TOGGLE", "toggle" }, + { PROP_TYPE_RADIO, "PROP_TYPE_RADIO", "radio" }, + { PROP_TYPE_MENU, "PROP_TYPE_MENU", "menu" }, + { PROP_TYPE_SEPARATOR, "PROP_TYPE_SEPARATOR", "separator" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static (g_intern_static_string ("IBusPropType"), values); + } + return etype; +} + +GType +ibus_prop_state_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GEnumValue values[] = { + { PROP_STATE_UNCHECKED, "PROP_STATE_UNCHECKED", "unchecked" }, + { PROP_STATE_CHECKED, "PROP_STATE_CHECKED", "checked" }, + { PROP_STATE_INCONSISTENT, "PROP_STATE_INCONSISTENT", "inconsistent" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static (g_intern_static_string ("IBusPropState"), values); + } + return etype; +} + +/* enumerations from "ibustypes.h" */ +GType +ibus_modifier_type_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GFlagsValue values[] = { + { IBUS_SHIFT_MASK, "IBUS_SHIFT_MASK", "shift-mask" }, + { IBUS_LOCK_MASK, "IBUS_LOCK_MASK", "lock-mask" }, + { IBUS_CONTROL_MASK, "IBUS_CONTROL_MASK", "control-mask" }, + { IBUS_MOD1_MASK, "IBUS_MOD1_MASK", "mod1-mask" }, + { IBUS_MOD2_MASK, "IBUS_MOD2_MASK", "mod2-mask" }, + { IBUS_MOD3_MASK, "IBUS_MOD3_MASK", "mod3-mask" }, + { IBUS_MOD4_MASK, "IBUS_MOD4_MASK", "mod4-mask" }, + { IBUS_MOD5_MASK, "IBUS_MOD5_MASK", "mod5-mask" }, + { IBUS_BUTTON1_MASK, "IBUS_BUTTON1_MASK", "button1-mask" }, + { IBUS_BUTTON2_MASK, "IBUS_BUTTON2_MASK", "button2-mask" }, + { IBUS_BUTTON3_MASK, "IBUS_BUTTON3_MASK", "button3-mask" }, + { IBUS_BUTTON4_MASK, "IBUS_BUTTON4_MASK", "button4-mask" }, + { IBUS_BUTTON5_MASK, "IBUS_BUTTON5_MASK", "button5-mask" }, + { IBUS_FORWARD_MASK, "IBUS_FORWARD_MASK", "forward-mask" }, + { IBUS_SUPER_MASK, "IBUS_SUPER_MASK", "super-mask" }, + { IBUS_HYPER_MASK, "IBUS_HYPER_MASK", "hyper-mask" }, + { IBUS_META_MASK, "IBUS_META_MASK", "meta-mask" }, + { IBUS_RELEASE_MASK, "IBUS_RELEASE_MASK", "release-mask" }, + { IBUS_MODIFIER_MASK, "IBUS_MODIFIER_MASK", "modifier-mask" }, + { 0, NULL, NULL } + }; + etype = g_flags_register_static (g_intern_static_string ("IBusModifierType"), values); + } + return etype; +} + +GType +ibus_capabilite_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const GFlagsValue values[] = { + { IBUS_CAP_PREEDIT_TEXT, "IBUS_CAP_PREEDIT_TEXT", "preedit-text" }, + { IBUS_CAP_AUXILIARY_TEXT, "IBUS_CAP_AUXILIARY_TEXT", "auxiliary-text" }, + { IBUS_CAP_LOOKUP_TABLE, "IBUS_CAP_LOOKUP_TABLE", "lookup-table" }, + { IBUS_CAP_FOCUS, "IBUS_CAP_FOCUS", "focus" }, + { IBUS_CAP_PROPERTY, "IBUS_CAP_PROPERTY", "property" }, + { 0, NULL, NULL } + }; + etype = g_flags_register_static (g_intern_static_string ("IBusCapabilite"), values); + } + return etype; +} + + +/* Generated data ends here */ + diff --git a/src/ibusenumtypes.c.template b/src/ibusenumtypes.c.template new file mode 100644 index 0000000..9f607a0 --- /dev/null +++ b/src/ibusenumtypes.c.template @@ -0,0 +1,34 @@ +/*** BEGIN file-header ***/ +#include "ibus.h" + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) +{ + static GType etype = 0; + if (G_UNLIKELY(etype == 0)) { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + } + return etype; +} + +/*** END value-tail ***/ + +/*** BEGIN file-tail ***/ +/*** END file-tail ***/ diff --git a/src/ibusenumtypes.h b/src/ibusenumtypes.h new file mode 100644 index 0000000..2e977a0 --- /dev/null +++ b/src/ibusenumtypes.h @@ -0,0 +1,37 @@ + +/* Generated data (by glib-mkenums) */ + +#ifndef __IBUS_ENUM_TYPES_H__ +#define __IBUS_ENUM_TYPES_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +/* enumerations from "ibusobject.h" */ +GType ibus_object_flags_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_OBJECT_FLAGS (ibus_object_flags_get_type ()) + +/* enumerations from "ibusattribute.h" */ +GType ibus_attr_type_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_ATTR_TYPE (ibus_attr_type_get_type ()) +GType ibus_attr_underline_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_ATTR_UNDERLINE (ibus_attr_underline_get_type ()) + +/* enumerations from "ibusproperty.h" */ +GType ibus_prop_type_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_PROP_TYPE (ibus_prop_type_get_type ()) +GType ibus_prop_state_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_PROP_STATE (ibus_prop_state_get_type ()) + +/* enumerations from "ibustypes.h" */ +GType ibus_modifier_type_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_MODIFIER_TYPE (ibus_modifier_type_get_type ()) +GType ibus_capabilite_get_type (void) G_GNUC_CONST; +#define IBUS_TYPE_CAPABILITE (ibus_capabilite_get_type ()) +G_END_DECLS + +#endif /* __IBUS_ENUM_TYPES_H__ */ + +/* Generated data ends here */ + diff --git a/src/ibusenumtypes.h.template b/src/ibusenumtypes.h.template new file mode 100644 index 0000000..15c1f02 --- /dev/null +++ b/src/ibusenumtypes.h.template @@ -0,0 +1,24 @@ +/*** BEGIN file-header ***/ +#ifndef __IBUS_ENUM_TYPES_H__ +#define __IBUS_ENUM_TYPES_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* enumerations from "@filename@" */ +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType @enum_name@_get_type (void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* __IBUS_ENUM_TYPES_H__ */ +/*** END file-tail ***/ diff --git a/src/ibuserror.c b/src/ibuserror.c new file mode 100644 index 0000000..c55f4a4 --- /dev/null +++ b/src/ibuserror.c @@ -0,0 +1,87 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibuserror.h" + +IBusError * +ibus_error_new (void) +{ + IBusError *error; + + error = g_slice_new0 (IBusError); + dbus_error_init (error); + + return error; +} + +IBusError * +ibus_error_new_from_text (const gchar *name, + const gchar *message) +{ + IBusError *error = ibus_error_new (); + + dbus_set_error (error, name, "%s", message); + + return error; +} + +IBusError * +ibus_error_new_from_printf (const gchar *name, + const gchar *format_message, + ...) +{ + IBusError *error; + gchar *message; + va_list va_args; + + va_start (va_args, format_message); + message = g_strdup_vprintf (format_message, va_args); + + error = ibus_error_new_from_text (name, message); + g_free (message); + + return error; +} + +IBusError * +ibus_error_new_from_message (DBusMessage *message) +{ + g_assert (message != NULL); + + IBusError *error; + + if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) + return NULL; + + error = ibus_error_new (); + + if (dbus_set_error_from_message (error, message)) + return error; + + dbus_error_free (error); + return NULL; +} + +void +ibus_error_free (IBusError *error) +{ + dbus_error_free (error); + g_slice_free (IBusError, error); +} + diff --git a/src/ibuserror.h b/src/ibuserror.h new file mode 100644 index 0000000..05733d5 --- /dev/null +++ b/src/ibuserror.h @@ -0,0 +1,41 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_ERROR_H_ +#define __IBUS_ERROR_H_ + +#include <glib.h> +#include <dbus/dbus.h> + +G_BEGIN_DECLS + +typedef DBusError IBusError; + +IBusError *ibus_error_new (void); +IBusError *ibus_error_new_from_text (const gchar *name, + const gchar *message); +IBusError *ibus_error_new_from_printf (const gchar *name, + const gchar *format_message, + ...); +IBusError *ibus_error_new_from_message + (DBusMessage *message); +void ibus_error_free (IBusError *error); + +G_END_DECLS +#endif diff --git a/src/ibusfactory.c b/src/ibusfactory.c new file mode 100644 index 0000000..af9d887 --- /dev/null +++ b/src/ibusfactory.c @@ -0,0 +1,483 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibusfactory.h" +#include "ibusengine.h" +#include "ibusshare.h" +#include "ibusinternal.h" + +#define IBUS_FACTORY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_FACTORY, IBusFactoryPrivate)) + +enum { + LAST_SIGNAL, +}; + +/* IBusFactoryPriv */ +struct _IBusFactoryPrivate { + guint id; + IBusConnection *connection; + GList *engine_list; + GHashTable *engine_table; +}; +typedef struct _IBusFactoryPrivate IBusFactoryPrivate; + +/* functions prototype */ +static void ibus_factory_class_init (IBusFactoryClass *klass); +static void ibus_factory_init (IBusFactory *factory); +static void ibus_factory_destroy (IBusFactory *factory); +static gboolean ibus_factory_ibus_message (IBusFactory *factory, + IBusConnection *connection, + IBusMessage *message); + +static void _engine_destroy_cb (IBusEngine *engine, + IBusFactory *factory); +static void ibus_factory_info_class_init(IBusFactoryInfoClass *klass); +static void ibus_factory_info_init (IBusFactoryInfo *info); +static void ibus_factory_info_destroy (IBusFactoryInfo *info); +static gboolean ibus_factory_info_serialize (IBusFactoryInfo *info, + IBusMessageIter *iter); +static gboolean ibus_factory_info_deserialize + (IBusFactoryInfo *info, + IBusMessageIter *iter); +static gboolean ibus_factory_info_copy (IBusFactoryInfo *dest, + const IBusFactoryInfo *src); + +static IBusServiceClass *factory_parent_class = NULL; +static IBusSerializableClass *factory_info_parent_class = NULL; + +GType +ibus_factory_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_factory_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusFactory), + 0, + (GInstanceInitFunc) ibus_factory_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERVICE, + "IBusFactory", + &type_info, + (GTypeFlags) 0); + } + return type; +} + +IBusFactory * +ibus_factory_new (IBusConnection *connection) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusFactory *factory; + IBusFactoryPrivate *priv; + + factory = (IBusFactory *) g_object_new (IBUS_TYPE_FACTORY, + "path", IBUS_PATH_FACTORY, + 0); + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + priv->connection = g_object_ref (connection); + ibus_service_add_to_connection ((IBusService *)factory, connection); + + return factory; +} + +static void +ibus_factory_class_init (IBusFactoryClass *klass) +{ + // GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + factory_parent_class = (IBusServiceClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusFactoryPrivate)); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_destroy; + + IBUS_SERVICE_CLASS (klass)->ibus_message = (ServiceIBusMessageFunc) ibus_factory_ibus_message; + +} + +static void +ibus_factory_init (IBusFactory *factory) +{ + IBusFactoryPrivate *priv; + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + priv->id = 0; + priv->connection = NULL; + priv->engine_table = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + NULL); + priv->engine_list = NULL; +} + +static void +ibus_factory_destroy (IBusFactory *factory) +{ + GList *list; + IBusFactoryPrivate *priv; + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + list = g_list_copy (priv->engine_list); + g_list_foreach (list, (GFunc) ibus_object_destroy, NULL); + g_list_free (priv->engine_list); + g_list_free (list); + priv->engine_list = NULL; + + if (priv->engine_table) { + g_hash_table_destroy (priv->engine_table); + } + + if (priv->connection) { + ibus_service_remove_from_connection ((IBusService *)factory, + priv->connection); + g_object_unref (priv->connection); + } + + IBUS_OBJECT_CLASS(factory_parent_class)->destroy (IBUS_OBJECT (factory)); +} + +static void +_engine_destroy_cb (IBusEngine *engine, + IBusFactory *factory) +{ + GList *list; + IBusFactoryPrivate *priv; + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + list = g_list_remove (priv->engine_list, engine); + + if (list) { + g_object_unref (engine); + g_list_free_1 (list); + } +} + +static gboolean +ibus_factory_ibus_message (IBusFactory *factory, + IBusConnection *connection, + IBusMessage *message) +{ + g_assert (IBUS_IS_FACTORY (factory)); + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (message != NULL); + + IBusMessage *reply_message; + IBusFactoryPrivate *priv; + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + g_assert (priv->connection == connection); + + if (ibus_message_is_method_call (message, + IBUS_INTERFACE_FACTORY, + "CreateEngine")) { + gchar *engine_name; + gchar *path; + IBusError *error; + IBusEngine *engine; + gboolean retval; + GType engine_type; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_STRING, &engine_name, + G_TYPE_INVALID); + + if (!retval) { + reply_message = ibus_message_new_error_printf (message, + DBUS_ERROR_INVALID_ARGS, + "The 1st arg should be engine name"); + ibus_connection_send (connection, reply_message); + ibus_message_unref (reply_message); + return TRUE; + } + + engine_type = (GType )g_hash_table_lookup (priv->engine_table, engine_name); + + if (engine_type == G_TYPE_INVALID) { + reply_message = ibus_message_new_error_printf (message, + DBUS_ERROR_FAILED, + "Can not create engine %s", engine_name); + ibus_connection_send (connection, reply_message); + ibus_message_unref (reply_message); + return TRUE; + + } + + path = g_strdup_printf ("/org/freedesktop/IBus/Engine/%d", ++priv->id); + + engine = g_object_new (engine_type, + "name", engine_name, + "path", path, + "connection", priv->connection, + 0); + + priv->engine_list = g_list_append (priv->engine_list, engine); + g_signal_connect (engine, + "destroy", + G_CALLBACK (_engine_destroy_cb), + factory); + + reply_message = ibus_message_new_method_return (message); + ibus_message_append_args (reply_message, + IBUS_TYPE_OBJECT_PATH, &path, + G_TYPE_INVALID); + g_free (path); + ibus_connection_send (connection, reply_message); + ibus_message_unref (reply_message); + return TRUE; + } + + return factory_parent_class->ibus_message ((IBusService *)factory, + connection, + message); +} + +void +ibus_factory_add_engine (IBusFactory *factory, + const gchar *engine_name, + GType engine_type) +{ + g_assert (IBUS_IS_FACTORY (factory)); + g_assert (engine_name); + g_assert (g_type_is_a (engine_type, IBUS_TYPE_ENGINE)); + + IBusFactoryPrivate *priv; + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + g_hash_table_insert (priv->engine_table, g_strdup (engine_name), (gpointer) engine_type); +} + +#if 0 +IBusFactoryInfo * +ibus_factory_get_info (IBusFactory *factory) +{ + IBusFactoryPrivate *priv; + priv = IBUS_FACTORY_GET_PRIVATE (factory); + + return priv->info; +} +#endif + +GType +ibus_factory_info_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusFactoryInfoClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_factory_info_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusFactoryInfo), + 0, + (GInstanceInitFunc) ibus_factory_info_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusFactoryInfo", + &type_info, + 0); + } + + return type; +} + +static void +ibus_factory_info_class_init (IBusFactoryInfoClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + factory_info_parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_factory_info_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_factory_info_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_factory_info_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_factory_info_copy; + + g_string_append (serializable_class->signature, "osssss"); +} + +static void +ibus_factory_info_init (IBusFactoryInfo *info) +{ + info->path = NULL; + info->name = NULL; + info->lang = NULL; + info->icon = NULL; + info->authors = NULL; + info->credits = NULL; +} + +static void +ibus_factory_info_destroy (IBusFactoryInfo *info) +{ + g_free (info->path); + g_free (info->name); + g_free (info->lang); + g_free (info->icon); + g_free (info->authors); + g_free (info->credits); + + info->path = NULL; + info->lang = NULL; + info->name = NULL; + info->icon = NULL; + info->authors = NULL; + info->credits = NULL; + + IBUS_OBJECT_CLASS (factory_info_parent_class)->destroy ((IBusObject *)info); +} + +static gboolean +ibus_factory_info_serialize (IBusFactoryInfo *info, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = factory_info_parent_class->serialize ((IBusSerializable *)info, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, IBUS_TYPE_OBJECT_PATH, &info->path); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->name); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->lang); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->icon); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->authors); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &info->credits); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_factory_info_deserialize (IBusFactoryInfo *info, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = factory_info_parent_class->deserialize ((IBusSerializable *)info, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, IBUS_TYPE_OBJECT_PATH, &info->path); + g_return_val_if_fail (retval, FALSE); + info->path = g_strdup (info->path); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->name); + g_return_val_if_fail (retval, FALSE); + info->name = g_strdup (info->name); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->lang); + g_return_val_if_fail (retval, FALSE); + info->lang = g_strdup (info->lang); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->icon); + g_return_val_if_fail (retval, FALSE); + info->icon = g_strdup (info->icon); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->authors); + g_return_val_if_fail (retval, FALSE); + info->authors = g_strdup (info->authors); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &info->credits); + g_return_val_if_fail (retval, FALSE); + info->credits = g_strdup (info->credits); + + return TRUE; +} + +static gboolean +ibus_factory_info_copy (IBusFactoryInfo *dest, + const IBusFactoryInfo *src) +{ + gboolean retval; + + retval = factory_info_parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_FACTORY_INFO (dest), FALSE); + g_return_val_if_fail (IBUS_IS_FACTORY_INFO (src), FALSE); + + dest->path = g_strdup (src->path); + dest->name = g_strdup (src->name); + dest->lang = g_strdup (src->lang); + dest->icon = g_strdup (src->icon); + dest->authors = g_strdup (src->authors); + dest->credits = g_strdup (src->credits); + + return TRUE; +} + +IBusFactoryInfo * +ibus_factory_info_new (const gchar *path, + const gchar *name, + const gchar *lang, + const gchar *icon, + const gchar *authors, + const gchar *credits) +{ + g_assert (path); + g_assert (name); + g_assert (lang); + g_assert (icon); + g_assert (authors); + g_assert (credits); + + IBusFactoryInfo *info; + + info = (IBusFactoryInfo *)g_object_new (IBUS_TYPE_FACTORY_INFO, 0); + + info->path = g_strdup (path); + info->name = g_strdup (name); + info->lang = g_strdup (lang); + info->icon = g_strdup (icon); + info->authors = g_strdup (authors); + info->credits = g_strdup (credits); + + return info; +} + + diff --git a/src/ibusfactory.h b/src/ibusfactory.h new file mode 100644 index 0000000..02c883c --- /dev/null +++ b/src/ibusfactory.h @@ -0,0 +1,120 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_FACTORY_H_ +#define __IBUS_FACTORY_H_ + +#include <dbus/dbus.h> +#include "ibusservice.h" +#include "ibusserializable.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_FACTORY \ + (ibus_factory_get_type ()) +#define IBUS_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_FACTORY, IBusFactory)) +#define IBUS_FACTORY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_FACTORY, IBusFactoryClass)) +#define IBUS_IS_FACTORY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_FACTORY)) +#define IBUS_IS_FACTORY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_FACTORY)) +#define IBUS_FACTORY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_FACTORY, IBusFactoryClass)) + +#define IBUS_TYPE_FACTORY_INFO \ + (ibus_factory_info_get_type ()) +#define IBUS_FACTORY_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_FACTORY_INFO, IBusFactoryInfo)) +#define IBUS_FACTORY_INFO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_FACTORY_INFO, IBusFactoryInfoClass)) +#define IBUS_IS_FACTORY_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_FACTORY_INFO)) +#define IBUS_IS_FACTORY_INFO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_FACTORY_INFO)) +#define IBUS_FACTORY_INFO_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_FACTORY_INFO, IBusFactoryInfoClass)) + + +G_BEGIN_DECLS + +typedef struct _IBusFactory IBusFactory; +typedef struct _IBusFactoryClass IBusFactoryClass; +typedef struct _IBusFactoryInfo IBusFactoryInfo; +typedef struct _IBusFactoryInfoClass IBusFactoryInfoClass; + +struct _IBusFactory { + IBusService parent; + + /* instance members */ +}; + +struct _IBusFactoryClass { + IBusServiceClass parent; + + /* signals */ + + /*< private >*/ + /* padding */ + gpointer pdummy[8]; +}; + +struct _IBusFactoryInfo { + IBusSerializable parent; + + /* instance members */ + gchar *path; + gchar *name; + gchar *lang; + gchar *icon; + gchar *authors; + gchar *credits; +}; + +struct _IBusFactoryInfoClass { + IBusSerializableClass parent; + + /* signals */ + + /*< private >*/ + /* padding */ + gpointer pdummy[8]; +}; + +GType ibus_factory_get_type (void); +IBusFactory *ibus_factory_new (IBusConnection *connection); +void ibus_factory_add_engine (IBusFactory *factory, + const gchar *engine_name, + GType engine_type); +IBusFactoryInfo *ibus_factory_get_info (IBusFactory *factory); +GType ibus_factory_info_get_type (void); +IBusFactoryInfo *ibus_factory_info_new (const gchar *path, + const gchar *name, + const gchar *lang, + const gchar *icon, + const gchar *authors, + const gchar *credits); + +G_END_DECLS +#endif + diff --git a/src/ibushotkey.c b/src/ibushotkey.c new file mode 100644 index 0000000..16aad70 --- /dev/null +++ b/src/ibushotkey.c @@ -0,0 +1,479 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibushotkey.h" +#include "ibuskeysyms.h" +#include "ibusinternal.h" +#include "ibusshare.h" + +#define IBUS_HOTKEY_PROFILE_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_HOTKEY_PROFILE, IBusHotkeyProfilePrivate)) + +enum { + TRIGGER, + LAST_SIGNAL, +}; + +typedef struct _IBusHotkey IBusHotkey; +typedef struct _IBusHotkeyEvent IBusHotkeyEvent; +typedef struct _IBusHotkeyProfilePrivate IBusHotkeyProfilePrivate; + +struct _IBusHotkey { + guint keyval; + guint modifiers; +}; + +struct _IBusHotkeyEvent { + GQuark event; + GList *hotkeys; +}; + +struct _IBusHotkeyProfilePrivate { + GTree *hotkeys; + GArray *events; + guint mask; +}; + + + +/* functions prototype */ +static IBusHotkey *ibus_hotkey_new (guint keyval, + guint modifiers); +static IBusHotkey *ibus_hotkey_copy (const IBusHotkey *src); +static void ibus_hotkey_free (IBusHotkey *hotkey); +static gboolean ibus_hotkey_serialize (IBusHotkey *hotkey, + IBusMessageIter *iter); +static gboolean ibus_hotkey_deserialize (IBusHotkey *hotkey, + IBusMessageIter *iter); + +static void ibus_hotkey_profile_class_init (IBusHotkeyProfileClass *klass); +static void ibus_hotkey_profile_init (IBusHotkeyProfile *profile); +static void ibus_hotkey_profile_destroy (IBusHotkeyProfile *profile); +static gboolean ibus_hotkey_profile_serialize (IBusHotkeyProfile *profile, + IBusMessageIter *iter); +static gboolean ibus_hotkey_profile_deserialize(IBusHotkeyProfile *profile, + IBusMessageIter *iter); +static gboolean ibus_hotkey_profile_copy (IBusHotkeyProfile *dest, + const IBusHotkeyProfile*src); +static void ibus_hotkey_profile_trigger (IBusHotkeyProfile *profile, + GQuark event); + +static IBusSerializableClass *parent_class = NULL; + +static guint profile_signals[LAST_SIGNAL] = { 0 }; + +GType +ibus_hotkey_get_type (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static ("IBusHotkey", + (GBoxedCopyFunc) ibus_hotkey_copy, + (GBoxedFreeFunc) ibus_hotkey_free); + } + + return type; +} + +static gboolean +ibus_hotkey_serialize (IBusHotkey *hotkey, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &hotkey->keyval); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &hotkey->modifiers); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_hotkey_deserialize (IBusHotkey *hotkey, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &hotkey->keyval); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &hotkey->modifiers); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + + +static IBusHotkey * +ibus_hotkey_new (guint keyval, + guint modifiers) +{ + IBusHotkey *hotkey = g_slice_new (IBusHotkey); + + hotkey->keyval = keyval; + hotkey->modifiers = modifiers; + + return hotkey; +} + +static void +ibus_hotkey_free (IBusHotkey *hotkey) +{ + g_slice_free (IBusHotkey, hotkey); +} + + +static IBusHotkey * +ibus_hotkey_copy (const IBusHotkey *src) +{ + return ibus_hotkey_new (src->keyval, src->modifiers); +} + +static gint +ibus_hotkey_cmp_with_data (IBusHotkey *hotkey1, + IBusHotkey *hotkey2, + gpointer user_data) +{ + gint retval; + + if (hotkey1 == hotkey2) + return 0; + + retval = hotkey1->keyval - hotkey2->keyval; + if (retval == 0) + retval = hotkey1->modifiers - hotkey2->modifiers; + + return retval; +} + + + +GType +ibus_hotkey_profile_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusHotkeyProfileClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_hotkey_profile_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusHotkeyProfile), + 0, + (GInstanceInitFunc) ibus_hotkey_profile_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusHotkeyProfile", + &type_info, + 0); + } + + return type; +} + +static void +ibus_hotkey_profile_class_init (IBusHotkeyProfileClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusHotkeyProfilePrivate)); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_hotkey_profile_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_hotkey_profile_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_hotkey_profile_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_hotkey_profile_copy; + + klass->trigger = ibus_hotkey_profile_trigger; + + g_string_append (serializable_class->signature, "av"); + + /* install signals */ + profile_signals[TRIGGER] = + g_signal_new (I_("trigger"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (IBusHotkeyProfileClass, trigger), + NULL, NULL, + ibus_marshal_VOID__UINT_POINTER, + G_TYPE_NONE, + 2, + G_TYPE_UINT, + G_TYPE_POINTER); +} + +static void +ibus_hotkey_profile_init (IBusHotkeyProfile *profile) +{ + IBusHotkeyProfilePrivate *priv; + priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile); + + priv->hotkeys = g_tree_new_full ((GCompareDataFunc) ibus_hotkey_cmp_with_data, + NULL, + (GDestroyNotify) ibus_hotkey_free, + NULL); + priv->events = g_array_new (TRUE, TRUE, sizeof (IBusHotkeyEvent)); + + priv->mask = IBUS_SHIFT_MASK | + IBUS_CONTROL_MASK | + IBUS_MOD1_MASK | + IBUS_RELEASE_MASK; +} + +static void +ibus_hotkey_profile_destroy (IBusHotkeyProfile *profile) +{ + IBusHotkeyProfilePrivate *priv; + priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile); + + if (priv->hotkeys) { + g_tree_destroy (priv->hotkeys); + priv->hotkeys = NULL; + } + + if (priv->events) { + IBusHotkeyEvent *events, *p; + p = events = (IBusHotkeyEvent *)g_array_free (priv->events, FALSE); + priv->events = NULL; + + while (p->event != 0) { + if (p->hotkeys) + g_list_free (p->hotkeys); + p ++; + } + g_free (events); + } + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)profile); +} + +static gboolean +ibus_hotkey_profile_serialize (IBusHotkeyProfile *profile, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *) profile, iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_hotkey_profile_deserialize (IBusHotkeyProfile *profile, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->deserialize ((IBusSerializable *) profile, iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_hotkey_profile_copy (IBusHotkeyProfile *dest, + const IBusHotkeyProfile *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_HOTKEY_PROFILE (dest), FALSE); + g_return_val_if_fail (IBUS_IS_HOTKEY_PROFILE (src), FALSE); + + return TRUE; +} + +IBusHotkeyProfile * +ibus_hotkey_profile_new (void) +{ + IBusHotkeyProfile *profile = g_object_new (IBUS_TYPE_HOTKEY_PROFILE, 0); + + return profile; +} + +static void +ibus_hotkey_profile_trigger (IBusHotkeyProfile *profile, + GQuark event) +{ + // g_debug ("%s is triggerred", g_quark_to_string (event)); +} + +gboolean +ibus_hotkey_profile_add_hotkey (IBusHotkeyProfile *profile, + guint keyval, + guint modifiers, + GQuark event) +{ + IBusHotkeyProfilePrivate *priv; + priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile); + + IBusHotkey *hotkey = ibus_hotkey_new (keyval, modifiers); + + /* has the same hotkey in profile */ + if (g_tree_lookup (priv->hotkeys, hotkey) != NULL) { + ibus_hotkey_free (hotkey); + g_return_val_if_reached (FALSE); + } + + g_tree_insert (priv->hotkeys, hotkey, (gpointer)event); + + gint i; + IBusHotkeyEvent *p = NULL; + for ( i = 0; i < priv->events->len; i++) { + p = &g_array_index (priv->events, IBusHotkeyEvent, i); + if (p->event == event) + break; + } + + if (i >= priv->events->len) { + g_array_set_size (priv->events, i + 1); + p = &g_array_index (priv->events, IBusHotkeyEvent, i); + p->event = event; + } + + p->hotkeys = g_list_append (p->hotkeys, hotkey); + + return TRUE; +} + + +gboolean +ibus_hotkey_profile_add_hotkey_from_string (IBusHotkeyProfile *profile, + const gchar *str, + GQuark event) +{ + guint keyval; + guint modifiers; + + if (ibus_key_event_from_string (str, &keyval, &modifiers) == FALSE) { + return FALSE; + } + + return ibus_hotkey_profile_add_hotkey (profile, keyval, modifiers, event); +} + +gboolean +ibus_hotkey_profile_remove_hotkey (IBusHotkeyProfile *profile, + guint keyval, + guint modifiers) +{ + IBusHotkeyProfilePrivate *priv; + priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile); + + IBusHotkey hotkey = { + keyval : keyval, + modifiers : modifiers + }; + + IBusHotkey *p1; + GQuark event; + gboolean retval; + + retval = g_tree_lookup_extended (priv->hotkeys, + &hotkey, + (gpointer)&p1, + (gpointer)&event); + + if (!retval) + return FALSE; + + gint i; + IBusHotkeyEvent *p2 = NULL; + for ( i = 0; i < priv->events->len; i++) { + p2 = &g_array_index (priv->events, IBusHotkeyEvent, i); + if (p2->event == event) + break; + } + + g_assert (p2->event == event); + + p2->hotkeys = g_list_remove (p2->hotkeys, p1); + if (p2->hotkeys == NULL) { + g_array_remove_index_fast (priv->events, i); + } + + g_tree_remove (priv->hotkeys, p1); + + return TRUE; +} + +gboolean +ibus_hotkey_profile_remove_hotkey_by_event (IBusHotkeyProfile *profile, + GQuark event) +{ + IBusHotkeyProfilePrivate *priv; + priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile); + + gint i; + IBusHotkeyEvent *p = NULL; + for ( i = 0; i < priv->events->len; i++) { + p = &g_array_index (priv->events, IBusHotkeyEvent, i); + if (p->event == event) + break; + } + + if (p == NULL || p->event != event) + return FALSE; + + GList *list; + for (list = p->hotkeys; list != NULL; list = list->next) { + g_tree_remove (priv->hotkeys, (IBusHotkey *)list->data); + } + + g_list_free (p->hotkeys); + g_array_remove_index_fast (priv->events, i); + + return TRUE; +} + +GQuark +ibus_hotkey_profile_filter_key_event (IBusHotkeyProfile *profile, + guint keyval, + guint modifiers, + gpointer user_data) +{ + IBusHotkeyProfilePrivate *priv; + priv = IBUS_HOTKEY_PROFILE_GET_PRIVATE (profile); + + IBusHotkey hotkey = { + keyval : keyval, + modifiers : modifiers & priv->mask, + }; + + GQuark event = (GQuark) g_tree_lookup (priv->hotkeys, &hotkey); + + if (event != 0) { + g_signal_emit (profile, profile_signals[TRIGGER], event, event, user_data); + } + + return event; +} diff --git a/src/ibushotkey.h b/src/ibushotkey.h new file mode 100644 index 0000000..75b0844 --- /dev/null +++ b/src/ibushotkey.h @@ -0,0 +1,87 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_HOTKEY_H_ +#define __IBUS_HOTKEY_H_ + +#include "ibusserializable.h" + +/* + * Type macros. + */ +/* define IBusHotkeyProfile macros */ +#define IBUS_TYPE_HOTKEY_PROFILE \ + (ibus_hotkey_profile_get_type ()) +#define IBUS_HOTKEY_PROFILE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_HOTKEY_PROFILE, IBusHotkeyProfile)) +#define IBUS_HOTKEY_PROFILE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_HOTKEY_PROFILE, IBusHotkeyProfileClass)) +#define IBUS_IS_HOTKEY_PROFILE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_HOTKEY_PROFILE)) +#define IBUS_IS_HOTKEY_PROFILE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_HOTKEY_PROFILE)) +#define IBUS_HOTKEY_PROFILE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_HOTKEY_PROFILE, IBusHotkeyProfileClass)) + +G_BEGIN_DECLS + +typedef struct _IBusHotkeyProfile IBusHotkeyProfile; +typedef struct _IBusHotkeyProfileClass IBusHotkeyProfileClass; + +struct _IBusHotkeyProfile { + IBusSerializable parent; + + /* members */ +}; + +struct _IBusHotkeyProfileClass { + IBusSerializableClass parent; + + void (* trigger) (IBusHotkeyProfile *profile, + GQuark event); +}; + +/* hotkey profile functions */ +GType ibus_hotkey_profile_get_type (void); +IBusHotkeyProfile + *ibus_hotkey_profile_new (void); +gboolean ibus_hotkey_profile_add_hotkey (IBusHotkeyProfile *profile, + guint keyval, + guint modifiers, + GQuark event); +gboolean ibus_hotkey_profile_add_hotkey_from_string + (IBusHotkeyProfile *profile, + const gchar *str, + GQuark event); +gboolean ibus_hotkey_profile_remove_hotkey + (IBusHotkeyProfile *profile, + guint keyval, + guint modifiers); +gboolean ibus_hotkey_profile_remove_hotkey_by_event + (IBusHotkeyProfile *profile, + GQuark event); +GQuark ibus_hotkey_profile_filter_key_event + (IBusHotkeyProfile *profile, + guint keyval, + guint modifiers, + gpointer user_data); + +G_END_DECLS +#endif + diff --git a/src/ibusinputcontext.c b/src/ibusinputcontext.c new file mode 100644 index 0000000..71de8fb --- /dev/null +++ b/src/ibusinputcontext.c @@ -0,0 +1,695 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibusshare.h" +#include "ibusinternal.h" +#include "ibusinputcontext.h" +#include "ibusattribute.h" +#include "ibuslookuptable.h" +#include "ibusproperty.h" + +#define IBUS_INPUT_CONTEXT_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_INPUT_CONTEXT, IBusInputContextPrivate)) + +enum { + ENABLED, + DISABLED, + COMMIT_TEXT, + FORWARD_KEY_EVENT, + UPDATE_PREEDIT_TEXT, + SHOW_PREEDIT_TEXT, + HIDE_PREEDIT_TEXT, + UPDATE_AUXILIARY_TEXT, + SHOW_AUXILIARY_TEXT, + HIDE_AUXILIARY_TEXT, + UPDATE_LOOKUP_TABLE, + SHOW_LOOKUP_TABLE, + HIDE_LOOKUP_TABLE, + PAGE_UP_LOOKUP_TABLE, + PAGE_DOWN_LOOKUP_TABLE, + CURSOR_UP_LOOKUP_TABLE, + CURSOR_DOWN_LOOKUP_TABLE, + REGISTER_PROPERTIES, + UPDATE_PROPERTY, + LAST_SIGNAL, +}; + + +/* BusInputContextPriv */ +struct _IBusInputContextPrivate { + void *pad; +}; +typedef struct _IBusInputContextPrivate IBusInputContextPrivate; + +static guint context_signals[LAST_SIGNAL] = { 0 }; +// static guint context_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_input_context_class_init (IBusInputContextClass *klass); +static void ibus_input_context_init (IBusInputContext *context); +static void ibus_input_context_real_destroy (IBusInputContext *context); +static gboolean ibus_input_context_ibus_signal (IBusProxy *proxy, + DBusMessage *message); + +static IBusProxyClass *parent_class = NULL; + +GType +ibus_input_context_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusInputContextClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_input_context_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusInputContext), + 0, + (GInstanceInitFunc) ibus_input_context_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_PROXY, + "IBusInputContext", + &type_info, + (GTypeFlags)0); + } + return type; +} + +IBusInputContext * +ibus_input_context_new (const gchar *path, + IBusConnection *connection) +{ + g_assert (path != NULL); + g_assert (IBUS_IS_CONNECTION (connection)); + GObject *obj; + + obj = g_object_new (IBUS_TYPE_INPUT_CONTEXT, + "name", IBUS_SERVICE_IBUS, + "path", path, + "connection", connection, + NULL); + + return IBUS_INPUT_CONTEXT (obj); +} + +static void +ibus_input_context_class_init (IBusInputContextClass *klass) +{ + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + IBusProxyClass *proxy_class = IBUS_PROXY_CLASS (klass); + + + parent_class = (IBusProxyClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusInputContextPrivate)); + + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_input_context_real_destroy; + + proxy_class->ibus_signal = ibus_input_context_ibus_signal; + + /* install signals */ + context_signals[ENABLED] = + g_signal_new (I_("enabled"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[DISABLED] = + g_signal_new (I_("disabled"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[COMMIT_TEXT] = + g_signal_new (I_("commit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_TEXT); + + context_signals[FORWARD_KEY_EVENT] = + g_signal_new (I_("forward-key-event"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__UINT_UINT, + G_TYPE_NONE, + 2, + G_TYPE_UINT, + G_TYPE_UINT); + + context_signals[UPDATE_PREEDIT_TEXT] = + g_signal_new (I_("update-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_UINT_BOOLEAN, + G_TYPE_NONE, + 3, + IBUS_TYPE_TEXT, + G_TYPE_UINT, + G_TYPE_BOOLEAN); + + context_signals[SHOW_PREEDIT_TEXT] = + g_signal_new (I_("show-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[HIDE_PREEDIT_TEXT] = + g_signal_new (I_("hide-preedit-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[UPDATE_AUXILIARY_TEXT] = + g_signal_new (I_("update-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, 2, + IBUS_TYPE_TEXT, + G_TYPE_BOOLEAN); + + context_signals[SHOW_AUXILIARY_TEXT] = + g_signal_new (I_("show-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[HIDE_AUXILIARY_TEXT] = + g_signal_new (I_("hide-auxiliary-text"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[UPDATE_LOOKUP_TABLE] = + g_signal_new (I_("update-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, 2, + IBUS_TYPE_LOOKUP_TABLE, + G_TYPE_BOOLEAN); + + context_signals[SHOW_LOOKUP_TABLE] = + g_signal_new (I_("show-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[HIDE_LOOKUP_TABLE] = + g_signal_new (I_("hide-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[PAGE_UP_LOOKUP_TABLE] = + g_signal_new (I_("page-up-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[PAGE_DOWN_LOOKUP_TABLE] = + g_signal_new (I_("page-down-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[CURSOR_UP_LOOKUP_TABLE] = + g_signal_new (I_("cursor-up-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + context_signals[CURSOR_DOWN_LOOKUP_TABLE] = + g_signal_new (I_("cursor-down-lookup-table"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + context_signals[REGISTER_PROPERTIES] = + g_signal_new (I_("register-properties"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_PROP_LIST); + + context_signals[UPDATE_PROPERTY] = + g_signal_new (I_("update-property"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + IBUS_TYPE_PROPERTY); +} + +static void +ibus_input_context_init (IBusInputContext *context) +{ + IBusInputContextPrivate *priv; + priv = IBUS_INPUT_CONTEXT_GET_PRIVATE (context); +} + +static void +ibus_input_context_real_destroy (IBusInputContext *context) +{ + if (ibus_proxy_get_connection ((IBusProxy *) context) != NULL) { + ibus_proxy_call (IBUS_PROXY (context), + "Destroy", + G_TYPE_INVALID); + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (context)); +} + +static gboolean +ibus_input_context_ibus_signal (IBusProxy *proxy, + IBusMessage *message) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (proxy)); + g_assert (message != NULL); + + IBusInputContext *context; + IBusError *error = NULL; + gint i; + + context = IBUS_INPUT_CONTEXT (proxy); + + static const struct { + const gchar *member; + guint signal_id; + } signals [] = { + { "Enabled", ENABLED }, + { "Disabled", DISABLED }, + { "ShowPreeditText", SHOW_PREEDIT_TEXT }, + { "HidePreeditText", HIDE_PREEDIT_TEXT }, + { "ShowAuxiliaryText", SHOW_AUXILIARY_TEXT }, + { "HideAuxiliaryText", HIDE_AUXILIARY_TEXT }, + { "ShowLookupTable", SHOW_LOOKUP_TABLE }, + { "HideLookupTable", HIDE_LOOKUP_TABLE }, + { "PageUpLookupTable", PAGE_UP_LOOKUP_TABLE }, + { "PageDownLookupTable", PAGE_DOWN_LOOKUP_TABLE }, + { "CursorUpLookupTable", CURSOR_UP_LOOKUP_TABLE }, + { "CursorDownLookupTable", CURSOR_DOWN_LOOKUP_TABLE}, + { NULL, 0}, + }; + + for (i = 0; ; i++) { + if (signals[i].member == NULL) + break; + if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + signals[i].member)) { + g_signal_emit (context, context_signals[signals[i].signal_id], 0); + goto handled; + } + } + + if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "CommitText")) { + IBusText *text; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_INVALID); + if (!retval) + goto failed; + + g_signal_emit (context, context_signals[COMMIT_TEXT], 0, text); + g_object_unref (text); + } + else if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "UpdatePreeditText")) { + IBusText *text; + gint32 cursor_pos; + gboolean visible; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_UINT, &cursor_pos, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (context, + context_signals[UPDATE_PREEDIT_TEXT], + 0, + text, + cursor_pos, + visible); + g_object_unref (text); + } + else if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "ForwardKeyEvent")) { + guint32 keyval; + gboolean is_press; + guint32 state; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + G_TYPE_UINT, &keyval, + G_TYPE_BOOLEAN, &is_press, + G_TYPE_UINT, &state, + G_TYPE_INVALID); + + if (!retval) + goto failed; + g_signal_emit (context, + context_signals[FORWARD_KEY_EVENT], + 0, + keyval, + state | IBUS_FORWARD_MASK); + } + else if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "UpdateAuxiliaryText")) { + IBusText *text; + gboolean visible; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_TEXT, &text, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (context, + context_signals[UPDATE_AUXILIARY_TEXT], + 0, + text, + visible); + g_object_unref (text); + } + else if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "UpdateLookupTable")) { + IBusLookupTable *table; + gboolean visible; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_LOOKUP_TABLE, &table, + G_TYPE_BOOLEAN, &visible, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (context, + context_signals[UPDATE_LOOKUP_TABLE], + 0, + table, + visible); + g_object_unref (table); + } + else if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "RegisterProperties")) { + IBusPropList *prop_list; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_PROP_LIST, &prop_list, + G_TYPE_INVALID); + + if (!retval) + goto failed; + + g_signal_emit (context, + context_signals[REGISTER_PROPERTIES], + 0, + prop_list); + g_object_unref (prop_list); + } + else if (ibus_message_is_signal (message, + IBUS_INTERFACE_INPUT_CONTEXT, + "UpdateProperty")) { + IBusProperty *prop; + gboolean retval; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_PROPERTY, &prop, + G_TYPE_INVALID); + if (!retval) + goto failed; + + g_signal_emit (context, context_signals[UPDATE_PROPERTY], 0, prop); + g_object_unref (prop); + } + else { + return FALSE; + } + +handled: + g_signal_stop_emission_by_name (context, "ibus-signal"); + return TRUE; + +failed: + if (error) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + } + return FALSE; +} + +gboolean +ibus_input_context_process_key_event (IBusInputContext *context, + guint32 keyval, + guint32 state) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + + IBusMessage *reply_message; + IBusPendingCall *pending = NULL; + IBusError *error = NULL; + gboolean retval; + + if (state & IBUS_FORWARD_MASK) + return FALSE; + + retval = ibus_proxy_call_with_reply ((IBusProxy *) context, + "ProcessKeyEvent", + &pending, + -1, + &error, + G_TYPE_UINT, &keyval, + G_TYPE_UINT, &state, + G_TYPE_INVALID); + if (!retval) { + g_debug ("%s: %s", error->name, error->message); + ibus_error_free (error); + return FALSE; + } + + /* wait reply or timeout */ + ibus_pending_call_wait (pending); + + reply_message = ibus_pending_call_steal_reply (pending); + ibus_pending_call_unref (pending); + + if (reply_message == NULL) { + g_debug ("%s: Do not recevie reply of ProcessKeyEvent", DBUS_ERROR_NO_REPLY); + retval = FALSE; + } + else if ((error = ibus_error_new_from_message (reply_message)) != NULL) { + g_debug ("%s: %s", error->name, error->message); + ibus_message_unref (reply_message); + ibus_error_free (error); + retval = FALSE; + } + else { + + if (!ibus_message_get_args (reply_message, + &error, + G_TYPE_BOOLEAN, &retval, + G_TYPE_INVALID)) { + g_debug ("%s: %s", error->name, error->message); + ibus_error_free (error); + retval = FALSE; + } + ibus_message_unref (reply_message); + } + return retval; +} + +void +ibus_input_context_set_cursor_location (IBusInputContext *context, + gint32 x, + gint32 y, + gint32 w, + gint32 h) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + + ibus_proxy_call ((IBusProxy *) context, + "SetCursorLocation", + G_TYPE_INT, &x, + G_TYPE_INT, &y, + G_TYPE_INT, &w, + G_TYPE_INT, &h, + G_TYPE_INVALID); +} + +void +ibus_input_context_set_capabilities (IBusInputContext *context, + guint32 capabilites) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + + ibus_proxy_call ((IBusProxy *) context, + "SetCapabilities", + G_TYPE_UINT, &capabilites, + G_TYPE_INVALID); +} + +void +ibus_input_context_property_activate (IBusInputContext *context, + const gchar *prop_name, + gint32 state) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + + ibus_proxy_call ((IBusProxy *) context, + "PropertyActivate", + G_TYPE_STRING, &prop_name, + G_TYPE_INT, &state, + G_TYPE_INVALID); +} + +void +ibus_input_context_property_show (IBusInputContext *context, + const gchar *prop_name) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + + ibus_proxy_call ((IBusProxy *) context, + "PropertyShow", + G_TYPE_STRING, &prop_name, + G_TYPE_INVALID); +} + +void +ibus_input_context_property_hide (IBusInputContext *context, + const gchar *prop_name) +{ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); + + ibus_proxy_call ((IBusProxy *) context, + "PropertyHide", + G_TYPE_STRING, &prop_name, + G_TYPE_INVALID); +} + +#define DEFINE_FUNC(name,Name) \ + void \ + ibus_input_context_##name (IBusInputContext *context) \ + { \ + g_assert (IBUS_IS_INPUT_CONTEXT (context)); \ + ibus_proxy_call ((IBusProxy *) context, \ + #Name, \ + G_TYPE_INVALID); \ + } + +DEFINE_FUNC(focus_in, FocusIn); +DEFINE_FUNC(focus_out, FocusOut); +DEFINE_FUNC(reset, Reset); +DEFINE_FUNC(page_up, PageUp); +DEFINE_FUNC(page_down, PageDown); +DEFINE_FUNC(cursor_up, CursorUp); +DEFINE_FUNC(cursor_down, CursorDown); +DEFINE_FUNC(enable, Enable); +DEFINE_FUNC(disable, Disable); + +#undef DEFINE_FUNC + diff --git a/src/ibusinputcontext.h b/src/ibusinputcontext.h new file mode 100644 index 0000000..3ec1bf9 --- /dev/null +++ b/src/ibusinputcontext.h @@ -0,0 +1,87 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_INPUT_CONTEXT_H_ +#define __IBUS_INPUT_CONTEXT_H_ + +#include "ibusproxy.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_INPUT_CONTEXT \ + (ibus_input_context_get_type ()) +#define IBUS_INPUT_CONTEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_INPUT_CONTEXT, IBusInputContext)) +#define IBUS_INPUT_CONTEXT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_INPUT_CONTEXT, IBusInputContextClass)) +#define IBUS_IS_INPUT_CONTEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_INPUT_CONTEXT)) +#define IBUS_IS_INPUT_CONTEXT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_INPUT_CONTEXT)) +#define IBUS_INPUT_CONTEXT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_INPUT_CONTEXT, IBusInputContextClass)) + +G_BEGIN_DECLS + +typedef struct _IBusInputContext IBusInputContext; +typedef struct _IBusInputContextClass IBusInputContextClass; + +struct _IBusInputContext { + IBusProxy parent; + /* instance members */ +}; + +struct _IBusInputContextClass { + IBusProxyClass parent; + /* signals */ + + /*< private >*/ + /* padding */ + gpointer pdummy[24]; +}; + +GType ibus_input_context_get_type (void); +IBusInputContext + *ibus_input_context_new (const gchar *path, + IBusConnection *connection); +gboolean ibus_input_context_process_key_event + (IBusInputContext *context, + guint32 keyval, + guint32 state); +void ibus_input_context_set_cursor_location + (IBusInputContext *context, + gint32 x, + gint32 y, + gint32 w, + gint32 h); +void ibus_input_context_set_capabilities + (IBusInputContext *context, + guint32 capabilites); +void ibus_input_context_focus_in (IBusInputContext *context); +void ibus_input_context_focus_out (IBusInputContext *context); +void ibus_input_context_reset (IBusInputContext *context); +void ibus_input_context_enable (IBusInputContext *context); +void ibus_input_context_disable (IBusInputContext *context); + +G_END_DECLS +#endif + diff --git a/src/ibusinternal.c b/src/ibusinternal.c new file mode 100644 index 0000000..3610b52 --- /dev/null +++ b/src/ibusinternal.c @@ -0,0 +1,667 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-gmain.c GLib main loop integration + * + * Copyright (C) 2002, 2003 CodeFactory AB + * Copyright (C) 2005 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "ibusinternal.h" + +/** + * IBusMessageQueue: + * A GSource subclass for dispatching DBusConnection messages. + * We need this on top of the IO handlers, because sometimes + * there are messages to dispatch queued up but no IO pending. + */ +typedef struct +{ + GSource source; /**< the parent GSource */ + DBusConnection *connection; /**< the connection to dispatch */ +} IBusMessageQueue; + +static gboolean message_queue_prepare (GSource *source, + gint *timeout); +static gboolean message_queue_check (GSource *source); +static gboolean message_queue_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data); + +static const GSourceFuncs message_queue_funcs = { + message_queue_prepare, + message_queue_check, + message_queue_dispatch, + NULL +}; + +static gboolean +message_queue_prepare (GSource *source, + gint *timeout) +{ + DBusConnection *connection = ((IBusMessageQueue *)source)->connection; + + *timeout = -1; + + return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS); +} + +static gboolean +message_queue_check (GSource *source) +{ + return FALSE; +} + +static gboolean +message_queue_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + DBusConnection *connection = ((IBusMessageQueue *)source)->connection; + + dbus_connection_ref (connection); + + /* Only dispatch once - we don't want to starve other GSource */ + dbus_connection_dispatch (connection); + + dbus_connection_unref (connection); + + return TRUE; +} + +typedef struct +{ + GMainContext *context; /**< the main context */ + GSList *ios; /**< all IOHandler */ + GSList *timeouts; /**< all TimeoutHandler */ + DBusConnection *connection; /**< NULL if this is really for a server not a connection */ + GSource *message_queue_source; /**< IBusMessageQueue */ +} ConnectionSetup; + + +typedef struct +{ + ConnectionSetup *cs; + GSource *source; + DBusWatch *watch; +} IOHandler; + +typedef struct +{ + ConnectionSetup *cs; + GSource *source; + DBusTimeout *timeout; +} TimeoutHandler; + +dbus_int32_t _dbus_gmain_connection_slot = -1; +static dbus_int32_t server_slot = -1; + +static ConnectionSetup* +connection_setup_new (GMainContext *context, + DBusConnection *connection) +{ + ConnectionSetup *cs; + + cs = g_new0 (ConnectionSetup, 1); + + g_assert (context != NULL); + + cs->context = context; + g_main_context_ref (cs->context); + + if (connection) + { + cs->connection = connection; + + cs->message_queue_source = g_source_new ((GSourceFuncs *) &message_queue_funcs, + sizeof (IBusMessageQueue)); + ((IBusMessageQueue*)cs->message_queue_source)->connection = connection; + g_source_attach (cs->message_queue_source, cs->context); + } + + return cs; +} + +static void +io_handler_source_finalized (gpointer data) +{ + IOHandler *handler; + + handler = data; + + if (handler->watch) + dbus_watch_set_data (handler->watch, NULL, NULL); + + g_free (handler); +} + +static void +io_handler_destroy_source (void *data) +{ + IOHandler *handler; + + handler = data; + + if (handler->source) + { + GSource *source = handler->source; + handler->source = NULL; + handler->cs->ios = g_slist_remove (handler->cs->ios, handler); + g_source_destroy (source); + g_source_unref (source); + } +} + +static void +io_handler_watch_freed (void *data) +{ + IOHandler *handler; + + handler = data; + + handler->watch = NULL; + + io_handler_destroy_source (handler); +} + +static gboolean +io_handler_dispatch (GIOChannel *source, + GIOCondition condition, + gpointer data) +{ + IOHandler *handler; + guint dbus_condition = 0; + DBusConnection *connection; + + handler = data; + + connection = handler->cs->connection; + + if (connection) + dbus_connection_ref (connection); + + if (condition & G_IO_IN) + dbus_condition |= DBUS_WATCH_READABLE; + if (condition & G_IO_OUT) + dbus_condition |= DBUS_WATCH_WRITABLE; + if (condition & G_IO_ERR) + dbus_condition |= DBUS_WATCH_ERROR; + if (condition & G_IO_HUP) + dbus_condition |= DBUS_WATCH_HANGUP; + + /* Note that we don't touch the handler after this, because + * dbus may have disabled the watch and thus killed the + * handler. + */ + dbus_watch_handle (handler->watch, dbus_condition); + handler = NULL; + + if (connection) + dbus_connection_unref (connection); + + return TRUE; +} + +static void +connection_setup_add_watch (ConnectionSetup *cs, + DBusWatch *watch) +{ + guint flags; + GIOCondition condition; + GIOChannel *channel; + IOHandler *handler; + + if (!dbus_watch_get_enabled (watch)) + return; + + g_assert (dbus_watch_get_data (watch) == NULL); + + flags = dbus_watch_get_flags (watch); + + condition = G_IO_ERR | G_IO_HUP; + if (flags & DBUS_WATCH_READABLE) + condition |= G_IO_IN; + if (flags & DBUS_WATCH_WRITABLE) + condition |= G_IO_OUT; + + handler = g_new0 (IOHandler, 1); + handler->cs = cs; + handler->watch = watch; + + channel = g_io_channel_unix_new (dbus_watch_get_unix_fd (watch)); + + handler->source = g_io_create_watch (channel, condition); + g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler, + io_handler_source_finalized); + g_source_attach (handler->source, cs->context); + + cs->ios = g_slist_prepend (cs->ios, handler); + + dbus_watch_set_data (watch, handler, io_handler_watch_freed); + g_io_channel_unref (channel); +} + +static void +connection_setup_remove_watch (ConnectionSetup *cs, + DBusWatch *watch) +{ + IOHandler *handler; + + handler = dbus_watch_get_data (watch); + + if (handler == NULL) + return; + + io_handler_destroy_source (handler); +} + +static void +timeout_handler_source_finalized (gpointer data) +{ + TimeoutHandler *handler; + + handler = data; + + if (handler->timeout) + dbus_timeout_set_data (handler->timeout, NULL, NULL); + + g_free (handler); +} + +static void +timeout_handler_destroy_source (void *data) +{ + TimeoutHandler *handler; + + handler = data; + + if (handler->source) + { + GSource *source = handler->source; + handler->source = NULL; + handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler); + g_source_destroy (source); + g_source_unref (source); + } +} + +static void +timeout_handler_timeout_freed (void *data) +{ + TimeoutHandler *handler; + + handler = data; + + handler->timeout = NULL; + + timeout_handler_destroy_source (handler); +} + +static gboolean +timeout_handler_dispatch (gpointer data) +{ + TimeoutHandler *handler; + + handler = data; + + dbus_timeout_handle (handler->timeout); + + return TRUE; +} + +static void +connection_setup_add_timeout (ConnectionSetup *cs, + DBusTimeout *timeout) +{ + TimeoutHandler *handler; + + if (!dbus_timeout_get_enabled (timeout)) + return; + + g_assert (dbus_timeout_get_data (timeout) == NULL); + + handler = g_new0 (TimeoutHandler, 1); + handler->cs = cs; + handler->timeout = timeout; + + handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout)); + g_source_set_callback (handler->source, timeout_handler_dispatch, handler, + timeout_handler_source_finalized); + g_source_attach (handler->source, handler->cs->context); + + cs->timeouts = g_slist_prepend (cs->timeouts, handler); + + dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed); +} + +static void +connection_setup_remove_timeout (ConnectionSetup *cs, + DBusTimeout *timeout) +{ + TimeoutHandler *handler; + + handler = dbus_timeout_get_data (timeout); + + if (handler == NULL) + return; + + timeout_handler_destroy_source (handler); +} + +static void +connection_setup_free (ConnectionSetup *cs) +{ + while (cs->ios) + io_handler_destroy_source (cs->ios->data); + + while (cs->timeouts) + timeout_handler_destroy_source (cs->timeouts->data); + + if (cs->message_queue_source) + { + GSource *source; + + source = cs->message_queue_source; + cs->message_queue_source = NULL; + + g_source_destroy (source); + g_source_unref (source); + } + + g_main_context_unref (cs->context); + g_free (cs); +} + +static dbus_bool_t +add_watch (DBusWatch *watch, + gpointer data) +{ + ConnectionSetup *cs; + + cs = data; + + connection_setup_add_watch (cs, watch); + + return TRUE; +} + +static void +remove_watch (DBusWatch *watch, + gpointer data) +{ + ConnectionSetup *cs; + + cs = data; + + connection_setup_remove_watch (cs, watch); +} + +static void +watch_toggled (DBusWatch *watch, + void *data) +{ + /* Because we just exit on OOM, enable/disable is + * no different from add/remove + */ + if (dbus_watch_get_enabled (watch)) + add_watch (watch, data); + else + remove_watch (watch, data); +} + +static dbus_bool_t +add_timeout (DBusTimeout *timeout, + void *data) +{ + ConnectionSetup *cs; + + cs = data; + + if (!dbus_timeout_get_enabled (timeout)) + return TRUE; + + connection_setup_add_timeout (cs, timeout); + + return TRUE; +} + +static void +remove_timeout (DBusTimeout *timeout, + void *data) +{ + ConnectionSetup *cs; + + cs = data; + + connection_setup_remove_timeout (cs, timeout); +} + +static void +timeout_toggled (DBusTimeout *timeout, + void *data) +{ + /* Because we just exit on OOM, enable/disable is + * no different from add/remove + */ + if (dbus_timeout_get_enabled (timeout)) + add_timeout (timeout, data); + else + remove_timeout (timeout, data); +} + +static void +wakeup_main (void *data) +{ + ConnectionSetup *cs = data; + + g_main_context_wakeup (cs->context); +} + + +/* Move to a new context */ +static ConnectionSetup* +connection_setup_new_from_old (GMainContext *context, + ConnectionSetup *old) +{ + GSList *tmp; + ConnectionSetup *cs; + + g_assert (old->context != context); + + cs = connection_setup_new (context, old->connection); + + tmp = old->ios; + while (tmp != NULL) + { + IOHandler *handler = tmp->data; + + connection_setup_add_watch (cs, handler->watch); + + tmp = tmp->next; + } + + tmp = old->timeouts; + while (tmp != NULL) + { + TimeoutHandler *handler = tmp->data; + + connection_setup_add_timeout (cs, handler->timeout); + + tmp = tmp->next; + } + + return cs; +} + +/** @} */ /* End of GLib bindings internals */ + +/** @addtogroup IBusLib + * @{ + */ + +/** + * dbus_connection_setup_with_g_main: + * @connection: the connection + * @context: the #GMainContext or #NULL for default context + * + * Sets the watch and timeout functions of a #DBusConnection + * to integrate the connection with the GLib main loop. + * Pass in #NULL for the #GMainContext unless you're + * doing something specialized. + * + * If called twice for the same context, does nothing the second + * time. If called once with context A and once with context B, + * context B replaces context A as the context monitoring the + * connection. + */ +void +dbus_connection_setup (DBusConnection *connection, + GMainContext *context) +{ + ConnectionSetup *old_setup; + ConnectionSetup *cs; + + /* FIXME we never free the slot, so its refcount just keeps growing, + * which is kind of broken. + */ + dbus_connection_allocate_data_slot (&_dbus_gmain_connection_slot); + if (_dbus_gmain_connection_slot < 0) + goto nomem; + + if (context == NULL) + context = g_main_context_default (); + + cs = NULL; + + old_setup = dbus_connection_get_data (connection, _dbus_gmain_connection_slot); + if (old_setup != NULL) + { + if (old_setup->context == context) + return; /* nothing to do */ + + cs = connection_setup_new_from_old (context, old_setup); + + /* Nuke the old setup */ + dbus_connection_set_data (connection, _dbus_gmain_connection_slot, NULL, NULL); + old_setup = NULL; + } + + if (cs == NULL) + cs = connection_setup_new (context, connection); + + if (!dbus_connection_set_data (connection, _dbus_gmain_connection_slot, cs, + (DBusFreeFunction)connection_setup_free)) + goto nomem; + + if (!dbus_connection_set_watch_functions (connection, + add_watch, + remove_watch, + watch_toggled, + cs, NULL)) + goto nomem; + + if (!dbus_connection_set_timeout_functions (connection, + add_timeout, + remove_timeout, + timeout_toggled, + cs, NULL)) + goto nomem; + + dbus_connection_set_wakeup_main_function (connection, + wakeup_main, + cs, NULL); + + return; + + nomem: + g_error ("Not enough memory to set up DBusConnection for use with GLib"); +} + +/** + * dbus_server_setup_with_g_main: + * @server: the server + * @context: the #GMainContext or #NULL for default + * + * Sets the watch and timeout functions of a #DBusServer + * to integrate the server with the GLib main loop. + * In most cases the context argument should be #NULL. + * + * If called twice for the same context, does nothing the second + * time. If called once with context A and once with context B, + * context B replaces context A as the context monitoring the + * connection. + */ +void +dbus_server_setup (DBusServer *server, + GMainContext *context) +{ + ConnectionSetup *old_setup; + ConnectionSetup *cs; + + /* FIXME we never free the slot, so its refcount just keeps growing, + * which is kind of broken. + */ + dbus_server_allocate_data_slot (&server_slot); + if (server_slot < 0) + goto nomem; + + if (context == NULL) + context = g_main_context_default (); + + cs = NULL; + + old_setup = dbus_server_get_data (server, server_slot); + if (old_setup != NULL) + { + if (old_setup->context == context) + return; /* nothing to do */ + + cs = connection_setup_new_from_old (context, old_setup); + + /* Nuke the old setup */ + dbus_server_set_data (server, server_slot, NULL, NULL); + old_setup = NULL; + } + + if (cs == NULL) + cs = connection_setup_new (context, NULL); + + if (!dbus_server_set_data (server, server_slot, cs, + (DBusFreeFunction)connection_setup_free)) + goto nomem; + + if (!dbus_server_set_watch_functions (server, + add_watch, + remove_watch, + watch_toggled, + cs, NULL)) + goto nomem; + + if (!dbus_server_set_timeout_functions (server, + add_timeout, + remove_timeout, + timeout_toggled, + cs, NULL)) + goto nomem; + + return; + + nomem: + g_error ("Not enough memory to set up DBusServer for use with GLib"); +} + diff --git a/src/ibusinternal.h b/src/ibusinternal.h new file mode 100644 index 0000000..924d96e --- /dev/null +++ b/src/ibusinternal.h @@ -0,0 +1,36 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_INTERNEL_H_ +#define __IBUS_INTERNEL_H_ + +#include <glib.h> +#include <dbus/dbus.h> + +#define I_(string) g_intern_static_string (string) + +void dbus_server_setup (DBusServer *server, + GMainContext *context); +void dbus_connection_setup (DBusConnection *connection, + GMainContext *context); + + + +#endif + diff --git a/src/ibuskeynames.c b/src/ibuskeynames.c new file mode 100644 index 0000000..9a8c1e4 --- /dev/null +++ b/src/ibuskeynames.c @@ -0,0 +1,199 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* Key handling not part of the keymap */ +#include <glib.h> +#include <glib/gprintf.h> +#include <stdlib.h> +#include <string.h> +#include "ibuskeysyms.h" +#include "keyname-table.h" + +#define IBUS_NUM_KEYS G_N_ELEMENTS (gdk_keys_by_keyval) + +static int +gdk_keys_keyval_compare (const void *pkey, const void *pbase) +{ + return (*(int *) pkey) - ((gdk_key *) pbase)->keyval; +} + +const gchar* +ibus_keyval_name (guint keyval) +{ + static gchar buf[100]; + gdk_key *found; + + /* Check for directly encoded 24-bit UCS characters: */ + if ((keyval & 0xff000000) == 0x01000000) + { + g_sprintf (buf, "U+%.04X", (keyval & 0x00ffffff)); + return buf; + } + + found = bsearch (&keyval, gdk_keys_by_keyval, + IBUS_NUM_KEYS, sizeof (gdk_key), + gdk_keys_keyval_compare); + + if (found != NULL) + { + while ((found > gdk_keys_by_keyval) && + ((found - 1)->keyval == keyval)) + found--; + + return (gchar *) (keynames + found->offset); + } + else if (keyval != 0) + { + g_sprintf (buf, "%#x", keyval); + return buf; + } + + return NULL; +} + +static int +gdk_keys_name_compare (const void *pkey, const void *pbase) +{ + return strcmp ((const char *) pkey, + (const char *) (keynames + ((const gdk_key *) pbase)->offset)); +} + +guint +ibus_keyval_from_name (const gchar *keyval_name) +{ + gdk_key *found; + + g_return_val_if_fail (keyval_name != NULL, 0); + + found = bsearch (keyval_name, gdk_keys_by_name, + IBUS_NUM_KEYS, sizeof (gdk_key), + gdk_keys_name_compare); + if (found != NULL) + return found->keyval; + else + return IBUS_VoidSymbol; +} + +static const gchar * +modifier_name[] = { + "Shift", + "Lock", + "Control", + "Alt", + "Mod2", + "Mod3", + "Mod4", + "Mod5", + "Button1", + "Button2", + "Button3", + "Button4", + "Button5", + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, + "Supper", + "Hyper", + "Meta", + NULL, + "Release", + NULL, + NULL, +}; + +const gchar * +ibus_key_event_to_string (guint keyval, + guint modifiers) +{ + guint i; + GString *str; + const gchar *keyval_name; + + g_return_val_if_fail (keyval != IBUS_VoidSymbol, NULL); + + keyval_name = ibus_keyval_name (keyval); + g_return_val_if_fail (keyval_name != NULL, NULL); + + str = g_string_new (""); + + for (i = 0; i < 32; i++) { + guint mask = 1 << i; + + if ((modifiers & mask) == 0) + continue; + if (modifier_name[i] == NULL) + continue; + + g_string_append (str, modifier_name[i]); + g_string_append_c (str, '+'); + } + + g_string_append (str, keyval_name); + + return g_string_free (str, FALSE); +} + +gboolean +ibus_key_event_from_string (const gchar *string, + guint *keyval, + guint *modifiers) +{ + g_return_val_if_fail (string != NULL, FALSE); + g_return_val_if_fail (keyval != NULL, FALSE); + g_return_val_if_fail (modifiers != NULL, FALSE); + + gchar **tokens = NULL; + gchar **p; + gboolean retval = FALSE; + + tokens = g_strsplit (string, "+", 0); + g_return_val_if_fail (tokens != NULL, FALSE); + + *keyval = 0; + *modifiers = 0; + + for (p = tokens; *(p + 1) != NULL; p++) { + gint i; + for (i = 0; i < 32; i++) { + if (g_strcmp0 (modifier_name[i], *p) != 0) + continue; + *modifiers |= (1 << i); + break; + } + if (i == 32) { + goto _out; + } + } + + *keyval = ibus_keyval_from_name (*p); + if (*keyval != IBUS_VoidSymbol) + retval = TRUE; +_out: + if (tokens) + g_strfreev (tokens); + return retval; +} + diff --git a/src/ibuskeysyms-update.pl b/src/ibuskeysyms-update.pl new file mode 100755 index 0000000..4fd426d --- /dev/null +++ b/src/ibuskeysyms-update.pl @@ -0,0 +1,105 @@ +#!/usr/bin/env perl + +# Updates http://svn.gnome.org/viewcvs/gtk%2B/trunk/gdk/gdkkeysyms.h?view=log from upstream (X.org 7.x), +# from http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob_plain;f=keysymdef.h +# +# Author : Simos Xenitellis <simos at gnome dot org>. +# Version : 1.2 +# +# Input : http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob_plain;f=keysymdef.h +# Output : http://svn.gnome.org/svn/gtk+/trunk/gdk/gdkkeysyms.h +# +# Notes : It downloads keysymdef.h from the Internet, if not found locally, +# Notes : and creates an updated gdkkeysyms.h +# Notes : This version updates the source of gdkkeysyms.h from CVS to the GIT server. + +use strict; + +# Used for reading the keysymdef symbols. +my @keysymelements; + +if ( ! -f "keysymdef.h" ) +{ + print "Trying to download keysymdef.h from\n"; + print "http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob_plain;f=keysymdef.h\n"; + die "Unable to download keysymdef.h from http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob_plain;f=keysymdef.h\n" + unless system("wget -c -O keysymdef.h \"http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob_plain;f=keysymdef.h\"") == 0; + print " done.\n\n"; +} +else +{ + print "We are using existing keysymdef.h found in this directory.\n"; + print "It is assumed that you took care and it is a recent version\n"; + print "as found at http://gitweb.freedesktop.org/?p=xorg/proto/x11proto.git;a=blob;f=keysymdef.h\n\n"; +} + + +if ( -f "ibuskeysyms.h" ) +{ + print "There is already a ibuskeysyms.h file in this directory. We are not overwriting it.\n"; + print "Please move it somewhere else in order to run this script.\n"; + die "Exiting...\n\n"; +} + +# Source: http://cvs.freedesktop.org/xorg/xc/include/keysymdef.h +die "Could not open file keysymdef.h: $!\n" unless open(IN_KEYSYMDEF, "<:utf8", "keysymdef.h"); + +# Output: gtk+/gdk/gdkkeysyms.h +die "Could not open file ibuskeysyms.h: $!\n" unless open(OUT_IBUSKEYSYMS, ">:utf8", "ibuskeysyms.h"); + +print OUT_IBUSKEYSYMS<<EOF; +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang\@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +#ifndef __IBUS_KEYSYMS_H__ +#define __IBUS_KEYSYMS_H__ + + +EOF + + +while (<IN_KEYSYMDEF>) +{ + next if ( ! /^#define / ); + + @keysymelements = split(/\s+/); + die "Internal error, no \@keysymelements: $_\n" unless @keysymelements; + + $_ = $keysymelements[1]; + die "Internal error, was expecting \"XC_*\", found: $_\n" if ( ! /^XK_/ ); + + $_ = $keysymelements[2]; + die "Internal error, was expecting \"0x*\", found: $_\n" if ( ! /^0x/ ); + + $keysymelements[1] =~ s/^XK_/IBUS_/g; + + printf OUT_IBUSKEYSYMS "#define %s 0x%03x\n", $keysymelements[1], hex($keysymelements[2]); +} + +#$ibussyms{"0"} = "0000"; + +close IN_KEYSYMDEF; + + +print OUT_IBUSKEYSYMS<<EOF; + +#endif /* __IBUS_KEYSYMS_H__ */ +EOF + +printf "We just finished converting keysymdef.h to ibuskeysyms.h\nThank you\n"; diff --git a/src/ibuskeysyms.h b/src/ibuskeysyms.h new file mode 100644 index 0000000..cfcfe8d --- /dev/null +++ b/src/ibuskeysyms.h @@ -0,0 +1,2014 @@ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ + +#ifndef __IBUS_KEYSYMS_H__ +#define __IBUS_KEYSYMS_H__ + + +#define IBUS_VoidSymbol 0xffffff +#define IBUS_BackSpace 0xff08 +#define IBUS_Tab 0xff09 +#define IBUS_Linefeed 0xff0a +#define IBUS_Clear 0xff0b +#define IBUS_Return 0xff0d +#define IBUS_Pause 0xff13 +#define IBUS_Scroll_Lock 0xff14 +#define IBUS_Sys_Req 0xff15 +#define IBUS_Escape 0xff1b +#define IBUS_Delete 0xffff +#define IBUS_Multi_key 0xff20 +#define IBUS_Codeinput 0xff37 +#define IBUS_SingleCandidate 0xff3c +#define IBUS_MultipleCandidate 0xff3d +#define IBUS_PreviousCandidate 0xff3e +#define IBUS_Kanji 0xff21 +#define IBUS_Muhenkan 0xff22 +#define IBUS_Henkan_Mode 0xff23 +#define IBUS_Henkan 0xff23 +#define IBUS_Romaji 0xff24 +#define IBUS_Hiragana 0xff25 +#define IBUS_Katakana 0xff26 +#define IBUS_Hiragana_Katakana 0xff27 +#define IBUS_Zenkaku 0xff28 +#define IBUS_Hankaku 0xff29 +#define IBUS_Zenkaku_Hankaku 0xff2a +#define IBUS_Touroku 0xff2b +#define IBUS_Massyo 0xff2c +#define IBUS_Kana_Lock 0xff2d +#define IBUS_Kana_Shift 0xff2e +#define IBUS_Eisu_Shift 0xff2f +#define IBUS_Eisu_toggle 0xff30 +#define IBUS_Kanji_Bangou 0xff37 +#define IBUS_Zen_Koho 0xff3d +#define IBUS_Mae_Koho 0xff3e +#define IBUS_Home 0xff50 +#define IBUS_Left 0xff51 +#define IBUS_Up 0xff52 +#define IBUS_Right 0xff53 +#define IBUS_Down 0xff54 +#define IBUS_Prior 0xff55 +#define IBUS_Page_Up 0xff55 +#define IBUS_Next 0xff56 +#define IBUS_Page_Down 0xff56 +#define IBUS_End 0xff57 +#define IBUS_Begin 0xff58 +#define IBUS_Select 0xff60 +#define IBUS_Print 0xff61 +#define IBUS_Execute 0xff62 +#define IBUS_Insert 0xff63 +#define IBUS_Undo 0xff65 +#define IBUS_Redo 0xff66 +#define IBUS_Menu 0xff67 +#define IBUS_Find 0xff68 +#define IBUS_Cancel 0xff69 +#define IBUS_Help 0xff6a +#define IBUS_Break 0xff6b +#define IBUS_Mode_switch 0xff7e +#define IBUS_script_switch 0xff7e +#define IBUS_Num_Lock 0xff7f +#define IBUS_KP_Space 0xff80 +#define IBUS_KP_Tab 0xff89 +#define IBUS_KP_Enter 0xff8d +#define IBUS_KP_F1 0xff91 +#define IBUS_KP_F2 0xff92 +#define IBUS_KP_F3 0xff93 +#define IBUS_KP_F4 0xff94 +#define IBUS_KP_Home 0xff95 +#define IBUS_KP_Left 0xff96 +#define IBUS_KP_Up 0xff97 +#define IBUS_KP_Right 0xff98 +#define IBUS_KP_Down 0xff99 +#define IBUS_KP_Prior 0xff9a +#define IBUS_KP_Page_Up 0xff9a +#define IBUS_KP_Next 0xff9b +#define IBUS_KP_Page_Down 0xff9b +#define IBUS_KP_End 0xff9c +#define IBUS_KP_Begin 0xff9d +#define IBUS_KP_Insert 0xff9e +#define IBUS_KP_Delete 0xff9f +#define IBUS_KP_Equal 0xffbd +#define IBUS_KP_Multiply 0xffaa +#define IBUS_KP_Add 0xffab +#define IBUS_KP_Separator 0xffac +#define IBUS_KP_Subtract 0xffad +#define IBUS_KP_Decimal 0xffae +#define IBUS_KP_Divide 0xffaf +#define IBUS_KP_0 0xffb0 +#define IBUS_KP_1 0xffb1 +#define IBUS_KP_2 0xffb2 +#define IBUS_KP_3 0xffb3 +#define IBUS_KP_4 0xffb4 +#define IBUS_KP_5 0xffb5 +#define IBUS_KP_6 0xffb6 +#define IBUS_KP_7 0xffb7 +#define IBUS_KP_8 0xffb8 +#define IBUS_KP_9 0xffb9 +#define IBUS_F1 0xffbe +#define IBUS_F2 0xffbf +#define IBUS_F3 0xffc0 +#define IBUS_F4 0xffc1 +#define IBUS_F5 0xffc2 +#define IBUS_F6 0xffc3 +#define IBUS_F7 0xffc4 +#define IBUS_F8 0xffc5 +#define IBUS_F9 0xffc6 +#define IBUS_F10 0xffc7 +#define IBUS_F11 0xffc8 +#define IBUS_L1 0xffc8 +#define IBUS_F12 0xffc9 +#define IBUS_L2 0xffc9 +#define IBUS_F13 0xffca +#define IBUS_L3 0xffca +#define IBUS_F14 0xffcb +#define IBUS_L4 0xffcb +#define IBUS_F15 0xffcc +#define IBUS_L5 0xffcc +#define IBUS_F16 0xffcd +#define IBUS_L6 0xffcd +#define IBUS_F17 0xffce +#define IBUS_L7 0xffce +#define IBUS_F18 0xffcf +#define IBUS_L8 0xffcf +#define IBUS_F19 0xffd0 +#define IBUS_L9 0xffd0 +#define IBUS_F20 0xffd1 +#define IBUS_L10 0xffd1 +#define IBUS_F21 0xffd2 +#define IBUS_R1 0xffd2 +#define IBUS_F22 0xffd3 +#define IBUS_R2 0xffd3 +#define IBUS_F23 0xffd4 +#define IBUS_R3 0xffd4 +#define IBUS_F24 0xffd5 +#define IBUS_R4 0xffd5 +#define IBUS_F25 0xffd6 +#define IBUS_R5 0xffd6 +#define IBUS_F26 0xffd7 +#define IBUS_R6 0xffd7 +#define IBUS_F27 0xffd8 +#define IBUS_R7 0xffd8 +#define IBUS_F28 0xffd9 +#define IBUS_R8 0xffd9 +#define IBUS_F29 0xffda +#define IBUS_R9 0xffda +#define IBUS_F30 0xffdb +#define IBUS_R10 0xffdb +#define IBUS_F31 0xffdc +#define IBUS_R11 0xffdc +#define IBUS_F32 0xffdd +#define IBUS_R12 0xffdd +#define IBUS_F33 0xffde +#define IBUS_R13 0xffde +#define IBUS_F34 0xffdf +#define IBUS_R14 0xffdf +#define IBUS_F35 0xffe0 +#define IBUS_R15 0xffe0 +#define IBUS_Shift_L 0xffe1 +#define IBUS_Shift_R 0xffe2 +#define IBUS_Control_L 0xffe3 +#define IBUS_Control_R 0xffe4 +#define IBUS_Caps_Lock 0xffe5 +#define IBUS_Shift_Lock 0xffe6 +#define IBUS_Meta_L 0xffe7 +#define IBUS_Meta_R 0xffe8 +#define IBUS_Alt_L 0xffe9 +#define IBUS_Alt_R 0xffea +#define IBUS_Super_L 0xffeb +#define IBUS_Super_R 0xffec +#define IBUS_Hyper_L 0xffed +#define IBUS_Hyper_R 0xffee +#define IBUS_ISO_Lock 0xfe01 +#define IBUS_ISO_Level2_Latch 0xfe02 +#define IBUS_ISO_Level3_Shift 0xfe03 +#define IBUS_ISO_Level3_Latch 0xfe04 +#define IBUS_ISO_Level3_Lock 0xfe05 +#define IBUS_ISO_Level5_Shift 0xfe11 +#define IBUS_ISO_Level5_Latch 0xfe12 +#define IBUS_ISO_Level5_Lock 0xfe13 +#define IBUS_ISO_Group_Shift 0xff7e +#define IBUS_ISO_Group_Latch 0xfe06 +#define IBUS_ISO_Group_Lock 0xfe07 +#define IBUS_ISO_Next_Group 0xfe08 +#define IBUS_ISO_Next_Group_Lock 0xfe09 +#define IBUS_ISO_Prev_Group 0xfe0a +#define IBUS_ISO_Prev_Group_Lock 0xfe0b +#define IBUS_ISO_First_Group 0xfe0c +#define IBUS_ISO_First_Group_Lock 0xfe0d +#define IBUS_ISO_Last_Group 0xfe0e +#define IBUS_ISO_Last_Group_Lock 0xfe0f +#define IBUS_ISO_Left_Tab 0xfe20 +#define IBUS_ISO_Move_Line_Up 0xfe21 +#define IBUS_ISO_Move_Line_Down 0xfe22 +#define IBUS_ISO_Partial_Line_Up 0xfe23 +#define IBUS_ISO_Partial_Line_Down 0xfe24 +#define IBUS_ISO_Partial_Space_Left 0xfe25 +#define IBUS_ISO_Partial_Space_Right 0xfe26 +#define IBUS_ISO_Set_Margin_Left 0xfe27 +#define IBUS_ISO_Set_Margin_Right 0xfe28 +#define IBUS_ISO_Release_Margin_Left 0xfe29 +#define IBUS_ISO_Release_Margin_Right 0xfe2a +#define IBUS_ISO_Release_Both_Margins 0xfe2b +#define IBUS_ISO_Fast_Cursor_Left 0xfe2c +#define IBUS_ISO_Fast_Cursor_Right 0xfe2d +#define IBUS_ISO_Fast_Cursor_Up 0xfe2e +#define IBUS_ISO_Fast_Cursor_Down 0xfe2f +#define IBUS_ISO_Continuous_Underline 0xfe30 +#define IBUS_ISO_Discontinuous_Underline 0xfe31 +#define IBUS_ISO_Emphasize 0xfe32 +#define IBUS_ISO_Center_Object 0xfe33 +#define IBUS_ISO_Enter 0xfe34 +#define IBUS_dead_grave 0xfe50 +#define IBUS_dead_acute 0xfe51 +#define IBUS_dead_circumflex 0xfe52 +#define IBUS_dead_tilde 0xfe53 +#define IBUS_dead_perispomeni 0xfe53 +#define IBUS_dead_macron 0xfe54 +#define IBUS_dead_breve 0xfe55 +#define IBUS_dead_abovedot 0xfe56 +#define IBUS_dead_diaeresis 0xfe57 +#define IBUS_dead_abovering 0xfe58 +#define IBUS_dead_doubleacute 0xfe59 +#define IBUS_dead_caron 0xfe5a +#define IBUS_dead_cedilla 0xfe5b +#define IBUS_dead_ogonek 0xfe5c +#define IBUS_dead_iota 0xfe5d +#define IBUS_dead_voiced_sound 0xfe5e +#define IBUS_dead_semivoiced_sound 0xfe5f +#define IBUS_dead_belowdot 0xfe60 +#define IBUS_dead_hook 0xfe61 +#define IBUS_dead_horn 0xfe62 +#define IBUS_dead_stroke 0xfe63 +#define IBUS_dead_abovecomma 0xfe64 +#define IBUS_dead_psili 0xfe64 +#define IBUS_dead_abovereversedcomma 0xfe65 +#define IBUS_dead_dasia 0xfe65 +#define IBUS_dead_belowring 0xfe67 +#define IBUS_dead_belowmacron 0xfe68 +#define IBUS_dead_belowcircumflex 0xfe69 +#define IBUS_dead_belowtilde 0xfe6a +#define IBUS_dead_belowbreve 0xfe6b +#define IBUS_dead_belowdiaeresis 0xfe6c +#define IBUS_First_Virtual_Screen 0xfed0 +#define IBUS_Prev_Virtual_Screen 0xfed1 +#define IBUS_Next_Virtual_Screen 0xfed2 +#define IBUS_Last_Virtual_Screen 0xfed4 +#define IBUS_Terminate_Server 0xfed5 +#define IBUS_AccessX_Enable 0xfe70 +#define IBUS_AccessX_Feedback_Enable 0xfe71 +#define IBUS_RepeatKeys_Enable 0xfe72 +#define IBUS_SlowKeys_Enable 0xfe73 +#define IBUS_BounceKeys_Enable 0xfe74 +#define IBUS_StickyKeys_Enable 0xfe75 +#define IBUS_MouseKeys_Enable 0xfe76 +#define IBUS_MouseKeys_Accel_Enable 0xfe77 +#define IBUS_Overlay1_Enable 0xfe78 +#define IBUS_Overlay2_Enable 0xfe79 +#define IBUS_AudibleBell_Enable 0xfe7a +#define IBUS_Pointer_Left 0xfee0 +#define IBUS_Pointer_Right 0xfee1 +#define IBUS_Pointer_Up 0xfee2 +#define IBUS_Pointer_Down 0xfee3 +#define IBUS_Pointer_UpLeft 0xfee4 +#define IBUS_Pointer_UpRight 0xfee5 +#define IBUS_Pointer_DownLeft 0xfee6 +#define IBUS_Pointer_DownRight 0xfee7 +#define IBUS_Pointer_Button_Dflt 0xfee8 +#define IBUS_Pointer_Button1 0xfee9 +#define IBUS_Pointer_Button2 0xfeea +#define IBUS_Pointer_Button3 0xfeeb +#define IBUS_Pointer_Button4 0xfeec +#define IBUS_Pointer_Button5 0xfeed +#define IBUS_Pointer_DblClick_Dflt 0xfeee +#define IBUS_Pointer_DblClick1 0xfeef +#define IBUS_Pointer_DblClick2 0xfef0 +#define IBUS_Pointer_DblClick3 0xfef1 +#define IBUS_Pointer_DblClick4 0xfef2 +#define IBUS_Pointer_DblClick5 0xfef3 +#define IBUS_Pointer_Drag_Dflt 0xfef4 +#define IBUS_Pointer_Drag1 0xfef5 +#define IBUS_Pointer_Drag2 0xfef6 +#define IBUS_Pointer_Drag3 0xfef7 +#define IBUS_Pointer_Drag4 0xfef8 +#define IBUS_Pointer_Drag5 0xfefd +#define IBUS_Pointer_EnableKeys 0xfef9 +#define IBUS_Pointer_Accelerate 0xfefa +#define IBUS_Pointer_DfltBtnNext 0xfefb +#define IBUS_Pointer_DfltBtnPrev 0xfefc +#define IBUS_3270_Duplicate 0xfd01 +#define IBUS_3270_FieldMark 0xfd02 +#define IBUS_3270_Right2 0xfd03 +#define IBUS_3270_Left2 0xfd04 +#define IBUS_3270_BackTab 0xfd05 +#define IBUS_3270_EraseEOF 0xfd06 +#define IBUS_3270_EraseInput 0xfd07 +#define IBUS_3270_Reset 0xfd08 +#define IBUS_3270_Quit 0xfd09 +#define IBUS_3270_PA1 0xfd0a +#define IBUS_3270_PA2 0xfd0b +#define IBUS_3270_PA3 0xfd0c +#define IBUS_3270_Test 0xfd0d +#define IBUS_3270_Attn 0xfd0e +#define IBUS_3270_CursorBlink 0xfd0f +#define IBUS_3270_AltCursor 0xfd10 +#define IBUS_3270_KeyClick 0xfd11 +#define IBUS_3270_Jump 0xfd12 +#define IBUS_3270_Ident 0xfd13 +#define IBUS_3270_Rule 0xfd14 +#define IBUS_3270_Copy 0xfd15 +#define IBUS_3270_Play 0xfd16 +#define IBUS_3270_Setup 0xfd17 +#define IBUS_3270_Record 0xfd18 +#define IBUS_3270_ChangeScreen 0xfd19 +#define IBUS_3270_DeleteWord 0xfd1a +#define IBUS_3270_ExSelect 0xfd1b +#define IBUS_3270_CursorSelect 0xfd1c +#define IBUS_3270_PrintScreen 0xfd1d +#define IBUS_3270_Enter 0xfd1e +#define IBUS_space 0x020 +#define IBUS_exclam 0x021 +#define IBUS_quotedbl 0x022 +#define IBUS_numbersign 0x023 +#define IBUS_dollar 0x024 +#define IBUS_percent 0x025 +#define IBUS_ampersand 0x026 +#define IBUS_apostrophe 0x027 +#define IBUS_quoteright 0x027 +#define IBUS_parenleft 0x028 +#define IBUS_parenright 0x029 +#define IBUS_asterisk 0x02a +#define IBUS_plus 0x02b +#define IBUS_comma 0x02c +#define IBUS_minus 0x02d +#define IBUS_period 0x02e +#define IBUS_slash 0x02f +#define IBUS_0 0x030 +#define IBUS_1 0x031 +#define IBUS_2 0x032 +#define IBUS_3 0x033 +#define IBUS_4 0x034 +#define IBUS_5 0x035 +#define IBUS_6 0x036 +#define IBUS_7 0x037 +#define IBUS_8 0x038 +#define IBUS_9 0x039 +#define IBUS_colon 0x03a +#define IBUS_semicolon 0x03b +#define IBUS_less 0x03c +#define IBUS_equal 0x03d +#define IBUS_greater 0x03e +#define IBUS_question 0x03f +#define IBUS_at 0x040 +#define IBUS_A 0x041 +#define IBUS_B 0x042 +#define IBUS_C 0x043 +#define IBUS_D 0x044 +#define IBUS_E 0x045 +#define IBUS_F 0x046 +#define IBUS_G 0x047 +#define IBUS_H 0x048 +#define IBUS_I 0x049 +#define IBUS_J 0x04a +#define IBUS_K 0x04b +#define IBUS_L 0x04c +#define IBUS_M 0x04d +#define IBUS_N 0x04e +#define IBUS_O 0x04f +#define IBUS_P 0x050 +#define IBUS_Q 0x051 +#define IBUS_R 0x052 +#define IBUS_S 0x053 +#define IBUS_T 0x054 +#define IBUS_U 0x055 +#define IBUS_V 0x056 +#define IBUS_W 0x057 +#define IBUS_X 0x058 +#define IBUS_Y 0x059 +#define IBUS_Z 0x05a +#define IBUS_bracketleft 0x05b +#define IBUS_backslash 0x05c +#define IBUS_bracketright 0x05d +#define IBUS_asciicircum 0x05e +#define IBUS_underscore 0x05f +#define IBUS_grave 0x060 +#define IBUS_quoteleft 0x060 +#define IBUS_a 0x061 +#define IBUS_b 0x062 +#define IBUS_c 0x063 +#define IBUS_d 0x064 +#define IBUS_e 0x065 +#define IBUS_f 0x066 +#define IBUS_g 0x067 +#define IBUS_h 0x068 +#define IBUS_i 0x069 +#define IBUS_j 0x06a +#define IBUS_k 0x06b +#define IBUS_l 0x06c +#define IBUS_m 0x06d +#define IBUS_n 0x06e +#define IBUS_o 0x06f +#define IBUS_p 0x070 +#define IBUS_q 0x071 +#define IBUS_r 0x072 +#define IBUS_s 0x073 +#define IBUS_t 0x074 +#define IBUS_u 0x075 +#define IBUS_v 0x076 +#define IBUS_w 0x077 +#define IBUS_x 0x078 +#define IBUS_y 0x079 +#define IBUS_z 0x07a +#define IBUS_braceleft 0x07b +#define IBUS_bar 0x07c +#define IBUS_braceright 0x07d +#define IBUS_asciitilde 0x07e +#define IBUS_nobreakspace 0x0a0 +#define IBUS_exclamdown 0x0a1 +#define IBUS_cent 0x0a2 +#define IBUS_sterling 0x0a3 +#define IBUS_currency 0x0a4 +#define IBUS_yen 0x0a5 +#define IBUS_brokenbar 0x0a6 +#define IBUS_section 0x0a7 +#define IBUS_diaeresis 0x0a8 +#define IBUS_copyright 0x0a9 +#define IBUS_ordfeminine 0x0aa +#define IBUS_guillemotleft 0x0ab +#define IBUS_notsign 0x0ac +#define IBUS_hyphen 0x0ad +#define IBUS_registered 0x0ae +#define IBUS_macron 0x0af +#define IBUS_degree 0x0b0 +#define IBUS_plusminus 0x0b1 +#define IBUS_twosuperior 0x0b2 +#define IBUS_threesuperior 0x0b3 +#define IBUS_acute 0x0b4 +#define IBUS_mu 0x0b5 +#define IBUS_paragraph 0x0b6 +#define IBUS_periodcentered 0x0b7 +#define IBUS_cedilla 0x0b8 +#define IBUS_onesuperior 0x0b9 +#define IBUS_masculine 0x0ba +#define IBUS_guillemotright 0x0bb +#define IBUS_onequarter 0x0bc +#define IBUS_onehalf 0x0bd +#define IBUS_threequarters 0x0be +#define IBUS_questiondown 0x0bf +#define IBUS_Agrave 0x0c0 +#define IBUS_Aacute 0x0c1 +#define IBUS_Acircumflex 0x0c2 +#define IBUS_Atilde 0x0c3 +#define IBUS_Adiaeresis 0x0c4 +#define IBUS_Aring 0x0c5 +#define IBUS_AE 0x0c6 +#define IBUS_Ccedilla 0x0c7 +#define IBUS_Egrave 0x0c8 +#define IBUS_Eacute 0x0c9 +#define IBUS_Ecircumflex 0x0ca +#define IBUS_Ediaeresis 0x0cb +#define IBUS_Igrave 0x0cc +#define IBUS_Iacute 0x0cd +#define IBUS_Icircumflex 0x0ce +#define IBUS_Idiaeresis 0x0cf +#define IBUS_ETH 0x0d0 +#define IBUS_Eth 0x0d0 +#define IBUS_Ntilde 0x0d1 +#define IBUS_Ograve 0x0d2 +#define IBUS_Oacute 0x0d3 +#define IBUS_Ocircumflex 0x0d4 +#define IBUS_Otilde 0x0d5 +#define IBUS_Odiaeresis 0x0d6 +#define IBUS_multiply 0x0d7 +#define IBUS_Oslash 0x0d8 +#define IBUS_Ooblique 0x0d8 +#define IBUS_Ugrave 0x0d9 +#define IBUS_Uacute 0x0da +#define IBUS_Ucircumflex 0x0db +#define IBUS_Udiaeresis 0x0dc +#define IBUS_Yacute 0x0dd +#define IBUS_THORN 0x0de +#define IBUS_Thorn 0x0de +#define IBUS_ssharp 0x0df +#define IBUS_agrave 0x0e0 +#define IBUS_aacute 0x0e1 +#define IBUS_acircumflex 0x0e2 +#define IBUS_atilde 0x0e3 +#define IBUS_adiaeresis 0x0e4 +#define IBUS_aring 0x0e5 +#define IBUS_ae 0x0e6 +#define IBUS_ccedilla 0x0e7 +#define IBUS_egrave 0x0e8 +#define IBUS_eacute 0x0e9 +#define IBUS_ecircumflex 0x0ea +#define IBUS_ediaeresis 0x0eb +#define IBUS_igrave 0x0ec +#define IBUS_iacute 0x0ed +#define IBUS_icircumflex 0x0ee +#define IBUS_idiaeresis 0x0ef +#define IBUS_eth 0x0f0 +#define IBUS_ntilde 0x0f1 +#define IBUS_ograve 0x0f2 +#define IBUS_oacute 0x0f3 +#define IBUS_ocircumflex 0x0f4 +#define IBUS_otilde 0x0f5 +#define IBUS_odiaeresis 0x0f6 +#define IBUS_division 0x0f7 +#define IBUS_oslash 0x0f8 +#define IBUS_ooblique 0x0f8 +#define IBUS_ugrave 0x0f9 +#define IBUS_uacute 0x0fa +#define IBUS_ucircumflex 0x0fb +#define IBUS_udiaeresis 0x0fc +#define IBUS_yacute 0x0fd +#define IBUS_thorn 0x0fe +#define IBUS_ydiaeresis 0x0ff +#define IBUS_Aogonek 0x1a1 +#define IBUS_breve 0x1a2 +#define IBUS_Lstroke 0x1a3 +#define IBUS_Lcaron 0x1a5 +#define IBUS_Sacute 0x1a6 +#define IBUS_Scaron 0x1a9 +#define IBUS_Scedilla 0x1aa +#define IBUS_Tcaron 0x1ab +#define IBUS_Zacute 0x1ac +#define IBUS_Zcaron 0x1ae +#define IBUS_Zabovedot 0x1af +#define IBUS_aogonek 0x1b1 +#define IBUS_ogonek 0x1b2 +#define IBUS_lstroke 0x1b3 +#define IBUS_lcaron 0x1b5 +#define IBUS_sacute 0x1b6 +#define IBUS_caron 0x1b7 +#define IBUS_scaron 0x1b9 +#define IBUS_scedilla 0x1ba +#define IBUS_tcaron 0x1bb +#define IBUS_zacute 0x1bc +#define IBUS_doubleacute 0x1bd +#define IBUS_zcaron 0x1be +#define IBUS_zabovedot 0x1bf +#define IBUS_Racute 0x1c0 +#define IBUS_Abreve 0x1c3 +#define IBUS_Lacute 0x1c5 +#define IBUS_Cacute 0x1c6 +#define IBUS_Ccaron 0x1c8 +#define IBUS_Eogonek 0x1ca +#define IBUS_Ecaron 0x1cc +#define IBUS_Dcaron 0x1cf +#define IBUS_Dstroke 0x1d0 +#define IBUS_Nacute 0x1d1 +#define IBUS_Ncaron 0x1d2 +#define IBUS_Odoubleacute 0x1d5 +#define IBUS_Rcaron 0x1d8 +#define IBUS_Uring 0x1d9 +#define IBUS_Udoubleacute 0x1db +#define IBUS_Tcedilla 0x1de +#define IBUS_racute 0x1e0 +#define IBUS_abreve 0x1e3 +#define IBUS_lacute 0x1e5 +#define IBUS_cacute 0x1e6 +#define IBUS_ccaron 0x1e8 +#define IBUS_eogonek 0x1ea +#define IBUS_ecaron 0x1ec +#define IBUS_dcaron 0x1ef +#define IBUS_dstroke 0x1f0 +#define IBUS_nacute 0x1f1 +#define IBUS_ncaron 0x1f2 +#define IBUS_odoubleacute 0x1f5 +#define IBUS_udoubleacute 0x1fb +#define IBUS_rcaron 0x1f8 +#define IBUS_uring 0x1f9 +#define IBUS_tcedilla 0x1fe +#define IBUS_abovedot 0x1ff +#define IBUS_Hstroke 0x2a1 +#define IBUS_Hcircumflex 0x2a6 +#define IBUS_Iabovedot 0x2a9 +#define IBUS_Gbreve 0x2ab +#define IBUS_Jcircumflex 0x2ac +#define IBUS_hstroke 0x2b1 +#define IBUS_hcircumflex 0x2b6 +#define IBUS_idotless 0x2b9 +#define IBUS_gbreve 0x2bb +#define IBUS_jcircumflex 0x2bc +#define IBUS_Cabovedot 0x2c5 +#define IBUS_Ccircumflex 0x2c6 +#define IBUS_Gabovedot 0x2d5 +#define IBUS_Gcircumflex 0x2d8 +#define IBUS_Ubreve 0x2dd +#define IBUS_Scircumflex 0x2de +#define IBUS_cabovedot 0x2e5 +#define IBUS_ccircumflex 0x2e6 +#define IBUS_gabovedot 0x2f5 +#define IBUS_gcircumflex 0x2f8 +#define IBUS_ubreve 0x2fd +#define IBUS_scircumflex 0x2fe +#define IBUS_kra 0x3a2 +#define IBUS_kappa 0x3a2 +#define IBUS_Rcedilla 0x3a3 +#define IBUS_Itilde 0x3a5 +#define IBUS_Lcedilla 0x3a6 +#define IBUS_Emacron 0x3aa +#define IBUS_Gcedilla 0x3ab +#define IBUS_Tslash 0x3ac +#define IBUS_rcedilla 0x3b3 +#define IBUS_itilde 0x3b5 +#define IBUS_lcedilla 0x3b6 +#define IBUS_emacron 0x3ba +#define IBUS_gcedilla 0x3bb +#define IBUS_tslash 0x3bc +#define IBUS_ENG 0x3bd +#define IBUS_eng 0x3bf +#define IBUS_Amacron 0x3c0 +#define IBUS_Iogonek 0x3c7 +#define IBUS_Eabovedot 0x3cc +#define IBUS_Imacron 0x3cf +#define IBUS_Ncedilla 0x3d1 +#define IBUS_Omacron 0x3d2 +#define IBUS_Kcedilla 0x3d3 +#define IBUS_Uogonek 0x3d9 +#define IBUS_Utilde 0x3dd +#define IBUS_Umacron 0x3de +#define IBUS_amacron 0x3e0 +#define IBUS_iogonek 0x3e7 +#define IBUS_eabovedot 0x3ec +#define IBUS_imacron 0x3ef +#define IBUS_ncedilla 0x3f1 +#define IBUS_omacron 0x3f2 +#define IBUS_kcedilla 0x3f3 +#define IBUS_uogonek 0x3f9 +#define IBUS_utilde 0x3fd +#define IBUS_umacron 0x3fe +#define IBUS_Babovedot 0x1001e02 +#define IBUS_babovedot 0x1001e03 +#define IBUS_Dabovedot 0x1001e0a +#define IBUS_Wgrave 0x1001e80 +#define IBUS_Wacute 0x1001e82 +#define IBUS_dabovedot 0x1001e0b +#define IBUS_Ygrave 0x1001ef2 +#define IBUS_Fabovedot 0x1001e1e +#define IBUS_fabovedot 0x1001e1f +#define IBUS_Mabovedot 0x1001e40 +#define IBUS_mabovedot 0x1001e41 +#define IBUS_Pabovedot 0x1001e56 +#define IBUS_wgrave 0x1001e81 +#define IBUS_pabovedot 0x1001e57 +#define IBUS_wacute 0x1001e83 +#define IBUS_Sabovedot 0x1001e60 +#define IBUS_ygrave 0x1001ef3 +#define IBUS_Wdiaeresis 0x1001e84 +#define IBUS_wdiaeresis 0x1001e85 +#define IBUS_sabovedot 0x1001e61 +#define IBUS_Wcircumflex 0x1000174 +#define IBUS_Tabovedot 0x1001e6a +#define IBUS_Ycircumflex 0x1000176 +#define IBUS_wcircumflex 0x1000175 +#define IBUS_tabovedot 0x1001e6b +#define IBUS_ycircumflex 0x1000177 +#define IBUS_OE 0x13bc +#define IBUS_oe 0x13bd +#define IBUS_Ydiaeresis 0x13be +#define IBUS_overline 0x47e +#define IBUS_kana_fullstop 0x4a1 +#define IBUS_kana_openingbracket 0x4a2 +#define IBUS_kana_closingbracket 0x4a3 +#define IBUS_kana_comma 0x4a4 +#define IBUS_kana_conjunctive 0x4a5 +#define IBUS_kana_middledot 0x4a5 +#define IBUS_kana_WO 0x4a6 +#define IBUS_kana_a 0x4a7 +#define IBUS_kana_i 0x4a8 +#define IBUS_kana_u 0x4a9 +#define IBUS_kana_e 0x4aa +#define IBUS_kana_o 0x4ab +#define IBUS_kana_ya 0x4ac +#define IBUS_kana_yu 0x4ad +#define IBUS_kana_yo 0x4ae +#define IBUS_kana_tsu 0x4af +#define IBUS_kana_tu 0x4af +#define IBUS_prolongedsound 0x4b0 +#define IBUS_kana_A 0x4b1 +#define IBUS_kana_I 0x4b2 +#define IBUS_kana_U 0x4b3 +#define IBUS_kana_E 0x4b4 +#define IBUS_kana_O 0x4b5 +#define IBUS_kana_KA 0x4b6 +#define IBUS_kana_KI 0x4b7 +#define IBUS_kana_KU 0x4b8 +#define IBUS_kana_KE 0x4b9 +#define IBUS_kana_KO 0x4ba +#define IBUS_kana_SA 0x4bb +#define IBUS_kana_SHI 0x4bc +#define IBUS_kana_SU 0x4bd +#define IBUS_kana_SE 0x4be +#define IBUS_kana_SO 0x4bf +#define IBUS_kana_TA 0x4c0 +#define IBUS_kana_CHI 0x4c1 +#define IBUS_kana_TI 0x4c1 +#define IBUS_kana_TSU 0x4c2 +#define IBUS_kana_TU 0x4c2 +#define IBUS_kana_TE 0x4c3 +#define IBUS_kana_TO 0x4c4 +#define IBUS_kana_NA 0x4c5 +#define IBUS_kana_NI 0x4c6 +#define IBUS_kana_NU 0x4c7 +#define IBUS_kana_NE 0x4c8 +#define IBUS_kana_NO 0x4c9 +#define IBUS_kana_HA 0x4ca +#define IBUS_kana_HI 0x4cb +#define IBUS_kana_FU 0x4cc +#define IBUS_kana_HU 0x4cc +#define IBUS_kana_HE 0x4cd +#define IBUS_kana_HO 0x4ce +#define IBUS_kana_MA 0x4cf +#define IBUS_kana_MI 0x4d0 +#define IBUS_kana_MU 0x4d1 +#define IBUS_kana_ME 0x4d2 +#define IBUS_kana_MO 0x4d3 +#define IBUS_kana_YA 0x4d4 +#define IBUS_kana_YU 0x4d5 +#define IBUS_kana_YO 0x4d6 +#define IBUS_kana_RA 0x4d7 +#define IBUS_kana_RI 0x4d8 +#define IBUS_kana_RU 0x4d9 +#define IBUS_kana_RE 0x4da +#define IBUS_kana_RO 0x4db +#define IBUS_kana_WA 0x4dc +#define IBUS_kana_N 0x4dd +#define IBUS_voicedsound 0x4de +#define IBUS_semivoicedsound 0x4df +#define IBUS_kana_switch 0xff7e +#define IBUS_Farsi_0 0x10006f0 +#define IBUS_Farsi_1 0x10006f1 +#define IBUS_Farsi_2 0x10006f2 +#define IBUS_Farsi_3 0x10006f3 +#define IBUS_Farsi_4 0x10006f4 +#define IBUS_Farsi_5 0x10006f5 +#define IBUS_Farsi_6 0x10006f6 +#define IBUS_Farsi_7 0x10006f7 +#define IBUS_Farsi_8 0x10006f8 +#define IBUS_Farsi_9 0x10006f9 +#define IBUS_Arabic_percent 0x100066a +#define IBUS_Arabic_superscript_alef 0x1000670 +#define IBUS_Arabic_tteh 0x1000679 +#define IBUS_Arabic_peh 0x100067e +#define IBUS_Arabic_tcheh 0x1000686 +#define IBUS_Arabic_ddal 0x1000688 +#define IBUS_Arabic_rreh 0x1000691 +#define IBUS_Arabic_comma 0x5ac +#define IBUS_Arabic_fullstop 0x10006d4 +#define IBUS_Arabic_0 0x1000660 +#define IBUS_Arabic_1 0x1000661 +#define IBUS_Arabic_2 0x1000662 +#define IBUS_Arabic_3 0x1000663 +#define IBUS_Arabic_4 0x1000664 +#define IBUS_Arabic_5 0x1000665 +#define IBUS_Arabic_6 0x1000666 +#define IBUS_Arabic_7 0x1000667 +#define IBUS_Arabic_8 0x1000668 +#define IBUS_Arabic_9 0x1000669 +#define IBUS_Arabic_semicolon 0x5bb +#define IBUS_Arabic_question_mark 0x5bf +#define IBUS_Arabic_hamza 0x5c1 +#define IBUS_Arabic_maddaonalef 0x5c2 +#define IBUS_Arabic_hamzaonalef 0x5c3 +#define IBUS_Arabic_hamzaonwaw 0x5c4 +#define IBUS_Arabic_hamzaunderalef 0x5c5 +#define IBUS_Arabic_hamzaonyeh 0x5c6 +#define IBUS_Arabic_alef 0x5c7 +#define IBUS_Arabic_beh 0x5c8 +#define IBUS_Arabic_tehmarbuta 0x5c9 +#define IBUS_Arabic_teh 0x5ca +#define IBUS_Arabic_theh 0x5cb +#define IBUS_Arabic_jeem 0x5cc +#define IBUS_Arabic_hah 0x5cd +#define IBUS_Arabic_khah 0x5ce +#define IBUS_Arabic_dal 0x5cf +#define IBUS_Arabic_thal 0x5d0 +#define IBUS_Arabic_ra 0x5d1 +#define IBUS_Arabic_zain 0x5d2 +#define IBUS_Arabic_seen 0x5d3 +#define IBUS_Arabic_sheen 0x5d4 +#define IBUS_Arabic_sad 0x5d5 +#define IBUS_Arabic_dad 0x5d6 +#define IBUS_Arabic_tah 0x5d7 +#define IBUS_Arabic_zah 0x5d8 +#define IBUS_Arabic_ain 0x5d9 +#define IBUS_Arabic_ghain 0x5da +#define IBUS_Arabic_tatweel 0x5e0 +#define IBUS_Arabic_feh 0x5e1 +#define IBUS_Arabic_qaf 0x5e2 +#define IBUS_Arabic_kaf 0x5e3 +#define IBUS_Arabic_lam 0x5e4 +#define IBUS_Arabic_meem 0x5e5 +#define IBUS_Arabic_noon 0x5e6 +#define IBUS_Arabic_ha 0x5e7 +#define IBUS_Arabic_heh 0x5e7 +#define IBUS_Arabic_waw 0x5e8 +#define IBUS_Arabic_alefmaksura 0x5e9 +#define IBUS_Arabic_yeh 0x5ea +#define IBUS_Arabic_fathatan 0x5eb +#define IBUS_Arabic_dammatan 0x5ec +#define IBUS_Arabic_kasratan 0x5ed +#define IBUS_Arabic_fatha 0x5ee +#define IBUS_Arabic_damma 0x5ef +#define IBUS_Arabic_kasra 0x5f0 +#define IBUS_Arabic_shadda 0x5f1 +#define IBUS_Arabic_sukun 0x5f2 +#define IBUS_Arabic_madda_above 0x1000653 +#define IBUS_Arabic_hamza_above 0x1000654 +#define IBUS_Arabic_hamza_below 0x1000655 +#define IBUS_Arabic_jeh 0x1000698 +#define IBUS_Arabic_veh 0x10006a4 +#define IBUS_Arabic_keheh 0x10006a9 +#define IBUS_Arabic_gaf 0x10006af +#define IBUS_Arabic_noon_ghunna 0x10006ba +#define IBUS_Arabic_heh_doachashmee 0x10006be +#define IBUS_Farsi_yeh 0x10006cc +#define IBUS_Arabic_farsi_yeh 0x10006cc +#define IBUS_Arabic_yeh_baree 0x10006d2 +#define IBUS_Arabic_heh_goal 0x10006c1 +#define IBUS_Arabic_switch 0xff7e +#define IBUS_Cyrillic_GHE_bar 0x1000492 +#define IBUS_Cyrillic_ghe_bar 0x1000493 +#define IBUS_Cyrillic_ZHE_descender 0x1000496 +#define IBUS_Cyrillic_zhe_descender 0x1000497 +#define IBUS_Cyrillic_KA_descender 0x100049a +#define IBUS_Cyrillic_ka_descender 0x100049b +#define IBUS_Cyrillic_KA_vertstroke 0x100049c +#define IBUS_Cyrillic_ka_vertstroke 0x100049d +#define IBUS_Cyrillic_EN_descender 0x10004a2 +#define IBUS_Cyrillic_en_descender 0x10004a3 +#define IBUS_Cyrillic_U_straight 0x10004ae +#define IBUS_Cyrillic_u_straight 0x10004af +#define IBUS_Cyrillic_U_straight_bar 0x10004b0 +#define IBUS_Cyrillic_u_straight_bar 0x10004b1 +#define IBUS_Cyrillic_HA_descender 0x10004b2 +#define IBUS_Cyrillic_ha_descender 0x10004b3 +#define IBUS_Cyrillic_CHE_descender 0x10004b6 +#define IBUS_Cyrillic_che_descender 0x10004b7 +#define IBUS_Cyrillic_CHE_vertstroke 0x10004b8 +#define IBUS_Cyrillic_che_vertstroke 0x10004b9 +#define IBUS_Cyrillic_SHHA 0x10004ba +#define IBUS_Cyrillic_shha 0x10004bb +#define IBUS_Cyrillic_SCHWA 0x10004d8 +#define IBUS_Cyrillic_schwa 0x10004d9 +#define IBUS_Cyrillic_I_macron 0x10004e2 +#define IBUS_Cyrillic_i_macron 0x10004e3 +#define IBUS_Cyrillic_O_bar 0x10004e8 +#define IBUS_Cyrillic_o_bar 0x10004e9 +#define IBUS_Cyrillic_U_macron 0x10004ee +#define IBUS_Cyrillic_u_macron 0x10004ef +#define IBUS_Serbian_dje 0x6a1 +#define IBUS_Macedonia_gje 0x6a2 +#define IBUS_Cyrillic_io 0x6a3 +#define IBUS_Ukrainian_ie 0x6a4 +#define IBUS_Ukranian_je 0x6a4 +#define IBUS_Macedonia_dse 0x6a5 +#define IBUS_Ukrainian_i 0x6a6 +#define IBUS_Ukranian_i 0x6a6 +#define IBUS_Ukrainian_yi 0x6a7 +#define IBUS_Ukranian_yi 0x6a7 +#define IBUS_Cyrillic_je 0x6a8 +#define IBUS_Serbian_je 0x6a8 +#define IBUS_Cyrillic_lje 0x6a9 +#define IBUS_Serbian_lje 0x6a9 +#define IBUS_Cyrillic_nje 0x6aa +#define IBUS_Serbian_nje 0x6aa +#define IBUS_Serbian_tshe 0x6ab +#define IBUS_Macedonia_kje 0x6ac +#define IBUS_Ukrainian_ghe_with_upturn 0x6ad +#define IBUS_Byelorussian_shortu 0x6ae +#define IBUS_Cyrillic_dzhe 0x6af +#define IBUS_Serbian_dze 0x6af +#define IBUS_numerosign 0x6b0 +#define IBUS_Serbian_DJE 0x6b1 +#define IBUS_Macedonia_GJE 0x6b2 +#define IBUS_Cyrillic_IO 0x6b3 +#define IBUS_Ukrainian_IE 0x6b4 +#define IBUS_Ukranian_JE 0x6b4 +#define IBUS_Macedonia_DSE 0x6b5 +#define IBUS_Ukrainian_I 0x6b6 +#define IBUS_Ukranian_I 0x6b6 +#define IBUS_Ukrainian_YI 0x6b7 +#define IBUS_Ukranian_YI 0x6b7 +#define IBUS_Cyrillic_JE 0x6b8 +#define IBUS_Serbian_JE 0x6b8 +#define IBUS_Cyrillic_LJE 0x6b9 +#define IBUS_Serbian_LJE 0x6b9 +#define IBUS_Cyrillic_NJE 0x6ba +#define IBUS_Serbian_NJE 0x6ba +#define IBUS_Serbian_TSHE 0x6bb +#define IBUS_Macedonia_KJE 0x6bc +#define IBUS_Ukrainian_GHE_WITH_UPTURN 0x6bd +#define IBUS_Byelorussian_SHORTU 0x6be +#define IBUS_Cyrillic_DZHE 0x6bf +#define IBUS_Serbian_DZE 0x6bf +#define IBUS_Cyrillic_yu 0x6c0 +#define IBUS_Cyrillic_a 0x6c1 +#define IBUS_Cyrillic_be 0x6c2 +#define IBUS_Cyrillic_tse 0x6c3 +#define IBUS_Cyrillic_de 0x6c4 +#define IBUS_Cyrillic_ie 0x6c5 +#define IBUS_Cyrillic_ef 0x6c6 +#define IBUS_Cyrillic_ghe 0x6c7 +#define IBUS_Cyrillic_ha 0x6c8 +#define IBUS_Cyrillic_i 0x6c9 +#define IBUS_Cyrillic_shorti 0x6ca +#define IBUS_Cyrillic_ka 0x6cb +#define IBUS_Cyrillic_el 0x6cc +#define IBUS_Cyrillic_em 0x6cd +#define IBUS_Cyrillic_en 0x6ce +#define IBUS_Cyrillic_o 0x6cf +#define IBUS_Cyrillic_pe 0x6d0 +#define IBUS_Cyrillic_ya 0x6d1 +#define IBUS_Cyrillic_er 0x6d2 +#define IBUS_Cyrillic_es 0x6d3 +#define IBUS_Cyrillic_te 0x6d4 +#define IBUS_Cyrillic_u 0x6d5 +#define IBUS_Cyrillic_zhe 0x6d6 +#define IBUS_Cyrillic_ve 0x6d7 +#define IBUS_Cyrillic_softsign 0x6d8 +#define IBUS_Cyrillic_yeru 0x6d9 +#define IBUS_Cyrillic_ze 0x6da +#define IBUS_Cyrillic_sha 0x6db +#define IBUS_Cyrillic_e 0x6dc +#define IBUS_Cyrillic_shcha 0x6dd +#define IBUS_Cyrillic_che 0x6de +#define IBUS_Cyrillic_hardsign 0x6df +#define IBUS_Cyrillic_YU 0x6e0 +#define IBUS_Cyrillic_A 0x6e1 +#define IBUS_Cyrillic_BE 0x6e2 +#define IBUS_Cyrillic_TSE 0x6e3 +#define IBUS_Cyrillic_DE 0x6e4 +#define IBUS_Cyrillic_IE 0x6e5 +#define IBUS_Cyrillic_EF 0x6e6 +#define IBUS_Cyrillic_GHE 0x6e7 +#define IBUS_Cyrillic_HA 0x6e8 +#define IBUS_Cyrillic_I 0x6e9 +#define IBUS_Cyrillic_SHORTI 0x6ea +#define IBUS_Cyrillic_KA 0x6eb +#define IBUS_Cyrillic_EL 0x6ec +#define IBUS_Cyrillic_EM 0x6ed +#define IBUS_Cyrillic_EN 0x6ee +#define IBUS_Cyrillic_O 0x6ef +#define IBUS_Cyrillic_PE 0x6f0 +#define IBUS_Cyrillic_YA 0x6f1 +#define IBUS_Cyrillic_ER 0x6f2 +#define IBUS_Cyrillic_ES 0x6f3 +#define IBUS_Cyrillic_TE 0x6f4 +#define IBUS_Cyrillic_U 0x6f5 +#define IBUS_Cyrillic_ZHE 0x6f6 +#define IBUS_Cyrillic_VE 0x6f7 +#define IBUS_Cyrillic_SOFTSIGN 0x6f8 +#define IBUS_Cyrillic_YERU 0x6f9 +#define IBUS_Cyrillic_ZE 0x6fa +#define IBUS_Cyrillic_SHA 0x6fb +#define IBUS_Cyrillic_E 0x6fc +#define IBUS_Cyrillic_SHCHA 0x6fd +#define IBUS_Cyrillic_CHE 0x6fe +#define IBUS_Cyrillic_HARDSIGN 0x6ff +#define IBUS_Greek_ALPHAaccent 0x7a1 +#define IBUS_Greek_EPSILONaccent 0x7a2 +#define IBUS_Greek_ETAaccent 0x7a3 +#define IBUS_Greek_IOTAaccent 0x7a4 +#define IBUS_Greek_IOTAdieresis 0x7a5 +#define IBUS_Greek_IOTAdiaeresis 0x7a5 +#define IBUS_Greek_OMICRONaccent 0x7a7 +#define IBUS_Greek_UPSILONaccent 0x7a8 +#define IBUS_Greek_UPSILONdieresis 0x7a9 +#define IBUS_Greek_OMEGAaccent 0x7ab +#define IBUS_Greek_accentdieresis 0x7ae +#define IBUS_Greek_horizbar 0x7af +#define IBUS_Greek_alphaaccent 0x7b1 +#define IBUS_Greek_epsilonaccent 0x7b2 +#define IBUS_Greek_etaaccent 0x7b3 +#define IBUS_Greek_iotaaccent 0x7b4 +#define IBUS_Greek_iotadieresis 0x7b5 +#define IBUS_Greek_iotaaccentdieresis 0x7b6 +#define IBUS_Greek_omicronaccent 0x7b7 +#define IBUS_Greek_upsilonaccent 0x7b8 +#define IBUS_Greek_upsilondieresis 0x7b9 +#define IBUS_Greek_upsilonaccentdieresis 0x7ba +#define IBUS_Greek_omegaaccent 0x7bb +#define IBUS_Greek_ALPHA 0x7c1 +#define IBUS_Greek_BETA 0x7c2 +#define IBUS_Greek_GAMMA 0x7c3 +#define IBUS_Greek_DELTA 0x7c4 +#define IBUS_Greek_EPSILON 0x7c5 +#define IBUS_Greek_ZETA 0x7c6 +#define IBUS_Greek_ETA 0x7c7 +#define IBUS_Greek_THETA 0x7c8 +#define IBUS_Greek_IOTA 0x7c9 +#define IBUS_Greek_KAPPA 0x7ca +#define IBUS_Greek_LAMDA 0x7cb +#define IBUS_Greek_LAMBDA 0x7cb +#define IBUS_Greek_MU 0x7cc +#define IBUS_Greek_NU 0x7cd +#define IBUS_Greek_XI 0x7ce +#define IBUS_Greek_OMICRON 0x7cf +#define IBUS_Greek_PI 0x7d0 +#define IBUS_Greek_RHO 0x7d1 +#define IBUS_Greek_SIGMA 0x7d2 +#define IBUS_Greek_TAU 0x7d4 +#define IBUS_Greek_UPSILON 0x7d5 +#define IBUS_Greek_PHI 0x7d6 +#define IBUS_Greek_CHI 0x7d7 +#define IBUS_Greek_PSI 0x7d8 +#define IBUS_Greek_OMEGA 0x7d9 +#define IBUS_Greek_alpha 0x7e1 +#define IBUS_Greek_beta 0x7e2 +#define IBUS_Greek_gamma 0x7e3 +#define IBUS_Greek_delta 0x7e4 +#define IBUS_Greek_epsilon 0x7e5 +#define IBUS_Greek_zeta 0x7e6 +#define IBUS_Greek_eta 0x7e7 +#define IBUS_Greek_theta 0x7e8 +#define IBUS_Greek_iota 0x7e9 +#define IBUS_Greek_kappa 0x7ea +#define IBUS_Greek_lamda 0x7eb +#define IBUS_Greek_lambda 0x7eb +#define IBUS_Greek_mu 0x7ec +#define IBUS_Greek_nu 0x7ed +#define IBUS_Greek_xi 0x7ee +#define IBUS_Greek_omicron 0x7ef +#define IBUS_Greek_pi 0x7f0 +#define IBUS_Greek_rho 0x7f1 +#define IBUS_Greek_sigma 0x7f2 +#define IBUS_Greek_finalsmallsigma 0x7f3 +#define IBUS_Greek_tau 0x7f4 +#define IBUS_Greek_upsilon 0x7f5 +#define IBUS_Greek_phi 0x7f6 +#define IBUS_Greek_chi 0x7f7 +#define IBUS_Greek_psi 0x7f8 +#define IBUS_Greek_omega 0x7f9 +#define IBUS_Greek_switch 0xff7e +#define IBUS_leftradical 0x8a1 +#define IBUS_topleftradical 0x8a2 +#define IBUS_horizconnector 0x8a3 +#define IBUS_topintegral 0x8a4 +#define IBUS_botintegral 0x8a5 +#define IBUS_vertconnector 0x8a6 +#define IBUS_topleftsqbracket 0x8a7 +#define IBUS_botleftsqbracket 0x8a8 +#define IBUS_toprightsqbracket 0x8a9 +#define IBUS_botrightsqbracket 0x8aa +#define IBUS_topleftparens 0x8ab +#define IBUS_botleftparens 0x8ac +#define IBUS_toprightparens 0x8ad +#define IBUS_botrightparens 0x8ae +#define IBUS_leftmiddlecurlybrace 0x8af +#define IBUS_rightmiddlecurlybrace 0x8b0 +#define IBUS_topleftsummation 0x8b1 +#define IBUS_botleftsummation 0x8b2 +#define IBUS_topvertsummationconnector 0x8b3 +#define IBUS_botvertsummationconnector 0x8b4 +#define IBUS_toprightsummation 0x8b5 +#define IBUS_botrightsummation 0x8b6 +#define IBUS_rightmiddlesummation 0x8b7 +#define IBUS_lessthanequal 0x8bc +#define IBUS_notequal 0x8bd +#define IBUS_greaterthanequal 0x8be +#define IBUS_integral 0x8bf +#define IBUS_therefore 0x8c0 +#define IBUS_variation 0x8c1 +#define IBUS_infinity 0x8c2 +#define IBUS_nabla 0x8c5 +#define IBUS_approximate 0x8c8 +#define IBUS_similarequal 0x8c9 +#define IBUS_ifonlyif 0x8cd +#define IBUS_implies 0x8ce +#define IBUS_identical 0x8cf +#define IBUS_radical 0x8d6 +#define IBUS_includedin 0x8da +#define IBUS_includes 0x8db +#define IBUS_intersection 0x8dc +#define IBUS_union 0x8dd +#define IBUS_logicaland 0x8de +#define IBUS_logicalor 0x8df +#define IBUS_partialderivative 0x8ef +#define IBUS_function 0x8f6 +#define IBUS_leftarrow 0x8fb +#define IBUS_uparrow 0x8fc +#define IBUS_rightarrow 0x8fd +#define IBUS_downarrow 0x8fe +#define IBUS_blank 0x9df +#define IBUS_soliddiamond 0x9e0 +#define IBUS_checkerboard 0x9e1 +#define IBUS_ht 0x9e2 +#define IBUS_ff 0x9e3 +#define IBUS_cr 0x9e4 +#define IBUS_lf 0x9e5 +#define IBUS_nl 0x9e8 +#define IBUS_vt 0x9e9 +#define IBUS_lowrightcorner 0x9ea +#define IBUS_uprightcorner 0x9eb +#define IBUS_upleftcorner 0x9ec +#define IBUS_lowleftcorner 0x9ed +#define IBUS_crossinglines 0x9ee +#define IBUS_horizlinescan1 0x9ef +#define IBUS_horizlinescan3 0x9f0 +#define IBUS_horizlinescan5 0x9f1 +#define IBUS_horizlinescan7 0x9f2 +#define IBUS_horizlinescan9 0x9f3 +#define IBUS_leftt 0x9f4 +#define IBUS_rightt 0x9f5 +#define IBUS_bott 0x9f6 +#define IBUS_topt 0x9f7 +#define IBUS_vertbar 0x9f8 +#define IBUS_emspace 0xaa1 +#define IBUS_enspace 0xaa2 +#define IBUS_em3space 0xaa3 +#define IBUS_em4space 0xaa4 +#define IBUS_digitspace 0xaa5 +#define IBUS_punctspace 0xaa6 +#define IBUS_thinspace 0xaa7 +#define IBUS_hairspace 0xaa8 +#define IBUS_emdash 0xaa9 +#define IBUS_endash 0xaaa +#define IBUS_signifblank 0xaac +#define IBUS_ellipsis 0xaae +#define IBUS_doubbaselinedot 0xaaf +#define IBUS_onethird 0xab0 +#define IBUS_twothirds 0xab1 +#define IBUS_onefifth 0xab2 +#define IBUS_twofifths 0xab3 +#define IBUS_threefifths 0xab4 +#define IBUS_fourfifths 0xab5 +#define IBUS_onesixth 0xab6 +#define IBUS_fivesixths 0xab7 +#define IBUS_careof 0xab8 +#define IBUS_figdash 0xabb +#define IBUS_leftanglebracket 0xabc +#define IBUS_decimalpoint 0xabd +#define IBUS_rightanglebracket 0xabe +#define IBUS_marker 0xabf +#define IBUS_oneeighth 0xac3 +#define IBUS_threeeighths 0xac4 +#define IBUS_fiveeighths 0xac5 +#define IBUS_seveneighths 0xac6 +#define IBUS_trademark 0xac9 +#define IBUS_signaturemark 0xaca +#define IBUS_trademarkincircle 0xacb +#define IBUS_leftopentriangle 0xacc +#define IBUS_rightopentriangle 0xacd +#define IBUS_emopencircle 0xace +#define IBUS_emopenrectangle 0xacf +#define IBUS_leftsinglequotemark 0xad0 +#define IBUS_rightsinglequotemark 0xad1 +#define IBUS_leftdoublequotemark 0xad2 +#define IBUS_rightdoublequotemark 0xad3 +#define IBUS_prescription 0xad4 +#define IBUS_minutes 0xad6 +#define IBUS_seconds 0xad7 +#define IBUS_latincross 0xad9 +#define IBUS_hexagram 0xada +#define IBUS_filledrectbullet 0xadb +#define IBUS_filledlefttribullet 0xadc +#define IBUS_filledrighttribullet 0xadd +#define IBUS_emfilledcircle 0xade +#define IBUS_emfilledrect 0xadf +#define IBUS_enopencircbullet 0xae0 +#define IBUS_enopensquarebullet 0xae1 +#define IBUS_openrectbullet 0xae2 +#define IBUS_opentribulletup 0xae3 +#define IBUS_opentribulletdown 0xae4 +#define IBUS_openstar 0xae5 +#define IBUS_enfilledcircbullet 0xae6 +#define IBUS_enfilledsqbullet 0xae7 +#define IBUS_filledtribulletup 0xae8 +#define IBUS_filledtribulletdown 0xae9 +#define IBUS_leftpointer 0xaea +#define IBUS_rightpointer 0xaeb +#define IBUS_club 0xaec +#define IBUS_diamond 0xaed +#define IBUS_heart 0xaee +#define IBUS_maltesecross 0xaf0 +#define IBUS_dagger 0xaf1 +#define IBUS_doubledagger 0xaf2 +#define IBUS_checkmark 0xaf3 +#define IBUS_ballotcross 0xaf4 +#define IBUS_musicalsharp 0xaf5 +#define IBUS_musicalflat 0xaf6 +#define IBUS_malesymbol 0xaf7 +#define IBUS_femalesymbol 0xaf8 +#define IBUS_telephone 0xaf9 +#define IBUS_telephonerecorder 0xafa +#define IBUS_phonographcopyright 0xafb +#define IBUS_caret 0xafc +#define IBUS_singlelowquotemark 0xafd +#define IBUS_doublelowquotemark 0xafe +#define IBUS_cursor 0xaff +#define IBUS_leftcaret 0xba3 +#define IBUS_rightcaret 0xba6 +#define IBUS_downcaret 0xba8 +#define IBUS_upcaret 0xba9 +#define IBUS_overbar 0xbc0 +#define IBUS_downtack 0xbc2 +#define IBUS_upshoe 0xbc3 +#define IBUS_downstile 0xbc4 +#define IBUS_underbar 0xbc6 +#define IBUS_jot 0xbca +#define IBUS_quad 0xbcc +#define IBUS_uptack 0xbce +#define IBUS_circle 0xbcf +#define IBUS_upstile 0xbd3 +#define IBUS_downshoe 0xbd6 +#define IBUS_rightshoe 0xbd8 +#define IBUS_leftshoe 0xbda +#define IBUS_lefttack 0xbdc +#define IBUS_righttack 0xbfc +#define IBUS_hebrew_doublelowline 0xcdf +#define IBUS_hebrew_aleph 0xce0 +#define IBUS_hebrew_bet 0xce1 +#define IBUS_hebrew_beth 0xce1 +#define IBUS_hebrew_gimel 0xce2 +#define IBUS_hebrew_gimmel 0xce2 +#define IBUS_hebrew_dalet 0xce3 +#define IBUS_hebrew_daleth 0xce3 +#define IBUS_hebrew_he 0xce4 +#define IBUS_hebrew_waw 0xce5 +#define IBUS_hebrew_zain 0xce6 +#define IBUS_hebrew_zayin 0xce6 +#define IBUS_hebrew_chet 0xce7 +#define IBUS_hebrew_het 0xce7 +#define IBUS_hebrew_tet 0xce8 +#define IBUS_hebrew_teth 0xce8 +#define IBUS_hebrew_yod 0xce9 +#define IBUS_hebrew_finalkaph 0xcea +#define IBUS_hebrew_kaph 0xceb +#define IBUS_hebrew_lamed 0xcec +#define IBUS_hebrew_finalmem 0xced +#define IBUS_hebrew_mem 0xcee +#define IBUS_hebrew_finalnun 0xcef +#define IBUS_hebrew_nun 0xcf0 +#define IBUS_hebrew_samech 0xcf1 +#define IBUS_hebrew_samekh 0xcf1 +#define IBUS_hebrew_ayin 0xcf2 +#define IBUS_hebrew_finalpe 0xcf3 +#define IBUS_hebrew_pe 0xcf4 +#define IBUS_hebrew_finalzade 0xcf5 +#define IBUS_hebrew_finalzadi 0xcf5 +#define IBUS_hebrew_zade 0xcf6 +#define IBUS_hebrew_zadi 0xcf6 +#define IBUS_hebrew_qoph 0xcf7 +#define IBUS_hebrew_kuf 0xcf7 +#define IBUS_hebrew_resh 0xcf8 +#define IBUS_hebrew_shin 0xcf9 +#define IBUS_hebrew_taw 0xcfa +#define IBUS_hebrew_taf 0xcfa +#define IBUS_Hebrew_switch 0xff7e +#define IBUS_Thai_kokai 0xda1 +#define IBUS_Thai_khokhai 0xda2 +#define IBUS_Thai_khokhuat 0xda3 +#define IBUS_Thai_khokhwai 0xda4 +#define IBUS_Thai_khokhon 0xda5 +#define IBUS_Thai_khorakhang 0xda6 +#define IBUS_Thai_ngongu 0xda7 +#define IBUS_Thai_chochan 0xda8 +#define IBUS_Thai_choching 0xda9 +#define IBUS_Thai_chochang 0xdaa +#define IBUS_Thai_soso 0xdab +#define IBUS_Thai_chochoe 0xdac +#define IBUS_Thai_yoying 0xdad +#define IBUS_Thai_dochada 0xdae +#define IBUS_Thai_topatak 0xdaf +#define IBUS_Thai_thothan 0xdb0 +#define IBUS_Thai_thonangmontho 0xdb1 +#define IBUS_Thai_thophuthao 0xdb2 +#define IBUS_Thai_nonen 0xdb3 +#define IBUS_Thai_dodek 0xdb4 +#define IBUS_Thai_totao 0xdb5 +#define IBUS_Thai_thothung 0xdb6 +#define IBUS_Thai_thothahan 0xdb7 +#define IBUS_Thai_thothong 0xdb8 +#define IBUS_Thai_nonu 0xdb9 +#define IBUS_Thai_bobaimai 0xdba +#define IBUS_Thai_popla 0xdbb +#define IBUS_Thai_phophung 0xdbc +#define IBUS_Thai_fofa 0xdbd +#define IBUS_Thai_phophan 0xdbe +#define IBUS_Thai_fofan 0xdbf +#define IBUS_Thai_phosamphao 0xdc0 +#define IBUS_Thai_moma 0xdc1 +#define IBUS_Thai_yoyak 0xdc2 +#define IBUS_Thai_rorua 0xdc3 +#define IBUS_Thai_ru 0xdc4 +#define IBUS_Thai_loling 0xdc5 +#define IBUS_Thai_lu 0xdc6 +#define IBUS_Thai_wowaen 0xdc7 +#define IBUS_Thai_sosala 0xdc8 +#define IBUS_Thai_sorusi 0xdc9 +#define IBUS_Thai_sosua 0xdca +#define IBUS_Thai_hohip 0xdcb +#define IBUS_Thai_lochula 0xdcc +#define IBUS_Thai_oang 0xdcd +#define IBUS_Thai_honokhuk 0xdce +#define IBUS_Thai_paiyannoi 0xdcf +#define IBUS_Thai_saraa 0xdd0 +#define IBUS_Thai_maihanakat 0xdd1 +#define IBUS_Thai_saraaa 0xdd2 +#define IBUS_Thai_saraam 0xdd3 +#define IBUS_Thai_sarai 0xdd4 +#define IBUS_Thai_saraii 0xdd5 +#define IBUS_Thai_saraue 0xdd6 +#define IBUS_Thai_sarauee 0xdd7 +#define IBUS_Thai_sarau 0xdd8 +#define IBUS_Thai_sarauu 0xdd9 +#define IBUS_Thai_phinthu 0xdda +#define IBUS_Thai_maihanakat_maitho 0xdde +#define IBUS_Thai_baht 0xddf +#define IBUS_Thai_sarae 0xde0 +#define IBUS_Thai_saraae 0xde1 +#define IBUS_Thai_sarao 0xde2 +#define IBUS_Thai_saraaimaimuan 0xde3 +#define IBUS_Thai_saraaimaimalai 0xde4 +#define IBUS_Thai_lakkhangyao 0xde5 +#define IBUS_Thai_maiyamok 0xde6 +#define IBUS_Thai_maitaikhu 0xde7 +#define IBUS_Thai_maiek 0xde8 +#define IBUS_Thai_maitho 0xde9 +#define IBUS_Thai_maitri 0xdea +#define IBUS_Thai_maichattawa 0xdeb +#define IBUS_Thai_thanthakhat 0xdec +#define IBUS_Thai_nikhahit 0xded +#define IBUS_Thai_leksun 0xdf0 +#define IBUS_Thai_leknung 0xdf1 +#define IBUS_Thai_leksong 0xdf2 +#define IBUS_Thai_leksam 0xdf3 +#define IBUS_Thai_leksi 0xdf4 +#define IBUS_Thai_lekha 0xdf5 +#define IBUS_Thai_lekhok 0xdf6 +#define IBUS_Thai_lekchet 0xdf7 +#define IBUS_Thai_lekpaet 0xdf8 +#define IBUS_Thai_lekkao 0xdf9 +#define IBUS_Hangul 0xff31 +#define IBUS_Hangul_Start 0xff32 +#define IBUS_Hangul_End 0xff33 +#define IBUS_Hangul_Hanja 0xff34 +#define IBUS_Hangul_Jamo 0xff35 +#define IBUS_Hangul_Romaja 0xff36 +#define IBUS_Hangul_Codeinput 0xff37 +#define IBUS_Hangul_Jeonja 0xff38 +#define IBUS_Hangul_Banja 0xff39 +#define IBUS_Hangul_PreHanja 0xff3a +#define IBUS_Hangul_PostHanja 0xff3b +#define IBUS_Hangul_SingleCandidate 0xff3c +#define IBUS_Hangul_MultipleCandidate 0xff3d +#define IBUS_Hangul_PreviousCandidate 0xff3e +#define IBUS_Hangul_Special 0xff3f +#define IBUS_Hangul_switch 0xff7e +#define IBUS_Hangul_Kiyeog 0xea1 +#define IBUS_Hangul_SsangKiyeog 0xea2 +#define IBUS_Hangul_KiyeogSios 0xea3 +#define IBUS_Hangul_Nieun 0xea4 +#define IBUS_Hangul_NieunJieuj 0xea5 +#define IBUS_Hangul_NieunHieuh 0xea6 +#define IBUS_Hangul_Dikeud 0xea7 +#define IBUS_Hangul_SsangDikeud 0xea8 +#define IBUS_Hangul_Rieul 0xea9 +#define IBUS_Hangul_RieulKiyeog 0xeaa +#define IBUS_Hangul_RieulMieum 0xeab +#define IBUS_Hangul_RieulPieub 0xeac +#define IBUS_Hangul_RieulSios 0xead +#define IBUS_Hangul_RieulTieut 0xeae +#define IBUS_Hangul_RieulPhieuf 0xeaf +#define IBUS_Hangul_RieulHieuh 0xeb0 +#define IBUS_Hangul_Mieum 0xeb1 +#define IBUS_Hangul_Pieub 0xeb2 +#define IBUS_Hangul_SsangPieub 0xeb3 +#define IBUS_Hangul_PieubSios 0xeb4 +#define IBUS_Hangul_Sios 0xeb5 +#define IBUS_Hangul_SsangSios 0xeb6 +#define IBUS_Hangul_Ieung 0xeb7 +#define IBUS_Hangul_Jieuj 0xeb8 +#define IBUS_Hangul_SsangJieuj 0xeb9 +#define IBUS_Hangul_Cieuc 0xeba +#define IBUS_Hangul_Khieuq 0xebb +#define IBUS_Hangul_Tieut 0xebc +#define IBUS_Hangul_Phieuf 0xebd +#define IBUS_Hangul_Hieuh 0xebe +#define IBUS_Hangul_A 0xebf +#define IBUS_Hangul_AE 0xec0 +#define IBUS_Hangul_YA 0xec1 +#define IBUS_Hangul_YAE 0xec2 +#define IBUS_Hangul_EO 0xec3 +#define IBUS_Hangul_E 0xec4 +#define IBUS_Hangul_YEO 0xec5 +#define IBUS_Hangul_YE 0xec6 +#define IBUS_Hangul_O 0xec7 +#define IBUS_Hangul_WA 0xec8 +#define IBUS_Hangul_WAE 0xec9 +#define IBUS_Hangul_OE 0xeca +#define IBUS_Hangul_YO 0xecb +#define IBUS_Hangul_U 0xecc +#define IBUS_Hangul_WEO 0xecd +#define IBUS_Hangul_WE 0xece +#define IBUS_Hangul_WI 0xecf +#define IBUS_Hangul_YU 0xed0 +#define IBUS_Hangul_EU 0xed1 +#define IBUS_Hangul_YI 0xed2 +#define IBUS_Hangul_I 0xed3 +#define IBUS_Hangul_J_Kiyeog 0xed4 +#define IBUS_Hangul_J_SsangKiyeog 0xed5 +#define IBUS_Hangul_J_KiyeogSios 0xed6 +#define IBUS_Hangul_J_Nieun 0xed7 +#define IBUS_Hangul_J_NieunJieuj 0xed8 +#define IBUS_Hangul_J_NieunHieuh 0xed9 +#define IBUS_Hangul_J_Dikeud 0xeda +#define IBUS_Hangul_J_Rieul 0xedb +#define IBUS_Hangul_J_RieulKiyeog 0xedc +#define IBUS_Hangul_J_RieulMieum 0xedd +#define IBUS_Hangul_J_RieulPieub 0xede +#define IBUS_Hangul_J_RieulSios 0xedf +#define IBUS_Hangul_J_RieulTieut 0xee0 +#define IBUS_Hangul_J_RieulPhieuf 0xee1 +#define IBUS_Hangul_J_RieulHieuh 0xee2 +#define IBUS_Hangul_J_Mieum 0xee3 +#define IBUS_Hangul_J_Pieub 0xee4 +#define IBUS_Hangul_J_PieubSios 0xee5 +#define IBUS_Hangul_J_Sios 0xee6 +#define IBUS_Hangul_J_SsangSios 0xee7 +#define IBUS_Hangul_J_Ieung 0xee8 +#define IBUS_Hangul_J_Jieuj 0xee9 +#define IBUS_Hangul_J_Cieuc 0xeea +#define IBUS_Hangul_J_Khieuq 0xeeb +#define IBUS_Hangul_J_Tieut 0xeec +#define IBUS_Hangul_J_Phieuf 0xeed +#define IBUS_Hangul_J_Hieuh 0xeee +#define IBUS_Hangul_RieulYeorinHieuh 0xeef +#define IBUS_Hangul_SunkyeongeumMieum 0xef0 +#define IBUS_Hangul_SunkyeongeumPieub 0xef1 +#define IBUS_Hangul_PanSios 0xef2 +#define IBUS_Hangul_KkogjiDalrinIeung 0xef3 +#define IBUS_Hangul_SunkyeongeumPhieuf 0xef4 +#define IBUS_Hangul_YeorinHieuh 0xef5 +#define IBUS_Hangul_AraeA 0xef6 +#define IBUS_Hangul_AraeAE 0xef7 +#define IBUS_Hangul_J_PanSios 0xef8 +#define IBUS_Hangul_J_KkogjiDalrinIeung 0xef9 +#define IBUS_Hangul_J_YeorinHieuh 0xefa +#define IBUS_Korean_Won 0xeff +#define IBUS_Armenian_ligature_ew 0x1000587 +#define IBUS_Armenian_full_stop 0x1000589 +#define IBUS_Armenian_verjaket 0x1000589 +#define IBUS_Armenian_separation_mark 0x100055d +#define IBUS_Armenian_but 0x100055d +#define IBUS_Armenian_hyphen 0x100058a +#define IBUS_Armenian_yentamna 0x100058a +#define IBUS_Armenian_exclam 0x100055c +#define IBUS_Armenian_amanak 0x100055c +#define IBUS_Armenian_accent 0x100055b +#define IBUS_Armenian_shesht 0x100055b +#define IBUS_Armenian_question 0x100055e +#define IBUS_Armenian_paruyk 0x100055e +#define IBUS_Armenian_AYB 0x1000531 +#define IBUS_Armenian_ayb 0x1000561 +#define IBUS_Armenian_BEN 0x1000532 +#define IBUS_Armenian_ben 0x1000562 +#define IBUS_Armenian_GIM 0x1000533 +#define IBUS_Armenian_gim 0x1000563 +#define IBUS_Armenian_DA 0x1000534 +#define IBUS_Armenian_da 0x1000564 +#define IBUS_Armenian_YECH 0x1000535 +#define IBUS_Armenian_yech 0x1000565 +#define IBUS_Armenian_ZA 0x1000536 +#define IBUS_Armenian_za 0x1000566 +#define IBUS_Armenian_E 0x1000537 +#define IBUS_Armenian_e 0x1000567 +#define IBUS_Armenian_AT 0x1000538 +#define IBUS_Armenian_at 0x1000568 +#define IBUS_Armenian_TO 0x1000539 +#define IBUS_Armenian_to 0x1000569 +#define IBUS_Armenian_ZHE 0x100053a +#define IBUS_Armenian_zhe 0x100056a +#define IBUS_Armenian_INI 0x100053b +#define IBUS_Armenian_ini 0x100056b +#define IBUS_Armenian_LYUN 0x100053c +#define IBUS_Armenian_lyun 0x100056c +#define IBUS_Armenian_KHE 0x100053d +#define IBUS_Armenian_khe 0x100056d +#define IBUS_Armenian_TSA 0x100053e +#define IBUS_Armenian_tsa 0x100056e +#define IBUS_Armenian_KEN 0x100053f +#define IBUS_Armenian_ken 0x100056f +#define IBUS_Armenian_HO 0x1000540 +#define IBUS_Armenian_ho 0x1000570 +#define IBUS_Armenian_DZA 0x1000541 +#define IBUS_Armenian_dza 0x1000571 +#define IBUS_Armenian_GHAT 0x1000542 +#define IBUS_Armenian_ghat 0x1000572 +#define IBUS_Armenian_TCHE 0x1000543 +#define IBUS_Armenian_tche 0x1000573 +#define IBUS_Armenian_MEN 0x1000544 +#define IBUS_Armenian_men 0x1000574 +#define IBUS_Armenian_HI 0x1000545 +#define IBUS_Armenian_hi 0x1000575 +#define IBUS_Armenian_NU 0x1000546 +#define IBUS_Armenian_nu 0x1000576 +#define IBUS_Armenian_SHA 0x1000547 +#define IBUS_Armenian_sha 0x1000577 +#define IBUS_Armenian_VO 0x1000548 +#define IBUS_Armenian_vo 0x1000578 +#define IBUS_Armenian_CHA 0x1000549 +#define IBUS_Armenian_cha 0x1000579 +#define IBUS_Armenian_PE 0x100054a +#define IBUS_Armenian_pe 0x100057a +#define IBUS_Armenian_JE 0x100054b +#define IBUS_Armenian_je 0x100057b +#define IBUS_Armenian_RA 0x100054c +#define IBUS_Armenian_ra 0x100057c +#define IBUS_Armenian_SE 0x100054d +#define IBUS_Armenian_se 0x100057d +#define IBUS_Armenian_VEV 0x100054e +#define IBUS_Armenian_vev 0x100057e +#define IBUS_Armenian_TYUN 0x100054f +#define IBUS_Armenian_tyun 0x100057f +#define IBUS_Armenian_RE 0x1000550 +#define IBUS_Armenian_re 0x1000580 +#define IBUS_Armenian_TSO 0x1000551 +#define IBUS_Armenian_tso 0x1000581 +#define IBUS_Armenian_VYUN 0x1000552 +#define IBUS_Armenian_vyun 0x1000582 +#define IBUS_Armenian_PYUR 0x1000553 +#define IBUS_Armenian_pyur 0x1000583 +#define IBUS_Armenian_KE 0x1000554 +#define IBUS_Armenian_ke 0x1000584 +#define IBUS_Armenian_O 0x1000555 +#define IBUS_Armenian_o 0x1000585 +#define IBUS_Armenian_FE 0x1000556 +#define IBUS_Armenian_fe 0x1000586 +#define IBUS_Armenian_apostrophe 0x100055a +#define IBUS_Georgian_an 0x10010d0 +#define IBUS_Georgian_ban 0x10010d1 +#define IBUS_Georgian_gan 0x10010d2 +#define IBUS_Georgian_don 0x10010d3 +#define IBUS_Georgian_en 0x10010d4 +#define IBUS_Georgian_vin 0x10010d5 +#define IBUS_Georgian_zen 0x10010d6 +#define IBUS_Georgian_tan 0x10010d7 +#define IBUS_Georgian_in 0x10010d8 +#define IBUS_Georgian_kan 0x10010d9 +#define IBUS_Georgian_las 0x10010da +#define IBUS_Georgian_man 0x10010db +#define IBUS_Georgian_nar 0x10010dc +#define IBUS_Georgian_on 0x10010dd +#define IBUS_Georgian_par 0x10010de +#define IBUS_Georgian_zhar 0x10010df +#define IBUS_Georgian_rae 0x10010e0 +#define IBUS_Georgian_san 0x10010e1 +#define IBUS_Georgian_tar 0x10010e2 +#define IBUS_Georgian_un 0x10010e3 +#define IBUS_Georgian_phar 0x10010e4 +#define IBUS_Georgian_khar 0x10010e5 +#define IBUS_Georgian_ghan 0x10010e6 +#define IBUS_Georgian_qar 0x10010e7 +#define IBUS_Georgian_shin 0x10010e8 +#define IBUS_Georgian_chin 0x10010e9 +#define IBUS_Georgian_can 0x10010ea +#define IBUS_Georgian_jil 0x10010eb +#define IBUS_Georgian_cil 0x10010ec +#define IBUS_Georgian_char 0x10010ed +#define IBUS_Georgian_xan 0x10010ee +#define IBUS_Georgian_jhan 0x10010ef +#define IBUS_Georgian_hae 0x10010f0 +#define IBUS_Georgian_he 0x10010f1 +#define IBUS_Georgian_hie 0x10010f2 +#define IBUS_Georgian_we 0x10010f3 +#define IBUS_Georgian_har 0x10010f4 +#define IBUS_Georgian_hoe 0x10010f5 +#define IBUS_Georgian_fi 0x10010f6 +#define IBUS_Xabovedot 0x1001e8a +#define IBUS_Ibreve 0x100012c +#define IBUS_Zstroke 0x10001b5 +#define IBUS_Gcaron 0x10001e6 +#define IBUS_Ocaron 0x10001d1 +#define IBUS_Obarred 0x100019f +#define IBUS_xabovedot 0x1001e8b +#define IBUS_ibreve 0x100012d +#define IBUS_zstroke 0x10001b6 +#define IBUS_gcaron 0x10001e7 +#define IBUS_ocaron 0x10001d2 +#define IBUS_obarred 0x1000275 +#define IBUS_SCHWA 0x100018f +#define IBUS_schwa 0x1000259 +#define IBUS_Lbelowdot 0x1001e36 +#define IBUS_lbelowdot 0x1001e37 +#define IBUS_Abelowdot 0x1001ea0 +#define IBUS_abelowdot 0x1001ea1 +#define IBUS_Ahook 0x1001ea2 +#define IBUS_ahook 0x1001ea3 +#define IBUS_Acircumflexacute 0x1001ea4 +#define IBUS_acircumflexacute 0x1001ea5 +#define IBUS_Acircumflexgrave 0x1001ea6 +#define IBUS_acircumflexgrave 0x1001ea7 +#define IBUS_Acircumflexhook 0x1001ea8 +#define IBUS_acircumflexhook 0x1001ea9 +#define IBUS_Acircumflextilde 0x1001eaa +#define IBUS_acircumflextilde 0x1001eab +#define IBUS_Acircumflexbelowdot 0x1001eac +#define IBUS_acircumflexbelowdot 0x1001ead +#define IBUS_Abreveacute 0x1001eae +#define IBUS_abreveacute 0x1001eaf +#define IBUS_Abrevegrave 0x1001eb0 +#define IBUS_abrevegrave 0x1001eb1 +#define IBUS_Abrevehook 0x1001eb2 +#define IBUS_abrevehook 0x1001eb3 +#define IBUS_Abrevetilde 0x1001eb4 +#define IBUS_abrevetilde 0x1001eb5 +#define IBUS_Abrevebelowdot 0x1001eb6 +#define IBUS_abrevebelowdot 0x1001eb7 +#define IBUS_Ebelowdot 0x1001eb8 +#define IBUS_ebelowdot 0x1001eb9 +#define IBUS_Ehook 0x1001eba +#define IBUS_ehook 0x1001ebb +#define IBUS_Etilde 0x1001ebc +#define IBUS_etilde 0x1001ebd +#define IBUS_Ecircumflexacute 0x1001ebe +#define IBUS_ecircumflexacute 0x1001ebf +#define IBUS_Ecircumflexgrave 0x1001ec0 +#define IBUS_ecircumflexgrave 0x1001ec1 +#define IBUS_Ecircumflexhook 0x1001ec2 +#define IBUS_ecircumflexhook 0x1001ec3 +#define IBUS_Ecircumflextilde 0x1001ec4 +#define IBUS_ecircumflextilde 0x1001ec5 +#define IBUS_Ecircumflexbelowdot 0x1001ec6 +#define IBUS_ecircumflexbelowdot 0x1001ec7 +#define IBUS_Ihook 0x1001ec8 +#define IBUS_ihook 0x1001ec9 +#define IBUS_Ibelowdot 0x1001eca +#define IBUS_ibelowdot 0x1001ecb +#define IBUS_Obelowdot 0x1001ecc +#define IBUS_obelowdot 0x1001ecd +#define IBUS_Ohook 0x1001ece +#define IBUS_ohook 0x1001ecf +#define IBUS_Ocircumflexacute 0x1001ed0 +#define IBUS_ocircumflexacute 0x1001ed1 +#define IBUS_Ocircumflexgrave 0x1001ed2 +#define IBUS_ocircumflexgrave 0x1001ed3 +#define IBUS_Ocircumflexhook 0x1001ed4 +#define IBUS_ocircumflexhook 0x1001ed5 +#define IBUS_Ocircumflextilde 0x1001ed6 +#define IBUS_ocircumflextilde 0x1001ed7 +#define IBUS_Ocircumflexbelowdot 0x1001ed8 +#define IBUS_ocircumflexbelowdot 0x1001ed9 +#define IBUS_Ohornacute 0x1001eda +#define IBUS_ohornacute 0x1001edb +#define IBUS_Ohorngrave 0x1001edc +#define IBUS_ohorngrave 0x1001edd +#define IBUS_Ohornhook 0x1001ede +#define IBUS_ohornhook 0x1001edf +#define IBUS_Ohorntilde 0x1001ee0 +#define IBUS_ohorntilde 0x1001ee1 +#define IBUS_Ohornbelowdot 0x1001ee2 +#define IBUS_ohornbelowdot 0x1001ee3 +#define IBUS_Ubelowdot 0x1001ee4 +#define IBUS_ubelowdot 0x1001ee5 +#define IBUS_Uhook 0x1001ee6 +#define IBUS_uhook 0x1001ee7 +#define IBUS_Uhornacute 0x1001ee8 +#define IBUS_uhornacute 0x1001ee9 +#define IBUS_Uhorngrave 0x1001eea +#define IBUS_uhorngrave 0x1001eeb +#define IBUS_Uhornhook 0x1001eec +#define IBUS_uhornhook 0x1001eed +#define IBUS_Uhorntilde 0x1001eee +#define IBUS_uhorntilde 0x1001eef +#define IBUS_Uhornbelowdot 0x1001ef0 +#define IBUS_uhornbelowdot 0x1001ef1 +#define IBUS_Ybelowdot 0x1001ef4 +#define IBUS_ybelowdot 0x1001ef5 +#define IBUS_Yhook 0x1001ef6 +#define IBUS_yhook 0x1001ef7 +#define IBUS_Ytilde 0x1001ef8 +#define IBUS_ytilde 0x1001ef9 +#define IBUS_Ohorn 0x10001a0 +#define IBUS_ohorn 0x10001a1 +#define IBUS_Uhorn 0x10001af +#define IBUS_uhorn 0x10001b0 +#define IBUS_EcuSign 0x10020a0 +#define IBUS_ColonSign 0x10020a1 +#define IBUS_CruzeiroSign 0x10020a2 +#define IBUS_FFrancSign 0x10020a3 +#define IBUS_LiraSign 0x10020a4 +#define IBUS_MillSign 0x10020a5 +#define IBUS_NairaSign 0x10020a6 +#define IBUS_PesetaSign 0x10020a7 +#define IBUS_RupeeSign 0x10020a8 +#define IBUS_WonSign 0x10020a9 +#define IBUS_NewSheqelSign 0x10020aa +#define IBUS_DongSign 0x10020ab +#define IBUS_EuroSign 0x20ac +#define IBUS_zerosuperior 0x1002070 +#define IBUS_foursuperior 0x1002074 +#define IBUS_fivesuperior 0x1002075 +#define IBUS_sixsuperior 0x1002076 +#define IBUS_sevensuperior 0x1002077 +#define IBUS_eightsuperior 0x1002078 +#define IBUS_ninesuperior 0x1002079 +#define IBUS_zerosubscript 0x1002080 +#define IBUS_onesubscript 0x1002081 +#define IBUS_twosubscript 0x1002082 +#define IBUS_threesubscript 0x1002083 +#define IBUS_foursubscript 0x1002084 +#define IBUS_fivesubscript 0x1002085 +#define IBUS_sixsubscript 0x1002086 +#define IBUS_sevensubscript 0x1002087 +#define IBUS_eightsubscript 0x1002088 +#define IBUS_ninesubscript 0x1002089 +#define IBUS_partdifferential 0x1002202 +#define IBUS_emptyset 0x1002205 +#define IBUS_elementof 0x1002208 +#define IBUS_notelementof 0x1002209 +#define IBUS_containsas 0x100220b +#define IBUS_squareroot 0x100221a +#define IBUS_cuberoot 0x100221b +#define IBUS_fourthroot 0x100221c +#define IBUS_dintegral 0x100222c +#define IBUS_tintegral 0x100222d +#define IBUS_because 0x1002235 +#define IBUS_approxeq 0x1002248 +#define IBUS_notapproxeq 0x1002247 +#define IBUS_notidentical 0x1002262 +#define IBUS_stricteq 0x1002263 +#define IBUS_braille_dot_1 0xfff1 +#define IBUS_braille_dot_2 0xfff2 +#define IBUS_braille_dot_3 0xfff3 +#define IBUS_braille_dot_4 0xfff4 +#define IBUS_braille_dot_5 0xfff5 +#define IBUS_braille_dot_6 0xfff6 +#define IBUS_braille_dot_7 0xfff7 +#define IBUS_braille_dot_8 0xfff8 +#define IBUS_braille_dot_9 0xfff9 +#define IBUS_braille_dot_10 0xfffa +#define IBUS_braille_blank 0x1002800 +#define IBUS_braille_dots_1 0x1002801 +#define IBUS_braille_dots_2 0x1002802 +#define IBUS_braille_dots_12 0x1002803 +#define IBUS_braille_dots_3 0x1002804 +#define IBUS_braille_dots_13 0x1002805 +#define IBUS_braille_dots_23 0x1002806 +#define IBUS_braille_dots_123 0x1002807 +#define IBUS_braille_dots_4 0x1002808 +#define IBUS_braille_dots_14 0x1002809 +#define IBUS_braille_dots_24 0x100280a +#define IBUS_braille_dots_124 0x100280b +#define IBUS_braille_dots_34 0x100280c +#define IBUS_braille_dots_134 0x100280d +#define IBUS_braille_dots_234 0x100280e +#define IBUS_braille_dots_1234 0x100280f +#define IBUS_braille_dots_5 0x1002810 +#define IBUS_braille_dots_15 0x1002811 +#define IBUS_braille_dots_25 0x1002812 +#define IBUS_braille_dots_125 0x1002813 +#define IBUS_braille_dots_35 0x1002814 +#define IBUS_braille_dots_135 0x1002815 +#define IBUS_braille_dots_235 0x1002816 +#define IBUS_braille_dots_1235 0x1002817 +#define IBUS_braille_dots_45 0x1002818 +#define IBUS_braille_dots_145 0x1002819 +#define IBUS_braille_dots_245 0x100281a +#define IBUS_braille_dots_1245 0x100281b +#define IBUS_braille_dots_345 0x100281c +#define IBUS_braille_dots_1345 0x100281d +#define IBUS_braille_dots_2345 0x100281e +#define IBUS_braille_dots_12345 0x100281f +#define IBUS_braille_dots_6 0x1002820 +#define IBUS_braille_dots_16 0x1002821 +#define IBUS_braille_dots_26 0x1002822 +#define IBUS_braille_dots_126 0x1002823 +#define IBUS_braille_dots_36 0x1002824 +#define IBUS_braille_dots_136 0x1002825 +#define IBUS_braille_dots_236 0x1002826 +#define IBUS_braille_dots_1236 0x1002827 +#define IBUS_braille_dots_46 0x1002828 +#define IBUS_braille_dots_146 0x1002829 +#define IBUS_braille_dots_246 0x100282a +#define IBUS_braille_dots_1246 0x100282b +#define IBUS_braille_dots_346 0x100282c +#define IBUS_braille_dots_1346 0x100282d +#define IBUS_braille_dots_2346 0x100282e +#define IBUS_braille_dots_12346 0x100282f +#define IBUS_braille_dots_56 0x1002830 +#define IBUS_braille_dots_156 0x1002831 +#define IBUS_braille_dots_256 0x1002832 +#define IBUS_braille_dots_1256 0x1002833 +#define IBUS_braille_dots_356 0x1002834 +#define IBUS_braille_dots_1356 0x1002835 +#define IBUS_braille_dots_2356 0x1002836 +#define IBUS_braille_dots_12356 0x1002837 +#define IBUS_braille_dots_456 0x1002838 +#define IBUS_braille_dots_1456 0x1002839 +#define IBUS_braille_dots_2456 0x100283a +#define IBUS_braille_dots_12456 0x100283b +#define IBUS_braille_dots_3456 0x100283c +#define IBUS_braille_dots_13456 0x100283d +#define IBUS_braille_dots_23456 0x100283e +#define IBUS_braille_dots_123456 0x100283f +#define IBUS_braille_dots_7 0x1002840 +#define IBUS_braille_dots_17 0x1002841 +#define IBUS_braille_dots_27 0x1002842 +#define IBUS_braille_dots_127 0x1002843 +#define IBUS_braille_dots_37 0x1002844 +#define IBUS_braille_dots_137 0x1002845 +#define IBUS_braille_dots_237 0x1002846 +#define IBUS_braille_dots_1237 0x1002847 +#define IBUS_braille_dots_47 0x1002848 +#define IBUS_braille_dots_147 0x1002849 +#define IBUS_braille_dots_247 0x100284a +#define IBUS_braille_dots_1247 0x100284b +#define IBUS_braille_dots_347 0x100284c +#define IBUS_braille_dots_1347 0x100284d +#define IBUS_braille_dots_2347 0x100284e +#define IBUS_braille_dots_12347 0x100284f +#define IBUS_braille_dots_57 0x1002850 +#define IBUS_braille_dots_157 0x1002851 +#define IBUS_braille_dots_257 0x1002852 +#define IBUS_braille_dots_1257 0x1002853 +#define IBUS_braille_dots_357 0x1002854 +#define IBUS_braille_dots_1357 0x1002855 +#define IBUS_braille_dots_2357 0x1002856 +#define IBUS_braille_dots_12357 0x1002857 +#define IBUS_braille_dots_457 0x1002858 +#define IBUS_braille_dots_1457 0x1002859 +#define IBUS_braille_dots_2457 0x100285a +#define IBUS_braille_dots_12457 0x100285b +#define IBUS_braille_dots_3457 0x100285c +#define IBUS_braille_dots_13457 0x100285d +#define IBUS_braille_dots_23457 0x100285e +#define IBUS_braille_dots_123457 0x100285f +#define IBUS_braille_dots_67 0x1002860 +#define IBUS_braille_dots_167 0x1002861 +#define IBUS_braille_dots_267 0x1002862 +#define IBUS_braille_dots_1267 0x1002863 +#define IBUS_braille_dots_367 0x1002864 +#define IBUS_braille_dots_1367 0x1002865 +#define IBUS_braille_dots_2367 0x1002866 +#define IBUS_braille_dots_12367 0x1002867 +#define IBUS_braille_dots_467 0x1002868 +#define IBUS_braille_dots_1467 0x1002869 +#define IBUS_braille_dots_2467 0x100286a +#define IBUS_braille_dots_12467 0x100286b +#define IBUS_braille_dots_3467 0x100286c +#define IBUS_braille_dots_13467 0x100286d +#define IBUS_braille_dots_23467 0x100286e +#define IBUS_braille_dots_123467 0x100286f +#define IBUS_braille_dots_567 0x1002870 +#define IBUS_braille_dots_1567 0x1002871 +#define IBUS_braille_dots_2567 0x1002872 +#define IBUS_braille_dots_12567 0x1002873 +#define IBUS_braille_dots_3567 0x1002874 +#define IBUS_braille_dots_13567 0x1002875 +#define IBUS_braille_dots_23567 0x1002876 +#define IBUS_braille_dots_123567 0x1002877 +#define IBUS_braille_dots_4567 0x1002878 +#define IBUS_braille_dots_14567 0x1002879 +#define IBUS_braille_dots_24567 0x100287a +#define IBUS_braille_dots_124567 0x100287b +#define IBUS_braille_dots_34567 0x100287c +#define IBUS_braille_dots_134567 0x100287d +#define IBUS_braille_dots_234567 0x100287e +#define IBUS_braille_dots_1234567 0x100287f +#define IBUS_braille_dots_8 0x1002880 +#define IBUS_braille_dots_18 0x1002881 +#define IBUS_braille_dots_28 0x1002882 +#define IBUS_braille_dots_128 0x1002883 +#define IBUS_braille_dots_38 0x1002884 +#define IBUS_braille_dots_138 0x1002885 +#define IBUS_braille_dots_238 0x1002886 +#define IBUS_braille_dots_1238 0x1002887 +#define IBUS_braille_dots_48 0x1002888 +#define IBUS_braille_dots_148 0x1002889 +#define IBUS_braille_dots_248 0x100288a +#define IBUS_braille_dots_1248 0x100288b +#define IBUS_braille_dots_348 0x100288c +#define IBUS_braille_dots_1348 0x100288d +#define IBUS_braille_dots_2348 0x100288e +#define IBUS_braille_dots_12348 0x100288f +#define IBUS_braille_dots_58 0x1002890 +#define IBUS_braille_dots_158 0x1002891 +#define IBUS_braille_dots_258 0x1002892 +#define IBUS_braille_dots_1258 0x1002893 +#define IBUS_braille_dots_358 0x1002894 +#define IBUS_braille_dots_1358 0x1002895 +#define IBUS_braille_dots_2358 0x1002896 +#define IBUS_braille_dots_12358 0x1002897 +#define IBUS_braille_dots_458 0x1002898 +#define IBUS_braille_dots_1458 0x1002899 +#define IBUS_braille_dots_2458 0x100289a +#define IBUS_braille_dots_12458 0x100289b +#define IBUS_braille_dots_3458 0x100289c +#define IBUS_braille_dots_13458 0x100289d +#define IBUS_braille_dots_23458 0x100289e +#define IBUS_braille_dots_123458 0x100289f +#define IBUS_braille_dots_68 0x10028a0 +#define IBUS_braille_dots_168 0x10028a1 +#define IBUS_braille_dots_268 0x10028a2 +#define IBUS_braille_dots_1268 0x10028a3 +#define IBUS_braille_dots_368 0x10028a4 +#define IBUS_braille_dots_1368 0x10028a5 +#define IBUS_braille_dots_2368 0x10028a6 +#define IBUS_braille_dots_12368 0x10028a7 +#define IBUS_braille_dots_468 0x10028a8 +#define IBUS_braille_dots_1468 0x10028a9 +#define IBUS_braille_dots_2468 0x10028aa +#define IBUS_braille_dots_12468 0x10028ab +#define IBUS_braille_dots_3468 0x10028ac +#define IBUS_braille_dots_13468 0x10028ad +#define IBUS_braille_dots_23468 0x10028ae +#define IBUS_braille_dots_123468 0x10028af +#define IBUS_braille_dots_568 0x10028b0 +#define IBUS_braille_dots_1568 0x10028b1 +#define IBUS_braille_dots_2568 0x10028b2 +#define IBUS_braille_dots_12568 0x10028b3 +#define IBUS_braille_dots_3568 0x10028b4 +#define IBUS_braille_dots_13568 0x10028b5 +#define IBUS_braille_dots_23568 0x10028b6 +#define IBUS_braille_dots_123568 0x10028b7 +#define IBUS_braille_dots_4568 0x10028b8 +#define IBUS_braille_dots_14568 0x10028b9 +#define IBUS_braille_dots_24568 0x10028ba +#define IBUS_braille_dots_124568 0x10028bb +#define IBUS_braille_dots_34568 0x10028bc +#define IBUS_braille_dots_134568 0x10028bd +#define IBUS_braille_dots_234568 0x10028be +#define IBUS_braille_dots_1234568 0x10028bf +#define IBUS_braille_dots_78 0x10028c0 +#define IBUS_braille_dots_178 0x10028c1 +#define IBUS_braille_dots_278 0x10028c2 +#define IBUS_braille_dots_1278 0x10028c3 +#define IBUS_braille_dots_378 0x10028c4 +#define IBUS_braille_dots_1378 0x10028c5 +#define IBUS_braille_dots_2378 0x10028c6 +#define IBUS_braille_dots_12378 0x10028c7 +#define IBUS_braille_dots_478 0x10028c8 +#define IBUS_braille_dots_1478 0x10028c9 +#define IBUS_braille_dots_2478 0x10028ca +#define IBUS_braille_dots_12478 0x10028cb +#define IBUS_braille_dots_3478 0x10028cc +#define IBUS_braille_dots_13478 0x10028cd +#define IBUS_braille_dots_23478 0x10028ce +#define IBUS_braille_dots_123478 0x10028cf +#define IBUS_braille_dots_578 0x10028d0 +#define IBUS_braille_dots_1578 0x10028d1 +#define IBUS_braille_dots_2578 0x10028d2 +#define IBUS_braille_dots_12578 0x10028d3 +#define IBUS_braille_dots_3578 0x10028d4 +#define IBUS_braille_dots_13578 0x10028d5 +#define IBUS_braille_dots_23578 0x10028d6 +#define IBUS_braille_dots_123578 0x10028d7 +#define IBUS_braille_dots_4578 0x10028d8 +#define IBUS_braille_dots_14578 0x10028d9 +#define IBUS_braille_dots_24578 0x10028da +#define IBUS_braille_dots_124578 0x10028db +#define IBUS_braille_dots_34578 0x10028dc +#define IBUS_braille_dots_134578 0x10028dd +#define IBUS_braille_dots_234578 0x10028de +#define IBUS_braille_dots_1234578 0x10028df +#define IBUS_braille_dots_678 0x10028e0 +#define IBUS_braille_dots_1678 0x10028e1 +#define IBUS_braille_dots_2678 0x10028e2 +#define IBUS_braille_dots_12678 0x10028e3 +#define IBUS_braille_dots_3678 0x10028e4 +#define IBUS_braille_dots_13678 0x10028e5 +#define IBUS_braille_dots_23678 0x10028e6 +#define IBUS_braille_dots_123678 0x10028e7 +#define IBUS_braille_dots_4678 0x10028e8 +#define IBUS_braille_dots_14678 0x10028e9 +#define IBUS_braille_dots_24678 0x10028ea +#define IBUS_braille_dots_124678 0x10028eb +#define IBUS_braille_dots_34678 0x10028ec +#define IBUS_braille_dots_134678 0x10028ed +#define IBUS_braille_dots_234678 0x10028ee +#define IBUS_braille_dots_1234678 0x10028ef +#define IBUS_braille_dots_5678 0x10028f0 +#define IBUS_braille_dots_15678 0x10028f1 +#define IBUS_braille_dots_25678 0x10028f2 +#define IBUS_braille_dots_125678 0x10028f3 +#define IBUS_braille_dots_35678 0x10028f4 +#define IBUS_braille_dots_135678 0x10028f5 +#define IBUS_braille_dots_235678 0x10028f6 +#define IBUS_braille_dots_1235678 0x10028f7 +#define IBUS_braille_dots_45678 0x10028f8 +#define IBUS_braille_dots_145678 0x10028f9 +#define IBUS_braille_dots_245678 0x10028fa +#define IBUS_braille_dots_1245678 0x10028fb +#define IBUS_braille_dots_345678 0x10028fc +#define IBUS_braille_dots_1345678 0x10028fd +#define IBUS_braille_dots_2345678 0x10028fe +#define IBUS_braille_dots_12345678 0x10028ff + +#endif /* __IBUS_KEYSYMS_H__ */ diff --git a/src/ibuslookuptable.c b/src/ibuslookuptable.c new file mode 100644 index 0000000..aab3ecd --- /dev/null +++ b/src/ibuslookuptable.c @@ -0,0 +1,283 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibuslookuptable.h" + +/* functions prototype */ +static void ibus_lookup_table_class_init (IBusLookupTableClass *klass); +static void ibus_lookup_table_init (IBusLookupTable *table); +static void ibus_lookup_table_destroy (IBusLookupTable *table); +static gboolean ibus_lookup_table_serialize (IBusLookupTable *table, + IBusMessageIter *iter); +static gboolean ibus_lookup_table_deserialize (IBusLookupTable *table, + IBusMessageIter *iter); +static gboolean ibus_lookup_table_copy (IBusLookupTable *dest, + IBusLookupTable *src); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_lookup_table_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusLookupTableClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_lookup_table_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusLookupTable), + 0, + (GInstanceInitFunc) ibus_lookup_table_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusLookupTable", + &type_info, + 0); + } + + return type; +} + +static void +ibus_lookup_table_class_init (IBusLookupTableClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_lookup_table_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_lookup_table_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_lookup_table_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_lookup_table_copy; + + g_string_append (serializable_class->signature, "uubav"); +} + +static void +ibus_lookup_table_init (IBusLookupTable *table) +{ + table->candidates = g_array_new (TRUE, TRUE, sizeof (IBusText *)); +} + +static void +ibus_lookup_table_destroy (IBusLookupTable *table) +{ + IBusText **sp, **p; + + if (table->candidates != NULL) { + p = sp = (IBusText **) g_array_free (table->candidates, FALSE); + table->candidates = NULL; + while (*p != NULL) { + g_object_unref (*p); + p ++; + } + g_free (sp); + } + + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *) table); +} + +static gboolean +ibus_lookup_table_serialize (IBusLookupTable *table, + IBusMessageIter *iter) +{ + IBusMessageIter array_iter; + gboolean retval; + guint i; + + retval = parent_class->serialize ((IBusSerializable *)table, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_LOOKUP_TABLE (table), FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &table->page_size); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &table->cursor_pos); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_BOOLEAN, &table->cursor_visible); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_open_container (iter, + IBUS_TYPE_ARRAY, + "v", + &array_iter); + g_return_val_if_fail (retval, FALSE); + + for (i = 0;; i++) { + IBusText *text; + + text = ibus_lookup_table_get_candidate (table, i); + if (text == NULL) + break; + + retval = ibus_message_iter_append (&array_iter, IBUS_TYPE_TEXT, &text); + g_return_val_if_fail (retval, FALSE); + } + + retval = ibus_message_iter_close_container (iter, &array_iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_lookup_table_deserialize (IBusLookupTable *table, + IBusMessageIter *iter) +{ + DBusMessageIter array_iter; + gboolean retval; + + retval = parent_class->deserialize ((IBusSerializable *)table, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_LOOKUP_TABLE (table), FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &table->page_size); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &table->cursor_pos); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_BOOLEAN, &table->cursor_visible); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_ARRAY, &array_iter); + g_return_val_if_fail (retval, FALSE); + + while (ibus_message_iter_get_arg_type (&array_iter) != G_TYPE_INVALID) { + IBusText *text; + retval = ibus_message_iter_get (&array_iter, IBUS_TYPE_TEXT, &text); + g_return_val_if_fail (retval, FALSE); + + ibus_lookup_table_append_candidate (table, text); + } + + ibus_message_iter_next (iter); + + return TRUE; +} + +static gboolean +ibus_lookup_table_copy (IBusLookupTable *dest, + IBusLookupTable *src) +{ + gboolean retval; + guint i; + + retval = parent_class->copy ((IBusSerializable *)dest, (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_LOOKUP_TABLE (dest), FALSE); + g_return_val_if_fail (IBUS_IS_LOOKUP_TABLE (src), FALSE); + + for (i = 0;; i++) { + IBusText *text; + + text = ibus_lookup_table_get_candidate (src, i); + if (text == NULL) + break; + + text = (IBusText *) ibus_serializable_copy ((IBusSerializable *) text); + + ibus_lookup_table_append_candidate (dest, text); + g_object_unref (text); + } + + return TRUE; +} + +IBusLookupTable * +ibus_lookup_table_new (guint page_size, + gboolean cursor_visible) +{ + IBusLookupTable *table; + + table= g_object_new (IBUS_TYPE_LOOKUP_TABLE, NULL); + + table->cursor_pos = 0; + table->page_size = page_size; + table->cursor_visible = cursor_visible; + + return table; +} + +void +ibus_lookup_table_append_candidate (IBusLookupTable *table, + IBusText *text) +{ + g_return_if_fail (IBUS_IS_LOOKUP_TABLE (table)); + g_return_if_fail (IBUS_IS_TEXT (text)); + + g_object_ref (text); + g_array_append_val (table->candidates, text); +} + +IBusText * +ibus_lookup_table_get_candidate (IBusLookupTable *table, + guint index) +{ + g_return_val_if_fail (IBUS_IS_LOOKUP_TABLE (table), NULL); + + if (index >= table->candidates->len) + return NULL; + + return g_array_index (table->candidates, IBusText *, index); +} + + +void +ibus_lookup_table_clear (IBusLookupTable *table) +{ + g_return_if_fail (IBUS_IS_LOOKUP_TABLE (table)); + + gint index; + + for (index = 0; index < table->candidates->len; index ++) { + g_object_unref (g_array_index (table->candidates, IBusText *, index)); + } + + g_array_set_size (table->candidates, 0); +} + +void +ibus_lookup_table_set_cursor_pos (IBusLookupTable *table, + guint cursor_pos) +{ + g_assert (IBUS_IS_LOOKUP_TABLE (table)); + + table->cursor_pos = cursor_pos; +} +void +ibus_lookup_table_set_page_size (IBusLookupTable *table, + guint page_size) +{ + g_assert (IBUS_IS_LOOKUP_TABLE (table)); + + table->page_size = page_size; +} + diff --git a/src/ibuslookuptable.h b/src/ibuslookuptable.h new file mode 100644 index 0000000..2b29138 --- /dev/null +++ b/src/ibuslookuptable.h @@ -0,0 +1,82 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_LOOKUP_TABLE_H_ +#define __IBUS_LOOKUP_TABLE_H_ + +#include "ibusserializable.h" +#include "ibustext.h" + +/* + * Type macros. + */ +/* define IBusLookupTable macros */ +#define IBUS_TYPE_LOOKUP_TABLE \ + (ibus_lookup_table_get_type ()) +#define IBUS_LOOKUP_TABLE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_LOOKUP_TABLE, IBusLookupTable)) +#define IBUS_LOOKUP_TABLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_LOOKUP_TABLE, IBusLookupTableClass)) +#define IBUS_IS_LOOKUP_TABLE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_LOOKUP_TABLE)) +#define IBUS_IS_LOOKUP_TABLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_LOOKUP_TABLE)) +#define IBUS_LOOKUP_TABLE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_LOOKUP_TABLE, IBusLookupTableClass)) + + +G_BEGIN_DECLS + +typedef struct _IBusLookupTable IBusLookupTable; +typedef struct _IBusLookupTableClass IBusLookupTableClass; + +struct _IBusLookupTable { + IBusSerializable parent; + + guint page_size; + guint cursor_pos; + gboolean cursor_visible; + + GArray *candidates; +}; + +struct _IBusLookupTableClass { + IBusSerializableClass parent; +}; + + +GType ibus_lookup_table_get_type (void); +IBusLookupTable *ibus_lookup_table_new (guint page_size, + gboolean cursor_visible); +void ibus_lookup_table_append_candidate + (IBusLookupTable *table, + IBusText *text); +IBusText *ibus_lookup_table_get_candidate + (IBusLookupTable *table, + guint index); +void ibus_lookup_table_set_cursor_pos + (IBusLookupTable *table, + guint cursor_pos); +void ibus_lookup_table_set_page_size + (IBusLookupTable *table, + guint page_size); +void ibus_lookup_table_clear (IBusLookupTable *table); +G_END_DECLS +#endif + diff --git a/src/ibusmarshalers.list b/src/ibusmarshalers.list new file mode 100644 index 0000000..14def28 --- /dev/null +++ b/src/ibusmarshalers.list @@ -0,0 +1,18 @@ +VOID:NONE +VOID:OBJECT +VOID:POINTER +VOID:STRING +VOID:STRING,INT +BOOL:POINTER +BOOL:POINTER,POINTER +BOOL:UINT,UINT +VOID:INT,INT,INT,INT +VOID:UINT,UINT +VOID:OBJECT,UINT,BOOL +VOID:OBJECT,BOOL +VOID:BOXED,BOOL +VOID:BOXED +VOID:STRING,STRING,BOXED +VOID:STRING,STRING,STRING +VOID:UINT +VOID:UINT,POINTER diff --git a/src/ibusmessage.c b/src/ibusmessage.c new file mode 100644 index 0000000..08457a3 --- /dev/null +++ b/src/ibusmessage.c @@ -0,0 +1,872 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibusmessage.h" +#include "ibusserializable.h" +#include "ibusconfigprivate.h" + +GType +ibus_type_get_object_path (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_type_register_static_simple ( + G_TYPE_STRING, + "IBusObjectPath", + 0, + NULL, + 0, + NULL, + G_TYPE_FLAG_ABSTRACT); + } + return type; +} + +GType +ibus_type_get_array (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_type_register_static_simple ( + G_TYPE_BOXED, + "IBusArray", + 0, + NULL, + 0, + NULL, + G_TYPE_FLAG_ABSTRACT); + } + return type; +} + +GType +ibus_type_get_struct (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_type_register_static_simple ( + G_TYPE_BOXED, + "IBusStruct", + 0, + NULL, + 0, + NULL, + G_TYPE_FLAG_ABSTRACT); + } + return type; +} + +GType +ibus_type_get_dict_entry (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_type_register_static_simple ( + G_TYPE_BOXED, + "IBusDictEntry", + 0, + NULL, + 0, + NULL, + G_TYPE_FLAG_ABSTRACT); + } + return type; +} + +GType +ibus_type_get_variant (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_type_register_static_simple (G_TYPE_BOXED, + "IBusVariant", + 0, + NULL, + 0, + NULL, + 0); + } + return type; +} + +IBusMessage * +ibus_message_new (gint message_type) +{ + return dbus_message_new (message_type); +} + +IBusMessage * +ibus_message_ref (IBusMessage *message) +{ + return dbus_message_ref (message); +} + +void +ibus_message_unref (IBusMessage *message) +{ + dbus_message_unref (message); +} + +IBusMessage * +ibus_message_new_method_call (const gchar *destination, + const gchar *path, + const gchar *interface, + const gchar *method) +{ + return dbus_message_new_method_call (destination, + path, + interface, + method); +} + +IBusMessage * +ibus_message_new_method_return (IBusMessage *reply_to) +{ + return dbus_message_new_method_return (reply_to); +} + +IBusMessage * +ibus_message_new_error (IBusMessage *reply_to, + const gchar *error_name, + const gchar *error_message) +{ + return dbus_message_new_error (reply_to, + error_name, + error_message); +} + +IBusMessage * +ibus_message_new_error_printf (IBusMessage *reply_to, + const gchar *error_name, + const gchar *error_format, + ...) +{ + va_list va_args; + gchar *error_message; + IBusMessage *message; + + va_start (va_args, error_format); + error_message = g_strdup_vprintf (error_format, va_args); + va_end (va_args); + + message = ibus_message_new_error (reply_to, + error_name, + error_message); + g_free (error_message); + + return message; +} + +IBusMessage * +ibus_message_new_signal (const gchar *path, + const gchar *interface, + const gchar *name) +{ + return dbus_message_new_signal (path, + interface, + name); +} + +gboolean +ibus_message_is_method_call (IBusMessage *message, + const gchar *interface, + const gchar *method) +{ + return dbus_message_is_method_call (message, + interface, + method); +} + +gboolean +ibus_message_is_error (IBusMessage *message, + const gchar *error_name) +{ + return dbus_message_is_error (message, error_name); +} + +gboolean +ibus_message_is_signal (IBusMessage *message, + const gchar *interface, + const gchar *signal_name) +{ + return dbus_message_is_signal (message, + interface, + signal_name); +} + +gboolean +ibus_message_set_destination (IBusMessage *message, + const gchar *destination) +{ + return dbus_message_set_destination (message, destination); +} + +gboolean +ibus_message_set_sender (IBusMessage *message, + const gchar *sender) +{ + return dbus_message_set_sender (message, sender); +} + +gboolean +ibus_message_set_error_name (IBusMessage *message, + const gchar *error_name) +{ + return dbus_message_set_error_name (message, error_name); +} + +gboolean +ibus_message_set_interface (IBusMessage *message, + const gchar *interface) +{ + return dbus_message_set_interface (message, interface); +} + +gboolean +ibus_message_set_member (IBusMessage *message, + const gchar *member) +{ + return dbus_message_set_member (message, member); +} + +gboolean +ibus_message_set_path (IBusMessage *message, + const gchar *path) +{ + return dbus_message_set_path (message, path); +} + +void +ibus_message_set_no_reply (IBusMessage *message, + gboolean no_reply) +{ + return dbus_message_set_no_reply (message, no_reply); +} + +gboolean +ibus_message_set_reply_serial (IBusMessage *message, + guint32 reply_serial) +{ + return dbus_message_set_reply_serial (message, reply_serial); +} + +gint +ibus_message_get_type (IBusMessage *message) +{ + return dbus_message_get_type (message); +} + +const gchar * +ibus_message_get_destination (IBusMessage *message) +{ + return dbus_message_get_destination (message); +} + +const gchar * +ibus_message_get_sender (IBusMessage *message) +{ + return dbus_message_get_sender (message); +} + +const gchar * +ibus_message_get_error_name (IBusMessage *message) +{ + return dbus_message_get_error_name (message); +} + +const gchar * +ibus_message_get_error_message (IBusMessage *message) +{ + gchar *error_message; + gboolean retval; + + retval = ibus_message_get_args (message, NULL, G_TYPE_STRING, &error_message, G_TYPE_INVALID); + + if (retval) + return error_message; + return NULL; +} + +const gchar * +ibus_message_get_interface (IBusMessage *message) +{ + return dbus_message_get_interface (message); +} + +const gchar * +ibus_message_get_member (IBusMessage *message) +{ + return dbus_message_get_member (message); +} + +const gchar * +ibus_message_get_path (IBusMessage *message) +{ + return dbus_message_get_path (message); +} + +gboolean +ibus_message_get_no_reply (IBusMessage *message) +{ + return dbus_message_get_no_reply (message); +} + +guint32 +ibus_message_get_reply_serial (IBusMessage *message) +{ + return dbus_message_get_reply_serial (message); +} + +guint32 +ibus_message_get_serial (IBusMessage *message) +{ + return dbus_message_get_serial (message); +} + +gboolean +ibus_message_append_args (IBusMessage *message, + GType first_arg_type, + ...) +{ + gboolean retval; + va_list va_args; + + va_start (va_args, first_arg_type); + retval = ibus_message_append_args_valist (message, + first_arg_type, + va_args); + va_end (va_args); + + return retval; +} + +gboolean +ibus_message_append_args_valist (IBusMessage *message, + GType first_arg_type, + va_list va_args) +{ + GType type; + gboolean retval; + IBusMessageIter iter; + + ibus_message_iter_init_append (message, &iter); + + type = first_arg_type; + while (type != G_TYPE_INVALID) { + gpointer value = va_arg (va_args, gpointer); + retval = ibus_message_iter_append (&iter, type, value); + type = va_arg (va_args, GType); + + g_return_val_if_fail (retval, FALSE); + } + + return TRUE; +} + +gboolean +ibus_message_get_args (IBusMessage *message, + IBusError **error, + GType first_arg_type, + ...) +{ + gboolean retval; + va_list va_args; + + va_start (va_args, first_arg_type); + retval = ibus_message_get_args_valist (message, + error, + first_arg_type, + va_args); + va_end (va_args); + + return retval; + +} + +gboolean +ibus_message_get_args_valist (IBusMessage *message, + IBusError **error, + GType first_arg_type, + va_list va_args) +{ + g_assert (message != NULL); + + gboolean retval; + IBusMessageIter iter; + GType type; + gpointer value; + va_list backup_args; + gint i; + + retval = ibus_message_iter_init (message, &iter); + + if (!retval) { + if (error) { + *error = ibus_error_new_from_printf (DBUS_ERROR_INVALID_ARGS, + "Message does not have arguments!"); + } + return FALSE; + } + + va_copy (backup_args, va_args); + + i = 0; + type = first_arg_type; + while (type != G_TYPE_INVALID) { + value = va_arg (va_args, gpointer); + retval = ibus_message_iter_get (&iter, type, value); + if (!retval) + goto _failed; + i ++; + type = va_arg (va_args, GType); + } + va_end (backup_args); + + return TRUE; + +_failed: + *error = ibus_error_new_from_printf (DBUS_ERROR_INVALID_ARGS, + "The argument %d is not %s", + i, + g_type_name (type)); + /* release resources */ + type = first_arg_type; + while (i > 0) { + gpointer *value = va_arg (backup_args, gpointer *); + if (g_type_is_a (type, G_TYPE_BOXED)) { + g_boxed_free (type, *value); + } + else if (g_type_is_a (type, G_TYPE_OBJECT)) { + g_object_unref (*value); + } + i --; + type = va_arg (backup_args, GType); + } + va_end (backup_args); + + return FALSE; +} + +void +ibus_message_iter_init_append (IBusMessage *message, + IBusMessageIter *iter) +{ + dbus_message_iter_init_append (message, iter); +} + +gboolean +ibus_message_iter_append (IBusMessageIter *iter, + GType type, + gconstpointer value) +{ + g_assert (iter != NULL); + g_assert (type != G_TYPE_INVALID); + g_assert (value != NULL); + + switch (type) { + case G_TYPE_CHAR: + { + char v; + v = * (gchar *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &v); + } + case G_TYPE_INT: + { + dbus_int32_t v; + v = * (gint *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &v); + } + case G_TYPE_UINT: + { + dbus_uint32_t v; + v = * (guint *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &v); + } + case G_TYPE_ULONG: + { + dbus_uint64_t v; + v = * (gulong *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &v); + } + case G_TYPE_LONG: + { + dbus_int64_t v; + v = * (glong *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &v); + } + case G_TYPE_BOOLEAN: + { + dbus_bool_t v; + v = * (gboolean *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v); + } + case G_TYPE_STRING: + { + const gchar *v; + v = * (gchar **)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &v); + } + case G_TYPE_INT64: + { + dbus_int64_t v; + v = * (gint64 *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &v); + } + case G_TYPE_UINT64: + { + dbus_uint64_t v; + v = * (guint64 *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &v); + } + case G_TYPE_FLOAT: + { + double v; + v = * (gfloat *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &v); + } + + case G_TYPE_DOUBLE: + { + double v; + v = * (gdouble *)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &v); + } + default: + if (type == G_TYPE_VALUE) { + _to_dbus_value (iter, (GValue *)value); + return TRUE; + } + if (type == IBUS_TYPE_OBJECT_PATH) { + const gchar *v; + v = * (gchar **)value; + return dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &v); + } + + if (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE)) { + return ibus_serializable_serialize (*(IBusSerializable **)value, iter); + } + } + + return FALSE; +} + +gboolean +ibus_message_iter_init (IBusMessage *message, + IBusMessageIter *iter) +{ + return dbus_message_iter_init (message, iter); +} + +void +ibus_message_iter_get_basic (IBusMessageIter *iter, + gpointer value) +{ + dbus_message_iter_get_basic (iter, value); + dbus_message_iter_next (iter); +} + +gboolean +ibus_message_iter_get (IBusMessageIter *iter, + GType type, + gpointer value) +{ + gboolean retval; + + retval = ibus_message_iter_peek (iter, type, value); + ibus_message_iter_next (iter); + + return retval; +} + +gboolean +ibus_message_iter_peek (IBusMessageIter *iter, + GType type, + gpointer value) +{ + g_assert (iter != NULL); + g_assert (type != G_TYPE_INVALID); + g_assert (value != NULL); + + switch (type) { + case G_TYPE_CHAR: + { + char v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_BYTE) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gchar *) value = (gchar) v; + return TRUE; + } + case G_TYPE_INT: + { + dbus_int32_t v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INT32) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gint *) value = (gint) v; + return TRUE; + } + case G_TYPE_UINT: + { + dbus_uint32_t v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT32) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(guint *) value = (guint) v; + return TRUE; + } + case G_TYPE_BOOLEAN: + { + dbus_bool_t v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_BOOLEAN) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gboolean *) value = (gboolean) v; + return TRUE; + } + case G_TYPE_STRING: + { + gchar *v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRING) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gchar **) value = (gchar *) v; + return TRUE; + } + case G_TYPE_INT64: + { + dbus_int64_t v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INT64) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gint64 *) value = (gint64) v; + return TRUE; + } + case G_TYPE_UINT64: + { + dbus_uint64_t v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT64) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(guint64 *) value = (guint64) v; + return TRUE; + } + case G_TYPE_FLOAT: + { + double v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_DOUBLE) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gfloat *) value = (gfloat) v; + return TRUE; + } + + case G_TYPE_DOUBLE: + { + double v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_DOUBLE) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gdouble *) value = (gdouble) v; + return TRUE; + } + default: + if (type == G_TYPE_VALUE) { + _from_dbus_value (iter, (GValue *) value); + return TRUE; + } + if (type == IBUS_TYPE_OBJECT_PATH) { + gchar *v; + if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_OBJECT_PATH) + return FALSE; + dbus_message_iter_get_basic (iter, &v); + *(gchar **) value = (gchar *) v; + return TRUE; + } + + if (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE)) { + IBusSerializable *v; + v = ibus_serializable_deserialize (iter); + + if (v == NULL) + return FALSE; + if (!g_type_is_a (G_OBJECT_TYPE (v), type)) { + g_object_unref (v); + return FALSE; + } + *(gpointer *) value = v; + return TRUE; + } + } + return FALSE; +} + +gboolean +ibus_message_iter_next (IBusMessageIter *iter) +{ + return dbus_message_iter_next (iter); +} + +gboolean +ibus_message_iter_has_next (IBusMessageIter *iter) +{ + return dbus_message_iter_has_next (iter); +} + +gboolean +ibus_message_iter_open_container (IBusMessageIter *iter, + GType type, + const gchar *contained_signature, + IBusMessageIter *sub) +{ + gint dbus_type; + + if (type == IBUS_TYPE_ARRAY) { + dbus_type = DBUS_TYPE_ARRAY; + } + else if (type == IBUS_TYPE_STRUCT) { + dbus_type = DBUS_TYPE_STRUCT; + } + else if (type == IBUS_TYPE_DICT_ENTRY) { + dbus_type = DBUS_TYPE_DICT_ENTRY; + } + else if (type == IBUS_TYPE_VARIANT) { + dbus_type = DBUS_TYPE_VARIANT; + } + else + g_return_val_if_reached (FALSE); + + return dbus_message_iter_open_container (iter, + dbus_type, + contained_signature, + sub); +} + +gboolean +ibus_message_iter_close_container (IBusMessageIter *iter, + IBusMessageIter *sub) +{ + return dbus_message_iter_close_container (iter, sub); +} + + +static GType +dbus_type_to_gtype (gint type) +{ + switch (type) { +#define TYPE_TABLE(a, b) case a: return (b); + TYPE_TABLE (DBUS_TYPE_BYTE, G_TYPE_CHAR); + TYPE_TABLE (DBUS_TYPE_INT32, G_TYPE_INT); + TYPE_TABLE (DBUS_TYPE_INT64, G_TYPE_INT64); + TYPE_TABLE (DBUS_TYPE_UINT32, G_TYPE_UINT); + TYPE_TABLE (DBUS_TYPE_UINT64, G_TYPE_UINT64); + TYPE_TABLE (DBUS_TYPE_BOOLEAN, G_TYPE_BOOLEAN); + TYPE_TABLE (DBUS_TYPE_DOUBLE, G_TYPE_DOUBLE); + TYPE_TABLE (DBUS_TYPE_STRING, G_TYPE_STRING); + TYPE_TABLE (DBUS_TYPE_OBJECT_PATH, IBUS_TYPE_OBJECT_PATH); + TYPE_TABLE (DBUS_TYPE_ARRAY, IBUS_TYPE_ARRAY); + TYPE_TABLE (DBUS_TYPE_STRUCT, IBUS_TYPE_STRUCT); + TYPE_TABLE (DBUS_TYPE_DICT_ENTRY, IBUS_TYPE_DICT_ENTRY); + TYPE_TABLE (DBUS_TYPE_VARIANT, IBUS_TYPE_VARIANT); +#undef TYPE_TABLE + } + return G_TYPE_INVALID; +} + + +gboolean +ibus_message_iter_recurse (IBusMessageIter *iter, + GType type, + IBusMessageIter *sub) +{ + g_assert (iter != NULL); + g_assert (sub != NULL); + g_assert (type == IBUS_TYPE_ARRAY || + type == IBUS_TYPE_STRUCT || + type == IBUS_TYPE_DICT_ENTRY || + type == IBUS_TYPE_VARIANT); + GType gtype; + + gtype = ibus_message_iter_get_arg_type (iter); + + g_return_val_if_fail (gtype == type, FALSE); + + dbus_message_iter_recurse (iter, sub); + + return TRUE; +} + +GType +ibus_message_iter_get_arg_type (IBusMessageIter *iter) +{ + gint type; + + type = dbus_message_iter_get_arg_type (iter); + + return dbus_type_to_gtype (type); +} + + +GType +ibus_message_iter_get_element_type (IBusMessageIter *iter) +{ + gint type; + + type = dbus_message_iter_get_element_type (iter); + + return dbus_type_to_gtype (type); +} + +gchar * +ibus_message_to_string (IBusMessage *message) +{ + g_assert (message != NULL); + + GString *string = g_string_new (""); + + IBusMessageIter iter; + GType type; + gint i = 0; + + g_string_append_printf (string, + "message: %d\n" + "\tdestination = %s\n" + "\tpath = %s\n" + "\tinterface = %s\n" + "\tmember = %s\n", + ibus_message_get_type (message), + ibus_message_get_destination (message), + ibus_message_get_path (message), + ibus_message_get_interface (message), + ibus_message_get_member (message)); + + ibus_message_iter_init (message, &iter); + while ((type = ibus_message_iter_get_arg_type (&iter)) != G_TYPE_INVALID) { + g_string_append_printf (string, "\t\targ%d is %s\n", i++, g_type_name (type)); + ibus_message_iter_next (&iter); + } + + return g_string_free (string, FALSE); +} + diff --git a/src/ibusmessage.h b/src/ibusmessage.h new file mode 100644 index 0000000..36f4066 --- /dev/null +++ b/src/ibusmessage.h @@ -0,0 +1,146 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_MESSAGE_H_ +#define __IBUS_MESSAGE_H_ + +#include <glib.h> +#include <glib-object.h> +#include <dbus/dbus.h> +#include "ibuserror.h" + +#define IBUS_TYPE_OBJECT_PATH (ibus_type_get_object_path ()) +#define IBUS_TYPE_ARRAY (ibus_type_get_array ()) +#define IBUS_TYPE_STRUCT (ibus_type_get_struct ()) +#define IBUS_TYPE_DICT_ENTRY (ibus_type_get_dict_entry ()) +#define IBUS_TYPE_VARIANT (ibus_type_get_variant ()) + +G_BEGIN_DECLS + +typedef DBusMessage IBusMessage; +typedef DBusMessageIter IBusMessageIter; + +GType ibus_type_get_object_path (void); +GType ibus_type_get_array (void); +GType ibus_type_get_struct (void); +GType ibus_type_get_dict_entry (void); +GType ibus_type_get_variant (void); + +IBusMessage *ibus_message_new (gint message_type); +IBusMessage *ibus_message_ref (IBusMessage *message); +void ibus_message_unref (IBusMessage *message); +IBusMessage *ibus_message_new_method_call (const gchar *destination, + const gchar *path, + const gchar *interface, + const gchar *method); +IBusMessage *ibus_message_new_method_return (IBusMessage *reply_to); +IBusMessage *ibus_message_new_error (IBusMessage *reply_to, + const gchar *error_name, + const gchar *error_message); +IBusMessage *ibus_message_new_error_printf (IBusMessage *reply_to, + const gchar *error_name, + const gchar *error_format, + ...); +IBusMessage *ibus_message_new_signal (const gchar *path, + const gchar *interface, + const gchar *method); +gboolean ibus_message_is_method_call (IBusMessage *message, + const gchar *interface, + const gchar *method); +gboolean ibus_message_is_error (IBusMessage *message, + const gchar *error_name); +gboolean ibus_message_is_signal (IBusMessage *message, + const gchar *interface, + const gchar *signal_name); +gboolean ibus_message_set_destination (IBusMessage *message, + const gchar *destination); +gboolean ibus_message_set_sender (IBusMessage *message, + const gchar *sender); +gboolean ibus_message_set_error_name (IBusMessage *message, + const gchar *error_name); +gboolean ibus_message_set_interface (IBusMessage *message, + const gchar *interface); +gboolean ibus_message_set_member (IBusMessage *message, + const gchar *member); +gboolean ibus_message_set_path (IBusMessage *message, + const gchar *path); +void ibus_message_set_no_reply (IBusMessage *message, + gboolean no_reply); +gboolean ibus_message_set_reply_serial (IBusMessage *message, + guint32 reply_serial); +gint ibus_message_get_type (IBusMessage *message); +const gchar *ibus_message_get_destination (IBusMessage *message); +const gchar *ibus_message_get_sender (IBusMessage *message); +const gchar *ibus_message_get_error_name (IBusMessage *message); +const gchar *ibus_message_get_error_message (IBusMessage *message); +const gchar *ibus_message_get_interface (IBusMessage *message); +const gchar *ibus_message_get_member (IBusMessage *message); +const gchar *ibus_message_get_path (IBusMessage *message); +gboolean ibus_message_get_no_reply (IBusMessage *message); +guint32 ibus_message_get_reply_serial (IBusMessage *message); +guint32 ibus_message_get_serial (IBusMessage *message); +gboolean ibus_message_append_args (IBusMessage *message, + GType first_arg_type, + ...); +gboolean ibus_message_append_args_valist(IBusMessage *message, + GType first_arg_type, + va_list va_args); +gboolean ibus_message_get_args (IBusMessage *message, + IBusError **error, + GType first_arg_type, + ...); +gboolean ibus_message_get_args_valist (IBusMessage *message, + IBusError **error, + GType first_arg_type, + va_list va_args); +void ibus_message_iter_init_append (IBusMessage *message, + IBusMessageIter *iter); +gboolean ibus_message_iter_append (IBusMessageIter *iter, + GType type, + gconstpointer value); +gboolean ibus_message_iter_init (IBusMessage *message, + IBusMessageIter *iter); +gboolean ibus_message_iter_peek (IBusMessageIter *iter, + GType type, + gpointer value); +void ibus_message_iter_get_basic (IBusMessageIter *iter, + gpointer value); +gboolean ibus_message_iter_get (IBusMessageIter *iter, + GType type, + gpointer value); +gboolean ibus_message_iter_next (IBusMessageIter *iter); +gboolean ibus_message_iter_has_next (IBusMessageIter *iter); +gboolean ibus_message_iter_open_container + (IBusMessageIter *iter, + GType type, + const gchar *contained_signature, + IBusMessageIter *sub); +gboolean ibus_message_iter_close_container + (IBusMessageIter *iter, + IBusMessageIter *sub); +gboolean ibus_message_iter_recurse (IBusMessageIter *iter, + GType type, + IBusMessageIter *sub); +GType ibus_message_iter_get_arg_type (IBusMessageIter *iter); +GType ibus_message_iter_get_element_type + (IBusMessageIter *iter); +gchar *ibus_message_to_string (IBusMessage *message); + +G_END_DECLS +#endif diff --git a/src/ibusobject.c b/src/ibusobject.c new file mode 100644 index 0000000..2c2c25a --- /dev/null +++ b/src/ibusobject.c @@ -0,0 +1,189 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibusobject.h" +#include "ibusinternal.h" + +#define IBUS_OBJECT_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_OBJECT, IBusObjectPrivate)) + +enum { + DESTROY, + LAST_SIGNAL, +}; + +typedef struct _IBusObjectPrivate IBusObjectPrivate; +struct _IBusObjectPrivate { + gpointer pad; +}; + +static guint object_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_object_class_init (IBusObjectClass *klass); +static void ibus_object_init (IBusObject *obj); +static GObject *ibus_object_constructor (GType type, + guint n, + GObjectConstructParam + *args); +static void ibus_object_dispose (IBusObject *obj); +static void ibus_object_finalize (IBusObject *obj); +static void ibus_object_real_destroy (IBusObject *obj); + +static GObjectClass *parent_class = NULL; + + +GType +ibus_object_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusObjectClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_object_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusObject), + 0, + (GInstanceInitFunc) ibus_object_init, + }; + + if (type == 0) { + type = g_type_register_static (G_TYPE_OBJECT, + "IBusObject", + &type_info, + G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +/** + * ibus_object_new: + * + * Creates a new instance of an #IBusObject. + * + * Returns: a new instance of #IBusObject. + */ +IBusObject * +ibus_object_new (void) +{ + return IBUS_OBJECT (g_object_new (IBUS_TYPE_OBJECT, NULL)); +} + +static void +ibus_object_class_init (IBusObjectClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + parent_class = (GObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusObjectPrivate)); + + gobject_class->constructor = ibus_object_constructor; + gobject_class->dispose = (GObjectFinalizeFunc) ibus_object_dispose; + gobject_class->finalize = (GObjectFinalizeFunc) ibus_object_finalize; + + klass->destroy = ibus_object_real_destroy; + + /* install signals */ + object_signals[DESTROY] = + g_signal_new (I_("destroy"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusObjectClass, destroy), + NULL, NULL, + ibus_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +ibus_object_init (IBusObject *obj) +{ + IBusObjectPrivate *priv; + priv = IBUS_OBJECT_GET_PRIVATE (obj); + + obj->flags = 0; +} + + +static GObject * +ibus_object_constructor (GType type, + guint n, + GObjectConstructParam *args) +{ + GObject *object; + + object = parent_class->constructor (type, n ,args); + + return object; +} + + +static void +ibus_object_dispose (IBusObject *obj) +{ + if (! (IBUS_OBJECT_FLAGS (obj) & IBUS_IN_DESTRUCTION)) { + IBUS_OBJECT_SET_FLAGS (obj, IBUS_IN_DESTRUCTION); + if (! (IBUS_OBJECT_FLAGS (obj) & IBUS_DESTROYED)) { + g_signal_emit (obj, object_signals[DESTROY], 0); + IBUS_OBJECT_SET_FLAGS (obj, IBUS_DESTROYED); + } + IBUS_OBJECT_UNSET_FLAGS (obj, IBUS_IN_DESTRUCTION); + } + + G_OBJECT_CLASS(parent_class)->dispose (G_OBJECT (obj)); +} + +static void +ibus_object_finalize (IBusObject *obj) +{ + G_OBJECT_CLASS(parent_class)->finalize (G_OBJECT (obj)); +} + +static void +ibus_object_real_destroy (IBusObject *obj) +{ + g_signal_handlers_destroy (obj); +} + +/** + * ibus_object_destroy: + * @object: an #IBusObject to destroy. + * + * Emit the "destory" signal notifying all reference holders that they should + * release the #IBusObject. + * + * The memory for the object itself won't be deleted until its reference count + * actually drops to 0; ibus_object_destroy merely asks reference holders to + * release their references. it does not free the object. + */ +void +ibus_object_destroy (IBusObject *obj) +{ + IBusObjectPrivate *priv; + priv = IBUS_OBJECT_GET_PRIVATE (obj); + + if (! (IBUS_OBJECT_FLAGS (obj) & IBUS_IN_DESTRUCTION)) { + g_object_run_dispose (G_OBJECT (obj)); + } +} diff --git a/src/ibusobject.h b/src/ibusobject.h new file mode 100644 index 0000000..2c09882 --- /dev/null +++ b/src/ibusobject.h @@ -0,0 +1,92 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_OBJECT_H_ +#define __IBUS_OBJECT_H_ + +#include <glib-object.h> +#include "ibusmarshalers.h" +#include "ibustypes.h" +#include "ibusdebug.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_OBJECT \ + (ibus_object_get_type ()) +#define IBUS_OBJECT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_OBJECT, IBusObject)) +#define IBUS_OBJECT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_OBJECT, IBusObjectClass)) +#define IBUS_IS_OBJECT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_OBJECT)) +#define IBUS_IS_OBJECT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_OBJECT)) +#define IBUS_OBJECT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_OBJECT, IBusObjectClass)) + +typedef enum { + IBUS_IN_DESTRUCTION = (1 << 0), + IBUS_DESTROYED = (1 << 1), + IBUS_RESERVED_1 = (1 << 2), + IBUS_RESERVED_2 = (1 << 3), +} IBusObjectFlags; + +#define IBUS_OBJECT_FLAGS(obj) (IBUS_OBJECT (obj)->flags) +#define IBUS_OBJECT_SET_FLAGS(obj,flag) G_STMT_START{ (IBUS_OBJECT_FLAGS (obj) |= (flag)); }G_STMT_END +#define IBUS_OBJECT_UNSET_FLAGS(obj,flag) G_STMT_START{ (IBUS_OBJECT_FLAGS (obj) &= ~(flag)); }G_STMT_END + +G_BEGIN_DECLS + +typedef struct _IBusObject IBusObject; +typedef struct _IBusObjectClass IBusObjectClass; +/** + * IBusObject: + * + * All the fields in the <structname>IBusObject</structname> structure are + * prtivate to the #IBusObject and should never be accessed directly. + */ +struct _IBusObject { + GObject parent; + /* instance members */ + guint32 flags; +}; + +typedef void ( *IBusObjectDestroyFunc) (IBusObject *); + +struct _IBusObjectClass { + GObjectClass parent; + + /* signals */ + void (* destroy) (IBusObject *object); + + /*< private >*/ + /* padding */ + gpointer pdummy[7]; +}; + +GType ibus_object_get_type (void); +IBusObject *ibus_object_new (void); +void ibus_object_destroy (IBusObject *object); + +G_END_DECLS +#endif + diff --git a/src/ibusobservedpath.c b/src/ibusobservedpath.c new file mode 100644 index 0000000..4dea00b --- /dev/null +++ b/src/ibusobservedpath.c @@ -0,0 +1,335 @@ +/* vim:set et sts=4: */ +/* ibus - The Input IBus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 <glib/gstdio.h> +#include <stdlib.h> +#include "ibusobservedpath.h" + + +enum { + LAST_SIGNAL, +}; + + +/* IBusObservedPathPriv */ +struct _IBusObservedPathPrivate { + gpointer pad; +}; +typedef struct _IBusObservedPathPrivate IBusObservedPathPrivate; + +#define IBUS_OBSERVED_PATH_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_OBSERVED_PATH, IBusObservedPathPrivate)) + +// static guint _signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_observed_path_class_init (IBusObservedPathClass *klass); +static void ibus_observed_path_init (IBusObservedPath *path); +static void ibus_observed_path_destroy (IBusObservedPath *path); +static gboolean ibus_observed_path_serialize (IBusObservedPath *path, + IBusMessageIter *iter); +static gboolean ibus_observed_path_deserialize (IBusObservedPath *path, + IBusMessageIter *iter); +static gboolean ibus_observed_path_copy (IBusObservedPath *dest, + const IBusObservedPath *src); +static gboolean ibus_observed_path_parse_xml_node (IBusObservedPath *path, + XMLNode *node); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_observed_path_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusObservedPathClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_observed_path_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusObservedPath), + 0, + (GInstanceInitFunc) ibus_observed_path_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusObservedPath", + &type_info, + (GTypeFlags)0); + } + + return type; +} + + +static void +ibus_observed_path_class_init (IBusObservedPathClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + // g_type_class_add_private (klass, sizeof (IBusObservedPathPrivate)); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_observed_path_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_observed_path_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_observed_path_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_observed_path_copy; + + g_string_append (serializable_class->signature, "sx"); +} + + +static void +ibus_observed_path_init (IBusObservedPath *path) +{ + path->path = NULL; +} + +static void +ibus_observed_path_destroy (IBusObservedPath *path) +{ + g_free (path->path); + IBUS_OBJECT_CLASS (parent_class)->destroy (IBUS_OBJECT (path)); +} + +static gboolean +ibus_observed_path_serialize (IBusObservedPath *path, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *)path, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &(path->path)); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_LONG, &(path->mtime)); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_observed_path_deserialize (IBusObservedPath *path, + IBusMessageIter *iter) +{ + gboolean retval; + gchar *str; + + retval = parent_class->deserialize ((IBusSerializable *)path, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + path->path = g_strdup (str); + + retval = ibus_message_iter_get (iter, G_TYPE_LONG, &(path->mtime)); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_observed_path_copy (IBusObservedPath *dest, + const IBusObservedPath *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + dest->path = g_strdup (src->path); + dest->mtime = src->mtime; + + return TRUE; +} + +#define g_string_append_indent(string, indent) \ + { \ + gint i; \ + for (i = 0; i < (indent); i++) { \ + g_string_append (string, " "); \ + } \ + } + +void +ibus_observed_path_output (IBusObservedPath *path, + GString *output, + gint indent) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + g_assert (output); + + g_string_append_indent (output, indent); + g_string_append_printf (output, "<path mtime=\"%ld\" >%s</path>\n", + path->mtime, + path->path); +} + +gboolean +ibus_observed_path_check_modification (IBusObservedPath *path) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + struct stat buf; + + if (g_stat (path->path, &buf) != 0) { + buf.st_mtime = 0; + } + + if (path->mtime == buf.st_mtime) + return FALSE; + return TRUE; +} + +static void +ibus_observed_path_fill_stat (IBusObservedPath *path) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + + struct stat buf; + + if (g_stat (path->path, &buf) == 0) { + path->is_exist = 1; + if (S_ISDIR (buf.st_mode)) { + path->is_dir = 1; + } + path->mtime = buf.st_mtime; + } + else { + path->is_dir = 0; + path->is_exist = 0; + path->mtime = 0; + } +} + +GList * +ibus_observed_path_traverse (IBusObservedPath *path) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + + GDir *dir; + const gchar *name; + GList *paths = NULL; + + dir = g_dir_open (path->path, 0, NULL); + + if (dir == NULL) + return NULL; + + while ((name = g_dir_read_name (dir)) != NULL) { + IBusObservedPath *sub; + + sub = g_object_new (IBUS_TYPE_OBSERVED_PATH, NULL); + sub->path = g_build_filename (path->path, name, NULL); + + ibus_observed_path_fill_stat (sub); + paths = g_list_append (paths, sub); + + if (sub->is_exist && sub->is_dir) + paths = g_list_concat (paths, ibus_observed_path_traverse (sub)); + } + g_dir_close (dir); + + return paths; +} + +static gboolean +ibus_observed_path_parse_xml_node (IBusObservedPath *path, + XMLNode *node) +{ + g_assert (IBUS_IS_OBSERVED_PATH (path)); + g_assert (node); + + if (G_UNLIKELY (g_strcmp0 (node->name, "path") != 0)) { + return FALSE; + } + + if (node->text[0] == '~' && node->text[1] != G_DIR_SEPARATOR) { + g_warning ("invalide path \"%s\"", node->text); + return FALSE; + } + + if (node->text[0] == '~') { + const gchar *homedir = g_getenv ("HOME"); + if (homedir == NULL) + homedir = g_get_home_dir (); + path->path = g_build_filename (homedir, node->text + 2, NULL); + } + else { + path->path = g_strdup (node->text); + } + + gchar **attr; + for (attr = node->attributes; attr[0]; attr += 2) { + if (g_strcmp0 (*attr, "mtime") == 0) { + path->mtime = atol (attr[1]); + continue; + } + g_warning ("Unkonwn attribute %s", attr[0]); + } + + return TRUE; +} + +IBusObservedPath * +ibus_observed_path_new_from_xml_node (XMLNode *node, + gboolean fill_stat) +{ + g_assert (node); + + IBusObservedPath *path; + + path = (IBusObservedPath *) g_object_new (IBUS_TYPE_OBSERVED_PATH, NULL); + + if (!ibus_observed_path_parse_xml_node (path, node)) { + g_object_unref (path); + path = NULL; + } + else if (fill_stat) { + ibus_observed_path_fill_stat (path); + } + + return path; +} + +IBusObservedPath * +ibus_observed_path_new (const gchar *path, + gboolean fill_stat) +{ + g_assert (path); + + IBusObservedPath *op; + + op = (IBusObservedPath *) g_object_new (IBUS_TYPE_OBSERVED_PATH, NULL); + op->path = g_strdup (path); + + if (fill_stat) { + ibus_observed_path_fill_stat (op); + } + + return op; +} + diff --git a/src/ibusobservedpath.h b/src/ibusobservedpath.h new file mode 100644 index 0000000..4ebd625 --- /dev/null +++ b/src/ibusobservedpath.h @@ -0,0 +1,79 @@ +/* vim:set et sts=4: */ +/* ibus - The Input IBus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_OBSERVED_PATH_H_ +#define __IBUS_OBSERVED_PATH_H_ + +#include "ibusserializable.h" +#include "ibusxml.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_OBSERVED_PATH \ + (ibus_observed_path_get_type ()) +#define IBUS_OBSERVED_PATH(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_OBSERVED_PATH, IBusObservedPath)) +#define IBUS_OBSERVED_PATH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_OBSERVED_PATH, IBusObservedPathClass)) +#define IBUS_IS_OBSERVED_PATH(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_OBSERVED_PATH)) +#define IBUS_IS_OBSERVED_PATH_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_OBSERVED_PATH)) +#define IBUS_OBSERVED_PATH_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_OBSERVED_PATH, IBusObservedPathClass)) + +G_BEGIN_DECLS + +typedef struct _IBusObservedPath IBusObservedPath; +typedef struct _IBusObservedPathClass IBusObservedPathClass; + +struct _IBusObservedPath { + IBusSerializable parent; + /* instance members */ + + gchar *path; + glong mtime; + gboolean is_dir; + gboolean is_exist; + +}; + +struct _IBusObservedPathClass { + IBusSerializableClass parent; + + /* class members */ +}; + +GType ibus_observed_path_get_type (void); +IBusObservedPath *ibus_observed_path_new_from_xml_node (XMLNode *node, + gboolean fill_stat); +IBusObservedPath *ibus_observed_path_new (const gchar *path, + gboolean fill_stat); +GList *ibus_observed_path_traverse (IBusObservedPath *path); +gboolean ibus_observed_path_check_modification (IBusObservedPath *path); +void ibus_observed_path_output (IBusObservedPath *path, + GString *output, + gint indent); + +G_END_DECLS +#endif + diff --git a/src/ibuspendingcall.c b/src/ibuspendingcall.c new file mode 100644 index 0000000..2812dbf --- /dev/null +++ b/src/ibuspendingcall.c @@ -0,0 +1,103 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibuspendingcall.h" + +IBusPendingCall* +ibus_pending_call_ref (IBusPendingCall *pending) +{ + return dbus_pending_call_ref (pending); +} + +void +ibus_pending_call_unref (IBusPendingCall *pending) +{ + dbus_pending_call_unref (pending); +} + +gboolean +ibus_pending_call_set_notify (IBusPendingCall *pending, + IBusPendingCallNotifyFunction function, + gpointer user_data, + GDestroyNotify free_user_data) +{ + return dbus_pending_call_set_notify (pending, function, user_data, free_user_data); +} + +void +ibus_pending_call_cancel (IBusPendingCall *pending) +{ + dbus_pending_call_cancel (pending); +} + +gboolean +ibus_pending_call_get_completed (IBusPendingCall *pending) +{ + return dbus_pending_call_get_completed (pending); +} + +IBusMessage* +ibus_pending_call_steal_reply (IBusPendingCall *pending) +{ + return dbus_pending_call_steal_reply (pending); +} + +void +ibus_pending_call_block (IBusPendingCall *pending) +{ + return dbus_pending_call_block (pending); +} + +void +ibus_pending_call_wait (IBusPendingCall *pending) +{ + g_assert (pending); + + while (!ibus_pending_call_get_completed (pending)) { + g_main_context_iteration (NULL, TRUE); + } +} + +gboolean +ibus_pending_call_allocate_data_slot (gint *slot_p) +{ + return dbus_pending_call_allocate_data_slot (slot_p); +} + +void +ibus_pending_call_free_data_slot (gint *slot_p) +{ + dbus_pending_call_free_data_slot (slot_p); +} + +gboolean +ibus_pending_call_set_data (IBusPendingCall *pending, + gint slot, + gpointer data, + GDestroyNotify free_data_func) +{ + return dbus_pending_call_set_data (pending, slot, data, free_data_func); +} + +gpointer +ibus_pending_call_get_data (IBusPendingCall *pending, + gint slot) +{ + return dbus_pending_call_get_data (pending, slot); +} diff --git a/src/ibuspendingcall.h b/src/ibuspendingcall.h new file mode 100644 index 0000000..ff76df6 --- /dev/null +++ b/src/ibuspendingcall.h @@ -0,0 +1,56 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_PENDING_CALL_H_ +#define __IBUS_PENDING_CALL_H_ + +#include <glib.h> +#include <dbus/dbus.h> +#include "ibusmessage.h" + +G_BEGIN_DECLS + +typedef DBusPendingCall IBusPendingCall; +typedef void (* IBusPendingCallNotifyFunction)(IBusPendingCall *pending, gpointer user_data); + + +IBusPendingCall* ibus_pending_call_ref (IBusPendingCall *pending); +void ibus_pending_call_unref (IBusPendingCall *pending); +gboolean ibus_pending_call_set_notify (IBusPendingCall *pending, + IBusPendingCallNotifyFunction function, + gpointer user_data, + GDestroyNotify free_user_data); +void ibus_pending_call_cancel (IBusPendingCall *pending); +gboolean ibus_pending_call_get_completed (IBusPendingCall *pending); +IBusMessage* ibus_pending_call_steal_reply (IBusPendingCall *pending); +void ibus_pending_call_block (IBusPendingCall *pending); +void ibus_pending_call_wait (IBusPendingCall *pending); +gboolean ibus_pending_call_allocate_data_slot + (gint *slot_p); +void ibus_pending_call_free_data_slot + (gint *slot_p); +gboolean ibus_pending_call_set_data (IBusPendingCall *pending, + gint slot, + gpointer data, + GDestroyNotify free_data_func); +gpointer ibus_pending_call_get_data (IBusPendingCall *pending, + gint slot); + +G_END_DECLS +#endif diff --git a/src/ibusproperty.c b/src/ibusproperty.c new file mode 100644 index 0000000..712bf1f --- /dev/null +++ b/src/ibusproperty.c @@ -0,0 +1,531 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibusproperty.h" + +/* functions prototype */ +static void ibus_property_class_init (IBusPropertyClass *klass); +static void ibus_property_init (IBusProperty *prop); +static void ibus_property_destroy (IBusProperty *prop); +static gboolean ibus_property_serialize (IBusProperty *prop, + IBusMessageIter *iter); +static gboolean ibus_property_deserialize (IBusProperty *prop, + IBusMessageIter *iter); +static gboolean ibus_property_copy (IBusProperty *dest, + const IBusProperty *src); + +static void ibus_prop_list_class_init (IBusPropListClass *klass); +static void ibus_prop_list_init (IBusPropList *prop_list); +static void ibus_prop_list_destroy (IBusPropList *prop_list); +static gboolean ibus_prop_list_serialize (IBusPropList *prop_list, + IBusMessageIter *iter); +static gboolean ibus_prop_list_deserialize (IBusPropList *prop_list, + IBusMessageIter *iter); +static gboolean ibus_prop_list_copy (IBusPropList *dest, + const IBusPropList *src); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_property_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusPropertyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_property_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusProperty), + 0, + (GInstanceInitFunc) ibus_property_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusProperty", + &type_info, + 0); + } + + return type; +} + +static void +ibus_property_class_init (IBusPropertyClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_property_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_property_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_property_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_property_copy; + + g_string_append (serializable_class->signature, "suvsvbbuv"); +} + +static void +ibus_property_init (IBusProperty *prop) +{ + prop->key = NULL; + prop->type = 0; + prop->label = NULL; + prop->icon = NULL; + prop->tooltip = NULL; + prop->sensitive = FALSE; + prop->visible = FALSE; + prop->state = 0; +} + +static void +ibus_property_destroy (IBusProperty *prop) +{ + g_free (prop->key); + g_free (prop->icon); + + prop->key = NULL; + prop->icon = NULL; + + if (prop->label) { + g_object_unref (prop->label); + prop->label = NULL; + } + + if (prop->tooltip) { + g_object_unref (prop->tooltip); + prop->tooltip = NULL; + } + + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)prop); +} + +gboolean +ibus_property_serialize (IBusProperty *prop, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *) prop, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_PROPERTY (prop), FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &prop->key); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &prop->type); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, IBUS_TYPE_TEXT, &prop->label); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &prop->icon); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, IBUS_TYPE_TEXT, &prop->tooltip); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_BOOLEAN, &prop->sensitive); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_BOOLEAN, &prop->visible); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_UINT, &prop->state); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, IBUS_TYPE_PROP_LIST, &prop->sub_props); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_property_deserialize (IBusProperty *prop, + IBusMessageIter *iter) +{ + gboolean retval; + gchar *p; + + retval = parent_class->deserialize ((IBusSerializable *) prop, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &p); + g_return_val_if_fail (retval, FALSE); + prop->key = g_strdup (p); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &prop->type); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, IBUS_TYPE_TEXT, &prop->label); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &p); + g_return_val_if_fail (retval, FALSE); + prop->icon = g_strdup (p); + + retval = ibus_message_iter_get (iter, IBUS_TYPE_TEXT, &prop->tooltip); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_BOOLEAN, &prop->sensitive); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_BOOLEAN, &prop->visible); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_UINT, &prop->state); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, IBUS_TYPE_PROP_LIST, &prop->sub_props); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_property_copy (IBusProperty *dest, + const IBusProperty *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *) dest, (IBusSerializable *) src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_PROPERTY (dest), FALSE); + g_return_val_if_fail (IBUS_IS_PROPERTY (src), FALSE); + + dest->key = g_strdup (src->key); + dest->icon = g_strdup (src->icon); + if (src->label) { + dest->label = (IBusText *) ibus_serializable_copy ((IBusSerializable *) src->label); + } + else + dest->label = ibus_text_new_from_static_string (""); + if (src->tooltip) { + dest->tooltip = (IBusText *) ibus_serializable_copy ((IBusSerializable *) src->tooltip); + } + else + dest->tooltip = ibus_text_new_from_static_string (""); + + dest->sensitive = src->sensitive; + dest->visible = src->visible; + dest->type = src->type; + dest->state = src->state; + + dest->sub_props = (IBusPropList *) ibus_serializable_copy ((IBusSerializable *) src->sub_props); + + return TRUE; +} + +IBusProperty * +ibus_property_new (const gchar *key, + IBusPropType type, + IBusText *label, + const gchar *icon, + IBusText *tooltip, + gboolean sensitive, + gboolean visible, + IBusPropState state, + IBusPropList *prop_list) +{ + g_return_val_if_fail (key != NULL, NULL); + g_return_val_if_fail (type >= PROP_TYPE_NORMAL && + type <= PROP_TYPE_SEPARATOR, + NULL); + g_return_val_if_fail (label == NULL || IBUS_IS_TEXT (label), NULL); + g_return_val_if_fail (tooltip == NULL || IBUS_IS_TEXT (tooltip), NULL); + g_return_val_if_fail (state == PROP_STATE_UNCHECKED || + state == PROP_STATE_CHECKED || + state == PROP_STATE_INCONSISTENT, + NULL); + + IBusProperty *prop; + + prop = (IBusProperty *)g_object_new (IBUS_TYPE_PROPERTY, 0); + + prop->key = g_strdup (key); + prop->icon = g_strdup (icon != NULL ? icon : ""); + prop->type = type; + + if (label) + prop->label = (IBusText *) g_object_ref (label); + else + prop->label = ibus_text_new_from_static_string (""); + + if (tooltip) + prop->tooltip = (IBusText *) g_object_ref (tooltip); + else + prop->tooltip = ibus_text_new_from_static_string (""); + + prop->sensitive = sensitive; + prop->visible = visible; + prop->state = state; + + if (prop_list) + prop->sub_props = g_object_ref (prop_list); + else + prop->sub_props = ibus_prop_list_new (); + + return prop; +} + +void +ibus_property_set_label (IBusProperty *prop, + IBusText *label) +{ + g_assert (IBUS_IS_PROPERTY (prop)); + + if (prop->label) { + g_object_unref (prop->label); + } + + if (label == NULL) { + label = ibus_text_new_from_static_string (""); + } + + prop->label = g_object_ref (label); +} + +void +ibus_property_set_visible (IBusProperty *prop, + gboolean visible) +{ + g_assert (IBUS_IS_PROPERTY (prop)); + prop->visible = visible; +} + +void +ibus_property_set_sub_props (IBusProperty *prop, + IBusPropList *prop_list) +{ + g_return_if_fail (IBUS_IS_PROPERTY (prop)); + g_return_if_fail (IBUS_IS_PROP_LIST (prop_list) || prop_list == NULL); + + if (prop->sub_props) { + g_object_unref (prop->sub_props); + } + + if (prop_list) { + g_object_ref (prop_list); + prop->sub_props = prop_list; + } + else + prop->sub_props = ibus_prop_list_new (); +} + +GType +ibus_prop_list_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusPropListClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_prop_list_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusProperty), + 0, + (GInstanceInitFunc) ibus_prop_list_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusPropList", + &type_info, + 0); + } + + return type; +} + +static void +ibus_prop_list_class_init (IBusPropListClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_prop_list_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_prop_list_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_prop_list_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_prop_list_copy; + + g_string_append (serializable_class->signature, "av"); +} + +static void +ibus_prop_list_init (IBusPropList *prop_list) +{ + prop_list->properties = g_array_new (TRUE, TRUE, sizeof (IBusProperty *)); +} + +static void +ibus_prop_list_destroy (IBusPropList *prop_list) +{ + IBusProperty **ps, **p; + p = ps = (IBusProperty **) g_array_free (prop_list->properties, FALSE); + + while (*p != NULL) { + g_object_unref (*p); + p ++; + } + g_free (ps); + + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *) prop_list); +} + +static gboolean +ibus_prop_list_serialize (IBusPropList *prop_list, + IBusMessageIter *iter) +{ + gboolean retval; + IBusMessageIter array_iter; + IBusProperty *prop; + guint i; + + retval = parent_class->serialize ((IBusSerializable *) prop_list, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_open_container (iter, IBUS_TYPE_ARRAY, "v", &array_iter); + g_return_val_if_fail (retval, FALSE); + + i = 0; + + while ((prop = ibus_prop_list_get (prop_list, i)) != NULL) { + retval = ibus_message_iter_append (&array_iter, IBUS_TYPE_PROPERTY, &prop); + g_return_val_if_fail (retval, FALSE); + i ++; + } + + retval = ibus_message_iter_close_container (iter, &array_iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +gboolean +ibus_prop_list_deserialize (IBusPropList *prop_list, + IBusMessageIter *iter) +{ + gboolean retval; + IBusMessageIter array_iter; + IBusSerializable *object; + + retval = parent_class->deserialize ((IBusSerializable *) prop_list, iter); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_PROP_LIST (prop_list), FALSE); + + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_ARRAY, &array_iter); + 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); + g_return_val_if_fail (retval, FALSE); + + ibus_prop_list_append (prop_list, (IBusProperty *)object); + g_object_unref (object); + } + + ibus_message_iter_next (iter); + + return TRUE; +} + + + +static gboolean +ibus_prop_list_copy (IBusPropList *dest, + const IBusPropList *src) +{ + gboolean retval; + IBusProperty *prop; + guint i; + + retval = parent_class->copy ((IBusSerializable *) dest, + (const IBusSerializable *) src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_PROP_LIST (dest), FALSE); + g_return_val_if_fail (IBUS_IS_PROP_LIST (src), FALSE); + + i = 0; + 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; +} + + +IBusPropList * +ibus_prop_list_new () +{ + IBusPropList *prop_list; + + prop_list = g_object_new (IBUS_TYPE_PROP_LIST, NULL); + + return prop_list; +} + +void +ibus_prop_list_append (IBusPropList *prop_list, + IBusProperty *prop) +{ + g_return_if_fail (IBUS_IS_PROP_LIST (prop_list)); + g_return_if_fail (IBUS_IS_PROPERTY (prop)); + + g_object_ref (prop); + + g_array_append_val (prop_list->properties, prop); +} + +IBusProperty * +ibus_prop_list_get (IBusPropList *prop_list, + guint index) +{ + g_return_val_if_fail (IBUS_IS_PROP_LIST (prop_list), NULL); + + + if (index >= prop_list->properties->len) + return NULL; + + return g_array_index (prop_list->properties, IBusProperty *, index); +} + + + +gboolean +ibus_prop_list_update_property (IBusPropList *prop_list, + IBusProperty *prop) +{ + return FALSE; +} diff --git a/src/ibusproperty.h b/src/ibusproperty.h new file mode 100644 index 0000000..7cd90c9 --- /dev/null +++ b/src/ibusproperty.h @@ -0,0 +1,140 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_PROPERTY_H_ +#define __IBUS_PROPERTY_H_ + +#include "ibusserializable.h" +#include "ibustext.h" + +G_BEGIN_DECLS + +/* + * Type macros. + */ +#define IBUS_TYPE_PROPERTY (ibus_property_get_type ()) +#define IBUS_TYPE_PROP_LIST (ibus_prop_list_get_type ()) + +/* define IBusProperty macros */ +#define IBUS_TYPE_PROPERTY \ + (ibus_property_get_type ()) +#define IBUS_PROPERTY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_PROPERTY, IBusProperty)) +#define IBUS_PROPERTY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_PROPERTY, IBusPropertyClass)) +#define IBUS_IS_PROPERTY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_PROPERTY)) +#define IBUS_IS_PROPERTY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_PROPERTY)) +#define IBUS_PROPERTY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_PROPERTY, IBusPropertyClass)) + +/* define IBusPropList macros */ +#define IBUS_TYPE_PROP_LIST \ + (ibus_prop_list_get_type ()) +#define IBUS_PROP_LIST(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_PROP_LIST, IBusPropList)) +#define IBUS_PROP_LIST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_PROP_LIST, IBusPropListClass)) +#define IBUS_IS_PROP_LIST(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_PROP_LIST)) +#define IBUS_IS_PROP_LIST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_PROP_LIST)) +#define IBUS_PROP_LIST_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_PROP_LIST, IBusPropListClass)) + + +typedef enum { + PROP_TYPE_NORMAL = 0, + PROP_TYPE_TOGGLE = 1, + PROP_TYPE_RADIO = 2, + PROP_TYPE_MENU = 3, + PROP_TYPE_SEPARATOR = 4, +} IBusPropType; + +typedef enum { + PROP_STATE_UNCHECKED = 0, + PROP_STATE_CHECKED = 1, + PROP_STATE_INCONSISTENT = 2, +} IBusPropState; + + +typedef struct _IBusProperty IBusProperty; +typedef struct _IBusPropertyClass IBusPropertyClass; +typedef struct _IBusPropList IBusPropList; +typedef struct _IBusPropListClass IBusPropListClass; + +struct _IBusProperty { + IBusSerializable parent; + + gchar *key; + gchar *icon; + IBusText *label; + IBusText *tooltip; + + gboolean sensitive; + gboolean visible; + guint type; + guint state; + + IBusPropList *sub_props; +}; + +struct _IBusPropertyClass { + IBusSerializableClass parent; +}; + +struct _IBusPropList { + IBusSerializable parent; + + GArray *properties; +}; + +struct _IBusPropListClass { + IBusSerializableClass parent; +}; + +GType ibus_property_get_type (); +IBusProperty *ibus_property_new (const gchar *key, + IBusPropType type, + IBusText *label, + const gchar *icon, + IBusText *tooltip, + gboolean sensitive, + gboolean visible, + IBusPropState state, + IBusPropList *prop_list); +void ibus_property_set_label (IBusProperty *prop, + IBusText *label); +void ibus_property_set_visible (IBusProperty *prop, + gboolean visible); +void ibus_property_set_sub_props(IBusProperty *prop, + IBusPropList *prop_list); + +GType ibus_prop_list_get_type (); +IBusPropList *ibus_prop_list_new (); +void ibus_prop_list_append (IBusPropList *prop_list, + IBusProperty *prop); +IBusProperty *ibus_prop_list_get (IBusPropList *prop_list, + guint index); +gboolean ibus_prop_list_update_property + (IBusPropList *prop_list, + IBusProperty *prop); +G_END_DECLS +#endif diff --git a/src/ibusproxy.c b/src/ibusproxy.c new file mode 100644 index 0000000..5ef3b40 --- /dev/null +++ b/src/ibusproxy.c @@ -0,0 +1,638 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 <stdarg.h> +#include "ibusmessage.h" +#include "ibusproxy.h" +#include "ibusinternal.h" + +#define IBUS_PROXY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_PROXY, IBusProxyPrivate)) + +enum { + IBUS_SIGNAL, + LAST_SIGNAL, +}; + +enum { + PROP_0, + PROP_NAME, + PROP_PATH, + PROP_INTERFACE, + PROP_CONNECTION, +}; + + +/* IBusProxyPriv */ +struct _IBusProxyPrivate { + gchar *name; + gchar *path; + gchar *interface; + IBusConnection *connection; +}; +typedef struct _IBusProxyPrivate IBusProxyPrivate; + +static guint proxy_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_proxy_class_init (IBusProxyClass *klass); +static void ibus_proxy_init (IBusProxy *proxy); +static GObject *ibus_proxy_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params); +static void ibus_proxy_destroy (IBusProxy *proxy); +static void ibus_proxy_set_property(IBusProxy *proxy, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void ibus_proxy_get_property(IBusProxy *proxy, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static gboolean ibus_proxy_ibus_signal (IBusProxy *proxy, + IBusMessage *message); + +static IBusObjectClass *parent_class = NULL; + +GType +ibus_proxy_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusProxyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_proxy_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusProxy), + 0, + (GInstanceInitFunc) ibus_proxy_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "IBusProxy", + &type_info, + (GTypeFlags)0); + } + return type; +} + +IBusProxy * +ibus_proxy_new (const gchar *name, + const gchar *path, + IBusConnection *connection) +{ + g_assert (name != NULL); + g_assert (path != NULL); + g_assert (IBUS_IS_CONNECTION (connection)); + + IBusProxy *proxy; + + proxy = IBUS_PROXY (g_object_new (IBUS_TYPE_PROXY, + "name", name, + "path", path, + "connection", connection, + NULL)); + + return proxy; +} + +static void +ibus_proxy_class_init (IBusProxyClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusProxyPrivate)); + + gobject_class->constructor = ibus_proxy_constructor; + gobject_class->set_property = (GObjectSetPropertyFunc) ibus_proxy_set_property; + gobject_class->get_property = (GObjectGetPropertyFunc) ibus_proxy_get_property; + + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_proxy_destroy; + + klass->ibus_signal = ibus_proxy_ibus_signal; + + /* install properties */ + g_object_class_install_property (gobject_class, + PROP_NAME, + g_param_spec_string ("name", + "service name", + "The service name of proxy object", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (gobject_class, + PROP_PATH, + g_param_spec_string ("path", + "object path", + "The path of proxy object", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (gobject_class, + PROP_INTERFACE, + g_param_spec_string ("interface", + "interface", + "The interface of proxy object", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (gobject_class, + PROP_CONNECTION, + g_param_spec_object ("connection", + "object path", + "The path of proxy object", + IBUS_TYPE_CONNECTION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /* install signals */ + proxy_signals[IBUS_SIGNAL] = + g_signal_new (I_("ibus-signal"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusProxyClass, ibus_signal), + NULL, NULL, + ibus_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, + 1, G_TYPE_POINTER); + +} + +static gboolean +_connection_ibus_signal_cb (IBusConnection *connection, + IBusMessage *message, + IBusProxy *proxy) +{ + if (ibus_proxy_handle_signal (proxy, message)) { + g_signal_stop_emission_by_name (connection, "ibus-signal"); + return TRUE; + } + + return FALSE; +} + +static void +_connection_destroy_cb (IBusConnection *connection, + IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + g_assert (priv->connection == connection); + + g_object_unref (connection); + priv->connection = NULL; + + ibus_object_destroy ((IBusObject *) proxy); +} + +static GObject * +ibus_proxy_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *obj; + IBusProxy *proxy; + IBusProxyPrivate *priv; + + obj = G_OBJECT_CLASS (parent_class)->constructor (type, n_construct_params, construct_params); + + proxy = IBUS_PROXY (obj); + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + if (priv->connection != NULL) { + if (priv->name != NULL) { + + IBusError *error; + gchar *rule; + + rule = g_strdup_printf ("type='signal'," + "sender='" DBUS_SERVICE_DBUS "'," + "path='" DBUS_PATH_DBUS "'," + "interface='" DBUS_INTERFACE_DBUS "'," + "member='NameOwnerChanged'," + "arg0='%s'", + priv->name); + + if (!ibus_connection_call (priv->connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "AddMatch", + &error, + G_TYPE_STRING, &rule, + G_TYPE_INVALID, + G_TYPE_INVALID)) { + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + } + g_free (rule); + } + g_signal_connect (priv->connection, + "ibus-signal", + (GCallback) _connection_ibus_signal_cb, + proxy); + + g_signal_connect (priv->connection, + "destroy", + (GCallback) _connection_destroy_cb, + proxy); + } + + return obj; +} + +static void +ibus_proxy_init (IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + priv->name = NULL; + priv->path = NULL; + priv->interface = NULL; + priv->connection = NULL; +} + +static void +ibus_proxy_destroy (IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + if (priv->connection) { + + g_signal_handlers_disconnect_by_func (priv->connection, + (GCallback) _connection_ibus_signal_cb, + proxy); + g_signal_handlers_disconnect_by_func (priv->connection, + (GCallback) _connection_destroy_cb, + proxy); + + if (priv->name != NULL) { + + IBusError *error; + gchar *rule; + + rule = g_strdup_printf ("type='signal'," + "sender='" DBUS_SERVICE_DBUS "'," + "path='" DBUS_PATH_DBUS "'," + "interface='" DBUS_INTERFACE_DBUS "'," + "member='NameOwnerChanged'," + "arg0='%s'", + priv->name); + + if (!ibus_connection_call (priv->connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RemoveMatch", + &error, + G_TYPE_STRING, &rule, + G_TYPE_INVALID, + G_TYPE_INVALID)) { + + g_warning ("%s: %s", error->name, error->message); + ibus_error_free (error); + } + g_free (rule); + } + } + + g_free (priv->name); + g_free (priv->path); + g_free (priv->interface); + + priv->name = NULL; + priv->path = NULL; + priv->interface = NULL; + + if (priv->connection) { + g_object_unref (priv->connection); + priv->connection = NULL; + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (proxy)); +} + +static void +ibus_proxy_set_property (IBusProxy *proxy, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + switch (prop_id) { + case PROP_NAME: + g_assert (priv->name == NULL); + priv->name = g_strdup (g_value_get_string (value)); + break; + case PROP_PATH: + g_assert (priv->path == NULL); + priv->path = g_strdup (g_value_get_string (value)); + break; + case PROP_INTERFACE: + g_assert (priv->interface == NULL); + priv->interface = g_strdup (g_value_get_string (value)); + break; + case PROP_CONNECTION: + g_assert (priv->connection == NULL); + priv->connection = IBUS_CONNECTION (g_value_get_object (value)); + g_object_ref (priv->connection); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec); + } +} + +static void +ibus_proxy_get_property (IBusProxy *proxy, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, ibus_proxy_get_name (proxy)); + break; + case PROP_PATH: + g_value_set_string (value, ibus_proxy_get_path (proxy)); + break; + case PROP_INTERFACE: + g_value_set_string (value, ibus_proxy_get_interface (proxy)); + break; + case PROP_CONNECTION: + g_value_set_object (value, ibus_proxy_get_connection (proxy)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (proxy, prop_id, pspec); + } +} + + +gboolean +ibus_proxy_handle_signal (IBusProxy *proxy, + DBusMessage *message) +{ + g_assert (IBUS_IS_PROXY (proxy)); + g_assert (message != NULL); + + gboolean retval = FALSE; + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + if (ibus_message_is_signal (message, DBUS_SERVICE_DBUS, "NameOwnerChanged")) { + gchar *name, *old_name, *new_name; + IBusError *error; + + if (!ibus_message_get_args (message, + &error, + G_TYPE_STRING, &name, + G_TYPE_STRING, &old_name, + G_TYPE_STRING, &new_name, + G_TYPE_INVALID)) { + g_warning ("%s :%s", error->name, error->message); + ibus_error_free (error); + } + + if (g_strcmp0 (priv->name, old_name) == 0) { + ibus_object_destroy (IBUS_OBJECT (proxy)); + return FALSE; + } + } + + if (g_strcmp0 (ibus_message_get_path (message), priv->path) == 0) { + g_signal_emit (proxy, proxy_signals[IBUS_SIGNAL], 0, message, &retval); + } + + return retval; +} + +static gboolean +ibus_proxy_ibus_signal (IBusProxy *proxy, + DBusMessage *message) +{ + return FALSE; +} + + +const gchar * +ibus_proxy_get_name (IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + return priv->name; +} + +const gchar * +ibus_proxy_get_path (IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + return priv->path; +} + +const gchar * +ibus_proxy_get_interface (IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + return priv->interface; +} + +IBusConnection * +ibus_proxy_get_connection (IBusProxy *proxy) +{ + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + return priv->connection; +} + +gboolean +ibus_proxy_send (IBusProxy *proxy, + DBusMessage *message) +{ + g_assert (IBUS_IS_PROXY (proxy)); + g_assert (message != NULL); + + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + g_return_val_if_fail (priv->connection, FALSE); + g_return_val_if_fail (ibus_connection_is_connected (priv->connection), FALSE); + + return ibus_connection_send (priv->connection, message); +} + +gboolean +ibus_proxy_call (IBusProxy *proxy, + const gchar *method, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_PROXY (proxy)); + g_assert (method != NULL); + + va_list args; + gboolean retval; + DBusMessage *message; + + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + g_return_val_if_fail (priv->connection, FALSE); + g_return_val_if_fail (ibus_connection_is_connected (priv->connection), FALSE); + + message = ibus_message_new_method_call (priv->name, + priv->path, + priv->interface, + method); + va_start (args, first_arg_type); + retval = ibus_message_append_args_valist (message, + first_arg_type, + args); + if (!retval) { + ibus_message_unref (message); + g_return_val_if_reached (FALSE); + } + + va_end (args); + + retval = ibus_connection_send (priv->connection, message); + + ibus_message_unref (message); + + return retval; +} + +gboolean +ibus_proxy_call_with_reply (IBusProxy *proxy, + const gchar *method, + IBusPendingCall **pending, + gint timeout_milliseconds, + IBusError **error, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_PROXY (proxy)); + g_assert (pending != NULL); + g_assert (method != NULL); + + va_list args; + gboolean retval; + DBusMessage *message; + + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + if (priv->connection == NULL || !ibus_connection_is_connected (priv->connection)) { + if (error) { + *error = ibus_error_new_from_printf (DBUS_ERROR_DISCONNECTED, + "Connection of %s was disconnected.", + G_OBJECT_TYPE_NAME (proxy)); + } + return FALSE; + } + + message = ibus_message_new_method_call (priv->name, + priv->path, + priv->interface, + method); + va_start (args, first_arg_type); + retval = ibus_message_append_args_valist (message, + first_arg_type, + args); + va_end (args); + + *pending = NULL; + retval = ibus_connection_send_with_reply (priv->connection, + message, + pending, + timeout_milliseconds); + ibus_message_unref (message); + + if (!retval && error != NULL) { + *error = ibus_error_new_from_printf (DBUS_ERROR_NO_MEMORY, ""); + } + + return retval; +} + + +IBusMessage * +ibus_proxy_call_with_reply_and_block (IBusProxy *proxy, + const gchar *method, + gint timeout_milliseconds, + IBusError **error, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_PROXY (proxy)); + g_assert (method != NULL); + + va_list args; + gboolean retval; + DBusMessage *message; + DBusMessage *reply_message; + + IBusProxyPrivate *priv; + priv = IBUS_PROXY_GET_PRIVATE (proxy); + + if (priv->connection == NULL || !ibus_connection_is_connected (priv->connection)) { + if (error) { + *error = ibus_error_new_from_printf (DBUS_ERROR_DISCONNECTED, + "Connection of %s was disconnected.", + G_OBJECT_TYPE_NAME (proxy)); + } + return NULL; + } + + message = ibus_message_new_method_call (priv->name, + priv->path, + priv->interface, + method); + va_start (args, first_arg_type); + retval = ibus_message_append_args_valist (message, + first_arg_type, + args); + va_end (args); + + reply_message = ibus_connection_send_with_reply_and_block ( + priv->connection, + message, + timeout_milliseconds, + error); + ibus_message_unref (message); + + return reply_message; +} diff --git a/src/ibusproxy.h b/src/ibusproxy.h new file mode 100644 index 0000000..0cc22d4 --- /dev/null +++ b/src/ibusproxy.h @@ -0,0 +1,107 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_PROXY_H_ +#define __IBUS_PROXY_H_ + +#include <dbus/dbus.h> +#include "ibusobject.h" +#include "ibusconnection.h" +#include "ibusmessage.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_PROXY \ + (ibus_proxy_get_type ()) +#define IBUS_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_PROXY, IBusProxy)) +#define IBUS_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_PROXY, IBusProxyClass)) +#define IBUS_IS_PROXY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_PROXY)) +#define IBUS_IS_PROXY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_PROXY)) +#define IBUS_PROXY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_PROXY, IBusProxyClass)) + +G_BEGIN_DECLS + +typedef struct _IBusProxy IBusProxy; +typedef struct _IBusProxyClass IBusProxyClass; + +struct _IBusProxy { + IBusObject parent; + /* instance members */ +}; + +struct _IBusProxyClass { + IBusObjectClass parent; + + /* class members */ + gboolean (* ibus_signal) (IBusProxy *proxy, + IBusMessage *message); + /*< private >*/ + /* padding */ + gpointer pdummy[7]; +}; + +GType ibus_proxy_get_type (void); +IBusProxy *ibus_proxy_new (const gchar *name, + const gchar *path, + IBusConnection *connection); +gboolean ibus_proxy_send (IBusProxy *proxy, + IBusMessage *message); +gboolean ibus_proxy_call (IBusProxy *proxy, + const gchar *method, + GType first_agr_type, + ...); +gboolean ibus_proxy_call_with_reply (IBusProxy *proxy, + const gchar *method, + IBusPendingCall **pending, + gint timeout_milliseconds, + IBusError **error, + GType first_arg_type, + ...); +IBusMessage *ibus_proxy_call_with_reply_and_block + (IBusProxy *proxy, + const gchar *method, + gint timeout_milliseconds, + IBusError **error, + GType first_arg_type, + ...); +gboolean ibus_proxy_send_with_reply (IBusProxy *proxy, + IBusMessage *message, + IBusPendingCall **pending, + gint timeout_milliseconds); +IBusMessage *ibus_proxy_send_with_reply_and_block + (IBusProxy *proxy, + IBusMessage *message); +gboolean ibus_proxy_handle_signal (IBusProxy *proxy, + IBusMessage *message); +const gchar *ibus_proxy_get_name (IBusProxy *proxy); +const gchar *ibus_proxy_get_path (IBusProxy *proxy); +const gchar *ibus_proxy_get_interface (IBusProxy *proxy); +IBusConnection *ibus_proxy_get_connection (IBusProxy *proxy); + +G_END_DECLS +#endif + diff --git a/src/ibusserializable.c b/src/ibusserializable.c new file mode 100644 index 0000000..82a49bc --- /dev/null +++ b/src/ibusserializable.c @@ -0,0 +1,578 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibusinternal.h" +#include "ibusserializable.h" + +#define IBUS_SERIALIZABLE_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_SERIALIZABLE, IBusSerializablePrivate)) + +enum { + LAST_SIGNAL, +}; + +typedef struct _IBusSerializablePrivate IBusSerializablePrivate; +struct _IBusSerializablePrivate { + GData *attachments; +}; + +// static guint object_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_serializable_base_init (IBusSerializableClass *klass); +static void ibus_serializable_base_fini (IBusSerializableClass *klass); +static void ibus_serializable_class_init (IBusSerializableClass *klass); +static void ibus_serializable_init (IBusSerializable *object); +static void ibus_serializable_destroy (IBusSerializable *object); +static gboolean ibus_serializable_real_serialize (IBusSerializable *object, + IBusMessageIter *iter); +static gboolean ibus_serializable_real_deserialize (IBusSerializable *object, + IBusMessageIter *iter); +static gboolean ibus_serializable_real_copy (IBusSerializable *dest, + const IBusSerializable *src); + +static IBusObjectClass *parent_class = NULL; + + +GType +ibus_serializable_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusSerializableClass), + (GBaseInitFunc) ibus_serializable_base_init, + (GBaseFinalizeFunc) ibus_serializable_base_fini, + (GClassInitFunc) ibus_serializable_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusSerializable), + 0, + (GInstanceInitFunc) ibus_serializable_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "IBusSerializable", + &type_info, + 0); + } + + return type; +} + +/** + * ibus_serializable_new: + * + * Creates a new instance of an #IBusSerializable. + * + * Returns: a new instance of #IBusSerializable. + */ +IBusSerializable * +ibus_serializable_new (void) +{ + return IBUS_SERIALIZABLE (g_object_new (IBUS_TYPE_SERIALIZABLE, NULL)); +} + +static void +ibus_serializable_base_init (IBusSerializableClass *klass) +{ + /* init signature */ + klass->signature = g_string_new ("a{sv}"); +} + +static void +ibus_serializable_base_fini (IBusSerializableClass *klass) +{ + /* init signature */ + g_string_free (klass->signature, TRUE); + klass->signature = NULL; +} + +static void +ibus_serializable_class_init (IBusSerializableClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusSerializablePrivate)); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_serializable_destroy; + + klass->serialize = ibus_serializable_real_serialize; + klass->deserialize = ibus_serializable_real_deserialize; + klass->copy = ibus_serializable_real_copy; +} + +static void +ibus_serializable_init (IBusSerializable *object) +{ + IBusSerializablePrivate *priv; + priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); + + priv->attachments = NULL; + g_datalist_init (&priv->attachments); +} + +static void +ibus_serializable_destroy (IBusSerializable *object) +{ + IBusSerializablePrivate *priv; + priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); + + g_datalist_clear (&priv->attachments); + + parent_class->destroy (IBUS_OBJECT (object)); +} + +static GValue * +ibus_g_value_dup (const GValue *value) +{ + GValue *new_value; + + new_value = g_slice_new0 (GValue); + g_value_init (new_value, G_VALUE_TYPE (value)); + g_value_copy (value, new_value); + + return new_value; +} + +static void +ibus_g_value_free (GValue *value) +{ + g_value_unset (value); + g_slice_free (GValue, value); +} + +static gboolean +_g_value_serialize (GValue *value, + IBusMessageIter *iter) +{ + gboolean retval; + GType type; + + type = G_VALUE_TYPE (value); + g_return_val_if_fail (type != G_TYPE_INVALID, FALSE); + + + if (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE)) { + IBusSerializable *object; + object = IBUS_SERIALIZABLE (g_value_get_object (value)); + retval = ibus_message_iter_append (iter, + type, + &object); + g_return_val_if_fail (retval, FALSE); + return TRUE; + } + + typedef const gchar *gstring; + switch (type) { +#define CASE_ENTRY(TYPE, _type, signature) \ + case G_TYPE_##TYPE: \ + { \ + g##_type v; \ + IBusMessageIter variant_iter; \ + \ + retval = ibus_message_iter_open_container (iter, \ + IBUS_TYPE_VARIANT, \ + signature, \ + &variant_iter); \ + g_return_val_if_fail (retval, FALSE); \ + \ + v = g_value_get_##_type (value); \ + retval = ibus_message_iter_append (&variant_iter, \ + G_TYPE_##TYPE, \ + &v); \ + g_return_val_if_fail (retval, FALSE); \ + \ + retval = ibus_message_iter_close_container (iter, &variant_iter); \ + g_return_val_if_fail (retval, FALSE); \ + \ + return TRUE; \ + } + CASE_ENTRY(CHAR, char, "y"); + CASE_ENTRY(BOOLEAN, boolean, "b"); + CASE_ENTRY(INT, int, "i"); + CASE_ENTRY(UINT, uint, "u"); + CASE_ENTRY(INT64, int64, "x"); + CASE_ENTRY(UINT64, uint64, "t"); + CASE_ENTRY(FLOAT, float, "d"); + CASE_ENTRY(DOUBLE, double, "d"); + CASE_ENTRY(STRING, string, "s"); +#undef CASE_ENTRY + } + + g_return_val_if_reached (FALSE); +} + +static GValue * +_g_value_deserialize (IBusMessageIter *iter) +{ + IBusMessageIter variant_iter; + gboolean retval; + GValue *value = NULL; + GType type; + + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_VARIANT, &variant_iter); + g_return_val_if_fail (retval, NULL); + + type = ibus_message_iter_get_arg_type (&variant_iter); + + if (type == IBUS_TYPE_STRUCT) { + IBusSerializable *object; + retval = ibus_message_iter_get (iter, IBUS_TYPE_SERIALIZABLE, &object); + g_return_val_if_fail (retval, NULL); + + value = g_slice_new0 (GValue); + g_value_init (value, G_OBJECT_TYPE (object)); + g_value_take_object (value, object); + return value; + } + + typedef gchar *gstring; + switch (type) { +#define CASE_ENTRY(TYPE, _type) \ + case G_TYPE_##TYPE: \ + { \ + g##_type v; \ + ibus_message_iter_get_basic (&variant_iter, &v); \ + value = g_slice_new0 (GValue); \ + g_value_init (value, G_TYPE_##TYPE); \ + g_value_set_##_type (value, v); \ + ibus_message_iter_next (iter); \ + return value; \ + } + CASE_ENTRY(CHAR, char); + CASE_ENTRY(BOOLEAN, boolean); + CASE_ENTRY(INT, int); + CASE_ENTRY(UINT, uint); + CASE_ENTRY(INT64, int64); + CASE_ENTRY(UINT64, uint64); + CASE_ENTRY(FLOAT, float); + CASE_ENTRY(DOUBLE, double); + CASE_ENTRY(STRING, string); + } + g_return_val_if_reached (NULL); +} + +static void +_serialize_cb (GQuark key, + GValue *value, + IBusMessageIter *iter) +{ + IBusMessageIter dict_entry; + gboolean retval; + const gchar *name; + + retval = ibus_message_iter_open_container (iter, + IBUS_TYPE_DICT_ENTRY, + NULL, + &dict_entry); + g_return_if_fail (retval); + name = g_quark_to_string (key); + retval = ibus_message_iter_append (&dict_entry, + G_TYPE_STRING, + &name); + g_return_if_fail (retval); + + retval = _g_value_serialize (value, &dict_entry); + g_return_if_fail (retval); + + retval = ibus_message_iter_close_container (iter, &dict_entry); + g_return_if_fail (retval); +} + +static gboolean +ibus_serializable_real_serialize (IBusSerializable *object, + IBusMessageIter *iter) +{ + IBusSerializablePrivate *priv; + IBusMessageIter array_iter; + gboolean retval; + + priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); + + retval = ibus_message_iter_open_container (iter, + IBUS_TYPE_ARRAY, + "{sv}", + &array_iter); + g_return_val_if_fail (retval, FALSE); + + g_datalist_foreach (&priv->attachments, + (GDataForeachFunc) _serialize_cb, + &array_iter); + + retval = ibus_message_iter_close_container (iter, &array_iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_serializable_real_deserialize (IBusSerializable *object, + IBusMessageIter *iter) +{ + IBusMessageIter array_iter; + gboolean retval; + + retval = ibus_message_iter_recurse (iter, + IBUS_TYPE_ARRAY, + &array_iter); + g_return_val_if_fail (retval, FALSE); + + while (ibus_message_iter_get_arg_type (&array_iter) != G_TYPE_INVALID) { + gchar *name; + GValue *value; + IBusMessageIter dict_entry; + + retval = ibus_message_iter_recurse (&array_iter, + IBUS_TYPE_DICT_ENTRY, + &dict_entry); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (&dict_entry, + G_TYPE_STRING, + &name); + g_return_val_if_fail (retval, FALSE); + + value = _g_value_deserialize (&dict_entry); + g_return_val_if_fail (value != NULL, FALSE); + + ibus_serializable_set_attachment (object, name, value); + + ibus_message_iter_next (&array_iter); + } + + ibus_message_iter_next (iter); + + return TRUE; +} + +static void +_copy_cb (GQuark key, + GValue *value, + GData **datalist) +{ + g_datalist_id_set_data_full (datalist, + key, + ibus_g_value_dup (value), + (GDestroyNotify) ibus_g_value_free); +} + +static gboolean +ibus_serializable_real_copy (IBusSerializable *dest, + const IBusSerializable *src) +{ + IBusSerializablePrivate *src_priv; + IBusSerializablePrivate *dest_priv; + src_priv = IBUS_SERIALIZABLE_GET_PRIVATE (src); + dest_priv = IBUS_SERIALIZABLE_GET_PRIVATE (dest); + + g_datalist_foreach (&src_priv->attachments, + (GDataForeachFunc) _copy_cb, + &dest_priv->attachments); + return TRUE; +} + +gboolean +ibus_serializable_set_qattachment (IBusSerializable *object, + GQuark key, + const GValue *value) +{ + g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), FALSE); + g_return_val_if_fail (key != 0, FALSE); + g_return_val_if_fail (G_IS_VALUE (value), FALSE); + + IBusSerializablePrivate *priv; + priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); + + GType type = G_VALUE_TYPE (value); + + switch (type) { + case G_TYPE_CHAR: + case G_TYPE_INT: + case G_TYPE_INT64: + case G_TYPE_UINT: + case G_TYPE_UINT64: + case G_TYPE_BOOLEAN: + case G_TYPE_DOUBLE: + case G_TYPE_FLOAT: + case G_TYPE_STRING: + g_datalist_id_set_data_full (&priv->attachments, + key, + ibus_g_value_dup (value), + (GDestroyNotify) ibus_g_value_free); + return TRUE; + } + + if (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE)) { + g_datalist_id_set_data_full (&priv->attachments, + key, + ibus_g_value_dup (value), + (GDestroyNotify) ibus_g_value_free); + return TRUE; + } + + g_warning ("The value of %s is not support serializing", g_type_name (type)); + return FALSE; +} + +const GValue * +ibus_serializable_get_qattachment (IBusSerializable *object, + GQuark key) +{ + + g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), NULL); + g_return_val_if_fail (key != 0, NULL); + + IBusSerializablePrivate *priv; + priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); + + return (const GValue *) g_datalist_id_get_data (&priv->attachments, key); +} + +void +ibus_serializable_remove_qattachment (IBusSerializable *object, + GQuark key) +{ + + g_return_if_fail (IBUS_IS_SERIALIZABLE (object)); + g_return_if_fail (key != 0); + + IBusSerializablePrivate *priv; + priv = IBUS_SERIALIZABLE_GET_PRIVATE (object); + + g_datalist_id_remove_no_notify (&priv->attachments, key); +} + +IBusSerializable * +ibus_serializable_copy (IBusSerializable *object) +{ + g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), NULL); + + GType type; + IBusSerializable *new_object; + + type = G_OBJECT_TYPE (object); + + new_object = g_object_new (type, 0); + g_return_val_if_fail (new_object != NULL, NULL); + + if (IBUS_SERIALIZABLE_GET_CLASS (new_object)->copy (new_object, object)) { + return new_object; + } + + g_object_unref (new_object); + g_return_val_if_reached (NULL); +} + +gboolean +ibus_serializable_serialize (IBusSerializable *object, + IBusMessageIter *iter) +{ + g_return_val_if_fail (IBUS_IS_SERIALIZABLE (object), FALSE); + g_return_val_if_fail (iter != NULL, FALSE); + + IBusMessageIter variant_iter; + IBusMessageIter sub_iter; + gboolean retval; + + gchar *signature; + + signature = g_strdup_printf ("(s%s)", IBUS_SERIALIZABLE_GET_CLASS (object)->signature->str); + retval = ibus_message_iter_open_container (iter, + IBUS_TYPE_VARIANT, + signature, + &variant_iter); + g_free (signature); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_open_container (&variant_iter, + IBUS_TYPE_STRUCT, + NULL, + &sub_iter); + g_return_val_if_fail (retval, FALSE); + + const gchar *type_name = g_type_name (G_OBJECT_TYPE (object)); + g_return_val_if_fail (type_name != NULL, FALSE); + + retval = ibus_message_iter_append (&sub_iter, + G_TYPE_STRING, + &type_name); + g_return_val_if_fail (retval, FALSE); + + retval = IBUS_SERIALIZABLE_GET_CLASS (object)->serialize (object, &sub_iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_close_container (&variant_iter, &sub_iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_close_container (iter, &variant_iter); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +IBusSerializable * +ibus_serializable_deserialize (IBusMessageIter *iter) +{ + g_return_val_if_fail (iter != NULL, NULL); + + gboolean retval; + IBusMessageIter variant_iter; + IBusMessageIter sub_iter; + gchar *type_name; + GType type; + IBusSerializable *object; + + type = ibus_message_iter_get_arg_type (iter); + + if (type == IBUS_TYPE_VARIANT) { + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_VARIANT, &variant_iter); + g_return_val_if_fail (retval, NULL); + + retval = ibus_message_iter_recurse (&variant_iter, IBUS_TYPE_STRUCT, &sub_iter); + g_return_val_if_fail (retval, NULL); + } + else if (type == IBUS_TYPE_STRUCT) { + retval = ibus_message_iter_recurse (iter, IBUS_TYPE_STRUCT, &sub_iter); + g_return_val_if_fail (retval, NULL); + } + else + g_return_val_if_reached (NULL); + + retval = ibus_message_iter_get (&sub_iter, G_TYPE_STRING, &type_name); + g_return_val_if_fail (retval, NULL); + + type = g_type_from_name (type_name); + + g_return_val_if_fail (g_type_is_a (type, IBUS_TYPE_SERIALIZABLE), NULL); + + object = g_object_new (type, 0); + + retval = IBUS_SERIALIZABLE_GET_CLASS (object)->deserialize (object, &sub_iter); + if (retval) + return object; + + g_object_unref (object); + g_return_val_if_reached (NULL); +} + diff --git a/src/ibusserializable.h b/src/ibusserializable.h new file mode 100644 index 0000000..a99f123 --- /dev/null +++ b/src/ibusserializable.h @@ -0,0 +1,108 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_SERIALIZABLE_H_ +#define __IBUS_SERIALIZABLE_H_ + +#include "ibusobject.h" +#include "ibusmessage.h" + +/* + * Type macros. + */ + +/* define IBusSerializable macros */ +#define IBUS_TYPE_SERIALIZABLE \ + (ibus_serializable_get_type ()) +#define IBUS_SERIALIZABLE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_SERIALIZABLE, IBusSerializable)) +#define IBUS_SERIALIZABLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_SERIALIZABLE, IBusSerializableClass)) +#define IBUS_IS_SERIALIZABLE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_SERIALIZABLE)) +#define IBUS_IS_SERIALIZABLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_SERIALIZABLE)) +#define IBUS_SERIALIZABLE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_SERIALIZABLE, IBusSerializableClass)) + +#define ibus_serializable_set_attachment(o, k, v) \ + ibus_serializable_set_qattachment (o, g_quark_from_string (k), v) +#define ibus_serializable_get_attachment(o, k, v) \ + ibus_serializable_get_qattachment (o, g_quark_from_string (k)) +#define ibus_serializable_remove_attachment(o, k) \ + ibus_serializable_remove_qattachment (o, g_quark_from_string (k)) + +G_BEGIN_DECLS + +typedef struct _IBusSerializable IBusSerializable; +typedef struct _IBusSerializableClass IBusSerializableClass; +/** + * IBusSerializable: + * + * All the fields in the <structname>IBusSerializable</structname> structure are + * prtivate to the #IBusSerializable and should never be accessed directly. + */ +struct _IBusSerializable { + GObject parent; + /* instance members */ + guint32 flags; +}; + +typedef gboolean (* IBusSerializableSerializeFunc) (IBusSerializable *object, + IBusMessageIter *iter); +typedef gboolean (* IBusSerializableDeserializeFunc) (IBusSerializable *object, + IBusMessageIter *iter); +typedef gboolean (* IBusSerializableCopyFunc) (IBusSerializable *dest, + const IBusSerializable *src); +struct _IBusSerializableClass { + IBusObjectClass parent; + + /* signature */ + GString *signature; + + /* virtual table */ + gboolean (* serialize) (IBusSerializable *object, + IBusMessageIter *iter); + gboolean (* deserialize) (IBusSerializable *object, + IBusMessageIter *iter); + gboolean (* copy) (IBusSerializable *dest, + const IBusSerializable *src); + /*< private >*/ + /* padding */ + gpointer pdummy[5]; +}; + +GType ibus_serializable_get_type (void); +IBusSerializable * ibus_serializable_new (void); +gboolean ibus_serializable_set_qattachment (IBusSerializable *object, + GQuark key, + const GValue *value); +const GValue *ibus_serializable_get_qattachment (IBusSerializable *object, + GQuark key); +void ibus_serializable_remove_qattachment + (IBusSerializable *object, + GQuark key); +IBusSerializable *ibus_serializable_copy (IBusSerializable *object); +gboolean ibus_serializable_serialize (IBusSerializable *object, + IBusMessageIter *iter); +IBusSerializable *ibus_serializable_deserialize (IBusMessageIter *iter); + +G_END_DECLS +#endif + diff --git a/src/ibusserver.c b/src/ibusserver.c new file mode 100644 index 0000000..cda80af --- /dev/null +++ b/src/ibusserver.c @@ -0,0 +1,327 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibusserver.h" +#include "ibusinternal.h" + +#define IBUS_SERVER_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_SERVER, IBusServerPrivate)) +#define DECLARE_PRIV IBusServerPrivate *priv = IBUS_SERVER_GET_PRIVATE(server) + +enum { + NEW_CONNECTION, + LAST_SIGNAL, +}; + +enum { + PROP_0, + PROP_CONNECTION_TYPE, +}; + +/* IBusServerPriv */ +struct _IBusServerPrivate { + DBusServer *server; + GType connection_type; +}; +typedef struct _IBusServerPrivate IBusServerPrivate; + +static guint server_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_server_class_init (IBusServerClass *klass); +static void ibus_server_init (IBusServer *server); +static void ibus_server_destroy (IBusServer *server); +static void ibus_server_set_property(IBusServer *server, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void ibus_server_get_property(IBusServer *server, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void ibus_server_listen_internal + (IBusServer *server, + const gchar *address); +static void ibus_server_new_connection + (IBusServer *server, + IBusConnection *connection); + +static IBusObjectClass *parent_class = NULL; + +GType +ibus_server_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusServerClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_server_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusServer), + 0, + (GInstanceInitFunc) ibus_server_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "IBusServer", + &type_info, + (GTypeFlags)0); + } + + return type; +} + +IBusServer * +ibus_server_new (void) +{ + IBusServer *server; + + server = IBUS_SERVER (g_object_new (IBUS_TYPE_SERVER, NULL)); + return server; +} + +gboolean +ibus_server_listen (IBusServer *server, + const gchar *address) +{ + g_assert (IBUS_IS_SERVER (server)); + g_assert (address != NULL); + ibus_server_listen_internal (server, address); + + return TRUE; +} + +static void +ibus_server_class_init (IBusServerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusServerPrivate)); + + gobject_class->set_property = (GObjectSetPropertyFunc) ibus_server_set_property; + gobject_class->get_property = (GObjectGetPropertyFunc) ibus_server_get_property; + + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_server_destroy; + + klass->new_connection = ibus_server_new_connection; + + /* install properties */ + g_object_class_install_property (gobject_class, + PROP_CONNECTION_TYPE, + g_param_spec_gtype ("connection-type", + "connection type", + "The connection type of server object", + IBUS_TYPE_CONNECTION, + G_PARAM_READWRITE)); + + /* install signals */ + server_signals[NEW_CONNECTION] = + g_signal_new (I_("new-connection"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusServerClass, new_connection), + NULL, NULL, + ibus_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); +} + +static void +ibus_server_init (IBusServer *server) +{ + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + priv->server = NULL; + priv->connection_type = IBUS_TYPE_CONNECTION; +} + +static void +ibus_server_destroy (IBusServer *server) +{ + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + if (priv->server) { + dbus_server_unref (priv->server); + priv->server = NULL; + } + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (server)); +} + +static void +ibus_server_set_property (IBusServer *server, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + switch (prop_id) { + case PROP_CONNECTION_TYPE: + { + GType type; + type = g_value_get_gtype (value); + g_assert (g_type_is_a (type, IBUS_TYPE_CONNECTION)); + priv->connection_type = type; + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (server, prop_id, pspec); + } +} + +static void +ibus_server_get_property (IBusServer *server, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + switch (prop_id) { + case PROP_CONNECTION_TYPE: + g_value_set_gtype (value, priv->connection_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (server, prop_id, pspec); + } +} + +static void +ibus_server_new_connection (IBusServer *server, + IBusConnection *connection) +{ +} + +static void +_new_connection_cb (DBusServer *dbus_server, + DBusConnection *new_connection, + IBusServer *server) +{ + IBusServerPrivate *priv; + IBusConnection *connection; + + priv = IBUS_SERVER_GET_PRIVATE (server); + connection = IBUS_CONNECTION (g_object_new (priv->connection_type, NULL)); + ibus_connection_set_connection (connection, new_connection, FALSE); + + g_signal_emit (server, server_signals[NEW_CONNECTION], 0, connection); + g_object_unref (connection); +} + +static void +ibus_server_listen_internal (IBusServer *server, + const gchar *address) +{ + g_assert (IBUS_IS_SERVER (server)); + g_assert (address != NULL); + + IBusServerPrivate *priv; + DBusError error; + + priv = IBUS_SERVER_GET_PRIVATE (server); + + g_assert (priv->server == NULL); + + dbus_error_init (&error); + priv->server = dbus_server_listen (address, &error); + + if (priv->server == NULL) { + g_error ("Can not listen on '%s':\n" + " %s:%s", + address, error.name, error.message); + } + + dbus_server_set_new_connection_function (priv->server, + (DBusNewConnectionFunction) _new_connection_cb, + server, NULL); + + dbus_server_set_auth_mechanisms (priv->server, NULL); + + dbus_server_setup (priv->server, NULL); +} + +void ibus_server_disconnect (IBusServer *server) +{ + g_assert (IBUS_IS_SERVER (server)); + + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + g_assert (priv->server != NULL); + dbus_server_disconnect (priv->server); +} + +const gchar *ibus_server_get_address (IBusServer *server) +{ + g_assert (IBUS_IS_SERVER (server)); + + gchar *address, *tmp; + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + g_assert (priv->server != NULL); + + tmp = dbus_server_get_address (priv->server); + address = g_strdup (tmp); + dbus_free (tmp); + return address; +} + +const gchar *ibus_server_get_id (IBusServer *server) +{ + g_assert (IBUS_IS_SERVER (server)); + + gchar *id, *tmp; + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + g_assert (priv->server != NULL); + + tmp = dbus_server_get_id (priv->server); + id = g_strdup (tmp); + dbus_free (tmp); + return id; +} + +gboolean +ibus_server_is_connected (IBusServer *server) +{ + g_assert (IBUS_IS_SERVER (server)); + + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + g_assert (priv->server != NULL); + + return dbus_server_get_is_connected (priv->server); +} + + diff --git a/src/ibusserver.h b/src/ibusserver.h new file mode 100644 index 0000000..cf3547f --- /dev/null +++ b/src/ibusserver.h @@ -0,0 +1,79 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_SERVER_H_ +#define __IBUS_SERVER_H_ + +#include <dbus/dbus.h> +#include "ibusobject.h" +#include "ibusconnection.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_SERVER \ + (ibus_server_get_type ()) +#define IBUS_SERVER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_SERVER, IBusServer)) +#define IBUS_SERVER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_SERVER, IBusServerClass)) +#define IBUS_IS_SERVER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_SERVER)) +#define IBUS_IS_SERVER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_SERVER)) +#define IBUS_SERVER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_SERVER, IBusServerClass)) + +G_BEGIN_DECLS + +typedef struct _IBusServer IBusServer; +typedef struct _IBusServerClass IBusServerClass; + +typedef void (* IBusNewConnectionFunc) (IBusServer *server, IBusConnection *connection); + +struct _IBusServer { + IBusObject parent; + /* instance members */ +}; + +struct _IBusServerClass { + IBusObjectClass parent; + + /* signals */ + void (* new_connection) (IBusServer *server, + IBusConnection *connectin); + /*< private >*/ + /* padding */ + gpointer pdummy[7]; +}; + +GType ibus_server_get_type (void); +IBusServer *ibus_server_new (void); +gboolean ibus_server_listen (IBusServer *server, + const gchar *address); +void ibus_server_disconnect (IBusServer *server); +const gchar *ibus_server_get_address (IBusServer *server); +const gchar *ibus_server_get_id (IBusServer *server); +gboolean ibus_server_is_connected (IBusServer *server); + +G_END_DECLS +#endif + diff --git a/src/ibusservice.c b/src/ibusservice.c new file mode 100644 index 0000000..380e3ee --- /dev/null +++ b/src/ibusservice.c @@ -0,0 +1,406 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibusservice.h" +#include "ibusinternal.h" + +#define IBUS_SERVICE_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_SERVICE, IBusServicePrivate)) + +enum { + IBUS_MESSAGE, + IBUS_SIGNAL, + LAST_SIGNAL, +}; + +enum { + PROP_0, + PROP_PATH +}; + +/* IBusServicePriv */ +struct _IBusServicePrivate { + gchar *path; + GList *connections; +}; +typedef struct _IBusServicePrivate IBusServicePrivate; + +static guint service_signals[LAST_SIGNAL] = { 0 }; + +/* functions prototype */ +static void ibus_service_class_init (IBusServiceClass *klass); +static void ibus_service_init (IBusService *service); +static void ibus_service_destroy (IBusService *service); +static void ibus_service_set_property (IBusService *service, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void ibus_service_get_property (IBusService *service, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static gboolean ibus_service_ibus_message (IBusService *service, + IBusConnection *connection, + IBusMessage *message); +static gboolean ibus_service_ibus_signal (IBusService *service, + IBusConnection *connection, + IBusMessage *message); + +static IBusObjectClass *parent_class = NULL; + +GType +ibus_service_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusServiceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_service_class_init, + NULL, /* class finalize */ + NULL, /* class data */ + sizeof (IBusService), + 0, + (GInstanceInitFunc) ibus_service_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_OBJECT, + "IBusService", + &type_info, + (GTypeFlags) 0); + } + return type; +} + +IBusService * +ibus_service_new (const gchar *path) +{ + GObject *obj; + obj = g_object_new (IBUS_TYPE_SERVICE, + "path", path, + NULL); + return IBUS_SERVICE (obj); +} + +static void +ibus_service_class_init (IBusServiceClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass); + + parent_class = (IBusObjectClass *) g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (IBusServicePrivate)); + + gobject_class->set_property = (GObjectSetPropertyFunc) ibus_service_set_property; + gobject_class->get_property = (GObjectGetPropertyFunc) ibus_service_get_property; + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_service_destroy; + + klass->ibus_message = ibus_service_ibus_message; + klass->ibus_signal = ibus_service_ibus_signal; + + /* install properties */ + g_object_class_install_property ( + gobject_class, + PROP_PATH, + g_param_spec_string ( + "path", + "object path", + "The path of service object", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) + ); + + /* Install signals */ + service_signals[IBUS_MESSAGE] = + g_signal_new (I_("ibus-message"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusServiceClass, ibus_message), + NULL, NULL, + ibus_marshal_BOOLEAN__POINTER_POINTER, + G_TYPE_BOOLEAN, + 2, + G_TYPE_POINTER, + G_TYPE_POINTER); + + service_signals[IBUS_SIGNAL] = + g_signal_new (I_("ibus-signal"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusServiceClass, ibus_signal), + NULL, NULL, + ibus_marshal_BOOLEAN__POINTER_POINTER, + G_TYPE_BOOLEAN, + 2, + G_TYPE_POINTER, + G_TYPE_POINTER); + +} + +static void +ibus_service_init (IBusService *service) +{ + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + priv->path = NULL; + priv->connections = NULL; +} + +static void +ibus_service_destroy (IBusService *service) +{ + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + ibus_service_remove_from_all_connections (service); + + g_free (priv->path); + priv->path = NULL; + + IBUS_OBJECT_CLASS(parent_class)->destroy (IBUS_OBJECT (service)); +} + +static void +ibus_service_set_property (IBusService *service, + guint prop_id, const GValue *value, GParamSpec *pspec) +{ + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + switch (prop_id) { + case PROP_PATH: + priv->path = g_strdup (g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (service, prop_id, pspec); + } +} + +static void +ibus_service_get_property (IBusService *service, + guint prop_id, GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_PATH: + g_value_set_string (value, ibus_service_get_path (service)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (service, prop_id, pspec); + } +} + +const gchar * +ibus_service_get_path (IBusService *service) +{ + g_assert (IBUS_IS_SERVICE (service)); + + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + return priv->path; +} + +gboolean +ibus_service_handle_message (IBusService *service, + IBusConnection *connection, + IBusMessage *message) +{ + gboolean retval = FALSE; + g_return_val_if_fail (message != NULL, FALSE); + + g_signal_emit (service, service_signals[IBUS_MESSAGE], 0, connection, message, &retval); + return retval; +} + +static gboolean +ibus_service_ibus_message (IBusService *service, + IBusConnection *connection, + IBusMessage *message) +{ + if (ibus_message_is_method_call (message, "", "Destroy")) { + IBusMessage *reply; + reply = ibus_message_new_method_return (message); + ibus_connection_send (connection, reply); + ibus_message_unref (reply); + return TRUE; + } + return FALSE; +} + +static gboolean +ibus_service_ibus_signal (IBusService *service, + IBusConnection *connection, + IBusMessage *message) +{ + return FALSE; +} + + +gboolean +_service_message_function (IBusConnection *connection, + IBusMessage *message, + IBusService *service) +{ + return ibus_service_handle_message (service, connection, message); +} + +static void +_connection_destroy_cb (IBusConnection *connection, IBusService *service) +{ + g_assert (IBUS_IS_CONNECTION (connection)); + g_assert (IBUS_IS_SERVICE (service)); + + ibus_service_remove_from_connection (service, connection); +} + +gboolean +ibus_service_add_to_connection (IBusService *service, IBusConnection *connection) +{ + g_assert (IBUS_IS_SERVICE (service)); + g_assert (IBUS_IS_CONNECTION (connection)); + + gboolean retval; + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + 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); + + retval = ibus_connection_register_object_path (connection, priv->path, + (IBusMessageFunc) _service_message_function, service); + if (!retval) { + g_object_unref (connection); + return FALSE; + } + + priv->connections = g_list_append (priv->connections, connection); + g_signal_connect (connection, + "destroy", + (GCallback) _connection_destroy_cb, + service); + + return retval; +} + +GList * +ibus_service_get_connections (IBusService *service) +{ + g_assert (IBUS_IS_SERVICE (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; +} + +gboolean +ibus_service_remove_from_connection (IBusService *service, IBusConnection *connection) +{ + g_return_val_if_fail (IBUS_IS_SERVICE (service), FALSE); + g_return_val_if_fail (IBUS_IS_CONNECTION (connection), FALSE); + + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + g_assert (priv->path != NULL); + g_assert (g_list_find (priv->connections, connection) != NULL); + + gboolean retval; + retval = ibus_connection_unregister_object_path (connection, priv->path); + + if (!retval) { + return FALSE; + } + + g_signal_handlers_disconnect_by_func (connection, + (GCallback) _connection_destroy_cb, + service); + priv->connections = g_list_remove (priv->connections, connection); + g_object_unref (connection); + + return TRUE; +} + +gboolean +ibus_service_remove_from_all_connections (IBusService *service) +{ + g_return_val_if_fail (IBUS_IS_SERVICE (service), FALSE); + + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + GList *element = priv->connections; + while (element != NULL) { + IBusConnection *connection = IBUS_CONNECTION (element->data); + + gboolean retval; + retval = ibus_connection_unregister_object_path (connection, priv->path); + + g_signal_handlers_disconnect_by_func (connection, + (GCallback) _connection_destroy_cb, + service); + g_object_unref (connection); + element = element->next; + } + + g_list_free (priv->connections); + priv->connections = NULL; + return TRUE; +} + +gboolean +ibus_service_send_signal (IBusService *service, + const gchar *interface, + const gchar *name, + GType first_arg_type, + ...) +{ + g_assert (IBUS_IS_SERVICE (service)); + g_assert (name != NULL); + + gboolean retval; + va_list args; + GList *p; + + IBusServicePrivate *priv; + priv = IBUS_SERVICE_GET_PRIVATE (service); + + for (p = priv->connections; p != NULL; p = p->next) { + va_start (args, first_arg_type); + retval = ibus_connection_send_signal_valist ((IBusConnection *) p->data, + priv->path, + interface, + name, + first_arg_type, + args); + va_end (args); + } + return retval; +} diff --git a/src/ibusservice.h b/src/ibusservice.h new file mode 100644 index 0000000..9d90a85 --- /dev/null +++ b/src/ibusservice.h @@ -0,0 +1,99 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_SERVICE_H_ +#define __IBUS_SERVICE_H_ + +#include <dbus/dbus.h> +#include "ibusobject.h" +#include "ibusconnection.h" + +/* + * Type macros. + */ + +/* define GOBJECT macros */ +#define IBUS_TYPE_SERVICE \ + (ibus_service_get_type ()) +#define IBUS_SERVICE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_SERVICE, IBusService)) +#define IBUS_SERVICE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_SERVICE, IBusServiceClass)) +#define IBUS_IS_SERVICE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_SERVICE)) +#define IBUS_IS_SERVICE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_SERVICE)) +#define IBUS_SERVICE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_SERVICE, IBusServiceClass)) + +G_BEGIN_DECLS + +typedef struct _IBusService IBusService; +typedef struct _IBusServiceClass IBusServiceClass; + +struct _IBusService { + IBusObject parent; + /* instance members */ +}; + +typedef gboolean (* ServiceIBusMessageFunc) (IBusService *service, + IBusConnection *connection, + IBusMessage *message); +typedef gboolean (* ServiceIBusSignalFunc) (IBusService *service, + IBusConnection *connection, + IBusMessage *message); + +struct _IBusServiceClass { + IBusObjectClass parent; + + /* signals */ + gboolean (* ibus_message) (IBusService *service, + IBusConnection *connection, + IBusMessage *message); + gboolean (* ibus_signal) (IBusService *service, + IBusConnection *connection, + IBusMessage *message); + /*< private >*/ + /* padding */ + gpointer pdummy[6]; +}; + + +GType ibus_service_get_type (void); +IBusService *ibus_service_new (const gchar *path); +const gchar *ibus_service_get_path (IBusService *service); +gboolean ibus_service_handle_message (IBusService *service, + IBusConnection *connection, + IBusMessage *message); +gboolean ibus_service_add_to_connection (IBusService *service, + IBusConnection *connection); +GList *ibus_service_get_connections (IBusService *service); +gboolean ibus_service_remove_from_connection + (IBusService *service, + IBusConnection *connection); +gboolean ibus_service_remove_from_all_connections + (IBusService *service); +gboolean ibus_service_send_signal (IBusService *service, + const gchar *interface, + const gchar *name, + GType first_arg_type, + ...); +G_END_DECLS +#endif + diff --git a/src/ibusshare.c b/src/ibusshare.c new file mode 100644 index 0000000..26a6480 --- /dev/null +++ b/src/ibusshare.c @@ -0,0 +1,164 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 <glib-object.h> +#include <unistd.h> +#include <stdlib.h> +#include <pwd.h> +#include "ibusshare.h" + +const gchar * +ibus_get_user_name (void) +{ + static gchar *username = NULL; + if (username == NULL) { + username = g_strdup (getlogin()); + if (username == NULL) + username = g_strdup (g_getenv("SUDO_USER")); + if (username == NULL) { + const gchar *uid = g_getenv ("USERHELPER_UID"); + if (uid != NULL) { + gchar *end; + uid_t id = (uid_t)strtol(uid, &end, 10); + if (uid != end) { + struct passwd *pw = getpwuid (id); + if (pw != NULL) { + username = g_strdup (pw->pw_name); + } + } + } + } + if (username == NULL) + username = g_strdup (g_getenv("USERNAME")); + if (username == NULL) + username = g_strdup (g_getenv("LOGNAME")); + if (username == NULL) + username = g_strdup (g_getenv("USER")); + if (username == NULL) + username = g_strdup (g_getenv("LNAME")); + + } + return username; +} + +const gchar * +ibus_get_socket_path (void) +{ + static gchar *path = NULL; + + if (path == NULL) { + gchar *display; + gchar *hostname = ""; + gchar *displaynumber = "0"; + gchar *screennumber = "0"; + const gchar *username = NULL; + gchar *p; + + display = g_strdup (g_getenv ("DISPLAY")); + if (display == NULL) { + g_warning ("DISPLAY is empty! We use default DISPLAY (:0.0)"); + } + else { + p = display; + hostname = display; + for (; *p != ':' && *p != '\0'; p++); + + if (*p == ':') { + *p = '\0'; + p++; + displaynumber = p; + } + + for (; *p != '.' && *p != '\0'; p++); + + if (*p == '.') { + *p = '\0'; + p++; + screennumber = p; + } + } + + username = ibus_get_user_name (); + + path = g_strdup_printf ( + "/tmp/ibus-%s/ibus-%s-%s.%s", + username, hostname, displaynumber, screennumber); + + g_free (display); + } + return path; + +} + +const gchar * +ibus_get_address (void) +{ + static gchar *address = NULL; + + if (address == NULL) { + address = g_strdup_printf ( + "unix:path=%s", + ibus_get_socket_path ()); + } + return address; +} + +void +ibus_free_strv (gchar **strv) +{ + gchar **p; + + if (strv == NULL) + return; + + for (p = strv; *p != NULL; p++) { + g_free (*p); + } + + g_free (strv); +} + + +void +ibus_init (void) +{ + g_type_init (); +} + +static GMainLoop *main_loop = NULL; + +void +ibus_main (void) +{ + main_loop = g_main_loop_new (NULL, FALSE); + + g_main_loop_run (main_loop); + + g_main_loop_unref (main_loop); + main_loop = NULL; +} + +void +ibus_quit (void) +{ + if (main_loop) { + g_main_loop_quit (main_loop); + } +} diff --git a/src/ibusshare.h b/src/ibusshare.h new file mode 100644 index 0000000..142bd47 --- /dev/null +++ b/src/ibusshare.h @@ -0,0 +1,68 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_SHARE_H_ +#define __IBUS_SHARE_H_ + +#include <glib.h> + +#define IBUS_SERVICE_IBUS "org.freedesktop.IBus" +#define IBUS_SERVICE_PANEL "org.freedesktop.IBus.Panel" +#define IBUS_SERVICE_CONFIG "org.freedesktop.IBus.Config" +#define IBUS_SERVICE_NOTIFICATIONS "org.freedesktop.IBus.Notifications" + +#define IBUS_PATH_IBUS "/org/freedesktop/IBus" +#define IBUS_PATH_FACTORY "/org/freedesktop/IBus/Factory" +#define IBUS_PATH_PANEL "/org/freedesktop/IBus/Panel" +#define IBUS_PATH_CONFIG "/org/freedesktop/IBus/Config" +#define IBUS_PATH_NOTIFICATIONS "/org/freedesktop/IBus/Notifications" +#define IBUS_PATH_INPUT_CONTEXT "/org/freedesktop/IBus/InputContext_%d" + +#define IBUS_INTERFACE_IBUS "org.freedesktop.IBus" +#define IBUS_INTERFACE_INPUT_CONTEXT \ + "org.freedesktop.IBus.InputContext" +#define IBUS_INTERFACE_FACTORY "org.freedesktop.IBus.Factory" +#define IBUS_INTERFACE_ENGINE "org.freedesktop.IBus.Engine" +#define IBUS_INTERFACE_PANEL "org.freedesktop.IBus.Panel" +#define IBUS_INTERFACE_CONFIG "org.freedesktop.IBus.Config" +#define IBUS_INTERFACE_NOTIFICATIONS "org.freedesktop.IBus.Notifications" + +G_BEGIN_DECLS + +const gchar *ibus_get_address (void); +const gchar *ibus_get_user_name (void); +const gchar *ibus_get_socket_path (void); + +const gchar *ibus_keyval_name (guint keyval); +guint ibus_keyval_from_name (const gchar *keyval_name); +void ibus_free_strv (gchar **strv); +const gchar *ibus_key_event_to_string + (guint keyval, + guint modifiers); + +gboolean ibus_key_event_from_string + (const gchar *string, + guint *keyval, + guint *modifiers); +void ibus_init (void); +void ibus_main (void); +void ibus_quit (void); + +G_END_DECLS +#endif diff --git a/src/ibustext.c b/src/ibustext.c new file mode 100644 index 0000000..9b87701 --- /dev/null +++ b/src/ibustext.c @@ -0,0 +1,283 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 "ibustext.h" + +/* functions prototype */ +static void ibus_text_class_init (IBusTextClass *klass); +static void ibus_text_init (IBusText *text); +static void ibus_text_destroy (IBusText *text); +static gboolean ibus_text_serialize (IBusText *text, + IBusMessageIter *iter); +static gboolean ibus_text_deserialize (IBusText *text, + IBusMessageIter *iter); +static gboolean ibus_text_copy (IBusText *dest, + const IBusText *src); + +static IBusSerializableClass *parent_class = NULL; + +GType +ibus_text_get_type (void) +{ + static GType type = 0; + + static const GTypeInfo type_info = { + sizeof (IBusTextClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ibus_text_class_init, + NULL, /* class finialize */ + NULL, /* class data */ + sizeof (IBusText), + 0, + (GInstanceInitFunc) ibus_text_init, + }; + + if (type == 0) { + type = g_type_register_static (IBUS_TYPE_SERIALIZABLE, + "IBusText", + &type_info, + 0); + } + + return type; +} + +static void +ibus_text_class_init (IBusTextClass *klass) +{ + IBusObjectClass *object_class = IBUS_OBJECT_CLASS (klass); + IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (klass); + + parent_class = (IBusSerializableClass *) g_type_class_peek_parent (klass); + + object_class->destroy = (IBusObjectDestroyFunc) ibus_text_destroy; + + serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_text_serialize; + serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_text_deserialize; + serializable_class->copy = (IBusSerializableCopyFunc) ibus_text_copy; + + g_string_append (serializable_class->signature, "sv"); +} + +static void +ibus_text_init (IBusText *text) +{ + text->is_static = TRUE; + text->text = ""; + text->attrs = NULL; +} + +static void +ibus_text_destroy (IBusText *text) +{ + if (text->text != NULL && text->is_static == FALSE) { + g_free (text->text); + text->text = NULL; + } + + if (text->attrs) { + g_object_unref (text->attrs); + text->attrs = NULL; + } + + IBUS_OBJECT_CLASS (parent_class)->destroy ((IBusObject *)text); +} + +static gboolean +ibus_text_serialize (IBusText *text, + IBusMessageIter *iter) +{ + gboolean retval; + + retval = parent_class->serialize ((IBusSerializable *)text, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_append (iter, G_TYPE_STRING, &text->text); + g_return_val_if_fail (retval, FALSE); + + if (text->attrs == NULL) + text->attrs = ibus_attr_list_new (); + + retval = ibus_message_iter_append (iter, IBUS_TYPE_ATTR_LIST, &text->attrs); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_text_deserialize (IBusText *text, + IBusMessageIter *iter) +{ + gboolean retval; + gchar *str; + + retval = parent_class->deserialize ((IBusSerializable *)text, iter); + g_return_val_if_fail (retval, FALSE); + + retval = ibus_message_iter_get (iter, G_TYPE_STRING, &str); + g_return_val_if_fail (retval, FALSE); + + text->is_static = FALSE; + text->text = g_strdup (str); + + if (text->attrs) { + g_object_unref (text->attrs); + text->attrs = NULL; + } + + retval = ibus_message_iter_get (iter, IBUS_TYPE_ATTR_LIST, &text->attrs); + g_return_val_if_fail (retval, FALSE); + + return TRUE; +} + +static gboolean +ibus_text_copy (IBusText *dest, + const IBusText *src) +{ + gboolean retval; + + retval = parent_class->copy ((IBusSerializable *)dest, + (IBusSerializable *)src); + g_return_val_if_fail (retval, FALSE); + + g_return_val_if_fail (IBUS_IS_TEXT (dest), FALSE); + g_return_val_if_fail (IBUS_IS_TEXT (src), FALSE); + + dest->text = g_strdup (src->text); + dest->is_static = FALSE; + if (src->attrs) + dest->attrs = (IBusAttrList *)ibus_serializable_copy ((IBusSerializable *)src->attrs); + + return TRUE; +} + +IBusText * +ibus_text_new_from_string (const gchar *str) +{ + g_return_val_if_fail (str != NULL, NULL); + + IBusText *text; + + text= g_object_new (IBUS_TYPE_TEXT, 0); + + text->is_static = FALSE; + text->text = g_strdup (str); + + return text; +} + +IBusText * +ibus_text_new_from_ucs4 (const gunichar *str) +{ + g_return_val_if_fail (str != NULL, NULL); + + IBusText *text; + + text= g_object_new (IBUS_TYPE_TEXT, 0); + + text->is_static = FALSE; + text->text = g_ucs4_to_utf8 (str, -1, NULL, NULL, NULL); + + return text; +} + +IBusText * +ibus_text_new_from_static_string (const gchar *str) +{ + g_return_val_if_fail (str != NULL, NULL); + + IBusText *text; + + text= g_object_new (IBUS_TYPE_TEXT, 0); + + text->is_static = TRUE; + text->text = (gchar *)str; + + return text; +} + +IBusText * +ibus_text_new_from_printf (const gchar *format, + ...) +{ + g_return_val_if_fail (format != NULL, NULL); + + gchar *str; + IBusText *text; + va_list args; + + va_start (args, format); + str = g_strdup_vprintf (format, args); + va_end (args); + + if (str == NULL) + return NULL; + + text= g_object_new (IBUS_TYPE_TEXT, 0); + + text->text = (gchar *)str; + + return text; +} + +IBusText * +ibus_text_new_from_unichar (gunichar c) +{ + IBusText *text; + gint len; + + text= g_object_new (IBUS_TYPE_TEXT, 0); + + text->text = (gchar *)g_malloc (12); + len = g_unichar_to_utf8 (c, text->text); + text->text[len] = 0; + + return text; + +} + +void +ibus_text_append_attribute (IBusText *text, + guint type, + guint value, + guint start_index, + gint end_index) +{ + g_assert (IBUS_IS_TEXT (text)); + + if (end_index < 0) { + end_index += g_utf8_strlen(text->text, -1) + 1; + } + + if (end_index <= 0) + return; + + if (text->attrs == NULL) + text->attrs = ibus_attr_list_new (); + + ibus_attr_list_append (text->attrs, ibus_attribute_new (type, value, start_index, end_index)); +} + +guint +ibus_text_get_length (IBusText *text) +{ + return g_utf8_strlen (text->text, -1); +} diff --git a/src/ibustext.h b/src/ibustext.h new file mode 100644 index 0000000..9696f80 --- /dev/null +++ b/src/ibustext.h @@ -0,0 +1,77 @@ +/* vim:set et sts=4: */ +/* IBus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_TEXT_H_ +#define __IBUS_TEXT_H_ + +#include "ibusserializable.h" +#include "ibusattribute.h" + +/* + * Type macros. + */ +/* define IBusText macros */ +#define IBUS_TYPE_TEXT \ + (ibus_text_get_type ()) +#define IBUS_TEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_TEXT, IBusText)) +#define IBUS_TEXT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_TEXT, IBusTextClass)) +#define IBUS_IS_TEXT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_TEXT)) +#define IBUS_IS_TEXT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_TEXT)) +#define IBUS_TEXT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_TEXT, IBusTextClass)) + +G_BEGIN_DECLS + +typedef struct _IBusText IBusText; +typedef struct _IBusTextClass IBusTextClass; + +struct _IBusText { + IBusSerializable parent; + + /* members */ + gboolean is_static; + gchar *text; + IBusAttrList *attrs; +}; + +struct _IBusTextClass { + IBusSerializableClass parent; +}; + +GType ibus_text_get_type (void); +IBusText *ibus_text_new_from_string (const gchar *str); +IBusText *ibus_text_new_from_ucs4 (const gunichar *str); +IBusText *ibus_text_new_from_static_string (const gchar *str); +IBusText *ibus_text_new_from_printf (const gchar *fmt, + ...); +IBusText *ibus_text_new_from_unichar (gunichar c); +void ibus_text_append_attribute (IBusText *text, + guint type, + guint value, + guint start_index, + gint end_index); +guint ibus_text_get_length (IBusText *text); + +G_END_DECLS +#endif + diff --git a/src/ibustypes.h b/src/ibustypes.h new file mode 100644 index 0000000..a977db4 --- /dev/null +++ b/src/ibustypes.h @@ -0,0 +1,74 @@ +/* vim:set et sts=4: */ +/* ibus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_TYPES_H_ +#define __IBUS_TYPES_H_ + +typedef enum +{ + IBUS_SHIFT_MASK = 1 << 0, + IBUS_LOCK_MASK = 1 << 1, + IBUS_CONTROL_MASK = 1 << 2, + IBUS_MOD1_MASK = 1 << 3, + IBUS_MOD2_MASK = 1 << 4, + IBUS_MOD3_MASK = 1 << 5, + IBUS_MOD4_MASK = 1 << 6, + IBUS_MOD5_MASK = 1 << 7, + IBUS_BUTTON1_MASK = 1 << 8, + IBUS_BUTTON2_MASK = 1 << 9, + IBUS_BUTTON3_MASK = 1 << 10, + IBUS_BUTTON4_MASK = 1 << 11, + IBUS_BUTTON5_MASK = 1 << 12, + + /* The next few modifiers are used by XKB, so we skip to the end. + * Bits 15 - 25 are currently unused. Bit 29 is used internally. + */ + + /* forard mask */ + IBUS_FORWARD_MASK = 1 << 25, + + IBUS_SUPER_MASK = 1 << 26, + IBUS_HYPER_MASK = 1 << 27, + IBUS_META_MASK = 1 << 28, + + IBUS_RELEASE_MASK = 1 << 30, + + IBUS_MODIFIER_MASK = 0x5c001fff +} IBusModifierType; + +typedef enum { + IBUS_CAP_PREEDIT_TEXT = 1 << 0, + IBUS_CAP_AUXILIARY_TEXT = 1 << 1, + IBUS_CAP_LOOKUP_TABLE = 1 << 2, + IBUS_CAP_FOCUS = 1 << 3, + IBUS_CAP_PROPERTY = 1 << 4, +} IBusCapabilite; + +typedef struct _IBusRectangle IBusRectangle; +struct _IBusRectangle { + gint x; + gint y; + gint width; + gint height; +}; + +typedef void (* IBusFreeFunc) (gpointer ); + +#endif + diff --git a/src/ibusxml.c b/src/ibusxml.c new file mode 100644 index 0000000..6a1e0bf --- /dev/null +++ b/src/ibusxml.c @@ -0,0 +1,317 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 <stdio.h> +#include <string.h> +#include "ibusxml.h" + +static GMarkupParser parser; + +void +ibus_xml_free (XMLNode *node) +{ + g_free (node->name); + + g_free (node->text); + + g_strfreev (node->attributes); + + g_list_foreach (node->sub_nodes, (GFunc) ibus_xml_free, NULL); + g_list_free (node->sub_nodes); + + g_slice_free (XMLNode, node); +} + +static void +_start_root_element_cb (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + XMLNode **node = (XMLNode **) user_data; + g_assert (node != NULL); + + XMLNode *p = g_slice_new0 (XMLNode); + + + p->name = g_strdup (element_name); + + GArray *attributes = g_array_new (TRUE, TRUE, sizeof (gchar *)); + while (*attribute_names != NULL && *attribute_values != NULL) { + gchar *p; + p = g_strdup (*attribute_names++); + g_array_append_val (attributes, p); + p = g_strdup (*attribute_values++); + g_array_append_val (attributes, p); + } + + p->attributes = (gchar **) g_array_free (attributes, FALSE); + + g_markup_parse_context_push (context, &parser, p); + *node = p; +} + + +static void +_start_element_cb (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + XMLNode *node = (XMLNode *) user_data; + + if (node->text) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, " "); + return; + } + + XMLNode *p = g_slice_new0 (XMLNode); + + node->sub_nodes = g_list_append (node->sub_nodes, p); + g_markup_parse_context_push (context, &parser, p); + + p->name = g_strdup (element_name); + + GArray *attributes = g_array_new (TRUE, TRUE, sizeof (gchar *)); + while (*attribute_names != NULL && *attribute_values != NULL) { + gchar *p; + p = g_strdup (*attribute_names++); + g_array_append_val (attributes, p); + p = g_strdup (*attribute_values++); + g_array_append_val (attributes, p); + } + + p->attributes = (gchar **)g_array_free (attributes, FALSE); +} + +static void +_end_element_cb (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + XMLNode *p = (XMLNode *) g_markup_parse_context_pop (context); + + if (p->text && p->sub_nodes) { + g_debug ("Error"); + } + + if (p->text == NULL && p->sub_nodes == NULL) { + p->text = g_strdup (""); + } +} + +static gboolean +_is_space (const gchar *text, + gsize text_len) +{ + gsize i = 0; + + for (i = 0; text[i] != '\0' && i < text_len; i++) { + switch (text[i]) { + case '\t': + case ' ': + case '\n': + case '\r': + continue; + default: + return FALSE; + } + } + + return TRUE; +} + +static void +_text_cb (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error) +{ + XMLNode *p = (XMLNode *)user_data; + + if (_is_space (text, text_len)) { + return; + } + + if (p->sub_nodes || p->text) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, " "); + return; + } + + p->text = g_strndup (text, text_len); +} + +static GMarkupParser parser = { + _start_element_cb, + _end_element_cb, + _text_cb, + 0, + 0, +}; + +XMLNode * +ibus_xml_parse_file (const gchar *filename) +{ + gboolean retval; + GError *error = NULL; + FILE *pf = fopen (filename, "r"); + + if (pf == NULL) { + return NULL; + } + + GMarkupParseContext *context; + XMLNode *node; + + const static GMarkupParser root_parser = { + _start_root_element_cb, + _end_element_cb, + _text_cb, + 0, + 0, + }; + + context = g_markup_parse_context_new (&root_parser, 0, &node, 0); + + while (!feof (pf)) { + gchar buf[1024]; + gssize len = 0; + + len = fread (buf, 1, sizeof (buf), pf); + retval = g_markup_parse_context_parse (context, buf, len, &error); + + if (!retval) + goto _failed_out; + } + + fclose (pf); + + retval = g_markup_parse_context_end_parse (context, &error); + if (!retval) + goto _failed_out; + + g_markup_parse_context_free (context); + + return node; + +_failed_out: + g_warning ("Parse %s failed: %s", filename, error->message); + g_error_free (error); + g_markup_parse_context_free (context); + return NULL; +} + +XMLNode * +ibus_xml_parse_buffer (const gchar *buffer) +{ + gboolean retval; + GError *error = NULL; + + GMarkupParseContext *context; + XMLNode *node; + + const static GMarkupParser root_parser = { + _start_root_element_cb, + _end_element_cb, + _text_cb, + 0, + 0, + }; + + context = g_markup_parse_context_new (&root_parser, 0, &node, 0); + + retval = g_markup_parse_context_parse (context, buffer, strlen (buffer), &error); + + if (!retval) + goto _failed_out; + + retval = g_markup_parse_context_end_parse (context, &error); + if (!retval) + goto _failed_out; + + g_markup_parse_context_free (context); + + return node; + +_failed_out: + g_warning ("Parse buffer failed: %s", error->message); + g_error_free (error); + g_markup_parse_context_free (context); + return NULL; + +} + + +void ibus_xml_free (XMLNode *node); +static void +output_indent (int level, GString *output) +{ + gint i; + for (i = 0; i < level; i++) { + g_string_append (output, " "); + } +} + +static void +xml_output_indent (const XMLNode *node, int level, GString *output) +{ + gchar **attrs; + + output_indent (level, output); + g_string_append_printf (output, "<%s", node->name); + + attrs = node->attributes; + + while (attrs != NULL && *attrs != NULL) { + g_string_append_printf (output, " %s", *(attrs++)); + g_string_append_printf (output, "=\"%s\"", *(attrs++)); + } + + if (node->sub_nodes != NULL){ + g_string_append (output, ">\n"); + GList *sub_node; + + for (sub_node = node->sub_nodes; sub_node != NULL; sub_node = sub_node->next) { + xml_output_indent (sub_node->data, level + 1, output); + } + output_indent (level, output); + g_string_append_printf (output, "</%s>\n",node->name); + } + else if (node->text != NULL) { + gchar *text = g_markup_escape_text (node->text, -1); + g_string_append_printf (output, ">%s</%s>\n", text, node->name); + g_free (text); + } + else { + g_string_append (output, "/>\n"); + } +} + +void +xml_output (const XMLNode *node, GString *output) +{ + xml_output_indent (node, 0, output); +} + diff --git a/src/ibusxml.h b/src/ibusxml.h new file mode 100644 index 0000000..f6aeb25 --- /dev/null +++ b/src/ibusxml.h @@ -0,0 +1,37 @@ +/* vim:set et sts=4: */ +/* bus - The Input Bus + * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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. + */ +#ifndef __IBUS_XML_H__ +#define __IBUS_XML_H__ + +#include <glib.h> + +typedef struct { + gchar *name; + gchar *text; + gchar **attributes; + GList *sub_nodes; +} XMLNode; + +XMLNode *ibus_xml_parse_file (const gchar *name); +XMLNode *ibus_xml_parse_buffer (const gchar *buffer); +void ibus_xml_free (XMLNode *node); +void ibus_xml_output (const XMLNode *node, + GString *output); +#endif diff --git a/src/keyname-table.h b/src/keyname-table.h new file mode 100644 index 0000000..6c51cc8 --- /dev/null +++ b/src/keyname-table.h @@ -0,0 +1,3978 @@ +/* keyname-table.h: Generated by gen-keyname-table.pl from keynames.txt + * + * Date: Thu Nov 2 17:26:30 2006 + * + * Do not edit. + */ +static const char keynames[] = + "space\0" + "exclam\0" + "quotedbl\0" + "numbersign\0" + "dollar\0" + "percent\0" + "ampersand\0" + "apostrophe\0" + "quoteright\0" + "parenleft\0" + "parenright\0" + "asterisk\0" + "plus\0" + "comma\0" + "minus\0" + "period\0" + "slash\0" + "0\0" + "1\0" + "2\0" + "3\0" + "4\0" + "5\0" + "6\0" + "7\0" + "8\0" + "9\0" + "colon\0" + "semicolon\0" + "less\0" + "equal\0" + "greater\0" + "question\0" + "at\0" + "A\0" + "B\0" + "C\0" + "D\0" + "E\0" + "F\0" + "G\0" + "H\0" + "I\0" + "J\0" + "K\0" + "L\0" + "M\0" + "N\0" + "O\0" + "P\0" + "Q\0" + "R\0" + "S\0" + "T\0" + "U\0" + "V\0" + "W\0" + "X\0" + "Y\0" + "Z\0" + "bracketleft\0" + "backslash\0" + "bracketright\0" + "asciicircum\0" + "underscore\0" + "grave\0" + "quoteleft\0" + "a\0" + "b\0" + "c\0" + "d\0" + "e\0" + "f\0" + "g\0" + "h\0" + "i\0" + "j\0" + "k\0" + "l\0" + "m\0" + "n\0" + "o\0" + "p\0" + "q\0" + "r\0" + "s\0" + "t\0" + "u\0" + "v\0" + "w\0" + "x\0" + "y\0" + "z\0" + "braceleft\0" + "bar\0" + "braceright\0" + "asciitilde\0" + "nobreakspace\0" + "exclamdown\0" + "cent\0" + "sterling\0" + "currency\0" + "yen\0" + "brokenbar\0" + "section\0" + "diaeresis\0" + "copyright\0" + "ordfeminine\0" + "guillemotleft\0" + "notsign\0" + "hyphen\0" + "registered\0" + "macron\0" + "degree\0" + "plusminus\0" + "twosuperior\0" + "threesuperior\0" + "acute\0" + "mu\0" + "paragraph\0" + "periodcentered\0" + "cedilla\0" + "onesuperior\0" + "masculine\0" + "guillemotright\0" + "onequarter\0" + "onehalf\0" + "threequarters\0" + "questiondown\0" + "Agrave\0" + "Aacute\0" + "Acircumflex\0" + "Atilde\0" + "Adiaeresis\0" + "Aring\0" + "AE\0" + "Ccedilla\0" + "Egrave\0" + "Eacute\0" + "Ecircumflex\0" + "Ediaeresis\0" + "Igrave\0" + "Iacute\0" + "Icircumflex\0" + "Idiaeresis\0" + "ETH\0" + "Eth\0" + "Ntilde\0" + "Ograve\0" + "Oacute\0" + "Ocircumflex\0" + "Otilde\0" + "Odiaeresis\0" + "multiply\0" + "Ooblique\0" + "Ugrave\0" + "Uacute\0" + "Ucircumflex\0" + "Udiaeresis\0" + "Yacute\0" + "THORN\0" + "Thorn\0" + "ssharp\0" + "agrave\0" + "aacute\0" + "acircumflex\0" + "atilde\0" + "adiaeresis\0" + "aring\0" + "ae\0" + "ccedilla\0" + "egrave\0" + "eacute\0" + "ecircumflex\0" + "ediaeresis\0" + "igrave\0" + "iacute\0" + "icircumflex\0" + "idiaeresis\0" + "eth\0" + "ntilde\0" + "ograve\0" + "oacute\0" + "ocircumflex\0" + "otilde\0" + "odiaeresis\0" + "division\0" + "oslash\0" + "ugrave\0" + "uacute\0" + "ucircumflex\0" + "udiaeresis\0" + "yacute\0" + "thorn\0" + "ydiaeresis\0" + "Aogonek\0" + "breve\0" + "Lstroke\0" + "Lcaron\0" + "Sacute\0" + "Scaron\0" + "Scedilla\0" + "Tcaron\0" + "Zacute\0" + "Zcaron\0" + "Zabovedot\0" + "aogonek\0" + "ogonek\0" + "lstroke\0" + "lcaron\0" + "sacute\0" + "caron\0" + "scaron\0" + "scedilla\0" + "tcaron\0" + "zacute\0" + "doubleacute\0" + "zcaron\0" + "zabovedot\0" + "Racute\0" + "Abreve\0" + "Lacute\0" + "Cacute\0" + "Ccaron\0" + "Eogonek\0" + "Ecaron\0" + "Dcaron\0" + "Dstroke\0" + "Nacute\0" + "Ncaron\0" + "Odoubleacute\0" + "Rcaron\0" + "Uring\0" + "Udoubleacute\0" + "Tcedilla\0" + "racute\0" + "abreve\0" + "lacute\0" + "cacute\0" + "ccaron\0" + "eogonek\0" + "ecaron\0" + "dcaron\0" + "dstroke\0" + "nacute\0" + "ncaron\0" + "odoubleacute\0" + "rcaron\0" + "uring\0" + "udoubleacute\0" + "tcedilla\0" + "abovedot\0" + "Hstroke\0" + "Hcircumflex\0" + "Iabovedot\0" + "Gbreve\0" + "Jcircumflex\0" + "hstroke\0" + "hcircumflex\0" + "idotless\0" + "gbreve\0" + "jcircumflex\0" + "Cabovedot\0" + "Ccircumflex\0" + "Gabovedot\0" + "Gcircumflex\0" + "Ubreve\0" + "Scircumflex\0" + "cabovedot\0" + "ccircumflex\0" + "gabovedot\0" + "gcircumflex\0" + "ubreve\0" + "scircumflex\0" + "kappa\0" + "kra\0" + "Rcedilla\0" + "Itilde\0" + "Lcedilla\0" + "Emacron\0" + "Gcedilla\0" + "Tslash\0" + "rcedilla\0" + "itilde\0" + "lcedilla\0" + "emacron\0" + "gcedilla\0" + "tslash\0" + "ENG\0" + "eng\0" + "Amacron\0" + "Iogonek\0" + "Eabovedot\0" + "Imacron\0" + "Ncedilla\0" + "Omacron\0" + "Kcedilla\0" + "Uogonek\0" + "Utilde\0" + "Umacron\0" + "amacron\0" + "iogonek\0" + "eabovedot\0" + "imacron\0" + "ncedilla\0" + "omacron\0" + "kcedilla\0" + "uogonek\0" + "utilde\0" + "umacron\0" + "overline\0" + "kana_fullstop\0" + "kana_openingbracket\0" + "kana_closingbracket\0" + "kana_comma\0" + "kana_conjunctive\0" + "kana_middledot\0" + "kana_WO\0" + "kana_a\0" + "kana_i\0" + "kana_u\0" + "kana_e\0" + "kana_o\0" + "kana_ya\0" + "kana_yu\0" + "kana_yo\0" + "kana_tsu\0" + "kana_tu\0" + "prolongedsound\0" + "kana_A\0" + "kana_I\0" + "kana_U\0" + "kana_E\0" + "kana_O\0" + "kana_KA\0" + "kana_KI\0" + "kana_KU\0" + "kana_KE\0" + "kana_KO\0" + "kana_SA\0" + "kana_SHI\0" + "kana_SU\0" + "kana_SE\0" + "kana_SO\0" + "kana_TA\0" + "kana_CHI\0" + "kana_TI\0" + "kana_TSU\0" + "kana_TU\0" + "kana_TE\0" + "kana_TO\0" + "kana_NA\0" + "kana_NI\0" + "kana_NU\0" + "kana_NE\0" + "kana_NO\0" + "kana_HA\0" + "kana_HI\0" + "kana_FU\0" + "kana_HU\0" + "kana_HE\0" + "kana_HO\0" + "kana_MA\0" + "kana_MI\0" + "kana_MU\0" + "kana_ME\0" + "kana_MO\0" + "kana_YA\0" + "kana_YU\0" + "kana_YO\0" + "kana_RA\0" + "kana_RI\0" + "kana_RU\0" + "kana_RE\0" + "kana_RO\0" + "kana_WA\0" + "kana_N\0" + "voicedsound\0" + "semivoicedsound\0" + "Arabic_comma\0" + "Arabic_semicolon\0" + "Arabic_question_mark\0" + "Arabic_hamza\0" + "Arabic_maddaonalef\0" + "Arabic_hamzaonalef\0" + "Arabic_hamzaonwaw\0" + "Arabic_hamzaunderalef\0" + "Arabic_hamzaonyeh\0" + "Arabic_alef\0" + "Arabic_beh\0" + "Arabic_tehmarbuta\0" + "Arabic_teh\0" + "Arabic_theh\0" + "Arabic_jeem\0" + "Arabic_hah\0" + "Arabic_khah\0" + "Arabic_dal\0" + "Arabic_thal\0" + "Arabic_ra\0" + "Arabic_zain\0" + "Arabic_seen\0" + "Arabic_sheen\0" + "Arabic_sad\0" + "Arabic_dad\0" + "Arabic_tah\0" + "Arabic_zah\0" + "Arabic_ain\0" + "Arabic_ghain\0" + "Arabic_tatweel\0" + "Arabic_feh\0" + "Arabic_qaf\0" + "Arabic_kaf\0" + "Arabic_lam\0" + "Arabic_meem\0" + "Arabic_noon\0" + "Arabic_ha\0" + "Arabic_heh\0" + "Arabic_waw\0" + "Arabic_alefmaksura\0" + "Arabic_yeh\0" + "Arabic_fathatan\0" + "Arabic_dammatan\0" + "Arabic_kasratan\0" + "Arabic_fatha\0" + "Arabic_damma\0" + "Arabic_kasra\0" + "Arabic_shadda\0" + "Arabic_sukun\0" + "Serbian_dje\0" + "Macedonia_gje\0" + "Cyrillic_io\0" + "Ukrainian_ie\0" + "Ukranian_je\0" + "Macedonia_dse\0" + "Ukrainian_i\0" + "Ukranian_i\0" + "Ukrainian_yi\0" + "Ukranian_yi\0" + "Cyrillic_je\0" + "Serbian_je\0" + "Cyrillic_lje\0" + "Serbian_lje\0" + "Cyrillic_nje\0" + "Serbian_nje\0" + "Serbian_tshe\0" + "Macedonia_kje\0" + "Byelorussian_shortu\0" + "Cyrillic_dzhe\0" + "Serbian_dze\0" + "numerosign\0" + "Serbian_DJE\0" + "Macedonia_GJE\0" + "Cyrillic_IO\0" + "Ukrainian_IE\0" + "Ukranian_JE\0" + "Macedonia_DSE\0" + "Ukrainian_I\0" + "Ukranian_I\0" + "Ukrainian_YI\0" + "Ukranian_YI\0" + "Cyrillic_JE\0" + "Serbian_JE\0" + "Cyrillic_LJE\0" + "Serbian_LJE\0" + "Cyrillic_NJE\0" + "Serbian_NJE\0" + "Serbian_TSHE\0" + "Macedonia_KJE\0" + "Byelorussian_SHORTU\0" + "Cyrillic_DZHE\0" + "Serbian_DZE\0" + "Cyrillic_yu\0" + "Cyrillic_a\0" + "Cyrillic_be\0" + "Cyrillic_tse\0" + "Cyrillic_de\0" + "Cyrillic_ie\0" + "Cyrillic_ef\0" + "Cyrillic_ghe\0" + "Cyrillic_ha\0" + "Cyrillic_i\0" + "Cyrillic_shorti\0" + "Cyrillic_ka\0" + "Cyrillic_el\0" + "Cyrillic_em\0" + "Cyrillic_en\0" + "Cyrillic_o\0" + "Cyrillic_pe\0" + "Cyrillic_ya\0" + "Cyrillic_er\0" + "Cyrillic_es\0" + "Cyrillic_te\0" + "Cyrillic_u\0" + "Cyrillic_zhe\0" + "Cyrillic_ve\0" + "Cyrillic_softsign\0" + "Cyrillic_yeru\0" + "Cyrillic_ze\0" + "Cyrillic_sha\0" + "Cyrillic_e\0" + "Cyrillic_shcha\0" + "Cyrillic_che\0" + "Cyrillic_hardsign\0" + "Cyrillic_YU\0" + "Cyrillic_A\0" + "Cyrillic_BE\0" + "Cyrillic_TSE\0" + "Cyrillic_DE\0" + "Cyrillic_IE\0" + "Cyrillic_EF\0" + "Cyrillic_GHE\0" + "Cyrillic_HA\0" + "Cyrillic_I\0" + "Cyrillic_SHORTI\0" + "Cyrillic_KA\0" + "Cyrillic_EL\0" + "Cyrillic_EM\0" + "Cyrillic_EN\0" + "Cyrillic_O\0" + "Cyrillic_PE\0" + "Cyrillic_YA\0" + "Cyrillic_ER\0" + "Cyrillic_ES\0" + "Cyrillic_TE\0" + "Cyrillic_U\0" + "Cyrillic_ZHE\0" + "Cyrillic_VE\0" + "Cyrillic_SOFTSIGN\0" + "Cyrillic_YERU\0" + "Cyrillic_ZE\0" + "Cyrillic_SHA\0" + "Cyrillic_E\0" + "Cyrillic_SHCHA\0" + "Cyrillic_CHE\0" + "Cyrillic_HARDSIGN\0" + "Greek_ALPHAaccent\0" + "Greek_EPSILONaccent\0" + "Greek_ETAaccent\0" + "Greek_IOTAaccent\0" + "Greek_IOTAdieresis\0" + "Greek_IOTAdiaeresis\0" + "Greek_OMICRONaccent\0" + "Greek_UPSILONaccent\0" + "Greek_UPSILONdieresis\0" + "Greek_OMEGAaccent\0" + "Greek_accentdieresis\0" + "Greek_horizbar\0" + "Greek_alphaaccent\0" + "Greek_epsilonaccent\0" + "Greek_etaaccent\0" + "Greek_iotaaccent\0" + "Greek_iotadieresis\0" + "Greek_iotaaccentdieresis\0" + "Greek_omicronaccent\0" + "Greek_upsilonaccent\0" + "Greek_upsilondieresis\0" + "Greek_upsilonaccentdieresis\0" + "Greek_omegaaccent\0" + "Greek_ALPHA\0" + "Greek_BETA\0" + "Greek_GAMMA\0" + "Greek_DELTA\0" + "Greek_EPSILON\0" + "Greek_ZETA\0" + "Greek_ETA\0" + "Greek_THETA\0" + "Greek_IOTA\0" + "Greek_KAPPA\0" + "Greek_LAMBDA\0" + "Greek_LAMDA\0" + "Greek_MU\0" + "Greek_NU\0" + "Greek_XI\0" + "Greek_OMICRON\0" + "Greek_PI\0" + "Greek_RHO\0" + "Greek_SIGMA\0" + "Greek_TAU\0" + "Greek_UPSILON\0" + "Greek_PHI\0" + "Greek_CHI\0" + "Greek_PSI\0" + "Greek_OMEGA\0" + "Greek_alpha\0" + "Greek_beta\0" + "Greek_gamma\0" + "Greek_delta\0" + "Greek_epsilon\0" + "Greek_zeta\0" + "Greek_eta\0" + "Greek_theta\0" + "Greek_iota\0" + "Greek_kappa\0" + "Greek_lambda\0" + "Greek_lamda\0" + "Greek_mu\0" + "Greek_nu\0" + "Greek_xi\0" + "Greek_omicron\0" + "Greek_pi\0" + "Greek_rho\0" + "Greek_sigma\0" + "Greek_finalsmallsigma\0" + "Greek_tau\0" + "Greek_upsilon\0" + "Greek_phi\0" + "Greek_chi\0" + "Greek_psi\0" + "Greek_omega\0" + "leftradical\0" + "topleftradical\0" + "horizconnector\0" + "topintegral\0" + "botintegral\0" + "vertconnector\0" + "topleftsqbracket\0" + "botleftsqbracket\0" + "toprightsqbracket\0" + "botrightsqbracket\0" + "topleftparens\0" + "botleftparens\0" + "toprightparens\0" + "botrightparens\0" + "leftmiddlecurlybrace\0" + "rightmiddlecurlybrace\0" + "topleftsummation\0" + "botleftsummation\0" + "topvertsummationconnector\0" + "botvertsummationconnector\0" + "toprightsummation\0" + "botrightsummation\0" + "rightmiddlesummation\0" + "lessthanequal\0" + "notequal\0" + "greaterthanequal\0" + "integral\0" + "therefore\0" + "variation\0" + "infinity\0" + "nabla\0" + "approximate\0" + "similarequal\0" + "ifonlyif\0" + "implies\0" + "identical\0" + "radical\0" + "includedin\0" + "includes\0" + "intersection\0" + "union\0" + "logicaland\0" + "logicalor\0" + "partialderivative\0" + "function\0" + "leftarrow\0" + "uparrow\0" + "rightarrow\0" + "downarrow\0" + "blank\0" + "soliddiamond\0" + "checkerboard\0" + "ht\0" + "ff\0" + "cr\0" + "lf\0" + "nl\0" + "vt\0" + "lowrightcorner\0" + "uprightcorner\0" + "upleftcorner\0" + "lowleftcorner\0" + "crossinglines\0" + "horizlinescan1\0" + "horizlinescan3\0" + "horizlinescan5\0" + "horizlinescan7\0" + "horizlinescan9\0" + "leftt\0" + "rightt\0" + "bott\0" + "topt\0" + "vertbar\0" + "emspace\0" + "enspace\0" + "em3space\0" + "em4space\0" + "digitspace\0" + "punctspace\0" + "thinspace\0" + "hairspace\0" + "emdash\0" + "endash\0" + "signifblank\0" + "ellipsis\0" + "doubbaselinedot\0" + "onethird\0" + "twothirds\0" + "onefifth\0" + "twofifths\0" + "threefifths\0" + "fourfifths\0" + "onesixth\0" + "fivesixths\0" + "careof\0" + "figdash\0" + "leftanglebracket\0" + "decimalpoint\0" + "rightanglebracket\0" + "marker\0" + "oneeighth\0" + "threeeighths\0" + "fiveeighths\0" + "seveneighths\0" + "trademark\0" + "signaturemark\0" + "trademarkincircle\0" + "leftopentriangle\0" + "rightopentriangle\0" + "emopencircle\0" + "emopenrectangle\0" + "leftsinglequotemark\0" + "rightsinglequotemark\0" + "leftdoublequotemark\0" + "rightdoublequotemark\0" + "prescription\0" + "minutes\0" + "seconds\0" + "latincross\0" + "hexagram\0" + "filledrectbullet\0" + "filledlefttribullet\0" + "filledrighttribullet\0" + "emfilledcircle\0" + "emfilledrect\0" + "enopencircbullet\0" + "enopensquarebullet\0" + "openrectbullet\0" + "opentribulletup\0" + "opentribulletdown\0" + "openstar\0" + "enfilledcircbullet\0" + "enfilledsqbullet\0" + "filledtribulletup\0" + "filledtribulletdown\0" + "leftpointer\0" + "rightpointer\0" + "club\0" + "diamond\0" + "heart\0" + "maltesecross\0" + "dagger\0" + "doubledagger\0" + "checkmark\0" + "ballotcross\0" + "musicalsharp\0" + "musicalflat\0" + "malesymbol\0" + "femalesymbol\0" + "telephone\0" + "telephonerecorder\0" + "phonographcopyright\0" + "caret\0" + "singlelowquotemark\0" + "doublelowquotemark\0" + "cursor\0" + "leftcaret\0" + "rightcaret\0" + "downcaret\0" + "upcaret\0" + "overbar\0" + "downtack\0" + "upshoe\0" + "downstile\0" + "underbar\0" + "jot\0" + "quad\0" + "uptack\0" + "circle\0" + "upstile\0" + "downshoe\0" + "rightshoe\0" + "leftshoe\0" + "lefttack\0" + "righttack\0" + "hebrew_doublelowline\0" + "hebrew_aleph\0" + "hebrew_bet\0" + "hebrew_beth\0" + "hebrew_gimel\0" + "hebrew_gimmel\0" + "hebrew_dalet\0" + "hebrew_daleth\0" + "hebrew_he\0" + "hebrew_waw\0" + "hebrew_zain\0" + "hebrew_zayin\0" + "hebrew_chet\0" + "hebrew_het\0" + "hebrew_tet\0" + "hebrew_teth\0" + "hebrew_yod\0" + "hebrew_finalkaph\0" + "hebrew_kaph\0" + "hebrew_lamed\0" + "hebrew_finalmem\0" + "hebrew_mem\0" + "hebrew_finalnun\0" + "hebrew_nun\0" + "hebrew_samech\0" + "hebrew_samekh\0" + "hebrew_ayin\0" + "hebrew_finalpe\0" + "hebrew_pe\0" + "hebrew_finalzade\0" + "hebrew_finalzadi\0" + "hebrew_zade\0" + "hebrew_zadi\0" + "hebrew_kuf\0" + "hebrew_qoph\0" + "hebrew_resh\0" + "hebrew_shin\0" + "hebrew_taf\0" + "hebrew_taw\0" + "Thai_kokai\0" + "Thai_khokhai\0" + "Thai_khokhuat\0" + "Thai_khokhwai\0" + "Thai_khokhon\0" + "Thai_khorakhang\0" + "Thai_ngongu\0" + "Thai_chochan\0" + "Thai_choching\0" + "Thai_chochang\0" + "Thai_soso\0" + "Thai_chochoe\0" + "Thai_yoying\0" + "Thai_dochada\0" + "Thai_topatak\0" + "Thai_thothan\0" + "Thai_thonangmontho\0" + "Thai_thophuthao\0" + "Thai_nonen\0" + "Thai_dodek\0" + "Thai_totao\0" + "Thai_thothung\0" + "Thai_thothahan\0" + "Thai_thothong\0" + "Thai_nonu\0" + "Thai_bobaimai\0" + "Thai_popla\0" + "Thai_phophung\0" + "Thai_fofa\0" + "Thai_phophan\0" + "Thai_fofan\0" + "Thai_phosamphao\0" + "Thai_moma\0" + "Thai_yoyak\0" + "Thai_rorua\0" + "Thai_ru\0" + "Thai_loling\0" + "Thai_lu\0" + "Thai_wowaen\0" + "Thai_sosala\0" + "Thai_sorusi\0" + "Thai_sosua\0" + "Thai_hohip\0" + "Thai_lochula\0" + "Thai_oang\0" + "Thai_honokhuk\0" + "Thai_paiyannoi\0" + "Thai_saraa\0" + "Thai_maihanakat\0" + "Thai_saraaa\0" + "Thai_saraam\0" + "Thai_sarai\0" + "Thai_saraii\0" + "Thai_saraue\0" + "Thai_sarauee\0" + "Thai_sarau\0" + "Thai_sarauu\0" + "Thai_phinthu\0" + "Thai_maihanakat_maitho\0" + "Thai_baht\0" + "Thai_sarae\0" + "Thai_saraae\0" + "Thai_sarao\0" + "Thai_saraaimaimuan\0" + "Thai_saraaimaimalai\0" + "Thai_lakkhangyao\0" + "Thai_maiyamok\0" + "Thai_maitaikhu\0" + "Thai_maiek\0" + "Thai_maitho\0" + "Thai_maitri\0" + "Thai_maichattawa\0" + "Thai_thanthakhat\0" + "Thai_nikhahit\0" + "Thai_leksun\0" + "Thai_leknung\0" + "Thai_leksong\0" + "Thai_leksam\0" + "Thai_leksi\0" + "Thai_lekha\0" + "Thai_lekhok\0" + "Thai_lekchet\0" + "Thai_lekpaet\0" + "Thai_lekkao\0" + "Hangul_Kiyeog\0" + "Hangul_SsangKiyeog\0" + "Hangul_KiyeogSios\0" + "Hangul_Nieun\0" + "Hangul_NieunJieuj\0" + "Hangul_NieunHieuh\0" + "Hangul_Dikeud\0" + "Hangul_SsangDikeud\0" + "Hangul_Rieul\0" + "Hangul_RieulKiyeog\0" + "Hangul_RieulMieum\0" + "Hangul_RieulPieub\0" + "Hangul_RieulSios\0" + "Hangul_RieulTieut\0" + "Hangul_RieulPhieuf\0" + "Hangul_RieulHieuh\0" + "Hangul_Mieum\0" + "Hangul_Pieub\0" + "Hangul_SsangPieub\0" + "Hangul_PieubSios\0" + "Hangul_Sios\0" + "Hangul_SsangSios\0" + "Hangul_Ieung\0" + "Hangul_Jieuj\0" + "Hangul_SsangJieuj\0" + "Hangul_Cieuc\0" + "Hangul_Khieuq\0" + "Hangul_Tieut\0" + "Hangul_Phieuf\0" + "Hangul_Hieuh\0" + "Hangul_A\0" + "Hangul_AE\0" + "Hangul_YA\0" + "Hangul_YAE\0" + "Hangul_EO\0" + "Hangul_E\0" + "Hangul_YEO\0" + "Hangul_YE\0" + "Hangul_O\0" + "Hangul_WA\0" + "Hangul_WAE\0" + "Hangul_OE\0" + "Hangul_YO\0" + "Hangul_U\0" + "Hangul_WEO\0" + "Hangul_WE\0" + "Hangul_WI\0" + "Hangul_YU\0" + "Hangul_EU\0" + "Hangul_YI\0" + "Hangul_I\0" + "Hangul_J_Kiyeog\0" + "Hangul_J_SsangKiyeog\0" + "Hangul_J_KiyeogSios\0" + "Hangul_J_Nieun\0" + "Hangul_J_NieunJieuj\0" + "Hangul_J_NieunHieuh\0" + "Hangul_J_Dikeud\0" + "Hangul_J_Rieul\0" + "Hangul_J_RieulKiyeog\0" + "Hangul_J_RieulMieum\0" + "Hangul_J_RieulPieub\0" + "Hangul_J_RieulSios\0" + "Hangul_J_RieulTieut\0" + "Hangul_J_RieulPhieuf\0" + "Hangul_J_RieulHieuh\0" + "Hangul_J_Mieum\0" + "Hangul_J_Pieub\0" + "Hangul_J_PieubSios\0" + "Hangul_J_Sios\0" + "Hangul_J_SsangSios\0" + "Hangul_J_Ieung\0" + "Hangul_J_Jieuj\0" + "Hangul_J_Cieuc\0" + "Hangul_J_Khieuq\0" + "Hangul_J_Tieut\0" + "Hangul_J_Phieuf\0" + "Hangul_J_Hieuh\0" + "Hangul_RieulYeorinHieuh\0" + "Hangul_SunkyeongeumMieum\0" + "Hangul_SunkyeongeumPieub\0" + "Hangul_PanSios\0" + "Hangul_KkogjiDalrinIeung\0" + "Hangul_SunkyeongeumPhieuf\0" + "Hangul_YeorinHieuh\0" + "Hangul_AraeA\0" + "Hangul_AraeAE\0" + "Hangul_J_PanSios\0" + "Hangul_J_KkogjiDalrinIeung\0" + "Hangul_J_YeorinHieuh\0" + "Korean_Won\0" + "OE\0" + "oe\0" + "Ydiaeresis\0" + "EcuSign\0" + "ColonSign\0" + "CruzeiroSign\0" + "FFrancSign\0" + "LiraSign\0" + "MillSign\0" + "NairaSign\0" + "PesetaSign\0" + "RupeeSign\0" + "WonSign\0" + "NewSheqelSign\0" + "DongSign\0" + "EuroSign\0" + "3270_Duplicate\0" + "3270_FieldMark\0" + "3270_Right2\0" + "3270_Left2\0" + "3270_BackTab\0" + "3270_EraseEOF\0" + "3270_EraseInput\0" + "3270_Reset\0" + "3270_Quit\0" + "3270_PA1\0" + "3270_PA2\0" + "3270_PA3\0" + "3270_Test\0" + "3270_Attn\0" + "3270_CursorBlink\0" + "3270_AltCursor\0" + "3270_KeyClick\0" + "3270_Jump\0" + "3270_Ident\0" + "3270_Rule\0" + "3270_Copy\0" + "3270_Play\0" + "3270_Setup\0" + "3270_Record\0" + "3270_ChangeScreen\0" + "3270_DeleteWord\0" + "3270_ExSelect\0" + "3270_CursorSelect\0" + "3270_PrintScreen\0" + "3270_Enter\0" + "ISO_Lock\0" + "ISO_Level2_Latch\0" + "ISO_Level3_Shift\0" + "ISO_Level3_Latch\0" + "ISO_Level3_Lock\0" + "ISO_Group_Latch\0" + "ISO_Group_Lock\0" + "ISO_Next_Group\0" + "ISO_Next_Group_Lock\0" + "ISO_Prev_Group\0" + "ISO_Prev_Group_Lock\0" + "ISO_First_Group\0" + "ISO_First_Group_Lock\0" + "ISO_Last_Group\0" + "ISO_Last_Group_Lock\0" + "ISO_Left_Tab\0" + "ISO_Move_Line_Up\0" + "ISO_Move_Line_Down\0" + "ISO_Partial_Line_Up\0" + "ISO_Partial_Line_Down\0" + "ISO_Partial_Space_Left\0" + "ISO_Partial_Space_Right\0" + "ISO_Set_Margin_Left\0" + "ISO_Set_Margin_Right\0" + "ISO_Release_Margin_Left\0" + "ISO_Release_Margin_Right\0" + "ISO_Release_Both_Margins\0" + "ISO_Fast_Cursor_Left\0" + "ISO_Fast_Cursor_Right\0" + "ISO_Fast_Cursor_Up\0" + "ISO_Fast_Cursor_Down\0" + "ISO_Continuous_Underline\0" + "ISO_Discontinuous_Underline\0" + "ISO_Emphasize\0" + "ISO_Center_Object\0" + "ISO_Enter\0" + "dead_grave\0" + "dead_acute\0" + "dead_circumflex\0" + "dead_tilde\0" + "dead_macron\0" + "dead_breve\0" + "dead_abovedot\0" + "dead_diaeresis\0" + "dead_abovering\0" + "dead_doubleacute\0" + "dead_caron\0" + "dead_cedilla\0" + "dead_ogonek\0" + "dead_iota\0" + "dead_voiced_sound\0" + "dead_semivoiced_sound\0" + "dead_belowdot\0" + "dead_hook\0" + "dead_horn\0" + "AccessX_Enable\0" + "AccessX_Feedback_Enable\0" + "RepeatKeys_Enable\0" + "SlowKeys_Enable\0" + "BounceKeys_Enable\0" + "StickyKeys_Enable\0" + "MouseKeys_Enable\0" + "MouseKeys_Accel_Enable\0" + "Overlay1_Enable\0" + "Overlay2_Enable\0" + "AudibleBell_Enable\0" + "First_Virtual_Screen\0" + "Prev_Virtual_Screen\0" + "Next_Virtual_Screen\0" + "Last_Virtual_Screen\0" + "Terminate_Server\0" + "Pointer_Left\0" + "Pointer_Right\0" + "Pointer_Up\0" + "Pointer_Down\0" + "Pointer_UpLeft\0" + "Pointer_UpRight\0" + "Pointer_DownLeft\0" + "Pointer_DownRight\0" + "Pointer_Button_Dflt\0" + "Pointer_Button1\0" + "Pointer_Button2\0" + "Pointer_Button3\0" + "Pointer_Button4\0" + "Pointer_Button5\0" + "Pointer_DblClick_Dflt\0" + "Pointer_DblClick1\0" + "Pointer_DblClick2\0" + "Pointer_DblClick3\0" + "Pointer_DblClick4\0" + "Pointer_DblClick5\0" + "Pointer_Drag_Dflt\0" + "Pointer_Drag1\0" + "Pointer_Drag2\0" + "Pointer_Drag3\0" + "Pointer_Drag4\0" + "Pointer_EnableKeys\0" + "Pointer_Accelerate\0" + "Pointer_DfltBtnNext\0" + "Pointer_DfltBtnPrev\0" + "Pointer_Drag5\0" + "BackSpace\0" + "Tab\0" + "Linefeed\0" + "Clear\0" + "Return\0" + "Pause\0" + "Scroll_Lock\0" + "Sys_Req\0" + "Escape\0" + "Multi_key\0" + "Kanji\0" + "Muhenkan\0" + "Henkan\0" + "Henkan_Mode\0" + "Romaji\0" + "Hiragana\0" + "Katakana\0" + "Hiragana_Katakana\0" + "Zenkaku\0" + "Hankaku\0" + "Zenkaku_Hankaku\0" + "Touroku\0" + "Massyo\0" + "Kana_Lock\0" + "Kana_Shift\0" + "Eisu_Shift\0" + "Eisu_toggle\0" + "Hangul\0" + "Hangul_Start\0" + "Hangul_End\0" + "Hangul_Hanja\0" + "Hangul_Jamo\0" + "Hangul_Romaja\0" + "Codeinput\0" + "Hangul_Jeonja\0" + "Hangul_Banja\0" + "Hangul_PreHanja\0" + "Hangul_PostHanja\0" + "SingleCandidate\0" + "MultipleCandidate\0" + "PreviousCandidate\0" + "Hangul_Special\0" + "Home\0" + "Left\0" + "Up\0" + "Right\0" + "Down\0" + "Page_Up\0" + "Prior\0" + "Page_Down\0" + "Next\0" + "End\0" + "Begin\0" + "Select\0" + "Print\0" + "Execute\0" + "Insert\0" + "Undo\0" + "Redo\0" + "Menu\0" + "Find\0" + "Cancel\0" + "Help\0" + "Break\0" + "Arabic_switch\0" + "Greek_switch\0" + "Hangul_switch\0" + "Hebrew_switch\0" + "ISO_Group_Shift\0" + "Mode_switch\0" + "kana_switch\0" + "script_switch\0" + "Num_Lock\0" + "KP_Space\0" + "KP_Tab\0" + "KP_Enter\0" + "KP_F1\0" + "KP_F2\0" + "KP_F3\0" + "KP_F4\0" + "KP_Home\0" + "KP_Left\0" + "KP_Up\0" + "KP_Right\0" + "KP_Down\0" + "KP_Page_Up\0" + "KP_Prior\0" + "KP_Page_Down\0" + "KP_Next\0" + "KP_End\0" + "KP_Begin\0" + "KP_Insert\0" + "KP_Delete\0" + "KP_Multiply\0" + "KP_Add\0" + "KP_Separator\0" + "KP_Subtract\0" + "KP_Decimal\0" + "KP_Divide\0" + "KP_0\0" + "KP_1\0" + "KP_2\0" + "KP_3\0" + "KP_4\0" + "KP_5\0" + "KP_6\0" + "KP_7\0" + "KP_8\0" + "KP_9\0" + "KP_Equal\0" + "F1\0" + "F2\0" + "F3\0" + "F4\0" + "F5\0" + "F6\0" + "F7\0" + "F8\0" + "F9\0" + "F10\0" + "F11\0" + "F12\0" + "F13\0" + "F14\0" + "F15\0" + "F16\0" + "F17\0" + "F18\0" + "F19\0" + "F20\0" + "F21\0" + "F22\0" + "F23\0" + "F24\0" + "F25\0" + "F26\0" + "F27\0" + "F28\0" + "F29\0" + "F30\0" + "F31\0" + "F32\0" + "F33\0" + "F34\0" + "F35\0" + "Shift_L\0" + "Shift_R\0" + "Control_L\0" + "Control_R\0" + "Caps_Lock\0" + "Shift_Lock\0" + "Meta_L\0" + "Meta_R\0" + "Alt_L\0" + "Alt_R\0" + "Super_L\0" + "Super_R\0" + "Hyper_L\0" + "Hyper_R\0" + "Delete\0" + "VoidSymbol\0"; + +typedef struct { + guint keyval; + guint offset; +} gdk_key; + +static const gdk_key gdk_keys_by_keyval[] = { + { 0x000020, 0 }, + { 0x000021, 6 }, + { 0x000022, 13 }, + { 0x000023, 22 }, + { 0x000024, 33 }, + { 0x000025, 40 }, + { 0x000026, 48 }, + { 0x000027, 58 }, + { 0x000027, 69 }, + { 0x000028, 80 }, + { 0x000029, 90 }, + { 0x00002a, 101 }, + { 0x00002b, 110 }, + { 0x00002c, 115 }, + { 0x00002d, 121 }, + { 0x00002e, 127 }, + { 0x00002f, 134 }, + { 0x000030, 140 }, + { 0x000031, 142 }, + { 0x000032, 144 }, + { 0x000033, 146 }, + { 0x000034, 148 }, + { 0x000035, 150 }, + { 0x000036, 152 }, + { 0x000037, 154 }, + { 0x000038, 156 }, + { 0x000039, 158 }, + { 0x00003a, 160 }, + { 0x00003b, 166 }, + { 0x00003c, 176 }, + { 0x00003d, 181 }, + { 0x00003e, 187 }, + { 0x00003f, 195 }, + { 0x000040, 204 }, + { 0x000041, 207 }, + { 0x000042, 209 }, + { 0x000043, 211 }, + { 0x000044, 213 }, + { 0x000045, 215 }, + { 0x000046, 217 }, + { 0x000047, 219 }, + { 0x000048, 221 }, + { 0x000049, 223 }, + { 0x00004a, 225 }, + { 0x00004b, 227 }, + { 0x00004c, 229 }, + { 0x00004d, 231 }, + { 0x00004e, 233 }, + { 0x00004f, 235 }, + { 0x000050, 237 }, + { 0x000051, 239 }, + { 0x000052, 241 }, + { 0x000053, 243 }, + { 0x000054, 245 }, + { 0x000055, 247 }, + { 0x000056, 249 }, + { 0x000057, 251 }, + { 0x000058, 253 }, + { 0x000059, 255 }, + { 0x00005a, 257 }, + { 0x00005b, 259 }, + { 0x00005c, 271 }, + { 0x00005d, 281 }, + { 0x00005e, 294 }, + { 0x00005f, 306 }, + { 0x000060, 317 }, + { 0x000060, 323 }, + { 0x000061, 333 }, + { 0x000062, 335 }, + { 0x000063, 337 }, + { 0x000064, 339 }, + { 0x000065, 341 }, + { 0x000066, 343 }, + { 0x000067, 345 }, + { 0x000068, 347 }, + { 0x000069, 349 }, + { 0x00006a, 351 }, + { 0x00006b, 353 }, + { 0x00006c, 355 }, + { 0x00006d, 357 }, + { 0x00006e, 359 }, + { 0x00006f, 361 }, + { 0x000070, 363 }, + { 0x000071, 365 }, + { 0x000072, 367 }, + { 0x000073, 369 }, + { 0x000074, 371 }, + { 0x000075, 373 }, + { 0x000076, 375 }, + { 0x000077, 377 }, + { 0x000078, 379 }, + { 0x000079, 381 }, + { 0x00007a, 383 }, + { 0x00007b, 385 }, + { 0x00007c, 395 }, + { 0x00007d, 399 }, + { 0x00007e, 410 }, + { 0x0000a0, 421 }, + { 0x0000a1, 434 }, + { 0x0000a2, 445 }, + { 0x0000a3, 450 }, + { 0x0000a4, 459 }, + { 0x0000a5, 468 }, + { 0x0000a6, 472 }, + { 0x0000a7, 482 }, + { 0x0000a8, 490 }, + { 0x0000a9, 500 }, + { 0x0000aa, 510 }, + { 0x0000ab, 522 }, + { 0x0000ac, 536 }, + { 0x0000ad, 544 }, + { 0x0000ae, 551 }, + { 0x0000af, 562 }, + { 0x0000b0, 569 }, + { 0x0000b1, 576 }, + { 0x0000b2, 586 }, + { 0x0000b3, 598 }, + { 0x0000b4, 612 }, + { 0x0000b5, 618 }, + { 0x0000b6, 621 }, + { 0x0000b7, 631 }, + { 0x0000b8, 646 }, + { 0x0000b9, 654 }, + { 0x0000ba, 666 }, + { 0x0000bb, 676 }, + { 0x0000bc, 691 }, + { 0x0000bd, 702 }, + { 0x0000be, 710 }, + { 0x0000bf, 724 }, + { 0x0000c0, 737 }, + { 0x0000c1, 744 }, + { 0x0000c2, 751 }, + { 0x0000c3, 763 }, + { 0x0000c4, 770 }, + { 0x0000c5, 781 }, + { 0x0000c6, 787 }, + { 0x0000c7, 790 }, + { 0x0000c8, 799 }, + { 0x0000c9, 806 }, + { 0x0000ca, 813 }, + { 0x0000cb, 825 }, + { 0x0000cc, 836 }, + { 0x0000cd, 843 }, + { 0x0000ce, 850 }, + { 0x0000cf, 862 }, + { 0x0000d0, 873 }, + { 0x0000d0, 877 }, + { 0x0000d1, 881 }, + { 0x0000d2, 888 }, + { 0x0000d3, 895 }, + { 0x0000d4, 902 }, + { 0x0000d5, 914 }, + { 0x0000d6, 921 }, + { 0x0000d7, 932 }, + { 0x0000d8, 941 }, + { 0x0000d9, 950 }, + { 0x0000da, 957 }, + { 0x0000db, 964 }, + { 0x0000dc, 976 }, + { 0x0000dd, 987 }, + { 0x0000de, 994 }, + { 0x0000de, 1000 }, + { 0x0000df, 1006 }, + { 0x0000e0, 1013 }, + { 0x0000e1, 1020 }, + { 0x0000e2, 1027 }, + { 0x0000e3, 1039 }, + { 0x0000e4, 1046 }, + { 0x0000e5, 1057 }, + { 0x0000e6, 1063 }, + { 0x0000e7, 1066 }, + { 0x0000e8, 1075 }, + { 0x0000e9, 1082 }, + { 0x0000ea, 1089 }, + { 0x0000eb, 1101 }, + { 0x0000ec, 1112 }, + { 0x0000ed, 1119 }, + { 0x0000ee, 1126 }, + { 0x0000ef, 1138 }, + { 0x0000f0, 1149 }, + { 0x0000f1, 1153 }, + { 0x0000f2, 1160 }, + { 0x0000f3, 1167 }, + { 0x0000f4, 1174 }, + { 0x0000f5, 1186 }, + { 0x0000f6, 1193 }, + { 0x0000f7, 1204 }, + { 0x0000f8, 1213 }, + { 0x0000f9, 1220 }, + { 0x0000fa, 1227 }, + { 0x0000fb, 1234 }, + { 0x0000fc, 1246 }, + { 0x0000fd, 1257 }, + { 0x0000fe, 1264 }, + { 0x0000ff, 1270 }, + { 0x0001a1, 1281 }, + { 0x0001a2, 1289 }, + { 0x0001a3, 1295 }, + { 0x0001a5, 1303 }, + { 0x0001a6, 1310 }, + { 0x0001a9, 1317 }, + { 0x0001aa, 1324 }, + { 0x0001ab, 1333 }, + { 0x0001ac, 1340 }, + { 0x0001ae, 1347 }, + { 0x0001af, 1354 }, + { 0x0001b1, 1364 }, + { 0x0001b2, 1372 }, + { 0x0001b3, 1379 }, + { 0x0001b5, 1387 }, + { 0x0001b6, 1394 }, + { 0x0001b7, 1401 }, + { 0x0001b9, 1407 }, + { 0x0001ba, 1414 }, + { 0x0001bb, 1423 }, + { 0x0001bc, 1430 }, + { 0x0001bd, 1437 }, + { 0x0001be, 1449 }, + { 0x0001bf, 1456 }, + { 0x0001c0, 1466 }, + { 0x0001c3, 1473 }, + { 0x0001c5, 1480 }, + { 0x0001c6, 1487 }, + { 0x0001c8, 1494 }, + { 0x0001ca, 1501 }, + { 0x0001cc, 1509 }, + { 0x0001cf, 1516 }, + { 0x0001d0, 1523 }, + { 0x0001d1, 1531 }, + { 0x0001d2, 1538 }, + { 0x0001d5, 1545 }, + { 0x0001d8, 1558 }, + { 0x0001d9, 1565 }, + { 0x0001db, 1571 }, + { 0x0001de, 1584 }, + { 0x0001e0, 1593 }, + { 0x0001e3, 1600 }, + { 0x0001e5, 1607 }, + { 0x0001e6, 1614 }, + { 0x0001e8, 1621 }, + { 0x0001ea, 1628 }, + { 0x0001ec, 1636 }, + { 0x0001ef, 1643 }, + { 0x0001f0, 1650 }, + { 0x0001f1, 1658 }, + { 0x0001f2, 1665 }, + { 0x0001f5, 1672 }, + { 0x0001f8, 1685 }, + { 0x0001f9, 1692 }, + { 0x0001fb, 1698 }, + { 0x0001fe, 1711 }, + { 0x0001ff, 1720 }, + { 0x0002a1, 1729 }, + { 0x0002a6, 1737 }, + { 0x0002a9, 1749 }, + { 0x0002ab, 1759 }, + { 0x0002ac, 1766 }, + { 0x0002b1, 1778 }, + { 0x0002b6, 1786 }, + { 0x0002b9, 1798 }, + { 0x0002bb, 1807 }, + { 0x0002bc, 1814 }, + { 0x0002c5, 1826 }, + { 0x0002c6, 1836 }, + { 0x0002d5, 1848 }, + { 0x0002d8, 1858 }, + { 0x0002dd, 1870 }, + { 0x0002de, 1877 }, + { 0x0002e5, 1889 }, + { 0x0002e6, 1899 }, + { 0x0002f5, 1911 }, + { 0x0002f8, 1921 }, + { 0x0002fd, 1933 }, + { 0x0002fe, 1940 }, + { 0x0003a2, 1952 }, + { 0x0003a2, 1958 }, + { 0x0003a3, 1962 }, + { 0x0003a5, 1971 }, + { 0x0003a6, 1978 }, + { 0x0003aa, 1987 }, + { 0x0003ab, 1995 }, + { 0x0003ac, 2004 }, + { 0x0003b3, 2011 }, + { 0x0003b5, 2020 }, + { 0x0003b6, 2027 }, + { 0x0003ba, 2036 }, + { 0x0003bb, 2044 }, + { 0x0003bc, 2053 }, + { 0x0003bd, 2060 }, + { 0x0003bf, 2064 }, + { 0x0003c0, 2068 }, + { 0x0003c7, 2076 }, + { 0x0003cc, 2084 }, + { 0x0003cf, 2094 }, + { 0x0003d1, 2102 }, + { 0x0003d2, 2111 }, + { 0x0003d3, 2119 }, + { 0x0003d9, 2128 }, + { 0x0003dd, 2136 }, + { 0x0003de, 2143 }, + { 0x0003e0, 2151 }, + { 0x0003e7, 2159 }, + { 0x0003ec, 2167 }, + { 0x0003ef, 2177 }, + { 0x0003f1, 2185 }, + { 0x0003f2, 2194 }, + { 0x0003f3, 2202 }, + { 0x0003f9, 2211 }, + { 0x0003fd, 2219 }, + { 0x0003fe, 2226 }, + { 0x00047e, 2234 }, + { 0x0004a1, 2243 }, + { 0x0004a2, 2257 }, + { 0x0004a3, 2277 }, + { 0x0004a4, 2297 }, + { 0x0004a5, 2308 }, + { 0x0004a5, 2325 }, + { 0x0004a6, 2340 }, + { 0x0004a7, 2348 }, + { 0x0004a8, 2355 }, + { 0x0004a9, 2362 }, + { 0x0004aa, 2369 }, + { 0x0004ab, 2376 }, + { 0x0004ac, 2383 }, + { 0x0004ad, 2391 }, + { 0x0004ae, 2399 }, + { 0x0004af, 2407 }, + { 0x0004af, 2416 }, + { 0x0004b0, 2424 }, + { 0x0004b1, 2439 }, + { 0x0004b2, 2446 }, + { 0x0004b3, 2453 }, + { 0x0004b4, 2460 }, + { 0x0004b5, 2467 }, + { 0x0004b6, 2474 }, + { 0x0004b7, 2482 }, + { 0x0004b8, 2490 }, + { 0x0004b9, 2498 }, + { 0x0004ba, 2506 }, + { 0x0004bb, 2514 }, + { 0x0004bc, 2522 }, + { 0x0004bd, 2531 }, + { 0x0004be, 2539 }, + { 0x0004bf, 2547 }, + { 0x0004c0, 2555 }, + { 0x0004c1, 2563 }, + { 0x0004c1, 2572 }, + { 0x0004c2, 2580 }, + { 0x0004c2, 2589 }, + { 0x0004c3, 2597 }, + { 0x0004c4, 2605 }, + { 0x0004c5, 2613 }, + { 0x0004c6, 2621 }, + { 0x0004c7, 2629 }, + { 0x0004c8, 2637 }, + { 0x0004c9, 2645 }, + { 0x0004ca, 2653 }, + { 0x0004cb, 2661 }, + { 0x0004cc, 2669 }, + { 0x0004cc, 2677 }, + { 0x0004cd, 2685 }, + { 0x0004ce, 2693 }, + { 0x0004cf, 2701 }, + { 0x0004d0, 2709 }, + { 0x0004d1, 2717 }, + { 0x0004d2, 2725 }, + { 0x0004d3, 2733 }, + { 0x0004d4, 2741 }, + { 0x0004d5, 2749 }, + { 0x0004d6, 2757 }, + { 0x0004d7, 2765 }, + { 0x0004d8, 2773 }, + { 0x0004d9, 2781 }, + { 0x0004da, 2789 }, + { 0x0004db, 2797 }, + { 0x0004dc, 2805 }, + { 0x0004dd, 2813 }, + { 0x0004de, 2820 }, + { 0x0004df, 2832 }, + { 0x0005ac, 2848 }, + { 0x0005bb, 2861 }, + { 0x0005bf, 2878 }, + { 0x0005c1, 2899 }, + { 0x0005c2, 2912 }, + { 0x0005c3, 2931 }, + { 0x0005c4, 2950 }, + { 0x0005c5, 2968 }, + { 0x0005c6, 2990 }, + { 0x0005c7, 3008 }, + { 0x0005c8, 3020 }, + { 0x0005c9, 3031 }, + { 0x0005ca, 3049 }, + { 0x0005cb, 3060 }, + { 0x0005cc, 3072 }, + { 0x0005cd, 3084 }, + { 0x0005ce, 3095 }, + { 0x0005cf, 3107 }, + { 0x0005d0, 3118 }, + { 0x0005d1, 3130 }, + { 0x0005d2, 3140 }, + { 0x0005d3, 3152 }, + { 0x0005d4, 3164 }, + { 0x0005d5, 3177 }, + { 0x0005d6, 3188 }, + { 0x0005d7, 3199 }, + { 0x0005d8, 3210 }, + { 0x0005d9, 3221 }, + { 0x0005da, 3232 }, + { 0x0005e0, 3245 }, + { 0x0005e1, 3260 }, + { 0x0005e2, 3271 }, + { 0x0005e3, 3282 }, + { 0x0005e4, 3293 }, + { 0x0005e5, 3304 }, + { 0x0005e6, 3316 }, + { 0x0005e7, 3328 }, + { 0x0005e7, 3338 }, + { 0x0005e8, 3349 }, + { 0x0005e9, 3360 }, + { 0x0005ea, 3379 }, + { 0x0005eb, 3390 }, + { 0x0005ec, 3406 }, + { 0x0005ed, 3422 }, + { 0x0005ee, 3438 }, + { 0x0005ef, 3451 }, + { 0x0005f0, 3464 }, + { 0x0005f1, 3477 }, + { 0x0005f2, 3491 }, + { 0x0006a1, 3504 }, + { 0x0006a2, 3516 }, + { 0x0006a3, 3530 }, + { 0x0006a4, 3542 }, + { 0x0006a4, 3555 }, + { 0x0006a5, 3567 }, + { 0x0006a6, 3581 }, + { 0x0006a6, 3593 }, + { 0x0006a7, 3604 }, + { 0x0006a7, 3617 }, + { 0x0006a8, 3629 }, + { 0x0006a8, 3641 }, + { 0x0006a9, 3652 }, + { 0x0006a9, 3665 }, + { 0x0006aa, 3677 }, + { 0x0006aa, 3690 }, + { 0x0006ab, 3702 }, + { 0x0006ac, 3715 }, + { 0x0006ae, 3729 }, + { 0x0006af, 3749 }, + { 0x0006af, 3763 }, + { 0x0006b0, 3775 }, + { 0x0006b1, 3786 }, + { 0x0006b2, 3798 }, + { 0x0006b3, 3812 }, + { 0x0006b4, 3824 }, + { 0x0006b4, 3837 }, + { 0x0006b5, 3849 }, + { 0x0006b6, 3863 }, + { 0x0006b6, 3875 }, + { 0x0006b7, 3886 }, + { 0x0006b7, 3899 }, + { 0x0006b8, 3911 }, + { 0x0006b8, 3923 }, + { 0x0006b9, 3934 }, + { 0x0006b9, 3947 }, + { 0x0006ba, 3959 }, + { 0x0006ba, 3972 }, + { 0x0006bb, 3984 }, + { 0x0006bc, 3997 }, + { 0x0006be, 4011 }, + { 0x0006bf, 4031 }, + { 0x0006bf, 4045 }, + { 0x0006c0, 4057 }, + { 0x0006c1, 4069 }, + { 0x0006c2, 4080 }, + { 0x0006c3, 4092 }, + { 0x0006c4, 4105 }, + { 0x0006c5, 4117 }, + { 0x0006c6, 4129 }, + { 0x0006c7, 4141 }, + { 0x0006c8, 4154 }, + { 0x0006c9, 4166 }, + { 0x0006ca, 4177 }, + { 0x0006cb, 4193 }, + { 0x0006cc, 4205 }, + { 0x0006cd, 4217 }, + { 0x0006ce, 4229 }, + { 0x0006cf, 4241 }, + { 0x0006d0, 4252 }, + { 0x0006d1, 4264 }, + { 0x0006d2, 4276 }, + { 0x0006d3, 4288 }, + { 0x0006d4, 4300 }, + { 0x0006d5, 4312 }, + { 0x0006d6, 4323 }, + { 0x0006d7, 4336 }, + { 0x0006d8, 4348 }, + { 0x0006d9, 4366 }, + { 0x0006da, 4380 }, + { 0x0006db, 4392 }, + { 0x0006dc, 4405 }, + { 0x0006dd, 4416 }, + { 0x0006de, 4431 }, + { 0x0006df, 4444 }, + { 0x0006e0, 4462 }, + { 0x0006e1, 4474 }, + { 0x0006e2, 4485 }, + { 0x0006e3, 4497 }, + { 0x0006e4, 4510 }, + { 0x0006e5, 4522 }, + { 0x0006e6, 4534 }, + { 0x0006e7, 4546 }, + { 0x0006e8, 4559 }, + { 0x0006e9, 4571 }, + { 0x0006ea, 4582 }, + { 0x0006eb, 4598 }, + { 0x0006ec, 4610 }, + { 0x0006ed, 4622 }, + { 0x0006ee, 4634 }, + { 0x0006ef, 4646 }, + { 0x0006f0, 4657 }, + { 0x0006f1, 4669 }, + { 0x0006f2, 4681 }, + { 0x0006f3, 4693 }, + { 0x0006f4, 4705 }, + { 0x0006f5, 4717 }, + { 0x0006f6, 4728 }, + { 0x0006f7, 4741 }, + { 0x0006f8, 4753 }, + { 0x0006f9, 4771 }, + { 0x0006fa, 4785 }, + { 0x0006fb, 4797 }, + { 0x0006fc, 4810 }, + { 0x0006fd, 4821 }, + { 0x0006fe, 4836 }, + { 0x0006ff, 4849 }, + { 0x0007a1, 4867 }, + { 0x0007a2, 4885 }, + { 0x0007a3, 4905 }, + { 0x0007a4, 4921 }, + { 0x0007a5, 4938 }, + { 0x0007a5, 4957 }, + { 0x0007a7, 4977 }, + { 0x0007a8, 4997 }, + { 0x0007a9, 5017 }, + { 0x0007ab, 5039 }, + { 0x0007ae, 5057 }, + { 0x0007af, 5078 }, + { 0x0007b1, 5093 }, + { 0x0007b2, 5111 }, + { 0x0007b3, 5131 }, + { 0x0007b4, 5147 }, + { 0x0007b5, 5164 }, + { 0x0007b6, 5183 }, + { 0x0007b7, 5208 }, + { 0x0007b8, 5228 }, + { 0x0007b9, 5248 }, + { 0x0007ba, 5270 }, + { 0x0007bb, 5298 }, + { 0x0007c1, 5316 }, + { 0x0007c2, 5328 }, + { 0x0007c3, 5339 }, + { 0x0007c4, 5351 }, + { 0x0007c5, 5363 }, + { 0x0007c6, 5377 }, + { 0x0007c7, 5388 }, + { 0x0007c8, 5398 }, + { 0x0007c9, 5410 }, + { 0x0007ca, 5421 }, + { 0x0007cb, 5433 }, + { 0x0007cb, 5446 }, + { 0x0007cc, 5458 }, + { 0x0007cd, 5467 }, + { 0x0007ce, 5476 }, + { 0x0007cf, 5485 }, + { 0x0007d0, 5499 }, + { 0x0007d1, 5508 }, + { 0x0007d2, 5518 }, + { 0x0007d4, 5530 }, + { 0x0007d5, 5540 }, + { 0x0007d6, 5554 }, + { 0x0007d7, 5564 }, + { 0x0007d8, 5574 }, + { 0x0007d9, 5584 }, + { 0x0007e1, 5596 }, + { 0x0007e2, 5608 }, + { 0x0007e3, 5619 }, + { 0x0007e4, 5631 }, + { 0x0007e5, 5643 }, + { 0x0007e6, 5657 }, + { 0x0007e7, 5668 }, + { 0x0007e8, 5678 }, + { 0x0007e9, 5690 }, + { 0x0007ea, 5701 }, + { 0x0007eb, 5713 }, + { 0x0007eb, 5726 }, + { 0x0007ec, 5738 }, + { 0x0007ed, 5747 }, + { 0x0007ee, 5756 }, + { 0x0007ef, 5765 }, + { 0x0007f0, 5779 }, + { 0x0007f1, 5788 }, + { 0x0007f2, 5798 }, + { 0x0007f3, 5810 }, + { 0x0007f4, 5832 }, + { 0x0007f5, 5842 }, + { 0x0007f6, 5856 }, + { 0x0007f7, 5866 }, + { 0x0007f8, 5876 }, + { 0x0007f9, 5886 }, + { 0x0008a1, 5898 }, + { 0x0008a2, 5910 }, + { 0x0008a3, 5925 }, + { 0x0008a4, 5940 }, + { 0x0008a5, 5952 }, + { 0x0008a6, 5964 }, + { 0x0008a7, 5978 }, + { 0x0008a8, 5995 }, + { 0x0008a9, 6012 }, + { 0x0008aa, 6030 }, + { 0x0008ab, 6048 }, + { 0x0008ac, 6062 }, + { 0x0008ad, 6076 }, + { 0x0008ae, 6091 }, + { 0x0008af, 6106 }, + { 0x0008b0, 6127 }, + { 0x0008b1, 6149 }, + { 0x0008b2, 6166 }, + { 0x0008b3, 6183 }, + { 0x0008b4, 6209 }, + { 0x0008b5, 6235 }, + { 0x0008b6, 6253 }, + { 0x0008b7, 6271 }, + { 0x0008bc, 6292 }, + { 0x0008bd, 6306 }, + { 0x0008be, 6315 }, + { 0x0008bf, 6332 }, + { 0x0008c0, 6341 }, + { 0x0008c1, 6351 }, + { 0x0008c2, 6361 }, + { 0x0008c5, 6370 }, + { 0x0008c8, 6376 }, + { 0x0008c9, 6388 }, + { 0x0008cd, 6401 }, + { 0x0008ce, 6410 }, + { 0x0008cf, 6418 }, + { 0x0008d6, 6428 }, + { 0x0008da, 6436 }, + { 0x0008db, 6447 }, + { 0x0008dc, 6456 }, + { 0x0008dd, 6469 }, + { 0x0008de, 6475 }, + { 0x0008df, 6486 }, + { 0x0008ef, 6496 }, + { 0x0008f6, 6514 }, + { 0x0008fb, 6523 }, + { 0x0008fc, 6533 }, + { 0x0008fd, 6541 }, + { 0x0008fe, 6552 }, + { 0x0009df, 6562 }, + { 0x0009e0, 6568 }, + { 0x0009e1, 6581 }, + { 0x0009e2, 6594 }, + { 0x0009e3, 6597 }, + { 0x0009e4, 6600 }, + { 0x0009e5, 6603 }, + { 0x0009e8, 6606 }, + { 0x0009e9, 6609 }, + { 0x0009ea, 6612 }, + { 0x0009eb, 6627 }, + { 0x0009ec, 6641 }, + { 0x0009ed, 6654 }, + { 0x0009ee, 6668 }, + { 0x0009ef, 6682 }, + { 0x0009f0, 6697 }, + { 0x0009f1, 6712 }, + { 0x0009f2, 6727 }, + { 0x0009f3, 6742 }, + { 0x0009f4, 6757 }, + { 0x0009f5, 6763 }, + { 0x0009f6, 6770 }, + { 0x0009f7, 6775 }, + { 0x0009f8, 6780 }, + { 0x000aa1, 6788 }, + { 0x000aa2, 6796 }, + { 0x000aa3, 6804 }, + { 0x000aa4, 6813 }, + { 0x000aa5, 6822 }, + { 0x000aa6, 6833 }, + { 0x000aa7, 6844 }, + { 0x000aa8, 6854 }, + { 0x000aa9, 6864 }, + { 0x000aaa, 6871 }, + { 0x000aac, 6878 }, + { 0x000aae, 6890 }, + { 0x000aaf, 6899 }, + { 0x000ab0, 6915 }, + { 0x000ab1, 6924 }, + { 0x000ab2, 6934 }, + { 0x000ab3, 6943 }, + { 0x000ab4, 6953 }, + { 0x000ab5, 6965 }, + { 0x000ab6, 6976 }, + { 0x000ab7, 6985 }, + { 0x000ab8, 6996 }, + { 0x000abb, 7003 }, + { 0x000abc, 7011 }, + { 0x000abd, 7028 }, + { 0x000abe, 7041 }, + { 0x000abf, 7059 }, + { 0x000ac3, 7066 }, + { 0x000ac4, 7076 }, + { 0x000ac5, 7089 }, + { 0x000ac6, 7101 }, + { 0x000ac9, 7114 }, + { 0x000aca, 7124 }, + { 0x000acb, 7138 }, + { 0x000acc, 7156 }, + { 0x000acd, 7173 }, + { 0x000ace, 7191 }, + { 0x000acf, 7204 }, + { 0x000ad0, 7220 }, + { 0x000ad1, 7240 }, + { 0x000ad2, 7261 }, + { 0x000ad3, 7281 }, + { 0x000ad4, 7302 }, + { 0x000ad6, 7315 }, + { 0x000ad7, 7323 }, + { 0x000ad9, 7331 }, + { 0x000ada, 7342 }, + { 0x000adb, 7351 }, + { 0x000adc, 7368 }, + { 0x000add, 7388 }, + { 0x000ade, 7409 }, + { 0x000adf, 7424 }, + { 0x000ae0, 7437 }, + { 0x000ae1, 7454 }, + { 0x000ae2, 7473 }, + { 0x000ae3, 7488 }, + { 0x000ae4, 7504 }, + { 0x000ae5, 7522 }, + { 0x000ae6, 7531 }, + { 0x000ae7, 7550 }, + { 0x000ae8, 7567 }, + { 0x000ae9, 7585 }, + { 0x000aea, 7605 }, + { 0x000aeb, 7617 }, + { 0x000aec, 7630 }, + { 0x000aed, 7635 }, + { 0x000aee, 7643 }, + { 0x000af0, 7649 }, + { 0x000af1, 7662 }, + { 0x000af2, 7669 }, + { 0x000af3, 7682 }, + { 0x000af4, 7692 }, + { 0x000af5, 7704 }, + { 0x000af6, 7717 }, + { 0x000af7, 7729 }, + { 0x000af8, 7740 }, + { 0x000af9, 7753 }, + { 0x000afa, 7763 }, + { 0x000afb, 7781 }, + { 0x000afc, 7801 }, + { 0x000afd, 7807 }, + { 0x000afe, 7826 }, + { 0x000aff, 7845 }, + { 0x000ba3, 7852 }, + { 0x000ba6, 7862 }, + { 0x000ba8, 7873 }, + { 0x000ba9, 7883 }, + { 0x000bc0, 7891 }, + { 0x000bc2, 7899 }, + { 0x000bc3, 7908 }, + { 0x000bc4, 7915 }, + { 0x000bc6, 7925 }, + { 0x000bca, 7934 }, + { 0x000bcc, 7938 }, + { 0x000bce, 7943 }, + { 0x000bcf, 7950 }, + { 0x000bd3, 7957 }, + { 0x000bd6, 7965 }, + { 0x000bd8, 7974 }, + { 0x000bda, 7984 }, + { 0x000bdc, 7993 }, + { 0x000bfc, 8002 }, + { 0x000cdf, 8012 }, + { 0x000ce0, 8033 }, + { 0x000ce1, 8046 }, + { 0x000ce1, 8057 }, + { 0x000ce2, 8069 }, + { 0x000ce2, 8082 }, + { 0x000ce3, 8096 }, + { 0x000ce3, 8109 }, + { 0x000ce4, 8123 }, + { 0x000ce5, 8133 }, + { 0x000ce6, 8144 }, + { 0x000ce6, 8156 }, + { 0x000ce7, 8169 }, + { 0x000ce7, 8181 }, + { 0x000ce8, 8192 }, + { 0x000ce8, 8203 }, + { 0x000ce9, 8215 }, + { 0x000cea, 8226 }, + { 0x000ceb, 8243 }, + { 0x000cec, 8255 }, + { 0x000ced, 8268 }, + { 0x000cee, 8284 }, + { 0x000cef, 8295 }, + { 0x000cf0, 8311 }, + { 0x000cf1, 8322 }, + { 0x000cf1, 8336 }, + { 0x000cf2, 8350 }, + { 0x000cf3, 8362 }, + { 0x000cf4, 8377 }, + { 0x000cf5, 8387 }, + { 0x000cf5, 8404 }, + { 0x000cf6, 8421 }, + { 0x000cf6, 8433 }, + { 0x000cf7, 8445 }, + { 0x000cf7, 8456 }, + { 0x000cf8, 8468 }, + { 0x000cf9, 8480 }, + { 0x000cfa, 8492 }, + { 0x000cfa, 8503 }, + { 0x000da1, 8514 }, + { 0x000da2, 8525 }, + { 0x000da3, 8538 }, + { 0x000da4, 8552 }, + { 0x000da5, 8566 }, + { 0x000da6, 8579 }, + { 0x000da7, 8595 }, + { 0x000da8, 8607 }, + { 0x000da9, 8620 }, + { 0x000daa, 8634 }, + { 0x000dab, 8648 }, + { 0x000dac, 8658 }, + { 0x000dad, 8671 }, + { 0x000dae, 8683 }, + { 0x000daf, 8696 }, + { 0x000db0, 8709 }, + { 0x000db1, 8722 }, + { 0x000db2, 8741 }, + { 0x000db3, 8757 }, + { 0x000db4, 8768 }, + { 0x000db5, 8779 }, + { 0x000db6, 8790 }, + { 0x000db7, 8804 }, + { 0x000db8, 8819 }, + { 0x000db9, 8833 }, + { 0x000dba, 8843 }, + { 0x000dbb, 8857 }, + { 0x000dbc, 8868 }, + { 0x000dbd, 8882 }, + { 0x000dbe, 8892 }, + { 0x000dbf, 8905 }, + { 0x000dc0, 8916 }, + { 0x000dc1, 8932 }, + { 0x000dc2, 8942 }, + { 0x000dc3, 8953 }, + { 0x000dc4, 8964 }, + { 0x000dc5, 8972 }, + { 0x000dc6, 8984 }, + { 0x000dc7, 8992 }, + { 0x000dc8, 9004 }, + { 0x000dc9, 9016 }, + { 0x000dca, 9028 }, + { 0x000dcb, 9039 }, + { 0x000dcc, 9050 }, + { 0x000dcd, 9063 }, + { 0x000dce, 9073 }, + { 0x000dcf, 9087 }, + { 0x000dd0, 9102 }, + { 0x000dd1, 9113 }, + { 0x000dd2, 9129 }, + { 0x000dd3, 9141 }, + { 0x000dd4, 9153 }, + { 0x000dd5, 9164 }, + { 0x000dd6, 9176 }, + { 0x000dd7, 9188 }, + { 0x000dd8, 9201 }, + { 0x000dd9, 9212 }, + { 0x000dda, 9224 }, + { 0x000dde, 9237 }, + { 0x000ddf, 9260 }, + { 0x000de0, 9270 }, + { 0x000de1, 9281 }, + { 0x000de2, 9293 }, + { 0x000de3, 9304 }, + { 0x000de4, 9323 }, + { 0x000de5, 9343 }, + { 0x000de6, 9360 }, + { 0x000de7, 9374 }, + { 0x000de8, 9389 }, + { 0x000de9, 9400 }, + { 0x000dea, 9412 }, + { 0x000deb, 9424 }, + { 0x000dec, 9441 }, + { 0x000ded, 9458 }, + { 0x000df0, 9472 }, + { 0x000df1, 9484 }, + { 0x000df2, 9497 }, + { 0x000df3, 9510 }, + { 0x000df4, 9522 }, + { 0x000df5, 9533 }, + { 0x000df6, 9544 }, + { 0x000df7, 9556 }, + { 0x000df8, 9569 }, + { 0x000df9, 9582 }, + { 0x000ea1, 9594 }, + { 0x000ea2, 9608 }, + { 0x000ea3, 9627 }, + { 0x000ea4, 9645 }, + { 0x000ea5, 9658 }, + { 0x000ea6, 9676 }, + { 0x000ea7, 9694 }, + { 0x000ea8, 9708 }, + { 0x000ea9, 9727 }, + { 0x000eaa, 9740 }, + { 0x000eab, 9759 }, + { 0x000eac, 9777 }, + { 0x000ead, 9795 }, + { 0x000eae, 9812 }, + { 0x000eaf, 9830 }, + { 0x000eb0, 9849 }, + { 0x000eb1, 9867 }, + { 0x000eb2, 9880 }, + { 0x000eb3, 9893 }, + { 0x000eb4, 9911 }, + { 0x000eb5, 9928 }, + { 0x000eb6, 9940 }, + { 0x000eb7, 9957 }, + { 0x000eb8, 9970 }, + { 0x000eb9, 9983 }, + { 0x000eba, 10001 }, + { 0x000ebb, 10014 }, + { 0x000ebc, 10028 }, + { 0x000ebd, 10041 }, + { 0x000ebe, 10055 }, + { 0x000ebf, 10068 }, + { 0x000ec0, 10077 }, + { 0x000ec1, 10087 }, + { 0x000ec2, 10097 }, + { 0x000ec3, 10108 }, + { 0x000ec4, 10118 }, + { 0x000ec5, 10127 }, + { 0x000ec6, 10138 }, + { 0x000ec7, 10148 }, + { 0x000ec8, 10157 }, + { 0x000ec9, 10167 }, + { 0x000eca, 10178 }, + { 0x000ecb, 10188 }, + { 0x000ecc, 10198 }, + { 0x000ecd, 10207 }, + { 0x000ece, 10218 }, + { 0x000ecf, 10228 }, + { 0x000ed0, 10238 }, + { 0x000ed1, 10248 }, + { 0x000ed2, 10258 }, + { 0x000ed3, 10268 }, + { 0x000ed4, 10277 }, + { 0x000ed5, 10293 }, + { 0x000ed6, 10314 }, + { 0x000ed7, 10334 }, + { 0x000ed8, 10349 }, + { 0x000ed9, 10369 }, + { 0x000eda, 10389 }, + { 0x000edb, 10405 }, + { 0x000edc, 10420 }, + { 0x000edd, 10441 }, + { 0x000ede, 10461 }, + { 0x000edf, 10481 }, + { 0x000ee0, 10500 }, + { 0x000ee1, 10520 }, + { 0x000ee2, 10541 }, + { 0x000ee3, 10561 }, + { 0x000ee4, 10576 }, + { 0x000ee5, 10591 }, + { 0x000ee6, 10610 }, + { 0x000ee7, 10624 }, + { 0x000ee8, 10643 }, + { 0x000ee9, 10658 }, + { 0x000eea, 10673 }, + { 0x000eeb, 10688 }, + { 0x000eec, 10704 }, + { 0x000eed, 10719 }, + { 0x000eee, 10735 }, + { 0x000eef, 10750 }, + { 0x000ef0, 10774 }, + { 0x000ef1, 10799 }, + { 0x000ef2, 10824 }, + { 0x000ef3, 10839 }, + { 0x000ef4, 10864 }, + { 0x000ef5, 10890 }, + { 0x000ef6, 10909 }, + { 0x000ef7, 10922 }, + { 0x000ef8, 10936 }, + { 0x000ef9, 10953 }, + { 0x000efa, 10980 }, + { 0x000eff, 11001 }, + { 0x0013bc, 11012 }, + { 0x0013bd, 11015 }, + { 0x0013be, 11018 }, + { 0x0020a0, 11029 }, + { 0x0020a1, 11037 }, + { 0x0020a2, 11047 }, + { 0x0020a3, 11060 }, + { 0x0020a4, 11071 }, + { 0x0020a5, 11080 }, + { 0x0020a6, 11089 }, + { 0x0020a7, 11099 }, + { 0x0020a8, 11110 }, + { 0x0020a9, 11120 }, + { 0x0020aa, 11128 }, + { 0x0020ab, 11142 }, + { 0x0020ac, 11151 }, + { 0x00fd01, 11160 }, + { 0x00fd02, 11175 }, + { 0x00fd03, 11190 }, + { 0x00fd04, 11202 }, + { 0x00fd05, 11213 }, + { 0x00fd06, 11226 }, + { 0x00fd07, 11240 }, + { 0x00fd08, 11256 }, + { 0x00fd09, 11267 }, + { 0x00fd0a, 11277 }, + { 0x00fd0b, 11286 }, + { 0x00fd0c, 11295 }, + { 0x00fd0d, 11304 }, + { 0x00fd0e, 11314 }, + { 0x00fd0f, 11324 }, + { 0x00fd10, 11341 }, + { 0x00fd11, 11356 }, + { 0x00fd12, 11370 }, + { 0x00fd13, 11380 }, + { 0x00fd14, 11391 }, + { 0x00fd15, 11401 }, + { 0x00fd16, 11411 }, + { 0x00fd17, 11421 }, + { 0x00fd18, 11432 }, + { 0x00fd19, 11444 }, + { 0x00fd1a, 11462 }, + { 0x00fd1b, 11478 }, + { 0x00fd1c, 11492 }, + { 0x00fd1d, 11510 }, + { 0x00fd1e, 11527 }, + { 0x00fe01, 11538 }, + { 0x00fe02, 11547 }, + { 0x00fe03, 11564 }, + { 0x00fe04, 11581 }, + { 0x00fe05, 11598 }, + { 0x00fe06, 11614 }, + { 0x00fe07, 11630 }, + { 0x00fe08, 11645 }, + { 0x00fe09, 11660 }, + { 0x00fe0a, 11680 }, + { 0x00fe0b, 11695 }, + { 0x00fe0c, 11715 }, + { 0x00fe0d, 11731 }, + { 0x00fe0e, 11752 }, + { 0x00fe0f, 11767 }, + { 0x00fe20, 11787 }, + { 0x00fe21, 11800 }, + { 0x00fe22, 11817 }, + { 0x00fe23, 11836 }, + { 0x00fe24, 11856 }, + { 0x00fe25, 11878 }, + { 0x00fe26, 11901 }, + { 0x00fe27, 11925 }, + { 0x00fe28, 11945 }, + { 0x00fe29, 11966 }, + { 0x00fe2a, 11990 }, + { 0x00fe2b, 12015 }, + { 0x00fe2c, 12040 }, + { 0x00fe2d, 12061 }, + { 0x00fe2e, 12083 }, + { 0x00fe2f, 12102 }, + { 0x00fe30, 12123 }, + { 0x00fe31, 12148 }, + { 0x00fe32, 12176 }, + { 0x00fe33, 12190 }, + { 0x00fe34, 12208 }, + { 0x00fe50, 12218 }, + { 0x00fe51, 12229 }, + { 0x00fe52, 12240 }, + { 0x00fe53, 12256 }, + { 0x00fe54, 12267 }, + { 0x00fe55, 12279 }, + { 0x00fe56, 12290 }, + { 0x00fe57, 12304 }, + { 0x00fe58, 12319 }, + { 0x00fe59, 12334 }, + { 0x00fe5a, 12351 }, + { 0x00fe5b, 12362 }, + { 0x00fe5c, 12375 }, + { 0x00fe5d, 12387 }, + { 0x00fe5e, 12397 }, + { 0x00fe5f, 12415 }, + { 0x00fe60, 12437 }, + { 0x00fe61, 12451 }, + { 0x00fe62, 12461 }, + { 0x00fe70, 12471 }, + { 0x00fe71, 12486 }, + { 0x00fe72, 12510 }, + { 0x00fe73, 12528 }, + { 0x00fe74, 12544 }, + { 0x00fe75, 12562 }, + { 0x00fe76, 12580 }, + { 0x00fe77, 12597 }, + { 0x00fe78, 12620 }, + { 0x00fe79, 12636 }, + { 0x00fe7a, 12652 }, + { 0x00fed0, 12671 }, + { 0x00fed1, 12692 }, + { 0x00fed2, 12712 }, + { 0x00fed4, 12732 }, + { 0x00fed5, 12752 }, + { 0x00fee0, 12769 }, + { 0x00fee1, 12782 }, + { 0x00fee2, 12796 }, + { 0x00fee3, 12807 }, + { 0x00fee4, 12820 }, + { 0x00fee5, 12835 }, + { 0x00fee6, 12851 }, + { 0x00fee7, 12868 }, + { 0x00fee8, 12886 }, + { 0x00fee9, 12906 }, + { 0x00feea, 12922 }, + { 0x00feeb, 12938 }, + { 0x00feec, 12954 }, + { 0x00feed, 12970 }, + { 0x00feee, 12986 }, + { 0x00feef, 13008 }, + { 0x00fef0, 13026 }, + { 0x00fef1, 13044 }, + { 0x00fef2, 13062 }, + { 0x00fef3, 13080 }, + { 0x00fef4, 13098 }, + { 0x00fef5, 13116 }, + { 0x00fef6, 13130 }, + { 0x00fef7, 13144 }, + { 0x00fef8, 13158 }, + { 0x00fef9, 13172 }, + { 0x00fefa, 13191 }, + { 0x00fefb, 13210 }, + { 0x00fefc, 13230 }, + { 0x00fefd, 13250 }, + { 0x00ff08, 13264 }, + { 0x00ff09, 13274 }, + { 0x00ff0a, 13278 }, + { 0x00ff0b, 13287 }, + { 0x00ff0d, 13293 }, + { 0x00ff13, 13300 }, + { 0x00ff14, 13306 }, + { 0x00ff15, 13318 }, + { 0x00ff1b, 13326 }, + { 0x00ff20, 13333 }, + { 0x00ff21, 13343 }, + { 0x00ff22, 13349 }, + { 0x00ff23, 13358 }, + { 0x00ff23, 13365 }, + { 0x00ff24, 13377 }, + { 0x00ff25, 13384 }, + { 0x00ff26, 13393 }, + { 0x00ff27, 13402 }, + { 0x00ff28, 13420 }, + { 0x00ff29, 13428 }, + { 0x00ff2a, 13436 }, + { 0x00ff2b, 13452 }, + { 0x00ff2c, 13460 }, + { 0x00ff2d, 13467 }, + { 0x00ff2e, 13477 }, + { 0x00ff2f, 13488 }, + { 0x00ff30, 13499 }, + { 0x00ff31, 13511 }, + { 0x00ff32, 13518 }, + { 0x00ff33, 13531 }, + { 0x00ff34, 13542 }, + { 0x00ff35, 13555 }, + { 0x00ff36, 13567 }, + { 0x00ff37, 13581 }, + { 0x00ff38, 13591 }, + { 0x00ff39, 13605 }, + { 0x00ff3a, 13618 }, + { 0x00ff3b, 13634 }, + { 0x00ff3c, 13651 }, + { 0x00ff3d, 13667 }, + { 0x00ff3e, 13685 }, + { 0x00ff3f, 13703 }, + { 0x00ff50, 13718 }, + { 0x00ff51, 13723 }, + { 0x00ff52, 13728 }, + { 0x00ff53, 13731 }, + { 0x00ff54, 13737 }, + { 0x00ff55, 13742 }, + { 0x00ff55, 13750 }, + { 0x00ff56, 13756 }, + { 0x00ff56, 13766 }, + { 0x00ff57, 13771 }, + { 0x00ff58, 13775 }, + { 0x00ff60, 13781 }, + { 0x00ff61, 13788 }, + { 0x00ff62, 13794 }, + { 0x00ff63, 13802 }, + { 0x00ff65, 13809 }, + { 0x00ff66, 13814 }, + { 0x00ff67, 13819 }, + { 0x00ff68, 13824 }, + { 0x00ff69, 13829 }, + { 0x00ff6a, 13836 }, + { 0x00ff6b, 13841 }, + { 0x00ff7e, 13847 }, + { 0x00ff7e, 13861 }, + { 0x00ff7e, 13874 }, + { 0x00ff7e, 13888 }, + { 0x00ff7e, 13902 }, + { 0x00ff7e, 13918 }, + { 0x00ff7e, 13930 }, + { 0x00ff7e, 13942 }, + { 0x00ff7f, 13956 }, + { 0x00ff80, 13965 }, + { 0x00ff89, 13974 }, + { 0x00ff8d, 13981 }, + { 0x00ff91, 13990 }, + { 0x00ff92, 13996 }, + { 0x00ff93, 14002 }, + { 0x00ff94, 14008 }, + { 0x00ff95, 14014 }, + { 0x00ff96, 14022 }, + { 0x00ff97, 14030 }, + { 0x00ff98, 14036 }, + { 0x00ff99, 14045 }, + { 0x00ff9a, 14053 }, + { 0x00ff9a, 14064 }, + { 0x00ff9b, 14073 }, + { 0x00ff9b, 14086 }, + { 0x00ff9c, 14094 }, + { 0x00ff9d, 14101 }, + { 0x00ff9e, 14110 }, + { 0x00ff9f, 14120 }, + { 0x00ffaa, 14130 }, + { 0x00ffab, 14142 }, + { 0x00ffac, 14149 }, + { 0x00ffad, 14162 }, + { 0x00ffae, 14174 }, + { 0x00ffaf, 14185 }, + { 0x00ffb0, 14195 }, + { 0x00ffb1, 14200 }, + { 0x00ffb2, 14205 }, + { 0x00ffb3, 14210 }, + { 0x00ffb4, 14215 }, + { 0x00ffb5, 14220 }, + { 0x00ffb6, 14225 }, + { 0x00ffb7, 14230 }, + { 0x00ffb8, 14235 }, + { 0x00ffb9, 14240 }, + { 0x00ffbd, 14245 }, + { 0x00ffbe, 14254 }, + { 0x00ffbf, 14257 }, + { 0x00ffc0, 14260 }, + { 0x00ffc1, 14263 }, + { 0x00ffc2, 14266 }, + { 0x00ffc3, 14269 }, + { 0x00ffc4, 14272 }, + { 0x00ffc5, 14275 }, + { 0x00ffc6, 14278 }, + { 0x00ffc7, 14281 }, + { 0x00ffc8, 14285 }, + { 0x00ffc9, 14289 }, + { 0x00ffca, 14293 }, + { 0x00ffcb, 14297 }, + { 0x00ffcc, 14301 }, + { 0x00ffcd, 14305 }, + { 0x00ffce, 14309 }, + { 0x00ffcf, 14313 }, + { 0x00ffd0, 14317 }, + { 0x00ffd1, 14321 }, + { 0x00ffd2, 14325 }, + { 0x00ffd3, 14329 }, + { 0x00ffd4, 14333 }, + { 0x00ffd5, 14337 }, + { 0x00ffd6, 14341 }, + { 0x00ffd7, 14345 }, + { 0x00ffd8, 14349 }, + { 0x00ffd9, 14353 }, + { 0x00ffda, 14357 }, + { 0x00ffdb, 14361 }, + { 0x00ffdc, 14365 }, + { 0x00ffdd, 14369 }, + { 0x00ffde, 14373 }, + { 0x00ffdf, 14377 }, + { 0x00ffe0, 14381 }, + { 0x00ffe1, 14385 }, + { 0x00ffe2, 14393 }, + { 0x00ffe3, 14401 }, + { 0x00ffe4, 14411 }, + { 0x00ffe5, 14421 }, + { 0x00ffe6, 14431 }, + { 0x00ffe7, 14442 }, + { 0x00ffe8, 14449 }, + { 0x00ffe9, 14456 }, + { 0x00ffea, 14462 }, + { 0x00ffeb, 14468 }, + { 0x00ffec, 14476 }, + { 0x00ffed, 14484 }, + { 0x00ffee, 14492 }, + { 0x00ffff, 14500 }, + { 0xffffff, 14507 } +}; + +static const gdk_key gdk_keys_by_name[] = { + { 0x000030, 140 }, + { 0x000031, 142 }, + { 0x000032, 144 }, + { 0x000033, 146 }, + { 0x00fd10, 11341 }, + { 0x00fd0e, 11314 }, + { 0x00fd05, 11213 }, + { 0x00fd19, 11444 }, + { 0x00fd15, 11401 }, + { 0x00fd0f, 11324 }, + { 0x00fd1c, 11492 }, + { 0x00fd1a, 11462 }, + { 0x00fd01, 11160 }, + { 0x00fd1e, 11527 }, + { 0x00fd06, 11226 }, + { 0x00fd07, 11240 }, + { 0x00fd1b, 11478 }, + { 0x00fd02, 11175 }, + { 0x00fd13, 11380 }, + { 0x00fd12, 11370 }, + { 0x00fd11, 11356 }, + { 0x00fd04, 11202 }, + { 0x00fd0a, 11277 }, + { 0x00fd0b, 11286 }, + { 0x00fd0c, 11295 }, + { 0x00fd16, 11411 }, + { 0x00fd1d, 11510 }, + { 0x00fd09, 11267 }, + { 0x00fd18, 11432 }, + { 0x00fd08, 11256 }, + { 0x00fd03, 11190 }, + { 0x00fd14, 11391 }, + { 0x00fd17, 11421 }, + { 0x00fd0d, 11304 }, + { 0x000034, 148 }, + { 0x000035, 150 }, + { 0x000036, 152 }, + { 0x000037, 154 }, + { 0x000038, 156 }, + { 0x000039, 158 }, + { 0x000041, 207 }, + { 0x0000c6, 787 }, + { 0x0000c1, 744 }, + { 0x0001c3, 1473 }, + { 0x00fe70, 12471 }, + { 0x00fe71, 12486 }, + { 0x0000c2, 751 }, + { 0x0000c4, 770 }, + { 0x0000c0, 737 }, + { 0x00ffe9, 14456 }, + { 0x00ffea, 14462 }, + { 0x0003c0, 2068 }, + { 0x0001a1, 1281 }, + { 0x0005d9, 3221 }, + { 0x0005c7, 3008 }, + { 0x0005e9, 3360 }, + { 0x0005c8, 3020 }, + { 0x0005ac, 2848 }, + { 0x0005d6, 3188 }, + { 0x0005cf, 3107 }, + { 0x0005ef, 3451 }, + { 0x0005ec, 3406 }, + { 0x0005ee, 3438 }, + { 0x0005eb, 3390 }, + { 0x0005e1, 3260 }, + { 0x0005da, 3232 }, + { 0x0005e7, 3328 }, + { 0x0005cd, 3084 }, + { 0x0005c1, 2899 }, + { 0x0005c3, 2931 }, + { 0x0005c4, 2950 }, + { 0x0005c6, 2990 }, + { 0x0005c5, 2968 }, + { 0x0005e7, 3338 }, + { 0x0005cc, 3072 }, + { 0x0005e3, 3282 }, + { 0x0005f0, 3464 }, + { 0x0005ed, 3422 }, + { 0x0005ce, 3095 }, + { 0x0005e4, 3293 }, + { 0x0005c2, 2912 }, + { 0x0005e5, 3304 }, + { 0x0005e6, 3316 }, + { 0x0005e2, 3271 }, + { 0x0005bf, 2878 }, + { 0x0005d1, 3130 }, + { 0x0005d5, 3177 }, + { 0x0005d3, 3152 }, + { 0x0005bb, 2861 }, + { 0x0005f1, 3477 }, + { 0x0005d4, 3164 }, + { 0x0005f2, 3491 }, + { 0x00ff7e, 13847 }, + { 0x0005d7, 3199 }, + { 0x0005e0, 3245 }, + { 0x0005ca, 3049 }, + { 0x0005c9, 3031 }, + { 0x0005d0, 3118 }, + { 0x0005cb, 3060 }, + { 0x0005e8, 3349 }, + { 0x0005ea, 3379 }, + { 0x0005d8, 3210 }, + { 0x0005d2, 3140 }, + { 0x0000c5, 781 }, + { 0x0000c3, 763 }, + { 0x00fe7a, 12652 }, + { 0x000042, 209 }, + { 0x00ff08, 13264 }, + { 0x00ff58, 13775 }, + { 0x00fe74, 12544 }, + { 0x00ff6b, 13841 }, + { 0x0006be, 4011 }, + { 0x0006ae, 3729 }, + { 0x000043, 211 }, + { 0x0002c5, 1826 }, + { 0x0001c6, 1487 }, + { 0x00ff69, 13829 }, + { 0x00ffe5, 14421 }, + { 0x0001c8, 1494 }, + { 0x0000c7, 790 }, + { 0x0002c6, 1836 }, + { 0x00ff0b, 13287 }, + { 0x00ff37, 13581 }, + { 0x0020a1, 11037 }, + { 0x00ffe3, 14401 }, + { 0x00ffe4, 14411 }, + { 0x0020a2, 11047 }, + { 0x0006e1, 4474 }, + { 0x0006e2, 4485 }, + { 0x0006fe, 4836 }, + { 0x0006e4, 4510 }, + { 0x0006bf, 4031 }, + { 0x0006fc, 4810 }, + { 0x0006e6, 4534 }, + { 0x0006ec, 4610 }, + { 0x0006ed, 4622 }, + { 0x0006ee, 4634 }, + { 0x0006f2, 4681 }, + { 0x0006f3, 4693 }, + { 0x0006e7, 4546 }, + { 0x0006e8, 4559 }, + { 0x0006ff, 4849 }, + { 0x0006e9, 4571 }, + { 0x0006e5, 4522 }, + { 0x0006b3, 3812 }, + { 0x0006b8, 3911 }, + { 0x0006eb, 4598 }, + { 0x0006b9, 3934 }, + { 0x0006ba, 3959 }, + { 0x0006ef, 4646 }, + { 0x0006f0, 4657 }, + { 0x0006fb, 4797 }, + { 0x0006fd, 4821 }, + { 0x0006ea, 4582 }, + { 0x0006f8, 4753 }, + { 0x0006f4, 4705 }, + { 0x0006e3, 4497 }, + { 0x0006f5, 4717 }, + { 0x0006f7, 4741 }, + { 0x0006f1, 4669 }, + { 0x0006f9, 4771 }, + { 0x0006e0, 4462 }, + { 0x0006fa, 4785 }, + { 0x0006f6, 4728 }, + { 0x0006c1, 4069 }, + { 0x0006c2, 4080 }, + { 0x0006de, 4431 }, + { 0x0006c4, 4105 }, + { 0x0006af, 3749 }, + { 0x0006dc, 4405 }, + { 0x0006c6, 4129 }, + { 0x0006cc, 4205 }, + { 0x0006cd, 4217 }, + { 0x0006ce, 4229 }, + { 0x0006d2, 4276 }, + { 0x0006d3, 4288 }, + { 0x0006c7, 4141 }, + { 0x0006c8, 4154 }, + { 0x0006df, 4444 }, + { 0x0006c9, 4166 }, + { 0x0006c5, 4117 }, + { 0x0006a3, 3530 }, + { 0x0006a8, 3629 }, + { 0x0006cb, 4193 }, + { 0x0006a9, 3652 }, + { 0x0006aa, 3677 }, + { 0x0006cf, 4241 }, + { 0x0006d0, 4252 }, + { 0x0006db, 4392 }, + { 0x0006dd, 4416 }, + { 0x0006ca, 4177 }, + { 0x0006d8, 4348 }, + { 0x0006d4, 4300 }, + { 0x0006c3, 4092 }, + { 0x0006d5, 4312 }, + { 0x0006d7, 4336 }, + { 0x0006d1, 4264 }, + { 0x0006d9, 4366 }, + { 0x0006c0, 4057 }, + { 0x0006da, 4380 }, + { 0x0006d6, 4323 }, + { 0x000044, 213 }, + { 0x0001cf, 1516 }, + { 0x00ffff, 14500 }, + { 0x0020ab, 11142 }, + { 0x00ff54, 13737 }, + { 0x0001d0, 1523 }, + { 0x000045, 215 }, + { 0x0003bd, 2060 }, + { 0x0000d0, 873 }, + { 0x0003cc, 2084 }, + { 0x0000c9, 806 }, + { 0x0001cc, 1509 }, + { 0x0000ca, 813 }, + { 0x0020a0, 11029 }, + { 0x0000cb, 825 }, + { 0x0000c8, 799 }, + { 0x00ff2f, 13488 }, + { 0x00ff30, 13499 }, + { 0x0003aa, 1987 }, + { 0x00ff57, 13771 }, + { 0x0001ca, 1501 }, + { 0x00ff1b, 13326 }, + { 0x0000d0, 877 }, + { 0x0020ac, 11151 }, + { 0x00ff62, 13794 }, + { 0x000046, 217 }, + { 0x00ffbe, 14254 }, + { 0x00ffc7, 14281 }, + { 0x00ffc8, 14285 }, + { 0x00ffc9, 14289 }, + { 0x00ffca, 14293 }, + { 0x00ffcb, 14297 }, + { 0x00ffcc, 14301 }, + { 0x00ffcd, 14305 }, + { 0x00ffce, 14309 }, + { 0x00ffcf, 14313 }, + { 0x00ffd0, 14317 }, + { 0x00ffbf, 14257 }, + { 0x00ffd1, 14321 }, + { 0x00ffd2, 14325 }, + { 0x00ffd3, 14329 }, + { 0x00ffd4, 14333 }, + { 0x00ffd5, 14337 }, + { 0x00ffd6, 14341 }, + { 0x00ffd7, 14345 }, + { 0x00ffd8, 14349 }, + { 0x00ffd9, 14353 }, + { 0x00ffda, 14357 }, + { 0x00ffc0, 14260 }, + { 0x00ffdb, 14361 }, + { 0x00ffdc, 14365 }, + { 0x00ffdd, 14369 }, + { 0x00ffde, 14373 }, + { 0x00ffdf, 14377 }, + { 0x00ffe0, 14381 }, + { 0x00ffc1, 14263 }, + { 0x00ffc2, 14266 }, + { 0x00ffc3, 14269 }, + { 0x00ffc4, 14272 }, + { 0x00ffc5, 14275 }, + { 0x00ffc6, 14278 }, + { 0x0020a3, 11060 }, + { 0x00ff68, 13824 }, + { 0x00fed0, 12671 }, + { 0x000047, 219 }, + { 0x0002d5, 1848 }, + { 0x0002ab, 1759 }, + { 0x0003ab, 1995 }, + { 0x0002d8, 1858 }, + { 0x0007c1, 5316 }, + { 0x0007a1, 4867 }, + { 0x0007c2, 5328 }, + { 0x0007d7, 5564 }, + { 0x0007c4, 5351 }, + { 0x0007c5, 5363 }, + { 0x0007a2, 4885 }, + { 0x0007c7, 5388 }, + { 0x0007a3, 4905 }, + { 0x0007c3, 5339 }, + { 0x0007c9, 5410 }, + { 0x0007a4, 4921 }, + { 0x0007a5, 4957 }, + { 0x0007a5, 4938 }, + { 0x0007ca, 5421 }, + { 0x0007cb, 5433 }, + { 0x0007cb, 5446 }, + { 0x0007cc, 5458 }, + { 0x0007cd, 5467 }, + { 0x0007d9, 5584 }, + { 0x0007ab, 5039 }, + { 0x0007cf, 5485 }, + { 0x0007a7, 4977 }, + { 0x0007d6, 5554 }, + { 0x0007d0, 5499 }, + { 0x0007d8, 5574 }, + { 0x0007d1, 5508 }, + { 0x0007d2, 5518 }, + { 0x0007d4, 5530 }, + { 0x0007c8, 5398 }, + { 0x0007d5, 5540 }, + { 0x0007a8, 4997 }, + { 0x0007a9, 5017 }, + { 0x0007ce, 5476 }, + { 0x0007c6, 5377 }, + { 0x0007ae, 5057 }, + { 0x0007e1, 5596 }, + { 0x0007b1, 5093 }, + { 0x0007e2, 5608 }, + { 0x0007f7, 5866 }, + { 0x0007e4, 5631 }, + { 0x0007e5, 5643 }, + { 0x0007b2, 5111 }, + { 0x0007e7, 5668 }, + { 0x0007b3, 5131 }, + { 0x0007f3, 5810 }, + { 0x0007e3, 5619 }, + { 0x0007af, 5078 }, + { 0x0007e9, 5690 }, + { 0x0007b4, 5147 }, + { 0x0007b6, 5183 }, + { 0x0007b5, 5164 }, + { 0x0007ea, 5701 }, + { 0x0007eb, 5713 }, + { 0x0007eb, 5726 }, + { 0x0007ec, 5738 }, + { 0x0007ed, 5747 }, + { 0x0007f9, 5886 }, + { 0x0007bb, 5298 }, + { 0x0007ef, 5765 }, + { 0x0007b7, 5208 }, + { 0x0007f6, 5856 }, + { 0x0007f0, 5779 }, + { 0x0007f8, 5876 }, + { 0x0007f1, 5788 }, + { 0x0007f2, 5798 }, + { 0x00ff7e, 13861 }, + { 0x0007f4, 5832 }, + { 0x0007e8, 5678 }, + { 0x0007f5, 5842 }, + { 0x0007b8, 5228 }, + { 0x0007ba, 5270 }, + { 0x0007b9, 5248 }, + { 0x0007ee, 5756 }, + { 0x0007e6, 5657 }, + { 0x000048, 221 }, + { 0x00ff31, 13511 }, + { 0x000ebf, 10068 }, + { 0x000ec0, 10077 }, + { 0x000ef6, 10909 }, + { 0x000ef7, 10922 }, + { 0x00ff39, 13605 }, + { 0x000eba, 10001 }, + { 0x000ea7, 9694 }, + { 0x000ec4, 10118 }, + { 0x000ec3, 10108 }, + { 0x000ed1, 10248 }, + { 0x00ff33, 13531 }, + { 0x00ff34, 13542 }, + { 0x000ebe, 10055 }, + { 0x000ed3, 10268 }, + { 0x000eb7, 9957 }, + { 0x000eea, 10673 }, + { 0x000eda, 10389 }, + { 0x000eee, 10735 }, + { 0x000ee8, 10643 }, + { 0x000ee9, 10658 }, + { 0x000eeb, 10688 }, + { 0x000ed4, 10277 }, + { 0x000ed6, 10314 }, + { 0x000ef9, 10953 }, + { 0x000ee3, 10561 }, + { 0x000ed7, 10334 }, + { 0x000ed9, 10369 }, + { 0x000ed8, 10349 }, + { 0x000ef8, 10936 }, + { 0x000eed, 10719 }, + { 0x000ee4, 10576 }, + { 0x000ee5, 10591 }, + { 0x000edb, 10405 }, + { 0x000ee2, 10541 }, + { 0x000edc, 10420 }, + { 0x000edd, 10441 }, + { 0x000ee1, 10520 }, + { 0x000ede, 10461 }, + { 0x000edf, 10481 }, + { 0x000ee0, 10500 }, + { 0x000ee6, 10610 }, + { 0x000ed5, 10293 }, + { 0x000ee7, 10624 }, + { 0x000eec, 10704 }, + { 0x000efa, 10980 }, + { 0x00ff35, 13555 }, + { 0x00ff38, 13591 }, + { 0x000eb8, 9970 }, + { 0x000ebb, 10014 }, + { 0x000ea1, 9594 }, + { 0x000ea3, 9627 }, + { 0x000ef3, 10839 }, + { 0x000eb1, 9867 }, + { 0x000ea4, 9645 }, + { 0x000ea6, 9676 }, + { 0x000ea5, 9658 }, + { 0x000ec7, 10148 }, + { 0x000eca, 10178 }, + { 0x000ef2, 10824 }, + { 0x000ebd, 10041 }, + { 0x000eb2, 9880 }, + { 0x000eb4, 9911 }, + { 0x00ff3b, 13634 }, + { 0x00ff3a, 13618 }, + { 0x000ea9, 9727 }, + { 0x000eb0, 9849 }, + { 0x000eaa, 9740 }, + { 0x000eab, 9759 }, + { 0x000eaf, 9830 }, + { 0x000eac, 9777 }, + { 0x000ead, 9795 }, + { 0x000eae, 9812 }, + { 0x000eef, 10750 }, + { 0x00ff36, 13567 }, + { 0x000eb5, 9928 }, + { 0x00ff3f, 13703 }, + { 0x000ea8, 9708 }, + { 0x000eb9, 9983 }, + { 0x000ea2, 9608 }, + { 0x000eb3, 9893 }, + { 0x000eb6, 9940 }, + { 0x00ff32, 13518 }, + { 0x000ef0, 10774 }, + { 0x000ef4, 10864 }, + { 0x000ef1, 10799 }, + { 0x000ebc, 10028 }, + { 0x000ecc, 10198 }, + { 0x000ec8, 10157 }, + { 0x000ec9, 10167 }, + { 0x000ece, 10218 }, + { 0x000ecd, 10207 }, + { 0x000ecf, 10228 }, + { 0x000ec1, 10087 }, + { 0x000ec2, 10097 }, + { 0x000ec6, 10138 }, + { 0x000ec5, 10127 }, + { 0x000ed2, 10258 }, + { 0x000ecb, 10188 }, + { 0x000ed0, 10238 }, + { 0x000ef5, 10890 }, + { 0x00ff7e, 13874 }, + { 0x00ff29, 13428 }, + { 0x0002a6, 1737 }, + { 0x00ff7e, 13888 }, + { 0x00ff6a, 13836 }, + { 0x00ff23, 13358 }, + { 0x00ff23, 13365 }, + { 0x00ff25, 13384 }, + { 0x00ff27, 13402 }, + { 0x00ff50, 13718 }, + { 0x0002a1, 1729 }, + { 0x00ffed, 14484 }, + { 0x00ffee, 14492 }, + { 0x000049, 223 }, + { 0x00fe33, 12190 }, + { 0x00fe30, 12123 }, + { 0x00fe31, 12148 }, + { 0x00fe32, 12176 }, + { 0x00fe34, 12208 }, + { 0x00fe2f, 12102 }, + { 0x00fe2c, 12040 }, + { 0x00fe2d, 12061 }, + { 0x00fe2e, 12083 }, + { 0x00fe0c, 11715 }, + { 0x00fe0d, 11731 }, + { 0x00fe06, 11614 }, + { 0x00fe07, 11630 }, + { 0x00ff7e, 13902 }, + { 0x00fe0e, 11752 }, + { 0x00fe0f, 11767 }, + { 0x00fe20, 11787 }, + { 0x00fe02, 11547 }, + { 0x00fe04, 11581 }, + { 0x00fe05, 11598 }, + { 0x00fe03, 11564 }, + { 0x00fe01, 11538 }, + { 0x00fe22, 11817 }, + { 0x00fe21, 11800 }, + { 0x00fe08, 11645 }, + { 0x00fe09, 11660 }, + { 0x00fe24, 11856 }, + { 0x00fe23, 11836 }, + { 0x00fe25, 11878 }, + { 0x00fe26, 11901 }, + { 0x00fe0a, 11680 }, + { 0x00fe0b, 11695 }, + { 0x00fe2b, 12015 }, + { 0x00fe29, 11966 }, + { 0x00fe2a, 11990 }, + { 0x00fe27, 11925 }, + { 0x00fe28, 11945 }, + { 0x0002a9, 1749 }, + { 0x0000cd, 843 }, + { 0x0000ce, 850 }, + { 0x0000cf, 862 }, + { 0x0000cc, 836 }, + { 0x0003cf, 2094 }, + { 0x00ff63, 13802 }, + { 0x0003c7, 2076 }, + { 0x0003a5, 1971 }, + { 0x00004a, 225 }, + { 0x0002ac, 1766 }, + { 0x00004b, 227 }, + { 0x00ffb0, 14195 }, + { 0x00ffb1, 14200 }, + { 0x00ffb2, 14205 }, + { 0x00ffb3, 14210 }, + { 0x00ffb4, 14215 }, + { 0x00ffb5, 14220 }, + { 0x00ffb6, 14225 }, + { 0x00ffb7, 14230 }, + { 0x00ffb8, 14235 }, + { 0x00ffb9, 14240 }, + { 0x00ffab, 14142 }, + { 0x00ff9d, 14101 }, + { 0x00ffae, 14174 }, + { 0x00ff9f, 14120 }, + { 0x00ffaf, 14185 }, + { 0x00ff99, 14045 }, + { 0x00ff9c, 14094 }, + { 0x00ff8d, 13981 }, + { 0x00ffbd, 14245 }, + { 0x00ff91, 13990 }, + { 0x00ff92, 13996 }, + { 0x00ff93, 14002 }, + { 0x00ff94, 14008 }, + { 0x00ff95, 14014 }, + { 0x00ff9e, 14110 }, + { 0x00ff96, 14022 }, + { 0x00ffaa, 14130 }, + { 0x00ff9b, 14086 }, + { 0x00ff9b, 14073 }, + { 0x00ff9a, 14053 }, + { 0x00ff9a, 14064 }, + { 0x00ff98, 14036 }, + { 0x00ffac, 14149 }, + { 0x00ff80, 13965 }, + { 0x00ffad, 14162 }, + { 0x00ff89, 13974 }, + { 0x00ff97, 14030 }, + { 0x00ff2d, 13467 }, + { 0x00ff2e, 13477 }, + { 0x00ff21, 13343 }, + { 0x00ff26, 13393 }, + { 0x0003d3, 2119 }, + { 0x000eff, 11001 }, + { 0x00004c, 229 }, + { 0x0001c5, 1480 }, + { 0x00fed4, 12732 }, + { 0x0001a5, 1303 }, + { 0x0003a6, 1978 }, + { 0x00ff51, 13723 }, + { 0x00ff0a, 13278 }, + { 0x0020a4, 11071 }, + { 0x0001a3, 1295 }, + { 0x00004d, 231 }, + { 0x0006b5, 3849 }, + { 0x0006b2, 3798 }, + { 0x0006bc, 3997 }, + { 0x0006a5, 3567 }, + { 0x0006a2, 3516 }, + { 0x0006ac, 3715 }, + { 0x00ff2c, 13460 }, + { 0x00ff67, 13819 }, + { 0x00ffe7, 14442 }, + { 0x00ffe8, 14449 }, + { 0x0020a5, 11080 }, + { 0x00ff7e, 13918 }, + { 0x00fe77, 12597 }, + { 0x00fe76, 12580 }, + { 0x00ff22, 13349 }, + { 0x00ff20, 13333 }, + { 0x00ff3d, 13667 }, + { 0x00004e, 233 }, + { 0x0001d1, 1531 }, + { 0x0020a6, 11089 }, + { 0x0001d2, 1538 }, + { 0x0003d1, 2102 }, + { 0x0020aa, 11128 }, + { 0x00ff56, 13766 }, + { 0x00fed2, 12712 }, + { 0x0000d1, 881 }, + { 0x00ff7f, 13956 }, + { 0x00004f, 235 }, + { 0x0013bc, 11012 }, + { 0x0000d3, 895 }, + { 0x0000d4, 902 }, + { 0x0000d6, 921 }, + { 0x0001d5, 1545 }, + { 0x0000d2, 888 }, + { 0x0003d2, 2111 }, + { 0x0000d8, 941 }, + { 0x0000d5, 914 }, + { 0x00fe78, 12620 }, + { 0x00fe79, 12636 }, + { 0x000050, 237 }, + { 0x00ff56, 13756 }, + { 0x00ff55, 13742 }, + { 0x00ff13, 13300 }, + { 0x0020a7, 11099 }, + { 0x00fefa, 13191 }, + { 0x00fee9, 12906 }, + { 0x00feea, 12922 }, + { 0x00feeb, 12938 }, + { 0x00feec, 12954 }, + { 0x00feed, 12970 }, + { 0x00fee8, 12886 }, + { 0x00feef, 13008 }, + { 0x00fef0, 13026 }, + { 0x00fef1, 13044 }, + { 0x00fef2, 13062 }, + { 0x00fef3, 13080 }, + { 0x00feee, 12986 }, + { 0x00fefb, 13210 }, + { 0x00fefc, 13230 }, + { 0x00fee3, 12807 }, + { 0x00fee6, 12851 }, + { 0x00fee7, 12868 }, + { 0x00fef5, 13116 }, + { 0x00fef6, 13130 }, + { 0x00fef7, 13144 }, + { 0x00fef8, 13158 }, + { 0x00fefd, 13250 }, + { 0x00fef4, 13098 }, + { 0x00fef9, 13172 }, + { 0x00fee0, 12769 }, + { 0x00fee1, 12782 }, + { 0x00fee2, 12796 }, + { 0x00fee4, 12820 }, + { 0x00fee5, 12835 }, + { 0x00fed1, 12692 }, + { 0x00ff3e, 13685 }, + { 0x00ff61, 13788 }, + { 0x00ff55, 13750 }, + { 0x000051, 239 }, + { 0x000052, 241 }, + { 0x0001c0, 1466 }, + { 0x0001d8, 1558 }, + { 0x0003a3, 1962 }, + { 0x00ff66, 13814 }, + { 0x00fe72, 12510 }, + { 0x00ff0d, 13293 }, + { 0x00ff53, 13731 }, + { 0x00ff24, 13377 }, + { 0x0020a8, 11110 }, + { 0x000053, 243 }, + { 0x0001a6, 1310 }, + { 0x0001a9, 1317 }, + { 0x0001aa, 1324 }, + { 0x0002de, 1877 }, + { 0x00ff14, 13306 }, + { 0x00ff60, 13781 }, + { 0x0006b1, 3786 }, + { 0x0006bf, 4045 }, + { 0x0006b8, 3923 }, + { 0x0006b9, 3947 }, + { 0x0006ba, 3972 }, + { 0x0006bb, 3984 }, + { 0x0006a1, 3504 }, + { 0x0006af, 3763 }, + { 0x0006a8, 3641 }, + { 0x0006a9, 3665 }, + { 0x0006aa, 3690 }, + { 0x0006ab, 3702 }, + { 0x00ffe1, 14385 }, + { 0x00ffe6, 14431 }, + { 0x00ffe2, 14393 }, + { 0x00ff3c, 13651 }, + { 0x00fe73, 12528 }, + { 0x00fe75, 12562 }, + { 0x00ffeb, 14468 }, + { 0x00ffec, 14476 }, + { 0x00ff15, 13318 }, + { 0x000054, 245 }, + { 0x0000de, 994 }, + { 0x00ff09, 13274 }, + { 0x0001ab, 1333 }, + { 0x0001de, 1584 }, + { 0x00fed5, 12752 }, + { 0x000ddf, 9260 }, + { 0x000dba, 8843 }, + { 0x000da8, 8607 }, + { 0x000daa, 8634 }, + { 0x000da9, 8620 }, + { 0x000dac, 8658 }, + { 0x000dae, 8683 }, + { 0x000db4, 8768 }, + { 0x000dbd, 8882 }, + { 0x000dbf, 8905 }, + { 0x000dcb, 9039 }, + { 0x000dce, 9073 }, + { 0x000da2, 8525 }, + { 0x000da5, 8566 }, + { 0x000da3, 8538 }, + { 0x000da4, 8552 }, + { 0x000da6, 8579 }, + { 0x000da1, 8514 }, + { 0x000de5, 9343 }, + { 0x000df7, 9556 }, + { 0x000df5, 9533 }, + { 0x000df6, 9544 }, + { 0x000df9, 9582 }, + { 0x000df1, 9484 }, + { 0x000df8, 9569 }, + { 0x000df3, 9510 }, + { 0x000df4, 9522 }, + { 0x000df2, 9497 }, + { 0x000df0, 9472 }, + { 0x000dcc, 9050 }, + { 0x000dc5, 8972 }, + { 0x000dc6, 8984 }, + { 0x000deb, 9424 }, + { 0x000de8, 9389 }, + { 0x000dd1, 9113 }, + { 0x000dde, 9237 }, + { 0x000de7, 9374 }, + { 0x000de9, 9400 }, + { 0x000dea, 9412 }, + { 0x000de6, 9360 }, + { 0x000dc1, 8932 }, + { 0x000da7, 8595 }, + { 0x000ded, 9458 }, + { 0x000db3, 8757 }, + { 0x000db9, 8833 }, + { 0x000dcd, 9063 }, + { 0x000dcf, 9087 }, + { 0x000dda, 9224 }, + { 0x000dbe, 8892 }, + { 0x000dbc, 8868 }, + { 0x000dc0, 8916 }, + { 0x000dbb, 8857 }, + { 0x000dc3, 8953 }, + { 0x000dc4, 8964 }, + { 0x000dd0, 9102 }, + { 0x000dd2, 9129 }, + { 0x000de1, 9281 }, + { 0x000de4, 9323 }, + { 0x000de3, 9304 }, + { 0x000dd3, 9141 }, + { 0x000de0, 9270 }, + { 0x000dd4, 9153 }, + { 0x000dd5, 9164 }, + { 0x000de2, 9293 }, + { 0x000dd8, 9201 }, + { 0x000dd6, 9176 }, + { 0x000dd7, 9188 }, + { 0x000dd9, 9212 }, + { 0x000dc9, 9016 }, + { 0x000dc8, 9004 }, + { 0x000dab, 8648 }, + { 0x000dca, 9028 }, + { 0x000dec, 9441 }, + { 0x000db1, 8722 }, + { 0x000db2, 8741 }, + { 0x000db7, 8804 }, + { 0x000db0, 8709 }, + { 0x000db8, 8819 }, + { 0x000db6, 8790 }, + { 0x000daf, 8696 }, + { 0x000db5, 8779 }, + { 0x000dc7, 8992 }, + { 0x000dc2, 8942 }, + { 0x000dad, 8671 }, + { 0x0000de, 1000 }, + { 0x00ff2b, 13452 }, + { 0x0003ac, 2004 }, + { 0x000055, 247 }, + { 0x0000da, 957 }, + { 0x0002dd, 1870 }, + { 0x0000db, 964 }, + { 0x0000dc, 976 }, + { 0x0001db, 1571 }, + { 0x0000d9, 950 }, + { 0x0006b6, 3863 }, + { 0x0006b4, 3824 }, + { 0x0006b7, 3886 }, + { 0x0006a6, 3581 }, + { 0x0006a4, 3542 }, + { 0x0006a7, 3604 }, + { 0x0006b6, 3875 }, + { 0x0006b4, 3837 }, + { 0x0006b7, 3899 }, + { 0x0006a6, 3593 }, + { 0x0006a4, 3555 }, + { 0x0006a7, 3617 }, + { 0x0003de, 2143 }, + { 0x00ff65, 13809 }, + { 0x0003d9, 2128 }, + { 0x00ff52, 13728 }, + { 0x0001d9, 1565 }, + { 0x0003dd, 2136 }, + { 0x000056, 249 }, + { 0xffffff, 14507 }, + { 0x000057, 251 }, + { 0x0020a9, 11120 }, + { 0x000058, 253 }, + { 0x000059, 255 }, + { 0x0000dd, 987 }, + { 0x0013be, 11018 }, + { 0x00005a, 257 }, + { 0x0001af, 1354 }, + { 0x0001ac, 1340 }, + { 0x0001ae, 1347 }, + { 0x00ff28, 13420 }, + { 0x00ff2a, 13436 }, + { 0x000061, 333 }, + { 0x0000e1, 1020 }, + { 0x0001ff, 1720 }, + { 0x0001e3, 1600 }, + { 0x0000e2, 1027 }, + { 0x0000b4, 612 }, + { 0x0000e4, 1046 }, + { 0x0000e6, 1063 }, + { 0x0000e0, 1013 }, + { 0x0003e0, 2151 }, + { 0x000026, 48 }, + { 0x0001b1, 1364 }, + { 0x000027, 58 }, + { 0x0008c8, 6376 }, + { 0x0000e5, 1057 }, + { 0x00005e, 294 }, + { 0x00007e, 410 }, + { 0x00002a, 101 }, + { 0x000040, 204 }, + { 0x0000e3, 1039 }, + { 0x000062, 335 }, + { 0x00005c, 271 }, + { 0x000af4, 7692 }, + { 0x00007c, 395 }, + { 0x0009df, 6562 }, + { 0x0008a5, 5952 }, + { 0x0008ac, 6062 }, + { 0x0008a8, 5995 }, + { 0x0008b2, 6166 }, + { 0x0008ae, 6091 }, + { 0x0008aa, 6030 }, + { 0x0008b6, 6253 }, + { 0x0009f6, 6770 }, + { 0x0008b4, 6209 }, + { 0x00007b, 385 }, + { 0x00007d, 399 }, + { 0x00005b, 259 }, + { 0x00005d, 281 }, + { 0x0001a2, 1289 }, + { 0x0000a6, 472 }, + { 0x000063, 337 }, + { 0x0002e5, 1889 }, + { 0x0001e6, 1614 }, + { 0x000ab8, 6996 }, + { 0x000afc, 7801 }, + { 0x0001b7, 1401 }, + { 0x0001e8, 1621 }, + { 0x0000e7, 1066 }, + { 0x0002e6, 1899 }, + { 0x0000b8, 646 }, + { 0x0000a2, 445 }, + { 0x0009e1, 6581 }, + { 0x000af3, 7682 }, + { 0x000bcf, 7950 }, + { 0x000aec, 7630 }, + { 0x00003a, 160 }, + { 0x00002c, 115 }, + { 0x0000a9, 500 }, + { 0x0009e4, 6600 }, + { 0x0009ee, 6668 }, + { 0x0000a4, 459 }, + { 0x000aff, 7845 }, + { 0x000064, 339 }, + { 0x000af1, 7662 }, + { 0x0001ef, 1643 }, + { 0x00fe56, 12290 }, + { 0x00fe58, 12319 }, + { 0x00fe51, 12229 }, + { 0x00fe60, 12437 }, + { 0x00fe55, 12279 }, + { 0x00fe5a, 12351 }, + { 0x00fe5b, 12362 }, + { 0x00fe52, 12240 }, + { 0x00fe57, 12304 }, + { 0x00fe59, 12334 }, + { 0x00fe50, 12218 }, + { 0x00fe61, 12451 }, + { 0x00fe62, 12461 }, + { 0x00fe5d, 12387 }, + { 0x00fe54, 12267 }, + { 0x00fe5c, 12375 }, + { 0x00fe5f, 12415 }, + { 0x00fe53, 12256 }, + { 0x00fe5e, 12397 }, + { 0x000abd, 7028 }, + { 0x0000b0, 569 }, + { 0x0000a8, 490 }, + { 0x000aed, 7635 }, + { 0x000aa5, 6822 }, + { 0x0000f7, 1204 }, + { 0x000024, 33 }, + { 0x000aaf, 6899 }, + { 0x0001bd, 1437 }, + { 0x000af2, 7669 }, + { 0x000afe, 7826 }, + { 0x0008fe, 6552 }, + { 0x000ba8, 7873 }, + { 0x000bd6, 7965 }, + { 0x000bc4, 7915 }, + { 0x000bc2, 7899 }, + { 0x0001f0, 1650 }, + { 0x000065, 341 }, + { 0x0003ec, 2167 }, + { 0x0000e9, 1082 }, + { 0x0001ec, 1636 }, + { 0x0000ea, 1089 }, + { 0x0000eb, 1101 }, + { 0x0000e8, 1075 }, + { 0x000aae, 6890 }, + { 0x000aa3, 6804 }, + { 0x000aa4, 6813 }, + { 0x0003ba, 2036 }, + { 0x000aa9, 6864 }, + { 0x000ade, 7409 }, + { 0x000adf, 7424 }, + { 0x000ace, 7191 }, + { 0x000acf, 7204 }, + { 0x000aa1, 6788 }, + { 0x000aaa, 6871 }, + { 0x000ae6, 7531 }, + { 0x000ae7, 7550 }, + { 0x0003bf, 2064 }, + { 0x000ae0, 7437 }, + { 0x000ae1, 7454 }, + { 0x000aa2, 6796 }, + { 0x0001ea, 1628 }, + { 0x00003d, 181 }, + { 0x0000f0, 1149 }, + { 0x000021, 6 }, + { 0x0000a1, 434 }, + { 0x000066, 343 }, + { 0x000af8, 7740 }, + { 0x0009e3, 6597 }, + { 0x000abb, 7003 }, + { 0x000adc, 7368 }, + { 0x000adb, 7351 }, + { 0x000add, 7388 }, + { 0x000ae9, 7585 }, + { 0x000ae8, 7567 }, + { 0x000ac5, 7089 }, + { 0x000ab7, 6985 }, + { 0x000ab5, 6965 }, + { 0x0008f6, 6514 }, + { 0x000067, 345 }, + { 0x0002f5, 1911 }, + { 0x0002bb, 1807 }, + { 0x0003bb, 2044 }, + { 0x0002f8, 1921 }, + { 0x000060, 317 }, + { 0x00003e, 187 }, + { 0x0008be, 6315 }, + { 0x0000ab, 522 }, + { 0x0000bb, 676 }, + { 0x000068, 347 }, + { 0x000aa8, 6854 }, + { 0x0002b6, 1786 }, + { 0x000aee, 7643 }, + { 0x000ce0, 8033 }, + { 0x000cf2, 8350 }, + { 0x000ce1, 8046 }, + { 0x000ce1, 8057 }, + { 0x000ce7, 8169 }, + { 0x000ce3, 8096 }, + { 0x000ce3, 8109 }, + { 0x000cdf, 8012 }, + { 0x000cea, 8226 }, + { 0x000ced, 8268 }, + { 0x000cef, 8295 }, + { 0x000cf3, 8362 }, + { 0x000cf5, 8387 }, + { 0x000cf5, 8404 }, + { 0x000ce2, 8069 }, + { 0x000ce2, 8082 }, + { 0x000ce4, 8123 }, + { 0x000ce7, 8181 }, + { 0x000ceb, 8243 }, + { 0x000cf7, 8445 }, + { 0x000cec, 8255 }, + { 0x000cee, 8284 }, + { 0x000cf0, 8311 }, + { 0x000cf4, 8377 }, + { 0x000cf7, 8456 }, + { 0x000cf8, 8468 }, + { 0x000cf1, 8322 }, + { 0x000cf1, 8336 }, + { 0x000cf9, 8480 }, + { 0x000cfa, 8492 }, + { 0x000cfa, 8503 }, + { 0x000ce8, 8192 }, + { 0x000ce8, 8203 }, + { 0x000ce5, 8133 }, + { 0x000ce9, 8215 }, + { 0x000cf6, 8421 }, + { 0x000cf6, 8433 }, + { 0x000ce6, 8144 }, + { 0x000ce6, 8156 }, + { 0x000ada, 7342 }, + { 0x0008a3, 5925 }, + { 0x0009ef, 6682 }, + { 0x0009f0, 6697 }, + { 0x0009f1, 6712 }, + { 0x0009f2, 6727 }, + { 0x0009f3, 6742 }, + { 0x0002b1, 1778 }, + { 0x0009e2, 6594 }, + { 0x0000ad, 544 }, + { 0x000069, 349 }, + { 0x0000ed, 1119 }, + { 0x0000ee, 1126 }, + { 0x0008cf, 6418 }, + { 0x0000ef, 1138 }, + { 0x0002b9, 1798 }, + { 0x0008cd, 6401 }, + { 0x0000ec, 1112 }, + { 0x0003ef, 2177 }, + { 0x0008ce, 6410 }, + { 0x0008da, 6436 }, + { 0x0008db, 6447 }, + { 0x0008c2, 6361 }, + { 0x0008bf, 6332 }, + { 0x0008dc, 6456 }, + { 0x0003e7, 2159 }, + { 0x0003b5, 2020 }, + { 0x00006a, 351 }, + { 0x0002bc, 1814 }, + { 0x000bca, 7934 }, + { 0x00006b, 353 }, + { 0x0004b1, 2439 }, + { 0x0004c1, 2563 }, + { 0x0004b4, 2460 }, + { 0x0004cc, 2669 }, + { 0x0004ca, 2653 }, + { 0x0004cd, 2685 }, + { 0x0004cb, 2661 }, + { 0x0004ce, 2693 }, + { 0x0004cc, 2677 }, + { 0x0004b2, 2446 }, + { 0x0004b6, 2474 }, + { 0x0004b9, 2498 }, + { 0x0004b7, 2482 }, + { 0x0004ba, 2506 }, + { 0x0004b8, 2490 }, + { 0x0004cf, 2701 }, + { 0x0004d2, 2725 }, + { 0x0004d0, 2709 }, + { 0x0004d3, 2733 }, + { 0x0004d1, 2717 }, + { 0x0004dd, 2813 }, + { 0x0004c5, 2613 }, + { 0x0004c8, 2637 }, + { 0x0004c6, 2621 }, + { 0x0004c9, 2645 }, + { 0x0004c7, 2629 }, + { 0x0004b5, 2467 }, + { 0x0004d7, 2765 }, + { 0x0004da, 2789 }, + { 0x0004d8, 2773 }, + { 0x0004db, 2797 }, + { 0x0004d9, 2781 }, + { 0x0004bb, 2514 }, + { 0x0004be, 2539 }, + { 0x0004bc, 2522 }, + { 0x0004bf, 2547 }, + { 0x0004bd, 2531 }, + { 0x0004c0, 2555 }, + { 0x0004c3, 2597 }, + { 0x0004c1, 2572 }, + { 0x0004c4, 2605 }, + { 0x0004c2, 2580 }, + { 0x0004c2, 2589 }, + { 0x0004b3, 2453 }, + { 0x0004dc, 2805 }, + { 0x0004a6, 2340 }, + { 0x0004d4, 2741 }, + { 0x0004d6, 2757 }, + { 0x0004d5, 2749 }, + { 0x0004a7, 2348 }, + { 0x0004a3, 2277 }, + { 0x0004a4, 2297 }, + { 0x0004a5, 2308 }, + { 0x0004aa, 2369 }, + { 0x0004a1, 2243 }, + { 0x0004a8, 2355 }, + { 0x0004a5, 2325 }, + { 0x0004ab, 2376 }, + { 0x0004a2, 2257 }, + { 0x00ff7e, 13930 }, + { 0x0004af, 2407 }, + { 0x0004af, 2416 }, + { 0x0004a9, 2362 }, + { 0x0004ac, 2383 }, + { 0x0004ae, 2399 }, + { 0x0004ad, 2391 }, + { 0x0003a2, 1952 }, + { 0x0003f3, 2202 }, + { 0x0003a2, 1958 }, + { 0x00006c, 355 }, + { 0x0001e5, 1607 }, + { 0x000ad9, 7331 }, + { 0x0001b5, 1387 }, + { 0x0003b6, 2027 }, + { 0x000abc, 7011 }, + { 0x0008fb, 6523 }, + { 0x000ba3, 7852 }, + { 0x000ad2, 7261 }, + { 0x0008af, 6106 }, + { 0x000acc, 7156 }, + { 0x000aea, 7605 }, + { 0x0008a1, 5898 }, + { 0x000bda, 7984 }, + { 0x000ad0, 7220 }, + { 0x0009f4, 6757 }, + { 0x000bdc, 7993 }, + { 0x00003c, 176 }, + { 0x0008bc, 6292 }, + { 0x0009e5, 6603 }, + { 0x0008de, 6475 }, + { 0x0008df, 6486 }, + { 0x0009ed, 6654 }, + { 0x0009ea, 6612 }, + { 0x0001b3, 1379 }, + { 0x00006d, 357 }, + { 0x0000af, 562 }, + { 0x000af7, 7729 }, + { 0x000af0, 7649 }, + { 0x000abf, 7059 }, + { 0x0000ba, 666 }, + { 0x00002d, 121 }, + { 0x000ad6, 7315 }, + { 0x0000b5, 618 }, + { 0x0000d7, 932 }, + { 0x000af6, 7717 }, + { 0x000af5, 7704 }, + { 0x00006e, 359 }, + { 0x0008c5, 6370 }, + { 0x0001f1, 1658 }, + { 0x0001f2, 1665 }, + { 0x0003f1, 2185 }, + { 0x0009e8, 6606 }, + { 0x0000a0, 421 }, + { 0x0008bd, 6306 }, + { 0x0000ac, 536 }, + { 0x0000f1, 1153 }, + { 0x000023, 22 }, + { 0x0006b0, 3775 }, + { 0x00006f, 361 }, + { 0x0000f3, 1167 }, + { 0x0000f4, 1174 }, + { 0x0000f6, 1193 }, + { 0x0001f5, 1672 }, + { 0x0013bd, 11015 }, + { 0x0001b2, 1372 }, + { 0x0000f2, 1160 }, + { 0x0003f2, 2194 }, + { 0x000ac3, 7066 }, + { 0x000ab2, 6934 }, + { 0x0000bd, 702 }, + { 0x0000bc, 691 }, + { 0x000ab6, 6976 }, + { 0x0000b9, 654 }, + { 0x000ab0, 6915 }, + { 0x000ae2, 7473 }, + { 0x000ae5, 7522 }, + { 0x000ae4, 7504 }, + { 0x000ae3, 7488 }, + { 0x0000aa, 510 }, + { 0x0000f8, 1213 }, + { 0x0000f5, 1186 }, + { 0x000bc0, 7891 }, + { 0x00047e, 2234 }, + { 0x000070, 363 }, + { 0x0000b6, 621 }, + { 0x000028, 80 }, + { 0x000029, 90 }, + { 0x0008ef, 6496 }, + { 0x000025, 40 }, + { 0x00002e, 127 }, + { 0x0000b7, 631 }, + { 0x000afb, 7781 }, + { 0x00002b, 110 }, + { 0x0000b1, 576 }, + { 0x000ad4, 7302 }, + { 0x0004b0, 2424 }, + { 0x000aa6, 6833 }, + { 0x000071, 365 }, + { 0x000bcc, 7938 }, + { 0x00003f, 195 }, + { 0x0000bf, 724 }, + { 0x000022, 13 }, + { 0x000060, 323 }, + { 0x000027, 69 }, + { 0x000072, 367 }, + { 0x0001e0, 1593 }, + { 0x0008d6, 6428 }, + { 0x0001f8, 1685 }, + { 0x0003b3, 2011 }, + { 0x0000ae, 551 }, + { 0x000abe, 7041 }, + { 0x0008fd, 6541 }, + { 0x000ba6, 7862 }, + { 0x000ad3, 7281 }, + { 0x0008b0, 6127 }, + { 0x0008b7, 6271 }, + { 0x000acd, 7173 }, + { 0x000aeb, 7617 }, + { 0x000bd8, 7974 }, + { 0x000ad1, 7240 }, + { 0x0009f5, 6763 }, + { 0x000bfc, 8002 }, + { 0x000073, 369 }, + { 0x0001b6, 1394 }, + { 0x0001b9, 1407 }, + { 0x0001ba, 1414 }, + { 0x0002fe, 1940 }, + { 0x00ff7e, 13942 }, + { 0x000ad7, 7323 }, + { 0x0000a7, 482 }, + { 0x00003b, 166 }, + { 0x0004df, 2832 }, + { 0x000ac6, 7101 }, + { 0x000aca, 7124 }, + { 0x000aac, 6878 }, + { 0x0008c9, 6388 }, + { 0x000afd, 7807 }, + { 0x00002f, 134 }, + { 0x0009e0, 6568 }, + { 0x000020, 0 }, + { 0x0000df, 1006 }, + { 0x0000a3, 450 }, + { 0x000074, 371 }, + { 0x0001bb, 1423 }, + { 0x0001fe, 1711 }, + { 0x000af9, 7753 }, + { 0x000afa, 7763 }, + { 0x0008c0, 6341 }, + { 0x000aa7, 6844 }, + { 0x0000fe, 1264 }, + { 0x000ac4, 7076 }, + { 0x000ab4, 6953 }, + { 0x0000be, 710 }, + { 0x0000b3, 598 }, + { 0x0008a4, 5940 }, + { 0x0008ab, 6048 }, + { 0x0008a2, 5910 }, + { 0x0008a7, 5978 }, + { 0x0008b1, 6149 }, + { 0x0008ad, 6076 }, + { 0x0008a9, 6012 }, + { 0x0008b5, 6235 }, + { 0x0009f7, 6775 }, + { 0x0008b3, 6183 }, + { 0x000ac9, 7114 }, + { 0x000acb, 7138 }, + { 0x0003bc, 2053 }, + { 0x000ab3, 6943 }, + { 0x0000b2, 586 }, + { 0x000ab1, 6924 }, + { 0x000075, 373 }, + { 0x0000fa, 1227 }, + { 0x0002fd, 1933 }, + { 0x0000fb, 1234 }, + { 0x0000fc, 1246 }, + { 0x0001fb, 1698 }, + { 0x0000f9, 1220 }, + { 0x0003fe, 2226 }, + { 0x000bc6, 7925 }, + { 0x00005f, 306 }, + { 0x0008dd, 6469 }, + { 0x0003f9, 2211 }, + { 0x0008fc, 6533 }, + { 0x000ba9, 7883 }, + { 0x0009ec, 6641 }, + { 0x0009eb, 6627 }, + { 0x000bc3, 7908 }, + { 0x000bd3, 7957 }, + { 0x000bce, 7943 }, + { 0x0001f9, 1692 }, + { 0x0003fd, 2219 }, + { 0x000076, 375 }, + { 0x0008c1, 6351 }, + { 0x0009f8, 6780 }, + { 0x0008a6, 5964 }, + { 0x0004de, 2820 }, + { 0x0009e9, 6609 }, + { 0x000077, 377 }, + { 0x000078, 379 }, + { 0x000079, 381 }, + { 0x0000fd, 1257 }, + { 0x0000ff, 1270 }, + { 0x0000a5, 468 }, + { 0x00007a, 383 }, + { 0x0001bf, 1456 }, + { 0x0001bc, 1430 }, + { 0x0001be, 1449 }}; + + +#if 0 + +N_("keyboard label|BackSpace") +N_("keyboard label|Tab") +N_("keyboard label|Return") +N_("keyboard label|Pause") +N_("keyboard label|Scroll_Lock") +N_("keyboard label|Sys_Req") +N_("keyboard label|Escape") +N_("keyboard label|Multi_key") +N_("keyboard label|Home") +N_("keyboard label|Left") +N_("keyboard label|Up") +N_("keyboard label|Right") +N_("keyboard label|Down") +N_("keyboard label|Page_Up") +N_("keyboard label|Page_Down") +N_("keyboard label|End") +N_("keyboard label|Begin") +N_("keyboard label|Print") +N_("keyboard label|Insert") +N_("keyboard label|Num_Lock") +N_("keyboard label|KP_Space") +N_("keyboard label|KP_Tab") +N_("keyboard label|KP_Enter") +N_("keyboard label|KP_Home") +N_("keyboard label|KP_Left") +N_("keyboard label|KP_Up") +N_("keyboard label|KP_Right") +N_("keyboard label|KP_Down") +N_("keyboard label|KP_Page_Up") +N_("keyboard label|KP_Prior") +N_("keyboard label|KP_Page_Down") +N_("keyboard label|KP_Next") +N_("keyboard label|KP_End") +N_("keyboard label|KP_Begin") +N_("keyboard label|KP_Insert") +N_("keyboard label|KP_Delete") +N_("keyboard label|Delete") + +#endif diff --git a/src/test-attribute.c b/src/test-attribute.c new file mode 100644 index 0000000..b2ab4e5 --- /dev/null +++ b/src/test-attribute.c @@ -0,0 +1,44 @@ +#include "ibus.h" +#include "stdio.h" + +int main() +{ + g_type_init (); + IBusAttrList *list; + IBusMessage *message; + gboolean retval; + IBusError *error; + + list = ibus_attr_list_new (); + ibus_attr_list_append (list, ibus_attribute_new (1, 1, 1, 2)); + ibus_attr_list_append (list, ibus_attribute_new (2, 1, 1, 2)); + ibus_attr_list_append (list, ibus_attribute_new (3, 1, 1, 2)); + ibus_attr_list_append (list, ibus_attribute_new (3, 1, 1, 2)); + + message = ibus_message_new_signal ("/org/freedesktop/IBus", + "org.freedesktop.IBus", + "Test"); + + IBusSerializable *p = ibus_serializable_new (); + retval = ibus_message_append_args (message, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + G_TYPE_INVALID); + g_assert (retval); + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + IBUS_TYPE_SERIALIZABLE, &p, + G_TYPE_INVALID); + g_assert (retval); + + return 0; + +} diff --git a/src/test-bus.c b/src/test-bus.c new file mode 100644 index 0000000..a7756fa --- /dev/null +++ b/src/test-bus.c @@ -0,0 +1,22 @@ +#include "ibus.h" + +int main() +{ + g_type_init (); + + GMainLoop *mainloop; + IBusBus *bus; + IBusInputContext *context; + + mainloop = g_main_loop_new (NULL, FALSE); + bus = ibus_bus_new (); + context = ibus_bus_create_input_context (bus, "test"); + ibus_input_context_set_capabilities (context, 0); + ibus_input_context_destroy (context); + g_object_unref (context); + g_object_unref (bus); + + g_main_loop_run (mainloop); + + return 0; +} diff --git a/src/test-engine.c b/src/test-engine.c new file mode 100644 index 0000000..bea99cf --- /dev/null +++ b/src/test-engine.c @@ -0,0 +1,16 @@ +#include "ibus.h" + +int main() +{ + g_type_init (); + + GMainLoop *mainloop; + IBusConnection *connection; + IBusService *service; + + mainloop = g_main_loop_new (NULL, FALSE); + connection = ibus_connection_open ("unix:path=/tmp/ibus-phuang/ibus--0.0"); + service = IBUS_SERVICE (ibus_engine_new ("/a/Engine", connection)); + g_main_loop_run (mainloop); + return 0; +} diff --git a/src/test-keynames.c b/src/test-keynames.c new file mode 100644 index 0000000..629f4d3 --- /dev/null +++ b/src/test-keynames.c @@ -0,0 +1,8 @@ +#include "ibus.h" + +int main() +{ + g_assert_cmpstr (ibus_keyval_name (IBUS_Home), ==, "Home"); + g_assert (ibus_keyval_from_name ("Home") == IBUS_Home); + return 0; +} diff --git a/src/test-lookuptable.c b/src/test-lookuptable.c new file mode 100644 index 0000000..ec56811 --- /dev/null +++ b/src/test-lookuptable.c @@ -0,0 +1,39 @@ +#include "ibus.h" + +int main() +{ + g_type_init (); + IBusLookupTable *table, *table1; + IBusMessage *message; + IBusError *error; + gboolean retval; + + table = ibus_lookup_table_new (9, TRUE); + ibus_lookup_table_append_candidate (table, ibus_text_new_from_static_string ("Hello")); + ibus_lookup_table_append_candidate (table, ibus_text_new_from_static_string ("Cool")); + + message = ibus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL); + + retval = ibus_message_append_args (message, + IBUS_TYPE_LOOKUP_TABLE, &table, + IBUS_TYPE_LOOKUP_TABLE, &table, + G_TYPE_INVALID); + g_assert (retval); + + g_object_unref (table); + table = table1 = NULL; + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_LOOKUP_TABLE, &table, + IBUS_TYPE_LOOKUP_TABLE, &table1, + G_TYPE_INVALID); + g_assert (retval); + g_assert (table); + g_assert (table1); + + g_object_unref (table); + g_object_unref (table1); + + return 0; +} diff --git a/src/test-proxy.c b/src/test-proxy.c new file mode 100644 index 0000000..31866f1 --- /dev/null +++ b/src/test-proxy.c @@ -0,0 +1,18 @@ +#include "ibus.h" + +int main() +{ + g_type_init (); + + IBusConnection *connection; + IBusProxy *proxy; + + connection = ibus_connection_new (); + proxy = ibus_proxy_new ("a", "/a", connection); + GValue value = {0}; + g_value_init (&value, G_TYPE_STRING); + g_value_set_static_string (&value, "aaa"); + g_object_set_property (G_OBJECT (proxy), "name", &value); + + return 0; +} diff --git a/src/test-server.c b/src/test-server.c new file mode 100644 index 0000000..4e37085 --- /dev/null +++ b/src/test-server.c @@ -0,0 +1,30 @@ +#include "ibus.h" + + +void connection_destroy_cb (IBusConnection *connection, gpointer user_data) +{ + g_debug ("connnection %p destroyed", connection ); +} + +void new_connection_cb (IBusServer *server, IBusConnection *connection, gpointer user_data) +{ + g_debug ("new-connection %p", connection); + g_signal_connect (connection, "destroy", (GCallback) connection_destroy_cb, 0); +} + +int main() +{ + g_type_init (); + + GMainLoop *mainloop; + IBusServer *server; + + mainloop = g_main_loop_new (NULL, FALSE); + server = ibus_server_new (); + ibus_server_listen (server, "unix:abstract=/tmp/1234567"); + g_signal_connect (server, "new-connection", (GCallback) new_connection_cb, 0); + + g_main_loop_run (mainloop); + + return 0; +} diff --git a/src/test-text.c b/src/test-text.c new file mode 100644 index 0000000..37bc3a6 --- /dev/null +++ b/src/test-text.c @@ -0,0 +1,42 @@ +#include "ibus.h" + +int main() +{ + g_type_init (); + + IBusText *text1; + IBusText *text2; + IBusMessage *message; + IBusError *error; + gboolean retval; + + text1 = ibus_text_new_from_string ("Hello"); + text2 = ibus_text_new_from_static_string ("Hello"); + + message = ibus_message_new_signal ("/org/freedesktop/IBus", + "org.freedesktop.IBus", + "Test"); + + retval = ibus_message_append_args (message, + IBUS_TYPE_SERIALIZABLE, &text1, + IBUS_TYPE_SERIALIZABLE, &text2, + G_TYPE_INVALID); + g_assert (retval); + g_object_unref (text1); + g_object_unref (text2); + + retval = ibus_message_get_args (message, + &error, + IBUS_TYPE_SERIALIZABLE, &text1, + IBUS_TYPE_SERIALIZABLE, &text2, + G_TYPE_INVALID); + g_assert (retval); + g_assert_cmpstr (text1->text, ==, "Hello"); + g_assert_cmpstr (text2->text, ==, "Hello"); + + g_object_unref (text1); + g_object_unref (text2); + + return 0; + +} |