summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.gitignore12
-rw-r--r--src/Makefile.am209
-rw-r--r--src/ibus.h51
-rw-r--r--src/ibusattribute.c433
-rw-r--r--src/ibusattribute.h126
-rw-r--r--src/ibusbus.c773
-rw-r--r--src/ibusbus.h97
-rw-r--r--src/ibuscomponent.c743
-rw-r--r--src/ibuscomponent.h115
-rw-r--r--src/ibusconfig.c357
-rw-r--r--src/ibusconfig.h70
-rw-r--r--src/ibusconfigprivate.h221
-rw-r--r--src/ibusconfigservice.c314
-rw-r--r--src/ibusconfigservice.h85
-rw-r--r--src/ibusconnection.c697
-rw-r--r--src/ibusconnection.h147
-rw-r--r--src/ibusdebug.h27
-rw-r--r--src/ibusengine.c957
-rw-r--r--src/ibusengine.h152
-rw-r--r--src/ibusenginedesc.c356
-rw-r--r--src/ibusenginedesc.h86
-rw-r--r--src/ibusenumtypes.c146
-rw-r--r--src/ibusenumtypes.c.template34
-rw-r--r--src/ibusenumtypes.h37
-rw-r--r--src/ibusenumtypes.h.template24
-rw-r--r--src/ibuserror.c87
-rw-r--r--src/ibuserror.h41
-rw-r--r--src/ibusfactory.c483
-rw-r--r--src/ibusfactory.h120
-rw-r--r--src/ibushotkey.c479
-rw-r--r--src/ibushotkey.h87
-rw-r--r--src/ibusinputcontext.c695
-rw-r--r--src/ibusinputcontext.h87
-rw-r--r--src/ibusinternal.c667
-rw-r--r--src/ibusinternal.h36
-rw-r--r--src/ibuskeynames.c199
-rwxr-xr-xsrc/ibuskeysyms-update.pl105
-rw-r--r--src/ibuskeysyms.h2014
-rw-r--r--src/ibuslookuptable.c283
-rw-r--r--src/ibuslookuptable.h82
-rw-r--r--src/ibusmarshalers.list18
-rw-r--r--src/ibusmessage.c872
-rw-r--r--src/ibusmessage.h146
-rw-r--r--src/ibusobject.c189
-rw-r--r--src/ibusobject.h92
-rw-r--r--src/ibusobservedpath.c335
-rw-r--r--src/ibusobservedpath.h79
-rw-r--r--src/ibuspendingcall.c103
-rw-r--r--src/ibuspendingcall.h56
-rw-r--r--src/ibusproperty.c531
-rw-r--r--src/ibusproperty.h140
-rw-r--r--src/ibusproxy.c638
-rw-r--r--src/ibusproxy.h107
-rw-r--r--src/ibusserializable.c578
-rw-r--r--src/ibusserializable.h108
-rw-r--r--src/ibusserver.c327
-rw-r--r--src/ibusserver.h79
-rw-r--r--src/ibusservice.c406
-rw-r--r--src/ibusservice.h99
-rw-r--r--src/ibusshare.c164
-rw-r--r--src/ibusshare.h68
-rw-r--r--src/ibustext.c283
-rw-r--r--src/ibustext.h77
-rw-r--r--src/ibustypes.h74
-rw-r--r--src/ibusxml.c317
-rw-r--r--src/ibusxml.h37
-rw-r--r--src/keyname-table.h3978
-rw-r--r--src/test-attribute.c44
-rw-r--r--src/test-bus.c22
-rw-r--r--src/test-engine.c16
-rw-r--r--src/test-keynames.c8
-rw-r--r--src/test-lookuptable.c39
-rw-r--r--src/test-proxy.c18
-rw-r--r--src/test-server.c30
-rw-r--r--src/test-text.c42
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, &section,
+ 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, &section,
+ 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, &section,
+ 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, &section,
+ 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, &section,
+ 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, &section,
+ 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;
+
+}